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