2 # SPDX-License-Identifier: ISC
5 # Copyright (c) 2022 by VMware, Inc. ("VMware")
6 # Used Copyright (c) 2018 by Network Device Education Foundation,
7 # Inc. ("NetDEF") in this file.
17 """Following tests are covered to test bgp admin distance functionality.
19 Verify bgp admin distance functionality when static route is
20 configured same as ebgp learnt route
23 Verify ebgp admin distance functionality with ECMP.
26 Verify ibgp admin distance functionality when static route is
27 configured same as bgp learnt route.
29 Verify ibgp admin distance functionality with ECMP.
31 TC_7: Chaos - Verify bgp admin distance functionality with chaos.
34 #################################
36 #################################
47 | iBGP +-------+ eBGP +-------+
48 +---------- | R3 |----------| R4 |
60 # Save the Current Working Directory to find configuration files.
61 CWD
= os
.path
.dirname(os
.path
.realpath(__file__
))
62 sys
.path
.append(os
.path
.join(CWD
, "../"))
63 sys
.path
.append(os
.path
.join(CWD
, "../lib/"))
65 # pylint: disable=C0413
66 # Import topogen and topotest helpers
67 from lib
.topogen
import Topogen
, get_topogen
69 # Required to instantiate the topology builder class.
70 from lib
.common_config
import (
80 reset_config_on_routers
,
86 get_frr_ipv6_linklocal
,
89 from lib
.topolog
import logger
91 verify_bgp_convergence
,
93 verify_best_path_as_per_admin_distance
,
97 # pylint: disable=C0413
98 # Import topogen and topotest helpers
99 from lib
.topogen
import Topogen
, get_topogen
100 from lib
.topojson
import build_config_from_json
101 from lib
.topolog
import logger
105 bgp_convergence
= False
106 pytestmark
= [pytest
.mark
.bgpd
, pytest
.mark
.staticd
]
127 ADDR_TYPES
= check_address_types()
130 def setup_module(mod
):
132 Sets up the pytest environment
139 testsuite_run_time
= time
.asctime(time
.localtime(time
.time()))
140 logger
.info("Testsuite start time: {}".format(testsuite_run_time
))
141 logger
.info("=" * 40)
143 logger
.info("Running setup_module to create topology")
145 # This function initiates the topology build with Topogen...
146 json_file
= "{}/bgp_admin_dist.json".format(CWD
)
147 tgen
= Topogen(json_file
, mod
.__name
__)
149 topo
= tgen
.json_topo
151 # Starting topology, create tmp files which are loaded to routers
152 # to start deamons and then start routers
155 # Creating configuration from JSON
156 build_config_from_json(tgen
, topo
)
158 # Checking BGP convergence
159 global bgp_convergence
162 # Don't run this test if we have any failure.
163 if tgen
.routers_have_failure():
164 pytest
.skip(tgen
.errors
)
166 # Api call verify whether BGP is converged
167 bgp_convergence
= verify_bgp_convergence(tgen
, topo
)
168 assert bgp_convergence
is True, "setup_module :Failed \n Error:" " {}".format(
171 logger
.info("Running setup_module() done")
174 def teardown_module(mod
):
177 Teardown the pytest environment.
180 logger
.info("Running teardown_module to delete topology")
183 # Stop toplogy and Remove tmp files
187 "Testsuite end time: {}".format(time
.asctime(time
.localtime(time
.time())))
189 logger
.info("=" * 40)
192 #####################################################
194 #####################################################
195 def test_bgp_admin_distance_ebgp_ecmp_p0():
198 Verify ebgp admin distance functionality with ECMP.
201 global bgp_convergence
203 if bgp_convergence
is not True:
204 pytest
.skip("skipping test case because of BGP Convergence failure at setup")
207 tc_name
= inspect
.stack()[0][3]
208 write_test_header(tc_name
)
209 if tgen
.routers_have_failure():
210 check_router_status(tgen
)
212 step("Configure base config as per the topology")
213 reset_config_on_routers(tgen
)
215 step("Configure static route in R4 and R5, redistribute in bgp")
217 for addr_type
in ADDR_TYPES
:
221 "static_routes": [{"network": NETWORK
[addr_type
], "next_hop": "Null0"}]
225 result
= create_static_routes(tgen
, input_dict
)
226 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
230 for addr_type
in ADDR_TYPES
:
234 "static_routes": [{"network": NETWORK
[addr_type
], "next_hop": "Null0"}]
238 result
= create_static_routes(tgen
, input_dict
)
239 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
243 step("Verify that route is learnt in DUT via ebgp")
245 # Verifying RIB routes
247 input_dict
= topo
["routers"]
249 nhop
= {"ipv4": [], "ipv6": []}
250 nhop
["ipv4"].append(topo
["routers"]["r4"]["links"]["r3"]["ipv4"].split("/")[0])
251 nhop
["ipv4"].append(topo
["routers"]["r5"]["links"]["r3"]["ipv4"].split("/")[0])
252 nhop
["ipv6"].append(get_frr_ipv6_linklocal(tgen
, "r4", "r3-r4-eth1"))
253 nhop
["ipv6"].append(get_frr_ipv6_linklocal(tgen
, "r5", "r1-r3-eth1"))
255 for addr_type
in ADDR_TYPES
:
259 {"network": NETWORK
[addr_type
][0], "next_hop": "Null0"}
263 result4
= verify_rib(tgen
, addr_type
, dut
, input_dict
, protocol
=protocol
)
264 assert result4
is True, "Testcase {} : Failed \n Error: {}".format(
268 step("Configure the static route in R3 (Dut).")
270 for addr_type
in ADDR_TYPES
:
275 {"network": NETWORK
[addr_type
][0], "next_hop": "Null0"}
280 result
= create_static_routes(tgen
, input_dict
)
281 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
285 step("Verify that static route is selected as best route in zebra.")
287 # Verifying RIB routes
291 for addr_type
in ADDR_TYPES
:
295 {"network": NETWORK
[addr_type
][0], "next_hop": "Null0"}
300 result4
= verify_rib(tgen
, addr_type
, dut
, input_dict
, protocol
=protocol
)
301 assert result4
is True, "Testcase {} : Failed \n Error: {}".format(
305 step(" Configure the admin distance of 254 to static route in R3.")
307 for addr_type
in ADDR_TYPES
:
313 "network": NETWORK
[addr_type
][0],
315 "admin_distance": 254,
321 result
= create_static_routes(tgen
, input_dict
)
322 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
326 step("Verify that bgp routes are selected as best routes in zebra.")
330 for addr_type
in ADDR_TYPES
:
334 {"network": NETWORK
[addr_type
][0], "next_hop": "Null0"}
338 result4
= verify_rib(tgen
, addr_type
, dut
, input_dict
, protocol
=protocol
)
339 assert result4
is True, "Testcase {} : Failed \n Error: {}".format(
350 "distance": {"ebgp": 254, "ibgp": 254, "local": 254}
355 "distance": {"ebgp": 254, "ibgp": 254, "local": 254}
363 result
= create_router_bgp(tgen
, topo
, input_dict_1
)
364 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
366 step("Verify that bgp routes are selected as best routes in zebra.")
367 # Verifying RIB routes
371 for addr_type
in ADDR_TYPES
:
375 {"network": NETWORK
[addr_type
][0], "next_hop": "Null0"}
379 result4
= verify_rib(tgen
, addr_type
, dut
, input_dict
, protocol
=protocol
)
380 assert result4
is True, "Testcase {} : Failed \n Error: {}".format(
384 step("Configure bgp admin distance 10 with CLI in dut.")
391 "unicast": {"distance": {"ebgp": 10, "ibgp": 254, "local": 254}}
394 "unicast": {"distance": {"ebgp": 10, "ibgp": 254, "local": 254}}
401 result
= create_router_bgp(tgen
, topo
, input_dict_1
)
402 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
404 step("Verify ebgp routes have admin distance of 10 in dut.")
407 input_dict
= topo
["routers"]
410 for addr_type
in ADDR_TYPES
:
414 {"network": NETWORK
[addr_type
][0], "next_hop": "Null0"}
418 result4
= verify_rib(
419 tgen
, addr_type
, dut
, input_dict
, protocol
=protocol
, admin_distance
=10
421 assert result4
is True, "Testcase {} : Failed \n Error: {}".format(
426 "Configure route map with weight as 200 and apply to one of the "
427 "neighbor (R4 neighbor)."
438 "network": NETWORK
["ipv4"][0],
448 "network": NETWORK
["ipv6"][0],
457 result
= create_prefix_lists(tgen
, input_dict_2
)
458 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
467 "match": {"ipv4": {"prefix_lists": "pf_ls_1"}},
468 "set": {"weight": 200},
472 "match": {"ipv6": {"prefix_lists": "pf_ls_1_ipv6"}},
473 "set": {"weight": 200},
479 result
= create_route_maps(tgen
, input_dict_3
)
480 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
482 # Configure neighbor for route map
495 "name": "RMAP_WEIGHT",
513 "name": "RMAP_WEIGHT",
527 result
= create_router_bgp(tgen
, topo
, input_dict_4
)
528 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
530 step("Verify that bgp route is selected as best on by zebra in r3.")
535 for addr_type
in ADDR_TYPES
:
539 {"network": NETWORK
[addr_type
][0], "next_hop": "Null0"}
543 result4
= verify_rib(
544 tgen
, addr_type
, dut
, input_dict
, protocol
=protocol
, admin_distance
=10
546 assert result4
is True, "Testcase {} : Failed \n Error: {}".format(
550 step("Static route should not be selected as best route.")
554 for addr_type
in ADDR_TYPES
:
558 {"network": NETWORK
[addr_type
][0], "next_hop": "Null0"}
562 result4
= verify_fib_routes(
563 tgen
, addr_type
, dut
, input_dict
, protocol
=protocol
, expected
=False
567 ), "Testcase {} : Failed. Wrong route is selected as best route.\n Error: {}".format(
571 step("Reconfigure the static route without admin distance")
573 for addr_type
in ADDR_TYPES
:
579 "network": NETWORK
[addr_type
][0],
581 "admin_distance": 254,
588 result
= create_static_routes(tgen
, input_dict
)
589 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
593 for addr_type
in ADDR_TYPES
:
597 {"network": NETWORK
[addr_type
][0], "next_hop": "Null0"}
602 result
= create_static_routes(tgen
, input_dict
)
603 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
607 step("Verify that static route is installed as best route.")
611 for addr_type
in ADDR_TYPES
:
615 {"network": NETWORK
[addr_type
][0], "next_hop": "Null0"}
619 result4
= verify_rib(
620 tgen
, addr_type
, dut
, input_dict
, protocol
=protocol
, fib
=True
622 assert result4
is True, "Testcase {} : Failed \n Error: {}".format(
626 step("Unconfigure the static route in R3.")
628 for addr_type
in ADDR_TYPES
:
633 "network": NETWORK
[addr_type
][0],
641 result
= create_static_routes(tgen
, input_dict
)
642 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
646 step("Verify that bgp route is selected as best on by zebra in r3.")
651 for addr_type
in ADDR_TYPES
:
655 {"network": NETWORK
[addr_type
][0], "next_hop": "Null0"}
659 result4
= verify_rib(tgen
, addr_type
, dut
, input_dict
, protocol
=protocol
)
660 assert result4
is True, "Testcase {} : Failed \n Error: {}".format(
664 step("Un configure the route map on R3.")
666 # Configure neighbor for route map
679 "name": "RMAP_WEIGHT",
698 "name": "RMAP_WEIGHT",
713 result
= create_router_bgp(tgen
, topo
, input_dict_4
)
714 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
716 step("verify bgp routes installed in zebra.")
718 # Verifying RIB routes
720 input_dict
= topo
["routers"]
722 for addr_type
in ADDR_TYPES
:
726 {"network": NETWORK
[addr_type
][0], "next_hop": "Null0"}
730 result4
= verify_rib(tgen
, addr_type
, dut
, input_dict
, protocol
=protocol
)
731 assert result4
is True, "Testcase {} : Failed \n Error: {}".format(
735 write_test_footer(tc_name
)
738 def test_bgp_admin_distance_ibgp_p0():
741 Verify bgp admin distance functionality when static route is
742 configured same as ibgp learnt route
745 global bgp_convergence
747 if bgp_convergence
is not True:
748 pytest
.skip("skipping test case because of BGP Convergence failure at setup")
751 tc_name
= inspect
.stack()[0][3]
752 write_test_header(tc_name
)
753 if tgen
.routers_have_failure():
754 check_router_status(tgen
)
756 step("Configure base config as per the topology")
757 reset_config_on_routers(tgen
)
759 step("Configure bgp admin distance 200 with CLI in dut.")
768 "distance": {"ebgp": 200, "ibgp": 200, "local": 200}
773 "distance": {"ebgp": 200, "ibgp": 200, "local": 200}
781 result
= create_router_bgp(tgen
, topo
, input_dict_1
)
782 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
784 step("Verify bgp routes have admin distance of 200 in dut.")
785 # Verifying best path
787 attribute
= "admin_distance"
794 "network": "192.168.22.1/32",
795 "admin_distance": 200,
798 "network": "192.168.22.2/32",
799 "admin_distance": 200,
808 "network": "fc07:1::1/128",
809 "admin_distance": 200,
812 "network": "fc07:1::2/128",
813 "admin_distance": 200,
820 for addr_type
in ADDR_TYPES
:
821 result
= verify_best_path_as_per_admin_distance(
822 tgen
, addr_type
, dut
, input_dict
[addr_type
], attribute
824 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
828 step("Modify the admin distance value to 150.")
837 "distance": {"ebgp": 150, "ibgp": 150, "local": 150}
842 "distance": {"ebgp": 150, "ibgp": 150, "local": 150}
850 result
= create_router_bgp(tgen
, topo
, input_dict_1
)
851 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
853 step("Verify bgp routes have admin distance of 150 in dut.")
854 # Verifying best path
856 attribute
= "admin_distance"
863 "network": "192.168.22.1/32",
864 "admin_distance": 150,
867 "network": "192.168.22.2/32",
868 "admin_distance": 150,
877 "network": "fc07:1::1/128",
878 "admin_distance": 150,
881 "network": "fc07:1::2/128",
882 "admin_distance": 150,
889 for addr_type
in ADDR_TYPES
:
890 result
= verify_best_path_as_per_admin_distance(
891 tgen
, addr_type
, dut
, input_dict
[addr_type
], attribute
893 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
897 step("Un configure the admin distance value on DUT")
929 result
= create_router_bgp(tgen
, topo
, input_dict_1
)
930 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
932 step("Verify bgp routes have default admin distance in dut.")
933 # Verifying best path
935 attribute
= "admin_distance"
942 "network": "192.168.22.1/32",
943 "admin_distance": 20,
946 "network": "192.168.22.2/32",
947 "admin_distance": 20,
956 "network": "fc07:1::1/128",
957 "admin_distance": 20,
960 "network": "fc07:1::2/128",
961 "admin_distance": 20,
968 for addr_type
in ADDR_TYPES
:
969 result
= verify_best_path_as_per_admin_distance(
970 tgen
, addr_type
, dut
, input_dict
[addr_type
], attribute
972 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
977 "Learn the same route via ebgp and ibgp peer. Configure admin "
978 "distance of 200 in DUT for both ebgp and ibgp peer. "
981 step("Verify that ebgp route is preferred over ibgp.")
983 # Verifying RIB routes
985 input_dict
= topo
["routers"]
987 for addr_type
in ADDR_TYPES
:
988 result4
= verify_rib(tgen
, addr_type
, dut
, input_dict
, protocol
=protocol
)
989 assert result4
is True, "Testcase {} : Failed \n Error: {}".format(
993 step("Configure static route Without any admin distance")
995 for addr_type
in ADDR_TYPES
:
999 "static_routes": [{"network": NETWORK
[addr_type
], "next_hop": "Null0"}]
1003 result
= create_static_routes(tgen
, input_dict
)
1004 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
1008 step("Verify that zebra selects static route.")
1011 for addr_type
in ADDR_TYPES
:
1015 "static_routes": [{"network": NETWORK
[addr_type
], "next_hop": "Null0"}]
1019 result4
= verify_rib(tgen
, addr_type
, dut
, input_dict
, protocol
=protocol
)
1020 assert result4
is True, "Testcase {} : Failed \n Error: {}".format(
1024 step("Configure static route with admin distance of 253")
1025 for addr_type
in ADDR_TYPES
:
1031 "network": NETWORK
[addr_type
],
1032 "next_hop": "Null0",
1033 "admin_distance": 253,
1039 result
= create_static_routes(tgen
, input_dict
)
1040 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
1044 step("Verify that zebra selects bgp route.")
1047 for addr_type
in ADDR_TYPES
:
1048 result4
= verify_rib(tgen
, addr_type
, dut
, input_dict
, protocol
=protocol
)
1049 assert result4
is True, "Testcase {} : Failed \n Error: {}".format(
1053 step("Configure admin distance of 254 in bgp for route.")
1062 "distance": {"ebgp": 254, "ibgp": 254, "local": 254}
1067 "distance": {"ebgp": 254, "ibgp": 254, "local": 254}
1075 result
= create_router_bgp(tgen
, topo
, input_dict_1
)
1076 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
1078 step("Verify that zebra selects static route.")
1081 for addr_type
in ADDR_TYPES
:
1082 result4
= verify_rib(tgen
, addr_type
, dut
, input_dict
, protocol
=protocol
)
1083 assert result4
is True, "Testcase {} : Failed \n Error: {}".format(
1087 step("Delete the static route.")
1088 for addr_type
in ADDR_TYPES
:
1094 "network": NETWORK
[addr_type
],
1095 "next_hop": "Null0",
1096 "admin_distance": 253,
1103 result
= create_static_routes(tgen
, input_dict
)
1104 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
1108 step("Verify that zebra selects bgp route.")
1111 for addr_type
in ADDR_TYPES
:
1112 result4
= verify_rib(tgen
, addr_type
, dut
, input_dict
, protocol
=protocol
)
1113 assert result4
is True, "Testcase {} : Failed \n Error: {}".format(
1117 write_test_footer(tc_name
)
1120 def test_bgp_admin_distance_chaos_p2():
1123 Chaos - Verify bgp admin distance functionality with chaos.
1125 tgen
= get_topogen()
1126 global bgp_convergence
1128 if bgp_convergence
is not True:
1129 pytest
.skip("skipping test case because of BGP Convergence failure at setup")
1132 tc_name
= inspect
.stack()[0][3]
1133 write_test_header(tc_name
)
1134 if tgen
.routers_have_failure():
1135 check_router_status(tgen
)
1137 step("Configure base config as per the topology")
1138 reset_config_on_routers(tgen
)
1140 step("Configure bgp admin distance 200 with CLI in dut.")
1149 "distance": {"ebgp": 200, "ibgp": 200, "local": 200}
1154 "distance": {"ebgp": 200, "ibgp": 200, "local": 200}
1162 result
= create_router_bgp(tgen
, topo
, input_dict_1
)
1163 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
1165 step("Verify bgp routes have admin distance of 200 in dut.")
1166 # Verifying best path
1168 attribute
= "admin_distance"
1175 "network": NETWORK
["ipv4"][0],
1176 "admin_distance": 200,
1179 "network": NETWORK
["ipv4"][1],
1180 "admin_distance": 200,
1189 "network": NETWORK
["ipv6"][0],
1190 "admin_distance": 200,
1193 "network": NETWORK
["ipv6"][1],
1194 "admin_distance": 200,
1201 for addr_type
in ADDR_TYPES
:
1202 result
= verify_best_path_as_per_admin_distance(
1203 tgen
, addr_type
, dut
, input_dict
[addr_type
], attribute
1205 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
1209 step("Restart frr on R3")
1210 stop_router(tgen
, "r3")
1211 start_router(tgen
, "r3")
1213 bgp_convergence
= verify_bgp_convergence(tgen
, topo
)
1214 assert bgp_convergence
is True, "Testcase {} : Failed \n Error: {}".format(
1215 tc_name
, bgp_convergence
1218 step("Verify ebgp and ibgp routes have admin distance of 200 in dut.")
1219 for addr_type
in ADDR_TYPES
:
1220 result
= verify_best_path_as_per_admin_distance(
1221 tgen
, addr_type
, dut
, input_dict
[addr_type
], attribute
1223 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
1227 step("Restart bgpd process on R3")
1228 kill_router_daemons(tgen
, "r3", ["bgpd"])
1229 start_router_daemons(tgen
, "r3", ["bgpd"])
1231 bgp_convergence
= verify_bgp_convergence(tgen
, topo
)
1232 assert bgp_convergence
is True, "Testcase {} : Failed \n Error: {}".format(
1233 tc_name
, bgp_convergence
1236 step("Verify ebgp and ibgp routes have admin distance of 200 in dut.")
1237 for addr_type
in ADDR_TYPES
:
1238 result
= verify_best_path_as_per_admin_distance(
1239 tgen
, addr_type
, dut
, input_dict
[addr_type
], attribute
1241 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
1246 for rtr
in topo
["routers"]:
1247 clear_bgp(tgen
, "ipv4", rtr
)
1248 clear_bgp(tgen
, "ipv6", rtr
)
1250 bgp_convergence
= verify_bgp_convergence(tgen
, topo
)
1251 assert bgp_convergence
is True, "Testcase {} : Failed \n Error: {}".format(
1252 tc_name
, bgp_convergence
1255 step("Verify that zebra selects bgp route.")
1258 for addr_type
in ADDR_TYPES
:
1259 result4
= verify_rib(tgen
, addr_type
, dut
, input_dict
, protocol
=protocol
)
1260 assert result4
is True, "Testcase {} : Failed \n Error: {}".format(
1264 write_test_footer(tc_name
)
1267 if __name__
== "__main__":
1268 args
= ["-s"] + sys
.argv
[1:]
1269 sys
.exit(pytest
.main(args
))