summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorIsaku Yamahata <yamahata@valinux.co.jp>2012-12-18 17:29:40 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2012-12-19 19:46:38 +0900
commit7e56bfb527863d2a2b763fa5e8451a4c744c9dd3 (patch)
treef83ed33f16a1555bc004248f0e2f72785077f1b0
parent65e7cf4b77bb2194ee5fb3fa28ec1c748fba1041 (diff)
ofp_handler: Improve hello version negotiation
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 <shivaram.mysore@gmail.com> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r--ryu/controller/ofp_handler.py66
1 files changed, 53 insertions, 13 deletions
diff --git a/ryu/controller/ofp_handler.py b/ryu/controller/ofp_handler.py
index 63f888a6..9c13c20c 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)