Supports statistics that Commercial routers provides.

Signed-off-by: FUJITA Tomonori <[email protected]>
---
 ryu/services/protocols/vrrp/event.py   |  6 +++--
 ryu/services/protocols/vrrp/manager.py | 47 +++++++++++++++++++++++++++++++---
 ryu/services/protocols/vrrp/monitor.py | 27 ++++++++++++++++---
 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 1eb4426..a92ac72 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 489b9ce..3b25c64 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 8f3bde8..4821c18 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 88b6ce9..ff2290d 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()
-- 
1.8.3.4 (Apple Git-47)


------------------------------------------------------------------------------
Rapidly troubleshoot problems before they affect your business. Most IT 
organizations don't have a clear picture of how application performance 
affects their revenue. With AppDynamics, you get 100% visibility into your 
Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics Pro!
http://pubads.g.doubleclick.net/gampad/clk?id=84349351&iu=/4140/ostg.clktrk
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to