diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index 447a21b5ea..c6c1ef82cd 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -2365,6 +2365,52 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */ 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; +} + 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_mplsvpn.h b/bgpd/bgp_mplsvpn.h index 3922fbcb11..5d9c9f6b6b 100644 --- a/bgpd/bgp_mplsvpn.h +++ b/bgpd/bgp_mplsvpn.h @@ -59,6 +59,10 @@ extern void vpn_leak_to_vrf_withdraw_all(struct bgp *to_bgp, 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_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 155aebc5f9..5285a221e2 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -4169,6 +4169,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. */