From 1298867671f7fe76c65730afbb9ae54dcd7264be Mon Sep 17 00:00:00 2001 From: Carmine Scarpitta Date: Thu, 6 Jun 2024 17:23:11 +0200 Subject: [PATCH] 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.c | 132 ++++++++++++++++++++++++++++++++++++++--- zebra/zebra_srv6.h | 29 +++++++++ zebra/zebra_srv6_vty.c | 33 ++++++++--- 3 files changed, 179 insertions(+), 15 deletions(-) diff --git a/zebra/zebra_srv6.c b/zebra/zebra_srv6.c index bb872ef91c..dffc6ca091 100644 --- a/zebra/zebra_srv6.c +++ b/zebra/zebra_srv6.c @@ -90,6 +90,98 @@ static int zebra_srv6_cleanup(struct zserv *client) return 0; } +/* --- Zebra SRv6 SID format management functions --------------------------- */ + +void zebra_srv6_sid_format_register(struct zebra_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)); + + listnode_add(srv6->sid_formats, format); +} + +void zebra_srv6_sid_format_unregister(struct zebra_srv6_sid_format *format) +{ + struct zebra_srv6 *srv6 = zebra_srv6_get_default(); + + listnode_delete(srv6->sid_formats, format); +} + +struct zebra_srv6_sid_format *zebra_srv6_sid_format_lookup(const char *name) +{ + struct zebra_srv6 *srv6 = zebra_srv6_get_default(); + struct zebra_srv6_sid_format *format; + struct listnode *node; + + for (ALL_LIST_ELEMENTS_RO(srv6->sid_formats, node, format)) + if (!strncmp(name, format->name, sizeof(format->name))) + return format; + + return NULL; +} + +/* + * Helper function to create the SRv6 compressed format `usid-f3216`. + */ +static struct zebra_srv6_sid_format *create_srv6_sid_format_usid_f3216(void) +{ + struct zebra_srv6_sid_format *format = NULL; + + format = zebra_srv6_sid_format_alloc( + ZEBRA_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; + + /* 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; + + return format; +} + +/* + * Helper function to create the SRv6 uncompressed format. + */ +static struct zebra_srv6_sid_format *create_srv6_sid_format_uncompressed(void) +{ + struct zebra_srv6_sid_format *format = NULL; + + format = zebra_srv6_sid_format_alloc( + ZEBRA_SRV6_SID_FORMAT_UNCOMPRESSED_F4024_NAME); + + format->type = ZEBRA_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; + + /* 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; + + return format; +} + void zebra_srv6_locator_add(struct srv6_locator *locator) { struct zebra_srv6 *srv6 = zebra_srv6_get_default(); @@ -222,10 +314,24 @@ struct zebra_srv6 srv6; struct zebra_srv6 *zebra_srv6_get_default(void) { static bool first_execution = true; + struct zebra_srv6_sid_format *format_usidf3216; + struct zebra_srv6_sid_format *format_uncompressed; if (first_execution) { first_execution = false; srv6.locators = list_new(); + + /* Initialize list of SID formats */ + srv6.sid_formats = list_new(); + srv6.sid_formats->del = delete_zebra_srv6_sid_format; + + /* Create SID format `usid-f3216` */ + format_usidf3216 = create_srv6_sid_format_usid_f3216(); + zebra_srv6_sid_format_register(format_usidf3216); + + /* Create SID format `uncompressed` */ + format_uncompressed = create_srv6_sid_format_uncompressed(); + zebra_srv6_sid_format_register(format_uncompressed); } return &srv6; } @@ -430,18 +536,30 @@ void zebra_srv6_encap_src_addr_unset(void) void zebra_srv6_terminate(void) { struct srv6_locator *locator; + struct zebra_srv6_sid_format *format; - if (!srv6.locators) - return; + if (srv6.locators) { + while (listcount(srv6.locators)) { + locator = listnode_head(srv6.locators); - while (listcount(srv6.locators)) { - locator = listnode_head(srv6.locators); + listnode_delete(srv6.locators, locator); + srv6_locator_free(locator); + } - listnode_delete(srv6.locators, locator); - srv6_locator_free(locator); + list_delete(&srv6.locators); } - list_delete(&srv6.locators); + /* Free SRv6 SID formats */ + if (srv6.sid_formats) { + while (listcount(srv6.sid_formats)) { + format = listnode_head(srv6.sid_formats); + + zebra_srv6_sid_format_unregister(format); + zebra_srv6_sid_format_free(format); + } + + list_delete(&srv6.sid_formats); + } } void zebra_srv6_init(void) diff --git a/zebra/zebra_srv6.h b/zebra/zebra_srv6.h index 21936c3323..a645c5cc0d 100644 --- a/zebra/zebra_srv6.h +++ b/zebra/zebra_srv6.h @@ -16,12 +16,37 @@ #include #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 + +/* 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 + /* SRv6 instance structure. */ struct zebra_srv6 { struct list *locators; /* Source address for SRv6 encapsulation */ struct in6_addr encap_src_addr; + + /* SRv6 SID formats */ + struct list *sid_formats; }; /* declare hooks for the basic API, so that it can be specialized or served @@ -74,4 +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 zebra_srv6_sid_format *format); +void zebra_srv6_sid_format_unregister(struct zebra_srv6_sid_format *format); +struct zebra_srv6_sid_format *zebra_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 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 (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 (CHECK_FLAG(locator->flags, SRV6_LOCATOR_USID)) - vty_out(vty, "Behavior: uSID\n"); + 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,