From 2150647069903840ef76353a5085eb5afc96cfaf Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Mon, 3 Jul 2023 17:15:05 +0200 Subject: [PATCH 1/4] isisd: add redistribute table identifier in nb configuration The yang model does not handle the table identifier in IS-IS. For each redistributed each address family, a new list of table elements is added to store the table identifier to redistribute, and also the optional metric and route-map values for each table identifier. Signed-off-by: Philippe Guibert --- doc/user/isisd.rst | 5 ++ isisd/isis_cli.c | 126 +++++++++++++++++++++++++++++++++++++---- isisd/isis_nb.c | 46 +++++++++++++++ isisd/isis_nb.h | 19 +++++++ isisd/isis_nb_config.c | 51 +++++++++++++++++ isisd/isis_redist.c | 47 +++++++++++++++ isisd/isis_redist.h | 13 +++++ yang/frr-isisd.yang | 51 ++++++++++++++++- 8 files changed, 344 insertions(+), 14 deletions(-) diff --git a/doc/user/isisd.rst b/doc/user/isisd.rst index 570b8bd182..83fc2e0281 100644 --- a/doc/user/isisd.rst +++ b/doc/user/isisd.rst @@ -166,6 +166,11 @@ flavors (local LFA, Remote LFA and TI-LFA). Configure a prefix-list to select eligible PQ nodes for remote LFA backups (valid for all protected interfaces). +.. clicmd:: redistribute table (1-65535) [metric (0-16777215)|route-map WORD] + + Redistribute routes from a given routing table into the given ISIS + level database. + .. _isis-region: ISIS region diff --git a/isisd/isis_cli.c b/isisd/isis_cli.c index 7c7a8d2389..6f53ab479f 100644 --- a/isisd/isis_cli.c +++ b/isisd/isis_cli.c @@ -1430,20 +1430,99 @@ DEFPY_YANG(isis_redistribute, isis_redistribute_cmd, level); } -static void vty_print_redistribute(struct vty *vty, - const struct lyd_node *dnode, - bool show_defaults, const char *family) +/* + * XPath: /frr-isisd:isis/instance/redistribute/table + */ +DEFPY_YANG(isis_redistribute_table, isis_redistribute_table_cmd, + "[no] redistribute $ip table (1-65535)$table" + "$level [{metric (0-16777215)|route-map WORD}]", + NO_STR REDIST_STR "Redistribute IPv4 routes\n" + "Redistribute IPv6 routes\n" + "Non-main Kernel Routing Table\n" + "Table Id\n" + "Redistribute into level-1\n" + "Redistribute into level-2\n" + "Metric for redistributed routes\n" + "IS-IS default metric\n" + "Route map reference\n" + "Pointer to route-map entries\n") { - const char *level = yang_dnode_get_string(dnode, "./level"); - const char *protocol = yang_dnode_get_string(dnode, "./protocol"); + struct isis_redist_table_present_args rtda = {}; + char xpath[XPATH_MAXLEN]; + char xpath_entry[XPATH_MAXLEN + 128]; + int rv; - vty_out(vty, " redistribute %s %s %s", family, protocol, level); + rtda.rtda_table = table_str; + rtda.rtda_ip = ip; + rtda.rtda_level = level; + + if (no) { + if (!isis_redist_table_is_present(vty, &rtda)) + return CMD_WARNING_CONFIG_FAILED; + + snprintf(xpath, sizeof(xpath), "./table[table='%s']", table_str); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + rv = nb_cli_apply_changes(vty, + "./redistribute/%s[protocol='table'][level='%s']", + ip, level); + if (rv == CMD_SUCCESS) { + if (isis_redist_table_get_first(vty, &rtda) > 0) + return CMD_SUCCESS; + nb_cli_enqueue_change(vty, "./table", NB_OP_DESTROY, + NULL); + nb_cli_apply_changes(vty, + "./redistribute/%s[protocol='table'][level='%s']", + ip, level); + } + return CMD_SUCCESS; + } + if (isis_redist_table_is_present(vty, &rtda)) + return CMD_SUCCESS; + + snprintf(xpath, sizeof(xpath), "./table[table='%s']", table_str); + nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL); + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); + snprintf(xpath_entry, sizeof(xpath_entry), "%s/route-map", xpath); + nb_cli_enqueue_change(vty, xpath_entry, + route_map ? NB_OP_MODIFY : NB_OP_DESTROY, + route_map ? route_map : NULL); + snprintf(xpath_entry, sizeof(xpath_entry), "%s/metric", xpath); + nb_cli_enqueue_change(vty, xpath_entry, NB_OP_MODIFY, + metric_str ? metric_str : NULL); + return nb_cli_apply_changes(vty, + "./redistribute/%s[protocol='table'][level='%s']", + ip, level); +} + +static void vty_print_redistribute(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults, const char *family, + bool table) +{ + const char *level; + const char *protocol = NULL; + const char *routemap = NULL; + uint16_t tableid; + + if (table) { + level = yang_dnode_get_string(dnode, "../level"); + tableid = yang_dnode_get_uint16(dnode, "./table"); + vty_out(vty, " redistribute %s table %d ", family, tableid); + } else { + protocol = yang_dnode_get_string(dnode, "./protocol"); + if (!table && strmatch(protocol, "table")) + return; + level = yang_dnode_get_string(dnode, "./level"); + vty_out(vty, " redistribute %s %s ", family, protocol); + } + vty_out(vty, "%s", level); if (show_defaults || !yang_dnode_is_default(dnode, "./metric")) vty_out(vty, " metric %s", - yang_dnode_get_string(dnode, "./metric")); + yang_dnode_get_string(dnode, "%s", "./metric")); + if (yang_dnode_exists(dnode, "./route-map")) - vty_out(vty, " route-map %s", - yang_dnode_get_string(dnode, "./route-map")); + routemap = yang_dnode_get_string(dnode, "./route-map"); + if (routemap) + vty_out(vty, " route-map %s", routemap); vty_out(vty, "\n"); } @@ -1451,13 +1530,37 @@ void cli_show_isis_redistribute_ipv4(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) { - vty_print_redistribute(vty, dnode, show_defaults, "ipv4"); + vty_print_redistribute(vty, dnode, show_defaults, "ipv4", false); } + void cli_show_isis_redistribute_ipv6(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) { - vty_print_redistribute(vty, dnode, show_defaults, "ipv6"); + vty_print_redistribute(vty, dnode, show_defaults, "ipv6", false); +} + +void cli_show_isis_redistribute_ipv4_table(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + vty_print_redistribute(vty, dnode, show_defaults, "ipv4", true); +} + +void cli_show_isis_redistribute_ipv6_table(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + vty_print_redistribute(vty, dnode, show_defaults, "ipv6", true); +} + +int cli_cmp_isis_redistribute_table(const struct lyd_node *dnode1, + const struct lyd_node *dnode2) +{ + uint16_t table1 = yang_dnode_get_uint16(dnode1, "./table"); + uint16_t table2 = yang_dnode_get_uint16(dnode2, "./table"); + + return table1 - table2; } /* @@ -3681,6 +3784,7 @@ void isis_cli_init(void) install_element(ISIS_NODE, &isis_default_originate_cmd); install_element(ISIS_NODE, &isis_redistribute_cmd); + install_element(ISIS_NODE, &isis_redistribute_table_cmd); install_element(ISIS_NODE, &isis_topology_cmd); diff --git a/isisd/isis_nb.c b/isisd/isis_nb.c index 6da8fa2d28..c81412d24a 100644 --- a/isisd/isis_nb.c +++ b/isisd/isis_nb.c @@ -381,6 +381,29 @@ const struct frr_yang_module_info frr_isisd_info = { }, { .xpath = "/frr-isisd:isis/instance/redistribute/ipv4/metric", + .cbs = { + .destroy = isis_instance_redistribute_ipv4_metric_destroy, + .modify = isis_instance_redistribute_ipv4_metric_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/redistribute/ipv4/table", + .cbs = { + .cli_show = cli_show_isis_redistribute_ipv4_table, + .cli_cmp = cli_cmp_isis_redistribute_table, + .create = isis_instance_redistribute_ipv4_table_create, + .destroy = isis_instance_redistribute_ipv4_table_destroy, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/redistribute/ipv4/table/route-map", + .cbs = { + .destroy = isis_instance_redistribute_ipv4_route_map_destroy, + .modify = isis_instance_redistribute_ipv4_route_map_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/redistribute/ipv4/table/metric", .cbs = { .modify = isis_instance_redistribute_ipv4_metric_modify, }, @@ -403,6 +426,29 @@ const struct frr_yang_module_info frr_isisd_info = { }, { .xpath = "/frr-isisd:isis/instance/redistribute/ipv6/metric", + .cbs = { + .destroy = isis_instance_redistribute_ipv6_metric_destroy, + .modify = isis_instance_redistribute_ipv6_metric_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/redistribute/ipv6/table", + .cbs = { + .cli_show = cli_show_isis_redistribute_ipv6_table, + .cli_cmp = cli_cmp_isis_redistribute_table, + .create = isis_instance_redistribute_ipv6_table_create, + .destroy = isis_instance_redistribute_ipv6_table_destroy, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/redistribute/ipv6/table/route-map", + .cbs = { + .destroy = isis_instance_redistribute_ipv6_route_map_destroy, + .modify = isis_instance_redistribute_ipv6_route_map_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/redistribute/ipv6/table/metric", .cbs = { .modify = isis_instance_redistribute_ipv6_metric_modify, }, diff --git a/isisd/isis_nb.h b/isisd/isis_nb.h index 13efa36d78..3b8ddca4f8 100644 --- a/isisd/isis_nb.h +++ b/isisd/isis_nb.h @@ -121,6 +121,11 @@ int isis_instance_redistribute_ipv4_route_map_destroy( struct nb_cb_destroy_args *args); int isis_instance_redistribute_ipv4_metric_modify( struct nb_cb_modify_args *args); +int isis_instance_redistribute_ipv4_metric_destroy( + struct nb_cb_destroy_args *args); +int isis_instance_redistribute_ipv4_table_create(struct nb_cb_create_args *args); +int isis_instance_redistribute_ipv4_table_destroy( + struct nb_cb_destroy_args *args); int isis_instance_redistribute_ipv6_create(struct nb_cb_create_args *args); int isis_instance_redistribute_ipv6_destroy(struct nb_cb_destroy_args *args); int isis_instance_redistribute_ipv6_route_map_modify( @@ -129,6 +134,11 @@ int isis_instance_redistribute_ipv6_route_map_destroy( struct nb_cb_destroy_args *args); int isis_instance_redistribute_ipv6_metric_modify( struct nb_cb_modify_args *args); +int isis_instance_redistribute_ipv6_metric_destroy( + struct nb_cb_destroy_args *args); +int isis_instance_redistribute_ipv6_table_create(struct nb_cb_create_args *args); +int isis_instance_redistribute_ipv6_table_destroy( + struct nb_cb_destroy_args *args); int isis_instance_multi_topology_ipv4_multicast_create( struct nb_cb_create_args *args); int isis_instance_multi_topology_ipv4_multicast_destroy( @@ -587,6 +597,12 @@ void cli_show_isis_redistribute_ipv6(struct vty *vty, void cli_show_isis_mt_ipv4_multicast(struct vty *vty, const struct lyd_node *dnode, bool show_defaults); +void cli_show_isis_redistribute_ipv4_table(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults); +void cli_show_isis_redistribute_ipv6_table(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults); void cli_show_isis_mt_ipv4_mgmt(struct vty *vty, const struct lyd_node *dnode, bool show_defaults); void cli_show_isis_mt_ipv6_unicast(struct vty *vty, @@ -742,6 +758,9 @@ void isis_notif_seqno_skipped(const struct isis_circuit *circuit, const uint8_t *lsp_id); void isis_notif_own_lsp_purge(const struct isis_circuit *circuit, const uint8_t *lsp_id); +/* cmp */ +int cli_cmp_isis_redistribute_table(const struct lyd_node *dnode1, + const struct lyd_node *dnode2); /* We also declare hook for every notification */ diff --git a/isisd/isis_nb_config.c b/isisd/isis_nb_config.c index 8a111b301d..278d4a8d85 100644 --- a/isisd/isis_nb_config.c +++ b/isisd/isis_nb_config.c @@ -1281,6 +1281,7 @@ int isis_instance_redistribute_ipv4_destroy(struct nb_cb_destroy_args *args) /* * XPath: /frr-isisd:isis/instance/redistribute/ipv4/route-map + * XPath: /frr-isisd:isis/instance/redistribute/ipv4/table/route-map */ int isis_instance_redistribute_ipv4_route_map_modify( struct nb_cb_modify_args *args) @@ -1298,6 +1299,7 @@ int isis_instance_redistribute_ipv4_route_map_destroy( /* * XPath: /frr-isisd:isis/instance/redistribute/ipv4/metric + * XPath: /frr-isisd:isis/instance/redistribute/ipv4/table/metric */ int isis_instance_redistribute_ipv4_metric_modify( struct nb_cb_modify_args *args) @@ -1306,6 +1308,28 @@ int isis_instance_redistribute_ipv4_metric_modify( return NB_OK; } +int isis_instance_redistribute_ipv4_metric_destroy(struct nb_cb_destroy_args *args) +{ + /* It's all done by redistribute_apply_finish */ + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/redistribute/ipv4/table + */ +int isis_instance_redistribute_ipv4_table_create(struct nb_cb_create_args *args) +{ + if (args->event != NB_EV_APPLY) + return NB_OK; + + /* TODO */ + return NB_OK; +} +int isis_instance_redistribute_ipv4_table_destroy(struct nb_cb_destroy_args *args) +{ + return NB_OK; +} + /* * XPath: /frr-isisd:isis/instance/redistribute/ipv6 */ @@ -1358,6 +1382,33 @@ int isis_instance_redistribute_ipv6_metric_modify( return NB_OK; } +int isis_instance_redistribute_ipv6_metric_destroy(struct nb_cb_destroy_args *args) +{ + /* It's all done by redistribute_apply_finish */ + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/redistribute/ipv6/table + */ +int isis_instance_redistribute_ipv6_table_create(struct nb_cb_create_args *args) +{ + if (args->event != NB_EV_APPLY) + return NB_OK; + + /* TODO */ + return NB_OK; +} + +int isis_instance_redistribute_ipv6_table_destroy(struct nb_cb_destroy_args *args) +{ + if (args->event != NB_EV_APPLY) + return NB_OK; + + /* TODO */ + return NB_OK; +} + /* * XPath: /frr-isisd:isis/instance/multi-topology/ipv4-multicast */ diff --git a/isisd/isis_redist.c b/isisd/isis_redist.c index 6a822f02fe..2b3facc436 100644 --- a/isisd/isis_redist.c +++ b/isisd/isis_redist.c @@ -206,6 +206,53 @@ static void isis_redist_ensure_default(struct isis *isis, int family) info->metric = MAX_WIDE_PATH_METRIC; } +static int _isis_redist_table_is_present(const struct lyd_node *dnode, void *arg) +{ + struct isis_redist_table_present_args *rtda = arg; + + /* This entry is the caller, so skip it. */ + if (yang_dnode_get_uint16(dnode, "table") != + (uint16_t)atoi(rtda->rtda_table)) + return YANG_ITER_CONTINUE; + + /* found */ + rtda->rtda_found = true; + return YANG_ITER_CONTINUE; +} + +static int _isis_redist_table_get_first_cb(const struct lyd_node *dnode, + void *arg) +{ + uint16_t *table = arg; + + *table = yang_dnode_get_uint16(dnode, "table"); + return YANG_ITER_STOP; +} + +uint16_t isis_redist_table_get_first(const struct vty *vty, + struct isis_redist_table_present_args *rtda) +{ + uint16_t table = 0; + + yang_dnode_iterate(_isis_redist_table_get_first_cb, &table, + vty->candidate_config->dnode, + "%s/redistribute/%s[protocol='table'][level='%s']/table", + VTY_CURR_XPATH, rtda->rtda_ip, rtda->rtda_level); + return table; +} + +bool isis_redist_table_is_present(const struct vty *vty, + struct isis_redist_table_present_args *rtda) +{ + rtda->rtda_found = false; + yang_dnode_iterate(_isis_redist_table_is_present, rtda, + vty->candidate_config->dnode, + "%s/redistribute/%s[protocol='table'][level='%s']/table", + VTY_CURR_XPATH, rtda->rtda_ip, rtda->rtda_level); + + return rtda->rtda_found; +} + /* Handle notification about route being added */ void isis_redist_add(struct isis *isis, int type, struct prefix *p, struct prefix_ipv6 *src_p, uint8_t distance, diff --git a/isisd/isis_redist.h b/isisd/isis_redist.h index ae5ec2b3b3..eb82f3083a 100644 --- a/isisd/isis_redist.h +++ b/isisd/isis_redist.h @@ -28,6 +28,14 @@ struct isis_redist { struct route_map *map; }; +struct isis_redist_table_present_args { + /* from filter.h, struct acl_dup_args */ + const char *rtda_ip; + const char *rtda_level; + const char *rtda_table; + bool rtda_found; +}; + struct isis; struct isis_area; struct prefix; @@ -53,4 +61,9 @@ void isis_redist_set(struct isis_area *area, int level, int family, int type, void isis_redist_unset(struct isis_area *area, int level, int family, int type); void isis_redist_free(struct isis *isis); + +bool isis_redist_table_is_present(const struct vty *vty, + struct isis_redist_table_present_args *rtda); +uint16_t isis_redist_table_get_first(const struct vty *vty, + struct isis_redist_table_present_args *rtda); #endif diff --git a/yang/frr-isisd.yang b/yang/frr-isisd.yang index ae69d53ccc..478d058c19 100644 --- a/yang/frr-isisd.yang +++ b/yang/frr-isisd.yang @@ -1495,9 +1495,32 @@ module frr-isisd { "IS-IS level into which the routes should be redistributed."; } - uses redistribute-attributes; - } + choice protocol-type { + case protocol-table { + when "./protocol = \"table\""; + list table { + key "table"; + when "../protocol = \"table\""; + description + "Routing table number"; + leaf table { + type uint16 { + range "1..65535"; + } + description + "Routing table number."; + } + + uses redistribute-attributes; + } + } + case protocol-other { + uses redistribute-attributes; + } + } + + } list ipv6 { key "protocol level"; description @@ -1516,7 +1539,29 @@ module frr-isisd { "IS-IS level into which the routes should be redistributed."; } - uses redistribute-attributes; + choice protocol-type { + case protocol-table { + when "./protocol = \"table\""; + list table { + key "table"; + when "../protocol = \"table\""; + + leaf table { + type uint16 { + range "1..65535"; + } + description + "Routing table number."; + } + + uses redistribute-attributes; + } + } + case protocol-other { + uses redistribute-attributes; + } + } + } } From 4aee03bfd5767a8eebbcf0a99cd55d82605ebda5 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Mon, 3 Jul 2023 18:01:52 +0200 Subject: [PATCH 2/4] isisd: add the 'redistribute table' internal support The 'redistribute table' command does not create the internal contexts with the appropriate table identifier. Redistributed prefixes in IS-IS do not care about the table identifier. Add a linked list of redistribution contexts, and map the nb configuration to the linked list. - A new 'table' attribute is added in the 'struct isis_redist' context. - The 'isis_redist_update_zebra_subscriptions()' function is removed and is replaced by direct call to zebra API for turning on/off redirection. - The redistributed routes coming from zebra import the 'tableid' information. - The fabricd redistribute running-config is reworked, and the 'get_redist_settings()' function is removed. Signed-off-by: Philippe Guibert --- isisd/isis_nb_config.c | 44 +++++++-- isisd/isis_redist.c | 207 +++++++++++++++++++++++------------------ isisd/isis_redist.h | 11 ++- isisd/isis_zebra.c | 16 ++-- isisd/isis_zebra.h | 6 +- isisd/isisd.c | 100 ++++++++++---------- isisd/isisd.h | 4 +- 7 files changed, 225 insertions(+), 163 deletions(-) diff --git a/isisd/isis_nb_config.c b/isisd/isis_nb_config.c index 278d4a8d85..a3d8896e4f 100644 --- a/isisd/isis_nb_config.c +++ b/isisd/isis_nb_config.c @@ -1088,7 +1088,7 @@ void default_info_origin_apply_finish(const struct lyd_node *dnode, int family) routemap = yang_dnode_get_string(dnode, "./route-map"); isis_redist_set(area, level, family, DEFAULT_ROUTE, metric, routemap, - originate_type); + originate_type, 0); } void default_info_origin_ipv4_apply_finish(struct nb_cb_apply_finish_args *args) @@ -1119,7 +1119,7 @@ int isis_instance_default_information_originate_ipv4_destroy( area = nb_running_get_entry(args->dnode, NULL, true); level = yang_dnode_get_enum(args->dnode, "./level"); - isis_redist_unset(area, level, AF_INET, DEFAULT_ROUTE); + isis_redist_unset(area, level, AF_INET, DEFAULT_ROUTE, 0); return NB_OK; } @@ -1182,7 +1182,7 @@ int isis_instance_default_information_originate_ipv6_destroy( area = nb_running_get_entry(args->dnode, NULL, true); level = yang_dnode_get_enum(args->dnode, "./level"); - isis_redist_unset(area, level, AF_INET6, DEFAULT_ROUTE); + isis_redist_unset(area, level, AF_INET6, DEFAULT_ROUTE, 0); return NB_OK; } @@ -1244,7 +1244,7 @@ void redistribute_apply_finish(const struct lyd_node *dnode, int family) if (yang_dnode_exists(dnode, "./route-map")) routemap = yang_dnode_get_string(dnode, "./route-map"); - isis_redist_set(area, level, family, type, metric, routemap, 0); + isis_redist_set(area, level, family, type, metric, routemap, 0, 0); } void redistribute_ipv4_apply_finish(struct nb_cb_apply_finish_args *args) @@ -1274,7 +1274,7 @@ int isis_instance_redistribute_ipv4_destroy(struct nb_cb_destroy_args *args) area = nb_running_get_entry(args->dnode, NULL, true); level = yang_dnode_get_enum(args->dnode, "./level"); type = yang_dnode_get_enum(args->dnode, "./protocol"); - isis_redist_unset(area, level, AF_INET, type); + isis_redist_unset(area, level, AF_INET, type, 0); return NB_OK; } @@ -1319,14 +1319,44 @@ int isis_instance_redistribute_ipv4_metric_destroy(struct nb_cb_destroy_args *ar */ int isis_instance_redistribute_ipv4_table_create(struct nb_cb_create_args *args) { + uint16_t table; + int type, level; + unsigned long metric = 0; + const char *routemap = NULL; + struct isis_area *area; + if (args->event != NB_EV_APPLY) return NB_OK; - /* TODO */ + type = yang_dnode_get_enum(args->dnode, "../protocol"); + level = yang_dnode_get_enum(args->dnode, "../level"); + area = nb_running_get_entry(args->dnode, "../.", true); + + if (yang_dnode_exists(args->dnode, "./metric")) + metric = yang_dnode_get_uint32(args->dnode, "./metric"); + if (yang_dnode_exists(args->dnode, "./route-map")) + routemap = yang_dnode_get_string(args->dnode, "./route-map"); + + table = yang_dnode_get_uint16(args->dnode, "./table"); + isis_redist_set(area, level, AF_INET, type, metric, routemap, 0, table); + return NB_OK; } int isis_instance_redistribute_ipv4_table_destroy(struct nb_cb_destroy_args *args) { + struct isis_area *area; + int level, type; + uint16_t table; + + if (args->event != NB_EV_APPLY) + return NB_OK; + + area = nb_running_get_entry(args->dnode, "../.", true); + level = yang_dnode_get_enum(args->dnode, "../level"); + type = yang_dnode_get_enum(args->dnode, "../protocol"); + table = yang_dnode_get_uint16(args->dnode, "./table"); + isis_redist_unset(area, level, AF_INET, type, table); + return NB_OK; } @@ -1350,7 +1380,7 @@ int isis_instance_redistribute_ipv6_destroy(struct nb_cb_destroy_args *args) area = nb_running_get_entry(args->dnode, NULL, true); level = yang_dnode_get_enum(args->dnode, "./level"); type = yang_dnode_get_enum(args->dnode, "./protocol"); - isis_redist_unset(area, level, AF_INET6, type); + isis_redist_unset(area, level, AF_INET6, type, 0); return NB_OK; } diff --git a/isisd/isis_redist.c b/isisd/isis_redist.c index 2b3facc436..2cb08db27b 100644 --- a/isisd/isis_redist.c +++ b/isisd/isis_redist.c @@ -31,6 +31,7 @@ DEFINE_MTYPE_STATIC(ISISD, ISIS_EXT_ROUTE, "ISIS redistributed route"); DEFINE_MTYPE_STATIC(ISISD, ISIS_EXT_INFO, "ISIS redistributed route info"); DEFINE_MTYPE_STATIC(ISISD, ISIS_RMAP_NAME, "ISIS redistribute route-map name"); +DEFINE_MTYPE_STATIC(ISISD, ISIS_REDISTRIBUTE, "ISIS redistribute"); static int redist_protocol(int family) { @@ -61,12 +62,43 @@ static struct route_table *get_ext_info(struct isis *i, int family) return i->ext_info[protocol]; } -static struct isis_redist *get_redist_settings(struct isis_area *area, - int family, int type, int level) +static struct isis_redist *isis_redist_lookup(struct isis_area *area, + int family, int type, int level, + uint16_t table) { int protocol = redist_protocol(family); + struct listnode *node; + struct isis_redist *red; - return &area->redist_settings[protocol][type][level - 1]; + if (area->redist_settings[protocol][type][level - 1]) { + for (ALL_LIST_ELEMENTS_RO(area->redist_settings[protocol][type] + [level - 1], + node, red)) + if (red->table == table) + return red; + } + return NULL; +} + +static struct isis_redist *isis_redist_get(struct isis_area *area, int family, + int type, int level, uint16_t table) +{ + struct isis_redist *red; + int protocol; + + red = isis_redist_lookup(area, family, type, level, table); + if (red) + return red; + + protocol = redist_protocol(family); + if (area->redist_settings[protocol][type][level - 1] == NULL) + area->redist_settings[protocol][type][level - 1] = list_new(); + + red = XCALLOC(MTYPE_ISIS_REDISTRIBUTE, sizeof(struct isis_redist)); + red->table = table; + + listnode_add(area->redist_settings[protocol][type][level - 1], red); + return red; } struct route_table *get_ext_reach(struct isis_area *area, int family, int level) @@ -256,7 +288,7 @@ bool isis_redist_table_is_present(const struct vty *vty, /* Handle notification about route being added */ void isis_redist_add(struct isis *isis, int type, struct prefix *p, struct prefix_ipv6 *src_p, uint8_t distance, - uint32_t metric, const route_tag_t tag) + uint32_t metric, const route_tag_t tag, uint16_t table) { int family = p->family; struct route_table *ei_table = get_ext_info(isis, family); @@ -296,8 +328,9 @@ void isis_redist_add(struct isis *isis, int type, struct prefix *p, for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) for (level = 1; level <= ISIS_LEVELS; level++) { - redist = get_redist_settings(area, family, type, level); - if (!redist->redist) + redist = isis_redist_lookup(area, family, type, level, + table); + if (!redist || !redist->redist) continue; isis_redist_update_ext_reach(area, level, redist, p, @@ -306,7 +339,7 @@ void isis_redist_add(struct isis *isis, int type, struct prefix *p, } void isis_redist_delete(struct isis *isis, int type, struct prefix *p, - struct prefix_ipv6 *src_p) + struct prefix_ipv6 *src_p, uint16_t table) { int family = p->family; struct route_table *ei_table = get_ext_info(isis, family); @@ -326,7 +359,7 @@ void isis_redist_delete(struct isis *isis, int type, struct prefix *p, * "always" setting will ignore routes with origin * DEFAULT_ROUTE. */ isis_redist_add(isis, DEFAULT_ROUTE, p, NULL, 254, - MAX_WIDE_PATH_METRIC, 0); + MAX_WIDE_PATH_METRIC, 0, table); return; } @@ -349,8 +382,9 @@ void isis_redist_delete(struct isis *isis, int type, struct prefix *p, for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) for (level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) { - redist = get_redist_settings(area, family, type, level); - if (!redist->redist) + redist = isis_redist_lookup(area, family, type, level, + table); + if (!redist || !redist->redist) continue; isis_redist_uninstall(area, level, p, src_p); @@ -376,53 +410,6 @@ static void isis_redist_routemap_set(struct isis_redist *redist, } } -static void isis_redist_update_zebra_subscriptions(struct isis *isis) -{ - struct listnode *node; - struct isis_area *area; - int type; - int level; - int protocol; - - if (isis->vrf_id == VRF_UNKNOWN) - return; - - char do_subscribe[REDIST_PROTOCOL_COUNT][ZEBRA_ROUTE_MAX + 1]; - - memset(do_subscribe, 0, sizeof(do_subscribe)); - - for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) - for (protocol = 0; protocol < REDIST_PROTOCOL_COUNT; protocol++) - for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++) - for (level = 0; level < ISIS_LEVELS; level++) - if (area->redist_settings[protocol] - [type][level] - .redist - == 1) - do_subscribe[protocol][type] = - 1; - - for (protocol = 0; protocol < REDIST_PROTOCOL_COUNT; protocol++) - for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++) { - /* This field is actually controlling transmission of - * the IS-IS - * routes to Zebra and has nothing to do with - * redistribution, - * so skip it. */ - if (type == PROTO_TYPE) - continue; - - afi_t afi = afi_for_redist_protocol(protocol); - - if (do_subscribe[protocol][type]) - isis_zebra_redistribute_set(afi, type, - isis->vrf_id); - else - isis_zebra_redistribute_unset(afi, type, - isis->vrf_id); - } -} - void isis_redist_free(struct isis *isis) { struct route_node *rn; @@ -444,11 +431,12 @@ void isis_redist_free(struct isis *isis) } void isis_redist_set(struct isis_area *area, int level, int family, int type, - uint32_t metric, const char *routemap, int originate_type) + uint32_t metric, const char *routemap, int originate_type, + uint16_t table) { int protocol = redist_protocol(family); - struct isis_redist *redist = - get_redist_settings(area, family, type, level); + struct isis_redist *redist = isis_redist_get(area, family, type, level, + table); int i; struct route_table *ei_table; struct route_node *rn; @@ -468,7 +456,8 @@ void isis_redist_set(struct isis_area *area, int level, int family, int type, } } - isis_redist_update_zebra_subscriptions(area->isis); + isis_zebra_redistribute_set(afi_for_redist_protocol(protocol), type, + area->isis->vrf_id, redist->table); if (type == DEFAULT_ROUTE && originate_type == DEFAULT_ORIGINATE_ALWAYS) isis_redist_ensure_default(area->isis, family); @@ -499,18 +488,26 @@ void isis_redist_set(struct isis_area *area, int level, int family, int type, } } -void isis_redist_unset(struct isis_area *area, int level, int family, int type) +void isis_redist_unset(struct isis_area *area, int level, int family, int type, + uint16_t table) { - struct isis_redist *redist = - get_redist_settings(area, family, type, level); + struct isis_redist *redist = isis_redist_lookup(area, family, type, + level, table); struct route_table *er_table = get_ext_reach(area, family, level); struct route_node *rn; struct isis_ext_info *info; + struct list *redist_list; + int protocol = redist_protocol(family); - if (!redist->redist) + if (!redist || !redist->redist) return; redist->redist = 0; + + redist_list = area->redist_settings[protocol][type][level - 1]; + listnode_delete(redist_list, redist); + XFREE(MTYPE_ISIS_REDISTRIBUTE, redist); + if (!er_table) { zlog_warn("%s: External reachability table uninitialized.", __func__); @@ -540,7 +537,8 @@ void isis_redist_unset(struct isis_area *area, int level, int family, int type) } lsp_regenerate_schedule(area, level, 0); - isis_redist_update_zebra_subscriptions(area->isis); + isis_zebra_redistribute_unset(afi_for_redist_protocol(protocol), type, + area->isis->vrf_id, table); } void isis_redist_area_finish(struct isis_area *area) @@ -549,16 +547,30 @@ void isis_redist_area_finish(struct isis_area *area) int protocol; int level; int type; + struct isis_redist *redist; + struct listnode *node, *nnode; + struct list *redist_list; for (protocol = 0; protocol < REDIST_PROTOCOL_COUNT; protocol++) for (level = 0; level < ISIS_LEVELS; level++) { for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++) { - struct isis_redist *redist; - - redist = &area->redist_settings[protocol][type] - [level]; - redist->redist = 0; - XFREE(MTYPE_ISIS_RMAP_NAME, redist->map_name); + redist_list = area->redist_settings[protocol] + [type][level]; + if (!redist_list) + continue; + for (ALL_LIST_ELEMENTS(redist_list, node, nnode, + redist)) { + redist->redist = 0; + XFREE(MTYPE_ISIS_RMAP_NAME, + redist->map_name); + isis_zebra_redistribute_unset( + afi_for_redist_protocol(protocol), + type, area->isis->vrf_id, + redist->table); + listnode_delete(redist_list, redist); + XFREE(MTYPE_ISIS_REDISTRIBUTE, redist); + } + list_delete(&redist_list); } if (!area->ext_reach[protocol][level]) continue; @@ -570,8 +582,6 @@ void isis_redist_area_finish(struct isis_area *area) route_table_finish(area->ext_reach[protocol][level]); area->ext_reach[protocol][level] = NULL; } - - isis_redist_update_zebra_subscriptions(area->isis); } #ifdef FABRICD @@ -628,7 +638,7 @@ DEFUN (isis_redistribute, routemap = argv[idx_metric_rmap + 1]->arg; } - isis_redist_set(area, level, family, type, metric, routemap, 0); + isis_redist_set(area, level, family, type, metric, routemap, 0, 0); return 0; } @@ -664,7 +674,7 @@ DEFUN (no_isis_redistribute, level = 2; - isis_redist_unset(area, level, family, type); + isis_redist_unset(area, level, family, type, 0); return 0; } @@ -724,7 +734,7 @@ DEFUN (isis_default_originate, } isis_redist_set(area, level, family, DEFAULT_ROUTE, metric, routemap, - originate_type); + originate_type, 0); return 0; } @@ -748,7 +758,7 @@ DEFUN (no_isis_default_originate, level = 2; - isis_redist_unset(area, level, family, DEFAULT_ROUTE); + isis_redist_unset(area, level, family, DEFAULT_ROUTE, 0); return 0; } #endif /* ifdef FABRICD */ @@ -760,7 +770,9 @@ int isis_redist_config_write(struct vty *vty, struct isis_area *area, int level; int write = 0; struct isis_redist *redist; + struct list *redist_list; const char *family_str; + struct listnode *node; if (family == AF_INET) family_str = "ipv4"; @@ -774,25 +786,36 @@ int isis_redist_config_write(struct vty *vty, struct isis_area *area, continue; for (level = 1; level <= ISIS_LEVELS; level++) { - redist = get_redist_settings(area, family, type, level); - if (!redist->redist) + redist_list = area->redist_settings[redist_protocol( + family)][type][level - 1]; + if (!redist_list) continue; - vty_out(vty, " redistribute %s %s", family_str, - zebra_route_string(type)); - if (!fabricd) - vty_out(vty, " level-%d", level); - if (redist->metric) - vty_out(vty, " metric %u", redist->metric); - if (redist->map_name) - vty_out(vty, " route-map %s", redist->map_name); - vty_out(vty, "\n"); - write++; + for (ALL_LIST_ELEMENTS_RO(redist_list, node, redist)) { + if (!redist->redist) + continue; + vty_out(vty, " redistribute %s %s", family_str, + zebra_route_string(type)); + if (type == ZEBRA_ROUTE_TABLE) + vty_out(vty, " %u", redist->table); + if (!fabricd) + vty_out(vty, " level-%d", level); + if (redist->metric) + vty_out(vty, " metric %u", + redist->metric); + if (redist->map_name) + vty_out(vty, " route-map %s", + redist->map_name); + vty_out(vty, "\n"); + write++; + } } } for (level = 1; level <= ISIS_LEVELS; level++) { - redist = - get_redist_settings(area, family, DEFAULT_ROUTE, level); + redist = isis_redist_lookup(area, family, DEFAULT_ROUTE, level, + 0); + if (!redist) + continue; if (!redist->redist) continue; vty_out(vty, " default-information originate %s", diff --git a/isisd/isis_redist.h b/isisd/isis_redist.h index eb82f3083a..688f27e62d 100644 --- a/isisd/isis_redist.h +++ b/isisd/isis_redist.h @@ -26,6 +26,7 @@ struct isis_redist { uint32_t metric; char *map_name; struct route_map *map; + uint16_t table; }; struct isis_redist_table_present_args { @@ -48,17 +49,19 @@ struct route_table *get_ext_reach(struct isis_area *area, int family, int level); void isis_redist_add(struct isis *isis, int type, struct prefix *p, struct prefix_ipv6 *src_p, uint8_t distance, - uint32_t metric, route_tag_t tag); + uint32_t metric, route_tag_t tag, uint16_t instance); void isis_redist_delete(struct isis *isis, int type, struct prefix *p, - struct prefix_ipv6 *src_p); + struct prefix_ipv6 *src_p, uint16_t tableid); int isis_redist_config_write(struct vty *vty, struct isis_area *area, int family); void isis_redist_init(void); void isis_redist_area_finish(struct isis_area *area); void isis_redist_set(struct isis_area *area, int level, int family, int type, - uint32_t metric, const char *routemap, int originate_type); -void isis_redist_unset(struct isis_area *area, int level, int family, int type); + uint32_t metric, const char *routemap, int originate_type, + uint16_t table); +void isis_redist_unset(struct isis_area *area, int level, int family, int type, + uint16_t table); void isis_redist_free(struct isis *isis); diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index 95bd37812f..43e9865fce 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -498,10 +498,10 @@ static int isis_zebra_read(ZAPI_CALLBACK_ARGS) if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD) isis_redist_add(isis, api.type, &api.prefix, &api.src_prefix, - api.distance, api.metric, api.tag); + api.distance, api.metric, api.tag, api.instance); else - isis_redist_delete(isis, api.type, &api.prefix, - &api.src_prefix); + isis_redist_delete(isis, api.type, &api.prefix, &api.src_prefix, + api.instance); return 0; } @@ -511,24 +511,26 @@ int isis_distribute_list_update(int routetype) return 0; } -void isis_zebra_redistribute_set(afi_t afi, int type, vrf_id_t vrf_id) +void isis_zebra_redistribute_set(afi_t afi, int type, vrf_id_t vrf_id, + uint16_t tableid) { if (type == DEFAULT_ROUTE) zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient, afi, vrf_id); else zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, afi, type, - 0, vrf_id); + tableid, vrf_id); } -void isis_zebra_redistribute_unset(afi_t afi, int type, vrf_id_t vrf_id) +void isis_zebra_redistribute_unset(afi_t afi, int type, vrf_id_t vrf_id, + uint16_t tableid) { if (type == DEFAULT_ROUTE) zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, zclient, afi, vrf_id); else zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE, zclient, afi, - type, 0, vrf_id); + type, tableid, vrf_id); } /** diff --git a/isisd/isis_zebra.h b/isisd/isis_zebra.h index 045c75874a..1dcd896d0b 100644 --- a/isisd/isis_zebra.h +++ b/isisd/isis_zebra.h @@ -43,8 +43,10 @@ void isis_zebra_prefix_sid_uninstall(struct isis_area *area, struct isis_sr_psid_info *psid); void isis_zebra_send_adjacency_sid(int cmd, const struct sr_adjacency *sra); int isis_distribute_list_update(int routetype); -void isis_zebra_redistribute_set(afi_t afi, int type, vrf_id_t vrf_id); -void isis_zebra_redistribute_unset(afi_t afi, int type, vrf_id_t vrf_id); +void isis_zebra_redistribute_set(afi_t afi, int type, vrf_id_t vrf_id, + uint16_t tableid); +void isis_zebra_redistribute_unset(afi_t afi, int type, vrf_id_t vrf_id, + uint16_t tableid); int isis_zebra_rlfa_register(struct isis_spftree *spftree, struct rlfa *rlfa); void isis_zebra_rlfa_unregister_all(struct isis_spftree *spftree); bool isis_zebra_label_manager_ready(void); diff --git a/isisd/isisd.c b/isisd/isisd.c index c6a7e803c1..942073b70c 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -599,64 +599,66 @@ static int isis_vrf_delete(struct vrf *vrf) static void isis_set_redist_vrf_bitmaps(struct isis *isis, bool set) { - struct listnode *node; + struct listnode *node, *lnode; struct isis_area *area; int type; int level; int protocol; - - char do_subscribe[REDIST_PROTOCOL_COUNT][ZEBRA_ROUTE_MAX + 1]; - - memset(do_subscribe, 0, sizeof(do_subscribe)); + struct isis_redist *redist; for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) for (protocol = 0; protocol < REDIST_PROTOCOL_COUNT; protocol++) for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++) - for (level = 0; level < ISIS_LEVELS; level++) - if (area->redist_settings[protocol] - [type][level] - .redist - == 1) - do_subscribe[protocol][type] = - 1; + for (level = 0; level < ISIS_LEVELS; level++) { + if (area->redist_settings[protocol][type] + [level] == NULL) + continue; + for (ALL_LIST_ELEMENTS_RO(area->redist_settings + [protocol] + [type] + [level], + lnode, + redist)) { + if (redist->redist == 0) + continue; + /* This field is actually + * controlling transmission of + * the IS-IS + * routes to Zebra and has + * nothing to do with + * redistribution, + * so skip it. */ + afi_t afi = + afi_for_redist_protocol( + protocol); - for (protocol = 0; protocol < REDIST_PROTOCOL_COUNT; protocol++) - for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++) { - /* This field is actually controlling transmission of - * the IS-IS - * routes to Zebra and has nothing to do with - * redistribution, - * so skip it. */ - if (type == PROTO_TYPE) - continue; - - if (!do_subscribe[protocol][type]) - continue; - - afi_t afi = afi_for_redist_protocol(protocol); - - if (type == DEFAULT_ROUTE) { - if (set) - vrf_bitmap_set( - &zclient->default_information - [afi], - isis->vrf_id); - else - vrf_bitmap_unset( - &zclient->default_information - [afi], - isis->vrf_id); - } else { - if (set) - vrf_bitmap_set( - &zclient->redist[afi][type], - isis->vrf_id); - else - vrf_bitmap_unset( - &zclient->redist[afi][type], - isis->vrf_id); - } - } + if (type == DEFAULT_ROUTE) { + if (set) + vrf_bitmap_set( + &zclient->default_information + [afi], + isis->vrf_id); + else + vrf_bitmap_unset( + &zclient->default_information + [afi], + isis->vrf_id); + } else { + if (set) + vrf_bitmap_set( + &zclient->redist + [afi] + [type], + isis->vrf_id); + else + vrf_bitmap_unset( + &zclient->redist + [afi] + [type], + isis->vrf_id); + } + } + } } static int isis_vrf_enable(struct vrf *vrf) diff --git a/isisd/isisd.h b/isisd/isisd.h index f0d236b643..cd2a694453 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -230,8 +230,8 @@ struct isis_area { #endif /* ifndef FABRICD */ /* Counters */ uint32_t circuit_state_changes; - struct isis_redist redist_settings[REDIST_PROTOCOL_COUNT] - [ZEBRA_ROUTE_MAX + 1][ISIS_LEVELS]; + struct list *redist_settings[REDIST_PROTOCOL_COUNT][ZEBRA_ROUTE_MAX + 1] + [ISIS_LEVELS]; struct route_table *ext_reach[REDIST_PROTOCOL_COUNT][ISIS_LEVELS]; struct spf_backoff *spf_delay_ietf[ISIS_LEVELS]; /*Structure with IETF From 23cd58e8573afc6d28a2a75cfc440ddc09ca6ed0 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Tue, 4 Jul 2023 10:50:40 +0200 Subject: [PATCH 3/4] topotests: add isis redistribute table functionality Add a test to ensure that isis redistribution works well. Signed-off-by: Philippe Guibert --- tests/topotests/isis_topo1/r3/r3_route.json | 15 +++++++++++++++ tests/topotests/isis_topo1/r4/r4_route.json | 15 +++++++++++++++ tests/topotests/isis_topo1/r5/isisd.conf | 1 + tests/topotests/isis_topo1/r5/r5_route.json | 16 ++++++++++++++++ tests/topotests/isis_topo1/r5/zebra.conf | 2 ++ 5 files changed, 49 insertions(+) diff --git a/tests/topotests/isis_topo1/r3/r3_route.json b/tests/topotests/isis_topo1/r3/r3_route.json index 61d05e80bb..c3b6e3b0a6 100644 --- a/tests/topotests/isis_topo1/r3/r3_route.json +++ b/tests/topotests/isis_topo1/r3/r3_route.json @@ -146,5 +146,20 @@ "protocol": "isis", "selected": true } + ], + "192.0.2.6/32": [ + { + "nexthops": [ + { + "active": true, + "fib": true, + "ip": "10.0.10.1", + "interfaceName": "r3-eth1" + } + ], + "prefix": "192.0.2.6/32", + "protocol": "isis", + "selected": true + } ] } diff --git a/tests/topotests/isis_topo1/r4/r4_route.json b/tests/topotests/isis_topo1/r4/r4_route.json index 79361af4b5..8fd46add33 100644 --- a/tests/topotests/isis_topo1/r4/r4_route.json +++ b/tests/topotests/isis_topo1/r4/r4_route.json @@ -61,5 +61,20 @@ "protocol": "connected", "selected": true } + ], + "192.0.2.6/32": [ + { + "nexthops": [ + { + "active": true, + "fib": true, + "ip": "10.0.11.1", + "interfaceName": "r4-eth1" + } + ], + "prefix": "192.0.2.6/32", + "protocol": "isis", + "selected": true + } ] } diff --git a/tests/topotests/isis_topo1/r5/isisd.conf b/tests/topotests/isis_topo1/r5/isisd.conf index e0e9200d62..81686e0525 100644 --- a/tests/topotests/isis_topo1/r5/isisd.conf +++ b/tests/topotests/isis_topo1/r5/isisd.conf @@ -20,4 +20,5 @@ router isis 1 is-type level-1 redistribute ipv4 connected level-1 redistribute ipv6 connected level-1 + redistribute ipv4 table 20 level-1 ! diff --git a/tests/topotests/isis_topo1/r5/r5_route.json b/tests/topotests/isis_topo1/r5/r5_route.json index cca844b27c..ec544b8e85 100644 --- a/tests/topotests/isis_topo1/r5/r5_route.json +++ b/tests/topotests/isis_topo1/r5/r5_route.json @@ -141,5 +141,21 @@ "protocol": "connected", "selected": true } + ], + "192.0.2.6/32": [ + { + "nexthops": [ + { + "active": true, + "fib": true, + "ip": "10.0.10.6", + "interfaceName": "r5-eth0" + } + ], + "prefix": "192.0.2.6/32", + "protocol": "table", + "instance": 20, + "selected": true + } ] } diff --git a/tests/topotests/isis_topo1/r5/zebra.conf b/tests/topotests/isis_topo1/r5/zebra.conf index 48fed69662..7c400f797b 100644 --- a/tests/topotests/isis_topo1/r5/zebra.conf +++ b/tests/topotests/isis_topo1/r5/zebra.conf @@ -1,4 +1,6 @@ hostname r5 +ip route 192.0.2.6/32 10.0.10.6 table 20 +ip import 20 interface r5-eth0 ip address 10.0.10.1/24 ipv6 address 2001:db8:2:1::1/64 From 492b93bea0f1c366ad7ba0b85557501f03c1c304 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Thu, 6 Jul 2023 22:40:50 +0200 Subject: [PATCH 4/4] zebra: fix imported static routes deletion When unconfiguring 'no import ', a static route imported from a routing table number is never deleted. When importing a route from a given table, a default distance of 15 is applied. At the time of deletion, when trying to compare the original route with the new one, the distance does not match, because the static route applies a default distance of 1. If the imported route has the distance set, unset the distance flag to avoid comparing it. Signed-off-by: Philippe Guibert --- zebra/redistribute.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 11b7b7cf82..9ca9c7a55a 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -675,6 +675,8 @@ int zebra_add_import_table_entry(struct zebra_vrf *zvrf, struct route_node *rn, zebra_del_import_table_entry(zvrf, rn, same); } + UNSET_FLAG(re->flags, ZEBRA_FLAG_RR_USE_DISTANCE); + newre = zebra_rib_route_entry_new( 0, ZEBRA_ROUTE_TABLE, re->table, re->flags, re->nhe_id, zvrf->table_id, re->metric, re->mtu,