]> git.proxmox.com Git - mirror_frr.git/commitdiff
isisd: move route_table into spftree
authorChristian Franke <chris@opensourcerouting.org>
Tue, 24 Jul 2018 15:40:24 +0000 (17:40 +0200)
committerChristian Franke <chris@opensourcerouting.org>
Fri, 3 Aug 2018 11:25:39 +0000 (13:25 +0200)
As isisd's route_tables are directly related to spf trees, move
the route tables into the spftree instead of maintaining them
alongside of the spftrees.

Signed-off-by: Christian Franke <chris@opensourcerouting.org>
isisd/isis_route.c
isisd/isis_route.h
isisd/isis_spf.c
isisd/isis_spf.h
isisd/isisd.c
isisd/isisd.h

index c98e16e2bdb40af92b14128d487cce7dfb42741d..b6fb90b6dd57bd8560b48b09ddda972f23e9e37e 100644 (file)
@@ -320,7 +320,8 @@ static int isis_route_info_same(struct isis_route_info *new,
 struct isis_route_info *isis_route_create(struct prefix *prefix, uint32_t cost,
                                          uint32_t depth,
                                          struct list *adjacencies,
-                                         struct isis_area *area, int level)
+                                         struct isis_area *area,
+                                         struct route_table *table)
 {
        struct route_node *route_node;
        struct isis_route_info *rinfo_new, *rinfo_old, *route_info = NULL;
@@ -331,18 +332,11 @@ struct isis_route_info *isis_route_create(struct prefix *prefix, uint32_t cost,
        /* for debugs */
        prefix2str(prefix, buff, sizeof(buff));
 
-       rinfo_new = isis_route_info_new(prefix, cost, depth, adjacencies);
-
-       if (family == AF_INET)
-               route_node =
-                       route_node_get(area->route_table[level - 1], prefix);
-       else if (family == AF_INET6)
-               route_node =
-                       route_node_get(area->route_table6[level - 1], prefix);
-       else {
-               isis_route_info_delete(rinfo_new);
+       if (!table)
                return NULL;
-       }
+
+       rinfo_new = isis_route_info_new(prefix, cost, depth, adjacencies);
+       route_node = route_node_get(table, prefix);
 
        rinfo_old = route_node->info;
        if (!rinfo_old) {
@@ -411,9 +405,9 @@ static void isis_route_delete(struct prefix *prefix, struct route_table *table)
        return;
 }
 
-/* Validating routes in particular table. */
-static void isis_route_validate_table(struct isis_area *area,
-                                     struct route_table *table)
+static void _isis_route_verify_table(struct isis_area *area,
+                                    struct route_table *table,
+                                    struct route_table **tables)
 {
        struct route_node *rnode, *drnode;
        struct isis_route_info *rinfo;
@@ -448,36 +442,17 @@ static void isis_route_validate_table(struct isis_area *area,
                        /* Area is either L1 or L2 => we use level route tables
                         * directly for
                         * validating => no problems with deleting routes. */
-                       if (area->is_type != IS_LEVEL_1_AND_2) {
+                       if (!tables) {
                                isis_route_delete(&rnode->p, table);
                                continue;
                        }
+
                        /* If area is L1L2, we work with merge table and
                         * therefore must
                         * delete node from level tables as well before deleting
-                        * route info.
-                        * FIXME: Is it performance problem? There has to be the
-                        * better way.
-                        * Like not to deal with it here at all (see the next
-                        * comment)? */
-                       if (rnode->p.family == AF_INET) {
-                               drnode = route_node_get(area->route_table[0],
-                                                       &rnode->p);
-                               if (drnode->info == rnode->info)
-                                       drnode->info = NULL;
-                               drnode = route_node_get(area->route_table[1],
-                                                       &rnode->p);
-                               if (drnode->info == rnode->info)
-                                       drnode->info = NULL;
-                       }
-
-                       if (rnode->p.family == AF_INET6) {
-                               drnode = route_node_get(area->route_table6[0],
-                                                       &rnode->p);
-                               if (drnode->info == rnode->info)
-                                       drnode->info = NULL;
-                               drnode = route_node_get(area->route_table6[1],
-                                                       &rnode->p);
+                        * route info. */
+                       for (int level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) {
+                               drnode = route_node_get(tables[level - 1], &rnode->p);
                                if (drnode->info == rnode->info)
                                        drnode->info = NULL;
                        }
@@ -487,6 +462,11 @@ static void isis_route_validate_table(struct isis_area *area,
        }
 }
 
+void isis_route_verify_table(struct isis_area *area, struct route_table *table)
+{
+       return _isis_route_verify_table(area, table, NULL);
+}
+
 /* Function to validate route tables for L1L2 areas. In this case we can't use
  * level route tables directly, we have to merge them at first. L1 routes are
  * preferred over the L2 ones.
@@ -497,81 +477,34 @@ static void isis_route_validate_table(struct isis_area *area,
  *
  * FIXME: Is it right place to do it at all? Maybe we should push both levels
  * to the RIB with different zebra route types and let RIB handle this? */
-static void isis_route_validate_merge(struct isis_area *area, int family)
+void isis_route_verify_merge(struct isis_area *area,
+                            struct route_table *level1_table,
+                            struct route_table *level2_table)
 {
-       struct route_table *table = NULL;
+       struct route_table *tables[] = { level1_table, level2_table };
        struct route_table *merge;
        struct route_node *rnode, *mrnode;
 
        merge = route_table_init();
 
-       if (family == AF_INET)
-               table = area->route_table[0];
-       else if (family == AF_INET6)
-               table = area->route_table6[0];
-       else {
-               zlog_warn("ISIS-Rte (%s) %s called for unknown family %d",
-                         area->area_tag, __func__, family);
-               route_table_finish(merge);
-               return;
-       }
-
-       for (rnode = route_top(table); rnode; rnode = route_next(rnode)) {
-               if (rnode->info == NULL)
-                       continue;
-               mrnode = route_node_get(merge, &rnode->p);
-               mrnode->info = rnode->info;
-       }
-
-       if (family == AF_INET)
-               table = area->route_table[1];
-       else if (family == AF_INET6)
-               table = area->route_table6[1];
-
-       for (rnode = route_top(table); rnode; rnode = route_next(rnode)) {
-               if (rnode->info == NULL)
-                       continue;
-               mrnode = route_node_get(merge, &rnode->p);
-               if (mrnode->info != NULL)
-                       continue;
-               mrnode->info = rnode->info;
+       for (int level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) {
+               for (rnode = route_top(tables[level - 1]); rnode;
+                    rnode = route_next(rnode)) {
+                       if (rnode->info == NULL)
+                               continue;
+                       mrnode = route_node_get(merge, &rnode->p);
+                       if (mrnode->info != NULL) {
+                               route_unlock_node(mrnode);
+                               continue;
+                       }
+                       mrnode->info = rnode->info;
+               }
        }
 
-       isis_route_validate_table(area, merge);
+       _isis_route_verify_table(area, merge, tables);
        route_table_finish(merge);
 }
 
-/* Walk through route tables and propagate necessary changes into RIB. In case
- * of L1L2 area, level tables have to be merged at first. */
-void isis_route_validate(struct isis_area *area)
-{
-       struct listnode *node;
-       struct isis_circuit *circuit;
-
-       if (area->is_type == IS_LEVEL_1)
-               isis_route_validate_table(area, area->route_table[0]);
-       else if (area->is_type == IS_LEVEL_2)
-               isis_route_validate_table(area, area->route_table[1]);
-       else
-               isis_route_validate_merge(area, AF_INET);
-
-       if (area->is_type == IS_LEVEL_1)
-               isis_route_validate_table(area, area->route_table6[0]);
-       else if (area->is_type == IS_LEVEL_2)
-               isis_route_validate_table(area, area->route_table6[1]);
-       else
-               isis_route_validate_merge(area, AF_INET6);
-
-       if (!area->circuit_list) {
-               return;
-       }
-       /* walk all circuits and reset any spf specific flags */
-       for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit))
-               UNSET_FLAG(circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF);
-
-       return;
-}
-
 void isis_route_invalidate_table(struct isis_area *area,
                                 struct route_table *table)
 {
@@ -585,11 +518,3 @@ void isis_route_invalidate_table(struct isis_area *area,
                UNSET_FLAG(rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE);
        }
 }
-
-void isis_route_invalidate(struct isis_area *area)
-{
-       if (area->is_type & IS_LEVEL_1)
-               isis_route_invalidate_table(area, area->route_table[0]);
-       if (area->is_type & IS_LEVEL_2)
-               isis_route_invalidate_table(area, area->route_table[1]);
-}
index 82f37c29f23b41fe96f89db68da7d847475143cd..ae4b855cc731bad4f20d8d73e1ddafe477f7c327 100644 (file)
@@ -53,11 +53,21 @@ struct isis_route_info {
 struct isis_route_info *isis_route_create(struct prefix *prefix, uint32_t cost,
                                          uint32_t depth,
                                          struct list *adjacencies,
-                                         struct isis_area *area, int level);
+                                         struct isis_area *area,
+                                         struct route_table *table);
 
-void isis_route_validate(struct isis_area *area);
+/* Walk the given table and install new routes to zebra and remove old ones.
+ * route status is tracked using ISIS_ROUTE_FLAG_ACTIVE */
+void isis_route_verify_table(struct isis_area *area,
+                            struct route_table *table);
+
+/* Same as isis_route_verify_table, but merge L1 and L2 routes before */
+void isis_route_verify_merge(struct isis_area *area,
+                            struct route_table *level1_table,
+                            struct route_table *level2_table);
+
+/* Unset ISIS_ROUTE_FLAG_ACTIVE on all routes. Used before running spf. */
 void isis_route_invalidate_table(struct isis_area *area,
                                 struct route_table *table);
-void isis_route_invalidate(struct isis_area *area);
 
 #endif /* _ZEBRA_ISIS_ROUTE_H */
index 556f2890cfbc22caee61a27ed0783f72bb3e799c..13be8bac5306da3888a5ced52e138c145df1a6fb 100644 (file)
@@ -275,6 +275,7 @@ static void isis_vertex_queue_delete(struct isis_vertex_queue *queue,
 struct isis_spftree {
        struct isis_vertex_queue paths; /* the SPT */
        struct isis_vertex_queue tents; /* TENT */
+       struct route_table *route_table;
        struct isis_area *area;    /* back pointer to area */
        unsigned int runcount;     /* number of runs since uptime */
        time_t last_run_timestamp; /* last run timestamp as wall time for display */
@@ -472,6 +473,7 @@ struct isis_spftree *isis_spftree_new(struct isis_area *area)
 
        isis_vertex_queue_init(&tree->tents, "IS-IS SPF tents", true);
        isis_vertex_queue_init(&tree->paths, "IS-IS SPF paths", false);
+       tree->route_table = route_table_init();
        tree->area = area;
        tree->last_run_timestamp = 0;
        tree->last_run_monotime = 0;
@@ -484,8 +486,10 @@ void isis_spftree_del(struct isis_spftree *spftree)
 {
        isis_vertex_queue_free(&spftree->tents);
        isis_vertex_queue_free(&spftree->paths);
-       XFREE(MTYPE_ISIS_SPFTREE, spftree);
+       route_table_finish(spftree->route_table);
+       spftree->route_table = NULL;
 
+       XFREE(MTYPE_ISIS_SPFTREE, spftree);
        return;
 }
 
@@ -1228,7 +1232,7 @@ static void add_to_paths(struct isis_spftree *spftree,
                        isis_route_create((struct prefix *)&vertex->N.prefix,
                                          vertex->d_N, vertex->depth,
                                          vertex->Adj_N, spftree->area,
-                                         spftree->level);
+                                         spftree->route_table);
                else if (isis->debugs & DEBUG_SPF_EVENTS)
                        zlog_debug(
                                "ISIS-Spf: no adjacencies do not install route for "
@@ -1261,7 +1265,6 @@ static int isis_run_spf(struct isis_area *area, int level, int family,
        struct isis_spftree *spftree = NULL;
        uint8_t lsp_id[ISIS_SYS_ID_LEN + 2];
        struct isis_lsp *lsp;
-       struct route_table *table = NULL;
        struct timeval time_now;
        unsigned long long start_time, end_time;
        uint16_t mtid;
@@ -1277,14 +1280,6 @@ static int isis_run_spf(struct isis_area *area, int level, int family,
        assert(spftree);
        assert(sysid);
 
-       /* Make all routes in current route table inactive. */
-       if (family == AF_INET)
-               table = area->route_table[level - 1];
-       else if (family == AF_INET6)
-               table = area->route_table6[level - 1];
-
-       isis_route_invalidate_table(area, table);
-
        /* We only support ipv4-unicast and ipv6-unicast as topologies for now
         */
        if (family == AF_INET6)
@@ -1342,7 +1337,6 @@ static int isis_run_spf(struct isis_area *area, int level, int family,
        }
 
 out:
-       isis_route_validate(area);
        spftree->runcount++;
        spftree->last_run_timestamp = time(NULL);
        spftree->last_run_monotime = monotime(&time_now);
@@ -1353,6 +1347,23 @@ out:
        return retval;
 }
 
+void isis_spf_verify_routes(struct isis_area *area, struct isis_spftree **trees)
+{
+       if (area->is_type == IS_LEVEL_1) {
+               isis_route_verify_table(area, trees[0]->route_table);
+       } else if (area->is_type == IS_LEVEL_2) {
+               isis_route_verify_table(area, trees[1]->route_table);
+       } else {
+               isis_route_verify_merge(area, trees[0]->route_table,
+                                       trees[1]->route_table);
+       }
+}
+
+void isis_spf_invalidate_routes(struct isis_spftree *tree)
+{
+       isis_route_invalidate_table(tree->area, tree->route_table);
+}
+
 static int isis_run_spf_cb(struct thread *thread)
 {
        struct isis_spf_run *run = THREAD_ARG(thread);
@@ -1370,6 +1381,8 @@ static int isis_run_spf_cb(struct thread *thread)
                return ISIS_WARNING;
        }
 
+       isis_area_invalidate_routes(area, level);
+
        if (isis->debugs & DEBUG_SPF_EVENTS)
                zlog_debug("ISIS-Spf (%s) L%d SPF needed, periodic SPF",
                           area->area_tag, level);
@@ -1381,6 +1394,14 @@ static int isis_run_spf_cb(struct thread *thread)
                retval = isis_run_spf(area, level, AF_INET6, isis->sysid,
                                      &thread->real);
 
+       isis_area_verify_routes(area);
+
+       /* walk all circuits and reset any spf specific flags */
+       struct listnode *node;
+       struct isis_circuit *circuit;
+       for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit))
+               UNSET_FLAG(circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF);
+
        return retval;
 }
 
index 84e07861d2c351252316efde190b28982f5a1f61..9a73ca8783dd3b6d766eb2b73b21fe45692773b0 100644 (file)
@@ -27,6 +27,9 @@
 struct isis_spftree;
 
 struct isis_spftree *isis_spftree_new(struct isis_area *area);
+void isis_spf_invalidate_routes(struct isis_spftree *tree);
+void isis_spf_verify_routes(struct isis_area *area,
+                           struct isis_spftree **trees);
 void isis_spftree_del(struct isis_spftree *spftree);
 void spftree_area_init(struct isis_area *area);
 void spftree_area_del(struct isis_area *area);
index cecaa0693dba709ee8212a699230edc0ffdbbf1c..0094b30c28cae5bad8ec19be47b8899fc6312302 100644 (file)
@@ -118,13 +118,9 @@ struct isis_area *isis_area_create(const char *area_tag)
         */
        if (area->is_type & IS_LEVEL_1) {
                area->lspdb[0] = lsp_db_init();
-               area->route_table[0] = route_table_init();
-               area->route_table6[0] = route_table_init();
        }
        if (area->is_type & IS_LEVEL_2) {
                area->lspdb[1] = lsp_db_init();
-               area->route_table[1] = route_table_init();
-               area->route_table6[1] = route_table_init();
        }
 
        spftree_area_init(area);
@@ -232,6 +228,10 @@ int isis_area_destroy(struct vty *vty, const char *area_tag)
                area->lspdb[1] = NULL;
        }
 
+       /* invalidate and verify to delete all routes from zebra */
+       isis_area_invalidate_routes(area, ISIS_LEVEL1 & ISIS_LEVEL2);
+       isis_area_verify_routes(area);
+
        spftree_area_del(area);
 
        THREAD_TIMER_OFF(area->spf_timer[0]);
@@ -240,27 +240,6 @@ int isis_area_destroy(struct vty *vty, const char *area_tag)
        spf_backoff_free(area->spf_delay_ietf[0]);
        spf_backoff_free(area->spf_delay_ietf[1]);
 
-       /* invalidate and validate would delete all routes from zebra */
-       isis_route_invalidate(area);
-       isis_route_validate(area);
-
-       if (area->route_table[0]) {
-               route_table_finish(area->route_table[0]);
-               area->route_table[0] = NULL;
-       }
-       if (area->route_table[1]) {
-               route_table_finish(area->route_table[1]);
-               area->route_table[1] = NULL;
-       }
-       if (area->route_table6[0]) {
-               route_table_finish(area->route_table6[0]);
-               area->route_table6[0] = NULL;
-       }
-       if (area->route_table6[1]) {
-               route_table_finish(area->route_table6[1]);
-               area->route_table6[1] = NULL;
-       }
-
        isis_redist_area_finish(area);
 
        for (ALL_LIST_ELEMENTS(area->area_addrs, node, nnode, addr)) {
@@ -1680,8 +1659,27 @@ int isis_area_passwd_hmac_md5_set(struct isis_area *area, int level,
                                    passwd, snp_auth);
 }
 
+void isis_area_invalidate_routes(struct isis_area *area, int levels)
+{
+       for (int level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) {
+               if (!(level & levels))
+                       continue;
+               isis_spf_invalidate_routes(area->spftree[level - 1]);
+               isis_spf_invalidate_routes(area->spftree6[level - 1]);
+       }
+}
+
+void isis_area_verify_routes(struct isis_area *area)
+{
+       isis_spf_verify_routes(area, area->spftree);
+       isis_spf_verify_routes(area, area->spftree6);
+}
+
 static void area_resign_level(struct isis_area *area, int level)
 {
+       isis_area_invalidate_routes(area, level);
+       isis_area_verify_routes(area);
+
        if (area->lspdb[level - 1]) {
                lsp_db_destroy(area->lspdb[level - 1]);
                area->lspdb[level - 1] = NULL;
@@ -1695,14 +1693,6 @@ static void area_resign_level(struct isis_area *area, int level)
                area->spftree6[level - 1] = NULL;
        }
        THREAD_TIMER_OFF(area->spf_timer[level - 1]);
-       if (area->route_table[level - 1]) {
-               route_table_finish(area->route_table[level - 1]);
-               area->route_table[level - 1] = NULL;
-       }
-       if (area->route_table6[level - 1]) {
-               route_table_finish(area->route_table6[level - 1]);
-               area->route_table6[level - 1] = NULL;
-       }
 
        sched_debug(
                "ISIS (%s): Resigned from L%d - canceling LSP regeneration timer.",
@@ -1731,10 +1721,6 @@ void isis_area_is_type_set(struct isis_area *area, int is_type)
 
                if (area->lspdb[1] == NULL)
                        area->lspdb[1] = lsp_db_init();
-               if (area->route_table[1] == NULL)
-                       area->route_table[1] = route_table_init();
-               if (area->route_table6[1] == NULL)
-                       area->route_table6[1] = route_table_init();
                break;
 
        case IS_LEVEL_1_AND_2:
@@ -1750,10 +1736,6 @@ void isis_area_is_type_set(struct isis_area *area, int is_type)
 
                if (area->lspdb[0] == NULL)
                        area->lspdb[0] = lsp_db_init();
-               if (area->route_table[0] == NULL)
-                       area->route_table[0] = route_table_init();
-               if (area->route_table6[0] == NULL)
-                       area->route_table6[0] = route_table_init();
                break;
 
        default:
index d1ad9f3b8e74ba91866d7893b2bbb9842a3a9a76..c1bf6bc9764069aaa6296f20fea97788c3a74e4f 100644 (file)
@@ -67,9 +67,7 @@ struct isis_area {
        struct isis *isis;                             /* back pointer */
        dict_t *lspdb[ISIS_LEVELS];                    /* link-state dbs */
        struct isis_spftree *spftree[ISIS_LEVELS];     /* The v4 SPTs */
-       struct route_table *route_table[ISIS_LEVELS];  /* IPv4 routes */
        struct isis_spftree *spftree6[ISIS_LEVELS];    /* The v6 SPTs */
-       struct route_table *route_table6[ISIS_LEVELS]; /* IPv6 routes */
 #define DEFAULT_LSP_MTU 1497
        unsigned int lsp_mtu;      /* Size of LSPs to generate */
        struct list *circuit_list; /* IS-IS circuits */
@@ -144,6 +142,9 @@ struct isis_area *isis_area_lookup(const char *);
 int isis_area_get(struct vty *vty, const char *area_tag);
 void print_debug(struct vty *, int, int);
 
+void isis_area_invalidate_routes(struct isis_area *area, int levels);
+void isis_area_verify_routes(struct isis_area *area);
+
 void isis_area_overload_bit_set(struct isis_area *area, bool overload_bit);
 void isis_area_attached_bit_set(struct isis_area *area, bool attached_bit);
 void isis_area_dynhostname_set(struct isis_area *area, bool dynhostname);