4 # Copyright (c) 2019 by VMware, Inc. ("VMware")
5 # Used Copyright (c) 2018 by Network Device Education Foundation,
6 # Inc. ("NetDEF") in this file.
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
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
29 from time
import sleep
31 # Save the Current Working Directory to find configuration files.
32 CWD
= os
.path
.dirname(os
.path
.realpath(__file__
))
33 sys
.path
.append(os
.path
.join(CWD
, "../"))
35 # pylint: disable=C0413
36 # Import topogen and topotest helpers
37 from lib
import topotest
38 from lib
.topogen
import Topogen
, get_topogen
39 from mininet
.topo
import Topo
41 # Required to instantiate the topology builder class.
42 from lib
.topojson
import *
43 from lib
.common_config
import (
50 create_bgp_community_lists
,
57 shutdown_bringup_interface
,
59 reset_config_on_routers
,
61 from lib
.topolog
import logger
63 verify_bgp_convergence
,
66 verify_bgp_attributes
,
68 from lib
.topojson
import build_topo_from_json
, build_config_from_json
70 pytestmark
= [pytest
.mark
.bgpd
, pytest
.mark
.staticd
]
73 #################################
75 #################################
87 +---------- | R3 |----------| R4 |
92 #################################
94 #################################
96 Following tests are covered to test route-map functionality:
98 Verify if route-maps is applied in both inbound and
99 outbound direction to same neighbor/interface.
101 Test permit/deny statements operation in route-maps with a
102 permutation and combination of permit/deny in prefix-lists
104 Test multiple sequence numbers in a single route-map for different
107 Test add/remove route-maps with multiple set
108 clauses and without any match statement.(Set only)
110 Test add/remove route-maps with multiple match
111 clauses and without any set statement.(Match only)
115 bgp_convergence
= False
116 BGP_CONVERGENCE
= False
117 ADDR_TYPES
= check_address_types()
118 # Reading the data from JSON File for topology and configuration creation
119 jsonFile
= "{}/bgp_route_map_topo1.json".format(CWD
)
121 with
open(jsonFile
, "r") as topoJson
:
122 topo
= json
.load(topoJson
)
124 assert False, "Could not read file {}".format(jsonFile
)
127 bgp_convergence
= False
128 NETWORK
= {"ipv4": ["11.0.20.1/32", "20.0.20.1/32"], "ipv6": ["1::1/128", "2::1/128"]}
129 MASK
= {"ipv4": "32", "ipv6": "128"}
130 NEXT_HOP
= {"ipv4": "10.0.0.2", "ipv6": "fd00::2"}
131 ADDR_TYPES
= check_address_types()
134 class CreateTopo(Topo
):
136 Test topology builder
139 * `Topo`: Topology object
142 def build(self
, *_args
, **_opts
):
144 tgen
= get_topogen(self
)
146 # Building topology from json file
147 build_topo_from_json(tgen
, topo
)
150 def setup_module(mod
):
152 Sets up the pytest environment
157 testsuite_run_time
= time
.asctime(time
.localtime(time
.time()))
158 logger
.info("Testsuite start time: {}".format(testsuite_run_time
))
159 logger
.info("=" * 40)
161 logger
.info("Running setup_module to create topology")
163 # This function initiates the topology build with Topogen...
164 tgen
= Topogen(CreateTopo
, mod
.__name
__)
165 # ... and here it calls Mininet initialization functions.
167 # Starting topology, create tmp files which are loaded to routers
168 # to start deamons and then start routers
171 # Creating configuration from JSON
172 build_config_from_json(tgen
, topo
)
174 # Checking BGP convergence
175 global bgp_convergence
177 # Don"t run this test if we have any failure.
178 if tgen
.routers_have_failure():
179 pytest
.skip(tgen
.errors
)
181 # Api call verify whether BGP is converged
182 bgp_convergence
= verify_bgp_convergence(tgen
, topo
)
183 assert bgp_convergence
is True, "setup_module :Failed \n Error:" " {}".format(
187 logger
.info("Running setup_module() done")
190 def teardown_module():
192 Teardown the pytest environment
197 logger
.info("Running teardown_module to delete topology")
201 # Stop toplogy and Remove tmp files
205 "Testsuite end time: {}".format(time
.asctime(time
.localtime(time
.time())))
207 logger
.info("=" * 40)
210 def test_route_map_inbound_outbound_same_neighbor_p0(request
):
213 Verify if route-maps is applied in both inbound and
214 outbound direction to same neighbor/interface.
217 tc_name
= request
.node
.name
218 write_test_header(tc_name
)
221 # Don"t run this test if we have any failure.
222 if tgen
.routers_have_failure():
223 pytest
.skip(tgen
.errors
)
225 # Creating configuration from JSON
226 reset_config_on_routers(tgen
)
228 for adt
in ADDR_TYPES
:
230 # Create Static routes
235 "network": NETWORK
[adt
][0],
237 "next_hop": NEXT_HOP
[adt
],
243 result
= create_static_routes(tgen
, input_dict
)
244 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
248 # Api call to redistribute static routes
257 {"redist_type": "static"},
258 {"redist_type": "connected"},
265 {"redist_type": "static"},
266 {"redist_type": "connected"},
275 result
= create_router_bgp(tgen
, topo
, input_dict_1
)
276 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
284 "network": NETWORK
[adt
][1],
286 "next_hop": NEXT_HOP
[adt
],
292 result
= create_static_routes(tgen
, input_dict_2
)
293 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
297 # Api call to redistribute static routes
305 {"redist_type": "static"},
306 {"redist_type": "connected"},
313 {"redist_type": "static"},
314 {"redist_type": "connected"},
322 result
= create_router_bgp(tgen
, topo
, input_dict_5
)
323 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
335 "network": NETWORK
["ipv4"][0],
342 "network": NETWORK
["ipv4"][1],
351 "network": NETWORK
["ipv6"][0],
358 "network": NETWORK
["ipv6"][1],
365 result
= create_prefix_lists(tgen
, input_dict_2
)
366 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
371 for addr_type
in ADDR_TYPES
:
375 "rmap_match_tag_1_{}".format(addr_type
): [
380 "prefix_lists": "pf_list_1_{}".format(addr_type
)
385 "rmap_match_tag_2_{}".format(addr_type
): [
390 "prefix_lists": "pf_list_2_{}".format(addr_type
)
398 result
= create_route_maps(tgen
, input_dict_6
)
399 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
403 # Configure neighbor for route map
416 "name": "rmap_match_tag_1_ipv4",
420 "name": "rmap_match_tag_1_ipv4",
438 "name": "rmap_match_tag_1_ipv6",
442 "name": "rmap_match_tag_1_ipv6",
457 result
= create_router_bgp(tgen
, topo
, input_dict_7
)
458 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
462 for adt
in ADDR_TYPES
:
463 # Verifying RIB routes
470 "network": [NETWORK
[adt
][1]],
472 "next_hop": NEXT_HOP
[adt
],
479 tgen
, adt
, dut
, input_dict_2
, protocol
=protocol
, expected
=False
481 assert result
is not True, ("Testcase {} : Failed \n"
482 "routes are not present in rib \n Error: {}".format(tc_name
, result
))
483 logger
.info("Expected behaviour: {}".format(result
))
485 # Verifying RIB routes
491 "network": [NETWORK
[adt
][0]],
493 "next_hop": NEXT_HOP
[adt
],
499 tgen
, adt
, dut
, input_dict
, protocol
=protocol
, expected
=False
501 assert result
is not True, ("Testcase {} : Failed \n "
502 "routes are not present in rib \n Error: {}".format(tc_name
, result
))
503 logger
.info("Expected behaviour: {}".format(result
))
505 write_test_footer(tc_name
)
508 @pytest.mark
.parametrize(
509 "prefix_action, rmap_action",
510 [("permit", "permit"), ("permit", "deny"), ("deny", "permit"), ("deny", "deny")],
512 def test_route_map_with_action_values_combination_of_prefix_action_p0(
513 request
, prefix_action
, rmap_action
517 Test permit/deny statements operation in route-maps with a permutation and
518 combination of permit/deny in prefix-lists
520 tc_name
= request
.node
.name
521 write_test_header(tc_name
)
524 # Don"t run this test if we have any failure.
525 if tgen
.routers_have_failure():
526 pytest
.skip(tgen
.errors
)
528 # Creating configuration from JSON
529 reset_config_on_routers(tgen
)
531 for adt
in ADDR_TYPES
:
532 # Create Static routes
537 "network": NETWORK
[adt
][0],
539 "next_hop": NEXT_HOP
[adt
],
545 result
= create_static_routes(tgen
, input_dict
)
546 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
550 # Api call to redistribute static routes
559 {"redist_type": "static"},
560 {"redist_type": "connected"},
567 {"redist_type": "static"},
568 {"redist_type": "connected"},
577 result
= create_router_bgp(tgen
, topo
, input_dict_1
)
578 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
582 # Permit in perfix list and route-map
588 {"seqid": 10, "network": "any", "action": prefix_action
}
593 {"seqid": 100, "network": "any", "action": prefix_action
}
599 result
= create_prefix_lists(tgen
, input_dict_2
)
600 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
605 for addr_type
in ADDR_TYPES
:
609 "rmap_match_pf_1_{}".format(addr_type
): [
611 "action": rmap_action
,
614 "prefix_lists": "pf_list_1_{}".format(addr_type
)
622 result
= create_route_maps(tgen
, input_dict_3
)
623 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
627 # Configure neighbor for route map
640 "name": "rmap_match_pf_1_ipv4",
658 "name": "rmap_match_pf_1_ipv6",
673 result
= create_router_bgp(tgen
, topo
, input_dict_7
)
674 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
684 "network": [NETWORK
[adt
][0]],
686 "next_hop": NEXT_HOP
[adt
],
693 if "deny" in [prefix_action
, rmap_action
]:
695 tgen
, adt
, dut
, input_dict_2
, protocol
=protocol
, expected
=False
697 assert result
is not True, ("Testcase {} : Failed \n "
698 "Routes are still present \n Error: {}".format(tc_name
, result
))
699 logger
.info("Expected behaviour: {}".format(result
))
702 tgen
, adt
, dut
, input_dict_2
, protocol
=protocol
704 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
709 def test_route_map_multiple_seq_different_match_set_clause_p0(request
):
712 Test multiple sequence numbers in a single route-map for different
718 tc_name
= request
.node
.name
719 write_test_header(tc_name
)
721 # Creating configuration from JSON
722 reset_config_on_routers(tgen
)
724 for adt
in ADDR_TYPES
:
725 # Create Static routes
730 "network": NETWORK
[adt
][0],
732 "next_hop": NEXT_HOP
[adt
],
737 result
= create_static_routes(tgen
, input_dict
)
738 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
742 # Api call to redistribute static routes
750 {"redist_type": "static"},
751 {"redist_type": "connected"},
758 {"redist_type": "static"},
759 {"redist_type": "connected"},
767 result
= create_router_bgp(tgen
, topo
, input_dict_1
)
768 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
772 # Create ip prefix list
778 {"seqid": 10, "network": "any", "action": "permit"}
783 {"seqid": 100, "network": "any", "action": "permit"}
789 result
= create_prefix_lists(tgen
, input_dict_2
)
790 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
795 for addr_type
in ADDR_TYPES
:
799 "rmap_match_pf_1_{}".format(addr_type
): [
804 "prefix_lists": "pf_list_2_{}".format(addr_type
)
807 "set": {"path": {"as_num": 500}},
813 "prefix_lists": "pf_list_2_{}".format(addr_type
)
824 "prefix_lists": "pf_list_1_{}".format(addr_type
)
827 "set": {"metric": 50},
833 result
= create_route_maps(tgen
, input_dict_3
)
834 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
838 # Configure neighbor for route map
851 "name": "rmap_match_pf_1_ipv4",
863 "name": "rmap_match_pf_1_ipv4",
881 "name": "rmap_match_pf_1_ipv6",
893 "name": "rmap_match_pf_1_ipv6",
907 result
= create_router_bgp(tgen
, topo
, input_dict_4
)
908 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
912 for adt
in ADDR_TYPES
:
913 # Verifying RIB routes
919 "rmap_match_pf_list1": [
930 static_routes
= [NETWORK
[adt
][0]]
933 result
= verify_bgp_attributes(
934 tgen
, adt
, dut
, static_routes
, "rmap_match_pf_list1", input_dict
936 assert result
is True, "Test case {} : Failed \n Error: {}".format(
941 result
= verify_bgp_attributes(
942 tgen
, adt
, dut
, static_routes
, "rmap_match_pf_list1", input_dict
944 assert result
is True, "Test case {} : Failed \n Error: {}".format(
948 logger
.info("Testcase " + tc_name
+ " :Passed \n")
950 # Uncomment next line for debugging
954 def test_route_map_set_only_no_match_p0(request
):
957 Test add/remove route-maps with multiple set
958 clauses and without any match statement.(Set only)
963 tc_name
= request
.node
.name
964 write_test_header(tc_name
)
966 # Creating configuration from JSON
967 reset_config_on_routers(tgen
)
969 for adt
in ADDR_TYPES
:
970 # Create Static routes
975 "network": NETWORK
[adt
][0],
977 "next_hop": NEXT_HOP
[adt
],
982 result
= create_static_routes(tgen
, input_dict
)
983 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
987 # Api call to redistribute static routes
995 {"redist_type": "static"},
996 {"redist_type": "connected"},
1003 {"redist_type": "static"},
1004 {"redist_type": "connected"},
1012 result
= create_router_bgp(tgen
, topo
, input_dict_1
)
1013 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
1021 "rmap_match_pf_1": [
1024 "set": {"metric": 50, "locPrf": 150, "weight": 4000},
1030 result
= create_route_maps(tgen
, input_dict_3
)
1031 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
1035 # Configure neighbor for route map
1048 "name": "rmap_match_pf_1",
1060 "name": "rmap_match_pf_1",
1078 "name": "rmap_match_pf_1",
1090 "name": "rmap_match_pf_1",
1104 result
= create_router_bgp(tgen
, topo
, input_dict_4
)
1105 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
1110 for adt
in ADDR_TYPES
:
1114 "rmap_match_pf_1": [
1125 # Verifying RIB routes
1126 static_routes
= [NETWORK
[adt
][0]]
1127 result
= verify_bgp_attributes(
1128 tgen
, adt
, "r3", static_routes
, "rmap_match_pf_1", input_dict_3
1130 assert result
is True, "Test case {} : Failed \n Error: {}".format(
1134 result
= verify_bgp_attributes(
1135 tgen
, adt
, "r4", static_routes
, "rmap_match_pf_1", input_dict_4
1137 assert result
is True, "Test case {} : Failed \n Error: {}".format(
1141 logger
.info("Testcase " + tc_name
+ " :Passed \n")
1143 # Uncomment next line for debugging
1144 # tgen.mininet_cli()
1147 def test_route_map_match_only_no_set_p0(request
):
1150 Test add/remove route-maps with multiple match
1151 clauses and without any set statement.(Match only)
1154 tgen
= get_topogen()
1156 tc_name
= request
.node
.name
1157 write_test_header(tc_name
)
1159 # Creating configuration from JSON
1160 reset_config_on_routers(tgen
)
1162 for adt
in ADDR_TYPES
:
1163 # Create Static routes
1168 "network": NETWORK
[adt
][0],
1170 "next_hop": NEXT_HOP
[adt
],
1175 result
= create_static_routes(tgen
, input_dict
)
1176 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
1180 # Api call to redistribute static routes
1188 {"redist_type": "static"},
1189 {"redist_type": "connected"},
1196 {"redist_type": "static"},
1197 {"redist_type": "connected"},
1205 result
= create_router_bgp(tgen
, topo
, input_dict_1
)
1206 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
1210 # Create ip prefix list
1216 {"seqid": 10, "network": "any", "action": "permit"}
1221 {"seqid": 100, "network": "any", "action": "permit"}
1227 result
= create_prefix_lists(tgen
, input_dict_2
)
1228 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
1233 for addr_type
in ADDR_TYPES
:
1237 "rmap_match_pf_1_{}".format(addr_type
): [
1249 result
= create_route_maps(tgen
, input_dict_3
)
1250 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
1254 # Configure neighbor for route map
1267 "name": "rmap_match_pf_1_ipv4",
1285 "name": "rmap_match_pf_1_ipv6",
1299 result
= create_router_bgp(tgen
, topo
, input_dict_4
)
1300 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
1304 # Create ip prefix list
1310 {"seqid": 10, "network": "any", "action": "permit"}
1315 {"seqid": 100, "network": "any", "action": "permit"}
1321 result
= create_prefix_lists(tgen
, input_dict_5
)
1322 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
1327 for addr_type
in ADDR_TYPES
:
1331 "rmap_match_pf_2_{}".format(addr_type
): [
1336 "prefix_lists": "pf_list_1_{}".format(addr_type
)
1344 result
= create_route_maps(tgen
, input_dict_6
)
1345 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
1349 # Configure neighbor for route map
1362 "name": "rmap_match_pf_2_ipv4",
1374 "name": "rmap_match_pf_2_ipv4",
1392 "name": "rmap_match_pf_2_ipv6",
1404 "name": "rmap_match_pf_2_ipv6",
1418 result
= create_router_bgp(tgen
, topo
, input_dict_7
)
1419 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
1423 for adt
in ADDR_TYPES
:
1424 # Verifying RIB routes
1425 static_routes
= [NETWORK
[adt
][0]]
1426 result
= verify_bgp_attributes(
1427 tgen
, adt
, "r3", static_routes
, "rmap_match_pf_1", input_dict_3
1429 assert result
is True, "Test case {} : Failed \n Error: {}".format(
1434 if __name__
== "__main__":
1435 args
= ["-s"] + sys
.argv
[1:]
1436 sys
.exit(pytest
.main(args
))