diff options
author | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2013-11-27 06:59:49 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2013-11-27 12:17:43 +0900 |
commit | aab020d0a0e7b261e635bdb23f9b16b139360217 (patch) | |
tree | 070edf1bcc6161607ea61bead9b2a0051a53da8d | |
parent | 8ad764f193c68c9ce5741d1ce3267b7ffb7fc51a (diff) |
vrrp: add statistics support
Supports statistics that Commercial routers provides.
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r-- | ryu/services/protocols/vrrp/event.py | 6 | ||||
-rw-r--r-- | ryu/services/protocols/vrrp/manager.py | 47 | ||||
-rw-r--r-- | ryu/services/protocols/vrrp/monitor.py | 27 | ||||
-rw-r--r-- | ryu/services/protocols/vrrp/router.py | 21 |
4 files changed, 91 insertions, 10 deletions
diff --git a/ryu/services/protocols/vrrp/event.py b/ryu/services/protocols/vrrp/event.py index 1eb4426b..a92ac724 100644 --- a/ryu/services/protocols/vrrp/event.py +++ b/ryu/services/protocols/vrrp/event.py @@ -118,7 +118,8 @@ class VRRPConfig(object): admin_state=None, priority=vrrp.VRRP_PRIORITY_BACKUP_DEFAULT, ip_addresses=None, advertisement_interval=vrrp.VRRP_MAX_ADVER_INT_DEFAULT_IN_SEC, - preempt_mode=True, preempt_delay=0, accept_mode=False): + preempt_mode=True, preempt_delay=0, accept_mode=False, + statistics_interval=None, resource_id=None): # To allow version and priority default assert vrid is not None assert ip_addresses is not None @@ -133,8 +134,9 @@ class VRRPConfig(object): self.preempt_mode = preempt_mode self.preempt_delay = preempt_delay self.accept_mode = accept_mode - self.is_ipv6 = vrrp.is_ipv6(ip_addresses[0]) + self.statistics_interval = statistics_interval + self.resource_id = resource_id @property def address_owner(self): diff --git a/ryu/services/protocols/vrrp/manager.py b/ryu/services/protocols/vrrp/manager.py index 489b9ce8..3b25c64c 100644 --- a/ryu/services/protocols/vrrp/manager.py +++ b/ryu/services/protocols/vrrp/manager.py @@ -25,6 +25,8 @@ PYTHONPATH=. ./bin/ryu-manager --verbose \ ryu.services.protocols.vrrp.dumper """ +import time + from ryu.base import app_manager from ryu.controller import handler from ryu.lib import hub @@ -75,11 +77,13 @@ class VRRPManager(app_manager.RyuApp): self.reply_to_request(ev, rep) return + statistics = VRRPStatistics(name, config.resource_id, + config.statistics_interval) monitor = vrrp_monitor.VRRPInterfaceMonitor.factory( - interface, config, name, *self._args, **self._kwargs) - router = vrrp_router.VRRPRouter.factory( - name, monitor.name, interface, config, *self._args, **self._kwargs) - + interface, config, name, statistics, *self._args, **self._kwargs) + router = vrrp_router.VRRPRouter.factory(name, monitor.name, interface, + config, statistics, + *self._args, **self._kwargs) # Event piping # vrrp_router -> vrrp_manager # EventVRRPStateChanged to vrrp_manager is handled by framework @@ -155,3 +159,38 @@ class VRRPManager(app_manager.RyuApp): vrrp_list = vrrp_event.EventVRRPListReply(instance_list) self.reply_to_request(ev, vrrp_list) + + +class VRRPStatistics(object): + def __init__(self, name, resource_id, statistics_interval): + self.name = name + self.resource_id = resource_id + self.statistics_interval = statistics_interval + self.tx_vrrp_packets = 0 + self.rx_vrrp_packets = 0 + self.rx_vrrp_zero_prio_packets = 0 + self.tx_vrrp_zero_prio_packets = 0 + self.rx_vrrp_invalid_packets = 0 + self.rx_vrrp_bad_auth = 0 + self.idle_to_master_transitions = 0 + self.idle_to_backup_transitions = 0 + self.backup_to_master_transitions = 0 + self.master_to_backup_transitions = 0 + + def get_stats(self): + ts = time.strftime("%Y-%m-%dT%H:%M:%S") + stats_dict = dict( + timestamp=ts, + resource_id=self.resource_id, + tx_vrrp_packets=self.tx_vrrp_packets, + rx_vrrp_packets=self.rx_vrrp_packets, + rx_vrrp_zero_prio_packets=self.rx_vrrp_zero_prio_packets, + tx_vrrp_zero_prio_packets=self.tx_vrrp_zero_prio_packets, + rx_vrrp_invalid_packets=self.rx_vrrp_invalid_packets, + rx_vrrp_bad_auth=self.rx_vrrp_bad_auth, + idle_to_master_transitions=self.idle_to_master_transitions, + idle_to_backup_transitions=self.idle_to_backup_transitions, + backup_to_master_transitions=self.backup_to_master_transitions, + master_to_backup_transitions=self.master_to_backup_transitions + ) + return stats_dict diff --git a/ryu/services/protocols/vrrp/monitor.py b/ryu/services/protocols/vrrp/monitor.py index 8f3bde8f..4821c188 100644 --- a/ryu/services/protocols/vrrp/monitor.py +++ b/ryu/services/protocols/vrrp/monitor.py @@ -40,7 +40,7 @@ class VRRPInterfaceMonitor(app_manager.RyuApp): return _register @staticmethod - def factory(interface, config, router_name, *args, **kwargs): + def factory(interface, config, router_name, statistics, *args, **kwargs): cls = VRRPInterfaceMonitor._CONSTRUCTORS[interface.__class__] app_mgr = app_manager.AppManager.get_instance() @@ -48,6 +48,7 @@ class VRRPInterfaceMonitor(app_manager.RyuApp): kwargs['router_name'] = router_name kwargs['vrrp_config'] = config kwargs['vrrp_interface'] = interface + kwargs['vrrp_statistics'] = statistics app = app_mgr.instantiate(cls, *args, **kwargs) return app @@ -60,9 +61,10 @@ class VRRPInterfaceMonitor(app_manager.RyuApp): self.config = kwargs['vrrp_config'] self.interface = kwargs['vrrp_interface'] self.router_name = kwargs['router_name'] + self.statistics = kwargs['vrrp_statistics'] self.name = self.instance_name(self.interface, self.config.vrid) - def _send_vrrp_packet_received(self, packet_data): + def _parse_received_packet(self, packet_data): # OF doesn't support VRRP packet matching, so we have to parse # it ourselvs. packet_ = packet.Packet(packet_data) @@ -120,9 +122,19 @@ class VRRPInterfaceMonitor(app_manager.RyuApp): # TODO: Optional check rfc5798 7.1 # may_vrrp.ip_addresses equals to self.config.ip_addresses + if may_vrrp.priority == 0: + self.statistics.rx_vrrp_zero_prio_packets += 1 vrrp_received = vrrp_event.EventVRRPReceived(self.interface, packet_) self.send_event(self.router_name, vrrp_received) + return True + + def _send_vrrp_packet_received(self, packet_data): + valid = self._parse_received_packet(packet_data) + if valid is True: + self.statistics.rx_vrrp_packets += 1 + else: + self.statistics.rx_vrrp_invalid_packets += 1 @handler.set_ev_handler(vrrp_event.EventVRRPTransmitRequest) def vrrp_transmit_request_handler(self, ev): @@ -146,6 +158,15 @@ class VRRPInterfaceMonitor(app_manager.RyuApp): self._initialize() elif ev.new_state in [vrrp_event.VRRP_STATE_BACKUP, vrrp_event.VRRP_STATE_MASTER]: - pass + + if ev.old_state == vrrp_event.VRRP_STATE_INITIALIZE: + if ev.new_state == vrrp_event.VRRP_STATE_MASTER: + self.statistics.idle_to_master_transitions += 1 + else: + self.statistics.idle_to_backup_transitions += 1 + elif ev.old_state == vrrp_event.VRRP_STATE_MASTER: + self.statistics.master_to_backup_transitions += 1 + else: + self.statistics.backup_to_master_transitions += 1 else: raise RuntimeError('unknown vrrp state %s' % ev.new_state) diff --git a/ryu/services/protocols/vrrp/router.py b/ryu/services/protocols/vrrp/router.py index 88b6ce9f..ff2290d5 100644 --- a/ryu/services/protocols/vrrp/router.py +++ b/ryu/services/protocols/vrrp/router.py @@ -148,7 +148,8 @@ class VRRPRouter(app_manager.RyuApp): return _register @staticmethod - def factory(name, monitor_name, interface, config, *args, **kwargs): + def factory(name, monitor_name, interface, config, statistics, *args, + **kwargs): cls = VRRPRouter._CONSTRUCTORS[config.version] app_mgr = app_manager.AppManager.get_instance() kwargs = kwargs.copy() @@ -156,6 +157,7 @@ class VRRPRouter(app_manager.RyuApp): kwargs['monitor_name'] = monitor_name kwargs['vrrp_interface'] = interface kwargs['vrrp_config'] = config + kwargs['vrrp_statistics'] = statistics return app_mgr.instantiate(cls, *args, **kwargs) class _EventMasterDown(event.EventBase): @@ -167,12 +169,16 @@ class VRRPRouter(app_manager.RyuApp): class _EventPreemptDelay(event.EventBase): pass + class _EventStatisticsOut(event.EventBase): + pass + def __init__(self, *args, **kwargs): super(VRRPRouter, self).__init__(*args, **kwargs) self.name = kwargs['name'] self.monitor_name = kwargs['monitor_name'] self.interface = kwargs['vrrp_interface'] self.config = kwargs['vrrp_config'] + self.statistics = kwargs['vrrp_statistics'] self.params = VRRPParams(self.config) self.state = None self.state_impl = None @@ -185,6 +191,10 @@ class VRRPRouter(app_manager.RyuApp): self.register_observer(self._EventMasterDown, self.name) self.register_observer(self._EventAdver, self.name) + self.stats_out_timer = TimerEventSender(self, + self._EventStatisticsOut) + self.register_observer(self._EventStatisticsOut, self.name) + def send_advertisement(self, release=False): if self.vrrp is None: config = self.config @@ -200,12 +210,15 @@ class VRRPRouter(app_manager.RyuApp): vrrp.VRRP_PRIORITY_RELEASE_RESPONSIBILITY, vrrp_.max_adver_int, vrrp_.ip_addresses) + if self.vrrp.priority == 0: + self.statistics.tx_vrrp_zero_prio_packets += 1 # create packet frame each time to generate new ip identity interface = self.interface packet_ = vrrp_.create_packet(interface.primary_ip_address, interface.vlan_id) packet_.serialize() vrrp_api.vrrp_transmit(self, self.monitor_name, packet_.data) + self.statistics.tx_vrrp_packets += 1 def state_change(self, new_state): old_state = self.state @@ -256,6 +269,11 @@ class VRRPRouter(app_manager.RyuApp): self.state_impl.vrrp_config_change_request(ev) + @handler.set_ev_handler(_EventStatisticsOut) + def statistics_handler(self, ev): + # sends stats to somewhere here + # print self.statistics.get_stats() + self.stats_out_timer.start(self.statistics.statistics_interval) # RFC defines that start timer, then change the state. # This causes the race between state change and event dispatching. @@ -686,4 +704,5 @@ class VRRPRouterV3(VRRPRouter): self.state_change(vrrp_event.VRRP_STATE_BACKUP) self.master_down_timer.start(params.master_down_interval) + self.stats_out_timer.start(self.statistics.statistics_interval) super(VRRPRouterV3, self).start() |