summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHiroki Shirokura <slank.dev@gmail.com>2020-02-23 11:27:15 +0000
committerMark Stapp <mjs@voltanet.io>2021-06-02 10:24:47 -0400
commitf2867068e679900582aeb263d1723f8d7c3aa0ed (patch)
tree8c34cedf751778b49fe9daa9d25415d05f25912c
parent6c0a7c094111b11b7f8c298b71c60e08b82d8e15 (diff)
lib: add new structures for srv6-locator (step2)
This commit is a part of #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>
-rw-r--r--lib/srv6.c85
-rw-r--r--lib/srv6.h32
-rw-r--r--lib/zclient.c184
-rw-r--r--lib/zclient.h16
4 files changed, 317 insertions, 0 deletions
diff --git a/lib/srv6.c b/lib/srv6.c
index 9b9f402987..d59d2d75b0 100644
--- a/lib/srv6.c
+++ b/lib/srv6.c
@@ -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) {
@@ -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;
+}
diff --git a/lib/srv6.h b/lib/srv6.h
index b72b098c78..46ff830e7f 100644
--- a/lib/srv6.h
+++ b/lib/srv6.h
@@ -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" {
@@ -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) {
@@ -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
diff --git a/lib/zclient.c b/lib/zclient.c
index bf67392cbe..c8bb720591 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -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");
@@ -2637,6 +2638,174 @@ stream_failure:
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
*
@@ -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;
diff --git a/lib/zclient.h b/lib/zclient.h
index 3f5225f097..6496e79c89 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -39,6 +39,7 @@
#include "mlag.h"
#include "srte.h"
+#include "srv6.h"
#ifdef __cplusplus
extern "C" {
@@ -216,6 +217,11 @@ typedef enum {
ZEBRA_NHG_NOTIFY_OWNER,
ZEBRA_EVPN_REMOTE_NH_ADD,
ZEBRA_EVPN_REMOTE_NH_DEL,
+ ZEBRA_SRV6_LOCATOR_ADD,
+ ZEBRA_SRV6_LOCATOR_DELETE,
+ ZEBRA_SRV6_MANAGER_CONNECT,
+ ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK,
+ ZEBRA_SRV6_MANAGER_RELEASE_LOCATOR_CHUNK,
ZEBRA_ERROR,
ZEBRA_CLIENT_CAPABILITIES,
ZEBRA_OPAQUE_MESSAGE,
@@ -387,6 +393,11 @@ struct zclient {
int (*mlag_process_down)(void);
int (*mlag_handle_msg)(struct stream *msg, int len);
int (*nhg_notify_owner)(ZAPI_CALLBACK_ARGS);
+ int (*srv6_locator_add)(ZAPI_CALLBACK_ARGS);
+ int (*srv6_locator_delete)(ZAPI_CALLBACK_ARGS);
+ int (*srv6_function_add)(ZAPI_CALLBACK_ARGS);
+ int (*srv6_function_delete)(ZAPI_CALLBACK_ARGS);
+ void (*process_srv6_locator_chunk)(ZAPI_CALLBACK_ARGS);
int (*handle_error)(enum zebra_error_types error);
int (*opaque_msg_handler)(ZAPI_CALLBACK_ARGS);
int (*opaque_register_handler)(ZAPI_CALLBACK_ARGS);
@@ -1051,6 +1062,11 @@ 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);
+extern int srv6_manager_connect(struct zclient *zclient);
+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 enum zclient_send_status zebra_send_sr_policy(struct zclient *zclient,
int cmd,