diff options
| author | Igor Ryzhov <iryzhov@nfware.com> | 2024-03-15 00:52:18 +0200 | 
|---|---|---|
| committer | Igor Ryzhov <iryzhov@nfware.com> | 2024-03-15 00:58:10 +0200 | 
| commit | 84a00a47b833ab43ec1f02c3d8351df0d02e4d28 (patch) | |
| tree | dd18d3e1b23dd97344a69bfac585fc7b92834f9e /lib | |
| parent | 4b512f2f0768b7f832db1627f32dd07493a420a3 (diff) | |
*: remove confd plugin
ConfD is not supported anymore and its use is discouraged by developers:
https://discuss.tail-f.com/t/confd-premium-no-longer-available-future-of-confd/4552/6
Remove the code and all mentions of ConfD from the documentation.
Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/lib_errors.c | 18 | ||||
| -rw-r--r-- | lib/lib_errors.h | 3 | ||||
| -rw-r--r-- | lib/northbound.c | 2 | ||||
| -rw-r--r-- | lib/northbound.h | 6 | ||||
| -rw-r--r-- | lib/northbound_confd.c | 1494 | ||||
| -rw-r--r-- | lib/subdir.am | 12 | ||||
| -rw-r--r-- | lib/yang.h | 3 | 
7 files changed, 0 insertions, 1538 deletions
diff --git a/lib/lib_errors.c b/lib/lib_errors.c index a96fac9cd4..9d6c04325c 100644 --- a/lib/lib_errors.c +++ b/lib/lib_errors.c @@ -308,24 +308,6 @@ static struct log_ref ferr_lib_err[] = {  		.suggestion = "Check if the FRR libyang plugins were installed correctly in the system",  	},  	{ -		.code = EC_LIB_CONFD_INIT, -		.title = "ConfD initialization error", -		.description = "Upon startup FRR failed to properly initialize and startup the ConfD northbound plugin", -		.suggestion = "Check if ConfD is installed correctly in the system. Also, check if the confd daemon is running.", -	}, -	{ -		.code = EC_LIB_CONFD_DATA_CONVERT, -		.title = "ConfD data conversion error", -		.description = "An error has occurred while converting a ConfD data value (binary) to a string", -		.suggestion = "Open an Issue with all relevant log files and restart FRR" -	}, -	{ -		.code = EC_LIB_LIBCONFD, -		.title = "libconfd error", -		.description = "The northbound subsystem has detected that the libconfd library returned an error", -		.suggestion = "Open an Issue with all relevant log files and restart FRR" -	}, -	{  		.code = EC_LIB_SYSREPO_INIT,  		.title = "Sysrepo initialization error",  		.description = "Upon startup FRR failed to properly initialize and startup the Sysrepo northbound plugin", diff --git a/lib/lib_errors.h b/lib/lib_errors.h index 8cdfb166c7..9e0d539599 100644 --- a/lib/lib_errors.h +++ b/lib/lib_errors.h @@ -65,9 +65,6 @@ enum lib_log_refs {  	EC_LIB_NB_TRANSACTION_RECORD_FAILED,  	EC_LIB_LIBYANG,  	EC_LIB_LIBYANG_PLUGIN_LOAD, -	EC_LIB_CONFD_INIT, -	EC_LIB_CONFD_DATA_CONVERT, -	EC_LIB_LIBCONFD,  	EC_LIB_SYSREPO_INIT,  	EC_LIB_SYSREPO_DATA_CONVERT,  	EC_LIB_LIBSYSREPO, diff --git a/lib/northbound.c b/lib/northbound.c index 487f225913..11dca732ba 100644 --- a/lib/northbound.c +++ b/lib/northbound.c @@ -2403,8 +2403,6 @@ const char *nb_client_name(enum nb_client client)  	switch (client) {  	case NB_CLIENT_CLI:  		return "CLI"; -	case NB_CLIENT_CONFD: -		return "ConfD";  	case NB_CLIENT_SYSREPO:  		return "Sysrepo";  	case NB_CLIENT_GRPC: diff --git a/lib/northbound.h b/lib/northbound.h index 5be111cf0a..01e23c8160 100644 --- a/lib/northbound.h +++ b/lib/northbound.h @@ -621,11 +621,6 @@ struct nb_node {  	/* Flags. */  	uint8_t flags; - -#ifdef HAVE_CONFD -	/* ConfD hash value corresponding to this YANG path. */ -	int confd_hash; -#endif  };  /* The YANG container or list contains only config data. */  #define F_NB_NODE_CONFIG_ONLY 0x01 @@ -700,7 +695,6 @@ enum nb_error {  enum nb_client {  	NB_CLIENT_NONE = 0,  	NB_CLIENT_CLI, -	NB_CLIENT_CONFD,  	NB_CLIENT_SYSREPO,  	NB_CLIENT_GRPC,  	NB_CLIENT_PCEP, diff --git a/lib/northbound_confd.c b/lib/northbound_confd.c deleted file mode 100644 index 8503d18002..0000000000 --- a/lib/northbound_confd.c +++ /dev/null @@ -1,1494 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright (C) 2018  NetDEF, Inc. - *                     Renato Westphal - */ - -#include <zebra.h> - -#include "log.h" -#include "lib_errors.h" -#include "command.h" -#include "debug.h" -#include "libfrr.h" -#include "lib/version.h" -#include "northbound.h" - -#include <confd_lib.h> -#include <confd_cdb.h> -#include <confd_dp.h> -#include <confd_maapi.h> - -DEFINE_MTYPE_STATIC(LIB, CONFD, "ConfD module"); - -static struct debug nb_dbg_client_confd = {0, "Northbound client: ConfD"}; - -static struct event_loop *master; -static struct sockaddr confd_addr; -static int cdb_sub_sock, dp_ctl_sock, dp_worker_sock; -static struct event *t_cdb_sub, *t_dp_ctl, *t_dp_worker; -static struct confd_daemon_ctx *dctx; -static struct confd_notification_ctx *live_ctx; -static bool confd_connected; -static struct list *confd_spoints; -static struct nb_transaction *transaction; - -static void frr_confd_finish_cdb(void); -static void frr_confd_finish_dp(void); -static int frr_confd_finish(void); - -#define flog_err_confd(funcname)                                               \ -	flog_err(EC_LIB_LIBCONFD, "%s: %s() failed: %s (%d): %s", __func__,    \ -		 (funcname), confd_strerror(confd_errno), confd_errno,         \ -		 confd_lasterr()) - - -/* ------------ Utils ------------ */ - -/* Get XPath string from ConfD hashed keypath. */ -static void frr_confd_get_xpath(const confd_hkeypath_t *kp, char *xpath, -				size_t len) -{ -	char *p; - -	confd_xpath_pp_kpath(xpath, len, 0, kp); - -	/* -	 * Replace double quotes by single quotes (the format accepted by the -	 * northbound API). -	 */ -	p = xpath; -	while ((p = strchr(p, '"')) != NULL) -		*p++ = '\''; -} - -/* Convert ConfD binary value to a string. */ -static int frr_confd_val2str(const char *xpath, const confd_value_t *value, -			     char *string, size_t string_size) -{ -	struct confd_cs_node *csp; - -	csp = confd_cs_node_cd(NULL, xpath); -	if (!csp) { -		flog_err_confd("confd_cs_node_cd"); -		return -1; -	} -	if (confd_val2str(csp->info.type, value, string, string_size) -	    == CONFD_ERR) { -		flog_err_confd("confd_val2str"); -		return -1; -	} - -	return 0; -} - -/* Obtain list entry from ConfD hashed keypath. */ -static int frr_confd_hkeypath_get_list_entry(const confd_hkeypath_t *kp, -					     struct nb_node *nb_node, -					     const void **list_entry) -{ -	struct nb_node *nb_node_list; -	int parent_lists = 0; -	int curr_list = 0; - -	*list_entry = NULL; - -	/* -	 * Count the number of YANG lists in the path, disconsidering the -	 * last element. -	 */ -	nb_node_list = nb_node; -	while (nb_node_list->parent_list) { -		nb_node_list = nb_node_list->parent_list; -		parent_lists++; -	} -	if (nb_node->snode->nodetype != LYS_LIST && parent_lists == 0) -		return 0; - -	/* Start from the beginning and move down the tree. */ -	for (int i = kp->len; i >= 0; i--) { -		struct yang_list_keys keys; - -		/* Not a YANG list. */ -		if (kp->v[i][0].type != C_BUF) -			continue; - -		/* Obtain list keys. */ -		memset(&keys, 0, sizeof(keys)); -		for (int j = 0; kp->v[i][j].type != C_NOEXISTS; j++) { -			strlcpy(keys.key[keys.num], -				(char *)kp->v[i][j].val.buf.ptr, -				sizeof(keys.key[keys.num])); -			keys.num++; -		} - -		/* Obtain northbound node associated to the YANG list. */ -		nb_node_list = nb_node; -		for (int j = curr_list; j < parent_lists; j++) -			nb_node_list = nb_node_list->parent_list; - -		/* Obtain list entry. */ -		if (!CHECK_FLAG(nb_node_list->flags, F_NB_NODE_KEYLESS_LIST)) { -			*list_entry = nb_callback_lookup_entry( -				nb_node, *list_entry, &keys); -			if (*list_entry == NULL) -				return -1; -		} else { -			unsigned long ptr_ulong; - -			/* Retrieve list entry from pseudo-key (string). */ -			if (sscanf(keys.key[0], "%lu", &ptr_ulong) != 1) -				return -1; -			*list_entry = (const void *)ptr_ulong; -		} - -		curr_list++; -	} - -	return 0; -} - -/* Fill the current date and time into a confd_datetime structure. */ -static void getdatetime(struct confd_datetime *datetime) -{ -	struct tm tm; -	struct timeval tv; - -	gettimeofday(&tv, NULL); -	gmtime_r(&tv.tv_sec, &tm); - -	memset(datetime, 0, sizeof(*datetime)); -	datetime->year = 1900 + tm.tm_year; -	datetime->month = tm.tm_mon + 1; -	datetime->day = tm.tm_mday; -	datetime->sec = tm.tm_sec; -	datetime->micro = tv.tv_usec; -	datetime->timezone = 0; -	datetime->timezone_minutes = 0; -	datetime->hour = tm.tm_hour; -	datetime->min = tm.tm_min; -} - -/* ------------ CDB code ------------ */ - -struct cdb_iter_args { -	struct nb_config *candidate; -	bool error; -}; - -static enum cdb_iter_ret -frr_confd_cdb_diff_iter(confd_hkeypath_t *kp, enum cdb_iter_op cdb_op, -			confd_value_t *oldv, confd_value_t *newv, void *args) -{ -	char xpath[XPATH_MAXLEN]; -	struct nb_node *nb_node; -	enum nb_operation nb_op; -	struct cdb_iter_args *iter_args = args; -	char value_str[YANG_VALUE_MAXLEN]; -	struct yang_data *data; -	char *sb1, *sb2; -	int ret; - -	frr_confd_get_xpath(kp, xpath, sizeof(xpath)); - -	/* -	 * HACK: obtain value of leaf-list elements from the XPath due to -	 * a bug in the ConfD API. -	 */ -	value_str[0] = '\0'; -	sb1 = strrchr(xpath, '['); -	sb2 = strrchr(xpath, ']'); -	if (sb1 && sb2 && !strchr(sb1, '=')) { -		*sb2 = '\0'; -		strlcpy(value_str, sb1 + 1, sizeof(value_str)); -		*sb1 = '\0'; -	} - -	nb_node = nb_node_find(xpath); -	if (!nb_node) { -		flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH, -			  "%s: unknown data path: %s", __func__, xpath); -		iter_args->error = true; -		return ITER_STOP; -	} - -	/* Map operation values. */ -	switch (cdb_op) { -	case MOP_CREATED: -		nb_op = NB_OP_CREATE; -		break; -	case MOP_DELETED: -		nb_op = NB_OP_DESTROY; -		break; -	case MOP_VALUE_SET: -		if (nb_is_operation_allowed(nb_node, NB_OP_MODIFY)) -			nb_op = NB_OP_MODIFY; -		else -			/* Ignore list keys modifications. */ -			return ITER_RECURSE; -		break; -	case MOP_MOVED_AFTER: -		nb_op = NB_OP_MOVE; -		break; -	case MOP_MODIFIED: -		/* We're not interested on this. */ -		return ITER_RECURSE; -	default: -		flog_err(EC_LIB_DEVELOPMENT, -			 "%s: unexpected operation %u [xpath %s]", __func__, -			 cdb_op, xpath); -		iter_args->error = true; -		return ITER_STOP; -	} - -	/* Convert ConfD value to a string. */ -	if (nb_node->snode->nodetype != LYS_LEAFLIST && newv -	    && frr_confd_val2str(nb_node->xpath, newv, value_str, -				 sizeof(value_str)) -		       != 0) { -		flog_err(EC_LIB_CONFD_DATA_CONVERT, -			 "%s: failed to convert ConfD value to a string", -			 __func__); -		iter_args->error = true; -		return ITER_STOP; -	} - -	/* Edit the candidate configuration. */ -	data = yang_data_new(xpath, value_str); -	ret = nb_candidate_edit(iter_args->candidate, nb_node, nb_op, xpath, -				NULL, data); -	yang_data_free(data); -	if (ret != NB_OK) { -		flog_warn( -			EC_LIB_NB_CANDIDATE_EDIT_ERROR, -			"%s: failed to edit candidate configuration: operation [%s] xpath [%s]", -			__func__, nb_operation_name(nb_op), xpath); -		iter_args->error = true; -		return ITER_STOP; -	} - -	return ITER_RECURSE; -} - -static void frr_confd_cdb_read_cb_prepare(int fd, int *subp, int reslen) -{ -	struct nb_context context = {}; -	struct nb_config *candidate; -	struct cdb_iter_args iter_args; -	char errmsg[BUFSIZ] = {0}; -	int ret; - -	candidate = nb_config_dup(running_config); - -	/* Iterate over all configuration changes. */ -	iter_args.candidate = candidate; -	iter_args.error = false; -	for (int i = 0; i < reslen; i++) { -		if (cdb_diff_iterate(fd, subp[i], frr_confd_cdb_diff_iter, -				     ITER_WANT_PREV, &iter_args) -		    != CONFD_OK) { -			flog_err_confd("cdb_diff_iterate"); -		} -	} -	free(subp); - -	if (iter_args.error) { -		nb_config_free(candidate); - -		if (cdb_sub_abort_trans( -			    cdb_sub_sock, CONFD_ERRCODE_APPLICATION_INTERNAL, 0, -			    0, "Couldn't apply configuration changes") -		    != CONFD_OK) { -			flog_err_confd("cdb_sub_abort_trans"); -			return; -		} -		return; -	} - -	/* -	 * Validate the configuration changes and allocate all resources -	 * required to apply them. -	 */ -	transaction = NULL; -	context.client = NB_CLIENT_CONFD; -	ret = nb_candidate_commit_prepare(context, candidate, NULL, -					  &transaction, false, false, errmsg, -					  sizeof(errmsg)); -	if (ret != NB_OK && ret != NB_ERR_NO_CHANGES) { -		enum confd_errcode errcode; - -		switch (ret) { -		case NB_ERR_LOCKED: -			errcode = CONFD_ERRCODE_IN_USE; -			break; -		case NB_ERR_RESOURCE: -			errcode = CONFD_ERRCODE_RESOURCE_DENIED; -			break; -		default: -			errcode = CONFD_ERRCODE_APPLICATION; -			break; -		} - -		/* Reject the configuration changes. */ -		if (cdb_sub_abort_trans(cdb_sub_sock, errcode, 0, 0, "%s", -					errmsg) -		    != CONFD_OK) { -			flog_err_confd("cdb_sub_abort_trans"); -			return; -		} -	} else { -		/* Acknowledge the notification. */ -		if (cdb_sync_subscription_socket(fd, CDB_DONE_PRIORITY) -		    != CONFD_OK) { -			flog_err_confd("cdb_sync_subscription_socket"); -			return; -		} - -		/* No configuration changes. */ -		if (!transaction) -			nb_config_free(candidate); -	} -} - -static void frr_confd_cdb_read_cb_commit(int fd, int *subp, int reslen) -{ -	/* -	 * No need to process the configuration changes again as we're already -	 * keeping track of them in the "transaction" variable. -	 */ -	free(subp); - -	/* Apply the transaction. */ -	if (transaction) { -		struct nb_config *candidate = transaction->config; -		char errmsg[BUFSIZ] = {0}; - -		nb_candidate_commit_apply(transaction, true, NULL, errmsg, -					  sizeof(errmsg)); -		nb_config_free(candidate); -	} - -	/* Acknowledge the notification. */ -	if (cdb_sync_subscription_socket(fd, CDB_DONE_PRIORITY) != CONFD_OK) { -		flog_err_confd("cdb_sync_subscription_socket"); -		return; -	} -} - -static int frr_confd_cdb_read_cb_abort(int fd, int *subp, int reslen) -{ -	/* -	 * No need to process the configuration changes again as we're already -	 * keeping track of them in the "transaction" variable. -	 */ -	free(subp); - -	/* Abort the transaction. */ -	if (transaction) { -		struct nb_config *candidate = transaction->config; -		char errmsg[BUFSIZ] = {0}; - -		nb_candidate_commit_abort(transaction, errmsg, sizeof(errmsg)); -		nb_config_free(candidate); -	} - -	/* Acknowledge the notification. */ -	if (cdb_sync_subscription_socket(fd, CDB_DONE_PRIORITY) != CONFD_OK) { -		flog_err_confd("cdb_sync_subscription_socket"); -		return -1; -	} - -	return 0; -} - -static void frr_confd_cdb_read_cb(struct event *thread) -{ -	int fd = EVENT_FD(thread); -	enum cdb_sub_notification cdb_ev; -	int flags; -	int *subp = NULL; -	int reslen = 0; - -	event_add_read(master, frr_confd_cdb_read_cb, NULL, fd, &t_cdb_sub); - -	if (cdb_read_subscription_socket2(fd, &cdb_ev, &flags, &subp, &reslen) -	    != CONFD_OK) { -		flog_err_confd("cdb_read_subscription_socket2"); -		return; -	} - -	switch (cdb_ev) { -	case CDB_SUB_PREPARE: -		frr_confd_cdb_read_cb_prepare(fd, subp, reslen); -		break; -	case CDB_SUB_COMMIT: -		frr_confd_cdb_read_cb_commit(fd, subp, reslen); -		break; -	case CDB_SUB_ABORT: -		frr_confd_cdb_read_cb_abort(fd, subp, reslen); -		break; -	default: -		flog_err_confd("unknown CDB event"); -		break; -	} -} - -/* Trigger CDB subscriptions to read the startup configuration. */ -static void *thread_cdb_trigger_subscriptions(void *data) -{ -	int sock; -	int *sub_points = NULL, len = 0; -	struct listnode *node; -	int *spoint; -	int i = 0; - -	/* Create CDB data socket. */ -	sock = socket(PF_INET, SOCK_STREAM, 0); -	if (sock < 0) { -		flog_err(EC_LIB_SOCKET, "%s: failed to create socket: %s", -			 __func__, safe_strerror(errno)); -		return NULL; -	} - -	if (cdb_connect(sock, CDB_DATA_SOCKET, &confd_addr, -			sizeof(struct sockaddr_in)) -	    != CONFD_OK) { -		flog_err_confd("cdb_connect"); -		return NULL; -	} - -	/* -	 * Fill array containing the subscription point of all loaded YANG -	 * modules. -	 */ -	len = listcount(confd_spoints); -	sub_points = XCALLOC(MTYPE_CONFD, len * sizeof(int)); -	for (ALL_LIST_ELEMENTS_RO(confd_spoints, node, spoint)) -		sub_points[i++] = *spoint; - -	if (cdb_trigger_subscriptions(sock, sub_points, len) != CONFD_OK) { -		flog_err_confd("cdb_trigger_subscriptions"); -		return NULL; -	} - -	/* Cleanup and exit thread. */ -	XFREE(MTYPE_CONFD, sub_points); -	cdb_close(sock); - -	return NULL; -} - -static int frr_confd_subscribe(const struct lysc_node *snode, void *arg) -{ -	struct yang_module *module = arg; -	struct nb_node *nb_node; -	int *spoint; -	int ret; - -	switch (snode->nodetype) { -	case LYS_CONTAINER: -	case LYS_LEAF: -	case LYS_LEAFLIST: -	case LYS_LIST: -		break; -	default: -		return YANG_ITER_CONTINUE; -	} - -	if (CHECK_FLAG(snode->flags, LYS_CONFIG_R)) -		return YANG_ITER_CONTINUE; - -	nb_node = snode->priv; -	if (!nb_node) -		return YANG_ITER_CONTINUE; - -	DEBUGD(&nb_dbg_client_confd, "%s: subscribing to '%s'", __func__, -	       nb_node->xpath); - -	spoint = XMALLOC(MTYPE_CONFD, sizeof(*spoint)); -	ret = cdb_subscribe2(cdb_sub_sock, CDB_SUB_RUNNING_TWOPHASE, -			     CDB_SUB_WANT_ABORT_ON_ABORT, 3, spoint, -			     module->confd_hash, nb_node->xpath); -	if (ret != CONFD_OK) { -		flog_err_confd("cdb_subscribe2"); -		XFREE(MTYPE_CONFD, spoint); -		return YANG_ITER_CONTINUE; -	} - -	listnode_add(confd_spoints, spoint); -	return YANG_ITER_CONTINUE; -} - -static int frr_confd_init_cdb(void) -{ -	struct yang_module *module; -	pthread_t cdb_trigger_thread; - -	/* Create CDB subscription socket. */ -	cdb_sub_sock = socket(PF_INET, SOCK_STREAM, 0); -	if (cdb_sub_sock < 0) { -		flog_err(EC_LIB_SOCKET, "%s: failed to create socket: %s", -			 __func__, safe_strerror(errno)); -		return -1; -	} - -	if (cdb_connect(cdb_sub_sock, CDB_SUBSCRIPTION_SOCKET, &confd_addr, -			sizeof(struct sockaddr_in)) -	    != CONFD_OK) { -		flog_err_confd("cdb_connect"); -		goto error; -	} - -	/* Subscribe to all loaded YANG data modules. */ -	confd_spoints = list_new(); -	RB_FOREACH (module, yang_modules, &yang_modules) { -		module->confd_hash = confd_str2hash(module->info->ns); -		if (module->confd_hash == 0) { -			flog_err( -				EC_LIB_LIBCONFD, -				"%s: failed to find hash value for namespace %s", -				__func__, module->info->ns); -			goto error; -		} - -		/* -		 * The CDB API doesn't provide a mechanism to subscribe to an -		 * entire YANG module. So we have to find the top level -		 * nodes ourselves and subscribe to their paths. -		 */ -		yang_snodes_iterate(module->info, frr_confd_subscribe, 0, -				    module); -	} - -	if (cdb_subscribe_done(cdb_sub_sock) != CONFD_OK) { -		flog_err_confd("cdb_subscribe_done"); -		goto error; -	} - -	/* Create short lived pthread to trigger the CDB subscriptions. */ -	if (pthread_create(&cdb_trigger_thread, NULL, -			   thread_cdb_trigger_subscriptions, NULL)) { -		flog_err(EC_LIB_SYSTEM_CALL, "%s: error creating pthread: %s", -			 __func__, safe_strerror(errno)); -		goto error; -	} -	pthread_detach(cdb_trigger_thread); - -	event_add_read(master, frr_confd_cdb_read_cb, NULL, cdb_sub_sock, -		       &t_cdb_sub); - -	return 0; - -error: -	frr_confd_finish_cdb(); - -	return -1; -} - -static void frr_confd_finish_cdb(void) -{ -	if (cdb_sub_sock > 0) { -		EVENT_OFF(t_cdb_sub); -		cdb_close(cdb_sub_sock); -	} -} - -/* ------------ DP code ------------ */ - -static int frr_confd_transaction_init(struct confd_trans_ctx *tctx) -{ -	confd_trans_set_fd(tctx, dp_worker_sock); - -	return CONFD_OK; -} - -#define CONFD_MAX_CHILD_NODES 32 - -static int frr_confd_data_get_elem(struct confd_trans_ctx *tctx, -				   confd_hkeypath_t *kp) -{ -	struct nb_node *nb_node; -	char xpath[XPATH_MAXLEN]; -	struct yang_data *data; -	confd_value_t v; -	const void *list_entry = NULL; - -	frr_confd_get_xpath(kp, xpath, sizeof(xpath)); - -	nb_node = nb_node_find(xpath); -	if (!nb_node) { -		flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH, -			  "%s: unknown data path: %s", __func__, xpath); -		confd_data_reply_not_found(tctx); -		return CONFD_OK; -	} - -	if (frr_confd_hkeypath_get_list_entry(kp, nb_node, &list_entry) != 0) { -		confd_data_reply_not_found(tctx); -		return CONFD_OK; -	} - -	data = nb_callback_get_elem(nb_node, xpath, list_entry); -	if (data) { -		if (data->value) { -			CONFD_SET_STR(&v, data->value); -			confd_data_reply_value(tctx, &v); -		} else -			confd_data_reply_found(tctx); -		yang_data_free(data); -	} else -		confd_data_reply_not_found(tctx); - -	return CONFD_OK; -} - -static int frr_confd_data_get_next(struct confd_trans_ctx *tctx, -				   confd_hkeypath_t *kp, long next) -{ -	struct nb_node *nb_node; -	char xpath[XPATH_MAXLEN]; -	struct yang_data *data; -	const void *parent_list_entry, *nb_next; -	confd_value_t v[LIST_MAXKEYS]; - -	frr_confd_get_xpath(kp, xpath, sizeof(xpath)); - -	nb_node = nb_node_find(xpath); -	if (!nb_node) { -		flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH, -			  "%s: unknown data path: %s", __func__, xpath); -		confd_data_reply_next_key(tctx, NULL, -1, -1); -		return CONFD_OK; -	} - -	if (frr_confd_hkeypath_get_list_entry(kp, nb_node, &parent_list_entry) -	    != 0) { -		/* List entry doesn't exist anymore. */ -		confd_data_reply_next_key(tctx, NULL, -1, -1); -		return CONFD_OK; -	} - -	nb_next = nb_callback_get_next(nb_node, parent_list_entry, -				       (next == -1) ? NULL : (void *)next); -	if (!nb_next) { -		/* End of the list or leaf-list. */ -		confd_data_reply_next_key(tctx, NULL, -1, -1); -		return CONFD_OK; -	} - -	switch (nb_node->snode->nodetype) { -	case LYS_LIST: -		if (!CHECK_FLAG(nb_node->flags, F_NB_NODE_KEYLESS_LIST)) { -			struct yang_list_keys keys; - -			memset(&keys, 0, sizeof(keys)); -			if (nb_callback_get_keys(nb_node, nb_next, &keys) -			    != NB_OK) { -				flog_warn(EC_LIB_NB_CB_STATE, -					  "%s: failed to get list keys", -					  __func__); -				confd_data_reply_next_key(tctx, NULL, -1, -1); -				return CONFD_OK; -			} - -			/* Feed keys to ConfD. */ -			for (size_t i = 0; i < keys.num; i++) -				CONFD_SET_STR(&v[i], keys.key[i]); -			confd_data_reply_next_key(tctx, v, keys.num, -						  (long)nb_next); -		} else { -			char pointer_str[32]; - -			/* -			 * ConfD 6.6 user guide, chapter 6.11 (Operational data -			 * lists without keys): -			 * "To support this without having completely separate -			 * APIs, we use a "pseudo" key in the ConfD APIs for -			 * this type of list. This key is not part of the data -			 * model, and completely hidden in the northbound agent -			 * interfaces, but is used with e.g. the get_next() and -			 * get_elem() callbacks as if it were a normal key. This -			 * "pseudo" key is always a single signed 64-bit -			 * integer, i.e. the confd_value_t type is C_INT64. The -			 * values can be chosen arbitrarily by the application, -			 * as long as a key value returned by get_next() can be -			 * used to get the data for the corresponding list entry -			 * with get_elem() or get_object() as usual. It could -			 * e.g. be an index into an array that holds the data, -			 * or even a memory address in integer form". -			 * -			 * Since we're using the CONFD_DAEMON_FLAG_STRINGSONLY -			 * option, we must convert our pseudo-key (a void -			 * pointer) to a string before sending it to confd. -			 */ -			snprintf(pointer_str, sizeof(pointer_str), "%lu", -				 (unsigned long)nb_next); -			CONFD_SET_STR(&v[0], pointer_str); -			confd_data_reply_next_key(tctx, v, 1, (long)nb_next); -		} -		break; -	case LYS_LEAFLIST: -		data = nb_callback_get_elem(nb_node, xpath, nb_next); -		if (data) { -			if (data->value) { -				CONFD_SET_STR(&v[0], data->value); -				confd_data_reply_next_key(tctx, v, 1, -							  (long)nb_next); -			} -			yang_data_free(data); -		} else -			confd_data_reply_next_key(tctx, NULL, -1, -1); -		break; -	default: -		break; -	} - -	return CONFD_OK; -} - -/* - * Optional callback - implemented for performance reasons. - */ -static int frr_confd_data_get_object(struct confd_trans_ctx *tctx, -				     confd_hkeypath_t *kp) -{ -	struct nb_node *nb_node; -	const struct lysc_node *child; -	char xpath[XPATH_MAXLEN]; -	char xpath_child[XPATH_MAXLEN * 2]; -	struct list *elements; -	struct yang_data *data; -	const void *list_entry; -	confd_value_t values[CONFD_MAX_CHILD_NODES]; -	size_t nvalues = 0; - -	frr_confd_get_xpath(kp, xpath, sizeof(xpath)); - -	nb_node = nb_node_find(xpath); -	if (!nb_node) { -		flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH, -			  "%s: unknown data path: %s", __func__, xpath); -		confd_data_reply_not_found(tctx); -		return CONFD_ERR; -	} - -	if (frr_confd_hkeypath_get_list_entry(kp, nb_node, &list_entry) != 0) { -		confd_data_reply_not_found(tctx); -		return CONFD_OK; -	} - -	elements = yang_data_list_new(); - -	/* Loop through list child nodes. */ -	LY_LIST_FOR (lysc_node_child(nb_node->snode), child) { -		struct nb_node *nb_node_child = child->priv; -		confd_value_t *v; - -		if (nvalues > CONFD_MAX_CHILD_NODES) -			break; - -		v = &values[nvalues++]; - -		/* Non-presence containers, lists and leaf-lists. */ -		if (!nb_node_child->cbs.get_elem) { -			CONFD_SET_NOEXISTS(v); -			continue; -		} - -		snprintf(xpath_child, sizeof(xpath_child), "%s/%s", xpath, -			 child->name); -		data = nb_callback_get_elem(nb_node_child, xpath_child, -					    list_entry); -		if (data) { -			if (data->value) -				CONFD_SET_STR(v, data->value); -			else { -				/* Presence containers and empty leafs. */ -				CONFD_SET_XMLTAG( -					v, nb_node_child->confd_hash, -					confd_str2hash(nb_node_child->snode -							       ->module->ns)); -			} -			listnode_add(elements, data); -		} else -			CONFD_SET_NOEXISTS(v); -	} - -	confd_data_reply_value_array(tctx, values, nvalues); - -	/* Release memory. */ -	list_delete(&elements); - -	return CONFD_OK; -} - -/* - * Optional callback - implemented for performance reasons. - */ -static int frr_confd_data_get_next_object(struct confd_trans_ctx *tctx, -					  confd_hkeypath_t *kp, long next) -{ -	char xpath[XPATH_MAXLEN]; -	struct nb_node *nb_node; -	struct list *elements; -	const void *parent_list_entry; -	const void *nb_next; -#define CONFD_OBJECTS_PER_TIME 100 -	struct confd_next_object objects[CONFD_OBJECTS_PER_TIME + 1]; -	char pseudo_keys[CONFD_OBJECTS_PER_TIME][32]; -	int nobjects = 0; - -	frr_confd_get_xpath(kp, xpath, sizeof(xpath)); - -	nb_node = nb_node_find(xpath); -	if (!nb_node) { -		flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH, -			  "%s: unknown data path: %s", __func__, xpath); -		confd_data_reply_next_object_array(tctx, NULL, 0, 0); -		return CONFD_OK; -	} - -	if (frr_confd_hkeypath_get_list_entry(kp, nb_node, &parent_list_entry) -	    != 0) { -		confd_data_reply_next_object_array(tctx, NULL, 0, 0); -		return CONFD_OK; -	} - -	elements = yang_data_list_new(); -	nb_next = (next == -1) ? NULL : (void *)next; - -	memset(objects, 0, sizeof(objects)); -	for (int j = 0; j < CONFD_OBJECTS_PER_TIME; j++) { -		struct confd_next_object *object; -		const struct lysc_node *child; -		struct yang_data *data; -		size_t nvalues = 0; - -		object = &objects[j]; - -		nb_next = nb_callback_get_next(nb_node, parent_list_entry, -					       nb_next); -		if (!nb_next) -			/* End of the list. */ -			break; - -		object->next = (long)nb_next; - -		/* Leaf-lists require special handling. */ -		if (nb_node->snode->nodetype == LYS_LEAFLIST) { -			object->v = XMALLOC(MTYPE_CONFD, sizeof(confd_value_t)); -			data = nb_callback_get_elem(nb_node, xpath, nb_next); -			assert(data && data->value); -			CONFD_SET_STR(object->v, data->value); -			nvalues++; -			listnode_add(elements, data); -			goto next; -		} - -		object->v = -			XMALLOC(MTYPE_CONFD, -				CONFD_MAX_CHILD_NODES * sizeof(confd_value_t)); - -		/* -		 * ConfD 6.6 user guide, chapter 6.11 (Operational data lists -		 * without keys): -		 * "In the response to the get_next_object() callback, the data -		 * provider is expected to provide the key values along with the -		 * other leafs in an array that is populated according to the -		 * data model. This must be done also for this type of list, -		 * even though the key isn't actually in the data model. The -		 * "pseudo" key must always be the first element in the array". -		 */ -		if (CHECK_FLAG(nb_node->flags, F_NB_NODE_KEYLESS_LIST)) { -			confd_value_t *v; - -			snprintf(pseudo_keys[j], sizeof(pseudo_keys[j]), "%lu", -				 (unsigned long)nb_next); - -			v = &object->v[nvalues++]; -			CONFD_SET_STR(v, pseudo_keys[j]); -		} - -		/* Loop through list child nodes. */ -		LY_LIST_FOR (lysc_node_child(nb_node->snode), child) { -			struct nb_node *nb_node_child = child->priv; -			char xpath_child[XPATH_MAXLEN * 2]; -			confd_value_t *v; - -			if (nvalues > CONFD_MAX_CHILD_NODES) -				break; - -			v = &object->v[nvalues++]; - -			/* Non-presence containers, lists and leaf-lists. */ -			if (!nb_node_child->cbs.get_elem) { -				CONFD_SET_NOEXISTS(v); -				continue; -			} - -			snprintf(xpath_child, sizeof(xpath_child), "%s/%s", -				 xpath, child->name); -			data = nb_callback_get_elem(nb_node_child, xpath_child, -						    nb_next); -			if (data) { -				if (data->value) -					CONFD_SET_STR(v, data->value); -				else { -					/* -					 * Presence containers and empty leafs. -					 */ -					CONFD_SET_XMLTAG( -						v, nb_node_child->confd_hash, -						confd_str2hash( -							nb_node_child->snode -								->module->ns)); -				} -				listnode_add(elements, data); -			} else -				CONFD_SET_NOEXISTS(v); -		} -	next: -		object->n = nvalues; -		nobjects++; -	} - -	if (nobjects == 0) { -		confd_data_reply_next_object_array(tctx, NULL, 0, 0); -		list_delete(&elements); -		return CONFD_OK; -	} - -	/* Detect end of the list. */ -	if (!nb_next) { -		nobjects++; -		objects[nobjects].v = NULL; -	} - -	/* Reply to ConfD. */ -	confd_data_reply_next_object_arrays(tctx, objects, nobjects, 0); -	if (!nb_next) -		nobjects--; - -	/* Release memory. */ -	list_delete(&elements); -	for (int j = 0; j < nobjects; j++) { -		struct confd_next_object *object; - -		object = &objects[j]; -		XFREE(MTYPE_CONFD, object->v); -	} - -	return CONFD_OK; -} - -static int frr_confd_notification_send(const char *xpath, -				       struct list *arguments) -{ -	struct nb_node *nb_node; -	struct yang_module *module; -	struct confd_datetime now; -	confd_tag_value_t *values; -	int nvalues; -	int i = 0; -	struct yang_data *data; -	struct listnode *node; -	int ret; - -	nb_node = nb_node_find(xpath); -	if (!nb_node) { -		flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH, -			  "%s: unknown data path: %s", __func__, xpath); -		return -1; -	} -	module = yang_module_find(nb_node->snode->module->name); -	assert(module); - -	nvalues = 2; -	if (arguments) -		nvalues += listcount(arguments); - -	values = XMALLOC(MTYPE_CONFD, nvalues * sizeof(*values)); - -	CONFD_SET_TAG_XMLBEGIN(&values[i++], nb_node->confd_hash, -			       module->confd_hash); -	for (ALL_LIST_ELEMENTS_RO(arguments, node, data)) { -		struct nb_node *nb_node_arg; - -		nb_node_arg = nb_node_find(data->xpath); -		if (!nb_node_arg) { -			flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH, -				  "%s: unknown data path: %s", __func__, -				  data->xpath); -			XFREE(MTYPE_CONFD, values); -			return NB_ERR; -		} - -		CONFD_SET_TAG_STR(&values[i++], nb_node_arg->confd_hash, -				  data->value); -	} -	CONFD_SET_TAG_XMLEND(&values[i++], nb_node->confd_hash, -			     module->confd_hash); - -	getdatetime(&now); -	ret = confd_notification_send(live_ctx, &now, values, nvalues); - -	/* Release memory. */ -	XFREE(MTYPE_CONFD, values); - -	/* Map ConfD return code to northbound return code. */ -	switch (ret) { -	case CONFD_OK: -		return NB_OK; -	default: -		return NB_ERR; -	} -} - -static int frr_confd_action_init(struct confd_user_info *uinfo) -{ -	confd_action_set_fd(uinfo, dp_worker_sock); - -	return CONFD_OK; -} - -static int frr_confd_action_execute(struct confd_user_info *uinfo, -				    struct xml_tag *name, confd_hkeypath_t *kp, -				    confd_tag_value_t *params, int nparams) -{ -	char xpath[XPATH_MAXLEN]; -	struct nb_node *nb_node; -	struct list *input; -	struct list *output; -	struct yang_data *data; -	confd_tag_value_t *reply; -	int ret = CONFD_OK; -	char errmsg[BUFSIZ] = {0}; - -	/* Getting the XPath is tricky. */ -	if (kp) { -		/* This is a YANG RPC. */ -		frr_confd_get_xpath(kp, xpath, sizeof(xpath)); -		strlcat(xpath, "/", sizeof(xpath)); -		strlcat(xpath, confd_hash2str(name->tag), sizeof(xpath)); -	} else { -		/* This is a YANG action. */ -		snprintf(xpath, sizeof(xpath), "/%s:%s", -			 confd_ns2prefix(name->ns), confd_hash2str(name->tag)); -	} - -	nb_node = nb_node_find(xpath); -	if (!nb_node) { -		flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH, -			  "%s: unknown data path: %s", __func__, xpath); -		return CONFD_ERR; -	} - -	input = yang_data_list_new(); -	output = yang_data_list_new(); - -	/* Process input nodes. */ -	for (int i = 0; i < nparams; i++) { -		char xpath_input[XPATH_MAXLEN * 2]; -		char value_str[YANG_VALUE_MAXLEN]; - -		snprintf(xpath_input, sizeof(xpath_input), "%s/%s", xpath, -			 confd_hash2str(params[i].tag.tag)); - -		if (frr_confd_val2str(xpath_input, ¶ms[i].v, value_str, -				      sizeof(value_str)) -		    != 0) { -			flog_err( -				EC_LIB_CONFD_DATA_CONVERT, -				"%s: failed to convert ConfD value to a string", -				__func__); -			ret = CONFD_ERR; -			goto exit; -		} - -		data = yang_data_new(xpath_input, value_str); -		listnode_add(input, data); -	} - -	/* Execute callback registered for this XPath. */ -	if (nb_callback_rpc(nb_node, xpath, input, output, errmsg, -			    sizeof(errmsg)) -	    != NB_OK) { -		flog_warn(EC_LIB_NB_CB_RPC, "%s: rpc callback failed: %s", -			  __func__, xpath); -		ret = CONFD_ERR; -		goto exit; -	} - -	/* Process output nodes. */ -	if (listcount(output) > 0) { -		struct listnode *node; -		int i = 0; - -		reply = XMALLOC(MTYPE_CONFD, -				listcount(output) * sizeof(*reply)); - -		for (ALL_LIST_ELEMENTS_RO(output, node, data)) { -			struct nb_node *nb_node_output; -			int hash; - -			nb_node_output = nb_node_find(data->xpath); -			if (!nb_node_output) { -				flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH, -					  "%s: unknown data path: %s", __func__, -					  data->xpath); -				goto exit; -			} - -			hash = confd_str2hash(nb_node_output->snode->name); -			CONFD_SET_TAG_STR(&reply[i++], hash, data->value); -		} -		confd_action_reply_values(uinfo, reply, listcount(output)); -		XFREE(MTYPE_CONFD, reply); -	} - -exit: -	/* Release memory. */ -	list_delete(&input); -	list_delete(&output); - -	return ret; -} - - -static int frr_confd_dp_read(struct confd_daemon_ctx *dctx, int fd) -{ -	int ret; - -	ret = confd_fd_ready(dctx, fd); -	if (ret == CONFD_EOF) { -		flog_err_confd("confd_fd_ready"); -		frr_confd_finish(); -		return -1; -	} else if (ret == CONFD_ERR && confd_errno != CONFD_ERR_EXTERNAL) { -		flog_err_confd("confd_fd_ready"); -		frr_confd_finish(); -		return -1; -	} - -	return 0; -} - -static void frr_confd_dp_ctl_read(struct event *thread) -{ -	struct confd_daemon_ctx *dctx = EVENT_ARG(thread); -	int fd = EVENT_FD(thread); - -	event_add_read(master, frr_confd_dp_ctl_read, dctx, fd, &t_dp_ctl); - -	frr_confd_dp_read(dctx, fd); -} - -static void frr_confd_dp_worker_read(struct event *thread) -{ -	struct confd_daemon_ctx *dctx = EVENT_ARG(thread); -	int fd = EVENT_FD(thread); - -	event_add_read(master, frr_confd_dp_worker_read, dctx, fd, -		       &t_dp_worker); - -	frr_confd_dp_read(dctx, fd); -} - -static int frr_confd_subscribe_state(const struct lysc_node *snode, void *arg) -{ -	struct nb_node *nb_node = snode->priv; -	struct confd_data_cbs *data_cbs = arg; - -	if (!nb_node || !CHECK_FLAG(snode->flags, LYS_CONFIG_R)) -		return YANG_ITER_CONTINUE; -	/* We only need to subscribe to the root of the state subtrees. */ -	if (snode->parent && CHECK_FLAG(snode->parent->flags, LYS_CONFIG_R)) -		return YANG_ITER_CONTINUE; - -	DEBUGD(&nb_dbg_client_confd, -	       "%s: providing data to '%s' (callpoint %s)", __func__, -	       nb_node->xpath, snode->name); - -	strlcpy(data_cbs->callpoint, snode->name, sizeof(data_cbs->callpoint)); -	if (confd_register_data_cb(dctx, data_cbs) != CONFD_OK) -		flog_err_confd("confd_register_data_cb"); - -	return YANG_ITER_CONTINUE; -} - -static int frr_confd_init_dp(const char *program_name) -{ -	struct confd_trans_cbs trans_cbs; -	struct confd_data_cbs data_cbs; -	struct confd_notification_stream_cbs ncbs; -	struct confd_action_cbs acbs; - -	/* Initialize daemon context. */ -	dctx = confd_init_daemon(program_name); -	if (!dctx) { -		flog_err_confd("confd_init_daemon"); -		goto error; -	} - -	/* -	 * Inform we want to receive YANG values as raw strings, and that we -	 * want to provide only strings in the reply functions, regardless of -	 * the YANG type. -	 */ -	confd_set_daemon_flags(dctx, CONFD_DAEMON_FLAG_STRINGSONLY); - -	/* Establish a control socket. */ -	dp_ctl_sock = socket(PF_INET, SOCK_STREAM, 0); -	if (dp_ctl_sock < 0) { -		flog_err(EC_LIB_SOCKET, "%s: failed to create socket: %s", -			 __func__, safe_strerror(errno)); -		goto error; -	} - -	if (confd_connect(dctx, dp_ctl_sock, CONTROL_SOCKET, &confd_addr, -			  sizeof(struct sockaddr_in)) -	    != CONFD_OK) { -		flog_err_confd("confd_connect"); -		goto error; -	} - -	/* -	 * Establish a worker socket (only one since this plugin runs on a -	 * single thread). -	 */ -	dp_worker_sock = socket(PF_INET, SOCK_STREAM, 0); -	if (dp_worker_sock < 0) { -		flog_err(EC_LIB_SOCKET, "%s: failed to create socket: %s", -			 __func__, safe_strerror(errno)); -		goto error; -	} -	if (confd_connect(dctx, dp_worker_sock, WORKER_SOCKET, &confd_addr, -			  sizeof(struct sockaddr_in)) -	    != CONFD_OK) { -		flog_err_confd("confd_connect"); -		goto error; -	} - -	/* Register transaction callback functions. */ -	memset(&trans_cbs, 0, sizeof(trans_cbs)); -	trans_cbs.init = frr_confd_transaction_init; -	confd_register_trans_cb(dctx, &trans_cbs); - -	/* Register our read/write callbacks. */ -	memset(&data_cbs, 0, sizeof(data_cbs)); -	data_cbs.get_elem = frr_confd_data_get_elem; -	data_cbs.exists_optional = frr_confd_data_get_elem; -	data_cbs.get_next = frr_confd_data_get_next; -	data_cbs.get_object = frr_confd_data_get_object; -	data_cbs.get_next_object = frr_confd_data_get_next_object; - -	/* -	 * Iterate over all loaded YANG modules and subscribe to the paths -	 * referent to state data. -	 */ -	yang_snodes_iterate(NULL, frr_confd_subscribe_state, 0, &data_cbs); - -	/* Register notification stream. */ -	memset(&ncbs, 0, sizeof(ncbs)); -	ncbs.fd = dp_worker_sock; -	/* -	 * RFC 5277 - Section 3.2.3: -	 * A NETCONF server implementation supporting the notification -	 * capability MUST support the "NETCONF" notification event -	 * stream. This stream contains all NETCONF XML event notifications -	 * supported by the NETCONF server. -	 */ -	strlcpy(ncbs.streamname, "NETCONF", sizeof(ncbs.streamname)); -	if (confd_register_notification_stream(dctx, &ncbs, &live_ctx) -	    != CONFD_OK) { -		flog_err_confd("confd_register_notification_stream"); -		goto error; -	} - -	/* Register the action handler callback. */ -	memset(&acbs, 0, sizeof(acbs)); -	strlcpy(acbs.actionpoint, "actionpoint", sizeof(acbs.actionpoint)); -	acbs.init = frr_confd_action_init; -	acbs.action = frr_confd_action_execute; -	if (confd_register_action_cbs(dctx, &acbs) != CONFD_OK) { -		flog_err_confd("confd_register_action_cbs"); -		goto error; -	} - -	/* Notify we registered all callbacks we wanted. */ -	if (confd_register_done(dctx) != CONFD_OK) { -		flog_err_confd("confd_register_done"); -		goto error; -	} - -	event_add_read(master, frr_confd_dp_ctl_read, dctx, dp_ctl_sock, -		       &t_dp_ctl); -	event_add_read(master, frr_confd_dp_worker_read, dctx, dp_worker_sock, -		       &t_dp_worker); - -	return 0; - -error: -	frr_confd_finish_dp(); - -	return -1; -} - -static void frr_confd_finish_dp(void) -{ -	if (dp_worker_sock > 0) { -		EVENT_OFF(t_dp_worker); -		close(dp_worker_sock); -	} -	if (dp_ctl_sock > 0) { -		EVENT_OFF(t_dp_ctl); -		close(dp_ctl_sock); -	} -	if (dctx != NULL) -		confd_release_daemon(dctx); -} - -/* ------------ CLI ------------ */ - -DEFUN (debug_nb_confd, -       debug_nb_confd_cmd, -       "[no] debug northbound client confd", -       NO_STR -       DEBUG_STR -       "Northbound debugging\n" -       "Client\n" -       "ConfD\n") -{ -	uint32_t mode = DEBUG_NODE2MODE(vty->node); -	bool no = strmatch(argv[0]->text, "no"); - -	DEBUG_MODE_SET(&nb_dbg_client_confd, mode, !no); - -	return CMD_SUCCESS; -} - -static int frr_confd_debug_config_write(struct vty *vty) -{ -	if (DEBUG_MODE_CHECK(&nb_dbg_client_confd, DEBUG_MODE_CONF)) -		vty_out(vty, "debug northbound client confd\n"); - -	return 0; -} - -static int frr_confd_debug_set_all(uint32_t flags, bool set) -{ -	DEBUG_FLAGS_SET(&nb_dbg_client_confd, flags, set); - -	/* If all modes have been turned off, don't preserve options. */ -	if (!DEBUG_MODE_CHECK(&nb_dbg_client_confd, DEBUG_MODE_ALL)) -		DEBUG_CLEAR(&nb_dbg_client_confd); - -	return 0; -} - -static void frr_confd_cli_init(void) -{ -	hook_register(nb_client_debug_config_write, -		      frr_confd_debug_config_write); -	hook_register(nb_client_debug_set_all, frr_confd_debug_set_all); - -	install_element(ENABLE_NODE, &debug_nb_confd_cmd); -	install_element(CONFIG_NODE, &debug_nb_confd_cmd); -} - -/* ------------ Main ------------ */ - -static int frr_confd_calculate_snode_hash(const struct lysc_node *snode, -					  void *arg) -{ -	struct nb_node *nb_node = snode->priv; - -	if (nb_node) -		nb_node->confd_hash = confd_str2hash(snode->name); - -	return YANG_ITER_CONTINUE; -} - -static int frr_confd_init(const char *program_name) -{ -	struct sockaddr_in *confd_addr4 = (struct sockaddr_in *)&confd_addr; -	int debuglevel = CONFD_SILENT; -	int ret = -1; - -	/* Initialize ConfD library. */ -	confd_init(program_name, stderr, debuglevel); - -	confd_addr4->sin_family = AF_INET; -	confd_addr4->sin_addr.s_addr = inet_addr("127.0.0.1"); -	confd_addr4->sin_port = htons(CONFD_PORT); -	if (confd_load_schemas(&confd_addr, sizeof(struct sockaddr_in)) -	    != CONFD_OK) { -		flog_err_confd("confd_load_schemas"); -		return -1; -	} - -	ret = frr_confd_init_cdb(); -	if (ret != 0) -		goto error; - -	ret = frr_confd_init_dp(program_name); -	if (ret != 0) { -		frr_confd_finish_cdb(); -		goto error; -	} - -	yang_snodes_iterate(NULL, frr_confd_calculate_snode_hash, 0, NULL); - -	hook_register(nb_notification_send, frr_confd_notification_send); - -	confd_connected = true; -	return 0; - -error: -	confd_free_schemas(); - -	return ret; -} - -static int frr_confd_finish(void) -{ -	if (!confd_connected) -		return 0; - -	frr_confd_finish_cdb(); -	frr_confd_finish_dp(); - -	confd_free_schemas(); - -	confd_connected = false; - -	return 0; -} - -static int frr_confd_module_late_init(struct event_loop *tm) -{ -	master = tm; - -	if (frr_confd_init(frr_get_progname()) < 0) { -		flog_err(EC_LIB_CONFD_INIT, -			 "failed to initialize the ConfD module"); -		return -1; -	} - -	hook_register(frr_fini, frr_confd_finish); -	frr_confd_cli_init(); - -	return 0; -} - -static int frr_confd_module_init(void) -{ -	hook_register(frr_late_init, frr_confd_module_late_init); - -	return 0; -} - -FRR_MODULE_SETUP(.name = "frr_confd", .version = FRR_VERSION, -		 .description = "FRR ConfD integration module", -		 .init = frr_confd_module_init, -); diff --git a/lib/subdir.am b/lib/subdir.am index c621ad0658..5ec6adf4c0 100644 --- a/lib/subdir.am +++ b/lib/subdir.am @@ -410,18 +410,6 @@ lib_libfrrzmq_la_SOURCES = \  	#end  # -# Tail-f's ConfD support -# -if CONFD -module_LTLIBRARIES += lib/confd.la -endif - -lib_confd_la_CFLAGS = $(AM_CFLAGS) $(CONFD_CFLAGS) -lib_confd_la_LDFLAGS = $(MODULE_LDFLAGS) -lib_confd_la_LIBADD = lib/libfrr.la $(CONFD_LIBS) -lib_confd_la_SOURCES = lib/northbound_confd.c - -#  # Sysrepo support  #  if SYSREPO diff --git a/lib/yang.h b/lib/yang.h index 65f6a73e0b..85be38bf81 100644 --- a/lib/yang.h +++ b/lib/yang.h @@ -45,9 +45,6 @@ struct yang_module {  	RB_ENTRY(yang_module) entry;  	const char *name;  	const struct lys_module *info; -#ifdef HAVE_CONFD -	int confd_hash; -#endif  #ifdef HAVE_SYSREPO  	sr_subscription_ctx_t *sr_subscription;  	struct event *sr_thread;  | 
