]>
Commit | Line | Data |
---|---|---|
27d9695d AP |
1 | #!/usr/bin/env python |
2 | ||
3 | # | |
4 | # Copyright (c) 2019 by VMware, Inc. ("VMware") | |
5 | # Used Copyright (c) 2018 by Network Device Education Foundation, Inc. | |
6 | # ("NetDEF") in this file. | |
7 | # | |
8 | # Permission to use, copy, modify, and/or distribute this software | |
9 | # for any purpose with or without fee is hereby granted, provided | |
10 | # that the above copyright notice and this permission notice appear | |
11 | # in all copies. | |
12 | # | |
13 | # THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES | |
14 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
15 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR | |
16 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY | |
17 | # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | |
18 | # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS | |
19 | # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |
20 | # OF THIS SOFTWARE. | |
21 | # | |
22 | ||
23 | ||
24 | """ | |
25 | Following tests are covered to test ecmp functionality on EBGP. | |
26 | 1. Verify routes installed as per maximum-paths configuration (8/16/32) | |
27 | 2. Disable/Shut selected paths nexthops and verify other next are installed in | |
28 | the RIB of DUT. Enable interfaces and verify RIB count. | |
29 | 3. Verify BGP table and RIB in DUT after clear BGP routes and neighbors. | |
30 | 4. Verify routes are cleared from BGP and RIB table of DUT when | |
31 | redistribute static configuration is removed. | |
32 | 5. Shut BGP neigbors one by one and verify BGP and routing table updated | |
33 | accordingly in DUT | |
34 | 6. Delete static routes and verify routers are cleared from BGP table and RIB | |
35 | of DUT. | |
36 | 7. Verify routes are cleared from BGP and RIB table of DUT when advertise | |
37 | network configuration is removed. | |
38 | """ | |
39 | import os | |
40 | import sys | |
41 | import time | |
27d9695d | 42 | import pytest |
3dfd384e | 43 | |
27d9695d AP |
44 | # Save the Current Working Directory to find configuration files. |
45 | CWD = os.path.dirname(os.path.realpath(__file__)) | |
787e7624 | 46 | sys.path.append(os.path.join(CWD, "../")) |
47 | sys.path.append(os.path.join(CWD, "../../")) | |
27d9695d AP |
48 | |
49 | # pylint: disable=C0413 | |
50 | # Import topogen and topotest helpers | |
51 | from lib.topogen import Topogen, get_topogen | |
3dfd384e | 52 | |
27d9695d | 53 | from lib.common_config import ( |
787e7624 | 54 | start_topology, |
55 | write_test_header, | |
27d9695d | 56 | write_test_footer, |
787e7624 | 57 | verify_rib, |
58 | create_static_routes, | |
59 | check_address_types, | |
60 | interface_status, | |
61 | reset_config_on_routers, | |
701a0192 | 62 | required_linux_kernel_version, |
27d9695d AP |
63 | ) |
64 | from lib.topolog import logger | |
f6f20a77 | 65 | from lib.bgp import verify_bgp_convergence, create_router_bgp, clear_bgp |
4953ca97 | 66 | from lib.topojson import build_config_from_json |
27d9695d | 67 | |
98ca91e1 DS |
68 | |
69 | pytestmark = [pytest.mark.bgpd, pytest.mark.staticd] | |
70 | ||
71 | ||
27d9695d AP |
72 | |
73 | # Global variables | |
74 | NEXT_HOPS = {"ipv4": [], "ipv6": []} | |
75 | INTF_LIST_R3 = [] | |
76 | INTF_LIST_R2 = [] | |
77 | NETWORK = {"ipv4": "11.0.20.1/32", "ipv6": "1::/64"} | |
78 | NEXT_HOP_IP = {"ipv4": "10.0.0.1", "ipv6": "fd00::1"} | |
79 | BGP_CONVERGENCE = False | |
80 | ||
81 | ||
27d9695d AP |
82 | def setup_module(mod): |
83 | """ | |
84 | Sets up the pytest environment. | |
85 | ||
86 | * `mod`: module name | |
87 | """ | |
88 | global NEXT_HOPS, INTF_LIST_R3, INTF_LIST_R2, TEST_STATIC | |
89 | global ADDR_TYPES | |
90 | ||
3dfd384e | 91 | # Required linux kernel version for this suite to run. |
701a0192 | 92 | result = required_linux_kernel_version("4.15") |
955212d9 | 93 | if result is not True: |
94 | pytest.skip("Kernel requirements are not met") | |
3dfd384e | 95 | |
27d9695d AP |
96 | testsuite_run_time = time.asctime(time.localtime(time.time())) |
97 | logger.info("Testsuite start time: {}".format(testsuite_run_time)) | |
98 | logger.info("=" * 40) | |
99 | ||
100 | logger.info("Running setup_module to create topology") | |
101 | ||
102 | # This function initiates the topology build with Topogen... | |
e82b531d CH |
103 | json_file = "{}/ibgp_ecmp_topo2.json".format(CWD) |
104 | tgen = Topogen(json_file, mod.__name__) | |
105 | global topo | |
106 | topo = tgen.json_topo | |
27d9695d AP |
107 | |
108 | # Starting topology, create tmp files which are loaded to routers | |
109 | # to start deamons and then start routers | |
110 | start_topology(tgen) | |
111 | ||
112 | # Creating configuration from JSON | |
113 | build_config_from_json(tgen, topo) | |
114 | ||
115 | # Don't run this test if we have any failure. | |
116 | if tgen.routers_have_failure(): | |
117 | pytest.skip(tgen.errors) | |
118 | ||
119 | # tgen.mininet_cli() | |
120 | # Api call verify whether BGP is converged | |
121 | ADDR_TYPES = check_address_types() | |
122 | ||
123 | for addr_type in ADDR_TYPES: | |
124 | BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) | |
787e7624 | 125 | assert BGP_CONVERGENCE is True, "setup_module :Failed \n Error:" " {}".format( |
126 | BGP_CONVERGENCE | |
127 | ) | |
128 | ||
129 | link_data = [ | |
701a0192 | 130 | val for links, val in topo["routers"]["r2"]["links"].items() if "r3" in links |
787e7624 | 131 | ] |
27d9695d AP |
132 | for adt in ADDR_TYPES: |
133 | NEXT_HOPS[adt] = [val[adt].split("/")[0] for val in link_data] | |
134 | if adt == "ipv4": | |
787e7624 | 135 | NEXT_HOPS[adt] = sorted(NEXT_HOPS[adt], key=lambda x: int(x.split(".")[2])) |
27d9695d AP |
136 | elif adt == "ipv6": |
137 | NEXT_HOPS[adt] = sorted( | |
787e7624 | 138 | NEXT_HOPS[adt], key=lambda x: int(x.split(":")[-3], 16) |
139 | ) | |
27d9695d AP |
140 | |
141 | INTF_LIST_R2 = [val["interface"].split("/")[0] for val in link_data] | |
142 | INTF_LIST_R2 = sorted(INTF_LIST_R2, key=lambda x: int(x.split("eth")[1])) | |
143 | ||
787e7624 | 144 | link_data = [ |
701a0192 | 145 | val for links, val in topo["routers"]["r3"]["links"].items() if "r2" in links |
787e7624 | 146 | ] |
27d9695d AP |
147 | INTF_LIST_R3 = [val["interface"].split("/")[0] for val in link_data] |
148 | INTF_LIST_R3 = sorted(INTF_LIST_R3, key=lambda x: int(x.split("eth")[1])) | |
149 | ||
150 | # STATIC_ROUTE = True | |
151 | logger.info("Running setup_module() done") | |
152 | ||
153 | ||
154 | def teardown_module(): | |
155 | """ | |
156 | Teardown the pytest environment. | |
157 | ||
158 | * `mod`: module name | |
159 | """ | |
160 | ||
161 | logger.info("Running teardown_module to delete topology") | |
162 | ||
163 | tgen = get_topogen() | |
164 | ||
165 | # Stop toplogy and Remove tmp files | |
166 | tgen.stop_topology() | |
167 | ||
168 | ||
169 | def static_or_nw(tgen, topo, tc_name, test_type, dut): | |
170 | ||
171 | if test_type == "redist_static": | |
172 | input_dict_static = { | |
173 | dut: { | |
174 | "static_routes": [ | |
787e7624 | 175 | {"network": NETWORK["ipv4"], "next_hop": NEXT_HOP_IP["ipv4"]}, |
176 | {"network": NETWORK["ipv6"], "next_hop": NEXT_HOP_IP["ipv6"]}, | |
27d9695d AP |
177 | ] |
178 | } | |
179 | } | |
180 | logger.info("Configuring static route on router %s", dut) | |
181 | result = create_static_routes(tgen, input_dict_static) | |
182 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
787e7624 | 183 | tc_name, result |
184 | ) | |
27d9695d AP |
185 | |
186 | input_dict_2 = { | |
187 | dut: { | |
188 | "bgp": { | |
189 | "address_family": { | |
190 | "ipv4": { | |
787e7624 | 191 | "unicast": {"redistribute": [{"redist_type": "static"}]} |
27d9695d AP |
192 | }, |
193 | "ipv6": { | |
787e7624 | 194 | "unicast": {"redistribute": [{"redist_type": "static"}]} |
195 | }, | |
27d9695d AP |
196 | } |
197 | } | |
198 | } | |
199 | } | |
200 | ||
201 | logger.info("Configuring redistribute static route on router %s", dut) | |
202 | result = create_router_bgp(tgen, topo, input_dict_2) | |
203 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
787e7624 | 204 | tc_name, result |
205 | ) | |
27d9695d AP |
206 | |
207 | elif test_type == "advertise_nw": | |
208 | input_dict_nw = { | |
209 | dut: { | |
210 | "bgp": { | |
211 | "address_family": { | |
212 | "ipv4": { | |
213 | "unicast": { | |
787e7624 | 214 | "advertise_networks": [{"network": NETWORK["ipv4"]}] |
27d9695d AP |
215 | } |
216 | }, | |
217 | "ipv6": { | |
218 | "unicast": { | |
787e7624 | 219 | "advertise_networks": [{"network": NETWORK["ipv6"]}] |
27d9695d | 220 | } |
787e7624 | 221 | }, |
27d9695d AP |
222 | } |
223 | } | |
224 | } | |
225 | } | |
226 | ||
787e7624 | 227 | logger.info( |
228 | "Advertising networks %s %s from router %s", | |
229 | NETWORK["ipv4"], | |
230 | NETWORK["ipv6"], | |
231 | dut, | |
232 | ) | |
27d9695d AP |
233 | result = create_router_bgp(tgen, topo, input_dict_nw) |
234 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
787e7624 | 235 | tc_name, result |
236 | ) | |
27d9695d AP |
237 | |
238 | ||
239 | @pytest.mark.parametrize("ecmp_num", ["8", "16", "32"]) | |
240 | @pytest.mark.parametrize("test_type", ["redist_static", "advertise_nw"]) | |
241 | def test_modify_ecmp_max_paths(request, ecmp_num, test_type): | |
242 | """ | |
243 | Verify routes installed as per maximum-paths | |
244 | configuration (8/16/32). | |
245 | """ | |
246 | ||
247 | tc_name = request.node.name | |
248 | write_test_header(tc_name) | |
249 | tgen = get_topogen() | |
250 | ||
251 | reset_config_on_routers(tgen) | |
252 | ||
253 | static_or_nw(tgen, topo, tc_name, test_type, "r2") | |
254 | ||
255 | input_dict = { | |
256 | "r3": { | |
257 | "bgp": { | |
258 | "address_family": { | |
9fa6ec14 | 259 | "ipv4": { |
260 | "unicast": { | |
261 | "maximum_paths": { | |
262 | "ibgp": ecmp_num, | |
263 | } | |
264 | } | |
265 | }, | |
266 | "ipv6": { | |
267 | "unicast": { | |
268 | "maximum_paths": { | |
269 | "ibgp": ecmp_num, | |
270 | } | |
271 | } | |
272 | }, | |
27d9695d AP |
273 | } |
274 | } | |
275 | } | |
276 | } | |
277 | ||
278 | logger.info("Configuring bgp maximum-paths %s on router r3", ecmp_num) | |
279 | result = create_router_bgp(tgen, topo, input_dict) | |
787e7624 | 280 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) |
27d9695d AP |
281 | |
282 | # Verifying RIB routes | |
283 | dut = "r3" | |
284 | protocol = "bgp" | |
285 | ||
286 | for addr_type in ADDR_TYPES: | |
787e7624 | 287 | input_dict_1 = {"r3": {"static_routes": [{"network": NETWORK[addr_type]}]}} |
27d9695d AP |
288 | |
289 | logger.info("Verifying %s routes on r3", addr_type) | |
15df6d31 MS |
290 | |
291 | # Test only the count of nexthops, not the specific nexthop addresses - | |
292 | # they're not deterministic | |
293 | # | |
787e7624 | 294 | result = verify_rib( |
295 | tgen, | |
296 | addr_type, | |
297 | dut, | |
298 | input_dict_1, | |
f6f20a77 | 299 | next_hop=NEXT_HOPS[addr_type][: int(ecmp_num)], |
787e7624 | 300 | protocol=protocol, |
9fa6ec14 | 301 | count_only=True, |
787e7624 | 302 | ) |
15df6d31 | 303 | |
27d9695d | 304 | assert result is True, "Testcase {} : Failed \n Error: {}".format( |
787e7624 | 305 | tc_name, result |
306 | ) | |
27d9695d AP |
307 | |
308 | write_test_footer(tc_name) | |
309 | ||
5980ad0a | 310 | |
ee51a3d9 | 311 | @pytest.mark.parametrize("ecmp_num", ["8", "16", "32"]) |
b7250ecf | 312 | @pytest.mark.parametrize("test_type", ["redist_static", "advertise_nw"]) |
ee51a3d9 | 313 | def test_ecmp_after_clear_bgp(request, ecmp_num, test_type): |
27d9695d AP |
314 | """ Verify BGP table and RIB in DUT after clear BGP routes and neighbors""" |
315 | ||
316 | tc_name = request.node.name | |
317 | write_test_header(tc_name) | |
318 | tgen = get_topogen() | |
319 | ||
320 | reset_config_on_routers(tgen) | |
321 | ||
322 | # Verifying RIB routes | |
323 | dut = "r3" | |
324 | protocol = "bgp" | |
325 | ||
b7250ecf | 326 | static_or_nw(tgen, topo, tc_name, test_type, "r2") |
27d9695d | 327 | for addr_type in ADDR_TYPES: |
787e7624 | 328 | input_dict_1 = {"r3": {"static_routes": [{"network": NETWORK[addr_type]}]}} |
27d9695d AP |
329 | |
330 | logger.info("Verifying %s routes on r3", addr_type) | |
787e7624 | 331 | result = verify_rib( |
332 | tgen, | |
333 | addr_type, | |
334 | dut, | |
335 | input_dict_1, | |
5980ad0a | 336 | next_hop=NEXT_HOPS[addr_type][: int(ecmp_num)], |
787e7624 | 337 | protocol=protocol, |
338 | ) | |
27d9695d | 339 | assert result is True, "Testcase {} : Failed \n Error: {}".format( |
787e7624 | 340 | tc_name, result |
341 | ) | |
27d9695d | 342 | |
f6f20a77 KK |
343 | # Clear BGP |
344 | for addr_type in ADDR_TYPES: | |
345 | clear_bgp(tgen, addr_type, dut) | |
346 | ||
347 | # Verify BGP convergence | |
348 | result = verify_bgp_convergence(tgen, topo) | |
787e7624 | 349 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) |
27d9695d AP |
350 | |
351 | for addr_type in ADDR_TYPES: | |
787e7624 | 352 | input_dict_1 = {"r3": {"static_routes": [{"network": NETWORK[addr_type]}]}} |
27d9695d | 353 | logger.info("Verifying %s routes on r3", addr_type) |
787e7624 | 354 | result = verify_rib( |
355 | tgen, | |
356 | addr_type, | |
357 | dut, | |
358 | input_dict_1, | |
5980ad0a | 359 | next_hop=NEXT_HOPS[addr_type][: int(ecmp_num)], |
787e7624 | 360 | protocol=protocol, |
361 | ) | |
27d9695d | 362 | assert result is True, "Testcase {} : Failed \n Error: {}".format( |
787e7624 | 363 | tc_name, result |
364 | ) | |
27d9695d AP |
365 | |
366 | write_test_footer(tc_name) | |
367 | ||
368 | ||
369 | def test_ecmp_remove_redistribute_static(request): | |
9fa6ec14 | 370 | """Verify routes are cleared from BGP and RIB table of DUT when |
371 | redistribute static configuration is removed.""" | |
27d9695d AP |
372 | |
373 | tc_name = request.node.name | |
374 | write_test_header(tc_name) | |
375 | tgen = get_topogen() | |
376 | ||
377 | reset_config_on_routers(tgen) | |
378 | static_or_nw(tgen, topo, tc_name, "redist_static", "r2") | |
379 | for addr_type in ADDR_TYPES: | |
380 | ||
381 | # Verifying RIB routes | |
382 | dut = "r3" | |
383 | protocol = "bgp" | |
787e7624 | 384 | input_dict_1 = {"r3": {"static_routes": [{"network": NETWORK[addr_type]}]}} |
27d9695d AP |
385 | |
386 | logger.info("Verifying %s routes on r3", addr_type) | |
787e7624 | 387 | result = verify_rib( |
388 | tgen, | |
389 | addr_type, | |
390 | dut, | |
391 | input_dict_1, | |
392 | next_hop=NEXT_HOPS[addr_type], | |
393 | protocol=protocol, | |
394 | ) | |
27d9695d | 395 | assert result is True, "Testcase {} : Failed \n Error: {}".format( |
787e7624 | 396 | tc_name, result |
397 | ) | |
27d9695d AP |
398 | |
399 | input_dict_2 = { | |
400 | "r2": { | |
401 | "bgp": { | |
402 | "address_family": { | |
403 | "ipv4": { | |
404 | "unicast": { | |
787e7624 | 405 | "redistribute": [{"redist_type": "static", "delete": True}] |
27d9695d AP |
406 | } |
407 | }, | |
408 | "ipv6": { | |
409 | "unicast": { | |
787e7624 | 410 | "redistribute": [{"redist_type": "static", "delete": True}] |
27d9695d | 411 | } |
787e7624 | 412 | }, |
27d9695d AP |
413 | } |
414 | } | |
415 | } | |
416 | } | |
417 | ||
418 | logger.info("Remove redistribute static") | |
419 | result = create_router_bgp(tgen, topo, input_dict_2) | |
787e7624 | 420 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) |
27d9695d AP |
421 | |
422 | for addr_type in ADDR_TYPES: | |
423 | ||
424 | # Verifying RIB routes | |
425 | dut = "r3" | |
426 | protocol = "bgp" | |
787e7624 | 427 | input_dict_1 = {"r3": {"static_routes": [{"network": NETWORK[addr_type]}]}} |
27d9695d AP |
428 | |
429 | logger.info("Verifying %s routes on r3 are deleted", addr_type) | |
787e7624 | 430 | result = verify_rib( |
431 | tgen, | |
432 | addr_type, | |
433 | dut, | |
434 | input_dict_1, | |
435 | next_hop=[], | |
436 | protocol=protocol, | |
437 | expected=False, | |
438 | ) | |
439 | assert ( | |
440 | result is not True | |
441 | ), "Testcase {} : Failed \n Routes still" " present in RIB".format(tc_name) | |
27d9695d AP |
442 | |
443 | logger.info("Enable redistribute static") | |
444 | input_dict_2 = { | |
445 | "r2": { | |
446 | "bgp": { | |
447 | "address_family": { | |
787e7624 | 448 | "ipv4": {"unicast": {"redistribute": [{"redist_type": "static"}]}}, |
449 | "ipv6": {"unicast": {"redistribute": [{"redist_type": "static"}]}}, | |
27d9695d AP |
450 | } |
451 | } | |
452 | } | |
453 | } | |
454 | result = create_router_bgp(tgen, topo, input_dict_2) | |
787e7624 | 455 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) |
27d9695d AP |
456 | |
457 | for addr_type in ADDR_TYPES: | |
458 | # Verifying RIB routes | |
459 | dut = "r3" | |
460 | protocol = "bgp" | |
787e7624 | 461 | input_dict_1 = {"r3": {"static_routes": [{"network": NETWORK[addr_type]}]}} |
27d9695d | 462 | logger.info("Verifying %s routes on r3", addr_type) |
787e7624 | 463 | result = verify_rib( |
464 | tgen, | |
465 | addr_type, | |
466 | dut, | |
467 | input_dict_1, | |
468 | next_hop=NEXT_HOPS[addr_type], | |
469 | protocol=protocol, | |
470 | ) | |
27d9695d | 471 | assert result is True, "Testcase {} : Failed \n Error: {}".format( |
787e7624 | 472 | tc_name, result |
473 | ) | |
27d9695d AP |
474 | |
475 | write_test_footer(tc_name) | |
476 | ||
477 | ||
b7250ecf KK |
478 | @pytest.mark.parametrize("test_type", ["redist_static", "advertise_nw"]) |
479 | def test_ecmp_shut_bgp_neighbor(request, test_type): | |
9fa6ec14 | 480 | """Shut BGP neigbors one by one and verify BGP and routing table updated |
481 | accordingly in DUT""" | |
27d9695d AP |
482 | |
483 | tc_name = request.node.name | |
484 | write_test_header(tc_name) | |
485 | tgen = get_topogen() | |
486 | ||
487 | logger.info(INTF_LIST_R2) | |
488 | # Verifying RIB routes | |
489 | dut = "r3" | |
490 | protocol = "bgp" | |
491 | ||
492 | reset_config_on_routers(tgen) | |
b7250ecf | 493 | static_or_nw(tgen, topo, tc_name, test_type, "r2") |
27d9695d AP |
494 | |
495 | for addr_type in ADDR_TYPES: | |
787e7624 | 496 | input_dict = {"r3": {"static_routes": [{"network": NETWORK[addr_type]}]}} |
27d9695d AP |
497 | |
498 | logger.info("Verifying %s routes on r3", addr_type) | |
787e7624 | 499 | result = verify_rib( |
500 | tgen, | |
501 | addr_type, | |
502 | dut, | |
503 | input_dict, | |
504 | next_hop=NEXT_HOPS[addr_type], | |
505 | protocol=protocol, | |
506 | ) | |
27d9695d | 507 | assert result is True, "Testcase {} : Failed \n Error: {}".format( |
787e7624 | 508 | tc_name, result |
509 | ) | |
27d9695d | 510 | |
787e7624 | 511 | for intf_num in range(len(INTF_LIST_R2) + 1, 16): |
512 | intf_val = INTF_LIST_R2[intf_num : intf_num + 16] | |
27d9695d | 513 | |
787e7624 | 514 | input_dict_1 = {"r2": {"interface_list": [intf_val], "status": "down"}} |
515 | logger.info("Shutting down neighbor interface {} on r2".format(intf_val)) | |
27d9695d AP |
516 | result = interface_status(tgen, topo, input_dict_1) |
517 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
787e7624 | 518 | tc_name, result |
519 | ) | |
27d9695d AP |
520 | |
521 | for addr_type in ADDR_TYPES: | |
522 | if intf_num + 16 < 32: | |
523 | check_hops = NEXT_HOPS[addr_type] | |
524 | else: | |
525 | check_hops = [] | |
526 | ||
787e7624 | 527 | input_dict = {"r3": {"static_routes": [{"network": NETWORK[addr_type]}]}} |
27d9695d | 528 | logger.info("Verifying %s routes on r3", addr_type) |
787e7624 | 529 | result = verify_rib( |
530 | tgen, addr_type, dut, input_dict, next_hop=check_hops, protocol=protocol | |
531 | ) | |
27d9695d | 532 | assert result is True, "Testcase {} : Failed \n Error: {}".format( |
787e7624 | 533 | tc_name, result |
534 | ) | |
27d9695d | 535 | |
787e7624 | 536 | input_dict_1 = {"r2": {"interface_list": INTF_LIST_R2, "status": "up"}} |
27d9695d AP |
537 | |
538 | logger.info("Enabling all neighbor interface {} on r2") | |
539 | result = interface_status(tgen, topo, input_dict_1) | |
787e7624 | 540 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) |
27d9695d | 541 | |
b7250ecf | 542 | static_or_nw(tgen, topo, tc_name, test_type, "r2") |
27d9695d | 543 | for addr_type in ADDR_TYPES: |
787e7624 | 544 | input_dict = {"r3": {"static_routes": [{"network": NETWORK[addr_type]}]}} |
27d9695d AP |
545 | |
546 | logger.info("Verifying %s routes on r3", addr_type) | |
787e7624 | 547 | result = verify_rib( |
548 | tgen, | |
549 | addr_type, | |
550 | dut, | |
551 | input_dict, | |
552 | next_hop=NEXT_HOPS[addr_type], | |
553 | protocol=protocol, | |
554 | ) | |
27d9695d | 555 | assert result is True, "Testcase {} : Failed \n Error: {}".format( |
787e7624 | 556 | tc_name, result |
557 | ) | |
27d9695d AP |
558 | |
559 | write_test_footer(tc_name) | |
560 | ||
561 | ||
562 | def test_ecmp_remove_static_route(request): | |
563 | """ | |
564 | Delete static routes and verify routers are cleared from BGP table, | |
565 | and RIB of DUT. | |
566 | """ | |
567 | ||
568 | tc_name = request.node.name | |
569 | write_test_header(tc_name) | |
570 | tgen = get_topogen() | |
571 | ||
572 | # Verifying RIB routes | |
573 | dut = "r3" | |
574 | protocol = "bgp" | |
575 | ||
576 | reset_config_on_routers(tgen) | |
577 | ||
578 | static_or_nw(tgen, topo, tc_name, "redist_static", "r2") | |
579 | for addr_type in ADDR_TYPES: | |
787e7624 | 580 | input_dict_1 = {"r3": {"static_routes": [{"network": NETWORK[addr_type]}]}} |
27d9695d AP |
581 | |
582 | logger.info("Verifying %s routes on r3", addr_type) | |
583 | result = verify_rib( | |
787e7624 | 584 | tgen, |
585 | addr_type, | |
586 | dut, | |
587 | input_dict_1, | |
588 | next_hop=NEXT_HOPS[addr_type], | |
589 | protocol=protocol, | |
590 | ) | |
27d9695d | 591 | assert result is True, "Testcase {} : Failed \n Error: {}".format( |
787e7624 | 592 | tc_name, result |
593 | ) | |
27d9695d AP |
594 | |
595 | for addr_type in ADDR_TYPES: | |
596 | input_dict_2 = { | |
597 | "r2": { | |
598 | "static_routes": [ | |
599 | { | |
600 | "network": NETWORK[addr_type], | |
601 | "next_hop": NEXT_HOP_IP[addr_type], | |
787e7624 | 602 | "delete": True, |
27d9695d AP |
603 | } |
604 | ] | |
605 | } | |
606 | } | |
607 | ||
608 | logger.info("Remove static routes") | |
609 | result = create_static_routes(tgen, input_dict_2) | |
610 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
787e7624 | 611 | tc_name, result |
612 | ) | |
27d9695d AP |
613 | |
614 | logger.info("Verifying %s routes on r3 are removed", addr_type) | |
787e7624 | 615 | result = verify_rib( |
616 | tgen, | |
617 | addr_type, | |
618 | dut, | |
619 | input_dict_2, | |
620 | next_hop=[], | |
621 | protocol=protocol, | |
622 | expected=False, | |
623 | ) | |
624 | assert ( | |
625 | result is not True | |
626 | ), "Testcase {} : Failed \n Routes still" " present in RIB".format(tc_name) | |
27d9695d AP |
627 | |
628 | for addr_type in ADDR_TYPES: | |
629 | # Enable static routes | |
630 | input_dict_4 = { | |
631 | "r2": { | |
632 | "static_routes": [ | |
787e7624 | 633 | {"network": NETWORK[addr_type], "next_hop": NEXT_HOP_IP[addr_type]} |
27d9695d AP |
634 | ] |
635 | } | |
636 | } | |
637 | ||
638 | logger.info("Enable static route") | |
639 | result = create_static_routes(tgen, input_dict_4) | |
640 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
787e7624 | 641 | tc_name, result |
642 | ) | |
27d9695d AP |
643 | |
644 | logger.info("Verifying %s routes on r3", addr_type) | |
787e7624 | 645 | result = verify_rib( |
646 | tgen, | |
647 | addr_type, | |
648 | dut, | |
649 | input_dict_4, | |
650 | next_hop=NEXT_HOPS[addr_type], | |
651 | protocol=protocol, | |
652 | ) | |
27d9695d | 653 | assert result is True, "Testcase {} : Failed \n Error: {}".format( |
787e7624 | 654 | tc_name, result |
655 | ) | |
27d9695d AP |
656 | |
657 | write_test_footer(tc_name) | |
658 | ||
659 | ||
660 | def test_ecmp_remove_nw_advertise(request): | |
661 | """ | |
662 | Verify routes are cleared from BGP and RIB table of DUT, | |
663 | when advertise network configuration is removed | |
664 | """ | |
665 | ||
666 | tc_name = request.node.name | |
667 | write_test_header(tc_name) | |
668 | tgen = get_topogen() | |
669 | ||
670 | # Verifying RIB routes | |
671 | dut = "r3" | |
672 | protocol = "bgp" | |
673 | ||
674 | reset_config_on_routers(tgen) | |
675 | static_or_nw(tgen, topo, tc_name, "advertise_nw", "r2") | |
676 | for addr_type in ADDR_TYPES: | |
787e7624 | 677 | input_dict = {"r3": {"static_routes": [{"network": NETWORK[addr_type]}]}} |
27d9695d AP |
678 | |
679 | logger.info("Verifying %s routes on r3", addr_type) | |
787e7624 | 680 | result = verify_rib( |
681 | tgen, | |
682 | addr_type, | |
683 | dut, | |
684 | input_dict, | |
685 | next_hop=NEXT_HOPS[addr_type], | |
686 | protocol=protocol, | |
687 | ) | |
27d9695d | 688 | assert result is True, "Testcase {} : Failed \n Error: {}".format( |
787e7624 | 689 | tc_name, result |
690 | ) | |
27d9695d AP |
691 | |
692 | input_dict_3 = { | |
693 | "r2": { | |
694 | "bgp": { | |
695 | "address_family": { | |
696 | "ipv4": { | |
697 | "unicast": { | |
787e7624 | 698 | "advertise_networks": [ |
699 | {"network": NETWORK["ipv4"], "delete": True} | |
700 | ] | |
701 | } | |
702 | }, | |
27d9695d AP |
703 | "ipv6": { |
704 | "unicast": { | |
787e7624 | 705 | "advertise_networks": [ |
706 | {"network": NETWORK["ipv6"], "delete": True} | |
707 | ] | |
27d9695d | 708 | } |
787e7624 | 709 | }, |
27d9695d AP |
710 | } |
711 | } | |
712 | } | |
787e7624 | 713 | } |
27d9695d AP |
714 | |
715 | logger.info("Withdraw advertised networks") | |
716 | result = create_router_bgp(tgen, topo, input_dict_3) | |
787e7624 | 717 | assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) |
27d9695d AP |
718 | |
719 | for addr_type in ADDR_TYPES: | |
787e7624 | 720 | input_dict = {"r3": {"static_routes": [{"network": NETWORK[addr_type]}]}} |
27d9695d AP |
721 | |
722 | logger.info("Verifying %s routes on r3", addr_type) | |
787e7624 | 723 | result = verify_rib( |
724 | tgen, | |
725 | addr_type, | |
726 | dut, | |
727 | input_dict, | |
728 | next_hop=[], | |
729 | protocol=protocol, | |
730 | expected=False, | |
731 | ) | |
732 | assert ( | |
733 | result is not True | |
734 | ), "Testcase {} : Failed \n Routes still" " present in RIB".format(tc_name) | |
27d9695d AP |
735 | |
736 | static_or_nw(tgen, topo, tc_name, "advertise_nw", "r2") | |
737 | for addr_type in ADDR_TYPES: | |
787e7624 | 738 | input_dict = {"r3": {"static_routes": [{"network": NETWORK[addr_type]}]}} |
27d9695d | 739 | logger.info("Verifying %s routes on r3", addr_type) |
787e7624 | 740 | result = verify_rib( |
741 | tgen, | |
742 | addr_type, | |
743 | dut, | |
744 | input_dict, | |
745 | next_hop=NEXT_HOPS[addr_type], | |
746 | protocol=protocol, | |
747 | ) | |
27d9695d | 748 | assert result is True, "Testcase {} : Failed \n Error: {}".format( |
787e7624 | 749 | tc_name, result |
750 | ) | |
27d9695d AP |
751 | |
752 | ||
753 | if __name__ == "__main__": | |
754 | args = ["-s"] + sys.argv[1:] | |
755 | sys.exit(pytest.main(args)) |