}
}
-/**
- * Encode SID function in the SRv6 SID.
- *
- * @param sid
- * @param func
- * @param offset
- * @param len
- */
-static void encode_sid_func(struct in6_addr *sid, uint32_t func, uint8_t offset,
- uint8_t len)
-{
- for (uint8_t idx = 0; idx < len; idx++) {
- uint8_t tidx = offset + idx;
- sid->s6_addr[tidx / 8] &= ~(0x1 << (7 - tidx % 8));
- if (func >> (len - 1 - idx) & 0x1)
- sid->s6_addr[tidx / 8] |= 0x1 << (7 - tidx % 8);
- }
-}
-
-static bool sid_exist(struct isis_area *area, const struct in6_addr *sid)
-{
- struct listnode *node;
- struct isis_srv6_sid *s;
- struct srv6_adjacency *sra;
-
- for (ALL_LIST_ELEMENTS_RO(area->srv6db.srv6_sids, node, s))
- if (sid_same(&s->sid, sid))
- return true;
- for (ALL_LIST_ELEMENTS_RO(area->srv6db.srv6_endx_sids, node, sra))
- if (sid_same(&sra->sid, sid))
- return true;
- return false;
-}
-
-/**
- * Request a SID from the SRv6 locator.
- *
- * @param area IS-IS area
- * @param locator SRv6 locator
- * @param sid_func The FUNCTION part of the SID to be allocated (a negative
- * number will allocate the first available SID)
- *
- * @return First available SID on success or in6addr_any if the SRv6
- * locator is full
- */
-static struct in6_addr srv6_locator_request_sid(struct isis_area *area,
- struct srv6_locator *locator,
- int sid_func)
-{
- struct in6_addr sid;
- uint8_t offset = 0;
- uint8_t func_len = 0;
- uint32_t func_max;
- bool allocated = false;
-
- if (!area || !locator)
- return in6addr_any;
-
- sr_debug("ISIS-SRv6 (%s): requested new SID from locator %s",
- area->area_tag, locator->name);
-
- /* Let's build the SID, step by step. A SID has the following structure
- (defined in RFC 8986): LOCATOR:FUNCTION:ARGUMENT.*/
-
- /* First, we encode the LOCATOR in the L most significant bits. */
- sid = locator->prefix.prefix;
-
- /* The next part of the SID is the FUNCTION. Let's compute the length
- * and the offset of the FUNCTION in the SID */
- func_len = locator->function_bits_length;
- offset = locator->block_bits_length + locator->node_bits_length;
-
- /* Then, encode the FUNCTION */
- if (sid_func >= 0) {
- /* SID FUNCTION has been specified. We need to allocate a SID
- * with the requested FUNCTION. */
- encode_sid_func(&sid, sid_func, offset, func_len);
- if (sid_exist(area, &sid)) {
- zlog_warn(
- "ISIS-SRv6 (%s): the requested SID %pI6 is already used",
- area->area_tag, &sid);
- return sid;
- }
- allocated = true;
- } else {
- /* SID FUNCTION not specified. We need to choose a FUNCTION that
- * is not already used. So let's iterate through all possible
- * functions and get the first available one. */
- func_max = (1 << func_len) - 1;
- for (uint32_t func = 1; func < func_max; func++) {
- encode_sid_func(&sid, func, offset, func_len);
- if (sid_exist(area, &sid))
- continue;
- allocated = true;
- break;
- }
- }
-
- if (!allocated) {
- /* We ran out of available SIDs */
- zlog_warn("ISIS-SRv6 (%s): no SIDs available in locator %s",
- area->area_tag, locator->name);
- return in6addr_any;
- }
-
- sr_debug("ISIS-SRv6 (%s): allocating new SID %pI6", area->area_tag,
- &sid);
-
- return sid;
-}
-
/**
* Allocate an SRv6 SID from an SRv6 locator.
*
ifp->ifindex, action, NULL);
}
-/**
- * Callback to process an SRv6 locator chunk received from SRv6 Manager (zebra).
- *
- * @result 0 on success, -1 otherwise
- */
-static int isis_zebra_process_srv6_locator_chunk(ZAPI_CALLBACK_ARGS)
-{
- struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
- struct stream *s = NULL;
- struct listnode *node;
- struct isis_area *area;
- struct srv6_locator_chunk *c;
- struct srv6_locator_chunk *chunk = srv6_locator_chunk_alloc();
- struct isis_srv6_sid *sid;
- struct isis_adjacency *adj;
- enum srv6_endpoint_behavior_codepoint behavior;
- bool allocated = false;
-
- if (!isis) {
- srv6_locator_chunk_free(&chunk);
- return -1;
- }
-
- /* Decode the received zebra message */
- s = zclient->ibuf;
- if (zapi_srv6_locator_chunk_decode(s, chunk) < 0) {
- srv6_locator_chunk_free(&chunk);
- return -1;
- }
-
- sr_debug(
- "Received SRv6 locator chunk from zebra: name %s, "
- "prefix %pFX, block_len %u, node_len %u, func_len %u, arg_len %u",
- chunk->locator_name, &chunk->prefix, chunk->block_bits_length,
- chunk->node_bits_length, chunk->function_bits_length,
- chunk->argument_bits_length);
-
- /* Walk through all areas of the ISIS instance */
- for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) {
- if (strncmp(area->srv6db.config.srv6_locator_name,
- chunk->locator_name,
- sizeof(area->srv6db.config.srv6_locator_name)) != 0)
- continue;
-
- for (ALL_LIST_ELEMENTS_RO(area->srv6db.srv6_locator_chunks,
- node, c)) {
- if (!prefix_cmp(&c->prefix, &chunk->prefix)) {
- srv6_locator_chunk_free(&chunk);
- return 0;
- }
- }
-
- sr_debug(
- "SRv6 locator chunk (locator %s, prefix %pFX) assigned to IS-IS area %s",
- chunk->locator_name, &chunk->prefix, area->area_tag);
-
- /* Add the SRv6 Locator chunk to the per-area chunks list */
- listnode_add(area->srv6db.srv6_locator_chunks, chunk);
-
- /* Decide which behavior to use,depending on the locator type
- * (i.e. uSID vs classic locator) */
- behavior = (CHECK_FLAG(chunk->flags, SRV6_LOCATOR_USID))
- ? SRV6_ENDPOINT_BEHAVIOR_END_NEXT_CSID
- : SRV6_ENDPOINT_BEHAVIOR_END;
-
- /* Allocate new SRv6 End SID */
- sid = isis_srv6_sid_alloc(area, chunk, behavior, 0);
- if (!sid)
- 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);
-
- /* Create SRv6 End.X SIDs from existing IS-IS Adjacencies */
- for (ALL_LIST_ELEMENTS_RO(area->adjacency_list, node, adj)) {
- if (adj->ll_ipv6_count > 0)
- srv6_endx_sid_add(adj);
- }
-
- /* Regenerate LSPs to advertise the new locator and the SID */
- lsp_regenerate_schedule(area, area->is_type, 0);
-
- allocated = true;
- break;
- }
-
- if (!allocated) {
- sr_debug("No IS-IS area configured for the locator %s",
- chunk->locator_name);
- srv6_locator_chunk_free(&chunk);
- }
-
- return 0;
-}
-
/**
* Internal function to process an SRv6 locator
*
[ZEBRA_CLIENT_CLOSE_NOTIFY] = isis_zebra_client_close_notify,
- [ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK] =
- isis_zebra_process_srv6_locator_chunk,
[ZEBRA_SRV6_LOCATOR_ADD] = isis_zebra_process_srv6_locator_add,
[ZEBRA_SRV6_LOCATOR_DELETE] = isis_zebra_process_srv6_locator_delete,
[ZEBRA_SRV6_SID_NOTIFY] = isis_zebra_srv6_sid_notify,