this should fix the following crash recently reported
by wataru yamamoto on ryu-devel.
hub: uncaught exception: Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/ryu/lib/hub.py", line 48, in
_launch
func(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/ryu/base/app_manager.py", line
110, in _event_loop
handler(ev)
File "/usr/local/lib/python2.7/dist-packages/ryu/controller/dpset.py", line
157, in dispacher_change
self.register(datapath)
File "/usr/local/lib/python2.7/dist-packages/ryu/controller/dpset.py", line
100, in register
assert dp.id not in self.dps
AssertionError
Signed-off-by: YAMAMOTO Takashi <[email protected]>
---
ryu/controller/dpset.py | 40 ++++++++++++++++++++++++++++------------
1 file changed, 28 insertions(+), 12 deletions(-)
diff --git a/ryu/controller/dpset.py b/ryu/controller/dpset.py
index 1a4de33..54c9b5a 100644
--- a/ryu/controller/dpset.py
+++ b/ryu/controller/dpset.py
@@ -96,18 +96,37 @@ class DPSet(app_manager.RyuApp):
self.port_state = {} # datapath_id => ports
def _register(self, dp):
+ LOG.debug('DPSET: register datapath %s', dp)
assert dp.id is not None
- assert dp.id not in self.dps
+ # while dpid should be unique, we need to handle duplicates here
+ # because it's entirely possible for a switch to reconnect us
+ # before we notice the drop of the previous connection.
+ # in that case,
+ # - forget the older connection as it likely will disappear soon
+ # - do not send EventDP leave/enter events
+ # - keep the PortState for the dpid
+ if dp.id in self.dps:
+ self.logger.warning('DPSET: Multiple connections from %s',
+ dpid_to_str(dp.id))
+ self.logger.debug('DPSET: Forgetting datapath %s', self.dps[dp.id])
+ self.logger.debug('DPSET: New datapath %s', dp)
self.dps[dp.id] = dp
- self.port_state[dp.id] = PortState()
- ev = EventDP(dp, True)
- for port in dp.ports.values():
- self._port_added(dp, port)
- ev.ports.append(port)
- self.send_event_to_observers(ev)
+ if not dp.id in self.port_state:
+ self.port_state[dp.id] = PortState()
+ ev = EventDP(dp, True)
+ for port in dp.ports.values():
+ self._port_added(dp, port)
+ ev.ports.append(port)
+ self.send_event_to_observers(ev)
def _unregister(self, dp):
+ # see the comment in _register().
+ if not dp in self.dps.values():
+ return
+ LOG.debug('DPSET: unregister datapath %s', dp)
+ assert self.dps[dp.id] == dp
+
# Now datapath is already dead, so port status change event doesn't
# interfere us.
ev = EventDP(dp, False)
@@ -117,9 +136,8 @@ class DPSet(app_manager.RyuApp):
self.send_event_to_observers(ev)
- if dp.id in self.dps:
- del self.dps[dp.id]
- del self.port_state[dp.id]
+ del self.dps[dp.id]
+ del self.port_state[dp.id]
def get(self, dp_id):
"""
@@ -153,10 +171,8 @@ class DPSet(app_manager.RyuApp):
datapath = ev.datapath
assert datapath is not None
if ev.state == handler.MAIN_DISPATCHER:
- LOG.debug('DPSET: register datapath %s', datapath)
self._register(datapath)
elif ev.state == handler.DEAD_DISPATCHER:
- LOG.debug('DPSET: unregister datapath %s', datapath)
self._unregister(datapath)
@set_ev_cls(ofp_event.EventOFPSwitchFeatures, handler.CONFIG_DISPATCHER)
--
1.8.3.1
------------------------------------------------------------------------------
DreamFactory - Open Source REST & JSON Services for HTML5 & Native Apps
OAuth, Users, Roles, SQL, NoSQL, BLOB Storage and External API Access
Free app hosting. Or install the open source package on any LAMP server.
Sign up and see examples for AngularJS, jQuery, Sencha Touch and Native!
http://pubads.g.doubleclick.net/gampad/clk?id=63469471&iu=/4140/ostg.clktrk
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel