Merge pull request #15604 from cscarpitta/srv6-sid-manager

Add support for SRv6 SID Manager
This commit is contained in:
Russ White 2024-06-18 12:16:24 -04:00 committed by GitHub
commit 7834c38ab3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 3752 additions and 75 deletions

View File

@ -1021,6 +1021,35 @@ and this section also helps that case.
!
...
.. clicmd:: format NAME
Specify the SID allocation schema for the SIDs allocated from this locator. Currently,
FRR supports supports the following allocation schemas:
- `usid-f3216`
- `uncompressed`
::
router# configure terminal
router(config)# segment-routinig
router(config-sr)# srv6
router(config-srv6)# locators
router(config-srv6-locators)# locator loc1
router(config-srv6-locator)# prefix fc00:0:1::/48
router(config-srv6-locator)# format usid-f3216
router(config-srv6-locator)# show run
...
segment-routing
srv6
locators
locator loc1
prefix fc00:0:1::/48
format usid-f3216
!
...
.. clicmd:: encapsulation
Configure parameters for SRv6 encapsulation.
@ -1029,6 +1058,61 @@ and this section also helps that case.
Configure the source address of the outer encapsulating IPv6 header.
.. clicmd:: formats
Configure SRv6 SID formats.
.. clicmd:: format NAME
Configure SRv6 SID format.
.. clicmd:: compressed usid
Enable SRv6 uSID compression and configure SRv6 uSID compression parameters.
.. clicmd:: local-id-block start START
Configure the start value for the Local ID Block (LIB).
.. clicmd:: local-id-block explicit start START end END
Configure the start/end values for the Explicit LIB (ELIB).
.. clicmd:: wide-local-id-block start START end END
Configure the start/end values for the Wide LIB (W-LIB).
.. clicmd:: wide-local-id-block explicit start START
Configure the start value for the Explicit Wide LIB (EW-LIB).
::
router# configure terminal
router(config)# segment-routinig
router(config-sr)# srv6
router(config-srv6)# formats
router(config-srv6-formats)# format usid-f3216
router(config-srv6-format)# compressed usid
router(config-srv6-format-usid)# local-id-block start 0xD000
router(config-srv6-format-usid)# local-id-block explicit start 0xF000 end 0xFDFF
router(config-srv6-format-usid)# wide-local-id-block start 0xFFF4 end 0xFFF5
router(config-srv6-format-usid)# wide-local-id-block explicit start 0xFFF4
router(config-srv6-locator)# show run
...
segment-routing
srv6
formats
format usid-f3216
compressed usid
local-id-block start 0xD000
local-id-block explicit start 0xF000 end 0xFDFF
wide-local-id-block start 0xFFF4 end 0xFFF5
wide-local-id-block explicit start 0xFFF4
!
...
.. _multicast-rib-commands:
Multicast RIB Commands

View File

