From 80ef2e89eeba4924cdd712535cf87e2a7ef4a49f Mon Sep 17 00:00:00 2001 From: Hiroki Shirokura Date: Fri, 21 Jan 2022 16:02:54 +0000 Subject: [PATCH] isisd: merge algorithm tables Create a temporary "merge" route table that contains the routing information from all algorithms and install the merge route table into the FIB. Signed-off-by: Hiroki Shirokura Signed-off-by: Louis Scalbert --- isisd/isis_route.c | 69 ++++++++++++++++++++++++++++++++++------------ isisd/isis_route.h | 4 +-- isisd/isis_spf.c | 9 +++--- isisd/isis_spf.h | 4 +-- isisd/isisd.c | 2 +- 5 files changed, 61 insertions(+), 27 deletions(-) diff --git a/isisd/isis_route.c b/isisd/isis_route.c index 3191dfa4ff..3983c704ce 100644 --- a/isisd/isis_route.c +++ b/isisd/isis_route.c @@ -36,6 +36,7 @@ #include "isis_spf_private.h" #include "isis_route.h" #include "isis_zebra.h" +#include "isis_flex_algo.h" DEFINE_MTYPE_STATIC(ISISD, ISIS_NEXTHOP, "ISIS nexthop"); DEFINE_MTYPE_STATIC(ISISD, ISIS_ROUTE_INFO, "ISIS route info"); @@ -725,7 +726,7 @@ static void _isis_route_verify_table(struct isis_area *area, if (CHECK_FLAG(rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE)) continue; - /* Area is either L1 or L2 => we use level route tables + /* In case the verify is not for a merge, we use a single table * directly for * validating => no problems with deleting routes. */ if (!tables) { @@ -733,13 +734,12 @@ static void _isis_route_verify_table(struct isis_area *area, continue; } - /* If area is L1L2, we work with merge table and - * therefore must - * delete node from level tables as well before deleting + /* If we work on a merged table, + * therefore we must + * delete node from each table as well before deleting * route info. */ - for (int level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) { - drnode = srcdest_rnode_lookup(tables[level - 1], - dst_p, src_p); + for (int i = 0; tables[i]; i++) { + drnode = srcdest_rnode_lookup(tables[i], dst_p, src_p); if (!drnode) continue; @@ -756,10 +756,36 @@ static void _isis_route_verify_table(struct isis_area *area, } } +static void _isis_route_verify_merge(struct isis_area *area, + struct route_table **tables, + struct route_table **tables_backup, + int tree); + void isis_route_verify_table(struct isis_area *area, struct route_table *table, - struct route_table *table_backup) + struct route_table *table_backup, int tree) { - _isis_route_verify_table(area, table, table_backup, NULL); + struct route_table *tables[SR_ALGORITHM_COUNT] = {table}; + struct route_table *tables_backup[SR_ALGORITHM_COUNT] = {table_backup}; +#ifndef FABRICD + int tables_next = 1; + int level = area->is_type == IS_LEVEL_1 ? ISIS_LEVEL1 : ISIS_LEVEL2; + struct listnode *node; + struct flex_algo *fa; + struct isis_flex_algo_data *data; + + for (ALL_LIST_ELEMENTS_RO(area->flex_algos->flex_algos, node, fa)) { + data = fa->data; + tables[tables_next] = + data->spftree[tree][level - 1]->route_table; + tables_backup[tables_next] = + data->spftree[tree][level - 1]->route_table_backup; + _isis_route_verify_table(area, tables[tables_next], + tables_backup[tables_next], NULL); + tables_next++; + } +#endif /* ifndef FABRICD */ + + _isis_route_verify_merge(area, tables, tables_backup, tree); } /* Function to validate route tables for L1L2 areas. In this case we can't use @@ -776,20 +802,27 @@ void isis_route_verify_merge(struct isis_area *area, struct route_table *level1_table, struct route_table *level1_table_backup, struct route_table *level2_table, - struct route_table *level2_table_backup) + struct route_table *level2_table_backup, int tree) { - struct route_table *tables[] = {level1_table, level2_table}; + struct route_table *tables[] = {level1_table, level2_table, NULL}; struct route_table *tables_backup[] = {level1_table_backup, - level2_table_backup}; + level2_table_backup, NULL}; + _isis_route_verify_merge(area, tables, tables_backup, tree); +} + +static void _isis_route_verify_merge(struct isis_area *area, + struct route_table **tables, + struct route_table **tables_backup, + int tree) +{ struct route_table *merge; struct route_node *rnode, *mrnode; 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; + for (int i = 0; tables[i]; i++) { + uint8_t algorithm = isis_route_table_algorithm(tables[i]); + for (rnode = route_top(tables[i]); rnode; rnode = srcdest_route_next(rnode)) { struct isis_route_info *rinfo = rnode->info; struct route_node *rnode_bck; @@ -805,8 +838,8 @@ void isis_route_verify_merge(struct isis_area *area, (const struct prefix **)&src_p); /* Link primary route to backup route. */ - rnode_bck = srcdest_rnode_lookup( - tables_backup[level - 1], prefix, src_p); + rnode_bck = srcdest_rnode_lookup(tables_backup[i], + prefix, src_p); if (rnode_bck) { rinfo->backup = rnode_bck->info; rinfo->sr_algo[algorithm].nexthops_backup = diff --git a/isisd/isis_route.h b/isisd/isis_route.h index 79b604b779..4d49a5ae9c 100644 --- a/isisd/isis_route.h +++ b/isisd/isis_route.h @@ -60,14 +60,14 @@ void isis_route_delete(struct isis_area *area, struct route_node *rode, /* 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, - struct route_table *table_backup); + struct route_table *table_backup, int tree); /* 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 *level1_table_backup, struct route_table *level2_table, - struct route_table *level2_table_backup); + struct route_table *level2_table_backup, int tree); /* Unset ISIS_ROUTE_FLAG_ACTIVE on all routes. Used before running spf. */ void isis_route_invalidate_table(struct isis_area *area, diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index cc8c5168e4..faaf8d94d3 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -1933,19 +1933,20 @@ static void isis_run_spf_with_protection(struct isis_area *area, isis_spf_run_lfa(area, spftree); } -void isis_spf_verify_routes(struct isis_area *area, struct isis_spftree **trees) +void isis_spf_verify_routes(struct isis_area *area, struct isis_spftree **trees, + int tree) { if (area->is_type == IS_LEVEL_1) { isis_route_verify_table(area, trees[0]->route_table, - trees[0]->route_table_backup); + trees[0]->route_table_backup, tree); } else if (area->is_type == IS_LEVEL_2) { isis_route_verify_table(area, trees[1]->route_table, - trees[1]->route_table_backup); + trees[1]->route_table_backup, tree); } else { isis_route_verify_merge(area, trees[0]->route_table, trees[0]->route_table_backup, trees[1]->route_table, - trees[1]->route_table_backup); + trees[1]->route_table_backup, tree); } } diff --git a/isisd/isis_spf.h b/isisd/isis_spf.h index bf79a084bb..9af4d1bdcf 100644 --- a/isisd/isis_spf.h +++ b/isisd/isis_spf.h @@ -44,8 +44,8 @@ isis_spftree_new(struct isis_area *area, struct lspdb_head *lspdb, struct isis_vertex *isis_spf_prefix_sid_lookup(struct isis_spftree *spftree, struct isis_prefix_sid *psid); void isis_spf_invalidate_routes(struct isis_spftree *tree); -void isis_spf_verify_routes(struct isis_area *area, - struct isis_spftree **trees); +void isis_spf_verify_routes(struct isis_area *area, struct isis_spftree **trees, + int tree); void isis_spf_switchover_routes(struct isis_area *area, struct isis_spftree **trees, int family, union g_addr *nexthop_ip, ifindex_t ifindex, diff --git a/isisd/isisd.c b/isisd/isisd.c index 195f9f16f1..e4689b0323 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -3097,7 +3097,7 @@ void isis_area_invalidate_routes(struct isis_area *area, int levels) void isis_area_verify_routes(struct isis_area *area) { for (int tree = SPFTREE_IPV4; tree < SPFTREE_COUNT; tree++) - isis_spf_verify_routes(area, area->spftree[tree]); + isis_spf_verify_routes(area, area->spftree[tree], tree); } void isis_area_switchover_routes(struct isis_area *area, int family,