Merge pull request #17370 from louis-6wind/fix-vpn-leaking

bgpd: fix for the validity and the presence of prefixes in the BGP VPN table.
This commit is contained in:
Russ White 2025-02-11 08:41:03 -05:00 committed by GitHub
commit 5518a8c916
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 871 additions and 136 deletions

View File

@ -1052,6 +1052,7 @@ static bool leak_update_nexthop_valid(struct bgp *to_bgp, struct bgp_dest *bn,
struct bgp_path_info *bpi_ultimate; struct bgp_path_info *bpi_ultimate;
struct bgp *bgp_nexthop; struct bgp *bgp_nexthop;
struct bgp_table *table; struct bgp_table *table;
struct interface *ifp;
bool nh_valid; bool nh_valid;
bpi_ultimate = bgp_get_imported_bpi_ultimate(source_bpi); bpi_ultimate = bgp_get_imported_bpi_ultimate(source_bpi);
@ -1062,6 +1063,15 @@ static bool leak_update_nexthop_valid(struct bgp *to_bgp, struct bgp_dest *bn,
else else
bgp_nexthop = bgp_orig; bgp_nexthop = bgp_orig;
/* The nexthop is invalid if its VRF does not exist */
if (bgp_nexthop->vrf_id == VRF_UNKNOWN)
return false;
/* The nexthop is invalid if its VRF interface is down*/
ifp = if_get_vrf_loopback(bgp_nexthop->vrf_id);
if (ifp && !if_is_up(ifp))
return false;
/* /*
* No nexthop tracking for redistributed routes, for * No nexthop tracking for redistributed routes, for
* EVPN-imported routes that get leaked, or for routes * EVPN-imported routes that get leaked, or for routes
@ -1126,8 +1136,8 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
struct bgp_path_info *bpi; struct bgp_path_info *bpi;
struct bgp_path_info *new; struct bgp_path_info *new;
struct bgp_path_info_extra *extra; struct bgp_path_info_extra *extra;
struct bgp_path_info *parent = source_bpi;
struct bgp_labels bgp_labels = {}; struct bgp_labels bgp_labels = {};
struct bgp *bgp_nexthop;
bool labelssame; bool labelssame;
uint8_t i; uint8_t i;
@ -1159,8 +1169,7 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
* match parent * match parent
*/ */
for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next) { for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next) {
if (bpi->extra && bpi->extra->vrfleak && if (bpi->extra && bpi->extra->vrfleak && bpi->extra->vrfleak->parent == source_bpi)
bpi->extra->vrfleak->parent == parent)
break; break;
} }
@ -1174,6 +1183,16 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
labelssame = bgp_path_info_labels_same(bpi, bgp_labels.label, labelssame = bgp_path_info_labels_same(bpi, bgp_labels.label,
bgp_labels.num_labels); bgp_labels.num_labels);
bgp_nexthop = bpi->extra->vrfleak->bgp_orig ?: bgp_orig;
if (bgp_nexthop->vrf_id == VRF_UNKNOWN) {
if (debug) {
zlog_debug("%s: ->%s(s_flags: 0x%x b_flags: 0x%x): %pFX: Found route, origin VRF does not exist, not leaking",
__func__, to_bgp->name_pretty, source_bpi->flags,
bpi->flags, p);
}
return NULL;
}
if (CHECK_FLAG(source_bpi->flags, BGP_PATH_REMOVED) if (CHECK_FLAG(source_bpi->flags, BGP_PATH_REMOVED)
&& CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) { && CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
if (debug) { if (debug) {
@ -1185,9 +1204,11 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
return NULL; return NULL;
} }
if (attrhash_cmp(bpi->attr, new_attr) && labelssame if (attrhash_cmp(bpi->attr, new_attr) && labelssame &&
&& !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) { !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED) &&
leak_update_nexthop_valid(to_bgp, bn, new_attr, afi, safi, source_bpi, bpi,
bgp_orig, p,
debug) == !!CHECK_FLAG(bpi->flags, BGP_PATH_VALID)) {
bgp_attr_unintern(&new_attr); bgp_attr_unintern(&new_attr);
if (debug) if (debug)
zlog_debug( zlog_debug(
@ -1274,6 +1295,14 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
return NULL; return NULL;
} }
if (bgp_orig->vrf_id == VRF_UNKNOWN) {
if (debug) {
zlog_debug("%s: ->%s(s_flags: 0x%x): %pFX: New route, origin VRF does not exist, not leaking",
__func__, to_bgp->name_pretty, source_bpi->flags, p);
}
return NULL;
}
new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_IMPORTED, 0, new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_IMPORTED, 0,
to_bgp->peer_self, new_attr, bn); to_bgp->peer_self, new_attr, bn);
@ -1297,9 +1326,8 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
if (bgp_labels.num_labels) if (bgp_labels.num_labels)
new->extra->labels = bgp_labels_intern(&bgp_labels); new->extra->labels = bgp_labels_intern(&bgp_labels);
new->extra->vrfleak->parent = bgp_path_info_lock(parent); new->extra->vrfleak->parent = bgp_path_info_lock(source_bpi);
bgp_dest_lock_node( bgp_dest_lock_node((struct bgp_dest *)source_bpi->net);
(struct bgp_dest *)parent->net);
new->extra->vrfleak->bgp_orig = bgp_lock(bgp_orig); new->extra->vrfleak->bgp_orig = bgp_lock(bgp_orig);

View File

@ -78,6 +78,13 @@ def setup_module(mod):
"tcpdump -nni r1-eth0 -s 0 -w {} &".format(pcap_file), stdout=None "tcpdump -nni r1-eth0 -s 0 -w {} &".format(pcap_file), stdout=None
) )
tgen.net["r2"].cmd(
"""
ip link add vrf1 type vrf table 10
ip link set vrf1 up
"""
)
for _, (rname, router) in enumerate(tgen.routers().items(), 1): for _, (rname, router) in enumerate(tgen.routers().items(), 1):
logger.info("Loading router %s" % rname) logger.info("Loading router %s" % rname)
router.load_frr_config( router.load_frr_config(

View File

@ -1,3 +1,7 @@
vrf DONNA
ip route 172.16.3.0/24 10.0.0.254
exit-vrf
!
int dummy0 int dummy0
ip address 10.0.4.1/24 ip address 10.0.4.1/24
no shut no shut
@ -28,6 +32,9 @@ ip router-id 10.0.4.1
! !
router bgp 99 router bgp 99
no bgp ebgp-requires-policy no bgp ebgp-requires-policy
! 10.0.4.254 peer session will not be established
! it is there just to activate the ipv4 vpn table
neighbor 10.0.4.254 remote-as external
address-family ipv4 unicast address-family ipv4 unicast
redistribute connected redistribute connected
rd vpn export 10.0.4.1:1 rd vpn export 10.0.4.1:1
@ -36,11 +43,14 @@ router bgp 99
export vpn export vpn
import vpn import vpn
! !
address-family ipv4 vpn
neighbor 10.0.4.254 activate
! !
router bgp 99 vrf DONNA router bgp 99 vrf DONNA
no bgp ebgp-requires-policy no bgp ebgp-requires-policy
address-family ipv4 unicast address-family ipv4 unicast
redistribute connected redistribute connected
network 172.16.3.0/24
label vpn export 101 label vpn export 101
rd vpn export 10.0.4.1:1 rd vpn export 10.0.4.1:1
rt vpn export 10.0.4.1:101 rt vpn export 10.0.4.1:101

View File

@ -0,0 +1,155 @@
{
"routerId": "10.0.4.1",
"localAS": 99,
"routes": {
"routeDistinguishers": {
"10.0.4.1:1": {
"10.0.0.0/24": [
{
"valid": true,
"pathFrom": "external",
"path": "",
"origin": "incomplete",
"announceNexthopSelf": true,
"nhVrfName": "DONNA",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
],
"10.0.1.0/24": [
{
"valid": true,
"pathFrom": "external",
"path": "",
"origin": "incomplete",
"announceNexthopSelf": true,
"nhVrfName": "EVA",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
],
"10.0.2.0/24": [
{
"valid": true,
"pathFrom": "external",
"path": "",
"origin": "incomplete",
"announceNexthopSelf": true,
"nhVrfName": "DONNA",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
],
"10.0.3.0/24": [
{
"valid": true,
"pathFrom": "external",
"path": "",
"origin": "incomplete",
"announceNexthopSelf": true,
"nhVrfName": "EVA",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
],
"10.0.4.0/24": [
{
"valid": true,
"pathFrom": "external",
"path": "",
"origin": "incomplete",
"announceNexthopSelf": true,
"nhVrfName": "default",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
],
"172.16.3.0/24": [
{
"valid": true,
"pathFrom": "external",
"path": "",
"origin": "IGP",
"announceNexthopSelf": true,
"nhVrfName": "DONNA",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
],
"172.16.3.0/24": [
{
"valid": true,
"pathFrom": "external",
"path": "",
"origin": "IGP",
"announceNexthopSelf": true,
"nhVrfName": "DONNA",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
],
"172.16.101.0/24": [
{
"valid": null,
"pathFrom": "external",
"path": "",
"origin": "IGP",
"announceNexthopSelf": true,
"nhVrfName": "ZITA",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
]
}
}
}
}

View File

@ -0,0 +1,103 @@
{
"routerId": "10.0.4.1",
"localAS": 99,
"routes": {
"routeDistinguishers": {
"10.0.4.1:1": {
"10.0.0.0/24": [
{
"valid": true,
"pathFrom": "external",
"path": "",
"origin": "incomplete",
"announceNexthopSelf": true,
"nhVrfName": "DONNA",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
],
"10.0.1.0/24": [
{
"valid": true,
"pathFrom": "external",
"path": "",
"origin": "incomplete",
"announceNexthopSelf": true,
"nhVrfName": "EVA",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
],
"10.0.2.0/24": [
{
"valid": true,
"pathFrom": "external",
"path": "",
"origin": "incomplete",
"announceNexthopSelf": true,
"nhVrfName": "DONNA",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
],
"10.0.3.0/24": [
{
"valid": true,
"pathFrom": "external",
"path": "",
"origin": "incomplete",
"announceNexthopSelf": true,
"nhVrfName": "EVA",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
],
"10.0.4.0/24": [
{
"valid": true,
"pathFrom": "external",
"path": "",
"origin": "incomplete",
"announceNexthopSelf": true,
"nhVrfName": "default",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
],
"172.16.3.0/24": null,
"172.16.101.0/24": null
}
}
}
}

View File

@ -0,0 +1,120 @@
{
"routerId": "10.0.4.1",
"localAS": 99,
"routes": {
"routeDistinguishers": {
"10.0.4.1:1": {
"10.0.0.0/24": [
{
"valid": true,
"pathFrom": "external",
"path": "",
"origin": "incomplete",
"announceNexthopSelf": true,
"nhVrfName": "DONNA",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
],
"10.0.1.0/24": [
{
"valid": null,
"pathFrom": "external",
"path": "",
"origin": "incomplete",
"announceNexthopSelf": true,
"nhVrfName": "EVA",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
],
"10.0.2.0/24": [
{
"valid": true,
"pathFrom": "external",
"path": "",
"origin": "incomplete",
"announceNexthopSelf": true,
"nhVrfName": "DONNA",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
],
"10.0.3.0/24": [
{
"valid": null,
"pathFrom": "external",
"path": "",
"origin": "incomplete",
"announceNexthopSelf": true,
"nhVrfName": "EVA",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
],
"10.0.4.0/24": [
{
"valid": true,
"pathFrom": "external",
"path": "",
"origin": "incomplete",
"announceNexthopSelf": true,
"nhVrfName": "default",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
],
"172.16.3.0/24": [
{
"valid": true,
"pathFrom": "external",
"path": "",
"origin": "IGP",
"announceNexthopSelf": true,
"nhVrfName": "DONNA",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
],
"172.16.101.0/24": null
}
}
}
}

View File

@ -0,0 +1,120 @@
{
"routerId": "10.0.4.1",
"localAS": 99,
"routes": {
"routeDistinguishers": {
"10.0.4.1:1": {
"10.0.0.0/24": [
{
"valid": true,
"pathFrom": "external",
"path": "",
"origin": "incomplete",
"announceNexthopSelf": true,
"nhVrfName": "DONNA",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
],
"10.0.1.0/24": [
{
"valid": true,
"pathFrom": "external",
"path": "",
"origin": "incomplete",
"announceNexthopSelf": true,
"nhVrfName": "EVA",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
],
"10.0.2.0/24": [
{
"valid": true,
"pathFrom": "external",
"path": "",
"origin": "incomplete",
"announceNexthopSelf": true,
"nhVrfName": "DONNA",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
],
"10.0.3.0/24": [
{
"valid": true,
"pathFrom": "external",
"path": "",
"origin": "incomplete",
"announceNexthopSelf": true,
"nhVrfName": "EVA",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
],
"10.0.4.0/24": [
{
"valid": true,
"pathFrom": "external",
"path": "",
"origin": "incomplete",
"announceNexthopSelf": true,
"nhVrfName": "default",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
],
"172.16.3.0/24": [
{
"valid": true,
"pathFrom": "external",
"path": "",
"origin": "IGP",
"announceNexthopSelf": true,
"nhVrfName": "DONNA",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
],
"172.16.101.0/24": null
}
}
}
}

View File

@ -0,0 +1,137 @@
{
"routerId": "10.0.4.1",
"localAS": 99,
"routes": {
"routeDistinguishers": {
"10.0.4.1:1": {
"10.0.0.0/24": [
{
"valid": true,
"pathFrom": "external",
"path": "",
"origin": "incomplete",
"announceNexthopSelf": true,
"nhVrfName": "DONNA",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
],
"10.0.1.0/24": [
{
"valid": true,
"pathFrom": "external",
"path": "",
"origin": "incomplete",
"announceNexthopSelf": true,
"nhVrfName": "EVA",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
],
"10.0.2.0/24": [
{
"valid": true,
"pathFrom": "external",
"path": "",
"origin": "incomplete",
"announceNexthopSelf": true,
"nhVrfName": "DONNA",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
],
"10.0.3.0/24": [
{
"valid": true,
"pathFrom": "external",
"path": "",
"origin": "incomplete",
"announceNexthopSelf": true,
"nhVrfName": "EVA",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
],
"10.0.4.0/24": [
{
"valid": true,
"pathFrom": "external",
"path": "",
"origin": "incomplete",
"announceNexthopSelf": true,
"nhVrfName": "default",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
],
"172.16.3.0/24": [
{
"valid": true,
"pathFrom": "external",
"path": "",
"origin": "IGP",
"announceNexthopSelf": true,
"nhVrfName": "DONNA",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
],
"172.16.101.0/24": [
{
"valid": true,
"pathFrom": "external",
"path": "",
"origin": "IGP",
"announceNexthopSelf": true,
"nhVrfName": "ZITA",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
]
}
}
}
}

View File

@ -13,6 +13,7 @@
Test basic VPNv4 route leaking Test basic VPNv4 route leaking
""" """
import json
import os import os
import sys import sys
from functools import partial from functools import partial
@ -60,6 +61,22 @@ def teardown_module(mod):
tgen.stop_topology() tgen.stop_topology()
def test_bgp_convergence():
tgen = get_topogen()
# Don't run this test if we have any failure.
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
r1 = tgen.gears["r1"]
json_file = "{}/{}/show_bgp_ipv4_vpn_init.json".format(CWD, r1.name)
expect = json.loads(open(json_file).read())
test_func = partial(topotest.router_json_cmp, r1, "show bgp ipv4 vpn json", expect)
result, diff = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
assert result, "BGP IPv4 VPN table check failed:\n{}".format(diff)
def test_vrf_route_leak_donna(): def test_vrf_route_leak_donna():
logger.info("Ensure that routes are leaked back and forth") logger.info("Ensure that routes are leaked back and forth")
tgen = get_topogen() tgen = get_topogen()
@ -119,20 +136,20 @@ def test_vrf_route_leak_donna():
], ],
}, },
], ],
"172.16.101.0/24": [ "172.16.3.0/24": [
{ {
"protocol": "bgp", "protocol": "static",
"selected": None, "selected": True,
"nexthops": [ "nexthops": [
{ {
"fib": None, "fib": True,
"interfaceName": "unknown", "interfaceName": "dummy1",
"vrf": "Unknown", "active": True,
"active": None, }
},
], ],
}, },
], ],
"172.16.101.0/24": None,
} }
test_func = partial( test_func = partial(
@ -191,20 +208,21 @@ def test_vrf_route_leak_eva():
"protocol": "connected", "protocol": "connected",
} }
], ],
"172.16.101.0/24": [ "172.16.3.0/24": [
{ {
"protocol": "bgp", "protocol": "bgp",
"selected": None, "selected": True,
"nexthops": [ "nexthops": [
{ {
"fib": None, "fib": True,
"interfaceName": "unknown", "interfaceName": "DONNA",
"vrf": "Unknown", "vrf": "DONNA",
"active": None, "active": True,
}, }
], ],
}, },
], ],
"172.16.101.0/24": None,
} }
test_func = partial( test_func = partial(
@ -258,6 +276,20 @@ def test_vrf_route_leak_default():
"protocol": "connected", "protocol": "connected",
} }
], ],
"172.16.3.0/24": [
{
"protocol": "bgp",
"selected": True,
"nexthops": [
{
"fib": True,
"interfaceName": "DONNA",
"vrf": "DONNA",
"active": True,
}
],
},
],
} }
test_func = partial(topotest.router_json_cmp, r1, "show ip route json", expect) test_func = partial(topotest.router_json_cmp, r1, "show ip route json", expect)
@ -298,34 +330,8 @@ interface EVA
# Test DONNA VRF. # Test DONNA VRF.
expect = { expect = {
"10.0.1.0/24": [ "10.0.1.0/24": None,
{ "10.0.3.0/24": None,
"protocol": "bgp",
"selected": None,
"nexthops": [
{
"fib": None,
"interfaceName": "EVA",
"vrf": "EVA",
"active": None,
},
],
},
],
"10.0.3.0/24": [
{
"protocol": "bgp",
"selected": None,
"nexthops": [
{
"fib": None,
"interfaceName": "EVA",
"vrf": "EVA",
"active": None,
},
],
},
],
} }
test_func = partial( test_func = partial(
@ -349,6 +355,14 @@ interface EVA
result, diff = topotest.run_and_expect(test_func, None, count=60, wait=0.5) result, diff = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
assert result, "BGP VRF DONNA check failed:\n{}".format(diff) assert result, "BGP VRF DONNA check failed:\n{}".format(diff)
# check BGP IPv4 VPN table
json_file = "{}/{}/show_bgp_ipv4_vpn_eva_down.json".format(CWD, r1.name)
expect = json.loads(open(json_file).read())
test_func = partial(topotest.router_json_cmp, r1, "show bgp ipv4 vpn json", expect)
result, diff = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
assert result, "BGP IPv4 VPN table check failed:\n{}".format(diff)
def test_vrf_route_leak_donna_after_eva_up(): def test_vrf_route_leak_donna_after_eva_up():
logger.info("Ensure that route states change after EVA interface goes up") logger.info("Ensure that route states change after EVA interface goes up")
@ -404,6 +418,14 @@ interface EVA
result, diff = topotest.run_and_expect(test_func, None, count=60, wait=0.5) result, diff = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
assert result, "BGP VRF DONNA check failed:\n{}".format(diff) assert result, "BGP VRF DONNA check failed:\n{}".format(diff)
# check BGP IPv4 VPN table
json_file = "{}/{}/show_bgp_ipv4_vpn_init.json".format(CWD, r1.name)
expect = json.loads(open(json_file).read())
test_func = partial(topotest.router_json_cmp, r1, "show bgp ipv4 vpn json", expect)
result, diff = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
assert result, "BGP IPv4 VPN table check failed:\n{}".format(diff)
def test_vrf_route_leak_donna_add_vrf_zita(): def test_vrf_route_leak_donna_add_vrf_zita():
logger.info("Add VRF ZITA and ensure that the route from VRF ZITA is updated") logger.info("Add VRF ZITA and ensure that the route from VRF ZITA is updated")
@ -417,20 +439,7 @@ def test_vrf_route_leak_donna_add_vrf_zita():
# Test DONNA VRF. # Test DONNA VRF.
expect = { expect = {
"172.16.101.0/24": [ "172.16.101.0/24": None,
{
"protocol": "bgp",
"selected": None,
"nexthops": [
{
"fib": None,
"interfaceName": "ZITA",
"vrf": "ZITA",
"active": None,
},
],
},
],
} }
test_func = partial( test_func = partial(
@ -439,6 +448,14 @@ def test_vrf_route_leak_donna_add_vrf_zita():
result, diff = topotest.run_and_expect(test_func, None, count=60, wait=0.5) result, diff = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
assert result, "BGP VRF DONNA check failed:\n{}".format(diff) assert result, "BGP VRF DONNA check failed:\n{}".format(diff)
# check BGP IPv4 VPN table
json_file = "{}/{}/show_bgp_ipv4_vpn_add_zita.json".format(CWD, r1.name)
expect = json.loads(open(json_file).read())
test_func = partial(topotest.router_json_cmp, r1, "show bgp ipv4 vpn json", expect)
result, diff = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
assert result, "BGP IPv4 VPN table check failed:\n{}".format(diff)
def test_vrf_route_leak_donna_set_zita_up(): def test_vrf_route_leak_donna_set_zita_up():
logger.info("Set VRF ZITA up and ensure that the route from VRF ZITA is updated") logger.info("Set VRF ZITA up and ensure that the route from VRF ZITA is updated")
@ -480,6 +497,14 @@ interface ZITA
result, diff = topotest.run_and_expect(test_func, None, count=60, wait=0.5) result, diff = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
assert result, "BGP VRF DONNA check failed:\n{}".format(diff) assert result, "BGP VRF DONNA check failed:\n{}".format(diff)
# check BGP IPv4 VPN table
json_file = "{}/{}/show_bgp_ipv4_vpn_zita_up.json".format(CWD, r1.name)
expect = json.loads(open(json_file).read())
test_func = partial(topotest.router_json_cmp, r1, "show bgp ipv4 vpn json", expect)
result, diff = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
assert result, "BGP IPv4 VPN table check failed:\n{}".format(diff)
def test_vrf_route_leak_donna_delete_vrf_zita(): def test_vrf_route_leak_donna_delete_vrf_zita():
logger.info("Delete VRF ZITA and ensure that the route from VRF ZITA is deleted") logger.info("Delete VRF ZITA and ensure that the route from VRF ZITA is deleted")
@ -502,6 +527,101 @@ def test_vrf_route_leak_donna_delete_vrf_zita():
result, diff = topotest.run_and_expect(test_func, None, count=60, wait=0.5) result, diff = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
assert result, "BGP VRF DONNA check failed:\n{}".format(diff) assert result, "BGP VRF DONNA check failed:\n{}".format(diff)
# check BGP IPv4 VPN table
json_file = "{}/{}/show_bgp_ipv4_vpn_init.json".format(CWD, r1.name)
expect = json.loads(open(json_file).read())
test_func = partial(topotest.router_json_cmp, r1, "show bgp ipv4 vpn json", expect)
result, diff = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
assert result, "BGP IPv4 VPN table check failed:\n{}".format(diff)
def test_vrf_route_leak_default_delete_prefix():
logger.info(
"Remove BGP static prefix 172.16.3.0/24 from VRF DONNA and ensure that the route is deleted on default"
)
tgen = get_topogen()
# Don't run this test if we have any failure.
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
r1 = tgen.gears["r1"]
r1.vtysh_cmd(
"""
configure
router bgp 99 vrf DONNA
address-family ipv4 unicast
no network 172.16.3.0/24
"""
)
# Test default VRF.
expect = {
"172.16.3.0/24": None,
}
test_func = partial(topotest.router_json_cmp, r1, "show ip route json", expect)
result, diff = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
assert result, "BGP VRF default check failed:\n{}".format(diff)
# check BGP IPv4 VPN table
json_file = "{}/{}/show_bgp_ipv4_vpn_del_donna_prefix.json".format(CWD, r1.name)
expect = json.loads(open(json_file).read())
test_func = partial(topotest.router_json_cmp, r1, "show bgp ipv4 vpn json", expect)
result, diff = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
assert result, "BGP IPv4 VPN table check failed:\n{}".format(diff)
def test_vrf_route_leak_default_prefix_back():
logger.info(
"Set back BGP static prefix 172.16.3.0/24 to VRF DONNA and ensure that the route is set on default"
)
tgen = get_topogen()
# Don't run this test if we have any failure.
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
r1 = tgen.gears["r1"]
r1.vtysh_cmd(
"""
configure
router bgp 99 vrf DONNA
address-family ipv4 unicast
network 172.16.3.0/24
"""
)
# Test default VRF.
expect = {
"172.16.3.0/24": [
{
"protocol": "bgp",
"selected": True,
"nexthops": [
{
"fib": True,
"interfaceName": "DONNA",
"vrf": "DONNA",
"active": True,
}
],
},
],
}
test_func = partial(topotest.router_json_cmp, r1, "show ip route json", expect)
result, diff = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
assert result, "BGP VRF default check failed:\n{}".format(diff)
# check BGP IPv4 VPN table
json_file = "{}/{}/show_bgp_ipv4_vpn_init.json".format(CWD, r1.name)
expect = json.loads(open(json_file).read())
test_func = partial(topotest.router_json_cmp, r1, "show bgp ipv4 vpn json", expect)
result, diff = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
assert result, "BGP IPv4 VPN table check failed:\n{}".format(diff)
def test_memory_leak(): def test_memory_leak():
"Run the memory leak test and report results." "Run the memory leak test and report results."

View File

@ -123,20 +123,7 @@ def test_vrf_route_leak_donna():
], ],
}, },
], ],
"172.16.101.0/24": [ "172.16.101.0/24": None,
{
"protocol": "bgp",
"selected": None,
"nexthops": [
{
"fib": None,
"interfaceName": "unknown",
"vrf": "Unknown",
"active": None,
},
],
},
],
} }
test_func = partial( test_func = partial(
@ -195,20 +182,7 @@ def test_vrf_route_leak_eva():
"protocol": "connected", "protocol": "connected",
} }
], ],
"172.16.101.0/24": [ "172.16.101.0/24": None,
{
"protocol": "bgp",
"selected": None,
"nexthops": [
{
"fib": None,
"interfaceName": "unknown",
"vrf": "Unknown",
"active": None,
},
],
},
],
} }
test_func = partial( test_func = partial(
@ -302,34 +276,8 @@ interface EVA
# Test DONNA VRF. # Test DONNA VRF.
expect = { expect = {
"10.0.1.0/24": [ "10.0.1.0/24": None,
{ "10.0.3.0/24": None,
"protocol": "bgp",
"selected": None,
"nexthops": [
{
"fib": None,
"interfaceName": "EVA",
"vrf": "EVA",
"active": None,
},
],
},
],
"10.0.3.0/24": [
{
"protocol": "bgp",
"selected": None,
"nexthops": [
{
"fib": None,
"interfaceName": "EVA",
"vrf": "EVA",
"active": None,
},
],
},
],
} }
test_func = partial( test_func = partial(
@ -421,20 +369,7 @@ def test_vrf_route_leak_donna_add_vrf_zita():
# Test DONNA VRF. # Test DONNA VRF.
expect = { expect = {
"172.16.101.0/24": [ "172.16.101.0/24": None,
{
"protocol": "bgp",
"selected": None,
"nexthops": [
{
"fib": None,
"interfaceName": "ZITA",
"vrf": "ZITA",
"active": None,
},
],
},
],
} }
test_func = partial( test_func = partial(