ryu/lib/stplib.py : Support OpenFlow 1.2/1.3
ryu/app/simple_switch_stp.py : Correspondence to parameter change of 
stplib.EventPortStateChange


Signed-off-by: WATANABE Fumitaka <watanabe.fumit...@nttcom.co.jp>
---
 ryu/app/simple_switch_stp.py |   10 +--
 ryu/lib/stplib.py            |  173 ++++++++++++++++++++++++++++++++----------
 2 files changed, 140 insertions(+), 43 deletions(-)

diff --git a/ryu/app/simple_switch_stp.py b/ryu/app/simple_switch_stp.py
index cfea26a..8efad14 100644
--- a/ryu/app/simple_switch_stp.py
+++ b/ryu/app/simple_switch_stp.py
@@ -123,10 +123,10 @@ class SimpleSwitchStp(app_manager.RyuApp):
     @set_ev_cls(stplib.EventPortStateChange, stplib.STP_EV_DISPATCHER)
     def _port_state_change_handler(self, ev):
         dpid_str = dpid_lib.dpid_to_str(ev.dp.id)
-        of_state = {ofproto_v1_0.OFPPS_LINK_DOWN: 'DISABLE',
-                    ofproto_v1_0.OFPPS_STP_BLOCK: 'BLOCK',
-                    ofproto_v1_0.OFPPS_STP_LISTEN: 'LISTEN',
-                    ofproto_v1_0.OFPPS_STP_LEARN: 'LEARN',
-                    ofproto_v1_0.OFPPS_STP_FORWARD: 'FORWARD'}
+        of_state = {stplib.PORT_STATE_DISABLE: 'DISABLE',
+                    stplib.PORT_STATE_BLOCK: 'BLOCK',
+                    stplib.PORT_STATE_LISTEN: 'LISTEN',
+                    stplib.PORT_STATE_LEARN: 'LEARN',
+                    stplib.PORT_STATE_FORWARD: 'FORWARD'}
         self.logger.debug("[dpid=%s][port=%d] state=%s",
                           dpid_str, ev.port_no, of_state[ev.port_state])
diff --git a/ryu/lib/stplib.py b/ryu/lib/stplib.py
index bcb77c4..bf6e919 100644
--- a/ryu/lib/stplib.py
+++ b/ryu/lib/stplib.py
@@ -31,6 +31,8 @@ from ryu.lib.packet import ethernet
 from ryu.lib.packet import llc
 from ryu.lib.packet import packet
 from ryu.ofproto import ofproto_v1_0
+from ryu.ofproto import ofproto_v1_2
+from ryu.ofproto import ofproto_v1_3


 STP_EV_DISPATCHER = "stplib"
@@ -38,6 +40,11 @@ STP_EV_DISPATCHER = "stplib"

 MAX_PORT_NO = 0xfff

+# for OpenFlow 1.2/1.3
+BPDU_PKT_IN_PRIORITY = 0xffff
+NO_PKT_IN_PRIORITY = 0xfffe
+
+
 # Result of compared config BPDU priority.
 SUPERIOR = -1
 REPEATED = 0
@@ -84,17 +91,42 @@ NON_DESIGNATED_PORT = 2  # The port which blocked.
 #  LISTEN : Not learning or relaying frames.
 #  LEARN  : Learning but not relaying frames.
 #  FORWARD: Learning and relaying frames.
