diff --git a/babeld/babeld.c b/babeld/babeld.c index 797d12478a9f..6f0a5a7bb4ff 100644 --- a/babeld/babeld.c +++ b/babeld/babeld.c @@ -696,9 +696,8 @@ DEFPY (babel_set_smoothing_half_life, DEFUN (babel_distribute_list, babel_distribute_list_cmd, - "distribute-list [prefix] ACCESSLIST4_NAME [WORD]", + "distribute-list ACCESSLIST4_NAME [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" @@ -710,16 +709,26 @@ DEFUN (babel_distribute_list, if (argv[argc - 1]->type == VARIABLE_TKN) ifname = argv[argc - 1]->arg; - return distribute_list_parser(NULL, prefix, true, argv[2 + prefix]->text, + return distribute_list_parser(babel_routing_process->distribute_ctx, + prefix, true, argv[2 + prefix]->text, argv[1 + prefix]->arg, ifname); } +ALIAS (babel_distribute_list, + babel_distribute_list_prefix_cmd, + "distribute-list prefix PREFIXLIST4_NAME [WORD]", + "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") + DEFUN (babel_no_distribute_list, babel_no_distribute_list_cmd, - "no distribute-list [prefix] ACCESSLIST4_NAME [WORD]", + "no distribute-list ACCESSLIST4_NAME [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" @@ -731,17 +740,28 @@ DEFUN (babel_no_distribute_list, if (argv[argc - 1]->type == VARIABLE_TKN) ifname = argv[argc - 1]->arg; - return distribute_list_no_parser(NULL, vty, prefix, true, + return distribute_list_no_parser(babel_routing_process->distribute_ctx, + vty, prefix, true, argv[3 + prefix]->text, argv[2 + prefix]->arg, ifname); } +ALIAS (babel_no_distribute_list, + babel_no_distribute_list_prefix_cmd, + "no distribute-list prefix PREFIXLIST4_NAME [WORD]", + 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") + DEFUN (babel_ipv6_distribute_list, babel_ipv6_distribute_list_cmd, - "ipv6 distribute-list [prefix] ACCESSLIST6_NAME [WORD]", + "ipv6 distribute-list ACCESSLIST6_NAME [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" @@ -753,18 +773,28 @@ DEFUN (babel_ipv6_distribute_list, if (argv[argc - 1]->type == VARIABLE_TKN) ifname = argv[argc - 1]->arg; - return distribute_list_parser(NULL, prefix, false, - argv[3 + prefix]->text, + return distribute_list_parser(babel_routing_process->distribute_ctx, + prefix, false, argv[3 + prefix]->text, argv[2 + prefix]->arg, ifname); } +ALIAS (babel_ipv6_distribute_list, + babel_ipv6_distribute_list_prefix_cmd, + "ipv6 distribute-list prefix PREFIXLIST6_NAME [WORD]", + "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") + DEFUN (babel_no_ipv6_distribute_list, babel_no_ipv6_distribute_list_cmd, - "no ipv6 distribute-list [prefix] ACCESSLIST6_NAME [WORD]", + "no ipv6 distribute-list ACCESSLIST6_NAME [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" @@ -776,11 +806,24 @@ DEFUN (babel_no_ipv6_distribute_list, if (argv[argc - 1]->type == VARIABLE_TKN) ifname = argv[argc - 1]->arg; - return distribute_list_no_parser(NULL, vty, prefix, false, + return distribute_list_no_parser(babel_routing_process->distribute_ctx, + vty, prefix, false, argv[4 + prefix]->text, argv[3 + prefix]->arg, ifname); } +ALIAS (babel_no_ipv6_distribute_list, + babel_no_ipv6_distribute_list_prefix_cmd, + "no ipv6 distribute-list prefix PREFIXLIST6_NAME [WORD]", + 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") + void babeld_quagga_init(void) { @@ -798,9 +841,13 @@ babeld_quagga_init(void) install_element(BABEL_NODE, &babel_set_smoothing_half_life_cmd); install_element(BABEL_NODE, &babel_distribute_list_cmd); + install_element(BABEL_NODE, &babel_distribute_list_prefix_cmd); install_element(BABEL_NODE, &babel_no_distribute_list_cmd); + install_element(BABEL_NODE, &babel_no_distribute_list_prefix_cmd); install_element(BABEL_NODE, &babel_ipv6_distribute_list_cmd); + install_element(BABEL_NODE, &babel_ipv6_distribute_list_prefix_cmd); install_element(BABEL_NODE, &babel_no_ipv6_distribute_list_cmd); + install_element(BABEL_NODE, &babel_no_ipv6_distribute_list_prefix_cmd); vrf_cmd_init(NULL); diff --git a/eigrpd/eigrp_cli.c b/eigrpd/eigrp_cli.c index b961cde8714a..4bd3434aebad 100644 --- a/eigrpd/eigrp_cli.c +++ b/eigrpd/eigrp_cli.c @@ -401,6 +401,117 @@ void eigrp_cli_show_neighbor(struct vty *vty, const struct lyd_node *dnode, vty_out(vty, " neighbor %s\n", prefix); } +/* + * XPath: /frr-eigrpd:eigrpd/instance/distribute-list + */ +DEFPY_YANG (eigrp_distribute_list, + eigrp_distribute_list_cmd, + "distribute-list ACCESSLIST4_NAME$name $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") +{ + char xpath[XPATH_MAXLEN]; + + 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); +} + +DEFPY_YANG (eigrp_distribute_list_prefix, + eigrp_distribute_list_prefix_cmd, + "distribute-list prefix PREFIXLIST4_NAME$name $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") +{ + char xpath[XPATH_MAXLEN]; + + 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); +} + +DEFPY_YANG (eigrp_no_distribute_list, + eigrp_no_distribute_list_cmd, + "no distribute-list [ACCESSLIST4_NAME$name] $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 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); +} + +DEFPY_YANG (eigrp_no_distribute_list_prefix, + eigrp_no_distribute_list_prefix_cmd, + "no distribute-list prefix [PREFIXLIST4_NAME$name] $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]; + + 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); +} + /* * XPath: /frr-eigrpd:eigrpd/instance/redistribute * XPath: /frr-eigrpd:eigrpd/instance/redistribute/route-map @@ -875,6 +986,10 @@ eigrp_cli_init(void) install_element(EIGRP_NODE, &no_eigrp_metric_weights_cmd); install_element(EIGRP_NODE, &eigrp_network_cmd); install_element(EIGRP_NODE, &eigrp_neighbor_cmd); + install_element(EIGRP_NODE, &eigrp_distribute_list_cmd); + install_element(EIGRP_NODE, &eigrp_distribute_list_prefix_cmd); + install_element(EIGRP_NODE, &eigrp_no_distribute_list_cmd); + install_element(EIGRP_NODE, &eigrp_no_distribute_list_prefix_cmd); install_element(EIGRP_NODE, &eigrp_redistribute_source_metric_cmd); vrf_cmd_init(NULL); diff --git a/eigrpd/eigrp_northbound.c b/eigrpd/eigrp_northbound.c index 562c292e2a86..4aeb635c05c3 100644 --- a/eigrpd/eigrp_northbound.c +++ b/eigrpd/eigrp_northbound.c @@ -14,6 +14,7 @@ #include "lib/table.h" #include "lib/vrf.h" #include "lib/zclient.h" +#include "lib/distribute.h" #include "eigrp_structs.h" #include "eigrpd.h" @@ -701,6 +702,22 @@ static int eigrpd_instance_neighbor_destroy(struct nb_cb_destroy_args *args) return NB_OK; } +/* + * XPath: /frr-eigrpd:eigrpd/instance/distribute-list + */ +static int eigrpd_instance_distribute_list_create(struct nb_cb_create_args *args) +{ + struct eigrp *eigrp; + + if (args->event != NB_EV_APPLY) + return NB_OK; + + eigrp = nb_running_get_entry(args->dnode, NULL, true); + group_distribute_list_create_helper(args, eigrp->distribute_ctx); + + return NB_OK; +} + /* * XPath: /frr-eigrpd:eigrpd/instance/redistribute */ @@ -1402,6 +1419,45 @@ const struct frr_yang_module_info frr_eigrpd_info = { .cli_show = eigrp_cli_show_neighbor, } }, + { + .xpath = "/frr-eigrpd:eigrpd/instance/distribute-list", + .cbs = { + .create = eigrpd_instance_distribute_list_create, + .destroy = group_distribute_list_destroy, + } + }, + { + .xpath = "/frr-eigrpd:eigrpd/instance/distribute-list/in/access-list", + .cbs = { + .modify = group_distribute_list_ipv4_modify, + .destroy = group_distribute_list_ipv4_destroy, + .cli_show = group_distribute_list_ipv4_cli_show, + } + }, + { + .xpath = "/frr-eigrpd:eigrpd/instance/distribute-list/out/access-list", + .cbs = { + .modify = group_distribute_list_ipv4_modify, + .destroy = group_distribute_list_ipv4_destroy, + .cli_show = group_distribute_list_ipv4_cli_show, + } + }, + { + .xpath = "/frr-eigrpd:eigrpd/instance/distribute-list/in/prefix-list", + .cbs = { + .modify = group_distribute_list_ipv4_modify, + .destroy = group_distribute_list_ipv4_destroy, + .cli_show = group_distribute_list_ipv4_cli_show, + } + }, + { + .xpath = "/frr-eigrpd:eigrpd/instance/distribute-list/out/prefix-list", + .cbs = { + .modify = group_distribute_list_ipv4_modify, + .destroy = group_distribute_list_ipv4_destroy, + .cli_show = group_distribute_list_ipv4_cli_show, + } + }, { .xpath = "/frr-eigrpd:eigrpd/instance/redistribute", .cbs = { diff --git a/eigrpd/eigrp_routemap.c b/eigrpd/eigrp_routemap.c index 5a1634592f67..420cb6cb414c 100644 --- a/eigrpd/eigrp_routemap.c +++ b/eigrpd/eigrp_routemap.c @@ -1107,49 +1107,6 @@ ALIAS(no_set_tag, no_set_tag_val_cmd, "no set tag (0-65535)", NO_STR SET_STR "Tag value for routing protocol\n" "Tag value\n") -DEFUN (eigrp_distribute_list, - eigrp_distribute_list_cmd, - "distribute-list [prefix] ACCESSLIST_NAME [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") -{ - 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; - - return distribute_list_parser(NULL, prefix, true, argv[2 + prefix]->text, - argv[1 + prefix]->arg, ifname); -} - -DEFUN (eigrp_no_distribute_list, - eigrp_no_distribute_list_cmd, - "no distribute-list [prefix] ACCESSLIST_NAME [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") -{ - 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; - - return distribute_list_no_parser(NULL, vty, prefix, true, - argv[3 + prefix]->text, - argv[2 + prefix]->arg, ifname); -} - - /* Route-map init */ void eigrp_route_map_init(void) { @@ -1158,9 +1115,6 @@ void eigrp_route_map_init(void) route_map_add_hook(eigrp_route_map_update); route_map_delete_hook(eigrp_route_map_update); - install_element(EIGRP_NODE, &eigrp_distribute_list_cmd); - install_element(EIGRP_NODE, &eigrp_no_distribute_list_cmd); - /*route_map_install_match (&route_match_metric_cmd); route_map_install_match (&route_match_interface_cmd);*/ /*route_map_install_match (&route_match_ip_next_hop_cmd); diff --git a/lib/distribute.c b/lib/distribute.c index 8d1fca9a9e4e..ccd1f1379efd 100644 --- a/lib/distribute.c +++ b/lib/distribute.c @@ -17,8 +17,6 @@ DEFINE_MTYPE_STATIC(LIB, DISTRIBUTE, "Distribute list"); DEFINE_MTYPE_STATIC(LIB, DISTRIBUTE_IFNAME, "Dist-list ifname"); DEFINE_MTYPE_STATIC(LIB, DISTRIBUTE_NAME, "Dist-list name"); -static struct list *dist_ctx_list; - static struct distribute *distribute_new(void) { return XCALLOC(MTYPE_DISTRIBUTE, sizeof(struct distribute)); @@ -249,9 +247,6 @@ int distribute_list_parser(struct distribute_ctx *ctx, bool prefix, bool v4, { enum distribute_type type = distribute_direction(dir, v4); - if (!ctx) - ctx = listnode_head(dist_ctx_list); - void (*distfn)(struct distribute_ctx *, const char *, enum distribute_type, const char *) = prefix ? &distribute_list_prefix_set : &distribute_list_set; @@ -269,9 +264,6 @@ int distribute_list_no_parser(struct distribute_ctx *ctx, struct vty *vty, enum distribute_type type = distribute_direction(dir, v4); int ret; - if (!ctx) - ctx = listnode_head(dist_ctx_list); - int (*distfn)(struct distribute_ctx *, const char *, enum distribute_type, const char *) = prefix ? &distribute_list_prefix_unset : &distribute_list_unset; @@ -573,12 +565,6 @@ void distribute_list_delete(struct distribute_ctx **ctx) hash_clean_and_free(&(*ctx)->disthash, (void (*)(void *))distribute_free); - if (dist_ctx_list) { - listnode_delete(dist_ctx_list, *ctx); - if (list_isempty(dist_ctx_list)) - list_delete(&dist_ctx_list); - } - XFREE(MTYPE_DISTRIBUTE_CTX, (*ctx)); } @@ -589,11 +575,9 @@ struct distribute_ctx *distribute_list_ctx_create(struct vrf *vrf) ctx = XCALLOC(MTYPE_DISTRIBUTE_CTX, sizeof(struct distribute_ctx)); ctx->vrf = vrf; - ctx->disthash = hash_create( - distribute_hash_make, - (bool (*)(const void *, const void *))distribute_cmp, NULL); - if (!dist_ctx_list) - dist_ctx_list = list_new(); - listnode_add(dist_ctx_list, ctx); + ctx->disthash = + hash_create(distribute_hash_make, + (bool (*)(const void *, const void *))distribute_cmp, + NULL); return ctx; } diff --git a/lib/plist.c b/lib/plist.c index 2f5827cf4354..605e7e73ea4e 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -1632,12 +1632,26 @@ static void plist_autocomplete(vector comps, struct cmd_token *token) plist_autocomplete_afi(AFI_IP6, comps, token); } +static void plist4_autocomplete(vector comps, struct cmd_token *token) +{ + plist_autocomplete_afi(AFI_IP, comps, token); +} + +static void plist6_autocomplete(vector comps, struct cmd_token *token) +{ + plist_autocomplete_afi(AFI_IP6, comps, token); +} + static const struct cmd_variable_handler plist_var_handlers[] = { {/* "prefix-list WORD" */ .varname = "prefix_list", .completions = plist_autocomplete}, {.tokenname = "PREFIXLIST_NAME", .completions = plist_autocomplete}, + {.tokenname = "PREFIXLIST4_NAME", + .completions = plist4_autocomplete}, + {.tokenname = "PREFIXLIST6_NAME", + .completions = plist6_autocomplete}, {.completions = NULL}}; diff --git a/ripd/rip_cli.c b/ripd/rip_cli.c index d4366d018667..daa83dd0550a 100644 --- a/ripd/rip_cli.c +++ b/ripd/rip_cli.c @@ -1130,10 +1130,29 @@ DEFPY_YANG (clear_ip_rip, DEFPY_YANG( rip_distribute_list, rip_distribute_list_cmd, - "distribute-list [prefix]$prefix ACCESSLIST4_NAME$name $dir [WORD$ifname]", + "distribute-list ACCESSLIST4_NAME$name $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") +{ + char xpath[XPATH_MAXLEN]; + + 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); +} + +DEFPY_YANG( + rip_distribute_list_prefix, rip_distribute_list_prefix_cmd, + "distribute-list prefix PREFIXLIST4_NAME$name $dir [WORD$ifname]", "Filter networks in routing updates\n" "Specify a prefix list\n" - "access-list or prefix-list name\n" + "Prefix-list name\n" "Filter incoming routing updates\n" "Filter outgoing routing updates\n" "Interface name\n") @@ -1141,8 +1160,8 @@ DEFPY_YANG( char xpath[XPATH_MAXLEN]; snprintf(xpath, sizeof(xpath), - "./distribute-list[interface='%s']/%s/%s-list", - ifname ? ifname : "", dir, prefix ? "prefix" : "access"); + "./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); @@ -1150,11 +1169,45 @@ DEFPY_YANG( DEFPY_YANG(no_rip_distribute_list, no_rip_distribute_list_cmd, - "no distribute-list [prefix]$prefix [ACCESSLIST4_NAME$name] $dir [WORD$ifname]", + "no distribute-list [ACCESSLIST4_NAME$name] $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 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); +} + +DEFPY_YANG(no_rip_distribute_list_prefix, + no_rip_distribute_list_prefix_cmd, + "no distribute-list prefix [PREFIXLIST4_NAME$name] $dir [WORD$ifname]", NO_STR "Filter networks in routing updates\n" "Specify a prefix list\n" - "access-list or prefix-list name\n" + "Prefix-list name\n" "Filter incoming routing updates\n" "Filter outgoing routing updates\n" "Interface name\n") @@ -1163,8 +1216,8 @@ DEFPY_YANG(no_rip_distribute_list, char xpath[XPATH_MAXLEN]; snprintf(xpath, sizeof(xpath), - "./distribute-list[interface='%s']/%s/%s-list", - ifname ? ifname : "", dir, prefix ? "prefix" : "access"); + "./distribute-list[interface='%s']/%s/prefix-list", + ifname ? ifname : "", dir); /* * See if the user has specified specific list so check it exists. * @@ -1189,7 +1242,9 @@ void rip_cli_init(void) install_element(CONFIG_NODE, &no_router_rip_cmd); install_element(RIP_NODE, &rip_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); diff --git a/ripngd/ripng_cli.c b/ripngd/ripng_cli.c index 3212229ac6a6..aa9f3cc0375b 100644 --- a/ripngd/ripng_cli.c +++ b/ripngd/ripng_cli.c @@ -518,10 +518,31 @@ DEFPY_YANG (clear_ipv6_rip, DEFPY_YANG( ripng_ipv6_distribute_list, ripng_ipv6_distribute_list_cmd, - "ipv6 distribute-list [prefix]$prefix ACCESSLIST4_NAME$name $dir [WORD$ifname]", + "ipv6 distribute-list ACCESSLIST6_NAME$name $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") +{ + char xpath[XPATH_MAXLEN]; + + 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); +} + +DEFPY_YANG( + ripng_ipv6_distribute_list_prefix, ripng_ipv6_distribute_list_prefix_cmd, + "ipv6 distribute-list prefix PREFIXLIST6_NAME$name $dir [WORD$ifname]", + "IPv6\n" "Filter networks in routing updates\n" "Specify a prefix list\n" - "access-list or prefix-list name\n" + "Prefix-list name\n" "Filter incoming routing updates\n" "Filter outgoing routing updates\n" "Interface name\n") @@ -529,8 +550,8 @@ DEFPY_YANG( char xpath[XPATH_MAXLEN]; snprintf(xpath, sizeof(xpath), - "./distribute-list[interface='%s']/%s/%s-list", - ifname ? ifname : "", dir, prefix ? "prefix" : "access"); + "./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); @@ -538,11 +559,47 @@ DEFPY_YANG( DEFPY_YANG(no_ripng_ipv6_distribute_list, no_ripng_ipv6_distribute_list_cmd, - "no ipv6 distribute-list [prefix]$prefix [ACCESSLIST4_NAME$name] $dir [WORD$ifname]", + "no ipv6 distribute-list [ACCESSLIST6_NAME$name] $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 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); +} + +DEFPY_YANG(no_ripng_ipv6_distribute_list_prefix, + no_ripng_ipv6_distribute_list_prefix_cmd, + "no ipv6 distribute-list prefix [PREFIXLIST6_NAME$name] $dir [WORD$ifname]", NO_STR + "IPv6\n" "Filter networks in routing updates\n" "Specify a prefix list\n" - "access-list or prefix-list name\n" + "Prefix-list name\n" "Filter incoming routing updates\n" "Filter outgoing routing updates\n" "Interface name\n") @@ -551,8 +608,8 @@ DEFPY_YANG(no_ripng_ipv6_distribute_list, char xpath[XPATH_MAXLEN]; snprintf(xpath, sizeof(xpath), - "./distribute-list[interface='%s']/%s/%s-list", - ifname ? ifname : "", dir, prefix ? "prefix" : "access"); + "./distribute-list[interface='%s']/%s/prefix-list", + ifname ? ifname : "", dir); /* * See if the user has specified specific list so check it exists. * @@ -577,7 +634,9 @@ void ripng_cli_init(void) install_element(CONFIG_NODE, &no_router_ripng_cmd); install_element(RIPNG_NODE, &ripng_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); diff --git a/yang/frr-eigrpd.yang b/yang/frr-eigrpd.yang index e9071c897199..f672dd557161 100644 --- a/yang/frr-eigrpd.yang +++ b/yang/frr-eigrpd.yang @@ -22,6 +22,9 @@ module frr-eigrpd { import frr-route-types { prefix frr-route-types; } + import frr-filter { + prefix frr-filter; + } organization "FRRouting"; contact @@ -224,6 +227,8 @@ module frr-eigrpd { type inet:ipv4-address; } + uses frr-filter:distribute-list-group; + list redistribute { description "Redistribute routes learned from other routing protocols";