From 6cd0aae924a5b434f66ecce6d5ad1013e84f0e33 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Mon, 9 Jan 2023 16:29:25 +0100 Subject: [PATCH] topotests: add vpnv4 ecmp test This test ensures that BGP VRF instance is able to import ECMP paths, and is able to install 2 labelled routes accordingly. The test also ensures that the imported 172.31.0.10/32 prefix is selected and that the reason why the 172.31.0.10/32 prefix is selected is not 'Locally configured route'. Actually, imported routes do not figure out correctly the peer, and the reason is falsely mentioned as local. This test also uses IP ranges used for documentation and for testing. Signed-off-by: Philippe Guibert --- .../bgp_vpnv4_ebgp/r1/bgp_ipv4_routes.json | 49 ++++++++++ tests/topotests/bgp_vpnv4_ebgp/r1/bgpd.conf | 13 ++- .../bgp_vpnv4_ebgp/r1/ipv4_routes.json | 26 +++-- tests/topotests/bgp_vpnv4_ebgp/r1/zebra.conf | 4 +- .../bgp_vpnv4_ebgp/r2/bgp_ipv4_routes.json | 18 ++-- tests/topotests/bgp_vpnv4_ebgp/r2/bgpd.conf | 10 +- tests/topotests/bgp_vpnv4_ebgp/r2/zebra.conf | 4 +- .../bgp_vpnv4_ebgp/r3/bgp_ipv4_routes.json | 38 ++++++++ tests/topotests/bgp_vpnv4_ebgp/r3/bgpd.conf | 25 +++++ tests/topotests/bgp_vpnv4_ebgp/r3/zebra.conf | 7 ++ .../bgp_vpnv4_ebgp/test_bgp_vpnv4_ebgp.py | 94 +++++++++++++++---- 11 files changed, 238 insertions(+), 50 deletions(-) create mode 100644 tests/topotests/bgp_vpnv4_ebgp/r1/bgp_ipv4_routes.json create mode 100644 tests/topotests/bgp_vpnv4_ebgp/r3/bgp_ipv4_routes.json create mode 100644 tests/topotests/bgp_vpnv4_ebgp/r3/bgpd.conf create mode 100644 tests/topotests/bgp_vpnv4_ebgp/r3/zebra.conf diff --git a/tests/topotests/bgp_vpnv4_ebgp/r1/bgp_ipv4_routes.json b/tests/topotests/bgp_vpnv4_ebgp/r1/bgp_ipv4_routes.json new file mode 100644 index 0000000000..184ab312b6 --- /dev/null +++ b/tests/topotests/bgp_vpnv4_ebgp/r1/bgp_ipv4_routes.json @@ -0,0 +1,49 @@ +{ + "vrfName": "vrf1", + "localAS": 65500, + "routes": + { + "172.31.0.10/32": [ + { + "prefix": "172.31.0.10", + "prefixLen": 32, + "network": "172.31.0.10\/32", + "nhVrfName": "default", + "nexthops": [ + { + "ip": "192.168.0.3", + "afi": "ipv4", + "used": true + } + ] + }, + { + "prefix": "172.31.0.10", + "prefixLen": 32, + "network": "172.31.0.10\/32", + "nhVrfName": "default", + "nexthops": [ + { + "ip": "192.168.0.2", + "afi": "ipv4", + "used": true + } + ] + } + ], + "172.31.0.1/32": [ + { + "prefix": "172.31.0.1", + "prefixLen": 32, + "network": "172.31.0.1\/32", + "nexthops": [ + { + "ip": "0.0.0.0", + "afi": "ipv4", + "used": true + } + ] + } + ] + } +} diff --git a/tests/topotests/bgp_vpnv4_ebgp/r1/bgpd.conf b/tests/topotests/bgp_vpnv4_ebgp/r1/bgpd.conf index 2eebe5e6dd..0249279c65 100644 --- a/tests/topotests/bgp_vpnv4_ebgp/r1/bgpd.conf +++ b/tests/topotests/bgp_vpnv4_ebgp/r1/bgpd.conf @@ -1,16 +1,19 @@ router bgp 65500 - bgp router-id 1.1.1.1 + bgp router-id 192.0.2.1 no bgp ebgp-requires-policy - neighbor 10.125.0.2 remote-as 65501 + neighbor 192.168.0.2 remote-as 65501 + neighbor 192.168.0.3 remote-as 65501 address-family ipv4 unicast - no neighbor 10.125.0.2 activate + no neighbor 192.168.0.3 activate + no neighbor 192.168.0.2 activate exit-address-family address-family ipv4 vpn - neighbor 10.125.0.2 activate + neighbor 192.168.0.2 activate + neighbor 192.168.0.3 activate exit-address-family ! router bgp 65500 vrf vrf1 - bgp router-id 1.1.1.1 + bgp router-id 192.0.2.1 address-family ipv4 unicast redistribute connected label vpn export 101 diff --git a/tests/topotests/bgp_vpnv4_ebgp/r1/ipv4_routes.json b/tests/topotests/bgp_vpnv4_ebgp/r1/ipv4_routes.json index da7d281833..79b020af76 100644 --- a/tests/topotests/bgp_vpnv4_ebgp/r1/ipv4_routes.json +++ b/tests/topotests/bgp_vpnv4_ebgp/r1/ipv4_routes.json @@ -1,8 +1,8 @@ { - "10.200.0.0/24": [ + "172.31.0.10/32": [ { - "prefix": "10.200.0.0/24", - "prefixLen": 24, + "prefix": "172.31.0.10/32", + "prefixLen": 32, "protocol": "bgp", "vrfName": "vrf1", "selected": true, @@ -13,7 +13,19 @@ { "flags": 3, "fib": true, - "ip": "10.125.0.2", + "ip": "192.168.0.2", + "afi": "ipv4", + "interfaceName": "r1-eth0", + "vrf": "default", + "active": true, + "labels":[ + 102 + ] + }, + { + "flags": 3, + "fib": true, + "ip": "192.168.0.3", "afi": "ipv4", "interfaceName": "r1-eth0", "vrf": "default", @@ -25,10 +37,10 @@ ] } ], - "10.201.0.0/24": [ + "172.31.0.1/32": [ { - "prefix": "10.201.0.0/24", - "prefixLen": 24, + "prefix": "172.31.0.1/32", + "prefixLen": 32, "protocol": "connected", "vrfName": "vrf1", "selected": true, diff --git a/tests/topotests/bgp_vpnv4_ebgp/r1/zebra.conf b/tests/topotests/bgp_vpnv4_ebgp/r1/zebra.conf index e9ae4e9831..f626e448a7 100644 --- a/tests/topotests/bgp_vpnv4_ebgp/r1/zebra.conf +++ b/tests/topotests/bgp_vpnv4_ebgp/r1/zebra.conf @@ -1,7 +1,7 @@ log stdout interface r1-eth1 vrf vrf1 - ip address 10.201.0.1/24 + ip address 172.31.0.1/32 ! interface r1-eth0 - ip address 10.125.0.1/24 + ip address 192.168.0.1/24 ! diff --git a/tests/topotests/bgp_vpnv4_ebgp/r2/bgp_ipv4_routes.json b/tests/topotests/bgp_vpnv4_ebgp/r2/bgp_ipv4_routes.json index 19797dd561..1fc3a4b89c 100644 --- a/tests/topotests/bgp_vpnv4_ebgp/r2/bgp_ipv4_routes.json +++ b/tests/topotests/bgp_vpnv4_ebgp/r2/bgp_ipv4_routes.json @@ -3,28 +3,28 @@ "localAS": 65501, "routes": { - "10.201.0.0/24": [ + "172.31.0.1/32": [ { - "prefix": "10.201.0.0", - "prefixLen": 24, - "network": "10.201.0.0\/24", + "prefix": "172.31.0.1", + "prefixLen": 32, + "network": "172.31.0.1\/32", "nhVrfName": "default", "nexthops": [ { - "ip": "10.125.0.1", + "ip": "192.168.0.1", "afi": "ipv4", "used": true } ] } ], - "10.200.0.0/24": [ + "172.31.0.10/32": [ { "valid": true, "bestpath": true, - "prefix": "10.200.0.0", - "prefixLen": 24, - "network": "10.200.0.0\/24", + "prefix": "172.31.0.10", + "prefixLen": 32, + "network": "172.31.0.10\/32", "nexthops": [ { "ip": "0.0.0.0", diff --git a/tests/topotests/bgp_vpnv4_ebgp/r2/bgpd.conf b/tests/topotests/bgp_vpnv4_ebgp/r2/bgpd.conf index e38c99d69c..e873469d79 100644 --- a/tests/topotests/bgp_vpnv4_ebgp/r2/bgpd.conf +++ b/tests/topotests/bgp_vpnv4_ebgp/r2/bgpd.conf @@ -1,16 +1,16 @@ router bgp 65501 - bgp router-id 2.2.2.2 + bgp router-id 192.0.2.2 no bgp ebgp-requires-policy - neighbor 10.125.0.1 remote-as 65500 + neighbor 192.168.0.1 remote-as 65500 address-family ipv4 unicast - no neighbor 10.125.0.1 activate + no neighbor 192.168.0.1 activate exit-address-family address-family ipv4 vpn - neighbor 10.125.0.1 activate + neighbor 192.168.0.1 activate exit-address-family ! router bgp 65501 vrf vrf1 - bgp router-id 2.2.2.2 + bgp router-id 192.0.2.2 address-family ipv4 unicast redistribute connected label vpn export 102 diff --git a/tests/topotests/bgp_vpnv4_ebgp/r2/zebra.conf b/tests/topotests/bgp_vpnv4_ebgp/r2/zebra.conf index 6c433aef2b..bbc524065d 100644 --- a/tests/topotests/bgp_vpnv4_ebgp/r2/zebra.conf +++ b/tests/topotests/bgp_vpnv4_ebgp/r2/zebra.conf @@ -1,7 +1,7 @@ log stdout interface r2-eth1 vrf vrf1 - ip address 10.200.0.2/24 + ip address 172.31.0.10/32 ! interface r2-eth0 - ip address 10.125.0.2/24 + ip address 192.168.0.2/24 ! diff --git a/tests/topotests/bgp_vpnv4_ebgp/r3/bgp_ipv4_routes.json b/tests/topotests/bgp_vpnv4_ebgp/r3/bgp_ipv4_routes.json new file mode 100644 index 0000000000..19797dd561 --- /dev/null +++ b/tests/topotests/bgp_vpnv4_ebgp/r3/bgp_ipv4_routes.json @@ -0,0 +1,38 @@ +{ + "vrfName": "vrf1", + "localAS": 65501, + "routes": + { + "10.201.0.0/24": [ + { + "prefix": "10.201.0.0", + "prefixLen": 24, + "network": "10.201.0.0\/24", + "nhVrfName": "default", + "nexthops": [ + { + "ip": "10.125.0.1", + "afi": "ipv4", + "used": true + } + ] + } + ], + "10.200.0.0/24": [ + { + "valid": true, + "bestpath": true, + "prefix": "10.200.0.0", + "prefixLen": 24, + "network": "10.200.0.0\/24", + "nexthops": [ + { + "ip": "0.0.0.0", + "afi": "ipv4", + "used": true + } + ] + } + ] + } +} diff --git a/tests/topotests/bgp_vpnv4_ebgp/r3/bgpd.conf b/tests/topotests/bgp_vpnv4_ebgp/r3/bgpd.conf new file mode 100644 index 0000000000..a327638c69 --- /dev/null +++ b/tests/topotests/bgp_vpnv4_ebgp/r3/bgpd.conf @@ -0,0 +1,25 @@ +router bgp 65501 + bgp router-id 192.0.2.3 + no bgp ebgp-requires-policy + neighbor 192.168.0.1 remote-as 65500 + address-family ipv4 unicast + no neighbor 192.168.0.1 activate + exit-address-family + address-family ipv4 vpn + neighbor 192.168.0.1 activate + exit-address-family +! +router bgp 65502 vrf vrf1 + bgp router-id 192.0.2.3 + address-family ipv4 unicast + redistribute connected + label vpn export 102 + rd vpn export 444:3 + rt vpn both 52:100 + export vpn + import vpn + exit-address-family +! +interface r3-eth0 + mpls bgp forwarding +! diff --git a/tests/topotests/bgp_vpnv4_ebgp/r3/zebra.conf b/tests/topotests/bgp_vpnv4_ebgp/r3/zebra.conf new file mode 100644 index 0000000000..4412c04a2b --- /dev/null +++ b/tests/topotests/bgp_vpnv4_ebgp/r3/zebra.conf @@ -0,0 +1,7 @@ +log stdout +interface r3-eth1 vrf vrf1 + ip address 172.31.0.10/32 +! +interface r3-eth0 + ip address 192.168.0.3/24 +! diff --git a/tests/topotests/bgp_vpnv4_ebgp/test_bgp_vpnv4_ebgp.py b/tests/topotests/bgp_vpnv4_ebgp/test_bgp_vpnv4_ebgp.py index 342bad20ab..61e1163c18 100644 --- a/tests/topotests/bgp_vpnv4_ebgp/test_bgp_vpnv4_ebgp.py +++ b/tests/topotests/bgp_vpnv4_ebgp/test_bgp_vpnv4_ebgp.py @@ -40,10 +40,12 @@ def build_topo(tgen): # Create 2 routers. tgen.add_router("r1") tgen.add_router("r2") + tgen.add_router("r3") switch = tgen.add_switch("s1") switch.add_link(tgen.gears["r1"]) switch.add_link(tgen.gears["r2"]) + switch.add_link(tgen.gears["r3"]) switch = tgen.add_switch("s2") switch.add_link(tgen.gears["r1"]) @@ -51,27 +53,38 @@ def build_topo(tgen): switch = tgen.add_switch("s3") switch.add_link(tgen.gears["r2"]) + switch = tgen.add_switch("s4") + switch.add_link(tgen.gears["r3"]) + + def _populate_iface(): tgen = get_topogen() cmds_list = [ - 'ip link add vrf1 type vrf table 10', - 'echo 100000 > /proc/sys/net/mpls/platform_labels', - 'ip link set dev vrf1 up', - 'ip link set dev {0}-eth1 master vrf1', - 'echo 1 > /proc/sys/net/mpls/conf/{0}-eth0/input', + "ip link add vrf1 type vrf table 10", + "echo 100000 > /proc/sys/net/mpls/platform_labels", + "ip link set dev vrf1 up", + "ip link set dev {0}-eth1 master vrf1", + "echo 1 > /proc/sys/net/mpls/conf/{0}-eth0/input", ] for cmd in cmds_list: - input = cmd.format('r1', '1', '2') - logger.info('input: ' + cmd) - output = tgen.net['r1'].cmd(cmd.format('r1', '1', '2')) - logger.info('output: ' + output) + input = cmd.format("r1") + logger.info("input: " + cmd) + output = tgen.net["r1"].cmd(cmd.format("r1")) + logger.info("output: " + output) + + for cmd in cmds_list: + input = cmd.format("r2") + logger.info("input: " + cmd) + output = tgen.net["r2"].cmd(cmd.format("r2")) + logger.info("output: " + output) for cmd in cmds_list: - input = cmd.format('r2', '2', '1') - logger.info('input: ' + cmd) - output = tgen.net['r2'].cmd(cmd.format('r2', '2', '1')) - logger.info('output: ' + output) + input = cmd.format("r3") + logger.info("input: " + cmd) + output = tgen.net["r3"].cmd(cmd.format("r3")) + logger.info("output: " + output) + def setup_module(mod): "Sets up the pytest environment" @@ -109,13 +122,13 @@ def test_protocols_convergence(): if tgen.routers_have_failure(): pytest.skip(tgen.errors) - router = tgen.gears['r1'] + router = tgen.gears["r1"] logger.info("Dump some context for r1") router.vtysh_cmd("show bgp ipv4 vpn") router.vtysh_cmd("show bgp summary") router.vtysh_cmd("show bgp vrf vrf1 ipv4") router.vtysh_cmd("show running-config") - router = tgen.gears['r2'] + router = tgen.gears["r2"] logger.info("Dump some context for r2") router.vtysh_cmd("show bgp ipv4 vpn") router.vtysh_cmd("show bgp summary") @@ -124,11 +137,11 @@ def test_protocols_convergence(): # Check IPv4 routing tables on r1 logger.info("Checking IPv4 routes for convergence on r1") - router = tgen.gears['r1'] + router = tgen.gears["r1"] json_file = "{}/{}/ipv4_routes.json".format(CWD, router.name) if not os.path.isfile(json_file): logger.info("skipping file {}".format(json_file)) - assert 0, 'ipv4_routes.json file not found' + assert 0, "ipv4_routes.json file not found" return expected = json.loads(open(json_file).read()) @@ -142,12 +155,52 @@ def test_protocols_convergence(): assertmsg = '"{}" JSON output mismatches'.format(router.name) assert result is None, assertmsg + # Check BGP IPv4 routing tables on r1 + logger.info("Checking BGP IPv4 routes for convergence on r1") + router = tgen.gears["r1"] + json_file = "{}/{}/bgp_ipv4_routes.json".format(CWD, router.name) + if not os.path.isfile(json_file): + assert 0, "bgp_ipv4_routes.json file not found" + + expected = json.loads(open(json_file).read()) + test_func = partial( + topotest.router_json_cmp, + router, + "show bgp vrf vrf1 ipv4 json", + expected, + ) + _, result = topotest.run_and_expect(test_func, None, count=40, wait=2) + assertmsg = '"{}" JSON output mismatches'.format(router.name) + assert result is None, assertmsg + + # Check BGP IPv4 imported entry is not detected as local + # "selectionReason": "Locally configured route" + donna = tgen.gears["r1"].vtysh_cmd( + "show bgp vrf vrf1 ipv4 172.31.0.10/32 json", isjson=True + ) + routes = donna["paths"] + selectionReasonFound = False + for route in routes: + if "bestpath" not in route.keys(): + continue + if "selectionReason" not in route["bestpath"].keys(): + continue + + if "Locally configured route" == route["bestpath"]["selectionReason"]: + assert 0, "imported prefix has wrong reason detected" + + selectionReasonFound = True + + if not selectionReasonFound: + assertmsg = '"{}" imported prefix has wrong reason detected'.format(router.name) + assert False, assertmsg + # Check BGP IPv4 routing tables on r2 not installed logger.info("Checking BGP IPv4 routes for convergence on r2") - router = tgen.gears['r2'] + router = tgen.gears["r2"] json_file = "{}/{}/bgp_ipv4_routes.json".format(CWD, router.name) if not os.path.isfile(json_file): - assert 0, 'bgp_ipv4_routes.json file not found' + assert 0, "bgp_ipv4_routes.json file not found" expected = json.loads(open(json_file).read()) test_func = partial( @@ -159,7 +212,8 @@ def test_protocols_convergence(): _, result = topotest.run_and_expect(test_func, None, count=40, wait=2) assertmsg = '"{}" JSON output mismatches'.format(router.name) assert result is None, assertmsg - + + def test_memory_leak(): "Run the memory leak test and report results." tgen = get_topogen() -- 2.39.5