1 # Copyright (C) 2013 Nippon Telegraph and Telephone Corporation.
2 # Copyright (C) 2013 Isaku Yamahata <yamahata at private email ne jp>
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 from ryu.controller import handler
18 from ryu.controller import ofp_event
19 from ryu.lib import dpid as dpid_lib
20 from ryu.lib.packet import vrrp
21 from ryu.ofproto import ether
22 from ryu.ofproto import inet
23 from ryu.ofproto import ofproto_v1_2
24 from ryu.ofproto import ofproto_v1_3
25 from ryu.services.protocols.vrrp import monitor
26 from ryu.services.protocols.vrrp import event as vrrp_event
27 from ryu.services.protocols.vrrp import utils
30 @monitor.VRRPInterfaceMonitor.register(vrrp_event.VRRPInterfaceOpenFlow)
31 class VRRPInterfaceMonitorOpenFlow(monitor.VRRPInterfaceMonitor):
33 OFP_VERSIONS = [ofproto_v1_2.OFP_VERSION,
34 ofproto_v1_3.OFP_VERSION] # probably work with OF1.3
36 _TABLE = 0 # generate packet-in in this table
37 _PRIORITY = 0x8000 # default priority
39 def __init__(self, *args, **kwargs):
40 super(VRRPInterfaceMonitorOpenFlow, self).__init__(*args, **kwargs)
41 table = kwargs.get('vrrp_imof_table', None)
43 self._TABLE = int(table)
44 priority = kwargs.get('vrrp_imof_priority', None)
45 if priority is not None:
46 self._PRIORITY = int(priority)
48 @handler.set_ev_cls(ofp_event.EventOFPPacketIn, handler.MAIN_DISPATCHER)
49 def packet_in_handler(self, ev):
50 self.logger.debug('packet_in_handler')
52 datapath = msg.datapath
53 ofproto = datapath.ofproto
55 # TODO: subscribe only the designated datapath
57 if dpid != self.interface.dpid:
58 self.logger.debug('packet_in_handler dpid %s %s',
59 dpid_lib.dpid_to_str(dpid),
60 dpid_lib.dpid_to_str(self.interface.dpid))
64 for field in msg.match.fields:
65 if field.header == ofproto.OXM_OF_IN_PORT:
69 if in_port != self.interface.port_no:
70 self.logger.debug('packet_in_handler in_port %s %s',
71 in_port, self.interface.port_no)
74 self._send_vrrp_packet_received(msg.data)
77 return utils.get_dp(self, self.interface.dpid)
79 @handler.set_ev_handler(vrrp_event.EventVRRPTransmitRequest)
80 def vrrp_transmit_request_handler(self, ev):
84 utils.dp_packet_out(dp, self.interface.port_no, ev.data)
86 def _ofp_match(self, ofproto_parser):
87 is_ipv6 = vrrp.is_ipv6(self.config.ip_addresses[0])
89 kwargs['in_port'] = self.interface.port_no
91 kwargs['eth_dst'] = vrrp.VRRP_IPV6_DST_MAC_ADDRESS
93 vrrp.vrrp_ipv6_src_mac_address(self.config.vrid)
94 kwargs['eth_type'] = ether.ETH_TYPE_IPV6
95 kwargs['ipv6_dst'] = vrrp.VRRP_IPV6_DST_ADDRESS
97 kwargs['eth_dst'] = vrrp.VRRP_IPV4_DST_MAC_ADDRESS
99 vrrp.vrrp_ipv4_src_mac_address(self.config.vrid)
100 kwargs['eth_type'] = ether.ETH_TYPE_IP
101 kwargs['ipv4_dst'] = vrrp.VRRP_IPV4_DST_ADDRESS
103 if self.interface.vlan_id is not None:
104 kwargs['vlan_vid'] = self.interface.vlan_id
105 kwargs['ip_proto'] = inet.IPPROTO_VRRP
106 # OF1.2 doesn't support TTL match.
107 # It needs to be checked by packet in handler
109 return ofproto_parser.OFPMatch(**kwargs)
111 def _initialize(self):
117 ofproto_parser = dp.ofproto_parser
119 match = self._ofp_match(ofproto_parser)
120 utils.dp_flow_mod(dp, self._TABLE, ofproto.OFPFC_DELETE_STRICT,
121 self._PRIORITY, match, [],
122 out_port=ofproto.OFPP_CONTROLLER)
124 match = self._ofp_match(ofproto_parser)
125 actions = [ofproto_parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,
126 ofproto.OFPCML_NO_BUFFER)]
127 instructions = [ofproto_parser.OFPInstructionActions(
128 ofproto.OFPIT_APPLY_ACTIONS, actions)]
129 utils.dp_flow_mod(dp, self._TABLE, ofproto.OFPFC_ADD, self._PRIORITY,
138 match = self._ofp_match(dp.ofproto_parser)
139 utils.dp_flow_mod(dp, self._TABLE, ofproto.OFPFC_DELETE_STRICT,
140 self._PRIORITY, match, [],
141 out_port=ofproto.OFPP_CONTROLLER)