]> git.puffer.fish Git - matthieu/frr.git/commitdiff
zebra: CLI to specify format of an SRv6 locator
authorCarmine Scarpitta <cscarpit@cisco.com>
Fri, 22 Mar 2024 18:31:01 +0000 (19:31 +0100)
committerCarmine Scarpitta <cscarpit@cisco.com>
Thu, 13 Jun 2024 12:54:16 +0000 (14:54 +0200)
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 <cscarpit@cisco.com>
lib/srv6.h
zebra/zapi_msg.c
zebra/zebra_srv6.c
zebra/zebra_srv6.h
zebra/zebra_srv6_vty.c

index 66f1854dabda6d5992ddba37a8ffac27b6a54293..4a6ea5c72beabe5badd4c3b4b346e53d2815b298 100644 (file)
@@ -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);
index d585ef996bf069e1abb56aed23302054f51bed1c..2d580e2972ed8665bd16230e101698d6bcea47f4 100644 (file)
@@ -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);
index 2e5c499838d8a271955f2e1e58b18d4fc83f773b..e6b3c2a2522a1649e7fdb305c07bdc02ce2fd963 100644 (file)
@@ -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`.
  */
index e81d182419ef0f54ef388bc90281f5da1dafa5a9..0a8b58ce6183084f5c5c9c8c7973e829e74bdc8c 100644 (file)
@@ -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);
index 963b528b8692750dfd32691a3e1045a0c5912432..c664a9c69f1ef758256223666427ef7dadd81f40 100644 (file)
@@ -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 <usid-f3216|uncompressed-f4024>$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,