Skip to content

Commit

Permalink
zebra: Add support for srv6 locator-opcode
Browse files Browse the repository at this point in the history
In order to support configuring static SRv6 decapsulation functionality on the system, we need to support configuring a purely static mode local SID. This local SID does not rely on BGP to randomly generate a specific mySID address. Instead, it generates a unique mySID table entry by manually specifying the opcode.

Signed-off-by: hanyu.zly <[email protected]>
  • Loading branch information
zice312963205 committed Nov 28, 2024
1 parent 399547f commit 5d6c171
Show file tree
Hide file tree
Showing 11 changed files with 392 additions and 20 deletions.
1 change: 1 addition & 0 deletions lib/command.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ enum node_type {
SRV6_NODE, /* SRv6 node */
SRV6_LOCS_NODE, /* SRv6 locators node */
SRV6_LOC_NODE, /* SRv6 locator node */
SRV6_PREFIX_NODE, /* SRv6 locator prefix 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 */
Expand Down
48 changes: 47 additions & 1 deletion lib/srv6.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,19 @@ struct srv6_locator *srv6_locator_alloc(const char *name)
locator->chunks = list_new();
locator->chunks->del = srv6_locator_chunk_list_free;

locator->sids = list_new();

QOBJ_REG(locator, srv6_locator);
return locator;
}
void srv6_locator_del(struct srv6_locator *locator)
{
if (locator->chunks)
list_delete(&locator->chunks);
if (locator->sids)
list_delete(&locator->sids);
XFREE(MTYPE_SRV6_LOCATOR, locator);
}

struct srv6_locator_chunk *srv6_locator_chunk_alloc(void)
{
Expand Down Expand Up @@ -205,6 +215,43 @@ void srv6_locator_free(struct srv6_locator *locator)
}
}

struct seg6_sid *srv6_locator_sid_alloc(void)
{
struct seg6_sid *sid = NULL;

sid = XCALLOC(MTYPE_SRV6_LOCATOR_CHUNK, sizeof(struct seg6_sid));
strlcpy(sid->vrfName, "Default", sizeof(sid->vrfName));
return sid;
}
void srv6_locator_sid_free(struct seg6_sid *sid)
{
XFREE(MTYPE_SRV6_LOCATOR_CHUNK, sid);
}

void combine_sid(struct srv6_locator *locator, struct in6_addr *sid_addr,
struct in6_addr *result_addr)
{
uint8_t idx = 0;
uint8_t funcid = 0;
uint8_t locatorbit = 0;
/* uint8_t sidbit = 0;*/
uint8_t totalbit = 0;
uint8_t funbit = 0;

locatorbit = (locator->block_bits_length + locator->node_bits_length) / 8;
/* sidbit = 16 - locatorbit; */
totalbit = (locator->block_bits_length + locator->node_bits_length +
locator->function_bits_length + locator->argument_bits_length) /
8;
funbit = (locator->function_bits_length + locator->argument_bits_length) / 8;
for (idx = 0; idx < locatorbit; idx++)
result_addr->s6_addr[idx] = locator->prefix.prefix.s6_addr[idx];
for (; idx < totalbit; idx++) {
result_addr->s6_addr[idx] = sid_addr->s6_addr[16 - funbit + funcid];
funcid++;
}
}

void srv6_locator_chunk_free(struct srv6_locator_chunk **chunk)
{
XFREE(MTYPE_SRV6_LOCATOR_CHUNK, *chunk);
Expand Down Expand Up @@ -485,7 +532,6 @@ json_object *srv6_locator_detailed_json(const struct srv6_locator *loc)
jo_chunk = srv6_locator_chunk_detailed_json(chunk);
json_object_array_add(jo_chunks, jo_chunk);
}

/* set sids */
jo_sids = json_object_new_array();
json_object_object_add(jo_root, "sids", jo_sids);
Expand Down
14 changes: 14 additions & 0 deletions lib/srv6.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <zebra.h>
#include "prefix.h"
#include "json.h"
#include "vrf.h"

