Skip to content

Commit

Permalink
lib: add new structures for srv6-locator (step2)
Browse files Browse the repository at this point in the history
This commit is a part of FRRouting#5853 works that add new structures for
SRv6-locator. This structure will be used by zebra and another
routing daemon and its ZAPI messaging to manage SRv6-locator.
Encoder/decoder for ZAPI stream is also added by this commit.

Real configuration mechanism isn't implemented at this commit.
later commit add real configure implementation. This commit add only
SRv6-locator's structures and misc functions.

Signed-off-by: Hiroki Shirokura <slank.dev@gmail.com>
  • Loading branch information
slankdev committed May 5, 2021
1 parent 64622ff commit 70c91fb
Show file tree
Hide file tree
Showing 4 changed files with 317 additions and 0 deletions.
85 changes: 85 additions & 0 deletions lib/srv6.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
#include "srv6.h"
#include "log.h"

DEFINE_QOBJ_TYPE(srv6_locator)
DEFINE_MTYPE_STATIC(LIB, SRV6_LOCATOR, "SRV6 locator")
DEFINE_MTYPE_STATIC(LIB, SRV6_LOCATOR_CHUNK, "SRV6 locator chunk")

const char *seg6local_action2str(uint32_t action)
{
switch (action) {
Expand Down Expand Up @@ -117,3 +121,84 @@ const char *seg6local_context2str(char *str, size_t size,
return str;
}
}

struct srv6_locator *srv6_locator_alloc(const char *name)
{
struct srv6_locator *locator = NULL;

locator = XCALLOC(MTYPE_SRV6_LOCATOR, sizeof(struct srv6_locator));
strlcpy(locator->name, name, sizeof(locator->name));
locator->chunks = list_new();
QOBJ_REG(locator, srv6_locator);
return locator;
}

struct srv6_locator_chunk *srv6_locator_chunk_alloc(void)
{
struct srv6_locator_chunk *chunk = NULL;

chunk = XCALLOC(MTYPE_SRV6_LOCATOR_CHUNK,
sizeof(struct srv6_locator_chunk));
return chunk;
}

void srv6_locator_free(struct srv6_locator *locator)
{
XFREE(MTYPE_SRV6_LOCATOR, locator);
}

void srv6_locator_chunk_free(struct srv6_locator_chunk *chunk)
{
XFREE(MTYPE_SRV6_LOCATOR_CHUNK, chunk);
}

json_object *srv6_locator_chunk_json(const struct srv6_locator_chunk *chunk)
{
char str[256];
json_object *jo_root = NULL;

jo_root = json_object_new_object();
prefix2str(&chunk->prefix, str, sizeof(str));
json_object_string_add(jo_root, "prefix", str);
json_object_string_add(jo_root, "proto",
zebra_route_string(chunk->proto));

return jo_root;
}

json_object *srv6_locator_json(const struct srv6_locator *loc)
{
char str[256];
struct listnode *node;
struct srv6_locator_chunk *chunk;
json_object *jo_root = NULL;
json_object *jo_chunk = NULL;
json_object *jo_chunks = NULL;

jo_root = json_object_new_object();

/* set name */
json_object_string_add(jo_root, "name", loc->name);

/* set prefix */
prefix2str(&loc->prefix, str, sizeof(str));
json_object_string_add(jo_root, "prefix", str);

/* set function_bits_length */
json_object_int_add(jo_root, "function_bits_length",
loc->function_bits_length);

/* set status_up */
json_object_boolean_add(jo_root, "status_up",
loc->status_up);

/* set chunks */
jo_chunks = json_object_new_array();
json_object_object_add(jo_root, "chunks", jo_chunks);
for (ALL_LIST_ELEMENTS_RO((struct list *)loc->chunks, node, chunk)) {
jo_chunk = srv6_locator_chunk_json(chunk);
json_object_array_add(jo_chunks, jo_chunk);
}

return jo_root;
}
32 changes: 32 additions & 0 deletions lib/srv6.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,14 @@
#define _FRR_SRV6_H

#include <zebra.h>
#include "prefix.h"
#include "json.h"

#include <arpa/inet.h>
#include <netinet/in.h>

#define SRV6_MAX_SIDS 16
#define SRV6_LOCNAME_SIZE 256

#ifdef __cplusplus
extern "C" {
Expand Down Expand Up @@ -69,6 +73,27 @@ struct seg6local_context {
uint32_t table;
};

struct srv6_locator {
char name[SRV6_LOCNAME_SIZE];
struct prefix_ipv6 prefix;
uint8_t function_bits_length;
int algonum;
uint64_t current;
bool status_up;
struct list *chunks;

QOBJ_FIELDS
};
DECLARE_QOBJ_TYPE(srv6_locator)

struct srv6_locator_chunk {
uint8_t keep;
uint8_t proto;
uint16_t instance;
uint32_t session_id;
struct prefix_ipv6 prefix;
};

static inline const char *seg6_mode2str(enum seg6_mode_t mode)
{
switch (mode) {
Expand Down Expand Up @@ -126,6 +151,13 @@ const char *seg6local_context2str(char *str, size_t size,
int snprintf_seg6_segs(char *str,
size_t size, const struct seg6_segs *segs);

extern struct srv6_locator *srv6_locator_alloc(const char *name);
extern struct srv6_locator_chunk *srv6_locator_chunk_alloc(void);
extern void srv6_locator_free(struct srv6_locator *locator);
extern void srv6_locator_chunk_free(struct srv6_locator_chunk *chunk);
json_object *srv6_locator_chunk_json(const struct srv6_locator_chunk *chunk);
json_object *srv6_locator_json(const struct srv6_locator *loc);

#ifdef __cplusplus
}
#endif
Expand Down
184 changes: 184 additions & 0 deletions lib/zclient.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include "lib_errors.h"
#include "srte.h"
#include "printfrr.h"
#include "srv6.h"

DEFINE_MTYPE_STATIC(LIB, ZCLIENT, "Zclient");
DEFINE_MTYPE_STATIC(LIB, REDIST_INST, "Redistribution instance IDs");
Expand Down Expand Up @@ -2637,6 +2638,174 @@ int lm_label_manager_connect(struct zclient *zclient, int async)
return -1;
}

/**
* Connect to srv6 manager in a syncronous way
*
* It first writes the request to zcient output buffer and then
* immediately reads the answer from the input buffer.
*
* @param zclient Zclient used to connect to srv6 manager (zebra)
* @result Result of response
*/
int srv6_manager_connect(struct zclient *zclient)
{
struct stream *s;
int ret, result = 0;
uint16_t cmd = ZEBRA_SRV6_MANAGER_CONNECT;

if (zclient_debug)
zlog_debug("Connecting to SRv6 Manager");

if (zclient->sock < 0) {
zlog_debug("%s: invalid zclient socket", __func__);
return -1;
}

/* send request */
s = zclient->obuf;
stream_reset(s);
zclient_create_header(s, cmd, VRF_DEFAULT);

stream_putc(s, zclient->redist_default); /* proto */
stream_putw(s, zclient->instance); /* instance */
stream_putw_at(s, 0, stream_get_endp(s));
ret = writen(zclient->sock, s->data, stream_get_endp(s));
if (ret < 0) {
flog_err(EC_LIB_ZAPI_SOCKET, "Can't write to zclient sock");
close(zclient->sock);
zclient->sock = -1;
return -1;
}
if (ret == 0) {
flog_err(EC_LIB_ZAPI_SOCKET, "Zclient sock closed");
close(zclient->sock);
zclient->sock = -1;
return -1;
}
if (zclient_debug)
zlog_debug("SRv6 Manager connect request sent (%d bytes)", ret);

/* read response */
if (zclient_read_sync_response(zclient, cmd)
!= 0)
return -1;

s = zclient->ibuf;

/* read instance and proto */
uint8_t proto;
uint16_t instance;

STREAM_GETC(s, proto);
STREAM_GETW(s, instance);

/* sanity */
if (proto != zclient->redist_default)
flog_err(
EC_LIB_ZAPI_ENCODE,
"Wrong proto (%u) in SRv6 Manager connect response. Should be %u",
proto, zclient->redist_default);
if (instance != zclient->instance)
flog_err(
EC_LIB_ZAPI_ENCODE,
"Wrong instId (%u) in SRv6 Manager connect response. Should be %u",
instance, zclient->instance);

/* result code */
STREAM_GETC(s, result);
if (zclient_debug)
zlog_debug("SRv6 Manager connect-response received, result %u", result);

return (int)result;

stream_failure:
return -1;
}

/**
* Function to request a srv6-locator chunk in an Asyncronous way
*
* It first writes the request to zclient output buffer and then
* immediately reads the answer from the input buffer.
*
* @param zclient Zclient used to connect to table manager (zebra)
* @param locator_name Name of SRv6-locator
* @result 0 on success, -1 otherwise
*/
int srv6_manager_get_locator_chunk(struct zclient *zclient,
const char *locator_name)
{
struct stream *s;
const size_t len = strlen(locator_name);

if (zclient_debug)
zlog_debug("Getting SRv6-Locator Chunk %s", locator_name);

if (zclient->sock < 0)
return -1;

/* send request */
s = zclient->obuf;
stream_reset(s);
zclient_create_header(s, ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK, VRF_DEFAULT);

/* proto */
stream_putc(s, zclient->redist_default);

/* instance */
stream_putw(s, zclient->instance);

/* 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 release a srv6-locator chunk
*
* @param zclient Zclient used to connect to table manager (zebra)
* @param locator_name Name of SRv6-locator
* @result 0 on success, -1 otherwise
*/
int srv6_manager_release_locator_chunk(struct zclient *zclient,
const char *locator_name)
{
struct stream *s;
const size_t len = strlen(locator_name);

if (zclient_debug)
zlog_debug("Releasing SRv6-Locator Chunk %s", locator_name);

if (zclient->sock < 0)
return -1;

/* send request */
s = zclient->obuf;
stream_reset(s);
zclient_create_header(s, ZEBRA_SRV6_MANAGER_RELEASE_LOCATOR_CHUNK,
VRF_DEFAULT);

/* proto */
stream_putc(s, zclient->redist_default);

/* instance */
stream_putw(s, zclient->instance);

/* 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);
}

/*
* Asynchronous label chunk request
*
Expand Down Expand Up @@ -3927,6 +4096,21 @@ static int zclient_read(struct thread *thread)
case ZEBRA_MLAG_FORWARD_MSG:
zclient_mlag_handle_msg(command, zclient, length, vrf_id);
break;
case ZEBRA_SRV6_LOCATOR_ADD:
if (zclient->srv6_locator_add)
(*zclient->srv6_locator_add)(command, zclient, length,
vrf_id);
break;
case ZEBRA_SRV6_LOCATOR_DELETE:
if (zclient->srv6_locator_delete)
(*zclient->srv6_locator_delete)(command, zclient,
length, vrf_id);
break;
case ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK:
if (zclient->process_srv6_locator_chunk)
(*zclient->process_srv6_locator_chunk)(command, zclient,
length, vrf_id);
break;
case ZEBRA_ERROR:
zclient_handle_error(command, zclient, length, vrf_id);
break;
Expand Down
Loading

0 comments on commit 70c91fb

Please sign in to comment.