diff options
Diffstat (limited to '')
-rw-r--r-- | ripd/rip_cli.c | 394 |
1 files changed, 297 insertions, 97 deletions
diff --git a/ripd/rip_cli.c b/ripd/rip_cli.c index 097c708..4d4349b 100644 --- a/ripd/rip_cli.c +++ b/ripd/rip_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_rip(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 rip"); @@ -82,6 +83,11 @@ void cli_show_router_rip(struct vty *vty, const struct lyd_node *dnode, vty_out(vty, "\n"); } +void cli_show_end_router_rip(struct vty *vty, const struct lyd_node *dnode) +{ + vty_out(vty, "exit\n"); +} + /* * XPath: /frr-ripd:ripd/instance/allow-ecmp */ @@ -255,11 +261,11 @@ void cli_show_rip_distance_source(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) { vty_out(vty, " distance %s %s", - yang_dnode_get_string(dnode, "./distance"), - yang_dnode_get_string(dnode, "./prefix")); - if (yang_dnode_exists(dnode, "./access-list")) + yang_dnode_get_string(dnode, "distance"), + yang_dnode_get_string(dnode, "prefix")); + if (yang_dnode_exists(dnode, "access-list")) vty_out(vty, " %s", - yang_dnode_get_string(dnode, "./access-list")); + yang_dnode_get_string(dnode, "access-list")); vty_out(vty, "\n"); } @@ -273,8 +279,13 @@ DEFPY_YANG (rip_neighbor, "Specify a neighbor router\n" "Neighbor address\n") { - nb_cli_enqueue_change(vty, "./explicit-neighbor", - no ? NB_OP_DESTROY : NB_OP_CREATE, neighbor_str); + char xpath[XPATH_MAXLEN]; + + snprintf(xpath, sizeof(xpath), "./explicit-neighbor[.='%s']", + neighbor_str); + + nb_cli_enqueue_change(vty, xpath, no ? NB_OP_DESTROY : NB_OP_CREATE, + NULL); return nb_cli_apply_changes(vty, NULL); } @@ -295,8 +306,12 @@ DEFPY_YANG (rip_network_prefix, "Enable routing on an IP network\n" "IP prefix <network>/<length>, e.g., 35.0.0.0/8\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); } @@ -317,8 +332,12 @@ DEFPY_YANG (rip_network_if, "Enable routing on an IP 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); } @@ -362,12 +381,12 @@ void cli_show_rip_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"); @@ -412,17 +431,21 @@ DEFPY_YANG (rip_passive_interface, bool passive_default = yang_dnode_get_bool(vty->candidate_config->dnode, "%s%s", VTY_CURR_XPATH, "/passive-default"); + char xpath[XPATH_MAXLEN]; + enum nb_operation op; if (passive_default) { - nb_cli_enqueue_change(vty, "./non-passive-interface", - no ? NB_OP_CREATE : NB_OP_DESTROY, - ifname); + snprintf(xpath, sizeof(xpath), + "./non-passive-interface[.='%s']", ifname); + op = no ? NB_OP_CREATE : NB_OP_DESTROY; } else { - nb_cli_enqueue_change(vty, "./passive-interface", - no ? NB_OP_DESTROY : NB_OP_CREATE, - ifname); + snprintf(xpath, sizeof(xpath), "./passive-interface[.='%s']", + ifname); + op = no ? NB_OP_DESTROY : NB_OP_CREATE; } + nb_cli_enqueue_change(vty, xpath, op, NULL); + return nb_cli_apply_changes(vty, NULL); } @@ -475,13 +498,13 @@ void cli_show_rip_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"); } @@ -495,8 +518,12 @@ DEFPY_YANG (rip_route, "RIP static route configuration\n" "IP prefix <network>/<length>\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); } @@ -550,9 +577,9 @@ void cli_show_rip_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")); } /* @@ -591,7 +618,7 @@ void cli_show_rip_version(struct vty *vty, const struct lyd_node *dnode, * We have only one "version" command and three possible combinations of * send/receive values. */ - switch (yang_dnode_get_enum(dnode, "./receive")) { + switch (yang_dnode_get_enum(dnode, "receive")) { case RI_RIP_VERSION_1: vty_out(vty, " version 1\n"); break; @@ -912,7 +939,7 @@ void cli_show_ip_rip_authentication_scheme(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) { - switch (yang_dnode_get_enum(dnode, "./mode")) { + switch (yang_dnode_get_enum(dnode, "mode")) { case RIP_NO_AUTH: vty_out(vty, " no ip rip authentication mode\n"); break; @@ -922,8 +949,8 @@ void cli_show_ip_rip_authentication_scheme(struct vty *vty, case RIP_AUTH_MD5: vty_out(vty, " ip rip authentication mode md5"); if (show_defaults - || !yang_dnode_is_default(dnode, "./md5-auth-length")) { - if (yang_dnode_get_enum(dnode, "./md5-auth-length") + || !yang_dnode_is_default(dnode, "md5-auth-length")) { + if (yang_dnode_get_enum(dnode, "md5-auth-length") == RIP_AUTH_MD5_SIZE) vty_out(vty, " auth-length rfc"); else @@ -1098,85 +1125,134 @@ void cli_show_ip_rip_bfd_profile(struct vty *vty, const struct lyd_node *dnode, yang_dnode_get_string(dnode, NULL)); } -/* - * XPath: /frr-ripd:clear-rip-route - */ -DEFPY_YANG (clear_ip_rip, - clear_ip_rip_cmd, - "clear ip rip [vrf WORD]", - CLEAR_STR - IP_STR - "Clear IP RIP database\n" - VRF_CMD_HELP_STR) +DEFPY_YANG( + rip_distribute_list, rip_distribute_list_cmd, + "distribute-list ACCESSLIST4_NAME$name <in|out>$dir [WORD$ifname]", + "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-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); + char xpath[XPATH_MAXLEN]; - return ret; + 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); } -DEFUN (rip_distribute_list, - rip_distribute_list_cmd, - "distribute-list [prefix] ACCESSLIST4_NAME <in|out> [WORD]", - "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( + rip_distribute_list_prefix, rip_distribute_list_prefix_cmd, + "distribute-list prefix PREFIXLIST4_NAME$name <in|out>$dir [WORD$ifname]", + "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[1]->type == WORD_TKN) ? 1 : 0; - - if (argv[argc - 1]->type == VARIABLE_TKN) - ifname = argv[argc - 1]->arg; + char xpath[XPATH_MAXLEN]; - return distribute_list_parser(prefix, true, argv[2 + prefix]->text, - argv[1 + prefix]->arg, ifname); + 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 (rip_no_distribute_list, - rip_no_distribute_list_cmd, - "no distribute-list [prefix] ACCESSLIST4_NAME <in|out> [WORD]", - NO_STR - "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_rip_distribute_list, + no_rip_distribute_list_cmd, + "no distribute-list [ACCESSLIST4_NAME$name] <in|out>$dir [WORD$ifname]", + NO_STR + "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; + const struct lyd_node *value_node; + char xpath[XPATH_MAXLEN]; + + 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); +} - if (argv[argc - 1]->type == VARIABLE_TKN) - ifname = argv[argc - 1]->arg; +DEFPY_YANG(no_rip_distribute_list_prefix, + no_rip_distribute_list_prefix_cmd, + "no distribute-list prefix [PREFIXLIST4_NAME$name] <in|out>$dir [WORD$ifname]", + NO_STR + "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 struct lyd_node *value_node; + char xpath[XPATH_MAXLEN]; - return distribute_list_no_parser(vty, prefix, true, - argv[3 + prefix]->text, - argv[2 + 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); } +/* RIP node structure. */ +static struct cmd_node rip_node = { + .name = "rip", + .node = RIP_NODE, + .parent_node = CONFIG_NODE, + .prompt = "%s(config-router)# ", + // .config_write = config_write_rip, +}; + void rip_cli_init(void) { + install_node(&rip_node); + install_element(CONFIG_NODE, &router_rip_cmd); install_element(CONFIG_NODE, &no_router_rip_cmd); install_element(RIP_NODE, &rip_distribute_list_cmd); - install_element(RIP_NODE, &rip_no_distribute_list_cmd); + install_element(RIP_NODE, &rip_distribute_list_prefix_cmd); + install_element(RIP_NODE, &no_rip_distribute_list_cmd); + install_element(RIP_NODE, &no_rip_distribute_list_prefix_cmd); install_element(RIP_NODE, &rip_allow_ecmp_cmd); install_element(RIP_NODE, &no_rip_allow_ecmp_cmd); @@ -1200,6 +1276,7 @@ void rip_cli_init(void) install_element(RIP_NODE, &no_rip_version_cmd); install_element(RIP_NODE, &rip_bfd_default_profile_cmd); install_element(RIP_NODE, &no_rip_bfd_default_profile_cmd); + install_default(RIP_NODE); install_element(INTERFACE_NODE, &ip_rip_split_horizon_cmd); install_element(INTERFACE_NODE, &ip_rip_v2_broadcast_cmd); @@ -1218,5 +1295,128 @@ void rip_cli_init(void) install_element(INTERFACE_NODE, &ip_rip_bfd_profile_cmd); install_element(INTERFACE_NODE, &no_ip_rip_bfd_profile_cmd); - install_element(ENABLE_NODE, &clear_ip_rip_cmd); -} + if_rmap_init(RIP_NODE); +} +/* clang-format off */ +const struct frr_yang_module_info frr_ripd_cli_info = { + .name = "frr-ripd", + .ignore_cfg_cbs = true, + .nodes = { + { + .xpath = "/frr-ripd:ripd/instance", + .cbs.cli_show = cli_show_router_rip, + .cbs.cli_show_end = cli_show_end_router_rip, + }, + { + .xpath = "/frr-ripd:ripd/instance/allow-ecmp", + .cbs.cli_show = cli_show_rip_allow_ecmp, + }, + { + .xpath = "/frr-ripd:ripd/instance/default-information-originate", + .cbs.cli_show = cli_show_rip_default_information_originate, + }, + { + .xpath = "/frr-ripd:ripd/instance/default-metric", + .cbs.cli_show = cli_show_rip_default_metric, + }, + { + .xpath = "/frr-ripd:ripd/instance/distance/default", + .cbs.cli_show = cli_show_rip_distance, + }, + { + .xpath = "/frr-ripd:ripd/instance/distance/source", + .cbs.cli_show = cli_show_rip_distance_source, + }, + { + .xpath = "/frr-ripd:ripd/instance/explicit-neighbor", + .cbs.cli_show = cli_show_rip_neighbor, + }, + { + .xpath = "/frr-ripd:ripd/instance/network", + .cbs.cli_show = cli_show_rip_network_prefix, + }, + { + .xpath = "/frr-ripd:ripd/instance/interface", + .cbs.cli_show = cli_show_rip_network_interface, + }, + { + .xpath = "/frr-ripd:ripd/instance/offset-list", + .cbs.cli_show = cli_show_rip_offset_list, + }, + { + .xpath = "/frr-ripd:ripd/instance/passive-default", + .cbs.cli_show = cli_show_rip_passive_default, + }, + { + .xpath = "/frr-ripd:ripd/instance/passive-interface", + .cbs.cli_show = cli_show_rip_passive_interface, + }, + { + .xpath = "/frr-ripd:ripd/instance/non-passive-interface", + .cbs.cli_show = cli_show_rip_non_passive_interface, + }, + { + .xpath = "/frr-ripd:ripd/instance/redistribute", + .cbs.cli_show = cli_show_rip_redistribute, + }, + { + .xpath = "/frr-ripd:ripd/instance/if-route-maps/if-route-map", + .cbs.cli_show = cli_show_if_route_map, + }, + { + .xpath = "/frr-ripd:ripd/instance/static-route", + .cbs.cli_show = cli_show_rip_route, + }, + { + .xpath = "/frr-ripd:ripd/instance/timers", + .cbs.cli_show = cli_show_rip_timers, + }, + { + .xpath = "/frr-ripd:ripd/instance/version", + .cbs.cli_show = cli_show_rip_version, + }, + { + .xpath = "/frr-ripd:ripd/instance/default-bfd-profile", + .cbs.cli_show = cli_show_ripd_instance_default_bfd_profile, + }, + { + .xpath = "/frr-interface:lib/interface/frr-ripd:rip/split-horizon", + .cbs.cli_show = cli_show_ip_rip_split_horizon, + }, + { + .xpath = "/frr-interface:lib/interface/frr-ripd:rip/v2-broadcast", + .cbs.cli_show = cli_show_ip_rip_v2_broadcast, + }, + { + .xpath = "/frr-interface:lib/interface/frr-ripd:rip/version-receive", + .cbs.cli_show = cli_show_ip_rip_receive_version, + }, + { + .xpath = "/frr-interface:lib/interface/frr-ripd:rip/version-send", + .cbs.cli_show = cli_show_ip_rip_send_version, + }, + { + .xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-scheme", + .cbs.cli_show = cli_show_ip_rip_authentication_scheme, + }, + { + .xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-password", + .cbs.cli_show = cli_show_ip_rip_authentication_string, + }, + { + .xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-key-chain", + .cbs.cli_show = cli_show_ip_rip_authentication_key_chain, + }, + { + .xpath = "/frr-interface:lib/interface/frr-ripd:rip/bfd-monitoring/enable", + .cbs.cli_show = cli_show_ip_rip_bfd_enable, + }, + { + .xpath = "/frr-interface:lib/interface/frr-ripd:rip/bfd-monitoring/profile", + .cbs.cli_show = cli_show_ip_rip_bfd_profile, + }, + { + .xpath = NULL, + }, + } +}; |