mirror of
				https://git.proxmox.com/git/mirror_frr
				synced 2025-11-03 23:47:16 +00:00 
			
		
		
		
	Merge pull request #3377 from opensourcerouting/northbound-improvements
northbound: API improvements + minor fixes
This commit is contained in:
		
						commit
						fe0c5ed4a0
					
				@ -1627,7 +1627,7 @@ dnl ---------------
 | 
			
		||||
dnl confd
 | 
			
		||||
dnl ---------------
 | 
			
		||||
if test "$enable_confd" != "" -a "$enable_confd" != "no"; then
 | 
			
		||||
   AC_CHECK_PROG([CONFD], [confd], [confd], [/bin/false])
 | 
			
		||||
   AC_CHECK_PROG([CONFD], [confd], [confd], [/bin/false], "${enable_confd}/bin")
 | 
			
		||||
   if test "x$CONFD" = "x/bin/false"; then
 | 
			
		||||
      AC_MSG_ERROR([confd was not found on your system.])]
 | 
			
		||||
   fi
 | 
			
		||||
 | 
			
		||||
@ -1051,8 +1051,13 @@ static int cmd_execute_command_real(vector vline, enum filter_type filter,
 | 
			
		||||
	int ret;
 | 
			
		||||
	if (matched_element->daemon)
 | 
			
		||||
		ret = CMD_SUCCESS_DAEMON;
 | 
			
		||||
	else
 | 
			
		||||
	else {
 | 
			
		||||
		/* Clear enqueued configuration changes. */
 | 
			
		||||
		vty->num_cfg_changes = 0;
 | 
			
		||||
		memset(&vty->cfg_changes, 0, sizeof(vty->cfg_changes));
 | 
			
		||||
 | 
			
		||||
		ret = matched_element->func(matched_element, vty, argc, argv);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// delete list and cmd_token's in it
 | 
			
		||||
	list_delete(&argv_list);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										50
									
								
								lib/if.c
									
									
									
									
									
								
							
							
						
						
									
										50
									
								
								lib/if.c
									
									
									
									
									
								
							@ -1086,12 +1086,6 @@ DEFPY_NOSH (interface,
 | 
			
		||||
       VRF_CMD_HELP_STR)
 | 
			
		||||
{
 | 
			
		||||
	char xpath_list[XPATH_MAXLEN];
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = ".",
 | 
			
		||||
			.operation = NB_OP_CREATE,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	vrf_id_t vrf_id;
 | 
			
		||||
	struct interface *ifp;
 | 
			
		||||
	int ret;
 | 
			
		||||
@ -1136,7 +1130,8 @@ DEFPY_NOSH (interface,
 | 
			
		||||
		 "/frr-interface:lib/interface[name='%s'][vrf='%s']", ifname,
 | 
			
		||||
		 vrfname);
 | 
			
		||||
 | 
			
		||||
	ret = nb_cli_cfg_change(vty, xpath_list, changes, array_size(changes));
 | 
			
		||||
	nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
 | 
			
		||||
	ret = nb_cli_apply_changes(vty, xpath_list);
 | 
			
		||||
	if (ret == CMD_SUCCESS) {
 | 
			
		||||
		VTY_PUSH_XPATH(INTERFACE_NODE, xpath_list);
 | 
			
		||||
 | 
			
		||||
@ -1162,22 +1157,14 @@ DEFPY (no_interface,
 | 
			
		||||
       "Interface's name\n"
 | 
			
		||||
       VRF_CMD_HELP_STR)
 | 
			
		||||
{
 | 
			
		||||
	char xpath_list[XPATH_MAXLEN];
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = ".",
 | 
			
		||||
			.operation = NB_OP_DELETE,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	if (!vrfname)
 | 
			
		||||
		vrfname = VRF_DEFAULT_NAME;
 | 
			
		||||
 | 
			
		||||
	snprintf(xpath_list, sizeof(xpath_list),
 | 
			
		||||
		 "/frr-interface:lib/interface[name='%s'][vrf='%s']", ifname,
 | 
			
		||||
		 vrfname);
 | 
			
		||||
	nb_cli_enqueue_change(vty, ".", NB_OP_DELETE, NULL);
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, xpath_list, changes, array_size(changes));
 | 
			
		||||
	return nb_cli_apply_changes(
 | 
			
		||||
		vty, "/frr-interface:lib/interface[name='%s'][vrf='%s']",
 | 
			
		||||
		ifname, vrfname);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void cli_show_interface(struct vty *vty, struct lyd_node *dnode,
 | 
			
		||||
@ -1203,18 +1190,12 @@ DEFPY (interface_desc,
 | 
			
		||||
       "Interface specific description\n"
 | 
			
		||||
       "Characters describing this interface\n")
 | 
			
		||||
{
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./description",
 | 
			
		||||
			.operation = NB_OP_MODIFY,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	char *desc;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	desc = argv_concat(argv, argc, 1);
 | 
			
		||||
	changes[0].value = desc;
 | 
			
		||||
	ret = nb_cli_cfg_change(vty, NULL, changes, array_size(changes));
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./description", NB_OP_MODIFY, desc);
 | 
			
		||||
	ret = nb_cli_apply_changes(vty, NULL);
 | 
			
		||||
	XFREE(MTYPE_TMP, desc);
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
@ -1226,14 +1207,9 @@ DEFPY  (no_interface_desc,
 | 
			
		||||
	NO_STR
 | 
			
		||||
	"Interface specific description\n")
 | 
			
		||||
{
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./description",
 | 
			
		||||
			.operation = NB_OP_DELETE,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./description", NB_OP_DELETE, NULL);
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, NULL, changes, array_size(changes));
 | 
			
		||||
	return nb_cli_apply_changes(vty, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void cli_show_interface_desc(struct vty *vty, struct lyd_node *dnode,
 | 
			
		||||
@ -1338,7 +1314,7 @@ static int lib_interface_delete(enum nb_event event,
 | 
			
		||||
{
 | 
			
		||||
	struct interface *ifp;
 | 
			
		||||
 | 
			
		||||
	ifp = yang_dnode_get_entry(dnode);
 | 
			
		||||
	ifp = yang_dnode_get_entry(dnode, true);
 | 
			
		||||
 | 
			
		||||
	switch (event) {
 | 
			
		||||
	case NB_EV_VALIDATE:
 | 
			
		||||
@ -1372,7 +1348,7 @@ static int lib_interface_description_modify(enum nb_event event,
 | 
			
		||||
	if (event != NB_EV_APPLY)
 | 
			
		||||
		return NB_OK;
 | 
			
		||||
 | 
			
		||||
	ifp = yang_dnode_get_entry(dnode);
 | 
			
		||||
	ifp = yang_dnode_get_entry(dnode, true);
 | 
			
		||||
	if (ifp->desc)
 | 
			
		||||
		XFREE(MTYPE_TMP, ifp->desc);
 | 
			
		||||
	description = yang_dnode_get_string(dnode, NULL);
 | 
			
		||||
@ -1389,7 +1365,7 @@ static int lib_interface_description_delete(enum nb_event event,
 | 
			
		||||
	if (event != NB_EV_APPLY)
 | 
			
		||||
		return NB_OK;
 | 
			
		||||
 | 
			
		||||
	ifp = yang_dnode_get_entry(dnode);
 | 
			
		||||
	ifp = yang_dnode_get_entry(dnode, true);
 | 
			
		||||
	if (ifp->desc)
 | 
			
		||||
		XFREE(MTYPE_TMP, ifp->desc);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -56,10 +56,30 @@ static void vty_show_libyang_errors(struct vty *vty, struct ly_ctx *ly_ctx)
 | 
			
		||||
	ly_err_clean(ly_ctx, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int nb_cli_cfg_change(struct vty *vty, char *xpath_base,
 | 
			
		||||
		      struct cli_config_change changes[], size_t size)
 | 
			
		||||
void nb_cli_enqueue_change(struct vty *vty, const char *xpath,
 | 
			
		||||
			   enum nb_operation operation, const char *value)
 | 
			
		||||
{
 | 
			
		||||
	struct vty_cfg_change *change;
 | 
			
		||||
 | 
			
		||||
	if (vty->num_cfg_changes == VTY_MAXCFGCHANGES) {
 | 
			
		||||
		/* Not expected to happen. */
 | 
			
		||||
		vty_out(vty,
 | 
			
		||||
			"%% Exceeded the maximum number of changes (%u) for a single command\n\n",
 | 
			
		||||
			VTY_MAXCFGCHANGES);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	change = &vty->cfg_changes[vty->num_cfg_changes++];
 | 
			
		||||
	change->xpath = xpath;
 | 
			
		||||
	change->operation = operation;
 | 
			
		||||
	change->value = value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int nb_cli_apply_changes(struct vty *vty, const char *xpath_base_fmt, ...)
 | 
			
		||||
{
 | 
			
		||||
	struct nb_config *candidate_transitory;
 | 
			
		||||
	char xpath_base[XPATH_MAXLEN];
 | 
			
		||||
	va_list ap;
 | 
			
		||||
	bool error = false;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
@ -72,9 +92,14 @@ int nb_cli_cfg_change(struct vty *vty, char *xpath_base,
 | 
			
		||||
	 */
 | 
			
		||||
	candidate_transitory = nb_config_dup(vty->candidate_config);
 | 
			
		||||
 | 
			
		||||
	/* Parse the base XPath format string. */
 | 
			
		||||
	va_start(ap, xpath_base_fmt);
 | 
			
		||||
	vsnprintf(xpath_base, sizeof(xpath_base), xpath_base_fmt, ap);
 | 
			
		||||
	va_end(ap);
 | 
			
		||||
 | 
			
		||||
	/* Edit candidate configuration. */
 | 
			
		||||
	for (size_t i = 0; i < size; i++) {
 | 
			
		||||
		struct cli_config_change *change = &changes[i];
 | 
			
		||||
	for (size_t i = 0; i < vty->num_cfg_changes; i++) {
 | 
			
		||||
		struct vty_cfg_change *change = &vty->cfg_changes[i];
 | 
			
		||||
		struct nb_node *nb_node;
 | 
			
		||||
		char xpath[XPATH_MAXLEN];
 | 
			
		||||
		struct yang_data *data;
 | 
			
		||||
@ -82,19 +107,21 @@ int nb_cli_cfg_change(struct vty *vty, char *xpath_base,
 | 
			
		||||
		/* Handle relative XPaths. */
 | 
			
		||||
		memset(xpath, 0, sizeof(xpath));
 | 
			
		||||
		if (vty->xpath_index > 0
 | 
			
		||||
		    && ((xpath_base && xpath_base[0] == '.')
 | 
			
		||||
		    && ((xpath_base_fmt && xpath_base[0] == '.')
 | 
			
		||||
			|| change->xpath[0] == '.'))
 | 
			
		||||
			strlcpy(xpath, VTY_CURR_XPATH, sizeof(xpath));
 | 
			
		||||
		if (xpath_base) {
 | 
			
		||||
		if (xpath_base_fmt) {
 | 
			
		||||
			if (xpath_base[0] == '.')
 | 
			
		||||
				xpath_base++;
 | 
			
		||||
			strlcat(xpath, xpath_base, sizeof(xpath));
 | 
			
		||||
				strlcat(xpath, xpath_base + 1, sizeof(xpath));
 | 
			
		||||
			else
 | 
			
		||||
				strlcat(xpath, xpath_base, sizeof(xpath));
 | 
			
		||||
		}
 | 
			
		||||
		if (change->xpath[0] == '.')
 | 
			
		||||
			strlcat(xpath, change->xpath + 1, sizeof(xpath));
 | 
			
		||||
		else
 | 
			
		||||
			strlcpy(xpath, change->xpath, sizeof(xpath));
 | 
			
		||||
 | 
			
		||||
		/* Find the northbound node associated to the data path. */
 | 
			
		||||
		nb_node = nb_node_find(xpath);
 | 
			
		||||
		if (!nb_node) {
 | 
			
		||||
			flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH,
 | 
			
		||||
 | 
			
		||||
@ -22,27 +22,6 @@
 | 
			
		||||
 | 
			
		||||
#include "northbound.h"
 | 
			
		||||
 | 
			
		||||
struct cli_config_change {
 | 
			
		||||
	/*
 | 
			
		||||
	 * XPath (absolute or relative) of the configuration option being
 | 
			
		||||
	 * edited.
 | 
			
		||||
	 */
 | 
			
		||||
	char xpath[XPATH_MAXLEN];
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Operation to apply (either NB_OP_CREATE, NB_OP_MODIFY or
 | 
			
		||||
	 * NB_OP_DELETE).
 | 
			
		||||
	 */
 | 
			
		||||
	enum nb_operation operation;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * New value of the configuration option. Should be NULL for typeless
 | 
			
		||||
	 * YANG data (e.g. presence-containers). For convenience, NULL can also
 | 
			
		||||
	 * be used to restore a leaf to its default value.
 | 
			
		||||
	 */
 | 
			
		||||
	const char *value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Possible formats in which a configuration can be displayed. */
 | 
			
		||||
enum nb_cfg_format {
 | 
			
		||||
	NB_CFG_FMT_CMDS = 0,
 | 
			
		||||
@ -52,13 +31,80 @@ enum nb_cfg_format {
 | 
			
		||||
 | 
			
		||||
extern struct nb_config *vty_shared_candidate_config;
 | 
			
		||||
 | 
			
		||||
/* Prototypes. */
 | 
			
		||||
extern int nb_cli_cfg_change(struct vty *vty, char *xpath_list,
 | 
			
		||||
			     struct cli_config_change changes[], size_t size);
 | 
			
		||||
/*
 | 
			
		||||
 * Enqueue change to be applied in the candidate configuration.
 | 
			
		||||
 *
 | 
			
		||||
 * vty
 | 
			
		||||
 *    The vty context.
 | 
			
		||||
 *
 | 
			
		||||
 * xpath
 | 
			
		||||
 *    XPath (absolute or relative) of the configuration option being edited.
 | 
			
		||||
 *
 | 
			
		||||
 * operation
 | 
			
		||||
 *    Operation to apply (either NB_OP_CREATE, NB_OP_MODIFY or NB_OP_DELETE).
 | 
			
		||||
 *
 | 
			
		||||
 * value
 | 
			
		||||
 *    New value of the configuration option. Should be NULL for typeless YANG
 | 
			
		||||
 *    data (e.g. presence-containers). For convenience, NULL can also be used
 | 
			
		||||
 *    to restore a leaf to its default value.
 | 
			
		||||
 */
 | 
			
		||||
extern void nb_cli_enqueue_change(struct vty *vty, const char *xpath,
 | 
			
		||||
				  enum nb_operation operation,
 | 
			
		||||
				  const char *value);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Apply enqueued changes to the candidate configuration.
 | 
			
		||||
 *
 | 
			
		||||
 * vty
 | 
			
		||||
 *    The vty context.
 | 
			
		||||
 *
 | 
			
		||||
 * xpath_base_fmt
 | 
			
		||||
 *    Prepend the given XPath (absolute or relative) to all enqueued
 | 
			
		||||
 *    configuration changes.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns:
 | 
			
		||||
 *    CMD_SUCCESS on success, CMD_WARNING_CONFIG_FAILED otherwise.
 | 
			
		||||
 */
 | 
			
		||||
extern int nb_cli_apply_changes(struct vty *vty, const char *xpath_base_fmt,
 | 
			
		||||
				...);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Execute a YANG RPC or Action.
 | 
			
		||||
 *
 | 
			
		||||
 * xpath
 | 
			
		||||
 *    XPath of the YANG RPC or Action node.
 | 
			
		||||
 *
 | 
			
		||||
 * input
 | 
			
		||||
 *    List of 'yang_data' structures containing the RPC input parameters. It
 | 
			
		||||
 *    can be set to NULL when there are no input parameters.
 | 
			
		||||
 *
 | 
			
		||||
 * output
 | 
			
		||||
 *    List of 'yang_data' structures used to retrieve the RPC output parameters.
 | 
			
		||||
 *    It can be set to NULL when it's known that the given YANG RPC or Action
 | 
			
		||||
 *    doesn't have any output parameters.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns:
 | 
			
		||||
 *    CMD_SUCCESS on success, CMD_WARNING otherwise.
 | 
			
		||||
 */
 | 
			
		||||
extern int nb_cli_rpc(const char *xpath, struct list *input,
 | 
			
		||||
		      struct list *output);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Show CLI commands associated to the given YANG data node.
 | 
			
		||||
 *
 | 
			
		||||
 * vty
 | 
			
		||||
 *    The vty terminal to dump the configuration to.
 | 
			
		||||
 *
 | 
			
		||||
 * dnode
 | 
			
		||||
 *    libyang data node that should be shown in the form of CLI commands.
 | 
			
		||||
 *
 | 
			
		||||
 * show_defaults
 | 
			
		||||
 *    Specify whether to display default configuration values or not.
 | 
			
		||||
 */
 | 
			
		||||
extern void nb_cli_show_dnode_cmds(struct vty *vty, struct lyd_node *dnode,
 | 
			
		||||
				   bool show_defaults);
 | 
			
		||||
 | 
			
		||||
/* Prototypes of internal functions. */
 | 
			
		||||
extern void nb_cli_install_default(int node);
 | 
			
		||||
extern void nb_cli_init(void);
 | 
			
		||||
extern void nb_cli_terminate(void);
 | 
			
		||||
 | 
			
		||||
@ -951,9 +951,11 @@ static int frr_confd_dp_read(struct thread *thread)
 | 
			
		||||
	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;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										12
									
								
								lib/vty.h
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								lib/vty.h
									
									
									
									
									
								
							@ -35,11 +35,19 @@
 | 
			
		||||
#define VTY_MAXHIST 20
 | 
			
		||||
#define VTY_MAXDEPTH 8
 | 
			
		||||
 | 
			
		||||
#define VTY_MAXCFGCHANGES 8
 | 
			
		||||
 | 
			
		||||
struct vty_error {
 | 
			
		||||
	char error_buf[VTY_BUFSIZ];
 | 
			
		||||
	uint32_t line_num;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct vty_cfg_change {
 | 
			
		||||
	const char *xpath;
 | 
			
		||||
	enum nb_operation operation;
 | 
			
		||||
	const char *value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* VTY struct. */
 | 
			
		||||
struct vty {
 | 
			
		||||
	/* File descripter of this vty. */
 | 
			
		||||
@ -98,6 +106,10 @@ struct vty {
 | 
			
		||||
	/* History insert end point */
 | 
			
		||||
	int hindex;
 | 
			
		||||
 | 
			
		||||
	/* Changes enqueued to be applied in the candidate configuration. */
 | 
			
		||||
	size_t num_cfg_changes;
 | 
			
		||||
	struct vty_cfg_change cfg_changes[VTY_MAXCFGCHANGES];
 | 
			
		||||
 | 
			
		||||
	/* XPath of the current node */
 | 
			
		||||
	int xpath_index;
 | 
			
		||||
	char xpath[VTY_MAXDEPTH][XPATH_MAXLEN];
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										33
									
								
								lib/yang.c
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								lib/yang.c
									
									
									
									
									
								
							@ -344,6 +344,29 @@ void yang_dnode_get_path(const struct lyd_node *dnode, char *xpath,
 | 
			
		||||
	free(xpath_ptr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *yang_dnode_get_schema_name(const struct lyd_node *dnode,
 | 
			
		||||
				       const char *xpath_fmt, ...)
 | 
			
		||||
{
 | 
			
		||||
	if (xpath_fmt) {
 | 
			
		||||
		va_list ap;
 | 
			
		||||
		char xpath[XPATH_MAXLEN];
 | 
			
		||||
 | 
			
		||||
		va_start(ap, xpath_fmt);
 | 
			
		||||
		vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
 | 
			
		||||
		va_end(ap);
 | 
			
		||||
 | 
			
		||||
		dnode = yang_dnode_get(dnode, xpath);
 | 
			
		||||
		if (!dnode) {
 | 
			
		||||
			flog_err(EC_LIB_YANG_DNODE_NOT_FOUND,
 | 
			
		||||
				 "%s: couldn't find %s", __func__, xpath);
 | 
			
		||||
			zlog_backtrace(LOG_ERR);
 | 
			
		||||
			abort();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return dnode->schema->name;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct lyd_node *yang_dnode_get(const struct lyd_node *dnode,
 | 
			
		||||
				const char *xpath_fmt, ...)
 | 
			
		||||
{
 | 
			
		||||
@ -470,7 +493,8 @@ void yang_dnode_set_entry(const struct lyd_node *dnode, void *entry)
 | 
			
		||||
	lyd_set_private(dnode, entry);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *yang_dnode_get_entry(const struct lyd_node *dnode)
 | 
			
		||||
void *yang_dnode_get_entry(const struct lyd_node *dnode,
 | 
			
		||||
			   bool abort_if_not_found)
 | 
			
		||||
{
 | 
			
		||||
	const struct lyd_node *orig_dnode = dnode;
 | 
			
		||||
	char xpath[XPATH_MAXLEN];
 | 
			
		||||
@ -489,6 +513,9 @@ void *yang_dnode_get_entry(const struct lyd_node *dnode)
 | 
			
		||||
		dnode = dnode->parent;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!abort_if_not_found)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	yang_dnode_get_path(orig_dnode, xpath, sizeof(xpath));
 | 
			
		||||
	flog_err(EC_LIB_YANG_DNODE_NOT_FOUND,
 | 
			
		||||
		 "%s: failed to find entry [xpath %s]", __func__, xpath);
 | 
			
		||||
@ -609,13 +636,13 @@ void yang_init(void)
 | 
			
		||||
	ly_log_options(LY_LOLOG | LY_LOSTORE);
 | 
			
		||||
 | 
			
		||||
	/* Initialize libyang container for native models. */
 | 
			
		||||
	ly_native_ctx = ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIR_CWD);
 | 
			
		||||
	ly_native_ctx =
 | 
			
		||||
		ly_ctx_new(YANG_MODELS_PATH, LY_CTX_DISABLE_SEARCHDIR_CWD);
 | 
			
		||||
	if (!ly_native_ctx) {
 | 
			
		||||
		flog_err(EC_LIB_LIBYANG, "%s: ly_ctx_new() failed", __func__);
 | 
			
		||||
		exit(1);
 | 
			
		||||
	}
 | 
			
		||||
	ly_ctx_set_module_imp_clb(ly_native_ctx, yang_module_imp_clb, NULL);
 | 
			
		||||
	ly_ctx_set_searchdir(ly_native_ctx, YANG_MODELS_PATH);
 | 
			
		||||
	ly_ctx_set_priv_dup_clb(ly_native_ctx, ly_dup_cb);
 | 
			
		||||
 | 
			
		||||
	/* Detect if the required libyang plugin(s) were loaded successfully. */
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										42
									
								
								lib/yang.h
									
									
									
									
									
								
							
							
						
						
									
										42
									
								
								lib/yang.h
									
									
									
									
									
								
							@ -284,6 +284,22 @@ extern const struct lys_type *yang_snode_get_type(const struct lys_node *snode);
 | 
			
		||||
extern void yang_dnode_get_path(const struct lyd_node *dnode, char *xpath,
 | 
			
		||||
				size_t xpath_len);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Return the schema name of the given libyang data node.
 | 
			
		||||
 *
 | 
			
		||||
 * dnode
 | 
			
		||||
 *    libyang data node.
 | 
			
		||||
 *
 | 
			
		||||
 * xpath_fmt
 | 
			
		||||
 *    Optional XPath expression (absolute or relative) to specify a different
 | 
			
		||||
 *    data node to operate on in the same data tree.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns:
 | 
			
		||||
 *    Schema name of the libyang data node.
 | 
			
		||||
 */
 | 
			
		||||
extern const char *yang_dnode_get_schema_name(const struct lyd_node *dnode,
 | 
			
		||||
					      const char *xpath_fmt, ...);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Find a libyang data node by its YANG data path.
 | 
			
		||||
 *
 | 
			
		||||
@ -369,15 +385,37 @@ extern void yang_dnode_change_leaf(struct lyd_node *dnode, const char *value);
 | 
			
		||||
extern void yang_dnode_set_entry(const struct lyd_node *dnode, void *entry);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Find the closest data node that contains an user pointer and return it.
 | 
			
		||||
 * Find the user pointer associated to the given libyang data node.
 | 
			
		||||
 *
 | 
			
		||||
 * The data node is traversed by following the parent pointers until an user
 | 
			
		||||
 * pointer is found or until the root node is reached.
 | 
			
		||||
 *
 | 
			
		||||
 * dnode
 | 
			
		||||
 *    libyang data node to operate on.
 | 
			
		||||
 *
 | 
			
		||||
 * abort_if_not_found
 | 
			
		||||
 *    When set to true, abort the program if no user pointer is found.
 | 
			
		||||
 *
 | 
			
		||||
 *    As a rule of thumb, this parameter should be set to true in the following
 | 
			
		||||
 *    scenarios:
 | 
			
		||||
 *    - Calling this function from any northbound configuration callback during
 | 
			
		||||
 *      the NB_EV_APPLY phase.
 | 
			
		||||
 *    - Calling this function from a 'delete' northbound configuration callback
 | 
			
		||||
 *      during any phase.
 | 
			
		||||
 *
 | 
			
		||||
 *    In both the above cases, the libyang data node should contain an user
 | 
			
		||||
 *    pointer except when there's a bug in the code, in which case it's better
 | 
			
		||||
 *    to abort the program right away and eliminate the need for unnecessary
 | 
			
		||||
 *    NULL checks.
 | 
			
		||||
 *
 | 
			
		||||
 *    In all other cases, this parameter should be set to false and the caller
 | 
			
		||||
 *    should check if the function returned NULL or not.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns:
 | 
			
		||||
 *    User pointer if found, NULL otherwise.
 | 
			
		||||
 */
 | 
			
		||||
extern void *yang_dnode_get_entry(const struct lyd_node *dnode);
 | 
			
		||||
extern void *yang_dnode_get_entry(const struct lyd_node *dnode,
 | 
			
		||||
				  bool abort_if_not_found);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Create a new libyang data node.
 | 
			
		||||
 | 
			
		||||
@ -162,12 +162,12 @@ struct yang_translator *yang_translator_load(const char *path)
 | 
			
		||||
	RB_INSERT(yang_translators, &yang_translators, translator);
 | 
			
		||||
 | 
			
		||||
	/* Initialize the translator libyang context. */
 | 
			
		||||
	translator->ly_ctx = ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIR_CWD);
 | 
			
		||||
	translator->ly_ctx =
 | 
			
		||||
		ly_ctx_new(YANG_MODELS_PATH, LY_CTX_DISABLE_SEARCHDIR_CWD);
 | 
			
		||||
	if (!translator->ly_ctx) {
 | 
			
		||||
		flog_warn(EC_LIB_LIBYANG, "%s: ly_ctx_new() failed", __func__);
 | 
			
		||||
		goto error;
 | 
			
		||||
	}
 | 
			
		||||
	ly_ctx_set_searchdir(translator->ly_ctx, YANG_MODELS_PATH);
 | 
			
		||||
 | 
			
		||||
	/* Load modules and deviations. */
 | 
			
		||||
	set = lyd_find_path(dnode, "./module");
 | 
			
		||||
@ -515,12 +515,12 @@ static void str_replace(char *o_string, const char *s_string,
 | 
			
		||||
 | 
			
		||||
void yang_translator_init(void)
 | 
			
		||||
{
 | 
			
		||||
	ly_translator_ctx = ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIR_CWD);
 | 
			
		||||
	ly_translator_ctx =
 | 
			
		||||
		ly_ctx_new(YANG_MODELS_PATH, LY_CTX_DISABLE_SEARCHDIR_CWD);
 | 
			
		||||
	if (!ly_translator_ctx) {
 | 
			
		||||
		flog_err(EC_LIB_LIBYANG, "%s: ly_ctx_new() failed", __func__);
 | 
			
		||||
		exit(1);
 | 
			
		||||
	}
 | 
			
		||||
	ly_ctx_set_searchdir(ly_translator_ctx, YANG_MODELS_PATH);
 | 
			
		||||
 | 
			
		||||
	if (!ly_ctx_load_module(ly_translator_ctx, "frr-module-translator",
 | 
			
		||||
				NULL)) {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										591
									
								
								ripd/rip_cli.c
									
									
									
									
									
								
							
							
						
						
									
										591
									
								
								ripd/rip_cli.c
									
									
									
									
									
								
							@ -45,17 +45,12 @@ DEFPY_NOSH (router_rip,
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "/frr-ripd:ripd/instance",
 | 
			
		||||
			.operation = NB_OP_CREATE,
 | 
			
		||||
			.value = NULL,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	nb_cli_enqueue_change(vty, "/frr-ripd:ripd/instance", NB_OP_CREATE,
 | 
			
		||||
			      NULL);
 | 
			
		||||
 | 
			
		||||
	ret = nb_cli_cfg_change(vty, NULL, changes, array_size(changes));
 | 
			
		||||
	ret = nb_cli_apply_changes(vty, NULL);
 | 
			
		||||
	if (ret == CMD_SUCCESS)
 | 
			
		||||
		VTY_PUSH_XPATH(RIP_NODE, changes[0].xpath);
 | 
			
		||||
		VTY_PUSH_XPATH(RIP_NODE, "/frr-ripd:ripd/instance");
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
@ -67,15 +62,10 @@ DEFPY (no_router_rip,
 | 
			
		||||
       "Enable a routing process\n"
 | 
			
		||||
       "Routing Information Protocol (RIP)\n")
 | 
			
		||||
{
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "/frr-ripd:ripd/instance",
 | 
			
		||||
			.operation = NB_OP_DELETE,
 | 
			
		||||
			.value = NULL,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	nb_cli_enqueue_change(vty, "/frr-ripd:ripd/instance", NB_OP_DELETE,
 | 
			
		||||
			      NULL);
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, NULL, changes, array_size(changes));
 | 
			
		||||
	return nb_cli_apply_changes(vty, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cli_show_router_rip(struct vty *vty, struct lyd_node *dnode,
 | 
			
		||||
@ -94,15 +84,10 @@ DEFPY (rip_allow_ecmp,
 | 
			
		||||
       NO_STR
 | 
			
		||||
       "Allow Equal Cost MultiPath\n")
 | 
			
		||||
{
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./allow-ecmp",
 | 
			
		||||
			.operation = NB_OP_MODIFY,
 | 
			
		||||
			.value = no ? "false" : "true",
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./allow-ecmp", NB_OP_MODIFY,
 | 
			
		||||
			      no ? "false" : "true");
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, NULL, changes, array_size(changes));
 | 
			
		||||
	return nb_cli_apply_changes(vty, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cli_show_rip_allow_ecmp(struct vty *vty, struct lyd_node *dnode,
 | 
			
		||||
@ -124,15 +109,10 @@ DEFPY (rip_default_information_originate,
 | 
			
		||||
       "Control distribution of default route\n"
 | 
			
		||||
       "Distribute a default route\n")
 | 
			
		||||
{
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./default-information-originate",
 | 
			
		||||
			.operation = NB_OP_MODIFY,
 | 
			
		||||
			.value = no ? "false" : "true",
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./default-information-originate",
 | 
			
		||||
			      NB_OP_MODIFY, no ? "false" : "true");
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, NULL, changes, array_size(changes));
 | 
			
		||||
	return nb_cli_apply_changes(vty, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cli_show_rip_default_information_originate(struct vty *vty,
 | 
			
		||||
@ -154,15 +134,10 @@ DEFPY (rip_default_metric,
 | 
			
		||||
       "Set a metric of redistribute routes\n"
 | 
			
		||||
       "Default metric\n")
 | 
			
		||||
{
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./default-metric",
 | 
			
		||||
			.operation = NB_OP_MODIFY,
 | 
			
		||||
			.value = default_metric_str,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./default-metric", NB_OP_MODIFY,
 | 
			
		||||
			      default_metric_str);
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, NULL, changes, array_size(changes));
 | 
			
		||||
	return nb_cli_apply_changes(vty, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFPY (no_rip_default_metric,
 | 
			
		||||
@ -172,15 +147,9 @@ DEFPY (no_rip_default_metric,
 | 
			
		||||
       "Set a metric of redistribute routes\n"
 | 
			
		||||
       "Default metric\n")
 | 
			
		||||
{
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./default-metric",
 | 
			
		||||
			.operation = NB_OP_MODIFY,
 | 
			
		||||
			.value = NULL,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./default-metric", NB_OP_MODIFY, NULL);
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, NULL, changes, array_size(changes));
 | 
			
		||||
	return nb_cli_apply_changes(vty, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cli_show_rip_default_metric(struct vty *vty, struct lyd_node *dnode,
 | 
			
		||||
@ -199,15 +168,10 @@ DEFPY (rip_distance,
 | 
			
		||||
       "Administrative distance\n"
 | 
			
		||||
       "Distance value\n")
 | 
			
		||||
{
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./distance/default",
 | 
			
		||||
			.operation = NB_OP_MODIFY,
 | 
			
		||||
			.value = distance_str,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./distance/default", NB_OP_MODIFY,
 | 
			
		||||
			      distance_str);
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, NULL, changes, array_size(changes));
 | 
			
		||||
	return nb_cli_apply_changes(vty, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFPY (no_rip_distance,
 | 
			
		||||
@ -217,21 +181,19 @@ DEFPY (no_rip_distance,
 | 
			
		||||
       "Administrative distance\n"
 | 
			
		||||
       "Distance value\n")
 | 
			
		||||
{
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./distance/default",
 | 
			
		||||
			.operation = NB_OP_MODIFY,
 | 
			
		||||
			.value = NULL,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./distance/default", NB_OP_MODIFY, NULL);
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, NULL, changes, array_size(changes));
 | 
			
		||||
	return nb_cli_apply_changes(vty, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cli_show_rip_distance(struct vty *vty, struct lyd_node *dnode,
 | 
			
		||||
			   bool show_defaults)
 | 
			
		||||
{
 | 
			
		||||
	vty_out(vty, " distance %s\n", yang_dnode_get_string(dnode, NULL));
 | 
			
		||||
	if (yang_dnode_is_default(dnode, NULL))
 | 
			
		||||
		vty_out(vty, " no distance\n");
 | 
			
		||||
	else
 | 
			
		||||
		vty_out(vty, " distance %s\n",
 | 
			
		||||
			yang_dnode_get_string(dnode, NULL));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@ -239,57 +201,23 @@ void cli_show_rip_distance(struct vty *vty, struct lyd_node *dnode,
 | 
			
		||||
 */
 | 
			
		||||
DEFPY (rip_distance_source,
 | 
			
		||||
       rip_distance_source_cmd,
 | 
			
		||||
       "distance (1-255) A.B.C.D/M$prefix [WORD$acl]",
 | 
			
		||||
       "Administrative distance\n"
 | 
			
		||||
       "Distance value\n"
 | 
			
		||||
       "IP source prefix\n"
 | 
			
		||||
       "Access list name\n")
 | 
			
		||||
{
 | 
			
		||||
	char xpath_list[XPATH_MAXLEN];
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = ".",
 | 
			
		||||
			.operation = NB_OP_CREATE,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./distance",
 | 
			
		||||
			.operation = NB_OP_MODIFY,
 | 
			
		||||
			.value = distance_str,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./access-list",
 | 
			
		||||
			.operation = acl ? NB_OP_MODIFY : NB_OP_DELETE,
 | 
			
		||||
			.value = acl,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	snprintf(xpath_list, sizeof(xpath_list),
 | 
			
		||||
		 "./distance/source[prefix='%s']", prefix_str);
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, xpath_list, changes, array_size(changes));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFPY (no_rip_distance_source,
 | 
			
		||||
       no_rip_distance_source_cmd,
 | 
			
		||||
       "no distance (1-255) A.B.C.D/M$prefix [WORD$acl]",
 | 
			
		||||
       "[no] distance (1-255) A.B.C.D/M$prefix [WORD$acl]",
 | 
			
		||||
       NO_STR
 | 
			
		||||
       "Administrative distance\n"
 | 
			
		||||
       "Distance value\n"
 | 
			
		||||
       "IP source prefix\n"
 | 
			
		||||
       "Access list name\n")
 | 
			
		||||
{
 | 
			
		||||
	char xpath_list[XPATH_MAXLEN];
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = ".",
 | 
			
		||||
			.operation = NB_OP_DELETE,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	if (!no) {
 | 
			
		||||
		nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
 | 
			
		||||
		nb_cli_enqueue_change(vty, "./distance", NB_OP_MODIFY, NULL);
 | 
			
		||||
		nb_cli_enqueue_change(vty, "./access-list",
 | 
			
		||||
				      acl ? NB_OP_MODIFY : NB_OP_DELETE, acl);
 | 
			
		||||
	} else
 | 
			
		||||
		nb_cli_enqueue_change(vty, ".", NB_OP_DELETE, NULL);
 | 
			
		||||
 | 
			
		||||
	snprintf(xpath_list, sizeof(xpath_list),
 | 
			
		||||
		 "./distance/source[prefix='%s']", prefix_str);
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, xpath_list, changes, 1);
 | 
			
		||||
	return nb_cli_apply_changes(vty, "./distance/source[prefix='%s']",
 | 
			
		||||
				    prefix_str);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cli_show_rip_distance_source(struct vty *vty, struct lyd_node *dnode,
 | 
			
		||||
@ -314,15 +242,10 @@ DEFPY (rip_neighbor,
 | 
			
		||||
       "Specify a neighbor router\n"
 | 
			
		||||
       "Neighbor address\n")
 | 
			
		||||
{
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./explicit-neighbor",
 | 
			
		||||
			.operation = no ? NB_OP_DELETE : NB_OP_CREATE,
 | 
			
		||||
			.value = neighbor_str,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./explicit-neighbor",
 | 
			
		||||
			      no ? NB_OP_DELETE : NB_OP_CREATE, neighbor_str);
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, NULL, changes, array_size(changes));
 | 
			
		||||
	return nb_cli_apply_changes(vty, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cli_show_rip_neighbor(struct vty *vty, struct lyd_node *dnode,
 | 
			
		||||
@ -341,15 +264,10 @@ DEFPY (rip_network_prefix,
 | 
			
		||||
       "Enable routing on an IP network\n"
 | 
			
		||||
       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
 | 
			
		||||
{
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./network",
 | 
			
		||||
			.operation = no ? NB_OP_DELETE : NB_OP_CREATE,
 | 
			
		||||
			.value = network_str,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./network",
 | 
			
		||||
			      no ? NB_OP_DELETE : NB_OP_CREATE, network_str);
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, NULL, changes, array_size(changes));
 | 
			
		||||
	return nb_cli_apply_changes(vty, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cli_show_rip_network_prefix(struct vty *vty, struct lyd_node *dnode,
 | 
			
		||||
@ -368,15 +286,10 @@ DEFPY (rip_network_if,
 | 
			
		||||
       "Enable routing on an IP network\n"
 | 
			
		||||
       "Interface name\n")
 | 
			
		||||
{
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./interface",
 | 
			
		||||
			.operation = no ? NB_OP_DELETE : NB_OP_CREATE,
 | 
			
		||||
			.value = network,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./interface",
 | 
			
		||||
			      no ? NB_OP_DELETE : NB_OP_CREATE, network);
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, NULL, changes, array_size(changes));
 | 
			
		||||
	return nb_cli_apply_changes(vty, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cli_show_rip_network_interface(struct vty *vty, struct lyd_node *dnode,
 | 
			
		||||
@ -390,42 +303,7 @@ void cli_show_rip_network_interface(struct vty *vty, struct lyd_node *dnode,
 | 
			
		||||
 */
 | 
			
		||||
DEFPY (rip_offset_list,
 | 
			
		||||
       rip_offset_list_cmd,
 | 
			
		||||
       "offset-list WORD$acl <in|out>$direction (0-16)$metric [IFNAME]",
 | 
			
		||||
       "Modify RIP metric\n"
 | 
			
		||||
       "Access-list name\n"
 | 
			
		||||
       "For incoming updates\n"
 | 
			
		||||
       "For outgoing updates\n"
 | 
			
		||||
       "Metric value\n"
 | 
			
		||||
       "Interface to match\n")
 | 
			
		||||
{
 | 
			
		||||
	char xpath_list[XPATH_MAXLEN];
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = ".",
 | 
			
		||||
			.operation = NB_OP_CREATE,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./access-list",
 | 
			
		||||
			.operation = NB_OP_MODIFY,
 | 
			
		||||
			.value = acl,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./metric",
 | 
			
		||||
			.operation = NB_OP_MODIFY,
 | 
			
		||||
			.value = metric_str,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	snprintf(xpath_list, sizeof(xpath_list),
 | 
			
		||||
		 "./offset-list[interface='%s'][direction='%s']",
 | 
			
		||||
		 ifname ? ifname : "*", direction);
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, xpath_list, changes, array_size(changes));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFPY (no_rip_offset_list,
 | 
			
		||||
       no_rip_offset_list_cmd,
 | 
			
		||||
       "no offset-list WORD$acl <in|out>$direction (0-16)$metric [IFNAME]",
 | 
			
		||||
       "[no] offset-list WORD$acl <in|out>$direction (0-16)$metric [IFNAME]",
 | 
			
		||||
       NO_STR
 | 
			
		||||
       "Modify RIP metric\n"
 | 
			
		||||
       "Access-list name\n"
 | 
			
		||||
@ -434,19 +312,17 @@ DEFPY (no_rip_offset_list,
 | 
			
		||||
       "Metric value\n"
 | 
			
		||||
       "Interface to match\n")
 | 
			
		||||
{
 | 
			
		||||
	char xpath_list[XPATH_MAXLEN];
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = ".",
 | 
			
		||||
			.operation = NB_OP_DELETE,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	if (!no) {
 | 
			
		||||
		nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
 | 
			
		||||
		nb_cli_enqueue_change(vty, "./access-list", NB_OP_MODIFY, acl);
 | 
			
		||||
		nb_cli_enqueue_change(vty, "./metric", NB_OP_MODIFY,
 | 
			
		||||
				      metric_str);
 | 
			
		||||
	} else
 | 
			
		||||
		nb_cli_enqueue_change(vty, ".", NB_OP_DELETE, NULL);
 | 
			
		||||
 | 
			
		||||
	snprintf(xpath_list, sizeof(xpath_list),
 | 
			
		||||
		 "./offset-list[interface='%s'][direction='%s']",
 | 
			
		||||
		 ifname ? ifname : "*", direction);
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, xpath_list, changes, array_size(changes));
 | 
			
		||||
	return nb_cli_apply_changes(
 | 
			
		||||
		vty, "./offset-list[interface='%s'][direction='%s']",
 | 
			
		||||
		ifname ? ifname : "*", direction);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cli_show_rip_offset_list(struct vty *vty, struct lyd_node *dnode,
 | 
			
		||||
@ -475,15 +351,10 @@ DEFPY (rip_passive_default,
 | 
			
		||||
       "Suppress routing updates on an interface\n"
 | 
			
		||||
       "default for all interfaces\n")
 | 
			
		||||
{
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./passive-default",
 | 
			
		||||
			.operation = NB_OP_MODIFY,
 | 
			
		||||
			.value = no ? "false" : "true",
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./passive-default", NB_OP_MODIFY,
 | 
			
		||||
			      no ? "false" : "true");
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, NULL, changes, array_size(changes));
 | 
			
		||||
	return nb_cli_apply_changes(vty, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cli_show_rip_passive_default(struct vty *vty, struct lyd_node *dnode,
 | 
			
		||||
@ -506,20 +377,12 @@ DEFPY (rip_passive_interface,
 | 
			
		||||
       "Suppress routing updates on an interface\n"
 | 
			
		||||
       "Interface name\n")
 | 
			
		||||
{
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./passive-interface",
 | 
			
		||||
			.operation = no ? NB_OP_DELETE : NB_OP_CREATE,
 | 
			
		||||
			.value = ifname,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./non-passive-interface",
 | 
			
		||||
			.operation = no ? NB_OP_CREATE : NB_OP_DELETE,
 | 
			
		||||
			.value = ifname,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./passive-interface",
 | 
			
		||||
			      no ? NB_OP_DELETE : NB_OP_CREATE, ifname);
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./non-passive-interface",
 | 
			
		||||
			      no ? NB_OP_CREATE : NB_OP_DELETE, ifname);
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, NULL, changes, array_size(changes));
 | 
			
		||||
	return nb_cli_apply_changes(vty, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cli_show_rip_passive_interface(struct vty *vty, struct lyd_node *dnode,
 | 
			
		||||
@ -541,41 +404,7 @@ void cli_show_rip_non_passive_interface(struct vty *vty, struct lyd_node *dnode,
 | 
			
		||||
 */
 | 
			
		||||
DEFPY (rip_redistribute,
 | 
			
		||||
       rip_redistribute_cmd,
 | 
			
		||||
       "redistribute " FRR_REDIST_STR_RIPD "$protocol [{metric (0-16)|route-map WORD}]",
 | 
			
		||||
       REDIST_STR
 | 
			
		||||
       FRR_REDIST_HELP_STR_RIPD
 | 
			
		||||
       "Metric\n"
 | 
			
		||||
       "Metric value\n"
 | 
			
		||||
       "Route map reference\n"
 | 
			
		||||
       "Pointer to route-map entries\n")
 | 
			
		||||
{
 | 
			
		||||
	char xpath_list[XPATH_MAXLEN];
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = ".",
 | 
			
		||||
			.operation = NB_OP_CREATE,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./route-map",
 | 
			
		||||
			.operation = route_map ? NB_OP_MODIFY : NB_OP_DELETE,
 | 
			
		||||
			.value = route_map,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./metric",
 | 
			
		||||
			.operation = metric_str ? NB_OP_MODIFY : NB_OP_DELETE,
 | 
			
		||||
			.value = metric_str,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	snprintf(xpath_list, sizeof(xpath_list),
 | 
			
		||||
		 "./redistribute[protocol='%s']", protocol);
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, xpath_list, changes, array_size(changes));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFPY (no_rip_redistribute,
 | 
			
		||||
       no_rip_redistribute_cmd,
 | 
			
		||||
       "no redistribute " FRR_REDIST_STR_RIPD "$protocol [{metric (0-16)|route-map WORD}]",
 | 
			
		||||
       "[no] redistribute " FRR_REDIST_STR_RIPD "$protocol [{metric (0-16)|route-map WORD}]",
 | 
			
		||||
       NO_STR
 | 
			
		||||
       REDIST_STR
 | 
			
		||||
       FRR_REDIST_HELP_STR_RIPD
 | 
			
		||||
@ -584,18 +413,19 @@ DEFPY (no_rip_redistribute,
 | 
			
		||||
       "Route map reference\n"
 | 
			
		||||
       "Pointer to route-map entries\n")
 | 
			
		||||
{
 | 
			
		||||
	char xpath_list[XPATH_MAXLEN];
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = ".",
 | 
			
		||||
			.operation = NB_OP_DELETE,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	if (!no) {
 | 
			
		||||
		nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
 | 
			
		||||
		nb_cli_enqueue_change(vty, "./route-map",
 | 
			
		||||
				      route_map ? NB_OP_MODIFY : NB_OP_DELETE,
 | 
			
		||||
				      route_map);
 | 
			
		||||
		nb_cli_enqueue_change(vty, "./metric",
 | 
			
		||||
				      metric_str ? NB_OP_MODIFY : NB_OP_DELETE,
 | 
			
		||||
				      metric_str);
 | 
			
		||||
	} else
 | 
			
		||||
		nb_cli_enqueue_change(vty, ".", NB_OP_DELETE, NULL);
 | 
			
		||||
 | 
			
		||||
	snprintf(xpath_list, sizeof(xpath_list),
 | 
			
		||||
		 "./redistribute[protocol='%s']", protocol);
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, xpath_list, changes, array_size(changes));
 | 
			
		||||
	return nb_cli_apply_changes(vty, "./redistribute[protocol='%s']",
 | 
			
		||||
				    protocol);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cli_show_rip_redistribute(struct vty *vty, struct lyd_node *dnode,
 | 
			
		||||
@ -622,15 +452,10 @@ DEFPY (rip_route,
 | 
			
		||||
       "RIP static route configuration\n"
 | 
			
		||||
       "IP prefix <network>/<length>\n")
 | 
			
		||||
{
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./static-route",
 | 
			
		||||
			.operation = no ? NB_OP_DELETE : NB_OP_CREATE,
 | 
			
		||||
			.value = route_str,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./static-route",
 | 
			
		||||
			      no ? NB_OP_DELETE : NB_OP_CREATE, route_str);
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, NULL, changes, array_size(changes));
 | 
			
		||||
	return nb_cli_apply_changes(vty, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cli_show_rip_route(struct vty *vty, struct lyd_node *dnode,
 | 
			
		||||
@ -651,25 +476,14 @@ DEFPY (rip_timers,
 | 
			
		||||
       "Routing information timeout timer. Default is 180.\n"
 | 
			
		||||
       "Garbage collection timer. Default is 120.\n")
 | 
			
		||||
{
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./timers/update-interval",
 | 
			
		||||
			.operation = NB_OP_MODIFY,
 | 
			
		||||
			.value = update_str,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./timers/holddown-interval",
 | 
			
		||||
			.operation = NB_OP_MODIFY,
 | 
			
		||||
			.value = timeout_str,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./timers/flush-interval",
 | 
			
		||||
			.operation = NB_OP_MODIFY,
 | 
			
		||||
			.value = garbage_str,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./update-interval", NB_OP_MODIFY,
 | 
			
		||||
			      update_str);
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./holddown-interval", NB_OP_MODIFY,
 | 
			
		||||
			      timeout_str);
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./flush-interval", NB_OP_MODIFY,
 | 
			
		||||
			      garbage_str);
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, NULL, changes, array_size(changes));
 | 
			
		||||
	return nb_cli_apply_changes(vty, "./timers");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFPY (no_rip_timers,
 | 
			
		||||
@ -682,25 +496,11 @@ DEFPY (no_rip_timers,
 | 
			
		||||
       "Routing information timeout timer. Default is 180.\n"
 | 
			
		||||
       "Garbage collection timer. Default is 120.\n")
 | 
			
		||||
{
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./timers/update-interval",
 | 
			
		||||
			.operation = NB_OP_MODIFY,
 | 
			
		||||
			.value =  NULL,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./timers/holddown-interval",
 | 
			
		||||
			.operation = NB_OP_MODIFY,
 | 
			
		||||
			.value =  NULL,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./timers/flush-interval",
 | 
			
		||||
			.operation = NB_OP_MODIFY,
 | 
			
		||||
			.value =  NULL,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./update-interval", NB_OP_MODIFY, NULL);
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./holddown-interval", NB_OP_MODIFY, NULL);
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./flush-interval", NB_OP_MODIFY, NULL);
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, NULL, changes, array_size(changes));
 | 
			
		||||
	return nb_cli_apply_changes(vty, "./timers");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cli_show_rip_timers(struct vty *vty, struct lyd_node *dnode,
 | 
			
		||||
@ -721,20 +521,11 @@ DEFPY (rip_version,
 | 
			
		||||
       "Set routing protocol version\n"
 | 
			
		||||
       "version\n")
 | 
			
		||||
{
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./version/receive",
 | 
			
		||||
			.operation = NB_OP_MODIFY,
 | 
			
		||||
			.value = version_str,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./version/send",
 | 
			
		||||
			.operation = NB_OP_MODIFY,
 | 
			
		||||
			.value = version_str,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./version/receive", NB_OP_MODIFY,
 | 
			
		||||
			      version_str);
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./version/send", NB_OP_MODIFY, version_str);
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, NULL, changes, array_size(changes));
 | 
			
		||||
	return nb_cli_apply_changes(vty, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFPY (no_rip_version,
 | 
			
		||||
@ -744,18 +535,10 @@ DEFPY (no_rip_version,
 | 
			
		||||
       "Set routing protocol version\n"
 | 
			
		||||
       "version\n")
 | 
			
		||||
{
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./version/receive",
 | 
			
		||||
			.operation = NB_OP_MODIFY,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./version/send",
 | 
			
		||||
			.operation = NB_OP_MODIFY,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./version/receive", NB_OP_MODIFY, NULL);
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./version/send", NB_OP_MODIFY, NULL);
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, NULL, changes, array_size(changes));
 | 
			
		||||
	return nb_cli_apply_changes(vty, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cli_show_rip_version(struct vty *vty, struct lyd_node *dnode,
 | 
			
		||||
@ -790,21 +573,18 @@ DEFPY (ip_rip_split_horizon,
 | 
			
		||||
       "Perform split horizon\n"
 | 
			
		||||
       "With poisoned-reverse\n")
 | 
			
		||||
{
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./frr-ripd:rip/split-horizon",
 | 
			
		||||
			.operation = NB_OP_MODIFY,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	const char *value;
 | 
			
		||||
 | 
			
		||||
	if (no)
 | 
			
		||||
		changes[0].value = "disabled";
 | 
			
		||||
		value = "disabled";
 | 
			
		||||
	else if (poisoned_reverse)
 | 
			
		||||
		changes[0].value = "poison-reverse";
 | 
			
		||||
		value = "poison-reverse";
 | 
			
		||||
	else
 | 
			
		||||
		changes[0].value = "simple";
 | 
			
		||||
		value = "simple";
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, NULL, changes, array_size(changes));
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./split-horizon", NB_OP_MODIFY, value);
 | 
			
		||||
 | 
			
		||||
	return nb_cli_apply_changes(vty, "./frr-ripd:rip");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cli_show_ip_rip_split_horizon(struct vty *vty, struct lyd_node *dnode,
 | 
			
		||||
@ -837,15 +617,10 @@ DEFPY (ip_rip_v2_broadcast,
 | 
			
		||||
       "Routing Information Protocol\n"
 | 
			
		||||
       "Send ip broadcast v2 update\n")
 | 
			
		||||
{
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./frr-ripd:rip/v2-broadcast",
 | 
			
		||||
			.operation = NB_OP_MODIFY,
 | 
			
		||||
			.value = no ? "false" : "true",
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./v2-broadcast", NB_OP_MODIFY,
 | 
			
		||||
			      no ? "false" : "true");
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, NULL, changes, array_size(changes));
 | 
			
		||||
	return nb_cli_apply_changes(vty, "./frr-ripd:rip");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cli_show_ip_rip_v2_broadcast(struct vty *vty, struct lyd_node *dnode,
 | 
			
		||||
@ -871,23 +646,20 @@ DEFPY (ip_rip_receive_version,
 | 
			
		||||
       "RIP version 2\n"
 | 
			
		||||
       "None\n")
 | 
			
		||||
{
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./frr-ripd:rip/version-receive",
 | 
			
		||||
			.operation = NB_OP_MODIFY,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	const char *value;
 | 
			
		||||
 | 
			
		||||
	if (v1 && v2)
 | 
			
		||||
		changes[0].value = "both";
 | 
			
		||||
		value = "both";
 | 
			
		||||
	else if (v1)
 | 
			
		||||
		changes[0].value = "1";
 | 
			
		||||
		value = "1";
 | 
			
		||||
	else if (v2)
 | 
			
		||||
		changes[0].value = "2";
 | 
			
		||||
		value = "2";
 | 
			
		||||
	else
 | 
			
		||||
		changes[0].value = "none";
 | 
			
		||||
		value = "none";
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, NULL, changes, array_size(changes));
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./version-receive", NB_OP_MODIFY, value);
 | 
			
		||||
 | 
			
		||||
	return nb_cli_apply_changes(vty, "./frr-ripd:rip");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFPY (no_ip_rip_receive_version,
 | 
			
		||||
@ -902,15 +674,9 @@ DEFPY (no_ip_rip_receive_version,
 | 
			
		||||
       "RIP version 2\n"
 | 
			
		||||
       "None\n")
 | 
			
		||||
{
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./frr-ripd:rip/version-receive",
 | 
			
		||||
			.operation = NB_OP_MODIFY,
 | 
			
		||||
			.value = NULL,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./version-receive", NB_OP_MODIFY, NULL);
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, NULL, changes, array_size(changes));
 | 
			
		||||
	return nb_cli_apply_changes(vty, "./frr-ripd:rip");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cli_show_ip_rip_receive_version(struct vty *vty, struct lyd_node *dnode,
 | 
			
		||||
@ -949,23 +715,20 @@ DEFPY (ip_rip_send_version,
 | 
			
		||||
       "RIP version 2\n"
 | 
			
		||||
       "None\n")
 | 
			
		||||
{
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./frr-ripd:rip/version-send",
 | 
			
		||||
			.operation = NB_OP_MODIFY,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	const char *value;
 | 
			
		||||
 | 
			
		||||
	if (v1 && v2)
 | 
			
		||||
		changes[0].value = "both";
 | 
			
		||||
		value = "both";
 | 
			
		||||
	else if (v1)
 | 
			
		||||
		changes[0].value = "1";
 | 
			
		||||
		value = "1";
 | 
			
		||||
	else if (v2)
 | 
			
		||||
		changes[0].value = "2";
 | 
			
		||||
		value = "2";
 | 
			
		||||
	else
 | 
			
		||||
		changes[0].value = "none";
 | 
			
		||||
		value = "none";
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, NULL, changes, array_size(changes));
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./version-send", NB_OP_MODIFY, value);
 | 
			
		||||
 | 
			
		||||
	return nb_cli_apply_changes(vty, "./frr-ripd:rip");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFPY (no_ip_rip_send_version,
 | 
			
		||||
@ -980,15 +743,9 @@ DEFPY (no_ip_rip_send_version,
 | 
			
		||||
       "RIP version 2\n"
 | 
			
		||||
       "None\n")
 | 
			
		||||
{
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./frr-ripd:rip/version-send",
 | 
			
		||||
			.operation = NB_OP_MODIFY,
 | 
			
		||||
			.value = NULL,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./version-send", NB_OP_MODIFY, NULL);
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, NULL, changes, array_size(changes));
 | 
			
		||||
	return nb_cli_apply_changes(vty, "./frr-ripd:rip");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cli_show_ip_rip_send_version(struct vty *vty, struct lyd_node *dnode,
 | 
			
		||||
@ -1029,26 +786,21 @@ DEFPY (ip_rip_authentication_mode,
 | 
			
		||||
       "Old ripd compatible\n"
 | 
			
		||||
       "Clear text authentication\n")
 | 
			
		||||
{
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./frr-ripd:rip/authentication-scheme/mode",
 | 
			
		||||
			.operation = NB_OP_MODIFY,
 | 
			
		||||
			.value = strmatch(mode, "md5") ? "md5" : "plain-text",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./frr-ripd:rip/authentication-scheme/md5-auth-length",
 | 
			
		||||
			.operation = NB_OP_MODIFY,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	const char *value = NULL;
 | 
			
		||||
 | 
			
		||||
	if (auth_length) {
 | 
			
		||||
		if (strmatch(auth_length, "rfc"))
 | 
			
		||||
			changes[1].value = "16";
 | 
			
		||||
			value = "16";
 | 
			
		||||
		else
 | 
			
		||||
			changes[1].value = "20";
 | 
			
		||||
			value = "20";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, NULL, changes, array_size(changes));
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./authentication-scheme/mode", NB_OP_MODIFY,
 | 
			
		||||
			      strmatch(mode, "md5") ? "md5" : "plain-text");
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./authentication-scheme/md5-auth-length",
 | 
			
		||||
			      NB_OP_MODIFY, value);
 | 
			
		||||
 | 
			
		||||
	return nb_cli_apply_changes(vty, "./frr-ripd:rip");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFPY (no_ip_rip_authentication_mode,
 | 
			
		||||
@ -1065,18 +817,12 @@ DEFPY (no_ip_rip_authentication_mode,
 | 
			
		||||
       "Old ripd compatible\n"
 | 
			
		||||
       "Clear text authentication\n")
 | 
			
		||||
{
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./frr-ripd:rip/authentication-scheme/mode",
 | 
			
		||||
			.operation = NB_OP_MODIFY,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./frr-ripd:rip/authentication-scheme/md5-auth-length",
 | 
			
		||||
			.operation = NB_OP_MODIFY,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./authentication-scheme/mode", NB_OP_MODIFY,
 | 
			
		||||
			      NULL);
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./authentication-scheme/md5-auth-length",
 | 
			
		||||
			      NB_OP_MODIFY, NULL);
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, NULL, changes, array_size(changes));
 | 
			
		||||
	return nb_cli_apply_changes(vty, "./frr-ripd:rip");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cli_show_ip_rip_authentication_scheme(struct vty *vty,
 | 
			
		||||
@ -1117,14 +863,6 @@ DEFPY (ip_rip_authentication_string,
 | 
			
		||||
       "Authentication string\n"
 | 
			
		||||
       "Authentication string\n")
 | 
			
		||||
{
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./frr-ripd:rip/authentication-password",
 | 
			
		||||
			.operation = NB_OP_MODIFY,
 | 
			
		||||
			.value = password,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	if (strlen(password) > 16) {
 | 
			
		||||
		vty_out(vty,
 | 
			
		||||
			"%% RIPv2 authentication string must be shorter than 16\n");
 | 
			
		||||
@ -1138,7 +876,10 @@ DEFPY (ip_rip_authentication_string,
 | 
			
		||||
		return CMD_WARNING_CONFIG_FAILED;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, NULL, changes, array_size(changes));
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./authentication-password", NB_OP_MODIFY,
 | 
			
		||||
			      password);
 | 
			
		||||
 | 
			
		||||
	return nb_cli_apply_changes(vty, "./frr-ripd:rip");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFPY (no_ip_rip_authentication_string,
 | 
			
		||||
@ -1151,14 +892,10 @@ DEFPY (no_ip_rip_authentication_string,
 | 
			
		||||
       "Authentication string\n"
 | 
			
		||||
       "Authentication string\n")
 | 
			
		||||
{
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./frr-ripd:rip/authentication-password",
 | 
			
		||||
			.operation = NB_OP_DELETE,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./authentication-password", NB_OP_MODIFY,
 | 
			
		||||
			      NULL);
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, NULL, changes, array_size(changes));
 | 
			
		||||
	return nb_cli_apply_changes(vty, "./frr-ripd:rip");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cli_show_ip_rip_authentication_string(struct vty *vty,
 | 
			
		||||
@ -1181,14 +918,6 @@ DEFPY (ip_rip_authentication_key_chain,
 | 
			
		||||
       "Authentication key-chain\n"
 | 
			
		||||
       "name of key-chain\n")
 | 
			
		||||
{
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./frr-ripd:rip/authentication-key-chain",
 | 
			
		||||
			.operation = NB_OP_MODIFY,
 | 
			
		||||
			.value = keychain,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	if (yang_dnode_exists(vty->candidate_config->dnode, "%s%s",
 | 
			
		||||
			      VTY_CURR_XPATH,
 | 
			
		||||
			      "/frr-ripd:rip/authentication-password")) {
 | 
			
		||||
@ -1196,7 +925,10 @@ DEFPY (ip_rip_authentication_key_chain,
 | 
			
		||||
		return CMD_WARNING_CONFIG_FAILED;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, NULL, changes, array_size(changes));
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./authentication-key-chain", NB_OP_MODIFY,
 | 
			
		||||
			      keychain);
 | 
			
		||||
 | 
			
		||||
	return nb_cli_apply_changes(vty, "./frr-ripd:rip");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFPY (no_ip_rip_authentication_key_chain,
 | 
			
		||||
@ -1209,14 +941,10 @@ DEFPY (no_ip_rip_authentication_key_chain,
 | 
			
		||||
       "Authentication key-chain\n"
 | 
			
		||||
       "name of key-chain\n")
 | 
			
		||||
{
 | 
			
		||||
	struct cli_config_change changes[] = {
 | 
			
		||||
		{
 | 
			
		||||
			.xpath = "./frr-ripd:rip/authentication-key-chain",
 | 
			
		||||
			.operation = NB_OP_DELETE,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	nb_cli_enqueue_change(vty, "./authentication-key-chain", NB_OP_DELETE,
 | 
			
		||||
			      NULL);
 | 
			
		||||
 | 
			
		||||
	return nb_cli_cfg_change(vty, NULL, changes, array_size(changes));
 | 
			
		||||
	return nb_cli_apply_changes(vty, "./frr-ripd:rip");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cli_show_ip_rip_authentication_key_chain(struct vty *vty,
 | 
			
		||||
@ -1252,16 +980,13 @@ void rip_cli_init(void)
 | 
			
		||||
	install_element(RIP_NODE, &rip_distance_cmd);
 | 
			
		||||
	install_element(RIP_NODE, &no_rip_distance_cmd);
 | 
			
		||||
	install_element(RIP_NODE, &rip_distance_source_cmd);
 | 
			
		||||
	install_element(RIP_NODE, &no_rip_distance_source_cmd);
 | 
			
		||||
	install_element(RIP_NODE, &rip_neighbor_cmd);
 | 
			
		||||
	install_element(RIP_NODE, &rip_network_prefix_cmd);
 | 
			
		||||
	install_element(RIP_NODE, &rip_network_if_cmd);
 | 
			
		||||
	install_element(RIP_NODE, &rip_offset_list_cmd);
 | 
			
		||||
	install_element(RIP_NODE, &no_rip_offset_list_cmd);
 | 
			
		||||
	install_element(RIP_NODE, &rip_passive_default_cmd);
 | 
			
		||||
	install_element(RIP_NODE, &rip_passive_interface_cmd);
 | 
			
		||||
	install_element(RIP_NODE, &rip_redistribute_cmd);
 | 
			
		||||
	install_element(RIP_NODE, &no_rip_redistribute_cmd);
 | 
			
		||||
	install_element(RIP_NODE, &rip_route_cmd);
 | 
			
		||||
	install_element(RIP_NODE, &rip_timers_cmd);
 | 
			
		||||
	install_element(RIP_NODE, &no_rip_timers_cmd);
 | 
			
		||||
 | 
			
		||||
@ -188,7 +188,7 @@ static int ripd_instance_distance_source_delete(enum nb_event event,
 | 
			
		||||
	if (event != NB_EV_APPLY)
 | 
			
		||||
		return NB_OK;
 | 
			
		||||
 | 
			
		||||
	rn = yang_dnode_get_entry(dnode);
 | 
			
		||||
	rn = yang_dnode_get_entry(dnode, true);
 | 
			
		||||
	rdistance = rn->info;
 | 
			
		||||
	if (rdistance->access_list)
 | 
			
		||||
		free(rdistance->access_list);
 | 
			
		||||
@ -216,7 +216,7 @@ ripd_instance_distance_source_distance_modify(enum nb_event event,
 | 
			
		||||
		return NB_OK;
 | 
			
		||||
 | 
			
		||||
	/* Set distance value. */
 | 
			
		||||
	rn = yang_dnode_get_entry(dnode);
 | 
			
		||||
	rn = yang_dnode_get_entry(dnode, true);
 | 
			
		||||
	distance = yang_dnode_get_uint8(dnode, NULL);
 | 
			
		||||
	rdistance = rn->info;
 | 
			
		||||
	rdistance->distance = distance;
 | 
			
		||||
@ -242,7 +242,7 @@ ripd_instance_distance_source_access_list_modify(enum nb_event event,
 | 
			
		||||
	acl_name = yang_dnode_get_string(dnode, NULL);
 | 
			
		||||
 | 
			
		||||
	/* Set access-list */
 | 
			
		||||
	rn = yang_dnode_get_entry(dnode);
 | 
			
		||||
	rn = yang_dnode_get_entry(dnode, true);
 | 
			
		||||
	rdistance = rn->info;
 | 
			
		||||
	if (rdistance->access_list)
 | 
			
		||||
		free(rdistance->access_list);
 | 
			
		||||
@ -262,7 +262,7 @@ ripd_instance_distance_source_access_list_delete(enum nb_event event,
 | 
			
		||||
		return NB_OK;
 | 
			
		||||
 | 
			
		||||
	/* Reset access-list configuration. */
 | 
			
		||||
	rn = yang_dnode_get_entry(dnode);
 | 
			
		||||
	rn = yang_dnode_get_entry(dnode, true);
 | 
			
		||||
	rdistance = rn->info;
 | 
			
		||||
	free(rdistance->access_list);
 | 
			
		||||
	rdistance->access_list = NULL;
 | 
			
		||||
@ -396,7 +396,7 @@ static int ripd_instance_offset_list_delete(enum nb_event event,
 | 
			
		||||
 | 
			
		||||
	direct = yang_dnode_get_enum(dnode, "./direction");
 | 
			
		||||
 | 
			
		||||
	offset = yang_dnode_get_entry(dnode);
 | 
			
		||||
	offset = yang_dnode_get_entry(dnode, true);
 | 
			
		||||
	if (offset->direct[direct].alist_name) {
 | 
			
		||||
		free(offset->direct[direct].alist_name);
 | 
			
		||||
		offset->direct[direct].alist_name = NULL;
 | 
			
		||||
@ -426,7 +426,7 @@ ripd_instance_offset_list_access_list_modify(enum nb_event event,
 | 
			
		||||
	direct = yang_dnode_get_enum(dnode, "../direction");
 | 
			
		||||
	alist_name = yang_dnode_get_string(dnode, NULL);
 | 
			
		||||
 | 
			
		||||
	offset = yang_dnode_get_entry(dnode);
 | 
			
		||||
	offset = yang_dnode_get_entry(dnode, true);
 | 
			
		||||
	if (offset->direct[direct].alist_name)
 | 
			
		||||
		free(offset->direct[direct].alist_name);
 | 
			
		||||
	offset->direct[direct].alist_name = strdup(alist_name);
 | 
			
		||||
@ -451,7 +451,7 @@ static int ripd_instance_offset_list_metric_modify(enum nb_event event,
 | 
			
		||||
	direct = yang_dnode_get_enum(dnode, "../direction");
 | 
			
		||||
	metric = yang_dnode_get_uint8(dnode, NULL);
 | 
			
		||||
 | 
			
		||||
	offset = yang_dnode_get_entry(dnode);
 | 
			
		||||
	offset = yang_dnode_get_entry(dnode, true);
 | 
			
		||||
	offset->direct[direct].metric = metric;
 | 
			
		||||
 | 
			
		||||
	return NB_OK;
 | 
			
		||||
@ -791,7 +791,7 @@ static int lib_interface_rip_split_horizon_modify(enum nb_event event,
 | 
			
		||||
	if (event != NB_EV_APPLY)
 | 
			
		||||
		return NB_OK;
 | 
			
		||||
 | 
			
		||||
	ifp = yang_dnode_get_entry(dnode);
 | 
			
		||||
	ifp = yang_dnode_get_entry(dnode, true);
 | 
			
		||||
	ri = ifp->info;
 | 
			
		||||
	ri->split_horizon = yang_dnode_get_enum(dnode, NULL);
 | 
			
		||||
 | 
			
		||||
@ -811,7 +811,7 @@ static int lib_interface_rip_v2_broadcast_modify(enum nb_event event,
 | 
			
		||||
	if (event != NB_EV_APPLY)
 | 
			
		||||
		return NB_OK;
 | 
			
		||||
 | 
			
		||||
	ifp = yang_dnode_get_entry(dnode);
 | 
			
		||||
	ifp = yang_dnode_get_entry(dnode, true);
 | 
			
		||||
	ri = ifp->info;
 | 
			
		||||
	ri->v2_broadcast = yang_dnode_get_bool(dnode, NULL);
 | 
			
		||||
 | 
			
		||||
@ -832,7 +832,7 @@ lib_interface_rip_version_receive_modify(enum nb_event event,
 | 
			
		||||
	if (event != NB_EV_APPLY)
 | 
			
		||||
		return NB_OK;
 | 
			
		||||
 | 
			
		||||
	ifp = yang_dnode_get_entry(dnode);
 | 
			
		||||
	ifp = yang_dnode_get_entry(dnode, true);
 | 
			
		||||
	ri = ifp->info;
 | 
			
		||||
	ri->ri_receive = yang_dnode_get_enum(dnode, NULL);
 | 
			
		||||
 | 
			
		||||
@ -852,7 +852,7 @@ static int lib_interface_rip_version_send_modify(enum nb_event event,
 | 
			
		||||
	if (event != NB_EV_APPLY)
 | 
			
		||||
		return NB_OK;
 | 
			
		||||
 | 
			
		||||
	ifp = yang_dnode_get_entry(dnode);
 | 
			
		||||
	ifp = yang_dnode_get_entry(dnode, true);
 | 
			
		||||
	ri = ifp->info;
 | 
			
		||||
	ri->ri_send = yang_dnode_get_enum(dnode, NULL);
 | 
			
		||||
 | 
			
		||||
@ -872,7 +872,7 @@ static int lib_interface_rip_authentication_scheme_mode_modify(
 | 
			
		||||
	if (event != NB_EV_APPLY)
 | 
			
		||||
		return NB_OK;
 | 
			
		||||
 | 
			
		||||
	ifp = yang_dnode_get_entry(dnode);
 | 
			
		||||
	ifp = yang_dnode_get_entry(dnode, true);
 | 
			
		||||
	ri = ifp->info;
 | 
			
		||||
	ri->auth_type = yang_dnode_get_enum(dnode, NULL);
 | 
			
		||||
 | 
			
		||||
@ -893,7 +893,7 @@ static int lib_interface_rip_authentication_scheme_md5_auth_length_modify(
 | 
			
		||||
	if (event != NB_EV_APPLY)
 | 
			
		||||
		return NB_OK;
 | 
			
		||||
 | 
			
		||||
	ifp = yang_dnode_get_entry(dnode);
 | 
			
		||||
	ifp = yang_dnode_get_entry(dnode, true);
 | 
			
		||||
	ri = ifp->info;
 | 
			
		||||
	ri->md5_auth_len = yang_dnode_get_enum(dnode, NULL);
 | 
			
		||||
 | 
			
		||||
@ -909,7 +909,7 @@ static int lib_interface_rip_authentication_scheme_md5_auth_length_delete(
 | 
			
		||||
	if (event != NB_EV_APPLY)
 | 
			
		||||
		return NB_OK;
 | 
			
		||||
 | 
			
		||||
	ifp = yang_dnode_get_entry(dnode);
 | 
			
		||||
	ifp = yang_dnode_get_entry(dnode, true);
 | 
			
		||||
	ri = ifp->info;
 | 
			
		||||
	ri->md5_auth_len = yang_get_default_enum(
 | 
			
		||||
		"%s/authentication-scheme/md5-auth-length", RIP_IFACE);
 | 
			
		||||
@ -931,7 +931,7 @@ lib_interface_rip_authentication_password_modify(enum nb_event event,
 | 
			
		||||
	if (event != NB_EV_APPLY)
 | 
			
		||||
		return NB_OK;
 | 
			
		||||
 | 
			
		||||
	ifp = yang_dnode_get_entry(dnode);
 | 
			
		||||
	ifp = yang_dnode_get_entry(dnode, true);
 | 
			
		||||
	ri = ifp->info;
 | 
			
		||||
	if (ri->auth_str)
 | 
			
		||||
		XFREE(MTYPE_RIP_INTERFACE_STRING, ri->auth_str);
 | 
			
		||||
@ -951,7 +951,7 @@ lib_interface_rip_authentication_password_delete(enum nb_event event,
 | 
			
		||||
	if (event != NB_EV_APPLY)
 | 
			
		||||
		return NB_OK;
 | 
			
		||||
 | 
			
		||||
	ifp = yang_dnode_get_entry(dnode);
 | 
			
		||||
	ifp = yang_dnode_get_entry(dnode, true);
 | 
			
		||||
	ri = ifp->info;
 | 
			
		||||
	XFREE(MTYPE_RIP_INTERFACE_STRING, ri->auth_str);
 | 
			
		||||
 | 
			
		||||
@ -972,7 +972,7 @@ lib_interface_rip_authentication_key_chain_modify(enum nb_event event,
 | 
			
		||||
	if (event != NB_EV_APPLY)
 | 
			
		||||
		return NB_OK;
 | 
			
		||||
 | 
			
		||||
	ifp = yang_dnode_get_entry(dnode);
 | 
			
		||||
	ifp = yang_dnode_get_entry(dnode, true);
 | 
			
		||||
	ri = ifp->info;
 | 
			
		||||
	if (ri->key_chain)
 | 
			
		||||
		XFREE(MTYPE_RIP_INTERFACE_STRING, ri->key_chain);
 | 
			
		||||
@ -992,7 +992,7 @@ lib_interface_rip_authentication_key_chain_delete(enum nb_event event,
 | 
			
		||||
	if (event != NB_EV_APPLY)
 | 
			
		||||
		return NB_OK;
 | 
			
		||||
 | 
			
		||||
	ifp = yang_dnode_get_entry(dnode);
 | 
			
		||||
	ifp = yang_dnode_get_entry(dnode, true);
 | 
			
		||||
	ri = ifp->info;
 | 
			
		||||
	XFREE(MTYPE_RIP_INTERFACE_STRING, ri->key_chain);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user