Skip to content

Commit 7b3038b

Browse files
guangyao6AharonMalkin
authored andcommitted
Add bgp sentinel support in GCU (sonic-net#9735)
What is the motivation for this PR? This PR is to verify the usage of 'config apply-patch' works on bgp sentinel config How did you do it? Add bgp sentinel config to dut and check if config change as expected How did you verify/test it? Run test of sonic-mgmt/tests/generic_config_updater/test_bgp_sentinel.py on KVM
1 parent a854cd9 commit 7b3038b

File tree

1 file changed

+264
-0
lines changed

1 file changed

+264
-0
lines changed
Lines changed: 264 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
1+
import logging
2+
import pytest
3+
import re
4+
import ipaddress
5+
6+
from tests.common.helpers.assertions import pytest_assert
7+
from tests.generic_config_updater.gu_utils import apply_patch, expect_op_success
8+
from tests.generic_config_updater.gu_utils import generate_tmpfile, delete_tmpfile
9+
from tests.generic_config_updater.gu_utils import create_checkpoint, delete_checkpoint, rollback_or_reload
10+
11+
12+
pytestmark = [
13+
pytest.mark.topology('t1'), # BGP Sentinel is limited to t1 only
14+
]
15+
16+
logger = logging.getLogger(__name__)
17+
18+
BGPSENTINEL_V4 = "BGPSentinel"
19+
BGPSENTINEL_V6 = "BGPSentinelV6"
20+
BGPSENTINEL_SRC_ADDR_RE = "neighbor {} update-source {}"
21+
BGPSENTINEL_IP_RANGE_RE = "bgp listen range {} peer-group {}"
22+
DUMMY_IP_RANGE_V4 = "10.255.0.0/25"
23+
DUMMY_IP_RANGE_V6 = "cc98:2008:2012:2022::/64"
24+
DUMMY_SRC_ADDRESS_V4 = "10.1.0.33"
25+
DUMMY_SRC_ADDRESS_V6 = "fc00:1::33"
26+
IP_RANGE_V4 = "10.10.20.0/24"
27+
IP_RANGE_V6 = "2603:10a1:30a:8000::/59"
28+
29+
30+
@pytest.fixture(scope="module")
31+
def lo_intf_ips(rand_selected_dut, tbinfo):
32+
""" Get loopback interface ip. This will be used as src_address in sentinel
33+
"""
34+
mg_facts = rand_selected_dut.get_extended_minigraph_facts(tbinfo)
35+
ip, ipv6 = "", ""
36+
for lo_interface in mg_facts['minigraph_lo_interfaces']:
37+
if ipaddress.ip_address(lo_interface['addr']).version == 4:
38+
ip = lo_interface['addr']
39+
elif ipaddress.ip_address(lo_interface['addr']).version == 6:
40+
ipv6 = lo_interface['addr']
41+
if ip and ipv6:
42+
return ip, ipv6
43+
pytest_assert(True, "Required ipv4 and ipv6 to start the test")
44+
45+
46+
def get_bgp_sentinel_runningconfig(duthost):
47+
""" Get bgp sentinel config that contains src_address and ip_range
48+
49+
Sample output in t0:
50+
['\n neighbor BGPSentinel update-source 10.1.0.32',
51+
'\n bgp listen range 10.255.0.0/25 peer-group BGPSentinel']
52+
"""
53+
cmds = "show runningconfiguration bgp"
54+
output = duthost.shell(cmds)
55+
pytest_assert(not output['rc'], "'{}' failed with rc={}".format(cmds, output['rc']))
56+
57+
# Sample:
58+
# neighbor BGPSentinel update-source 10.1.0.32
59+
# bgp listen range 192.168.0.0/21 peer-group BGPSentinel
60+
bgp_sentinel_pattern = r"\s+neighbor.*update-source.*|\s+bgp listen range.*"
61+
bgp_sentinel_config = re.findall(bgp_sentinel_pattern, output['stdout'])
62+
return bgp_sentinel_config
63+
64+
65+
@pytest.fixture(autouse=True)
66+
def setup_env(duthosts, rand_one_dut_hostname):
67+
"""
68+
Setup/teardown fixture for bgp sentinel config
69+
Args:
70+
duthosts: list of DUTs.
71+
rand_selected_dut: The fixture returns a randomly selected DuT.
72+
"""
73+
duthost = duthosts[rand_one_dut_hostname]
74+
original_bgp_sentinel_config = get_bgp_sentinel_runningconfig(duthost)
75+
create_checkpoint(duthost)
76+
77+
yield
78+
79+
try:
80+
logger.info("Rolled back to original checkpoint")
81+
rollback_or_reload(duthost)
82+
current_bgp_sentinel_config = get_bgp_sentinel_runningconfig(duthost)
83+
pytest_assert(
84+
set(original_bgp_sentinel_config) == set(current_bgp_sentinel_config),
85+
"bgp sentinel config are not suppose to change after test org: {}, cur: {}"
86+
.format(original_bgp_sentinel_config, current_bgp_sentinel_config)
87+
)
88+
finally:
89+
delete_checkpoint(duthost)
90+
91+
92+
def bgp_sentinel_config_cleanup(duthost):
93+
""" Clean up bgp sentinel config to avoid ip range conflict
94+
"""
95+
cmds = 'sonic-db-cli CONFIG_DB keys "BGP_SENTINELS|*" | xargs -r sonic-db-cli CONFIG_DB del'
96+
output = duthost.shell(cmds)
97+
pytest_assert(not output['rc'], "bgp sentinel config cleanup failed.")
98+
99+
100+
def show_bgp_running_config(duthost):
101+
return duthost.shell("show runningconfiguration bgp")['stdout']
102+
103+
104+
def bgp_sentinel_tc1_add_config(duthost, lo_intf_ips):
105+
""" Test to add desired v4&v6 bgp sentinel config
106+
"""
107+
lo_ip, lo_ipv6 = lo_intf_ips
108+
ip_range, ip_rangev6 = IP_RANGE_V4, IP_RANGE_V6
109+
110+
json_patch = [
111+
{
112+
"op": "add",
113+
"path": "/BGP_SENTINELS",
114+
"value": {
115+
"{}".format(BGPSENTINEL_V4): {
116+
"ip_range": [
117+
"{}".format(ip_range)
118+
],
119+
"name": "{}".format(BGPSENTINEL_V4),
120+
"src_address": "{}".format(lo_ip)
121+
},
122+
"{}".format(BGPSENTINEL_V6): {
123+
"ip_range": [
124+
"{}".format(ip_rangev6)
125+
],
126+
"name": "{}".format(BGPSENTINEL_V6),
127+
"src_address": "{}".format(lo_ipv6)
128+
}
129+
}
130+
}
131+
]
132+
133+
tmpfile = generate_tmpfile(duthost)
134+
logger.info("tmpfile {}".format(tmpfile))
135+
136+
try:
137+
output = apply_patch(duthost, json_data=json_patch, dest_file=tmpfile)
138+
expect_op_success(duthost, output)
139+
140+
bgp_config = show_bgp_running_config(duthost)
141+
pytest_assert(
142+
re.search(BGPSENTINEL_SRC_ADDR_RE.format(BGPSENTINEL_V4, lo_ip), bgp_config) and
143+
re.search(BGPSENTINEL_SRC_ADDR_RE.format(BGPSENTINEL_V6, lo_ipv6), bgp_config),
144+
"Failed to update bgp sentinel src address."
145+
)
146+
pytest_assert(
147+
re.search(BGPSENTINEL_IP_RANGE_RE.format(ip_range, BGPSENTINEL_V4), bgp_config) and
148+
re.search(BGPSENTINEL_IP_RANGE_RE.format(ip_rangev6, BGPSENTINEL_V6), bgp_config),
149+
"Failed to add bgp sentinel ip range."
150+
)
151+
152+
finally:
153+
delete_tmpfile(duthost, tmpfile)
154+
155+
156+
def bgp_sentinel_tc1_add_dummy_ip_range(duthost):
157+
""" Test to add dummy ip range to existed config
158+
"""
159+
json_patch = [
160+
{
161+
"op": "add",
162+
"path": "/BGP_SENTINELS/{}/ip_range/1".format(BGPSENTINEL_V4),
163+
"value": "{}".format(DUMMY_IP_RANGE_V4)
164+
},
165+
{
166+
"op": "add",
167+
"path": "/BGP_SENTINELS/{}/ip_range/1".format(BGPSENTINEL_V6),
168+
"value": "{}".format(DUMMY_IP_RANGE_V6)
169+
}
170+
]
171+
172+
tmpfile = generate_tmpfile(duthost)
173+
logger.info("tmpfile {}".format(tmpfile))
174+
175+
try:
176+
output = apply_patch(duthost, json_data=json_patch, dest_file=tmpfile)
177+
expect_op_success(duthost, output)
178+
179+
bgp_config = show_bgp_running_config(duthost)
180+
181+
pytest_assert(
182+
re.search(BGPSENTINEL_IP_RANGE_RE.format(DUMMY_IP_RANGE_V4, BGPSENTINEL_V4), bgp_config) and
183+
re.search(BGPSENTINEL_IP_RANGE_RE.format(DUMMY_IP_RANGE_V6, BGPSENTINEL_V6), bgp_config),
184+
"Failed to add bgp sentinel dummy ip range."
185+
)
186+
187+
finally:
188+
delete_tmpfile(duthost, tmpfile)
189+
190+
191+
def bgp_sentinel_tc1_rm_dummy_ip_range(duthost):
192+
""" Test to remove dummy ip range to existed config
193+
"""
194+
json_patch = [
195+
{
196+
"op": "remove",
197+
"path": "/BGP_SENTINELS/{}/ip_range/1".format(BGPSENTINEL_V4)
198+
},
199+
{
200+
"op": "remove",
201+
"path": "/BGP_SENTINELS/{}/ip_range/1".format(BGPSENTINEL_V6)
202+
}
203+
]
204+
205+
tmpfile = generate_tmpfile(duthost)
206+
logger.info("tmpfile {}".format(tmpfile))
207+
208+
try:
209+
output = apply_patch(duthost, json_data=json_patch, dest_file=tmpfile)
210+
expect_op_success(duthost, output)
211+
212+
bgp_config = show_bgp_running_config(duthost)
213+
pytest_assert(
214+
not re.search(BGPSENTINEL_IP_RANGE_RE.format(DUMMY_IP_RANGE_V4, BGPSENTINEL_V4), bgp_config) and
215+
not re.search(BGPSENTINEL_IP_RANGE_RE.format(DUMMY_IP_RANGE_V6, BGPSENTINEL_V6), bgp_config),
216+
"Failed to remove bgp sentinel dummy ip range."
217+
)
218+
219+
finally:
220+
delete_tmpfile(duthost, tmpfile)
221+
222+
223+
def bgp_sentinel_tc1_replace_src_address(duthost):
224+
""" Test to replace dummy src_address to existed config
225+
"""
226+
json_patch = [
227+
{
228+
"op": "replace",
229+
"path": "/BGP_SENTINELS/{}/src_address".format(BGPSENTINEL_V4),
230+
"value": "{}".format(DUMMY_SRC_ADDRESS_V4)
231+
},
232+
{
233+
"op": "replace",
234+
"path": "/BGP_SENTINELS/{}/src_address".format(BGPSENTINEL_V6),
235+
"value": "{}".format(DUMMY_SRC_ADDRESS_V6)
236+
}
237+
]
238+
239+
tmpfile = generate_tmpfile(duthost)
240+
logger.info("tmpfile {}".format(tmpfile))
241+
242+
try:
243+
output = apply_patch(duthost, json_data=json_patch, dest_file=tmpfile)
244+
expect_op_success(duthost, output)
245+
246+
bgp_config = show_bgp_running_config(duthost)
247+
pytest_assert(
248+
re.search(BGPSENTINEL_SRC_ADDR_RE.format(BGPSENTINEL_V4, DUMMY_SRC_ADDRESS_V4), bgp_config) and
249+
re.search(BGPSENTINEL_SRC_ADDR_RE.format(BGPSENTINEL_V6, DUMMY_SRC_ADDRESS_V6), bgp_config),
250+
"Failed to replace bgp sentinel src address."
251+
)
252+
253+
finally:
254+
delete_tmpfile(duthost, tmpfile)
255+
256+
257+
def test_bgp_sentinel_tc1_test_config(rand_selected_dut, lo_intf_ips):
258+
""" Test suite for bgp sentinel config for v4 and v6
259+
"""
260+
bgp_sentinel_config_cleanup(rand_selected_dut)
261+
bgp_sentinel_tc1_add_config(rand_selected_dut, lo_intf_ips)
262+
bgp_sentinel_tc1_add_dummy_ip_range(rand_selected_dut)
263+
bgp_sentinel_tc1_rm_dummy_ip_range(rand_selected_dut)
264+
bgp_sentinel_tc1_replace_src_address(rand_selected_dut)

0 commit comments

Comments
 (0)