@ -161,6 +161,9 @@ enum node_type {
SRV6_LOCS_NODE, /* SRv6 locators node */
SRV6_LOC_NODE, /* SRv6 locator node */
SRV6_ENCAP_NODE, /* SRv6 encapsulation node */
SRV6_SID_FORMATS_NODE, /* SRv6 SID formats config node */
SRV6_SID_FORMAT_USID_F3216_NODE, /* SRv6 uSID f3216 format config node */
SRV6_SID_FORMAT_UNCOMPRESSED_F4024_NODE, /* SRv6 uncompressed f4024 format config node */
VTY_NODE, /* Vty node. */
FPM_NODE, /* Dataplane FPM node. */
LINK_PARAMS_NODE, /* Link-parameters node */

View File

@ -436,6 +436,9 @@ static const struct zebra_desc_table command_types[] = {
DESC_ENTRY(ZEBRA_SRV6_LOCATOR_DELETE),
DESC_ENTRY(ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK),
DESC_ENTRY(ZEBRA_SRV6_MANAGER_RELEASE_LOCATOR_CHUNK),
DESC_ENTRY(ZEBRA_SRV6_MANAGER_GET_LOCATOR),
DESC_ENTRY(ZEBRA_SRV6_MANAGER_GET_SRV6_SID),
DESC_ENTRY(ZEBRA_SRV6_MANAGER_RELEASE_SRV6_SID),
DESC_ENTRY(ZEBRA_ERROR),
DESC_ENTRY(ZEBRA_CLIENT_CAPABILITIES),
DESC_ENTRY(ZEBRA_OPAQUE_MESSAGE),
@ -461,7 +464,8 @@ static const struct zebra_desc_table command_types[] = {
DESC_ENTRY(ZEBRA_TC_CLASS_DELETE),
DESC_ENTRY(ZEBRA_TC_FILTER_ADD),
DESC_ENTRY(ZEBRA_TC_FILTER_DELETE),
DESC_ENTRY(ZEBRA_OPAQUE_NOTIFY)
DESC_ENTRY(ZEBRA_OPAQUE_NOTIFY),
DESC_ENTRY(ZEBRA_SRV6_SID_NOTIFY)
};
#undef DESC_ENTRY

View File

@ -10,8 +10,11 @@
#include "log.h"
DEFINE_QOBJ_TYPE(srv6_locator);
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)
{
@ -139,6 +142,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) {
@ -154,6 +172,59 @@ void srv6_locator_chunk_free(struct srv6_locator_chunk **chunk)
XFREE(MTYPE_SRV6_LOCATOR_CHUNK, *chunk);
}
struct srv6_sid_format *srv6_sid_format_alloc(const char *name)
{
struct srv6_sid_format *format = NULL;
format = XCALLOC(MTYPE_SRV6_SID_FORMAT, sizeof(struct srv6_sid_format));
strlcpy(format->name, name, sizeof(format->name));
QOBJ_REG(format, srv6_sid_format);
return format;
}
void srv6_sid_format_free(struct srv6_sid_format *format)
{
if (!format)
return;
QOBJ_UNREG(format);
XFREE(MTYPE_SRV6_SID_FORMAT, format);
}
/**
* Free an SRv6 SID format.
*
* @param val SRv6 SID format to be freed
*/
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;
@ -223,23 +294,47 @@ json_object *srv6_locator_json(const struct srv6_locator *loc)
/* set prefix */
json_object_string_addf(jo_root, "prefix", "%pFX", &loc->prefix);
/* set block_bits_length */
json_object_int_add(jo_root, "blockBitsLength", loc->block_bits_length);
if (loc->sid_format) {
/* set block_bits_length */
json_object_int_add(jo_root, "blockBitsLength",
loc->sid_format->block_len);
/* set node_bits_length */
json_object_int_add(jo_root, "nodeBitsLength", loc->node_bits_length);
/* set node_bits_length */
json_object_int_add(jo_root, "nodeBitsLength",
loc->sid_format->node_len);
/* set function_bits_length */
json_object_int_add(jo_root, "functionBitsLength",
loc->function_bits_length);
/* set function_bits_length */
json_object_int_add(jo_root, "functionBitsLength",
loc->sid_format->function_len);
/* set argument_bits_length */
json_object_int_add(jo_root, "argumentBitsLength",
loc->argument_bits_length);
/* set argument_bits_length */
json_object_int_add(jo_root, "argumentBitsLength",
loc->sid_format->argument_len);
/* set true if the locator is a Micro-segment (uSID) locator */
if (CHECK_FLAG(loc->flags, SRV6_LOCATOR_USID))
json_object_string_add(jo_root, "behavior", "usid");
/* set true if the locator is a Micro-segment (uSID) locator */
if (loc->sid_format->type == SRV6_SID_FORMAT_TYPE_USID)
json_object_string_add(jo_root, "behavior", "usid");
} else {
/* set block_bits_length */
json_object_int_add(jo_root, "blockBitsLength",
loc->block_bits_length);
/* set node_bits_length */
json_object_int_add(jo_root, "nodeBitsLength",
loc->node_bits_length);
/* set function_bits_length */
json_object_int_add(jo_root, "functionBitsLength",
loc->function_bits_length);
/* set argument_bits_length */
json_object_int_add(jo_root, "argumentBitsLength",
loc->argument_bits_length);
/* set true if the locator is a Micro-segment (uSID) locator */
if (CHECK_FLAG(loc->flags, SRV6_LOCATOR_USID))
json_object_string_add(jo_root, "behavior", "usid");
}
/* set status_up */
json_object_boolean_add(jo_root, "statusUp",
@ -272,23 +367,47 @@ json_object *srv6_locator_detailed_json(const struct srv6_locator *loc)
/* set prefix */
json_object_string_addf(jo_root, "prefix", "%pFX", &loc->prefix);
/* set block_bits_length */
json_object_int_add(jo_root, "blockBitsLength", loc->block_bits_length);
if (loc->sid_format) {
/* set block_bits_length */
json_object_int_add(jo_root, "blockBitsLength",
loc->sid_format->block_len);
/* set node_bits_length */
json_object_int_add(jo_root, "nodeBitsLength", loc->node_bits_length);
/* set node_bits_length */
json_object_int_add(jo_root, "nodeBitsLength",
loc->sid_format->node_len);
/* set function_bits_length */
json_object_int_add(jo_root, "functionBitsLength",
loc->function_bits_length);
/* set function_bits_length */
json_object_int_add(jo_root, "functionBitsLength",
loc->sid_format->function_len);
/* set argument_bits_length */
json_object_int_add(jo_root, "argumentBitsLength",
loc->argument_bits_length);
/* set argument_bits_length */
json_object_int_add(jo_root, "argumentBitsLength",
loc->sid_format->argument_len);
/* set true if the locator is a Micro-segment (uSID) locator */
if (CHECK_FLAG(loc->flags, SRV6_LOCATOR_USID))
json_object_string_add(jo_root, "behavior", "usid");
/* set true if the locator is a Micro-segment (uSID) locator */
if (loc->sid_format->type == SRV6_SID_FORMAT_TYPE_USID)
json_object_string_add(jo_root, "behavior", "usid");
} else {
/* set block_bits_length */
json_object_int_add(jo_root, "blockBitsLength",
loc->block_bits_length);
/* set node_bits_length */
json_object_int_add(jo_root, "nodeBitsLength",
loc->node_bits_length);
/* set function_bits_length */
json_object_int_add(jo_root, "functionBitsLength",
loc->function_bits_length);
/* set argument_bits_length */
json_object_int_add(jo_root, "argumentBitsLength",
loc->argument_bits_length);
/* set true if the locator is a Micro-segment (uSID) locator */
if (CHECK_FLAG(loc->flags, SRV6_LOCATOR_USID))
json_object_string_add(jo_root, "behavior", "usid");
}
/* set algonum */
json_object_int_add(jo_root, "algoNum", loc->algonum);

View File

@ -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
@ -127,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);
@ -183,6 +191,72 @@ 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);
/* 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) {
@ -246,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);
@ -254,12 +376,24 @@ 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);
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);
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

View File

@ -1125,6 +1125,10 @@ int zapi_srv6_locator_encode(struct stream *s, const struct srv6_locator *l)
stream_put(s, l->name, strlen(l->name));
stream_putw(s, l->prefix.prefixlen);
stream_put(s, &l->prefix.prefix, sizeof(l->prefix.prefix));
stream_putc(s, l->block_bits_length);
stream_putc(s, l->node_bits_length);
stream_putc(s, l->function_bits_length);
stream_putc(s, l->argument_bits_length);
stream_putc(s, l->flags);
return 0;
}
@ -1141,6 +1145,10 @@ int zapi_srv6_locator_decode(struct stream *s, struct srv6_locator *l)
STREAM_GETW(s, l->prefix.prefixlen);
STREAM_GET(&l->prefix.prefix, s, sizeof(l->prefix.prefix));
l->prefix.family = AF_INET6;
STREAM_GETC(s, l->block_bits_length);
STREAM_GETC(s, l->node_bits_length);
STREAM_GETC(s, l->function_bits_length);
STREAM_GETC(s, l->argument_bits_length);
STREAM_GETC(s, l->flags);
return 0;
@ -2125,6 +2133,46 @@ stream_failure:
return false;
}
bool zapi_srv6_sid_notify_decode(struct stream *s, struct srv6_sid_ctx *ctx,
struct in6_addr *sid_value, uint32_t *func,
uint32_t *wide_func,
enum zapi_srv6_sid_notify *note,
char **p_locator_name)
{
uint32_t f, wf;
uint16_t len;
static char locator_name[SRV6_LOCNAME_SIZE] = {};
STREAM_GET(note, s, sizeof(*note));
STREAM_GET(ctx, s, sizeof(struct srv6_sid_ctx));
STREAM_GET(sid_value, s, sizeof(struct in6_addr));
STREAM_GETL(s, f);
STREAM_GETL(s, wf);
if (func)
*func = f;
if (wide_func)
*wide_func = wf;
STREAM_GETW(s, len);
if (len > SRV6_LOCNAME_SIZE) {
*p_locator_name = NULL;
return false;
}
if (p_locator_name) {
if (len == 0)
*p_locator_name = NULL;
else {
STREAM_GET(locator_name, s, len);
*p_locator_name = locator_name;
}
}
return true;
stream_failure:
return false;
}
struct nexthop *nexthop_from_zapi_nexthop(const struct zapi_nexthop *znh)
{
struct nexthop *n = nexthop_new();
@ -3269,10 +3317,154 @@ int srv6_manager_release_locator_chunk(struct zclient *zclient,
return zclient_send_message(zclient);
}
/**
* Function to request a SRv6 locator in an asynchronous way
*
* @param zclient The zclient used to connect to SRv6 Manager (zebra)
* @param locator_name Name of SRv6 locator
* @return 0 on success, -1 otherwise
*/
int srv6_manager_get_locator(struct zclient *zclient, const char *locator_name)
{
struct stream *s;
size_t len;
if (!locator_name)
return -1;
if (zclient->sock < 0) {
flog_err(EC_LIB_ZAPI_SOCKET, "%s: invalid zclient socket",
__func__);
return -1;
}
if (zclient_debug)
zlog_debug("Getting SRv6 Locator %s", locator_name);
len = strlen(locator_name);
/* Send request */
s = zclient->obuf;
stream_reset(s);
zclient_create_header(s, ZEBRA_SRV6_MANAGER_GET_LOCATOR, VRF_DEFAULT);
/* Locator name */
stream_putw(s, len);
stream_put(s, locator_name, len);
/* Put length at the first point of the stream. */
stream_putw_at(s, 0, stream_get_endp(s));
return zclient_send_message(zclient);
}
/**
* Function to request an SRv6 SID in an asynchronous way
*
* @param zclient The zclient used to connect to SRv6 manager (zebra)
* @param ctx Context associated with the SRv6 SID
* @param sid_value SRv6 SID value for explicit SID allocation
* @param locator_name Name of the parent locator for dynamic SID allocation
* @param sid_func SID function assigned by the SRv6 Manager
* @result 0 on success, -1 otherwise
*/
int srv6_manager_get_sid(struct zclient *zclient, const struct srv6_sid_ctx *ctx,
struct in6_addr *sid_value, const char *locator_name,
uint32_t *sid_func)
{
struct stream *s;
uint8_t flags = 0;
size_t len;
char buf[256];
if (zclient->sock < 0) {
flog_err(EC_LIB_ZAPI_SOCKET, "%s: invalid zclient socket",
__func__);
return ZCLIENT_SEND_FAILURE;
}
if (zclient_debug)
zlog_debug("Getting SRv6 SID: %s",
srv6_sid_ctx2str(buf, sizeof(buf), ctx));
/* send request */
s = zclient->obuf;
stream_reset(s);
zclient_create_header(s, ZEBRA_SRV6_MANAGER_GET_SRV6_SID, VRF_DEFAULT);
/* Context associated with the SRv6 SID */
stream_put(s, ctx, sizeof(struct srv6_sid_ctx));
/* Flags */
if (!sid_zero_ipv6(sid_value))
SET_FLAG(flags, ZAPI_SRV6_MANAGER_SID_FLAG_HAS_SID_VALUE);
if (locator_name)
SET_FLAG(flags, ZAPI_SRV6_MANAGER_SID_FLAG_HAS_LOCATOR);
stream_putc(s, flags);
/* SRv6 SID value */
if (CHECK_FLAG(flags, ZAPI_SRV6_MANAGER_SID_FLAG_HAS_SID_VALUE))
stream_put(s, sid_value, sizeof(struct in6_addr));
/* SRv6 locator */
if (CHECK_FLAG(flags, ZAPI_SRV6_MANAGER_SID_FLAG_HAS_LOCATOR)) {
len = strlen(locator_name);
stream_putw(s, len);
stream_put(s, locator_name, len);
}
/* Put length at the first point of the stream. */
stream_putw_at(s, 0, stream_get_endp(s));
/* Send the request to SRv6 Manager */
return zclient_send_message(zclient);
}
/**
* Function to release an SRv6 SID
*
* @param zclient Zclient used to connect to SRv6 manager (zebra)
* @param ctx Context associated with the SRv6 SID to be removed
* @result 0 on success, -1 otherwise
*/
int srv6_manager_release_sid(struct zclient *zclient,
const struct srv6_sid_ctx *ctx)
{
struct stream *s;
char buf[256];
if (zclient->sock < 0) {
flog_err(EC_LIB_ZAPI_SOCKET, "%s: invalid zclient socket",
__func__);
return -1;
}
if (zclient_debug)
zlog_debug("Releasing SRv6 SID: %s",
srv6_sid_ctx2str(buf, sizeof(buf), ctx));
/* send request */
s = zclient->obuf;
stream_reset(s);
zclient_create_header(s, ZEBRA_SRV6_MANAGER_RELEASE_SRV6_SID,
VRF_DEFAULT);
/* Context associated with the SRv6 SID */
stream_put(s, ctx, sizeof(struct srv6_sid_ctx));
/* Put length at the first point of the stream. */
stream_putw_at(s, 0, stream_get_endp(s));
/* Send the SID release message */
return zclient_send_message(zclient);
}
/*
* Asynchronous label chunk request
*
* @param zclient Zclient used to connect to label manager (zebra)
* @param zclient The zclient used to connect to label manager (zebra)
* @param keep Avoid garbage collection
* @param chunk_size Amount of labels requested
* @param base Base for the label chunk. if MPLS_LABEL_BASE_ANY we do not care

View File

@ -209,6 +209,9 @@ typedef enum {
ZEBRA_SRV6_LOCATOR_DELETE,
ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK,
ZEBRA_SRV6_MANAGER_RELEASE_LOCATOR_CHUNK,
ZEBRA_SRV6_MANAGER_GET_LOCATOR,
ZEBRA_SRV6_MANAGER_GET_SRV6_SID,
ZEBRA_SRV6_MANAGER_RELEASE_SRV6_SID,
ZEBRA_ERROR,
ZEBRA_CLIENT_CAPABILITIES,
ZEBRA_OPAQUE_MESSAGE,
@ -235,6 +238,7 @@ typedef enum {
ZEBRA_TC_FILTER_ADD,
ZEBRA_TC_FILTER_DELETE,
ZEBRA_OPAQUE_NOTIFY,
ZEBRA_SRV6_SID_NOTIFY,
} zebra_message_types_t;
/* Zebra message types. Please update the corresponding
* command_types array with any changes!
@ -761,6 +765,13 @@ enum zapi_iptable_notify_owner {
ZAPI_IPTABLE_FAIL_REMOVE,
};
enum zapi_srv6_sid_notify {
ZAPI_SRV6_SID_FAIL_ALLOC = 0,
ZAPI_SRV6_SID_ALLOCATED,
ZAPI_SRV6_SID_RELEASED,
ZAPI_SRV6_SID_FAIL_RELEASE,
};
enum zclient_send_status {
ZCLIENT_SEND_FAILURE = -1,
ZCLIENT_SEND_SUCCESS = 0,
@ -813,6 +824,28 @@ zapi_rule_notify_owner2str(enum zapi_rule_notify_owner note)
return ret;
}
static inline const char *zapi_srv6_sid_notify2str(enum zapi_srv6_sid_notify note)
{
const char *ret = "UNKNOWN";
switch (note) {
case ZAPI_SRV6_SID_FAIL_ALLOC:
ret = "ZAPI_SRV6_SID_FAIL_ALLOC";
break;
case ZAPI_SRV6_SID_ALLOCATED:
ret = "ZAPI_SRV6_SID_ALLOCATED";
break;
case ZAPI_SRV6_SID_FAIL_RELEASE:
ret = "ZAPI_SRV6_SID_FAIL_RELEASE";
break;
case ZAPI_SRV6_SID_RELEASED:
ret = "ZAPI_SRV6_SID_RELEASED";
break;
}
return ret;
}
/* Zebra MAC types */
#define ZEBRA_MACIP_TYPE_STICKY 0x01 /* Sticky MAC*/
#define ZEBRA_MACIP_TYPE_GW 0x02 /* gateway (SVI) mac*/
@ -1070,10 +1103,23 @@ extern int tm_get_table_chunk(struct zclient *zclient, uint32_t chunk_size,
uint32_t *start, uint32_t *end);
extern int tm_release_table_chunk(struct zclient *zclient, uint32_t start,
uint32_t end);
/* Zebra SRv6 Manager flags */
#define ZAPI_SRV6_MANAGER_SID_FLAG_HAS_SID_VALUE 0x01
#define ZAPI_SRV6_MANAGER_SID_FLAG_HAS_LOCATOR 0x02
extern int srv6_manager_get_locator_chunk(struct zclient *zclient,
const char *locator_name);
extern int srv6_manager_release_locator_chunk(struct zclient *zclient,
const char *locator_name);
extern int srv6_manager_get_locator(struct zclient *zclient,
const char *locator_name);
extern int srv6_manager_get_sid(struct zclient *zclient,
const struct srv6_sid_ctx *ctx,
struct in6_addr *sid_value,
const char *locator_name, uint32_t *sid_func);
extern int srv6_manager_release_sid(struct zclient *zclient,
const struct srv6_sid_ctx *ctx);
extern enum zclient_send_status zebra_send_sr_policy(struct zclient *zclient,
int cmd,
@ -1128,6 +1174,11 @@ bool zapi_rule_notify_decode(struct stream *s, uint32_t *seqno,
bool zapi_ipset_notify_decode(struct stream *s,
uint32_t *unique,
enum zapi_ipset_notify_owner *note);
bool zapi_srv6_sid_notify_decode(struct stream *s, struct srv6_sid_ctx *ctx,
struct in6_addr *sid_value, uint32_t *func,
uint32_t *wide_func,
enum zapi_srv6_sid_notify *note,
char **locator_name);
/* Nexthop-group message apis */
extern enum zclient_send_status

View File

@ -1344,6 +1344,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)# "
};
#ifdef HAVE_PBRD
static struct cmd_node pbr_map_node = {
.name = "pbr-map",
@ -1715,6 +1736,31 @@ DEFUNSH(VTYSH_ZEBRA, srv6_encap, srv6_encap_cmd,
return CMD_SUCCESS;
}
DEFUNSH(VTYSH_ZEBRA, srv6_sid_formats, srv6_sid_formats_cmd, "formats",
"Segment Routing SRv6 SID formats\n")
{
vty->node = SRV6_SID_FORMATS_NODE;
return CMD_SUCCESS;
}
DEFUNSH(VTYSH_ZEBRA, 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")
{
vty->node = SRV6_SID_FORMAT_USID_F3216_NODE;
return CMD_SUCCESS;
}
DEFUNSH(VTYSH_ZEBRA, srv6_sid_format_f4024_uncompressed, srv6_sid_format_f4024_uncompressed_cmd,
"format uncompressed-f4024",
"Configure SRv6 SID format\n"
"Configure the uncompressed f4024 format\n")
{
vty->node = SRV6_SID_FORMAT_UNCOMPRESSED_F4024_NODE;
return CMD_SUCCESS;
}
#ifdef HAVE_BGPD
DEFUNSH(VTYSH_BGPD, router_bgp, router_bgp_cmd,
"router bgp [ASNUM [<view|vrf> VIEWVRFNAME] [as-notation <dot|dot+|plain>]]",
@ -2515,6 +2561,23 @@ DEFUNSH(VTYSH_ZEBRA, exit_srv6_encap, exit_srv6_encap_cmd, "exit",
return CMD_SUCCESS;
}
DEFUNSH(VTYSH_ZEBRA, exit_srv6_sid_formats, exit_srv6_sid_formats_cmd, "exit",
"Exit from SRv6 SID formats configuration mode\n")
{
if (vty->node == SRV6_SID_FORMATS_NODE)
vty->node = SRV6_NODE;
return CMD_SUCCESS;
}
DEFUNSH(VTYSH_ZEBRA, exit_srv6_sid_format, exit_srv6_sid_format_cmd,
"exit", "Exit from SRv6 SID format configuration mode\n")
{
if (vty->node == SRV6_SID_FORMAT_USID_F3216_NODE ||
vty->node == SRV6_SID_FORMAT_UNCOMPRESSED_F4024_NODE)
vty->node = SRV6_SID_FORMATS_NODE;
return CMD_SUCCESS;
}
#ifdef HAVE_RIPD
DEFUNSH(VTYSH_MGMTD, vtysh_exit_ripd, vtysh_exit_ripd_cmd, "exit",
"Exit current mode and down to previous mode\n")
@ -5304,6 +5367,7 @@ void vtysh_init_vty(void)
install_node(&srv6_node);
install_element(SEGMENT_ROUTING_NODE, &srv6_cmd);
install_element(SRV6_NODE, &srv6_locators_cmd);
install_element(SRV6_NODE, &srv6_sid_formats_cmd);
install_element(SRV6_NODE, &exit_srv6_config_cmd);
install_element(SRV6_NODE, &vtysh_end_all_cmd);
install_element(SRV6_NODE, &srv6_encap_cmd);
@ -5321,6 +5385,24 @@ void vtysh_init_vty(void)
install_element(SRV6_ENCAP_NODE, &exit_srv6_encap_cmd);
install_element(SRV6_ENCAP_NODE, &vtysh_end_all_cmd);
install_node(&srv6_sid_formats_node);
install_element(SRV6_SID_FORMATS_NODE, &srv6_sid_format_f3216_usid_cmd);
install_element(SRV6_SID_FORMATS_NODE,
&srv6_sid_format_f4024_uncompressed_cmd);
install_element(SRV6_SID_FORMATS_NODE, &exit_srv6_sid_formats_cmd);
install_element(SRV6_SID_FORMATS_NODE, &vtysh_end_all_cmd);
install_node(&srv6_sid_format_usid_f3216_node);
install_element(SRV6_SID_FORMAT_USID_F3216_NODE,
&exit_srv6_sid_format_cmd);
install_element(SRV6_SID_FORMAT_USID_F3216_NODE, &vtysh_end_all_cmd);
install_node(&srv6_sid_format_uncompressed_f4024_node);
install_element(SRV6_SID_FORMAT_UNCOMPRESSED_F4024_NODE,
&exit_srv6_sid_format_cmd);
install_element(SRV6_SID_FORMAT_UNCOMPRESSED_F4024_NODE,
&vtysh_end_all_cmd);
install_element(ENABLE_NODE, &vtysh_show_running_config_cmd);
install_element(ENABLE_NODE, &vtysh_copy_running_config_cmd);
install_element(ENABLE_NODE, &vtysh_copy_to_running_cmd);

View File

@ -999,6 +999,48 @@ void zsend_neighbor_notify(int cmd, struct interface *ifp,
}
}
void zsend_srv6_sid_notify(struct zserv *client, const struct srv6_sid_ctx *ctx,
struct in6_addr *sid_value, uint32_t func,
uint32_t wide_func, const char *locator_name,
enum zapi_srv6_sid_notify note)
{
struct stream *s;
uint16_t cmd = ZEBRA_SRV6_SID_NOTIFY;
char buf[256];
if (IS_ZEBRA_DEBUG_PACKET)
zlog_debug("%s: notifying %s ctx %s sid %pI6 note %s (proto=%u, instance=%u, sessionId=%u)",
__func__, zserv_command_string(cmd),
srv6_sid_ctx2str(buf, sizeof(buf), ctx), sid_value,
zapi_srv6_sid_notify2str(note), client->proto,
client->instance, client->session_id);
s = stream_new(ZEBRA_MAX_PACKET_SIZ);
zclient_create_header(s, cmd, VRF_DEFAULT);
/* Notification type (e.g. ZAPI_SRV6_SID_ALLOCATED, ZAPI_SRV6_SID_FAIL_ALLOC, ...) */
stream_put(s, &note, sizeof(note));
/* Context associated with the SRv6 SID */
stream_put(s, ctx, sizeof(struct srv6_sid_ctx));
/* SRv6 SID value (i.e. IPv6 address) */
stream_put(s, sid_value, sizeof(struct in6_addr));
/* SRv6 SID function */
stream_putl(s, func);
/* SRv6 wide SID function */
stream_putl(s, wide_func);
/* SRv6 locator name optional */
if (locator_name) {
stream_putw(s, strlen(locator_name));
stream_put(s, locator_name, strlen(locator_name));
} else
stream_putw(s, 0);
stream_putw_at(s, 0, stream_get_endp(s));
zserv_send_message(client, s);
}
/* Router-id is updated. Send ZEBRA_ROUTER_ID_UPDATE to client. */
int zsend_router_id_update(struct zserv *client, afi_t afi, struct prefix *p,
@ -1136,9 +1178,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 == 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);
@ -2990,6 +3048,96 @@ stream_failure:
return;
}
/**
* Handle SRv6 SID request received from a client daemon protocol.
*
* @param client The client zapi session
* @param msg The request message
*/
static void zread_srv6_manager_get_srv6_sid(struct zserv *client,
struct stream *msg)
{
struct stream *s;
struct srv6_sid_ctx ctx = {};
struct in6_addr sid_value = {};
struct in6_addr *sid_value_ptr = NULL;
char locator[SRV6_LOCNAME_SIZE] = { 0 };
uint16_t len;
struct zebra_srv6_sid *sid = NULL;
uint8_t flags;
/* Get input stream */
s = msg;
/* Get data */
STREAM_GET(&ctx, s, sizeof(struct srv6_sid_ctx));
STREAM_GETC(s, flags);
if (CHECK_FLAG(flags, ZAPI_SRV6_MANAGER_SID_FLAG_HAS_SID_VALUE)) {
STREAM_GET(&sid_value, s, sizeof(struct in6_addr));
sid_value_ptr = &sid_value;
}
if (CHECK_FLAG(flags, ZAPI_SRV6_MANAGER_SID_FLAG_HAS_LOCATOR)) {
STREAM_GETW(s, len);
STREAM_GET(locator, s, len);
}
/* Call hook to get a SID using wrapper */
srv6_manager_get_sid_call(&sid, client, &ctx, sid_value_ptr, locator);
stream_failure:
return;
}
/**
* Handle SRv6 SID release request received from a client daemon protocol.
*
* @param client The client zapi session
* @param msg The request message
*/
static void zread_srv6_manager_release_srv6_sid(struct zserv *client,
struct stream *msg)
{
struct stream *s;
struct srv6_sid_ctx ctx = {};
/* Get input stream */
s = msg;
/* Get data */
STREAM_GET(&ctx, s, sizeof(struct srv6_sid_ctx));
/* Call hook to release a SID using wrapper */
srv6_manager_release_sid_call(client, &ctx);
stream_failure:
return;
}
/**
* Handle SRv6 locator get request received from a client daemon protocol.
*
* @param client The client zapi session
* @param msg The request message
*/
static void zread_srv6_manager_get_locator(struct zserv *client,
struct stream *msg)
{
struct stream *s = msg;
uint16_t len;
char locator_name[SRV6_LOCNAME_SIZE] = { 0 };
struct srv6_locator *locator = NULL;
/* Get data */
STREAM_GETW(s, len);
STREAM_GET(locator_name, s, len);
/* Call hook to get the locator info using wrapper */
srv6_manager_get_locator_call(&locator, client, locator_name);
stream_failure:
return;
}
static void zread_srv6_manager_request(ZAPI_HANDLER_ARGS)
{
switch (hdr->command) {
@ -3001,6 +3149,15 @@ static void zread_srv6_manager_request(ZAPI_HANDLER_ARGS)
zread_srv6_manager_release_locator_chunk(client, msg,
zvrf_id(zvrf));
break;
case ZEBRA_SRV6_MANAGER_GET_SRV6_SID:
zread_srv6_manager_get_srv6_sid(client, msg);
break;
case ZEBRA_SRV6_MANAGER_RELEASE_SRV6_SID:
zread_srv6_manager_release_srv6_sid(client, msg);
break;
case ZEBRA_SRV6_MANAGER_GET_LOCATOR:
zread_srv6_manager_get_locator(client, msg);
break;
default:
zlog_err("%s: unknown SRv6 Manager command", __func__);
break;
@ -3949,6 +4106,9 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
[ZEBRA_MLAG_FORWARD_MSG] = zebra_mlag_forward_client_msg,
[ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK] = zread_srv6_manager_request,
[ZEBRA_SRV6_MANAGER_RELEASE_LOCATOR_CHUNK] = zread_srv6_manager_request,
[ZEBRA_SRV6_MANAGER_GET_SRV6_SID] = zread_srv6_manager_request,
[ZEBRA_SRV6_MANAGER_RELEASE_SRV6_SID] = zread_srv6_manager_request,
[ZEBRA_SRV6_MANAGER_GET_LOCATOR] = zread_srv6_manager_request,
[ZEBRA_CLIENT_CAPABILITIES] = zread_client_capabilities,
[ZEBRA_NEIGH_DISCOVER] = zread_neigh_discover,
[ZEBRA_NHG_ADD] = zread_nhg_add,

View File

@ -94,6 +94,11 @@ extern int zsend_sr_policy_notify_status(uint32_t color,
extern void zsend_neighbor_notify(int cmd, struct interface *ifp,
struct ipaddr *ipaddr, int ndm_state,
union sockunion *link_layer_ipv4, int ip_len);
extern void zsend_srv6_sid_notify(struct zserv *client,
const struct srv6_sid_ctx *ctx,
struct in6_addr *sid_value, uint32_t func,
uint32_t wide_func, const char *locator_name,
enum zapi_srv6_sid_notify note);
extern int zsend_client_close_notify(struct zserv *client,
struct zserv *closed_client);
@ -110,6 +115,9 @@ extern int zsend_zebra_srv6_locator_delete(struct zserv *client,
extern int zsend_srv6_manager_get_locator_chunk_response(struct zserv *client,
vrf_id_t vrf_id, struct srv6_locator *loc);
extern int zsend_srv6_manager_get_locator_response(struct zserv *client,
struct srv6_locator *locator);
#ifdef __cplusplus
}
#endif

View File

@ -787,6 +787,18 @@ static struct log_ref ferr_zebra_err[] = {
.suggestion =
"Wait for Zebra to reattempt update.",
},
{
.code = EC_ZEBRA_SM_CANNOT_ASSIGN_SID,
.title = "SRv6 manager unable to assign SID",
.description = "Zebra's SRv6 manager was unable to assign a SID to client.",
.suggestion = "Ensure that Zebra has a sufficient SID range available.",
},
{
.code = EC_ZEBRA_SM_DAEMON_MISMATCH,
.title = "Daemon mismatch when releasing SRV6 SIDs",
.description = "Zebra noticed a mismatch between a SRv6 SID and a protocol daemon number or instance when releasing unused SRv6 SIDs.",
.suggestion = "Ignore this error.",
},
{
.code = END_FERR,
}

View File

@ -124,6 +124,8 @@ enum zebra_log_refs {
EC_ZEBRA_GRE_SET_UPDATE,
EC_ZEBRA_SRV6M_UNRELEASED_LOCATOR_CHUNK,
EC_ZEBRA_INTF_UPDATE_FAILURE,
EC_ZEBRA_SM_CANNOT_ASSIGN_SID,
EC_ZEBRA_SM_DAEMON_MISMATCH,
};
void zebra_error_init(void);

File diff suppressed because it is too large Load Diff

View File

@ -16,12 +16,197 @@
#include <pthread.h>
#include <plist.h>
/* Default config for SRv6 SID `usid-f3216` format */
#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 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
/* 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 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;
};
/**
* The function part of an SRv6 SID can be allocated in one
* of the following ways:
* - dynamic: allocate any available function
* - explicit: allocate a specific function
*/
enum srv6_sid_alloc_mode {
SRV6_SID_ALLOC_MODE_UNSPEC = 0,
/* Dynamic SID allocation */
SRV6_SID_ALLOC_MODE_DYNAMIC = 1,
/* Explicit SID allocation */
SRV6_SID_ALLOC_MODE_EXPLICIT = 2,
SRV6_SID_ALLOC_MODE_MAX = 3,
};
/**
* Convert SID allocation mode to string.
*
* @param alloc_mode SID allocation mode
* @return String representing the allocation mode
*/
static inline const char *
srv6_sid_alloc_mode2str(enum srv6_sid_alloc_mode alloc_mode)
{
switch (alloc_mode) {
case SRV6_SID_ALLOC_MODE_EXPLICIT:
return "explicit";
case SRV6_SID_ALLOC_MODE_DYNAMIC:
return "dynamic";
case SRV6_SID_ALLOC_MODE_UNSPEC:
return "unspec";
case SRV6_SID_ALLOC_MODE_MAX:
default:
return "unknown";
}
}
/* SRv6 SID instance. */
struct zebra_srv6_sid {
/*
* SID context associated with the SID.
* Defines behavior and attributes of the SID.
*/
struct zebra_srv6_sid_ctx *ctx;
/* SID value (e.g. fc00:0:1:e000::) */
struct in6_addr value;
/* Pointer to the SRv6 locator from which the SID has been allocated */
struct srv6_locator *locator;
/* Pointer to the SRv6 block from which the SID has been allocated */
struct zebra_srv6_sid_block *block;
/*
* Function part of the SID
* Example:
* SID = fc00:0:1:e000:: => func = e000
*/
uint32_t func;
/* SID wide function. */
uint32_t wide_func;
/* SID allocation mode: dynamic or explicit */
enum srv6_sid_alloc_mode alloc_mode;
/* List of clients that are using the SID */
struct list *client_list;
};
/*
* Zebra SRv6 SID context.
* A context defines a behavior and (optionally) some behavior-specific
* attributes. Client daemons (bgp, isis, ...) ask SRv6 Manager to allocate
* a SID for a particular context. SRv6 Manager is responsible for allocating
* a SID from a given SID block and associating with the context.
*
* Example:
* bgp asks to associate a SID to the context {behavior=End.DT46 vrf=Vrf10}.
* SRv6 Manager allocate SID fc00:0:1:e000:: for that context.
*/
struct zebra_srv6_sid_ctx {
/* SRv6 SID context information. */
struct srv6_sid_ctx ctx;
/* SID associated with the context. */
struct zebra_srv6_sid *sid;
};
/* 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;
/* SRv6 SIDs */
struct list *sids;
/* SRv6 SID blocks */
struct list *sid_blocks;
};
/* declare hooks for the basic API, so that it can be specialized or served
@ -46,6 +231,17 @@ DECLARE_HOOK(srv6_manager_release_chunk,
vrf_id_t vrf_id),
(client, locator_name, vrf_id));
DECLARE_HOOK(srv6_manager_get_sid,
(struct zebra_srv6_sid **sid, struct zserv *client,
struct srv6_sid_ctx *ctx, struct in6_addr *sid_value,
const char *locator_name),
(sid, client, ctx, sid_value, locator_name));
DECLARE_HOOK(srv6_manager_release_sid,
(struct zserv *client, struct srv6_sid_ctx *ctx), (client, ctx));
DECLARE_HOOK(srv6_manager_get_locator,
(struct srv6_locator **locator, struct zserv *client,
const char *locator_name),
(locator, client, locator_name));
extern void zebra_srv6_locator_add(struct srv6_locator *locator);
extern void zebra_srv6_locator_delete(struct srv6_locator *locator);
@ -74,4 +270,55 @@ 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 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 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);
extern struct zebra_srv6_sid *
zebra_srv6_sid_alloc(struct zebra_srv6_sid_ctx *ctx, struct in6_addr *sid_value,
struct srv6_locator *locator,
struct zebra_srv6_sid_block *sid_block, uint32_t sid_func,
enum srv6_sid_alloc_mode alloc_mode);
extern void zebra_srv6_sid_free(struct zebra_srv6_sid *sid);
extern void delete_zebra_srv6_sid(void *val);
extern void srv6_manager_get_sid_call(struct zebra_srv6_sid **sid,
struct zserv *client,
struct srv6_sid_ctx *ctx,
struct in6_addr *sid_value,
const char *locator_name);
extern void srv6_manager_release_sid_call(struct zserv *client,
struct srv6_sid_ctx *ctx);
extern void srv6_manager_get_locator_call(struct srv6_locator **locator,
struct zserv *client,
const char *locator_name);
extern int get_srv6_sid(struct zebra_srv6_sid **sid, struct srv6_sid_ctx *ctx,
struct in6_addr *sid_value, const char *locator_name);
extern int release_srv6_sid(struct zserv *client,
struct zebra_srv6_sid_ctx *zctx);
extern int release_daemon_srv6_sids(struct zserv *client);
extern int srv6_manager_get_sid_response(struct zebra_srv6_sid *sid,
struct zserv *client);
extern struct zebra_srv6_sid_ctx *zebra_srv6_sid_ctx_alloc(void);
extern void zebra_srv6_sid_ctx_free(struct zebra_srv6_sid_ctx *ctx);
extern void delete_zebra_srv6_sid_ctx(void *val);
#endif /* _ZEBRA_SRV6_H */

View File

@ -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]",
@ -198,15 +219,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,
@ -248,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;
}
@ -297,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;
}
@ -323,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;
@ -401,7 +508,8 @@ DEFPY (locator_prefix,
}
}
zebra_srv6_locator_add(locator);
zebra_srv6_locator_format_set(locator, locator->sid_format);
return CMD_SUCCESS;
}
@ -422,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)
@ -431,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;
}
@ -469,11 +645,312 @@ 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;
/* Notify zclients that the format has changed */
zebra_srv6_sid_format_changed_cb(format);
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;
/* Notify zclients that the format has changed */
zebra_srv6_sid_format_changed_cb(format);
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;
/* Notify zclients that the format has changed */
zebra_srv6_sid_format_changed_cb(format);
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);
/* Notify zclients that the format has changed */
zebra_srv6_sid_format_changed_cb(format);
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;
/* Notify zclients that the format has changed */
zebra_srv6_sid_format_changed_cb(format);
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);
}
/* Notify zclients that the format has changed */
zebra_srv6_sid_format_changed_cb(format);
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;
/* Notify zclients that the format has changed */
zebra_srv6_sid_format_changed_cb(format);
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);
}
/* Notify zclients that the format has changed */
zebra_srv6_sid_format_changed_cb(format);
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;
/* Notify zclients that the format has changed */
zebra_srv6_sid_format_changed_cb(format);
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);
/* Notify zclients that the format has changed */
zebra_srv6_sid_format_changed_cb(format);
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;
/* Notify zclients that the format has changed */
zebra_srv6_sid_format_changed_cb(format);
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);
/* Notify zclients that the format has changed */
zebra_srv6_sid_format_changed_cb(format);
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;
@ -515,6 +992,54 @@ 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");
}
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_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");
}
@ -538,11 +1063,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);
@ -550,14 +1081,44 @@ 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_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,
&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);