-PORT_STATE_DISABLE = (ofproto_v1_0.OFPPC_NO_RECV_STP
-                      | ofproto_v1_0.OFPPC_NO_RECV
-                      | ofproto_v1_0.OFPPC_NO_FLOOD
-                      | ofproto_v1_0.OFPPC_NO_FWD)
-PORT_STATE_BLOCK = (ofproto_v1_0.OFPPC_NO_RECV
-                    | ofproto_v1_0.OFPPC_NO_FLOOD
-                    | ofproto_v1_0.OFPPC_NO_FWD)
-PORT_STATE_LISTEN = (ofproto_v1_0.OFPPC_NO_RECV
-                     | ofproto_v1_0.OFPPC_NO_FLOOD)
-PORT_STATE_LEARN = ofproto_v1_0.OFPPC_NO_FLOOD
-PORT_STATE_FORWARD = 0
+PORT_STATE_DISABLE = 0
+PORT_STATE_BLOCK = 1
+PORT_STATE_LISTEN = 2
+PORT_STATE_LEARN = 3
+PORT_STATE_FORWARD = 4
+
+# for OpenFlow 1.0
+PORT_CONFIG_V1_0 = {PORT_STATE_DISABLE: (ofproto_v1_0.OFPPC_NO_RECV_STP
+                                         | ofproto_v1_0.OFPPC_NO_RECV
+                                         | ofproto_v1_0.OFPPC_NO_FLOOD
+                                         | ofproto_v1_0.OFPPC_NO_FWD),
+                    PORT_STATE_BLOCK: (ofproto_v1_0.OFPPC_NO_RECV
+                                       | ofproto_v1_0.OFPPC_NO_FLOOD
+                                       | ofproto_v1_0.OFPPC_NO_FWD),
+                    PORT_STATE_LISTEN: (ofproto_v1_0.OFPPC_NO_RECV
+                                        | ofproto_v1_0.OFPPC_NO_FLOOD),
+                    PORT_STATE_LEARN: ofproto_v1_0.OFPPC_NO_FLOOD,
+                    PORT_STATE_FORWARD: 0}
+
+# for OpenFlow 1.2
+PORT_CONFIG_V1_2 = {PORT_STATE_DISABLE: (ofproto_v1_2.OFPPC_NO_RECV
+                                         | ofproto_v1_2.OFPPC_NO_FWD),
+                    PORT_STATE_BLOCK: (ofproto_v1_2.OFPPC_NO_FWD
+                                       | ofproto_v1_2.OFPPC_NO_PACKET_IN),
+                    PORT_STATE_LISTEN: ofproto_v1_2.OFPPC_NO_PACKET_IN,
+                    PORT_STATE_LEARN: ofproto_v1_2.OFPPC_NO_PACKET_IN,
+                    PORT_STATE_FORWARD: 0}
+
+# for OpenFlow 1.3
+PORT_CONFIG_V1_3 = {PORT_STATE_DISABLE: (ofproto_v1_3.OFPPC_NO_RECV
+                                         | ofproto_v1_3.OFPPC_NO_FWD),
+                    PORT_STATE_BLOCK: (ofproto_v1_3.OFPPC_NO_FWD
+                                       | ofproto_v1_3.OFPPC_NO_PACKET_IN),
+                    PORT_STATE_LISTEN: ofproto_v1_3.OFPPC_NO_PACKET_IN,
+                    PORT_STATE_LEARN: ofproto_v1_3.OFPPC_NO_PACKET_IN,
+                    PORT_STATE_FORWARD: 0}

 """ Port state machine

@@ -128,16 +160,9 @@ class EventTopologyChange(event.EventBase):
 class EventPortStateChange(event.EventBase):
     def __init__(self, dp, port):
         super(EventPortStateChange, self).__init__()
-
-        of_state = {PORT_STATE_DISABLE: ofproto_v1_0.OFPPS_LINK_DOWN,
-                    PORT_STATE_BLOCK: ofproto_v1_0.OFPPS_STP_BLOCK,
-                    PORT_STATE_LISTEN: ofproto_v1_0.OFPPS_STP_LISTEN,
-                    PORT_STATE_LEARN: ofproto_v1_0.OFPPS_STP_LEARN,
-                    PORT_STATE_FORWARD: ofproto_v1_0.OFPPS_STP_FORWARD}
-
         self.dp = dp
         self.port_no = port.ofport.port_no
-        self.port_state = of_state[port.state]
+        self.port_state = port.state


 # Event for receive packet in message except BPDU packet.
@@ -150,7 +175,9 @@ class EventPacketIn(event.EventBase):
 class Stp(app_manager.RyuApp):
     """ STP(spanning tree) library. """

-    OFP_VERSIONS = [ofproto_v1_0.OFP_VERSION]
+    OFP_VERSIONS = [ofproto_v1_0.OFP_VERSION,
+                    ofproto_v1_2.OFP_VERSION,
+                    ofproto_v1_3.OFP_VERSION]

     def __init__(self):
         super(Stp, self).__init__()
@@ -381,6 +408,11 @@ class Bridge(object):
         for ofport in dp.ports.values():
             self.port_add(ofport)

+        # Install BPDU PacketIn flow. (OpenFlow 1.2/1.3)
+        if dp.ofproto == ofproto_v1_2 or dp.ofproto == ofproto_v1_3:
+            ofctl = OfCtl_v1_2later(self.dp)
+            ofctl.add_bpdu_pkt_in_flow()
+
     @property
     def is_root_bridge(self):
         return bool(self.bridge_id.value == self.root_priority.root_id.value)
@@ -420,12 +452,24 @@ class Bridge(object):
             self.recalculate_spanning_tree()

     def packet_in_handler(self, msg):
-        if not msg.in_port in self.ports:
+        dp = msg.datapath
+        if dp.ofproto == ofproto_v1_0:
+            in_port_no = msg.in_port
+        else:
+            assert dp.ofproto == ofproto_v1_2 or dp.ofproto == ofproto_v1_3
+            in_port_no = None
+            for match_field in msg.match.fields:
+                if match_field.header == dp.ofproto.OXM_OF_IN_PORT:
+                    in_port_no = match_field.value
+                    break
+        if not in_port_no in self.ports:
             return

-        pkt = packet.Packet(msg.data)
-        in_port = self.ports[msg.in_port]
+        in_port = self.ports[in_port_no]
+        if in_port.state == PORT_STATE_DISABLE:
+            return

+        pkt = packet.Packet(msg.data)
         if bpdu.ConfigurationBPDUs in pkt:
             """ Receive Configuration BPDU.
                  - If receive superior BPDU:
