summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAtzm Watanabe <atzm@iij.ad.jp>2018-09-13 12:24:28 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2018-09-26 15:34:16 +0900
commite3aa55872b70b97e2fd0946cbd404ef29e2cd092 (patch)
treeaade3c2f15bff78199b71582fa8055d5489cb409
parent0031cff9a3e1943161cfad688143c5b0e9911688 (diff)
app/ofctl: fix possible deadlock when the datapath disconnects
Signed-off-by: Atzm Watanabe <atzm@iij.ad.jp> Reviewed-by: IWAMOTO Toshihiro <iwamoto@valinux.co.jp>
-rw-r--r--ryu/app/ofctl/service.py20
1 files changed, 17 insertions, 3 deletions
diff --git a/ryu/app/ofctl/service.py b/ryu/app/ofctl/service.py
index ce604958..08ee75bd 100644
--- a/ryu/app/ofctl/service.py
+++ b/ryu/app/ofctl/service.py
@@ -112,6 +112,7 @@ class OfctlService(app_manager.RyuApp):
msg = req.msg
datapath = msg.datapath
parser = datapath.ofproto_parser
+ is_barrier = isinstance(msg, parser.OFPBarrierRequest)
try:
si = self._switches[datapath.id]
@@ -130,7 +131,16 @@ class OfctlService(app_manager.RyuApp):
si.xids[xid] = req
si.barriers[barrier_xid] = xid
- if isinstance(req.msg, parser.OFPBarrierRequest):
+ def _cancel(barrier_xid, exc):
+ xid = si.barriers.pop(barrier_xid)
+ si.results.pop(xid)
+ si.xids.pop(xid)
+ if not is_barrier and req.reply_cls is not None:
+ self._unobserve_msg(req.reply_cls)
+ self.logger.error('failed to send message <%s>', msg)
+ self.reply_to_request(req, event.Reply(exception=exc))
+
+ if is_barrier:
barrier = msg
datapath.set_xid(barrier)
_store_xid(barrier.xid, barrier.xid)
@@ -141,9 +151,13 @@ class OfctlService(app_manager.RyuApp):
barrier = datapath.ofproto_parser.OFPBarrierRequest(datapath)
datapath.set_xid(barrier)
_store_xid(msg.xid, barrier.xid)
- datapath.send_msg(msg)
+ if not datapath.send_msg(msg):
+ return _cancel(barrier.xid,
+ exception.InvalidDatapath(result=datapath.id))
- datapath.send_msg(barrier)
+ if not datapath.send_msg(barrier):
+ return _cancel(barrier.xid,
+ exception.InvalidDatapath(result=datapath.id))
@set_ev_cls(ofp_event.EventOFPBarrierReply, MAIN_DISPATCHER)
def _handle_barrier(self, ev):