File: monitor_openflow.py

package info (click to toggle)
python-os-ken 4.1.1-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 21,396 kB
  • sloc: python: 100,059; erlang: 14,517; ansic: 594; sh: 338; makefile: 136
file content (141 lines) | stat: -rw-r--r-- 5,477 bytes parent folder | download | duplicates (5)
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)