backing up
[vsorcdistro/.git] / ryu / build / lib.linux-armv7l-2.7 / ryu / services / protocols / vrrp / router.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 """
18 VRRP state machine implementation
19
20 VRRPManager creates/deletes VRRPRounter instances dynamically.
21 """
22
23 import abc
24 import six
25
26 from ryu.base import app_manager
27 from ryu.controller import event
28 from ryu.controller import handler
29 from ryu.lib import hub
30 from ryu.lib.packet import vrrp
31 from ryu.services.protocols.vrrp import event as vrrp_event
32 from ryu.services.protocols.vrrp import api as vrrp_api
33
34
35 # TODO: improve Timer service and move it into framework
36 class Timer(object):
37     def __init__(self, handler_):
38         assert callable(handler_)
39
40         super(Timer, self).__init__()
41         self._handler = handler_
42         self._event = hub.Event()
43         self._thread = None
44
45     def start(self, interval):
46         """interval is in seconds"""
47         if self._thread:
48             self.cancel()
49         self._event.clear()
50         self._thread = hub.spawn(self._timer, interval)
51
52     def cancel(self):
53         if self._thread is None:
54             return
55         self._event.set()
56         hub.joinall([self._thread])
57         self._thread = None
58
59     def is_running(self):
60         return self._thread is not None
61
62     def _timer(self, interval):
63         # Avoid cancellation during execution of self._callable()
64         cancel = self._event.wait(interval)
65         if cancel:
66             return
67
68         self._handler()
69
70
71 class TimerEventSender(Timer):
72     # timeout handler is called by timer thread context.
73     # So in order to actual execution context to application's event thread,
74     # post the event to the application
75     def __init__(self, app, ev_cls):
76         super(TimerEventSender, self).__init__(self._timeout)
77         self._app = app
78         self._ev_cls = ev_cls
79
80     def _timeout(self):
81         self._app.send_event(self._app.name, self._ev_cls())
82
83
84 class VRRPParams(object):
85     def __init__(self, config):
86         self.config = config
87         self.master_adver_interval = None       # In seconds
88
89     @property
90     def skew_time(self):
91         # In seconds
92         config = self.config
93         version = config.version
94         priority = config.priority
95         if config.version == vrrp.VRRP_VERSION_V2:
96             return (256.0 - priority) / 256.0
97         if config.version == vrrp.VRRP_VERSION_V3:
98             return (((256.0 - priority) * self.master_adver_interval) / 256.0)
99         raise ValueError('unknown vrrp version %d' % version)
100
101     @property
102     def master_down_interval(self):
103         # In seconds
104         return (3.0 * self.master_adver_interval) + self.skew_time
105
106
107 @six.add_metaclass(abc.ABCMeta)
108 class VRRPState(object):
109     def __init__(self, vrrp_router):
110         super(VRRPState, self).__init__()
111         self.vrrp_router = vrrp_router
112
113     @abc.abstractmethod
114     def master_down(self, ev):
115         pass
116
117     @abc.abstractmethod
118     def adver(self, ev):
119         pass
120
121     @abc.abstractmethod
122     def preempt_delay(self, ev):
123         pass
124
125     @abc.abstractmethod
126     def vrrp_received(self, ev):
127         pass
128
129     @abc.abstractmethod
130     def vrrp_shutdown_request(self, ev):
131         pass
132
133     @abc.abstractmethod
134     def vrrp_config_change_request(self, ev):
135         pass
136
137
138 class VRRPRouter(app_manager.RyuApp):
139     _EVENTS = [vrrp_event.EventVRRPStateChanged]
140     _CONSTRUCTORS = {}
141     _STATE_MAP = {}     # should be overrided by concrete class
142
143     @staticmethod
144     def register(version):
145         def _register(cls):
146             VRRPRouter._CONSTRUCTORS[version] = cls
147             return cls
148         return _register
149
150     @staticmethod
151     def factory(name, monitor_name, interface, config, statistics, *args,
152                 **kwargs):
153         cls = VRRPRouter._CONSTRUCTORS[config.version]
154         app_mgr = app_manager.AppManager.get_instance()
155         kwargs = kwargs.copy()
156         kwargs['name'] = name
157         kwargs['monitor_name'] = monitor_name
158         kwargs['vrrp_interface'] = interface
159         kwargs['vrrp_config'] = config
160         kwargs['vrrp_statistics'] = statistics
161         return app_mgr.instantiate(cls, *args, **kwargs)
162
163     class _EventMasterDown(event.EventBase):
164         pass
165
166     class _EventAdver(event.EventBase):
167         pass
168
169     class _EventPreemptDelay(event.EventBase):
170         pass
171
172     class _EventStatisticsOut(event.EventBase):
173         pass
174
175     def __init__(self, *args, **kwargs):
176         super(VRRPRouter, self).__init__(*args, **kwargs)
177         self.name = kwargs['name']
178         self.monitor_name = kwargs['monitor_name']
179         self.interface = kwargs['vrrp_interface']
180         self.config = kwargs['vrrp_config']
181         self.statistics = kwargs['vrrp_statistics']
182         self.params = VRRPParams(self.config)
183         self.state = None
184         self.state_impl = None
185         self.vrrp = None
186
187         self.master_down_timer = TimerEventSender(self, self._EventMasterDown)
188         self.adver_timer = TimerEventSender(self, self._EventAdver)
189         self.preempt_delay_timer = TimerEventSender(self,
190                                                     self._EventPreemptDelay)
191         self.register_observer(self._EventMasterDown, self.name)
192         self.register_observer(self._EventAdver, self.name)
193
194         self.stats_out_timer = TimerEventSender(self,
195                                                 self._EventStatisticsOut)
196         self.register_observer(self._EventStatisticsOut, self.name)
197
198     def send_advertisement(self, release=False):
199         if self.vrrp is None:
200             config = self.config
201             max_adver_int = vrrp.vrrp.sec_to_max_adver_int(
202                 config.version, config.advertisement_interval)
203             self.vrrp = vrrp.vrrp.create_version(
204                 config.version, vrrp.VRRP_TYPE_ADVERTISEMENT, config.vrid,
205                 config.priority, max_adver_int, config.ip_addresses)
206
207         vrrp_ = self.vrrp
208         if release:
209             vrrp_ = vrrp_.create(vrrp_.type, vrrp_.vrid,
210                                  vrrp.VRRP_PRIORITY_RELEASE_RESPONSIBILITY,
211                                  vrrp_.max_adver_int, vrrp_.ip_addresses)
212
213         if self.vrrp.priority == 0:
214             self.statistics.tx_vrrp_zero_prio_packets += 1
215         # create packet frame each time to generate new ip identity
216         interface = self.interface
217         packet_ = vrrp_.create_packet(interface.primary_ip_address,
218                                       interface.vlan_id)
219         packet_.serialize()
220         vrrp_api.vrrp_transmit(self, self.monitor_name, packet_.data)
221         self.statistics.tx_vrrp_packets += 1
222
223     def state_change(self, new_state):
224         old_state = self.state
225         self.state = new_state
226         self.state_impl = self._STATE_MAP[new_state](self)
227         state_changed = vrrp_event.EventVRRPStateChanged(
228             self.name, self.monitor_name, self.interface, self.config,
229             old_state, new_state)
230         self.send_event_to_observers(state_changed)
231
232     @handler.set_ev_handler(_EventMasterDown)
233     def master_down_handler(self, ev):
234         self.state_impl.master_down(ev)
235
236     @handler.set_ev_handler(_EventAdver)
237     def adver_handler(self, ev):
238         self.state_impl.adver(ev)
239
240     @handler.set_ev_handler(_EventPreemptDelay)
241     def preempt_delay_handler(self, ev):
242         self.state_impl.preempt_delay(ev)
243
244     @handler.set_ev_handler(vrrp_event.EventVRRPReceived)
245     def vrrp_received_handler(self, ev):
246         self.state_impl.vrrp_received(ev)
247
248     @handler.set_ev_handler(vrrp_event.EventVRRPShutdownRequest)
249     def vrrp_shutdown_request_handler(self, ev):
250         assert ev.instance_name == self.name
251         self.state_impl.vrrp_shutdown_request(ev)
252
253     @handler.set_ev_handler(vrrp_event.EventVRRPConfigChangeRequest)
254     def vrrp_config_change_request_handler(self, ev):
255         config = self.config
256         if ev.priority is not None:
257             config.priority = ev.priority
258         if ev.advertisement_interval is not None:
259             config.advertisement_interval = ev.advertisement_interval
260         if ev.preempt_mode is not None:
261             config.preempt_mode = ev.preempt_mode
262         if ev.preempt_delay is not None:
263             config.preempt_delay = ev.preempt_delay
264         if ev.accept_mode is not None:
265             config.accept_mode = ev.accept_mode
266
267         # force to recreate cached vrrp packet
268         self.vrrp = None
269
270         self.state_impl.vrrp_config_change_request(ev)
271
272     @handler.set_ev_handler(_EventStatisticsOut)
273     def statistics_handler(self, ev):
274         # sends stats to somewhere here
275         # print self.statistics.get_stats()
276         self.stats_out_timer.start(self.statistics.statistics_interval)
277
278 # RFC defines that start timer, then change the state.
279 # This causes the race between state change and event dispatching.
280 # So our implementation does, state change, then start timer
281
282
283 class VRRPV2StateInitialize(VRRPState):
284     # In theory this shouldn't be called.
285     def master_down(self, ev):
286         self.vrrp_router.logger.warning('%s master_down',
287                                         self.__class__.__name__)
288
289     def adver(self, ev):
290         self.vrrp_router.logger.warning('%s adver', self.__class__.__name__)
291
292     def preempt_delay(self, ev):
293         self.vrrp_router.logger.warning('%s preempt_delay',
294                                         self.__class__.__name__)
295
296     def vrrp_received(self, ev):
297         self.vrrp_router.logger.warning('%s vrrp_received',
298                                         self.__class__.__name__)
299
300     def vrrp_shutdown_request(self, ev):
301         self.vrrp_router.logger.warning('%s vrrp_shutdown_request',
302                                         self.__class__.__name__)
303
304     def vrrp_config_change_request(self, ev):
305         self.vrrp_router.logger.warning('%s vrrp_config_change_request',
306                                         self.__class__.__name__)
307
308
309 class VRRPV2StateMaster(VRRPState):
310     def master_down(self, ev):
311         # should not reach here.
312         # In fact this can be happned due to event scheduling
313         vrrp_router = self.vrrp_router
314         vrrp_router.logger.debug('%s master_down %s %s',
315                                  self.__class__.__name__,
316                                  ev.__class__.__name__, vrrp_router.state)
317
318     def _adver(self):
319         vrrp_router = self.vrrp_router
320         vrrp_router.send_advertisement()
321         vrrp_router.adver_timer.start(
322             vrrp_router.config.advertisement_interval)
323
324     def adver(self, ev):
325         self.vrrp_router.logger.debug('%s adver', self.__class__.__name__)
326         self._adver()
327
328     def preempt_delay(self, ev):
329         self.vrrp_router.logger.warning('%s preempt_delay',
330                                         self.__class__.__name__)
331
332     def vrrp_received(self, ev):
333         vrrp_router = self.vrrp_router
334         vrrp_router.logger.debug('%s vrrp_received', self.__class__.__name__)
335
336         ip, vrrp_ = vrrp.vrrp.get_payload(ev.packet)
337         config = vrrp_router.config
338         if vrrp_.priority == 0:
339             vrrp_router.send_advertisement()
340             vrrp_router.adver_timer.start(config.advertisement_interval)
341         else:
342             params = vrrp_router.params
343             if (config.priority < vrrp_.priority or
344                 (config.priority == vrrp_.priority and
345                  vrrp.ip_address_lt(vrrp_router.interface.primary_ip_address,
346                                     ip.src))):
347                 vrrp_router.adver_timer.cancel()
348
349                 vrrp_router.state_change(vrrp_event.VRRP_STATE_BACKUP)
350                 vrrp_router.master_down_timer.start(
351                     params.master_down_interval)
352
353     def vrrp_shutdown_request(self, ev):
354         vrrp_router = self.vrrp_router
355         vrrp_router.logger.debug('%s vrrp_shutdown_request',
356                                  self.__class__.__name__)
357
358         vrrp_router.adver_timer.cancel()
359         vrrp_router.send_advertisement(True)
360         vrrp_router.state_change(vrrp_event.VRRP_STATE_INITIALIZE)
361
362     def vrrp_config_change_request(self, ev):
363         vrrp_router = self.vrrp_router
364         vrrp_router.logger.warning('%s vrrp_config_change_request',
365                                    self.__class__.__name__)
366         if ev.priority is not None or ev.advertisement_interval is not None:
367             vrrp_router.adver_timer.cancel()
368             self._adver()
369
370
371 class VRRPV2StateBackup(VRRPState):
372     def _master_down(self):
373         vrrp_router = self.vrrp_router
374         vrrp_router.send_advertisement()
375
376         # This action should be done router on
377         # EventVRRPStateChanged(VRRP_STATE_BACKUP->VRRP_STATE_MASTER)
378         #
379         # RFC3768 6.4.2 Backup
380         # o  Broadcast a gratuitous ARP request containing the virtual
381         #    router MAC address for each IP address associated with the
382         #    virtual router
383
384         # RACE: actual router has the responsiblity to send garp.
385         #       so due to thread scheduling there is a race between
386         #       actual router sending GARP and VRRPRouter becoming
387         #       master/backup
388
389         vrrp_router.preempt_delay_timer.cancel()
390         vrrp_router.state_change(vrrp_event.VRRP_STATE_MASTER)
391         vrrp_router.adver_timer.start(
392             vrrp_router.config.advertisement_interval)
393
394     def master_down(self, ev):
395         self.vrrp_router.logger.debug('%s master_down',
396                                       self.__class__.__name__)
397         self._master_down()
398
399     def adver(self, ev):
400         # should not reach here
401         # In fact this can be happned due to event scheduling
402         vrrp_router = self.vrrp_router
403         vrrp_router.logger.debug('%s adver %s %s',
404                                  self.__class__.__name__,
405                                  ev.__class__.__name__, vrrp_router.state)
406
407     def preempt_delay(self, ev):
408         self.vrrp_router.logger.warning('%s preempt_delay',
409                                         self.__class__.__name__)
410         self._master_down()
411
412     def vrrp_received(self, ev):
413         vrrp_router = self.vrrp_router
414         vrrp_router.logger.debug('%s vrrp_received', self.__class__.__name__)
415
416         _ip, vrrp_ = vrrp.vrrp.get_payload(ev.packet)
417         if vrrp_.priority == 0:
418             vrrp_router.master_down_timer.start(vrrp_router.params.skew_time)
419         else:
420             config = vrrp_router.config
421             params = vrrp_router.params
422             if (not config.preempt_mode or config.priority <= vrrp_.priority):
423                 vrrp_router.preempt_delay_timer.cancel()
424                 vrrp_router.master_down_timer.start(
425                     params.master_down_interval)
426             elif (config.preempt_mode and config.preempt_delay > 0 and
427                   config.priority > vrrp_.priority):
428                 if not vrrp_router.preempt_delay_timer.is_running():
429                     vrrp_router.preempt_delay_timer.start(config.preempt_delay)
430                 vrrp_router.master_down_timer.start(
431                     params.master_down_interval)
432
433     def vrrp_shutdown_request(self, ev):
434         vrrp_router = self.vrrp_router
435         vrrp_router.logger.debug('%s vrrp_shutdown_request',
436                                  self.__class__.__name__)
437
438         vrrp_router.master_down_timer.cancel()
439         vrrp_router.preempt_delay_timer.cancel()
440         vrrp_router.state_change(vrrp_event.VRRP_STATE_INITIALIZE)
441
442     def vrrp_config_change_request(self, ev):
443         vrrp_router = self.vrrp_router
444         vrrp_router.logger.warning('%s vrrp_config_change_request',
445                                    self.__class__.__name__)
446         if ev.priority is not None and vrrp_router.config.address_owner:
447             vrrp_router.master_down_timer.cancel()
448             self._master_down()
449         if ev.preempt_mode is not None or ev.preempt_delay is not None:
450             vrrp_router.preempt_delay_timer.cancel()
451
452
453 @VRRPRouter.register(vrrp.VRRP_VERSION_V2)
454 class VRRPRouterV2(VRRPRouter):
455     _STATE_MAP = {
456         vrrp_event.VRRP_STATE_INITIALIZE: VRRPV2StateInitialize,
457         vrrp_event.VRRP_STATE_MASTER: VRRPV2StateMaster,
458         vrrp_event.VRRP_STATE_BACKUP: VRRPV2StateBackup,
459     }
460
461     def __init__(self, *args, **kwargs):
462         super(VRRPRouterV2, self).__init__(*args, **kwargs)
463
464     def start(self):
465         params = self.params
466         params.master_adver_interval = self.config.advertisement_interval
467         self.state_change(vrrp_event.VRRP_STATE_INITIALIZE)
468         if self.config.address_owner:
469             self.send_advertisement()
470
471             # This action should be done router on
472             # EventVRRPStateChanged(None->VRRP_STATE_MASTER)
473             #
474             # RFC3768 6.4.1
475             # o  Broadcast a gratuitous ARP request containing the virtual
476             # router MAC address for each IP address associated with the
477             # virtual router.
478
479             self.state_change(vrrp_event.VRRP_STATE_MASTER)
480             self.adver_timer.start(self.config.advertisement_interval)
481         else:
482             self.state_change(vrrp_event.VRRP_STATE_BACKUP)
483             self.master_down_timer.start(params.master_down_interval)
484
485         super(VRRPRouterV2, self).start()
486
487
488 class VRRPV3StateInitialize(VRRPState):
489     # In theory this shouldn't be called.
490     def master_down(self, ev):
491         self.vrrp_router.logger.debug('%s master_down',
492                                       self.__class__.__name__)
493
494     def adver(self, ev):
495         self.vrrp_router.logger.debug('%s adver', self.__class__.__name__)
496
497     def preempt_delay(self, ev):
498         self.vrrp_router.logger.warning('%s preempt_delay',
499                                         self.__class__.__name__)
500
501     def vrrp_received(self, ev):
502         self.vrrp_router.logger.debug('%s vrrp_received',
503                                       self.__class__.__name__)
504
505     def vrrp_shutdown_request(self, ev):
506         self.vrrp_router.logger.debug('%s vrrp_shutdown_request',
507                                       self.__class__.__name__)
508
509     def vrrp_config_change_request(self, ev):
510         self.vrrp_router.logger.warning('%s vrrp_config_change_request',
511                                         self.__class__.__name__)
512
513
514 class VRRPV3StateMaster(VRRPState):
515     def master_down(self, ev):
516         # should not reach here
517         # In fact this can be happned due to event scheduling
518         vrrp_router = self.vrrp_router
519         vrrp_router.logger.debug('%s master_down %s %s',
520                                  self.__class__.__name__,
521                                  ev.__class__.__name__, vrrp_router.state)
522
523     def _adver(self):
524         vrrp_router = self.vrrp_router
525         vrrp_router.send_advertisement()
526         vrrp_router.adver_timer.start(
527             vrrp_router.config.advertisement_interval)
528
529     def adver(self, ev):
530         self.vrrp_router.logger.debug('%s adver', self.__class__.__name__)
531         self._adver()
532
533     def preempt_delay(self, ev):
534         self.vrrp_router.logger.warning('%s preempt_delay',
535                                         self.__class__.__name__)
536
537     def vrrp_received(self, ev):
538         vrrp_router = self.vrrp_router
539         vrrp_router.logger.debug('%s vrrp_received', self.__class__.__name__)
540
541         ip, vrrp_ = vrrp.vrrp.get_payload(ev.packet)
542         config = vrrp_router.config
543         if vrrp_.priority == 0:
544             vrrp_router.send_advertisement()
545             vrrp_router.adver_timer.start(config.advertisement_interval)
546         else:
547             params = vrrp_router.params
548             if (config.priority < vrrp_.priority or
549                 (config.priority == vrrp_.priority and
550                  vrrp.ip_address_lt(vrrp_router.interface.primary_ip_address,
551                                     ip.src))):
552                 vrrp_router.adver_timer.cancel()
553                 params.master_adver_interval = vrrp_.max_adver_int_in_sec
554
555                 vrrp_router.state_change(vrrp_event.VRRP_STATE_BACKUP)
556                 vrrp_router.master_down_timer.start(
557                     params.master_down_interval)
558
559     def vrrp_shutdown_request(self, ev):
560         vrrp_router = self.vrrp_router
561         vrrp_router.logger.debug('%s vrrp_shutdown_request',
562                                  self.__class__.__name__)
563
564         vrrp_router.adver_timer.cancel()
565         vrrp_router.send_advertisement(True)
566         vrrp_router.state_change(vrrp_event.VRRP_STATE_INITIALIZE)
567
568     def vrrp_config_change_request(self, ev):
569         vrrp_router = self.vrrp_router
570         vrrp_router.logger.warning('%s vrrp_config_change_request',
571                                    self.__class__.__name__)
572         if ev.priority is not None or ev.advertisement_interval is not None:
573             vrrp_router.adver_timer.cancel()
574             self._adver()
575
576
577 class VRRPV3StateBackup(VRRPState):
578     def _master_down(self):
579         vrrp_router = self.vrrp_router
580         vrrp_router.send_advertisement()
581
582         # This action should be done by router on
583         # EventStateChange(VRRP_SATE_BACKUP -> VRRP_STATE_MASTER)
584         #
585         # RFC 5795 6.4.2
586         # (375) + If the protected IPvX address is an IPv4 address, then:
587         #   (380) * Broadcast a gratuitous ARP request on that interface
588         #   containing the virtual router MAC address for each IPv4
589         #   address associated with the virtual router.
590         # (385) + else // ipv6
591         #   (390) * Compute and join the Solicited-Node multicast
592         #   address [RFC4291] for the IPv6 address(es) associated with
593         #   the virtual router.
594         #   (395) * For each IPv6 address associated with the virtual
595         #   router, send an unsolicited ND Neighbor Advertisement with
596         #   the Router Flag (R) set, the Solicited Flag (S) unset, the
597         #   Override flag (O) set, the target address set to the IPv6
598         #   address of the virtual router, and the target link-layer
599         #   address set to the virtual router MAC address.
600
601         # RACE: actual router has the responsiblity to send garp.
602         #       so due to thread scheduling there is a race between
603         #       actual router sending GARP and VRRPRouter becoming
604         #       master/backup
605
606         vrrp_router.preempt_delay_timer.cancel()
607         vrrp_router.state_change(vrrp_event.VRRP_STATE_MASTER)
608         vrrp_router.adver_timer.start(
609             vrrp_router.config.advertisement_interval)
610
611     def master_down(self, ev):
612         self.vrrp_router.logger.debug('%s master_down',
613                                       self.__class__.__name__)
614         self._master_down()
615
616     def adver(self, ev):
617         # should not reach here
618         # In fact this can be happned due to event scheduling
619         vrrp_router = self.vrrp_router
620         vrrp_router.logger.debug('adver %s %s %s',
621                                  self.__class__.__name__,
622                                  ev.__class__.__name__, vrrp_router.state)
623
624     def preempt_delay(self, ev):
625         self.vrrp_router.logger.warning('%s preempt_delay',
626                                         self.__class__.__name__)
627         self._master_down()
628
629     def vrrp_received(self, ev):
630         vrrp_router = self.vrrp_router
631         vrrp_router.logger.debug('%s vrrp_received', self.__class__.__name__)
632
633         _ip, vrrp_ = vrrp.vrrp.get_payload(ev.packet)
634         if vrrp_.priority == 0:
635             vrrp_router.master_down_timer.start(vrrp_router.params.skew_time)
636         else:
637             params = vrrp_router.params
638             config = vrrp_router.config
639             if (not config.preempt_mode or config.priority <= vrrp_.priority):
640                 params.master_adver_interval = vrrp_.max_adver_int_in_sec
641                 vrrp_router.master_down_timer.start(
642                     params.master_down_interval)
643             elif (config.preempt_mode and config.preempt_delay > 0 and
644                   config.priority > vrrp_.priority):
645                 if not vrrp_router.preempt_delay_timer.is_running():
646                     vrrp_router.preempt_delay_timer.start(config.preempt_delay)
647                 vrrp_router.master_down_timer.start(
648                     params.master_down_interval)
649
650     def vrrp_shutdown_request(self, ev):
651         vrrp_router = self.vrrp_router
652         vrrp_router.logger.debug('%s vrrp_shutdown_request',
653                                  self.__class__.__name__)
654
655         vrrp_router.preempt_delay_timer.cancel()
656         vrrp_router.master_down_timer.cancel()
657         vrrp_router.state_change(vrrp_event.VRRP_STATE_INITIALIZE)
658
659     def vrrp_config_change_request(self, ev):
660         vrrp_router = self.vrrp_router
661         vrrp_router.logger.warning('%s vrrp_config_change_request',
662                                    self.__class__.__name__)
663         if ev.priority is not None and vrrp_router.config.address_owner:
664             vrrp_router.master_down_timer.cancel()
665             self._master_down()
666         if ev.preempt_mode is not None or ev.preempt_delay is not None:
667             vrrp_router.preempt_delay_timer.cancel()
668
669
670 @VRRPRouter.register(vrrp.VRRP_VERSION_V3)
671 class VRRPRouterV3(VRRPRouter):
672     _STATE_MAP = {
673         vrrp_event.VRRP_STATE_INITIALIZE: VRRPV3StateInitialize,
674         vrrp_event.VRRP_STATE_MASTER: VRRPV3StateMaster,
675         vrrp_event.VRRP_STATE_BACKUP: VRRPV3StateBackup,
676     }
677
678     def __init__(self, *args, **kwargs):
679         super(VRRPRouterV3, self).__init__(*args, **kwargs)
680
681     def start(self):
682         self.state_change(vrrp_event.VRRP_STATE_INITIALIZE)
683         # Check role here and change accordingly
684         # Check config.admin_state
685         if self.config.address_owner or self.config.admin_state == 'master':
686             self.send_advertisement()
687
688             # This action should be done router on
689             # EventVRRPStateChanged(None->VRRP_STATE_MASTER)
690             #
691             # RFC 5795 6.4.1
692             # (115) + If the protected IPvX address is an IPv4 address, then:
693             #   (120) * Broadcast a gratuitous ARP request containing the
694             #   virtual router MAC address for each IP address associated
695             #   with the virtual router.
696             # (125) + else // IPv6
697             #   (130) * For each IPv6 address associated with the virtual
698             #   router, send an unsolicited ND Neighbor Advertisement with
699             #   the Router Flag (R) set, the Solicited Flag (S) unset, the
700             #   Override flag (O) set, the target address set to the IPv6
701             #   address of the virtual router, and the target link-layer
702             #   address set to the virtual router MAC address.
703
704             self.state_change(vrrp_event.VRRP_STATE_MASTER)
705             self.adver_timer.start(self.config.advertisement_interval)
706         else:
707             params = self.params
708             params.master_adver_interval = self.config.advertisement_interval
709             self.state_change(vrrp_event.VRRP_STATE_BACKUP)
710             self.master_down_timer.start(params.master_down_interval)
711
712         self.stats_out_timer.start(self.statistics.statistics_interval)
713         super(VRRPRouterV3, self).start()