2 # SPDX-License-Identifier: ISC
5 # Copyright (c) 2020 by VMware, Inc. ("VMware")
6 # Used Copyright (c) 2018 by Network Device Education Foundation,
7 # Inc. ("NetDEF") in this file.
11 Following tests are covered to test BGP VRF Lite:
13 1. Verify BGP best path selection algorithm works fine when
14 routes are imported from ISR to default vrf and vice versa.
23 # Save the Current Working Directory to find configuration files.
24 CWD
= os
.path
.dirname(os
.path
.realpath(__file__
))
25 sys
.path
.append(os
.path
.join(CWD
, "../"))
26 sys
.path
.append(os
.path
.join(CWD
, "../lib/"))
28 # Required to instantiate the topology builder class.
30 # pylint: disable=C0413
31 # Import topogen and topotest helpers
32 from lib
.topogen
import Topogen
, get_topogen
33 from lib
.topotest
import version_cmp
35 from lib
.common_config
import (
44 get_frr_ipv6_linklocal
,
45 shutdown_bringup_interface
,
48 from lib
.topolog
import logger
50 verify_bgp_convergence
,
55 verify_best_path_as_per_bgp_attribute
57 from lib
.topojson
import build_config_from_json
60 pytestmark
= [pytest
.mark
.bgpd
, pytest
.mark
.staticd
]
63 NETWORK1_1
= {"ipv4": "11.11.11.1/32", "ipv6": "11:11::1/128"}
64 NETWORK1_2
= {"ipv4": "11.11.11.11/32", "ipv6": "11:11::11/128"}
65 NETWORK1_3
= {"ipv4": "10.10.10.10/32", "ipv6": "10:10::10/128"}
66 NETWORK1_4
= {"ipv4": "10.10.10.100/32", "ipv6": "10:10::100/128"}
68 NETWORK2_1
= {"ipv4": "22.22.22.2/32", "ipv6": "22:22::2/128"}
69 NETWORK2_2
= {"ipv4": "22.22.22.22/32", "ipv6": "22:22::22/128"}
70 NETWORK2_3
= {"ipv4": "20.20.20.20/32", "ipv6": "20:20::20/128"}
71 NETWORK2_4
= {"ipv4": "20.20.20.200/32", "ipv6": "20:20::200/128"}
73 NETWORK3_1
= {"ipv4": "30.30.30.3/32", "ipv6": "30:30::3/128"}
74 NETWORK3_2
= {"ipv4": "30.30.30.30/32", "ipv6": "30:30::30/128"}
75 NETWORK3_3
= {"ipv4": "50.50.50.5/32", "ipv6": "50:50::5/128"}
76 NETWORK3_4
= {"ipv4": "50.50.50.50/32", "ipv6": "50:50::50/128"}
78 NETWORK4_1
= {"ipv4": "40.40.40.4/32", "ipv6": "40:40::4/128"}
79 NETWORK4_2
= {"ipv4": "40.40.40.40/32", "ipv6": "40:40::40/128"}
80 NETWORK4_3
= {"ipv4": "50.50.50.5/32", "ipv6": "50:50::5/128"}
81 NETWORK4_4
= {"ipv4": "50.50.50.50/32", "ipv6": "50:50::50/128"}
82 NEXT_HOP_IP
= {"ipv4": "Null0", "ipv6": "Null0"}
84 "ipv4": "10.0.0.7/24",
85 "ipv6": "fd00:0:0:1::7/64",
86 "ipv4_mask": "255.255.255.0",
90 "ipv4": "10.0.0.16/24",
91 "ipv6": "fd00:0:0:3::5/64",
92 "ipv4_mask": "255.255.255.0",
95 PREFERRED_NEXT_HOP
= "global"
98 def setup_module(mod
):
100 Sets up the pytest environment
105 testsuite_run_time
= time
.asctime(time
.localtime(time
.time()))
106 logger
.info("Testsuite start time: {}".format(testsuite_run_time
))
107 logger
.info("=" * 40)
109 logger
.info("Running setup_module to create topology")
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
__)
115 topo
= tgen
.json_topo
116 # ... and here it calls Mininet initialization functions.
118 # Starting topology, create tmp files which are loaded to routers
119 # to start daemons and then start routers
122 # Run these tests for kernel version 4.19 or above
123 if version_cmp(platform
.release(), "4.19") < 0:
125 "BGP vrf dynamic route leak tests will not run "
126 '(have kernel "{}", but it requires >= 4.19)'.format(platform
.release())
128 pytest
.skip(error_msg
)
130 # Creating configuration from JSON
131 build_config_from_json(tgen
, topo
)
133 global BGP_CONVERGENCE
135 ADDR_TYPES
= check_address_types()
137 BGP_CONVERGENCE
= verify_bgp_convergence(tgen
, topo
)
138 assert BGP_CONVERGENCE
is True, "setup_module : Failed \n Error: {}".format(
142 logger
.info("Running setup_module() done")
145 def teardown_module():
146 """Teardown the pytest environment"""
148 logger
.info("Running teardown_module to delete topology")
152 # Stop toplogy and Remove tmp files
156 "Testsuite end time: {}".format(time
.asctime(time
.localtime(time
.time())))
158 logger
.info("=" * 40)
161 #####################################################
165 #####################################################
168 def disable_route_map_to_prefer_global_next_hop(tgen
, topo
):
170 This API is to remove prefer global route-map applied on neighbors
174 * `tgen` : Topogen object
175 * `topo` : Input JSON data
183 logger
.info("Remove prefer-global rmap applied on neighbors")
199 "name": "rmap_global",
223 "name": "rmap_global",
247 "name": "rmap_global",
276 "name": "rmap_global",
300 "name": "rmap_global",
324 "name": "rmap_global",
352 "name": "rmap_global",
376 "name": "rmap_global",
404 "name": "rmap_global",
428 "name": "rmap_global",
445 result
= create_router_bgp(tgen
, topo
, input_dict
)
446 assert result
is True, "Testcase :Failed \n Error: {}".format(result
)
451 def test_bgp_best_path_with_dynamic_import_p0(request
):
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.
458 tc_name
= request
.node
.name
459 write_test_header(tc_name
)
460 build_config_from_json(tgen
, topo
)
462 if tgen
.routers_have_failure():
463 check_router_status(tgen
)
465 for addr_type
in ADDR_TYPES
:
468 "Redistribute configured static routes into BGP process" " on R1/R2 and R3"
472 DUT
= ["r1", "r2", "r3", "r4"]
473 VRFS
= ["ISR", "ISR", "default", "default"]
474 AS_NUM
= [100, 100, 300, 400]
476 for dut
, vrf
, as_num
in zip(DUT
, VRFS
, AS_NUM
):
477 temp
= {dut
: {"bgp": []}}
478 input_dict_1
.update(temp
)
480 temp
[dut
]["bgp"].append(
486 "unicast": {"redistribute": [{"redist_type": "static"}]}
492 result
= create_router_bgp(tgen
, topo
, input_dict_1
)
493 assert result
is True, "Testcase {} :Failed \n Error: {}".format(
497 for addr_type
in ADDR_TYPES
:
499 step("Import from default vrf into vrf ISR on R1 and R2 as below")
503 VRFS
= ["ISR", "ISR"]
506 for dut
, vrf
, as_num
in zip(DUT
, VRFS
, AS_NUM
):
507 temp
= {dut
: {"bgp": []}}
508 input_dict_vrf
.update(temp
)
510 temp
[dut
]["bgp"].append(
515 addr_type
: {"unicast": {"import": {"vrf": "default"}}}
520 result
= create_router_bgp(tgen
, topo
, input_dict_vrf
)
521 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
525 input_dict_default
= {}
527 VRFS
= ["default", "default"]
530 for dut
, vrf
, as_num
in zip(DUT
, VRFS
, AS_NUM
):
531 temp
= {dut
: {"bgp": []}}
532 input_dict_default
.update(temp
)
534 temp
[dut
]["bgp"].append(
539 addr_type
: {"unicast": {"import": {"vrf": "ISR"}}}
544 result
= create_router_bgp(tgen
, topo
, input_dict_default
)
545 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
550 "Verify ECMP/Next-hop/Imported routes Vs Locally originated "
551 "routes/eBGP routes vs iBGP routes --already covered in almost"
555 for addr_type
in ADDR_TYPES
:
557 step("Verify Pre-emption")
560 "r3": {"static_routes": [{"network": [NETWORK3_3
[addr_type
]]}]}
563 intf_r3_r1
= topo
["routers"]["r3"]["links"]["r1-link1"]["interface"]
564 intf_r4_r1
= topo
["routers"]["r4"]["links"]["r1-link1"]["interface"]
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
)
570 nh_r3_r1
= topo
["routers"]["r3"]["links"]["r1-link1"][addr_type
].split("/")[
573 nh_r4_r1
= topo
["routers"]["r4"]["links"]["r1-link1"][addr_type
].split("/")[
577 result
= verify_bgp_rib(
578 tgen
, addr_type
, "r1", input_routes_r3
, next_hop
=[nh_r4_r1
]
580 assert result
is True, "Testcase {} : Failed \n Error {}".format(
584 step("Shutdown interface connected to r1 from r4:")
585 shutdown_bringup_interface(tgen
, "r4", intf_r4_r1
, False)
587 for addr_type
in ADDR_TYPES
:
590 "r3": {"static_routes": [{"network": [NETWORK3_3
[addr_type
]]}]}
593 intf_r3_r1
= topo
["routers"]["r3"]["links"]["r1-link1"]["interface"]
594 intf_r4_r1
= topo
["routers"]["r4"]["links"]["r1-link1"]["interface"]
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
)
600 nh_r3_r1
= topo
["routers"]["r3"]["links"]["r1-link1"][addr_type
].split("/")[
603 nh_r4_r1
= topo
["routers"]["r4"]["links"]["r1-link1"][addr_type
].split("/")[
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
]
611 assert result
is True, "Testcase {} : Failed \n Error {}".format(
615 step("Bringup interface connected to r1 from r4:")
616 shutdown_bringup_interface(tgen
, "r4", intf_r4_r1
, True)
618 for addr_type
in ADDR_TYPES
:
621 "r3": {"static_routes": [{"network": [NETWORK3_3
[addr_type
]]}]}
624 intf_r3_r1
= topo
["routers"]["r3"]["links"]["r1-link1"]["interface"]
625 intf_r4_r1
= topo
["routers"]["r4"]["links"]["r1-link1"]["interface"]
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
)
631 nh_r3_r1
= topo
["routers"]["r3"]["links"]["r1-link1"][addr_type
].split("/")[
634 nh_r4_r1
= topo
["routers"]["r4"]["links"]["r1-link1"][addr_type
].split("/")[
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
]
642 assert result
is True, "Testcase {} : Failed \n Error {}".format(
646 step("Active-Standby scenario(as-path prepend and Local pref)")
648 for addr_type
in ADDR_TYPES
:
650 step("Create prefix-list")
656 "pf_ls_{}".format(addr_type
): [
659 "network": NETWORK3_4
[addr_type
],
667 result
= create_prefix_lists(tgen
, input_dict_pf
)
668 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
672 for addr_type
in ADDR_TYPES
:
674 step("Create route-map to match prefix-list and set localpref 500")
679 "rmap_PATH1_{}".format(addr_type
): [
685 "prefix_lists": "pf_ls_{}".format(addr_type
)
688 "set": {"locPrf": 500},
695 result
= create_route_maps(tgen
, input_dict_rm
)
696 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
700 step("Create route-map to match prefix-list and set localpref 600")
705 "rmap_PATH2_{}".format(addr_type
): [
711 "prefix_lists": "pf_ls_{}".format(addr_type
)
714 "set": {"locPrf": 600},
721 result
= create_route_maps(tgen
, input_dict_rm
)
722 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
740 "name": "rmap_PATH1_{}".format(
754 "name": "rmap_PATH2_{}".format(
772 result
= create_router_bgp(tgen
, topo
, input_dict_rma
)
773 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
780 for addr_type
in ADDR_TYPES
:
782 step("Verify bestpath is installed as per highest localpref")
787 {"network": [NETWORK3_3
[addr_type
], NETWORK3_4
[addr_type
]]}
792 result
= verify_best_path_as_per_bgp_attribute(
793 tgen
, addr_type
, dut
, input_routes_r3
, attribute
795 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
799 for addr_type
in ADDR_TYPES
:
801 step("Create route-map to match prefix-list and set localpref 700")
806 "rmap_PATH1_{}".format(addr_type
): [
812 "prefix_lists": "pf_ls_{}".format(addr_type
)
815 "set": {"locPrf": 700},
822 result
= create_route_maps(tgen
, input_dict_rm
)
823 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
827 for addr_type
in ADDR_TYPES
:
829 step("Verify bestpath is changed as per highest localpref")
834 {"network": [NETWORK3_3
[addr_type
], NETWORK3_4
[addr_type
]]}
839 result
= verify_best_path_as_per_bgp_attribute(
840 tgen
, addr_type
, dut
, input_routes_r3
, attribute
842 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
846 for addr_type
in ADDR_TYPES
:
848 step("Create route-map to match prefix-list and set as-path prepend")
853 "rmap_PATH2_{}".format(addr_type
): [
859 "prefix_lists": "pf_ls_{}".format(addr_type
)
864 "path": {"as_num": "111", "as_action": "prepend"},
872 result
= create_route_maps(tgen
, input_dict_rm
)
873 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
879 for addr_type
in ADDR_TYPES
:
881 step("Verify bestpath is changed as per shortest as-path")
886 {"network": [NETWORK3_3
[addr_type
], NETWORK3_4
[addr_type
]]}
891 result
= verify_best_path_as_per_bgp_attribute(
892 tgen
, addr_type
, dut
, input_routes_r3
, attribute
894 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
898 write_test_footer(tc_name
)
901 if __name__
== "__main__":
902 args
= ["-s"] + sys
.argv
[1:]
903 sys
.exit(pytest
.main(args
))