From 1298867671f7fe76c65730afbb9ae54dcd7264be Mon Sep 17 00:00:00 2001 From: Carmine Scarpitta Date: Thu, 6 Jun 2024 17:23:11 +0200 Subject: zebra: Add support for SRv6 SID formats Add functionalities to manage SRv6 SID formats (register / unregister / lookup) and create two SID formats upon SRv6 Manager initialization: `uncompressed-f4024` and `usid-f3216`. In future commits, we will add the CLI to allow the user to choose between the two formats. Signed-off-by: Carmine Scarpitta --- zebra/zebra_srv6_vty.c | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) (limited to 'zebra/zebra_srv6_vty.c') diff --git a/zebra/zebra_srv6_vty.c b/zebra/zebra_srv6_vty.c index d5cd30e64b..ddb0922475 100644 --- a/zebra/zebra_srv6_vty.c +++ b/zebra/zebra_srv6_vty.c @@ -198,15 +198,32 @@ DEFUN (show_srv6_locator_detail, prefix2str(&locator->prefix, str, sizeof(str)); vty_out(vty, "Name: %s\n", locator->name); vty_out(vty, "Prefix: %s\n", str); - vty_out(vty, "Block-Bit-Len: %u\n", locator->block_bits_length); - vty_out(vty, "Node-Bit-Len: %u\n", locator->node_bits_length); - vty_out(vty, "Function-Bit-Len: %u\n", - locator->function_bits_length); - vty_out(vty, "Argument-Bit-Len: %u\n", - locator->argument_bits_length); - - if (CHECK_FLAG(locator->flags, SRV6_LOCATOR_USID)) - vty_out(vty, "Behavior: uSID\n"); + if (locator->sid_format) { + vty_out(vty, "Block-Bit-Len: %u\n", + locator->sid_format->block_len); + vty_out(vty, "Node-Bit-Len: %u\n", + locator->sid_format->node_len); + vty_out(vty, "Function-Bit-Len: %u\n", + locator->sid_format->function_len); + vty_out(vty, "Argument-Bit-Len: %u\n", + locator->sid_format->argument_len); + + if (locator->sid_format->type == + SRV6_SID_FORMAT_TYPE_USID) + vty_out(vty, "Behavior: uSID\n"); + } else { + vty_out(vty, "Block-Bit-Len: %u\n", + locator->block_bits_length); + vty_out(vty, "Node-Bit-Len: %u\n", + locator->node_bits_length); + vty_out(vty, "Function-Bit-Len: %u\n", + locator->function_bits_length); + vty_out(vty, "Argument-Bit-Len: %u\n", + locator->argument_bits_length); + + 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, -- cgit v1.2.3 From 51d3cd8a007d5c2ad6bb27af404f2d95164cf4c2 Mon Sep 17 00:00:00 2001 From: Carmine Scarpitta Date: Tue, 26 Mar 2024 08:53:55 +0100 Subject: zebra: CLI to override default SID format config Add CLI commands to support overriding default configuration of the SID format. Signed-off-by: Carmine Scarpitta --- zebra/zebra_srv6.c | 57 ++++---- zebra/zebra_srv6.h | 42 +++--- zebra/zebra_srv6_vty.c | 365 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 411 insertions(+), 53 deletions(-) (limited to 'zebra/zebra_srv6_vty.c') diff --git a/zebra/zebra_srv6.c b/zebra/zebra_srv6.c index fa3b4a733b..825f0f7fc2 100644 --- a/zebra/zebra_srv6.c +++ b/zebra/zebra_srv6.c @@ -92,24 +92,24 @@ static int zebra_srv6_cleanup(struct zserv *client) /* --- Zebra SRv6 SID format management functions --------------------------- */ -void zebra_srv6_sid_format_register(struct srv6_sid_format *format) +void srv6_sid_format_register(struct srv6_sid_format *format) { struct zebra_srv6 *srv6 = zebra_srv6_get_default(); /* Ensure that the format is registered only once */ - assert(!zebra_srv6_sid_format_lookup(format->name)); + assert(!srv6_sid_format_lookup(format->name)); listnode_add(srv6->sid_formats, format); } -void zebra_srv6_sid_format_unregister(struct srv6_sid_format *format) +void srv6_sid_format_unregister(struct srv6_sid_format *format) { struct zebra_srv6 *srv6 = zebra_srv6_get_default(); listnode_delete(srv6->sid_formats, format); } -struct srv6_sid_format *zebra_srv6_sid_format_lookup(const char *name) +struct srv6_sid_format *srv6_sid_format_lookup(const char *name) { struct zebra_srv6 *srv6 = zebra_srv6_get_default(); struct srv6_sid_format *format; @@ -129,27 +129,23 @@ static struct srv6_sid_format *create_srv6_sid_format_usid_f3216(void) { struct srv6_sid_format *format = NULL; - format = srv6_sid_format_alloc(ZEBRA_SRV6_SID_FORMAT_USID_F3216_NAME); + format = srv6_sid_format_alloc(SRV6_SID_FORMAT_USID_F3216_NAME); format->type = SRV6_SID_FORMAT_TYPE_USID; /* Define block/node/function length */ - format->block_len = ZEBRA_SRV6_SID_FORMAT_USID_F3216_BLOCK_LEN; - format->node_len = ZEBRA_SRV6_SID_FORMAT_USID_F3216_NODE_LEN; - format->function_len = ZEBRA_SRV6_SID_FORMAT_USID_F3216_FUNCTION_LEN; - format->argument_len = ZEBRA_SRV6_SID_FORMAT_USID_F3216_ARGUMENT_LEN; + format->block_len = SRV6_SID_FORMAT_USID_F3216_BLOCK_LEN; + format->node_len = SRV6_SID_FORMAT_USID_F3216_NODE_LEN; + format->function_len = SRV6_SID_FORMAT_USID_F3216_FUNCTION_LEN; + format->argument_len = SRV6_SID_FORMAT_USID_F3216_ARGUMENT_LEN; /* Define the ranges from which the SID function can be allocated */ - format->config.usid.lib_start = - ZEBRA_SRV6_SID_FORMAT_USID_F3216_LIB_START; - format->config.usid.elib_start = - ZEBRA_SRV6_SID_FORMAT_USID_F3216_ELIB_START; - format->config.usid.elib_end = ZEBRA_SRV6_SID_FORMAT_USID_F3216_ELIB_END; - format->config.usid.wlib_start = - ZEBRA_SRV6_SID_FORMAT_USID_F3216_WLIB_START; - format->config.usid.wlib_end = ZEBRA_SRV6_SID_FORMAT_USID_F3216_WLIB_END; - format->config.usid.ewlib_start = - ZEBRA_SRV6_SID_FORMAT_USID_F3216_EWLIB_START; + format->config.usid.lib_start = SRV6_SID_FORMAT_USID_F3216_LIB_START; + format->config.usid.elib_start = SRV6_SID_FORMAT_USID_F3216_ELIB_START; + format->config.usid.elib_end = SRV6_SID_FORMAT_USID_F3216_ELIB_END; + format->config.usid.wlib_start = SRV6_SID_FORMAT_USID_F3216_WLIB_START; + format->config.usid.wlib_end = SRV6_SID_FORMAT_USID_F3216_WLIB_END; + format->config.usid.ewlib_start = SRV6_SID_FORMAT_USID_F3216_EWLIB_START; return format; } @@ -161,22 +157,19 @@ static struct srv6_sid_format *create_srv6_sid_format_uncompressed(void) { struct srv6_sid_format *format = NULL; - format = srv6_sid_format_alloc( - ZEBRA_SRV6_SID_FORMAT_UNCOMPRESSED_F4024_NAME); + format = srv6_sid_format_alloc(SRV6_SID_FORMAT_UNCOMPRESSED_F4024_NAME); - format->type = ZEBRA_SRV6_SID_FORMAT_TYPE_UNCOMPRESSED; + format->type = SRV6_SID_FORMAT_TYPE_UNCOMPRESSED; /* Define block/node/function length */ - format->block_len = ZEBRA_SRV6_SID_FORMAT_UNCOMPRESSED_F4024_BLOCK_LEN; - format->node_len = ZEBRA_SRV6_SID_FORMAT_UNCOMPRESSED_F4024_NODE_LEN; - format->function_len = - ZEBRA_SRV6_SID_FORMAT_UNCOMPRESSED_F4024_FUNCTION_LEN; - format->argument_len = - ZEBRA_SRV6_SID_FORMAT_UNCOMPRESSED_F4024_ARGUMENT_LEN; + format->block_len = SRV6_SID_FORMAT_UNCOMPRESSED_F4024_BLOCK_LEN; + format->node_len = SRV6_SID_FORMAT_UNCOMPRESSED_F4024_NODE_LEN; + format->function_len = SRV6_SID_FORMAT_UNCOMPRESSED_F4024_FUNCTION_LEN; + format->argument_len = SRV6_SID_FORMAT_UNCOMPRESSED_F4024_ARGUMENT_LEN; /* Define the ranges from which the SID function can be allocated */ format->config.uncompressed.explicit_start = - ZEBRA_SRV6_SID_FORMAT_UNCOMPRESSED_F4024_EXPLICIT_RANGE_START; + SRV6_SID_FORMAT_UNCOMPRESSED_F4024_EXPLICIT_RANGE_START; return format; } @@ -326,11 +319,11 @@ struct zebra_srv6 *zebra_srv6_get_default(void) /* Create SID format `usid-f3216` */ format_usidf3216 = create_srv6_sid_format_usid_f3216(); - zebra_srv6_sid_format_register(format_usidf3216); + srv6_sid_format_register(format_usidf3216); /* Create SID format `uncompressed` */ format_uncompressed = create_srv6_sid_format_uncompressed(); - zebra_srv6_sid_format_register(format_uncompressed); + srv6_sid_format_register(format_uncompressed); } return &srv6; } @@ -553,7 +546,7 @@ void zebra_srv6_terminate(void) while (listcount(srv6.sid_formats)) { format = listnode_head(srv6.sid_formats); - zebra_srv6_sid_format_unregister(format); + srv6_sid_format_unregister(format); srv6_sid_format_free(format); } diff --git a/zebra/zebra_srv6.h b/zebra/zebra_srv6.h index 57f9d83825..92e4fcf912 100644 --- a/zebra/zebra_srv6.h +++ b/zebra/zebra_srv6.h @@ -17,26 +17,26 @@ #include /* Default config for SRv6 SID `usid-f3216` format */ -#define ZEBRA_SRV6_SID_FORMAT_USID_F3216_NAME "usid-f3216" -#define ZEBRA_SRV6_SID_FORMAT_USID_F3216_BLOCK_LEN 32 -#define ZEBRA_SRV6_SID_FORMAT_USID_F3216_NODE_LEN 16 -#define ZEBRA_SRV6_SID_FORMAT_USID_F3216_FUNCTION_LEN 16 -#define ZEBRA_SRV6_SID_FORMAT_USID_F3216_ARGUMENT_LEN 0 -#define ZEBRA_SRV6_SID_FORMAT_USID_F3216_LIB_START 0xE000 -#define ZEBRA_SRV6_SID_FORMAT_USID_F3216_ELIB_START 0xFE00 -#define ZEBRA_SRV6_SID_FORMAT_USID_F3216_ELIB_END 0xFEFF -#define ZEBRA_SRV6_SID_FORMAT_USID_F3216_WLIB_START 0xFFF0 -#define ZEBRA_SRV6_SID_FORMAT_USID_F3216_WLIB_END 0xFFF7 -#define ZEBRA_SRV6_SID_FORMAT_USID_F3216_EWLIB_START 0xFFF7 +#define SRV6_SID_FORMAT_USID_F3216_NAME "usid-f3216" +#define SRV6_SID_FORMAT_USID_F3216_BLOCK_LEN 32 +#define SRV6_SID_FORMAT_USID_F3216_NODE_LEN 16 +#define SRV6_SID_FORMAT_USID_F3216_FUNCTION_LEN 16 +#define SRV6_SID_FORMAT_USID_F3216_ARGUMENT_LEN 0 +#define SRV6_SID_FORMAT_USID_F3216_LIB_START 0xE000 +#define SRV6_SID_FORMAT_USID_F3216_ELIB_START 0xFE00 +#define SRV6_SID_FORMAT_USID_F3216_ELIB_END 0xFEFF +#define SRV6_SID_FORMAT_USID_F3216_WLIB_START 0xFFF0 +#define SRV6_SID_FORMAT_USID_F3216_WLIB_END 0xFFF7 +#define SRV6_SID_FORMAT_USID_F3216_EWLIB_START 0xFFF7 /* Default config for SRv6 SID `uncompressed` format */ -#define ZEBRA_SRV6_SID_FORMAT_UNCOMPRESSED_F4024_NAME "uncompressed-f4024" -#define ZEBRA_SRV6_SID_FORMAT_UNCOMPRESSED_F4024_BLOCK_LEN 40 -#define ZEBRA_SRV6_SID_FORMAT_UNCOMPRESSED_F4024_NODE_LEN 24 -#define ZEBRA_SRV6_SID_FORMAT_UNCOMPRESSED_F4024_FUNCTION_LEN 16 -#define ZEBRA_SRV6_SID_FORMAT_UNCOMPRESSED_F4024_ARGUMENT_LEN 0 -#define ZEBRA_SRV6_SID_FORMAT_UNCOMPRESSED_F4024_EXPLICIT_RANGE_START 0xFF00 -#define ZEBRA_SRV6_SID_FORMAT_UNCOMPRESSED_F4024_FUNC_UNRESERVED_MIN 0x40 +#define SRV6_SID_FORMAT_UNCOMPRESSED_F4024_NAME "uncompressed-f4024" +#define SRV6_SID_FORMAT_UNCOMPRESSED_F4024_BLOCK_LEN 40 +#define SRV6_SID_FORMAT_UNCOMPRESSED_F4024_NODE_LEN 24 +#define SRV6_SID_FORMAT_UNCOMPRESSED_F4024_FUNCTION_LEN 16 +#define SRV6_SID_FORMAT_UNCOMPRESSED_F4024_ARGUMENT_LEN 0 +#define SRV6_SID_FORMAT_UNCOMPRESSED_F4024_EXPLICIT_RANGE_START 0xFF00 +#define SRV6_SID_FORMAT_UNCOMPRESSED_F4024_FUNC_UNRESERVED_MIN 0x40 /* SRv6 instance structure. */ struct zebra_srv6 { @@ -99,8 +99,8 @@ extern int release_daemon_srv6_locator_chunks(struct zserv *client); extern void zebra_srv6_encap_src_addr_set(struct in6_addr *src_addr); extern void zebra_srv6_encap_src_addr_unset(void); -void zebra_srv6_sid_format_register(struct srv6_sid_format *format); -void zebra_srv6_sid_format_unregister(struct srv6_sid_format *format); -struct srv6_sid_format *zebra_srv6_sid_format_lookup(const char *name); +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); #endif /* _ZEBRA_SRV6_H */ diff --git a/zebra/zebra_srv6_vty.c b/zebra/zebra_srv6_vty.c index ddb0922475..e5fe0d58a9 100644 --- a/zebra/zebra_srv6_vty.c +++ b/zebra/zebra_srv6_vty.c @@ -68,6 +68,27 @@ static struct cmd_node srv6_encap_node = { .prompt = "%s(config-srv6-encap)# " }; +static struct cmd_node srv6_sid_formats_node = { + .name = "srv6-formats", + .node = SRV6_SID_FORMATS_NODE, + .parent_node = SRV6_NODE, + .prompt = "%s(config-srv6-formats)# ", +}; + +static struct cmd_node srv6_sid_format_usid_f3216_node = { + .name = "srv6-format-usid-f3216", + .node = SRV6_SID_FORMAT_USID_F3216_NODE, + .parent_node = SRV6_SID_FORMATS_NODE, + .prompt = "%s(config-srv6-format)# " +}; + +static struct cmd_node srv6_sid_format_uncompressed_f4024_node = { + .name = "srv6-format-uncompressed-f4024", + .node = SRV6_SID_FORMAT_UNCOMPRESSED_F4024_NODE, + .parent_node = SRV6_SID_FORMATS_NODE, + .prompt = "%s(config-srv6-format)# " +}; + DEFPY (show_srv6_manager, show_srv6_manager_cmd, "show segment-routing srv6 manager [json]", @@ -486,11 +507,276 @@ DEFPY (no_srv6_src_addr, return CMD_SUCCESS; } +DEFUN_NOSH(srv6_sid_formats, + srv6_sid_formats_cmd, + "formats", + "Segment Routing SRv6 SID formats\n") +{ + vty->node = SRV6_SID_FORMATS_NODE; + return CMD_SUCCESS; +} + +DEFUN_NOSH (srv6_sid_format_f3216_usid, + srv6_sid_format_f3216_usid_cmd, + "format usid-f3216", + "Configure SRv6 SID format\n" + "Configure the uSID f3216 format\n") +{ + struct srv6_sid_format *format; + + format = srv6_sid_format_lookup(SRV6_SID_FORMAT_USID_F3216_NAME); + assert(format); + + VTY_PUSH_CONTEXT(SRV6_SID_FORMAT_USID_F3216_NODE, format); + return CMD_SUCCESS; +} + +DEFUN(no_srv6_sid_format_f3216_usid, + no_srv6_sid_format_f3216_usid_cmd, + "no format usid-f3216", + NO_STR + "Configure SRv6 SID format\n" + "Configure the uSID f3216 format\n") +{ + struct srv6_sid_format *format; + + format = srv6_sid_format_lookup(SRV6_SID_FORMAT_USID_F3216_NAME); + assert(format); + + format->config.usid.lib_start = SRV6_SID_FORMAT_USID_F3216_LIB_START; + format->config.usid.elib_start = SRV6_SID_FORMAT_USID_F3216_ELIB_START; + format->config.usid.elib_end = SRV6_SID_FORMAT_USID_F3216_ELIB_END; + format->config.usid.wlib_start = SRV6_SID_FORMAT_USID_F3216_WLIB_START; + format->config.usid.wlib_end = SRV6_SID_FORMAT_USID_F3216_WLIB_END; + format->config.usid.ewlib_start = SRV6_SID_FORMAT_USID_F3216_EWLIB_START; + + return CMD_SUCCESS; +} + +DEFUN_NOSH (srv6_sid_format_f4024_uncompressed, + srv6_sid_format_uncompressed_cmd, + "format uncompressed-f4024", + "Configure SRv6 SID format\n" + "Configure the uncompressed f4024 format\n") +{ + struct srv6_sid_format *format; + + format = srv6_sid_format_lookup(SRV6_SID_FORMAT_UNCOMPRESSED_F4024_NAME); + assert(format); + + VTY_PUSH_CONTEXT(SRV6_SID_FORMAT_UNCOMPRESSED_F4024_NODE, format); + return CMD_SUCCESS; +} + +DEFUN(no_srv6_sid_format_f4024_uncompressed, + no_srv6_sid_format_f4024_uncompressed_cmd, + "no format uncompressed-f4024", + NO_STR + "Configure SRv6 SID format\n" + "Configure the uncompressed f4024 format\n") +{ + struct srv6_sid_format *format; + + format = srv6_sid_format_lookup(SRV6_SID_FORMAT_UNCOMPRESSED_F4024_NAME); + assert(format); + + format->config.uncompressed.explicit_start = + SRV6_SID_FORMAT_UNCOMPRESSED_F4024_EXPLICIT_RANGE_START; + + return CMD_SUCCESS; +} + +DEFPY(srv6_sid_format_usid_lib, + srv6_sid_format_usid_lib_cmd, + "local-id-block start (0-4294967295)$start", + "Configure LIB\n" + "Configure the start value for the LIB\n" + "Specify the start value for the LIB\n") +{ + VTY_DECLVAR_CONTEXT(srv6_sid_format, format); + + format->config.usid.lib_start = start; + + return CMD_SUCCESS; +} + +DEFPY(no_srv6_sid_format_usid_lib, + no_srv6_sid_format_usid_lib_cmd, + "no local-id-block [start (0-4294967295)]", + NO_STR + "Configure LIB\n" + "Configure the start value for the LIB\n" + "Specify the start value for the LIB\n") +{ + VTY_DECLVAR_CONTEXT(srv6_sid_format, format); + + if (strmatch(format->name, SRV6_SID_FORMAT_USID_F3216_NAME)) + format->config.usid.lib_start = + SRV6_SID_FORMAT_USID_F3216_LIB_START; + else + assert(0); + + return CMD_SUCCESS; +} + +DEFPY(srv6_sid_format_usid_lib_explicit, + srv6_sid_format_usid_lib_explicit_cmd, + "local-id-block explicit start (0-4294967295)$start end (0-4294967295)$end", + "Configure LIB\n" + "Configure the Explicit LIB\n" + "Configure the start value for the Explicit LIB\n" + "Specify the start value for the Explicit LIB\n" + "Configure the end value for the Explicit LIB\n" + "Specify the end value for the Explicit LIB\n") +{ + VTY_DECLVAR_CONTEXT(srv6_sid_format, format); + + format->config.usid.elib_start = start; + format->config.usid.elib_end = end; + + return CMD_SUCCESS; +} + +DEFPY(no_srv6_sid_format_usid_lib_explicit, + no_srv6_sid_format_usid_lib_explicit_cmd, + "no local-id-block explicit [start (0-4294967295) end (0-4294967295)]", + NO_STR + "Configure LIB\n" + "Configure the Explicit LIB\n" + "Configure the start value for the Explicit LIB\n" + "Specify the start value for the Explicit LIB\n" + "Configure the end value for the Explicit LIB\n" + "Specify the end value for the Explicit LIB\n") +{ + VTY_DECLVAR_CONTEXT(srv6_sid_format, format); + + if (strmatch(format->name, SRV6_SID_FORMAT_USID_F3216_NAME)) { + format->config.usid.elib_start = + SRV6_SID_FORMAT_USID_F3216_ELIB_START; + format->config.usid.elib_end = + SRV6_SID_FORMAT_USID_F3216_ELIB_END; + } else { + assert(0); + } + + return CMD_SUCCESS; +} + +DEFPY(srv6_sid_format_usid_wlib, + srv6_sid_format_usid_wlib_cmd, + "wide-local-id-block start (0-4294967295)$start end (0-4294967295)$end", + "Configure Wide LIB\n" + "Configure the start value for the Wide LIB\n" + "Specify the start value for the Wide LIB\n" + "Configure the end value for the Wide LIB\n" + "Specify the end value for the Wide LIB\n") +{ + VTY_DECLVAR_CONTEXT(srv6_sid_format, format); + + format->config.usid.wlib_start = start; + format->config.usid.wlib_end = end; + + return CMD_SUCCESS; +} + +DEFPY(no_srv6_sid_format_usid_wlib, + no_srv6_sid_format_usid_wlib_cmd, + "no wide-local-id-block [start (0-4294967295) end (0-4294967295)]", + NO_STR + "Configure Wide LIB\n" + "Configure the start value for the Wide LIB\n" + "Specify the start value for the Wide LIB\n" + "Configure the end value for the Wide LIB\n" + "Specify the end value for the Wide LIB\n") +{ + VTY_DECLVAR_CONTEXT(srv6_sid_format, format); + + if (strmatch(format->name, SRV6_SID_FORMAT_USID_F3216_NAME)) { + format->config.usid.wlib_start = + SRV6_SID_FORMAT_USID_F3216_WLIB_START; + format->config.usid.wlib_end = + SRV6_SID_FORMAT_USID_F3216_WLIB_END; + } else { + assert(0); + } + + return CMD_SUCCESS; +} + +DEFPY(srv6_sid_format_usid_wide_lib_explicit, + srv6_sid_format_usid_wide_lib_explicit_cmd, + "wide-local-id-block explicit start (0-4294967295)$start", + "Configure Wide LIB\n" + "Configure Explicit Wide LIB\n" + "Configure the start value for the Explicit Wide LIB\n" + "Specify the start value for the Explicit Wide LIB\n") +{ + VTY_DECLVAR_CONTEXT(srv6_sid_format, format); + + format->config.usid.ewlib_start = start; + + return CMD_SUCCESS; +} + +DEFPY(no_srv6_sid_format_usid_wide_lib_explicit, + no_srv6_sid_format_usid_wide_lib_explicit_cmd, + "no wide-local-id-block explicit [start (0-4294967295)]", + NO_STR + "Configure Wide LIB\n" + "Configure Explicit Wide LIB\n" + "Configure the start value for the Explicit Wide LIB\n" + "Specify the start value for the Explicit Wide LIB\n") +{ + VTY_DECLVAR_CONTEXT(srv6_sid_format, format); + + if (strmatch(format->name, SRV6_SID_FORMAT_USID_F3216_NAME)) + format->config.usid.ewlib_start = + SRV6_SID_FORMAT_USID_F3216_EWLIB_START; + else + assert(0); + + return CMD_SUCCESS; +} + +DEFPY(srv6_sid_format_explicit, + srv6_sid_format_explicit_cmd, + "explicit start (0-4294967295)$start", + "Configure Explicit range\n" + "Configure the start value for the Explicit range\n" + "Specify the start value for the Explicit range\n") +{ + VTY_DECLVAR_CONTEXT(srv6_sid_format, format); + + format->config.uncompressed.explicit_start = start; + + return CMD_SUCCESS; +} + +DEFPY(no_srv6_sid_format_explicit, + no_srv6_sid_format_explicit_cmd, + "no explicit [start (0-4294967295)$start]", + NO_STR + "Configure Explicit range\n" + "Configure the start value for the Explicit range\n" + "Specify the start value for the Explicit range\n") +{ + VTY_DECLVAR_CONTEXT(srv6_sid_format, format); + + if (strmatch(format->name, SRV6_SID_FORMAT_UNCOMPRESSED_F4024_NAME)) + format->config.usid.ewlib_start = + SRV6_SID_FORMAT_UNCOMPRESSED_F4024_EXPLICIT_RANGE_START; + else + assert(0); + + return CMD_SUCCESS; +} + static int zebra_sr_config(struct vty *vty) { struct zebra_srv6 *srv6 = zebra_srv6_get_default(); struct listnode *node; struct srv6_locator *locator; + struct srv6_sid_format *format; char str[256]; bool display_source_srv6 = false; @@ -537,6 +823,51 @@ static int zebra_sr_config(struct vty *vty) } vty_out(vty, " exit\n"); vty_out(vty, " !\n"); + vty_out(vty, " formats\n"); + for (ALL_LIST_ELEMENTS_RO(srv6->sid_formats, node, format)) { + if (format->type == SRV6_SID_FORMAT_TYPE_UNCOMPRESSED) { + vty_out(vty, " format %s\n", format->name); + if (format->config.uncompressed.explicit_start != + SRV6_SID_FORMAT_UNCOMPRESSED_F4024_EXPLICIT_RANGE_START) + vty_out(vty, " explicit start %u\n", + format->config.uncompressed + .explicit_start); + } + if (format->type == + SRV6_SID_FORMAT_TYPE_COMPRESSED_USID) { + vty_out(vty, " format %s\n", format->name); + if (format->config.usid.lib_start != + SRV6_SID_FORMAT_USID_F3216_LIB_START) + vty_out(vty, + " local-id-block start %u\n", + format->config.usid.lib_start); + if (format->config.usid.elib_start != + SRV6_SID_FORMAT_USID_F3216_ELIB_START || + format->config.usid.elib_end != + SRV6_SID_FORMAT_USID_F3216_ELIB_END) + vty_out(vty, + " local-id-block explicit start %u end %u\n", + format->config.usid.elib_start, + format->config.usid.elib_end); + if (format->config.usid.wlib_start != + SRV6_SID_FORMAT_USID_F3216_WLIB_START || + format->config.usid.wlib_end != + SRV6_SID_FORMAT_USID_F3216_WLIB_END) + vty_out(vty, + " wide-local-id-block start %u end %u\n", + format->config.usid.wlib_start, + format->config.usid.wlib_end); + if (format->config.usid.ewlib_start != + SRV6_SID_FORMAT_USID_F3216_EWLIB_START) + vty_out(vty, + " wide-local-id-block explicit start %u\n", + format->config.usid.ewlib_start); + } + vty_out(vty, " exit\n"); + vty_out(vty, " !\n"); + } + vty_out(vty, " exit\n"); + vty_out(vty, " !\n"); vty_out(vty, " exit\n"); vty_out(vty, " !\n"); } @@ -555,11 +886,17 @@ void zebra_srv6_vty_init(void) install_node(&srv6_locs_node); install_node(&srv6_loc_node); install_node(&srv6_encap_node); + install_node(&srv6_sid_formats_node); + install_node(&srv6_sid_format_usid_f3216_node); + install_node(&srv6_sid_format_uncompressed_f4024_node); install_default(SEGMENT_ROUTING_NODE); install_default(SRV6_NODE); install_default(SRV6_LOCS_NODE); install_default(SRV6_LOC_NODE); install_default(SRV6_ENCAP_NODE); + install_default(SRV6_SID_FORMATS_NODE); + install_default(SRV6_SID_FORMAT_USID_F3216_NODE); + install_default(SRV6_SID_FORMAT_UNCOMPRESSED_F4024_NODE); /* Command for change node */ install_element(CONFIG_NODE, &segment_routing_cmd); @@ -567,14 +904,42 @@ void zebra_srv6_vty_init(void) install_element(SEGMENT_ROUTING_NODE, &no_srv6_cmd); install_element(SRV6_NODE, &srv6_locators_cmd); install_element(SRV6_NODE, &srv6_encap_cmd); + install_element(SRV6_NODE, &srv6_sid_formats_cmd); install_element(SRV6_LOCS_NODE, &srv6_locator_cmd); install_element(SRV6_LOCS_NODE, &no_srv6_locator_cmd); + install_element(SRV6_SID_FORMATS_NODE, &srv6_sid_format_f3216_usid_cmd); + install_element(SRV6_SID_FORMATS_NODE, + &srv6_sid_format_uncompressed_cmd); + install_element(SRV6_SID_FORMATS_NODE, + &no_srv6_sid_format_f3216_usid_cmd); + install_element(SRV6_SID_FORMATS_NODE, + &no_srv6_sid_format_f4024_uncompressed_cmd); /* Command for configuration */ install_element(SRV6_LOC_NODE, &locator_prefix_cmd); install_element(SRV6_LOC_NODE, &locator_behavior_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, + &srv6_sid_format_usid_lib_cmd); + install_element(SRV6_SID_FORMAT_USID_F3216_NODE, + &no_srv6_sid_format_usid_lib_cmd); + install_element(SRV6_SID_FORMAT_USID_F3216_NODE, + &srv6_sid_format_usid_lib_explicit_cmd); + install_element(SRV6_SID_FORMAT_USID_F3216_NODE, + &no_srv6_sid_format_usid_lib_explicit_cmd); + install_element(SRV6_SID_FORMAT_USID_F3216_NODE, + &srv6_sid_format_usid_wlib_cmd); + install_element(SRV6_SID_FORMAT_USID_F3216_NODE, + &no_srv6_sid_format_usid_wlib_cmd); + install_element(SRV6_SID_FORMAT_USID_F3216_NODE, + &srv6_sid_format_usid_wide_lib_explicit_cmd); + install_element(SRV6_SID_FORMAT_USID_F3216_NODE, + &no_srv6_sid_format_usid_wide_lib_explicit_cmd); + install_element(SRV6_SID_FORMAT_UNCOMPRESSED_F4024_NODE, + &srv6_sid_format_explicit_cmd); + install_element(SRV6_SID_FORMAT_UNCOMPRESSED_F4024_NODE, + &no_srv6_sid_format_explicit_cmd); /* Command for operation */ install_element(VIEW_NODE, &show_srv6_locator_cmd); -- cgit v1.2.3 From bf10e4437e476c8550f4f146d34cce0828445a5e Mon Sep 17 00:00:00 2001 From: Carmine Scarpitta Date: Fri, 22 Mar 2024 18:19:36 +0100 Subject: zebra: Add support for SRv6 SID blocks An SRv6 block is an IPv6 prefix from which SIDs are allocated. This commit adds support for SRv6 SID blocks. Specifically, it adds a data structure to store information about an SRv6 block (e.g., its occupancy status, which SIDs have been allocated and which are available, which SID format is used for that block, etc.). It also adds some functions to manage the block (allocate / free / lookup). These functions will be used in the next commits to support the allocation of SIDs from a block in the SID Manager. Signed-off-by: Carmine Scarpitta --- zebra/zebra_srv6.c | 191 +++++++++++++++++++++++++++++++++++++++++++++++++ zebra/zebra_srv6.h | 79 ++++++++++++++++++++ zebra/zebra_srv6_vty.c | 3 +- 3 files changed, 271 insertions(+), 2 deletions(-) (limited to 'zebra/zebra_srv6_vty.c') diff --git a/zebra/zebra_srv6.c b/zebra/zebra_srv6.c index 825f0f7fc2..2e5c499838 100644 --- a/zebra/zebra_srv6.c +++ b/zebra/zebra_srv6.c @@ -33,6 +33,10 @@ DEFINE_MGROUP(SRV6_MGR, "SRv6 Manager"); DEFINE_MTYPE_STATIC(SRV6_MGR, SRV6M_CHUNK, "SRv6 Manager Chunk"); +DEFINE_MTYPE_STATIC(SRV6_MGR, ZEBRA_SRV6_SID_BLOCK, "SRv6 SID block"); +DEFINE_MTYPE_STATIC(SRV6_MGR, ZEBRA_SRV6_SID_FUNC, "SRv6 SID function"); +DEFINE_MTYPE_STATIC(SRV6_MGR, ZEBRA_SRV6_USID_WLIB, + "SRv6 uSID Wide LIB information"); /* define hooks for the basic API, so that it can be specialized or served * externally @@ -174,6 +178,176 @@ static struct srv6_sid_format *create_srv6_sid_format_uncompressed(void) return format; } +/* --- Zebra SRv6 SID function management functions ---------------------------- */ + +uint32_t *zebra_srv6_sid_func_alloc(uint32_t func) +{ + uint32_t *sid_func_ptr; + + sid_func_ptr = XCALLOC(MTYPE_ZEBRA_SRV6_SID_FUNC, sizeof(uint32_t)); + *sid_func_ptr = func; + + return sid_func_ptr; +} + +void zebra_srv6_sid_func_free(uint32_t *func) +{ + XFREE(MTYPE_ZEBRA_SRV6_SID_FUNC, func); +} + +/** + * Free an SRv6 SID function. + * + * @param val SRv6 SID function to be freed + */ +void delete_zebra_srv6_sid_func(void *val) +{ + zebra_srv6_sid_func_free((uint32_t *)val); +} + +/* --- Zebra SRv6 SID block management functions ---------------------------- */ + +static struct zebra_srv6_sid_block *zebra_srv6_sid_block_alloc_internal(void) +{ + struct zebra_srv6_sid_block *block = NULL; + + block = XCALLOC(MTYPE_ZEBRA_SRV6_SID_BLOCK, + sizeof(struct zebra_srv6_sid_block)); + + return block; +} + +struct zebra_srv6_sid_block * +zebra_srv6_sid_block_alloc(struct srv6_sid_format *format, + struct prefix_ipv6 *prefix) +{ + struct zebra_srv6_sid_block *block; + + block = zebra_srv6_sid_block_alloc_internal(); + block->sid_format = format; + block->prefix = *prefix; + + if (format) { + if (format->type == SRV6_SID_FORMAT_TYPE_USID) { + uint32_t wlib_start, wlib_end, func; + + /* Init uSID LIB */ + block->u.usid.lib.func_allocated = list_new(); + block->u.usid.lib.func_allocated->del = + delete_zebra_srv6_sid_func; + block->u.usid.lib.func_released = list_new(); + block->u.usid.lib.func_released->del = + delete_zebra_srv6_sid_func; + block->u.usid.lib.first_available_func = + format->config.usid.lib_start; + + /* Init uSID Wide LIB */ + wlib_start = block->sid_format->config.usid.wlib_start; + wlib_end = block->sid_format->config.usid.wlib_end; + block->u.usid.wide_lib = + XCALLOC(MTYPE_ZEBRA_SRV6_USID_WLIB, + (wlib_end - wlib_start + 1) * + sizeof(struct wide_lib)); + for (func = 0; func < wlib_end - wlib_start + 1; + func++) { + block->u.usid.wide_lib[func].func_allocated = + list_new(); + block->u.usid.wide_lib[func].func_allocated->del = + delete_zebra_srv6_sid_func; + block->u.usid.wide_lib[func].func_released = + list_new(); + block->u.usid.wide_lib[func].func_released->del = + delete_zebra_srv6_sid_func; + block->u.usid.wide_lib[func].func = func; + } + } else if (format->type == SRV6_SID_FORMAT_TYPE_UNCOMPRESSED) { + block->u.uncompressed.func_allocated = list_new(); + block->u.uncompressed.func_allocated->del = + delete_zebra_srv6_sid_func; + block->u.uncompressed.func_released = list_new(); + block->u.uncompressed.func_released->del = + delete_zebra_srv6_sid_func; + block->u.uncompressed.first_available_func = + SRV6_SID_FORMAT_UNCOMPRESSED_F4024_FUNC_UNRESERVED_MIN; + } else { + /* We should never arrive here */ + assert(0); + } + } else { + block->u.uncompressed.func_allocated = list_new(); + block->u.uncompressed.func_allocated->del = + delete_zebra_srv6_sid_func; + block->u.uncompressed.func_released = list_new(); + block->u.uncompressed.func_released->del = + delete_zebra_srv6_sid_func; + block->u.uncompressed.first_available_func = 1; + } + + return block; +} + +void zebra_srv6_sid_block_free(struct zebra_srv6_sid_block *block) +{ + if (block->sid_format) { + if (block->sid_format->type == SRV6_SID_FORMAT_TYPE_USID) { + uint32_t wlib_start, wlib_end, func; + + /* Free uSID LIB */ + list_delete(&block->u.usid.lib.func_allocated); + list_delete(&block->u.usid.lib.func_released); + + /* Free uSID Wide LIB */ + wlib_start = block->sid_format->config.usid.wlib_start; + wlib_end = block->sid_format->config.usid.wlib_end; + for (func = 0; func < wlib_end - wlib_start + 1; + func++) { + list_delete(&block->u.usid.wide_lib[func] + .func_allocated); + list_delete(&block->u.usid.wide_lib[func] + .func_released); + } + XFREE(MTYPE_ZEBRA_SRV6_USID_WLIB, + block->u.usid.wide_lib); + } else if (block->sid_format->type == + SRV6_SID_FORMAT_TYPE_UNCOMPRESSED) { + list_delete(&block->u.uncompressed.func_allocated); + list_delete(&block->u.uncompressed.func_released); + } else { + /* We should never arrive here */ + assert(0); + } + } else { + list_delete(&block->u.uncompressed.func_allocated); + list_delete(&block->u.uncompressed.func_released); + } + + XFREE(MTYPE_ZEBRA_SRV6_SID_BLOCK, block); +} + +/** + * Free an SRv6 SID block. + * + * @param val SRv6 SID block to be freed + */ +void delete_zebra_srv6_sid_block(void *val) +{ + zebra_srv6_sid_block_free((struct zebra_srv6_sid_block *)val); +} + +struct zebra_srv6_sid_block * +zebra_srv6_sid_block_lookup(struct prefix_ipv6 *prefix) +{ + struct zebra_srv6 *srv6 = zebra_srv6_get_default(); + struct zebra_srv6_sid_block *block; + struct listnode *node; + + for (ALL_LIST_ELEMENTS_RO(srv6->sid_blocks, node, block)) + if (prefix_match(prefix, &block->prefix)) + return block; + + return NULL; +} + void zebra_srv6_locator_add(struct srv6_locator *locator) { struct zebra_srv6 *srv6 = zebra_srv6_get_default(); @@ -324,6 +498,10 @@ struct zebra_srv6 *zebra_srv6_get_default(void) /* Create SID format `uncompressed` */ format_uncompressed = create_srv6_sid_format_uncompressed(); srv6_sid_format_register(format_uncompressed); + + /* Init list to store SRv6 SID blocks */ + srv6.sid_blocks = list_new(); + srv6.sid_blocks->del = delete_zebra_srv6_sid_block; } return &srv6; } @@ -529,6 +707,7 @@ void zebra_srv6_terminate(void) { struct srv6_locator *locator; struct srv6_sid_format *format; + struct zebra_srv6_sid_block *block; if (srv6.locators) { while (listcount(srv6.locators)) { @@ -541,6 +720,18 @@ void zebra_srv6_terminate(void) list_delete(&srv6.locators); } + /* Free SRv6 SID blocks */ + if (srv6.sid_blocks) { + while (listcount(srv6.sid_blocks)) { + block = listnode_head(srv6.sid_blocks); + + listnode_delete(srv6.sid_blocks, block); + zebra_srv6_sid_block_free(block); + } + + list_delete(&srv6.sid_blocks); + } + /* Free SRv6 SID formats */ if (srv6.sid_formats) { while (listcount(srv6.sid_formats)) { diff --git a/zebra/zebra_srv6.h b/zebra/zebra_srv6.h index 92e4fcf912..e81d182419 100644 --- a/zebra/zebra_srv6.h +++ b/zebra/zebra_srv6.h @@ -38,6 +38,70 @@ #define SRV6_SID_FORMAT_UNCOMPRESSED_F4024_EXPLICIT_RANGE_START 0xFF00 #define SRV6_SID_FORMAT_UNCOMPRESSED_F4024_FUNC_UNRESERVED_MIN 0x40 +/* uSID Wide LIB */ +struct wide_lib { + uint32_t func; + uint32_t num_func_allocated; + uint32_t first_available_func; + struct list *func_allocated; + struct list *func_released; +}; + +/* + * SRv6 SID block. + * + * A SID block is an IPv6 prefix from which SRv6 SIDs are allocated. + * Example: + * SID block = fc00:0::/32 + * SID 1 = fc00:0:1:e000:: + * SID 2 = fc00:0:1:fe00:: + * ... + */ +struct zebra_srv6_sid_block { + /* Prefix of this block, e.g. fc00:0::/32 */ + struct prefix_ipv6 prefix; + + /* Reference counter */ + unsigned long refcnt; + + /* + * Pointer to the SID format that defines the structure of the SIDs + * allocated from this block + */ + struct zebra_srv6_sid_format *sid_format; + + /* + * Run-time information/state of this SID block. + * + * This includes stuff like how many SID functions have been allocated + * from this block, which functions are still available to be allocated + * and so on... + */ + union { + /* Information/state for compressed uSID format */ + struct { + /* uSID Local ID Block (LIB) */ + struct { + uint32_t num_func_allocated; + uint32_t first_available_func; + struct list *func_allocated; + struct list *func_released; + } lib; + + /* uSID Wide LIB */ + struct wide_lib *wide_lib; + } usid; + + /* Information/state for uncompressed SID format */ + struct { + uint32_t num_func_allocated; + uint32_t first_available_func; + struct list *func_allocated; + struct list *func_released; + } uncompressed; + } u; +}; + /* SRv6 instance structure. */ struct zebra_srv6 { struct list *locators; @@ -47,6 +111,9 @@ struct zebra_srv6 { /* SRv6 SID formats */ struct list *sid_formats; + + /* SRv6 SID blocks */ + struct list *sid_blocks; }; /* declare hooks for the basic API, so that it can be specialized or served @@ -103,4 +170,16 @@ 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); +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, + 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); +extern struct zebra_srv6_sid_block * +zebra_srv6_sid_block_lookup(struct prefix_ipv6 *prefix); + #endif /* _ZEBRA_SRV6_H */ diff --git a/zebra/zebra_srv6_vty.c b/zebra/zebra_srv6_vty.c index e5fe0d58a9..963b528b86 100644 --- a/zebra/zebra_srv6_vty.c +++ b/zebra/zebra_srv6_vty.c @@ -833,8 +833,7 @@ static int zebra_sr_config(struct vty *vty) format->config.uncompressed .explicit_start); } - if (format->type == - SRV6_SID_FORMAT_TYPE_COMPRESSED_USID) { + if (format->type == SRV6_SID_FORMAT_TYPE_USID) { vty_out(vty, " format %s\n", format->name); if (format->config.usid.lib_start != SRV6_SID_FORMAT_USID_F3216_LIB_START) -- 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 'zebra/zebra_srv6_vty.c') 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