diff --git a/src/sonic-frr/patch/0068-bgpd-Extend-BGP-to-communicate-with-the-SRv6-SID-Manager-to-allocate-release-SRv6-SIDs.patch b/src/sonic-frr/patch/0068-bgpd-Extend-BGP-to-communicate-with-the-SRv6-SID-Manager-to-allocate-release-SRv6-SIDs.patch new file mode 100644 index 000000000000..df60dfa9404b --- /dev/null +++ b/src/sonic-frr/patch/0068-bgpd-Extend-BGP-to-communicate-with-the-SRv6-SID-Manager-to-allocate-release-SRv6-SIDs.patch @@ -0,0 +1,1126 @@ +From c50b4b9afc2a23369f1fd26e5c8bd47a412fa04f Mon Sep 17 00:00:00 2001 + +From: Carmine Scarpitta + +Subject: [PATCH 01/10] bgpd: Add API to get SRv6 locator info + +Add an API to request information from the SRv6 SID Manager (zebra) +regarding a specific SRv6 locator. + +Signed-off-by: Carmine Scarpitta +--- + bgpd/bgp_mplsvpn.c | 293 +++++++++++++++++++++------------------ + bgpd/bgp_mplsvpn.h | 2 + bgpd/bgp_vty.c | 38 +++-- + bgpd/bgp_zebra.c | 394 ++++++++++++++++++++++++++++++++++++++++++++++++++-- + bgpd/bgp_zebra.h | 7 + + bgpd/bgpd.c | 17 ++ + bgpd/bgpd.h | 5 - + 7 files changed, 588 insertions(+), 168 deletions(-) + +diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c +index ef8ca39e8..29644b19f 100644 +--- a/bgpd/bgp_mplsvpn.c ++++ b/bgpd/bgp_mplsvpn.c +@@ -491,6 +491,7 @@ void vpn_leak_zebra_vrf_sid_withdraw_per_af(struct bgp *bgp, afi_t afi) + { + int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL); + struct seg6local_context seg6localctx = {}; ++ struct srv6_sid_ctx ctx = {}; + + if (bgp->vrf_id == VRF_UNKNOWN) { + if (debug) +@@ -523,6 +524,11 @@ void vpn_leak_zebra_vrf_sid_withdraw_per_af(struct bgp *bgp, afi_t afi) + XFREE(MTYPE_BGP_SRV6_SID, + bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent); + bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent = NULL; ++ ++ ctx.vrf_id = bgp->vrf_id; ++ ctx.behavior = afi == AFI_IP ? ZEBRA_SEG6_LOCAL_ACTION_END_DT4 ++ : ZEBRA_SEG6_LOCAL_ACTION_END_DT6; ++ bgp_zebra_release_srv6_sid(&ctx); + } + + /* +@@ -533,6 +539,7 @@ void vpn_leak_zebra_vrf_sid_withdraw_per_vrf(struct bgp *bgp) + { + int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL); + struct seg6local_context seg6localctx = {}; ++ struct srv6_sid_ctx ctx = {}; + + if (bgp->vrf_id == VRF_UNKNOWN) { + if (debug) +@@ -561,6 +568,10 @@ void vpn_leak_zebra_vrf_sid_withdraw_per_vrf(struct bgp *bgp) + &seg6localctx); + XFREE(MTYPE_BGP_SRV6_SID, bgp->tovpn_zebra_vrf_sid_last_sent); + bgp->tovpn_zebra_vrf_sid_last_sent = NULL; ++ ++ ctx.vrf_id = bgp->vrf_id; ++ ctx.behavior = ZEBRA_SEG6_LOCAL_ACTION_END_DT46; ++ bgp_zebra_release_srv6_sid(&ctx); + } + + /* +@@ -637,8 +648,8 @@ int vpn_leak_label_callback( + return 0; + } + +-static void sid_register(struct bgp *bgp, const struct in6_addr *sid, +- const char *locator_name) ++void sid_register(struct bgp *bgp, const struct in6_addr *sid, ++ const char *locator_name) + { + struct bgp_srv6_function *func; + func = XCALLOC(MTYPE_BGP_SRV6_FUNCTION, +@@ -677,108 +688,97 @@ static bool sid_exist(struct bgp *bgp, const struct in6_addr *sid) + return false; + } + +-/* +- * This function generates a new SID based on bgp->srv6_locator_chunks and +- * index. The locator and generated SID are stored in arguments sid_locator +- * and sid, respectively. ++/** ++ * Return the SRv6 SID value obtained by composing the LOCATOR and FUNCTION. + * +- * if index != 0: try to allocate as index-mode +- * else: try to allocate as auto-mode ++ * @param sid_value SRv6 SID value returned ++ * @param locator Parent locator of the SRv6 SID ++ * @param sid_func Function part of the SID ++ * @return True if success, False otherwise + */ +-static uint32_t alloc_new_sid(struct bgp *bgp, uint32_t index, +- struct srv6_locator_chunk *sid_locator_chunk, +- struct in6_addr *sid) ++static bool srv6_sid_compose(struct in6_addr *sid_value, ++ struct srv6_locator *locator, uint32_t sid_func) + { + int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL); +- struct listnode *node; +- struct srv6_locator_chunk *chunk; +- bool alloced = false; + int label = 0; + uint8_t offset = 0; + uint8_t func_len = 0, shift_len = 0; +- uint32_t index_max = 0; ++ uint32_t sid_func_max = 0; + +- if (!bgp || !sid_locator_chunk || !sid) ++ if (!locator || !sid_value) + return false; + +- for (ALL_LIST_ELEMENTS_RO(bgp->srv6_locator_chunks, node, chunk)) { +- if (chunk->function_bits_length > +- BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH) { +- if (debug) +- zlog_debug( +- "%s: invalid SRv6 Locator chunk (%pFX): Function Length must be less or equal to %d", +- __func__, &chunk->prefix, +- BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH); +- continue; +- } ++ if (locator->function_bits_length > ++ BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH) { ++ if (debug) ++ zlog_debug("%s: invalid SRv6 Locator (%pFX): Function Length must be less or equal to %d", ++ __func__, &locator->prefix, ++ BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH); ++ return false; ++ } + +- index_max = (1 << chunk->function_bits_length) - 1; ++ /* Max value that can be encoded in the Function part of the SID */ ++ sid_func_max = (1 << locator->function_bits_length) - 1; + +- if (index > index_max) { +- if (debug) +- zlog_debug( +- "%s: skipped SRv6 Locator chunk (%pFX): Function Length is too short to support specified index (%u)", +- __func__, &chunk->prefix, index); +- continue; +- } ++ if (sid_func > sid_func_max) { ++ if (debug) ++ zlog_debug("%s: invalid SRv6 Locator (%pFX): Function Length is too short to support specified function (%u)", ++ __func__, &locator->prefix, sid_func); ++ return false; ++ } + +- *sid = chunk->prefix.prefix; +- *sid_locator_chunk = *chunk; +- offset = chunk->block_bits_length + chunk->node_bits_length; +- func_len = chunk->function_bits_length; +- shift_len = BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH - func_len; ++ /** ++ * Let's build the SID value. ++ * sid_value = LOC:FUNC:: ++ */ + +- if (index != 0) { +- label = index << shift_len; +- if (label < MPLS_LABEL_UNRESERVED_MIN) { +- if (debug) +- zlog_debug( +- "%s: skipped to allocate SRv6 SID (%pFX): Label (%u) is too small to use", +- __func__, &chunk->prefix, +- label); +- continue; +- } ++ /* First, we put the locator (LOC) in the most significant bits of sid_value */ ++ *sid_value = locator->prefix.prefix; + +- transpose_sid(sid, label, offset, func_len); +- if (sid_exist(bgp, sid)) +- continue; +- alloced = true; +- break; +- } ++ /* ++ * Then, we compute the offset at which we have to place the function (FUNC). ++ * FUNC will be placed immediately after LOC, i.e. at block_bits_length + node_bits_length ++ */ ++ offset = locator->block_bits_length + locator->node_bits_length; + +- for (uint32_t i = 1; i < index_max; i++) { +- label = i << shift_len; +- if (label < MPLS_LABEL_UNRESERVED_MIN) { +- if (debug) +- zlog_debug( +- "%s: skipped to allocate SRv6 SID (%pFX): Label (%u) is too small to use", +- __func__, &chunk->prefix, +- label); +- continue; +- } +- transpose_sid(sid, label, offset, func_len); +- if (sid_exist(bgp, sid)) +- continue; +- alloced = true; +- break; +- } ++ /* ++ * The FUNC part of the SID is advertised in the label field of SRv6 Service TLV. ++ * (see SID Transposition Scheme, RFC 9252 section #4). ++ * Therefore, we need to encode the FUNC in the most significant bits of the ++ * 20-bit label. ++ */ ++ func_len = locator->function_bits_length; ++ shift_len = BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH - func_len; ++ ++ label = sid_func << shift_len; ++ if (label < MPLS_LABEL_UNRESERVED_MIN) { ++ if (debug) ++ zlog_debug("%s: skipped to allocate SRv6 SID (%pFX): Label (%u) is too small to use", ++ __func__, &locator->prefix, label); ++ return false; + } + +- if (!alloced) +- return 0; ++ if (sid_exist(bgp_get_default(), sid_value)) { ++ zlog_warn("%s: skipped to allocate SRv6 SID (%pFX): SID %pI6 already in use", ++ __func__, &locator->prefix, sid_value); ++ return false; ++ } + +- sid_register(bgp, sid, bgp->srv6_locator_name); +- return label; ++ /* Finally, we put the FUNC in sid_value at the computed offset */ ++ transpose_sid(sid_value, label, offset, func_len); ++ ++ return true; + } + + void ensure_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); +- struct srv6_locator_chunk *tovpn_sid_locator; +- struct in6_addr *tovpn_sid; +- uint32_t tovpn_sid_index = 0, tovpn_sid_transpose_label; ++ struct in6_addr tovpn_sid = {}; ++ uint32_t tovpn_sid_index = 0; + bool tovpn_sid_auto = false; ++ struct srv6_sid_ctx ctx = {}; ++ uint32_t sid_func; + + if (debug) + zlog_debug("%s: try to allocate new SID for vrf %s: afi %s", +@@ -790,10 +790,17 @@ void ensure_vrf_tovpn_sid_per_af(struct bgp *bgp_vpn, struct bgp *bgp_vrf, + + /* + * skip when bgp vpn instance ins't allocated +- * or srv6 locator chunk isn't allocated ++ * or srv6 locator isn't allocated + */ +- if (!bgp_vpn || !bgp_vpn->srv6_locator_chunks) ++ if (!bgp_vpn || !bgp_vpn->srv6_locator) ++ return; ++ ++ if (bgp_vrf->vrf_id == VRF_UNKNOWN) { ++ if (debug) ++ zlog_debug("%s: vrf %s: vrf_id not set, can't set zebra vrf SRv6 SID", ++ __func__, bgp_vrf->name_pretty); + return; ++ } + + tovpn_sid_index = bgp_vrf->vpn_policy[afi].tovpn_sid_index; + tovpn_sid_auto = CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags, +@@ -810,40 +817,34 @@ void ensure_vrf_tovpn_sid_per_af(struct bgp *bgp_vpn, struct bgp *bgp_vrf, + return; + } + +- tovpn_sid_locator = srv6_locator_chunk_alloc(); +- tovpn_sid = XCALLOC(MTYPE_BGP_SRV6_SID, sizeof(struct in6_addr)); +- +- tovpn_sid_transpose_label = alloc_new_sid(bgp_vpn, tovpn_sid_index, +- tovpn_sid_locator, tovpn_sid); ++ if (!tovpn_sid_auto) { ++ if (!srv6_sid_compose(&tovpn_sid, bgp_vpn->srv6_locator, ++ tovpn_sid_index)) { ++ zlog_err("%s: failed to compose sid for vrf %s: afi %s", ++ __func__, bgp_vrf->name_pretty, afi2str(afi)); ++ return; ++ } ++ } + +- if (tovpn_sid_transpose_label == 0) { +- if (debug) +- zlog_debug( +- "%s: not allocated new sid for vrf %s: afi %s", +- __func__, bgp_vrf->name_pretty, afi2str(afi)); +- srv6_locator_chunk_free(&tovpn_sid_locator); +- XFREE(MTYPE_BGP_SRV6_SID, tovpn_sid); ++ ctx.vrf_id = bgp_vrf->vrf_id; ++ ctx.behavior = afi == AFI_IP ? ZEBRA_SEG6_LOCAL_ACTION_END_DT4 ++ : ZEBRA_SEG6_LOCAL_ACTION_END_DT6; ++ if (!bgp_zebra_request_srv6_sid(&ctx, &tovpn_sid, ++ bgp_vpn->srv6_locator_name, &sid_func)) { ++ zlog_err("%s: failed to request sid for vrf %s: afi %s", ++ __func__, bgp_vrf->name_pretty, afi2str(afi)); + return; + } +- +- if (debug) +- zlog_debug("%s: new sid %pI6 allocated for vrf %s: afi %s", +- __func__, tovpn_sid, bgp_vrf->name_pretty, +- afi2str(afi)); +- +- bgp_vrf->vpn_policy[afi].tovpn_sid = tovpn_sid; +- bgp_vrf->vpn_policy[afi].tovpn_sid_locator = tovpn_sid_locator; +- bgp_vrf->vpn_policy[afi].tovpn_sid_transpose_label = +- tovpn_sid_transpose_label; + } + + void ensure_vrf_tovpn_sid_per_vrf(struct bgp *bgp_vpn, struct bgp *bgp_vrf) + { + int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF); +- struct srv6_locator_chunk *tovpn_sid_locator; +- struct in6_addr *tovpn_sid; +- uint32_t tovpn_sid_index = 0, tovpn_sid_transpose_label; ++ struct in6_addr tovpn_sid = {}; ++ uint32_t tovpn_sid_index = 0; + bool tovpn_sid_auto = false; ++ struct srv6_sid_ctx ctx = {}; ++ uint32_t sid_func; + + if (debug) + zlog_debug("%s: try to allocate new SID for vrf %s", __func__, +@@ -855,11 +856,18 @@ void ensure_vrf_tovpn_sid_per_vrf(struct bgp *bgp_vpn, struct bgp *bgp_vrf) + + /* + * skip when bgp vpn instance ins't allocated +- * or srv6 locator chunk isn't allocated ++ * or srv6 locator isn't allocated + */ +- if (!bgp_vpn || !bgp_vpn->srv6_locator_chunks) ++ if (!bgp_vpn || !bgp_vpn->srv6_locator) + return; + ++ if (bgp_vrf->vrf_id == VRF_UNKNOWN) { ++ if (debug) ++ zlog_debug("%s: vrf %s: vrf_id not set, can't set zebra vrf SRv6 SID", ++ __func__, bgp_vrf->name_pretty); ++ return; ++ } ++ + tovpn_sid_index = bgp_vrf->tovpn_sid_index; + tovpn_sid_auto = CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_TOVPN_SID_AUTO); + +@@ -874,28 +882,23 @@ void ensure_vrf_tovpn_sid_per_vrf(struct bgp *bgp_vpn, struct bgp *bgp_vrf) + return; + } + +- tovpn_sid_locator = srv6_locator_chunk_alloc(); +- tovpn_sid = XCALLOC(MTYPE_BGP_SRV6_SID, sizeof(struct in6_addr)); +- +- tovpn_sid_transpose_label = alloc_new_sid(bgp_vpn, tovpn_sid_index, +- tovpn_sid_locator, tovpn_sid); ++ if (!tovpn_sid_auto) { ++ if (!srv6_sid_compose(&tovpn_sid, bgp_vpn->srv6_locator, ++ bgp_vrf->tovpn_sid_index)) { ++ zlog_err("%s: failed to compose new sid for vrf %s", ++ __func__, bgp_vrf->name_pretty); ++ return; ++ } ++ } + +- if (tovpn_sid_transpose_label == 0) { +- if (debug) +- zlog_debug("%s: not allocated new sid for vrf %s", +- __func__, bgp_vrf->name_pretty); +- srv6_locator_chunk_free(&tovpn_sid_locator); +- XFREE(MTYPE_BGP_SRV6_SID, tovpn_sid); ++ ctx.vrf_id = bgp_vrf->vrf_id; ++ ctx.behavior = ZEBRA_SEG6_LOCAL_ACTION_END_DT46; ++ if (!bgp_zebra_request_srv6_sid(&ctx, &tovpn_sid, ++ bgp_vpn->srv6_locator_name, &sid_func)) { ++ zlog_err("%s: failed to request new sid for vrf %s", __func__, ++ bgp_vrf->name_pretty); + return; + } +- +- if (debug) +- zlog_debug("%s: new sid %pI6 allocated for vrf %s", __func__, +- tovpn_sid, bgp_vrf->name_pretty); +- +- bgp_vrf->tovpn_sid = tovpn_sid; +- bgp_vrf->tovpn_sid_locator = tovpn_sid_locator; +- bgp_vrf->tovpn_sid_transpose_label = tovpn_sid_transpose_label; + } + + void ensure_vrf_tovpn_sid(struct bgp *bgp_vpn, struct bgp *bgp_vrf, afi_t afi) +@@ -918,6 +921,7 @@ void delete_vrf_tovpn_sid_per_af(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; ++ struct srv6_sid_ctx ctx = {}; + + if (debug) + zlog_debug("%s: try to remove SID for vrf %s: afi %s", __func__, +@@ -931,9 +935,22 @@ void delete_vrf_tovpn_sid_per_af(struct bgp *bgp_vpn, struct bgp *bgp_vrf, + if (tovpn_sid_index != 0 || tovpn_sid_auto) + return; + +- srv6_locator_chunk_free(&bgp_vrf->vpn_policy[afi].tovpn_sid_locator); ++ if (bgp_vrf->vrf_id == VRF_UNKNOWN) { ++ if (debug) ++ zlog_debug("%s: vrf %s: vrf_id not set, can't set zebra vrf label", ++ __func__, bgp_vrf->name_pretty); ++ return; ++ } ++ ++ srv6_locator_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) { ++ ctx.vrf_id = bgp_vrf->vrf_id; ++ ctx.behavior = afi == AFI_IP ? ZEBRA_SEG6_LOCAL_ACTION_END_DT4 ++ : ZEBRA_SEG6_LOCAL_ACTION_END_DT6; ++ bgp_zebra_release_srv6_sid(&ctx); ++ + sid_unregister(bgp_vpn, bgp_vrf->vpn_policy[afi].tovpn_sid); + XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->vpn_policy[afi].tovpn_sid); + } +@@ -945,6 +962,7 @@ 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; ++ struct srv6_sid_ctx ctx = {}; + + if (debug) + zlog_debug("%s: try to remove SID for vrf %s", __func__, +@@ -958,9 +976,21 @@ void delete_vrf_tovpn_sid_per_vrf(struct bgp *bgp_vpn, struct bgp *bgp_vrf) + if (tovpn_sid_index != 0 || tovpn_sid_auto) + return; + +- srv6_locator_chunk_free(&bgp_vrf->tovpn_sid_locator); ++ if (bgp_vrf->vrf_id == VRF_UNKNOWN) { ++ if (debug) ++ zlog_debug("%s: vrf %s: vrf_id not set, can't set zebra vrf label", ++ __func__, bgp_vrf->name_pretty); ++ return; ++ } ++ ++ srv6_locator_free(bgp_vrf->tovpn_sid_locator); ++ bgp_vrf->tovpn_sid_locator = NULL; + + if (bgp_vrf->tovpn_sid) { ++ ctx.vrf_id = bgp_vrf->vrf_id; ++ ctx.behavior = ZEBRA_SEG6_LOCAL_ACTION_END_DT46; ++ bgp_zebra_release_srv6_sid(&ctx); ++ + sid_unregister(bgp_vpn, bgp_vrf->tovpn_sid); + XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->tovpn_sid); + } +@@ -1829,8 +1859,9 @@ void vpn_leak_from_vrf_update(struct bgp *to_bgp, /* to */ + + /* Set SID for SRv6 VPN */ + if (from_bgp->vpn_policy[afi].tovpn_sid_locator) { +- struct srv6_locator_chunk *locator = ++ struct srv6_locator *locator = + from_bgp->vpn_policy[afi].tovpn_sid_locator; ++ + encode_label( + from_bgp->vpn_policy[afi].tovpn_sid_transpose_label, + &label); +@@ -1871,8 +1902,8 @@ void vpn_leak_from_vrf_update(struct bgp *to_bgp, /* to */ + .tovpn_sid_locator->prefix.prefix, + sizeof(struct in6_addr)); + } else if (from_bgp->tovpn_sid_locator) { +- struct srv6_locator_chunk *locator = +- from_bgp->tovpn_sid_locator; ++ struct srv6_locator *locator = from_bgp->tovpn_sid_locator; ++ + encode_label(from_bgp->tovpn_sid_transpose_label, &label); + static_attr.srv6_l3vpn = + XCALLOC(MTYPE_BGP_SRV6_L3VPN, +diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h +index cd2589996..0593a736d 100644 +--- a/bgpd/bgp_mplsvpn.h ++++ b/bgpd/bgp_mplsvpn.h +@@ -429,6 +429,8 @@ struct bgp_mplsvpn_nh_label_bind_cache *bgp_mplsvpn_nh_label_bind_find( + struct bgp_mplsvpn_nh_label_bind_cache_head *tree, struct prefix *p, + mpls_label_t orig_label); + void bgp_mplsvpn_nexthop_init(void); ++extern void sid_register(struct bgp *bgp, const struct in6_addr *sid, ++ const char *locator_name); + extern void sid_unregister(struct bgp *bgp, const struct in6_addr *sid); + + #endif /* _QUAGGA_BGP_MPLSVPN_H */ +diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c +index 9530a66fc..4b30f087c 100644 +--- a/bgpd/bgp_vty.c ++++ b/bgpd/bgp_vty.c +@@ -298,18 +298,11 @@ static const char *get_afi_safi_json_str(afi_t afi, safi_t safi) + /* unset srv6 locator */ + static int bgp_srv6_locator_unset(struct bgp *bgp) + { +- int ret; + struct listnode *node, *nnode; + struct srv6_locator_chunk *chunk; + struct bgp_srv6_function *func; + struct bgp *bgp_vrf; + +- /* release chunk notification via ZAPI */ +- ret = bgp_zebra_srv6_manager_release_locator_chunk( +- bgp->srv6_locator_name); +- if (ret < 0) +- return -1; +- + /* refresh chunks */ + for (ALL_LIST_ELEMENTS(bgp->srv6_locator_chunks, node, nnode, chunk)) { + listnode_delete(bgp->srv6_locator_chunks, chunk); +@@ -348,20 +341,28 @@ static int bgp_srv6_locator_unset(struct bgp *bgp) + continue; + + /* refresh vpnv4 tovpn_sid_locator */ +- srv6_locator_chunk_free( +- &bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_locator); ++ srv6_locator_free(bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_locator); ++ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_locator = NULL; + + /* refresh vpnv6 tovpn_sid_locator */ +- srv6_locator_chunk_free( +- &bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_locator); ++ srv6_locator_free( ++ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_locator); ++ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_locator = NULL; + + /* refresh per-vrf tovpn_sid_locator */ +- srv6_locator_chunk_free(&bgp_vrf->tovpn_sid_locator); ++ srv6_locator_free(bgp_vrf->tovpn_sid_locator); ++ bgp_vrf->tovpn_sid_locator = NULL; + } + + /* clear locator name */ + memset(bgp->srv6_locator_name, 0, sizeof(bgp->srv6_locator_name)); + ++ /* clear SRv6 locator */ ++ if (bgp->srv6_locator) { ++ srv6_locator_free(bgp->srv6_locator); ++ bgp->srv6_locator = NULL; ++ } ++ + return 0; + } + +@@ -10515,7 +10516,7 @@ DEFPY (bgp_srv6_locator, + snprintf(bgp->srv6_locator_name, + sizeof(bgp->srv6_locator_name), "%s", name); + +- ret = bgp_zebra_srv6_manager_get_locator_chunk(name); ++ ret = bgp_zebra_srv6_manager_get_locator(name); + if (ret < 0) + return CMD_WARNING_CONFIG_FAILED; + +@@ -10566,6 +10567,17 @@ DEFPY (show_bgp_srv6, + return CMD_SUCCESS; + + vty_out(vty, "locator_name: %s\n", bgp->srv6_locator_name); ++ if (bgp->srv6_locator) { ++ vty_out(vty, " prefix: %pFX\n", &bgp->srv6_locator->prefix); ++ vty_out(vty, " block-length: %d\n", ++ bgp->srv6_locator->block_bits_length); ++ vty_out(vty, " node-length: %d\n", ++ bgp->srv6_locator->node_bits_length); ++ vty_out(vty, " func-length: %d\n", ++ bgp->srv6_locator->function_bits_length); ++ vty_out(vty, " arg-length: %d\n", ++ bgp->srv6_locator->argument_bits_length); ++ } + vty_out(vty, "locator_chunks:\n"); + for (ALL_LIST_ELEMENTS_RO(bgp->srv6_locator_chunks, node, chunk)) { + vty_out(vty, "- %pFX\n", &chunk->prefix); +diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c +index d553d3d27..03c0be0bf 100644 +--- a/bgpd/bgp_zebra.c ++++ b/bgpd/bgp_zebra.c +@@ -3359,11 +3359,278 @@ static int bgp_zebra_process_srv6_locator_chunk(ZAPI_CALLBACK_ARGS) + return 0; + } + ++/** ++ * Internal function to process an SRv6 locator ++ * ++ * @param locator The locator to be processed ++ */ ++static int bgp_zebra_process_srv6_locator_internal(struct srv6_locator *locator) ++{ ++ struct bgp *bgp = bgp_get_default(); ++ ++ if (!bgp || !bgp->srv6_enabled || !locator) ++ return -1; ++ ++ /* ++ * Check if the main BGP instance is configured to use the received ++ * locator ++ */ ++ if (strcmp(bgp->srv6_locator_name, locator->name) != 0) { ++ zlog_err("%s: SRv6 Locator name unmatch %s:%s", __func__, ++ bgp->srv6_locator_name, locator->name); ++ return 0; ++ } ++ ++ zlog_info("%s: Received SRv6 locator %s %pFX, loc-block-len=%u, loc-node-len=%u func-len=%u, arg-len=%u", ++ __func__, locator->name, &locator->prefix, ++ locator->block_bits_length, locator->node_bits_length, ++ locator->function_bits_length, locator->argument_bits_length); ++ ++ /* Store the locator in the main BGP instance */ ++ bgp->srv6_locator = srv6_locator_alloc(locator->name); ++ srv6_locator_copy(bgp->srv6_locator, locator); ++ ++ /* ++ * Process VPN-to-VRF and VRF-to-VPN leaks to advertise new locator ++ * and SIDs. ++ */ ++ vpn_leak_postchange_all(); ++ ++ return 0; ++} ++ ++static int bgp_zebra_srv6_sid_notify(ZAPI_CALLBACK_ARGS) ++{ ++ struct bgp *bgp = bgp_get_default(); ++ struct srv6_locator *locator; ++ struct srv6_sid_ctx ctx; ++ struct in6_addr sid_addr; ++ enum zapi_srv6_sid_notify note; ++ struct bgp *bgp_vrf; ++ struct vrf *vrf; ++ struct listnode *node, *nnode; ++ char buf[256]; ++ struct in6_addr *tovpn_sid; ++ struct prefix_ipv6 tmp_prefix; ++ uint32_t sid_func; ++ bool found = false; ++ ++ if (!bgp || !bgp->srv6_enabled) ++ return -1; ++ ++ if (!bgp->srv6_locator) { ++ if (BGP_DEBUG(zebra, ZEBRA)) ++ zlog_debug("%s: ignoring SRv6 SID notify: locator not set", ++ __func__); ++ return -1; ++ } ++ ++ /* Decode the received notification message */ ++ if (!zapi_srv6_sid_notify_decode(zclient->ibuf, &ctx, &sid_addr, ++ &sid_func, NULL, ¬e, NULL)) { ++ zlog_err("%s : error in msg decode", __func__); ++ return -1; ++ } ++ ++ if (BGP_DEBUG(zebra, ZEBRA)) ++ zlog_debug("%s: received SRv6 SID notify: ctx %s sid_value %pI6 %s", ++ __func__, srv6_sid_ctx2str(buf, sizeof(buf), &ctx), ++ &sid_addr, zapi_srv6_sid_notify2str(note)); ++ ++ /* Get the BGP instance for which the SID has been requested, if any */ ++ for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp_vrf)) { ++ vrf = vrf_lookup_by_id(bgp_vrf->vrf_id); ++ if (!vrf) ++ continue; ++ ++ if (vrf->vrf_id == ctx.vrf_id) { ++ found = true; ++ break; ++ } ++ } ++ ++ if (!found) { ++ if (BGP_DEBUG(zebra, ZEBRA)) ++ zlog_debug("%s: ignoring SRv6 SID notify: No VRF suitable for received SID ctx %s sid_value %pI6", ++ __func__, ++ srv6_sid_ctx2str(buf, sizeof(buf), &ctx), ++ &sid_addr); ++ return -1; ++ } ++ ++ /* Handle notification */ ++ switch (note) { ++ case ZAPI_SRV6_SID_ALLOCATED: ++ if (BGP_DEBUG(zebra, ZEBRA)) ++ zlog_debug("SRv6 SID %pI6 %s : ALLOCATED", &sid_addr, ++ srv6_sid_ctx2str(buf, sizeof(buf), &ctx)); ++ ++ /* Verify that the received SID belongs to the configured locator */ ++ tmp_prefix.family = AF_INET6; ++ tmp_prefix.prefixlen = IPV6_MAX_BITLEN; ++ tmp_prefix.prefix = sid_addr; ++ ++ if (!prefix_match((struct prefix *)&bgp->srv6_locator->prefix, ++ (struct prefix *)&tmp_prefix)) ++ return -1; ++ ++ /* Get label */ ++ uint8_t func_len = bgp->srv6_locator->function_bits_length; ++ uint8_t shift_len = BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH - ++ func_len; ++ ++ int label = sid_func << shift_len; ++ ++ /* Un-export VPN to VRF routes */ ++ vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP, bgp, ++ bgp_vrf); ++ vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP6, bgp, ++ bgp_vrf); ++ ++ locator = srv6_locator_alloc(bgp->srv6_locator_name); ++ srv6_locator_copy(locator, bgp->srv6_locator); ++ ++ /* Store SID, locator, and label */ ++ tovpn_sid = XCALLOC(MTYPE_BGP_SRV6_SID, sizeof(struct in6_addr)); ++ *tovpn_sid = sid_addr; ++ if (ctx.behavior == ZEBRA_SEG6_LOCAL_ACTION_END_DT6) { ++ XFREE(MTYPE_BGP_SRV6_SID, ++ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid); ++ srv6_locator_free( ++ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_locator); ++ sid_unregister(bgp, ++ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid); ++ ++ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid = tovpn_sid; ++ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_locator = locator; ++ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_transpose_label = ++ label; ++ } else if (ctx.behavior == ZEBRA_SEG6_LOCAL_ACTION_END_DT4) { ++ XFREE(MTYPE_BGP_SRV6_SID, ++ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid); ++ srv6_locator_free( ++ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_locator); ++ sid_unregister(bgp, ++ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid); ++ ++ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid = tovpn_sid; ++ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_locator = locator; ++ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_transpose_label = ++ label; ++ } else if (ctx.behavior == ZEBRA_SEG6_LOCAL_ACTION_END_DT46) { ++ XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->tovpn_sid); ++ srv6_locator_free(bgp_vrf->tovpn_sid_locator); ++ sid_unregister(bgp, bgp_vrf->tovpn_sid); ++ ++ bgp_vrf->tovpn_sid = tovpn_sid; ++ bgp_vrf->tovpn_sid_locator = locator; ++ bgp_vrf->tovpn_sid_transpose_label = label; ++ } else { ++ srv6_locator_free(locator); ++ if (BGP_DEBUG(zebra, ZEBRA)) ++ zlog_debug("Unsupported behavior. Not assigned SRv6 SID: %s %pI6", ++ srv6_sid_ctx2str(buf, sizeof(buf), ++ &ctx), ++ &sid_addr); ++ return -1; ++ } ++ ++ /* Register the new SID */ ++ sid_register(bgp, tovpn_sid, bgp->srv6_locator_name); ++ ++ /* Export VPN to VRF routes */ ++ vpn_leak_postchange_all(); ++ ++ break; ++ case ZAPI_SRV6_SID_RELEASED: ++ if (BGP_DEBUG(zebra, ZEBRA)) ++ zlog_debug("SRv6 SID %pI6 %s: RELEASED", &sid_addr, ++ srv6_sid_ctx2str(buf, sizeof(buf), &ctx)); ++ ++ /* Un-export VPN to VRF routes */ ++ vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP, bgp, ++ bgp_vrf); ++ vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP6, bgp, ++ bgp_vrf); ++ ++ /* Remove SID, locator, and label */ ++ if (ctx.behavior == ZEBRA_SEG6_LOCAL_ACTION_END_DT6) { ++ XFREE(MTYPE_BGP_SRV6_SID, ++ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid); ++ if (bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_locator) { ++ srv6_locator_free(bgp->vpn_policy[AFI_IP6] ++ .tovpn_sid_locator); ++ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_locator = ++ NULL; ++ } ++ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_transpose_label = ++ 0; ++ ++ /* Unregister the SID */ ++ sid_unregister(bgp, ++ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid); ++ } else if (ctx.behavior == ZEBRA_SEG6_LOCAL_ACTION_END_DT4) { ++ XFREE(MTYPE_BGP_SRV6_SID, ++ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid); ++ if (bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_locator) { ++ srv6_locator_free(bgp->vpn_policy[AFI_IP] ++ .tovpn_sid_locator); ++ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_locator = ++ NULL; ++ } ++ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_transpose_label = ++ 0; ++ ++ /* Unregister the SID */ ++ sid_unregister(bgp, ++ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid); ++ } else if (ctx.behavior == ZEBRA_SEG6_LOCAL_ACTION_END_DT46) { ++ XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->tovpn_sid); ++ if (bgp_vrf->tovpn_sid_locator) { ++ srv6_locator_free(bgp_vrf->tovpn_sid_locator); ++ bgp_vrf->tovpn_sid_locator = NULL; ++ } ++ bgp_vrf->tovpn_sid_transpose_label = 0; ++ ++ /* Unregister the SID */ ++ sid_unregister(bgp, bgp_vrf->tovpn_sid); ++ } else { ++ if (BGP_DEBUG(zebra, ZEBRA)) ++ zlog_debug("Unsupported behavior. Not assigned SRv6 SID: %s %pI6", ++ srv6_sid_ctx2str(buf, sizeof(buf), ++ &ctx), ++ &sid_addr); ++ return -1; ++ } ++ ++ /* Export VPN to VRF routes*/ ++ vpn_leak_postchange_all(); ++ break; ++ case ZAPI_SRV6_SID_FAIL_ALLOC: ++ if (BGP_DEBUG(zebra, ZEBRA)) ++ zlog_debug("SRv6 SID %pI6 %s: Failed to allocate", ++ &sid_addr, ++ srv6_sid_ctx2str(buf, sizeof(buf), &ctx)); ++ ++ /* Error will be logged by zebra module */ ++ break; ++ case ZAPI_SRV6_SID_FAIL_RELEASE: ++ if (BGP_DEBUG(zebra, ZEBRA)) ++ zlog_debug("%s: SRv6 SID %pI6 %s failure to release", ++ __func__, &sid_addr, ++ srv6_sid_ctx2str(buf, sizeof(buf), &ctx)); ++ ++ /* Error will be logged by zebra module */ ++ break; ++ } ++ ++ return 0; ++} ++ + static int bgp_zebra_process_srv6_locator_add(ZAPI_CALLBACK_ARGS) + { + struct srv6_locator loc = {}; + struct bgp *bgp = bgp_get_default(); +- const char *loc_name = bgp->srv6_locator_name; + + if (!bgp || !bgp->srv6_enabled) + return 0; +@@ -3371,10 +3638,7 @@ static int bgp_zebra_process_srv6_locator_add(ZAPI_CALLBACK_ARGS) + if (zapi_srv6_locator_decode(zclient->ibuf, &loc) < 0) + return -1; + +- if (bgp_zebra_srv6_manager_get_locator_chunk(loc_name) < 0) +- return -1; +- +- return 0; ++ return bgp_zebra_process_srv6_locator_internal(&loc); + } + + static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS) +@@ -3382,7 +3646,8 @@ static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS) + struct srv6_locator loc = {}; + struct bgp *bgp = bgp_get_default(); + struct listnode *node, *nnode; +- struct srv6_locator_chunk *chunk, *tovpn_sid_locator; ++ struct srv6_locator_chunk *chunk; ++ struct srv6_locator *tovpn_sid_locator; + struct bgp_srv6_function *func; + struct bgp *bgp_vrf; + struct in6_addr *tovpn_sid; +@@ -3394,6 +3659,12 @@ static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS) + if (zapi_srv6_locator_decode(zclient->ibuf, &loc) < 0) + return -1; + ++ // clear SRv6 locator ++ if (bgp->srv6_locator) { ++ srv6_locator_free(bgp->srv6_locator); ++ bgp->srv6_locator = NULL; ++ } ++ + // refresh chunks + for (ALL_LIST_ELEMENTS(bgp->srv6_locator_chunks, node, nnode, chunk)) + if (prefix_match((struct prefix *)&loc.prefix, +@@ -3470,10 +3741,12 @@ static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS) + tmp_prefi.prefixlen = IPV6_MAX_BITLEN; + tmp_prefi.prefix = tovpn_sid_locator->prefix.prefix; + if (prefix_match((struct prefix *)&loc.prefix, +- (struct prefix *)&tmp_prefi)) +- srv6_locator_chunk_free( +- &bgp_vrf->vpn_policy[AFI_IP] +- .tovpn_sid_locator); ++ (struct prefix *)&tmp_prefi)) { ++ srv6_locator_free(bgp_vrf->vpn_policy[AFI_IP] ++ .tovpn_sid_locator); ++ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_locator = ++ NULL; ++ } + } + + /* refresh vpnv6 tovpn_sid_locator */ +@@ -3484,10 +3757,12 @@ static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS) + tmp_prefi.prefixlen = IPV6_MAX_BITLEN; + tmp_prefi.prefix = tovpn_sid_locator->prefix.prefix; + if (prefix_match((struct prefix *)&loc.prefix, +- (struct prefix *)&tmp_prefi)) +- srv6_locator_chunk_free( +- &bgp_vrf->vpn_policy[AFI_IP6] +- .tovpn_sid_locator); ++ (struct prefix *)&tmp_prefi)) { ++ srv6_locator_free(bgp_vrf->vpn_policy[AFI_IP6] ++ .tovpn_sid_locator); ++ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_locator = ++ NULL; ++ } + } + + /* refresh per-vrf tovpn_sid_locator */ +@@ -3497,9 +3772,10 @@ static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS) + tmp_prefi.prefixlen = IPV6_MAX_BITLEN; + tmp_prefi.prefix = tovpn_sid_locator->prefix.prefix; + if (prefix_match((struct prefix *)&loc.prefix, +- (struct prefix *)&tmp_prefi)) +- srv6_locator_chunk_free( +- &bgp_vrf->tovpn_sid_locator); ++ (struct prefix *)&tmp_prefi)) { ++ srv6_locator_free(bgp_vrf->tovpn_sid_locator); ++ bgp_vrf->tovpn_sid_locator = NULL; ++ } + } + } + +@@ -3536,6 +3812,7 @@ static zclient_handler *const bgp_handlers[] = { + [ZEBRA_SRV6_LOCATOR_DELETE] = bgp_zebra_process_srv6_locator_delete, + [ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK] = + bgp_zebra_process_srv6_locator_chunk, ++ [ZEBRA_SRV6_SID_NOTIFY] = bgp_zebra_srv6_sid_notify, + }; + + static int bgp_if_new_hook(struct interface *ifp) +@@ -4068,6 +4345,89 @@ int bgp_zebra_srv6_manager_release_locator_chunk(const char *name) + return srv6_manager_release_locator_chunk(zclient, name); + } + ++/** ++ * Ask the SRv6 Manager (zebra) about a specific locator ++ * ++ * @param name Locator name ++ * @return 0 on success, -1 otherwise ++ */ ++int bgp_zebra_srv6_manager_get_locator(const char *name) ++{ ++ if (!name) ++ return -1; ++ ++ /* ++ * Send the Get Locator request to the SRv6 Manager and return the ++ * result ++ */ ++ return srv6_manager_get_locator(zclient, name); ++} ++ ++/** ++ * Ask the SRv6 Manager (zebra) to allocate a SID. ++ * ++ * Optionally, it is possible to provide an IPv6 address (sid_value parameter). ++ * ++ * When sid_value is provided, the SRv6 Manager allocates the requested SID ++ * address, if the request can be satisfied (explicit allocation). ++ * ++ * When sid_value is not provided, the SRv6 Manager allocates any available SID ++ * from the provided locator (dynamic allocation). ++ * ++ * @param ctx Context to be associated with the request SID ++ * @param sid_value IPv6 address to be associated with the requested SID (optional) ++ * @param locator_name Name of the locator from which the SID must be allocated ++ * @param sid_func SID Function allocated by the SRv6 Manager. ++ */ ++bool bgp_zebra_request_srv6_sid(const struct srv6_sid_ctx *ctx, ++ struct in6_addr *sid_value, ++ const char *locator_name, uint32_t *sid_func) ++{ ++ int ret; ++ ++ if (!ctx || !locator_name) ++ return false; ++ ++ /* ++ * Send the Get SRv6 SID request to the SRv6 Manager and check the ++ * result ++ */ ++ ret = srv6_manager_get_sid(zclient, ctx, sid_value, locator_name, ++ sid_func); ++ if (ret < 0) { ++ zlog_warn("%s: error getting SRv6 SID!", __func__); ++ return false; ++ } ++ ++ return true; ++} ++ ++/** ++ * Ask the SRv6 Manager (zebra) to release a previously allocated SID. ++ * ++ * This function is used to tell the SRv6 Manager that BGP no longer intends ++ * to use the SID. ++ * ++ * @param ctx Context to be associated with the SID to be released ++ */ ++void bgp_zebra_release_srv6_sid(const struct srv6_sid_ctx *ctx) ++{ ++ int ret; ++ ++ if (!ctx) ++ return; ++ ++ /* ++ * Send the Release SRv6 SID request to the SRv6 Manager and check the ++ * result ++ */ ++ ret = srv6_manager_release_sid(zclient, ctx); ++ if (ret < 0) { ++ zlog_warn("%s: error releasing SRv6 SID!", __func__); ++ return; ++ } ++} ++ + void bgp_zebra_send_nexthop_label(int cmd, mpls_label_t label, + ifindex_t ifindex, vrf_id_t vrf_id, + enum lsp_types_t ltype, struct prefix *p, +diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h +index d0b3351ad..1471770dc 100644 +--- a/bgpd/bgp_zebra.h ++++ b/bgpd/bgp_zebra.h +@@ -120,6 +120,13 @@ extern int bgp_zebra_update(struct bgp *bgp, afi_t afi, safi_t safi, + extern int bgp_zebra_stale_timer_update(struct bgp *bgp); + extern int bgp_zebra_srv6_manager_get_locator_chunk(const char *name); + extern int bgp_zebra_srv6_manager_release_locator_chunk(const char *name); ++extern int bgp_zebra_srv6_manager_get_locator(const char *name); ++extern bool bgp_zebra_request_srv6_sid(const struct srv6_sid_ctx *ctx, ++ struct in6_addr *sid_value, ++ const char *locator_name, ++ uint32_t *sid_func); ++extern void bgp_zebra_release_srv6_sid(const struct srv6_sid_ctx *ctx); ++ + extern void bgp_zebra_send_nexthop_label(int cmd, mpls_label_t label, + ifindex_t index, vrf_id_t vrfid, + enum lsp_types_t ltype, +diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c +index cf52053c4..06a0e0367 100644 +--- a/bgpd/bgpd.c ++++ b/bgpd/bgpd.c +@@ -1478,9 +1478,11 @@ static void bgp_srv6_init(struct bgp *bgp) + static void bgp_srv6_cleanup(struct bgp *bgp) + { + for (afi_t afi = AFI_IP; afi < AFI_MAX; afi++) { +- if (bgp->vpn_policy[afi].tovpn_sid_locator != NULL) +- srv6_locator_chunk_free( +- &bgp->vpn_policy[afi].tovpn_sid_locator); ++ if (bgp->vpn_policy[afi].tovpn_sid_locator != NULL) { ++ srv6_locator_free( ++ bgp->vpn_policy[afi].tovpn_sid_locator); ++ bgp->vpn_policy[afi].tovpn_sid_locator = NULL; ++ } + if (bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent != NULL) + XFREE(MTYPE_BGP_SRV6_SID, + bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent); +@@ -1491,8 +1493,10 @@ static void bgp_srv6_cleanup(struct bgp *bgp) + } + } + +- if (bgp->tovpn_sid_locator != NULL) +- srv6_locator_chunk_free(&bgp->tovpn_sid_locator); ++ if (bgp->tovpn_sid_locator != NULL) { ++ srv6_locator_free(bgp->tovpn_sid_locator); ++ bgp->tovpn_sid_locator = NULL; ++ } + if (bgp->tovpn_zebra_vrf_sid_last_sent != NULL) + XFREE(MTYPE_BGP_SRV6_SID, bgp->tovpn_zebra_vrf_sid_last_sent); + if (bgp->tovpn_sid != NULL) { +@@ -1504,6 +1508,9 @@ static void bgp_srv6_cleanup(struct bgp *bgp) + list_delete(&bgp->srv6_locator_chunks); + if (bgp->srv6_functions) + list_delete(&bgp->srv6_functions); ++ ++ srv6_locator_free(bgp->srv6_locator); ++ bgp->srv6_locator = NULL; + } + + /* Allocate new peer object, implicitely locked. */ +diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h +index 057e26a83..b1feb8bde 100644 +--- a/bgpd/bgpd.h ++++ b/bgpd/bgpd.h +@@ -249,7 +249,7 @@ struct vpn_policy { + */ + uint32_t tovpn_sid_index; /* unset => set to 0 */ + struct in6_addr *tovpn_sid; +- struct srv6_locator_chunk *tovpn_sid_locator; ++ struct srv6_locator *tovpn_sid_locator; + uint32_t tovpn_sid_transpose_label; + struct in6_addr *tovpn_zebra_vrf_sid_last_sent; + }; +@@ -813,11 +813,12 @@ struct bgp { + /* BGP VPN SRv6 backend */ + bool srv6_enabled; + char srv6_locator_name[SRV6_LOCNAME_SIZE]; ++ struct srv6_locator *srv6_locator; + struct list *srv6_locator_chunks; + struct list *srv6_functions; + uint32_t tovpn_sid_index; /* unset => set to 0 */ + struct in6_addr *tovpn_sid; +- struct srv6_locator_chunk *tovpn_sid_locator; ++ struct srv6_locator *tovpn_sid_locator; + uint32_t tovpn_sid_transpose_label; + struct in6_addr *tovpn_zebra_vrf_sid_last_sent; + diff --git a/src/sonic-frr/patch/series b/src/sonic-frr/patch/series index 1eebafcae045..8381f11a0d7b 100644 --- a/src/sonic-frr/patch/series +++ b/src/sonic-frr/patch/series @@ -47,3 +47,4 @@ 0065-zebra-display-srv6-encapsulation-source-address-when-configured.patch 0066-lib-fix-srv6-locator-flags-propagated-to-isis.patch 0067-Add-support-for-SRv6-SID-Manager.patch +0068-bgpd-Extend-BGP-to-communicate-with-the-SRv6-SID-Manager-to-allocate-release-SRv6-SIDs.patch