Looks like a bug. Can you please test this patch? >From 34a3c034c3d67b73c0a806195e9984f95a381bf3 Mon Sep 17 00:00:00 2001 Message-Id: <34a3c034c3d67b73c0a806195e9984f95a381bf3.1372911748.git.yamah...@valinux.co.jp> In-Reply-To: <[email protected]> References: <[email protected]> From: Isaku Yamahata <[email protected]> Date: Thu, 4 Jul 2013 13:07:15 +0900 Subject: [PATCH] ryu/base/app_manager.py: teach state
Signed-off-by: Isaku Yamahata <[email protected]> --- ryu/base/app_manager.py | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/ryu/base/app_manager.py b/ryu/base/app_manager.py index 173e35c..c666f2c 100644 --- a/ryu/base/app_manager.py +++ b/ryu/base/app_manager.py @@ -57,8 +57,8 @@ class RyuApp(object): def __init__(self, *_args, **_kwargs): super(RyuApp, self).__init__() self.name = self.__class__.__name__ - self.event_handlers = {} - self.observers = {} + self.event_handlers = {} # ev_cls -> handlers:list + self.observers = {} # ev_cls -> observer-name -> states:set self.threads = [] self.events = hub.Queue(128) self.replies = hub.Queue() @@ -71,11 +71,17 @@ class RyuApp(object): self.event_handlers[ev_cls].append(handler) def register_observer(self, ev_cls, name, states=None): - states = states or [] - self.observers.setdefault(ev_cls, {})[name] = states + states = states or set() + ev_cls_observers = self.observers.setdefault(ev_cls, {}) + ev_cls_observers.setdefault(name, set()).update(states) - def get_handlers(self, ev): - return self.event_handlers.get(ev.__class__, []) + def get_handlers(self, ev, state=None): + handlers = self.event_handlers.get(ev.__class__, []) + if state is None: + return handlers + + return [handler for handler in handlers + if not handler.dispatchers or state in handler.dispatchers] def get_observers(self, ev, state): observers = [] @@ -98,28 +104,28 @@ class RyuApp(object): def _event_loop(self): while True: - ev = self.events.get() - handlers = self.get_handlers(ev) + ev, state = self.events.get() + handlers = self.get_handlers(ev, state) for handler in handlers: handler(ev) - def _send_event(self, ev): - self.events.put(ev) + def _send_event(self, ev, state): + self.events.put((ev, state)) - def send_event(self, name, ev): + def send_event(self, name, ev, state=None): if name in SERVICE_BRICKS: if isinstance(ev, EventRequestBase): ev.src = self.name LOG.debug("EVENT %s->%s %s" % (self.name, name, ev.__class__.__name__)) - SERVICE_BRICKS[name]._send_event(ev) + SERVICE_BRICKS[name]._send_event(ev, state) else: LOG.debug("EVENT LOST %s->%s %s" % (self.name, name, ev.__class__.__name__)) def send_event_to_observers(self, ev, state=None): for observer in self.get_observers(ev, state): - self.send_event(observer, ev) + self.send_event(observer, ev, state) def reply_to_request(self, req, rep): rep.dst = req.src -- 1.7.10.4 On Wed, Jul 03, 2013 at 09:50:50AM +0100, Alan Barr wrote: > Thanks for your reply, please find code and output below. > > > > I have done some minimal debugging, and know that register_observer is over > writing the states for the app class each time it is called. It expects one > method with multiple states instead of multiple methods each registered for > one > state. > > Granted, I don?t fully understand this process yet as I?m not sure why the > method along with the class is not being stored - though I feel this may be > part of the problem. I haven?t looked at where the events are being picked up > by the observers yet ? which must be responsible for calling all of the > registered methods for this event, regardless of their registered dispatcher. > > > > > > ##### CODE ##### > > import logging > > import struct > > > > from ryu.base import app_manager > > from ryu.controller import mac_to_port > > from ryu.controller import ofp_event > > from ryu.controller.handler import set_ev_cls > > from ryu.ofproto import ofproto_v1_3 > > from ryu.ofproto import ofproto_v1_3_parser > > from ryu.lib.mac import haddr_to_str > > > > from ryu.controller.controller import Datapath > > from ryu.controller.handler import HANDSHAKE_DISPATCHER > > from ryu.controller.handler import CONFIG_DISPATCHER > > from ryu.controller.handler import DEAD_DISPATCHER > > from ryu.controller.handler import MAIN_DISPATCHER > > > > class PacketTesting(app_manager.RyuApp): > > OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION] > > > > def __init__(self, *args, **kwargs): > > super(PacketTesting, self).__init__(*args, **kwargs) > > > > @set_ev_cls(ofp_event.EventOFPEchoRequest, MAIN_DISPATCHER) > > def _echo_rep_main(self, ev): > > print "DEBUG: In Handler for Echo Request (Main)" > > > > @set_ev_cls(ofp_event.EventOFPEchoRequest, CONFIG_DISPATCHER) > > def _echo_rep_conf(self, ev): > > print "DEBUG: In Handler for Echo Request (Config)" > > > > @set_ev_cls(ofp_event.EventOFPEchoRequest, HANDSHAKE_DISPATCHER) > > def _echo_rep_hand(self, ev): > > print "DEBUG: In Handler for Echo Request (Handshake)" > > > > @set_ev_cls(ofp_event.EventOFPEchoRequest, DEAD_DISPATCHER) > > def _echo_rep_dead(self, ev): > > print "DEBUG: In Handler for Echo Request (Dead)" > > > > > > ##### OUTPUT ##### > > > > loading app ../ryu_echo_req_ex.py > > loading app ryu.controller.ofp_handler > > instantiating app ../ryu_echo_req_ex.py > > instantiating app ryu.controller.ofp_handler > > BRICK PacketTesting > > CONSUMES EventOFPEchoRequest > > BRICK ofp_event > > PROVIDES EventOFPEchoRequest TO {'PacketTesting': ['main']} > > CONSUMES EventOFPErrorMsg > > CONSUMES EventOFPEchoRequest > > CONSUMES EventOFPSwitchFeatures > > CONSUMES EventOFPHello > > connected socket:<eventlet.greenio.GreenSocket object at 0xa0fb84c> address: > ('127.0.0.1', 60098) > > hello ev <ryu.controller.ofp_event.EventOFPHello object at 0xa0fbb6c> > > move onto config mode > > switch features ev version: 0x4 msg_type 0x6 xid 0xf8480126 OFPSwitchFeatures > (auxiliary_id=0,capabilities=71,datapath_id=153,n_buffers=256,n_tables= > 254,reserved=0) > > move onto main mode > > EVENT ofp_event->PacketTesting EventOFPEchoRequest > > DEBUG: In Handler for Echo Request (Config) > > DEBUG: In Handler for Echo Request (Dead) > > DEBUG: In Handler for Echo Request (Handshake) > > DEBUG: In Handler for Echo Request (Main) > > EVENT ofp_event->PacketTesting EventOFPEchoRequest > > DEBUG: In Handler for Echo Request (Config) > > DEBUG: In Handler for Echo Request (Dead) > > DEBUG: In Handler for Echo Request (Handshake) > > DEBUG: In Handler for Echo Request (Main) > > On 3 Jul 2013 07:41, "Isaku Yamahata" <[email protected]> wrote: > > Your expectation sounds correct. Posting your code would help. > > thanks, > > On Tue, Jul 02, 2013 at 01:54:20PM +0100, Alan Barr wrote: > > Hello all, > > > > > > > > I was wondering if someone could clarify if what I am seeing is expected > > behaviour. > > > > I am new to Ryu and currently trying to familiarise myself with it. > > > > In one of my test applications I have registered four different methods > for > > EventOFPEchoRequest, one method for each of HANDSHAKE, CONFIG, MAIN and > DEAD > > dispatchers. > > > > When this event is triggered, all of these methods are called, not just > the one > > registered for the appropriate state. > > > > > > > > Is this the correct behaviour? I don't have a valid use case of this, > I'm > just > > trying to better understand Ryu and this was my first test setup. I > wasn? > t > > expecting this behaviour. > > > > > > > > I was basing this off: > > > > > > > > ?A decorator for Ryu application to declare an event handler. Decorated > method > > will become an event handler. ev_cls is an event class whose instances > this > > RyuApp wants to receive. dispatchers argument specifies one of the > following > > negotiation phases (or a list of them) for which events should be > generated for > > this handler. Note that, in case an event changes the phase, the phase > before > > the change is used to check the interest.? https://github.com/osrg/ryu/ > wiki/API > > > > > > > > I'm on commit a66bcf031d782c25b987431feb76251970158573. > > > > > > > > Kind Regards, > > > > Alan Barr > > > > > > > > > > > ------------------------------------------------------------------------------ > > This SF.net email is sponsored by Windows: > > > > Build for Windows Store. > > > > http://p.sf.net/sfu/windows-dev2dev > > _______________________________________________ > > Ryu-devel mailing list > > [email protected] > > https://lists.sourceforge.net/lists/listinfo/ryu-devel > > > -- > yamahata > > > ------------------------------------------------------------------------------ > This SF.net email is sponsored by Windows: > > Build for Windows Store. > > http://p.sf.net/sfu/windows-dev2dev > _______________________________________________ > Ryu-devel mailing list > [email protected] > https://lists.sourceforge.net/lists/listinfo/ryu-devel > > ------------------------------------------------------------------------------ > This SF.net email is sponsored by Windows: > > Build for Windows Store. > > http://p.sf.net/sfu/windows-dev2dev > _______________________________________________ > Ryu-devel mailing list > [email protected] > https://lists.sourceforge.net/lists/listinfo/ryu-devel -- yamahata ------------------------------------------------------------------------------ This SF.net email is sponsored by Windows: Build for Windows Store. http://p.sf.net/sfu/windows-dev2dev _______________________________________________ Ryu-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/ryu-devel
