For discovery, it's interested only in datapath/port appearance/disappearance.
With this, discovery app would not have to handle OFP events directly.

Signed-off-by: Isaku Yamahata <[email protected]>
---
 ryu/controller/dpset.py |   79 ++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 75 insertions(+), 4 deletions(-)

diff --git a/ryu/controller/dpset.py b/ryu/controller/dpset.py
index fe42b95..b4d2e45 100644
--- a/ryu/controller/dpset.py
+++ b/ryu/controller/dpset.py
@@ -19,7 +19,9 @@ from ryu.controller import event
 from ryu.controller import dispatcher
 from ryu.controller import dp_type
 from ryu.controller import handler
+from ryu.controller import ofp_event
 from ryu.controller.handler import set_ev_cls
+import ryu.exception as ryu_exc
 
 LOG = logging.getLogger('ryu.controller.dpset')
 
@@ -36,17 +38,57 @@ class EventDP(EventDPBase):
         # True: dp entered
         # False: dp leaving
         super(EventDP, self).__init__(dp)
-        self.enter = enter_leave
+        self.enter_leave = enter_leave
+
+
+class EventPortBase(EventDPBase):
+    def __init__(self, dp, port):
+        super(EventPortBase, self).__init__(dp)
+        self.port = port
+
+
+class EventPortAdd(EventPortBase):
+    def __init__(self, dp, port):
+        super(EventPortAdd, self).__init__(dp, port)
+
+
+class EventPortDelete(EventPortBase):
+    def __init__(self, dp, port):
+        super(EventPortDelete, self).__init__(dp, port)
+
+
+class EventPortModify(EventPortBase):
+    def __init__(self, dp, new_port):
+        super(EventPortModify, self).__init__(dp, new_port)
+
+
+class PortState(dict):
+    def __init__(self, dp):
+        super(PortState, self).__init__()
+        for port in dp.ports.values():
+            self.add(port.port_no, port.state)
+
+    def add(self, port_no, state):
+        self[port_no] = state
+
+    def remove(self, port_no):
+        del self[port_no]
+
+    def modify(self, port_no, state):
+        self[port_no] = state
 
 
 # this depends on controller::Datapath and dispatchers in handler
 class DPSet(object):
     def __init__(self, ev_q, dispatcher_):
+        super(DPSet, self).__init__()
+
         # dp registration and type setting can be occur in any order
         # Sometimes the sw_type is set before dp connection
         self.dp_types = {}
 
         self.dps = {}   # datapath_id => class Datapath
+        self.port_state = {}  # datapath_id => ports
         self.ev_q = ev_q
         self.dispatcher = dispatcher_
 
@@ -60,17 +102,18 @@ class DPSet(object):
         if dp_type_ is not None:
             dp.dp_type = dp_type_
 
-        self.ev_q.queue(EventDP(dp, True))
         self.dps[dp.id] = dp
+        self.port_state[dp.id] = PortState(dp)
+        self.ev_q.queue(EventDP(dp, True))
 
     def unregister(self, dp):
         if dp.id in self.dps:
+            self.ev_q.queue(EventDP(dp, False))
             del self.dps[dp.id]
+            del self.port_state[dp.id]
             assert dp.id not in self.dp_types
             self.dp_types[dp.id] = getattr(dp, 'dp_type', dp_type.UNKNOWN)
 
-            self.ev_q.queue(EventDP(dp, False))
-
     def set_type(self, dp_id, dp_type_=dp_type.UNKNOWN):
         if dp_id in self.dps:
             dp = self.dps[dp_id]
@@ -102,6 +145,34 @@ class DPSet(object):
             LOG.debug('DPSET: unregister datapath %s', datapath)
             self.unregister(datapath)
 
+    @set_ev_cls(ofp_event.EventOFPPortStatus, handler.MAIN_DISPATCHER)
+    def port_status_handler(self, ev):
+        msg = ev.msg
+        reason = msg.reason
+        datapath = msg.datapath
+        port = msg.desc
+        ofproto = datapath.ofproto
+
+        LOG.debug('port status %s', reason)
+
+        if reason == ofproto.OFPPR_ADD:
+            self.port_state[datapath.id].add(port.port_no, port.state)
+            self.ev_q.queue(EventPortAdd(datapath, port))
+        elif reason == ofproto.OFPPR_DELETE:
+            self.port_state[datapath.id].remove(port.port_no)
+            self.ev_q.queue(EventPortDelete(datapath, port))
+        else:
+            assert reason == ofproto.OFPPR_MODIFY
+            self.port_state[datapath.id].modify(port.port_no, port.state)
+            self.ev_q.queue(EventPortModify(datapath, port))
+
+    def get_port_state(self, dpid, port_no):
+        try:
+            return self.port_state[dpid][port_no]
+        except KeyError:
+            raise ryu_exc.PortNotFound(dpid=dpid, port=port_no,
+                                       network_id=None)
+
 
 DISPATCHER_NAME_DPSET = 'dpset'
 DPSET_EV_DISPATCHER = dispatcher.EventDispatcher(DISPATCHER_NAME_DPSET)
-- 
1.7.1.1


------------------------------------------------------------------------------
Better than sec? Nothing is better than sec when it comes to
monitoring Big Data applications. Try Boundary one-second 
resolution app monitoring today. Free.
http://p.sf.net/sfu/Boundary-dev2dev
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to