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