From af79038c4be1b5cec7da9f67b81280d6f14e2479 Mon Sep 17 00:00:00 2001 From: Louis Scalbert Date: Wed, 7 Jun 2023 12:46:30 +0200 Subject: [PATCH] bgpd: cleanup un-imported vpn prefix if no retain set After some VRF imports are removed and "no bgp retain route-target all" is set, prefixes that are not imported anymore remain in the BGP table. Parse the BGP table and remove un-imported prefixes in such a case. Signed-off-by: Louis Scalbert --- bgpd/bgp_mplsvpn.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++ bgpd/bgp_mplsvpn.h | 3 +++ bgpd/bgp_vty.c | 9 ++++++-- 3 files changed, 67 insertions(+), 2 deletions(-) diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index c6c1ef82cd..ea82591ced 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -2551,6 +2551,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) { @@ -3755,6 +3800,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; @@ -3833,6 +3879,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 5d9c9f6b6b..23458caf53 100644 --- a/bgpd/bgp_mplsvpn.h +++ b/bgpd/bgp_mplsvpn.h @@ -56,6 +56,9 @@ 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); diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 6d7b745713..7b75c96e2f 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); -- 2.39.5