isisd: Receive SRv6 SIDs notifications from zebra

Zebra sends a SRV6_SID_NOTIFY notification to inform clients about the
result of a SID alloc/release operation.  This commit adds a handler to
process a SRV6_SID_NOTIFY notification received from zebra.

If the notification indicates that a SID allocation operation was
successful, then it stores the allocated SID in the SRv6 database,
installs the SID into the RIB, and advertises the SID to the other IS-IS
routers.

If the notification indicates that an operation has failed, it logs the
error.

Signed-off-by: Carmine Scarpitta <cscarpit@cisco.com>
This commit is contained in:
Carmine Scarpitta 2024-05-09 11:51:16 +02:00
parent 7c203a05bf
commit 0af0f4616d

View file

@ -1535,6 +1535,151 @@ void isis_zebra_release_srv6_sid(const struct srv6_sid_ctx *ctx)
} }
} }
static int isis_zebra_srv6_sid_notify(ZAPI_CALLBACK_ARGS)
{
struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
struct srv6_sid_ctx ctx;
struct in6_addr sid_addr;
enum zapi_srv6_sid_notify note;
uint32_t sid_func;
struct isis_area *area;
struct listnode *node, *nnode, *n;
char buf[256];
struct srv6_locator *locator;
struct prefix_ipv6 tmp_prefix;
struct srv6_adjacency *sra;
enum srv6_endpoint_behavior_codepoint behavior;
struct isis_srv6_sid *sid;
struct isis_adjacency *adj;
if (!isis)
return -1;
/* Decode the received notification message */
if (!zapi_srv6_sid_notify_decode(zclient->ibuf, &ctx, &sid_addr,
&sid_func, NULL, &note)) {
zlog_err("%s : error in msg decode", __func__);
return -1;
}
sr_debug("%s: received SRv6 SID notify: ctx %s sid_value %pI6 sid_func %u note %s",
__func__, srv6_sid_ctx2str(buf, sizeof(buf), &ctx), &sid_addr,
sid_func, zapi_srv6_sid_notify2str(note));
for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) {
if (!area->srv6db.config.enabled || !area->srv6db.srv6_locator)
continue;
locator = area->srv6db.srv6_locator;
/* Verify that the received SID belongs to the configured locator */
if (note == ZAPI_SRV6_SID_ALLOCATED) {
tmp_prefix.family = AF_INET6;
tmp_prefix.prefixlen = IPV6_MAX_BITLEN;
tmp_prefix.prefix = sid_addr;
if (!prefix_match((struct prefix *)&locator->prefix,
(struct prefix *)&tmp_prefix)) {
sr_debug("%s : ignoring SRv6 SID notify: locator (area %s) does not match",
__func__, area->area_tag);
continue;
}
}
/* Handle notification */
switch (note) {
case ZAPI_SRV6_SID_ALLOCATED:
sr_debug("SRv6 SID %pI6 %s ALLOCATED", &sid_addr,
srv6_sid_ctx2str(buf, sizeof(buf), &ctx));
if (ctx.behavior == ZEBRA_SEG6_LOCAL_ACTION_END) {
/* Remove old End SIDs, if any */
for (ALL_LIST_ELEMENTS(area->srv6db.srv6_sids,
node, nnode, sid)) {
isis_zebra_srv6_sid_uninstall(area, sid);
listnode_delete(area->srv6db.srv6_sids,
sid);
}
/* Allocate new SRv6 End SID */
behavior =
(CHECK_FLAG(locator->flags,
SRV6_LOCATOR_USID))
? SRV6_ENDPOINT_BEHAVIOR_END_NEXT_CSID
: SRV6_ENDPOINT_BEHAVIOR_END;
sid = isis_srv6_sid_alloc(area,
area->srv6db
.srv6_locator,
behavior, &sid_addr);
if (!sid) {
zlog_warn("%s: isis_srv6_sid_alloc failed",
__func__);
return -1;
}
/*
* Install the new SRv6 End SID in the forwarding plane through
* Zebra
*/
isis_zebra_srv6_sid_install(area, sid);
/* Store the SID */
listnode_add(area->srv6db.srv6_sids, sid);
} else if (ctx.behavior ==
ZEBRA_SEG6_LOCAL_ACTION_END_X) {
for (ALL_LIST_ELEMENTS_RO(area->adjacency_list,
n, adj)) {
/* Check if the End.X SID is for this adjacecny */
if (adj->ll_ipv6_count == 0 ||
memcmp(&adj->ll_ipv6_addrs[0],
&ctx.nh6,
sizeof(struct in6_addr)) != 0)
continue;
/* Remove old End.X SIDs, if any */
for (ALL_LIST_ELEMENTS(adj->srv6_endx_sids,
node, nnode, sra))
srv6_endx_sid_del(sra);
/* Allocate new End.X SID for the adjacency */
srv6_endx_sid_add_single(adj, false,
NULL,
&sid_addr);
}
} else {
zlog_warn("%s: unsupported behavior %u",
__func__, ctx.behavior);
return -1;
}
break;
case ZAPI_SRV6_SID_RELEASED:
sr_debug("SRv6 SID %pI6 %s: RELEASED", &sid_addr,
srv6_sid_ctx2str(buf, sizeof(buf), &ctx));
break;
case ZAPI_SRV6_SID_FAIL_ALLOC:
sr_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:
zlog_warn("%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;
}
/* Regenerate LSPs to advertise the new locator and the SID */
lsp_regenerate_schedule(area, area->is_type, 0);
}
return 0;
}
static zclient_handler *const isis_handlers[] = { static zclient_handler *const isis_handlers[] = {
[ZEBRA_ROUTER_ID_UPDATE] = isis_router_id_update_zebra, [ZEBRA_ROUTER_ID_UPDATE] = isis_router_id_update_zebra,
[ZEBRA_INTERFACE_ADDRESS_ADD] = isis_zebra_if_address_add, [ZEBRA_INTERFACE_ADDRESS_ADD] = isis_zebra_if_address_add,
@ -1551,6 +1696,7 @@ static zclient_handler *const isis_handlers[] = {
isis_zebra_process_srv6_locator_chunk, isis_zebra_process_srv6_locator_chunk,
[ZEBRA_SRV6_LOCATOR_ADD] = isis_zebra_process_srv6_locator_add, [ZEBRA_SRV6_LOCATOR_ADD] = isis_zebra_process_srv6_locator_add,
[ZEBRA_SRV6_LOCATOR_DELETE] = isis_zebra_process_srv6_locator_delete, [ZEBRA_SRV6_LOCATOR_DELETE] = isis_zebra_process_srv6_locator_delete,
[ZEBRA_SRV6_SID_NOTIFY] = isis_zebra_srv6_sid_notify,
}; };
void isis_zebra_init(struct event_loop *master, int instance) void isis_zebra_init(struct event_loop *master, int instance)