summaryrefslogtreecommitdiff
path: root/ripngd/ripng_cli.c
diff options
context:
space:
mode:
Diffstat (limited to 'ripngd/ripng_cli.c')
-rw-r--r--ripngd/ripng_cli.c381
1 files changed, 284 insertions, 97 deletions
diff --git a/ripngd/ripng_cli.c b/ripngd/ripng_cli.c
index 5e59dfd2c4..4806861fe0 100644
--- a/ripngd/ripng_cli.c
+++ b/ripngd/ripng_cli.c
@@ -8,6 +8,7 @@
#include <zebra.h>
#include "if.h"
+#include "if_rmap.h"
#include "vrf.h"
#include "log.h"
#include "prefix.h"
@@ -73,7 +74,7 @@ void cli_show_router_ripng(struct vty *vty, const struct lyd_node *dnode,
{
const char *vrf_name;
- vrf_name = yang_dnode_get_string(dnode, "./vrf");
+ vrf_name = yang_dnode_get_string(dnode, "vrf");
vty_out(vty, "!\n");
vty_out(vty, "router ripng");
@@ -82,17 +83,40 @@ void cli_show_router_ripng(struct vty *vty, const struct lyd_node *dnode,
vty_out(vty, "\n");
}
+void cli_show_end_router_ripng(struct vty *vty, const struct lyd_node *dnode)
+{
+ vty_out(vty, "exit\n");
+}
+
/*
* XPath: /frr-ripngd:ripngd/instance/allow-ecmp
*/
-DEFPY_YANG (ripng_allow_ecmp,
- ripng_allow_ecmp_cmd,
- "[no] allow-ecmp",
- NO_STR
- "Allow Equal Cost MultiPath\n")
+DEFUN_YANG (ripng_allow_ecmp,
+ ripng_allow_ecmp_cmd,
+ "allow-ecmp [" CMD_RANGE_STR(1, MULTIPATH_NUM) "]",
+ "Allow Equal Cost MultiPath\n"
+ "Number of paths\n")
+{
+ int idx_number = 0;
+ char mpaths[3] = {};
+ uint32_t paths = MULTIPATH_NUM;
+
+ if (argv_find(argv, argc, CMD_RANGE_STR(1, MULTIPATH_NUM), &idx_number))
+ paths = strtol(argv[idx_number]->arg, NULL, 10);
+ snprintf(mpaths, sizeof(mpaths), "%u", paths);
+
+ nb_cli_enqueue_change(vty, "./allow-ecmp", NB_OP_MODIFY, mpaths);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFUN_YANG (no_ripng_allow_ecmp,
+ no_ripng_allow_ecmp_cmd,
+ "no allow-ecmp [" CMD_RANGE_STR(1, MULTIPATH_NUM) "]", NO_STR
+ "Allow Equal Cost MultiPath\n"
+ "Number of paths\n")
{
- nb_cli_enqueue_change(vty, "./allow-ecmp", NB_OP_MODIFY,
- no ? "false" : "true");
+ nb_cli_enqueue_change(vty, "./allow-ecmp", NB_OP_MODIFY, 0);
return nb_cli_apply_changes(vty, NULL);
}
@@ -100,10 +124,14 @@ DEFPY_YANG (ripng_allow_ecmp,
void cli_show_ripng_allow_ecmp(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
- if (!yang_dnode_get_bool(dnode, NULL))
- vty_out(vty, " no");
+ uint8_t paths;
+
+ paths = yang_dnode_get_uint8(dnode, NULL);
- vty_out(vty, " allow-ecmp\n");
+ if (!paths)
+ vty_out(vty, " no allow-ecmp\n");
+ else
+ vty_out(vty, " allow-ecmp %d\n", paths);
}
/*
@@ -177,8 +205,12 @@ DEFPY_YANG (ripng_network_prefix,
"RIPng enable on specified interface or network.\n"
"IPv6 network\n")
{
- nb_cli_enqueue_change(vty, "./network",
- no ? NB_OP_DESTROY : NB_OP_CREATE, network_str);
+ char xpath[XPATH_MAXLEN];
+
+ snprintf(xpath, sizeof(xpath), "./network[.='%s']", network_str);
+
+ nb_cli_enqueue_change(vty, xpath, no ? NB_OP_DESTROY : NB_OP_CREATE,
+ NULL);
return nb_cli_apply_changes(vty, NULL);
}
@@ -200,8 +232,12 @@ DEFPY_YANG (ripng_network_if,
"RIPng enable on specified interface or network.\n"
"Interface name\n")
{
- nb_cli_enqueue_change(vty, "./interface",
- no ? NB_OP_DESTROY : NB_OP_CREATE, network);
+ char xpath[XPATH_MAXLEN];
+
+ snprintf(xpath, sizeof(xpath), "./interface[.='%s']", network);
+
+ nb_cli_enqueue_change(vty, xpath, no ? NB_OP_DESTROY : NB_OP_CREATE,
+ NULL);
return nb_cli_apply_changes(vty, NULL);
}
@@ -245,12 +281,12 @@ void cli_show_ripng_offset_list(struct vty *vty, const struct lyd_node *dnode,
{
const char *interface;
- interface = yang_dnode_get_string(dnode, "./interface");
+ interface = yang_dnode_get_string(dnode, "interface");
vty_out(vty, " offset-list %s %s %s",
- yang_dnode_get_string(dnode, "./access-list"),
- yang_dnode_get_string(dnode, "./direction"),
- yang_dnode_get_string(dnode, "./metric"));
+ yang_dnode_get_string(dnode, "access-list"),
+ yang_dnode_get_string(dnode, "direction"),
+ yang_dnode_get_string(dnode, "metric"));
if (!strmatch(interface, "*"))
vty_out(vty, " %s", interface);
vty_out(vty, "\n");
@@ -266,8 +302,12 @@ DEFPY_YANG (ripng_passive_interface,
"Suppress routing updates on an interface\n"
"Interface name\n")
{
- nb_cli_enqueue_change(vty, "./passive-interface",
- no ? NB_OP_DESTROY : NB_OP_CREATE, ifname);
+ char xpath[XPATH_MAXLEN];
+
+ snprintf(xpath, sizeof(xpath), "./passive-interface[.='%s']", ifname);
+
+ nb_cli_enqueue_change(vty, xpath, no ? NB_OP_DESTROY : NB_OP_CREATE,
+ ifname);
return nb_cli_apply_changes(vty, NULL);
}
@@ -313,13 +353,13 @@ void cli_show_ripng_redistribute(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " redistribute %s",
- yang_dnode_get_string(dnode, "./protocol"));
- if (yang_dnode_exists(dnode, "./metric"))
+ yang_dnode_get_string(dnode, "protocol"));
+ if (yang_dnode_exists(dnode, "metric"))
vty_out(vty, " metric %s",
- yang_dnode_get_string(dnode, "./metric"));
- if (yang_dnode_exists(dnode, "./route-map"))
+ yang_dnode_get_string(dnode, "metric"));
+ if (yang_dnode_exists(dnode, "route-map"))
vty_out(vty, " route-map %s",
- yang_dnode_get_string(dnode, "./route-map"));
+ yang_dnode_get_string(dnode, "route-map"));
vty_out(vty, "\n");
}
@@ -333,8 +373,12 @@ DEFPY_YANG (ripng_route,
"Static route setup\n"
"Set static RIPng route announcement\n")
{
- nb_cli_enqueue_change(vty, "./static-route",
- no ? NB_OP_DESTROY : NB_OP_CREATE, route_str);
+ char xpath[XPATH_MAXLEN];
+
+ snprintf(xpath, sizeof(xpath), "./static-route[.='%s']", route_str);
+
+ nb_cli_enqueue_change(vty, xpath, no ? NB_OP_DESTROY : NB_OP_CREATE,
+ NULL);
return nb_cli_apply_changes(vty, NULL);
}
@@ -355,9 +399,13 @@ DEFPY_YANG (ripng_aggregate_address,
"Set aggregate RIPng route announcement\n"
"Aggregate network\n")
{
- nb_cli_enqueue_change(vty, "./aggregate-address",
- no ? NB_OP_DESTROY : NB_OP_CREATE,
- aggregate_address_str);
+ char xpath[XPATH_MAXLEN];
+
+ snprintf(xpath, sizeof(xpath), "./aggregate-address[.='%s']",
+ aggregate_address_str);
+
+ nb_cli_enqueue_change(vty, xpath, no ? NB_OP_DESTROY : NB_OP_CREATE,
+ NULL);
return nb_cli_apply_changes(vty, NULL);
}
@@ -413,9 +461,9 @@ void cli_show_ripng_timers(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " timers basic %s %s %s\n",
- yang_dnode_get_string(dnode, "./update-interval"),
- yang_dnode_get_string(dnode, "./holddown-interval"),
- yang_dnode_get_string(dnode, "./flush-interval"));
+ yang_dnode_get_string(dnode, "update-interval"),
+ yang_dnode_get_string(dnode, "holddown-interval"),
+ yang_dnode_get_string(dnode, "flush-interval"));
}
/*
@@ -464,89 +512,142 @@ void cli_show_ipv6_ripng_split_horizon(struct vty *vty,
}
}
-/*
- * XPath: /frr-ripngd:clear-ripng-route
- */
-DEFPY_YANG (clear_ipv6_rip,
- clear_ipv6_rip_cmd,
- "clear ipv6 ripng [vrf WORD]",
- CLEAR_STR
- IPV6_STR
- "Clear IPv6 RIP database\n"
- VRF_CMD_HELP_STR)
+DEFPY_YANG(
+ ripng_ipv6_distribute_list, ripng_ipv6_distribute_list_cmd,
+ "ipv6 distribute-list ACCESSLIST6_NAME$name <in|out>$dir [WORD$ifname]",
+ "IPv6\n"
+ "Filter networks in routing updates\n"
+ "Access-list name\n"
+ "Filter incoming routing updates\n"
+ "Filter outgoing routing updates\n"
+ "Interface name\n")
{
- 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);
- }
+ char xpath[XPATH_MAXLEN];
- ret = nb_cli_rpc(vty, "/frr-ripngd:clear-ripng-route", input, NULL);
+ snprintf(xpath, sizeof(xpath),
+ "./distribute-list[interface='%s']/%s/access-list",
+ ifname ? ifname : "", dir);
+ /* nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL); */
+ nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, name);
+ return nb_cli_apply_changes(vty, NULL);
+}
- list_delete(&input);
+DEFPY_YANG(
+ ripng_ipv6_distribute_list_prefix, ripng_ipv6_distribute_list_prefix_cmd,
+ "ipv6 distribute-list prefix PREFIXLIST6_NAME$name <in|out>$dir [WORD$ifname]",
+ "IPv6\n"
+ "Filter networks in routing updates\n"
+ "Specify a prefix list\n"
+ "Prefix-list name\n"
+ "Filter incoming routing updates\n"
+ "Filter outgoing routing updates\n"
+ "Interface name\n")
+{
+ char xpath[XPATH_MAXLEN];
- return ret;
+ snprintf(xpath, sizeof(xpath),
+ "./distribute-list[interface='%s']/%s/prefix-list",
+ ifname ? ifname : "", dir);
+ /* nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL); */
+ nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, name);
+ return nb_cli_apply_changes(vty, NULL);
}
-DEFUN (ripng_ipv6_distribute_list,
- ripng_ipv6_distribute_list_cmd,
- "ipv6 distribute-list [prefix] ACCESSLIST6_NAME <in|out> [WORD]",
- "IPv6\n"
- "Filter networks in routing updates\n"
- "Specify a prefix\n"
- "Access-list name\n"
- "Filter incoming routing updates\n"
- "Filter outgoing routing updates\n"
- "Interface name\n")
+DEFPY_YANG(no_ripng_ipv6_distribute_list,
+ no_ripng_ipv6_distribute_list_cmd,
+ "no ipv6 distribute-list [ACCESSLIST6_NAME$name] <in|out>$dir [WORD$ifname]",
+ NO_STR
+ "IPv6\n"
+ "Filter networks in routing updates\n"
+ "Access-list name\n"
+ "Filter incoming routing updates\n"
+ "Filter outgoing routing updates\n"
+ "Interface name\n")
{
- const char *ifname = NULL;
- int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0;
-
- if (argv[argc - 1]->type == VARIABLE_TKN)
- ifname = argv[argc - 1]->arg;
+ const struct lyd_node *value_node;
+ char xpath[XPATH_MAXLEN];
- return distribute_list_parser(prefix, false, argv[3 + prefix]->text,
- argv[2 + prefix]->arg, ifname);
+ snprintf(xpath, sizeof(xpath),
+ "./distribute-list[interface='%s']/%s/access-list",
+ ifname ? ifname : "", dir);
+ /*
+ * See if the user has specified specific list so check it exists.
+ *
+ * NOTE: Other FRR CLI commands do not do this sort of verification and
+ * there may be an official decision not to.
+ */
+ if (name) {
+ value_node = yang_dnode_getf(vty->candidate_config->dnode, "%s/%s",
+ VTY_CURR_XPATH, xpath);
+ if (!value_node || strcmp(name, lyd_get_value(value_node))) {
+ vty_out(vty, "distribute list doesn't exist\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ }
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
}
-DEFUN (ripng_no_ipv6_distribute_list,
- ripng_no_ipv6_distribute_list_cmd,
- "no ipv6 distribute-list [prefix] ACCESSLIST6_NAME <in|out> [WORD]",
- NO_STR
- "IPv6\n"
- "Filter networks in routing updates\n"
- "Specify a prefix\n"
- "Access-list name\n"
- "Filter incoming routing updates\n"
- "Filter outgoing routing updates\n"
- "Interface name\n")
+DEFPY_YANG(no_ripng_ipv6_distribute_list_prefix,
+ no_ripng_ipv6_distribute_list_prefix_cmd,
+ "no ipv6 distribute-list prefix [PREFIXLIST6_NAME$name] <in|out>$dir [WORD$ifname]",
+ NO_STR
+ "IPv6\n"
+ "Filter networks in routing updates\n"
+ "Specify a prefix list\n"
+ "Prefix-list name\n"
+ "Filter incoming routing updates\n"
+ "Filter outgoing routing updates\n"
+ "Interface name\n")
{
- const char *ifname = NULL;
- int prefix = (argv[3]->type == WORD_TKN) ? 1 : 0;
-
- if (argv[argc - 1]->type == VARIABLE_TKN)
- ifname = argv[argc - 1]->arg;
+ const struct lyd_node *value_node;
+ char xpath[XPATH_MAXLEN];
- return distribute_list_no_parser(vty, prefix, false,
- argv[4 + prefix]->text,
- argv[3 + prefix]->arg, ifname);
+ snprintf(xpath, sizeof(xpath),
+ "./distribute-list[interface='%s']/%s/prefix-list",
+ ifname ? ifname : "", dir);
+ /*
+ * See if the user has specified specific list so check it exists.
+ *
+ * NOTE: Other FRR CLI commands do not do this sort of verification and
+ * there may be an official decision not to.
+ */
+ if (name) {
+ value_node = yang_dnode_getf(vty->candidate_config->dnode, "%s/%s",
+ VTY_CURR_XPATH, xpath);
+ if (!value_node || strcmp(name, lyd_get_value(value_node))) {
+ vty_out(vty, "distribute list doesn't exist\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ }
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
}
+/* RIPng node structure. */
+static struct cmd_node cmd_ripng_node = {
+ .name = "ripng",
+ .node = RIPNG_NODE,
+ .parent_node = CONFIG_NODE,
+ .prompt = "%s(config-router)# ",
+};
+
void ripng_cli_init(void)
{
+ /* Install RIPNG_NODE. */
+ install_node(&cmd_ripng_node);
+ install_default(RIPNG_NODE);
+
install_element(CONFIG_NODE, &router_ripng_cmd);
install_element(CONFIG_NODE, &no_router_ripng_cmd);
install_element(RIPNG_NODE, &ripng_ipv6_distribute_list_cmd);
- install_element(RIPNG_NODE, &ripng_no_ipv6_distribute_list_cmd);
+ install_element(RIPNG_NODE, &ripng_ipv6_distribute_list_prefix_cmd);
+ install_element(RIPNG_NODE, &no_ripng_ipv6_distribute_list_cmd);
+ install_element(RIPNG_NODE, &no_ripng_ipv6_distribute_list_prefix_cmd);
install_element(RIPNG_NODE, &ripng_allow_ecmp_cmd);
+ install_element(RIPNG_NODE, &no_ripng_allow_ecmp_cmd);
install_element(RIPNG_NODE, &ripng_default_information_originate_cmd);
install_element(RIPNG_NODE, &ripng_default_metric_cmd);
install_element(RIPNG_NODE, &no_ripng_default_metric_cmd);
@@ -562,5 +663,91 @@ void ripng_cli_init(void)
install_element(INTERFACE_NODE, &ipv6_ripng_split_horizon_cmd);
- install_element(ENABLE_NODE, &clear_ipv6_rip_cmd);
-}
+ if_rmap_init(RIPNG_NODE);
+}
+
+/* clang-format off */
+const struct frr_yang_module_info frr_ripngd_cli_info = {
+ .name = "frr-ripngd",
+ .ignore_cfg_cbs = true,
+ .nodes = {
+ {
+ .xpath = "/frr-ripngd:ripngd/instance",
+ .cbs.cli_show = cli_show_router_ripng,
+ .cbs.cli_show_end = cli_show_end_router_ripng,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/allow-ecmp",
+ .cbs.cli_show = cli_show_ripng_allow_ecmp,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/default-information-originate",
+ .cbs.cli_show = cli_show_ripng_default_information_originate,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/default-metric",
+ .cbs.cli_show = cli_show_ripng_default_metric,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/network",
+ .cbs.cli_show = cli_show_ripng_network_prefix,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/interface",
+ .cbs.cli_show = cli_show_ripng_network_interface,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/offset-list",
+ .cbs.cli_show = cli_show_ripng_offset_list,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/passive-interface",
+ .cbs.cli_show = cli_show_ripng_passive_interface,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/distribute-list/in/access-list",
+ .cbs.cli_show = group_distribute_list_ipv6_cli_show,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/distribute-list/out/access-list",
+ .cbs.cli_show = group_distribute_list_ipv6_cli_show,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/distribute-list/in/prefix-list",
+ .cbs.cli_show = group_distribute_list_ipv6_cli_show,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/distribute-list/out/prefix-list",
+ .cbs.cli_show = group_distribute_list_ipv6_cli_show,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/redistribute",
+ .cbs.cli_show = cli_show_ripng_redistribute,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/if-route-maps/if-route-map",
+ .cbs.cli_show = cli_show_if_route_map,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/static-route",
+ .cbs.cli_show = cli_show_ripng_route,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/aggregate-address",
+ .cbs.cli_show = cli_show_ripng_aggregate_address,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/timers",
+ .cbs.cli_show = cli_show_ripng_timers,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-ripngd:ripng/split-horizon",
+ .cbs = {
+ .cli_show = cli_show_ipv6_ripng_split_horizon,
+ },
+ },
+ {
+ .xpath = NULL,
+ },
+ }
+};