Skip to content

SRv6: Add support for multiple SRv6 locators #18806

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions bgpd/bgp_mplsvpn.c
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,7 @@ void vpn_leak_zebra_vrf_sid_withdraw_per_af(struct bgp *bgp, afi_t afi)
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);
bgp_zebra_release_srv6_sid(&ctx, bgp->vpn_policy[afi].tovpn_sid_locator->name);
}

/*
Expand Down Expand Up @@ -576,7 +576,7 @@ void vpn_leak_zebra_vrf_sid_withdraw_per_vrf(struct bgp *bgp)

ctx.vrf_id = bgp->vrf_id;
ctx.behavior = ZEBRA_SEG6_LOCAL_ACTION_END_DT46;
bgp_zebra_release_srv6_sid(&ctx);
bgp_zebra_release_srv6_sid(&ctx, bgp->tovpn_sid_locator->name);
}

/*
Expand Down Expand Up @@ -963,19 +963,19 @@ void delete_vrf_tovpn_sid_per_af(struct bgp *bgp_vpn, struct bgp *bgp_vrf,
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);
bgp_zebra_release_srv6_sid(&ctx, bgp_vrf->vpn_policy[afi].tovpn_sid_locator->name);

sid_unregister(bgp_vpn, 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;

srv6_locator_free(bgp_vrf->vpn_policy[afi].tovpn_sid_locator);
bgp_vrf->vpn_policy[afi].tovpn_sid_locator = NULL;
}

void delete_vrf_tovpn_sid_per_vrf(struct bgp *bgp_vpn, struct bgp *bgp_vrf)
Expand Down Expand Up @@ -1006,13 +1006,10 @@ void delete_vrf_tovpn_sid_per_vrf(struct bgp *bgp_vpn, struct bgp *bgp_vrf)
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);
bgp_zebra_release_srv6_sid(&ctx, bgp_vrf->tovpn_sid_locator->name);

sid_unregister(bgp_vpn, bgp_vrf->tovpn_sid);
XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->tovpn_sid);
Expand All @@ -1021,6 +1018,9 @@ void delete_vrf_tovpn_sid_per_vrf(struct bgp *bgp_vpn, struct bgp *bgp_vrf)
XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->tovpn_sid_explicit);
}
bgp_vrf->tovpn_sid_transpose_label = 0;

srv6_locator_free(bgp_vrf->tovpn_sid_locator);
bgp_vrf->tovpn_sid_locator = NULL;
}

void delete_vrf_tovpn_sid(struct bgp *bgp_vpn, struct bgp *bgp_vrf, afi_t afi)
Expand Down
9 changes: 4 additions & 5 deletions bgpd/bgp_zebra.c
Original file line number Diff line number Diff line change
Expand Up @@ -4543,8 +4543,7 @@ bool bgp_zebra_request_srv6_sid(const struct srv6_sid_ctx *ctx,
* Send the Get SRv6 SID request to the SRv6 Manager and check the
* result
*/
ret = srv6_manager_get_sid(bgp_zclient, ctx, sid_value, locator_name,
sid_func);
ret = srv6_manager_get_sid(bgp_zclient, ctx, sid_value, locator_name, sid_func, false);
if (ret < 0) {
zlog_warn("%s: error getting SRv6 SID!", __func__);
return false;
Expand All @@ -4561,18 +4560,18 @@ bool bgp_zebra_request_srv6_sid(const struct srv6_sid_ctx *ctx,
*
* @param ctx Context to be associated with the SID to be released
*/
void bgp_zebra_release_srv6_sid(const struct srv6_sid_ctx *ctx)
void bgp_zebra_release_srv6_sid(const struct srv6_sid_ctx *ctx, const char *locator_name)
{
int ret;

if (!ctx)
if (!ctx || !locator_name)
return;

/*
* Send the Release SRv6 SID request to the SRv6 Manager and check the
* result
*/
ret = srv6_manager_release_sid(bgp_zclient, ctx);
ret = srv6_manager_release_sid(bgp_zclient, ctx, locator_name, false);
if (ret < 0) {
zlog_warn("%s: error releasing SRv6 SID!", __func__);
return;
Expand Down
2 changes: 1 addition & 1 deletion bgpd/bgp_zebra.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ 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_release_srv6_sid(const struct srv6_sid_ctx *ctx, const char *locator_name);

extern void bgp_zebra_send_nexthop_label(int cmd, mpls_label_t label,
ifindex_t index, vrf_id_t vrfid,
Expand Down
4 changes: 2 additions & 2 deletions isisd/isis_srv6.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ bool isis_srv6_locator_unset(struct isis_area *area)
* and release/free the SID context if it is not yes by other protocols.
*/
ctx.behavior = ZEBRA_SEG6_LOCAL_ACTION_END;
isis_zebra_release_srv6_sid(&ctx);
isis_zebra_release_srv6_sid(&ctx, area->srv6db.config.srv6_locator_name);

listnode_delete(area->srv6db.srv6_sids, sid);
isis_srv6_sid_free(sid);
Expand All @@ -143,7 +143,7 @@ bool isis_srv6_locator_unset(struct isis_area *area)
ctx.behavior = ZEBRA_SEG6_LOCAL_ACTION_END_X;
ctx.nh6 = sra->nexthop;
ctx.ifindex = sra->adj->circuit->interface->ifindex;
isis_zebra_release_srv6_sid(&ctx);
isis_zebra_release_srv6_sid(&ctx, area->srv6db.config.srv6_locator_name);

srv6_endx_sid_del(sra);
}
Expand Down
8 changes: 4 additions & 4 deletions isisd/isis_zebra.c
Original file line number Diff line number Diff line change
Expand Up @@ -1462,7 +1462,7 @@ bool isis_zebra_request_srv6_sid(const struct srv6_sid_ctx *ctx,
* Send the Get SRv6 SID request to the SRv6 Manager and check the
* result
*/
ret = srv6_manager_get_sid(isis_zclient, ctx, sid_value, locator_name, NULL);
ret = srv6_manager_get_sid(isis_zclient, ctx, sid_value, locator_name, NULL, false);
if (ret < 0) {
zlog_warn("%s: error getting SRv6 SID!", __func__);
return false;
Expand All @@ -1479,18 +1479,18 @@ bool isis_zebra_request_srv6_sid(const struct srv6_sid_ctx *ctx,
*
* @param ctx Context to be associated with the SID to be released
*/
void isis_zebra_release_srv6_sid(const struct srv6_sid_ctx *ctx)
void isis_zebra_release_srv6_sid(const struct srv6_sid_ctx *ctx, const char *locator_name)
{
int ret;

if (!ctx)
if (!ctx || !locator_name)
return;

/*
* Send the Release SRv6 SID request to the SRv6 Manager and check the
* result
*/
ret = srv6_manager_release_sid(isis_zclient, ctx);
ret = srv6_manager_release_sid(isis_zclient, ctx, locator_name, false);
if (ret < 0) {
zlog_warn("%s: error releasing SRv6 SID!", __func__);
return;
Expand Down
2 changes: 1 addition & 1 deletion isisd/isis_zebra.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,6 @@ extern void isis_zebra_request_srv6_sid_endx(struct isis_adjacency *adj);
extern bool isis_zebra_request_srv6_sid(const struct srv6_sid_ctx *ctx,
struct in6_addr *sid_value,
const char *locator_name);
extern void isis_zebra_release_srv6_sid(const struct srv6_sid_ctx *ctx);
extern void isis_zebra_release_srv6_sid(const struct srv6_sid_ctx *ctx, const char *locator_name);

#endif /* _ZEBRA_ISIS_ZEBRA_H */
26 changes: 22 additions & 4 deletions lib/zclient.c
Original file line number Diff line number Diff line change
Expand Up @@ -3526,8 +3526,8 @@ int srv6_manager_get_locator(struct zclient *zclient, const char *locator_name)
* @result 0 on success, -1 otherwise
*/
int srv6_manager_get_sid(struct zclient *zclient, const struct srv6_sid_ctx *ctx,
struct in6_addr *sid_value, const char *locator_name,
uint32_t *sid_func)
struct in6_addr *sid_value, const char *locator_name, uint32_t *sid_func,
bool is_localonly)
{
struct stream *s;
uint8_t flags = 0;
Expand Down Expand Up @@ -3558,6 +3558,8 @@ int srv6_manager_get_sid(struct zclient *zclient, const struct srv6_sid_ctx *ctx
SET_FLAG(flags, ZAPI_SRV6_MANAGER_SID_FLAG_HAS_SID_VALUE);
if (locator_name)
SET_FLAG(flags, ZAPI_SRV6_MANAGER_SID_FLAG_HAS_LOCATOR);
if (is_localonly)
SET_FLAG(flags, ZAPI_SRV6_MANAGER_SID_FLAG_IS_LOCALONLY);
stream_putc(s, flags);

/* SRv6 SID value */
Expand Down Expand Up @@ -3585,10 +3587,12 @@ int srv6_manager_get_sid(struct zclient *zclient, const struct srv6_sid_ctx *ctx
* @param ctx Context associated with the SRv6 SID to be removed
* @result 0 on success, -1 otherwise
*/
int srv6_manager_release_sid(struct zclient *zclient,
const struct srv6_sid_ctx *ctx)
int srv6_manager_release_sid(struct zclient *zclient, const struct srv6_sid_ctx *ctx,
const char *locator_name, bool is_localonly)
{
struct stream *s;
uint8_t flags = 0;
size_t len;
char buf[256];

if (zclient->sock < 0) {
Expand All @@ -3611,6 +3615,20 @@ int srv6_manager_release_sid(struct zclient *zclient,
/* Context associated with the SRv6 SID */
stream_put(s, ctx, sizeof(struct srv6_sid_ctx));

/* Flags */
if (locator_name)
SET_FLAG(flags, ZAPI_SRV6_MANAGER_SID_FLAG_HAS_LOCATOR);
if (is_localonly)
SET_FLAG(flags, ZAPI_SRV6_MANAGER_SID_FLAG_IS_LOCALONLY);
stream_putc(s, flags);

/* SRv6 locator */
if (CHECK_FLAG(flags, ZAPI_SRV6_MANAGER_SID_FLAG_HAS_LOCATOR)) {
len = strlen(locator_name);
stream_putw(s, len);
stream_put(s, locator_name, len);
}

/* Put length at the first point of the stream. */
stream_putw_at(s, 0, stream_get_endp(s));

Expand Down
12 changes: 6 additions & 6 deletions lib/zclient.h
Original file line number Diff line number Diff line change
Expand Up @@ -1114,19 +1114,19 @@ extern int tm_release_table_chunk(struct zclient *zclient, uint32_t start,
/* Zebra SRv6 Manager flags */
#define ZAPI_SRV6_MANAGER_SID_FLAG_HAS_SID_VALUE 0x01
#define ZAPI_SRV6_MANAGER_SID_FLAG_HAS_LOCATOR 0x02
#define ZAPI_SRV6_MANAGER_SID_FLAG_IS_LOCALONLY 0x04

extern int srv6_manager_get_locator_chunk(struct zclient *zclient,
const char *locator_name);
extern int srv6_manager_release_locator_chunk(struct zclient *zclient,
const char *locator_name);
extern int srv6_manager_get_locator(struct zclient *zclient,
const char *locator_name);
extern int srv6_manager_get_sid(struct zclient *zclient,
const struct srv6_sid_ctx *ctx,
struct in6_addr *sid_value,
const char *locator_name, uint32_t *sid_func);
extern int srv6_manager_release_sid(struct zclient *zclient,
const struct srv6_sid_ctx *ctx);
extern int srv6_manager_get_sid(struct zclient *zclient, const struct srv6_sid_ctx *ctx,
struct in6_addr *sid_value, const char *locator_name,
uint32_t *sid_func, bool is_localonly);
extern int srv6_manager_release_sid(struct zclient *zclient, const struct srv6_sid_ctx *ctx,
const char *locator_name, bool is_localonly);

extern enum zclient_send_status zebra_send_sr_policy(struct zclient *zclient,
int cmd,
Expand Down
36 changes: 28 additions & 8 deletions staticd/static_zebra.c
Original file line number Diff line number Diff line change
Expand Up @@ -654,14 +654,10 @@ void static_zebra_srv6_sid_install(struct static_srv6_sid *sid)
action = ZEBRA_SEG6_LOCAL_ACTION_END;
SET_SRV6_FLV_OP(ctx.flv.flv_ops, ZEBRA_SEG6_LOCAL_FLV_OP_NEXT_CSID);
SET_SRV6_FLV_OP(ctx.flv.flv_ops, ZEBRA_SEG6_LOCAL_FLV_OP_PSP);
ctx.flv.lcblock_len = sid->locator->block_bits_length;
ctx.flv.lcnode_func_len = sid->locator->node_bits_length;
break;
case SRV6_ENDPOINT_BEHAVIOR_END_NEXT_CSID:
action = ZEBRA_SEG6_LOCAL_ACTION_END;
SET_SRV6_FLV_OP(ctx.flv.flv_ops, ZEBRA_SEG6_LOCAL_FLV_OP_NEXT_CSID);
ctx.flv.lcblock_len = sid->locator->block_bits_length;
ctx.flv.lcnode_func_len = sid->locator->node_bits_length;
break;
case SRV6_ENDPOINT_BEHAVIOR_END_DT6:
action = ZEBRA_SEG6_LOCAL_ACTION_END_DT6;
Expand Down Expand Up @@ -772,8 +768,6 @@ void static_zebra_srv6_sid_install(struct static_srv6_sid *sid)
return;
}
SET_SRV6_FLV_OP(ctx.flv.flv_ops, ZEBRA_SEG6_LOCAL_FLV_OP_NEXT_CSID);
ctx.flv.lcblock_len = sid->locator->block_bits_length;
ctx.flv.lcnode_func_len = sid->locator->node_bits_length;
break;
case SRV6_ENDPOINT_BEHAVIOR_END_PSP_USD:
case SRV6_ENDPOINT_BEHAVIOR_END_NEXT_CSID_PSP_USD:
Expand Down Expand Up @@ -802,6 +796,9 @@ void static_zebra_srv6_sid_install(struct static_srv6_sid *sid)

ctx.function_len = sid->addr.prefixlen - (ctx.block_len + ctx.node_len);

ctx.flv.lcblock_len = sid->locator->block_bits_length;
ctx.flv.lcnode_func_len = ctx.node_len + ctx.function_len;

/* Attach the SID to the SRv6 interface */
if (!ifp) {
ifp = if_lookup_by_name(DEFAULT_SRV6_IFNAME, VRF_DEFAULT);
Expand Down Expand Up @@ -982,12 +979,30 @@ static bool static_zebra_sid_locator_block_check(struct static_srv6_sid *sid)
return true;
}

static bool is_srv6_sid_localonly(const struct static_srv6_sid *sid)
{
struct prefix_ipv6 block = {};
struct prefix_ipv6 locator = {};

block = sid->locator->prefix;
block.prefixlen = sid->locator->block_bits_length;
apply_mask(&block);

locator = sid->locator->prefix;

if (prefix_match(&block, &sid->addr) && !prefix_match(&locator, &sid->addr))
return true;

return false;
}

extern void static_zebra_request_srv6_sid(struct static_srv6_sid *sid)
{
struct srv6_sid_ctx ctx = {};
int ret = 0;
struct vrf *vrf;
struct interface *ifp;
bool is_localonly;

if (!sid)
return;
Expand Down Expand Up @@ -1075,9 +1090,11 @@ extern void static_zebra_request_srv6_sid(struct static_srv6_sid *sid)
return;
}

is_localonly = is_srv6_sid_localonly(sid);

/* Request SRv6 SID from SID Manager */
ret = srv6_manager_get_sid(static_zclient, &ctx, &sid->addr.prefix, sid->locator->name,
NULL);
NULL, is_localonly);
if (ret < 0)
zlog_warn("%s: error getting SRv6 SID!", __func__);
}
Expand All @@ -1088,6 +1105,7 @@ extern void static_zebra_release_srv6_sid(struct static_srv6_sid *sid)
struct vrf *vrf;
int ret = 0;
struct interface *ifp;
bool is_localonly;

if (!sid || !CHECK_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_VALID))
return;
Expand Down Expand Up @@ -1167,8 +1185,10 @@ extern void static_zebra_release_srv6_sid(struct static_srv6_sid *sid)
return;
}

is_localonly = is_srv6_sid_localonly(sid);

/* remove the SRv6 SID from the zebra RIB */
ret = srv6_manager_release_sid(static_zclient, &ctx);
ret = srv6_manager_release_sid(static_zclient, &ctx, sid->locator->name, is_localonly);
if (ret == ZCLIENT_SEND_FAILURE)
flog_err(EC_LIB_ZAPI_SOCKET, "zclient_send_get_srv6_sid() delete failed: %s",
safe_strerror(errno));
Expand Down
Empty file.
Loading
Loading