mirror of
https://github.com/FRRouting/frr.git
synced 2025-04-30 21:47:15 +02:00
zebra: Alloc/Release SIDs to daemons upon request
Previous commits introduced two new ZAPI operations, `ZEBRA_SRV6_MANAGER_GET_SRV6_SID` and `ZEBRA_SRV6_MANAGER_RELEASE_SRV6_SID`. These operations allow a daemon to interact with the SRv6 SID Manager to get and release an SRv6 SID, respectively. This commit extends the SID Manager by adding logic to process the requests `ZEBRA_SRV6_MANAGER_GET_SRV6_SID` and `ZEBRA_SRV6_MANAGER_RELEASE_SRV6_SID`, and allocate/release SIDs to requesting daemons. Signed-off-by: Carmine Scarpitta <cscarpit@cisco.com>
This commit is contained in:
parent
c570d2bcae
commit
84dd482cb9
|
@ -3006,6 +3006,71 @@ stream_failure:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle SRv6 SID request received from a client daemon protocol.
|
||||||
|
*
|
||||||
|
* @param client The client zapi session
|
||||||
|
* @param msg The request message
|
||||||
|
*/
|
||||||
|
static void zread_srv6_manager_get_srv6_sid(struct zserv *client,
|
||||||
|
struct stream *msg)
|
||||||
|
{
|
||||||
|
struct stream *s;
|
||||||
|
struct srv6_sid_ctx ctx = {};
|
||||||
|
struct in6_addr sid_value = {};
|
||||||
|
struct in6_addr *sid_value_ptr = NULL;
|
||||||
|
char locator[SRV6_LOCNAME_SIZE] = { 0 };
|
||||||
|
uint16_t len;
|
||||||
|
struct zebra_srv6_sid *sid = NULL;
|
||||||
|
uint8_t flags;
|
||||||
|
|
||||||
|
/* Get input stream */
|
||||||
|
s = msg;
|
||||||
|
|
||||||
|
/* Get data */
|
||||||
|
STREAM_GET(&ctx, s, sizeof(struct srv6_sid_ctx));
|
||||||
|
STREAM_GETC(s, flags);
|
||||||
|
if (CHECK_FLAG(flags, ZAPI_SRV6_MANAGER_SID_FLAG_HAS_SID_VALUE)) {
|
||||||
|
STREAM_GET(&sid_value, s, sizeof(struct in6_addr));
|
||||||
|
sid_value_ptr = &sid_value;
|
||||||
|
}
|
||||||
|
if (CHECK_FLAG(flags, ZAPI_SRV6_MANAGER_SID_FLAG_HAS_LOCATOR)) {
|
||||||
|
STREAM_GETW(s, len);
|
||||||
|
STREAM_GET(locator, s, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Call hook to get a SID using wrapper */
|
||||||
|
srv6_manager_get_sid_call(&sid, client, &ctx, sid_value_ptr, locator);
|
||||||
|
|
||||||
|
stream_failure:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle SRv6 SID release request received from a client daemon protocol.
|
||||||
|
*
|
||||||
|
* @param client The client zapi session
|
||||||
|
* @param msg The request message
|
||||||
|
*/
|
||||||
|
static void zread_srv6_manager_release_srv6_sid(struct zserv *client,
|
||||||
|
struct stream *msg)
|
||||||
|
{
|
||||||
|
struct stream *s;
|
||||||
|
struct srv6_sid_ctx ctx = {};
|
||||||
|
|
||||||
|
/* Get input stream */
|
||||||
|
s = msg;
|
||||||
|
|
||||||
|
/* Get data */
|
||||||
|
STREAM_GET(&ctx, s, sizeof(struct srv6_sid_ctx));
|
||||||
|
|
||||||
|
/* Call hook to release a SID using wrapper */
|
||||||
|
srv6_manager_release_sid_call(client, &ctx);
|
||||||
|
|
||||||
|
stream_failure:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle SRv6 locator get request received from a client daemon protocol.
|
* Handle SRv6 locator get request received from a client daemon protocol.
|
||||||
*
|
*
|
||||||
|
@ -3042,6 +3107,12 @@ static void zread_srv6_manager_request(ZAPI_HANDLER_ARGS)
|
||||||
zread_srv6_manager_release_locator_chunk(client, msg,
|
zread_srv6_manager_release_locator_chunk(client, msg,
|
||||||
zvrf_id(zvrf));
|
zvrf_id(zvrf));
|
||||||
break;
|
break;
|
||||||
|
case ZEBRA_SRV6_MANAGER_GET_SRV6_SID:
|
||||||
|
zread_srv6_manager_get_srv6_sid(client, msg);
|
||||||
|
break;
|
||||||
|
case ZEBRA_SRV6_MANAGER_RELEASE_SRV6_SID:
|
||||||
|
zread_srv6_manager_release_srv6_sid(client, msg);
|
||||||
|
break;
|
||||||
case ZEBRA_SRV6_MANAGER_GET_LOCATOR:
|
case ZEBRA_SRV6_MANAGER_GET_LOCATOR:
|
||||||
zread_srv6_manager_get_locator(client, msg);
|
zread_srv6_manager_get_locator(client, msg);
|
||||||
break;
|
break;
|
||||||
|
@ -3993,6 +4064,8 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
|
||||||
[ZEBRA_MLAG_FORWARD_MSG] = zebra_mlag_forward_client_msg,
|
[ZEBRA_MLAG_FORWARD_MSG] = zebra_mlag_forward_client_msg,
|
||||||
[ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK] = zread_srv6_manager_request,
|
[ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK] = zread_srv6_manager_request,
|
||||||
[ZEBRA_SRV6_MANAGER_RELEASE_LOCATOR_CHUNK] = zread_srv6_manager_request,
|
[ZEBRA_SRV6_MANAGER_RELEASE_LOCATOR_CHUNK] = zread_srv6_manager_request,
|
||||||
|
[ZEBRA_SRV6_MANAGER_GET_SRV6_SID] = zread_srv6_manager_request,
|
||||||
|
[ZEBRA_SRV6_MANAGER_RELEASE_SRV6_SID] = zread_srv6_manager_request,
|
||||||
[ZEBRA_SRV6_MANAGER_GET_LOCATOR] = zread_srv6_manager_request,
|
[ZEBRA_SRV6_MANAGER_GET_LOCATOR] = zread_srv6_manager_request,
|
||||||
[ZEBRA_CLIENT_CAPABILITIES] = zread_client_capabilities,
|
[ZEBRA_CLIENT_CAPABILITIES] = zread_client_capabilities,
|
||||||
[ZEBRA_NEIGH_DISCOVER] = zread_neigh_discover,
|
[ZEBRA_NEIGH_DISCOVER] = zread_neigh_discover,
|
||||||
|
|
|
@ -65,6 +65,13 @@ DEFINE_HOOK(srv6_manager_release_chunk,
|
||||||
vrf_id_t vrf_id),
|
vrf_id_t vrf_id),
|
||||||
(client, locator_name, vrf_id));
|
(client, locator_name, vrf_id));
|
||||||
|
|
||||||
|
DEFINE_HOOK(srv6_manager_get_sid,
|
||||||
|
(struct zebra_srv6_sid **sid, struct zserv *client,
|
||||||
|
struct srv6_sid_ctx *ctx, struct in6_addr *sid_value,
|
||||||
|
const char *locator_name),
|
||||||
|
(sid, client, ctx, sid_value, locator_name));
|
||||||
|
DEFINE_HOOK(srv6_manager_release_sid,
|
||||||
|
(struct zserv *client, struct srv6_sid_ctx *ctx), (client, ctx));
|
||||||
DEFINE_HOOK(srv6_manager_get_locator,
|
DEFINE_HOOK(srv6_manager_get_locator,
|
||||||
(struct srv6_locator **locator, struct zserv *client,
|
(struct srv6_locator **locator, struct zserv *client,
|
||||||
const char *locator_name),
|
const char *locator_name),
|
||||||
|
@ -100,6 +107,22 @@ int srv6_manager_client_disconnect_cb(struct zserv *client)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void srv6_manager_get_sid_call(struct zebra_srv6_sid **sid,
|
||||||
|
struct zserv *client, struct srv6_sid_ctx *ctx,
|
||||||
|
struct in6_addr *sid_value,
|
||||||
|
const char *locator_name)
|
||||||
|
{
|
||||||
|
hook_call(srv6_manager_get_sid, sid, client, ctx, sid_value,
|
||||||
|
locator_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void srv6_manager_release_sid_call(struct zserv *client,
|
||||||
|
struct srv6_sid_ctx *ctx)
|
||||||
|
{
|
||||||
|
hook_call(srv6_manager_release_sid, client, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
void srv6_manager_get_locator_call(struct srv6_locator **locator,
|
void srv6_manager_get_locator_call(struct srv6_locator **locator,
|
||||||
struct zserv *client,
|
struct zserv *client,
|
||||||
const char *locator_name)
|
const char *locator_name)
|
||||||
|
@ -109,6 +132,8 @@ void srv6_manager_get_locator_call(struct srv6_locator **locator,
|
||||||
|
|
||||||
static int zebra_srv6_cleanup(struct zserv *client)
|
static int zebra_srv6_cleanup(struct zserv *client)
|
||||||
{
|
{
|
||||||
|
/* Client has disconnected, let's release all the SIDs allocated by it. */
|
||||||
|
release_daemon_srv6_sids(client);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2225,6 +2250,141 @@ static int srv6_manager_get_srv6_locator_internal(struct srv6_locator **locator,
|
||||||
return zsend_zebra_srv6_locator_add(client, *locator);
|
return zsend_zebra_srv6_locator_add(client, *locator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle a get SID request received from a client.
|
||||||
|
*
|
||||||
|
* It gets a SID for a given context. If there is no SID associated with the context yet,
|
||||||
|
* we allocate one and return it to the client. Otherwise, we return the existing SID.
|
||||||
|
*
|
||||||
|
* - When the `sid_value` parameter is non-NULL, SRv6 Manager assigns the requested SID value
|
||||||
|
* if it is available (explicit SID allocation).
|
||||||
|
* - When the `sid_value` parameter is NULL, SRv6 Manager assigns any available SID value
|
||||||
|
* (dynamic SID allocation).
|
||||||
|
*
|
||||||
|
* Finally, notify the client whether the SID allocation was successful or failed.
|
||||||
|
*
|
||||||
|
* @param sid SID returned by this function
|
||||||
|
* @param client The client that requested the SID
|
||||||
|
* @param ctx Context for which the SID was requested
|
||||||
|
* @param sid_value SID value (i.e., IPv6 address) that has to be assigned to the SID
|
||||||
|
* (for explicit SID allocation)
|
||||||
|
* @param locator_name Locator from which the SID has to be allocated (for dynamic SID allocation)
|
||||||
|
*
|
||||||
|
* @return 0 on success, -1 otherwise
|
||||||
|
*/
|
||||||
|
static int srv6_manager_get_sid_internal(struct zebra_srv6_sid **sid,
|
||||||
|
struct zserv *client,
|
||||||
|
struct srv6_sid_ctx *ctx,
|
||||||
|
struct in6_addr *sid_value,
|
||||||
|
const char *locator_name)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
char buf[256];
|
||||||
|
|
||||||
|
if (IS_ZEBRA_DEBUG_PACKET)
|
||||||
|
zlog_debug("%s: getting SRv6 SID for ctx %s, sid_value=%pI6, locator_name=%s",
|
||||||
|
__func__, srv6_sid_ctx2str(buf, sizeof(buf), ctx),
|
||||||
|
sid_value, locator_name);
|
||||||
|
|
||||||
|
ret = get_srv6_sid(sid, ctx, sid_value, locator_name);
|
||||||
|
if (ret < 0) {
|
||||||
|
zlog_warn("%s: not got SRv6 SID for ctx %s, sid_value=%pI6, locator_name=%s",
|
||||||
|
__func__, srv6_sid_ctx2str(buf, sizeof(buf), ctx),
|
||||||
|
sid_value, locator_name);
|
||||||
|
} else if (ret == 0) {
|
||||||
|
if (IS_ZEBRA_DEBUG_PACKET)
|
||||||
|
zlog_debug("%s: got existing SRv6 SID for ctx %s: sid_value=%pI6 (func=%u) (proto=%u, instance=%u, sessionId=%u), notify client",
|
||||||
|
__func__,
|
||||||
|
srv6_sid_ctx2str(buf, sizeof(buf), ctx),
|
||||||
|
&(*sid)->value, (*sid)->func, client->proto,
|
||||||
|
client->instance, client->session_id);
|
||||||
|
if (!listnode_lookup((*sid)->client_list, client))
|
||||||
|
listnode_add((*sid)->client_list, client);
|
||||||
|
} else {
|
||||||
|
if (IS_ZEBRA_DEBUG_PACKET)
|
||||||
|
zlog_debug("%s: got new SRv6 SID for ctx %s: sid_value=%pI6 (func=%u) (proto=%u, instance=%u, sessionId=%u), notifying all clients",
|
||||||
|
__func__,
|
||||||
|
srv6_sid_ctx2str(buf, sizeof(buf), ctx),
|
||||||
|
&(*sid)->value, (*sid)->func, client->proto,
|
||||||
|
client->instance, client->session_id);
|
||||||
|
if (!listnode_lookup((*sid)->client_list, client))
|
||||||
|
listnode_add((*sid)->client_list, client);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release SRv6 SIDs from a client.
|
||||||
|
*
|
||||||
|
* Called on client disconnection or reconnection.
|
||||||
|
*
|
||||||
|
* @param client The client to release SIDs from
|
||||||
|
* @return Number of SIDs released
|
||||||
|
*/
|
||||||
|
int release_daemon_srv6_sids(struct zserv *client)
|
||||||
|
{
|
||||||
|
struct zebra_srv6 *srv6 = zebra_srv6_get_default();
|
||||||
|
struct listnode *node, *nnode;
|
||||||
|
struct zebra_srv6_sid_ctx *ctx;
|
||||||
|
int count = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (IS_ZEBRA_DEBUG_PACKET)
|
||||||
|
zlog_debug("%s: releasing SRv6 SIDs for client proto %s, instance %d, session %u",
|
||||||
|
__func__, zebra_route_string(client->proto),
|
||||||
|
client->instance, client->session_id);
|
||||||
|
|
||||||
|
/* Iterate over the SIDs and release SIDs used by the client daemon */
|
||||||
|
for (ALL_LIST_ELEMENTS(srv6->sids, node, nnode, ctx)) {
|
||||||
|
if (!listnode_lookup(ctx->sid->client_list, client))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ret = release_srv6_sid(client, ctx);
|
||||||
|
if (ret == 0)
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_ZEBRA_DEBUG_PACKET)
|
||||||
|
zlog_debug("%s: released %d SRv6 SIDs", __func__, count);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release SRv6 SIDs from a client.
|
||||||
|
*
|
||||||
|
* @param client The client zapi session
|
||||||
|
* @param ctx Context associated with the SRv6 SID
|
||||||
|
* @return 0 on success, -1 on failure
|
||||||
|
*/
|
||||||
|
static int srv6_manager_release_sid_internal(struct zserv *client,
|
||||||
|
struct srv6_sid_ctx *ctx)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
struct zebra_srv6 *srv6 = zebra_srv6_get_default();
|
||||||
|
struct zebra_srv6_sid_ctx *zctx;
|
||||||
|
struct listnode *node, *nnode;
|
||||||
|
char buf[256];
|
||||||
|
|
||||||
|
if (IS_ZEBRA_DEBUG_PACKET)
|
||||||
|
zlog_debug("%s: releasing SRv6 SID associated with ctx %s",
|
||||||
|
__func__, srv6_sid_ctx2str(buf, sizeof(buf), ctx));
|
||||||
|
|
||||||
|
/* Lookup Zebra SID context and release it */
|
||||||
|
for (ALL_LIST_ELEMENTS(srv6->sids, node, nnode, zctx))
|
||||||
|
if (memcmp(&zctx->ctx, ctx, sizeof(struct srv6_sid_ctx)) == 0) {
|
||||||
|
ret = release_srv6_sid(client, zctx);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_ZEBRA_DEBUG_PACKET)
|
||||||
|
zlog_debug("%s: no SID associated with ctx %s", __func__,
|
||||||
|
srv6_sid_ctx2str(buf, sizeof(buf), ctx));
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void zebra_srv6_terminate(void)
|
void zebra_srv6_terminate(void)
|
||||||
{
|
{
|
||||||
struct srv6_locator *locator;
|
struct srv6_locator *locator;
|
||||||
|
@ -2288,6 +2448,9 @@ void zebra_srv6_init(void)
|
||||||
hook_register(srv6_manager_release_chunk,
|
hook_register(srv6_manager_release_chunk,
|
||||||
zebra_srv6_manager_release_locator_chunk);
|
zebra_srv6_manager_release_locator_chunk);
|
||||||
|
|
||||||
|
hook_register(srv6_manager_get_sid, srv6_manager_get_sid_internal);
|
||||||
|
hook_register(srv6_manager_release_sid,
|
||||||
|
srv6_manager_release_sid_internal);
|
||||||
hook_register(srv6_manager_get_locator,
|
hook_register(srv6_manager_get_locator,
|
||||||
srv6_manager_get_srv6_locator_internal);
|
srv6_manager_get_srv6_locator_internal);
|
||||||
}
|
}
|
||||||
|
|
|
@ -231,6 +231,13 @@ DECLARE_HOOK(srv6_manager_release_chunk,
|
||||||
vrf_id_t vrf_id),
|
vrf_id_t vrf_id),
|
||||||
(client, locator_name, vrf_id));
|
(client, locator_name, vrf_id));
|
||||||
|
|
||||||
|
DECLARE_HOOK(srv6_manager_get_sid,
|
||||||
|
(struct zebra_srv6_sid **sid, struct zserv *client,
|
||||||
|
struct srv6_sid_ctx *ctx, struct in6_addr *sid_value,
|
||||||
|
const char *locator_name),
|
||||||
|
(sid, client, ctx, sid_value, locator_name));
|
||||||
|
DECLARE_HOOK(srv6_manager_release_sid,
|
||||||
|
(struct zserv *client, struct srv6_sid_ctx *ctx), (client, ctx));
|
||||||
DECLARE_HOOK(srv6_manager_get_locator,
|
DECLARE_HOOK(srv6_manager_get_locator,
|
||||||
(struct srv6_locator **locator, struct zserv *client,
|
(struct srv6_locator **locator, struct zserv *client,
|
||||||
const char *locator_name),
|
const char *locator_name),
|
||||||
|
@ -290,6 +297,14 @@ zebra_srv6_sid_alloc(struct zebra_srv6_sid_ctx *ctx, struct in6_addr *sid_value,
|
||||||
extern void zebra_srv6_sid_free(struct zebra_srv6_sid *sid);
|
extern void zebra_srv6_sid_free(struct zebra_srv6_sid *sid);
|
||||||
extern void delete_zebra_srv6_sid(void *val);
|
extern void delete_zebra_srv6_sid(void *val);
|
||||||
|
|
||||||
|
extern void srv6_manager_get_sid_call(struct zebra_srv6_sid **sid,
|
||||||
|
struct zserv *client,
|
||||||
|
struct srv6_sid_ctx *ctx,
|
||||||
|
struct in6_addr *sid_value,
|
||||||
|
const char *locator_name);
|
||||||
|
extern void srv6_manager_release_sid_call(struct zserv *client,
|
||||||
|
struct srv6_sid_ctx *ctx);
|
||||||
|
|
||||||
extern void srv6_manager_get_locator_call(struct srv6_locator **locator,
|
extern void srv6_manager_get_locator_call(struct srv6_locator **locator,
|
||||||
struct zserv *client,
|
struct zserv *client,
|
||||||
const char *locator_name);
|
const char *locator_name);
|
||||||
|
@ -298,6 +313,9 @@ extern int get_srv6_sid(struct zebra_srv6_sid **sid, struct srv6_sid_ctx *ctx,
|
||||||
struct in6_addr *sid_value, const char *locator_name);
|
struct in6_addr *sid_value, const char *locator_name);
|
||||||
extern int release_srv6_sid(struct zserv *client,
|
extern int release_srv6_sid(struct zserv *client,
|
||||||
struct zebra_srv6_sid_ctx *zctx);
|
struct zebra_srv6_sid_ctx *zctx);
|
||||||
|
extern int release_daemon_srv6_sids(struct zserv *client);
|
||||||
|
extern int srv6_manager_get_sid_response(struct zebra_srv6_sid *sid,
|
||||||
|
struct zserv *client);
|
||||||
|
|
||||||
extern struct zebra_srv6_sid_ctx *zebra_srv6_sid_ctx_alloc(void);
|
extern struct zebra_srv6_sid_ctx *zebra_srv6_sid_ctx_alloc(void);
|
||||||
extern void zebra_srv6_sid_ctx_free(struct zebra_srv6_sid_ctx *ctx);
|
extern void zebra_srv6_sid_ctx_free(struct zebra_srv6_sid_ctx *ctx);
|
||||||
|
|
Loading…
Reference in a new issue