* Reply dead exceptions to all pending requests when dp disconnects * Rufuse handling msg of dead dp
Signed-off-by: Zang MingJie <zealot0...@gmail.com> --- ryu/app/ofctl/exception.py | 9 +++++++++ ryu/app/ofctl/service.py | 37 ++++++++++++++++++++++++++----------- 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/ryu/app/ofctl/exception.py b/ryu/app/ofctl/exception.py index 0c6555a..9d317dd 100644 --- a/ryu/app/ofctl/exception.py +++ b/ryu/app/ofctl/exception.py @@ -31,6 +31,15 @@ class UnexpectedMultiReply(_ExceptionBase): message = 'Unexpected Multi replies %(result)s' +class OFDead(_ExceptionBase): + """Connection to switch is closed.""" + + message = 'OpenFlow connection closed' + + def __init__(self): + super(OFDead, self).__init__(result=None) + + class OFError(_ExceptionBase): """OFPErrorMsg is received.""" diff --git a/ryu/app/ofctl/service.py b/ryu/app/ofctl/service.py index 2e04c27..73539af 100644 --- a/ryu/app/ofctl/service.py +++ b/ryu/app/ofctl/service.py @@ -64,6 +64,16 @@ class OfctlService(app_manager.RyuApp): self.unobserve_event(ev_cls) self.logger.debug('ofctl: stop observing %s', ev_cls) + def forget_info(self, info): + # make sure no more msg can be inserted + (xids, info.xids) = (info.xids, None) + for xid, req in xids.items(): + if req.reply_cls is not None: + self._unobserve_msg(req.reply_cls) + rep = event.Reply(exception=exception.OFDead()) + self.reply_to_request(req, rep) + self.logger.debug('forget info %s', info) + @staticmethod def _is_error(msg): return (ofp_event.ofp_msg_to_ev_cls(type(msg)) == @@ -74,11 +84,12 @@ class OfctlService(app_manager.RyuApp): datapath = ev.msg.datapath id = datapath.id assert isinstance(id, numbers.Integral) - old_info = self._switches.get(id, None) - new_info = _SwitchInfo(datapath=datapath) + (self._switches[id], info) = \ + (_SwitchInfo(datapath=datapath), self._switches.get(id, None)) + if info is not None: + self.forget_info(info) self.logger.debug('add dpid %s datapath %s new_info %s old_info %s', - id, datapath, new_info, old_info) - self._switches[id] = new_info + id, datapath, self._switches[id], info) @set_ev_cls(ofp_event.EventOFPStateChange, DEAD_DISPATCHER) def _handle_dead(self, ev): @@ -94,6 +105,7 @@ class OfctlService(app_manager.RyuApp): if info.datapath is datapath: self.logger.debug('forget info %s', info) self._switches.pop(id) + self.forget_info(info) @set_ev_cls(event.GetDatapathRequest, MAIN_DISPATCHER) def _handle_get_datapath(self, req): @@ -107,17 +119,20 @@ class OfctlService(app_manager.RyuApp): rep = event.Reply(result=datapath) self.reply_to_request(req, rep) - @set_ev_cls(event.SendMsgRequest, MAIN_DISPATCHER) + @set_ev_cls(event.SendMsgRequest, []) def _handle_send_msg(self, req): msg = req.msg datapath = msg.datapath - try: - si = self._switches[datapath.id] - except KeyError: - self.logger.error('unknown dpid %s' % (datapath.id,)) - rep = event.Reply(exception=exception. - InvalidDatapath(result=datapath.id)) + si = self._switches.get(datapath.id, None) + # The datapath may reconnect with the same id, refuse to handle msg of + # last dead connection. + if (si is None or + datapath.state not in [CONFIG_DISPATCHER, MAIN_DISPATCHER] or + si.datapath != datapath): + self.logger.debug('datapath already dead %s(id=%s)', + datapath, datapath.id) + rep = event.Reply(exception=exception.OFDead()) self.reply_to_request(req, rep) return -- 1.7.10.4 ------------------------------------------------------------------------------ BPM Camp - Free Virtual Workshop May 6th at 10am PDT/1PM EDT Develop your own process in accordance with the BPMN 2 standard Learn Process modeling best practices with Bonita BPM through live exercises http://www.bonitasoft.com/be-part-of-it/events/bpm-camp-virtual- event?utm_ source=Sourceforge_BPM_Camp_5_6_15&utm_medium=email&utm_campaign=VA_SF _______________________________________________ Ryu-devel mailing list Ryu-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ryu-devel