diff options
| -rw-r--r-- | zebra/main.c | 2 | ||||
| -rw-r--r-- | zebra/subdir.am | 2 | ||||
| -rw-r--r-- | zebra/zapi_msg.c | 166 | ||||
| -rw-r--r-- | zebra/zapi_msg.h | 9 | ||||
| -rw-r--r-- | zebra/zebra_errors.c | 6 | ||||
| -rw-r--r-- | zebra/zebra_errors.h | 1 | ||||
| -rw-r--r-- | zebra/zebra_srv6.c | 349 | ||||
| -rw-r--r-- | zebra/zebra_srv6.h | 79 | 
8 files changed, 614 insertions, 0 deletions
diff --git a/zebra/main.c b/zebra/main.c index 259c70d0df..e36af51005 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -57,6 +57,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 @@ -419,6 +420,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. */ diff --git a/zebra/subdir.am b/zebra/subdir.am index ca77502ba3..4d8115597b 100644 --- a/zebra/subdir.am +++ b/zebra/subdir.am @@ -93,6 +93,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 \ @@ -163,6 +164,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 \ 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, diff --git a/zebra/zapi_msg.h b/zebra/zapi_msg.h index 0beb3cc100..35bb554121 100644 --- a/zebra/zapi_msg.h +++ b/zebra/zapi_msg.h @@ -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 @@ -116,6 +117,14 @@ int zsend_nhg_notify(uint16_t type, uint16_t instance, uint32_t session_id,  extern void zapi_opaque_free(struct opaque *opaque); +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 diff --git a/zebra/zebra_errors.c b/zebra/zebra_errors.c index 29b271425d..c3890f7220 100644 --- a/zebra/zebra_errors.c +++ b/zebra/zebra_errors.c @@ -786,6 +786,12 @@ static struct log_ref ferr_zebra_err[] = {  		.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,  	}  }; diff --git a/zebra/zebra_errors.h b/zebra/zebra_errors.h index 200a977a69..540c6dd7d0 100644 --- a/zebra/zebra_errors.h +++ b/zebra/zebra_errors.h @@ -135,6 +135,7 @@ enum zebra_log_refs {  	EC_ZEBRA_VRF_MISCONFIGURED,  	EC_ZEBRA_ES_CREATE,  	EC_ZEBRA_GRE_SET_UPDATE, +	EC_ZEBRA_SRV6M_UNRELEASED_LOCATOR_CHUNK,  };  void zebra_error_init(void); diff --git a/zebra/zebra_srv6.c b/zebra/zebra_srv6.c new file mode 100644 index 0000000000..b4b691e8e0 --- /dev/null +++ b/zebra/zebra_srv6.c @@ -0,0 +1,349 @@ +/* + * Zebra SRv6 definitions + * Copyright (C) 2020  Hiroki Shirokura, LINE Corporation + * Copyright (C) 2020  Masakazu Asama + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <zebra.h> + +#include "network.h" +#include "prefix.h" +#include "stream.h" +#include "srv6.h" +#include "zebra/debug.h" +#include "zebra/zapi_msg.h" +#include "zebra/zserv.h" +#include "zebra/zebra_router.h" +#include "zebra/zebra_srv6.h" +#include "zebra/zebra_errors.h" +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <arpa/inet.h> +#include <netinet/in.h> + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <arpa/inet.h> +#include <netinet/in.h> + + +DEFINE_MGROUP(SRV6_MGR, "SRv6 Manager"); +DEFINE_MTYPE_STATIC(SRV6_MGR, SRV6M_CHUNK, "SRv6 Manager Chunk"); + +/* define hooks for the basic API, so that it can be specialized or served + * externally + */ + +DEFINE_HOOK(srv6_manager_client_connect, +	    (struct zserv *client, vrf_id_t vrf_id), +	    (client, vrf_id)); +DEFINE_HOOK(srv6_manager_client_disconnect, +	    (struct zserv *client), (client)); +DEFINE_HOOK(srv6_manager_get_chunk, +	    (struct srv6_locator **loc, +	     struct zserv *client, +	     const char *locator_name, +	     vrf_id_t vrf_id), +	    (loc, client, locator_name, vrf_id)); +DEFINE_HOOK(srv6_manager_release_chunk, +	    (struct zserv *client, +	     const char *locator_name, +	     vrf_id_t vrf_id), +	    (client, locator_name, vrf_id)); + +/* define wrappers to be called in zapi_msg.c (as hooks must be called in + * source file where they were defined) + */ + +void srv6_manager_client_connect_call(struct zserv *client, vrf_id_t vrf_id) +{ +	hook_call(srv6_manager_client_connect, client, vrf_id); +} + +void srv6_manager_get_locator_chunk_call(struct srv6_locator **loc, +					 struct zserv *client, +					 const char *locator_name, +					 vrf_id_t vrf_id) +{ +	hook_call(srv6_manager_get_chunk, loc, client, locator_name, vrf_id); +} + +void srv6_manager_release_locator_chunk_call(struct zserv *client, +					     const char *locator_name, +					     vrf_id_t vrf_id) +{ +	hook_call(srv6_manager_release_chunk, client, locator_name, vrf_id); +} + +int srv6_manager_client_disconnect_cb(struct zserv *client) +{ +	hook_call(srv6_manager_client_disconnect, client); +	return 0; +} + +static int zebra_srv6_cleanup(struct zserv *client) +{ +	return 0; +} + +void zebra_srv6_locator_add(struct srv6_locator *locator) +{ +	struct zebra_srv6 *srv6 = zebra_srv6_get_default(); +	struct srv6_locator *tmp; + +	tmp = zebra_srv6_locator_lookup(locator->name); +	if (!tmp) +		listnode_add(srv6->locators, locator); +} + +void zebra_srv6_locator_delete(struct srv6_locator *locator) +{ +	struct zebra_srv6 *srv6 = zebra_srv6_get_default(); +	listnode_delete(srv6->locators, locator); +} + +struct srv6_locator *zebra_srv6_locator_lookup(const char *name) +{ +	struct zebra_srv6 *srv6 = zebra_srv6_get_default(); +	struct srv6_locator *locator; +	struct listnode *node; + +	for (ALL_LIST_ELEMENTS_RO(srv6->locators, node, locator)) +		if (!strncmp(name, locator->name, SRV6_LOCNAME_SIZE)) +			return locator; +	return NULL; +} + +struct zebra_srv6 *zebra_srv6_get_default(void) +{ +	static struct zebra_srv6 srv6; +	static bool first_execution = true; + +	if (first_execution) { +		first_execution = false; +		srv6.locators = list_new(); +	} +	return &srv6; +} + +/** + * Core function, assigns srv6-locator chunks + * + * It first searches through the list to check if there's one available + * (previously released). Otherwise it creates and assigns a new one + * + * @param proto Daemon protocol of client, to identify the owner + * @param instance Instance, to identify the owner + * @param session_id SessionID of client + * @param name Name of SRv6-locator + * @return Pointer to the assigned srv6-locator chunk, + *         or NULL if the request could not be satisfied + */ +static struct srv6_locator * +assign_srv6_locator_chunk(uint8_t proto, +			  uint16_t instance, +			  uint32_t session_id, +			  const char *locator_name) +{ +	bool chunk_found = false; +	struct listnode *node = NULL; +	struct srv6_locator *loc = NULL; +	struct srv6_locator_chunk *chunk = NULL; + +	loc = zebra_srv6_locator_lookup(locator_name); +	if (!loc) { +		zlog_info("%s: locator %s was not found", +			  __func__, locator_name); + +		loc = srv6_locator_alloc(locator_name); +		if (!loc) { +			zlog_info("%s: locator %s can't allocated", +				  __func__, locator_name); +			return NULL; +		} + +		loc->status_up = false; +		chunk = srv6_locator_chunk_alloc(); +		chunk->proto = 0; +		listnode_add(loc->chunks, chunk); +		zebra_srv6_locator_add(loc); +	} + +	for (ALL_LIST_ELEMENTS_RO((struct list *)loc->chunks, node, chunk)) { +		if (chunk->proto != 0 && chunk->proto != proto) +			continue; +		chunk_found = true; +		break; +	} + +	if (!chunk_found) { +		zlog_info("%s: locator is already owned", __func__); +		return NULL; +	} + +	chunk->proto = proto; +	return loc; +} + +static int zebra_srv6_manager_get_locator_chunk(struct srv6_locator **loc, +						struct zserv *client, +						const char *locator_name, +						vrf_id_t vrf_id) +{ +	*loc = assign_srv6_locator_chunk(client->proto, client->instance, +					 client->session_id, locator_name); + +	if (!*loc) +		zlog_err("Unable to assign locator chunk to %s instance %u", +			 zebra_route_string(client->proto), client->instance); +	else if (IS_ZEBRA_DEBUG_PACKET) +		zlog_info("Assigned locator chunk %s to %s instance %u", +			  (*loc)->name, zebra_route_string(client->proto), +			  client->instance); + +	int ret = 0; +	if ((*loc)->status_up) +		ret = zsend_srv6_manager_get_locator_chunk_response(client, +								    vrf_id, +								    *loc); +	return ret; +} + +/** + * Core function, release no longer used srv6-locator chunks + * + * @param proto Daemon protocol of client, to identify the owner + * @param instance Instance, to identify the owner + * @param session_id Zclient session ID, to identify the zclient session + * @param locator_name SRv6-locator name, to identify the actual locator + * @return 0 on success, -1 otherwise + */ +static int release_srv6_locator_chunk(uint8_t proto, uint16_t instance, +				      uint32_t session_id, +				      const char *locator_name) +{ +	int ret = -1; +	struct listnode *node; +	struct srv6_locator_chunk *chunk; +	struct srv6_locator *loc = NULL; + +	loc = zebra_srv6_locator_lookup(locator_name); +	if (!loc) { +		return -1; +	} + +	if (IS_ZEBRA_DEBUG_PACKET) +		zlog_debug("%s: Releasing srv6-locator on %s", __func__, +			   locator_name); + +	for (ALL_LIST_ELEMENTS_RO((struct list *)loc->chunks, node, chunk)) { +		if (chunk->proto != proto || +		    chunk->instance != instance || +		    chunk->session_id != session_id) +			continue; +		chunk->proto = NO_PROTO; +		chunk->instance = 0; +		chunk->session_id = 0; +		chunk->keep = 0; +		ret = 0; +		break; +	} + +	if (ret != 0) +		flog_err(EC_ZEBRA_SRV6M_UNRELEASED_LOCATOR_CHUNK, +			 "%s: SRv6 locator chunk not released", __func__); + +	return ret; +} + +static int zebra_srv6_manager_release_locator_chunk(struct zserv *client, +						    const char *locator_name, +						    vrf_id_t vrf_id) +{ +	if (vrf_id != VRF_DEFAULT) { +		zlog_err("SRv6 locator doesn't support vrf"); +		return -1; +	} + +	return release_srv6_locator_chunk(client->proto, client->instance, +					  client->session_id, locator_name); +} + +/** + * Release srv6-locator chunks from a client. + * + * Called on client disconnection or reconnection. It only releases chunks + * with empty keep value. + * + * @param proto Daemon protocol of client, to identify the owner + * @param instance Instance, to identify the owner + * @return Number of chunks released + */ +int release_daemon_srv6_locator_chunks(struct zserv *client) +{ +	int ret; +	int count = 0; +	struct zebra_srv6 *srv6 = zebra_srv6_get_default(); +	struct listnode *loc_node; +	struct listnode *chunk_node; +	struct srv6_locator *loc; +	struct srv6_locator_chunk *chunk; + +	if (IS_ZEBRA_DEBUG_PACKET) +		zlog_debug("%s: Releasing chunks for client proto %s, instance %d, session %u", +			   __func__, zebra_route_string(client->proto), +			   client->instance, client->session_id); + +	for (ALL_LIST_ELEMENTS_RO(srv6->locators, loc_node, loc)) { +		for (ALL_LIST_ELEMENTS_RO(loc->chunks, chunk_node, chunk)) { +			if (chunk->proto == client->proto && +			    chunk->instance == client->instance && +			    chunk->session_id == client->session_id && +			    chunk->keep == 0) { +				ret = release_srv6_locator_chunk( +						chunk->proto, chunk->instance, +						chunk->session_id, loc->name); +				if (ret == 0) +					count++; +			} +		} +	} + +	if (IS_ZEBRA_DEBUG_PACKET) +		zlog_debug("%s: Released %d srv6-locator chunks", +			   __func__, count); + +	return count; +} + +void zebra_srv6_init(void) +{ +	hook_register(zserv_client_close, zebra_srv6_cleanup); +	hook_register(srv6_manager_get_chunk, +		      zebra_srv6_manager_get_locator_chunk); +	hook_register(srv6_manager_release_chunk, +		      zebra_srv6_manager_release_locator_chunk); +} + +bool zebra_srv6_is_enable(void) +{ +	struct zebra_srv6 *srv6 = zebra_srv6_get_default(); + +	return listcount(srv6->locators); +} diff --git a/zebra/zebra_srv6.h b/zebra/zebra_srv6.h new file mode 100644 index 0000000000..751cee6e70 --- /dev/null +++ b/zebra/zebra_srv6.h @@ -0,0 +1,79 @@ +/* + * Zebra SRv6 definitions + * Copyright (C) 2020  Hiroki Shirokura, LINE Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _ZEBRA_SRV6_H +#define _ZEBRA_SRV6_H + +#include <zebra.h> +#include <arpa/inet.h> +#include <netinet/in.h> + +#include "qobj.h" +#include "prefix.h" +#include <pthread.h> +#include <plist.h> + +/* SRv6 instance structure. */ +struct zebra_srv6 { +	struct list *locators; +}; + +/* declare hooks for the basic API, so that it can be specialized or served + * externally. Also declare a hook when those functions have been registered, + * so that any external module wanting to replace those can react + */ + +DECLARE_HOOK(srv6_manager_client_connect, +	    (struct zserv *client, vrf_id_t vrf_id), +	    (client, vrf_id)); +DECLARE_HOOK(srv6_manager_client_disconnect, +	     (struct zserv *client), (client)); +DECLARE_HOOK(srv6_manager_get_chunk, +	     (struct srv6_locator **loc, +	      struct zserv *client, +	      const char *locator_name, +	      vrf_id_t vrf_id), +	     (mc, client, keep, size, base, vrf_id)); +DECLARE_HOOK(srv6_manager_release_chunk, +	     (struct zserv *client, +	      const char *locator_name, +	      vrf_id_t vrf_id), +	     (client, locator_name, vrf_id)); + + +extern void zebra_srv6_locator_add(struct srv6_locator *locator); +extern void zebra_srv6_locator_delete(struct srv6_locator *locator); +extern struct srv6_locator *zebra_srv6_locator_lookup(const char *name); + +extern void zebra_srv6_init(void); +extern struct zebra_srv6 *zebra_srv6_get_default(void); +extern bool zebra_srv6_is_enable(void); + +extern void srv6_manager_client_connect_call(struct zserv *client, vrf_id_t vrf_id); +extern void srv6_manager_get_locator_chunk_call(struct srv6_locator **loc, +						struct zserv *client, +						const char *locator_name, +						vrf_id_t vrf_id); +extern void srv6_manager_release_locator_chunk_call(struct zserv *client, +						    const char *locator_name, +						    vrf_id_t vrf_id); +extern int srv6_manager_client_disconnect_cb(struct zserv *client); +extern int release_daemon_srv6_locator_chunks(struct zserv *client); + +#endif /* _ZEBRA_SRV6_H */  | 
