an example:
msg = parser.OFPPortDescStatsRequest(datapath=datapath)
result = ofctl.api.send_msg(self, msg,
reply_cls=parser.OFPPortDescStatsReply,
reply_multi=True)
Signed-off-by: YAMAMOTO Takashi <[email protected]>
---
ryu/app/ofctl/api.py | 5 +++--
ryu/app/ofctl/event.py | 8 ++++++--
ryu/app/ofctl/exception.py | 29 +++++++++++++++++++++++++++++
ryu/app/ofctl/service.py | 31 ++++++++++++++++++++++---------
4 files changed, 60 insertions(+), 13 deletions(-)
create mode 100644 ryu/app/ofctl/exception.py
diff --git a/ryu/app/ofctl/api.py b/ryu/app/ofctl/api.py
index 476543e..569fd6a 100644
--- a/ryu/app/ofctl/api.py
+++ b/ryu/app/ofctl/api.py
@@ -29,12 +29,13 @@ def get_datapath(app, dpid):
return app.send_request(event.GetDatapathRequest(dpid=dpid))()
-def send_msg(app, msg, reply_cls=None):
+def send_msg(app, msg, reply_cls=None, reply_multi=False):
"""
Send an openflow message.
"""
return app.send_request(event.SendMsgRequest(msg=msg,
- reply_cls=reply_cls))()
+ reply_cls=reply_cls,
+ reply_multi=reply_multi))()
app_manager.require_app('ryu.app.ofctl.service')
diff --git a/ryu/app/ofctl/event.py b/ryu/app/ofctl/event.py
index 9dfefcd..909f2a8 100644
--- a/ryu/app/ofctl/event.py
+++ b/ryu/app/ofctl/event.py
@@ -40,17 +40,21 @@ class GetDatapathRequest(_RequestBase):
# send msg
class SendMsgRequest(_RequestBase):
- def __init__(self, msg, reply_cls=None):
+ def __init__(self, msg, reply_cls=None, reply_multi=False):
super(SendMsgRequest, self).__init__()
self.msg = msg
self.reply_cls = reply_cls
+ self.reply_multi = reply_multi
# generic reply
class Reply(_ReplyBase):
- def __init__(self, result=None):
+ def __init__(self, result=None, exception=None):
self.result = result
+ self.exception = exception
def __call__(self):
+ if self.exception:
+ raise self.exception
return self.result
diff --git a/ryu/app/ofctl/exception.py b/ryu/app/ofctl/exception.py
new file mode 100644
index 0000000..90113ae
--- /dev/null
+++ b/ryu/app/ofctl/exception.py
@@ -0,0 +1,29 @@
+# Copyright (C) 2014 Nippon Telegraph and Telephone Corporation.
+# Copyright (C) 2014 YAMAMOTO Takashi <yamamoto at valinux co jp>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from ryu import exception
+
+
+# base classes
+
+class _ExceptionBase(exception.RyuException):
+ def __init__(self, result):
+ self.result = result
+ super(_ExceptionBase, self).__init__(result=result)
+
+
+class UnexpectedMultiReply(_ExceptionBase):
+ message = 'Unexpected Multi replies %(result)s'
diff --git a/ryu/app/ofctl/service.py b/ryu/app/ofctl/service.py
index 183cc6c..cb6ba19 100644
--- a/ryu/app/ofctl/service.py
+++ b/ryu/app/ofctl/service.py
@@ -24,6 +24,7 @@ from ryu.controller.handler import CONFIG_DISPATCHER,
MAIN_DISPATCHER,\
from ryu.controller.handler import set_ev_cls
import event
+import exception
class _SwitchInfo(object):
@@ -102,19 +103,26 @@ class OfctlService(app_manager.RyuApp):
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)
xid = msg.xid
- datapath.send_msg(msg)
barrier = datapath.ofproto_parser.OFPBarrierRequest(datapath)
datapath.set_xid(barrier)
barrier_xid = barrier.xid
- datapath.send_msg(barrier)
+
si = self._switches[datapath.id]
+ assert not xid in si.results
+ assert not xid in si.xids
+ assert not barrier_xid in si.barriers
+ si.results[xid] = []
si.xids[xid] = req
si.barriers[barrier_xid] = xid
+ datapath.send_msg(msg)
+ datapath.send_msg(barrier)
+
@set_ev_cls(ofp_event.EventOFPBarrierReply, MAIN_DISPATCHER)
def _handle_barrier(self, ev):
msg = ev.msg
@@ -125,18 +133,23 @@ class OfctlService(app_manager.RyuApp):
self.logger.error('unknown dpid %s' % (datapath.id,))
return
try:
- xid = si.barriers[msg.xid]
+ xid = si.barriers.pop(msg.xid)
except KeyError:
self.logger.error('unknown barrier xid %s' % (msg.xid,))
return
- try:
- result = si.results.pop(xid)
- except KeyError:
- result = None
+ result = si.results.pop(xid)
req = si.xids.pop(xid)
if not req.reply_cls is None:
self._unobserve_msg(req.reply_cls)
- rep = event.Reply(result=result)
+ if req.reply_multi:
+ rep = event.Reply(result=result)
+ elif len(result) == 0:
+ rep = event.Reply()
+ elif len(result) == 1:
+ rep = event.Reply(result=result[0])
+ else:
+ rep = event.Reply(exception=exception.
+ UnexpectedMultiReply(result=result))
self.reply_to_request(req, rep)
@set_ev_cls(ofp_event.EventOFPErrorMsg, MAIN_DISPATCHER)
@@ -159,6 +172,6 @@ class OfctlService(app_manager.RyuApp):
(ev, msg.xid,))
return
try:
- si.results[msg.xid] = ev.msg
+ si.results[msg.xid].append(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