]>
Commit | Line | Data |
---|---|---|
0705f312 | 1 | #!/usr/bin/python |
2 | ||
3 | # | |
4 | # Copyright (c) 2020 by VMware, Inc. ("VMware") | |
5 | # Used Copyright (c) 2018 by Network Device Education Foundation, | |
6 | # Inc. ("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 | -Verify static route functionality with 8 next hop different AD value | |
26 | and BGP ECMP | |
27 | ||
28 | -Verify 8 static route functionality with 8 next hop different AD | |
29 | ||
30 | -Verify static route with 8 next hop with different AD value and 8 | |
31 | EBGP neighbors | |
32 | ||
33 | -Verify static route with 8 next hop with different AD value and 8 | |
34 | IBGP neighbors | |
35 | ||
36 | -Delete the static route and verify the RIB and FIB state | |
37 | ||
38 | -Verify 8 static route functionality with 8 ECMP next hop | |
39 | """ | |
40 | import sys | |
41 | import json | |
42 | import time | |
43 | import os | |
44 | import pytest | |
d33a0fcf | 45 | import platform |
0705f312 | 46 | import random |
d33a0fcf | 47 | from lib.topotest import version_cmp |
0705f312 | 48 | |
49 | # Save the Current Working Directory to find configuration files. | |
50 | CWD = os.path.dirname(os.path.realpath(__file__)) | |
51 | sys.path.append(os.path.join(CWD, "../")) | |
52 | sys.path.append(os.path.join(CWD, "../lib/")) | |
53 | # pylint: disable=C0413 | |
54 | # Import topogen and topotest helpers | |
55 | from mininet.topo import Topo | |
56 | from lib.topogen import Topogen, get_topogen | |
57 | ||
58 | # Import topoJson from lib, to create topology and initial configuration | |
59 | from lib.common_config import ( | |
60 | start_topology, | |
61 | write_test_header, | |
62 | write_test_footer, | |
63 | reset_config_on_routers, | |
64 | verify_rib, | |
65 | create_static_routes, | |
66 | check_address_types, | |
67 | step, | |
0705f312 | 68 | shutdown_bringup_interface, |
69 | stop_router, | |
70 | start_router, | |
71 | ) | |
72 | from lib.topolog import logger | |
73 | from lib.bgp import verify_bgp_convergence, create_router_bgp, verify_bgp_rib | |
74 | from lib.topojson import build_topo_from_json, build_config_from_json | |
75 | ||
efb62eed DS |
76 | pytestmark = [pytest.mark.bgpd, pytest.mark.staticd] |
77 | ||
0705f312 | 78 | # Reading the data from JSON File for topology creation |
79 | jsonFile = "{}/static_routes_topo2_ebgp.json".format(CWD) | |
80 | try: | |
81 | with open(jsonFile, "r") as topoJson: | |
82 | topo = json.load(topoJson) | |
83 | except IOError: | |
84 | assert False, "Could not read file {}".format(jsonFile) | |
85 | # Global variables | |
86 | BGP_CONVERGENCE = False | |
87 | ADDR_TYPES = check_address_types() | |
88 | NETWORK = { | |
89 | "ipv4": [ | |
90 | "11.0.20.1/32", | |
91 | "11.0.20.2/32", | |
92 | "11.0.20.3/32", | |
93 | "11.0.20.4/32", | |
94 | "11.0.20.5/32", | |
95 | "11.0.20.6/32", | |
96 | "11.0.20.7/32", | |
97 | "11.0.20.8/32", | |
98 | ], | |
99 | "ipv6": [ | |
100 | "2::1/128", | |
101 | "2::2/128", | |
102 | "2::3/128", | |
103 | "2::4/128", | |
104 | "2::5/128", | |
105 | "2::6/128", | |
106 | "2::7/128", | |
107 | "2::8/128", | |
108 | ], | |
109 | } | |
110 | PREFIX1 = {"ipv4": "110.0.20.1/32", "ipv6": "20::1/128"} | |
111 | PREFIX2 = {"ipv4": "110.0.20.2/32", "ipv6": "20::2/128"} | |
112 | NEXT_HOP_IP = [] | |
113 | topo_diag = """ | |
114 | Please view in a fixed-width font such as Courier. | |
115 | +------+ +------+ +------+ | |
116 | | +--------------+ +--------------+ | | |
117 | | | | | | | | |
118 | | R1 +---8 links----+ R2 +---8 links----+ R3 | | |
119 | | | | | | | | |
120 | | +--------------+ +--------------+ | | |
121 | +------+ +------+ +------+ | |
122 | ||
123 | """ | |
124 | ||
125 | ||
126 | class CreateTopo(Topo): | |
127 | """ | |
128 | Test CreateTopo - topology 1. | |
129 | ||
130 | * `Topo`: Topology object | |
131 | """ | |
132 | ||
133 | def build(self, *_args, **_opts): | |
134 | """Build function.""" | |
135 | tgen = get_topogen(self) | |
136 | ||
137 | # Building topology from json file | |
138 | build_topo_from_json(tgen, topo) | |
139 | ||
140 | ||
141 | def setup_module(mod): | |
142 | """ | |
143 | ||
144 | Set up the pytest environment. | |
145 | ||
146 | * `mod`: module name | |
147 | """ | |
148 | global topo | |
149 | testsuite_run_time = time.asctime(time.localtime(time.time())) | |
150 | logger.info("Testsuite start time: {}".format(testsuite_run_time)) | |
151 | logger.info("=" * 40) | |
152 | ||
153 | logger.info("Running setup_module to create topology") | |
154 | ||
155 | # This function initiates the topology build with Topogen... | |
156 | tgen = Topogen(CreateTopo, mod.__name__) | |
157 | # ... and here it calls Mininet initialization functions. | |
158 | ||
159 | # Starting topology, create tmp files which are loaded to routers | |
160 | # to start deamons and then start routers | |
161 | start_topology(tgen) | |
162 | ||
163 | # Creating configuration from JSON | |
164 | build_config_from_json(tgen, topo) | |
165 | ||
5980ad0a DS |
166 | if version_cmp(platform.release(), "4.19") < 0: |
167 | error_msg = ( | |
168 | 'These tests will not run. (have kernel "{}", ' | |
169 | "requires kernel >= 4.19)".format(platform.release()) | |
170 | ) | |
d33a0fcf | 171 | pytest.skip(error_msg) |
172 | ||
0705f312 | 173 | # Checking BGP convergence |
174 | global BGP_CONVERGENCE | |
175 | global ADDR_TYPES | |
176 | # Don't run this test if we have any failure. | |
177 | if tgen.routers_have_failure(): | |
178 | pytest.skip(tgen.errors) | |
179 | # Api call verify whether BGP is converged | |
180 | BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) | |
181 | assert BGP_CONVERGENCE is True, "setup_module :Failed \n Error: {}".format( | |
182 | BGP_CONVERGENCE | |
183 | ) | |
184 | ||
185 | logger.info("Running setup_module() done") | |
186 | ||
187 | ||
188 | def teardown_module(mod): | |
189 | """ | |
190 | Teardown the pytest environment | |
191 | ||
192 | * `mod`: module name | |
193 | """ | |
194 | ||
195 | logger.info("Running teardown_module to delete topology") | |
196 | ||
197 | tgen = get_topogen() | |
198 | ||
199 | # Stop toplogy and Remove tmp files | |
200 | tgen.stop_topology() | |
201 | ||
202 | logger.info( | |
203 | "Testsuite end time: {}".format(time.asctime(time.localtime(time.time()))) | |
204 | ) | |
205 | logger.info("=" * 40) | |
206 | ||
207 | ||
208 | def populate_nh(): | |
209 | NEXT_HOP_IP = { | |
210 | "nh1": { | |
211 | "ipv4": topo["routers"]["r1"]["links"]["r2-link0"]["ipv4"].split("/")[0], | |
212 | "ipv6": topo["routers"]["r1"]["links"]["r2-link0"]["ipv6"].split("/")[0], | |
213 | }, | |
214 | "nh2": { | |
215 | "ipv4": topo["routers"]["r1"]["links"]["r2-link1"]["ipv4"].split("/")[0], | |
216 | "ipv6": topo["routers"]["r1"]["links"]["r2-link1"]["ipv6"].split("/")[0], | |
217 | }, | |
218 | "nh3": { | |
219 | "ipv4": topo["routers"]["r1"]["links"]["r2-link2"]["ipv4"].split("/")[0], | |
220 | "ipv6": topo["routers"]["r1"]["links"]["r2-link2"]["ipv6"].split("/")[0], | |
221 | }, | |
222 | "nh4": { | |
223 | "ipv4": topo["routers"]["r1"]["links"]["r2-link3"]["ipv4"].split("/")[0], | |
224 | "ipv6": topo["routers"]["r1"]["links"]["r2-link3"]["ipv6"].split("/")[0], | |
225 | }, | |
226 | "nh5": { | |
227 | "ipv4": topo["routers"]["r1"]["links"]["r2-link4"]["ipv4"].split("/")[0], | |
228 | "ipv6": topo["routers"]["r1"]["links"]["r2-link4"]["ipv6"].split("/")[0], | |
229 | }, | |
230 | "nh6": { | |
231 | "ipv4": topo["routers"]["r1"]["links"]["r2-link5"]["ipv4"].split("/")[0], | |
232 | "ipv6": topo["routers"]["r1"]["links"]["r2-link5"]["ipv6"].split("/")[0], | |
233 | }, | |
234 | "nh7": { | |
235 | "ipv4": topo["routers"]["r1"]["links"]["r2-link6"]["ipv4"].split("/")[0], | |
236 | "ipv6": topo["routers"]["r1"]["links"]["r2-link6"]["ipv6"].split("/")[0], | |
237 | }, | |
238 | "nh8": { | |
239 | "ipv4": topo["routers"]["r1"]["links"]["r2-link7"]["ipv4"].split("/")[0], | |
240 | "ipv6": topo["routers"]["r1"]["links"]["r2-link7"]["ipv6"].split("/")[0], | |
241 | }, | |
242 | } | |
243 | return NEXT_HOP_IP | |
244 | ||
245 | ||
246 | ##################################################### | |
247 | # | |
248 | # Testcases | |
249 | # | |
250 | ##################################################### | |
251 | ||
252 | ||
253 | def test_static_rte_with_8ecmp_nh_p1_tc9_ebgp(request): | |
254 | """ | |
255 | Verify 8 static route functionality with 8 ECMP next hop | |
256 | ||
257 | """ | |
258 | tc_name = request.node.name | |
259 | write_test_header(tc_name) | |
260 | tgen = get_topogen() | |
261 | # Don't run this test if we have any failure. | |
262 | if tgen.routers_have_failure(): | |
263 | pytest.skip(tgen.errors) | |
264 | NEXT_HOP_IP = populate_nh() | |
265 | step("Configure 8 interfaces / links between R1 and R2") | |
266 | step("Configure 8 interfaces / links between R2 and R3") | |
267 | step("Configure 8 IBGP IPv4 peering between R2 and R3 router.") | |
268 | reset_config_on_routers(tgen) | |
269 | ||
270 | step( | |
271 | "Configure 8 IPv4 static route in R2 with 8 next hop" | |
272 | "N1(21.1.1.2) , N2(22.1.1.2) , N3(23.1.1.2) , N4(24.1.1.2) ," | |
273 | "N5(25.1.1.2) , N6(26.1.1.2) , N7(27.1.1.2) , N8(28.1.1.2) ," | |
274 | "Static route next-hop present on R1" | |
275 | ) | |
276 | nh_all = {} | |
277 | for addr_type in ADDR_TYPES: | |
278 | # Enable static routes | |
279 | for nhp in range(1, 9): | |
280 | input_dict_4 = { | |
281 | "r2": { | |
282 | "static_routes": [ | |
283 | { | |
284 | "network": PREFIX1[addr_type], | |
285 | "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type], | |
286 | } | |
287 | ] | |
288 | } | |
289 | } | |
290 | logger.info("Configure static routes") | |
291 | result = create_static_routes(tgen, input_dict_4) | |
292 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
293 | tc_name, result | |
294 | ) | |
295 | logger.info("Verifying %s routes on r2", addr_type) | |
296 | nh_all[addr_type] = [ | |
297 | NEXT_HOP_IP["nh1"][addr_type], | |
298 | NEXT_HOP_IP["nh2"][addr_type], | |
299 | NEXT_HOP_IP["nh3"][addr_type], | |
300 | NEXT_HOP_IP["nh4"][addr_type], | |
301 | NEXT_HOP_IP["nh5"][addr_type], | |
302 | NEXT_HOP_IP["nh6"][addr_type], | |
303 | NEXT_HOP_IP["nh7"][addr_type], | |
304 | NEXT_HOP_IP["nh8"][addr_type], | |
305 | ] | |
306 | ||
307 | dut = "r2" | |
308 | protocol = "static" | |
309 | result = verify_rib( | |
310 | tgen, | |
311 | addr_type, | |
312 | dut, | |
313 | input_dict_4, | |
314 | next_hop=nh_all[addr_type], | |
315 | protocol=protocol, | |
316 | ) | |
317 | assert result is True, "Testcase {} : Failed \nError: Routes are" | |
318 | " missing in RIB".format(tc_name) | |
319 | ||
320 | step("Configure redistribute static in BGP on R2 router") | |
321 | for addr_type in ADDR_TYPES: | |
322 | input_dict_2 = { | |
323 | "r2": { | |
324 | "bgp": { | |
325 | "address_family": { | |
326 | addr_type: { | |
327 | "unicast": {"redistribute": [{"redist_type": "static"}]} | |
328 | } | |
329 | } | |
330 | } | |
331 | } | |
332 | } | |
333 | result = create_router_bgp(tgen, topo, input_dict_2) | |
334 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
335 | tc_name, result | |
336 | ) | |
337 | ||
338 | dut = "r3" | |
339 | protocol = "bgp" | |
340 | result = verify_bgp_rib(tgen, addr_type, dut, input_dict_4) | |
341 | assert result is True, "Testcase {} : Failed \nError: Routes are" | |
342 | " missing in RIB".format(tc_name) | |
343 | ||
344 | step( | |
345 | "Remove the static route configured with nexthop N1 to N8, one" | |
346 | "by one from running config" | |
347 | ) | |
348 | dut = "r2" | |
349 | protocol = "static" | |
350 | step( | |
351 | "After removing the static route with N1 to N8 one by one , " | |
352 | "verify that entry is removed from RIB and FIB of R3 " | |
353 | ) | |
354 | for addr_type in ADDR_TYPES: | |
355 | for nhp in range(1, 9): | |
356 | input_dict_4 = { | |
357 | "r2": { | |
358 | "static_routes": [ | |
359 | { | |
360 | "network": PREFIX1[addr_type], | |
361 | "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type], | |
362 | "delete": True, | |
363 | } | |
364 | ] | |
365 | } | |
366 | } | |
367 | logger.info("Configure static routes") | |
368 | result = create_static_routes(tgen, input_dict_4) | |
369 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
370 | tc_name, result | |
371 | ) | |
372 | ||
373 | step( | |
374 | "After removing the static route with N1 to N8 one by one , " | |
375 | "verify that entry is removed from RIB and FIB of R3 " | |
376 | ) | |
377 | nh = NEXT_HOP_IP["nh" + str(nhp)][addr_type] | |
378 | result = verify_rib( | |
379 | tgen, | |
380 | addr_type, | |
381 | dut, | |
382 | input_dict_4, | |
383 | next_hop=nh, | |
384 | protocol=protocol, | |
385 | expected=False, | |
386 | ) | |
387 | assert result is not True, "Testcase {} : Failed\nError: Routes is" | |
388 | " still present in RIB".format(tc_name) | |
389 | ||
390 | step("Configure the static route with nexthop N1 to N8, one by one") | |
391 | for addr_type in ADDR_TYPES: | |
392 | for nhp in range(1, 9): | |
393 | input_dict_4 = { | |
394 | "r2": { | |
395 | "static_routes": [ | |
396 | { | |
397 | "network": PREFIX1[addr_type], | |
398 | "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type], | |
399 | } | |
400 | ] | |
401 | } | |
402 | } | |
403 | logger.info("Configure static routes") | |
404 | result = create_static_routes(tgen, input_dict_4) | |
405 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
406 | tc_name, result | |
407 | ) | |
408 | ||
409 | nh = NEXT_HOP_IP["nh" + str(nhp)][addr_type] | |
410 | result = verify_rib( | |
411 | tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol | |
412 | ) | |
413 | assert result is True, "Testcase {} : Failed\nError: Routes are" | |
414 | " missing in RIB".format(tc_name) | |
415 | ||
0705f312 | 416 | protocol = "static" |
0705f312 | 417 | step("Random shut of the nexthop interfaces") |
418 | randnum = random.randint(0, 7) | |
419 | # Shutdown interface | |
420 | dut = "r2" | |
421 | step( | |
422 | " interface which is about to be shut no shut between r1 and r2 is " "%s", | |
423 | topo["routers"]["r2"]["links"]["r1-link{}".format(randnum)]["interface"], | |
424 | ) | |
425 | intf = topo["routers"]["r2"]["links"]["r1-link{}".format(randnum)]["interface"] | |
426 | shutdown_bringup_interface(tgen, dut, intf, False) | |
427 | ||
0705f312 | 428 | step("Random no shut of the nexthop interfaces") |
429 | # Bringup interface | |
430 | shutdown_bringup_interface(tgen, dut, intf, True) | |
431 | ||
432 | step( | |
433 | "After random shut/no shut of nexthop , only that " | |
434 | "nexthop deleted/added from all the routes , other nexthop remain " | |
435 | "unchanged" | |
436 | ) | |
437 | dut = "r2" | |
438 | protocol = "static" | |
439 | for addr_type in ADDR_TYPES: | |
440 | input_dict_4 = { | |
441 | "r2": { | |
442 | "static_routes": [ | |
443 | { | |
444 | "network": PREFIX1[addr_type], | |
445 | "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type], | |
446 | } | |
447 | ] | |
448 | } | |
449 | } | |
450 | result = verify_rib( | |
451 | tgen, | |
452 | addr_type, | |
453 | dut, | |
454 | input_dict_4, | |
455 | next_hop=nh_all[addr_type], | |
456 | protocol=protocol, | |
457 | ) | |
458 | assert result is True, "Testcase {} : Failed \nError: Routes are" | |
459 | " missing in RIB".format(tc_name) | |
460 | ||
461 | step("Remove random static route with all the nexthop") | |
462 | dut = "r2" | |
463 | randnum = random.randint(1, 7) | |
464 | for addr_type in ADDR_TYPES: | |
465 | input_dict_4 = { | |
466 | "r2": { | |
467 | "static_routes": [ | |
468 | { | |
469 | "network": PREFIX1[addr_type], | |
470 | "next_hop": NEXT_HOP_IP["nh" + str(randnum)][addr_type], | |
471 | "delete": True, | |
472 | } | |
473 | ] | |
474 | } | |
475 | } | |
476 | logger.info("Configure static routes") | |
477 | result = create_static_routes(tgen, input_dict_4) | |
478 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
479 | tc_name, result | |
480 | ) | |
481 | ||
482 | step( | |
483 | "After delete of random route , that route only got deleted from" | |
484 | " RIB/FIB other route are showing properly" | |
485 | ) | |
486 | nh = NEXT_HOP_IP["nh{}".format(randnum)][addr_type] | |
487 | result = verify_rib( | |
488 | tgen, | |
489 | addr_type, | |
490 | dut, | |
491 | input_dict_4, | |
492 | next_hop=nh, | |
493 | protocol=protocol, | |
494 | expected=False, | |
495 | ) | |
496 | assert result is not True, "Testcase {} : Failed \nError: Routes are" | |
497 | " missing in RIB".format(tc_name) | |
498 | ||
499 | for addr_type in ADDR_TYPES: | |
500 | input_dict_4 = { | |
501 | "r2": { | |
502 | "static_routes": [ | |
503 | { | |
504 | "network": PREFIX1[addr_type], | |
505 | "next_hop": NEXT_HOP_IP["nh" + str(randnum)][addr_type], | |
506 | } | |
507 | ] | |
508 | } | |
509 | } | |
510 | logger.info("Configure static routes") | |
511 | result = create_static_routes(tgen, input_dict_4) | |
512 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
513 | tc_name, result | |
514 | ) | |
515 | ||
516 | step("Reload the FRR router") | |
517 | # stop/start -> restart FRR router and verify | |
518 | stop_router(tgen, "r2") | |
0705f312 | 519 | start_router(tgen, "r2") |
520 | ||
521 | step( | |
522 | "After reload of FRR router , static route " | |
523 | "installed in RIB and FIB properly ." | |
524 | ) | |
525 | for addr_type in ADDR_TYPES: | |
526 | # Enable static routes | |
527 | nhp = 1 | |
528 | input_dict_4 = { | |
529 | "r2": { | |
530 | "static_routes": [ | |
531 | { | |
532 | "network": PREFIX1[addr_type], | |
533 | "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type], | |
534 | } | |
535 | ] | |
536 | } | |
537 | } | |
538 | logger.info("Verifying %s routes on r2", addr_type) | |
539 | dut = "r2" | |
540 | protocol = "static" | |
541 | result = verify_rib( | |
542 | tgen, | |
543 | addr_type, | |
544 | dut, | |
545 | input_dict_4, | |
546 | next_hop=nh_all[addr_type], | |
547 | protocol=protocol, | |
548 | ) | |
549 | assert result is True, "Testcase {} : Failed \nError: Routes are" | |
550 | " missing in RIB".format(tc_name) | |
551 | ||
0705f312 | 552 | step("Remove the redistribute static knob") |
553 | for addr_type in ADDR_TYPES: | |
554 | input_dict_2 = { | |
555 | "r2": { | |
556 | "bgp": { | |
557 | "address_family": { | |
558 | addr_type: { | |
559 | "unicast": { | |
560 | "redistribute": [ | |
561 | {"redist_type": "static", "delete": True} | |
562 | ] | |
563 | } | |
564 | } | |
565 | } | |
566 | } | |
567 | } | |
568 | } | |
569 | result = create_router_bgp(tgen, topo, input_dict_2) | |
570 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
571 | tc_name, result | |
572 | ) | |
573 | ||
574 | step( | |
575 | "After removing the BGP neighbor or redistribute static knob , " | |
576 | "verify route got clear from RIB and FIB of R3 routes " | |
577 | ) | |
578 | dut = "r3" | |
579 | protocol = "bgp" | |
580 | result = verify_rib( | |
581 | tgen, addr_type, dut, input_dict_4, protocol=protocol, expected=False | |
582 | ) | |
583 | assert result is not True, "Testcase {} : Failed \nError: Routes are" | |
584 | " still present in RIB".format(tc_name) | |
585 | ||
586 | write_test_footer(tc_name) | |
587 | ||
588 | ||
589 | def test_static_route_8nh_diff_AD_bgp_ecmp_p1_tc6_ebgp(request): | |
590 | """ | |
591 | Verify static route functionality with 8 next hop different AD | |
592 | value and BGP ECMP | |
593 | ||
594 | """ | |
595 | tc_name = request.node.name | |
596 | write_test_header(tc_name) | |
597 | tgen = get_topogen() | |
598 | # Don't run this test if we have any failure. | |
599 | if tgen.routers_have_failure(): | |
600 | pytest.skip(tgen.errors) | |
601 | ||
602 | step("Configure 8 interfaces / links between R1 and R2 ,") | |
603 | step("Configure 8 interlaces/links between R2 and R3") | |
604 | step( | |
605 | "Configure IBGP IPv4 peering over loopback interface between" | |
606 | "R2 and R3 router." | |
607 | ) | |
608 | step("Configure redistribute static in BGP on R2 router") | |
609 | reset_config_on_routers(tgen) | |
610 | NEXT_HOP_IP = populate_nh() | |
611 | nh_all = {} | |
612 | for addr_type in ADDR_TYPES: | |
613 | nh_all[addr_type] = [] | |
614 | for nhp in range(1, 9): | |
615 | nh_all[addr_type].append(NEXT_HOP_IP["nh" + str(nhp)][addr_type]) | |
616 | step( | |
617 | "Configure IPv4 static route in R2 with 8 next hop" | |
618 | "N1(21.1.1.2) AD 10, N2(22.1.1.2) AD 20, N3(23.1.1.2) AD 30," | |
619 | "N4(24.1.1.2) AD 40, N5(25.1.1.2) AD 50, N6(26.1.1.2) AD 60," | |
620 | "N7(27.1.1.2) AD 70, N8(28.1.1.2) AD 80, Static route next-hop" | |
621 | "present on R1" | |
622 | ) | |
623 | for addr_type in ADDR_TYPES: | |
624 | for nhp in range(1, 9): | |
625 | input_dict_4 = { | |
626 | "r2": { | |
627 | "static_routes": [ | |
628 | { | |
629 | "network": PREFIX1[addr_type], | |
630 | "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type], | |
631 | "admin_distance": 10 * nhp, | |
632 | } | |
633 | ] | |
634 | } | |
635 | } | |
636 | logger.info("Configure static routes") | |
637 | result = create_static_routes(tgen, input_dict_4) | |
638 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
639 | tc_name, result | |
640 | ) | |
641 | logger.info("Verifying %s routes on r2", addr_type) | |
642 | ||
643 | step( | |
644 | "On R2, static route installed in RIB using " | |
645 | "show ip route with 8 next hop , lowest AD nexthop is active" | |
646 | ) | |
647 | input_dict_4 = { | |
648 | "r2": { | |
649 | "static_routes": [ | |
650 | { | |
651 | "network": PREFIX1[addr_type], | |
652 | "next_hop": NEXT_HOP_IP["nh1"][addr_type], | |
653 | "admin_distance": 10, | |
654 | } | |
655 | ] | |
656 | } | |
657 | } | |
658 | dut = "r2" | |
659 | protocol = "static" | |
660 | nh = NEXT_HOP_IP["nh1"][addr_type] | |
661 | result = verify_rib( | |
662 | tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True | |
663 | ) | |
664 | assert result is True, "Testcase {} : Failed \nError: Routes are" | |
665 | " missing in RIB".format(tc_name) | |
666 | ||
667 | nh = [] | |
668 | for nhp in range(2, 9): | |
669 | nh.append(NEXT_HOP_IP["nh" + str(nhp)][addr_type]) | |
670 | result = verify_rib( | |
671 | tgen, | |
672 | addr_type, | |
673 | dut, | |
674 | input_dict_4, | |
675 | next_hop=nh, | |
676 | protocol=protocol, | |
677 | fib=True, | |
678 | expected=False, | |
679 | wait=2, | |
680 | attempts=3, | |
681 | ) | |
682 | assert result is not True, "Testcase {} : Failed \nError: Routes " | |
683 | " are missing in RIB".format(tc_name) | |
684 | ||
685 | step( | |
686 | "Remove the static route configured with nexthop N1 to N8, one" | |
687 | "by one from running config" | |
688 | ) | |
689 | ||
690 | for addr_type in ADDR_TYPES: | |
691 | # delete static routes | |
692 | for nhp in range(1, 9): | |
693 | input_dict_4 = { | |
694 | "r2": { | |
695 | "static_routes": [ | |
696 | { | |
697 | "network": PREFIX1[addr_type], | |
698 | "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type], | |
699 | "admin_distance": 10 * nhp, | |
700 | "delete": True, | |
701 | } | |
702 | ] | |
703 | } | |
704 | } | |
705 | ||
706 | logger.info("Configure static routes") | |
707 | result = create_static_routes(tgen, input_dict_4) | |
708 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
709 | tc_name, result | |
710 | ) | |
711 | ||
712 | step( | |
713 | "After removing the static route with N1 to N8 one by one , " | |
714 | "route become active with next preferred nexthop and nexthop which " | |
715 | "got removed is not shown in RIB and FIB" | |
716 | ) | |
717 | result = verify_rib( | |
718 | tgen, | |
719 | addr_type, | |
720 | dut, | |
721 | input_dict_4, | |
722 | next_hop=nh_all[addr_type], | |
723 | protocol=protocol, | |
724 | expected=False, | |
725 | ) | |
726 | assert result is not True, "Testcase {} : Failed \nError: Routes are" | |
727 | " still present in RIB".format(tc_name) | |
728 | ||
729 | step("Configure the static route with nexthop N1 to N8, one by one") | |
730 | ||
731 | for addr_type in ADDR_TYPES: | |
732 | # add static routes | |
733 | for nhp in range(1, 9): | |
734 | input_dict_4 = { | |
735 | "r2": { | |
736 | "static_routes": [ | |
737 | { | |
738 | "network": PREFIX1[addr_type], | |
739 | "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type], | |
740 | "admin_distance": 10 * nhp, | |
741 | } | |
742 | ] | |
743 | } | |
744 | } | |
745 | logger.info("Configure static routes") | |
746 | result = create_static_routes(tgen, input_dict_4) | |
747 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
748 | tc_name, result | |
749 | ) | |
750 | ||
751 | step( | |
752 | " After configuring them, route is always active with lowest AD" | |
753 | " value and all the nexthop populated in RIB and FIB again" | |
754 | ) | |
755 | for addr_type in ADDR_TYPES: | |
756 | input_dict_4 = { | |
757 | "r2": { | |
758 | "static_routes": [ | |
759 | { | |
760 | "network": PREFIX1[addr_type], | |
761 | "next_hop": NEXT_HOP_IP["nh1"][addr_type], | |
762 | "admin_distance": 10, | |
763 | } | |
764 | ] | |
765 | } | |
766 | } | |
767 | dut = "r2" | |
768 | protocol = "static" | |
769 | nh = NEXT_HOP_IP["nh1"][addr_type] | |
770 | result = verify_rib( | |
771 | tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True | |
772 | ) | |
773 | assert result is True, "Testcase {} : Failed \nError: Routes are" | |
774 | " missing in RIB".format(tc_name) | |
775 | nh = [] | |
776 | for nhp in range(2, 9): | |
777 | nh.append(NEXT_HOP_IP["nh" + str(nhp)][addr_type]) | |
778 | result = verify_rib( | |
779 | tgen, | |
780 | addr_type, | |
781 | dut, | |
782 | input_dict_4, | |
783 | next_hop=nh, | |
784 | protocol=protocol, | |
785 | fib=True, | |
786 | expected=False, | |
787 | wait=2, | |
788 | attempts=3, | |
789 | ) | |
790 | assert result is not True, "Testcase {} : Failed \nError: Routes " | |
791 | " are missing in RIB".format(tc_name) | |
792 | ||
0705f312 | 793 | step("Random shut of the nexthop interfaces") |
794 | randnum = random.randint(0, 7) | |
795 | for addr_type in ADDR_TYPES: | |
796 | intf = topo["routers"]["r2"]["links"]["r1-link" + str(randnum)]["interface"] | |
797 | shutdown_bringup_interface(tgen, dut, intf, False) | |
798 | nhip = NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type] | |
799 | input_dict_5 = { | |
800 | "r2": { | |
801 | "static_routes": [ | |
802 | { | |
803 | "network": PREFIX1[addr_type], | |
804 | "next_hop": NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type], | |
805 | } | |
806 | ] | |
807 | } | |
808 | } | |
809 | result = verify_rib( | |
810 | tgen, | |
811 | addr_type, | |
812 | dut, | |
813 | input_dict_5, | |
814 | next_hop=nhip, | |
815 | protocol=protocol, | |
816 | expected=False, | |
817 | ) | |
818 | assert result is not True, "Testcase {} : Failed \n" | |
819 | "Error: Routes are still present in RIB".format(tc_name) | |
820 | ||
821 | step("Random no shut of the nexthop interfaces") | |
822 | for addr_type in ADDR_TYPES: | |
823 | intf = topo["routers"]["r2"]["links"]["r1-link" + str(randnum)]["interface"] | |
824 | shutdown_bringup_interface(tgen, dut, intf, True) | |
825 | nhip = NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type] | |
826 | result = verify_rib( | |
827 | tgen, addr_type, dut, input_dict_5, next_hop=nhip, protocol=protocol | |
828 | ) | |
829 | assert result is True, "Testcase {} : Failed \n" | |
830 | "Error: Routes are missing in RIB".format(tc_name) | |
831 | ||
832 | dut = "r2" | |
0705f312 | 833 | protocol = "static" |
0705f312 | 834 | for addr_type in ADDR_TYPES: |
835 | input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}} | |
836 | result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol) | |
837 | assert ( | |
838 | result is True | |
839 | ), "Testcase {}: Failed \n " "Error: Routes are missing in RIB".format(tc_name) | |
840 | ||
841 | protocol = "bgp" | |
842 | dut = "r3" | |
843 | for addr_type in ADDR_TYPES: | |
844 | input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}} | |
845 | result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol) | |
846 | assert ( | |
847 | result is True | |
848 | ), "Testcase {}: Failed \n " "Error: Routes are missing in RIB".format(tc_name) | |
849 | ||
850 | step("Reload the FRR router") | |
851 | # stop/start -> restart FRR router and verify | |
852 | stop_router(tgen, "r2") | |
ee51a3d9 | 853 | |
0705f312 | 854 | start_router(tgen, "r2") |
855 | ||
856 | for addr_type in ADDR_TYPES: | |
857 | input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}} | |
858 | result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol) | |
5980ad0a DS |
859 | assert ( |
860 | result is True | |
861 | ), "Testcase {} : Failed \n" "Error: Routes are still present in RIB".format( | |
862 | tc_name | |
0705f312 | 863 | ) |
864 | ||
0705f312 | 865 | write_test_footer(tc_name) |
866 | ||
867 | ||
868 | def test_static_route_8nh_diff_AD_ebgp_ecmp_p1_tc8_ebgp(request): | |
869 | """ | |
870 | Verify static route with 8 next hop with different AD value and 8 | |
871 | EBGP neighbors | |
872 | """ | |
873 | tc_name = request.node.name | |
874 | write_test_header(tc_name) | |
875 | tgen = get_topogen() | |
876 | # Don't run this test if we have any failure. | |
877 | if tgen.routers_have_failure(): | |
878 | pytest.skip(tgen.errors) | |
879 | ||
880 | step("Configure 8 interfaces / links between R1 and R2") | |
881 | step("Configure 8 interlaces/links between R2 and R3") | |
882 | step("Configure 8 EBGP IPv4 peering between R2 and R3") | |
883 | ||
884 | reset_config_on_routers(tgen) | |
885 | NEXT_HOP_IP = populate_nh() | |
886 | ||
887 | step("Configure redistribute static in BGP on R2 router") | |
888 | for addr_type in ADDR_TYPES: | |
889 | input_dict_2 = { | |
890 | "r2": { | |
891 | "bgp": { | |
892 | "address_family": { | |
893 | addr_type: { | |
894 | "unicast": {"redistribute": [{"redist_type": "static"}]} | |
895 | } | |
896 | } | |
897 | } | |
898 | } | |
899 | } | |
900 | result = create_router_bgp(tgen, topo, input_dict_2) | |
901 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
902 | tc_name, result | |
903 | ) | |
904 | ||
905 | step( | |
906 | "Configure IPv4 static route in R2 with 8 next hop" | |
907 | "N1(21.1.1.2) AD 10, N2(22.1.1.2) AD 20, N3(23.1.1.2) AD 30," | |
908 | "N4(24.1.1.2) AD 40, N5(25.1.1.2) AD 50, N6(26.1.1.2) AD 60," | |
909 | "N7(27.1.1.2) AD 70, N8(28.1.1.2) AD 80, Static route next-hop" | |
910 | "present on R1" | |
911 | ) | |
912 | nh_all = {} | |
913 | for addr_type in ADDR_TYPES: | |
914 | nh_all[addr_type] = [] | |
915 | for nhp in range(1, 9): | |
916 | nh_all[addr_type].append(NEXT_HOP_IP["nh" + str(nhp)][addr_type]) | |
917 | for addr_type in ADDR_TYPES: | |
918 | for nhp in range(1, 9): | |
919 | input_dict_4 = { | |
920 | "r2": { | |
921 | "static_routes": [ | |
922 | { | |
923 | "network": PREFIX1[addr_type], | |
924 | "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type], | |
925 | "admin_distance": 10 * nhp, | |
926 | } | |
927 | ] | |
928 | } | |
929 | } | |
930 | logger.info("Configure static routes") | |
931 | result = create_static_routes(tgen, input_dict_4) | |
932 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
933 | tc_name, result | |
934 | ) | |
935 | logger.info("Verifying %s routes on r2", addr_type) | |
936 | ||
937 | step( | |
938 | "On R2, static route installed in RIB using " | |
939 | "show ip route with 8 next hop , lowest AD nexthop is active" | |
940 | ) | |
941 | input_dict_4 = { | |
942 | "r2": { | |
943 | "static_routes": [ | |
944 | { | |
945 | "network": PREFIX1[addr_type], | |
946 | "next_hop": NEXT_HOP_IP["nh1"][addr_type], | |
947 | "admin_distance": 10, | |
948 | } | |
949 | ] | |
950 | } | |
951 | } | |
952 | dut = "r2" | |
953 | protocol = "static" | |
954 | nh = NEXT_HOP_IP["nh1"][addr_type] | |
955 | result = verify_rib( | |
956 | tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True | |
957 | ) | |
958 | assert result is True, "Testcase {} : Failed \nError: Routes are" | |
959 | " missing in RIB".format(tc_name) | |
960 | ||
961 | nh = [] | |
962 | for nhp in range(2, 9): | |
963 | nh.append(NEXT_HOP_IP["nh" + str(nhp)][addr_type]) | |
964 | result = verify_rib( | |
965 | tgen, | |
966 | addr_type, | |
967 | dut, | |
968 | input_dict_4, | |
969 | next_hop=nh, | |
970 | protocol=protocol, | |
971 | fib=True, | |
972 | expected=False, | |
973 | ) | |
974 | assert result is not True, "Testcase {} : Failed \nError: Routes " | |
975 | " are missing in RIB".format(tc_name) | |
976 | ||
977 | step( | |
978 | "Remove the static route configured with nexthop N1 to N8, one" | |
979 | "by one from running config" | |
980 | ) | |
981 | ||
982 | for addr_type in ADDR_TYPES: | |
983 | # delete static routes | |
984 | for nhp in range(1, 9): | |
985 | input_dict_4 = { | |
986 | "r2": { | |
987 | "static_routes": [ | |
988 | { | |
989 | "network": PREFIX1[addr_type], | |
990 | "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type], | |
991 | "admin_distance": 10 * nhp, | |
992 | "delete": True, | |
993 | } | |
994 | ] | |
995 | } | |
996 | } | |
997 | ||
998 | logger.info("Configure static routes") | |
999 | result = create_static_routes(tgen, input_dict_4) | |
1000 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
1001 | tc_name, result | |
1002 | ) | |
1003 | ||
1004 | step( | |
1005 | "After removing the static route with N1 to N8 one by one , " | |
1006 | "route become active with next preferred nexthop and nexthop which " | |
1007 | "got removed is not shown in RIB and FIB" | |
1008 | ) | |
1009 | result = verify_rib( | |
1010 | tgen, | |
1011 | addr_type, | |
1012 | dut, | |
1013 | input_dict_4, | |
1014 | next_hop=nh_all[addr_type], | |
1015 | protocol=protocol, | |
1016 | expected=False, | |
1017 | ) | |
1018 | assert result is not True, "Testcase {} : Failed \nError: Routes are" | |
1019 | " still present in RIB".format(tc_name) | |
1020 | ||
1021 | step("Configure the static route with nexthop N1 to N8, one by one") | |
1022 | ||
1023 | for addr_type in ADDR_TYPES: | |
1024 | # add static routes | |
1025 | for nhp in range(1, 9): | |
1026 | input_dict_4 = { | |
1027 | "r2": { | |
1028 | "static_routes": [ | |
1029 | { | |
1030 | "network": PREFIX1[addr_type], | |
1031 | "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type], | |
1032 | "admin_distance": 10 * nhp, | |
1033 | } | |
1034 | ] | |
1035 | } | |
1036 | } | |
1037 | logger.info("Configure static routes") | |
1038 | result = create_static_routes(tgen, input_dict_4) | |
1039 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
1040 | tc_name, result | |
1041 | ) | |
1042 | ||
1043 | step( | |
1044 | " After configuring them, route is always active with lowest AD" | |
1045 | " value and all the nexthop populated in RIB and FIB again" | |
1046 | ) | |
1047 | for addr_type in ADDR_TYPES: | |
1048 | input_dict_4 = { | |
1049 | "r2": { | |
1050 | "static_routes": [ | |
1051 | { | |
1052 | "network": PREFIX1[addr_type], | |
1053 | "next_hop": NEXT_HOP_IP["nh1"][addr_type], | |
1054 | "admin_distance": 10, | |
1055 | } | |
1056 | ] | |
1057 | } | |
1058 | } | |
1059 | dut = "r2" | |
1060 | protocol = "static" | |
1061 | nh = NEXT_HOP_IP["nh1"][addr_type] | |
1062 | result = verify_rib( | |
1063 | tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True | |
1064 | ) | |
1065 | assert result is True, "Testcase {} : Failed \nError: Routes are" | |
1066 | " missing in RIB".format(tc_name) | |
1067 | nh = [] | |
1068 | for nhp in range(2, 9): | |
1069 | nh.append(NEXT_HOP_IP["nh" + str(nhp)][addr_type]) | |
1070 | result = verify_rib( | |
1071 | tgen, | |
1072 | addr_type, | |
1073 | dut, | |
1074 | input_dict_4, | |
1075 | next_hop=nh, | |
1076 | protocol=protocol, | |
1077 | fib=True, | |
1078 | expected=False, | |
1079 | ) | |
1080 | assert result is not True, "Testcase {} : Failed \nError: Routes " | |
1081 | " are missing in RIB".format(tc_name) | |
1082 | ||
0705f312 | 1083 | step("Random shut of the nexthop interfaces") |
1084 | randnum = random.randint(0, 7) | |
1085 | for addr_type in ADDR_TYPES: | |
1086 | intf = topo["routers"]["r2"]["links"]["r1-link" + str(randnum)]["interface"] | |
1087 | shutdown_bringup_interface(tgen, dut, intf, False) | |
1088 | nhip = NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type] | |
1089 | input_dict_5 = { | |
1090 | "r2": { | |
1091 | "static_routes": [ | |
1092 | { | |
1093 | "network": PREFIX1[addr_type], | |
1094 | "next_hop": NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type], | |
1095 | } | |
1096 | ] | |
1097 | } | |
1098 | } | |
1099 | result = verify_rib( | |
1100 | tgen, | |
1101 | addr_type, | |
1102 | dut, | |
1103 | input_dict_5, | |
1104 | next_hop=nhip, | |
1105 | protocol=protocol, | |
1106 | expected=False, | |
1107 | ) | |
1108 | assert result is not True, "Testcase {} : Failed \n" | |
1109 | "Error: Routes are still present in RIB".format(tc_name) | |
1110 | ||
1111 | step("Random no shut of the nexthop interfaces") | |
1112 | for addr_type in ADDR_TYPES: | |
1113 | intf = topo["routers"]["r2"]["links"]["r1-link" + str(randnum)]["interface"] | |
1114 | shutdown_bringup_interface(tgen, dut, intf, True) | |
1115 | nhip = NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type] | |
1116 | result = verify_rib( | |
1117 | tgen, addr_type, dut, input_dict_5, next_hop=nhip, protocol=protocol | |
1118 | ) | |
1119 | assert result is True, "Testcase {} : Failed \n" | |
1120 | "Error: Routes are missing in RIB".format(tc_name) | |
1121 | ||
1122 | dut = "r2" | |
0705f312 | 1123 | protocol = "static" |
0705f312 | 1124 | |
1125 | step("Reload the FRR router") | |
1126 | # stop/start -> restart FRR router and verify | |
1127 | stop_router(tgen, "r2") | |
ee51a3d9 | 1128 | |
0705f312 | 1129 | start_router(tgen, "r2") |
1130 | ||
1131 | for addr_type in ADDR_TYPES: | |
1132 | input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}} | |
1133 | result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol) | |
5980ad0a DS |
1134 | assert ( |
1135 | result is True | |
1136 | ), "Testcase {} : Failed \n" "Error: Routes are still present in RIB".format( | |
1137 | tc_name | |
0705f312 | 1138 | ) |
1139 | ||
0705f312 | 1140 | write_test_footer(tc_name) |
1141 | ||
1142 | ||
1143 | def test_static_route_8nh_diff_AD_bgp_ecmp_p1_tc10_ebgp(request): | |
1144 | """ | |
1145 | Verify 8 static route functionality with 8 next hop different AD' | |
1146 | ||
1147 | """ | |
1148 | tc_name = request.node.name | |
1149 | write_test_header(tc_name) | |
1150 | tgen = get_topogen() | |
1151 | # Don't run this test if we have any failure. | |
1152 | if tgen.routers_have_failure(): | |
1153 | pytest.skip(tgen.errors) | |
1154 | NEXT_HOP_IP = populate_nh() | |
1155 | ||
1156 | step("Configure 8 interfaces / links between R1 and R2 ") | |
1157 | step("Configure 8 IBGP IPv4 peering between R2 and R3 router.") | |
1158 | reset_config_on_routers(tgen) | |
1159 | ||
1160 | step( | |
1161 | "Configure IPv4 static route in R2 with 8 next hop" | |
1162 | "N1(21.1.1.2) AD 10, N2(22.1.1.2) AD 20, N3(23.1.1.2) AD 30," | |
1163 | "N4(24.1.1.2) AD 40, N5(25.1.1.2) AD 50, N6(26.1.1.2) AD 60," | |
1164 | "N7(27.1.1.2) AD 70, N8(28.1.1.2) AD 80" | |
1165 | ) | |
1166 | step( | |
1167 | "Configure nexthop AD in such way for static route S1 , N1 is" | |
1168 | "preferred and for S2 , N2 is preferred and so on .." | |
1169 | ) | |
1170 | nh_all = {} | |
1171 | for addr_type in ADDR_TYPES: | |
1172 | nh_all[addr_type] = [] | |
1173 | for nhp in range(1, 9): | |
1174 | nh_all[addr_type].append(NEXT_HOP_IP["nh" + str(nhp)][addr_type]) | |
1175 | ||
1176 | for addr_type in ADDR_TYPES: | |
1177 | for nhp in range(1, 9): | |
1178 | input_dict_4 = { | |
1179 | "r2": { | |
1180 | "static_routes": [ | |
1181 | { | |
1182 | "network": PREFIX1[addr_type], | |
1183 | "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type], | |
1184 | "admin_distance": 10 * nhp, | |
1185 | } | |
1186 | ] | |
1187 | } | |
1188 | } | |
1189 | logger.info("Configure static routes") | |
1190 | result = create_static_routes(tgen, input_dict_4) | |
1191 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
1192 | tc_name, result | |
1193 | ) | |
1194 | second_rte = { | |
1195 | "r2": { | |
1196 | "static_routes": [ | |
1197 | { | |
1198 | "network": PREFIX2[addr_type], | |
1199 | "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type], | |
1200 | "admin_distance": 10 * nhp, | |
1201 | } | |
1202 | ] | |
1203 | } | |
1204 | } | |
1205 | logger.info("Configure static routes") | |
1206 | result = create_static_routes(tgen, second_rte) | |
1207 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
1208 | tc_name, result | |
1209 | ) | |
1210 | logger.info("Verifying %s routes on r2", addr_type) | |
1211 | ||
1212 | step( | |
1213 | "On R2, static route installed in RIB using " | |
1214 | "show ip route with 8 next hop , lowest AD nexthop is active" | |
1215 | ) | |
1216 | input_dict_4 = { | |
1217 | "r2": { | |
1218 | "static_routes": [ | |
1219 | { | |
1220 | "network": PREFIX1[addr_type], | |
1221 | "next_hop": NEXT_HOP_IP["nh1"][addr_type], | |
1222 | "admin_distance": 10, | |
1223 | } | |
1224 | ] | |
1225 | } | |
1226 | } | |
1227 | dut = "r2" | |
1228 | protocol = "static" | |
1229 | nh = NEXT_HOP_IP["nh1"][addr_type] | |
1230 | result = verify_rib( | |
1231 | tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True | |
1232 | ) | |
1233 | assert result is True, "Testcase {} : Failed \nError: Routes are" | |
1234 | " missing in RIB".format(tc_name) | |
1235 | ||
1236 | step("Verify that highest AD nexthop are inactive") | |
1237 | nh = [] | |
1238 | for nhp in range(2, 9): | |
1239 | nh.append(NEXT_HOP_IP["nh" + str(nhp)][addr_type]) | |
1240 | result = verify_rib( | |
1241 | tgen, | |
1242 | addr_type, | |
1243 | dut, | |
1244 | input_dict_4, | |
1245 | next_hop=nh, | |
1246 | protocol=protocol, | |
1247 | fib=True, | |
1248 | expected=False, | |
1249 | wait=2, | |
1250 | attempts=3, | |
1251 | ) | |
1252 | assert result is not True, "Testcase {} : Failed \nError: Routes " | |
1253 | " are missing in RIB".format(tc_name) | |
1254 | ||
1255 | step("Configure redistribute static in BGP on R2 router") | |
1256 | for addr_type in ADDR_TYPES: | |
1257 | input_dict_2 = { | |
1258 | "r2": { | |
1259 | "bgp": { | |
1260 | "address_family": { | |
1261 | addr_type: { | |
1262 | "unicast": {"redistribute": [{"redist_type": "static"}]} | |
1263 | } | |
1264 | } | |
1265 | } | |
1266 | } | |
1267 | } | |
1268 | result = create_router_bgp(tgen, topo, input_dict_2) | |
1269 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
1270 | tc_name, result | |
1271 | ) | |
1272 | ||
1273 | step( | |
1274 | "Remove the static route configured with nexthop N1 to N8, one" | |
1275 | "by one from running config" | |
1276 | ) | |
1277 | ||
1278 | for addr_type in ADDR_TYPES: | |
1279 | # delete static routes | |
1280 | for nhp in range(1, 9): | |
1281 | input_dict_4 = { | |
1282 | "r2": { | |
1283 | "static_routes": [ | |
1284 | { | |
1285 | "network": PREFIX1[addr_type], | |
1286 | "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type], | |
1287 | "admin_distance": 10 * nhp, | |
1288 | "delete": True, | |
1289 | } | |
1290 | ] | |
1291 | } | |
1292 | } | |
1293 | ||
1294 | logger.info("Configure static routes") | |
1295 | result = create_static_routes(tgen, input_dict_4) | |
1296 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
1297 | tc_name, result | |
1298 | ) | |
1299 | ||
1300 | step( | |
1301 | "After removing the static route with N1 to N8 one by one , " | |
1302 | "route become active with next preferred nexthop and nexthop which" | |
1303 | "got removed is not shown in RIB and FIB" | |
1304 | ) | |
1305 | ||
1306 | result = verify_rib( | |
1307 | tgen, | |
1308 | addr_type, | |
1309 | dut, | |
1310 | input_dict_4, | |
1311 | next_hop=nh, | |
1312 | protocol=protocol, | |
1313 | expected=False, | |
1314 | ) | |
1315 | assert result is not True, "Testcase {} : Failed \nError: Routes are" | |
1316 | " still present in RIB".format(tc_name) | |
1317 | ||
1318 | step("Configure the static route with nexthop N1 to N8, one by one") | |
1319 | for addr_type in ADDR_TYPES: | |
1320 | # add static routes | |
1321 | for nhp in range(1, 9): | |
1322 | input_dict_4 = { | |
1323 | "r2": { | |
1324 | "static_routes": [ | |
1325 | { | |
1326 | "network": PREFIX1[addr_type], | |
1327 | "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type], | |
1328 | "admin_distance": 10 * nhp, | |
1329 | } | |
1330 | ] | |
1331 | } | |
1332 | } | |
1333 | ||
1334 | logger.info("Configure static routes") | |
1335 | result = create_static_routes(tgen, input_dict_4) | |
1336 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
1337 | tc_name, result | |
1338 | ) | |
1339 | ||
1340 | step( | |
1341 | " After configuring them, route is always active with lowest AD" | |
1342 | " value and all the nexthop populated in RIB and FIB again" | |
1343 | ) | |
1344 | for addr_type in ADDR_TYPES: | |
5980ad0a DS |
1345 | input_dict_4 = { |
1346 | "r2": { | |
1347 | "static_routes": [ | |
1348 | { | |
1349 | "network": PREFIX1[addr_type], | |
1350 | } | |
1351 | ] | |
1352 | } | |
1353 | } | |
0705f312 | 1354 | nh = NEXT_HOP_IP["nh1"][addr_type] |
1355 | result = verify_rib( | |
1356 | tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True | |
1357 | ) | |
1358 | assert result is True, "Testcase {} : Failed \nError: Route with " | |
1359 | "lowest AD is missing in RIB".format(tc_name) | |
1360 | ||
0705f312 | 1361 | step("Random shut of the nexthop interfaces") |
1362 | randnum = random.randint(0, 7) | |
1363 | for addr_type in ADDR_TYPES: | |
1364 | intf = topo["routers"]["r2"]["links"]["r1-link" + str(randnum)]["interface"] | |
1365 | shutdown_bringup_interface(tgen, dut, intf, False) | |
1366 | nhip = NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type] | |
1367 | input_dict_5 = { | |
1368 | "r2": { | |
1369 | "static_routes": [ | |
1370 | { | |
1371 | "network": PREFIX1[addr_type], | |
1372 | "next_hop": NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type], | |
1373 | } | |
1374 | ] | |
1375 | } | |
1376 | } | |
1377 | result = verify_rib( | |
1378 | tgen, | |
1379 | addr_type, | |
1380 | dut, | |
1381 | input_dict_5, | |
1382 | next_hop=nhip, | |
1383 | protocol=protocol, | |
1384 | expected=False, | |
1385 | ) | |
1386 | assert result is not True, "Testcase {} : Failed \n" | |
1387 | "Error: Routes are still present in RIB".format(tc_name) | |
1388 | ||
1389 | step("Random no shut of the nexthop interfaces") | |
1390 | for addr_type in ADDR_TYPES: | |
1391 | intf = topo["routers"]["r2"]["links"]["r1-link" + str(randnum)]["interface"] | |
1392 | shutdown_bringup_interface(tgen, dut, intf, True) | |
1393 | nhip = NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type] | |
1394 | result = verify_rib( | |
1395 | tgen, addr_type, dut, input_dict_5, next_hop=nhip, protocol=protocol | |
1396 | ) | |
1397 | assert result is True, "Testcase {} : Failed \n" | |
1398 | "Error: Routes are missing in RIB".format(tc_name) | |
1399 | ||
1400 | step("Remove random static route with all the nexthop") | |
1401 | for addr_type in ADDR_TYPES: | |
1402 | # delete static routes | |
1403 | for nhp in range(1, 9): | |
1404 | input_dict_4 = { | |
1405 | "r2": { | |
1406 | "static_routes": [ | |
1407 | { | |
1408 | "network": PREFIX1[addr_type], | |
1409 | "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type], | |
1410 | "admin_distance": 10 * nhp, | |
1411 | "delete": True, | |
1412 | } | |
1413 | ] | |
1414 | } | |
1415 | } | |
1416 | logger.info("Configure static routes") | |
1417 | result = create_static_routes(tgen, input_dict_4) | |
1418 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
1419 | tc_name, result | |
1420 | ) | |
1421 | ||
1422 | step( | |
1423 | "After removing the static route with N1 to N8 one by one , " | |
1424 | "route become active with next preferred nexthop and nexthop " | |
1425 | "which got removed is not shown in RIB and FIB" | |
1426 | ) | |
1427 | nh = NEXT_HOP_IP["nh" + str(nhp)][addr_type] | |
1428 | result = verify_rib( | |
1429 | tgen, | |
1430 | addr_type, | |
1431 | dut, | |
1432 | input_dict_4, | |
1433 | next_hop=nh, | |
1434 | protocol=protocol, | |
1435 | expected=False, | |
1436 | ) | |
1437 | assert result is not True, "Testcase {} : Failed \nError: Route " | |
1438 | " is still present in RIB".format(tc_name) | |
1439 | ||
1440 | step("Reconfigure the deleted routes and verify they are installed") | |
1441 | for nhp in range(1, 9): | |
1442 | input_dict_4 = { | |
1443 | "r2": { | |
1444 | "static_routes": [ | |
1445 | { | |
1446 | "network": PREFIX1[addr_type], | |
1447 | "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type], | |
1448 | "admin_distance": 10 * nhp, | |
1449 | } | |
1450 | ] | |
1451 | } | |
1452 | } | |
1453 | logger.info("Configure static routes") | |
1454 | result = create_static_routes(tgen, input_dict_4) | |
1455 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
1456 | tc_name, result | |
1457 | ) | |
1458 | ||
1459 | dut = "r2" | |
1460 | protocol = "static" | |
1461 | nh = NEXT_HOP_IP["nh1"][addr_type] | |
1462 | result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol) | |
1463 | assert result is True, "Testcase {} : Failed \nError: Route " | |
1464 | " is still present in RIB".format(tc_name) | |
1465 | ||
1466 | step("Reload the FRR router") | |
1467 | # stop/start -> restart FRR router and verify | |
1468 | stop_router(tgen, "r2") | |
ee51a3d9 | 1469 | |
0705f312 | 1470 | start_router(tgen, "r2") |
1471 | ||
1472 | step("After reloading, verify that routes are still present in R2.") | |
1473 | result = verify_rib( | |
1474 | tgen, | |
1475 | addr_type, | |
1476 | dut, | |
1477 | second_rte, | |
1478 | next_hop=nh, | |
1479 | protocol=protocol, | |
1480 | fib=True, | |
1481 | ) | |
5980ad0a DS |
1482 | assert ( |
1483 | result is True | |
1484 | ), "Testcase {} : Failed \nError: Route " " is missing in RIB".format( | |
1485 | tc_name | |
0705f312 | 1486 | ) |
1487 | ||
0705f312 | 1488 | write_test_footer(tc_name) |
1489 | ||
1490 | ||
1491 | def test_static_route_delete_p0_tc11_ebgp(request): | |
1492 | """ | |
1493 | Delete the static route and verify the RIB and FIB state | |
1494 | """ | |
1495 | tc_name = request.node.name | |
1496 | write_test_header(tc_name) | |
1497 | tgen = get_topogen() | |
1498 | # Don't run this test if we have any failure. | |
1499 | if tgen.routers_have_failure(): | |
1500 | pytest.skip(tgen.errors) | |
1501 | NEXT_HOP_IP = populate_nh() | |
1502 | ||
1503 | step("Configure 8 interfaces / links between R1 and R2 ") | |
1504 | step("Configure 8 IBGP IPv4 peering between R2 and R3 router.") | |
1505 | reset_config_on_routers(tgen) | |
1506 | ||
1507 | step( | |
1508 | "Configure IPv4 static route in R2 with 8 next hop" | |
1509 | "N1(21.1.1.2) AD 10, N2(22.1.1.2) AD 20, N3(23.1.1.2) AD 30," | |
1510 | "N4(24.1.1.2) AD 40, N5(25.1.1.2) AD 50, N6(26.1.1.2) AD 60," | |
1511 | "N7(27.1.1.2) AD 70, N8(28.1.1.2) AD 80" | |
1512 | ) | |
1513 | step( | |
1514 | "Configure nexthop AD in such way for static route S1 , N1 is" | |
1515 | "preferred and for S2 , N2 is preferred and so on .." | |
1516 | ) | |
1517 | nh_all = {} | |
1518 | for addr_type in ADDR_TYPES: | |
1519 | nh_all[addr_type] = [] | |
1520 | for nhp in range(1, 9): | |
1521 | nh_all[addr_type].append(NEXT_HOP_IP["nh" + str(nhp)][addr_type]) | |
1522 | ||
1523 | for addr_type in ADDR_TYPES: | |
1524 | for nhp in range(1, 9): | |
1525 | input_dict_4 = { | |
1526 | "r2": { | |
1527 | "static_routes": [ | |
1528 | { | |
1529 | "network": PREFIX1[addr_type], | |
1530 | "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type], | |
1531 | "admin_distance": 10 * nhp, | |
1532 | } | |
1533 | ] | |
1534 | } | |
1535 | } | |
1536 | logger.info("Configure static routes") | |
1537 | result = create_static_routes(tgen, input_dict_4) | |
1538 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
1539 | tc_name, result | |
1540 | ) | |
1541 | second_rte = { | |
1542 | "r2": { | |
1543 | "static_routes": [ | |
1544 | { | |
1545 | "network": PREFIX2[addr_type], | |
1546 | "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type], | |
1547 | "admin_distance": 10 * nhp, | |
1548 | } | |
1549 | ] | |
1550 | } | |
1551 | } | |
1552 | logger.info("Configure static routes") | |
1553 | result = create_static_routes(tgen, second_rte) | |
1554 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
1555 | tc_name, result | |
1556 | ) | |
1557 | logger.info("Verifying %s routes on r2", addr_type) | |
1558 | ||
1559 | step( | |
1560 | "On R2, static route installed in RIB using " | |
1561 | "show ip route with 8 next hop , lowest AD nexthop is active" | |
1562 | ) | |
1563 | input_dict_4 = { | |
1564 | "r2": { | |
1565 | "static_routes": [ | |
1566 | { | |
1567 | "network": PREFIX1[addr_type], | |
1568 | "next_hop": NEXT_HOP_IP["nh1"][addr_type], | |
1569 | "admin_distance": 10, | |
1570 | } | |
1571 | ] | |
1572 | } | |
1573 | } | |
1574 | dut = "r2" | |
1575 | protocol = "static" | |
1576 | nh = NEXT_HOP_IP["nh1"][addr_type] | |
1577 | result = verify_rib( | |
1578 | tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True | |
1579 | ) | |
1580 | assert result is True, "Testcase {} : Failed \nError: Routes are" | |
1581 | " missing in RIB".format(tc_name) | |
1582 | ||
1583 | step("Verify that highest AD nexthop are inactive") | |
1584 | nh = [] | |
1585 | for nhp in range(2, 9): | |
1586 | nh.append(NEXT_HOP_IP["nh" + str(nhp)][addr_type]) | |
1587 | result = verify_rib( | |
1588 | tgen, | |
1589 | addr_type, | |
1590 | dut, | |
1591 | input_dict_4, | |
1592 | next_hop=nh, | |
1593 | protocol=protocol, | |
1594 | fib=True, | |
1595 | expected=False, | |
1596 | ) | |
1597 | assert result is not True, "Testcase {} : Failed \nError: Routes " | |
1598 | " are missing in RIB".format(tc_name) | |
1599 | ||
1600 | step("Configure redistribute static in BGP on R2 router") | |
1601 | for addr_type in ADDR_TYPES: | |
1602 | input_dict_2 = { | |
1603 | "r2": { | |
1604 | "bgp": { | |
1605 | "address_family": { | |
1606 | addr_type: { | |
1607 | "unicast": {"redistribute": [{"redist_type": "static"}]} | |
1608 | } | |
1609 | } | |
1610 | } | |
1611 | } | |
1612 | } | |
1613 | result = create_router_bgp(tgen, topo, input_dict_2) | |
1614 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
1615 | tc_name, result | |
1616 | ) | |
1617 | ||
1618 | step("Remove the redistribute static knob") | |
1619 | for addr_type in ADDR_TYPES: | |
1620 | input_dict_2 = { | |
1621 | "r2": { | |
1622 | "bgp": { | |
1623 | "address_family": { | |
1624 | addr_type: { | |
1625 | "unicast": { | |
1626 | "redistribute": [ | |
1627 | {"redist_type": "static", "delete": True} | |
1628 | ] | |
1629 | } | |
1630 | } | |
1631 | } | |
1632 | } | |
1633 | } | |
1634 | } | |
1635 | result = create_router_bgp(tgen, topo, input_dict_2) | |
1636 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
1637 | tc_name, result | |
1638 | ) | |
1639 | ||
1640 | step( | |
1641 | "Verify after removing the redistribute static from BGP all the" | |
1642 | "routes got delete from RIB and FIB of R3 " | |
1643 | ) | |
1644 | ||
1645 | dut = "r3" | |
1646 | protocol = "bgp" | |
1647 | result = verify_rib( | |
1648 | tgen, addr_type, dut, input_dict_4, protocol=protocol, expected=False | |
1649 | ) | |
1650 | assert result is not True, "Testcase {} : Failed \nError: Routes are" | |
1651 | " still present in RIB".format(tc_name) | |
1652 | ||
1653 | for addr_type in ADDR_TYPES: | |
1654 | for nhp in range(1, 9): | |
1655 | input_dict_4 = { | |
1656 | "r2": { | |
1657 | "static_routes": [ | |
1658 | { | |
1659 | "network": PREFIX1[addr_type], | |
1660 | "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type], | |
1661 | "admin_distance": 10 * nhp, | |
1662 | "delete": True, | |
1663 | } | |
1664 | ] | |
1665 | } | |
1666 | } | |
1667 | logger.info("Configure static routes") | |
1668 | result = create_static_routes(tgen, input_dict_4) | |
1669 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
1670 | tc_name, result | |
1671 | ) | |
1672 | second_rte = { | |
1673 | "r2": { | |
1674 | "static_routes": [ | |
1675 | { | |
1676 | "network": PREFIX2[addr_type], | |
1677 | "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type], | |
1678 | "admin_distance": 10 * nhp, | |
1679 | } | |
1680 | ] | |
1681 | } | |
1682 | } | |
1683 | logger.info("Configure static routes") | |
1684 | result = create_static_routes(tgen, second_rte) | |
1685 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
1686 | tc_name, result | |
1687 | ) | |
1688 | logger.info("Verifying %s routes on r2", addr_type) | |
1689 | ||
1690 | step( | |
1691 | " After removing all the routes and nexthop from R2 , " | |
1692 | " verify R2 RIB and FIB is cleared" | |
1693 | ) | |
1694 | input_dict_4 = { | |
1695 | "r2": { | |
1696 | "static_routes": [ | |
1697 | { | |
1698 | "network": PREFIX1[addr_type], | |
1699 | "next_hop": NEXT_HOP_IP["nh1"][addr_type], | |
1700 | "admin_distance": 10, | |
1701 | } | |
1702 | ] | |
1703 | } | |
1704 | } | |
1705 | dut = "r2" | |
1706 | protocol = "static" | |
1707 | nh = NEXT_HOP_IP["nh1"][addr_type] | |
1708 | result = verify_rib( | |
1709 | tgen, | |
1710 | addr_type, | |
1711 | dut, | |
1712 | input_dict_4, | |
1713 | next_hop=nh, | |
1714 | protocol=protocol, | |
1715 | fib=True, | |
1716 | expected=False, | |
1717 | ) | |
1718 | assert result is not True, "Testcase {} : Failed \nError: Routes are" | |
1719 | " still active in RIB".format(tc_name) | |
1720 | write_test_footer(tc_name) | |
1721 | ||
1722 | ||
1723 | if __name__ == "__main__": | |
1724 | args = ["-s"] + sys.argv[1:] | |
1725 | sys.exit(pytest.main(args)) |