When switch sends version higher than Ryu supports, Ryu fails to negotiate.
In this case
  4 = OF1.3 from switch
  3 = OF1.2 from Ryu
  datapath.supported_ofp_version = (3 = OF1.2,)
In such cases, we should use OF1.2 instead of error.
> Connection to controller closed because of {"localhost",6633,0, 
> {unsupported_version,4}}

Reported-by: Shivaram Mysore <[email protected]>
Signed-off-by: Isaku Yamahata <[email protected]>
---
Changes v1 -> v2:
- return error when min(switch version, ryu version) isn't usable
- typo min instead of max
- minor code clean up
---
 ryu/controller/ofp_handler.py |   66 +++++++++++++++++++++++++++++++++--------
 1 file changed, 53 insertions(+), 13 deletions(-)

diff --git a/ryu/controller/ofp_handler.py b/ryu/controller/ofp_handler.py
index 63f888a..9c13c20 100644
--- a/ryu/controller/ofp_handler.py
+++ b/ryu/controller/ofp_handler.py
@@ -18,7 +18,6 @@ import logging
 
 from ryu import utils
 from ryu.base import app_manager
-from ryu.controller import dispatcher
 from ryu.controller import ofp_event
 from ryu.controller.handler import set_ev_cls
 from ryu.controller.handler import HANDSHAKE_DISPATCHER, CONFIG_DISPATCHER,\
@@ -44,6 +43,15 @@ class OFPHandler(app_manager.RyuApp):
     def __init__(self, *args, **kwargs):
         super(OFPHandler, self).__init__(*args, **kwargs)
 
+    @staticmethod
+    def hello_failed(datapath, error_desc):
+        LOG.error(error_desc)
+        error_msg = datapath.ofproto_parser.OFPErrorMsg(datapath)
+        error_msg.type = datapath.ofproto.OFPET_HELLO_FAILED
+        error_msg.code = datapath.ofproto.OFPHFC_INCOMPATIBLE
+        error_msg.data = error_desc
+        datapath.send_msg(error_msg)
+
     @set_ev_cls(ofp_event.EventOFPHello, HANDSHAKE_DISPATCHER)
     def hello_handler(self, ev):
         LOG.debug('hello ev %s', ev)
@@ -52,20 +60,52 @@ class OFPHandler(app_manager.RyuApp):
 
         # TODO: check if received version is supported.
         #       pre 1.0 is not supported
-        if msg.version not in datapath.supported_ofp_version:
+        # TODO: OFPHET_VERSIONBITMAP
+        usable_versions = [version for version
+                           in datapath.supported_ofp_version
+                           if version <= msg.version]
+        if not usable_versions:
             # send the error
-            error_msg = datapath.ofproto_parser.OFPErrorMsg(datapath)
-            error_msg.type = datapath.ofproto.OFPET_HELLO_FAILED
-            error_msg.code = datapath.ofproto.OFPHFC_INCOMPATIBLE
-            error_msg.data = 'unsupported version 0x%x' % msg.version
-            datapath.send_msg(error_msg)
+            error_desc = 'unsupported version 0x%x. '
+            'If possible, set the switch to use one of the versions %s' % (
+                msg.version, datapath.supported_ofp_version.keys())
+            self.hello_failed(error_desc)
             return
-
-        # should we again send HELLO with the version that the switch
-        # supports?
-        # msg.version != datapath.ofproto.OFP_VERSION:
-
-        datapath.set_version(msg.version)
+        version = max(usable_versions)
+        if version != min(msg.version, datapath.ofproto.OFP_VERSION):
+            # The version of min(msg.version, datapath.ofproto.OFP_VERSION)
+            # should be used according to the spec. But we can't.
+            # So log it and use max(usable_versions) with the hope that
+            # the switch is able to understand lower version.
+            # e.g.
+            # OF 1.1 from switch
+            # OF 1.2 from Ryu and supported_ofp_version = (1.0, 1.2)
+            # In this case, 1.1 should be used according to the spec,
+            # but 1.1 can't be used.
+            #
+            # OF1.3.1 6.3.1
+            # Upon receipt of this message, the recipient must
+            # calculate the OpenFlow protocol version to be used. If
+            # both the Hello message sent and the Hello message
+            # received contained a OFPHET_VERSIONBITMAP hello element,
+            # and if those bitmaps have some common bits set, the
+            # negotiated version must be the highest version set in
+            # both bitmaps. Otherwise, the negotiated version must be
+            # the smaller of the version number that was sent and the
+            # one that was received in the version fields.  If the
+            # negotiated version is supported by the recipient, then
+            # the connection proceeds. Otherwise, the recipient must
+            # reply with an OFPT_ERROR message with a type field of
+            # OFPET_HELLO_FAILED, a code field of OFPHFC_INCOMPATIBLE,
+            # and optionally an ASCII string explaining the situation
+            # in data, and then terminate the connection.
+            error_desc = 'no compatible version found: '
+            'switch 0x%x controller 0x%x, but found usable 0x%x. '
+            'If possible, set the switch to use OF version 0x%x' % (
+                msg.version, datapath.ofproto.OFP_VERSION, version, version)
+            self.hello_failed(error_desc)
+            return
+        datapath.set_version(version)
 
         # now send feature
         features_reqeust = datapath.ofproto_parser.OFPFeaturesRequest(datapath)
-- 
1.7.10.4


------------------------------------------------------------------------------
LogMeIn Rescue: Anywhere, Anytime Remote support for IT. Free Trial
Remotely access PCs and mobile devices and provide instant support
Improve your efficiency, and focus on delivering more value-add services
Discover what IT Professionals Know. Rescue delivers
http://p.sf.net/sfu/logmein_12329d2d
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to