backing up
[vsorcdistro/.git] / ryu / build / lib.linux-armv7l-2.7 / ryu / services / protocols / vrrp / monitor.py
1 # Copyright (C) 2013 Nippon Telegraph and Telephone Corporation.
2 # Copyright (C) 2013 Isaku Yamahata <yamahata at private email ne jp>
3 #
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
7 #
8 #    http://www.apache.org/licenses/LICENSE-2.0
9 #
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
13 # implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16 """
17 Interface monitor.
18 Watching packet received on this interface and parse VRRP packet.
19
20 VRRPManager creates/deletes instances of interface monitor dynamically.
21 """
22
23 from ryu.base import app_manager
24 from ryu.controller import handler
25 from ryu.lib.packet import packet
26 from ryu.lib.packet import vlan
27 from ryu.lib.packet import vrrp
28 from ryu.services.protocols.vrrp import event as vrrp_event
29
30
31 class VRRPInterfaceMonitor(app_manager.RyuApp):
32     # subclass of VRRPInterfaceBase -> subclass of VRRPInterfaceMonitor
33     _CONSTRUCTORS = {}
34
35     @staticmethod
36     def register(interface_cls):
37         def _register(cls):
38             VRRPInterfaceMonitor._CONSTRUCTORS[interface_cls] = cls
39             return cls
40         return _register
41
42     @staticmethod
43     def factory(interface, config, router_name, statistics, *args, **kwargs):
44         cls = VRRPInterfaceMonitor._CONSTRUCTORS[interface.__class__]
45         app_mgr = app_manager.AppManager.get_instance()
46
47         kwargs = kwargs.copy()
48         kwargs['router_name'] = router_name
49         kwargs['vrrp_config'] = config
50         kwargs['vrrp_interface'] = interface
51         kwargs['vrrp_statistics'] = statistics
52         app = app_mgr.instantiate(cls, *args, **kwargs)
53         return app
54
55     @classmethod
56     def instance_name(cls, interface, vrid):
57         return '%s-%s-%d' % (cls.__name__, str(interface), vrid)
58
59     def __init__(self, *args, **kwargs):
60         super(VRRPInterfaceMonitor, self).__init__(*args, **kwargs)
61         self.config = kwargs['vrrp_config']
62         self.interface = kwargs['vrrp_interface']
63         self.router_name = kwargs['router_name']
64         self.statistics = kwargs['vrrp_statistics']
65         self.name = self.instance_name(self.interface, self.config.vrid)
66
67     def _parse_received_packet(self, packet_data):
68         # OF doesn't support VRRP packet matching, so we have to parse
69         # it ourselvs.
70         packet_ = packet.Packet(packet_data)
71         protocols = packet_.protocols
72
73         # we expect either of
74         #   [ether, vlan, ip, vrrp{, padding}]
75         # or
76         #   [ether, ip, vrrp{, padding}]
77
78         if len(protocols) < 2:
79             self.logger.debug('len(protocols) %d', len(protocols))
80             return
81
82         vlan_vid = self.interface.vlan_id
83         may_vlan = protocols[1]
84         if (vlan_vid is not None) != isinstance(may_vlan, vlan.vlan):
85             self.logger.debug('vlan_vid: %s %s', vlan_vid, type(may_vlan))
86             return
87         if vlan_vid is not None and vlan_vid != may_vlan.vid:
88             self.logger.debug('vlan_vid: %s vlan %s', vlan_vid, type(may_vlan))
89             return
90
91         # self.logger.debug('%s %s', packet_, packet_.protocols)
92         may_ip, may_vrrp = vrrp.vrrp.get_payload(packet_)
93         if not may_ip or not may_vrrp:
94             # self.logger.debug('may_ip %s may_vrrp %s', may_ip, may_vrrp)
95             return
96         if not vrrp.vrrp.is_valid_ttl(may_ip):
97             self.logger.debug('valid_ttl')
98             return
99         if may_vrrp.version != self.config.version:
100             self.logger.debug('vrrp version %d %d',
101                               may_vrrp.version, self.config.version)
102             return
103         if not may_vrrp.is_valid():
104             self.logger.debug('valid vrrp')
105             return
106         offset = 0
107         for proto in packet_.protocols:
108             if proto == may_vrrp:
109                 break
110             offset += len(proto)
111         if not may_vrrp.checksum_ok(
112                 may_ip, packet_.data[offset:offset + len(may_vrrp)]):
113             self.logger.debug('bad checksum')
114             return
115         if may_vrrp.vrid != self.config.vrid:
116             self.logger.debug('vrid %d %d', may_vrrp.vrid, self.config.vrid)
117             return
118         if may_vrrp.is_ipv6 != self.config.is_ipv6:
119             self.logger.debug('is_ipv6 %s %s',
120                               may_vrrp.is_ipv6, self.config.is_ipv6)
121             return
122
123         # TODO: Optional check rfc5798 7.1
124         # may_vrrp.ip_addresses equals to self.config.ip_addresses
125         if may_vrrp.priority == 0:
126             self.statistics.rx_vrrp_zero_prio_packets += 1
127
128         vrrp_received = vrrp_event.EventVRRPReceived(self.interface, packet_)
129         self.send_event(self.router_name, vrrp_received)
130         return True
131
132     def _send_vrrp_packet_received(self, packet_data):
133         valid = self._parse_received_packet(packet_data)
134         if valid is True:
135             self.statistics.rx_vrrp_packets += 1
136         else:
137             self.statistics.rx_vrrp_invalid_packets += 1
138
139     @handler.set_ev_handler(vrrp_event.EventVRRPTransmitRequest)
140     def vrrp_transmit_request_handler(self, ev):
141         raise NotImplementedError()
142
143     def _initialize(self):
144         raise NotImplementedError()
145
146     def _shutdown(self):
147         raise NotImplementedError()
148
149     @handler.set_ev_handler(vrrp_event.EventVRRPStateChanged)
150     def vrrp_state_changed_handler(self, ev):
151         assert ev.interface == self.interface
152
153         if ev.new_state == vrrp_event.VRRP_STATE_INITIALIZE:
154             # add/del packet in rule
155             if ev.old_state:
156                 self._shutdown()
157             else:
158                 self._initialize()
159         elif ev.new_state in [vrrp_event.VRRP_STATE_BACKUP,
160                               vrrp_event.VRRP_STATE_MASTER]:
161
162             if ev.old_state == vrrp_event.VRRP_STATE_INITIALIZE:
163                 if ev.new_state == vrrp_event.VRRP_STATE_MASTER:
164                     self.statistics.idle_to_master_transitions += 1
165                 else:
166                     self.statistics.idle_to_backup_transitions += 1
167             elif ev.old_state == vrrp_event.VRRP_STATE_MASTER:
168                 self.statistics.master_to_backup_transitions += 1
169             else:
170                 self.statistics.backup_to_master_transitions += 1
171         else:
172             raise RuntimeError('unknown vrrp state %s' % ev.new_state)