4 # Copyright (c) 2021 by VMware, Inc. ("VMware")
5 # Used Copyright (c) 2018 by Network Device Education Foundation, Inc.
6 # ("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 """RFC5549 Automation."""
30 from copy
import deepcopy
32 from re
import search
as re_search
34 # Save the Current Working Directory to find configuration files.
35 CWD
= os
.path
.dirname(os
.path
.realpath(__file__
))
36 sys
.path
.append(os
.path
.join(CWD
, "../"))
37 sys
.path
.append(os
.path
.join(CWD
, "../../"))
39 # pylint: disable=C0413
40 # Import topogen and topotest helpers
41 from lib
.topogen
import Topogen
, get_topogen
42 from mininet
.topo
import Topo
44 from lib
.common_config
import (
47 get_frr_ipv6_linklocal
,
53 reset_config_on_routers
,
56 create_interfaces_cfg
,
58 from lib
.topolog
import logger
61 verify_bgp_convergence
,
65 from lib
.topojson
import build_topo_from_json
, build_config_from_json
69 # Reading the data from JSON File for topology creation
70 jsonFile
= "{}/rfc5549_ebgp_ibgp_nbr.json".format(CWD
)
72 with
open(jsonFile
, "r") as topoJson
:
73 topo
= json
.load(topoJson
)
75 assert False, "Could not read file {}".format(jsonFile
)
86 "ipv6": ["1::1/128", "1::2/128", "1::3/128", "1::4/128", "1::5/128"],
88 MASK
= {"ipv4": "32", "ipv6": "128"}
90 "ipv4": ["10.0.0.1", "10.0.1.1", "10.0.2.1", "10.0.3.1", "10.0.4.1"],
91 "ipv6": ["Null0", "Null0", "Null0", "Null0", "Null0"],
94 NETWORK_CMD_IP
= "1.0.1.17/32"
95 ADDR_TYPES
= check_address_types()
97 Please view in a fixed-width font such as Courier.
106 +----+ 5links +----+ 8links +--+-+ +----+
107 |R0 +----------+ R1 +------------+ R2 | ipv6 nbr |R3 |
108 | +----------+ +------------+ +-------------+ |
109 +----+ +----+ ipv6 nbr +----+ +----+
113 1. Verify Ipv4 route next hop is changed when advertised using
114 next hop -self command
115 2. Verify IPv4 route advertised to peer when IPv6 BGP session established
117 3. Verify IPv4 routes received with IPv6 nexthop are getting advertised
118 to another IBGP peer without changing the nexthop
119 4. Verify IPv4 routes advertised with correct nexthop when nexthop
120 unchange is configure on EBGP peers
124 class CreateTopo(Topo
):
126 Test topology builder.
128 * `Topo`: Topology object
131 def build(self
, *_args
, **_opts
):
132 """Build function."""
133 tgen
= get_topogen(self
)
135 # Building topology from json file
136 build_topo_from_json(tgen
, topo
)
139 def setup_module(mod
):
140 """Set up the pytest environment."""
143 testsuite_run_time
= time
.asctime(time
.localtime(time
.time()))
144 logger
.info("Testsuite start time: {}".format(testsuite_run_time
))
145 logger
.info("=" * 40)
147 logger
.info("Running setup_module to create topology")
149 # This function initiates the topology build with Topogen...
150 tgen
= Topogen(CreateTopo
, mod
.__name
__)
152 # Starting topology, create tmp files which are loaded to routers
153 # to start deamons and then start routers
156 # Creating configuration from JSON
157 build_config_from_json(tgen
, topo
)
158 # Don't run this test if we have any failure.
159 if tgen
.routers_have_failure():
160 pytest
.skip(tgen
.errors
)
162 BGP_CONVERGENCE
= verify_bgp_convergence(tgen
, topo
)
163 assert BGP_CONVERGENCE
is True, "setup_module :Failed \n Error:" " {}".format(
166 logger
.info("Running setup_module() done")
169 def teardown_module():
171 Teardown the pytest environment.
175 logger
.info("Running teardown_module to delete topology")
179 # Stop toplogy and Remove tmp files
183 def get_llip(onrouter
, intf
):
185 API to get the link local ipv6 address of a perticular interface
189 * `fromnode`: Source node
190 * `tonode` : interface for which link local ip needs to be returned.
194 result = get_llip('r1', 'r2-link0')
198 1) link local ipv6 address from the interface.
199 2) errormsg - when link local ip not found.
202 intf
= topo
["routers"][onrouter
]["links"][intf
]["interface"]
203 llip
= get_frr_ipv6_linklocal(tgen
, onrouter
, intf
)
205 logger
.info("llip ipv6 address to be set as NH is %s", llip
)
210 def get_glipv6(onrouter
, intf
):
212 API to get the global ipv6 address of a perticular interface
216 * `onrouter`: Source node
217 * `intf` : interface for which link local ip needs to be returned.
221 result = get_glipv6('r1', 'r2-link0')
225 1) global ipv6 address from the interface.
226 2) errormsg - when link local ip not found.
228 glipv6
= (topo
["routers"][onrouter
]["links"][intf
]["ipv6"]).split("/")[0]
230 logger
.info("Global ipv6 address to be set as NH is %s", glipv6
)
235 # ##################################
236 # Test cases start here.
237 # ##################################
238 def test_ibgp_to_ibgp_p1(request
):
241 Test Capability extended nexthop.
243 Verify IPv4 routes received with IPv6 nexthop are getting advertised to
244 another IBGP peer without changing the nexthop
246 tc_name
= request
.node
.name
247 write_test_header(tc_name
)
249 # Don't run this test if we have any failure.
250 if tgen
.routers_have_failure():
251 pytest
.skip(tgen
.errors
)
252 reset_config_on_routers(tgen
)
254 topo23
= deepcopy(topo
)
255 build_config_from_json(tgen
, topo23
, save_bkup
=False)
257 step("Configure IPv6 EBGP session between R1 and R2 with " "global IPv6 address")
258 step("Configure IPv6 IBGP session betn R2 & R3 using IPv6 global address")
259 step("Enable capability extended-nexthop on both the IPv6 BGP peers")
260 step("Activate same IPv6 nbr from IPv4 unicast family")
261 step("Enable cap ext nh on r1 and r2 and activate in ipv4 addr family")
262 step("Verify bgp convergence as ipv6 nbr is enabled on ipv4 addr family.")
264 # verify bgp convergence as ipv6 nbr is enabled on ipv4 addr family.
265 bgp_convergence
= verify_bgp_convergence(tgen
, topo23
)
266 assert bgp_convergence
is True, "Testcase :Failed \n Error:" " {}".format(
270 step(" Configure 5 IPv4 static" " routes on R1, Nexthop as different links of R0")
271 for rte
in range(0, NO_OF_RTES
):
272 # Create Static routes
277 "network": NETWORK
["ipv4"][rte
],
279 "next_hop": NEXT_HOP
["ipv4"][rte
],
284 result
= create_static_routes(tgen
, input_dict
)
285 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
290 "Advertise static routes from IPv4 unicast family and IPv6 "
291 "unicast family respectively from R1 using red static cmd "
292 "Advertise loopback from IPv4 unicast family using network command "
296 configure_bgp_on_r1
= {
302 "redistribute": [{"redist_type": "static"}],
303 "advertise_networks": [
304 {"network": NETWORK_CMD_IP
, "no_of_network": 1}
312 result
= create_router_bgp(tgen
, topo23
, configure_bgp_on_r1
)
313 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
315 "IPv4 routes advertised using static and network command are "
316 " received on R2 BGP and routing table , "
317 "verify using show ip bgp, show ip route for IPv4 routes ."
320 gllip
= get_llip("r1", "r2-link0")
321 assert gllip
is not None, "Testcase {} : Failed \n Error: {}".format(
327 # verify the routes with nh as ext_nh
328 verify_nh_for_static_rtes
= {
332 "network": NETWORK
["ipv4"][0],
333 "no_of_ip": NO_OF_RTES
,
339 bgp_rib
= verify_bgp_rib(
340 tgen
, "ipv4", dut
, verify_nh_for_static_rtes
, next_hop
=gllip
342 assert bgp_rib
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, bgp_rib
)
344 tgen
, "ipv4", dut
, verify_nh_for_static_rtes
, next_hop
=gllip
, protocol
=protocol
346 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
348 configure_bgp_on_r2
= {
359 "capability": "extended-nexthop",
370 result
= create_router_bgp(tgen
, topo
, configure_bgp_on_r2
)
371 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
373 configure_bgp_on_r3
= {
384 "capability": "extended-nexthop",
395 result
= create_router_bgp(tgen
, topo
, configure_bgp_on_r3
)
396 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
399 "IPv4 routes installed on R3 with global address without "
400 "changing the nexthop ( nexthop should IPv6 link local which is"
403 gipv6
= get_glipv6("r1", "r2-link0")
405 verify_nh_for_static_rtes
= {
409 "network": NETWORK
["ipv4"][0],
410 "no_of_ip": NO_OF_RTES
,
416 bgp_rib
= verify_bgp_rib(
417 tgen
, "ipv4", dut
, verify_nh_for_static_rtes
, next_hop
=gipv6
419 assert bgp_rib
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, bgp_rib
)
420 write_test_footer(tc_name
)
423 def test_ext_nh_cap_red_static_network_ibgp_peer_p1(request
):
426 Test Extended capability next hop, with ibgp peer.
428 Verify IPv4 routes advertise using "redistribute static" and
429 "network command" are received on EBGP peer with IPv6 nexthop
431 tc_name
= request
.node
.name
432 write_test_header(tc_name
)
434 # Don't run this test if we have any failure.
435 if tgen
.routers_have_failure():
436 pytest
.skip(tgen
.errors
)
437 reset_config_on_routers(tgen
)
439 " Configure IPv6 EBGP session between R1 & R2 with global IPv6 address"
440 " Enable capability extended-nexthop on the nbr from both the routers"
441 " Activate same IPv6 nbr from IPv4 unicast family"
443 configure_bgp_on_r2
= {
446 "default_ipv4_unicast": "False",
454 "capability": "extended-nexthop",
456 "next_hop_self": True,
468 result
= create_router_bgp(tgen
, topo
, configure_bgp_on_r2
)
469 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
471 configure_bgp_on_r3
= {
481 "capability": "extended-nexthop",
493 result
= create_router_bgp(tgen
, topo
, configure_bgp_on_r3
)
494 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
495 for rte
in range(0, NO_OF_RTES
):
496 # Create Static routes
501 "network": NETWORK
["ipv4"][rte
],
503 "next_hop": NEXT_HOP
["ipv4"][rte
],
508 result
= create_static_routes(tgen
, input_dict
)
509 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
513 configure_bgp_on_r1
= {
516 "default_ipv4_unicast": "False",
520 "redistribute": [{"redist_type": "static"}],
521 "advertise_networks": [
522 {"network": NETWORK_CMD_IP
, "no_of_network": 1}
530 result
= create_router_bgp(tgen
, topo
, configure_bgp_on_r1
)
531 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
533 gllip
= get_llip("r1", "r2-link0")
534 assert gllip
is not None, "Testcase {} : Failed \n Error: {}".format(
540 verify_nh_for_static_rtes
= {
544 "network": NETWORK
["ipv4"][0],
545 "no_of_ip": NO_OF_RTES
,
552 tgen
, "ipv4", dut
, verify_nh_for_static_rtes
, next_hop
=gllip
, protocol
=protocol
554 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
556 verify_nh_for_nw_cmd_rtes
= {
560 "network": NETWORK_CMD_IP
,
569 tgen
, "ipv4", dut
, verify_nh_for_nw_cmd_rtes
, next_hop
=gllip
, protocol
=protocol
571 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
573 gllip
= get_glipv6("r2", "r3")
574 assert gllip
is not None, "Testcase {} : Failed \n Error: {}".format(
580 # verify the routes with nh as ext_nh
581 verify_nh_for_static_rtes
= {
585 "network": NETWORK
["ipv4"][0],
586 "no_of_ip": NO_OF_RTES
,
593 tgen
, "ipv4", dut
, verify_nh_for_static_rtes
, next_hop
=gllip
, protocol
=protocol
595 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
596 verify_nh_for_nw_cmd_rtes
= {
600 "network": NETWORK_CMD_IP
,
607 bgp_rib
= verify_bgp_rib(
608 tgen
, "ipv4", dut
, verify_nh_for_nw_cmd_rtes
, next_hop
=gllip
610 assert bgp_rib
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, bgp_rib
)
612 tgen
, "ipv4", dut
, verify_nh_for_nw_cmd_rtes
, next_hop
=gllip
, protocol
=protocol
614 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
616 write_test_footer(tc_name
)
619 def test_bgp_peer_group_p1(request
):
621 Test extended capability next hop with peer groups.
623 Verify IPv4 routes received with IPv6 nexthop are getting advertised to
624 another IBGP peer without changing the nexthop
626 tc_name
= request
.node
.name
627 write_test_header(tc_name
)
629 # Don't run this test if we have any failure.
630 if tgen
.routers_have_failure():
631 pytest
.skip(tgen
.errors
)
632 reset_config_on_routers(tgen
)
634 topo1
= deepcopy(topo
)
635 step("Configure IPv6 EBGP session between R1 and R2 with " "global IPv6 address")
636 step("Configure IPv6 IBGP session betn R2 & R3 using IPv6 global address")
637 step("Enable capability extended-nexthop on both the IPv6 BGP peers")
638 step("Activate same IPv6 nbr from IPv4 unicast family")
639 step("Enable cap ext nh on r1 and r2 and activate in ipv4 addr family")
640 configure_bgp_on_r1
= {
643 "default_ipv4_unicast": "False",
645 "rfc5549": {"capability": "extended-nexthop", "remote-as": "200"}
650 result
= create_router_bgp(tgen
, topo
, configure_bgp_on_r1
)
651 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
652 configure_bgp_on_r1
= {
663 "capability": "extended-nexthop",
664 "peer-group": "rfc5549",
675 result
= create_router_bgp(tgen
, topo
, configure_bgp_on_r1
)
676 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
677 configure_bgp_on_r2
= {
680 "default_ipv4_unicast": "False",
682 "rfc5549": {"capability": "extended-nexthop", "remote-as": "100"}
687 result
= create_router_bgp(tgen
, topo
, configure_bgp_on_r2
)
688 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
689 configure_bgp_on_r2
= {
699 "capability": "extended-nexthop",
701 "peer-group": "rfc5549",
705 "r3": {"dest_link": {"r2": {}}},
713 result
= create_router_bgp(tgen
, topo
, configure_bgp_on_r2
)
714 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
716 configure_bgp_on_r3
= {
720 "ipv4": {"unicast": {"neighbor": {"r2": {"dest_link": {"r3": {}}}}}}
725 result
= create_router_bgp(tgen
, topo
, configure_bgp_on_r3
)
726 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
728 step("Verify bgp convergence as ipv6 nbr is enabled on ipv4 addr family.")
729 bgp_convergence
= verify_bgp_convergence(tgen
, topo
)
730 assert bgp_convergence
is True, "Testcase :Failed \n Error:" " {}".format(
734 step(" Configure 2 IPv4 static" " routes on R1, Nexthop as different links of R0")
735 for rte
in range(0, NO_OF_RTES
):
736 # Create Static routes
741 "network": NETWORK
["ipv4"][rte
],
743 "next_hop": NEXT_HOP
["ipv4"][rte
],
748 result
= create_static_routes(tgen
, input_dict
)
749 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
754 "Advertise static routes from IPv4 unicast family and IPv6 "
755 "unicast family respectively from R1 using red static cmd "
756 "Advertise loopback from IPv4 unicast family using network command "
760 configure_bgp_on_r1
= {
766 "redistribute": [{"redist_type": "static"}],
767 "advertise_networks": [
768 {"network": NETWORK_CMD_IP
, "no_of_network": 1}
776 result
= create_router_bgp(tgen
, topo
, configure_bgp_on_r1
)
777 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
779 "IPv4 routes advertised using static and network command are "
780 " received on R2 BGP and routing table , "
781 "verify using show ip bgp, show ip route for IPv4 routes ."
784 gllip
= get_llip("r1", "r2-link0")
785 assert gllip
is not None, "Testcase {} : Failed \n Error: {}".format(
791 verify_nh_for_static_rtes
= {
795 "network": NETWORK
["ipv4"][0],
796 "no_of_ip": NO_OF_RTES
,
802 bgp_rib
= verify_bgp_rib(
803 tgen
, "ipv4", dut
, verify_nh_for_static_rtes
, next_hop
=gllip
805 assert bgp_rib
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, bgp_rib
)
807 tgen
, "ipv4", dut
, verify_nh_for_static_rtes
, next_hop
=gllip
, protocol
=protocol
809 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
811 step("Enable cap ext nh on r1 and r2 and activate in ipv4 addr family")
812 configure_bgp_on_r1
= {
815 "default_ipv4_unicast": "False",
817 "rfc5549": {"capability": "extended-nexthop", "remote-as": "200"}
822 result
= create_router_bgp(tgen
, topo
, configure_bgp_on_r1
)
823 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
824 configure_bgp_on_r1
= {
835 "capability": "extended-nexthop",
836 "peer-group": "rfc5549",
847 result
= create_router_bgp(tgen
, topo
, configure_bgp_on_r1
)
848 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
849 configure_bgp_on_r2
= {
852 "default_ipv4_unicast": "False",
854 "rfc5549": {"capability": "extended-nexthop", "remote-as": "100"}
859 result
= create_router_bgp(tgen
, topo
, configure_bgp_on_r2
)
860 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
861 configure_bgp_on_r2
= {
871 "capability": "extended-nexthop",
873 "peer-group": "rfc5549",
877 "r3": {"dest_link": {"r2": {}}},
885 result
= create_router_bgp(tgen
, topo
, configure_bgp_on_r2
)
886 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
888 configure_bgp_on_r3
= {
892 "ipv4": {"unicast": {"neighbor": {"r2": {"dest_link": {"r3": {}}}}}}
897 result
= create_router_bgp(tgen
, topo
, configure_bgp_on_r3
)
898 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
900 step("Verify bgp convergence as ipv6 nbr is enabled on ipv4 addr family.")
901 bgp_convergence
= verify_bgp_convergence(tgen
, topo
)
902 assert bgp_convergence
is True, "Testcase :Failed \n Error:" " {}".format(
906 step(" Configure 2 IPv4 static" " routes on R1, Nexthop as different links of R0")
907 for rte
in range(0, NO_OF_RTES
):
912 "network": NETWORK
["ipv4"][rte
],
914 "next_hop": NEXT_HOP
["ipv4"][rte
],
919 result
= create_static_routes(tgen
, input_dict
)
920 assert result
is True, "Testcase {} : Failed \n Error: {}".format(
925 "Advertise static routes from IPv4 unicast family and IPv6 "
926 "unicast family respectively from R1 using red static cmd "
927 "Advertise loopback from IPv4 unicast family using network command "
931 configure_bgp_on_r1
= {
937 "redistribute": [{"redist_type": "static"}],
938 "advertise_networks": [
939 {"network": NETWORK_CMD_IP
, "no_of_network": 1}
947 result
= create_router_bgp(tgen
, topo
, configure_bgp_on_r1
)
948 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
950 "IPv4 routes advertised using static and network command are "
951 " received on R2 BGP and routing table , "
952 "verify using show ip bgp, show ip route for IPv4 routes ."
955 gllip
= get_llip("r1", "r2-link0")
956 assert gllip
is not None, "Testcase {} : Failed \n Error: {}".format(
962 verify_nh_for_static_rtes
= {
966 "network": NETWORK
["ipv4"][0],
967 "no_of_ip": NO_OF_RTES
,
973 bgp_rib
= verify_bgp_rib(
974 tgen
, "ipv4", dut
, verify_nh_for_static_rtes
, next_hop
=gllip
976 assert bgp_rib
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, bgp_rib
)
978 tgen
, "ipv4", dut
, verify_nh_for_static_rtes
, next_hop
=gllip
, protocol
=protocol
980 assert result
is True, "Testcase {} : Failed \n Error: {}".format(tc_name
, result
)
982 write_test_footer(tc_name
)
985 if __name__
== "__main__":
986 args
= ["-s"] + sys
.argv
[1:]
987 sys
.exit(pytest
.main(args
))