Sigh. Needed to check that the datapath being unregistered is the same as the 
one returned from _get_switch(), especially since a switch re-connection could 
cause an OFPStateChange event for a DEAD_DISPATCHER transition to be queued 
after the new datapath is added to self.dps.

Without this check, the event generated for the old datapath could interfere 
with the newly generated datapath.

Signed-off-by: Victor J. Orlikowski <[email protected]>

diff --git a/ryu/topology/event.py b/ryu/topology/event.py
index c54152b..e7b682c 100644
--- a/ryu/topology/event.py
+++ b/ryu/topology/event.py
@@ -41,6 +41,11 @@ class EventSwitchLeave(EventSwitchBase):
         super(EventSwitchLeave, self).__init__(switch)
 
 
+class EventSwitchReconnected(EventSwitchBase):
+    def __init__(self, switch):
+        super(EventSwitchReconnected, self).__init__(switch)
+
+
 class EventPortBase(event.EventBase):
     def __init__(self, port):
         super(EventPortBase, self).__init__()
diff --git a/ryu/topology/switches.py b/ryu/topology/switches.py
index 5fe5d26..1b37983 100644
--- a/ryu/topology/switches.py
+++ b/ryu/topology/switches.py
@@ -495,6 +495,7 @@ class Switches(app_manager.RyuApp):
     OFP_VERSIONS = [ofproto_v1_0.OFP_VERSION, ofproto_v1_2.OFP_VERSION,
                     ofproto_v1_3.OFP_VERSION, ofproto_v1_4.OFP_VERSION]
     _EVENTS = [event.EventSwitchEnter, event.EventSwitchLeave,
+               event.EventSwitchReconnected,
                event.EventPortAdd, event.EventPortDelete,
                event.EventPortModify,
                event.EventLinkAdd, event.EventLinkDelete,
@@ -547,8 +548,9 @@ class Switches(app_manager.RyuApp):
 
     def _unregister(self, dp):
         if dp.id in self.dps:
-            del self.dps[dp.id]
-            del self.port_state[dp.id]
+            if (self.dps[dp.id] == dp):
+                del self.dps[dp.id]
+                del self.port_state[dp.id]
 
     def _get_switch(self, dpid):
         if dpid in self.dps:
@@ -602,16 +604,18 @@ class Switches(app_manager.RyuApp):
         if ev.state == MAIN_DISPATCHER:
             dp_multiple_conns = False
             if dp.id in self.dps:
-                LOG.warning('multiple connections from %s', dpid_to_str(dp.id))
+                LOG.warning('Multiple connections from %s', dpid_to_str(dp.id))
                 dp_multiple_conns = True
+                (self.dps[dp.id]).close()
 
             self._register(dp)
             switch = self._get_switch(dp.id)
             LOG.debug('register %s', switch)
 
-            # Do not send event while dp has multiple connections.
             if not dp_multiple_conns:
                 self.send_event_to_observers(event.EventSwitchEnter(switch))
+            else:
+                
self.send_event_to_observers(event.EventSwitchReconnected(switch))
 
             if not self.link_discovery:
                 return
@@ -665,19 +669,23 @@ class Switches(app_manager.RyuApp):
             # dp.id is None when datapath dies before handshake
             if dp.id is None:
                 return
+
             switch = self._get_switch(dp.id)
-            self._unregister(dp)
-            LOG.debug('unregister %s', switch)
-            self.send_event_to_observers(event.EventSwitchLeave(switch))
+            if switch:
+                if (dp == switch.dp):
+                    self._unregister(dp)
+                    LOG.debug('unregister %s', switch)
 
-            if not self.link_discovery:
-                return
+                    
self.send_event_to_observers(event.EventSwitchLeave(switch))
 
-            for port in switch.ports:
-                if not port.is_reserved():
-                    self.ports.del_port(port)
-                    self._link_down(port)
-            self.lldp_event.set()
+                    if not self.link_discovery:
+                        return
+
+                    for port in switch.ports:
+                        if not port.is_reserved():
+                            self.ports.del_port(port)
+                            self._link_down(port)
+                    self.lldp_event.set()
 
     @set_ev_cls(ofp_event.EventOFPPortStatus, MAIN_DISPATCHER)
     def port_status_handler(self, ev):
@@ -762,7 +770,7 @@ class Switches(app_manager.RyuApp):
         try:
             src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data)
         except LLDPPacket.LLDPUnknownFormat as e:
-            # This handler can receive all the packtes which can be
+            # This handler can receive all the packets which can be
             # not-LLDP packet. Ignore it silently
             return
 


Best,
Victor
--
Victor J. Orlikowski <> vjo@[cs.]duke.edu

------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=267308311&iu=/4140
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to