@@ -443,7 +487,7 @@ class Bridge(object):

             if rcv_info is SUPERIOR:
                 self.logger.info('[port=%d] Receive superior BPDU.',
-                                 msg.in_port, extra=self.dpid_str)
+                                 in_port_no, extra=self.dpid_str)
                 self.recalculate_spanning_tree(init=False)

             elif rcv_tc:
@@ -643,14 +687,6 @@ class Port(object):
                       'path_cost': bpdu.PORT_PATH_COST_10MB,
                       'enable': True}

-    _PATH_COST = {ofproto_v1_0.OFPPF_10MB_HD: bpdu.PORT_PATH_COST_10MB,
-                  ofproto_v1_0.OFPPF_10MB_FD: bpdu.PORT_PATH_COST_10MB,
-                  ofproto_v1_0.OFPPF_100MB_HD: bpdu.PORT_PATH_COST_100MB,
-                  ofproto_v1_0.OFPPF_100MB_FD: bpdu.PORT_PATH_COST_100MB,
-                  ofproto_v1_0.OFPPF_1GB_HD: bpdu.PORT_PATH_COST_1GB,
-                  ofproto_v1_0.OFPPF_1GB_FD: bpdu.PORT_PATH_COST_1GB,
-                  ofproto_v1_0.OFPPF_10GB_FD: bpdu.PORT_PATH_COST_10GB}
-
     def __init__(self, dp, logger, config, send_ev_func, timeout_func,
                  topology_change_func, bridge_id, bridge_times, ofport):
         super(Port, self).__init__()
@@ -662,20 +698,28 @@ class Port(object):
         self.send_event = send_ev_func
         self.wait_bpdu_timeout = timeout_func
         self.topology_change_notify = topology_change_func
-        self.ofctl = OfCtl_v1_0(dp)
+        self.ofctl = (OfCtl_v1_0(dp) if dp.ofproto == ofproto_v1_0
+                      else OfCtl_v1_2later(dp))

         # Bridge data
         self.bridge_id = bridge_id
         # Root bridge data
         self.port_priority = None
         self.port_times = None
-        # ofproto_v1_0_parser.OFPPhyPort data
+        # ofproto_v1_X_parser.OFPPhyPort data
         self.ofport = ofport
         # Port data
         values = self._DEFAULT_VALUE
