Skip to content

Commit

Permalink
zebra: ZAPI add new api to manipulate 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 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(FRRouting#7680).

Signed-off-by: Hiroki Shirokura <slank.dev@gmail.com>
  • Loading branch information
slankdev committed Jan 31, 2021
1 parent fb4c0f8 commit 99724ba
Show file tree
Hide file tree
Showing 8 changed files with 615 additions and 0 deletions.
2 changes: 2 additions & 0 deletions zebra/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
#include "zebra/zebra_nb.h"
#include "zebra/zebra_opaque.h"
#include "zebra/zebra_srte.h"
#include "zebra/zebra_srv6.h"
#include "zebra/zebra_srv6_vty.h"

#define ZEBRA_PTM_SUPPORT
Expand Down Expand Up @@ -418,6 +419,7 @@ int main(int argc, char **argv)
zebra_pbr_init();
zebra_opaque_init();
zebra_srte_init();
zebra_srv6_init();
zebra_srv6_vty_init();

/* For debug purpose. */
Expand Down
2 changes: 2 additions & 0 deletions zebra/subdir.am
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ zebra_zebra_SOURCES = \
zebra/zebra_mpls_openbsd.c \
zebra/zebra_mpls_null.c \
zebra/zebra_mpls_vty.c \
zebra/zebra_srv6.c \
zebra/zebra_srv6_vty.c \
zebra/zebra_mroute.c \
zebra/zebra_nb.c \
Expand Down Expand Up @@ -164,6 +165,7 @@ noinst_HEADERS += \
zebra/zebra_mlag.h \
zebra/zebra_mlag_vty.h \
zebra/zebra_mpls.h \
zebra/zebra_srv6.h \
zebra/zebra_srv6_vty.h \
zebra/zebra_mroute.h \
zebra/zebra_nb.h \
Expand Down
166 changes: 166 additions & 0 deletions zebra/zapi_msg.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
#include "zebra/connected.h"
#include "zebra/zebra_opaque.h"
#include "zebra/zebra_srte.h"
#include "zebra/zebra_srv6.h"

static int zapi_nhg_decode(struct stream *s, int cmd, struct zapi_nhg *api_nhg);

Expand Down Expand Up @@ -1083,6 +1084,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[] = {
Expand Down Expand Up @@ -2558,6 +2582,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)
Expand Down Expand Up @@ -2767,6 +2859,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;
Expand Down Expand Up @@ -3329,6 +3492,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,
Expand Down
9 changes: 9 additions & 0 deletions zebra/zapi_msg.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "zebra/zebra_pbr.h"
#include "zebra/zebra_errors.h"
#include "zebra/label_manager.h"
#include "zebra/zebra_srv6.h"


#ifdef __cplusplus
Expand Down Expand Up @@ -111,6 +112,14 @@ extern int zsend_client_close_notify(struct zserv *client,
int zsend_nhg_notify(uint16_t type, uint16_t instance, uint32_t session_id,
uint32_t id, enum zapi_nhg_notify_owner note);

extern int zsend_zebra_srv6_locator_add(struct zserv *client,
struct srv6_locator *loc);
extern int zsend_zebra_srv6_locator_delete(struct zserv *client,
struct srv6_locator *loc);
extern int zsend_srv6_manager_get_locator_chunk_response(struct zserv *client,
vrf_id_t vrf_id,
struct srv6_locator *loc);

#ifdef __cplusplus
}
#endif
6 changes: 6 additions & 0 deletions zebra/zebra_errors.c
Original file line number Diff line number Diff line change
Expand Up @@ -785,6 +785,12 @@ static struct log_ref ferr_zebra_err[] = {
.description = "Zebra has detected a situation where there are two vrf devices with the exact same tableid. This is considered a complete misconfiguration of VRF devices and breaks a fundamental assumption in FRR about how VRF's work",
.suggestion = "Use different table id's for the VRF's in question"
},
{
.code = EC_ZEBRA_SRV6M_UNRELEASED_LOCATOR_CHUNK,
.title = "Zebra did not free any srv6 locator chunks",
.description = "Zebra's srv6-locator chunk cleanup procedure ran, but no srv6 locator chunks were released.",
.suggestion = "Ignore this error.",
},
{
.code = END_FERR,
}
Expand Down
1 change: 1 addition & 0 deletions zebra/zebra_errors.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ enum zebra_log_refs {
EC_ZEBRA_DUPLICATE_NHG_MESSAGE,
EC_ZEBRA_VRF_MISCONFIGURED,
EC_ZEBRA_ES_CREATE,
EC_ZEBRA_SRV6M_UNRELEASED_LOCATOR_CHUNK,
};

void zebra_error_init(void);
Expand Down
Loading

0 comments on commit 99724ba

Please sign in to comment.