diff options
Diffstat (limited to 'ripngd/ripng_cli.c')
| -rw-r--r-- | ripngd/ripng_cli.c | 381 |
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, + }, + } +}; |
