summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2013-11-27 06:59:49 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2013-11-27 12:17:43 +0900
commitaab020d0a0e7b261e635bdb23f9b16b139360217 (patch)
tree070edf1bcc6161607ea61bead9b2a0051a53da8d
parent8ad764f193c68c9ce5741d1ce3267b7ffb7fc51a (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.py6
-rw-r--r--ryu/services/protocols/vrrp/manager.py47
-rw-r--r--ryu/services/protocols/vrrp/monitor.py27
-rw-r--r--ryu/services/protocols/vrrp/router.py21
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()