Skip to content

Commit 359b80e

Browse files
authored
[master]staticroutebfd process implementation (#13789)
* [BFD] staticroutebfd implementation * To enable the BFD for static route HLD: sonic-net/SONiC#1216
1 parent a09048a commit 359b80e

File tree

9 files changed

+1465
-7
lines changed

9 files changed

+1465
-7
lines changed

dockers/docker-fpm-frr/frr/supervisord/critical_processes.j2

+1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ program:pimd
99
program:frrcfgd
1010
{%- else %}
1111
program:bgpcfgd
12+
program:staticroutebfd
1213
{%- endif %}

dockers/docker-fpm-frr/frr/supervisord/supervisord.conf.j2

+14
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,20 @@ stderr_logfile=syslog
141141
dependent_startup=true
142142
dependent_startup_wait_for=bgpd:running
143143

144+
{% if DEVICE_METADATA.localhost.frr_mgmt_framework_config is defined and DEVICE_METADATA.localhost.frr_mgmt_framework_config == "true" %}
145+
{% else %}
146+
[program:staticroutebfd]
147+
command=/usr/local/bin/staticroutebfd
148+
priority=6
149+
autostart=false
150+
autorestart=false
151+
startsecs=0
152+
stdout_logfile=syslog
153+
stderr_logfile=syslog
154+
dependent_startup=true
155+
dependent_startup_wait_for=bgpd:running
156+
{% endif %}
157+
144158
[program:bgpmon]
145159
command=/usr/local/bin/bgpmon
146160
priority=6

src/sonic-bgpcfgd/bgpcfgd/managers_static_rt.py

+56-5
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ def __init__(self, common_objs, db, table):
2525
self.directory.subscribe([("CONFIG_DB", swsscommon.CFG_DEVICE_METADATA_TABLE_NAME, "localhost/bgp_asn"),], self.on_bgp_asn_change)
2626
self.static_routes = {}
2727
self.vrf_pending_redistribution = set()
28+
self.config_db = None
2829

2930
OP_DELETE = 'DELETE'
3031
OP_ADD = 'ADD'
@@ -41,7 +42,17 @@ def set_handler(self, key, data):
4142
intf_list = arg_list(data['ifname']) if 'ifname' in data else None
4243
dist_list = arg_list(data['distance']) if 'distance' in data else None
4344
nh_vrf_list = arg_list(data['nexthop-vrf']) if 'nexthop-vrf' in data else None
44-
route_tag = self.ROUTE_ADVERTISE_DISABLE_TAG if 'advertise' in data and data['advertise'] == "false" else self.ROUTE_ADVERTISE_ENABLE_TAG
45+
bfd_enable = arg_list(data['bfd']) if 'bfd' in data else None
46+
route_tag = self.ROUTE_ADVERTISE_DISABLE_TAG if 'advertise' in data and data['advertise'] == "false" else self.ROUTE_ADVERTISE_ENABLE_TAG
47+
48+
# bfd enabled route would be handled in staticroutebfd, skip here
49+
if bfd_enable and bfd_enable[0].lower() == "true":
50+
log_debug("{} static route {} bfd flag is true".format(self.db_name, key))
51+
tmp_nh_set, tmp_route_tag = self.static_routes.get(vrf, {}).get(ip_prefix, (IpNextHopSet(is_ipv6), route_tag))
52+
if tmp_nh_set: #clear nexthop set if it is not empty
53+
log_debug("{} static route {} bfd flag is true, cur_nh is not empty, clear it".format(self.db_name, key))
54+
self.static_routes.setdefault(vrf, {}).pop(ip_prefix, None)
55+
return True
4556

4657
try:
4758
ip_nh_set = IpNextHopSet(is_ipv6, bkh_list, nh_list, intf_list, dist_list, nh_vrf_list)
@@ -60,19 +71,59 @@ def set_handler(self, key, data):
6071

6172
if cmd_list:
6273
self.cfg_mgr.push_list(cmd_list)
63-
log_debug("Static route {} is scheduled for updates".format(key))
74+
log_debug("{} Static route {} is scheduled for updates. {}".format(self.db_name, key, str(cmd_list)))
6475
else:
65-
log_debug("Nothing to update for static route {}".format(key))
76+
log_debug("{} Nothing to update for static route {}".format(self.db_name, key))
6677

6778
self.static_routes.setdefault(vrf, {})[ip_prefix] = (ip_nh_set, route_tag)
6879

6980
return True
7081

7182

83+
def skip_appl_del(self, vrf, ip_prefix):
84+
"""
85+
If a static route is bfd enabled, the processed static route is written into application DB by staticroutebfd.
86+
When we disable bfd for that route at runtime, that static route entry will be removed from APPL_DB STATIC_ROUTE_TABLE.
87+
In the case, the StaticRouteMgr(appl_db) cannot uninstall the static route from FRR if the static route is still in CONFIG_DB,
88+
so need this checking (skip appl_db deletion) to avoid race condition between StaticRouteMgr(appl_db) and StaticRouteMgr(config_db)
89+
For more detailed information:
90+
https://github.com/sonic-net/SONiC/blob/master/doc/static-route/SONiC_static_route_bfd_hld.md#bfd-field-changes-from-true-to-false
91+
92+
:param vrf: vrf from the split_key(key) return
93+
:param ip_prefix: ip_prefix from the split_key(key) return
94+
:return: True if the deletion comes from APPL_DB and the vrf|ip_prefix exists in CONFIG_DB, otherwise return False
95+
"""
96+
if self.db_name == "CONFIG_DB":
97+
return False
98+
99+
if self.config_db is None:
100+
self.config_db = swsscommon.SonicV2Connector()
101+
self.config_db.connect(self.config_db.CONFIG_DB)
102+
103+
#just pop local cache if the route exist in config_db
104+
cfg_key = "STATIC_ROUTE|" + vrf + "|" + ip_prefix
105+
nexthop = self.config_db.get(self.config_db.CONFIG_DB, cfg_key, "nexthop")
106+
if nexthop and len(nexthop)>0:
107+
self.static_routes.setdefault(vrf, {}).pop(ip_prefix, None)
108+
return True
109+
110+
if vrf == "default":
111+
cfg_key = "STATIC_ROUTE|" + ip_prefix
112+
nexthop = self.config_db.get(self.config_db.CONFIG_DB, cfg_key, "nexthop")
113+
if nexthop and len(nexthop)>0:
114+
self.static_routes.setdefault(vrf, {}).pop(ip_prefix, None)
115+
return True
116+
117+
return False
118+
72119
def del_handler(self, key):
73120
vrf, ip_prefix = self.split_key(key)
74121
is_ipv6 = TemplateFabric.is_ipv6(ip_prefix)
75122

123+
if self.skip_appl_del(vrf, ip_prefix):
124+
log_debug("{} ignore appl_db static route deletion because of key {} exist in config_db".format(self.db_name, key))
125+
return
126+
76127
ip_nh_set = IpNextHopSet(is_ipv6)
77128
cur_nh_set, route_tag = self.static_routes.get(vrf, {}).get(ip_prefix, (IpNextHopSet(is_ipv6), self.ROUTE_ADVERTISE_DISABLE_TAG))
78129
cmd_list = self.static_route_commands(ip_nh_set, cur_nh_set, ip_prefix, vrf, route_tag, route_tag)
@@ -85,9 +136,9 @@ def del_handler(self, key):
85136

86137
if cmd_list:
87138
self.cfg_mgr.push_list(cmd_list)
88-
log_debug("Static route {} is scheduled for updates".format(key))
139+
log_debug("{} Static route {} is scheduled for updates. {}".format(self.db_name, key, str(cmd_list)))
89140
else:
90-
log_debug("Nothing to update for static route {}".format(key))
141+
log_debug("{} Nothing to update for static route {}".format(self.db_name, key))
91142

92143
self.static_routes.setdefault(vrf, {}).pop(ip_prefix, None)
93144

src/sonic-bgpcfgd/setup.py

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
entry_points = {
1212
'console_scripts': [
1313
'bgpcfgd = bgpcfgd.main:main',
14+
'staticroutebfd = staticroutebfd.main:main',
1415
'bgpmon = bgpmon.bgpmon:main',
1516
]
1617
},

src/sonic-bgpcfgd/staticroutebfd/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)