diff options
author | Isaku Yamahata <yamahata@valinux.co.jp> | 2012-12-18 17:29:40 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2012-12-19 19:46:38 +0900 |
commit | 7e56bfb527863d2a2b763fa5e8451a4c744c9dd3 (patch) | |
tree | f83ed33f16a1555bc004248f0e2f72785077f1b0 | |
parent | 65e7cf4b77bb2194ee5fb3fa28ec1c748fba1041 (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.py | 66 |
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) |