summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/northbound.c7
-rw-r--r--lib/northbound.h10
-rw-r--r--lib/northbound_cli.c59
-rw-r--r--lib/northbound_cli.h34
-rw-r--r--lib/northbound_grpc.cpp61
-rw-r--r--lib/northbound_sysrepo.c65
-rw-r--r--lib/vty.h4
-rw-r--r--ripd/rip_nb_rpcs.c9
-rw-r--r--ripd/ripd.c19
-rw-r--r--ripngd/ripng_nb_rpcs.c9
-rw-r--r--ripngd/ripngd.c19
-rw-r--r--zebra/zebra_nb_rpcs.c50
-rw-r--r--zebra/zebra_vty.c53
13 files changed, 177 insertions, 222 deletions
diff --git a/lib/northbound.c b/lib/northbound.c
index 9a5d67cd1b..57068cc4e0 100644
--- a/lib/northbound.c
+++ b/lib/northbound.c
@@ -1820,14 +1820,11 @@ const void *nb_callback_lookup_next(const struct nb_node *nb_node,
}
int nb_callback_rpc(const struct nb_node *nb_node, const char *xpath,
- const struct list *input, struct list *output, char *errmsg,
- size_t errmsg_len)
+ const struct lyd_node *input, struct lyd_node *output,
+ char *errmsg, size_t errmsg_len)
{
struct nb_cb_rpc_args args = {};
- if (CHECK_FLAG(nb_node->flags, F_NB_NODE_IGNORE_CFG_CBS))
- return 0;
-
DEBUGD(&nb_dbg_cbs_rpc, "northbound RPC: %s", xpath);
args.xpath = xpath;
diff --git a/lib/northbound.h b/lib/northbound.h
index 3bf1eacd61..34d17a587c 100644
--- a/lib/northbound.h
+++ b/lib/northbound.h
@@ -274,11 +274,11 @@ struct nb_cb_rpc_args {
/* XPath of the YANG RPC or action. */
const char *xpath;
- /* Read-only list of input parameters. */
- const struct list *input;
+ /* Read-only "input" tree of the RPC/action. */
+ const struct lyd_node *input;
- /* List of output parameters to be populated by the callback. */
- struct list *output;
+ /* The "output" tree of the RPC/action to be populated by the callback. */
+ struct lyd_node *output;
/* Buffer to store human-readable error message in case of error. */
char *errmsg;
@@ -833,7 +833,7 @@ extern const void *nb_callback_lookup_next(const struct nb_node *nb_node,
const void *parent_list_entry,
const struct yang_list_keys *keys);
extern int nb_callback_rpc(const struct nb_node *nb_node, const char *xpath,
- const struct list *input, struct list *output,
+ const struct lyd_node *input, struct lyd_node *output,
char *errmsg, size_t errmsg_len);
extern void nb_callback_notify(const struct nb_node *nb_node, const char *xpath,
struct lyd_node *dnode);
diff --git a/lib/northbound_cli.c b/lib/northbound_cli.c
index 8809ec2ad8..5be64f0134 100644
--- a/lib/northbound_cli.c
+++ b/lib/northbound_cli.c
@@ -275,10 +275,31 @@ int nb_cli_apply_changes_clear_pending(struct vty *vty,
return nb_cli_apply_changes_internal(vty, xpath_base_abs, true);
}
-int nb_cli_rpc(struct vty *vty, const char *xpath, struct list *input,
- struct list *output)
+int nb_cli_rpc_enqueue(struct vty *vty, const char *xpath, const char *value)
+{
+ struct nb_cfg_change *param;
+
+ if (vty->num_rpc_params == VTY_MAXCFGCHANGES) {
+ /* Not expected to happen. */
+ vty_out(vty,
+ "%% Exceeded the maximum number of params (%u) for a single command\n\n",
+ VTY_MAXCFGCHANGES);
+ return CMD_WARNING;
+ }
+
+ param = &vty->rpc_params[vty->num_rpc_params++];
+ strlcpy(param->xpath, xpath, sizeof(param->xpath));
+ param->value = value;
+
+ return CMD_SUCCESS;
+}
+
+int nb_cli_rpc(struct vty *vty, const char *xpath, struct lyd_node **output_p)
{
struct nb_node *nb_node;
+ struct lyd_node *input = NULL;
+ struct lyd_node *output = NULL;
+ LY_ERR err;
int ret;
char errmsg[BUFSIZ] = {0};
@@ -289,12 +310,46 @@ int nb_cli_rpc(struct vty *vty, const char *xpath, struct list *input,
return CMD_WARNING;
}
+ /* create input tree */
+ err = lyd_new_path2(NULL, ly_native_ctx, xpath, NULL, 0, 0, 0, NULL,
+ &input);
+ assert(err == LY_SUCCESS);
+
+ for (size_t i = 0; i < vty->num_rpc_params; i++) {
+ err = lyd_new_path(input, ly_native_ctx,
+ vty->rpc_params[i].xpath,
+ vty->rpc_params[i].value, 0, NULL);
+ assert(err == LY_SUCCESS);
+ }
+
+ /* validate input tree to create implicit defaults */
+ err = lyd_validate_op(input, NULL, LYD_TYPE_RPC_YANG, NULL);
+ assert(err == LY_SUCCESS);
+
+ /* create output tree root for population in the callback */
+ err = lyd_new_path2(NULL, ly_native_ctx, xpath, NULL, 0, 0, 0, NULL,
+ &output);
+ assert(err == LY_SUCCESS);
+
ret = nb_callback_rpc(nb_node, xpath, input, output, errmsg,
sizeof(errmsg));
+
+ /* validate output tree to create implicit defaults */
+ err = lyd_validate_op(output, NULL, LYD_TYPE_REPLY_YANG, NULL);
+ assert(err == LY_SUCCESS);
+
+ lyd_free_all(input);
+ vty->num_rpc_params = 0;
+
switch (ret) {
case NB_OK:
+ if (output_p)
+ *output_p = output;
+ else
+ lyd_free_all(output);
return CMD_SUCCESS;
default:
+ lyd_free_all(output);
if (strlen(errmsg))
vty_show_nb_errors(vty, ret, errmsg);
return CMD_WARNING;
diff --git a/lib/northbound_cli.h b/lib/northbound_cli.h
index 1a45794d45..4c8dc50bd2 100644
--- a/lib/northbound_cli.h
+++ b/lib/northbound_cli.h
@@ -80,7 +80,23 @@ extern int nb_cli_apply_changes(struct vty *vty, const char *xpath_base_fmt,
...) PRINTFRR(2, 3);
/*
- * Execute a YANG RPC or Action.
+ * Add an input child node for an RPC or an action.
+ *
+ * vty
+ * The vty context.
+ *
+ * xpath
+ * XPath of the child being added, relative to the input container.
+ *
+ * value
+ * Value of the child being added. Can be NULL for containers and leafs of
+ * type 'empty'.
+ */
+extern int nb_cli_rpc_enqueue(struct vty *vty, const char *xpath,
+ const char *value);
+
+/*
+ * Execute a YANG RPC or Action using the enqueued input parameters.
*
* vty
* The vty terminal to dump any error.
@@ -88,20 +104,16 @@ extern int nb_cli_apply_changes(struct vty *vty, const char *xpath_base_fmt,
* 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.
+ * output_p
+ * A pointer to the libyang data node that will hold the output data tree.
+ * It can be set to NULL if the caller is not interested in processing the
+ * output. The caller is responsible for freeing the output data tree.
*
* Returns:
* CMD_SUCCESS on success, CMD_WARNING otherwise.
*/
-extern int nb_cli_rpc(struct vty *vty, const char *xpath, struct list *input,
- struct list *output);
+extern int nb_cli_rpc(struct vty *vty, const char *xpath,
+ struct lyd_node **output_p);
/*
* Show CLI commands associated to the given YANG data node.
diff --git a/lib/northbound_grpc.cpp b/lib/northbound_grpc.cpp
index 7957752589..612ec3981b 100644
--- a/lib/northbound_grpc.cpp
+++ b/lib/northbound_grpc.cpp
@@ -1011,12 +1011,11 @@ grpc::Status HandleUnaryExecute(
grpc_debug("%s: entered", __func__);
struct nb_node *nb_node;
- struct list *input_list;
- struct list *output_list;
- struct listnode *node;
- struct yang_data *data;
+ struct lyd_node *input_tree, *output_tree, *child;
const char *xpath;
char errmsg[BUFSIZ] = {0};
+ char path[XPATH_MAXLEN];
+ LY_ERR err;
// Request: string path = 1;
xpath = tag->request.path().c_str();
@@ -1032,40 +1031,66 @@ grpc::Status HandleUnaryExecute(
return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
"Unknown data path");
- input_list = yang_data_list_new();
- output_list = yang_data_list_new();
+ // Create input data tree.
+ err = lyd_new_path2(NULL, ly_native_ctx, xpath, NULL, 0,
+ (LYD_ANYDATA_VALUETYPE)0, 0, NULL, &input_tree);
+ if (err != LY_SUCCESS) {
+ return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
+ "Invalid data path");
+ }
// Read input parameters.
auto input = tag->request.input();
for (const frr::PathValue &pv : input) {
// Request: repeated PathValue input = 2;
- data = yang_data_new(pv.path().c_str(), pv.value().c_str());
- listnode_add(input_list, data);
+ err = lyd_new_path(input_tree, ly_native_ctx, pv.path().c_str(),
+ pv.value().c_str(), 0, NULL);
+ if (err != LY_SUCCESS) {
+ lyd_free_tree(input_tree);
+ return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
+ "Invalid input data");
+ }
+ }
+
+ // Validate input data.
+ err = lyd_validate_op(input_tree, NULL, LYD_TYPE_RPC_YANG, NULL);
+ if (err != LY_SUCCESS) {
+ lyd_free_tree(input_tree);
+ return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
+ "Invalid input data");
+ }
+
+ // Create output data tree.
+ err = lyd_new_path2(NULL, ly_native_ctx, xpath, NULL, 0,
+ (LYD_ANYDATA_VALUETYPE)0, 0, NULL, &output_tree);
+ if (err != LY_SUCCESS) {
+ lyd_free_tree(input_tree);
+ return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
+ "Invalid data path");
}
// Execute callback registered for this XPath.
- if (nb_callback_rpc(nb_node, xpath, input_list, output_list, errmsg,
- sizeof(errmsg))
- != NB_OK) {
+ if (nb_callback_rpc(nb_node, xpath, input_tree, output_tree, errmsg,
+ sizeof(errmsg)) != NB_OK) {
flog_warn(EC_LIB_NB_CB_RPC, "%s: rpc callback failed: %s",
__func__, xpath);
- list_delete(&input_list);
- list_delete(&output_list);
+ lyd_free_tree(input_tree);
+ lyd_free_tree(output_tree);
return grpc::Status(grpc::StatusCode::INTERNAL, "RPC failed");
}
// Process output parameters.
- for (ALL_LIST_ELEMENTS_RO(output_list, node, data)) {
+ LY_LIST_FOR (lyd_child(output_tree), child) {
// Response: repeated PathValue output = 1;
frr::PathValue *pv = tag->response.add_output();
- pv->set_path(data->xpath);
- pv->set_value(data->value);
+ pv->set_path(lyd_path(child, LYD_PATH_STD, path, sizeof(path)));
+ pv->set_value(yang_dnode_get_string(child, NULL));
}
// Release memory.
- list_delete(&input_list);
- list_delete(&output_list);
+ lyd_free_tree(input_tree);
+ lyd_free_tree(output_tree);
return grpc::Status::OK;
}
diff --git a/lib/northbound_sysrepo.c b/lib/northbound_sysrepo.c
index 640334926d..0ec7610a9a 100644
--- a/lib/northbound_sysrepo.c
+++ b/lib/northbound_sysrepo.c
@@ -377,16 +377,11 @@ static int frr_sr_state_cb(sr_session_ctx_t *session, uint32_t sub_id,
return SR_ERR_OK;
}
static int frr_sr_config_rpc_cb(sr_session_ctx_t *session, uint32_t sub_id,
- const char *xpath, const sr_val_t *sr_input,
- const size_t input_cnt, sr_event_t sr_ev,
- uint32_t request_id, sr_val_t **sr_output,
- size_t *sr_output_cnt, void *private_ctx)
+ const char *xpath, const struct lyd_node *input,
+ sr_event_t sr_ev, uint32_t request_id,
+ struct lyd_node *output, void *private_ctx)
{
struct nb_node *nb_node;
- struct list *input;
- struct list *output;
- struct yang_data *data;
- size_t cb_output_cnt;
int ret = SR_ERR_OK;
char errmsg[BUFSIZ] = {0};
@@ -397,19 +392,6 @@ static int frr_sr_config_rpc_cb(sr_session_ctx_t *session, uint32_t sub_id,
return SR_ERR_INTERNAL;
}
- input = yang_data_list_new();
- output = yang_data_list_new();
-
- /* Process input. */
- for (size_t i = 0; i < input_cnt; i++) {
- char value_str[YANG_VALUE_MAXLEN];
-
- sr_val_to_buff(&sr_input[i], value_str, sizeof(value_str));
-
- data = yang_data_new(xpath, value_str);
- listnode_add(input, data);
- }
-
/* Execute callback registered for this XPath. */
if (nb_callback_rpc(nb_node, xpath, input, output, errmsg,
sizeof(errmsg))
@@ -417,44 +399,8 @@ static int frr_sr_config_rpc_cb(sr_session_ctx_t *session, uint32_t sub_id,
flog_warn(EC_LIB_NB_CB_RPC, "%s: rpc callback failed: %s",
__func__, xpath);
ret = SR_ERR_OPERATION_FAILED;
- goto exit;
}
- /* Process output. */
- if (listcount(output) > 0) {
- sr_val_t *values = NULL;
- struct listnode *node;
- int i = 0;
-
- cb_output_cnt = listcount(output);
- ret = sr_new_values(cb_output_cnt, &values);
- if (ret != SR_ERR_OK) {
- flog_err(EC_LIB_LIBSYSREPO, "%s: sr_new_values(): %s",
- __func__, sr_strerror(ret));
- goto exit;
- }
-
- for (ALL_LIST_ELEMENTS_RO(output, node, data)) {
- if (yang_data_frr2sr(data, &values[i++]) != 0) {
- flog_err(
- EC_LIB_SYSREPO_DATA_CONVERT,
- "%s: failed to convert data to Sysrepo format",
- __func__);
- ret = SR_ERR_INTERNAL;
- sr_free_values(values, cb_output_cnt);
- goto exit;
- }
- }
-
- *sr_output = values;
- *sr_output_cnt = cb_output_cnt;
- }
-
-exit:
- /* Release memory. */
- list_delete(&input);
- list_delete(&output);
-
return ret;
}
@@ -579,8 +525,9 @@ static int frr_sr_subscribe_rpc(const struct lysc_node *snode, void *arg)
DEBUGD(&nb_dbg_client_sysrepo, "sysrepo: providing RPC to '%s'",
nb_node->xpath);
- ret = sr_rpc_subscribe(session, nb_node->xpath, frr_sr_config_rpc_cb,
- NULL, 0, 0, &module->sr_subscription);
+ ret = sr_rpc_subscribe_tree(session, nb_node->xpath,
+ frr_sr_config_rpc_cb, NULL, 0, 0,
+ &module->sr_subscription);
if (ret != SR_ERR_OK)
flog_err(EC_LIB_LIBSYSREPO, "sr_rpc_subscribe(): %s",
sr_strerror(ret));
diff --git a/lib/vty.h b/lib/vty.h
index 0e0c92c336..a51cee76fb 100644
--- a/lib/vty.h
+++ b/lib/vty.h
@@ -122,6 +122,10 @@ struct vty {
size_t num_cfg_changes;
struct nb_cfg_change cfg_changes[VTY_MAXCFGCHANGES];
+ /* Input parameters */
+ size_t num_rpc_params;
+ struct nb_cfg_change rpc_params[VTY_MAXCFGCHANGES];
+
/* XPath of the current node */
int xpath_index;
char xpath[VTY_MAXDEPTH][XPATH_MAXLEN];
diff --git a/ripd/rip_nb_rpcs.c b/ripd/rip_nb_rpcs.c
index bbe3d0f0f8..5d3d7145b1 100644
--- a/ripd/rip_nb_rpcs.c
+++ b/ripd/rip_nb_rpcs.c
@@ -68,12 +68,11 @@ static void clear_rip_route(struct rip *rip)
int clear_rip_route_rpc(struct nb_cb_rpc_args *args)
{
struct rip *rip;
- struct yang_data *yang_vrf;
- yang_vrf = yang_data_list_find(args->input, "%s/%s", args->xpath,
- "input/vrf");
- if (yang_vrf) {
- rip = rip_lookup_by_vrf_name(yang_vrf->value);
+ if (args->input && yang_dnode_exists(args->input, "vrf")) {
+ const char *name = yang_dnode_get_string(args->input, "vrf");
+
+ rip = rip_lookup_by_vrf_name(name);
if (rip)
clear_rip_route(rip);
} else {
diff --git a/ripd/ripd.c b/ripd/ripd.c
index e3220a9267..4640880e49 100644
--- a/ripd/ripd.c
+++ b/ripd/ripd.c
@@ -3267,23 +3267,10 @@ DEFPY_YANG (clear_ip_rip,
"Clear IP RIP database\n"
VRF_CMD_HELP_STR)
{
- struct list *input;
- int ret;
-
- input = list_new();
- if (vrf) {
- struct yang_data *yang_vrf;
-
- yang_vrf = yang_data_new("/frr-ripd:clear-rip-route/input/vrf",
- vrf);
- listnode_add(input, yang_vrf);
- }
-
- ret = nb_cli_rpc(vty, "/frr-ripd:clear-rip-route", input, NULL);
-
- list_delete(&input);
+ if (vrf)
+ nb_cli_rpc_enqueue(vty, "vrf", vrf);
- return ret;
+ return nb_cli_rpc(vty, "/frr-ripd:clear-rip-route", NULL);
}
/* Distribute-list update functions. */
diff --git a/ripngd/ripng_nb_rpcs.c b/ripngd/ripng_nb_rpcs.c
index b23572d492..5498bbfc8e 100644
--- a/ripngd/ripng_nb_rpcs.c
+++ b/ripngd/ripng_nb_rpcs.c
@@ -70,12 +70,11 @@ static void clear_ripng_route(struct ripng *ripng)
int clear_ripng_route_rpc(struct nb_cb_rpc_args *args)
{
struct ripng *ripng;
- struct yang_data *yang_vrf;
- yang_vrf = yang_data_list_find(args->input, "%s/%s", args->xpath,
- "input/vrf");
- if (yang_vrf) {
- ripng = ripng_lookup_by_vrf_name(yang_vrf->value);
+ if (args->input && yang_dnode_exists(args->input, "vrf")) {
+ const char *name = yang_dnode_get_string(args->input, "vrf");
+
+ ripng = ripng_lookup_by_vrf_name(name);
if (ripng)
clear_ripng_route(ripng);
} else {
diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c
index 80b9013e0f..e26acf59d1 100644
--- a/ripngd/ripngd.c
+++ b/ripngd/ripngd.c
@@ -2244,23 +2244,10 @@ DEFPY_YANG (clear_ipv6_rip,
"Clear IPv6 RIP database\n"
VRF_CMD_HELP_STR)
{
- struct list *input;
- int ret;
-
- input = list_new();
- if (vrf) {
- struct yang_data *yang_vrf;
-
- yang_vrf = yang_data_new(
- "/frr-ripngd:clear-ripng-route/input/vrf", vrf);
- listnode_add(input, yang_vrf);
- }
-
- ret = nb_cli_rpc(vty, "/frr-ripngd:clear-ripng-route", input, NULL);
-
- list_delete(&input);
+ if (vrf)
+ nb_cli_rpc_enqueue(vty, "vrf", vrf);
- return ret;
+ return nb_cli_rpc(vty, "/frr-ripngd:clear-ripng-route", NULL);
}
/* Update ECMP routes to zebra when ECMP is disabled. */
diff --git a/zebra/zebra_nb_rpcs.c b/zebra/zebra_nb_rpcs.c
index 083ab3fde6..938193df2f 100644
--- a/zebra/zebra_nb_rpcs.c
+++ b/zebra/zebra_nb_rpcs.c
@@ -20,48 +20,30 @@ int clear_evpn_dup_addr_rpc(struct nb_cb_rpc_args *args)
{
struct zebra_vrf *zvrf;
int ret = NB_OK;
- struct yang_data *yang_dup_choice = NULL, *yang_dup_vni = NULL,
- *yang_dup_ip = NULL, *yang_dup_mac = NULL;
-
- yang_dup_choice = yang_data_list_find(args->input, "%s/%s", args->xpath,
- "input/clear-dup-choice");
zvrf = zebra_vrf_get_evpn();
- if (yang_dup_choice
- && strcmp(yang_dup_choice->value, "all-case") == 0) {
+ if (yang_dnode_exists(args->input, "all-vnis")) {
zebra_vxlan_clear_dup_detect_vni_all(zvrf);
} else {
- vni_t vni;
+ vni_t vni = yang_dnode_get_uint32(args->input, "vni-id");
struct ipaddr host_ip = {.ipa_type = IPADDR_NONE};
struct ethaddr mac;
- yang_dup_vni = yang_data_list_find(
- args->input, "%s/%s", args->xpath,
- "input/clear-dup-choice/single-case/vni-id");
- if (yang_dup_vni) {
- vni = yang_str2uint32(yang_dup_vni->value);
-
- yang_dup_mac = yang_data_list_find(
- args->input, "%s/%s", args->xpath,
- "input/clear-dup-choice/single-case/vni-id/mac-addr");
- yang_dup_ip = yang_data_list_find(
- args->input, "%s/%s", args->xpath,
- "input/clear-dup-choice/single-case/vni-id/vni-ipaddr");
-
- if (yang_dup_mac) {
- yang_str2mac(yang_dup_mac->value, &mac);
- ret = zebra_vxlan_clear_dup_detect_vni_mac(
- zvrf, vni, &mac, args->errmsg,
- args->errmsg_len);
- } else if (yang_dup_ip) {
- yang_str2ip(yang_dup_ip->value, &host_ip);
- ret = zebra_vxlan_clear_dup_detect_vni_ip(
- zvrf, vni, &host_ip, args->errmsg,
- args->errmsg_len);
- } else
- ret = zebra_vxlan_clear_dup_detect_vni(zvrf,
- vni);
+ if (yang_dnode_exists(args->input, "mac-addr")) {
+ yang_dnode_get_mac(&mac, args->input, "mac-addr");
+ ret = zebra_vxlan_clear_dup_detect_vni_mac(zvrf, vni,
+ &mac,
+ args->errmsg,
+ args->errmsg_len);
+ } else if (yang_dnode_exists(args->input, "vni-ipaddr")) {
+ yang_dnode_get_ip(&host_ip, args->input, "vni-ipaddr");
+ ret = zebra_vxlan_clear_dup_detect_vni_ip(zvrf, vni,
+ &host_ip,
+ args->errmsg,
+ args->errmsg_len);
+ } else {
+ ret = zebra_vxlan_clear_dup_detect_vni(zvrf, vni);
}
}
if (ret < 0)
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 0b5362094e..bdbb059e56 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -3553,56 +3553,17 @@ DEFPY (clear_evpn_dup_addr,
"IPv4 address\n"
"IPv6 address\n")
{
- struct ipaddr host_ip = {.ipa_type = IPADDR_NONE };
- int ret = CMD_SUCCESS;
- struct list *input;
- struct yang_data *yang_dup = NULL, *yang_dup_ip = NULL,
- *yang_dup_mac = NULL;
-
- input = list_new();
-
if (!vni_str) {
- yang_dup = yang_data_new(
- "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice",
- "all-case");
+ nb_cli_rpc_enqueue(vty, "all-vnis", NULL);
} else {
- yang_dup = yang_data_new_uint32(
- "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id",
- vni);
- if (!is_zero_mac(&mac->eth_addr)) {
- yang_dup_mac = yang_data_new_mac(
- "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/mac-addr",
- &mac->eth_addr);
- if (yang_dup_mac)
- listnode_add(input, yang_dup_mac);
- } else if (ip) {
- if (sockunion_family(ip) == AF_INET) {
- host_ip.ipa_type = IPADDR_V4;
- host_ip.ipaddr_v4.s_addr = sockunion2ip(ip);
- } else {
- host_ip.ipa_type = IPADDR_V6;
- memcpy(&host_ip.ipaddr_v6, &ip->sin6.sin6_addr,
- sizeof(struct in6_addr));
- }
-
- yang_dup_ip = yang_data_new_ip(
- "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/vni-ipaddr",
- &host_ip);
-
- if (yang_dup_ip)
- listnode_add(input, yang_dup_ip);
- }
- }
-
- if (yang_dup) {
- listnode_add(input, yang_dup);
- ret = nb_cli_rpc(vty, "/frr-zebra:clear-evpn-dup-addr", input,
- NULL);
+ nb_cli_rpc_enqueue(vty, "vni-id", vni_str);
+ if (mac_str)
+ nb_cli_rpc_enqueue(vty, "mac-addr", mac_str);
+ else if (ip_str)
+ nb_cli_rpc_enqueue(vty, "vni-ipaddr", ip_str);
}
- list_delete(&input);
-
- return ret;
+ return nb_cli_rpc(vty, "/frr-zebra:clear-evpn-dup-addr", NULL);
}
DEFPY_HIDDEN (evpn_accept_bgp_seq,