mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-05-24 21:50:42 +00:00
Merge pull request #15604 from cscarpitta/srv6-sid-manager
Add support for SRv6 SID Manager
This commit is contained in:
commit
7834c38ab3
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
||||
|
171
lib/srv6.c
171
lib/srv6.c
@ -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);
|
||||
|
134
lib/srv6.h
134
lib/srv6.h
@ -20,6 +20,8 @@
|
||||
#define SRH_BASE_HEADER_LENGTH 8
|
||||
#define SRH_SEGMENT_LENGTH 16
|
||||
|
||||
#define SRV6_SID_FORMAT_NAME_SIZE 512
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -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
|
||||
|
194
lib/zclient.c
194
lib/zclient.c
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
162
zebra/zapi_msg.c
162
zebra/zapi_msg.c
@ -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, ¬e, 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,
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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);
|
||||
|
2078
zebra/zebra_srv6.c
2078
zebra/zebra_srv6.c
File diff suppressed because it is too large
Load Diff
@ -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 */
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user