-        for rate in sorted(self._PATH_COST.keys(), reverse=True):
+        path_costs = {dp.ofproto.OFPPF_10MB_HD: bpdu.PORT_PATH_COST_10MB,
+                      dp.ofproto.OFPPF_10MB_FD: bpdu.PORT_PATH_COST_10MB,
+                      dp.ofproto.OFPPF_100MB_HD: bpdu.PORT_PATH_COST_100MB,
+                      dp.ofproto.OFPPF_100MB_FD: bpdu.PORT_PATH_COST_100MB,
+                      dp.ofproto.OFPPF_1GB_HD: bpdu.PORT_PATH_COST_1GB,
+                      dp.ofproto.OFPPF_1GB_FD: bpdu.PORT_PATH_COST_1GB,
+                      dp.ofproto.OFPPF_10GB_FD: bpdu.PORT_PATH_COST_10GB}
+        for rate in sorted(path_costs.keys(), reverse=True):
             if ofport.curr & rate:
-                values['path_cost'] = self._PATH_COST[rate]
+                values['path_cost'] = path_costs[rate]
                 break
         for key, value in values.items():
             values[key] = value
@@ -1091,9 +1135,62 @@ class OfCtl_v1_0(object):
                                 in_port=self.dp.ofproto.OFPP_CONTROLLER,
                                 actions=actions, data=data)

-    def set_port_status(self, port, config):
+    def set_port_status(self, port, state):
         ofproto_parser = self.dp.ofproto_parser
         mask = 0b1111111
         msg = ofproto_parser.OFPPortMod(self.dp, port.port_no, port.hw_addr,
-                                        config, mask, port.advertised)
+                                        PORT_CONFIG_V1_0[state], mask,
+                                        port.advertised)
+        self.dp.send_msg(msg)
+
+
+class OfCtl_v1_2later(OfCtl_v1_0):
+    def __init__(self, dp):
+        super(OfCtl_v1_2later, self).__init__(dp)
+
+    def set_port_status(self, port, state):
+        ofp = self.dp.ofproto
+        parser = self.dp.ofproto_parser
+        config = {ofproto_v1_2: PORT_CONFIG_V1_2,
+                  ofproto_v1_3: PORT_CONFIG_V1_3}
+
+        mask = 0b1111111
+        msg = parser.OFPPortMod(self.dp, port.port_no, port.hw_addr,
+                                config[ofp][state], mask, port.advertised)
         self.dp.send_msg(msg)
+
+        if config[ofp][state] & ofp.OFPPC_NO_PACKET_IN:
+            self.add_no_pkt_in_flow(port.port_no)
+        else:
+            self.del_no_pkt_in_flow(port.port_no)
+
+    def add_bpdu_pkt_in_flow(self):
+        ofp = self.dp.ofproto
+        parser = self.dp.ofproto_parser
+
+        match = parser.OFPMatch(eth_dst=bpdu.BRIDGE_GROUP_ADDRESS)
+        actions = [parser.OFPActionOutput(ofp.OFPP_CONTROLLER,
+                                          ofp.OFPCML_NO_BUFFER)]
+        inst = [parser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS,
+                                             actions)]
+        mod = parser.OFPFlowMod(self.dp, priority=BPDU_PKT_IN_PRIORITY,
+                                match=match, instructions=inst)
+        self.dp.send_msg(mod)
+
+    def add_no_pkt_in_flow(self, in_port):
+        parser = self.dp.ofproto_parser
+
+        match = parser.OFPMatch(in_port=in_port)
+        mod = parser.OFPFlowMod(self.dp, priority=NO_PKT_IN_PRIORITY,
+                                match=match)
+        self.dp.send_msg(mod)
+
+    def del_no_pkt_in_flow(self, in_port):
+        ofp = self.dp.ofproto
+        parser = self.dp.ofproto_parser
+
+        match = parser.OFPMatch(in_port=in_port)
+        mod = parser.OFPFlowMod(self.dp, command=ofp.OFPFC_DELETE_STRICT,
+                                out_port=ofp.OFPP_ANY, out_group=ofp.OFPG_ANY,
+                                priority=NO_PKT_IN_PRIORITY, match=match)
+        self.dp.send_msg(mod)
-- 1.7.10.4



------------------------------------------------------------------------------
Sponsored by Intel(R) XDK 
Develop, test and display web and hybrid apps with a single code base.
Download it for free now!
http://pubads.g.doubleclick.net/gampad/clk?id=111408631&iu=/4140/ostg.clktrk
_______________________________________________
Ryu-devel mailing list
Ryu-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to