4 # Copyright (c) 2020 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
24 Following tests are covered to test BGP VRF Lite:
26 1. Verify BGP best path selection algorithm works fine when
27 routes are imported from ISR to default vrf and vice versa.
36 # Save the Current Working Directory to find configuration files.
37 CWD
= os
.path
.dirname(os
.path
.realpath(__file__
))
38 sys
.path
.append(os
.path
.join(CWD
, "../"))
39 sys
.path
.append(os
.path
.join(CWD
, "../lib/"))
41 # Required to instantiate the topology builder class.
43 # pylint: disable=C0413
44 # Import topogen and topotest helpers
45 from lib
.topogen
import Topogen
, get_topogen
46 from lib
.topotest
import version_cmp
48 from lib
.common_config
import (
57 get_frr_ipv6_linklocal
,
58 shutdown_bringup_interface
,
61 from lib
.topolog
import logger
63 verify_bgp_convergence
,
68 verify_best_path_as_per_bgp_attribute
70 from lib
.topojson
import build_config_from_json
73 pytestmark
= [pytest
.mark
.bgpd
, pytest
.mark
.staticd
]
76 NETWORK1_1
= {"ipv4": "11.11.11.1/32", "ipv6": "11:11::1/128"}
77 NETWORK1_2
= {"ipv4": "11.11.11.11/32", "ipv6": "11:11::11/128"}
78 NETWORK1_3
= {"ipv4": "10.10.10.10/32", "ipv6": "10:10::10/128"}
79 NETWORK1_4
= {"ipv4": "10.10.10.100/32", "ipv6": "10:10::100/128"}
81 NETWORK2_1
= {"ipv4": "22.22.22.2/32", "ipv6": "22:22::2/128"}
82 NETWORK2_2
= {"ipv4": "22.22.22.22/32", "ipv6": "22:22::22/128"}
83 NETWORK2_3
= {"ipv4": "20.20.20.20/32", "ipv6": "20:20::20/128"}
84 NETWORK2_4
= {"ipv4": "20.20.20.200/32", "ipv6": "20:20::200/128"}
86 NETWORK3_1
= {"ipv4": "30.30.30.3/32", "ipv6": "30:30::3/128"}
87 NETWORK3_2
= {"ipv4": "30.30.30.30/32", "ipv6": "30:30::30/128"}
88 NETWORK3_3
= {"ipv4": "50.50.50.5/32", "ipv6": "50:50::5/128"}
89 NETWORK3_4
= {"ipv4": "50.50.50.50/32", "ipv6": "50:50::50/128"}
91 NETWORK4_1
= {"ipv4": "40.40.40.4/32", "ipv6": "40:40::4/128"}
92 NETWORK4_2
= {"ipv4": "40.40.40.40/32", "ipv6": "40:40::40/128"}
93 NETWORK4_3
= {"ipv4": "50.50.50.5/32", "ipv6": "50:50::5/128"}
94 NETWORK4_4
= {"ipv4": "50.50.50.50/32", "ipv6": "50:50::50/128"}
95 NEXT_HOP_IP
= {"ipv4": "Null0", "ipv6": "Null0"}
97 "ipv4": "10.0.0.7/24",
98 "ipv6": "fd00:0:0:1::7/64",
99 "ipv4_mask": "255.255.255.0",
103 "ipv4": "10.0.0.16/24",
104 "ipv6": "fd00:0:0:3::5/64",
105 "ipv4_mask": "255.255.255.0",
108 PREFERRED_NEXT_HOP
= "global"
111 def setup_module(mod
):
113 Sets up the pytest environment
118 testsuite_run_time
= time
.asctime(time
.localtime(time
.time()))
119 logger
.info("Testsuite start time: {}".format(testsuite_run_time
))
120 logger
.info("=" * 40)
122 logger
.info("Running setup_module to create topology")
124 # This function initiates the topology build with Topogen...
125 json_file
= "{}/bgp_vrf_lite_best_path_topo1.json".format(CWD
)
126 tgen
= Topogen(json_file
, mod
.__name
__)
128 topo
= tgen
.json_topo
129 # ... and here it calls Mininet initialization functions.
131 # Starting topology, create tmp files which are loaded to routers
132 # to start deamons and then start routers
135 # Run these tests for kernel version 4.19 or above
136 if version_cmp(platform
.release(), "4.19") < 0:
138 "BGP vrf dynamic route leak tests will not run "
139 '(have kernel "{}", but it requires >= 4.19)'.format(platform
.release())
141 pytest
.skip(error_msg
)
143 # Creating configuration from JSON
144 build_config_from_json(tgen
, topo
)
146 global BGP_CONVERGENCE
148 ADDR_TYPES
= check_address_types()
150 BGP_CONVERGENCE
= verify_bgp_convergence(tgen
, topo
)
151 assert BGP_CONVERGENCE
is True, "setup_module : Failed \n Error: {}".format(
155 logger
.info("Running setup_module() done")
158 def teardown_module():
159 """Teardown the pytest environment"""
161 logger
.info("Running teardown_module to delete topology")
165 # Stop toplogy and Remove tmp files
169 "Testsuite end time: {}".format(time
.asctime(time
.localtime(time
.time())))
171 logger
.info("=" * 40)
174 #####################################################
178 #####################################################
181 def disable_route_map_to_prefer_global_next_hop(tgen
, topo
):
183 This API is to remove prefer global route-map applied on neighbors
187 * `tgen` : Topogen object
188 * `topo` : Input JSON data
196 logger
.info("Remove prefer-global rmap applied on neighbors")
212 "name": "rmap_global",
236 "name": "rmap_global",
260 "name": "rmap_global",
289 "name": "rmap_global",
313 "name": "rmap_global",
337 "name": "rmap_global",
365 "name": "rmap_global",
389 "name": "rmap_global",
417 "name": "rmap_global",
441 "name": "rmap_global",
458 result
= create_router_bgp(tgen
, topo
, input_dict
)
459 assert result
is True, "Testcase :Failed \n Error: {}".format(result
)
464 def test_bgp_best_path_with_dynamic_import_p0(request
):
466 1.5.6. Verify BGP best path selection algorithm works fine when
467 routes are imported from ISR to default vrf and vice versa.
471 tc_name
= request
.node
.name
472 write_test_header(tc_name
)
473 build_config_from_json(tgen
, topo
)
475 if tgen
.routers_have_failure():
476 check_router_status(tgen
)
478 for addr_type
in ADDR_TYPES
:
481 "Redistribute configured static routes into BGP process" " on R1/R2 and R3"
485 DUT
= ["r1", "r2", "r3", "r4"]
486 VRFS
= ["ISR", "ISR", "default", "default"]
487 AS_NUM
= [100, 100, 300, 400]
489 for dut
, vrf
, as_num
in zip(DUT
, VRFS
, AS_NUM
):
490 temp
= {dut
: {"bgp": []}}
491 input_dict_1
.update(temp
)
493 temp
[dut
]["bgp"].append(
499 "unicast": {"redistribute": [{"redist_type": "static"}]}
505 result
= create_router_bgp(tgen
, topo
, input_dict_1
)
506 assert result
is True, "Testcase {} :Failed \n Error: {}".format(
510 for addr_type
in ADDR_TYPES
:
512 step("Import from default vrf into vrf ISR on R1 and R2 as below")
516 VRFS
= ["ISR", "ISR"]
519 for dut
, vrf
, as_num
in zip(DUT
, VRFS
, AS_NUM
):
520 temp
= {dut
: {"bgp": []}}
521 input_dict_vrf
.update(temp
)
523 temp
[dut
]["bgp"].append(
528 addr_type
: {"unicast": {"import": {"vrf": "default"}}}
533 result
= create_router_bgp(tgen
, topo
, input_dict_vrf
)
534 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
538 input_dict_default
= {}
540 VRFS
= ["default", "default"]
543 for dut
, vrf
, as_num
in zip(DUT
, VRFS
, AS_NUM
):
544 temp
= {dut
: {"bgp": []}}
545 input_dict_default
.update(temp
)
547 temp
[dut
]["bgp"].append(
552 addr_type
: {"unicast": {"import": {"vrf": "ISR"}}}
557 result
= create_router_bgp(tgen
, topo
, input_dict_default
)
558 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
563 "Verify ECMP/Next-hop/Imported routes Vs Locally originated "
564 "routes/eBGP routes vs iBGP routes --already covered in almost"
568 for addr_type
in ADDR_TYPES
:
570 step("Verify Pre-emption")
573 "r3": {"static_routes": [{"network": [NETWORK3_3
[addr_type
]]}]}
576 intf_r3_r1
= topo
["routers"]["r3"]["links"]["r1-link1"]["interface"]
577 intf_r4_r1
= topo
["routers"]["r4"]["links"]["r1-link1"]["interface"]
579 if addr_type
== "ipv6" and "link_local" in PREFERRED_NEXT_HOP
:
580 nh_r3_r1
= get_frr_ipv6_linklocal(tgen
, "r3", intf
=intf_r3_r1
)
581 nh_r4_r1
= get_frr_ipv6_linklocal(tgen
, "r4", intf
=intf_r4_r1
)
583 nh_r3_r1
= topo
["routers"]["r3"]["links"]["r1-link1"][addr_type
].split("/")[
586 nh_r4_r1
= topo
["routers"]["r4"]["links"]["r1-link1"][addr_type
].split("/")[
590 result
= verify_bgp_rib(
591 tgen
, addr_type
, "r1", input_routes_r3
, next_hop
=[nh_r4_r1
]
593 assert result
is True, "Testcase {} : Failed \n Error {}".format(
597 step("Shutdown interface connected to r1 from r4:")
598 shutdown_bringup_interface(tgen
, "r4", intf_r4_r1
, False)
600 for addr_type
in ADDR_TYPES
:
603 "r3": {"static_routes": [{"network": [NETWORK3_3
[addr_type
]]}]}
606 intf_r3_r1
= topo
["routers"]["r3"]["links"]["r1-link1"]["interface"]
607 intf_r4_r1
= topo
["routers"]["r4"]["links"]["r1-link1"]["interface"]
609 if addr_type
== "ipv6" and "link_local" in PREFERRED_NEXT_HOP
:
610 nh_r3_r1
= get_frr_ipv6_linklocal(tgen
, "r3", intf
=intf_r3_r1
)
611 nh_r4_r1
= get_frr_ipv6_linklocal(tgen
, "r4", intf
=intf_r4_r1
)
613 nh_r3_r1
= topo
["routers"]["r3"]["links"]["r1-link1"][addr_type
].split("/")[
616 nh_r4_r1
= topo
["routers"]["r4"]["links"]["r1-link1"][addr_type
].split("/")[
620 step("Verify next-hop is changed")
621 result
= verify_bgp_rib(
622 tgen
, addr_type
, "r1", input_routes_r3
, next_hop
=[nh_r3_r1
]
624 assert result
is True, "Testcase {} : Failed \n Error {}".format(
628 step("Bringup interface connected to r1 from r4:")
629 shutdown_bringup_interface(tgen
, "r4", intf_r4_r1
, True)
631 for addr_type
in ADDR_TYPES
:
634 "r3": {"static_routes": [{"network": [NETWORK3_3
[addr_type
]]}]}
637 intf_r3_r1
= topo
["routers"]["r3"]["links"]["r1-link1"]["interface"]
638 intf_r4_r1
= topo
["routers"]["r4"]["links"]["r1-link1"]["interface"]
640 if addr_type
== "ipv6" and "link_local" in PREFERRED_NEXT_HOP
:
641 nh_r3_r1
= get_frr_ipv6_linklocal(tgen
, "r3", intf
=intf_r3_r1
)
642 nh_r4_r1
= get_frr_ipv6_linklocal(tgen
, "r4", intf
=intf_r4_r1
)
644 nh_r3_r1
= topo
["routers"]["r3"]["links"]["r1-link1"][addr_type
].split("/")[
647 nh_r4_r1
= topo
["routers"]["r4"]["links"]["r1-link1"][addr_type
].split("/")[
651 step("Verify next-hop is not chnaged aftr shutdown:")
652 result
= verify_bgp_rib(
653 tgen
, addr_type
, "r1", input_routes_r3
, next_hop
=[nh_r3_r1
]
655 assert result
is True, "Testcase {} : Failed \n Error {}".format(
659 step("Active-Standby scenario(as-path prepend and Local pref)")
661 for addr_type
in ADDR_TYPES
:
663 step("Create prefix-list")
669 "pf_ls_{}".format(addr_type
): [
672 "network": NETWORK3_4
[addr_type
],
680 result
= create_prefix_lists(tgen
, input_dict_pf
)
681 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
685 for addr_type
in ADDR_TYPES
:
687 step("Create route-map to match prefix-list and set localpref 500")
692 "rmap_PATH1_{}".format(addr_type
): [
698 "prefix_lists": "pf_ls_{}".format(addr_type
)
701 "set": {"locPrf": 500},
708 result
= create_route_maps(tgen
, input_dict_rm
)
709 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
713 step("Create route-map to match prefix-list and set localpref 600")
718 "rmap_PATH2_{}".format(addr_type
): [
724 "prefix_lists": "pf_ls_{}".format(addr_type
)
727 "set": {"locPrf": 600},
734 result
= create_route_maps(tgen
, input_dict_rm
)
735 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
753 "name": "rmap_PATH1_{}".format(
767 "name": "rmap_PATH2_{}".format(
785 result
= create_router_bgp(tgen
, topo
, input_dict_rma
)
786 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
793 for addr_type
in ADDR_TYPES
:
795 step("Verify bestpath is installed as per highest localpref")
800 {"network": [NETWORK3_3
[addr_type
], NETWORK3_4
[addr_type
]]}
805 result
= verify_best_path_as_per_bgp_attribute(
806 tgen
, addr_type
, dut
, input_routes_r3
, attribute
808 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
812 for addr_type
in ADDR_TYPES
:
814 step("Create route-map to match prefix-list and set localpref 700")
819 "rmap_PATH1_{}".format(addr_type
): [
825 "prefix_lists": "pf_ls_{}".format(addr_type
)
828 "set": {"locPrf": 700},
835 result
= create_route_maps(tgen
, input_dict_rm
)
836 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
840 for addr_type
in ADDR_TYPES
:
842 step("Verify bestpath is changed as per highest localpref")
847 {"network": [NETWORK3_3
[addr_type
], NETWORK3_4
[addr_type
]]}
852 result
= verify_best_path_as_per_bgp_attribute(
853 tgen
, addr_type
, dut
, input_routes_r3
, attribute
855 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
859 for addr_type
in ADDR_TYPES
:
861 step("Create route-map to match prefix-list and set as-path prepend")
866 "rmap_PATH2_{}".format(addr_type
): [
872 "prefix_lists": "pf_ls_{}".format(addr_type
)
877 "path": {"as_num": "111", "as_action": "prepend"},
885 result
= create_route_maps(tgen
, input_dict_rm
)
886 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
892 for addr_type
in ADDR_TYPES
:
894 step("Verify bestpath is changed as per shortest as-path")
899 {"network": [NETWORK3_3
[addr_type
], NETWORK3_4
[addr_type
]]}
904 result
= verify_best_path_as_per_bgp_attribute(
905 tgen
, addr_type
, dut
, input_routes_r3
, attribute
907 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
911 write_test_footer(tc_name
)
914 if __name__
== "__main__":
915 args
= ["-s"] + sys
.argv
[1:]
916 sys
.exit(pytest
.main(args
))