Hello,
It works, thanks!
However, when both TCP FIN & retransmission packets sent from switch were
lost, the socket for the older connection remains open on controller host.
(old connections remain ESTABLISHED in netstat.) We can wait for its
timeout, but when I tried to call self.dps[dp.id].socket.close() before
older dp being replaced and made further request to the same dpid, it
raised runtime error as below:
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/eventlet/greenpool.py", line 80,
in _spawn_n_impl
func(*args, **kwargs)
File "/usr/lib/python2.7/dist-packages/eventlet/wsgi.py", line 575, in
process_request
proto = self.protocol(socket, address, self)
File "/usr/lib/python2.7/SocketServer.py", line 638, in __init__
self.handle()
File "/usr/lib/python2.7/BaseHTTPServer.py", line 342, in handle
self.handle_one_request()
File "/usr/lib/python2.7/dist-packages/eventlet/wsgi.py", line 225, in
handle_one_request
self.raw_requestline = self.rfile.readline(self.server.url_length_limit)
File "/usr/lib/python2.7/socket.py", line 476, in readline
data = self._sock.recv(self._rbufsize)
File "/usr/lib/python2.7/dist-packages/eventlet/greenio.py", line 249, in
recv
timeout_exc=socket.timeout("timed out"))
File "/usr/lib/python2.7/dist-packages/eventlet/hubs/__init__.py", line
117, in trampoline
listener = hub.add(hub.READ, fileno, current.switch)
File "/usr/lib/python2.7/dist-packages/eventlet/hubs/epolls.py", line 48,
in add
listener = BaseHub.add(self, evtype, fileno, cb)
File "/usr/lib/python2.7/dist-packages/eventlet/hubs/hub.py", line 126,
in add
evtype, fileno, evtype))
RuntimeError: Second simultaneous read on fileno 6 detected. Unless you
really know what you're doing, make sure that only one greenthread can read
any particular socket. Consider using a pools.Pool. If you do know what
you're doing and want to disable this error, call
eventlet.debug.hub_multiple_reader_prevention(False)
Any comment on more graceful way to cleanup the old dp?
Thanks.
Sincerely,
Wei-Li Tang
2013/11/14 YAMAMOTO Takashi <[email protected]>
> 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
------------------------------------------------------------------------------
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