summaryrefslogtreecommitdiff
path: root/zebra/zapi_msg.c
diff options
context:
space:
mode:
authorHiroki Shirokura <slank.dev@gmail.com>2020-12-09 18:52:17 +0900
committerMark Stapp <mjs@voltanet.io>2021-06-02 10:24:47 -0400
commit6e68a08484bf8f5c79f041ce8c103ce42abc2e7f (patch)
treefe15369c2c80eb9db7c125098f910272b5012291 /zebra/zapi_msg.c
parentf2867068e679900582aeb263d1723f8d7c3aa0ed (diff)
zebra: ZAPI add new api to manipulate srv6-locator (step2)
This commit is a part of #5853 works that add new ZAPI to configure SRv6 locator which manages chunk prefix for SRv6 SID IPv6 address for each routing protocol daemons. NEW-ZAPIs: * ZEBRA_SRV6_LOCATOR_ADD * ZEBRA_SRV6_LOCATOR_DELETE * ZEBRA_SRV6_MANAGER_CONNECT * ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK * ZEBRA_SRV6_MANAGER_RELEASE_LOCATOR_CHUNK Zclient can connect to zebra's srv6-manager with ZEBRA_SRV6_MANAGER_CONNECT api like a label-manager. Then zclient uses ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK to allocated dedicated locator chunk for it's routing protocol. Zebra works for only prefix reservation and distribute the ownership of the locator chunks for zcliens. Then, zclient installs SRv6 function with ZEBRA_ROUTE_ADD api with nh_seg6local_* fields. This feature is already implemented by another PR(#7680). Signed-off-by: Hiroki Shirokura <slank.dev@gmail.com>
Diffstat (limited to 'zebra/zapi_msg.c')
-rw-r--r--zebra/zapi_msg.c166
1 files changed, 166 insertions, 0 deletions
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 752738b214..fa6a4cfca7 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -60,6 +60,7 @@
#include "zebra/connected.h"
#include "zebra/zebra_opaque.h"
#include "zebra/zebra_srte.h"
+#include "zebra/zebra_srv6.h"
DEFINE_MTYPE_STATIC(ZEBRA, OPAQUE, "Opaque Data");
@@ -1136,6 +1137,29 @@ static int zsend_table_manager_connect_response(struct zserv *client,
return zserv_send_message(client, s);
}
+static int zsend_srv6_manager_connect_response(struct zserv *client,
+ vrf_id_t vrf_id,
+ uint16_t result)
+{
+ struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+
+ zclient_create_header(s, ZEBRA_SRV6_MANAGER_CONNECT, vrf_id);
+
+ /* proto */
+ stream_putc(s, client->proto);
+
+ /* instance */
+ stream_putw(s, client->instance);
+
+ /* result */
+ stream_putc(s, result);
+
+ /* Write packet size. */
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ return zserv_send_message(client, s);
+}
+
/* Inbound message handling ------------------------------------------------ */
const int cmd2type[] = {
@@ -2624,6 +2648,74 @@ int zsend_client_close_notify(struct zserv *client, struct zserv *closed_client)
return zserv_send_message(client, s);
}
+/* Send response to a srv6 manager connect request to client */
+static void zread_srv6_manager_connect(struct zserv *client,
+ struct stream *msg, vrf_id_t vrf_id)
+{
+ struct stream *s;
+ uint8_t proto;
+ uint16_t instance;
+ struct vrf *vrf = vrf_lookup_by_id(vrf_id);
+
+ s = msg;
+
+ /* Get data. */
+ STREAM_GETC(s, proto);
+ STREAM_GETW(s, instance);
+
+ /* accept only dynamic routing protocols */
+ if ((proto >= ZEBRA_ROUTE_MAX) || (proto <= ZEBRA_ROUTE_STATIC)) {
+ flog_err(EC_ZEBRA_TM_WRONG_PROTO,
+ "client %d has wrong protocol %s", client->sock,
+ zebra_route_string(proto));
+ zsend_srv6_manager_connect_response(client, vrf_id, 1);
+ return;
+ }
+ zlog_notice("client %d with vrf %s(%u) instance %u connected as %s",
+ client->sock, VRF_LOGNAME(vrf), vrf_id, instance,
+ zebra_route_string(proto));
+ client->proto = proto;
+ client->instance = instance;
+
+ /*
+ * Release previous locators of same protocol and instance.
+ * This is done in case it restarted from an unexpected shutdown.
+ */
+ release_daemon_srv6_locator_chunks(client);
+
+ zsend_srv6_manager_connect_response(client, vrf_id, 0);
+
+stream_failure:
+ return;
+}
+
+int zsend_srv6_manager_get_locator_chunk_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_CHUNK, vrf_id);
+
+ /* proto */
+ stream_putc(s, client->proto);
+
+ /* instance */
+ stream_putw(s, client->instance);
+
+ if (loc) {
+ 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, 16);
+ }
+
+ /* Write packet size. */
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ return zserv_send_message(client, s);
+}
+
/* Send response to a table manager connect request to client */
static void zread_table_manager_connect(struct zserv *client,
struct stream *msg, vrf_id_t vrf_id)
@@ -2833,6 +2925,77 @@ static void zread_table_manager_request(ZAPI_HANDLER_ARGS)
}
}
+static void zread_srv6_manager_get_locator_chunk(struct zserv *client,
+ struct stream *msg,
+ vrf_id_t vrf_id)
+{
+ struct stream *s = msg;
+ uint8_t proto;
+ uint16_t instance;
+ uint16_t len;
+ char locator_name[SRV6_LOCNAME_SIZE] = {0};
+
+ /* Get data. */
+ STREAM_GETC(s, proto);
+ STREAM_GETW(s, instance);
+ STREAM_GETW(s, len);
+ STREAM_GET(locator_name, s, len);
+
+ assert(proto == client->proto && instance == client->instance);
+
+ /* call hook to get a chunk using wrapper */
+ struct srv6_locator *loc = NULL;
+ srv6_manager_get_locator_chunk_call(&loc, client, locator_name, vrf_id);
+
+stream_failure:
+ return;
+}
+
+static void zread_srv6_manager_release_locator_chunk(struct zserv *client,
+ struct stream *msg,
+ vrf_id_t vrf_id)
+{
+ struct stream *s = msg;
+ uint8_t proto;
+ uint16_t instance;
+ uint16_t len;
+ char locator_name[SRV6_LOCNAME_SIZE] = {0};
+
+ /* Get data. */
+ STREAM_GETC(s, proto);
+ STREAM_GETW(s, instance);
+ STREAM_GETW(s, len);
+ STREAM_GET(locator_name, s, len);
+
+ assert(proto == client->proto && instance == client->instance);
+
+ /* call hook to release a chunk using wrapper */
+ srv6_manager_release_locator_chunk_call(client, locator_name, vrf_id);
+
+stream_failure:
+ return;
+}
+
+static void zread_srv6_manager_request(ZAPI_HANDLER_ARGS)
+{
+ switch (hdr->command) {
+ case ZEBRA_SRV6_MANAGER_CONNECT:
+ zread_srv6_manager_connect(client, msg, zvrf_id(zvrf));
+ break;
+ case ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK:
+ zread_srv6_manager_get_locator_chunk(client, msg,
+ zvrf_id(zvrf));
+ break;
+ case ZEBRA_SRV6_MANAGER_RELEASE_LOCATOR_CHUNK:
+ zread_srv6_manager_release_locator_chunk(client, msg,
+ zvrf_id(zvrf));
+ break;
+ default:
+ zlog_err("%s: unknown SRv6 Mamanger command", __func__);
+ break;
+ }
+}
+
static void zread_pseudowire(ZAPI_HANDLER_ARGS)
{
struct stream *s;
@@ -3592,6 +3755,9 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
[ZEBRA_MLAG_CLIENT_REGISTER] = zebra_mlag_client_register,
[ZEBRA_MLAG_CLIENT_UNREGISTER] = zebra_mlag_client_unregister,
[ZEBRA_MLAG_FORWARD_MSG] = zebra_mlag_forward_client_msg,
+ [ZEBRA_SRV6_MANAGER_CONNECT] = zread_srv6_manager_request,
+ [ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK] = zread_srv6_manager_request,
+ [ZEBRA_SRV6_MANAGER_RELEASE_LOCATOR_CHUNK] = zread_srv6_manager_request,
[ZEBRA_CLIENT_CAPABILITIES] = zread_client_capabilities,
[ZEBRA_NEIGH_DISCOVER] = zread_neigh_discover,
[ZEBRA_NHG_ADD] = zread_nhg_add,