static route expiry feature support (#12865)
*[Bgpcfgd] static route expiry feature
This commit is contained in:
parent
bbcad1362f
commit
fe9667950c
@ -2,6 +2,7 @@ import os
|
|||||||
import signal
|
import signal
|
||||||
import sys
|
import sys
|
||||||
import syslog
|
import syslog
|
||||||
|
import threading
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
from swsscommon import swsscommon
|
from swsscommon import swsscommon
|
||||||
@ -17,6 +18,7 @@ from .managers_db import BGPDataBaseMgr
|
|||||||
from .managers_intf import InterfaceMgr
|
from .managers_intf import InterfaceMgr
|
||||||
from .managers_setsrc import ZebraSetSrc
|
from .managers_setsrc import ZebraSetSrc
|
||||||
from .managers_static_rt import StaticRouteMgr
|
from .managers_static_rt import StaticRouteMgr
|
||||||
|
from .static_rt_timer import StaticRouteTimer
|
||||||
from .managers_rm import RouteMapMgr
|
from .managers_rm import RouteMapMgr
|
||||||
from .runner import Runner, signal_handler
|
from .runner import Runner, signal_handler
|
||||||
from .template import TemplateFabric
|
from .template import TemplateFabric
|
||||||
@ -27,6 +29,9 @@ from .vars import g_debug
|
|||||||
|
|
||||||
def do_work():
|
def do_work():
|
||||||
""" Main function """
|
""" Main function """
|
||||||
|
st_rt_timer = StaticRouteTimer()
|
||||||
|
thr = threading.Thread(target = st_rt_timer.run)
|
||||||
|
thr.start()
|
||||||
frr = FRR(["bgpd", "zebra", "staticd"])
|
frr = FRR(["bgpd", "zebra", "staticd"])
|
||||||
frr.wait_for_daemons(seconds=20)
|
frr.wait_for_daemons(seconds=20)
|
||||||
#
|
#
|
||||||
@ -59,6 +64,7 @@ def do_work():
|
|||||||
BBRMgr(common_objs, "CONFIG_DB", "BGP_BBR"),
|
BBRMgr(common_objs, "CONFIG_DB", "BGP_BBR"),
|
||||||
# Static Route Managers
|
# Static Route Managers
|
||||||
StaticRouteMgr(common_objs, "CONFIG_DB", "STATIC_ROUTE"),
|
StaticRouteMgr(common_objs, "CONFIG_DB", "STATIC_ROUTE"),
|
||||||
|
StaticRouteMgr(common_objs, "APPL_DB", "STATIC_ROUTE"),
|
||||||
# Route Advertisement Managers
|
# Route Advertisement Managers
|
||||||
AdvertiseRouteMgr(common_objs, "STATE_DB", swsscommon.STATE_ADVERTISE_NETWORK_TABLE_NAME),
|
AdvertiseRouteMgr(common_objs, "STATE_DB", swsscommon.STATE_ADVERTISE_NETWORK_TABLE_NAME),
|
||||||
RouteMapMgr(common_objs, "APPL_DB", swsscommon.APP_BGP_PROFILE_TABLE_NAME),
|
RouteMapMgr(common_objs, "APPL_DB", swsscommon.APP_BGP_PROFILE_TABLE_NAME),
|
||||||
@ -67,6 +73,7 @@ def do_work():
|
|||||||
for mgr in managers:
|
for mgr in managers:
|
||||||
runner.add_manager(mgr)
|
runner.add_manager(mgr)
|
||||||
runner.run()
|
runner.run()
|
||||||
|
thr.join()
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -4,6 +4,7 @@ from .manager import Manager
|
|||||||
from .template import TemplateFabric
|
from .template import TemplateFabric
|
||||||
import socket
|
import socket
|
||||||
from swsscommon import swsscommon
|
from swsscommon import swsscommon
|
||||||
|
from ipaddress import ip_network, IPv4Network
|
||||||
|
|
||||||
class StaticRouteMgr(Manager):
|
class StaticRouteMgr(Manager):
|
||||||
""" This class updates static routes when STATIC_ROUTE table is updated """
|
""" This class updates static routes when STATIC_ROUTE table is updated """
|
||||||
@ -93,11 +94,28 @@ class StaticRouteMgr(Manager):
|
|||||||
Split key into vrf name and prefix.
|
Split key into vrf name and prefix.
|
||||||
:param key: key to split
|
:param key: key to split
|
||||||
:return: vrf name extracted from the key, ip prefix extracted from the key
|
:return: vrf name extracted from the key, ip prefix extracted from the key
|
||||||
|
key example: APPL_DB vrf:5.5.5.0/24, 5.5.5.0/24, vrf:2001::0/64, 2001::0/64
|
||||||
|
CONFIG_DB vrf|5.5.5.0/24, 5.5.5.0/24, vrf|2001::0/64, 2001::0/64
|
||||||
"""
|
"""
|
||||||
if '|' not in key:
|
vrf = ""
|
||||||
return 'default', key
|
prefix = ""
|
||||||
else:
|
|
||||||
|
if '|' in key:
|
||||||
return tuple(key.split('|', 1))
|
return tuple(key.split('|', 1))
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
_ = ip_network(key)
|
||||||
|
vrf, prefix = 'default', key
|
||||||
|
except ValueError:
|
||||||
|
# key in APPL_DB
|
||||||
|
log_debug("static route key {} is not prefix only formart, split with ':'".format(key))
|
||||||
|
output = key.split(':', 1)
|
||||||
|
if len(output) < 2:
|
||||||
|
log_debug("invalid input in APPL_DB {}".format(key))
|
||||||
|
raise ValueError
|
||||||
|
vrf = output[0]
|
||||||
|
prefix = key[len(vrf)+1:]
|
||||||
|
return vrf, prefix
|
||||||
|
|
||||||
def static_route_commands(self, ip_nh_set, cur_nh_set, ip_prefix, vrf):
|
def static_route_commands(self, ip_nh_set, cur_nh_set, ip_prefix, vrf):
|
||||||
diff_set = ip_nh_set.symmetric_difference(cur_nh_set)
|
diff_set = ip_nh_set.symmetric_difference(cur_nh_set)
|
||||||
|
58
src/sonic-bgpcfgd/bgpcfgd/static_rt_timer.py
Normal file
58
src/sonic-bgpcfgd/bgpcfgd/static_rt_timer.py
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
from .log import log_err, log_info, log_debug
|
||||||
|
from swsscommon import swsscommon
|
||||||
|
import time
|
||||||
|
|
||||||
|
class StaticRouteTimer(object):
|
||||||
|
""" This class checks the static routes and deletes those entries that have not been refreshed """
|
||||||
|
def __init__(self):
|
||||||
|
self.db = swsscommon.SonicV2Connector()
|
||||||
|
self.db.connect(self.db.APPL_DB)
|
||||||
|
self.timer = None
|
||||||
|
self.start = None
|
||||||
|
|
||||||
|
DEFAULT_TIMER = 180
|
||||||
|
DEFAULT_SLEEP = 60
|
||||||
|
MAX_TIMER = 1800
|
||||||
|
|
||||||
|
def set_timer(self):
|
||||||
|
""" Check for custom route expiry time in STATIC_ROUTE_EXPIRY_TIME """
|
||||||
|
timer = self.db.get(self.db.APPL_DB, "STATIC_ROUTE_EXPIRY_TIME", "time")
|
||||||
|
if timer is not None:
|
||||||
|
if timer.isdigit():
|
||||||
|
timer = int(timer)
|
||||||
|
if timer > 0 and timer <= self.MAX_TIMER:
|
||||||
|
self.timer = timer
|
||||||
|
return
|
||||||
|
log_err("Custom static route expiry time of {}s is invalid!".format(timer))
|
||||||
|
return
|
||||||
|
|
||||||
|
def alarm(self):
|
||||||
|
""" Clear unrefreshed static routes """
|
||||||
|
static_routes = self.db.keys(self.db.APPL_DB, "STATIC_ROUTE:*")
|
||||||
|
if static_routes is not None:
|
||||||
|
for sr in static_routes:
|
||||||
|
expiry = self.db.get(self.db.APPL_DB, sr, "expiry")
|
||||||
|
if expiry == "false":
|
||||||
|
continue
|
||||||
|
refresh = self.db.get(self.db.APPL_DB, sr, "refresh")
|
||||||
|
if refresh == "true":
|
||||||
|
self.db.set(self.db.APPL_DB, sr, "refresh", "false")
|
||||||
|
log_debug("Refresh status of static route {} is set to false".format(sr))
|
||||||
|
else:
|
||||||
|
self.db.delete(self.db.APPL_DB, sr)
|
||||||
|
log_debug("Static route {} deleted".format(sr))
|
||||||
|
self.start = time.time()
|
||||||
|
return
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
self.start = time.time()
|
||||||
|
while True:
|
||||||
|
self.set_timer()
|
||||||
|
if self.timer:
|
||||||
|
log_info("Static route expiry set to {}s".format(self.timer))
|
||||||
|
time.sleep(self.timer)
|
||||||
|
self.alarm()
|
||||||
|
else:
|
||||||
|
time.sleep(self.DEFAULT_SLEEP)
|
||||||
|
if time.time() - self.start >= self.DEFAULT_TIMER:
|
||||||
|
self.alarm()
|
Reference in New Issue
Block a user