Merge pull request #13750 from louis-6wind/fix-no-retain-memory-usage

bgpd: fix memory usage of vpn no retain
This commit is contained in:
Russ White 2023-06-20 09:19:50 -04:00 committed by GitHub
commit 554c2e0350
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 1275 additions and 215 deletions

View File

@ -2120,7 +2120,7 @@ static struct bgp *bgp_lookup_by_rd(struct bgp_path_info *bpi,
return NULL; return NULL;
} }
static bool vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
struct bgp *from_bgp, /* from */ struct bgp *from_bgp, /* from */
struct bgp_path_info *path_vpn, struct bgp_path_info *path_vpn,
struct prefix_rd *prd) struct prefix_rd *prd)
@ -2150,7 +2150,7 @@ static bool vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
"%s: from vpn (%s) to vrf (%s), skipping: %s", "%s: from vpn (%s) to vrf (%s), skipping: %s",
__func__, from_bgp->name_pretty, __func__, from_bgp->name_pretty,
to_bgp->name_pretty, debugmsg); to_bgp->name_pretty, debugmsg);
return false; return;
} }
/* /*
@ -2177,7 +2177,7 @@ static bool vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
zlog_debug( zlog_debug(
"from vpn (%s) to vrf (%s), skipping after no intersection of route targets", "from vpn (%s) to vrf (%s), skipping after no intersection of route targets",
from_bgp->name_pretty, to_bgp->name_pretty); from_bgp->name_pretty, to_bgp->name_pretty);
return false; return;
} }
rd_buf[0] = '\0'; rd_buf[0] = '\0';
@ -2194,7 +2194,7 @@ static bool vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
zlog_debug( zlog_debug(
"%s: skipping import, match RD (%s) of src VRF (%s) and the prefix (%pFX)", "%s: skipping import, match RD (%s) of src VRF (%s) and the prefix (%pFX)",
__func__, rd_buf, to_bgp->name_pretty, p); __func__, rd_buf, to_bgp->name_pretty, p);
return false; return;
} }
if (debug) if (debug)
@ -2305,7 +2305,7 @@ static bool vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
to_bgp->vpn_policy[afi] to_bgp->vpn_policy[afi]
.rmap[BGP_VPN_POLICY_DIR_FROMVPN] .rmap[BGP_VPN_POLICY_DIR_FROMVPN]
->name); ->name);
return false; return;
} }
/* /*
* if route-map changed nexthop, don't nexthop-self on output * if route-map changed nexthop, don't nexthop-self on output
@ -2367,17 +2367,60 @@ static bool vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
num_labels, src_vrf, &nexthop_orig, nexthop_self_flag, num_labels, src_vrf, &nexthop_orig, nexthop_self_flag,
debug)) debug))
bgp_dest_unlock_node(bn); bgp_dest_unlock_node(bn);
}
bool vpn_leak_to_vrf_no_retain_filter_check(struct bgp *from_bgp,
struct attr *attr, afi_t afi)
{
struct ecommunity *ecom_route_target = bgp_attr_get_ecommunity(attr);
int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF);
struct listnode *node;
const char *debugmsg;
struct bgp *to_bgp;
/* Loop over BGP instances */
for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, to_bgp)) {
if (!vpn_leak_from_vpn_active(to_bgp, afi, &debugmsg)) {
if (debug)
zlog_debug(
"%s: from vpn (%s) to vrf (%s) afi %s, skipping: %s",
__func__, from_bgp->name_pretty,
to_bgp->name_pretty, afi2str(afi),
debugmsg);
continue;
}
/* Check for intersection of route targets */
if (!ecommunity_include(
to_bgp->vpn_policy[afi]
.rtlist[BGP_VPN_POLICY_DIR_FROMVPN],
ecom_route_target)) {
if (debug)
zlog_debug(
"%s: from vpn (%s) to vrf (%s) afi %s %s, skipping after no intersection of route targets",
__func__, from_bgp->name_pretty,
to_bgp->name_pretty, afi2str(afi),
ecommunity_str(ecom_route_target));
continue;
}
return false;
}
if (debug)
zlog_debug(
"%s: from vpn (%s) afi %s %s, no import - must be filtered",
__func__, from_bgp->name_pretty, afi2str(afi),
ecommunity_str(ecom_route_target));
return true; return true;
} }
bool vpn_leak_to_vrf_update(struct bgp *from_bgp, void vpn_leak_to_vrf_update(struct bgp *from_bgp,
struct bgp_path_info *path_vpn, struct bgp_path_info *path_vpn,
struct prefix_rd *prd) struct prefix_rd *prd)
{ {
struct listnode *mnode, *mnnode; struct listnode *mnode, *mnnode;
struct bgp *bgp; struct bgp *bgp;
bool leak_success = false;
int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF); int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF);
@ -2389,11 +2432,10 @@ bool vpn_leak_to_vrf_update(struct bgp *from_bgp,
if (!path_vpn->extra if (!path_vpn->extra
|| path_vpn->extra->bgp_orig != bgp) { /* no loop */ || path_vpn->extra->bgp_orig != bgp) { /* no loop */
leak_success |= vpn_leak_to_vrf_update_onevrf( vpn_leak_to_vrf_update_onevrf(bgp, from_bgp, path_vpn,
bgp, from_bgp, path_vpn, prd); prd);
} }
} }
return leak_success;
} }
void vpn_leak_to_vrf_withdraw(struct bgp_path_info *path_vpn) void vpn_leak_to_vrf_withdraw(struct bgp_path_info *path_vpn)
@ -2513,6 +2555,51 @@ void vpn_leak_to_vrf_withdraw_all(struct bgp *to_bgp, afi_t afi)
} }
} }
void vpn_leak_no_retain(struct bgp *to_bgp, struct bgp *vpn_from, afi_t afi)
{
struct bgp_dest *pdest;
safi_t safi = SAFI_MPLS_VPN;
assert(vpn_from);
/*
* Walk vpn table
*/
for (pdest = bgp_table_top(vpn_from->rib[afi][safi]); pdest;
pdest = bgp_route_next(pdest)) {
struct bgp_table *table;
struct bgp_dest *bn;
struct bgp_path_info *bpi;
/* This is the per-RD table of prefixes */
table = bgp_dest_get_bgp_table_info(pdest);
if (!table)
continue;
for (bn = bgp_table_top(table); bn; bn = bgp_route_next(bn)) {
for (bpi = bgp_dest_get_bgp_path_info(bn); bpi;
bpi = bpi->next) {
if (bpi->extra &&
bpi->extra->bgp_orig == to_bgp)
continue;
if (bpi->sub_type != BGP_ROUTE_NORMAL)
continue;
if (!vpn_leak_to_vrf_no_retain_filter_check(
vpn_from, bpi->attr, afi))
/* do not filter */
continue;
bgp_unlink_nexthop(bpi);
bgp_rib_remove(bn, bpi, bpi->peer, afi, safi);
}
}
}
}
void vpn_leak_to_vrf_update_all(struct bgp *to_bgp, struct bgp *vpn_from, void vpn_leak_to_vrf_update_all(struct bgp *to_bgp, struct bgp *vpn_from,
afi_t afi) afi_t afi)
{ {
@ -3717,6 +3804,7 @@ void vpn_leak_postchange_all(void)
*/ */
void bgp_vpn_leak_unimport(struct bgp *from_bgp) void bgp_vpn_leak_unimport(struct bgp *from_bgp)
{ {
struct bgp *bgp_default = bgp_get_default();
struct bgp *to_bgp; struct bgp *to_bgp;
const char *tmp_name; const char *tmp_name;
char *vname; char *vname;
@ -3795,6 +3883,17 @@ void bgp_vpn_leak_unimport(struct bgp *from_bgp)
} }
} }
} }
if (bgp_default &&
!CHECK_FLAG(bgp_default->af_flags[afi][SAFI_MPLS_VPN],
BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL)) {
/* 'from_bgp' instance will be deleted
* so force to unset importation to update VPN labels
*/
UNSET_FLAG(from_bgp->af_flags[afi][SAFI_UNICAST],
BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT);
vpn_leak_no_retain(from_bgp, bgp_default, afi);
}
} }
return; return;
} }

