mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-14 16:04:49 +00:00
Merge pull request #15676 from cscarpitta/bgp-srv6-sid-manager
bgpd: Extend BGP to communicate with the SRv6 SID Manager to allocate/release SRv6 SIDs
This commit is contained in:
commit
5d9ddcce7c
@ -474,6 +474,7 @@ void vpn_leak_zebra_vrf_sid_update(struct bgp *bgp, afi_t afi)
|
||||
void vpn_leak_zebra_vrf_sid_withdraw_per_af(struct bgp *bgp, afi_t afi)
|
||||
{
|
||||
int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL);
|
||||
struct srv6_sid_ctx ctx = {};
|
||||
|
||||
if (bgp->vrf_id == VRF_UNKNOWN) {
|
||||
if (debug)
|
||||
@ -492,6 +493,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);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -501,6 +507,7 @@ void vpn_leak_zebra_vrf_sid_withdraw_per_af(struct bgp *bgp, afi_t afi)
|
||||
void vpn_leak_zebra_vrf_sid_withdraw_per_vrf(struct bgp *bgp)
|
||||
{
|
||||
int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL);
|
||||
struct srv6_sid_ctx ctx = {};
|
||||
|
||||
if (bgp->vrf_id == VRF_UNKNOWN) {
|
||||
if (debug)
|
||||
@ -519,6 +526,10 @@ void vpn_leak_zebra_vrf_sid_withdraw_per_vrf(struct bgp *bgp)
|
||||
NULL);
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -595,7 +606,7 @@ int vpn_leak_label_callback(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sid_register(struct bgp *bgp, const struct in6_addr *sid,
|
||||
void sid_register(struct bgp *bgp, const struct in6_addr *sid,
|
||||
const char *locator_name)
|
||||
{
|
||||
struct bgp_srv6_function *func;
|
||||
@ -635,108 +646,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 >
|
||||
if (locator->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,
|
||||
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);
|
||||
continue;
|
||||
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 (sid_func > sid_func_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;
|
||||
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;
|
||||
/**
|
||||
* Let's build the SID value.
|
||||
* sid_value = LOC:FUNC::
|
||||
*/
|
||||
|
||||
/* First, we put the locator (LOC) in the most significant bits of sid_value */
|
||||
*sid_value = locator->prefix.prefix;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
if (index != 0) {
|
||||
label = index << shift_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__, &chunk->prefix,
|
||||
label);
|
||||
continue;
|
||||
zlog_debug("%s: skipped to allocate SRv6 SID (%pFX): Label (%u) is too small to use",
|
||||
__func__, &locator->prefix, label);
|
||||
return false;
|
||||
}
|
||||
|
||||
transpose_sid(sid, label, offset, func_len);
|
||||
if (sid_exist(bgp, sid))
|
||||
continue;
|
||||
alloced = true;
|
||||
break;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
/* Finally, we put the FUNC in sid_value at the computed offset */
|
||||
transpose_sid(sid_value, label, offset, func_len);
|
||||
|
||||
if (!alloced)
|
||||
return 0;
|
||||
|
||||
sid_register(bgp, sid, bgp->srv6_locator_name);
|
||||
return label;
|
||||
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",
|
||||
@ -748,11 +748,18 @@ 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,
|
||||
BGP_VPN_POLICY_TOVPN_SID_AUTO);
|
||||
@ -768,40 +775,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_transpose_label == 0) {
|
||||
if (debug)
|
||||
zlog_debug(
|
||||
"%s: not allocated new sid for vrf %s: afi %s",
|
||||
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));
|
||||
srv6_locator_chunk_free(&tovpn_sid_locator);
|
||||
XFREE(MTYPE_BGP_SRV6_SID, tovpn_sid);
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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__,
|
||||
@ -813,11 +814,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);
|
||||
|
||||
@ -832,28 +840,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_transpose_label == 0) {
|
||||
if (debug)
|
||||
zlog_debug("%s: not allocated new sid for vrf %s",
|
||||
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);
|
||||
srv6_locator_chunk_free(&tovpn_sid_locator);
|
||||
XFREE(MTYPE_BGP_SRV6_SID, tovpn_sid);
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void ensure_vrf_tovpn_sid(struct bgp *bgp_vpn, struct bgp *bgp_vrf, afi_t afi)
|
||||
@ -876,6 +879,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__,
|
||||
@ -889,9 +893,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);
|
||||
}
|
||||
@ -903,6 +920,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__,
|
||||
@ -916,9 +934,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);
|
||||
}
|
||||
@ -1763,8 +1793,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);
|
||||
@ -1805,8 +1836,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,
|
||||
|
@ -419,6 +419,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 */
|
||||
|
@ -302,18 +302,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);
|
||||
@ -352,20 +345,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;
|
||||
}
|
||||
|
||||
@ -10878,7 +10879,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;
|
||||
|
||||
@ -10929,6 +10930,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);
|
||||
|
390
bgpd/bgp_zebra.c
390
bgpd/bgp_zebra.c
@ -3379,11 +3379,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;
|
||||
@ -3391,10 +3658,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)
|
||||
@ -3402,7 +3666,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;
|
||||
@ -3414,6 +3679,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,
|
||||
@ -3490,10 +3761,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]
|
||||
(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 */
|
||||
@ -3504,10 +3777,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]
|
||||
(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 */
|
||||
@ -3517,9 +3792,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3556,6 +3832,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)
|
||||
@ -4093,6 +4370,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,
|
||||
|
@ -117,6 +117,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,
|
||||
|
17
bgpd/bgpd.c
17
bgpd/bgpd.c
@ -1497,9 +1497,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);
|
||||
@ -1510,8 +1512,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) {
|
||||
@ -1523,6 +1527,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. */
|
||||
|
@ -270,7 +270,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;
|
||||
};
|
||||
@ -836,11 +836,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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user