* 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

Reply via email to