summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_packet.c5
-rw-r--r--bgpd/bgp_route.c8
-rw-r--r--bgpd/bgp_vty.c8
-rw-r--r--bgpd/bgpd.c2
-rw-r--r--bgpd/bgpd.h3
-rw-r--r--doc/user/isisd.rst5
-rw-r--r--isisd/isis_cli.c128
-rw-r--r--isisd/isis_nb.c46
-rw-r--r--isisd/isis_nb.h19
-rw-r--r--isisd/isis_nb_config.c93
-rw-r--r--isisd/isis_redist.c254
-rw-r--r--isisd/isis_redist.h24
-rw-r--r--isisd/isis_zebra.c16
-rw-r--r--isisd/isis_zebra.h6
-rw-r--r--isisd/isisd.c102
-rw-r--r--isisd/isisd.h4
-rw-r--r--lib/nexthop.c2
-rw-r--r--tests/topotests/isis_topo1/r3/r3_route.json15
-rw-r--r--tests/topotests/isis_topo1/r4/r4_route.json15
-rw-r--r--tests/topotests/isis_topo1/r5/isisd.conf1
-rw-r--r--tests/topotests/isis_topo1/r5/r5_route.json16
-rw-r--r--tests/topotests/isis_topo1/r5/zebra.conf2
-rw-r--r--yang/frr-isisd.yang51
-rw-r--r--zebra/redistribute.c2
-rw-r--r--zebra/zebra_rib.c8
25 files changed, 643 insertions, 192 deletions
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index ab9e940997..2d1fc103bc 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -956,8 +956,9 @@ static void bgp_notify_send_internal(struct peer *peer, uint8_t code,
if (use_curr && peer->curr) {
size_t packetsize = stream_get_endp(peer->curr);
assert(packetsize <= peer->max_packet_size);
- memcpy(peer->last_reset_cause, peer->curr->data, packetsize);
- peer->last_reset_cause_size = packetsize;
+ if (peer->last_reset_cause)
+ stream_free(peer->last_reset_cause);
+ peer->last_reset_cause = stream_dup(peer->curr);
}
/* For debug */
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 4e83b36fe0..5f923c598f 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -14639,8 +14639,12 @@ CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
json_object_free(json_ocode);
}
- vty_json(vty, json);
- } else if (output_count > 0) {
+ /*
+ * This is an extremely expensive operation at scale
+ * and non-pretty reduces memory footprint significantly.
+ */
+ vty_json_no_pretty(vty, json);
+ } else if (output_count > 0) {
if (!match && filtered_count > 0)
vty_out(vty,
"\nTotal number of prefixes %ld (%ld filtered)\n",
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 02ee5320e9..4f773f21a5 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -14862,15 +14862,15 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
BGP_UPTIME_LEN, 0, NULL));
bgp_show_peer_reset(vty, p, NULL, false);
- if (p->last_reset_cause_size) {
- msg = p->last_reset_cause;
+ if (p->last_reset_cause) {
+ msg = p->last_reset_cause->data;
vty_out(vty,
" Message received that caused BGP to send a NOTIFICATION:\n ");
- for (i = 1; i <= p->last_reset_cause_size;
+ for (i = 1; i <= p->last_reset_cause->size;
i++) {
vty_out(vty, "%02X", *msg++);
- if (i != p->last_reset_cause_size) {
+ if (i != p->last_reset_cause->size) {
if (i % 16 == 0) {
vty_out(vty, "\n ");
} else if (i % 4 == 0) {
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index fa28a3098b..dfa5956ba1 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -1189,6 +1189,8 @@ static void peer_free(struct peer *peer)
bgp_unlock(peer->bgp);
+ stream_free(peer->last_reset_cause);
+
memset(peer, 0, sizeof(struct peer));
XFREE(MTYPE_BGP_PEER, peer);
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 5c42abef5e..5e467bb873 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -1716,8 +1716,7 @@ struct peer {
* a new value to the last_reset reason
*/
- uint16_t last_reset_cause_size;
- uint8_t last_reset_cause[BGP_MAX_PACKET_SIZE];
+ struct stream *last_reset_cause;
/* The kind of route-map Flags.*/
uint16_t rmap_type;
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 <ipv4 | ipv6> table (1-65535) <level-1 | level-2> [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)
-{
- const char *level = yang_dnode_get_string(dnode, "./level");
- const char *protocol = yang_dnode_get_string(dnode, "./protocol");
+/*
+ * XPath: /frr-isisd:isis/instance/redistribute/table
+ */
+DEFPY_YANG(isis_redistribute_table, isis_redistribute_table_cmd,
+ "[no] redistribute <ipv4|ipv6>$ip table (1-65535)$table"
+ "<level-1|level-2>$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")
+{
+ struct isis_redist_table_present_args rtda = {};
+ char xpath[XPATH_MAXLEN];
+ char xpath_entry[XPATH_MAXLEN + 128];
+ int rv;
+
+ rtda.rtda_table = table_str;
+ rtda.rtda_ip = ip;
+ rtda.rtda_level = level;
- vty_out(vty, " redistribute %s %s %s", family, protocol, 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
@@ -382,6 +382,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,
},
},
@@ -404,6 +427,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..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,13 +1274,14 @@ 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;
}
/*
* 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,58 @@ 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)
+{
+ 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;
+
+ 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;
+}
+
/*
* XPath: /frr-isisd:isis/instance/redistribute/ipv6
*/
@@ -1326,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;
}
@@ -1358,6 +1412,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..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;
+
+ 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;
- return &area->redist_settings[protocol][type][level - 1];
+ 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)
@@ -206,10 +238,57 @@ 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,
- 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);
@@ -249,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,
@@ -259,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);
@@ -279,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;
}
@@ -302,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);
@@ -329,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;
@@ -397,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;
@@ -421,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);
@@ -452,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__);
@@ -493,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)
@@ -502,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;
@@ -523,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
@@ -581,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;
}
@@ -617,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;
}
@@ -677,7 +734,7 @@ DEFUN (isis_default_originate,
}
isis_redist_set(area, level, family, DEFAULT_ROUTE, metric, routemap,
- originate_type);
+ originate_type, 0);
return 0;
}
@@ -701,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 */
@@ -713,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";
@@ -727,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 ae5ec2b3b3..688f27e62d 100644
--- a/isisd/isis_redist.h
+++ b/isisd/isis_redist.h
@@ -26,6 +26,15 @@ struct isis_redist {
uint32_t metric;
char *map_name;
struct route_map *map;
+ uint16_t table;
+};
+
+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;
@@ -40,17 +49,24 @@ 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);
+
+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/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 (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);
- }
- }
+ 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);
+
+ 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
diff --git a/lib/nexthop.c b/lib/nexthop.c
index dcbb76b68e..6b6b0a79c1 100644
--- a/lib/nexthop.c
+++ b/lib/nexthop.c
@@ -932,6 +932,8 @@ ssize_t printfrr_nhs(struct fbuf *buf, const struct nexthop *nexthop)
ret += bputs(buf, "blackhole");
break;
}
+
+ ret += bprintfrr(buf, " vrfid %u", nexthop->vrf_id);
return ret;
}
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
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;
+ }
+ }
+
}
}
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,
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index a5e036fe48..c61b37a697 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -4170,10 +4170,10 @@ static int rib_meta_queue_early_route_add(struct meta_queue *mq, void *data)
mq->size++;
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
- zlog_debug(
- "Route %pFX(%u) queued for processing into sub-queue %s",
- &ere->p, ere->re->vrf_id,
- subqueue2str(META_QUEUE_EARLY_ROUTE));
+ zlog_debug("Route %pFX(%u) (%s) queued for processing into sub-queue %s",
+ &ere->p, ere->re->vrf_id,
+ ere->deletion ? "delete" : "add",
+ subqueue2str(META_QUEUE_EARLY_ROUTE));
return 0;
}