]> git.puffer.fish Git - matthieu/frr.git/commitdiff
isisd: add redistribute table identifier in nb configuration
authorPhilippe Guibert <philippe.guibert@6wind.com>
Mon, 3 Jul 2023 15:15:05 +0000 (17:15 +0200)
committerPhilippe Guibert <philippe.guibert@6wind.com>
Wed, 12 Jul 2023 12:06:00 +0000 (14:06 +0200)
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>
doc/user/isisd.rst
isisd/isis_cli.c
isisd/isis_nb.c
isisd/isis_nb.h
isisd/isis_nb_config.c
isisd/isis_redist.c
isisd/isis_redist.h
yang/frr-isisd.yang

index 570b8bd182d4cd0df236bd9ab3b4529cf3a59c16..83fc2e0281ea8dba8813f985f5d09be21780570a 100644 (file)
@@ -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
index 7c7a8d238941a2d1c88aa680801e3d1275c6116b..6f53ab479fe0541ed93ae3e5677ec13ae83de6a8 100644 (file)
@@ -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);
 
index 6da8fa2d28e2a6952f0022ea23de4d8db3a090c8..c81412d24ab280ded6a641c33ec275429f9090ce 100644 (file)
@@ -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,
                        },
index 13efa36d789e051bd26b5b4a2745c488c1fcb6a9..3b8ddca4f840a9ef3e56fdbb90bed1751fc84ac9 100644 (file)
@@ -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 */
 
index 8a111b301da7ea59d9c4cd2bb76267bb4c9a721c..278d4a8d857194725298386715b07d2a23f3a30c 100644 (file)
@@ -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
  */
index 6a822f02fea0de9ed4fb16be3b44a4a7ca314c1c..2b3facc4368dce362d65be23fa369adcafb7a33c 100644 (file)
@@ -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,
index ae5ec2b3b3fe2f12948bee5ececa94e5e7663293..eb82f3083a756689f59db1fed1544b59ec269027 100644 (file)
@@ -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
index ae69d53ccc0ec9603dbe13226fc14fd05dd1aecb..478d058c192db654c4d46c2af1d8e553690058b7 100644 (file)
@@ -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;
+            }
+          }
+
         }
       }