Skip to content

Commit 39aab70

Browse files
committed
[chassis] Added support of isolating given LC in Chassis with TSA mode (#16732)
What I did: Added support when TSA is done on Line Card make sure it's completely isolated from all e-BGP peer devices from this LC or remote LC Why I did: Currently when TSA is executed on LC routes are withdrawn from it's connected e-BGP peers only. e-BGP peers on remote LC can/will (via i-BGP) still have route pointing/attracting traffic towards this isolated LC. How I did: When TSA is applied on LC all the routes that are advertised via i-BGP are set with community tag of no-export so that when remote LC received these routes it does not send over to it's connected e-BGP peers. Also once we receive the route with no-export over iBGP match on it and and set the local preference of that route to lower value (80) so that we remove that route from the forwarding database. Below scenario explains why we do this: - LC1 advertise R1 to LC3 - LC2 advertise R1 to LC3 - On LC3 we have multi-path/ECMP over both LC1 and LC2 - On LC3 R1 received from LC1 is consider best route over R1 over received from LC2 and is send to LC3 e-BGP peers - Now we do TSA on LC2 - LC3 will receive R1 from LC2 with community no-export and from LC1 same as earlier (no change) - LC3 will still get traffic for R1 since it is still advertised to e-BGP peers (since R1 from LC1 is best route) - LC3 will forward to both LC1 and LC2 (ecmp) and this causes issue as LC2 is in TSA mode and should not receive traffic To fix above scenario we change the preference to lower value of R1 received from LC2 so that it is removed from Multi-path/ECMP group. How I verfiy: UT has been added to make sure Template generation is correct Manual Verification of the functionality sonic-mgmt test case will be updated accordingly. Please note this PR is on top of this :#16714 which needs to be merged first. Signed-off-by: Abhishek Dosi <[email protected]>
1 parent 306175b commit 39aab70

File tree

13 files changed

+171
-14
lines changed

13 files changed

+171
-14
lines changed

dockers/docker-fpm-frr/TS

+18-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@ switch_type=`sonic-cfggen -d -v "DEVICE_METADATA['localhost']['switch_type']"`
44
# Check whether the routemap is for internal BGP sessions.
55
function is_internal_route_map()
66
{
7-
[[ "$1" =~ .*"_INTERNAL_".* || "$1" =~ .*"VOQ_".* ]]
7+
if [[ "$1" =~ .*"_INTERNAL_".* || "$1" =~ .*"VOQ_".* ]]
8+
then
9+
return 1
10+
else
11+
return 0
12+
fi
813
}
914

1015
function check_not_installed()
@@ -13,7 +18,10 @@ function check_not_installed()
1318
config=$(vtysh -c "show run")
1419
for route_map_name in $(echo "$config" | sed -ne 's/ neighbor \S* route-map \(\S*\) out/\1/p' | egrep 'V4|V6' | uniq);
1520
do
16-
is_internal_route_map $route_map_name && continue
21+
is_internal_route_map $route_map_name
22+
if [[ $? -eq 1 ]]; then
23+
continue
24+
fi
1725
echo "$config" | egrep -q "^route-map $route_map_name permit 20$"
1826
c=$((c+$?))
1927
echo "$config" | egrep -q "^route-map $route_map_name permit 30$"
@@ -31,7 +39,10 @@ function check_installed()
3139
config=$(vtysh -c "show run")
3240
for route_map_name in $(echo "$config" | sed -ne 's/ neighbor \S* route-map \(\S*\) out/\1/p' | egrep 'V4|V6' | uniq);
3341
do
34-
is_internal_route_map $route_map_name && continue
42+
is_internal_route_map $route_map_name
43+
if [[ $? -eq 1 ]]; then
44+
continue
45+
fi
3546
echo "$config" | egrep -q "^route-map $route_map_name permit 20$"
3647
c=$((c+$?))
3748
e=$((e+1))
@@ -51,7 +62,10 @@ function find_num_routemap()
5162
config=$(vtysh -c "show run")
5263
for route_map_name in $(echo "$config" | sed -ne 's/ neighbor \S* route-map \(\S*\) out/\1/p' | egrep 'V4|V6' | uniq);
5364
do
54-
is_internal_route_map $route_map_name && continue
65+
is_internal_route_map $route_map_name
66+
if [[ $? -eq 1 ]]; then
67+
continue
68+
fi
5569
c=$((c+1))
5670
done
5771
return $c

dockers/docker-fpm-frr/TSA

+3-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ then
1616
TSA_FILE=$(mktemp)
1717
for route_map_name in $(echo "$config" | sed -ne 's/ neighbor \S* route-map \(\S*\) out/\1/p' | uniq);
1818
do
19-
is_internal_route_map $route_map_name && continue
19+
is_internal_route_map $route_map_name
20+
internal_route_map=$?
2021
case "$route_map_name" in
2122
*V4*)
2223
ip_version=V4
@@ -30,7 +31,7 @@ then
3031
continue
3132
;;
3233
esac
33-
sonic-cfggen -d -a "{\"route_map_name\":\"$route_map_name\", \"ip_version\": \"$ip_version\", \"ip_protocol\": \"$ip_protocol\"}" -y /etc/sonic/constants.yml -t /usr/share/sonic/templates/bgpd/tsa/bgpd.tsa.isolate.conf.j2 > "$TSA_FILE"
34+
sonic-cfggen -d -a "{\"route_map_name\":\"$route_map_name\", \"ip_version\": \"$ip_version\", \"ip_protocol\": \"$ip_protocol\", \"internal_route_map\": \"$internal_route_map\"}" -y /etc/sonic/constants.yml -t /usr/share/sonic/templates/bgpd/tsa/bgpd.tsa.isolate.conf.j2 > "$TSA_FILE"
3435
vtysh -f "$TSA_FILE"
3536
rm -f "$TSA_FILE"
3637
done

