summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss White <russ@riw.us>2025-02-11 08:41:03 -0500
committerGitHub <noreply@github.com>2025-02-11 08:41:03 -0500
commit5518a8c916493a67dbaaef21bf9cbefd3d64d86b (patch)
tree24affe4c066ebe60f235a948822ec35a69c2a6d3
parentbaf4c1a78fe4cafdbb2cdbed030a31ea04a18c4a (diff)
parentfcae7a401d0d7c42a1c1f5dfc096c8a76731ebab (diff)
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.
-rw-r--r--bgpd/bgp_mplsvpn.c46
-rw-r--r--tests/topotests/bgp_bmp/test_bgp_bmp_1.py7
-rw-r--r--tests/topotests/bgp_vpnv4_route_leak_basic/r1/frr.conf10
-rw-r--r--tests/topotests/bgp_vpnv4_route_leak_basic/r1/show_bgp_ipv4_vpn_add_zita.json155
-rw-r--r--tests/topotests/bgp_vpnv4_route_leak_basic/r1/show_bgp_ipv4_vpn_del_donna_prefix.json103
-rw-r--r--tests/topotests/bgp_vpnv4_route_leak_basic/r1/show_bgp_ipv4_vpn_eva_down.json120
-rw-r--r--tests/topotests/bgp_vpnv4_route_leak_basic/r1/show_bgp_ipv4_vpn_init.json120
-rw-r--r--tests/topotests/bgp_vpnv4_route_leak_basic/r1/show_bgp_ipv4_vpn_zita_up.json137
-rw-r--r--tests/topotests/bgp_vpnv4_route_leak_basic/test_bgp_vpnv4_route_leak_basic.py234
-rw-r--r--tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py75
10 files changed, 871 insertions, 136 deletions
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index 46e529f03d..6a8df3b68e 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -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 *bgp_nexthop;
struct bgp_table *table;
+ struct interface *ifp;
bool nh_valid;
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
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
* 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 *new;
struct bgp_path_info_extra *extra;
- struct bgp_path_info *parent = source_bpi;
struct bgp_labels bgp_labels = {};
+ struct bgp *bgp_nexthop;
bool labelssame;
uint8_t i;
@@ -1159,8 +1169,7 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
* match parent
*/
for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next) {
- if (bpi->extra && bpi->extra->vrfleak &&
- bpi->extra->vrfleak->parent == parent)
+ if (bpi->extra && bpi->extra->vrfleak && bpi->extra->vrfleak->parent == source_bpi)
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,
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)
&& CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
if (debug) {
@@ -1185,9 +1204,11 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
return NULL;
}
- if (attrhash_cmp(bpi->attr, new_attr) && labelssame
- && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
-
+ if (attrhash_cmp(bpi->attr, new_attr) && labelssame &&
+ !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);
if (debug)
zlog_debug(
@@ -1274,6 +1295,14 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
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,
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)
new->extra->labels = bgp_labels_intern(&bgp_labels);
- new->extra->vrfleak->parent = bgp_path_info_lock(parent);
- bgp_dest_lock_node(
- (struct bgp_dest *)parent->net);
+ new->extra->vrfleak->parent = bgp_path_info_lock(source_bpi);
+ bgp_dest_lock_node((struct bgp_dest *)source_bpi->net);
new->extra->vrfleak->bgp_orig = bgp_lock(bgp_orig);
diff --git a/tests/topotests/bgp_bmp/test_bgp_bmp_1.py b/tests/topotests/bgp_bmp/test_bgp_bmp_1.py
index 1d7aa97473..c454c9c4a4 100644
--- a/tests/topotests/bgp_bmp/test_bgp_bmp_1.py
+++ b/tests/topotests/bgp_bmp/test_bgp_bmp_1.py
@@ -78,6 +78,13 @@ def setup_module(mod):
"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):
logger.info("Loading router %s" % rname)
router.load_frr_config(
diff --git a/tests/topotests/bgp_vpnv4_route_leak_basic/r1/frr.conf b/tests/topotests/bgp_vpnv4_route_leak_basic/r1/frr.conf
index d3ababde3a..e3f8b242a1 100644
--- a/tests/topotests/bgp_vpnv4_route_leak_basic/r1/frr.conf
+++ b/tests/topotests/bgp_vpnv4_route_leak_basic/r1/frr.conf
@@ -1,3 +1,7 @@
+vrf DONNA
+ ip route 172.16.3.0/24 10.0.0.254
+exit-vrf
+!
int dummy0
ip address 10.0.4.1/24
no shut
@@ -28,6 +32,9 @@ ip router-id 10.0.4.1
!
router bgp 99
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
redistribute connected
rd vpn export 10.0.4.1:1
@@ -36,11 +43,14 @@ router bgp 99
export vpn
import vpn
!
+ address-family ipv4 vpn
+ neighbor 10.0.4.254 activate
!
router bgp 99 vrf DONNA
no bgp ebgp-requires-policy
address-family ipv4 unicast
redistribute connected
+ network 172.16.3.0/24
label vpn export 101
rd vpn export 10.0.4.1:1
rt vpn export 10.0.4.1:101
diff --git a/tests/topotests/bgp_vpnv4_route_leak_basic/r1/show_bgp_ipv4_vpn_add_zita.json b/tests/topotests/bgp_vpnv4_route_leak_basic/r1/show_bgp_ipv4_vpn_add_zita.json
new file mode 100644
index 0000000000..c7ff2f4f80
--- /dev/null
+++ b/tests/topotests/bgp_vpnv4_route_leak_basic/r1/show_bgp_ipv4_vpn_add_zita.json
@@ -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
+ }
+ ]
+ }
+ ]
+ }
+ }
+ }
+}
+
diff --git a/tests/topotests/bgp_vpnv4_route_leak_basic/r1/show_bgp_ipv4_vpn_del_donna_prefix.json b/tests/topotests/bgp_vpnv4_route_leak_basic/r1/show_bgp_ipv4_vpn_del_donna_prefix.json
new file mode 100644
index 0000000000..1797d78582
--- /dev/null
+++ b/tests/topotests/bgp_vpnv4_route_leak_basic/r1/show_bgp_ipv4_vpn_del_donna_prefix.json
@@ -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
+ }
+ }
+ }
+}
+
diff --git a/tests/topotests/bgp_vpnv4_route_leak_basic/r1/show_bgp_ipv4_vpn_eva_down.json b/tests/topotests/bgp_vpnv4_route_leak_basic/r1/show_bgp_ipv4_vpn_eva_down.json
new file mode 100644
index 0000000000..4b0eaaa052
--- /dev/null
+++ b/tests/topotests/bgp_vpnv4_route_leak_basic/r1/show_bgp_ipv4_vpn_eva_down.json
@@ -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
+ }
+ }
+ }
+}
+
diff --git a/tests/topotests/bgp_vpnv4_route_leak_basic/r1/show_bgp_ipv4_vpn_init.json b/tests/topotests/bgp_vpnv4_route_leak_basic/r1/show_bgp_ipv4_vpn_init.json
new file mode 100644
index 0000000000..de18bc8463
--- /dev/null
+++ b/tests/topotests/bgp_vpnv4_route_leak_basic/r1/show_bgp_ipv4_vpn_init.json
@@ -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
+ }
+ }
+ }
+}
+
diff --git a/tests/topotests/bgp_vpnv4_route_leak_basic/r1/show_bgp_ipv4_vpn_zita_up.json b/tests/topotests/bgp_vpnv4_route_leak_basic/r1/show_bgp_ipv4_vpn_zita_up.json
new file mode 100644
index 0000000000..0c249e241e
--- /dev/null
+++ b/tests/topotests/bgp_vpnv4_route_leak_basic/r1/show_bgp_ipv4_vpn_zita_up.json
@@ -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
+ }
+ ]
+ }
+ ]
+ }
+ }
+ }
+}
+
diff --git a/tests/topotests/bgp_vpnv4_route_leak_basic/test_bgp_vpnv4_route_leak_basic.py b/tests/topotests/bgp_vpnv4_route_leak_basic/test_bgp_vpnv4_route_leak_basic.py
index a44f07b560..67e53cb0cc 100644
--- a/tests/topotests/bgp_vpnv4_route_leak_basic/test_bgp_vpnv4_route_leak_basic.py
+++ b/tests/topotests/bgp_vpnv4_route_leak_basic/test_bgp_vpnv4_route_leak_basic.py
@@ -13,6 +13,7 @@
Test basic VPNv4 route leaking
"""
+import json
import os
import sys
from functools import partial
@@ -60,6 +61,22 @@ def teardown_module(mod):
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():
logger.info("Ensure that routes are leaked back and forth")
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",
- "selected": None,
+ "protocol": "static",
+ "selected": True,
"nexthops": [
{
- "fib": None,
- "interfaceName": "unknown",
- "vrf": "Unknown",
- "active": None,
- },
+ "fib": True,
+ "interfaceName": "dummy1",
+ "active": True,
+ }
],
},
],
+ "172.16.101.0/24": None,
}
test_func = partial(
@@ -191,20 +208,21 @@ def test_vrf_route_leak_eva():
"protocol": "connected",
}
],
- "172.16.101.0/24": [
+ "172.16.3.0/24": [
{
"protocol": "bgp",
- "selected": None,
+ "selected": True,
"nexthops": [
{
- "fib": None,
- "interfaceName": "unknown",
- "vrf": "Unknown",
- "active": None,
- },
+ "fib": True,
+ "interfaceName": "DONNA",
+ "vrf": "DONNA",
+ "active": True,
+ }
],
},
],
+ "172.16.101.0/24": None,
}
test_func = partial(
@@ -258,6 +276,20 @@ def test_vrf_route_leak_default():
"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)
@@ -298,34 +330,8 @@ interface EVA
# Test DONNA VRF.
expect = {
- "10.0.1.0/24": [
- {
- "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,
- },
- ],
- },
- ],
+ "10.0.1.0/24": None,
+ "10.0.3.0/24": None,
}
test_func = partial(
@@ -349,6 +355,14 @@ interface EVA
result, diff = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
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():
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)
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():
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.
expect = {
- "172.16.101.0/24": [
- {
- "protocol": "bgp",
- "selected": None,
- "nexthops": [
- {
- "fib": None,
- "interfaceName": "ZITA",
- "vrf": "ZITA",
- "active": None,
- },
- ],
- },
- ],
+ "172.16.101.0/24": None,
}
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)
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():
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)
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():
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)
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():
"Run the memory leak test and report results."
diff --git a/tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py b/tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py
index 6d4b436bcc..3bc36862bf 100644
--- a/tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py
+++ b/tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py
@@ -123,20 +123,7 @@ def test_vrf_route_leak_donna():
],
},
],
- "172.16.101.0/24": [
- {
- "protocol": "bgp",
- "selected": None,
- "nexthops": [
- {
- "fib": None,
- "interfaceName": "unknown",
- "vrf": "Unknown",
- "active": None,
- },
- ],
- },
- ],
+ "172.16.101.0/24": None,
}
test_func = partial(
@@ -195,20 +182,7 @@ def test_vrf_route_leak_eva():
"protocol": "connected",
}
],
- "172.16.101.0/24": [
- {
- "protocol": "bgp",
- "selected": None,
- "nexthops": [
- {
- "fib": None,
- "interfaceName": "unknown",
- "vrf": "Unknown",
- "active": None,
- },
- ],
- },
- ],
+ "172.16.101.0/24": None,
}
test_func = partial(
@@ -302,34 +276,8 @@ interface EVA
# Test DONNA VRF.
expect = {
- "10.0.1.0/24": [
- {
- "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,
- },
- ],
- },
- ],
+ "10.0.1.0/24": None,
+ "10.0.3.0/24": None,
}
test_func = partial(
@@ -421,20 +369,7 @@ def test_vrf_route_leak_donna_add_vrf_zita():
# Test DONNA VRF.
expect = {
- "172.16.101.0/24": [
- {
- "protocol": "bgp",
- "selected": None,
- "nexthops": [
- {
- "fib": None,
- "interfaceName": "ZITA",
- "vrf": "ZITA",
- "active": None,
- },
- ],
- },
- ],
+ "172.16.101.0/24": None,
}
test_func = partial(