diff options
| -rw-r--r-- | zebra/label_manager.c | 425 | ||||
| -rw-r--r-- | zebra/label_manager.h | 58 | ||||
| -rw-r--r-- | zebra/main.c | 11 | ||||
| -rw-r--r-- | zebra/zapi_msg.c | 72 | ||||
| -rw-r--r-- | zebra/zapi_msg.h | 10 | ||||
| -rw-r--r-- | zebra/zserv.c | 25 | ||||
| -rw-r--r-- | zebra/zserv.h | 1 | 
7 files changed, 220 insertions, 382 deletions
diff --git a/zebra/label_manager.c b/zebra/label_manager.c index 6de94e63da..03cfa572db 100644 --- a/zebra/label_manager.c +++ b/zebra/label_manager.c @@ -38,295 +38,65 @@  #include "zebra/zebra_router.h"  #include "zebra/label_manager.h"  #include "zebra/zebra_errors.h" +#include "zebra/zapi_msg.h"  #define CONNECTION_DELAY 5  struct label_manager lbl_mgr; -extern struct zebra_privs_t zserv_privs; -  DEFINE_MGROUP(LBL_MGR, "Label Manager");  DEFINE_MTYPE_STATIC(LBL_MGR, LM_CHUNK, "Label Manager Chunk"); -/* In case this zebra daemon is not acting as label manager, - * it will be a proxy to relay messages to external label manager - * This zclient thus is to connect to it +/* define hooks for the basic API, so that it can be specialized or served + * externally   */ -static struct stream *obuf; -static struct zclient *zclient; -bool lm_is_external; -static void delete_label_chunk(void *val) +DEFINE_HOOK(lm_client_connect, +	    (uint8_t proto, uint16_t instance, vrf_id_t vrf_id), +	    (proto, instance, vrf_id)); +DEFINE_HOOK(lm_client_disconnect, (uint8_t proto, uint16_t instance), +	    (proto, instance)); +DEFINE_HOOK(lm_get_chunk, +	    (struct label_manager_chunk * *lmc, uint8_t proto, +	     uint16_t instance, uint8_t keep, uint32_t size, uint32_t base, +	     vrf_id_t vrf_id), +	    (lmc, proto, instance, keep, size, base, vrf_id)); +DEFINE_HOOK(lm_release_chunk, +	    (uint8_t proto, uint16_t instance, uint32_t start, uint32_t end), +	    (proto, instance, start, end)); +DEFINE_HOOK(lm_cbs_inited, (), ()); + +/* define wrappers to be called in zapi_msg.c (as hooks must be called in + * source file where they were defined) + */ +void lm_client_connect_call(uint8_t proto, uint16_t instance, vrf_id_t vrf_id)  { -	XFREE(MTYPE_LM_CHUNK, val); +	hook_call(lm_client_connect, proto, instance, vrf_id);  } - -static int relay_response_back(void) +void lm_get_chunk_call(struct label_manager_chunk **lmc, uint8_t proto, +		       uint16_t instance, uint8_t keep, uint32_t size, +		       uint32_t base, vrf_id_t vrf_id)  { -	int ret = 0; -	struct stream *src, *dst; -	uint16_t size = 0; -	uint8_t marker; -	uint8_t version; -	vrf_id_t vrf_id; -	uint16_t resp_cmd; -	uint8_t proto; -	const char *proto_str; -	unsigned short instance; -	struct zserv *zserv; - -	/* sanity */ -	if (!zclient || zclient->sock < 0) -		return -1; - -	/* input buffer with msg from label manager */ -	src = zclient->ibuf; - -	stream_reset(src); - -	/* parse header */ -	ret = zclient_read_header(src, zclient->sock, &size, &marker, &version, -				  &vrf_id, &resp_cmd); -	if (ret < 0) { -		if (errno != EAGAIN) -			flog_err(EC_ZEBRA_LM_RESPONSE, -				 "Error reading Label Manager response: %s", -				 strerror(errno)); -		return -1; -	} - -	/* do not relay a msg that has nothing to do with LM */ -	switch (resp_cmd) { -	case ZEBRA_LABEL_MANAGER_CONNECT: -	case ZEBRA_LABEL_MANAGER_CONNECT_ASYNC: /* should not be seen */ -	case ZEBRA_GET_LABEL_CHUNK: -	case ZEBRA_RELEASE_LABEL_CHUNK: -		break; -	default: -		zlog_debug("Not relaying '%s' response (size %d) from LM", -			   zserv_command_string(resp_cmd), size); -		return -1; -	} - -	zlog_debug("Received '%s' response (size %d) from LM", -		   zserv_command_string(resp_cmd), size); - -	if (size == 0) -		return -1; - -	/* Get the 'proto' field of the message */ -	proto = stream_getc(src); - -	/* Get the 'instance' field of the message */ -	instance = stream_getw(src); - -	proto_str = zebra_route_string(proto); - -	/* lookup the client to relay the msg to */ -	zserv = zserv_find_client(proto, instance); -	if (!zserv) { -		flog_err( -			EC_ZEBRA_LM_NO_SUCH_CLIENT, -			"Error relaying LM response: can't find client %s, instance %u", -			proto_str, instance); -		return -1; -	} -	zlog_debug("Found client to relay LM response to client %s instance %u", -		   proto_str, instance); - -	/* copy msg into output buffer */ -	dst = obuf; -	stream_copy(dst, src); - -	/* send response back */ -	ret = writen(zserv->sock, dst->data, stream_get_endp(dst)); -	if (ret <= 0) { -		flog_err(EC_ZEBRA_LM_RELAY_FAILED, -			 "Error relaying LM response to %s instance %u: %s", -			 proto_str, instance, strerror(errno)); -		return -1; -	} -	zlog_debug("Relayed LM response (%d bytes) to %s instance %u", ret, -		   proto_str, instance); - -	return 0; +	hook_call(lm_get_chunk, lmc, proto, instance, keep, size, base, vrf_id);  } - -static int lm_zclient_read(struct thread *t) -{ -	int ret; - -	zclient->t_read = NULL; - -	/* read response and send it back */ -	ret = relay_response_back(); - -	/* re-arm read */ -	thread_add_read(zclient->master, lm_zclient_read, NULL, -			zclient->sock, &zclient->t_read); -	return ret; -} - -static int reply_error(int cmd, struct zserv *zserv, vrf_id_t vrf_id) +void lm_release_chunk_call(uint8_t proto, uint16_t instance, uint32_t start, +			   uint32_t end)  { -	int ret; -	struct stream *s; - -	s = stream_new(ZEBRA_MAX_PACKET_SIZ); - -	zclient_create_header(s, cmd, vrf_id); - -	/* proto */ -	stream_putc(s, zserv->proto); -	/* instance */ -	stream_putw(s, zserv->instance); -	/* result */ -	stream_putc(s, 1); - -	/* Write packet size. */ -	stream_putw_at(s, 0, stream_get_endp(s)); - -	ret = writen(zserv->sock, s->data, stream_get_endp(s)); - -	stream_free(s); -	return ret; -} -/** - * Receive a request to get or release a label chunk and forward it to external - * label manager. - * - * It's called from zserv in case it's not an actual label manager, but just a - * proxy. - * - * @param cmd Type of request (connect, get or release) - * @param zserv - * @return 0 on success, -1 otherwise - */ -int zread_relay_label_manager_request(int cmd, struct zserv *zserv, -				      struct stream *msg, vrf_id_t vrf_id) -{ -	struct stream *dst; -	int ret = 0; -	uint8_t proto; -	const char *proto_str; -	unsigned short instance; - -	if (zclient->sock < 0) { -		flog_err(EC_ZEBRA_LM_NO_SOCKET, -			 "Unable to relay LM request: no socket"); -		reply_error(cmd, zserv, vrf_id); -		return -1; -	} - -	/* peek msg to get proto and instance id. This zebra, which acts as -	 * a proxy needs to have such values for each client in order to -	 * relay responses back to it. -	 */ - -	/* Get the 'proto' field of incoming msg */ -	proto = stream_getc(msg); - -	/* Get the 'instance' field of incoming msg */ -	instance = stream_getw(msg); - -	/* stringify proto */ -	proto_str = zebra_route_string(proto); - -	/* check & set client proto if unset */ -	if (zserv->proto && zserv->proto != proto) { -		flog_warn(EC_ZEBRAING_LM_PROTO_MISMATCH, -			  "Client proto(%u) != msg proto(%u)", zserv->proto, -			  proto); -		return -1; -	} - -	/* check & set client instance if unset */ -	if (zserv->instance && zserv->instance != instance) { -		flog_err(EC_ZEBRA_LM_BAD_INSTANCE, -			 "Client instance(%u) != msg instance(%u)", -			 zserv->instance, instance); -		return -1; -	} - -	/* recall proto and instance */ -	zserv->instance = instance; -	zserv->proto = proto; - -	/* in case there's any incoming message enqueued, read and forward it */ -	if (zserv->is_synchronous) -		while (ret == 0) -			ret = relay_response_back(); - -	/* get the msg buffer used toward the 'master' Label Manager */ -	dst = zclient->obuf; - -	/* copy the message */ -	stream_copy(dst, msg); - -	/* Send request to external label manager */ -	ret = writen(zclient->sock, dst->data, stream_get_endp(dst)); -	if (ret <= 0) { -		flog_err(EC_ZEBRA_LM_RELAY_FAILED, -			 "Error relaying LM request from %s instance %u: %s", -			 proto_str, instance, strerror(errno)); -		reply_error(cmd, zserv, vrf_id); -		return -1; -	} -	zlog_debug("Relayed LM request (%d bytes) from %s instance %u", ret, -		   proto_str, instance); - - -	/* Release label chunk has no response */ -	if (cmd == ZEBRA_RELEASE_LABEL_CHUNK) -		return 0; - -	/* make sure we listen to the response */ -	if (!zclient->t_read) -		thread_add_read(zclient->master, lm_zclient_read, NULL, -				zclient->sock, &zclient->t_read); - -	return 0; +	hook_call(lm_release_chunk, proto, instance, start, end);  } -static int lm_zclient_connect(struct thread *t) -{ -	zclient->t_connect = NULL; - -	if (zclient->sock >= 0) -		return 0; - -	if (zclient_socket_connect(zclient) < 0) { -		flog_err(EC_ZEBRA_LM_CLIENT_CONNECTION_FAILED, -			 "Error connecting synchronous zclient!"); -		thread_add_timer(zrouter.master, lm_zclient_connect, zclient, -				 CONNECTION_DELAY, &zclient->t_connect); -		return -1; -	} - -	/* make socket non-blocking */ -	(void)set_nonblocking(zclient->sock); - -	return 0; -} +/* forward declarations of the static functions to be used for some hooks */ +static int label_manager_connect(uint8_t proto, uint16_t instance, +				 vrf_id_t vrf_id); +static int label_manager_disconnect(uint8_t proto, uint16_t instance); +static int label_manager_get_chunk(struct label_manager_chunk **lmc, +				   uint8_t proto, uint16_t instance, +				   uint8_t keep, uint32_t size, uint32_t base, +				   vrf_id_t vrf_id); -/** - * Function to initialize zclient in case this is not an actual - * label manager, but just a proxy to an external one. - * - * @param lm_zserv_path Path to zserv socket of external label manager - */ -static void lm_zclient_init(char *lm_zserv_path) +void delete_label_chunk(void *val)  { -	if (lm_zserv_path) -		frr_zclient_addr(&zclient_addr, &zclient_addr_len, -				 lm_zserv_path); - -	/* Set default values. */ -	zclient = zclient_new(zrouter.master, &zclient_options_default); -	zclient->privs = &zserv_privs; -	zclient->sock = -1; -	zclient->t_connect = NULL; -	lm_zclient_connect(NULL); +	XFREE(MTYPE_LM_CHUNK, val);  }  /** @@ -339,15 +109,16 @@ static void lm_zclient_init(char *lm_zserv_path)   * @param instance Instance, to identify the owner   * @return Number of chunks released   */ -int release_daemon_label_chunks(struct zserv *client) +int release_daemon_label_chunks(uint8_t proto, unsigned short instance)  { -	uint8_t proto = client->proto; -	uint16_t instance = client->instance;  	struct listnode *node;  	struct label_manager_chunk *lmc;  	int count = 0;  	int ret; +	zlog_debug("%s: Releasing chunks for client proto %s, instance %d", +		   __func__, zebra_route_string(proto), instance); +  	for (ALL_LIST_ELEMENTS_RO(lbl_mgr.lc_list, node, lmc)) {  		if (lmc->proto == proto && lmc->instance == instance  		    && lmc->keep == 0) { @@ -363,33 +134,51 @@ int release_daemon_label_chunks(struct zserv *client)  	return count;  } +int lm_client_disconnect_cb(struct zserv *client) +{ +	uint8_t proto = client->proto; +	uint16_t instance = client->instance; + +	hook_call(lm_client_disconnect, proto, instance); +	return 0; +} + +void lm_hooks_register(void) +{ +	hook_register(lm_client_connect, label_manager_connect); +	hook_register(lm_client_disconnect, label_manager_disconnect); +	hook_register(lm_get_chunk, label_manager_get_chunk); +	hook_register(lm_release_chunk, release_label_chunk); +} +void lm_hooks_unregister(void) +{ +	hook_unregister(lm_client_connect, label_manager_connect); +	hook_unregister(lm_client_disconnect, label_manager_disconnect); +	hook_unregister(lm_get_chunk, label_manager_get_chunk); +	hook_unregister(lm_release_chunk, release_label_chunk); +} +  /**   * Init label manager (or proxy to an external one)   */ -void label_manager_init(char *lm_zserv_path) +void label_manager_init(void)  { -	/* this is an actual label manager */ -	if (!lm_zserv_path) { -		zlog_debug("Initializing internal label manager"); -		lm_is_external = false; -		lbl_mgr.lc_list = list_new(); -		lbl_mgr.lc_list->del = delete_label_chunk; -	} else { /* it's acting just as a proxy */ -		zlog_debug("Initializing external label manager at %s", -			   lm_zserv_path); -		lm_is_external = true; -		lm_zclient_init(lm_zserv_path); -	} +	lbl_mgr.lc_list = list_new(); +	lbl_mgr.lc_list->del = delete_label_chunk; +	hook_register(zserv_client_close, lm_client_disconnect_cb); -	obuf = stream_new(ZEBRA_MAX_PACKET_SIZ); +	/* register default hooks for the label manager actions */ +	lm_hooks_register(); -	hook_register(zserv_client_close, release_daemon_label_chunks); +	/* notify any external module that we are done */ +	hook_call(lm_cbs_inited);  }  /* alloc and fill a label chunk */ -static struct label_manager_chunk * -create_label_chunk(uint8_t proto, unsigned short instance, uint8_t keep, -		   uint32_t start, uint32_t end) +struct label_manager_chunk *create_label_chunk(uint8_t proto, +					       unsigned short instance, +					       uint8_t keep, uint32_t start, +					       uint32_t end)  {  	/* alloc chunk, fill it and return it */  	struct label_manager_chunk *lmc = @@ -405,7 +194,7 @@ create_label_chunk(uint8_t proto, unsigned short instance, uint8_t keep,  }  /* attempt to get a specific label chunk */ -struct label_manager_chunk * +static struct label_manager_chunk *  assign_specific_label_chunk(uint8_t proto, unsigned short instance,  			    uint8_t keep, uint32_t size, uint32_t base)  { @@ -607,9 +396,59 @@ int release_label_chunk(uint8_t proto, unsigned short instance, uint32_t start,  	return ret;  } +/* default functions to be called on hooks  */ +static int label_manager_connect(uint8_t proto, uint16_t instance, +				 vrf_id_t vrf_id) +{ +	/* +	 * Release previous labels of same protocol and instance. +	 * This is done in case it restarted from an unexpected shutdown. +	 */ +	release_daemon_label_chunks(proto, instance); +	return lm_client_connect_response(proto, instance, vrf_id, 0); +} +static int label_manager_disconnect(uint8_t proto, uint16_t instance) +{ +	release_daemon_label_chunks(proto, instance); +	return 0; +} +static int label_manager_get_chunk(struct label_manager_chunk **lmc, +				   uint8_t proto, uint16_t instance, +				   uint8_t keep, uint32_t size, uint32_t base, +				   vrf_id_t vrf_id) +{ +	*lmc = assign_label_chunk(proto, instance, keep, size, base); +	return lm_get_chunk_response(*lmc, proto, instance, vrf_id); +} + +/* Respond to a connect request */ +int lm_client_connect_response(uint8_t proto, uint16_t instance, +			       vrf_id_t vrf_id, uint8_t result) +{ +	struct zserv *client = zserv_find_client(proto, instance); +	if (!client) { +		zlog_err("%s: could not find client for daemon %s instance %u", +			 __func__, zebra_route_string(proto), instance); +		return 1; +	} +	return zsend_label_manager_connect_response(client, vrf_id, result); +} + +/* Respond to a get_chunk request */ +int lm_get_chunk_response(struct label_manager_chunk *lmc, uint8_t proto, +			  uint16_t instance, vrf_id_t vrf_id) +{ +	struct zserv *client = zserv_find_client(proto, instance); +	if (!client) { +		zlog_err("%s: could not find client for daemon %s instance %u", +			 __func__, zebra_route_string(proto), instance); +		return 1; +	} +	return zsend_assign_label_chunk_response(client, vrf_id, proto, +						 instance, lmc); +}  void label_manager_close(void)  {  	list_delete(&lbl_mgr.lc_list); -	stream_free(obuf);  } diff --git a/zebra/label_manager.h b/zebra/label_manager.h index f1b7d050cf..74e283e85e 100644 --- a/zebra/label_manager.h +++ b/zebra/label_manager.h @@ -28,6 +28,7 @@  #include "lib/linklist.h"  #include "lib/thread.h" +#include "lib/hook.h"  #include "zebra/zserv.h" @@ -57,6 +58,54 @@ struct label_manager_chunk {  	uint32_t end;   /* Last label of the chunk */  }; +/* 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(lm_client_connect, +	     (uint8_t proto, uint16_t instance, vrf_id_t vrf_id), +	     (proto, instance, vrf_id)); +DECLARE_HOOK(lm_client_disconnect, (uint8_t proto, uint16_t instance), +	     (proto, instance)); +DECLARE_HOOK(lm_get_chunk, +	     (struct label_manager_chunk * *lmc, uint8_t proto, +	      uint16_t instance, uint8_t keep, uint32_t size, uint32_t base, +	      vrf_id_t vrf_id), +	     (lmc, proto, instance, keep, size, base, vrf_id)); +DECLARE_HOOK(lm_release_chunk, +	     (uint8_t proto, uint16_t instance, uint32_t start, uint32_t end), +	     (proto, instance, start, end)); +DECLARE_HOOK(lm_cbs_inited, (), ()); + + +/* declare wrappers to be called in zapi_msg.c (as hooks must be called in + * source file where they were defined) + */ +void lm_client_connect_call(uint8_t proto, uint16_t instance, vrf_id_t vrf_id); +void lm_get_chunk_call(struct label_manager_chunk **lmc, uint8_t proto, +		       uint16_t instance, uint8_t keep, uint32_t size, +		       uint32_t base, vrf_id_t vrf_id); +void lm_release_chunk_call(uint8_t proto, uint16_t instance, uint32_t start, +			   uint32_t end); + +/* API for an external LM to return responses for requests */ +int lm_client_connect_response(uint8_t proto, uint16_t instance, +			       vrf_id_t vrf_id, uint8_t result); +int lm_get_chunk_response(struct label_manager_chunk *lmc, uint8_t proto, +			  uint16_t instance, vrf_id_t vrf_id); + +/* convenience function to allocate an lmc to be consumed by the above API */ +struct label_manager_chunk *create_label_chunk(uint8_t proto, +					       unsigned short instance, +					       uint8_t keep, uint32_t start, +					       uint32_t end); +void delete_label_chunk(void *val); + +/* register/unregister callbacks for hooks */ +void lm_hooks_register(void); +void lm_hooks_unregister(void); +  /*   * Main label manager struct   * Holds a linked list of label chunks. @@ -65,18 +114,15 @@ struct label_manager {  	struct list *lc_list;  }; -bool lm_is_external; - -int zread_relay_label_manager_request(int cmd, struct zserv *zserv, -				      struct stream *msg, vrf_id_t vrf_id); -void label_manager_init(char *lm_zserv_path); +void label_manager_init(void);  struct label_manager_chunk *assign_label_chunk(uint8_t proto,  					       unsigned short instance,  					       uint8_t keep, uint32_t size,  					       uint32_t base);  int release_label_chunk(uint8_t proto, unsigned short instance, uint32_t start,  			uint32_t end); -int release_daemon_label_chunks(struct zserv *client); +int lm_client_disconnect_cb(struct zserv *client); +int release_daemon_label_chunks(uint8_t proto, unsigned short instance);  void label_manager_close(void);  #ifdef __cplusplus diff --git a/zebra/main.c b/zebra/main.c index 1947106750..84e83bc37e 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -92,7 +92,6 @@ struct option longopts[] = {  	{"keep_kernel", no_argument, NULL, 'k'},  	{"socket", required_argument, NULL, 'z'},  	{"ecmp", required_argument, NULL, 'e'}, -	{"label_socket", no_argument, NULL, 'l'},  	{"retain", no_argument, NULL, 'r'},  	{"vrfdefaultname", required_argument, NULL, 'o'},  	{"graceful_restart", required_argument, NULL, 'K'}, @@ -252,8 +251,6 @@ int main(int argc, char **argv)  	// int batch_mode = 0;  	char *zserv_path = NULL;  	char *vrf_default_name_configured = NULL; -	/* Socket to external label manager */ -	char *lblmgr_path = NULL;  	struct sockaddr_storage dummy;  	socklen_t dummylen;  #if defined(HANDLE_ZAPI_FUZZING) @@ -270,7 +267,7 @@ int main(int argc, char **argv)  	frr_preinit(&zebra_di, argc, argv);  	frr_opt_add( -		"baz:e:l:o:rK:" +		"baz:e:o:rK:"  #ifdef HAVE_NETLINK  		"s:n"  #endif @@ -286,7 +283,6 @@ int main(int argc, char **argv)  		"  -a, --allow_delete       Allow other processes to delete zebra routes\n"  		"  -z, --socket             Set path of zebra socket\n"  		"  -e, --ecmp               Specify ECMP to use.\n" -		"  -l, --label_socket       Socket to external label manager\n"  		"  -r, --retain             When program terminates, retain added route by zebra.\n"  		"  -o, --vrfdefaultname     Set default VRF name.\n"  		"  -K, --graceful_restart   Graceful restart at the kernel level, timer in seconds for expiration\n" @@ -341,9 +337,6 @@ int main(int argc, char **argv)  				exit(1);  			}  			break; -		case 'l': -			lblmgr_path = optarg; -			break;  		case 'r':  			retain_mode = 1;  			break; @@ -451,7 +444,7 @@ int main(int argc, char **argv)  	zserv_start(zserv_path);  	/* Init label manager */ -	label_manager_init(lblmgr_path); +	label_manager_init();  	/* RNH init */  	zebra_rnh_init(); diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 198a47a21f..e018b9595c 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -57,7 +57,6 @@  #include "zebra/rtadv.h"  #include "zebra/zebra_mpls.h"  #include "zebra/zebra_mroute.h" -#include "zebra/label_manager.h"  #include "zebra/zebra_vxlan.h"  #include "zebra/rt.h"  #include "zebra/zebra_pbr.h" @@ -928,10 +927,9 @@ int zsend_pw_update(struct zserv *client, struct zebra_pw *pw)  }  /* Send response to a get label chunk request to client */ -static int zsend_assign_label_chunk_response(struct zserv *client, -					     vrf_id_t vrf_id, uint8_t proto, -					     uint16_t instance, -					     struct label_manager_chunk *lmc) +int zsend_assign_label_chunk_response(struct zserv *client, vrf_id_t vrf_id, +				      uint8_t proto, uint16_t instance, +				      struct label_manager_chunk *lmc)  {  	int ret;  	struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); @@ -959,9 +957,8 @@ static int zsend_assign_label_chunk_response(struct zserv *client,  }  /* Send response to a label manager connect request to client */ -static int zsend_label_manager_connect_response(struct zserv *client, -						vrf_id_t vrf_id, -						unsigned short result) +int zsend_label_manager_connect_response(struct zserv *client, vrf_id_t vrf_id, +					 unsigned short result)  {  	int ret;  	struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); @@ -1897,27 +1894,16 @@ static void zread_label_manager_connect(struct zserv *client,  		flog_err(EC_ZEBRA_TM_WRONG_PROTO,  			 "client %d has wrong protocol %s", client->sock,  			 zebra_route_string(proto)); -		if (client->is_synchronous) -			zsend_label_manager_connect_response(client, vrf_id, 1); +		zsend_label_manager_connect_response(client, vrf_id, 1);  		return;  	} -	zlog_notice("client %d with vrf %u instance %u connected as %s", -		    client->sock, vrf_id, instance, zebra_route_string(proto)); + +	/* recall proto and instance in this socket */  	client->proto = proto;  	client->instance = instance; -	/* -	 * Release previous labels of same protocol and instance. -	 * This is done in case it restarted from an unexpected shutdown. -	 */ -	release_daemon_label_chunks(client); - -	zlog_debug( -		" Label Manager client connected: sock %d, proto %s, vrf %u instance %u", -		client->sock, zebra_route_string(proto), vrf_id, instance); -	/* send response back */ -	if (client->is_synchronous) -		zsend_label_manager_connect_response(client, vrf_id, 0); +	/* call hook for connection using wrapper */ +	lm_client_connect_call(proto, instance, vrf_id);  stream_failure:  	return; @@ -1929,7 +1915,7 @@ static void zread_get_label_chunk(struct zserv *client, struct stream *msg,  	struct stream *s;  	uint8_t keep;  	uint32_t size, base; -	struct label_manager_chunk *lmc; +	struct label_manager_chunk *lmc = NULL;  	uint8_t proto;  	unsigned short instance; @@ -1943,7 +1929,9 @@ static void zread_get_label_chunk(struct zserv *client, struct stream *msg,  	STREAM_GETL(s, size);  	STREAM_GETL(s, base); -	lmc = assign_label_chunk(proto, instance, keep, size, base); +	/* call hook to get a chunk using wrapper */ +	lm_get_chunk_call(&lmc, proto, instance, keep, size, base, vrf_id); +  	if (!lmc)  		flog_err(  			EC_ZEBRA_LM_CANNOT_ASSIGN_CHUNK, @@ -1953,8 +1941,6 @@ static void zread_get_label_chunk(struct zserv *client, struct stream *msg,  		zlog_debug("Assigned Label Chunk %u - %u to %s instance %u",  			   lmc->start, lmc->end,  			   zebra_route_string(proto), instance); -	/* send response back */ -	zsend_assign_label_chunk_response(client, vrf_id, proto, instance, lmc);  stream_failure:  	return; @@ -1976,33 +1962,23 @@ static void zread_release_label_chunk(struct zserv *client, struct stream *msg)  	STREAM_GETL(s, start);  	STREAM_GETL(s, end); -	release_label_chunk(proto, instance, start, end); +	/* call hook to release a chunk using wrapper */ +	lm_release_chunk_call(proto, instance, start, end);  stream_failure:  	return;  } +  static void zread_label_manager_request(ZAPI_HANDLER_ARGS)  { -	/* to avoid sending other messages like ZERBA_INTERFACE_UP */ -	client->is_synchronous = hdr->command == -				 ZEBRA_LABEL_MANAGER_CONNECT; - -	/* external label manager */ -	if (lm_is_external) -		zread_relay_label_manager_request(hdr->command, client, msg, -						  zvrf_id(zvrf)); -	/* this is a label manager */ +	if (hdr->command == ZEBRA_LABEL_MANAGER_CONNECT +	    || hdr->command == ZEBRA_LABEL_MANAGER_CONNECT_ASYNC) +		zread_label_manager_connect(client, msg, zvrf_id(zvrf));  	else { -		if (hdr->command == ZEBRA_LABEL_MANAGER_CONNECT || -		    hdr->command == ZEBRA_LABEL_MANAGER_CONNECT_ASYNC) -			zread_label_manager_connect(client, msg, zvrf_id(zvrf)); -		else { -			if (hdr->command == ZEBRA_GET_LABEL_CHUNK) -				zread_get_label_chunk(client, msg, -						      zvrf_id(zvrf)); -			else if (hdr->command == ZEBRA_RELEASE_LABEL_CHUNK) -				zread_release_label_chunk(client, msg); -		} +		if (hdr->command == ZEBRA_GET_LABEL_CHUNK) +			zread_get_label_chunk(client, msg, zvrf_id(zvrf)); +		else if (hdr->command == ZEBRA_RELEASE_LABEL_CHUNK) +			zread_release_label_chunk(client, msg);  	}  } diff --git a/zebra/zapi_msg.h b/zebra/zapi_msg.h index d30fa2d0ef..884edfef04 100644 --- a/zebra/zapi_msg.h +++ b/zebra/zapi_msg.h @@ -29,6 +29,8 @@  #include "zebra/zserv.h"  #include "zebra/zebra_pbr.h"  #include "zebra/zebra_errors.h" +#include "zebra/label_manager.h" +  #ifdef __cplusplus  extern "C" { @@ -90,6 +92,14 @@ extern void zserv_nexthop_num_warn(const char *caller, const struct prefix *p,  				   const unsigned int nexthop_num);  extern void zsend_capabilities_all_clients(void); +extern int zsend_assign_label_chunk_response(struct zserv *client, +					     vrf_id_t vrf_id, uint8_t proto, +					     uint16_t instance, +					     struct label_manager_chunk *lmc); +extern int zsend_label_manager_connect_response(struct zserv *client, +						vrf_id_t vrf_id, +						unsigned short result); +  #ifdef __cplusplus  } diff --git a/zebra/zserv.c b/zebra/zserv.c index cb9ca6578b..70b4594813 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -535,28 +535,6 @@ static int zserv_process_messages(struct thread *thread)  int zserv_send_message(struct zserv *client, struct stream *msg)  { -	/* -	 * This is a somewhat poorly named variable added with Zebra's portion -	 * of the label manager. That component does not use the regular -	 * zserv/zapi_msg interface for handling its messages, as the client -	 * itself runs in-process. Instead it uses synchronous writes on the -	 * zserv client's socket directly in the zread* handlers for its -	 * message types. Furthermore, it cannot handle the usual messages -	 * Zebra sends (such as those for interface changes) and so has added -	 * this flag and check here as a hack to suppress all messages that it -	 * does not explicitly know about. -	 * -	 * In any case this needs to be cleaned up at some point. -	 * -	 * See also: -	 *    zread_label_manager_request -	 *    zsend_label_manager_connect_response -	 *    zsend_assign_label_chunk_response -	 *    ... -	 */ -	if (client->is_synchronous) -		return 0; -  	pthread_mutex_lock(&client->obuf_mtx);  	{  		stream_fifo_push(client->obuf_fifo, msg); @@ -710,9 +688,6 @@ static struct zserv *zserv_client_create(int sock)  	}  	client->ridinfo = vrf_bitmap_init(); -	/* by default, it's not a synchronous client */ -	client->is_synchronous = 0; -  	/* Add this client to linked list. */  	listnode_add(zrouter.client_list, client); diff --git a/zebra/zserv.h b/zebra/zserv.h index 34965618f2..708ff1e226 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -98,7 +98,6 @@ struct zserv {  	/* client's protocol */  	uint8_t proto;  	uint16_t instance; -	uint8_t is_synchronous;  	/* Statistics */  	uint32_t redist_v4_add_cnt;  | 
