]>
Commit | Line | Data |
---|---|---|
26bbe9af | 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 | -Verify static route ECMP functionality with 8 next hop | |
24 | ||
25 | -Verify static route functionality with 8 next hop different AD value | |
26 | ||
27 | -Verify static route with tag option | |
28 | ||
29 | -Verify BGP did not install the static route when it receive route | |
30 | with local next hop | |
31 | ||
32 | """ | |
33 | import sys | |
26bbe9af | 34 | import time |
35 | import os | |
36 | import pytest | |
37 | import random | |
38 | import platform | |
39 | from lib.topotest import version_cmp | |
40 | ||
41 | # Save the Current Working Directory to find configuration files. | |
42 | CWD = os.path.dirname(os.path.realpath(__file__)) | |
43 | sys.path.append(os.path.join(CWD, "../")) | |
44 | sys.path.append(os.path.join(CWD, "../lib/")) | |
45 | # pylint: disable=C0413 | |
46 | # Import topogen and topotest helpers | |
26bbe9af | 47 | from lib.topogen import Topogen, get_topogen |
48 | ||
49 | from lib.common_config import ( | |
50 | start_topology, | |
51 | write_test_header, | |
52 | write_test_footer, | |
53 | reset_config_on_routers, | |
54 | verify_rib, | |
55 | create_static_routes, | |
56 | check_address_types, | |
57 | step, | |
26bbe9af | 58 | shutdown_bringup_interface, |
59 | stop_router, | |
60 | start_router, | |
61 | create_route_maps, | |
62 | verify_ip_nht, | |
63 | ) | |
64 | from lib.topolog import logger | |
65 | from lib.bgp import verify_bgp_convergence, create_router_bgp, verify_bgp_rib | |
4953ca97 | 66 | from lib.topojson import build_config_from_json |
26bbe9af | 67 | |
efb62eed DS |
68 | pytestmark = [pytest.mark.bgpd, pytest.mark.staticd] |
69 | ||
26bbe9af | 70 | # Global variables |
71 | BGP_CONVERGENCE = False | |
72 | ADDR_TYPES = check_address_types() | |
73 | NETWORK = { | |
74 | "ipv4": [ | |
75 | "11.0.20.1/32", | |
76 | "11.0.20.2/32", | |
77 | "11.0.20.3/32", | |
78 | "11.0.20.4/32", | |
79 | "11.0.20.5/32", | |
80 | "11.0.20.6/32", | |
81 | "11.0.20.7/32", | |
82 | "11.0.20.8/32", | |
83 | ], | |
84 | "ipv6": [ | |
85 | "2::1/128", | |
86 | "2::2/128", | |
87 | "2::3/128", | |
88 | "2::4/128", | |
89 | "2::5/128", | |
90 | "2::6/128", | |
91 | "2::7/128", | |
92 | "2::8/128", | |
93 | ], | |
94 | } | |
95 | PREFIX1 = {"ipv4": "110.0.20.1/32", "ipv6": "20::1/128"} | |
96 | NETWORK2 = {"ipv4": ["11.0.20.1/32"], "ipv6": ["2::1/128"]} | |
97 | NEXT_HOP_IP = [] | |
98 | ||
99 | ||
26bbe9af | 100 | def setup_module(mod): |
101 | """ | |
102 | ||
103 | Set up the pytest environment. | |
104 | ||
105 | * `mod`: module name | |
106 | """ | |
26bbe9af | 107 | testsuite_run_time = time.asctime(time.localtime(time.time())) |
108 | logger.info("Testsuite start time: {}".format(testsuite_run_time)) | |
109 | logger.info("=" * 40) | |
110 | ||
111 | logger.info("Running setup_module to create topology") | |
112 | ||
113 | # This function initiates the topology build with Topogen... | |
e82b531d CH |
114 | json_file = "{}/static_routes_topo3_ebgp.json".format(CWD) |
115 | tgen = Topogen(json_file, mod.__name__) | |
116 | global topo | |
117 | topo = tgen.json_topo | |
26bbe9af | 118 | # ... and here it calls Mininet initialization functions. |
119 | ||
120 | # Starting topology, create tmp files which are loaded to routers | |
d60a3f0e | 121 | # to start daemons and then start routers |
26bbe9af | 122 | start_topology(tgen) |
123 | ||
124 | # Creating configuration from JSON | |
125 | build_config_from_json(tgen, topo) | |
126 | ||
127 | if version_cmp(platform.release(), "4.19") < 0: | |
128 | error_msg = ( | |
129 | 'These tests will not run. (have kernel "{}", ' | |
130 | "requires kernel >= 4.19)".format(platform.release()) | |
131 | ) | |
132 | pytest.skip(error_msg) | |
133 | ||
134 | # Checking BGP convergence | |
135 | global BGP_CONVERGENCE | |
136 | global ADDR_TYPES | |
137 | ||
138 | # Don't run this test if we have any failure. | |
139 | if tgen.routers_have_failure(): | |
140 | pytest.skip(tgen.errors) | |
141 | # Api call verify whether BGP is converged | |
142 | BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) | |
143 | assert BGP_CONVERGENCE is True, "setup_module :Failed \n Error: {}".format( | |
144 | BGP_CONVERGENCE | |
145 | ) | |
146 | ||
147 | logger.info("Running setup_module() done") | |
148 | ||
149 | ||
150 | def teardown_module(mod): | |
151 | """ | |
152 | Teardown the pytest environment | |
153 | ||
154 | * `mod`: module name | |
155 | """ | |
156 | ||
157 | logger.info("Running teardown_module to delete topology") | |
158 | ||
159 | tgen = get_topogen() | |
160 | ||
161 | # Stop toplogy and Remove tmp files | |
162 | tgen.stop_topology() | |
163 | ||
164 | logger.info( | |
165 | "Testsuite end time: {}".format(time.asctime(time.localtime(time.time()))) | |
166 | ) | |
167 | logger.info("=" * 40) | |
168 | ||
169 | ||
170 | def populate_nh(): | |
171 | NEXT_HOP_IP = { | |
172 | "nh1": { | |
173 | "ipv4": topo["routers"]["r1"]["links"]["r2-link0"]["ipv4"].split("/")[0], | |
174 | "ipv6": topo["routers"]["r1"]["links"]["r2-link0"]["ipv6"].split("/")[0], | |
175 | }, | |
176 | "nh2": { | |
177 | "ipv4": topo["routers"]["r1"]["links"]["r2-link1"]["ipv4"].split("/")[0], | |
178 | "ipv6": topo["routers"]["r1"]["links"]["r2-link1"]["ipv6"].split("/")[0], | |
179 | }, | |
180 | "nh3": { | |
181 | "ipv4": topo["routers"]["r1"]["links"]["r2-link2"]["ipv4"].split("/")[0], | |
182 | "ipv6": topo["routers"]["r1"]["links"]["r2-link2"]["ipv6"].split("/")[0], | |
183 | }, | |
184 | "nh4": { | |
185 | "ipv4": topo["routers"]["r1"]["links"]["r2-link3"]["ipv4"].split("/")[0], | |
186 | "ipv6": topo["routers"]["r1"]["links"]["r2-link3"]["ipv6"].split("/")[0], | |
187 | }, | |
188 | "nh5": { | |
189 | "ipv4": topo["routers"]["r1"]["links"]["r2-link4"]["ipv4"].split("/")[0], | |
190 | "ipv6": topo["routers"]["r1"]["links"]["r2-link4"]["ipv6"].split("/")[0], | |
191 | }, | |
192 | "nh6": { | |
193 | "ipv4": topo["routers"]["r1"]["links"]["r2-link5"]["ipv4"].split("/")[0], | |
194 | "ipv6": topo["routers"]["r1"]["links"]["r2-link5"]["ipv6"].split("/")[0], | |
195 | }, | |
196 | "nh7": { | |
197 | "ipv4": topo["routers"]["r1"]["links"]["r2-link6"]["ipv4"].split("/")[0], | |
198 | "ipv6": topo["routers"]["r1"]["links"]["r2-link6"]["ipv6"].split("/")[0], | |
199 | }, | |
200 | "nh8": { | |
201 | "ipv4": topo["routers"]["r1"]["links"]["r2-link7"]["ipv4"].split("/")[0], | |
202 | "ipv6": topo["routers"]["r1"]["links"]["r2-link7"]["ipv6"].split("/")[0], | |
203 | }, | |
204 | } | |
205 | return NEXT_HOP_IP | |
206 | ||
207 | ||
208 | ##################################################### | |
209 | # | |
210 | # Tests starting | |
211 | # | |
212 | ##################################################### | |
213 | ||
214 | ||
215 | def test_staticroute_with_ecmp_p0_tc3_ebgp(request): | |
216 | """ | |
217 | Verify static route ECMP functionality with 8 next hop' | |
218 | ||
219 | """ | |
220 | tc_name = request.node.name | |
221 | write_test_header(tc_name) | |
222 | tgen = get_topogen() | |
223 | ||
224 | # Don't run this test if we have any failure. | |
225 | if tgen.routers_have_failure(): | |
226 | pytest.skip(tgen.errors) | |
227 | ||
228 | reset_config_on_routers(tgen) | |
229 | NEXT_HOP_IP = populate_nh() | |
230 | ||
231 | step("Configure 8 interfaces / links between R1 and R2,") | |
232 | step( | |
233 | "Configure IPv4 static route in R2 with 8 next hop" | |
234 | "N1(21.1.1.2), N2(22.1.1.2), N3(23.1.1.2), N4(24.1.1.2)," | |
235 | "N5(25.1.1.2), N6(26.1.1.2), N7(27.1.1.2),N8(28.1.1.2), Static" | |
236 | "route next-hop present on R1" | |
237 | ) | |
238 | ||
239 | step("Configure IBGP IPv4 peering between R2 and R3 router.") | |
240 | ||
241 | for addr_type in ADDR_TYPES: | |
242 | # Enable static routes | |
243 | for nhp in range(1, 9): | |
244 | input_dict_4 = { | |
245 | "r2": { | |
246 | "static_routes": [ | |
247 | { | |
248 | "network": PREFIX1[addr_type], | |
249 | "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type], | |
250 | } | |
251 | ] | |
252 | } | |
253 | } | |
254 | logger.info("Configure static routes") | |
255 | result = create_static_routes(tgen, input_dict_4) | |
256 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
257 | tc_name, result | |
258 | ) | |
259 | logger.info("Verifying %s routes on r2", addr_type) | |
260 | nh = [ | |
261 | NEXT_HOP_IP["nh1"][addr_type], | |
262 | NEXT_HOP_IP["nh2"][addr_type], | |
263 | NEXT_HOP_IP["nh3"][addr_type], | |
264 | NEXT_HOP_IP["nh4"][addr_type], | |
265 | NEXT_HOP_IP["nh5"][addr_type], | |
266 | NEXT_HOP_IP["nh6"][addr_type], | |
267 | NEXT_HOP_IP["nh7"][addr_type], | |
268 | NEXT_HOP_IP["nh8"][addr_type], | |
269 | ] | |
270 | ||
271 | dut = "r2" | |
272 | protocol = "static" | |
273 | result = verify_rib( | |
274 | tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol | |
275 | ) | |
d7265db9 MS |
276 | assert ( |
277 | result is True | |
278 | ), "Testcase {} : Failed \nError: Routes are" " missing in RIB".format(tc_name) | |
26bbe9af | 279 | step("Configure redistribute static in BGP on R2 router") |
280 | for addr_type in ADDR_TYPES: | |
281 | input_dict_2 = { | |
282 | "r2": { | |
283 | "bgp": { | |
284 | "address_family": { | |
285 | addr_type: { | |
286 | "unicast": {"redistribute": [{"redist_type": "static"}]} | |
287 | } | |
288 | } | |
289 | } | |
290 | } | |
291 | } | |
292 | result = create_router_bgp(tgen, topo, input_dict_2) | |
293 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
294 | tc_name, result | |
295 | ) | |
296 | ||
297 | step( | |
298 | "Remove the static route configured with nexthop N1 to N8, one" | |
299 | "by one from running config" | |
300 | ) | |
301 | for addr_type in ADDR_TYPES: | |
302 | # delete static routes | |
303 | for nhp in range(1, 9): | |
304 | input_dict_4 = { | |
305 | "r2": { | |
306 | "static_routes": [ | |
307 | { | |
308 | "network": PREFIX1[addr_type], | |
309 | "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type], | |
310 | "delete": True, | |
311 | } | |
312 | ] | |
313 | } | |
314 | } | |
315 | ||
316 | logger.info("Configure static routes") | |
317 | result = create_static_routes(tgen, input_dict_4) | |
318 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
319 | tc_name, result | |
320 | ) | |
321 | ||
322 | result = verify_rib( | |
323 | tgen, | |
324 | addr_type, | |
325 | dut, | |
326 | input_dict_4, | |
327 | next_hop=nh, | |
328 | protocol=protocol, | |
329 | expected=False, | |
330 | ) | |
d7265db9 MS |
331 | assert ( |
332 | result is not True | |
333 | ), "Testcase {} : Failed \nError: Routes are" " still present in RIB".format( | |
334 | tc_name | |
335 | ) | |
26bbe9af | 336 | |
337 | step("Configure the static route with nexthop N1 to N8, one by" "one") | |
338 | ||
339 | for addr_type in ADDR_TYPES: | |
340 | # add static routes | |
341 | for nhp in range(1, 9): | |
342 | input_dict_4 = { | |
343 | "r2": { | |
344 | "static_routes": [ | |
345 | { | |
346 | "network": PREFIX1[addr_type], | |
347 | "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type], | |
348 | } | |
349 | ] | |
350 | } | |
351 | } | |
352 | ||
353 | logger.info("Configure static routes") | |
354 | result = create_static_routes(tgen, input_dict_4) | |
355 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
356 | tc_name, result | |
357 | ) | |
358 | ||
359 | result = verify_rib( | |
360 | tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol | |
361 | ) | |
d7265db9 MS |
362 | assert ( |
363 | result is True | |
364 | ), "Testcase {} : Failed \nError: Routes are" " missing in RIB".format(tc_name) | |
26bbe9af | 365 | |
366 | step("Random shut of the nexthop interfaces") | |
367 | randnum = random.randint(0, 7) | |
368 | for addr_type in ADDR_TYPES: | |
369 | intf = topo["routers"]["r2"]["links"]["r1-link" + str(randnum)]["interface"] | |
370 | shutdown_bringup_interface(tgen, dut, intf, False) | |
371 | nhip = NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type] | |
372 | input_dict_5 = { | |
373 | "r2": { | |
374 | "static_routes": [ | |
375 | { | |
376 | "network": PREFIX1[addr_type], | |
377 | "next_hop": NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type], | |
378 | } | |
379 | ] | |
380 | } | |
381 | } | |
382 | result = verify_rib( | |
383 | tgen, | |
384 | addr_type, | |
385 | dut, | |
386 | input_dict_5, | |
387 | next_hop=nhip, | |
388 | protocol=protocol, | |
389 | expected=False, | |
390 | ) | |
d7265db9 MS |
391 | assert ( |
392 | result is not True | |
393 | ), "Testcase {} : Failed \n" "Error: Routes are still present in RIB".format( | |
394 | tc_name | |
395 | ) | |
26bbe9af | 396 | |
397 | step("Random no shut of the nexthop interfaces") | |
398 | for addr_type in ADDR_TYPES: | |
399 | intf = topo["routers"]["r2"]["links"]["r1-link" + str(randnum)]["interface"] | |
400 | shutdown_bringup_interface(tgen, dut, intf, True) | |
401 | nhip = NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type] | |
402 | result = verify_rib( | |
403 | tgen, addr_type, dut, input_dict_5, next_hop=nhip, protocol=protocol | |
404 | ) | |
d7265db9 MS |
405 | assert ( |
406 | result is True | |
407 | ), "Testcase {} : Failed \n" "Error: Routes are missing in RIB".format(tc_name) | |
26bbe9af | 408 | |
409 | step("Reload the FRR router") | |
410 | # stop/start -> restart FRR router and verify | |
411 | stop_router(tgen, "r2") | |
412 | start_router(tgen, "r2") | |
413 | ||
414 | result = verify_rib( | |
415 | tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol | |
416 | ) | |
d7265db9 MS |
417 | assert ( |
418 | result is True | |
419 | ), "Testcase {} : Failed \nError: Routes are" " missing in RIB".format(tc_name) | |
26bbe9af | 420 | |
421 | write_test_footer(tc_name) | |
422 | ||
423 | ||
424 | def test_staticroute_with_ecmp_with_diff_AD_p0_tc4_ebgp(request): | |
425 | """ | |
426 | Verify static route ECMP functionality with 8 next hop | |
427 | ||
428 | """ | |
429 | tc_name = request.node.name | |
430 | write_test_header(tc_name) | |
431 | tgen = get_topogen() | |
432 | ||
433 | # Don't run this test if we have any failure. | |
434 | if tgen.routers_have_failure(): | |
435 | pytest.skip(tgen.errors) | |
436 | ||
437 | reset_config_on_routers(tgen) | |
26bbe9af | 438 | |
439 | step("Configure 8 interfaces / links between R1 and R2,") | |
440 | step("Configure IBGP IPv4 peering between R2 and R3 router.") | |
26bbe9af | 441 | NEXT_HOP_IP = populate_nh() |
442 | nh_all = {} | |
443 | for addr_type in ADDR_TYPES: | |
444 | nh_all[addr_type] = [] | |
445 | for nhp in range(1, 9): | |
446 | nh_all[addr_type].append(NEXT_HOP_IP["nh" + str(nhp)][addr_type]) | |
447 | step( | |
448 | "Configure IPv4 static route in R2 with 8 next hop" | |
449 | "N1(21.1.1.2) AD 10, N2(22.1.1.2) AD 20, N3(23.1.1.2) AD 30," | |
450 | "N4(24.1.1.2) AD 40, N5(25.1.1.2) AD 50, N6(26.1.1.2) AD 60," | |
451 | "N7(27.1.1.2) AD 70, N8(28.1.1.2) AD 80, Static route next-hop" | |
452 | "present on R1" | |
453 | ) | |
454 | for addr_type in ADDR_TYPES: | |
455 | for nhp in range(1, 9): | |
456 | input_dict_4 = { | |
457 | "r2": { | |
458 | "static_routes": [ | |
459 | { | |
460 | "network": PREFIX1[addr_type], | |
461 | "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type], | |
462 | "admin_distance": 10 * nhp, | |
463 | } | |
464 | ] | |
465 | } | |
466 | } | |
467 | logger.info("Configure static routes") | |
468 | result = create_static_routes(tgen, input_dict_4) | |
469 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
470 | tc_name, result | |
471 | ) | |
472 | logger.info("Verifying %s routes on r2", addr_type) | |
473 | ||
474 | step( | |
475 | "On R2, static route installed in RIB using " | |
476 | "show ip route with 8 next hop, lowest AD nexthop is active" | |
477 | ) | |
478 | step("On R2, static route with lowest AD nexthop installed in FIB") | |
479 | input_dict_4 = { | |
480 | "r2": { | |
481 | "static_routes": [ | |
482 | { | |
483 | "network": PREFIX1[addr_type], | |
484 | "next_hop": NEXT_HOP_IP["nh1"][addr_type], | |
485 | "admin_distance": 10, | |
486 | } | |
487 | ] | |
488 | } | |
489 | } | |
490 | dut = "r2" | |
491 | protocol = "static" | |
492 | nh = NEXT_HOP_IP["nh1"][addr_type] | |
493 | result = verify_rib( | |
494 | tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True | |
495 | ) | |
d7265db9 MS |
496 | assert result is True, ( |
497 | "Testcase {} : Failed \nError: Route with " | |
498 | " lowest AD is missing in RIB".format(tc_name) | |
499 | ) | |
26bbe9af | 500 | |
501 | nh = [] | |
502 | for nhp in range(2, 9): | |
503 | nh.append(NEXT_HOP_IP["nh" + str(nhp)][addr_type]) | |
504 | result = verify_rib( | |
505 | tgen, | |
506 | addr_type, | |
507 | dut, | |
508 | input_dict_4, | |
509 | next_hop=nh, | |
510 | protocol=protocol, | |
511 | fib=True, | |
512 | expected=False, | |
513 | ) | |
d7265db9 MS |
514 | assert result is not True, ( |
515 | "Testcase {} : Failed \nError: Routes " | |
516 | " with high AD are active in RIB".format(tc_name) | |
517 | ) | |
26bbe9af | 518 | |
519 | step("Configure redistribute static in BGP on R2 router") | |
520 | for addr_type in ADDR_TYPES: | |
521 | input_dict_2 = { | |
522 | "r2": { | |
523 | "bgp": { | |
524 | "address_family": { | |
525 | addr_type: { | |
526 | "unicast": {"redistribute": [{"redist_type": "static"}]} | |
527 | } | |
528 | } | |
529 | } | |
530 | } | |
531 | } | |
532 | ||
533 | logger.info("Configuring redistribute static") | |
534 | result = create_router_bgp(tgen, topo, input_dict_2) | |
535 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
536 | tc_name, result | |
537 | ) | |
538 | ||
539 | step( | |
540 | "After configuring them, route is always active with lowest AD" | |
541 | "value and all the nexthop populated in RIB and FIB again " | |
542 | ) | |
543 | input_dict_4 = { | |
544 | "r2": { | |
545 | "static_routes": [ | |
546 | { | |
547 | "network": PREFIX1[addr_type], | |
548 | "next_hop": NEXT_HOP_IP["nh1"][addr_type], | |
549 | "admin_distance": 10, | |
550 | } | |
551 | ] | |
552 | } | |
553 | } | |
554 | dut = "r2" | |
555 | protocol = "static" | |
556 | nh = NEXT_HOP_IP["nh1"][addr_type] | |
557 | result = verify_rib( | |
558 | tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True | |
559 | ) | |
d7265db9 MS |
560 | assert result is True, ( |
561 | "Testcase {} : Failed \nError: Route with " | |
562 | " lowest AD is missing in RIB".format(tc_name) | |
563 | ) | |
26bbe9af | 564 | |
565 | step( | |
566 | "Remove the static route configured with nexthop N1 to N8, one" | |
567 | "by one from running config" | |
568 | ) | |
569 | ||
570 | for addr_type in ADDR_TYPES: | |
571 | # delete static routes | |
572 | for nhp in range(1, 9): | |
573 | input_dict_4 = { | |
574 | "r2": { | |
575 | "static_routes": [ | |
576 | { | |
577 | "network": PREFIX1[addr_type], | |
578 | "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type], | |
579 | "admin_distance": 10 * nhp, | |
580 | "delete": True, | |
581 | } | |
582 | ] | |
583 | } | |
584 | } | |
585 | ||
586 | logger.info("Configure static routes") | |
587 | result = create_static_routes(tgen, input_dict_4) | |
588 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
589 | tc_name, result | |
590 | ) | |
591 | ||
592 | step( | |
593 | "After removing the static route with N1 to N8 one by one, " | |
594 | "route become active with next preferred nexthop and nexthop which " | |
595 | "got removed is not shown in RIB and FIB" | |
596 | ) | |
597 | result = verify_rib( | |
598 | tgen, | |
599 | addr_type, | |
600 | dut, | |
601 | input_dict_4, | |
602 | next_hop=nh_all[addr_type], | |
603 | protocol=protocol, | |
604 | expected=False, | |
605 | ) | |
d7265db9 MS |
606 | assert ( |
607 | result is not True | |
608 | ), "Testcase {} : Failed \nError: Routes are" " still present in RIB".format( | |
609 | tc_name | |
610 | ) | |
26bbe9af | 611 | |
612 | step("Configure the static route with nexthop N1 to N8, one by" "one") | |
613 | for addr_type in ADDR_TYPES: | |
614 | # add static routes | |
615 | for nhp in range(1, 9): | |
616 | input_dict_4 = { | |
617 | "r2": { | |
618 | "static_routes": [ | |
619 | { | |
620 | "network": PREFIX1[addr_type], | |
621 | "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type], | |
622 | "admin_distance": 10 * nhp, | |
623 | } | |
624 | ] | |
625 | } | |
626 | } | |
627 | logger.info("Configure static routes") | |
628 | result = create_static_routes(tgen, input_dict_4) | |
629 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
630 | tc_name, result | |
631 | ) | |
632 | ||
633 | step("On R2, static route with lowest AD nexthop installed in FIB") | |
634 | input_dict_4 = { | |
635 | "r2": { | |
636 | "static_routes": [ | |
637 | { | |
638 | "network": PREFIX1[addr_type], | |
639 | "next_hop": NEXT_HOP_IP["nh1"][addr_type], | |
640 | "admin_distance": 10, | |
641 | } | |
642 | ] | |
643 | } | |
644 | } | |
645 | dut = "r2" | |
646 | protocol = "static" | |
647 | nh = NEXT_HOP_IP["nh1"][addr_type] | |
648 | result = verify_rib( | |
649 | tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True | |
650 | ) | |
d7265db9 MS |
651 | assert result is True, ( |
652 | "Testcase {} : Failed \nError: Route with " | |
653 | " lowest AD is missing in RIB".format(tc_name) | |
654 | ) | |
26bbe9af | 655 | |
656 | nh = [] | |
657 | for nhp in range(2, 9): | |
658 | nh.append(NEXT_HOP_IP["nh" + str(nhp)][addr_type]) | |
659 | result = verify_rib( | |
660 | tgen, | |
661 | addr_type, | |
662 | dut, | |
663 | input_dict_4, | |
664 | next_hop=nh, | |
665 | protocol=protocol, | |
666 | fib=True, | |
667 | expected=False, | |
668 | ) | |
d7265db9 MS |
669 | assert result is not True, ( |
670 | "Testcase {} : Failed \nError: Routes " | |
671 | " with high AD are active in RIB".format(tc_name) | |
672 | ) | |
26bbe9af | 673 | |
674 | step("Random shut of the nexthop interfaces") | |
675 | randnum = random.randint(0, 7) | |
676 | for addr_type in ADDR_TYPES: | |
677 | intf = topo["routers"]["r2"]["links"]["r1-link" + str(randnum)]["interface"] | |
678 | shutdown_bringup_interface(tgen, dut, intf, False) | |
679 | nhip = NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type] | |
680 | input_dict_5 = { | |
681 | "r2": { | |
682 | "static_routes": [ | |
683 | { | |
684 | "network": PREFIX1[addr_type], | |
685 | "next_hop": NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type], | |
686 | } | |
687 | ] | |
688 | } | |
689 | } | |
690 | result = verify_rib( | |
691 | tgen, | |
692 | addr_type, | |
693 | dut, | |
694 | input_dict_5, | |
695 | next_hop=nhip, | |
696 | protocol=protocol, | |
697 | expected=False, | |
698 | ) | |
d7265db9 MS |
699 | assert ( |
700 | result is not True | |
701 | ), "Testcase {} : Failed \n" "Error: Routes are still present in RIB".format( | |
702 | tc_name | |
703 | ) | |
26bbe9af | 704 | |
705 | step("Random no shut of the nexthop interfaces") | |
706 | for addr_type in ADDR_TYPES: | |
707 | intf = topo["routers"]["r2"]["links"]["r1-link" + str(randnum)]["interface"] | |
708 | shutdown_bringup_interface(tgen, dut, intf, True) | |
709 | nhip = NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type] | |
710 | result = verify_rib( | |
711 | tgen, addr_type, dut, input_dict_5, next_hop=nhip, protocol=protocol | |
712 | ) | |
d7265db9 MS |
713 | assert ( |
714 | result is True | |
715 | ), "Testcase {} : Failed \n" "Error: Routes are missing in RIB".format(tc_name) | |
26bbe9af | 716 | |
717 | step("Reload the FRR router") | |
718 | # stop/start -> restart FRR router and verify | |
719 | stop_router(tgen, "r2") | |
720 | start_router(tgen, "r2") | |
721 | ||
722 | step( | |
723 | "After reload of FRR router, static route installed " | |
724 | "in RIB and FIB properly ." | |
725 | ) | |
726 | for addr_type in ADDR_TYPES: | |
727 | input_dict_4 = { | |
728 | "r2": { | |
729 | "static_routes": [ | |
730 | { | |
731 | "network": PREFIX1[addr_type], | |
732 | "next_hop": NEXT_HOP_IP["nh1"][addr_type], | |
733 | "admin_distance": 10, | |
734 | } | |
735 | ] | |
736 | } | |
737 | } | |
738 | dut = "r2" | |
739 | protocol = "static" | |
740 | nh = NEXT_HOP_IP["nh1"][addr_type] | |
741 | result = verify_rib( | |
742 | tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True | |
743 | ) | |
d7265db9 MS |
744 | assert result is True, ( |
745 | "Testcase {} : Failed \nError: Route with " | |
746 | " lowest AD is missing in RIB".format(tc_name) | |
747 | ) | |
26bbe9af | 748 | |
749 | nh = [] | |
750 | for nhp in range(2, 9): | |
751 | nh.append(NEXT_HOP_IP["nh" + str(nhp)][addr_type]) | |
752 | result = verify_rib( | |
753 | tgen, | |
754 | addr_type, | |
755 | dut, | |
756 | input_dict_4, | |
757 | next_hop=nh, | |
758 | protocol=protocol, | |
759 | fib=True, | |
760 | expected=False, | |
761 | ) | |
d7265db9 MS |
762 | assert result is not True, ( |
763 | "Testcase {} : Failed \nError: Routes " | |
764 | " with high AD are active in RIB".format(tc_name) | |
765 | ) | |
26bbe9af | 766 | |
767 | write_test_footer(tc_name) | |
768 | ||
769 | ||
770 | def test_bgp_local_nexthop_p1_tc14_ebgp(request): | |
771 | """ | |
772 | Verify BGP did not install the static route when it receive route | |
773 | with local next hop | |
774 | ||
775 | """ | |
776 | tc_name = request.node.name | |
777 | write_test_header(tc_name) | |
778 | tgen = get_topogen() | |
779 | ||
780 | step("Configure BGP IPv4 session between R2 and R3") | |
781 | step("Configure IPv4 static route on R2") | |
782 | reset_config_on_routers(tgen) | |
783 | ||
784 | for addr_type in ADDR_TYPES: | |
785 | # Enable static routes | |
786 | input_dict_4 = { | |
787 | "r2": { | |
788 | "static_routes": [ | |
789 | { | |
790 | "network": NETWORK[addr_type], | |
791 | "next_hop": topo["routers"]["r3"]["links"]["r2-link0"][ | |
792 | addr_type | |
793 | ].split("/")[0], | |
794 | } | |
795 | ] | |
796 | } | |
797 | } | |
798 | ||
799 | logger.info("Configure static routes") | |
800 | result = create_static_routes(tgen, input_dict_4) | |
801 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
802 | tc_name, result | |
803 | ) | |
804 | ||
805 | step("Configure redistribute static in the BGP") | |
806 | ||
807 | input_dict_2 = { | |
808 | "r2": { | |
809 | "bgp": { | |
810 | "address_family": { | |
811 | addr_type: { | |
812 | "unicast": {"redistribute": [{"redist_type": "static"}]} | |
813 | } | |
814 | } | |
815 | } | |
816 | } | |
817 | } | |
818 | result = create_router_bgp(tgen, topo, input_dict_2) | |
819 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
820 | tc_name, result | |
821 | ) | |
822 | ||
823 | step("Verify R2 BGP table has IPv4 route") | |
824 | dut = "r2" | |
825 | result = verify_rib(tgen, addr_type, dut, input_dict_4) | |
d7265db9 MS |
826 | assert ( |
827 | result is True | |
828 | ), "Testcase {} : Failed \nError: Routes is" " missing in RIB of R2".format( | |
829 | tc_name | |
830 | ) | |
26bbe9af | 831 | |
832 | step(" Verify route did not install in the R3 BGP table, RIB/FIB") | |
833 | dut = "r3" | |
834 | result = verify_bgp_rib(tgen, addr_type, dut, input_dict_4, expected=False) | |
d7265db9 MS |
835 | assert result is not True, ( |
836 | "Testcase {} : Failed \nError: Routes is" | |
837 | " still present in BGP RIB of R2".format(tc_name) | |
838 | ) | |
26bbe9af | 839 | |
840 | result = verify_rib(tgen, addr_type, dut, input_dict_4, expected=False) | |
d7265db9 MS |
841 | assert result is not True, ( |
842 | "Testcase {} : Failed \nError: Routes is" | |
843 | " still present in RIB of R2".format(tc_name) | |
844 | ) | |
26bbe9af | 845 | |
846 | write_test_footer(tc_name) | |
847 | ||
848 | ||
849 | def test_frr_intf_name_as_gw_gap_tc4_ebgp_p0(request): | |
850 | """ | |
851 | Verify static route configure with interface name as gateway' | |
852 | 'address' | |
853 | """ | |
854 | tc_name = request.node.name | |
855 | write_test_header(tc_name) | |
856 | tgen = get_topogen() | |
857 | ||
858 | # Don't run this test if we have any failure. | |
859 | if tgen.routers_have_failure(): | |
860 | pytest.skip(tgen.errors) | |
861 | ||
862 | reset_config_on_routers(tgen) | |
863 | ||
864 | dut = "r1" | |
865 | intf = topo["routers"]["r1"]["links"]["r2-link0"]["interface"] | |
866 | nh = topo["routers"]["r1"]["links"]["r2-link0"] | |
867 | ip_list = { | |
868 | "ipv4": [(dut, intf, ["1.1.1.1/32"], nh["ipv4"].split("/")[0])], | |
869 | "ipv6": [(dut, intf, ["4001::32/128"], nh["ipv6"].split("/")[0])], | |
870 | } | |
871 | ||
872 | step( | |
873 | "Configure IPv4 and IPv6 static route in FRR with different next" | |
874 | "hop (ens224 as nexthop))" | |
875 | ) | |
876 | step("ip route 2.2.2.0/24 20.1.1.1 ens224 ----from FRR cli") | |
877 | step("ipv6 route 2000::1/120 5000::1 ens224 ----from FRR cli") | |
878 | ||
879 | for addr_type in ADDR_TYPES: | |
880 | # Enable static routes | |
881 | nh = topo["routers"]["r2"]["links"]["r1-link0"][addr_type].split("/")[0] | |
882 | input_dict_4 = { | |
883 | "r1": { | |
884 | "static_routes": [ | |
885 | {"network": ip_list[addr_type][0][2][0], "next_hop": nh} | |
886 | ] | |
887 | } | |
888 | } | |
889 | ||
890 | logger.info("Configure static routes") | |
891 | result = create_static_routes(tgen, input_dict_4) | |
892 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
893 | tc_name, result | |
894 | ) | |
895 | ||
896 | step( | |
897 | "IPv4 and IPv6 Static route added in FRR verify using " | |
898 | "show ip route , nexthop is resolved using show nht" | |
899 | ) | |
900 | protocol = "static" | |
901 | result = verify_rib( | |
902 | tgen, addr_type, dut, input_dict_4, protocol=protocol, next_hop=nh | |
903 | ) | |
d7265db9 MS |
904 | assert ( |
905 | result is True | |
906 | ), "Testcase {} : Failed \nError: Routes is" " missing in RIB".format(tc_name) | |
26bbe9af | 907 | |
908 | input_dict_nh = { | |
909 | "r1": { | |
910 | nh: { | |
911 | "Address": nh, | |
912 | "resolvedVia": "connected", | |
913 | "nexthops": {"nexthop1": {"Interfcae": intf}}, | |
914 | } | |
915 | } | |
916 | } | |
917 | result = verify_ip_nht(tgen, input_dict_nh) | |
d7265db9 MS |
918 | assert ( |
919 | result is True | |
920 | ), "Testcase {} : Failed \nError: Nexthop is" " missing in RIB".format(tc_name) | |
26bbe9af | 921 | |
922 | step( | |
923 | "Shut / no shut IPv4 and IPv6 static next hop interface from" | |
924 | "kernel and FRR CLI" | |
925 | ) | |
926 | ||
927 | shutdown_bringup_interface(tgen, dut, intf, False) | |
928 | ||
929 | step( | |
930 | "After shut of nexthop interface, IPv4 and IPv6 route got removed " | |
931 | "from RIB verify using show ip route show nht" | |
932 | ) | |
933 | result = verify_rib( | |
934 | tgen, | |
935 | addr_type, | |
936 | dut, | |
937 | input_dict_4, | |
938 | protocol=protocol, | |
939 | next_hop=nh, | |
940 | expected=False, | |
941 | ) | |
d7265db9 MS |
942 | assert ( |
943 | result is not True | |
944 | ), "Testcase {} : Failed \nError: Routes is" " missing in RIB".format(tc_name) | |
26bbe9af | 945 | |
946 | shutdown_bringup_interface(tgen, dut, intf, True) | |
947 | ||
948 | step( | |
949 | "After no shut route got added again in RIB /FIB using " | |
950 | "show ip route nexthop is resolved using show nht" | |
951 | ) | |
952 | result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol) | |
953 | assert result is True, "Testcase {} : Failed".format(tc_name) | |
954 | ||
955 | for addr_type in ADDR_TYPES: | |
956 | nh = topo["routers"]["r2"]["links"]["r1-link0"][addr_type].split("/")[0] | |
957 | input_dict_4 = { | |
958 | "r1": { | |
959 | "static_routes": [ | |
960 | { | |
961 | "network": ip_list[addr_type][0][2][0], | |
962 | "next_hop": nh, | |
963 | "delete": True, | |
964 | } | |
965 | ] | |
966 | } | |
967 | } | |
968 | ||
969 | logger.info("Configure static routes") | |
970 | result = create_static_routes(tgen, input_dict_4) | |
971 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
972 | tc_name, result | |
973 | ) | |
974 | ||
975 | step( | |
976 | "Removing FRR configured static route verify FRR route also " | |
977 | "removed from FRR" | |
978 | ) | |
979 | result = verify_rib( | |
980 | tgen, | |
981 | addr_type, | |
982 | dut, | |
983 | input_dict_4, | |
984 | protocol=protocol, | |
985 | next_hop=nh, | |
986 | expected=False, | |
987 | ) | |
d7265db9 MS |
988 | assert ( |
989 | result is not True | |
990 | ), "Testcase {} : Failed \nError: Routes" " still present in RIB".format( | |
991 | tc_name | |
992 | ) | |
26bbe9af | 993 | |
994 | write_test_footer(tc_name) | |
995 | ||
996 | ||
997 | def test_static_route_with_tag_p0_tc_13_ebgp(request): | |
998 | """ | |
999 | Verify static route with tag option | |
1000 | ||
1001 | """ | |
1002 | tc_name = request.node.name | |
1003 | write_test_header(tc_name) | |
1004 | tgen = get_topogen() | |
1005 | ||
1006 | # Don't run this test if we have any failure. | |
1007 | if tgen.routers_have_failure(): | |
1008 | pytest.skip(tgen.errors) | |
1009 | ||
1010 | step("Configure 8 links between R1 and R2") | |
1011 | step("Configure 1 links between R2 and R3") | |
1012 | NEXT_HOP_IP = populate_nh() | |
1013 | ||
1014 | step( | |
1015 | "Configure 2 IPv4 static route (S1 and S2) in R2 with same" | |
1016 | "next hop N1 28.1.1.2" | |
1017 | ) | |
1018 | step("Configure static route S1 with tag 1 and static route S2 with" "tag2") | |
1019 | step("S1= ip route 10.1.1.1/24 28.1.1.2 tag 1") | |
1020 | step("S2= ip route 20.1.1.1/24 28.1.1.2 tag 2") | |
1021 | step("Enable redistribute static in BGP with route-map") | |
1022 | reset_config_on_routers(tgen) | |
1023 | ||
1024 | for addr_type in ADDR_TYPES: | |
1025 | # Enable static routes | |
1026 | input_dict_4 = { | |
1027 | "r2": { | |
1028 | "static_routes": [ | |
1029 | { | |
1030 | "network": NETWORK[addr_type], | |
1031 | "next_hop": NEXT_HOP_IP["nh1"][addr_type], | |
1032 | "tag": 4001, | |
1033 | }, | |
1034 | { | |
1035 | "network": NETWORK2[addr_type], | |
1036 | "next_hop": NEXT_HOP_IP["nh1"][addr_type], | |
1037 | "tag": 4002, | |
1038 | }, | |
1039 | ] | |
1040 | } | |
1041 | } | |
1042 | ||
1043 | logger.info("Configure static routes") | |
1044 | result = create_static_routes(tgen, input_dict_4) | |
1045 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
1046 | tc_name, result | |
1047 | ) | |
1048 | step("verify routes are present in RIB") | |
1049 | dut = "r2" | |
1050 | protocol = "static" | |
1051 | nh = NEXT_HOP_IP["nh1"][addr_type] | |
1052 | result = verify_rib( | |
1053 | tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol | |
1054 | ) | |
d7265db9 MS |
1055 | assert ( |
1056 | result is True | |
1057 | ), "Testcase {} : Failed \nError: Routes are" " missing in RIB".format(tc_name) | |
26bbe9af | 1058 | |
1059 | step("Configure route-map on R2 with allow tag1 and deny tag2") | |
1060 | ||
1061 | # Create route map | |
1062 | input_dict_3 = { | |
1063 | "r2": { | |
1064 | "route_maps": { | |
1065 | "rmap_match_tag_1_{}".format(addr_type): [ | |
1066 | { | |
1067 | "action": "permit", | |
1068 | "seq_id": 10, | |
1069 | "match": {addr_type: {"tag": "4001"}}, | |
1070 | }, | |
1071 | { | |
1072 | "action": "deny", | |
1073 | "seq_id": 20, | |
1074 | "match": {addr_type: {"tag": "4002"}}, | |
1075 | }, | |
1076 | ] | |
1077 | } | |
1078 | } | |
1079 | } | |
1080 | result = create_route_maps(tgen, input_dict_3) | |
1081 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
1082 | tc_name, result | |
1083 | ) | |
1084 | ||
1085 | # Configure neighbor for route map | |
1086 | input_dict_4 = { | |
1087 | "r2": { | |
1088 | "bgp": { | |
1089 | "address_family": { | |
1090 | addr_type: { | |
1091 | "unicast": { | |
1092 | "neighbor": { | |
1093 | "r3": { | |
1094 | "dest_link": { | |
1095 | "r2-link0": { | |
1096 | "route_maps": [ | |
1097 | { | |
1098 | "name": "rmap_match_tag_1_ipv4", | |
1099 | "direction": "out", | |
1100 | } | |
1101 | ] | |
1102 | } | |
1103 | } | |
1104 | } | |
1105 | }, | |
1106 | "redistribute": [{"redist_type": "static"}], | |
1107 | } | |
1108 | } | |
1109 | } | |
1110 | } | |
1111 | } | |
1112 | } | |
1113 | result = create_router_bgp(tgen, topo, input_dict_4) | |
1114 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
1115 | tc_name, result | |
1116 | ) | |
1117 | ||
1118 | step( | |
1119 | "Verify static route S1 advetised in BGP table when tag1 permit" | |
1120 | "in route-map else it is denied" | |
1121 | ) | |
1122 | dut = "r3" | |
1123 | input_dict_0 = { | |
1124 | "r2": { | |
1125 | "static_routes": [ | |
1126 | { | |
1127 | "network": NETWORK2[addr_type], | |
1128 | "next_hop": NEXT_HOP_IP["nh1"][addr_type], | |
1129 | "tag": 4002, | |
1130 | } | |
1131 | ] | |
1132 | } | |
1133 | } | |
1134 | ||
1135 | result = verify_rib( | |
1136 | tgen, addr_type, dut, input_dict_0, protocol=protocol, expected=False | |
1137 | ) | |
d7265db9 MS |
1138 | assert result is not True, ( |
1139 | "Testcase {} : Failed \nError: Route with " | |
1140 | "tag 4002 is still present in RIB".format(tc_name) | |
1141 | ) | |
26bbe9af | 1142 | |
1143 | dut = "r2" | |
1144 | input_dict_1 = { | |
1145 | "r2": {"static_routes": [{"network": NETWORK[addr_type], "tag": 4001}]} | |
1146 | } | |
1147 | ||
1148 | result = verify_rib(tgen, addr_type, dut, input_dict_0, protocol=protocol) | |
d7265db9 MS |
1149 | assert result is True, ( |
1150 | "Testcase {} : Failed \nError: Route with " | |
1151 | "tag 4001 is missing in RIB".format(tc_name) | |
1152 | ) | |
26bbe9af | 1153 | |
1154 | step("Modify the route-map to allow tag2 and deny tag1") | |
1155 | # Create route map | |
1156 | input_dict_3 = { | |
1157 | "r2": { | |
1158 | "route_maps": { | |
1159 | "rmap_match_tag_1_{}".format(addr_type): [ | |
1160 | { | |
1161 | "action": "deny", | |
1162 | "seq_id": 10, | |
1163 | "match": {addr_type: {"tag": "4001"}}, | |
1164 | }, | |
1165 | { | |
1166 | "action": "permit", | |
1167 | "seq_id": 20, | |
1168 | "match": {addr_type: {"tag": "4002"}}, | |
1169 | }, | |
1170 | ] | |
1171 | } | |
1172 | } | |
1173 | } | |
1174 | result = create_route_maps(tgen, input_dict_3) | |
1175 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
1176 | tc_name, result | |
1177 | ) | |
1178 | ||
1179 | dut = "r3" | |
1180 | step( | |
1181 | "Verify static route S2 advertised in BGP table when tag2" | |
1182 | "permit in route-map else it is denied" | |
1183 | ) | |
1184 | protocol = "bgp" | |
1185 | input_dict_0 = { | |
1186 | "r2": {"static_routes": [{"network": NETWORK2[addr_type], "tag": 4002}]} | |
1187 | } | |
1188 | ||
1189 | result = verify_rib(tgen, addr_type, dut, input_dict_0, protocol=protocol) | |
d7265db9 MS |
1190 | assert result is True, ( |
1191 | "Testcase {} : Failed \nError: Route with " | |
1192 | "tag 4002 is missing in RIB".format(tc_name) | |
1193 | ) | |
26bbe9af | 1194 | |
1195 | input_dict_1 = { | |
1196 | "r2": {"static_routes": [{"network": NETWORK[addr_type], "tag": 4001}]} | |
1197 | } | |
1198 | result = verify_rib( | |
1199 | tgen, addr_type, dut, input_dict_1, protocol=protocol, expected=False | |
1200 | ) | |
d7265db9 MS |
1201 | assert result is not True, ( |
1202 | "Testcase {} : Failed \nError: Route with " | |
1203 | "tag 4001 is still present in RIB".format(tc_name) | |
1204 | ) | |
26bbe9af | 1205 | |
1206 | step("Configure one static route with 2 ECMP nexthop N1 and N2") | |
1207 | step("For N1 configure tag 1 and for N2 configure tag 2") | |
1208 | step("S1= ip route 10.1.1.1/24 28.1.1.2 tag 1") | |
1209 | step("S1= ip route 10.1.1.1/24 29.1.1.2 tag 2") | |
1210 | step("configure the route-map to allow tag1 and deny tag 2") | |
1211 | step("Modify the route-map to allow tag2 and deny tag1") | |
1212 | ||
1213 | for addr_type in ADDR_TYPES: | |
1214 | # Enable static routes | |
1215 | input_dict_4 = { | |
1216 | "r2": { | |
1217 | "static_routes": [ | |
1218 | { | |
1219 | "network": NETWORK2[addr_type], | |
1220 | "next_hop": NEXT_HOP_IP["nh1"][addr_type], | |
1221 | "tag": 4001, | |
1222 | }, | |
1223 | { | |
1224 | "network": NETWORK2[addr_type], | |
1225 | "next_hop": NEXT_HOP_IP["nh2"][addr_type], | |
1226 | "tag": 4002, | |
1227 | }, | |
1228 | ] | |
1229 | } | |
1230 | } | |
1231 | ||
1232 | logger.info("Configure static routes") | |
1233 | result = create_static_routes(tgen, input_dict_4) | |
1234 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
1235 | tc_name, result | |
1236 | ) | |
1237 | ||
1238 | dut = "r2" | |
1239 | protocol = "static" | |
1240 | result = verify_rib( | |
1241 | tgen, addr_type, dut, input_dict_4, protocol=protocol, fib=True | |
1242 | ) | |
d7265db9 MS |
1243 | assert ( |
1244 | result is True | |
1245 | ), "Testcase {} : Failed \nError: Routes are" " missing in RIB".format(tc_name) | |
26bbe9af | 1246 | |
1247 | step("shut/no shut of tag1 and tag2 nexthop") | |
1248 | ||
1249 | intf = topo["routers"]["r2"]["links"]["r1-link0"]["interface"] | |
1250 | shutdown_bringup_interface(tgen, dut, intf, False) | |
1251 | ||
1252 | shutdown_bringup_interface(tgen, dut, intf, True) | |
1253 | ||
1254 | step("configure one static route with 3 next-hop") | |
1255 | step("N1-tag1, N2-tag2, N3-tag3") | |
1256 | step("S1= ip route 10.1.1.1/24 28.1.1.2 tag 1") | |
1257 | step("S1= ip route 10.1.1.1/24 29.1.1.2 tag 2") | |
1258 | step("S1= ip route 10.1.1.1/24 28.1.1.2 tag 3") | |
1259 | ||
1260 | for addr_type in ADDR_TYPES: | |
1261 | # Enable static routes | |
1262 | input_dict_4 = { | |
1263 | "r2": { | |
1264 | "static_routes": [ | |
1265 | { | |
1266 | "network": NETWORK2[addr_type], | |
1267 | "next_hop": NEXT_HOP_IP["nh1"][addr_type], | |
1268 | "tag": 4001, | |
1269 | }, | |
1270 | { | |
1271 | "network": NETWORK2[addr_type], | |
1272 | "next_hop": NEXT_HOP_IP["nh2"][addr_type], | |
1273 | "tag": 4002, | |
1274 | }, | |
1275 | { | |
1276 | "network": NETWORK2[addr_type], | |
1277 | "next_hop": NEXT_HOP_IP["nh3"][addr_type], | |
1278 | "tag": 4003, | |
1279 | }, | |
1280 | ] | |
1281 | } | |
1282 | } | |
1283 | ||
1284 | logger.info("Configure static routes") | |
1285 | result = create_static_routes(tgen, input_dict_4) | |
1286 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
1287 | tc_name, result | |
1288 | ) | |
1289 | ||
1290 | dut = "r2" | |
1291 | protocol = "static" | |
1292 | result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol) | |
1293 | ||
1294 | step("configure the route-map to allow tag2 & tag3 and deny tag1") | |
1295 | # Create route map | |
1296 | input_dict_3 = { | |
1297 | "r2": { | |
1298 | "route_maps": { | |
1299 | "rmap_match_tag_1_{}".format(addr_type): [ | |
1300 | { | |
1301 | "action": "deny", | |
1302 | "seq_id": 10, | |
1303 | "match": {addr_type: {"tag": "4001"}}, | |
1304 | }, | |
1305 | { | |
1306 | "action": "permit", | |
1307 | "seq_id": 20, | |
1308 | "match": {addr_type: {"tag": "4002"}}, | |
1309 | }, | |
1310 | { | |
1311 | "action": "permit", | |
1312 | "seq_id": 30, | |
1313 | "match": {addr_type: {"tag": "4003"}}, | |
1314 | }, | |
1315 | ] | |
1316 | } | |
1317 | } | |
1318 | } | |
1319 | result = create_route_maps(tgen, input_dict_3) | |
1320 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
1321 | tc_name, result | |
1322 | ) | |
1323 | ||
1324 | step( | |
1325 | "Verify static route advertised in BGP table with tag3" | |
1326 | " nexthop if tag2 is down" | |
1327 | ) | |
1328 | dut = "r3" | |
1329 | protocol = "bgp" | |
1330 | result = verify_bgp_rib(tgen, addr_type, dut, input_dict_4) | |
1331 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
1332 | tc_name, result | |
1333 | ) | |
1334 | ||
1335 | step("shut / no shut of tag2 and tag3 next-hop") | |
1336 | ||
1337 | intf = topo["routers"]["r2"]["links"]["r1-link1"]["interface"] | |
1338 | shutdown_bringup_interface(tgen, dut, intf, False) | |
1339 | ||
1340 | intf = topo["routers"]["r2"]["links"]["r1-link2"]["interface"] | |
1341 | shutdown_bringup_interface(tgen, dut, intf, False) | |
1342 | ||
1343 | step("shut/no shut of tag2 and tag3 nexthop") | |
1344 | intf = topo["routers"]["r2"]["links"]["r1-link1"]["interface"] | |
1345 | shutdown_bringup_interface(tgen, dut, intf, True) | |
1346 | ||
1347 | intf = topo["routers"]["r2"]["links"]["r1-link2"]["interface"] | |
1348 | shutdown_bringup_interface(tgen, dut, intf, True) | |
1349 | ||
1350 | step("Verify after shut/noshut of nexthop BGP table updated correctly") | |
1351 | dut = "r3" | |
1352 | protocol = "bgp" | |
1353 | result = verify_bgp_rib(tgen, addr_type, dut, input_dict_4) | |
1354 | assert result is True, "Testcase {} : Failed \n Error: {}".format( | |
1355 | tc_name, result | |
1356 | ) | |
1357 | ||
1358 | write_test_footer(tc_name) | |
1359 | ||
1360 | ||
1361 | if __name__ == "__main__": | |
1362 | args = ["-s"] + sys.argv[1:] | |
1363 | sys.exit(pytest.main(args)) |