]> git.puffer.fish Git - matthieu/frr.git/commitdiff
isisd: update struct isis_route_info has multiple sr info by algorithm
authorHiroki Shirokura <hiroki.shirokura@linecorp.com>
Sun, 12 Dec 2021 09:20:21 +0000 (09:20 +0000)
committerLouis Scalbert <louis.scalbert@6wind.com>
Tue, 18 Apr 2023 08:11:53 +0000 (10:11 +0200)
Before this commit, there was only one sr psid info
included in route_info.

In fact, in RFC8667, Algorithm ID, which is a property of
Prefix-SID, has 8 bits of information. That is, each Prefix
can hold up to 256 Prefix-SIDs. This commit implements it.
The previously implemented single Prefix-SID will be
continued as Algorithm 0.

Signed-off-by: Hiroki Shirokura <hiroki.shirokura@linecorp.com>
Signed-off-by: Louis Scalbert <louis.scalbert@6wind.com>
isisd/isis_route.c
isisd/isis_route.h
isisd/isis_spf.c

index 20d30a148c5011d9f575ba90e1f1d52190a8eb2e..3191dfa4ff41bde804228957e8ef1e419ceefacc 100644 (file)
@@ -39,6 +39,8 @@
 
 DEFINE_MTYPE_STATIC(ISISD, ISIS_NEXTHOP,    "ISIS nexthop");
 DEFINE_MTYPE_STATIC(ISISD, ISIS_ROUTE_INFO, "ISIS route info");
