diff options
author | Christian Franke <chris@opensourcerouting.org> | 2018-07-24 17:40:24 +0200 |
---|---|---|
committer | Christian Franke <chris@opensourcerouting.org> | 2018-08-03 13:25:39 +0200 |
commit | 3dace42de964a00429681544167679083b52807a (patch) | |
tree | 94d7cc43a4ac55777f739efd67c189033f8a730f /isisd | |
parent | isisd: learn and advertise IPv6 dst-src routes (diff) | |
download | frr-3dace42de964a00429681544167679083b52807a.tar.xz frr-3dace42de964a00429681544167679083b52807a.zip |
isisd: move route_table into spftree
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>
Diffstat (limited to 'isisd')
-rw-r--r-- | isisd/isis_route.c | 147 | ||||
-rw-r--r-- | isisd/isis_route.h | 16 | ||||
-rw-r--r-- | isisd/isis_spf.c | 45 | ||||
-rw-r--r-- | isisd/isis_spf.h | 3 | ||||
-rw-r--r-- | isisd/isisd.c | 64 | ||||
-rw-r--r-- | isisd/isisd.h | 5 |
6 files changed, 111 insertions, 169 deletions
diff --git a/isisd/isis_route.c b/isisd/isis_route.c index c98e16e2b..b6fb90b6d 100644 --- a/isisd/isis_route.c +++ b/isisd/isis_route.c @@ -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]); -} diff --git a/isisd/isis_route.h b/isisd/isis_route.h index 82f37c29f..ae4b855cc 100644 --- a/isisd/isis_route.h +++ b/isisd/isis_route.h @@ -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 */ diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index 556f2890c..13be8bac5 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -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; } diff --git a/isisd/isis_spf.h b/isisd/isis_spf.h index 84e07861d..9a73ca878 100644 --- a/isisd/isis_spf.h +++ b/isisd/isis_spf.h @@ -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); diff --git a/isisd/isisd.c b/isisd/isisd.c index cecaa0693..0094b30c2 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -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: diff --git a/isisd/isisd.h b/isisd/isisd.h index d1ad9f3b8..c1bf6bc97 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -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); |