2 # SPDX-License-Identifier: ISC
5 # Modified work Copyright (c) 2019 by VMware, Inc. ("VMware")
6 # Original work Copyright (c) 2018 by Network Device Education
7 # Foundation, Inc. ("NetDEF")
11 Following tests are covered to test AS-Path functionality:
14 - Create topology (setup module)
16 - Verify BGP convergence
19 1. Test next_hop attribute and verify best path is installed as per
21 2. Test aspath attribute and verify best path is installed as per
23 3. Test localpref attribute and verify best path is installed as per
24 shortest local-preference
25 4. Test weight attribute and and verify best path is installed as per
27 5. Test origin attribute and verify best path is installed as per
28 IGP>EGP>INCOMPLETE rule
29 6. Test med attribute and verify best path is installed as per lowest
31 7. Test admin distance and verify best path is installed as per lowest
35 - Bring down the topology
45 # Save the Current Working Directory to find configuration files.
46 CWD
= os
.path
.dirname(os
.path
.realpath(__file__
))
47 sys
.path
.append(os
.path
.join(CWD
, "../"))
49 # pylint: disable=C0413
50 # Import topogen and topotest helpers
51 from lib
.topogen
import Topogen
, get_topogen
53 # Required to instantiate the topology builder class.
54 from lib
.common_config
import (
58 reset_config_on_routers
,
65 from lib
.topolog
import logger
67 verify_bgp_convergence
,
69 verify_best_path_as_per_bgp_attribute
,
70 verify_best_path_as_per_admin_distance
,
72 from lib
.topojson
import build_config_from_json
75 pytestmark
= [pytest
.mark
.bgpd
, pytest
.mark
.staticd
]
78 # Address read from env variables
79 ADDR_TYPES
= check_address_types()
82 def setup_module(mod
):
84 Sets up the pytest environment
91 testsuite_run_time
= time
.asctime(time
.localtime(time
.time()))
92 logger
.info("Testsuite start time: %s", testsuite_run_time
)
95 logger
.info("Running setup_module to create topology")
97 # This function initiates the topology build with Topogen...
98 json_file
= "{}/bgp_path_attributes.json".format(CWD
)
99 tgen
= Topogen(json_file
, mod
.__name
__)
101 topo
= tgen
.json_topo
102 # ... and here it calls Mininet initialization functions.
104 # Starting topology, create tmp files which are loaded to routers
105 # to start daemons and then start routers
108 # Creating configuration from JSON
109 build_config_from_json(tgen
, topo
)
111 # Don't run this test if we have any failure.
112 if tgen
.routers_have_failure():
113 pytest
.skip(tgen
.errors
)
115 # Checking BGP convergence
116 result
= verify_bgp_convergence(tgen
, topo
)
117 assert result
is True, "setup_module :Failed \n Error:" " {}".format(result
)
119 logger
.info("Running setup_module() done")
122 def teardown_module():
124 Teardown the pytest environment
127 logger
.info("Running teardown_module to delete topology")
131 # Stop toplogy and Remove tmp files
134 logger
.info("Testsuite end time: %s", time
.asctime(time
.localtime(time
.time())))
135 logger
.info("=" * 40)
138 #####################################################
142 #####################################################
145 def test_next_hop_attribute(request
):
147 Verifying route are not getting installed in, as next_hop is
148 unreachable, Making next hop reachable using next_hop_self
149 command and verifying routes are installed.
154 # Don't run this test if we have any failure.
155 if tgen
.routers_have_failure():
156 pytest
.skip(tgen
.errors
)
159 tc_name
= request
.node
.name
160 write_test_header(tc_name
)
162 # Creating configuration from JSON
163 reset_config_on_routers(tgen
)
165 # Api call to advertise networks
172 "advertise_networks": [
173 {"network": "200.50.2.0/32"},
174 {"network": "200.60.2.0/32"},
180 "advertise_networks": [
181 {"network": "200:50:2::/128"},
182 {"network": "200:60:2::/128"},
190 result
= create_router_bgp(tgen
, topo
, input_dict
)
191 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
193 # Verifying RIB routes
196 # Verification should fail as nexthop-self is not enabled
197 for addr_type
in ADDR_TYPES
:
199 tgen
, addr_type
, dut
, input_dict
, protocol
=protocol
, expected
=False
203 ), "Testcase {} : Failed \n Error: " "{} routes are not present in RIB".format(
207 # Configure next-hop-self to bgp neighbor
215 "r1": {"dest_link": {"r2": {"next_hop_self": True}}}
222 "r1": {"dest_link": {"r2": {"next_hop_self": True}}}
235 "r1": {"dest_link": {"r3": {"next_hop_self": True}}}
242 "r1": {"dest_link": {"r3": {"next_hop_self": True}}}
251 result
= create_router_bgp(tgen
, topo
, input_dict_1
)
252 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
254 # Verifying RIB routes
257 for addr_type
in ADDR_TYPES
:
258 result
= verify_rib(tgen
, addr_type
, dut
, input_dict
, protocol
=protocol
)
259 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
263 write_test_footer(tc_name
)
266 def test_aspath_attribute(request
):
267 "Verifying AS_PATH attribute functionality"
271 # Don't run this test if we have any failure.
272 if tgen
.routers_have_failure():
273 pytest
.skip(tgen
.errors
)
276 tc_name
= request
.node
.name
277 write_test_header(tc_name
)
279 # Creating configuration from JSON
280 reset_config_on_routers(tgen
)
282 # Api call to advertise networks
289 "advertise_networks": [
290 {"network": "200.50.2.0/32"},
291 {"network": "200.60.2.0/32"},
297 "advertise_networks": [
298 {"network": "200:50:2::/128"},
299 {"network": "200:60:2::/128"},
312 "r1": {"dest_link": {"r2": {"next_hop_self": True}}}
319 "r1": {"dest_link": {"r2": {"next_hop_self": True}}}
332 "r1": {"dest_link": {"r3": {"next_hop_self": True}}}
339 "r1": {"dest_link": {"r3": {"next_hop_self": True}}}
347 result
= create_router_bgp(tgen
, topo
, input_dict
)
348 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
350 # Verifying best path
353 for addr_type
in ADDR_TYPES
:
354 result
= verify_best_path_as_per_bgp_attribute(
355 tgen
, addr_type
, dut
, {"r7": input_dict
["r7"]}, attribute
357 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
361 # Modify AS-Path and verify best path is changed
371 "network": "200.0.0.0/8",
381 "network": "200::/8",
390 result
= create_prefix_lists(tgen
, input_dict_2
)
391 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
400 "match": {"ipv4": {"prefix_lists": "pf_ls_1_ipv4"}},
401 "set": {"path": {"as_num": "111 222", "as_action": "prepend"}},
405 "match": {"ipv6": {"prefix_lists": "pf_ls_1_ipv6"}},
406 "set": {"path": {"as_num": "111 222", "as_action": "prepend"}},
412 result
= create_route_maps(tgen
, input_dict_3
)
413 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
415 # Configure neighbor for route map
428 "name": "RMAP_AS_PATH",
446 "name": "RMAP_AS_PATH",
460 result
= create_router_bgp(tgen
, topo
, input_dict_4
)
461 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
463 # Verifying best path
466 for addr_type
in ADDR_TYPES
:
467 result
= verify_best_path_as_per_bgp_attribute(
468 tgen
, addr_type
, dut
, {"r7": input_dict
["r7"]}, attribute
470 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
474 write_test_footer(tc_name
)
477 def test_localpref_attribute(request
):
478 "Verifying LOCAL PREFERENCE attribute functionality"
482 # Don't run this test if we have any failure.
483 if tgen
.routers_have_failure():
484 pytest
.skip(tgen
.errors
)
487 tc_name
= request
.node
.name
488 write_test_header(tc_name
)
490 # Creating configuration from JSON
491 reset_config_on_routers(tgen
)
493 # Api call to advertise networks
500 "advertise_networks": [
501 {"network": "200.50.2.0/32"},
502 {"network": "200.60.2.0/32"},
508 "advertise_networks": [
509 {"network": "200:50:2::/128"},
510 {"network": "200:60:2::/128"},
523 "r1": {"dest_link": {"r2": {"next_hop_self": True}}}
530 "r1": {"dest_link": {"r2": {"next_hop_self": True}}}
543 "r1": {"dest_link": {"r3": {"next_hop_self": True}}}
550 "r1": {"dest_link": {"r3": {"next_hop_self": True}}}
559 result
= create_router_bgp(tgen
, topo
, input_dict
)
560 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
570 "network": "200.0.0.0/8",
580 "network": "200::/8",
589 result
= create_prefix_lists(tgen
, input_dict_2
)
590 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
600 "match": {"ipv4": {"prefix_lists": "pf_ls_1_ipv4"}},
601 "set": {"locPrf": 1111},
606 "match": {"ipv6": {"prefix_lists": "pf_ls_1_ipv6"}},
607 "set": {"locPrf": 1111},
613 result
= create_route_maps(tgen
, input_dict_3
)
614 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
616 # Configure neighbor for route map
629 "name": "RMAP_LOCAL_PREF",
647 "name": "RMAP_LOCAL_PREF",
661 result
= create_router_bgp(tgen
, topo
, input_dict_4
)
662 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
664 # Verifying best path
667 for addr_type
in ADDR_TYPES
:
668 result
= verify_best_path_as_per_bgp_attribute(
669 tgen
, addr_type
, dut
, {"r7": input_dict
["r7"]}, attribute
671 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
683 "match": {"ipv4": {"prefix_lists": "pf_ls_1_ipv4"}},
684 "set": {"locPrf": 50},
689 "match": {"ipv6": {"prefix_lists": "pf_ls_1_ipv6"}},
690 "set": {"locPrf": 50},
696 result
= create_route_maps(tgen
, input_dict_3
)
697 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
699 # Verifying best path
702 for addr_type
in ADDR_TYPES
:
703 result
= verify_best_path_as_per_bgp_attribute(
704 tgen
, addr_type
, dut
, {"r7": input_dict
["r7"]}, attribute
706 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
710 write_test_footer(tc_name
)
713 def test_weight_attribute(request
):
715 Test configure/modify weight attribute and
716 verify best path is installed as per highest weight
721 # Don't run this test if we have any failure.
722 if tgen
.routers_have_failure():
723 pytest
.skip(tgen
.errors
)
726 tc_name
= request
.node
.name
727 write_test_header(tc_name
)
729 # Creating configuration from JSON
730 reset_config_on_routers(tgen
)
732 # Api call to advertise networks
739 "advertise_networks": [
740 {"network": "200.50.2.0/32"},
741 {"network": "200.60.2.0/32"},
747 "advertise_networks": [
748 {"network": "200:50:2::/128"},
749 {"network": "200:60:2::/128"},
762 "r1": {"dest_link": {"r2": {"next_hop_self": True}}}
769 "r1": {"dest_link": {"r2": {"next_hop_self": True}}}
782 "r1": {"dest_link": {"r3": {"next_hop_self": True}}}
789 "r1": {"dest_link": {"r3": {"next_hop_self": True}}}
797 result
= create_router_bgp(tgen
, topo
, input_dict
)
798 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
808 "network": "200.0.0.0/8",
818 "network": "200::/8",
827 result
= create_prefix_lists(tgen
, input_dict_2
)
828 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
838 "match": {"ipv4": {"prefix_lists": "pf_ls_1_ipv4"}},
839 "set": {"weight": 500},
844 "match": {"ipv6": {"prefix_lists": "pf_ls_1_ipv6"}},
845 "set": {"weight": 500},
851 result
= create_route_maps(tgen
, input_dict_3
)
852 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
854 # Configure neighbor for route map
867 "name": "RMAP_WEIGHT",
885 "name": "RMAP_WEIGHT",
899 result
= create_router_bgp(tgen
, topo
, input_dict_4
)
900 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
902 # Verifying best path
905 for addr_type
in ADDR_TYPES
:
906 result
= verify_best_path_as_per_bgp_attribute(
907 tgen
, addr_type
, dut
, {"r7": input_dict
["r7"]}, attribute
909 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
921 "match": {"ipv4": {"prefix_lists": "pf_ls_1_ipv4"}},
922 "set": {"weight": 1000},
927 "match": {"ipv6": {"prefix_lists": "pf_ls_1_ipv6"}},
928 "set": {"weight": 1000},
934 result
= create_route_maps(tgen
, input_dict_3
)
935 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
937 # Verifying best path
940 for addr_type
in ADDR_TYPES
:
941 result
= verify_best_path_as_per_bgp_attribute(
942 tgen
, addr_type
, dut
, {"r7": input_dict
["r7"]}, attribute
944 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
948 write_test_footer(tc_name
)
951 def test_origin_attribute(request
):
953 Test origin attribute and verify best path is
954 installed as per IGP>EGP>INCOMPLETE rule
959 # Don't run this test if we have any failure.
960 if tgen
.routers_have_failure():
961 pytest
.skip(tgen
.errors
)
964 tc_name
= request
.node
.name
965 write_test_header(tc_name
)
967 # Creating configuration from JSON
968 reset_config_on_routers(tgen
)
970 # Api call to advertise networks
977 "advertise_networks": [
978 {"network": "200.50.2.0/32"},
979 {"network": "200.60.2.0/32"},
985 "advertise_networks": [
986 {"network": "200:50:2::/128"},
987 {"network": "200:60:2::/128"},
1000 "r1": {"dest_link": {"r2": {"next_hop_self": True}}}
1007 "r1": {"dest_link": {"r2": {"next_hop_self": True}}}
1020 "r1": {"dest_link": {"r3": {"next_hop_self": True}}}
1027 "r1": {"dest_link": {"r3": {"next_hop_self": True}}}
1040 {"redist_type": "static"},
1041 {"redist_type": "connected"},
1048 {"redist_type": "static"},
1049 {"redist_type": "connected"},
1057 result
= create_router_bgp(tgen
, topo
, input_dict
)
1058 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
1060 # Api call to create static routes
1064 {"network": "200.50.2.0/32", "next_hop": "Null0"},
1065 {"network": "200.60.2.0/32", "next_hop": "Null0"},
1066 {"network": "200:50:2::/128", "next_hop": "Null0"},
1067 {"network": "200:60:2::/128", "next_hop": "Null0"},
1071 result
= create_static_routes(tgen
, input_dict_3
)
1072 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
1074 # Verifying best path
1076 attribute
= "origin"
1077 for addr_type
in ADDR_TYPES
:
1078 result
= verify_best_path_as_per_bgp_attribute(
1079 tgen
, addr_type
, dut
, {"r4": input_dict
["r4"]}, attribute
1081 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
1085 write_test_footer(tc_name
)
1088 def test_med_attribute(request
):
1090 Test configure/modify MED attribute and verify best path
1091 is installed as per lowest med value
1094 tgen
= get_topogen()
1096 # Don't run this test if we have any failure.
1097 if tgen
.routers_have_failure():
1098 pytest
.skip(tgen
.errors
)
1101 tc_name
= request
.node
.name
1102 write_test_header(tc_name
)
1104 # Creating configuration from JSON
1105 reset_config_on_routers(tgen
)
1107 # Api call to advertise networks
1114 "advertise_networks": [
1115 {"network": "200.50.2.0/32"},
1116 {"network": "200.60.2.0/32"},
1122 "advertise_networks": [
1123 {"network": "200:50:2::/128"},
1124 {"network": "200:60:2::/128"},
1136 "advertise_networks": [
1137 {"network": "200.50.2.0/32"},
1138 {"network": "200.60.2.0/32"},
1144 "advertise_networks": [
1145 {"network": "200:50:2::/128"},
1146 {"network": "200:60:2::/128"},
1155 result
= create_router_bgp(tgen
, topo
, input_dict
)
1156 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
1158 # Create Prefix list
1166 "network": "200.0.0.0/8",
1176 "network": "200::/8",
1190 "network": "200.0.0.0/8",
1200 "network": "200::/8",
1209 result
= create_prefix_lists(tgen
, input_dict_2
)
1210 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
1220 "match": {"ipv4": {"prefix_lists": "pf_ls_r2_ipv4"}},
1221 "set": {"metric": 100},
1226 "match": {"ipv6": {"prefix_lists": "pf_ls_r2_ipv6"}},
1227 "set": {"metric": 100},
1238 "match": {"ipv4": {"prefix_lists": "pf_ls_r3_ipv4"}},
1239 "set": {"metric": 10},
1244 "match": {"ipv6": {"prefix_lists": "pf_ls_r3_ipv6"}},
1245 "set": {"metric": 10},
1251 result
= create_route_maps(tgen
, input_dict_3
)
1252 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
1254 # Configure neighbor for route map
1267 "name": "RMAP_MED_R2",
1274 "r1": {"dest_link": {"r2": {"next_hop_self": True}}},
1286 "name": "RMAP_MED_R2",
1293 "r1": {"dest_link": {"r2": {"next_hop_self": True}}},
1306 "r1": {"dest_link": {"r3": {"next_hop_self": True}}},
1312 "name": "RMAP_MED_R3",
1325 "r1": {"dest_link": {"r3": {"next_hop_self": True}}},
1331 "name": "RMAP_MED_R3",
1346 result
= create_router_bgp(tgen
, topo
, input_dict_4
)
1347 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
1349 # Verifying best path
1351 attribute
= "metric"
1352 for addr_type
in ADDR_TYPES
:
1353 result
= verify_best_path_as_per_bgp_attribute(
1354 tgen
, addr_type
, dut
, input_dict
, attribute
1356 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
1360 # Modify route-map to set med value
1368 "match": {"ipv4": {"prefix_lists": "pf_ls_r3_ipv4"}},
1369 "set": {"metric": 200},
1374 "match": {"ipv6": {"prefix_lists": "pf_ls_r3_ipv6"}},
1375 "set": {"metric": 200},
1382 result
= create_route_maps(tgen
, input_dict_3
)
1383 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
1385 # Verifying best path
1387 attribute
= "metric"
1388 for addr_type
in ADDR_TYPES
:
1389 result
= verify_best_path_as_per_bgp_attribute(
1390 tgen
, addr_type
, dut
, input_dict
, attribute
1392 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
1396 write_test_footer(tc_name
)
1398 # Uncomment next line for debugging
1399 # tgen.mininet_cli()
1402 def test_admin_distance(request
):
1403 "Verifying admin distance functionality"
1405 tgen
= get_topogen()
1407 # Don't run this test if we have any failure.
1408 if tgen
.routers_have_failure():
1409 pytest
.skip(tgen
.errors
)
1412 tc_name
= request
.node
.name
1413 write_test_header(tc_name
)
1415 # Creating configuration from JSON
1416 reset_config_on_routers(tgen
)
1418 # Api call to create static routes
1423 "network": "200.50.2.0/32",
1424 "admin_distance": 80,
1425 "next_hop": "10.0.0.14",
1428 "network": "200.50.2.0/32",
1429 "admin_distance": 60,
1430 "next_hop": "10.0.0.18",
1433 "network": "200:50:2::/128",
1434 "admin_distance": 80,
1435 "next_hop": "fd00::1",
1438 "network": "200:50:2::/128",
1439 "admin_distance": 60,
1440 "next_hop": "fd00::1",
1445 result
= create_static_routes(tgen
, input_dict
)
1446 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
1448 # Api call to redistribute static routes
1456 {"redist_type": "static"},
1457 {"redist_type": "connected"},
1464 {"redist_type": "static"},
1465 {"redist_type": "connected"},
1473 result
= create_router_bgp(tgen
, input_dict_2
)
1474 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
1476 # Verifying best path
1478 attribute
= "admin_distance"
1485 "network": "200.50.2.0/32",
1486 "admin_distance": 80,
1487 "next_hop": "10.0.0.14",
1490 "network": "200.50.2.0/32",
1491 "admin_distance": 60,
1492 "next_hop": "10.0.0.18",
1501 "network": "200:50:2::/128",
1502 "admin_distance": 80,
1503 "next_hop": "fd00::1",
1506 "network": "200:50:2::/128",
1507 "admin_distance": 60,
1508 "next_hop": "fd00::1",
1515 for addr_type
in ADDR_TYPES
:
1516 result
= verify_best_path_as_per_admin_distance(
1517 tgen
, addr_type
, dut
, input_dict
[addr_type
], attribute
1519 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
1523 write_test_footer(tc_name
)
1526 if __name__
== "__main__":
1527 args
= ["-s"] + sys
.argv
[1:]
1528 sys
.exit(pytest
.main(args
))