dockers/docker-fpm-frr/TSB

+3-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ then
1616
TSB_FILE=$(mktemp)
1717
for route_map_name in $(echo "$config" | sed -ne 's/ neighbor \S* route-map \(\S*\) out/\1/p' | uniq);
1818
do
19-
is_internal_route_map $route_map_name && continue
19+
is_internal_route_map $route_map_name
20+
internal_route_map=$?
2021
case "$route_map_name" in
2122
*V4*)
2223
;;
@@ -26,7 +27,7 @@ then
2627
continue
2728
;;
2829
esac
29-
sonic-cfggen -d -a "{\"route_map_name\":\"$route_map_name\"}" -t /usr/share/sonic/templates/bgpd/tsa/bgpd.tsa.unisolate.conf.j2 > "$TSB_FILE"
30+
sonic-cfggen -d -a "{\"route_map_name\":\"$route_map_name\", \"internal_route_map\": \"$internal_route_map\"}" -t /usr/share/sonic/templates/bgpd/tsa/bgpd.tsa.unisolate.conf.j2 > "$TSB_FILE"
3031
vtysh -f "$TSB_FILE"
3132
rm -f "$TSB_FILE"
3233
done

dockers/docker-fpm-frr/frr/bgpd/templates/internal/policies.conf.j2

