Thanks, I can confirm that with the patch my example works as I originally
anticipated - the handler for Echo Request for the main dispatcher is the
only method called when an Echo Request is received.
Regards,
Alan Barr
On 4 Jul 2013 05:39, "Isaku Yamahata" <[email protected]> wrote:
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
------------------------------------------------------------------------------
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