backing up
[vsorcdistro/.git] / ryu / build / lib.linux-armv7l-2.7 / ryu / app / simple_switch_stp.py
1 # Copyright (C) 2013 Nippon Telegraph and Telephone Corporation.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12 # implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 import struct
17
18 from ryu.base import app_manager
19 from ryu.controller.handler import MAIN_DISPATCHER
20 from ryu.controller.handler import set_ev_cls
21 from ryu.ofproto import ofproto_v1_0
22 from ryu.lib import dpid as dpid_lib
23 from ryu.lib import stplib
24 from ryu.lib.mac import haddr_to_str
25
26
27 class SimpleSwitchStp(app_manager.RyuApp):
28     OFP_VERSIONS = [ofproto_v1_0.OFP_VERSION]
29     _CONTEXTS = {'stplib': stplib.Stp}
30
31     def __init__(self, *args, **kwargs):
32         super(SimpleSwitchStp, self).__init__(*args, **kwargs)
33         self.mac_to_port = {}
34         self.stp = kwargs['stplib']
35
36         # Sample of stplib config.
37         #  please refer to stplib.Stp.set_config() for details.
38         """
39         config = {dpid_lib.str_to_dpid('0000000000000001'):
40                      {'bridge': {'priority': 0x8000,
41                                  'max_age': 10},
42                       'ports': {1: {'priority': 0x80},
43                                 2: {'priority': 0x90}}},
44                   dpid_lib.str_to_dpid('0000000000000002'):
45                      {'bridge': {'priority': 0x9000}}}
46         self.stp.set_config(config)
47         """
48
49     def add_flow(self, datapath, in_port, dst, actions):
50         ofproto = datapath.ofproto
51
52         wildcards = ofproto_v1_0.OFPFW_ALL
53         wildcards &= ~ofproto_v1_0.OFPFW_IN_PORT
54         wildcards &= ~ofproto_v1_0.OFPFW_DL_DST
55
56         match = datapath.ofproto_parser.OFPMatch(
57             wildcards, in_port, 0, dst,
58             0, 0, 0, 0, 0, 0, 0, 0, 0)
59
60         mod = datapath.ofproto_parser.OFPFlowMod(
61             datapath=datapath, match=match, cookie=0,
62             command=ofproto.OFPFC_ADD, idle_timeout=0, hard_timeout=0,
63             priority=ofproto.OFP_DEFAULT_PRIORITY,
64             flags=ofproto.OFPFF_SEND_FLOW_REM, actions=actions)
65         datapath.send_msg(mod)
66
67     def delete_flow(self, datapath):
68         ofproto = datapath.ofproto
69
70         wildcards = ofproto_v1_0.OFPFW_ALL
71         match = datapath.ofproto_parser.OFPMatch(
72             wildcards, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
73
74         mod = datapath.ofproto_parser.OFPFlowMod(
75             datapath=datapath, match=match, cookie=0,
76             command=ofproto.OFPFC_DELETE)
77         datapath.send_msg(mod)
78
79     @set_ev_cls(stplib.EventPacketIn, MAIN_DISPATCHER)
80     def packet_in_handler(self, ev):
81         msg = ev.msg
82         datapath = msg.datapath
83         ofproto = datapath.ofproto
84
85         dst, src, _eth_type = struct.unpack_from('!6s6sH', buffer(msg.data), 0)
86
87         dpid = datapath.id
88         self.mac_to_port.setdefault(dpid, {})
89
90         self.logger.debug("packet in %s %s %s %s",
91                           dpid, haddr_to_str(src), haddr_to_str(dst),
92                           msg.in_port)
93
94         # learn a mac address to avoid FLOOD next time.
95         self.mac_to_port[dpid][src] = msg.in_port
96
97         if dst in self.mac_to_port[dpid]:
98             out_port = self.mac_to_port[dpid][dst]
99         else:
100             out_port = ofproto.OFPP_FLOOD
101
102         actions = [datapath.ofproto_parser.OFPActionOutput(out_port)]
103
104         # install a flow to avoid packet_in next time
105         if out_port != ofproto.OFPP_FLOOD:
106             self.add_flow(datapath, msg.in_port, dst, actions)
107
108         out = datapath.ofproto_parser.OFPPacketOut(
109             datapath=datapath, buffer_id=msg.buffer_id, in_port=msg.in_port,
110             actions=actions)
111         datapath.send_msg(out)
112
113     @set_ev_cls(stplib.EventTopologyChange, MAIN_DISPATCHER)
114     def _topology_change_handler(self, ev):
115         dp = ev.dp
116         dpid_str = dpid_lib.dpid_to_str(dp.id)
117         msg = 'Receive topology change event. Flush MAC table.'
118         self.logger.debug("[dpid=%s] %s", dpid_str, msg)
119
120         if dp.id in self.mac_to_port:
121             del self.mac_to_port[dp.id]
122         self.delete_flow(dp)
123
124     @set_ev_cls(stplib.EventPortStateChange, MAIN_DISPATCHER)
125     def _port_state_change_handler(self, ev):
126         dpid_str = dpid_lib.dpid_to_str(ev.dp.id)
127         of_state = {stplib.PORT_STATE_DISABLE: 'DISABLE',
128                     stplib.PORT_STATE_BLOCK: 'BLOCK',
129                     stplib.PORT_STATE_LISTEN: 'LISTEN',
130                     stplib.PORT_STATE_LEARN: 'LEARN',
131                     stplib.PORT_STATE_FORWARD: 'FORWARD'}
132         self.logger.debug("[dpid=%s][port=%d] state=%s",
133                           dpid_str, ev.port_no, of_state[ev.port_state])