#include <arpa/inet.h>
#include <netinet/in.h>
Expand Down Expand Up @@ -129,6 +130,7 @@ struct srv6_locator {
uint64_t current;
bool status_up;
struct list *chunks;
struct list *sids;

uint8_t flags;
#define SRV6_LOCATOR_USID (1 << 0) /* The SRv6 Locator is a uSID Locator */
Expand Down Expand Up @@ -167,6 +169,12 @@ struct srv6_locator_chunk {
uint8_t flags;
};

struct seg6_sid {
enum seg6local_action_t sidaction;
char vrfName[VRF_NAMSIZ + 1];
struct prefix_ipv6 ipv6Addr;
char sidstr[PREFIX_STRLEN];
};
/*
* SRv6 Endpoint Behavior codepoints, as defined by IANA in
* https://www.iana.org/assignments/segment-routing/segment-routing.xhtml
Expand Down Expand Up @@ -376,8 +384,14 @@ static inline const char *srv6_sid_ctx2str(char *str, size_t size,
int snprintf_seg6_segs(char *str,
size_t size, const struct seg6_segs *segs);

extern void combine_sid(struct srv6_locator *locator, struct in6_addr *sid_addr,
struct in6_addr *result_addr);
extern void srv6_locator_del(struct srv6_locator *locator);

extern struct srv6_locator *srv6_locator_alloc(const char *name);
extern struct srv6_locator_chunk *srv6_locator_chunk_alloc(void);
extern struct seg6_sid *srv6_locator_sid_alloc(void);
extern void srv6_locator_sid_free(struct seg6_sid *sid);
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);
Expand Down
27 changes: 27 additions & 0 deletions lib/zclient.c
Original file line number Diff line number Diff line change
Expand Up @@ -1156,6 +1156,33 @@ int zapi_srv6_locator_decode(struct stream *s, struct srv6_locator *l)
return -1;
}

int zapi_srv6_locator_sid_encode(struct stream *s, struct srv6_locator *loc)
{
struct seg6_sid *sidtmp = NULL;
struct listnode *node = NULL;

stream_putw(s, strlen(loc->name));
stream_put(s, loc->name, strlen(loc->name));

stream_putw(s, loc->prefix.prefixlen);
stream_put(s, &loc->prefix.prefix, sizeof(loc->prefix.prefix));
stream_putc(s, loc->block_bits_length);
stream_putc(s, loc->node_bits_length);
stream_putc(s, loc->function_bits_length);
stream_putc(s, loc->argument_bits_length);

stream_putl(s, loc->sids->count);
for (ALL_LIST_ELEMENTS_RO(loc->sids, node, sidtmp)) {
stream_putw(s, sidtmp->ipv6Addr.prefixlen);
stream_put(s, &sidtmp->ipv6Addr.prefix, sizeof(sidtmp->ipv6Addr.prefix));
stream_putl(s, sidtmp->sidaction);
stream_putw(s, strlen(sidtmp->vrfName));
stream_put(s, sidtmp->vrfName, strlen(sidtmp->vrfName));
}

return 0;
}

static int zapi_nhg_encode(struct stream *s, int cmd, struct zapi_nhg *api_nhg)
{
int i;
Expand Down
5 changes: 5 additions & 0 deletions lib/zclient.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,9 @@ typedef enum {
ZEBRA_SRV6_MANAGER_GET_LOCATOR,
ZEBRA_SRV6_MANAGER_GET_SRV6_SID,
ZEBRA_SRV6_MANAGER_RELEASE_SRV6_SID,
ZEBRA_SRV6_MANAGER_GET_LOCATOR_SID,
ZEBRA_SRV6_MANAGER_RELEASE_LOCATOR_SID,
ZEBRA_SRV6_MANAGER_GET_LOCATOR_ALL,
ZEBRA_ERROR,
ZEBRA_CLIENT_CAPABILITIES,
ZEBRA_OPAQUE_MESSAGE,
Expand Down Expand Up @@ -1064,6 +1067,8 @@ extern struct interface *zebra_interface_link_params_read(struct stream *s,
bool *changed);
extern size_t zebra_interface_link_params_write(struct stream *,
struct interface *);

extern int zapi_srv6_locator_sid_encode(struct stream *s, struct srv6_locator *loc);
extern enum zclient_send_status
zclient_send_get_label_chunk(struct zclient *zclient, uint8_t keep,
uint32_t chunk_size, uint32_t base);
Expand Down
36 changes: 36 additions & 0 deletions vtysh/vtysh.c
Original file line number Diff line number Diff line change
Expand Up @@ -1325,6 +1325,13 @@ static struct cmd_node srv6_loc_node = {
.prompt = "%s(config-srv6-locator)# ",
};

static struct cmd_node srv6_prefix_node = {
.name = "srv6-locator-prefix",
.node = SRV6_PREFIX_NODE,
.parent_node = SRV6_LOC_NODE,
.prompt = "%s(config-srv6-locator-prefix)# ",
};

static struct cmd_node srv6_encap_node = {
.name = "srv6-encap",
.node = SRV6_ENCAP_NODE,
Expand Down Expand Up @@ -1709,6 +1716,22 @@ DEFUNSH(VTYSH_ZEBRA, srv6_locator, srv6_locator_cmd,
return CMD_SUCCESS;
}

DEFUNSH(VTYSH_ZEBRA, srv6_prefix, srv6_prefix_cmd,
"prefix X:X::X:X/M$prefix \
[block-len (16-64)$block_bit_len] [node-len (16-64)$node_bit_len] [func-bits (16-80)$func_bit_len]",
"Configure SRv6 locator prefix\n"
"Specify SRv6 locator prefix\n"
"Configure SRv6 locator block length in bits\n"
"Specify SRv6 locator block length in bits\n"
"Configure SRv6 locator node length in bits\n"
"Specify SRv6 locator node length in bits\n"
"Configure SRv6 locator function length in bits\n"
"Specify SRv6 locator function length in bits\n")
{
vty->node = SRV6_PREFIX_NODE;
return CMD_SUCCESS;
}

DEFUNSH(VTYSH_ZEBRA, srv6_encap, srv6_encap_cmd,
"encapsulation",
"Segment Routing SRv6 encapsulation\n")
Expand Down Expand Up @@ -2558,6 +2581,14 @@ DEFUNSH(VTYSH_ZEBRA, exit_srv6_loc_config, exit_srv6_loc_config_cmd, "exit",
return CMD_SUCCESS;
}

DEFUNSH(VTYSH_ZEBRA, exit_srv6_prefix_config, exit_srv6_prefix_config_cmd,
"exit", "Exit from SRv6-locators prefix configuration mode\n")
{
if (vty->node == SRV6_PREFIX_NODE)
vty->node = SRV6_LOC_NODE;
return CMD_SUCCESS;
}

DEFUNSH(VTYSH_ZEBRA, exit_srv6_encap, exit_srv6_encap_cmd, "exit",
"Exit from SRv6-encapsulation configuration mode\n")
{
Expand Down Expand Up @@ -5001,6 +5032,7 @@ void vtysh_init_vty(void)
install_node(&srv6_node);
install_node(&srv6_locs_node);
install_node(&srv6_loc_node);
install_node(&srv6_prefix_node);
install_node(&srv6_encap_node);
install_node(&srv6_sid_formats_node);
install_node(&srv6_sid_format_usid_f3216_node);
Expand Down Expand Up @@ -5447,9 +5479,13 @@ void vtysh_init_vty(void)
install_element(SRV6_LOCS_NODE, &exit_srv6_locs_config_cmd);
install_element(SRV6_LOCS_NODE, &vtysh_end_all_cmd);

install_element(SRV6_LOC_NODE, &srv6_prefix_cmd);
install_element(SRV6_LOC_NODE, &exit_srv6_loc_config_cmd);
install_element(SRV6_LOC_NODE, &vtysh_end_all_cmd);

install_element(SRV6_PREFIX_NODE, &exit_srv6_prefix_config_cmd);
install_element(SRV6_PREFIX_NODE, &vtysh_end_all_cmd);

install_element(SRV6_ENCAP_NODE, &exit_srv6_encap_cmd);
install_element(SRV6_ENCAP_NODE, &vtysh_end_all_cmd);

Expand Down
31 changes: 31 additions & 0 deletions zebra/zapi_msg.c
Original file line number Diff line number Diff line change
Expand Up @@ -2760,6 +2760,37 @@ int zsend_client_close_notify(struct zserv *client, struct zserv *closed_client)
return zserv_send_message(client, s);
}

int zsend_srv6_manager_get_locator_sid_response(struct zserv *client, vrf_id_t vrf_id,
struct srv6_locator *loc)
{
struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);

zclient_create_header(s, ZEBRA_SRV6_MANAGER_GET_LOCATOR_SID, vrf_id);
zapi_srv6_locator_sid_encode(s, loc);
stream_putw_at(s, 0, stream_get_endp(s));
return zserv_send_message(client, s);
}

int zsend_srv6_manager_del_sid(struct zserv *client, vrf_id_t vrf_id, struct srv6_locator *loc,
struct seg6_sid *sid)
{
struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);

zclient_create_header(s, ZEBRA_SRV6_MANAGER_RELEASE_LOCATOR_SID, vrf_id);

stream_putw(s, strlen(loc->name));
stream_put(s, loc->name, strlen(loc->name));

stream_putl(s, 1);
stream_putw(s, sid->ipv6Addr.prefixlen);
stream_put(s, &sid->ipv6Addr.prefix, sizeof(sid->ipv6Addr.prefix));
stream_putl(s, sid->sidaction);
stream_putw(s, strlen(sid->vrfName));
stream_put(s, sid->vrfName, strlen(sid->vrfName));
stream_putw_at(s, 0, stream_get_endp(s));
return zserv_send_message(client, s);
}

int zsend_srv6_manager_get_locator_chunk_response(struct zserv *client,
vrf_id_t vrf_id,
struct srv6_locator *loc)
Expand Down
5 changes: 5 additions & 0 deletions zebra/zapi_msg.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ extern int zsend_srv6_manager_get_locator_chunk_response(struct zserv *client,
extern int zsend_srv6_manager_get_locator_response(struct zserv *client,
struct srv6_locator *locator);

extern int zsend_srv6_manager_get_locator_sid_response(struct zserv *client, vrf_id_t vrf_id,
struct srv6_locator *loc);
extern int zsend_srv6_manager_del_sid(struct zserv *client, vrf_id_t vrf_id,
struct srv6_locator *loc, struct seg6_sid *sid);

#ifdef __cplusplus
}
#endif
11 changes: 9 additions & 2 deletions zebra/zebra_srv6.c
Original file line number Diff line number Diff line change
Expand Up @@ -628,10 +628,16 @@ void zebra_srv6_locator_add(struct srv6_locator *locator)

void zebra_srv6_locator_delete(struct srv6_locator *locator)
{
struct listnode *n;
struct listnode *n, *nnode;
struct zebra_srv6 *srv6 = zebra_srv6_get_default();
struct seg6_sid *sid = NULL;
struct zserv *client;
struct listnode *client_node;

for (ALL_LIST_ELEMENTS(locator->sids, n, nnode, sid)) {
listnode_delete(locator->sids, sid);
srv6_locator_sid_free(sid);
}
/*
* Notify deleted locator info to zclients if needed.
*
Expand All @@ -643,7 +649,8 @@ void zebra_srv6_locator_delete(struct srv6_locator *locator)
* by ZEBRA_SRV6_LOCATOR_DELETE, and this notification is sent to the
* owner of each chunk.
*/
for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, n, client))

for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, client_node, client))
zsend_zebra_srv6_locator_delete(client, locator);

listnode_delete(srv6->locators, locator);
Expand Down
1 change: 1 addition & 0 deletions zebra/zebra_srv6.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ DECLARE_HOOK(srv6_manager_get_locator,

extern void zebra_srv6_locator_add(struct srv6_locator *locator);
extern void zebra_srv6_locator_delete(struct srv6_locator *locator);
extern void zebra_srv6_prefix_delete(struct srv6_locator *locator);
extern struct srv6_locator *zebra_srv6_locator_lookup(const char *name);

void zebra_notify_srv6_locator_add(struct srv6_locator *locator);
Expand Down
Loading

0 comments on commit 5d6c171

Please sign in to comment.