View File

@ -56,10 +56,17 @@ extern void vpn_leak_from_vrf_update_all(struct bgp *to_bgp,
extern void vpn_leak_to_vrf_withdraw_all(struct bgp *to_bgp, afi_t afi); extern void vpn_leak_to_vrf_withdraw_all(struct bgp *to_bgp, afi_t afi);
extern void vpn_leak_no_retain(struct bgp *to_bgp, struct bgp *vpn_from,
afi_t afi);
extern void vpn_leak_to_vrf_update_all(struct bgp *to_bgp, struct bgp *from_bgp, extern void vpn_leak_to_vrf_update_all(struct bgp *to_bgp, struct bgp *from_bgp,
afi_t afi); afi_t afi);
extern bool vpn_leak_to_vrf_update(struct bgp *from_bgp, extern bool vpn_leak_to_vrf_no_retain_filter_check(struct bgp *from_bgp,
struct attr *attr,
afi_t afi);
extern void vpn_leak_to_vrf_update(struct bgp *from_bgp,
struct bgp_path_info *path_vpn, struct bgp_path_info *path_vpn,
struct prefix_rd *prd); struct prefix_rd *prd);

View File

@ -4152,7 +4152,6 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
afi_t nh_afi; afi_t nh_afi;
bool force_evpn_import = false; bool force_evpn_import = false;
safi_t orig_safi = safi; safi_t orig_safi = safi;
bool leak_success = true;
int allowas_in = 0; int allowas_in = 0;
if (frrtrace_enabled(frr_bgp, process_update)) { if (frrtrace_enabled(frr_bgp, process_update)) {
@ -4296,6 +4295,16 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
goto filtered; goto filtered;
} }
if ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_MPLS_VPN &&
bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT &&
!CHECK_FLAG(bgp->af_flags[afi][safi],
BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
vpn_leak_to_vrf_no_retain_filter_check(bgp, attr, afi)) {
reason =
"no import. Filtered by no bgp retain route-target all";
goto filtered;
}
/* If the route has Node Target Extended Communities, check /* If the route has Node Target Extended Communities, check
* if it's allowed to be installed locally. * if it's allowed to be installed locally.
*/ */
@ -4848,7 +4857,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
} }
if ((SAFI_MPLS_VPN == safi) if ((SAFI_MPLS_VPN == safi)
&& (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) { && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
leak_success = vpn_leak_to_vrf_update(bgp, pi, prd); vpn_leak_to_vrf_update(bgp, pi, prd);
} }
#ifdef ENABLE_BGP_VNC #ifdef ENABLE_BGP_VNC
@ -4863,13 +4872,6 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
type, sub_type, NULL); type, sub_type, NULL);
} }
#endif #endif
if ((safi == SAFI_MPLS_VPN) &&
!CHECK_FLAG(bgp->af_flags[afi][safi],
BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
!leak_success) {
bgp_unlink_nexthop(pi);
bgp_path_info_delete(dest, pi);
}
return; return;
} // End of implicit withdraw } // End of implicit withdraw
@ -5020,7 +5022,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
} }
if ((SAFI_MPLS_VPN == safi) if ((SAFI_MPLS_VPN == safi)
&& (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) { && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
leak_success = vpn_leak_to_vrf_update(bgp, new, prd); vpn_leak_to_vrf_update(bgp, new, prd);
} }
#ifdef ENABLE_BGP_VNC #ifdef ENABLE_BGP_VNC
if (SAFI_MPLS_VPN == safi) { if (SAFI_MPLS_VPN == safi) {
@ -5034,13 +5036,6 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
sub_type, NULL); sub_type, NULL);
} }
#endif #endif
if ((safi == SAFI_MPLS_VPN) &&
!CHECK_FLAG(bgp->af_flags[afi][safi],
BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
!leak_success) {
bgp_unlink_nexthop(new);
bgp_path_info_delete(dest, new);
}
return; return;
@ -11932,7 +11927,7 @@ int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
"\nDisplayed %ld routes and %ld total paths\n", "\nDisplayed %ld routes and %ld total paths\n",
output_cum, total_cum); output_cum, total_cum);
} else { } else {
if (use_json && output_cum == 0) if (use_json && output_cum == 0 && json_header_depth == 0)
vty_out(vty, "{}\n"); vty_out(vty, "{}\n");
} }
return CMD_SUCCESS; return CMD_SUCCESS;

View File

@ -9954,6 +9954,7 @@ DEFPY (bgp_imexport_vpn,
bool yes = true; bool yes = true;
int flag; int flag;
enum vpn_policy_direction dir; enum vpn_policy_direction dir;
struct bgp *bgp_default = bgp_get_default();
if (argv_find(argv, argc, "no", &idx)) if (argv_find(argv, argc, "no", &idx))
yes = false; yes = false;
@ -9989,14 +9990,18 @@ DEFPY (bgp_imexport_vpn,
SET_FLAG(bgp->af_flags[afi][safi], flag); SET_FLAG(bgp->af_flags[afi][safi], flag);
if (!previous_state) { if (!previous_state) {
/* trigger export current vrf */ /* trigger export current vrf */
vpn_leak_postchange(dir, afi, bgp_get_default(), bgp); vpn_leak_postchange(dir, afi, bgp_default, bgp);
} }
} else { } else {
if (previous_state) { if (previous_state) {
/* trigger un-export current vrf */ /* trigger un-export current vrf */
vpn_leak_prechange(dir, afi, bgp_get_default(), bgp); vpn_leak_prechange(dir, afi, bgp_default, bgp);
} }
UNSET_FLAG(bgp->af_flags[afi][safi], flag); UNSET_FLAG(bgp->af_flags[afi][safi], flag);
if (previous_state && bgp_default &&
!CHECK_FLAG(bgp_default->af_flags[afi][SAFI_MPLS_VPN],
BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL))
vpn_leak_no_retain(bgp, bgp_default, afi);
} }
hook_call(bgp_snmp_init_stats, bgp); hook_call(bgp_snmp_init_stats, bgp);

