diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index 33cc836dac..a68167977d 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -611,6 +611,18 @@ static void sid_register(struct bgp *bgp, const struct in6_addr *sid, listnode_add(bgp->srv6_functions, func); } +static void sid_unregister(struct bgp *bgp, const struct in6_addr *sid) +{ + struct listnode *node, *nnode; + struct bgp_srv6_function *func; + + for (ALL_LIST_ELEMENTS(bgp->srv6_functions, node, nnode, func)) + if (sid_same(&func->sid, sid)) { + listnode_delete(bgp->srv6_functions, func); + XFREE(MTYPE_BGP_SRV6_FUNCTION, func); + } +} + static bool sid_exist(struct bgp *bgp, const struct in6_addr *sid) { struct listnode *node; @@ -860,6 +872,69 @@ void ensure_vrf_tovpn_sid(struct bgp *bgp_vpn, struct bgp *bgp_vrf, afi_t afi) return ensure_vrf_tovpn_sid_per_vrf(bgp_vpn, bgp_vrf); } +void delete_vrf_tovpn_sid_per_af(struct bgp *bgp_vpn, struct bgp *bgp_vrf, + afi_t afi) +{ + int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF); + uint32_t tovpn_sid_index = 0; + bool tovpn_sid_auto = false; + + if (debug) + zlog_debug("%s: try to remove SID for vrf %s: afi %s", __func__, + bgp_vrf->name_pretty, afi2str(afi)); + + tovpn_sid_index = bgp_vrf->vpn_policy[afi].tovpn_sid_index; + tovpn_sid_auto = CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags, + BGP_VPN_POLICY_TOVPN_SID_AUTO); + + /* skip when VPN is configured on vrf-instance */ + if (tovpn_sid_index != 0 || tovpn_sid_auto) + return; + + srv6_locator_chunk_free(bgp_vrf->vpn_policy[afi].tovpn_sid_locator); + bgp_vrf->vpn_policy[afi].tovpn_sid_locator = NULL; + + if (bgp_vrf->vpn_policy[afi].tovpn_sid) { + sid_unregister(bgp_vrf, bgp_vrf->vpn_policy[afi].tovpn_sid); + XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->vpn_policy[afi].tovpn_sid); + } + bgp_vrf->vpn_policy[afi].tovpn_sid_transpose_label = 0; +} + +void delete_vrf_tovpn_sid_per_vrf(struct bgp *bgp_vpn, struct bgp *bgp_vrf) +{ + int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF); + uint32_t tovpn_sid_index = 0; + bool tovpn_sid_auto = false; + + if (debug) + zlog_debug("%s: try to remove SID for vrf %s", __func__, + bgp_vrf->name_pretty); + + tovpn_sid_index = bgp_vrf->tovpn_sid_index; + tovpn_sid_auto = + CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VPN_POLICY_TOVPN_SID_AUTO); + + /* skip when VPN is configured on vrf-instance */ + if (tovpn_sid_index != 0 || tovpn_sid_auto) + return; + + srv6_locator_chunk_free(bgp_vrf->tovpn_sid_locator); + bgp_vrf->tovpn_sid_locator = NULL; + + if (bgp_vrf->tovpn_sid) { + sid_unregister(bgp_vrf, bgp_vrf->tovpn_sid); + XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->tovpn_sid); + } + bgp_vrf->tovpn_sid_transpose_label = 0; +} + +void delete_vrf_tovpn_sid(struct bgp *bgp_vpn, struct bgp *bgp_vrf, afi_t afi) +{ + delete_vrf_tovpn_sid_per_af(bgp_vpn, bgp_vrf, afi); + delete_vrf_tovpn_sid_per_vrf(bgp_vpn, bgp_vrf); +} + /* * This function embeds upper `len` bits of `label` in `sid`, * starting at offset `offset` as seen from the MSB of `sid`. diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h index 03d7a0dd2c..7b57e4c75d 100644 --- a/bgpd/bgp_mplsvpn.h +++ b/bgpd/bgp_mplsvpn.h @@ -88,6 +88,10 @@ extern void vpn_leak_zebra_vrf_sid_withdraw_per_af(struct bgp *bgp, afi_t afi); extern void vpn_leak_zebra_vrf_sid_withdraw_per_vrf(struct bgp *bgp); extern int vpn_leak_label_callback(mpls_label_t label, void *lblid, bool alloc); extern void ensure_vrf_tovpn_sid(struct bgp *vpn, struct bgp *vrf, afi_t afi); +extern void delete_vrf_tovpn_sid(struct bgp *vpn, struct bgp *vrf, afi_t afi); +extern void delete_vrf_tovpn_sid_per_af(struct bgp *vpn, struct bgp *vrf, + afi_t afi); +extern void delete_vrf_tovpn_sid_per_vrf(struct bgp *vpn, struct bgp *vrf); extern void ensure_vrf_tovpn_sid_per_af(struct bgp *vpn, struct bgp *vrf, afi_t afi); extern void ensure_vrf_tovpn_sid_per_vrf(struct bgp *vpn, struct bgp *vrf); @@ -258,6 +262,13 @@ static inline void vpn_leak_postchange(enum vpn_policy_direction direction, vpn_leak_zebra_vrf_label_update(bgp_vrf, afi); } + if (bgp_vrf->vpn_policy[afi].tovpn_sid_index == 0 && + !CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags, + BGP_VPN_POLICY_TOVPN_SID_AUTO) && + bgp_vrf->tovpn_sid_index == 0 && + !CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_TOVPN_SID_AUTO)) + delete_vrf_tovpn_sid(bgp_vpn, bgp_vrf, afi); + if (!bgp_vrf->vpn_policy[afi].tovpn_sid && !bgp_vrf->tovpn_sid) ensure_vrf_tovpn_sid(bgp_vpn, bgp_vrf, afi); diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 427ad1b332..f380460a95 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -9068,9 +9068,15 @@ DEFPY (bgp_sid_vpn_export, BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF)); if (no) { - /* implement me */ - vty_out(vty, "It's not implemented\n"); - return CMD_WARNING_CONFIG_FAILED; + /* when per-VRF SID is not set, do nothing */ + if (bgp->tovpn_sid_index == 0 && + !CHECK_FLAG(bgp->vrf_flags, BGP_VRF_TOVPN_SID_AUTO)) + return CMD_SUCCESS; + + sid_idx = 0; + sid_auto = false; + bgp->tovpn_sid_index = 0; + UNSET_FLAG(bgp->vrf_flags, BGP_VRF_TOVPN_SID_AUTO); } if (bgp->vpn_policy[AFI_IP].tovpn_sid_index != 0 || @@ -9113,7 +9119,7 @@ DEFPY (bgp_sid_vpn_export, if (debug) zlog_debug("%s: auto per-vrf sid alloc.", __func__); SET_FLAG(bgp->vrf_flags, BGP_VRF_TOVPN_SID_AUTO); - } else { + } else if (sid_idx != 0) { /* SID allocation index-mode */ if (debug) zlog_debug("%s: idx %ld per-vrf sid alloc.", __func__, @@ -9138,6 +9144,15 @@ ALIAS (af_label_vpn_export, "Between current address-family and vpn\n" "For routes leaked from current address-family to vpn\n") +ALIAS (bgp_sid_vpn_export, + no_bgp_sid_vpn_export_cmd, + "no$no sid vpn per-vrf export", + NO_STR + "sid value for VRF\n" + "Between current vrf and vpn\n" + "sid per-VRF (both IPv4 and IPv6 address families)\n" + "For routes leaked from current vrf to vpn\n") + DEFPY (af_nexthop_vpn_export, af_nexthop_vpn_export_cmd, "[no] nexthop vpn export [$nexthop_su]", @@ -19913,6 +19928,7 @@ void bgp_vty_init(void) install_element(BGP_IPV4_NODE, &af_sid_vpn_export_cmd); install_element(BGP_IPV6_NODE, &af_sid_vpn_export_cmd); install_element(BGP_NODE, &bgp_sid_vpn_export_cmd); + install_element(BGP_NODE, &no_bgp_sid_vpn_export_cmd); bgp_vty_if_init(); }