+9
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,17 @@ route-map FROM_BGP_INTERNAL_PEER_V6 permit 2
1616
set originator-id {{ get_ipv4_loopback_address(CONFIG_DB__LOOPBACK_INTERFACE, "Loopback4096") | ip }}
1717
{% elif CONFIG_DB__DEVICE_METADATA['localhost']['switch_type'] == 'chassis-packet' %}
1818
bgp community-list standard DEVICE_INTERNAL_COMMUNITY permit {{ constants.bgp.internal_community }}
19+
bgp community-list standard NO_EXPORT permit no-export
1920
!
2021
route-map FROM_BGP_INTERNAL_PEER_V4 permit 1
2122
match community DEVICE_INTERNAL_COMMUNITY
2223
set comm-list DEVICE_INTERNAL_COMMUNITY delete
2324
set tag {{ constants.bgp.internal_community_match_tag }}
2425
!
26+
route-map FROM_BGP_INTERNAL_PEER_V4 permit 2
27+
match community NO_EXPORT
28+
set local-preference 80
29+
!
2530
route-map FROM_BGP_INTERNAL_PEER_V6 permit 1
2631
set ipv6 next-hop prefer-global
2732
on-match next
@@ -31,6 +36,10 @@ route-map FROM_BGP_INTERNAL_PEER_V6 permit 2
3136
set comm-list DEVICE_INTERNAL_COMMUNITY delete
3237
set tag {{ constants.bgp.internal_community_match_tag }}
3338
!
39+
route-map FROM_BGP_INTERNAL_PEER_V6 permit 3
40+
match community NO_EXPORT
41+
set local-preference 80
42+
!
3443
route-map TO_BGP_INTERNAL_PEER_V4 permit 1
3544
match ip address prefix-list PL_LoopbackV4
3645
set community {{ constants.bgp.internal_community }}

dockers/docker-fpm-frr/frr/bgpd/templates/voq_chassis/policies.conf.j2