View File

@ -1,8 +1,12 @@
router bgp 65500 router bgp 65500
bgp router-id 1.1.1.1 bgp router-id 192.0.2.1
neighbor 10.125.0.2 remote-as 65500 neighbor 10.125.0.2 remote-as 65500
address-family ipv4 unicast address-family ipv4 unicast
no neighbor 10.125.0.2 activate no neighbor 10.125.0.2 activate
label vpn export 100
rd vpn export 192.0.2.1:0
rt vpn import 192.0.2.2:400
import vpn
exit-address-family exit-address-family
address-family ipv4 vpn address-family ipv4 vpn
neighbor 10.125.0.2 activate neighbor 10.125.0.2 activate
@ -10,15 +14,33 @@ router bgp 65500
exit-address-family exit-address-family
! !
router bgp 65500 vrf vrf1 router bgp 65500 vrf vrf1
bgp router-id 1.1.1.1 bgp router-id 192.0.2.1
address-family ipv4 unicast address-family ipv4 unicast
redistribute connected redistribute connected
label vpn export 101 label vpn export 101
rd vpn export 444:1 rd vpn export 192.0.2.1:1
rt vpn import 51:100 52:100 rt vpn import 192.0.2.2:100
rt vpn export 51:100 rt vpn export 192.0.2.1:100
export vpn export vpn
import vpn import vpn
exit-address-family exit-address-family
! !
router bgp 65500 vrf vrf3
bgp router-id 192.0.2.1
address-family ipv4 unicast
redistribute connected
label vpn export 103
rd vpn export 192.0.2.1:3
rt vpn export 192.0.2.1:300
export vpn
exit-address-family
!
router bgp 65500 vrf vrf4
bgp router-id 192.0.2.1
address-family ipv4 unicast
label vpn export 104
rd vpn export 192.0.2.1:4
rt vpn import 192.0.2.1:300
import vpn
exit-address-family
!

View File

@ -1,68 +0,0 @@
{
"vrfId":0,
"vrfName":"default",
"routerId":"1.1.1.1",
"defaultLocPrf":100,
"localAS":65500,
"routes":{
"routeDistinguishers":{
"444:1":{
"10.201.0.0/24":[
{
"valid":true,
"bestpath":true,
"selectionReason":"First path received",
"pathFrom":"external",
"prefix":"10.201.0.0",
"prefixLen":24,
"network":"10.201.0.0\/24",
"metric":0,
"weight":32768,
"peerId":"(unspec)",
"path":"",
"origin":"incomplete",
"announceNexthopSelf":true,
"nhVrfName":"vrf1",
"nexthops":[
{
"ip":"0.0.0.0",
"hostname":"r1",
"afi":"ipv4",
"used":true
}
]
}
]
},
"444:2":{
"10.200.0.0/24":[
{
"valid":true,
"bestpath":true,
"selectionReason":"First path received",
"pathFrom":"internal",
"prefix":"10.200.0.0",
"prefixLen":24,
"network":"10.200.0.0\/24",
"metric":0,
"locPrf":100,
"weight":0,
"peerId":"10.125.0.2",
"path":"",
"origin":"incomplete",
"nexthops":[
{
"ip":"10.125.0.2",
"hostname":"r2",
"afi":"ipv4",
"used":true
}
]
}
]
},
"444:3":{
}
}
}
}

View File

@ -0,0 +1,175 @@
{
"vrfId":0,
"vrfName":"default",
"routerId":"192.0.2.1",
"defaultLocPrf":100,
"localAS":65500,
"routes":{
"routeDistinguishers":{
"192.0.2.1:1":{
"10.101.0.0/24":[
{
"valid":true,
"bestpath":true,
"selectionReason":"First path received",
"pathFrom":"external",
"prefix":"10.101.0.0",
"prefixLen":24,
"network":"10.101.0.0\/24",
"metric":0,
"weight":32768,
"peerId":"(unspec)",
"path":"",
"origin":"incomplete",
"announceNexthopSelf":true,
"nhVrfName":"vrf1",
"nexthops":[
{
"ip":"0.0.0.0",
"hostname":"r1",
"afi":"ipv4",
"used":true
}
]
}
]
},
"192.0.2.1:3":{
"10.103.0.0/24":[
{
"valid":true,
"bestpath":true,
"selectionReason":"First path received",
"pathFrom":"external",
"prefix":"10.103.0.0",
"prefixLen":24,
"network":"10.103.0.0\/24",
"metric":0,
"weight":32768,
"peerId":"(unspec)",
"path":"",
"origin":"incomplete",
"announceNexthopSelf":true,
"nhVrfName":"vrf3",
"nexthops":[
{
"ip":"0.0.0.0",
"hostname":"r1",
"afi":"ipv4",
"used":true
}
]
}
]
},
"192.0.2.2:1":{
"10.201.0.0/24":[
{
"valid":true,
"bestpath":true,
"selectionReason":"First path received",
"pathFrom":"internal",
"prefix":"10.201.0.0",
"prefixLen":24,
"network":"10.201.0.0\/24",
"metric":0,
"locPrf":100,
"weight":0,
"peerId":"10.125.0.2",
"path":"",
"origin":"incomplete",
"nexthops":[
{
"ip":"10.125.0.2",
"hostname":"r2",
"afi":"ipv4",
"used":true
}
]
}
]
},
"192.0.2.2:2":{
"10.202.0.0/24":[
{
"valid":true,
"bestpath":true,
"selectionReason":"First path received",
"pathFrom":"internal",
"prefix":"10.202.0.0",
"prefixLen":24,
"network":"10.202.0.0\/24",
"metric":0,
"locPrf":100,
"weight":0,
"peerId":"10.125.0.2",
"path":"",
"origin":"incomplete",
"nexthops":[
{
"ip":"10.125.0.2",
"hostname":"r2",
"afi":"ipv4",
"used":true
}
]
}
]
},
"192.0.2.2:3":{
"10.203.0.0/24":[
{
"valid":true,
"bestpath":true,
"selectionReason":"First path received",
"pathFrom":"internal",
"prefix":"10.203.0.0",
"prefixLen":24,
"network":"10.203.0.0\/24",
"metric":0,
"locPrf":100,
"weight":0,
"peerId":"10.125.0.2",
"path":"",
"origin":"incomplete",
"nexthops":[
{
"ip":"10.125.0.2",
"hostname":"r2",
"afi":"ipv4",
"used":true
}
]
}
]
},
"192.0.2.2:4":{
"10.204.0.0/24":[
{
"valid":true,
"bestpath":true,
"selectionReason":"First path received",
"pathFrom":"internal",
"prefix":"10.204.0.0",
"prefixLen":24,
"network":"10.204.0.0\/24",
"metric":0,
"locPrf":100,
"weight":0,
"peerId":"10.125.0.2",
"path":"",
"origin":"incomplete",
"nexthops":[
{
"ip":"10.125.0.2",
"hostname":"r2",
"afi":"ipv4",
"used":true
}
]
}
]
}
}
}
}

