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 <philippe.guibert@6wind.com>
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
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");
}
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;
}
/*
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);
},
{
.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,
},
},
{
.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,
},
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(
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(
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,
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 */
/*
* 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)
/*
* 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)
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
*/
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
*/
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,
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;
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
"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
"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;
+ }
+ }
+
}
}