+DEFINE_MTYPE_STATIC(ISISD, ISIS_ROUTE_TABLE_INFO, "ISIS route table info");
+
 
 DEFINE_HOOK(isis_route_update_hook,
            (struct isis_area * area, struct prefix *prefix,
@@ -51,8 +53,25 @@ static void isis_route_update(struct isis_area *area, struct prefix *prefix,
                              struct prefix_ipv6 *src_p,
                              struct isis_route_info *route_info);
 
-static struct isis_nexthop *isis_nexthop_create(int family, union g_addr *ip,
-                                               ifindex_t ifindex)
+static struct mpls_label_stack *
+label_stack_dup(const struct mpls_label_stack *const orig)
+{
+       struct mpls_label_stack *copy;
+       int array_size;
+
+       if (orig == NULL)
+               return NULL;
+
+       array_size = orig->num_labels * sizeof(mpls_label_t);
+       copy = XCALLOC(MTYPE_ISIS_NEXTHOP_LABELS,
+                      sizeof(struct mpls_label_stack) + array_size);
+       copy->num_labels = orig->num_labels;
+       memcpy(copy->label, orig->label, array_size);
+       return copy;
+}
+
+static struct isis_nexthop *
+isis_nexthop_create(int family, const union g_addr *const ip, ifindex_t ifindex)
 {
        struct isis_nexthop *nexthop;
 
@@ -65,12 +84,40 @@ static struct isis_nexthop *isis_nexthop_create(int family, union g_addr *ip,
        return nexthop;
 }
 
+static struct isis_nexthop *
+isis_nexthop_dup(const struct isis_nexthop *const orig)
+{
+       struct isis_nexthop *nexthop;
+
+       nexthop = isis_nexthop_create(orig->family, &orig->ip, orig->ifindex);
+       memcpy(nexthop->sysid, orig->sysid, ISIS_SYS_ID_LEN);
+       nexthop->sr = orig->sr;
+       nexthop->label_stack = label_stack_dup(orig->label_stack);
+
+       return nexthop;
+}
+
 void isis_nexthop_delete(struct isis_nexthop *nexthop)
 {
        XFREE(MTYPE_ISIS_NEXTHOP_LABELS, nexthop->label_stack);
        XFREE(MTYPE_ISIS_NEXTHOP, nexthop);
 }
 
+static struct list *isis_nexthop_list_dup(const struct list *orig)
+{
+       struct list *copy;
+       struct listnode *node;
+       struct isis_nexthop *nh;
+       struct isis_nexthop *nhcopy;
+
+       copy = list_new();
+       for (ALL_LIST_ELEMENTS_RO(orig, node, nh)) {
+               nhcopy = isis_nexthop_dup(nh);
+               listnode_add(copy, nhcopy);
+       }
+       return copy;
+}
+
 static struct isis_nexthop *nexthoplookup(struct list *nexthops, int family,
                                          union g_addr *ip, ifindex_t ifindex)
 {
@@ -238,9 +285,9 @@ isis_route_info_new(struct prefix *prefix, struct prefix_ipv6 *src_p,
 
        rinfo->cost = cost;
        rinfo->depth = depth;
-       rinfo->sr = *sr;
-       rinfo->sr.nexthops = rinfo->nexthops;
-       rinfo->sr.nexthops_backup =
+       rinfo->sr_algo[sr->algorithm] = *sr;
+       rinfo->sr_algo[sr->algorithm].nexthops = rinfo->nexthops;
+       rinfo->sr_algo[sr->algorithm].nexthops_backup =
                rinfo->backup ? rinfo->backup->nexthops : NULL;
 
        return rinfo;
@@ -248,6 +295,18 @@ isis_route_info_new(struct prefix *prefix, struct prefix_ipv6 *src_p,
 
 static void isis_route_info_delete(struct isis_route_info *route_info)
 {
+       for (int i = 0; i < SR_ALGORITHM_COUNT; i++) {
+               if (!route_info->sr_algo[i].present)
+                       continue;
+
+               if (route_info->sr_algo[i].nexthops == route_info->nexthops)
+                       continue;
+
+               route_info->sr_algo[i].nexthops->del =
+                       (void (*)(void *))isis_nexthop_delete;
+               list_delete(&route_info->sr_algo[i].nexthops);
+       }
+
        if (route_info->nexthops) {
                route_info->nexthops->del =
                        (void (*)(void *))isis_nexthop_delete;
@@ -263,6 +322,27 @@ void isis_route_node_cleanup(struct route_table *table, struct route_node *node)
                isis_route_info_delete(node->info);
 }
 
+struct isis_route_table_info *isis_route_table_info_alloc(uint8_t algorithm)
+{
+       struct isis_route_table_info *info;
+
+       info = XCALLOC(MTYPE_ISIS_ROUTE_TABLE_INFO, sizeof(*info));
+       info->algorithm = algorithm;
+       return info;
+}
+
+void isis_route_table_info_free(void *info)
+{
+       XFREE(MTYPE_ISIS_ROUTE_TABLE_INFO, info);
+}
+
+uint8_t isis_route_table_algorithm(const struct route_table *table)
+{
+       const struct isis_route_table_info *info = table->info;
+
+       return info ? info->algorithm : 0;
+}
+
 static bool isis_sr_psid_info_same(struct isis_sr_psid_info *new,
                                   struct isis_sr_psid_info *old)
 {
@@ -319,10 +399,22 @@ static int isis_route_info_same(struct isis_route_info *new,
                return 0;
        }
 
-       if (!isis_sr_psid_info_same(&new->sr, &old->sr)) {
-               if (buf)
-                       snprintf(buf, buf_size, "SR input label");
-               return 0;
+       for (int i = 0; i < SR_ALGORITHM_COUNT; i++) {
+               struct isis_sr_psid_info new_sr_algo;
+               struct isis_sr_psid_info old_sr_algo;
+
+               new_sr_algo = new->sr_algo[i];
+               old_sr_algo = old->sr_algo[i];
+
+               if (!isis_sr_psid_info_same(&new_sr_algo, &old_sr_algo)) {
+                       if (buf)
+                               snprintf(
+                                       buf, buf_size,
+                                       "SR input label algo-%u (old: %s, new: %s)",
+                                       i, old_sr_algo.present ? "yes" : "no",
+                                       new_sr_algo.present ? "yes" : "no");
+                       return 0;
+               }
        }
 
        if (new->nexthops->count != old->nexthops->count) {
@@ -411,7 +503,9 @@ isis_route_create(struct prefix *prefix, struct prefix_ipv6 *src_p,
                                zlog_debug(
                                        "ISIS-Rte (%s): route changed: %pFX, change: %s",
                                        area->area_tag, prefix, change_buf);
-                       rinfo_new->sr_previous = rinfo_old->sr;
+                       for (int i = 0; i < SR_ALGORITHM_COUNT; i++)
+                               rinfo_new->sr_algo_previous[i] =
+                                       rinfo_old->sr_algo[i];
                        isis_route_info_delete(rinfo_old);
                        route_info = rinfo_new;
                        UNSET_FLAG(route_info->flag,
@@ -467,11 +561,42 @@ static void isis_route_remove_previous_sid(struct isis_area *area,
         * Explicitly uninstall previous Prefix-SID label if it has
         * changed or was removed.
         */
-       if (route_info->sr_previous.present &&
-           (!route_info->sr.present ||
-            route_info->sr_previous.label != route_info->sr.label))
-               isis_zebra_prefix_sid_uninstall(area, prefix, route_info,
-                                               &route_info->sr_previous);
+       for (int i = 0; i < SR_ALGORITHM_COUNT; i++) {
+               if (route_info->sr_algo_previous[i].present &&
+                   (!route_info->sr_algo[i].present ||
+                    route_info->sr_algo_previous[i].label !=
+                            route_info->sr_algo[i].label))
+                       isis_zebra_prefix_sid_uninstall(
+                               area, prefix, route_info,
+                               &route_info->sr_algo_previous[i]);
+       }
+}
+
+static void set_merge_route_info_sr_algo(struct isis_route_info *mrinfo,
+                                        struct isis_route_info *rinfo)
+{
+       for (int i = 0; i < SR_ALGORITHM_COUNT; i++) {
+               if (rinfo->sr_algo[i].present) {
+                       assert(i == rinfo->sr_algo[i].algorithm);
+                       assert(rinfo->nexthops);
+                       assert(rinfo->backup ? rinfo->backup->nexthops != NULL
+                                            : true);
+
+                       if (mrinfo->sr_algo[i].nexthops != NULL &&
+                           mrinfo->sr_algo[i].nexthops != mrinfo->nexthops) {
+                               mrinfo->sr_algo[i].nexthops->del =
+                                       (void (*)(void *))isis_nexthop_delete;
+                               list_delete(&mrinfo->sr_algo[i].nexthops);
+                       }
+
+                       mrinfo->sr_algo[i] = rinfo->sr_algo[i];
+                       mrinfo->sr_algo[i].nexthops = isis_nexthop_list_dup(
+                               rinfo->sr_algo[i].nexthops);
+               }
+       }
+
+       UNSET_FLAG(rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
+       UNSET_FLAG(mrinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
 }
 
 static void isis_route_update(struct isis_area *area, struct prefix *prefix,
@@ -490,10 +615,22 @@ static void isis_route_update(struct isis_area *area, struct prefix *prefix,
                /* Install route. */
                isis_zebra_route_add_route(area->isis, prefix, src_p,
                                           route_info);
-               /* Install/reinstall Prefix-SID label. */
-               if (route_info->sr.present)
-                       isis_zebra_prefix_sid_install(area, prefix,
-                                                     &route_info->sr);
+
+               for (int i = 0; i < SR_ALGORITHM_COUNT; i++) {
+                       struct isis_sr_psid_info sr_algo;
+
+                       sr_algo = route_info->sr_algo[i];
+
+                       /*
+                        * Install/reinstall Prefix-SID label.
+                        */
+                       if (sr_algo.present)
+                               isis_zebra_prefix_sid_install(area, prefix,
+                                                             &sr_algo);
+
+                       hook_call(isis_route_update_hook, area, prefix,
+                                 route_info);
+               }
 
                hook_call(isis_route_update_hook, area, prefix, route_info);
 
@@ -501,9 +638,12 @@ static void isis_route_update(struct isis_area *area, struct prefix *prefix,
                UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
        } else {
                /* Uninstall Prefix-SID label. */
-               if (route_info->sr.present)
-                       isis_zebra_prefix_sid_uninstall(
-                               area, prefix, route_info, &route_info->sr);
+               for (int i = 0; i < SR_ALGORITHM_COUNT; i++)
+                       if (route_info->sr_algo[i].present)
+                               isis_zebra_prefix_sid_uninstall(
+                                       area, prefix, route_info,
+                                       &route_info->sr_algo[i]);
+
                /* Uninstall route. */
                isis_zebra_route_del_route(area->isis, prefix, src_p,
                                           route_info);
@@ -523,6 +663,7 @@ static void _isis_route_verify_table(struct isis_area *area,
 #ifdef EXTREME_DEBUG
        char buff[SRCDEST2STR_BUFFER];
 #endif /* EXTREME_DEBUG */
+       uint8_t algorithm = isis_route_table_algorithm(table);
 
        for (rnode = route_top(table); rnode;
             rnode = srcdest_route_next(rnode)) {
@@ -545,13 +686,14 @@ static void _isis_route_verify_table(struct isis_area *area,
                                                         src_p);
                        if (rnode_bck) {
                                rinfo->backup = rnode_bck->info;
-                               rinfo->sr.nexthops_backup =
+                               rinfo->sr_algo[algorithm].nexthops_backup =
                                        rinfo->backup->nexthops;
                                UNSET_FLAG(rinfo->flag,
                                           ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
                        } else if (rinfo->backup) {
                                rinfo->backup = NULL;
-                               rinfo->sr.nexthops_backup = NULL;
+                               rinfo->sr_algo[algorithm].nexthops_backup =
+                                       NULL;
                                UNSET_FLAG(rinfo->flag,
                                           ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
                        }
@@ -645,6 +787,8 @@ void isis_route_verify_merge(struct isis_area *area,
        merge = srcdest_table_init();
 
        for (int level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) {
+               uint8_t algorithm =
+                       isis_route_table_algorithm(tables[level - 1]);
                for (rnode = route_top(tables[level - 1]); rnode;
                     rnode = srcdest_route_next(rnode)) {
                        struct isis_route_info *rinfo = rnode->info;
@@ -665,13 +809,14 @@ void isis_route_verify_merge(struct isis_area *area,
                                tables_backup[level - 1], prefix, src_p);
                        if (rnode_bck) {
                                rinfo->backup = rnode_bck->info;
-                               rinfo->sr.nexthops_backup =
+                               rinfo->sr_algo[algorithm].nexthops_backup =
                                        rinfo->backup->nexthops;
                                UNSET_FLAG(rinfo->flag,
                                           ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
                        } else if (rinfo->backup) {
                                rinfo->backup = NULL;
-                               rinfo->sr.nexthops_backup = NULL;
+                               rinfo->sr_algo[algorithm].nexthops_backup =
+                                       NULL;
                                UNSET_FLAG(rinfo->flag,
                                           ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
                        }
@@ -680,6 +825,8 @@ void isis_route_verify_merge(struct isis_area *area,
                        struct isis_route_info *mrinfo = mrnode->info;
                        if (mrinfo) {
                                route_unlock_node(mrnode);
+                               set_merge_route_info_sr_algo(mrinfo, rinfo);
+
                                if (CHECK_FLAG(mrinfo->flag,
                                               ISIS_ROUTE_FLAG_ACTIVE)) {
                                        /* Clear the ZEBRA_SYNCED flag on the
@@ -723,6 +870,7 @@ void isis_route_invalidate_table(struct isis_area *area,
 {
        struct route_node *rode;
        struct isis_route_info *rinfo;
+       uint8_t algorithm = isis_route_table_algorithm(table);
        for (rode = route_top(table); rode; rode = srcdest_route_next(rode)) {
                if (rode->info == NULL)
                        continue;
@@ -730,7 +878,7 @@ void isis_route_invalidate_table(struct isis_area *area,
 
                if (rinfo->backup) {
                        rinfo->backup = NULL;
-                       rinfo->sr.nexthops_backup = NULL;
+                       rinfo->sr_algo[algorithm].nexthops_backup = NULL;
                        /*
                         * For now, always force routes that have backup
                         * nexthops to be reinstalled.
index 40e7462898d4da027b98ac1d1dd10cbc6aecec63..79b604b779f32268ae492003186f072c7fb499c0 100644 (file)
@@ -30,12 +30,16 @@ struct isis_route_info {
        uint8_t flag;
        uint32_t cost;
        uint32_t depth;
-       struct isis_sr_psid_info sr;
-       struct isis_sr_psid_info sr_previous;
+       struct isis_sr_psid_info sr_algo[SR_ALGORITHM_COUNT];
+       struct isis_sr_psid_info sr_algo_previous[SR_ALGORITHM_COUNT];
        struct list *nexthops;
        struct isis_route_info *backup;
 };
 
+struct isis_route_table_info {
+       uint8_t algorithm;
+};
+
 DECLARE_HOOK(isis_route_update_hook,
             (struct isis_area * area, struct prefix *prefix,
              struct isis_route_info *route_info),
@@ -73,9 +77,14 @@ void isis_route_invalidate_table(struct isis_area *area,
 void isis_route_node_cleanup(struct route_table *table,
                             struct route_node *node);
 
+
 void isis_route_switchover_nexthop(struct isis_area *area,
                                   struct route_table *table, int family,
                                   union g_addr *nexthop_addr,
                                   ifindex_t ifindex);
 
+struct isis_route_table_info *isis_route_table_info_alloc(uint8_t algorithm);
+void isis_route_table_info_free(void *info);
+uint8_t isis_route_table_algorithm(const struct route_table *table);
+
 #endif /* _ZEBRA_ISIS_ROUTE_H */
index 4a9f0ed0cd5da7fbc99034fec4b24cdad8f89dfc..6bfb83c2108f2dac6375d19baeebf425f09e4ff6 100644 (file)
@@ -335,7 +335,9 @@ isis_spftree_new(struct isis_area *area, struct lspdb_head *lspdb,
        isis_vertex_queue_init(&tree->paths, "IS-IS SPF paths", false);
        tree->route_table = srcdest_table_init();
        tree->route_table->cleanup = isis_route_node_cleanup;
+       tree->route_table->info = isis_route_table_info_alloc(algorithm);
        tree->route_table_backup = srcdest_table_init();
+       tree->route_table_backup->info = isis_route_table_info_alloc(algorithm);
        tree->route_table_backup->cleanup = isis_route_node_cleanup;
        tree->area = area;
        tree->lspdb = lspdb;
@@ -380,6 +382,8 @@ void isis_spftree_del(struct isis_spftree *spftree)
        list_delete(&spftree->sadj_list);
        isis_vertex_queue_free(&spftree->tents);
        isis_vertex_queue_free(&spftree->paths);
+       isis_route_table_info_free(spftree->route_table->info);
+       isis_route_table_info_free(spftree->route_table_backup->info);
        route_table_finish(spftree->route_table);
        route_table_finish(spftree->route_table_backup);
        spftree->route_table = NULL;
@@ -1838,11 +1842,18 @@ void isis_spf_verify_routes(struct isis_area *area, struct isis_spftree **trees)
 
 void isis_spf_invalidate_routes(struct isis_spftree *tree)
 {
+       struct isis_route_table_info *backup_info;
+
        isis_route_invalidate_table(tree->area, tree->route_table);
 
        /* Delete backup routes. */
+
+       backup_info = tree->route_table_backup->info;
        route_table_finish(tree->route_table_backup);
+       isis_route_table_info_free(backup_info);
        tree->route_table_backup = srcdest_table_init();
+       tree->route_table_backup->info =
+               isis_route_table_info_alloc(tree->algorithm);
        tree->route_table_backup->cleanup = isis_route_node_cleanup;
 }
 
@@ -2242,8 +2253,10 @@ static void isis_print_route(struct ttable *tt, const struct prefix *prefix,
                        if (nexthop->sr.present) {
                                snprintf(buf_sid, sizeof(buf_sid), "%u",
                                         nexthop->sr.sid.value);
-                               sr_op2str(buf_lblop, sizeof(buf_lblop),
-                                         rinfo->sr.label, nexthop->sr.label);
+                               sr_op2str(
+                                       buf_lblop, sizeof(buf_lblop),
+                                       rinfo->sr_algo[SR_ALGORITHM_SPF].label,
+                                       nexthop->sr.label);
                        } else {
                                strlcpy(buf_sid, "-", sizeof(buf_sid));
                                strlcpy(buf_lblop, "-", sizeof(buf_lblop));
@@ -2298,12 +2311,14 @@ static void isis_print_route(struct ttable *tt, const struct prefix *prefix,
                        char buf_sid[BUFSIZ] = {};
                        char buf_lblop[BUFSIZ] = {};
 
-                       if (rinfo->sr.present) {
+                       if (rinfo->sr_algo[SR_ALGORITHM_SPF].present) {
                                snprintf(buf_sid, sizeof(buf_sid), "%u",
-                                        rinfo->sr.sid.value);
-                               sr_op2str(buf_lblop, sizeof(buf_lblop),
-                                         rinfo->sr.label,
-                                         MPLS_LABEL_IMPLICIT_NULL);
+                                        rinfo->sr_algo[SR_ALGORITHM_SPF]
+                                                .sid.value);
+                               sr_op2str(
+                                       buf_lblop, sizeof(buf_lblop),
+                                       rinfo->sr_algo[SR_ALGORITHM_SPF].label,
+                                       MPLS_LABEL_IMPLICIT_NULL);
                        } else {
                                strlcpy(buf_sid, "-", sizeof(buf_sid));
                                strlcpy(buf_lblop, "-", sizeof(buf_lblop));