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