From 021386a34eb49893ce6b7df16c2fe1096a8fedf6 Mon Sep 17 00:00:00 2001 From: Carmine Scarpitta Date: Fri, 22 Mar 2024 15:13:00 +0100 Subject: lib: Add support for SRv6 SID formats Add functionalities to manage SRv6 SID formats (allocate / free). Signed-off-by: Carmine Scarpitta --- lib/srv6.h | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) (limited to 'lib/srv6.h') diff --git a/lib/srv6.h b/lib/srv6.h index 433c5c14fd..04f560b267 100644 --- a/lib/srv6.h +++ b/lib/srv6.h @@ -20,6 +20,8 @@ #define SRH_BASE_HEADER_LENGTH 8 #define SRH_SEGMENT_LENGTH 16 +#define SRV6_SID_FORMAT_NAME_SIZE 512 + #ifdef __cplusplus extern "C" { #endif @@ -183,6 +185,61 @@ struct nexthop_srv6 { struct seg6_seg_stack *seg6_segs; }; +/* SID format type */ +enum srv6_sid_format_type { + SRV6_SID_FORMAT_TYPE_UNSPEC = 0, + /* SRv6 SID uncompressed format */ + SRV6_SID_FORMAT_TYPE_UNCOMPRESSED = 1, + /* SRv6 SID compressed uSID format */ + SRV6_SID_FORMAT_TYPE_USID = 2, +}; + +/* SRv6 SID format */ +struct srv6_sid_format { + /* Name of the format */ + char name[SRV6_SID_FORMAT_NAME_SIZE]; + + /* Format type: uncompressed vs compressed */ + enum srv6_sid_format_type type; + + /* + * Lengths of block/node/function/argument parts of the SIDs allocated + * using this format + */ + uint8_t block_len; + uint8_t node_len; + uint8_t function_len; + uint8_t argument_len; + + union { + /* Configuration settings for compressed uSID format type */ + struct { + /* Start of the Local ID Block (LIB) range */ + uint32_t lib_start; + + /* Start/End of the Explicit LIB range */ + uint32_t elib_start; + uint32_t elib_end; + + /* Start/End of the Wide LIB range */ + uint32_t wlib_start; + uint32_t wlib_end; + + /* Start/End of the Explicit Wide LIB range */ + uint32_t ewlib_start; + } usid; + + /* Configuration settings for uncompressed format type */ + struct { + /* Start of the Explicit range */ + uint32_t explicit_start; + } uncompressed; + } config; + + QOBJ_FIELDS; +}; +DECLARE_QOBJ_TYPE(srv6_sid_format); + static inline const char *seg6_mode2str(enum seg6_mode_t mode) { switch (mode) { @@ -260,6 +317,10 @@ json_object *srv6_locator_detailed_json(const struct srv6_locator *loc); json_object * srv6_locator_chunk_detailed_json(const struct srv6_locator_chunk *chunk); +extern struct srv6_sid_format *srv6_sid_format_alloc(const char *name); +extern void srv6_sid_format_free(struct srv6_sid_format *format); +extern void delete_srv6_sid_format(void *format); + #ifdef __cplusplus } #endif -- cgit v1.2.3 From f00554ed563b8a4ce0cc7fff7ea107d3ae8aa6b1 Mon Sep 17 00:00:00 2001 From: Carmine Scarpitta Date: Wed, 8 May 2024 16:41:05 +0200 Subject: lib: Add function to copy an SRv6 locator Add a new function to copy an SRv6 locator. Signed-off-by: Carmine Scarpitta --- lib/srv6.c | 15 +++++++++++++++ lib/srv6.h | 2 ++ 2 files changed, 17 insertions(+) (limited to 'lib/srv6.h') diff --git a/lib/srv6.c b/lib/srv6.c index abaff7eab8..1f485fb8ac 100644 --- a/lib/srv6.c +++ b/lib/srv6.c @@ -141,6 +141,21 @@ struct srv6_locator_chunk *srv6_locator_chunk_alloc(void) return chunk; } +void srv6_locator_copy(struct srv6_locator *copy, + const struct srv6_locator *locator) +{ + strlcpy(copy->name, locator->name, sizeof(locator->name)); + copy->prefix = locator->prefix; + copy->block_bits_length = locator->block_bits_length; + copy->node_bits_length = locator->node_bits_length; + copy->function_bits_length = locator->function_bits_length; + copy->argument_bits_length = locator->argument_bits_length; + copy->algonum = locator->algonum; + copy->current = locator->current; + copy->status_up = locator->status_up; + copy->flags = locator->flags; +} + void srv6_locator_free(struct srv6_locator *locator) { if (locator) { diff --git a/lib/srv6.h b/lib/srv6.h index 04f560b267..66f1854dab 100644 --- a/lib/srv6.h +++ b/lib/srv6.h @@ -311,6 +311,8 @@ extern struct srv6_locator_chunk *srv6_locator_chunk_alloc(void); extern void srv6_locator_free(struct srv6_locator *locator); extern void srv6_locator_chunk_list_free(void *data); extern void srv6_locator_chunk_free(struct srv6_locator_chunk **chunk); +extern void srv6_locator_copy(struct srv6_locator *copy, + const struct srv6_locator *locator); json_object *srv6_locator_chunk_json(const struct srv6_locator_chunk *chunk); json_object *srv6_locator_json(const struct srv6_locator *loc); json_object *srv6_locator_detailed_json(const struct srv6_locator *loc); -- cgit v1.2.3 From 779d4c2702ac446cc4b96a1a9d2d62d1b0bbe232 Mon Sep 17 00:00:00 2001 From: Carmine Scarpitta Date: Fri, 22 Mar 2024 19:31:01 +0100 Subject: zebra: CLI to specify format of an SRv6 locator Add the CLI to choose the SID format of a locator. When the SID format of a locator is changed, the SIDs allocated from that locator might no longer be valid (for example, because the new format might involve a different SID allocation schema). In such a case, it is necessary to notify all the zclients so that they can withdraw/uninstall the old SIDs that use the previous format and allocate/install/advertise the new SIDs based on the new format. Signed-off-by: Carmine Scarpitta --- lib/srv6.h | 6 ++ zebra/zapi_msg.c | 18 ++++- zebra/zebra_srv6.c | 133 ++++++++++++++++++++++++++++++++ zebra/zebra_srv6.h | 7 +- zebra/zebra_srv6_vty.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 351 insertions(+), 13 deletions(-) (limited to 'lib/srv6.h') diff --git a/lib/srv6.h b/lib/srv6.h index 66f1854dab..4a6ea5c72b 100644 --- a/lib/srv6.h +++ b/lib/srv6.h @@ -129,6 +129,12 @@ struct srv6_locator { uint8_t flags; #define SRV6_LOCATOR_USID (1 << 0) /* The SRv6 Locator is a uSID Locator */ + /* Pointer to the SID format. */ + struct srv6_sid_format *sid_format; + + /* Pointer to the parent SID block of the locator. */ + void *sid_block; + QOBJ_FIELDS; }; DECLARE_QOBJ_TYPE(srv6_locator); diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index d585ef996b..2d580e2972 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -1136,9 +1136,25 @@ static int zsend_table_manager_connect_response(struct zserv *client, int zsend_zebra_srv6_locator_add(struct zserv *client, struct srv6_locator *loc) { struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); + struct srv6_locator locator = {}; + struct srv6_sid_format *format = loc->sid_format; + + /* + * Copy the locator and fill locator block/node/func/arg length from the format + * before sending the locator to the zclient + */ + srv6_locator_copy(&locator, loc); + if (format) { + locator.block_bits_length = format->block_len; + locator.node_bits_length = format->node_len; + locator.function_bits_length = format->function_len; + locator.argument_bits_length = format->argument_len; + if (format->type == ZEBRA_SRV6_SID_FORMAT_TYPE_USID) + SET_FLAG(locator.flags, SRV6_LOCATOR_USID); + } zclient_create_header(s, ZEBRA_SRV6_LOCATOR_ADD, VRF_DEFAULT); - zapi_srv6_locator_encode(s, loc); + zapi_srv6_locator_encode(s, &locator); stream_putw_at(s, 0, stream_get_endp(s)); return zserv_send_message(client, s); diff --git a/zebra/zebra_srv6.c b/zebra/zebra_srv6.c index 2e5c499838..e6b3c2a252 100644 --- a/zebra/zebra_srv6.c +++ b/zebra/zebra_srv6.c @@ -126,6 +126,139 @@ struct srv6_sid_format *srv6_sid_format_lookup(const char *name) return NULL; } +/* + * Called to change the SID format of a locator. + * + * After switching the locator to a different format, the SIDs allocated + * from the locator may no longer be valid; we need to notify the + * interested zclient that the locator has changed, so that the + * zclients can withdraw/uninstall the old SIDs, allocate/advertise/program + * the new SIDs. + */ +void zebra_srv6_locator_format_set(struct srv6_locator *locator, + struct srv6_sid_format *format) +{ + struct zebra_srv6 *srv6 = zebra_srv6_get_default(); + struct zebra_srv6_sid_block *block_old, *block_new; + struct prefix_ipv6 block_pfx_new; + struct listnode *node, *nnode; + struct zebra_srv6_sid_ctx *ctx; + + if (!locator) + return; + + locator->sid_format = format; + + if (IS_ZEBRA_DEBUG_PACKET) + zlog_debug("%s: Locator %s format has changed, old=%s new=%s", + __func__, locator->name, + locator->sid_format ? ((struct srv6_sid_format *) + locator->sid_format) + ->name + : NULL, + format ? format->name : NULL); + + /* Notify zclients that the locator is no longer valid */ + zebra_notify_srv6_locator_delete(locator); + + for (ALL_LIST_ELEMENTS(srv6->sids, node, nnode, ctx)) { + if (!ctx->sid || ctx->sid->locator != locator) + continue; + + if (ctx->sid) + zebra_srv6_sid_free(ctx->sid); + + listnode_delete(srv6->sids, ctx); + zebra_srv6_sid_ctx_free(ctx); + } + + if (IS_ZEBRA_DEBUG_PACKET) + zlog_debug("%s: Locator %s format has changed, send SRV6_LOCATOR_DEL notification to zclients", + __func__, locator->name); + + /* Release the current parent block */ + block_old = locator->sid_block; + if (block_old) { + block_old->refcnt--; + if (block_old->refcnt == 0) { + listnode_delete(srv6->sid_blocks, block_old); + zebra_srv6_sid_block_free(block_old); + } + } + locator->sid_block = NULL; + + block_pfx_new = locator->prefix; + if (format) + block_pfx_new.prefixlen = format->block_len; + else + block_pfx_new.prefixlen = locator->block_bits_length; + apply_mask(&block_pfx_new); + + /* Allocate the new parent block */ + block_new = zebra_srv6_sid_block_lookup(&block_pfx_new); + if (!block_new) { + block_new = zebra_srv6_sid_block_alloc(format, &block_pfx_new); + listnode_add(srv6->sid_blocks, block_new); + } + + block_new->refcnt++; + locator->sid_block = block_new; + + if (IS_ZEBRA_DEBUG_PACKET) + zlog_debug("%s: Locator %s format has changed, send SRV6_LOCATOR_ADD notification to zclients", + __func__, locator->name); + + /* Notify zclients about the updated locator */ + zebra_srv6_locator_add(locator); +} + +/* + * Called when a SID format is modified by the user. + * + * After modifying a SID format, the SIDs that are using that format may no + * longer be valid. + * This function walks through the list of locators that are using the SID format + * and notifies the zclients that the locator has changed, so that the zclients + * can withdraw/uninstall the old SIDs, allocate/program/advertise the new SIDs. + */ +void zebra_srv6_sid_format_changed_cb(struct srv6_sid_format *format) +{ + struct zebra_srv6 *srv6 = zebra_srv6_get_default(); + struct srv6_locator *locator; + struct listnode *node, *nnode; + struct zebra_srv6_sid_ctx *ctx; + + if (IS_ZEBRA_DEBUG_PACKET) + zlog_debug("%s: SID format %s has changed. Notifying zclients.", + __func__, format->name); + + for (ALL_LIST_ELEMENTS_RO(srv6->locators, node, locator)) { + if (locator->sid_format == format) { + if (IS_ZEBRA_DEBUG_PACKET) + zlog_debug("%s: Locator %s has changed because its format (%s) has been modified. Notifying zclients.", + __func__, locator->name, + format->name); + + /* Notify zclients that the locator is no longer valid */ + zebra_notify_srv6_locator_delete(locator); + + for (ALL_LIST_ELEMENTS(srv6->sids, node, nnode, ctx)) { + if (!ctx->sid || ctx->sid->locator != locator) + continue; + + if (ctx->sid) + zebra_srv6_sid_free(ctx->sid); + + listnode_delete(srv6->sids, ctx); + zebra_srv6_sid_ctx_free(ctx); + } + + /* Notify zclients about the updated locator */ + zebra_notify_srv6_locator_add(locator); + } + } +} + /* * Helper function to create the SRv6 compressed format `usid-f3216`. */ diff --git a/zebra/zebra_srv6.h b/zebra/zebra_srv6.h index e81d182419..0a8b58ce61 100644 --- a/zebra/zebra_srv6.h +++ b/zebra/zebra_srv6.h @@ -68,7 +68,7 @@ struct zebra_srv6_sid_block { * Pointer to the SID format that defines the structure of the SIDs * allocated from this block */ - struct zebra_srv6_sid_format *sid_format; + struct srv6_sid_format *sid_format; /* * Run-time information/state of this SID block. @@ -169,13 +169,16 @@ extern void zebra_srv6_encap_src_addr_unset(void); void srv6_sid_format_register(struct srv6_sid_format *format); void srv6_sid_format_unregister(struct srv6_sid_format *format); struct srv6_sid_format *srv6_sid_format_lookup(const char *name); +void zebra_srv6_locator_format_set(struct srv6_locator *locator, + struct srv6_sid_format *format); +void zebra_srv6_sid_format_changed_cb(struct srv6_sid_format *format); uint32_t *zebra_srv6_sid_func_alloc(uint32_t func); void zebra_srv6_sid_func_free(uint32_t *func); void delete_zebra_srv6_sid_func(void *val); extern struct zebra_srv6_sid_block * -zebra_srv6_sid_block_alloc(struct zebra_srv6_sid_format *format, +zebra_srv6_sid_block_alloc(struct srv6_sid_format *format, struct prefix_ipv6 *prefix); extern void zebra_srv6_sid_block_free(struct zebra_srv6_sid_block *block); extern void delete_zebra_srv6_sid_block(void *val); diff --git a/zebra/zebra_srv6_vty.c b/zebra/zebra_srv6_vty.c index 963b528b86..c664a9c69f 100644 --- a/zebra/zebra_srv6_vty.c +++ b/zebra/zebra_srv6_vty.c @@ -232,7 +232,7 @@ DEFUN (show_srv6_locator_detail, if (locator->sid_format->type == SRV6_SID_FORMAT_TYPE_USID) vty_out(vty, "Behavior: uSID\n"); - } else { + } else { vty_out(vty, "Block-Bit-Len: %u\n", locator->block_bits_length); vty_out(vty, "Node-Bit-Len: %u\n", @@ -244,7 +244,7 @@ DEFUN (show_srv6_locator_detail, if (CHECK_FLAG(locator->flags, SRV6_LOCATOR_USID)) vty_out(vty, "Behavior: uSID\n"); - } + } vty_out(vty, "Chunks:\n"); for (ALL_LIST_ELEMENTS_RO((struct list *)locator->chunks, node, @@ -286,9 +286,30 @@ DEFUN (no_srv6, struct zebra_srv6 *srv6 = zebra_srv6_get_default(); struct srv6_locator *locator; struct listnode *node, *nnode; + struct zebra_srv6_sid_block *block; + struct zebra_srv6_sid_ctx *ctx; + + for (ALL_LIST_ELEMENTS(srv6->sids, node, nnode, ctx)) { + if (ctx->sid) + zebra_srv6_sid_free(ctx->sid); + + listnode_delete(srv6->sids, ctx); + zebra_srv6_sid_ctx_free(ctx); + } + + for (ALL_LIST_ELEMENTS(srv6->locators, node, nnode, locator)) { + block = locator->sid_block; + if (block) { + block->refcnt--; + if (block->refcnt == 0) { + listnode_delete(srv6->sid_blocks, block); + zebra_srv6_sid_block_free(block); + } + locator->sid_block = NULL; + } - for (ALL_LIST_ELEMENTS(srv6->locators, node, nnode, locator)) zebra_srv6_locator_delete(locator); + } return CMD_SUCCESS; } @@ -335,12 +356,37 @@ DEFUN (no_srv6_locator, "Segment Routing SRv6 locator\n" "Specify locator-name\n") { + struct zebra_srv6 *srv6 = zebra_srv6_get_default(); + struct zebra_srv6_sid_block *block; + struct listnode *node, *nnode; + struct zebra_srv6_sid_ctx *ctx; struct srv6_locator *locator = zebra_srv6_locator_lookup(argv[2]->arg); if (!locator) { vty_out(vty, "%% Can't find SRv6 locator\n"); return CMD_WARNING_CONFIG_FAILED; } + for (ALL_LIST_ELEMENTS(srv6->sids, node, nnode, ctx)) { + if (!ctx->sid || ctx->sid->locator != locator) + continue; + + if (ctx->sid) + zebra_srv6_sid_free(ctx->sid); + + listnode_delete(srv6->sids, ctx); + zebra_srv6_sid_ctx_free(ctx); + } + + block = locator->sid_block; + if (block) { + block->refcnt--; + if (block->refcnt == 0) { + listnode_delete(srv6->sid_blocks, block); + zebra_srv6_sid_block_free(block); + } + locator->sid_block = NULL; + } + zebra_srv6_locator_delete(locator); return CMD_SUCCESS; } @@ -361,14 +407,37 @@ DEFPY (locator_prefix, VTY_DECLVAR_CONTEXT(srv6_locator, locator); struct srv6_locator_chunk *chunk = NULL; struct listnode *node = NULL; + uint8_t expected_prefixlen; + struct srv6_sid_format *format; locator->prefix = *prefix; func_bit_len = func_bit_len ?: ZEBRA_SRV6_FUNCTION_LENGTH; + expected_prefixlen = prefix->prefixlen; + format = locator->sid_format; + if (format) { + if (strmatch(format->name, SRV6_SID_FORMAT_USID_F3216_NAME)) + expected_prefixlen = + SRV6_SID_FORMAT_USID_F3216_BLOCK_LEN + + SRV6_SID_FORMAT_USID_F3216_NODE_LEN; + else if (strmatch(format->name, + SRV6_SID_FORMAT_UNCOMPRESSED_F4024_NAME)) + expected_prefixlen = + SRV6_SID_FORMAT_UNCOMPRESSED_F4024_BLOCK_LEN + + SRV6_SID_FORMAT_UNCOMPRESSED_F4024_NODE_LEN; + } + + if (prefix->prefixlen != expected_prefixlen) { + vty_out(vty, + "%% Locator prefix length '%u' inconsistent with configured format '%s'. Please either use a prefix length that is consistent with the format or change the format.\n", + prefix->prefixlen, format->name); + return CMD_WARNING_CONFIG_FAILED; + } + /* Resolve optional arguments */ if (block_bit_len == 0 && node_bit_len == 0) { - block_bit_len = - prefix->prefixlen - ZEBRA_SRV6_LOCATOR_NODE_LENGTH; + block_bit_len = prefix->prefixlen - + ZEBRA_SRV6_LOCATOR_NODE_LENGTH; node_bit_len = ZEBRA_SRV6_LOCATOR_NODE_LENGTH; } else if (block_bit_len == 0) { block_bit_len = prefix->prefixlen - node_bit_len; @@ -439,7 +508,8 @@ DEFPY (locator_prefix, } } - zebra_srv6_locator_add(locator); + zebra_srv6_locator_format_set(locator, locator->sid_format); + return CMD_SUCCESS; } @@ -460,8 +530,9 @@ DEFPY (locator_behavior, /* SRv6 locator uSID flag already set, nothing to do */ return CMD_SUCCESS; - /* Remove old locator from zclients */ - zebra_notify_srv6_locator_delete(locator); + if (!locator->sid_format) + /* Remove old locator from zclients */ + zebra_notify_srv6_locator_delete(locator); /* Set/Unset the SRV6_LOCATOR_USID */ if (no) @@ -469,8 +540,75 @@ DEFPY (locator_behavior, else SET_FLAG(locator->flags, SRV6_LOCATOR_USID); - /* Notify the new locator to zclients */ - zebra_notify_srv6_locator_add(locator); + if (!locator->sid_format) + /* Notify the new locator to zclients */ + zebra_srv6_locator_add(locator); + + return CMD_SUCCESS; +} + +DEFPY(locator_sid_format, + locator_sid_format_cmd, + "format $format", + "Configure SRv6 SID format\n" + "Specify usid-f3216 format\n" + "Specify uncompressed-f4024 format\n") +{ + VTY_DECLVAR_CONTEXT(srv6_locator, locator); + struct srv6_sid_format *sid_format = NULL; + uint8_t expected_prefixlen; + + expected_prefixlen = locator->prefix.prefixlen; + if (strmatch(format, SRV6_SID_FORMAT_USID_F3216_NAME)) + expected_prefixlen = SRV6_SID_FORMAT_USID_F3216_BLOCK_LEN + + SRV6_SID_FORMAT_USID_F3216_NODE_LEN; + else if (strmatch(format, SRV6_SID_FORMAT_UNCOMPRESSED_F4024_NAME)) + expected_prefixlen = + SRV6_SID_FORMAT_UNCOMPRESSED_F4024_BLOCK_LEN + + SRV6_SID_FORMAT_UNCOMPRESSED_F4024_NODE_LEN; + + if (IPV6_ADDR_SAME(&locator->prefix, &in6addr_any)) { + vty_out(vty, + "%% Unexpected configuration sequence: the prefix of the locator is required before configuring the format. Please configure the prefix first and then configure the format.\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (locator->prefix.prefixlen != expected_prefixlen) { + vty_out(vty, + "%% Locator prefix length '%u' inconsistent with configured format '%s'. Please either use a prefix length that is consistent with the format or change the format.\n", + locator->prefix.prefixlen, format); + return CMD_WARNING_CONFIG_FAILED; + } + + sid_format = srv6_sid_format_lookup(format); + if (!sid_format) { + vty_out(vty, "%% Cannot find SRv6 SID format '%s'\n", format); + return CMD_WARNING_CONFIG_FAILED; + } + + if (sid_format == locator->sid_format) + /* Format has not changed, nothing to do */ + return CMD_SUCCESS; + + zebra_srv6_locator_format_set(locator, sid_format); + + return CMD_SUCCESS; +} + +DEFPY (no_locator_sid_format, + no_locator_sid_format_cmd, + "no format [WORD]", + NO_STR + "Configure SRv6 SID format\n" + "Specify SRv6 SID format\n") +{ + VTY_DECLVAR_CONTEXT(srv6_locator, locator); + + if (!locator->sid_format) + /* SID format already unset, nothing to do */ + return CMD_SUCCESS; + + zebra_srv6_locator_format_set(locator, NULL); return CMD_SUCCESS; } @@ -550,6 +688,9 @@ DEFUN(no_srv6_sid_format_f3216_usid, format->config.usid.wlib_end = SRV6_SID_FORMAT_USID_F3216_WLIB_END; format->config.usid.ewlib_start = SRV6_SID_FORMAT_USID_F3216_EWLIB_START; + /* Notify zclients that the format has changed */ + zebra_srv6_sid_format_changed_cb(format); + return CMD_SUCCESS; } @@ -583,6 +724,9 @@ DEFUN(no_srv6_sid_format_f4024_uncompressed, format->config.uncompressed.explicit_start = SRV6_SID_FORMAT_UNCOMPRESSED_F4024_EXPLICIT_RANGE_START; + /* Notify zclients that the format has changed */ + zebra_srv6_sid_format_changed_cb(format); + return CMD_SUCCESS; } @@ -597,6 +741,9 @@ DEFPY(srv6_sid_format_usid_lib, format->config.usid.lib_start = start; + /* Notify zclients that the format has changed */ + zebra_srv6_sid_format_changed_cb(format); + return CMD_SUCCESS; } @@ -616,6 +763,9 @@ DEFPY(no_srv6_sid_format_usid_lib, else assert(0); + /* Notify zclients that the format has changed */ + zebra_srv6_sid_format_changed_cb(format); + return CMD_SUCCESS; } @@ -634,6 +784,9 @@ DEFPY(srv6_sid_format_usid_lib_explicit, format->config.usid.elib_start = start; format->config.usid.elib_end = end; + /* Notify zclients that the format has changed */ + zebra_srv6_sid_format_changed_cb(format); + return CMD_SUCCESS; } @@ -659,6 +812,9 @@ DEFPY(no_srv6_sid_format_usid_lib_explicit, assert(0); } + /* Notify zclients that the format has changed */ + zebra_srv6_sid_format_changed_cb(format); + return CMD_SUCCESS; } @@ -676,6 +832,9 @@ DEFPY(srv6_sid_format_usid_wlib, format->config.usid.wlib_start = start; format->config.usid.wlib_end = end; + /* Notify zclients that the format has changed */ + zebra_srv6_sid_format_changed_cb(format); + return CMD_SUCCESS; } @@ -700,6 +859,9 @@ DEFPY(no_srv6_sid_format_usid_wlib, assert(0); } + /* Notify zclients that the format has changed */ + zebra_srv6_sid_format_changed_cb(format); + return CMD_SUCCESS; } @@ -715,6 +877,9 @@ DEFPY(srv6_sid_format_usid_wide_lib_explicit, format->config.usid.ewlib_start = start; + /* Notify zclients that the format has changed */ + zebra_srv6_sid_format_changed_cb(format); + return CMD_SUCCESS; } @@ -735,6 +900,9 @@ DEFPY(no_srv6_sid_format_usid_wide_lib_explicit, else assert(0); + /* Notify zclients that the format has changed */ + zebra_srv6_sid_format_changed_cb(format); + return CMD_SUCCESS; } @@ -749,6 +917,9 @@ DEFPY(srv6_sid_format_explicit, format->config.uncompressed.explicit_start = start; + /* Notify zclients that the format has changed */ + zebra_srv6_sid_format_changed_cb(format); + return CMD_SUCCESS; } @@ -768,6 +939,9 @@ DEFPY(no_srv6_sid_format_explicit, else assert(0); + /* Notify zclients that the format has changed */ + zebra_srv6_sid_format_changed_cb(format); + return CMD_SUCCESS; } @@ -818,6 +992,10 @@ static int zebra_sr_config(struct vty *vty) vty_out(vty, "\n"); if (CHECK_FLAG(locator->flags, SRV6_LOCATOR_USID)) vty_out(vty, " behavior usid\n"); + if (locator->sid_format) { + format = locator->sid_format; + vty_out(vty, " format %s\n", format->name); + } vty_out(vty, " exit\n"); vty_out(vty, " !\n"); } @@ -917,6 +1095,8 @@ void zebra_srv6_vty_init(void) /* Command for configuration */ install_element(SRV6_LOC_NODE, &locator_prefix_cmd); install_element(SRV6_LOC_NODE, &locator_behavior_cmd); + install_element(SRV6_LOC_NODE, &locator_sid_format_cmd); + install_element(SRV6_LOC_NODE, &no_locator_sid_format_cmd); install_element(SRV6_ENCAP_NODE, &srv6_src_addr_cmd); install_element(SRV6_ENCAP_NODE, &no_srv6_src_addr_cmd); install_element(SRV6_SID_FORMAT_USID_F3216_NODE, -- cgit v1.2.3 From 3cb88e69848d607a8d069b0858798e2de324fd43 Mon Sep 17 00:00:00 2001 From: Carmine Scarpitta Date: Mon, 6 May 2024 17:44:18 +0200 Subject: lib: Add support for SRv6 SIDs Add a data structure to represent an SRv6 SID context and the related management functions (allocate/free). Signed-off-by: Carmine Scarpitta --- lib/srv6.c | 24 +++++++++++++++++++++++ lib/srv6.h | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) (limited to 'lib/srv6.h') diff --git a/lib/srv6.c b/lib/srv6.c index 1f485fb8ac..883d429b62 100644 --- a/lib/srv6.c +++ b/lib/srv6.c @@ -14,6 +14,7 @@ DEFINE_QOBJ_TYPE(srv6_sid_format); DEFINE_MTYPE_STATIC(LIB, SRV6_LOCATOR, "SRV6 locator"); DEFINE_MTYPE_STATIC(LIB, SRV6_LOCATOR_CHUNK, "SRV6 locator chunk"); DEFINE_MTYPE_STATIC(LIB, SRV6_SID_FORMAT, "SRv6 SID format"); +DEFINE_MTYPE_STATIC(LIB, SRV6_SID_CTX, "SRv6 SID context"); const char *seg6local_action2str(uint32_t action) { @@ -201,6 +202,29 @@ void delete_srv6_sid_format(void *val) srv6_sid_format_free((struct srv6_sid_format *)val); } +struct srv6_sid_ctx *srv6_sid_ctx_alloc(enum seg6local_action_t behavior, + struct in_addr *nh4, + struct in6_addr *nh6, vrf_id_t vrf_id) +{ + struct srv6_sid_ctx *ctx = NULL; + + ctx = XCALLOC(MTYPE_SRV6_SID_CTX, sizeof(struct srv6_sid_ctx)); + ctx->behavior = behavior; + if (nh4) + ctx->nh4 = *nh4; + if (nh6) + ctx->nh6 = *nh6; + if (vrf_id) + ctx->vrf_id = vrf_id; + + return ctx; +} + +void srv6_sid_ctx_free(struct srv6_sid_ctx *ctx) +{ + XFREE(MTYPE_SRV6_SID_CTX, ctx); +} + json_object *srv6_locator_chunk_json(const struct srv6_locator_chunk *chunk) { json_object *jo_root = NULL; diff --git a/lib/srv6.h b/lib/srv6.h index 4a6ea5c72b..01b0820133 100644 --- a/lib/srv6.h +++ b/lib/srv6.h @@ -246,6 +246,17 @@ struct srv6_sid_format { }; DECLARE_QOBJ_TYPE(srv6_sid_format); +/* Context for an SRv6 SID */ +struct srv6_sid_ctx { + /* Behavior associated with the SID */ + enum seg6local_action_t behavior; + + /* Behavior-specific attributes */ + struct in_addr nh4; + struct in6_addr nh6; + vrf_id_t vrf_id; +}; + static inline const char *seg6_mode2str(enum seg6_mode_t mode) { switch (mode) { @@ -309,6 +320,54 @@ const char *seg6local_context2str(char *str, size_t size, const struct seg6local_context *ctx, uint32_t action); +static inline const char *srv6_sid_ctx2str(char *str, size_t size, + const struct srv6_sid_ctx *ctx) +{ + int len = 0; + + len += snprintf(str + len, size - len, "%s", + seg6local_action2str(ctx->behavior)); + + switch (ctx->behavior) { + case ZEBRA_SEG6_LOCAL_ACTION_UNSPEC: + break; + + case ZEBRA_SEG6_LOCAL_ACTION_END: + len += snprintf(str + len, size - len, " USP"); + break; + + case ZEBRA_SEG6_LOCAL_ACTION_END_X: + case ZEBRA_SEG6_LOCAL_ACTION_END_DX6: + len += snprintfrr(str + len, size - len, " nh6 %pI6", &ctx->nh6); + break; + + case ZEBRA_SEG6_LOCAL_ACTION_END_DX4: + len += snprintfrr(str + len, size - len, " nh4 %pI4", &ctx->nh4); + break; + + case ZEBRA_SEG6_LOCAL_ACTION_END_T: + case ZEBRA_SEG6_LOCAL_ACTION_END_DT6: + case ZEBRA_SEG6_LOCAL_ACTION_END_DT4: + case ZEBRA_SEG6_LOCAL_ACTION_END_DT46: + len += snprintf(str + len, size - len, " vrf_id %u", + ctx->vrf_id); + break; + + case ZEBRA_SEG6_LOCAL_ACTION_END_DX2: + case ZEBRA_SEG6_LOCAL_ACTION_END_B6: + case ZEBRA_SEG6_LOCAL_ACTION_END_B6_ENCAP: + case ZEBRA_SEG6_LOCAL_ACTION_END_BM: + case ZEBRA_SEG6_LOCAL_ACTION_END_S: + case ZEBRA_SEG6_LOCAL_ACTION_END_AS: + case ZEBRA_SEG6_LOCAL_ACTION_END_AM: + case ZEBRA_SEG6_LOCAL_ACTION_END_BPF: + default: + len += snprintf(str + len, size - len, " unknown(%s)", __func__); + } + + return str; +} + int snprintf_seg6_segs(char *str, size_t size, const struct seg6_segs *segs); @@ -329,6 +388,12 @@ extern struct srv6_sid_format *srv6_sid_format_alloc(const char *name); extern void srv6_sid_format_free(struct srv6_sid_format *format); extern void delete_srv6_sid_format(void *format); +extern struct srv6_sid_ctx *srv6_sid_ctx_alloc(enum seg6local_action_t behavior, + struct in_addr *nh4, + struct in6_addr *nh6, + vrf_id_t vrf_id); +extern void srv6_sid_ctx_free(struct srv6_sid_ctx *ctx); + #ifdef __cplusplus } #endif -- cgit v1.2.3