an example:
    msg = parser.OFPEchoRequest(datapath=datapath)
    result = ofctl.api.send_msg(self, msg, reply_cls=parser.OFPEchoReply)
    assert isinstance(result, parser.OFPEchoReply)

Signed-off-by: YAMAMOTO Takashi <[email protected]>
---
 ryu/app/ofctl/api.py     |  5 +++--
 ryu/app/ofctl/event.py   |  3 ++-
 ryu/app/ofctl/service.py | 36 +++++++++++++++++++++++++++++++++++-
 3 files changed, 40 insertions(+), 4 deletions(-)

diff --git a/ryu/app/ofctl/api.py b/ryu/app/ofctl/api.py
index e49a001..476543e 100644
--- a/ryu/app/ofctl/api.py
+++ b/ryu/app/ofctl/api.py
@@ -29,11 +29,12 @@ def get_datapath(app, dpid):
     return app.send_request(event.GetDatapathRequest(dpid=dpid))()
 
 
-def send_msg(app, msg):
+def send_msg(app, msg, reply_cls=None):
     """
     Send an openflow message.
     """
-    return app.send_request(event.SendMsgRequest(msg=msg))()
+    return app.send_request(event.SendMsgRequest(msg=msg,
+                                                 reply_cls=reply_cls))()
 
 
 app_manager.require_app('ryu.app.ofctl.service')
diff --git a/ryu/app/ofctl/event.py b/ryu/app/ofctl/event.py
index 9920833..9dfefcd 100644
--- a/ryu/app/ofctl/event.py
+++ b/ryu/app/ofctl/event.py
@@ -40,9 +40,10 @@ class GetDatapathRequest(_RequestBase):
 # send msg
 
 class SendMsgRequest(_RequestBase):
-    def __init__(self, msg):
+    def __init__(self, msg, reply_cls=None):
         super(SendMsgRequest, self).__init__()
         self.msg = msg
+        self.reply_cls = reply_cls
 
 
 # generic reply
diff --git a/ryu/app/ofctl/service.py b/ryu/app/ofctl/service.py
index 3e24170..183cc6c 100644
--- a/ryu/app/ofctl/service.py
+++ b/ryu/app/ofctl/service.py
@@ -39,6 +39,26 @@ class OfctlService(app_manager.RyuApp):
         super(OfctlService, self).__init__(*args, **kwargs)
         self.name = 'ofctl_service'
         self._switches = {}
+        self._observing_events = {}
+
+    def _observe_msg(self, msg_cls):
+        assert msg_cls is not None
+        ev_cls = ofp_event.ofp_msg_to_ev_cls(msg_cls)
+        self._observing_events.setdefault(ev_cls, 0)
+        if self._observing_events[ev_cls] == 0:
+            self.logger.debug('ofctl: start observing %s' % (ev_cls,))
+            self.observe_event(ev_cls)
+        self._observing_events[ev_cls] += 1
+        self.register_handler(ev_cls, self._handle_reply)
+
+    def _unobserve_msg(self, msg_cls):
+        assert msg_cls is not None
+        ev_cls = ofp_event.ofp_msg_to_ev_cls(msg_cls)
+        assert self._observing_events[ev_cls] > 0
+        self._observing_events[ev_cls] -= 1
+        if self._observing_events[ev_cls] == 0:
+            self.unobserve_event(ev_cls)
+            self.logger.debug('ofctl: stop observing %s' % (ev_cls,))
 
     @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
     def _switch_features_handler(self, ev):
@@ -80,6 +100,8 @@ class OfctlService(app_manager.RyuApp):
 
     @set_ev_cls(event.SendMsgRequest, MAIN_DISPATCHER)
     def _handle_send_msg(self, req):
+        if not req.reply_cls is None:
+            self._observe_msg(req.reply_cls)
         msg = req.msg
         datapath = msg.datapath
         datapath.set_xid(msg)
@@ -112,11 +134,13 @@ class OfctlService(app_manager.RyuApp):
         except KeyError:
             result = None
         req = si.xids.pop(xid)
+        if not req.reply_cls is None:
+            self._unobserve_msg(req.reply_cls)
         rep = event.Reply(result=result)
         self.reply_to_request(req, rep)
 
     @set_ev_cls(ofp_event.EventOFPErrorMsg, MAIN_DISPATCHER)
-    def _handle_error(self, ev):
+    def _handle_reply(self, ev):
         msg = ev.msg
         datapath = msg.datapath
         try:
@@ -125,6 +149,16 @@ class OfctlService(app_manager.RyuApp):
             self.logger.error('unknown dpid %s' % (datapath.id,))
             return
         try:
+            req = si.xids[msg.xid]
+        except KeyError:
+            self.logger.error('unknown error xid %s' % (msg.xid,))
+            return
+        if ((not isinstance(ev, ofp_event.EventOFPErrorMsg)) and
+           (req.reply_cls is None or not isinstance(ev.msg, req.reply_cls))):
+            self.logger.error('unexpected reply %s for xid %s' %
+                              (ev, msg.xid,))
+            return
+        try:
             si.results[msg.xid] = ev.msg
         except KeyError:
             self.logger.error('unknown error xid %s' % (msg.xid,))
-- 
1.8.3.1


------------------------------------------------------------------------------
Learn Graph Databases - Download FREE O'Reilly Book
"Graph Databases" is the definitive new guide to graph databases and their
applications. Written by three acclaimed leaders in the field,
this first edition is now available. Download your free book today!
http://p.sf.net/sfu/13534_NeoTech
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to