diff --git a/configure.ac b/configure.ac index c925509fa..09d57ab0f 100755 --- a/configure.ac +++ b/configure.ac @@ -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 diff --git a/lib/command.c b/lib/command.c index bd000c374..a01aabcc2 100644 --- a/lib/command.c +++ b/lib/command.c @@ -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); diff --git a/lib/if.c b/lib/if.c index e02c89b9a..0fd65da03 100644 --- a/lib/if.c +++ b/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); diff --git a/lib/northbound_cli.c b/lib/northbound_cli.c index 8ae44e72d..94f7bb7c1 100644 --- a/lib/northbound_cli.c +++ b/lib/northbound_cli.c @@ -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, diff --git a/lib/northbound_cli.h b/lib/northbound_cli.h index 7f4a64c01..febcbd86f 100644 --- a/lib/northbound_cli.h +++ b/lib/northbound_cli.h @@ -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); diff --git a/lib/northbound_confd.c b/lib/northbound_confd.c index 8cfa2fe11..ec5e0c32c 100644 --- a/lib/northbound_confd.c +++ b/lib/northbound_confd.c @@ -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; } diff --git a/lib/vty.h b/lib/vty.h index 4c434fb2f..5cc077523 100644 --- a/lib/vty.h +++ b/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]; diff --git a/lib/yang.c b/lib/yang.c index a7a50a46b..757982d36 100644 --- a/lib/yang.c +++ b/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. */ diff --git a/lib/yang.h b/lib/yang.h index b0348e320..c92006007 100644 --- a/lib/yang.h +++ b/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. diff --git a/lib/yang_translator.c b/lib/yang_translator.c index 27b92a0e6..02da3ebd6 100644 --- a/lib/yang_translator.c +++ b/lib/yang_translator.c @@ -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)) { diff --git a/ripd/rip_cli.c b/ripd/rip_cli.c index 510aa6615..e0e5d9589 100644 --- a/ripd/rip_cli.c +++ b/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 /, 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 $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 $direction (0-16)$metric [IFNAME]", + "[no] offset-list WORD$acl $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 /\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); diff --git a/ripd/rip_northbound.c b/ripd/rip_northbound.c index bb32409a2..d1e298c25 100644 --- a/ripd/rip_northbound.c +++ b/ripd/rip_northbound.c @@ -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);