View File

@ -1,21 +1,21 @@
{ {
"vrfId":0, "vrfId":0,
"vrfName":"default", "vrfName":"default",
"routerId":"1.1.1.1", "routerId":"192.0.2.1",
"defaultLocPrf":100, "defaultLocPrf":100,
"localAS":65500, "localAS":65500,
"routes":{ "routes":{
"routeDistinguishers":{ "routeDistinguishers":{
"444:1":{ "192.0.2.1:1":{
"10.201.0.0/24":[ "10.101.0.0/24":[
{ {
"valid":true, "valid":true,
"bestpath":true, "bestpath":true,
"selectionReason":"First path received", "selectionReason":"First path received",
"pathFrom":"external", "pathFrom":"external",
"prefix":"10.201.0.0", "prefix":"10.101.0.0",
"prefixLen":24, "prefixLen":24,
"network":"10.201.0.0\/24", "network":"10.101.0.0\/24",
"metric":0, "metric":0,
"weight":32768, "weight":32768,
"peerId":"(unspec)", "peerId":"(unspec)",
@ -34,16 +34,44 @@
} }
] ]
}, },
"444:2":{ "192.0.2.1:3":{
"10.200.0.0/24":[ "10.103.0.0/24":[
{
"valid":true,
"bestpath":true,
"selectionReason":"First path received",
"pathFrom":"external",
"prefix":"10.103.0.0",
"prefixLen":24,
"network":"10.103.0.0\/24",
"metric":0,
"weight":32768,
"peerId":"(unspec)",
"path":"",
"origin":"incomplete",
"announceNexthopSelf":true,
"nhVrfName":"vrf3",
"nexthops":[
{
"ip":"0.0.0.0",
"hostname":"r1",
"afi":"ipv4",
"used":true
}
]
}
]
},
"192.0.2.2:1":{
"10.201.0.0/24":[
{ {
"valid":true, "valid":true,
"bestpath":true, "bestpath":true,
"selectionReason":"First path received", "selectionReason":"First path received",
"pathFrom":"internal", "pathFrom":"internal",
"prefix":"10.200.0.0", "prefix":"10.201.0.0",
"prefixLen":24, "prefixLen":24,
"network":"10.200.0.0\/24", "network":"10.201.0.0\/24",
"metric":0, "metric":0,
"locPrf":100, "locPrf":100,
"weight":0, "weight":0,
@ -61,16 +89,16 @@
} }
] ]
}, },
"444:3":{ "192.0.2.2:4":{
"10.210.0.0/24":[ "10.204.0.0/24":[
{ {
"valid":true, "valid":true,
"bestpath":true, "bestpath":true,
"selectionReason":"First path received", "selectionReason":"First path received",
"pathFrom":"internal", "pathFrom":"internal",
"prefix":"10.210.0.0", "prefix":"10.204.0.0",
"prefixLen":24, "prefixLen":24,
"network":"10.210.0.0\/24", "network":"10.204.0.0\/24",
"metric":0, "metric":0,
"locPrf":100, "locPrf":100,
"weight":0, "weight":0,

View File

@ -0,0 +1,148 @@
{
"vrfId":0,
"vrfName":"default",
"routerId":"192.0.2.1",
"defaultLocPrf":100,
"localAS":65500,
"routes":{
"routeDistinguishers":{
"192.0.2.1:1":{
"10.101.0.0/24":[
{
"valid":true,
"bestpath":true,
"selectionReason":"First path received",
"pathFrom":"external",
"prefix":"10.101.0.0",
"prefixLen":24,
"network":"10.101.0.0\/24",
"metric":0,
"weight":32768,
"peerId":"(unspec)",
"path":"",
"origin":"incomplete",
"announceNexthopSelf":true,
"nhVrfName":"vrf1",
"nexthops":[
{
"ip":"0.0.0.0",
"hostname":"r1",
"afi":"ipv4",
"used":true
}
]
}
]
},
"192.0.2.1:3":{
"10.103.0.0/24":[
{
"valid":true,
"bestpath":true,
"selectionReason":"First path received",
"pathFrom":"external",
"prefix":"10.103.0.0",
"prefixLen":24,
"network":"10.103.0.0\/24",
"metric":0,
"weight":32768,
"peerId":"(unspec)",
"path":"",
"origin":"incomplete",
"announceNexthopSelf":true,
"nhVrfName":"vrf3",
"nexthops":[
{
"ip":"0.0.0.0",
"hostname":"r1",
"afi":"ipv4",
"used":true
}
]
}
]
},
"192.0.2.2:1":{
"10.201.0.0/24":[
{
"valid":true,
"bestpath":true,
"selectionReason":"First path received",
"pathFrom":"internal",
"prefix":"10.201.0.0",
"prefixLen":24,
"network":"10.201.0.0\/24",
"metric":0,
"locPrf":100,
"weight":0,
"peerId":"10.125.0.2",
"path":"",
"origin":"incomplete",
"nexthops":[
{
"ip":"10.125.0.2",
"hostname":"r2",
"afi":"ipv4",
"used":true
}
]
}
]
},
"192.0.2.2:2":{
"10.202.0.0/24":[
{
"valid":true,
"bestpath":true,
"selectionReason":"First path received",
"pathFrom":"internal",
"prefix":"10.202.0.0",
"prefixLen":24,
"network":"10.202.0.0\/24",
"metric":0,
"locPrf":100,
"weight":0,
"peerId":"10.125.0.2",
"path":"",
"origin":"incomplete",
"nexthops":[
{
"ip":"10.125.0.2",
"hostname":"r2",
"afi":"ipv4",
"used":true
}
]
}
]
},
"192.0.2.2:4":{
"10.204.0.0/24":[
{
"valid":true,
"bestpath":true,
"selectionReason":"First path received",
"pathFrom":"internal",
"prefix":"10.204.0.0",
"prefixLen":24,
"network":"10.204.0.0\/24",
"metric":0,
"locPrf":100,
"weight":0,
"peerId":"10.125.0.2",
"path":"",
"origin":"incomplete",
"nexthops":[
{
"ip":"10.125.0.2",
"hostname":"r2",
"afi":"ipv4",
"used":true
}
]
}
]
}
}
}
}

View File

@ -0,0 +1,148 @@
{
"vrfId":0,
"vrfName":"default",
"routerId":"192.0.2.1",
"defaultLocPrf":100,
"localAS":65500,
"routes":{
"routeDistinguishers":{
"192.0.2.1:1":{
"10.101.0.0/24":[
{
"valid":true,
"bestpath":true,
"selectionReason":"First path received",
"pathFrom":"external",
"prefix":"10.101.0.0",
"prefixLen":24,
"network":"10.101.0.0\/24",
"metric":0,
"weight":32768,
"peerId":"(unspec)",
"path":"",
"origin":"incomplete",
"announceNexthopSelf":true,
"nhVrfName":"vrf1",
"nexthops":[
{
"ip":"0.0.0.0",
"hostname":"r1",
"afi":"ipv4",
"used":true
}
]
}
]
},
"192.0.2.1:3":{
"10.103.0.0/24":[
{
"valid":true,
"bestpath":true,
"selectionReason":"First path received",
"pathFrom":"external",
"prefix":"10.103.0.0",
"prefixLen":24,
"network":"10.103.0.0\/24",
"metric":0,
"weight":32768,
"peerId":"(unspec)",
"path":"",
"origin":"incomplete",
"announceNexthopSelf":true,
"nhVrfName":"vrf3",
"nexthops":[
{
"ip":"0.0.0.0",
"hostname":"r1",
"afi":"ipv4",
"used":true
}
]
}
]
},
"192.0.2.2:1":{
"10.201.0.0/24":[
{
"valid":true,
"bestpath":true,
"selectionReason":"First path received",
"pathFrom":"internal",
"prefix":"10.201.0.0",
"prefixLen":24,
"network":"10.201.0.0\/24",
"metric":0,
"locPrf":100,
"weight":0,
"peerId":"10.125.0.2",
"path":"",
"origin":"incomplete",
"nexthops":[
{
"ip":"10.125.0.2",
"hostname":"r2",
"afi":"ipv4",
"used":true
}
]
}
]
},
"192.0.2.2:3":{
"10.203.0.0/24":[
{
"valid":true,
"bestpath":true,
"selectionReason":"First path received",
"pathFrom":"internal",
"prefix":"10.203.0.0",
"prefixLen":24,
"network":"10.203.0.0\/24",
"metric":0,
"locPrf":100,
"weight":0,
"peerId":"10.125.0.2",
"path":"",
"origin":"incomplete",
"nexthops":[
{
"ip":"10.125.0.2",
"hostname":"r2",
"afi":"ipv4",
"used":true
}
]
}
]
},
"192.0.2.2:4":{
"10.204.0.0/24":[
{
"valid":true,
"bestpath":true,
"selectionReason":"First path received",
"pathFrom":"internal",
"prefix":"10.204.0.0",
"prefixLen":24,
"network":"10.204.0.0\/24",
"metric":0,
"locPrf":100,
"weight":0,
"peerId":"10.125.0.2",
"path":"",
"origin":"incomplete",
"nexthops":[
{
"ip":"10.125.0.2",
"hostname":"r2",
"afi":"ipv4",
"used":true
}
]
}
]
}
}
}
}

View File

@ -10,5 +10,5 @@ router isis 1
is-type level-1 is-type level-1
net 49.0002.0000.1994.00 net 49.0002.0000.1994.00
segment-routing on segment-routing on
segment-routing prefix 1.1.1.1/32 index 11 segment-routing prefix 192.0.2.1/32 index 11
! !

View File

@ -1,13 +1,16 @@
log stdout log stdout
interface lo interface lo
ip address 1.1.1.1/32 ip address 192.0.2.1/32
! !
interface r1-gre0 interface r1-gre0
ip address 192.168.0.1/24 ip address 192.168.0.1/24
! !
interface r1-eth1 vrf vrf1
ip address 10.201.0.1/24
!
interface r1-eth0 interface r1-eth0
ip address 10.125.0.1/24 ip address 10.125.0.1/24
! !
interface r1-eth1 vrf vrf1
ip address 10.101.0.1/24
!
interface r1-eth3 vrf vrf3
ip address 10.103.0.1/24
!

View File

@ -1,35 +1,54 @@
router bgp 65500 router bgp 65500
bgp router-id 2.2.2.2 bgp router-id 192.0.2.2
neighbor 10.125.0.1 remote-as 65500 neighbor 10.125.0.1 remote-as 65500
address-family ipv4 unicast address-family ipv4 unicast
no neighbor 10.125.0.1 activate no neighbor 10.125.0.1 activate
exit-address-family exit-address-family
address-family ipv4 vpn address-family ipv4 vpn
neighbor 10.125.0.1 activate neighbor 10.125.0.1 activate
no bgp retain route-target all
exit-address-family exit-address-family
! !
router bgp 65500 vrf vrf1 router bgp 65500 vrf vrf1
bgp router-id 2.2.2.2 bgp router-id 192.0.2.2
address-family ipv4 unicast address-family ipv4 unicast
redistribute connected redistribute connected
label vpn export 102 label vpn export 201
rd vpn export 444:2 rd vpn export 192.0.2.2:1
rt vpn import 53:100 52:100 51:100 rt vpn import 192.0.2.1:100 192.0.2.2:100 192.0.2.2:200
rt vpn export 52:100 rt vpn export 192.0.2.2:100
export vpn export vpn
import vpn import vpn
exit-address-family exit-address-family
! !
router bgp 65500 vrf vrf2 router bgp 65500 vrf vrf2
bgp router-id 2.2.2.2 bgp router-id 192.0.2.2
address-family ipv4 unicast address-family ipv4 unicast
redistribute connected redistribute connected
label vpn export 102 label vpn export 202
rd vpn export 444:3 rd vpn export 192.0.2.2:2
rt vpn both 53:100 52:100 51:100 rt vpn import 192.0.2.1:100 192.0.2.2:100 192.0.2.2:200
rt vpn both 53:100 rt vpn export 192.0.2.2:200
export vpn export vpn
import vpn import vpn
exit-address-family exit-address-family
! !
router bgp 65500 vrf vrf3
bgp router-id 192.0.2.2
address-family ipv4 unicast
redistribute connected
label vpn export 203
rd vpn export 192.0.2.2:3
rt vpn export 192.0.2.2:300
export vpn
exit-address-family
!
router bgp 65500 vrf vrf4
bgp router-id 192.0.2.2
address-family ipv4 unicast
redistribute connected
label vpn export 204
rd vpn export 192.0.2.2:4
rt vpn export 192.0.2.2:400
export vpn
exit-address-family
!

View File

@ -0,0 +1,177 @@
{
"vrfId": 0,
"vrfName": "default",
"routerId":"192.0.2.2",
"defaultLocPrf": 100,
"localAS": 65500,
"routes": {
"routeDistinguishers": {
"192.0.2.1:1": {
"10.101.0.0/24": [
{
"valid": true,
"bestpath": true,
"selectionReason": "First path received",
"pathFrom": "internal",
"prefix": "10.101.0.0",
"prefixLen": 24,
"network": "10.101.0.0/24",
"metric": 0,
"locPrf": 100,
"weight": 0,
"peerId": "10.125.0.1",
"path": "",
"origin": "incomplete",
"nexthops": [
{
"ip": "10.125.0.1",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
]
},
"192.0.2.1:3": {
"10.103.0.0/24": [
{
"valid": true,
"bestpath": true,
"selectionReason": "First path received",
"pathFrom": "internal",
"prefix": "10.103.0.0",
"prefixLen": 24,
"network": "10.103.0.0/24",
"metric": 0,
"locPrf": 100,
"weight": 0,
"peerId": "10.125.0.1",
"path": "",
"origin": "incomplete",
"nexthops": [
{
"ip": "10.125.0.1",
"hostname": "r1",
"afi": "ipv4",
"used": true
}
]
}
]
},
"192.0.2.2:1": {
"10.201.0.0/24": [
{
"valid": true,
"bestpath": true,
"selectionReason": "First path received",
"pathFrom": "external",
"network": "10.201.0.0/24",
"prefixLen": 24,
"prefix": "10.201.0.0",
"metric": 0,
"weight": 32768,
"peerId": "(unspec)",
"path": "",
"origin": "incomplete",
"announceNexthopSelf": true,
"nhVrfName": "vrf1",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r2",
"afi": "ipv4",
"used": true
}
]
}
]
},
"192.0.2.2:2": {
"10.202.0.0/24": [
{
"valid": true,
"bestpath": true,
"selectionReason": "First path received",
"pathFrom": "external",
"network": "10.202.0.0/24",
"prefixLen": 24,
"prefix": "10.202.0.0",
"metric": 0,
"weight": 32768,
"peerId": "(unspec)",
"path": "",
"origin": "incomplete",
"announceNexthopSelf": true,
"nhVrfName": "vrf2",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r2",
"afi": "ipv4",
"used": true
}
]
}
]
},
"192.0.2.2:3": {
"10.203.0.0/24": [
{
"valid": true,
"bestpath": true,
"selectionReason": "First path received",
"pathFrom": "external",
"prefix": "10.203.0.0",
"prefixLen": 24,
"network": "10.203.0.0/24",
"metric": 0,
"weight": 32768,
"peerId": "(unspec)",
"path": "",
"origin": "incomplete",
"announceNexthopSelf": true,
"nhVrfName": "vrf3",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r2",
"afi": "ipv4",
"used": true
}
]
}
]
},
"192.0.2.2:4": {
"10.204.0.0/24": [
{
"valid": true,
"bestpath": true,
"selectionReason": "First path received",
"pathFrom": "external",
"prefix": "10.204.0.0",
"prefixLen": 24,
"network": "10.204.0.0/24",
"metric": 0,
"weight": 32768,
"peerId": "(unspec)",
"path": "",
"origin": "incomplete",
"announceNexthopSelf": true,
"nhVrfName": "vrf4",
"nexthops": [
{
"ip": "0.0.0.0",
"hostname": "r2",
"afi": "ipv4",
"used": true
}
]
}
]
}
}
}
}

View File

@ -0,0 +1,17 @@
{
"routerId":"192.0.2.2",
"as":65500,
"vrfId":0,
"vrfName":"default",
"peerCount":1,
"peers":{
"10.125.0.1":{
"remoteAs":65500,
"localAs":65500,
"version":4,
"state":"Established",
"peerState":"OK"
}
},
"totalPeers":1
}

View File

@ -10,5 +10,5 @@ router isis 1
is-type level-1 is-type level-1
net 49.0002.0000.1995.00 net 49.0002.0000.1995.00
segment-routing on segment-routing on
segment-routing prefix 2.2.2.2/32 index 22 segment-routing prefix 192.0.2.2/32 index 22
! !

View File

@ -1,16 +1,22 @@
log stdout log stdout
interface lo interface lo
ip address 2.2.2.2/32 ip address 192.0.2.2/32
! !
interface r2-gre0 interface r2-gre0
ip address 192.168.0.2/24 ip address 192.168.0.2/24
! !
interface r2-eth1 vrf vrf1
ip address 10.200.0.2/24
!
interface r2-eth2 vrf vrf2
ip address 10.210.0.2/24
!
interface r2-eth0 interface r2-eth0
ip address 10.125.0.2/24 ip address 10.125.0.2/24
! !
interface r2-eth1 vrf vrf1
ip address 10.201.0.2/24
!
interface r2-eth2 vrf vrf2
ip address 10.202.0.2/24
!
interface r2-eth3 vrf vrf3
ip address 10.203.0.1/24
!
interface r2-eth4 vrf vrf4
ip address 10.204.0.1/24
!

View File

@ -17,6 +17,7 @@ import os
import sys import sys
import json import json
from functools import partial from functools import partial
from copy import deepcopy
import pytest import pytest
# Save the Current Working Directory to find configuration files. # Save the Current Working Directory to find configuration files.
@ -34,6 +35,7 @@ from lib.topolog import logger
pytestmark = [pytest.mark.bgpd] pytestmark = [pytest.mark.bgpd]
def build_topo(tgen): def build_topo(tgen):
"Build function" "Build function"
@ -53,41 +55,54 @@ def build_topo(tgen):
switch = tgen.add_switch("s4") switch = tgen.add_switch("s4")
switch.add_link(tgen.gears["r2"]) switch.add_link(tgen.gears["r2"])
switch = tgen.add_switch("s5")
switch.add_link(tgen.gears["r1"])
switch = tgen.add_switch("s6")
switch.add_link(tgen.gears["r2"])
switch = tgen.add_switch("s7")
switch.add_link(tgen.gears["r1"])
switch = tgen.add_switch("s8")
switch.add_link(tgen.gears["r2"])
def _populate_iface(): def _populate_iface():
tgen = get_topogen() tgen = get_topogen()
cmds_list = [ cmds_list = [
'modprobe mpls_router', "modprobe mpls_router",
'echo 100000 > /proc/sys/net/mpls/platform_labels', "echo 100000 > /proc/sys/net/mpls/platform_labels",
'ip link add vrf1 type vrf table 10', "ip link add vrf1 type vrf table 10",
'ip link set dev vrf1 up', "ip link set dev vrf1 up",
'ip link set dev {0}-eth1 master vrf1', "ip link set dev {0}-eth1 master vrf1",
'echo 1 > /proc/sys/net/mpls/conf/vrf1/input', "echo 1 > /proc/sys/net/mpls/conf/vrf1/input",
] "ip link add vrf2 type vrf table 20",
cmds_list_extra = [ "ip link set dev vrf2 up",
'ip link add vrf2 type vrf table 20', "ip link set dev {0}-eth2 master vrf2",
'ip link set dev vrf2 up', "echo 1 > /proc/sys/net/mpls/conf/vrf2/input",
'ip link set dev {0}-eth2 master vrf2', "ip link add vrf3 type vrf table 30",
'echo 1 > /proc/sys/net/mpls/conf/vrf2/input', "ip link set dev vrf3 up",
"ip link set dev {0}-eth3 master vrf3",
"echo 1 > /proc/sys/net/mpls/conf/vrf3/input",
"ip link add vrf4 type vrf table 40",
"ip link set dev vrf4 up",
"ip link set dev {0}-eth4 master vrf4",
"echo 1 > /proc/sys/net/mpls/conf/vrf4/input",
] ]
for cmd in cmds_list: for cmd in cmds_list:
input = cmd.format('r1', '1', '2') input = cmd.format("r1", "1", "2")
logger.info('input: ' + cmd) logger.info("input: " + cmd)
output = tgen.net['r1'].cmd(cmd.format('r1', '1', '2')) output = tgen.net["r1"].cmd(cmd.format("r1", "1", "2"))
logger.info('output: ' + output) logger.info("output: " + output)
for cmd in cmds_list: for cmd in cmds_list:
input = cmd.format('r2', '2', '1') input = cmd.format("r2", "2", "1")
logger.info('input: ' + cmd) logger.info("input: " + cmd)
output = tgen.net['r2'].cmd(cmd.format('r2', '2', '1')) output = tgen.net["r2"].cmd(cmd.format("r2", "2", "1"))
logger.info('output: ' + output) logger.info("output: " + output)
for cmd in cmds_list_extra:
input = cmd.format('r2', '2', '1')
logger.info('input: ' + cmd)
output = tgen.net['r2'].cmd(cmd.format('r2', '2', '1'))
logger.info('output: ' + output)
def setup_module(mod): def setup_module(mod):
"Sets up the pytest environment" "Sets up the pytest environment"
@ -136,70 +151,334 @@ def router_json_cmp_exact_filter(router, cmd, expected):
if "version" in attr: if "version" in attr:
attr.pop("version") attr.pop("version")
# filter out RD with no data (e.g. "444:3": {})
json_tmp = deepcopy(json_output)
for rd, data in json_tmp["routes"]["routeDistinguishers"].items():
if len(data.keys()) == 0:
json_output["routes"]["routeDistinguishers"].pop(rd)
return topotest.json_cmp(json_output, expected, exact=True) return topotest.json_cmp(json_output, expected, exact=True)
def test_bgp_no_retain(): def check_show_bgp_ipv4_vpn(rname, json_file):
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
router = tgen.gears[rname]
logger.info("Checking VPNv4 routes for convergence on {}".format(rname))
json_file = "{}/{}/{}".format(CWD, router.name, json_file)
expected = json.loads(open(json_file).read())
test_func = partial(
router_json_cmp_exact_filter,
router,
"show bgp ipv4 vpn json",
expected,
)
_, result = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
assertmsg = '"{}" JSON output mismatches'.format(router.name)
assert result is None, assertmsg
def test_protocols_convergence_step0():
"""
Assert that all protocols have converged
"""
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
# check that r2 peerings are ok
logger.info("Checking BGP ipv4 vpn summary for r2")
router = tgen.gears["r2"]
json_file = "{}/{}/ipv4_vpn_summary.json".format(CWD, router.name)
expected = json.loads(open(json_file).read())
test_func = partial(
topotest.router_json_cmp,
router,
"show bgp ipv4 vpn summary json",
expected,
)
_, result = topotest.run_and_expect(test_func, None, count=20, wait=0.5)
assertmsg = '"{}" JSON output mismatches'.format(router.name)
assert result is None, assertmsg
def test_bgp_no_retain_step1():
""" """
Check bgp no retain route-target all on r1 Check bgp no retain route-target all on r1
""" """
tgen = get_topogen() rname = "r1"
if tgen.routers_have_failure(): check_show_bgp_ipv4_vpn(rname, "ipv4_vpn_routes_no_retain_init.json")
pytest.skip(tgen.errors) check_show_bgp_ipv4_vpn("r2", "ipv4_vpn_routes_all.json")
# Check IPv4 VPN routing tables on r1
logger.info("Checking VPNv4 routes for convergence on r1")
router = tgen.gears["r1"]
json_file = "{}/{}/ipv4_vpn_routes.json".format(CWD, router.name)
if not os.path.isfile(json_file):
logger.info("skipping file {}".format(json_file))
assert 0, "{} file not found".format(json_file)
return
expected = json.loads(open(json_file).read())
test_func = partial(
router_json_cmp_exact_filter,
router,
"show bgp ipv4 vpn json",
expected,
)
_, result = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
assertmsg = '"{}" JSON output mismatches'.format(router.name)
assert result is None, assertmsg
def test_bgp_retain(): def test_bgp_retain_step2():
""" """
Apply and check bgp retain route-target all on r1 Apply and check bgp retain route-target all on r1
""" """
rname = "r1"
cfg = """
configure
router bgp 65500
address-family ipv4 vpn
bgp retain route-target all
"""
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
router = tgen.gears[rname]
router.vtysh_cmd(cfg)
check_show_bgp_ipv4_vpn(rname, "ipv4_vpn_routes_all.json")
check_show_bgp_ipv4_vpn("r2", "ipv4_vpn_routes_all.json")
def test_bgp_no_retain_step3():
"""
Apply and check no bgp retain route-target all on r1
"""
rname = "r1"
tgen = get_topogen() tgen = get_topogen()
if tgen.routers_have_failure(): if tgen.routers_have_failure():
pytest.skip(tgen.errors) pytest.skip(tgen.errors)
# Check IPv4 VPN routing tables on r1
logger.info("Checking VPNv4 routes on r1 after bgp no retain")
router = tgen.gears["r1"] router = tgen.gears["r1"]
router.vtysh_cmd( router.vtysh_cmd(
"configure\nrouter bgp 65500\naddress-family ipv4 vpn\nbgp retain route-target all\n" "configure\nrouter bgp 65500\naddress-family ipv4 vpn\nno bgp retain route-target all\n"
) )
json_file = "{}/{}/ipv4_vpn_routes_unfiltered.json".format(CWD, router.name)
if not os.path.isfile(json_file):
logger.info("skipping file {}".format(json_file))
assert 0, "{} file not found".format(json_file)
return
expected = json.loads(open(json_file).read()) check_show_bgp_ipv4_vpn(rname, "ipv4_vpn_routes_no_retain_init.json")
test_func = partial( check_show_bgp_ipv4_vpn("r2", "ipv4_vpn_routes_all.json")
router_json_cmp_exact_filter,
router,
"show bgp ipv4 vpn json", def test_bgp_no_retain_add_vrf2_step4():
expected, """
) Add vrf2 on r1 and check bgp vpnv4 table
_, result = topotest.run_and_expect(test_func, None, count=10, wait=0.5) """
assertmsg = '"{}" JSON output mismatches'.format(router.name)
assert result is None, assertmsg rname = "r1"
cfg = """
configure
router bgp 65500 vrf vrf2
bgp router-id 192.0.2.1
address-family ipv4 unicast
redistribute connected
label vpn export 102
rd vpn export 192.0.2.1:200
rt vpn import 192.0.2.2:200
import vpn
exit-address-family
!
"""
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
router = tgen.gears[rname]
router.vtysh_cmd(cfg)
check_show_bgp_ipv4_vpn(rname, "ipv4_vpn_routes_no_retain_init_plus_r2_vrf2.json")
check_show_bgp_ipv4_vpn("r2", "ipv4_vpn_routes_all.json")
def test_bgp_no_retain_unimport_vrf2_step5():
"""
Unimport to vrf2 on r1 and check bgp vpnv4 table
"""
rname = "r1"
cfg = """
configure
router bgp 65500 vrf vrf2
address-family ipv4 unicast
no import vpn
exit-address-family
!
"""
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
router = tgen.gears[rname]
router.vtysh_cmd(cfg)
check_show_bgp_ipv4_vpn(rname, "ipv4_vpn_routes_no_retain_init.json")
check_show_bgp_ipv4_vpn("r2", "ipv4_vpn_routes_all.json")
def test_bgp_no_retain_import_vrf2_step6():
"""
Re-import to vrf2 on r1 and check bgp vpnv4 table
"""
rname = "r1"
cfg = """
configure
router bgp 65500 vrf vrf2
address-family ipv4 unicast
import vpn
exit-address-family
!
"""
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
router = tgen.gears[rname]
router.vtysh_cmd(cfg)
check_show_bgp_ipv4_vpn(rname, "ipv4_vpn_routes_no_retain_init_plus_r2_vrf2.json")
check_show_bgp_ipv4_vpn("r2", "ipv4_vpn_routes_all.json")
def test_bgp_no_retain_import_vrf1_step7():
"""
Import r2 vrf1 into r1 vrf2 and check bgp vpnv4 table
"""
rname = "r1"
cfg = """
configure
router bgp 65500 vrf vrf2
address-family ipv4 unicast
rt vpn import 192.0.2.1:100
exit-address-family
!
"""
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
router = tgen.gears[rname]
router.vtysh_cmd(cfg)
check_show_bgp_ipv4_vpn(rname, "ipv4_vpn_routes_no_retain_init.json")
check_show_bgp_ipv4_vpn("r2", "ipv4_vpn_routes_all.json")
def test_bgp_no_retain_import_vrf3_step8():
"""
Import r2 vrf3 into r1 vrf2 and check bgp vpnv4 table
"""
rname = "r1"
cfg = """
configure
router bgp 65500 vrf vrf2
address-family ipv4 unicast
rt vpn import 192.0.2.2:300
exit-address-family
!
"""
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
router = tgen.gears[rname]
router.vtysh_cmd(cfg)
check_show_bgp_ipv4_vpn(rname, "ipv4_vpn_routes_no_retain_init_plus_r2_vrf3.json")
check_show_bgp_ipv4_vpn("r2", "ipv4_vpn_routes_all.json")
def test_bgp_no_retain_unimport_vrf3_step9():
"""
Un-import r2 vrf3 into r1 vrf2 and check bgp vpnv4 table
"""
rname = "r1"
cfg = """
configure
router bgp 65500 vrf vrf2
address-family ipv4 unicast
no rt vpn import 192.0.2.2:300
exit-address-family
!
"""
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
router = tgen.gears[rname]
router.vtysh_cmd(cfg)
check_show_bgp_ipv4_vpn(rname, "ipv4_vpn_routes_no_retain_init.json")
check_show_bgp_ipv4_vpn("r2", "ipv4_vpn_routes_all.json")
def test_bgp_no_retain_import_vrf3_step10():
"""
Import r2 vrf3 into r1 vrf2 and check bgp vpnv4 table
"""
rname = "r1"
cfg = """
configure
router bgp 65500 vrf vrf2
address-family ipv4 unicast
rt vpn import 192.0.2.2:300
exit-address-family
!
"""
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
router = tgen.gears[rname]
router.vtysh_cmd(cfg)
check_show_bgp_ipv4_vpn(rname, "ipv4_vpn_routes_no_retain_init_plus_r2_vrf3.json")
check_show_bgp_ipv4_vpn("r2", "ipv4_vpn_routes_all.json")
def test_bgp_no_retain_remove_vrf2_step11():
"""
Import r2 vrf3 into r1 vrf2 and check bgp vpnv4 table
"""
rname = "r1"
cfg = """
configure
no router bgp 65500 vrf vrf2
"""
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
router = tgen.gears[rname]
router.vtysh_cmd(cfg)
check_show_bgp_ipv4_vpn(rname, "ipv4_vpn_routes_no_retain_init.json")
check_show_bgp_ipv4_vpn("r2", "ipv4_vpn_routes_all.json")
def test_bgp_retain_step12():
"""
Configure retain and check bgp vpnv4 table
"""
rname = "r1"
cfg = """
configure
router bgp 65500
address-family ipv4 vpn
bgp retain route-target all
"""
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
router = tgen.gears[rname]
router.vtysh_cmd(cfg)
check_show_bgp_ipv4_vpn(rname, "ipv4_vpn_routes_all.json")
check_show_bgp_ipv4_vpn("r2", "ipv4_vpn_routes_all.json")
def test_memory_leak(): def test_memory_leak():