+9
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,17 @@
22
! template: bgpd/templates/voq_chassis/policies.conf.j2
33
!
44
bgp community-list standard DEVICE_INTERNAL_COMMUNITY permit {{ constants.bgp.internal_community }}
5+
bgp community-list standard NO_EXPORT permit no-export
56
!
67
route-map FROM_VOQ_CHASSIS_V4_PEER permit 1
78
match community DEVICE_INTERNAL_COMMUNITY
89
set comm-list DEVICE_INTERNAL_COMMUNITY delete
910
set tag {{ constants.bgp.internal_community_match_tag }}
1011
!
12+
route-map FROM_VOQ_CHASSIS_V4_PEER permit 2
13+
match community NO_EXPORT
14+
set local-preference 80
15+
!
1116
route-map FROM_VOQ_CHASSIS_V4_PEER permit 100
1217
!
1318
route-map TO_VOQ_CHASSIS_V4_PEER permit 1
@@ -26,6 +31,10 @@ route-map FROM_VOQ_CHASSIS_V6_PEER permit 2
2631
set comm-list DEVICE_INTERNAL_COMMUNITY delete
2732
set tag {{ constants.bgp.internal_community_match_tag }}
2833
!
34+
route-map FROM_VOQ_CHASSIS_V6_PEER permit 3
35+
match community NO_EXPORT
36+
set local-preference 80
37+
!
2938
route-map FROM_VOQ_CHASSIS_V6_PEER permit 100
3039
!
3140
route-map TO_VOQ_CHASSIS_V6_PEER permit 1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
1+
{%- if internal_route_map == '1' -%}
2+
route-map {{ route_map_name }} permit 20
3+
set community no-export additive
4+
{# #}
5+
{%- else -%}
16
route-map {{ route_map_name }} permit 20
27
match {{ ip_protocol }} address prefix-list PL_Loopback{{ ip_version }}
38
set community {{ constants.bgp.traffic_shift_community }}
49
route-map {{ route_map_name }} permit 30
510
match tag {{ constants.bgp.internal_community_match_tag }}
611
set community {{ constants.bgp.traffic_shift_community }}
712
route-map {{ route_map_name }} deny 40
13+
{# #}
14+
{%- endif -%}
815
!
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1+
{%- if internal_route_map == '1' -%}
2+
no route-map {{ route_map_name }} permit 20
3+
{# #}
4+
{%- else -%}
15
no route-map {{ route_map_name }} permit 20
26
no route-map {{ route_map_name }} permit 30
37
no route-map {{ route_map_name }} deny 40
8+
{# #}
9+
{%- endif -%}
410
!

src/sonic-bgpcfgd/bgpcfgd/managers_device_global.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -91,14 +91,16 @@ def __generate_routemaps_from_template(self, route_map_names, template):
9191
# For packet-based chassis, the bgp session between the linecards are also considered internal sessions
9292
# While isolating a single linecard, these sessions should not be skipped
9393
if "_INTERNAL_" in rm or "VOQ_" in rm:
94-
continue
94+
is_internal="1"
95+
else:
96+
is_internal="0"
9597
if "V4" in rm:
9698
ipv="V4" ; ipp="ip"
9799
elif "V6" in rm:
98100
ipv="V6" ; ipp="ipv6"
99101
else:
100102
continue
101-
cmd += template.render(route_map_name=rm,ip_version=ipv,ip_protocol=ipp, constants=self.constants)
103+
cmd += template.render(route_map_name=rm,ip_version=ipv,ip_protocol=ipp,internal_route_map=is_internal, constants=self.constants)
102104
cmd += "\n"
103105
return cmd
104106

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
!
2+
! template: bgpd/templates/internal/peer-group.conf.j2
3+
!
4+
neighbor INTERNAL_PEER_V4 peer-group
5+
neighbor INTERNAL_PEER_V6 peer-group
6+
neighbor INTERNAL_PEER_V4 update-source Loopback4096
7+
address-family ipv4
8+
neighbor INTERNAL_PEER_V4 soft-reconfiguration inbound
9+
neighbor INTERNAL_PEER_V4 allowas-in 1
10+
neighbor INTERNAL_PEER_V4 route-map FROM_BGP_INTERNAL_PEER_V4 in
11+
neighbor INTERNAL_PEER_V4 route-map TO_BGP_INTERNAL_PEER_V4 out
12+
neighbor INTERNAL_PEER_V4 send-community
13+
neighbor INTERNAL_PEER_V4 ttl-security hops 1
14+
exit-address-family
15+
neighbor INTERNAL_PEER_V6 update-source Loopback4096
16+
address-family ipv6
17+
neighbor INTERNAL_PEER_V6 soft-reconfiguration inbound
18+
neighbor INTERNAL_PEER_V6 allowas-in 1
19+
neighbor INTERNAL_PEER_V6 route-map FROM_BGP_INTERNAL_PEER_V6 in
20+
neighbor INTERNAL_PEER_V6 route-map TO_BGP_INTERNAL_PEER_V6 out
21+
neighbor INTERNAL_PEER_V6 send-community
22+
neighbor INTERNAL_PEER_V6 ttl-security hops 1
23+
exit-address-family
24+
!
25+
! end of template: bgpd/templates/internal/peer-group.conf.j2
26+
!
27+
28+
29+
route-map TO_BGP_INTERNAL_PEER_V4 permit 20
30+
set community no-export additive
31+
!
32+
route-map TO_BGP_INTERNAL_PEER_V6 permit 20
33+
set community no-export additive
34+
!
35+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
!
2+
! template: bgpd/templates/internal/peer-group.conf.j2
3+
!
4+
neighbor INTERNAL_PEER_V4 peer-group
5+
neighbor INTERNAL_PEER_V6 peer-group
6+
neighbor INTERNAL_PEER_V4 update-source Loopback4096
7+
address-family ipv4
8+
neighbor INTERNAL_PEER_V4 soft-reconfiguration inbound
9+
neighbor INTERNAL_PEER_V4 allowas-in 1
10+
neighbor INTERNAL_PEER_V4 route-map FROM_BGP_INTERNAL_PEER_V4 in
11+
neighbor INTERNAL_PEER_V4 route-map TO_BGP_INTERNAL_PEER_V4 out
12+
neighbor INTERNAL_PEER_V4 send-community
13+
neighbor INTERNAL_PEER_V4 ttl-security hops 1
14+
exit-address-family
15+
neighbor INTERNAL_PEER_V6 update-source Loopback4096
16+
address-family ipv6
17+
neighbor INTERNAL_PEER_V6 soft-reconfiguration inbound
18+
neighbor INTERNAL_PEER_V6 allowas-in 1
19+
neighbor INTERNAL_PEER_V6 route-map FROM_BGP_INTERNAL_PEER_V6 in
20+
neighbor INTERNAL_PEER_V6 route-map TO_BGP_INTERNAL_PEER_V6 out
21+
neighbor INTERNAL_PEER_V6 send-community
22+
neighbor INTERNAL_PEER_V6 ttl-security hops 1
23+
exit-address-family
24+
!
25+
! end of template: bgpd/templates/internal/peer-group.conf.j2
26+
!
27+
28+
29+
no route-map TO_BGP_INTERNAL_PEER_V4 permit 20
30+
!
31+
no route-map TO_BGP_INTERNAL_PEER_V6 permit 20
32+
!
33+

src/sonic-bgpcfgd/tests/data/internal/policies.conf/result_chasiss_packet.conf

+9
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,17 @@
22
! template: bgpd/templates/internal/policies.conf.j2
33
!
44
bgp community-list standard DEVICE_INTERNAL_COMMUNITY permit 12345:556
5+
bgp community-list standard NO_EXPORT permit no-export
56
!
67
route-map FROM_BGP_INTERNAL_PEER_V4 permit 1
78
match community DEVICE_INTERNAL_COMMUNITY
89
set comm-list DEVICE_INTERNAL_COMMUNITY delete
910
set tag 101
1011
!
12+
route-map FROM_BGP_INTERNAL_PEER_V4 permit 2
13+
match community NO_EXPORT
14+
set local-preference 80
15+
!
1116
route-map FROM_BGP_INTERNAL_PEER_V6 permit 1
1217
set ipv6 next-hop prefer-global
1318
on-match next
@@ -17,6 +22,10 @@ route-map FROM_BGP_INTERNAL_PEER_V6 permit 2
1722
set comm-list DEVICE_INTERNAL_COMMUNITY delete
1823
set tag 101
1924
!
25+
route-map FROM_BGP_INTERNAL_PEER_V6 permit 3
26+
match community NO_EXPORT
27+
set local-preference 80
28+
!
2029
route-map TO_BGP_INTERNAL_PEER_V4 permit 1
2130
match ip address prefix-list PL_LoopbackV4
2231
set community 12345:556

src/sonic-bgpcfgd/tests/data/voq_chassis/policies.conf/result_base.conf

+9
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,17 @@
22
! template: bgpd/templates/voq_chassis/policies.conf.j2
33
!
44
bgp community-list standard DEVICE_INTERNAL_COMMUNITY permit 12345:556
5+
bgp community-list standard NO_EXPORT permit no-export
56
!
67
route-map FROM_VOQ_CHASSIS_V4_PEER permit 1
78
match community DEVICE_INTERNAL_COMMUNITY
89
set comm-list DEVICE_INTERNAL_COMMUNITY delete
910
set tag 101
1011
!
12+
route-map FROM_VOQ_CHASSIS_V4_PEER permit 2
13+
match community NO_EXPORT
14+
set local-preference 80
15+
!
1116
route-map FROM_VOQ_CHASSIS_V4_PEER permit 100
1217
!
1318
route-map TO_VOQ_CHASSIS_V4_PEER permit 1
@@ -25,6 +30,10 @@ route-map FROM_VOQ_CHASSIS_V6_PEER permit 2
2530
set comm-list DEVICE_INTERNAL_COMMUNITY delete
2631
set tag 101
2732
!
33+
route-map FROM_VOQ_CHASSIS_V6_PEER permit 3
34+
match community NO_EXPORT
35+
set local-preference 80
36+
!
2837
route-map FROM_VOQ_CHASSIS_V6_PEER permit 100
2938
!
3039
route-map TO_VOQ_CHASSIS_V6_PEER permit 1

src/sonic-bgpcfgd/tests/test_device_global.py

+26-4
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,15 @@
1111

1212
TEMPLATE_PATH = os.path.abspath('../../dockers/docker-fpm-frr/frr')
1313
BASE_PATH = os.path.abspath('../sonic-bgpcfgd/tests/data/general/peer-group.conf/')
14+
INTERNAL_BASE_PATH = os.path.abspath('../sonic-bgpcfgd/tests/data/internal/peer-group.conf/')
1415
global_constants = {
1516
"bgp": {
1617
"traffic_shift_community" :"12345:12345",
1718
"internal_community_match_tag" : "1001"
1819
}
1920
}
2021

21-
def constructor():
22+
def constructor(check_internal=False):
2223
cfg_mgr = MagicMock()
2324
def get_text():
2425
text = []
@@ -29,7 +30,10 @@ def get_text():
2930
text += [" "]
3031
return text
3132
def update():
32-
cfg_mgr.changes = get_string_from_file("/result_all.conf")
33+
if check_internal:
34+
cfg_mgr.changes = get_string_from_file("/result_chasiss_packet.conf", INTERNAL_BASE_PATH)
35+
else:
36+
cfg_mgr.changes = get_string_from_file("/result_all.conf")
3337
def push(cfg):
3438
cfg_mgr.changes += cfg + "\n"
3539
def get_config():
@@ -59,6 +63,15 @@ def test_isolate_device(mocked_log_info):
5963
mocked_log_info.assert_called_with("DeviceGlobalCfgMgr::Done")
6064
assert m.cfg_mgr.get_config() == get_string_from_file("/result_all_isolate.conf")
6165

66+
@patch('bgpcfgd.managers_device_global.log_debug')
67+
def test_isolate_device_internal_session(mocked_log_info):
68+
m = constructor(check_internal=True)
69+
res = m.set_handler("STATE", {"tsa_enabled": "true"})
70+
assert res, "Expect True return value for set_handler"
71+
mocked_log_info.assert_called_with("DeviceGlobalCfgMgr::Done")
72+
assert m.cfg_mgr.get_config() == get_string_from_file("/result_chassis_packet_isolate.conf", INTERNAL_BASE_PATH)
73+
74+
6275
@patch('bgpcfgd.managers_device_global.log_debug')
6376
def test_unisolate_device(mocked_log_info):
6477
m = constructor()
@@ -67,6 +80,15 @@ def test_unisolate_device(mocked_log_info):
6780
mocked_log_info.assert_called_with("DeviceGlobalCfgMgr::Done")
6881
assert m.cfg_mgr.get_config() == get_string_from_file("/result_all_unisolate.conf")
6982

83+
@patch('bgpcfgd.managers_device_global.log_debug')
84+
def test_unisolate_device_internal_session(mocked_log_info):
85+
m = constructor(check_internal=True)
86+
res = m.set_handler("STATE", {"tsa_enabled": "false"})
87+
assert res, "Expect True return value for set_handler"
88+
mocked_log_info.assert_called_with("DeviceGlobalCfgMgr::Done")
89+
assert m.cfg_mgr.get_config() == get_string_from_file("/result_chassis_packet_unisolate.conf", INTERNAL_BASE_PATH)
90+
91+
7092
def test_check_state_and_get_tsa_routemaps():
7193
m = constructor()
7294
m.set_handler("STATE", {"tsa_enabled": "true"})
@@ -93,8 +115,8 @@ def test_get_tsb_routemaps():
93115
expected_res = get_string_from_file("/result_unisolate.conf")
94116
assert res == expected_res
95117

96-
def get_string_from_file(filename):
97-
fp = open(BASE_PATH + filename, "r")
118+
def get_string_from_file(filename, base_path=BASE_PATH):
119+
fp = open(base_path + filename, "r")
98120
cfg = fp.read()
99121
fp.close()
100122

0 commit comments

Comments
 (0)