diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index a439790fd7..068dc44bc6 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -2120,7 +2120,7 @@ static struct bgp *bgp_lookup_by_rd(struct bgp_path_info *bpi, 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_path_info *path_vpn, 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", __func__, from_bgp->name_pretty, 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( "from vpn (%s) to vrf (%s), skipping after no intersection of route targets", from_bgp->name_pretty, to_bgp->name_pretty); - return false; + return; } rd_buf[0] = '\0'; @@ -2194,7 +2194,7 @@ static bool vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */ zlog_debug( "%s: skipping import, match RD (%s) of src VRF (%s) and the prefix (%pFX)", __func__, rd_buf, to_bgp->name_pretty, p); - return false; + return; } if (debug) @@ -2305,7 +2305,7 @@ static bool vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */ to_bgp->vpn_policy[afi] .rmap[BGP_VPN_POLICY_DIR_FROMVPN] ->name); - return false; + return; } /* * 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, debug)) 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; } -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 prefix_rd *prd) { struct listnode *mnode, *mnnode; struct bgp *bgp; - bool leak_success = false; 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 || path_vpn->extra->bgp_orig != bgp) { /* no loop */ - leak_success |= vpn_leak_to_vrf_update_onevrf( - bgp, from_bgp, path_vpn, prd); + vpn_leak_to_vrf_update_onevrf(bgp, from_bgp, path_vpn, + prd); } } - return leak_success; } 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, afi_t afi) { @@ -3717,6 +3804,7 @@ void vpn_leak_postchange_all(void) */ void bgp_vpn_leak_unimport(struct bgp *from_bgp) { + struct bgp *bgp_default = bgp_get_default(); struct bgp *to_bgp; const char *tmp_name; 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; } diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h index 894094fdad..a7f31854f0 100644 --- a/bgpd/bgp_mplsvpn.h +++ b/bgpd/bgp_mplsvpn.h @@ -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_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, 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 prefix_rd *prd); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index ecc08305f0..35b8223644 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -4152,7 +4152,6 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, afi_t nh_afi; bool force_evpn_import = false; safi_t orig_safi = safi; - bool leak_success = true; int allowas_in = 0; 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; } + 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 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) && (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 @@ -4863,13 +4872,6 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, type, sub_type, NULL); } #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; } // 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) && (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 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); } #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; @@ -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", output_cum, total_cum); } else { - if (use_json && output_cum == 0) + if (use_json && output_cum == 0 && json_header_depth == 0) vty_out(vty, "{}\n"); } return CMD_SUCCESS; diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 6a4c7c4e98..66fb7ae77a 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -9954,6 +9954,7 @@ DEFPY (bgp_imexport_vpn, bool yes = true; int flag; enum vpn_policy_direction dir; + struct bgp *bgp_default = bgp_get_default(); if (argv_find(argv, argc, "no", &idx)) yes = false; @@ -9989,14 +9990,18 @@ DEFPY (bgp_imexport_vpn, SET_FLAG(bgp->af_flags[afi][safi], flag); if (!previous_state) { /* trigger export current vrf */ - vpn_leak_postchange(dir, afi, bgp_get_default(), bgp); + vpn_leak_postchange(dir, afi, bgp_default, bgp); } } else { if (previous_state) { /* 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); + 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); diff --git a/tests/topotests/bgp_vpnv4_noretain/r1/bgpd.conf b/tests/topotests/bgp_vpnv4_noretain/r1/bgpd.conf index 3d8773b8bf..0709e43edf 100644 --- a/tests/topotests/bgp_vpnv4_noretain/r1/bgpd.conf +++ b/tests/topotests/bgp_vpnv4_noretain/r1/bgpd.conf @@ -1,8 +1,12 @@ 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 address-family ipv4 unicast 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 address-family ipv4 vpn neighbor 10.125.0.2 activate @@ -10,15 +14,33 @@ router bgp 65500 exit-address-family ! router bgp 65500 vrf vrf1 - bgp router-id 1.1.1.1 + bgp router-id 192.0.2.1 address-family ipv4 unicast redistribute connected label vpn export 101 - rd vpn export 444:1 - rt vpn import 51:100 52:100 - rt vpn export 51:100 + rd vpn export 192.0.2.1:1 + rt vpn import 192.0.2.2:100 + rt vpn export 192.0.2.1:100 export vpn import vpn 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 +! diff --git a/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vpn_routes.json b/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vpn_routes.json deleted file mode 100644 index 28e153e3de..0000000000 --- a/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vpn_routes.json +++ /dev/null @@ -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":{ - } - } - } -} diff --git a/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vpn_routes_all.json b/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vpn_routes_all.json new file mode 100644 index 0000000000..648bf854ba --- /dev/null +++ b/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vpn_routes_all.json @@ -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 + } + ] + } + ] + } + } + } +} diff --git a/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vpn_routes_unfiltered.json b/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vpn_routes_no_retain_init.json similarity index 66% rename from tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vpn_routes_unfiltered.json rename to tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vpn_routes_no_retain_init.json index 45f4acce6f..f01607ac4e 100644 --- a/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vpn_routes_unfiltered.json +++ b/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vpn_routes_no_retain_init.json @@ -1,21 +1,21 @@ { "vrfId":0, "vrfName":"default", - "routerId":"1.1.1.1", + "routerId":"192.0.2.1", "defaultLocPrf":100, "localAS":65500, "routes":{ "routeDistinguishers":{ - "444:1":{ - "10.201.0.0/24":[ + "192.0.2.1:1":{ + "10.101.0.0/24":[ { "valid":true, "bestpath":true, "selectionReason":"First path received", "pathFrom":"external", - "prefix":"10.201.0.0", + "prefix":"10.101.0.0", "prefixLen":24, - "network":"10.201.0.0\/24", + "network":"10.101.0.0\/24", "metric":0, "weight":32768, "peerId":"(unspec)", @@ -34,16 +34,44 @@ } ] }, - "444:2":{ - "10.200.0.0/24":[ + "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.200.0.0", + "prefix":"10.201.0.0", "prefixLen":24, - "network":"10.200.0.0\/24", + "network":"10.201.0.0\/24", "metric":0, "locPrf":100, "weight":0, @@ -61,16 +89,16 @@ } ] }, - "444:3":{ - "10.210.0.0/24":[ + "192.0.2.2:4":{ + "10.204.0.0/24":[ { "valid":true, "bestpath":true, "selectionReason":"First path received", "pathFrom":"internal", - "prefix":"10.210.0.0", + "prefix":"10.204.0.0", "prefixLen":24, - "network":"10.210.0.0\/24", + "network":"10.204.0.0\/24", "metric":0, "locPrf":100, "weight":0, diff --git a/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vpn_routes_no_retain_init_plus_r2_vrf2.json b/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vpn_routes_no_retain_init_plus_r2_vrf2.json new file mode 100644 index 0000000000..6df6c69b8f --- /dev/null +++ b/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vpn_routes_no_retain_init_plus_r2_vrf2.json @@ -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 + } + ] + } + ] + } + } + } +} diff --git a/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vpn_routes_no_retain_init_plus_r2_vrf3.json b/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vpn_routes_no_retain_init_plus_r2_vrf3.json new file mode 100644 index 0000000000..7a17ff0f16 --- /dev/null +++ b/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vpn_routes_no_retain_init_plus_r2_vrf3.json @@ -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 + } + ] + } + ] + } + } + } +} diff --git a/tests/topotests/bgp_vpnv4_noretain/r1/isisd.conf b/tests/topotests/bgp_vpnv4_noretain/r1/isisd.conf index 6f5cb6ec68..233a6473b3 100644 --- a/tests/topotests/bgp_vpnv4_noretain/r1/isisd.conf +++ b/tests/topotests/bgp_vpnv4_noretain/r1/isisd.conf @@ -10,5 +10,5 @@ router isis 1 is-type level-1 net 49.0002.0000.1994.00 segment-routing on - segment-routing prefix 1.1.1.1/32 index 11 + segment-routing prefix 192.0.2.1/32 index 11 ! diff --git a/tests/topotests/bgp_vpnv4_noretain/r1/zebra.conf b/tests/topotests/bgp_vpnv4_noretain/r1/zebra.conf index 5b8b1e8ffb..f99cfafe32 100644 --- a/tests/topotests/bgp_vpnv4_noretain/r1/zebra.conf +++ b/tests/topotests/bgp_vpnv4_noretain/r1/zebra.conf @@ -1,13 +1,16 @@ log stdout interface lo - ip address 1.1.1.1/32 + ip address 192.0.2.1/32 ! interface r1-gre0 ip address 192.168.0.1/24 ! -interface r1-eth1 vrf vrf1 - ip address 10.201.0.1/24 -! interface r1-eth0 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 +! \ No newline at end of file diff --git a/tests/topotests/bgp_vpnv4_noretain/r2/bgpd.conf b/tests/topotests/bgp_vpnv4_noretain/r2/bgpd.conf index 235fb31177..729daef2bc 100644 --- a/tests/topotests/bgp_vpnv4_noretain/r2/bgpd.conf +++ b/tests/topotests/bgp_vpnv4_noretain/r2/bgpd.conf @@ -1,35 +1,54 @@ 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 address-family ipv4 unicast no neighbor 10.125.0.1 activate exit-address-family address-family ipv4 vpn neighbor 10.125.0.1 activate - no bgp retain route-target all exit-address-family ! router bgp 65500 vrf vrf1 - bgp router-id 2.2.2.2 + bgp router-id 192.0.2.2 address-family ipv4 unicast redistribute connected - label vpn export 102 - rd vpn export 444:2 - rt vpn import 53:100 52:100 51:100 - rt vpn export 52:100 + label vpn export 201 + rd vpn export 192.0.2.2:1 + rt vpn import 192.0.2.1:100 192.0.2.2:100 192.0.2.2:200 + rt vpn export 192.0.2.2:100 export vpn import vpn exit-address-family ! router bgp 65500 vrf vrf2 - bgp router-id 2.2.2.2 + bgp router-id 192.0.2.2 address-family ipv4 unicast redistribute connected - label vpn export 102 - rd vpn export 444:3 - rt vpn both 53:100 52:100 51:100 - rt vpn both 53:100 + label vpn export 202 + rd vpn export 192.0.2.2:2 + rt vpn import 192.0.2.1:100 192.0.2.2:100 192.0.2.2:200 + rt vpn export 192.0.2.2:200 export vpn import vpn 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 +! diff --git a/tests/topotests/bgp_vpnv4_noretain/r2/ipv4_vpn_routes_all.json b/tests/topotests/bgp_vpnv4_noretain/r2/ipv4_vpn_routes_all.json new file mode 100644 index 0000000000..d8b8e88d93 --- /dev/null +++ b/tests/topotests/bgp_vpnv4_noretain/r2/ipv4_vpn_routes_all.json @@ -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 + } + ] + } + ] + } + } + } +} diff --git a/tests/topotests/bgp_vpnv4_noretain/r2/ipv4_vpn_summary.json b/tests/topotests/bgp_vpnv4_noretain/r2/ipv4_vpn_summary.json new file mode 100644 index 0000000000..a4408f1915 --- /dev/null +++ b/tests/topotests/bgp_vpnv4_noretain/r2/ipv4_vpn_summary.json @@ -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 +} diff --git a/tests/topotests/bgp_vpnv4_noretain/r2/isisd.conf b/tests/topotests/bgp_vpnv4_noretain/r2/isisd.conf index cbec8c3674..547d10f2bc 100644 --- a/tests/topotests/bgp_vpnv4_noretain/r2/isisd.conf +++ b/tests/topotests/bgp_vpnv4_noretain/r2/isisd.conf @@ -10,5 +10,5 @@ router isis 1 is-type level-1 net 49.0002.0000.1995.00 segment-routing on - segment-routing prefix 2.2.2.2/32 index 22 + segment-routing prefix 192.0.2.2/32 index 22 ! diff --git a/tests/topotests/bgp_vpnv4_noretain/r2/zebra.conf b/tests/topotests/bgp_vpnv4_noretain/r2/zebra.conf index 7ec644ac2a..f19ad9d3e8 100644 --- a/tests/topotests/bgp_vpnv4_noretain/r2/zebra.conf +++ b/tests/topotests/bgp_vpnv4_noretain/r2/zebra.conf @@ -1,16 +1,22 @@ log stdout interface lo - ip address 2.2.2.2/32 + ip address 192.0.2.2/32 ! interface r2-gre0 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 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 +! diff --git a/tests/topotests/bgp_vpnv4_noretain/test_bgp_vpnv4_noretain.py b/tests/topotests/bgp_vpnv4_noretain/test_bgp_vpnv4_noretain.py index 9b8ae4b7e3..f665040f7f 100644 --- a/tests/topotests/bgp_vpnv4_noretain/test_bgp_vpnv4_noretain.py +++ b/tests/topotests/bgp_vpnv4_noretain/test_bgp_vpnv4_noretain.py @@ -17,6 +17,7 @@ import os import sys import json from functools import partial +from copy import deepcopy import pytest # Save the Current Working Directory to find configuration files. @@ -34,6 +35,7 @@ from lib.topolog import logger pytestmark = [pytest.mark.bgpd] + def build_topo(tgen): "Build function" @@ -53,41 +55,54 @@ def build_topo(tgen): switch = tgen.add_switch("s4") 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(): tgen = get_topogen() cmds_list = [ - 'modprobe mpls_router', - 'echo 100000 > /proc/sys/net/mpls/platform_labels', - 'ip link add vrf1 type vrf table 10', - 'ip link set dev vrf1 up', - 'ip link set dev {0}-eth1 master vrf1', - 'echo 1 > /proc/sys/net/mpls/conf/vrf1/input', + "modprobe mpls_router", + "echo 100000 > /proc/sys/net/mpls/platform_labels", + "ip link add vrf1 type vrf table 10", + "ip link set dev vrf1 up", + "ip link set dev {0}-eth1 master vrf1", + "echo 1 > /proc/sys/net/mpls/conf/vrf1/input", + "ip link add vrf2 type vrf table 20", + "ip link set dev vrf2 up", + "ip link set dev {0}-eth2 master vrf2", + "echo 1 > /proc/sys/net/mpls/conf/vrf2/input", + "ip link add vrf3 type vrf table 30", + "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", ] - cmds_list_extra = [ - 'ip link add vrf2 type vrf table 20', - 'ip link set dev vrf2 up', - 'ip link set dev {0}-eth2 master vrf2', - 'echo 1 > /proc/sys/net/mpls/conf/vrf2/input', - ] - - for cmd in cmds_list: - input = cmd.format('r1', '1', '2') - logger.info('input: ' + cmd) - output = tgen.net['r1'].cmd(cmd.format('r1', '1', '2')) - logger.info('output: ' + output) for cmd in cmds_list: - input = cmd.format('r2', '2', '1') - logger.info('input: ' + cmd) - output = tgen.net['r2'].cmd(cmd.format('r2', '2', '1')) - logger.info('output: ' + output) + input = cmd.format("r1", "1", "2") + logger.info("input: " + cmd) + output = tgen.net["r1"].cmd(cmd.format("r1", "1", "2")) + logger.info("output: " + output) + + for cmd in cmds_list: + input = cmd.format("r2", "2", "1") + logger.info("input: " + cmd) + output = tgen.net["r2"].cmd(cmd.format("r2", "2", "1")) + logger.info("output: " + output) - 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): "Sets up the pytest environment" @@ -96,7 +111,7 @@ def setup_module(mod): tgen.start_topology() router_list = tgen.routers() - _populate_iface() + _populate_iface() for rname, router in router_list.items(): router.load_config( @@ -136,70 +151,334 @@ def router_json_cmp_exact_filter(router, cmd, expected): if "version" in attr: 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) -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 """ - tgen = get_topogen() - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # 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 + rname = "r1" + 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(): +def test_bgp_retain_step2(): """ 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() if tgen.routers_have_failure(): 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.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()) - 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 + 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_add_vrf2_step4(): + """ + Add vrf2 on r1 and check bgp vpnv4 table + """ + + 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():