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