]> git.proxmox.com Git - mirror_frr.git/blame - tests/topotests/bgp_vrf_lite_best_path_test/test_bgp_vrf_lite_best_path_topo1.py
Merge pull request #12816 from gpnaveen/stc_rte_err_msg
[mirror_frr.git] / tests / topotests / bgp_vrf_lite_best_path_test / test_bgp_vrf_lite_best_path_topo1.py
CommitLineData
687c62fc 1#!/usr/bin/env python
acddc0ed 2# SPDX-License-Identifier: ISC
687c62fc
IS
3
4#
5# Copyright (c) 2020 by VMware, Inc. ("VMware")
6# Used Copyright (c) 2018 by Network Device Education Foundation,
7# Inc. ("NetDEF") in this file.
8#
687c62fc
IS
9
10"""
11Following tests are covered to test BGP VRF Lite:
12
131. Verify BGP best path selection algorithm works fine when
14routes are imported from ISR to default vrf and vice versa.
15"""
16
17import os
18import sys
19import time
20import pytest
21import platform
22
23# Save the Current Working Directory to find configuration files.
24CWD = os.path.dirname(os.path.realpath(__file__))
25sys.path.append(os.path.join(CWD, "../"))
26sys.path.append(os.path.join(CWD, "../lib/"))
27
28# Required to instantiate the topology builder class.
29
30# pylint: disable=C0413
31# Import topogen and topotest helpers
32from lib.topogen import Topogen, get_topogen
33from lib.topotest import version_cmp
34
35from lib.common_config import (
36 start_topology,
37 write_test_header,
38 check_address_types,
39 write_test_footer,
40 step,
41 create_route_maps,
42 create_prefix_lists,
43 check_router_status,
44 get_frr_ipv6_linklocal,
45 shutdown_bringup_interface,
46)
47
48from lib.topolog import logger
49from lib.bgp import (
50 verify_bgp_convergence,
51 create_router_bgp,
52 verify_bgp_community,
53 verify_bgp_rib,
54 clear_bgp,
55 verify_best_path_as_per_bgp_attribute
56)
57from lib.topojson import build_config_from_json
58
59
60pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
61
62# Global variables
63NETWORK1_1 = {"ipv4": "11.11.11.1/32", "ipv6": "11:11::1/128"}
64NETWORK1_2 = {"ipv4": "11.11.11.11/32", "ipv6": "11:11::11/128"}
65NETWORK1_3 = {"ipv4": "10.10.10.10/32", "ipv6": "10:10::10/128"}
66NETWORK1_4 = {"ipv4": "10.10.10.100/32", "ipv6": "10:10::100/128"}
67
68NETWORK2_1 = {"ipv4": "22.22.22.2/32", "ipv6": "22:22::2/128"}
69NETWORK2_2 = {"ipv4": "22.22.22.22/32", "ipv6": "22:22::22/128"}
70NETWORK2_3 = {"ipv4": "20.20.20.20/32", "ipv6": "20:20::20/128"}
71NETWORK2_4 = {"ipv4": "20.20.20.200/32", "ipv6": "20:20::200/128"}
72
73NETWORK3_1 = {"ipv4": "30.30.30.3/32", "ipv6": "30:30::3/128"}
74NETWORK3_2 = {"ipv4": "30.30.30.30/32", "ipv6": "30:30::30/128"}
75NETWORK3_3 = {"ipv4": "50.50.50.5/32", "ipv6": "50:50::5/128"}
76NETWORK3_4 = {"ipv4": "50.50.50.50/32", "ipv6": "50:50::50/128"}
77
78NETWORK4_1 = {"ipv4": "40.40.40.4/32", "ipv6": "40:40::4/128"}
79NETWORK4_2 = {"ipv4": "40.40.40.40/32", "ipv6": "40:40::40/128"}
80NETWORK4_3 = {"ipv4": "50.50.50.5/32", "ipv6": "50:50::5/128"}
81NETWORK4_4 = {"ipv4": "50.50.50.50/32", "ipv6": "50:50::50/128"}
82NEXT_HOP_IP = {"ipv4": "Null0", "ipv6": "Null0"}
83LOOPBACK_1 = {
84 "ipv4": "10.0.0.7/24",
85 "ipv6": "fd00:0:0:1::7/64",
86 "ipv4_mask": "255.255.255.0",
87 "ipv6_mask": None,
88}
89LOOPBACK_2 = {
90 "ipv4": "10.0.0.16/24",
91 "ipv6": "fd00:0:0:3::5/64",
92 "ipv4_mask": "255.255.255.0",
93 "ipv6_mask": None,
94}
95PREFERRED_NEXT_HOP = "global"
96
97
98def setup_module(mod):
99 """
100 Sets up the pytest environment
101
102 * `mod`: module name
103 """
104
105 testsuite_run_time = time.asctime(time.localtime(time.time()))
106 logger.info("Testsuite start time: {}".format(testsuite_run_time))
107 logger.info("=" * 40)
108
109 logger.info("Running setup_module to create topology")
110
111 # This function initiates the topology build with Topogen...
112 json_file = "{}/bgp_vrf_lite_best_path_topo1.json".format(CWD)
113 tgen = Topogen(json_file, mod.__name__)
114 global topo
115 topo = tgen.json_topo
116 # ... and here it calls Mininet initialization functions.
117
118 # Starting topology, create tmp files which are loaded to routers
d60a3f0e 119 # to start daemons and then start routers
687c62fc
IS
120 start_topology(tgen)
121
122 # Run these tests for kernel version 4.19 or above
123 if version_cmp(platform.release(), "4.19") < 0:
124 error_msg = (
125 "BGP vrf dynamic route leak tests will not run "
126 '(have kernel "{}", but it requires >= 4.19)'.format(platform.release())
127 )
128 pytest.skip(error_msg)
129
130 # Creating configuration from JSON
131 build_config_from_json(tgen, topo)
132
133 global BGP_CONVERGENCE
134 global ADDR_TYPES
135 ADDR_TYPES = check_address_types()
136
137 BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
138 assert BGP_CONVERGENCE is True, "setup_module : Failed \n Error: {}".format(
139 BGP_CONVERGENCE
140 )
141
142 logger.info("Running setup_module() done")
143
144
145def teardown_module():
146 """Teardown the pytest environment"""
147
148 logger.info("Running teardown_module to delete topology")
149
150 tgen = get_topogen()
151
152 # Stop toplogy and Remove tmp files
153 tgen.stop_topology()
154
155 logger.info(
156 "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
157 )
158 logger.info("=" * 40)
159
160
161#####################################################
162#
163# Testcases
164#
165#####################################################
166
167
168def disable_route_map_to_prefer_global_next_hop(tgen, topo):
169 """
170 This API is to remove prefer global route-map applied on neighbors
171
172 Parameter:
173 ----------
174 * `tgen` : Topogen object
175 * `topo` : Input JSON data
176
177 Returns:
178 --------
179 True/errormsg
180
181 """
182
183 logger.info("Remove prefer-global rmap applied on neighbors")
184 input_dict = {
185 "r1": {
186 "bgp": [
187 {
188 "local_as": "100",
189 "vrf": "ISR",
190 "address_family": {
191 "ipv6": {
192 "unicast": {
193 "neighbor": {
194 "r2": {
195 "dest_link": {
196 "r1-link1": {
197 "route_maps": [
198 {
199 "name": "rmap_global",
200 "direction": "in",
201 "delete": True,
202 }
203 ]
204 }
205 }
206 }
207 }
208 }
209 }
210 },
211 },
212 {
213 "local_as": "100",
214 "address_family": {
215 "ipv6": {
216 "unicast": {
217 "neighbor": {
218 "r3": {
219 "dest_link": {
220 "r1-link1": {
221 "route_maps": [
222 {
223 "name": "rmap_global",
224 "direction": "in",
225 "delete": True,
226 }
227 ]
228 }
229 }
230 }
231 }
232 }
233 }
234 },
235 },
236 {
237 "local_as": "100",
238 "address_family": {
239 "ipv6": {
240 "unicast": {
241 "neighbor": {
242 "r4": {
243 "dest_link": {
244 "r1-link1": {
245 "route_maps": [
246 {
247 "name": "rmap_global",
248 "direction": "in",
249 "delete": True,
250 }
251 ]
252 }
253 }
254 }
255 }
256 }
257 }
258 },
259 },
260 ]
261 },
262 "r2": {
263 "bgp": [
264 {
265 "local_as": "100",
266 "vrf": "ISR",
267 "address_family": {
268 "ipv6": {
269 "unicast": {
270 "neighbor": {
271 "r1": {
272 "dest_link": {
273 "r2-link1": {
274 "route_maps": [
275 {
276 "name": "rmap_global",
277 "direction": "in",
278 "delete": True,
279 }
280 ]
281 }
282 }
283 }
284 }
285 }
286 }
287 },
288 },
289 {
290 "local_as": "100",
291 "address_family": {
292 "ipv6": {
293 "unicast": {
294 "neighbor": {
295 "r3": {
296 "dest_link": {
297 "r2-link1": {
298 "route_maps": [
299 {
300 "name": "rmap_global",
301 "direction": "in",
302 "delete": True,
303 }
304 ]
305 }
306 }
307 }
308 }
309 }
310 }
311 },
312 },
313 {
314 "local_as": "100",
315 "address_family": {
316 "ipv6": {
317 "unicast": {
318 "neighbor": {
319 "r4": {
320 "dest_link": {
321 "r2-link1": {
322 "route_maps": [
323 {
324 "name": "rmap_global",
325 "direction": "in",
326 "delete": True,
327 }
328 ]
329 }
330 }
331 }
332 }
333 }
334 }
335 },
336 },
337 ]
338 },
339 "r3": {
340 "bgp": [
341 {
342 "local_as": "300",
343 "address_family": {
344 "ipv6": {
345 "unicast": {
346 "neighbor": {
347 "r1": {
348 "dest_link": {
349 "r3-link1": {
350 "route_maps": [
351 {
352 "name": "rmap_global",
353 "direction": "in",
354 "delete": True,
355 }
356 ]
357 }
358 }
359 }
360 }
361 }
362 }
363 },
364 },
365 {
366 "local_as": "300",
367 "address_family": {
368 "ipv6": {
369 "unicast": {
370 "neighbor": {
371 "r2": {
372 "dest_link": {
373 "r3-link1": {
374 "route_maps": [
375 {
376 "name": "rmap_global",
377 "direction": "in",
378 "delete": True,
379 }
380 ]
381 }
382 }
383 }
384 }
385 }
386 }
387 },
388 },
389 ]
390 },
391 "r4": {
392 "bgp": [
393 {
394 "local_as": "400",
395 "address_family": {
396 "ipv6": {
397 "unicast": {
398 "neighbor": {
399 "r1": {
400 "dest_link": {
401 "r4-link1": {
402 "route_maps": [
403 {
404 "name": "rmap_global",
405 "direction": "in",
406 "delete": True,
407 }
408 ]
409 }
410 }
411 }
412 }
413 }
414 }
415 },
416 },
417 {
418 "local_as": "400",
419 "address_family": {
420 "ipv6": {
421 "unicast": {
422 "neighbor": {
423 "r2": {
424 "dest_link": {
425 "r4-link1": {
426 "route_maps": [
427 {
428 "name": "rmap_global",
429 "direction": "in",
430 "delete": True,
431 }
432 ]
433 }
434 }
435 }
436 }
437 }
438 }
439 },
440 },
441 ]
442 },
443 }
444
445 result = create_router_bgp(tgen, topo, input_dict)
446 assert result is True, "Testcase :Failed \n Error: {}".format(result)
447
448 return True
449
450
451def test_bgp_best_path_with_dynamic_import_p0(request):
452 """
453 1.5.6. Verify BGP best path selection algorithm works fine when
454 routes are imported from ISR to default vrf and vice versa.
455 """
456
457 tgen = get_topogen()
458 tc_name = request.node.name
459 write_test_header(tc_name)
460 build_config_from_json(tgen, topo)
461
462 if tgen.routers_have_failure():
463 check_router_status(tgen)
464
465 for addr_type in ADDR_TYPES:
466
467 step(
468 "Redistribute configured static routes into BGP process" " on R1/R2 and R3"
469 )
470
471 input_dict_1 = {}
472 DUT = ["r1", "r2", "r3", "r4"]
473 VRFS = ["ISR", "ISR", "default", "default"]
474 AS_NUM = [100, 100, 300, 400]
475
476 for dut, vrf, as_num in zip(DUT, VRFS, AS_NUM):
477 temp = {dut: {"bgp": []}}
478 input_dict_1.update(temp)
479
480 temp[dut]["bgp"].append(
481 {
482 "local_as": as_num,
483 "vrf": vrf,
484 "address_family": {
485 addr_type: {
486 "unicast": {"redistribute": [{"redist_type": "static"}]}
487 }
488 },
489 }
490 )
491
492 result = create_router_bgp(tgen, topo, input_dict_1)
493 assert result is True, "Testcase {} :Failed \n Error: {}".format(
494 tc_name, result
495 )
496
497 for addr_type in ADDR_TYPES:
498
499 step("Import from default vrf into vrf ISR on R1 and R2 as below")
500
501 input_dict_vrf = {}
502 DUT = ["r1", "r2"]
503 VRFS = ["ISR", "ISR"]
504 AS_NUM = [100, 100]
505
506 for dut, vrf, as_num in zip(DUT, VRFS, AS_NUM):
507 temp = {dut: {"bgp": []}}
508 input_dict_vrf.update(temp)
509
510 temp[dut]["bgp"].append(
511 {
512 "local_as": as_num,
513 "vrf": vrf,
514 "address_family": {
515 addr_type: {"unicast": {"import": {"vrf": "default"}}}
516 },
517 }
518 )
519
520 result = create_router_bgp(tgen, topo, input_dict_vrf)
521 assert result is True, "Testcase {} : Failed \n Error: {}".format(
522 tc_name, result
523 )
524
525 input_dict_default = {}
526 DUT = ["r1", "r2"]
527 VRFS = ["default", "default"]
528 AS_NUM = [100, 100]
529
530 for dut, vrf, as_num in zip(DUT, VRFS, AS_NUM):
531 temp = {dut: {"bgp": []}}
532 input_dict_default.update(temp)
533
534 temp[dut]["bgp"].append(
535 {
536 "local_as": as_num,
537 "vrf": vrf,
538 "address_family": {
539 addr_type: {"unicast": {"import": {"vrf": "ISR"}}}
540 },
541 }
542 )
543
544 result = create_router_bgp(tgen, topo, input_dict_default)
545 assert result is True, "Testcase {} : Failed \n Error: {}".format(
546 tc_name, result
547 )
548
549 step(
550 "Verify ECMP/Next-hop/Imported routes Vs Locally originated "
551 "routes/eBGP routes vs iBGP routes --already covered in almost"
552 " all tests"
553 )
554
555 for addr_type in ADDR_TYPES:
556
557 step("Verify Pre-emption")
558
559 input_routes_r3 = {
560 "r3": {"static_routes": [{"network": [NETWORK3_3[addr_type]]}]}
561 }
562
563 intf_r3_r1 = topo["routers"]["r3"]["links"]["r1-link1"]["interface"]
564 intf_r4_r1 = topo["routers"]["r4"]["links"]["r1-link1"]["interface"]
565
566 if addr_type == "ipv6" and "link_local" in PREFERRED_NEXT_HOP:
567 nh_r3_r1 = get_frr_ipv6_linklocal(tgen, "r3", intf=intf_r3_r1)
568 nh_r4_r1 = get_frr_ipv6_linklocal(tgen, "r4", intf=intf_r4_r1)
569 else:
570 nh_r3_r1 = topo["routers"]["r3"]["links"]["r1-link1"][addr_type].split("/")[
571 0
572 ]
573 nh_r4_r1 = topo["routers"]["r4"]["links"]["r1-link1"][addr_type].split("/")[
574 0
575 ]
576
577 result = verify_bgp_rib(
578 tgen, addr_type, "r1", input_routes_r3, next_hop=[nh_r4_r1]
579 )
580 assert result is True, "Testcase {} : Failed \n Error {}".format(
581 tc_name, result
582 )
583
584 step("Shutdown interface connected to r1 from r4:")
585 shutdown_bringup_interface(tgen, "r4", intf_r4_r1, False)
586
587 for addr_type in ADDR_TYPES:
588
589 input_routes_r3 = {
590 "r3": {"static_routes": [{"network": [NETWORK3_3[addr_type]]}]}
591 }
592
593 intf_r3_r1 = topo["routers"]["r3"]["links"]["r1-link1"]["interface"]
594 intf_r4_r1 = topo["routers"]["r4"]["links"]["r1-link1"]["interface"]
595
596 if addr_type == "ipv6" and "link_local" in PREFERRED_NEXT_HOP:
597 nh_r3_r1 = get_frr_ipv6_linklocal(tgen, "r3", intf=intf_r3_r1)
598 nh_r4_r1 = get_frr_ipv6_linklocal(tgen, "r4", intf=intf_r4_r1)
599 else:
600 nh_r3_r1 = topo["routers"]["r3"]["links"]["r1-link1"][addr_type].split("/")[
601 0
602 ]
603 nh_r4_r1 = topo["routers"]["r4"]["links"]["r1-link1"][addr_type].split("/")[
604 0
605 ]
606
607 step("Verify next-hop is changed")
608 result = verify_bgp_rib(
609 tgen, addr_type, "r1", input_routes_r3, next_hop=[nh_r3_r1]
610 )
611 assert result is True, "Testcase {} : Failed \n Error {}".format(
612 tc_name, result
613 )
614
615 step("Bringup interface connected to r1 from r4:")
616 shutdown_bringup_interface(tgen, "r4", intf_r4_r1, True)
617
618 for addr_type in ADDR_TYPES:
619
620 input_routes_r3 = {
621 "r3": {"static_routes": [{"network": [NETWORK3_3[addr_type]]}]}
622 }
623
624 intf_r3_r1 = topo["routers"]["r3"]["links"]["r1-link1"]["interface"]
625 intf_r4_r1 = topo["routers"]["r4"]["links"]["r1-link1"]["interface"]
626
627 if addr_type == "ipv6" and "link_local" in PREFERRED_NEXT_HOP:
628 nh_r3_r1 = get_frr_ipv6_linklocal(tgen, "r3", intf=intf_r3_r1)
629 nh_r4_r1 = get_frr_ipv6_linklocal(tgen, "r4", intf=intf_r4_r1)
630 else:
631 nh_r3_r1 = topo["routers"]["r3"]["links"]["r1-link1"][addr_type].split("/")[
632 0
633 ]
634 nh_r4_r1 = topo["routers"]["r4"]["links"]["r1-link1"][addr_type].split("/")[
635 0
636 ]
637
638 step("Verify next-hop is not chnaged aftr shutdown:")
639 result = verify_bgp_rib(
640 tgen, addr_type, "r1", input_routes_r3, next_hop=[nh_r3_r1]
641 )
642 assert result is True, "Testcase {} : Failed \n Error {}".format(
643 tc_name, result
644 )
645
646 step("Active-Standby scenario(as-path prepend and Local pref)")
647
648 for addr_type in ADDR_TYPES:
649
650 step("Create prefix-list")
651
652 input_dict_pf = {
653 "r1": {
654 "prefix_lists": {
655 addr_type: {
656 "pf_ls_{}".format(addr_type): [
657 {
658 "seqid": 10,
659 "network": NETWORK3_4[addr_type],
660 "action": "permit",
661 }
662 ]
663 }
664 }
665 }
666 }
667 result = create_prefix_lists(tgen, input_dict_pf)
668 assert result is True, "Testcase {} : Failed \n Error: {}".format(
669 tc_name, result
670 )
671
672 for addr_type in ADDR_TYPES:
673
674 step("Create route-map to match prefix-list and set localpref 500")
675
676 input_dict_rm = {
677 "r1": {
678 "route_maps": {
679 "rmap_PATH1_{}".format(addr_type): [
680 {
681 "action": "permit",
682 "seq_id": 10,
683 "match": {
684 addr_type: {
685 "prefix_lists": "pf_ls_{}".format(addr_type)
686 }
687 },
688 "set": {"locPrf": 500},
689 }
690 ]
691 }
692 }
693 }
694
695 result = create_route_maps(tgen, input_dict_rm)
696 assert result is True, "Testcase {} : Failed \n Error: {}".format(
697 tc_name, result
698 )
699
700 step("Create route-map to match prefix-list and set localpref 600")
701
702 input_dict_rm = {
703 "r1": {
704 "route_maps": {
705 "rmap_PATH2_{}".format(addr_type): [
706 {
707 "action": "permit",
708 "seq_id": 20,
709 "match": {
710 addr_type: {
711 "prefix_lists": "pf_ls_{}".format(addr_type)
712 }
713 },
714 "set": {"locPrf": 600},
715 }
716 ]
717 }
718 }
719 }
720
721 result = create_route_maps(tgen, input_dict_rm)
722 assert result is True, "Testcase {} : Failed \n Error: {}".format(
723 tc_name, result
724 )
725
726 input_dict_rma = {
727 "r1": {
728 "bgp": [
729 {
730 "local_as": "100",
731 "address_family": {
732 addr_type: {
733 "unicast": {
734 "neighbor": {
735 "r3": {
736 "dest_link": {
737 "r1-link1": {
738 "route_maps": [
739 {
740 "name": "rmap_PATH1_{}".format(
741 addr_type
742 ),
743 "direction": "in",
744 }
745 ]
746 }
747 }
748 },
749 "r4": {
750 "dest_link": {
751 "r1-link1": {
752 "route_maps": [
753 {
754 "name": "rmap_PATH2_{}".format(
755 addr_type
756 ),
757 "direction": "in",
758 }
759 ]
760 }
761 }
762 },
763 }
764 }
765 }
766 },
767 }
768 ]
769 }
770 }
771
772 result = create_router_bgp(tgen, topo, input_dict_rma)
773 assert result is True, "Testcase {} : Failed \n Error: {}".format(
774 tc_name, result
775 )
776
777 dut = "r1"
778 attribute = "locPrf"
779
780 for addr_type in ADDR_TYPES:
781
782 step("Verify bestpath is installed as per highest localpref")
783
784 input_routes_r3 = {
785 "r3": {
786 "static_routes": [
787 {"network": [NETWORK3_3[addr_type], NETWORK3_4[addr_type]]}
788 ]
789 }
790 }
791
792 result = verify_best_path_as_per_bgp_attribute(
793 tgen, addr_type, dut, input_routes_r3, attribute
794 )
795 assert result is True, "Testcase {} : Failed \n Error: {}".format(
796 tc_name, result
797 )
798
799 for addr_type in ADDR_TYPES:
800
801 step("Create route-map to match prefix-list and set localpref 700")
802
803 input_dict_rm = {
804 "r1": {
805 "route_maps": {
806 "rmap_PATH1_{}".format(addr_type): [
807 {
808 "action": "permit",
809 "seq_id": 10,
810 "match": {
811 addr_type: {
812 "prefix_lists": "pf_ls_{}".format(addr_type)
813 }
814 },
815 "set": {"locPrf": 700},
816 }
817 ]
818 }
819 }
820 }
821
822 result = create_route_maps(tgen, input_dict_rm)
823 assert result is True, "Testcase {} : Failed \n Error: {}".format(
824 tc_name, result
825 )
826
827 for addr_type in ADDR_TYPES:
828
829 step("Verify bestpath is changed as per highest localpref")
830
831 input_routes_r3 = {
832 "r3": {
833 "static_routes": [
834 {"network": [NETWORK3_3[addr_type], NETWORK3_4[addr_type]]}
835 ]
836 }
837 }
838
839 result = verify_best_path_as_per_bgp_attribute(
840 tgen, addr_type, dut, input_routes_r3, attribute
841 )
842 assert result is True, "Testcase {} : Failed \n Error: {}".format(
843 tc_name, result
844 )
845
846 for addr_type in ADDR_TYPES:
847
848 step("Create route-map to match prefix-list and set as-path prepend")
849
850 input_dict_rm = {
851 "r1": {
852 "route_maps": {
853 "rmap_PATH2_{}".format(addr_type): [
854 {
855 "action": "permit",
856 "seq_id": 20,
857 "match": {
858 addr_type: {
859 "prefix_lists": "pf_ls_{}".format(addr_type)
860 }
861 },
862 "set": {
863 "localpref": 700,
864 "path": {"as_num": "111", "as_action": "prepend"},
865 },
866 }
867 ]
868 }
869 }
870 }
871
872 result = create_route_maps(tgen, input_dict_rm)
873 assert result is True, "Testcase {} : Failed \n Error: {}".format(
874 tc_name, result
875 )
876
877 attribute = "path"
878
879 for addr_type in ADDR_TYPES:
880
881 step("Verify bestpath is changed as per shortest as-path")
882
883 input_routes_r3 = {
884 "r3": {
885 "static_routes": [
886 {"network": [NETWORK3_3[addr_type], NETWORK3_4[addr_type]]}
887 ]
888 }
889 }
890
891 result = verify_best_path_as_per_bgp_attribute(
892 tgen, addr_type, dut, input_routes_r3, attribute
893 )
894 assert result is True, "Testcase {} : Failed \n Error: {}".format(
895 tc_name, result
896 )
897
898 write_test_footer(tc_name)
899
900
901if __name__ == "__main__":
902 args = ["-s"] + sys.argv[1:]
903 sys.exit(pytest.main(args))