mirror of
https://github.com/faucetsdn/ryu.git
synced 2026-05-08 22:06:10 +02:00
vrrp: add statistics support
Supports statistics that Commercial routers provides. Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
This commit is contained in:
parent
8ad764f193
commit
aab020d0a0
@ -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):
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user