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 <hiroki.shirokura@linecorp.com>
Signed-off-by: Louis Scalbert <louis.scalbert@6wind.com>
This commit is contained in:
Hiroki Shirokura 2022-01-21 16:02:54 +00:00 committed by Louis Scalbert
parent 860b75b40e
commit 80ef2e89ee
5 changed files with 61 additions and 27 deletions

View File

@ -36,6 +36,7 @@
#include "isis_spf_private.h" #include "isis_spf_private.h"
#include "isis_route.h" #include "isis_route.h"
#include "isis_zebra.h" #include "isis_zebra.h"
#include "isis_flex_algo.h"
DEFINE_MTYPE_STATIC(ISISD, ISIS_NEXTHOP, "ISIS nexthop"); DEFINE_MTYPE_STATIC(ISISD, ISIS_NEXTHOP, "ISIS nexthop");
DEFINE_MTYPE_STATIC(ISISD, ISIS_ROUTE_INFO, "ISIS route info"); 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)) if (CHECK_FLAG(rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE))
continue; 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 * directly for
* validating => no problems with deleting routes. */ * validating => no problems with deleting routes. */
if (!tables) { if (!tables) {
@ -733,13 +734,12 @@ static void _isis_route_verify_table(struct isis_area *area,
continue; continue;
} }
/* If area is L1L2, we work with merge table and /* If we work on a merged table,
* therefore must * therefore we must
* delete node from level tables as well before deleting * delete node from each table as well before deleting
* route info. */ * route info. */
for (int level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) { for (int i = 0; tables[i]; i++) {
drnode = srcdest_rnode_lookup(tables[level - 1], drnode = srcdest_rnode_lookup(tables[i], dst_p, src_p);
dst_p, src_p);
if (!drnode) if (!drnode)
continue; 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, 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 /* 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,
struct route_table *level1_table_backup, struct route_table *level1_table_backup,
struct route_table *level2_table, 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, 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_table *merge;
struct route_node *rnode, *mrnode; struct route_node *rnode, *mrnode;
merge = srcdest_table_init(); merge = srcdest_table_init();
for (int level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) { for (int i = 0; tables[i]; i++) {
uint8_t algorithm = uint8_t algorithm = isis_route_table_algorithm(tables[i]);
isis_route_table_algorithm(tables[level - 1]); for (rnode = route_top(tables[i]); rnode;
for (rnode = route_top(tables[level - 1]); rnode;
rnode = srcdest_route_next(rnode)) { rnode = srcdest_route_next(rnode)) {
struct isis_route_info *rinfo = rnode->info; struct isis_route_info *rinfo = rnode->info;
struct route_node *rnode_bck; struct route_node *rnode_bck;
@ -805,8 +838,8 @@ void isis_route_verify_merge(struct isis_area *area,
(const struct prefix **)&src_p); (const struct prefix **)&src_p);
/* Link primary route to backup route. */ /* Link primary route to backup route. */
rnode_bck = srcdest_rnode_lookup( rnode_bck = srcdest_rnode_lookup(tables_backup[i],
tables_backup[level - 1], prefix, src_p); prefix, src_p);
if (rnode_bck) { if (rnode_bck) {
rinfo->backup = rnode_bck->info; rinfo->backup = rnode_bck->info;
rinfo->sr_algo[algorithm].nexthops_backup = rinfo->sr_algo[algorithm].nexthops_backup =

View File

@ -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. /* Walk the given table and install new routes to zebra and remove old ones.
* route status is tracked using ISIS_ROUTE_FLAG_ACTIVE */ * route status is tracked using ISIS_ROUTE_FLAG_ACTIVE */
void isis_route_verify_table(struct isis_area *area, struct route_table *table, 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 */ /* Same as isis_route_verify_table, but merge L1 and L2 routes before */
void isis_route_verify_merge(struct isis_area *area, void isis_route_verify_merge(struct isis_area *area,
struct route_table *level1_table, struct route_table *level1_table,
struct route_table *level1_table_backup, struct route_table *level1_table_backup,
struct route_table *level2_table, 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. */ /* Unset ISIS_ROUTE_FLAG_ACTIVE on all routes. Used before running spf. */
void isis_route_invalidate_table(struct isis_area *area, void isis_route_invalidate_table(struct isis_area *area,

View File

@ -1933,19 +1933,20 @@ static void isis_run_spf_with_protection(struct isis_area *area,
isis_spf_run_lfa(area, spftree); 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) { if (area->is_type == IS_LEVEL_1) {
isis_route_verify_table(area, trees[0]->route_table, 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) { } else if (area->is_type == IS_LEVEL_2) {
isis_route_verify_table(area, trees[1]->route_table, isis_route_verify_table(area, trees[1]->route_table,
trees[1]->route_table_backup); trees[1]->route_table_backup, tree);
} else { } else {
isis_route_verify_merge(area, trees[0]->route_table, isis_route_verify_merge(area, trees[0]->route_table,
trees[0]->route_table_backup, trees[0]->route_table_backup,
trees[1]->route_table, trees[1]->route_table,
trees[1]->route_table_backup); trees[1]->route_table_backup, tree);
} }
} }

View File

@ -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_vertex *isis_spf_prefix_sid_lookup(struct isis_spftree *spftree,
struct isis_prefix_sid *psid); struct isis_prefix_sid *psid);
void isis_spf_invalidate_routes(struct isis_spftree *tree); void isis_spf_invalidate_routes(struct isis_spftree *tree);
void isis_spf_verify_routes(struct isis_area *area, void isis_spf_verify_routes(struct isis_area *area, struct isis_spftree **trees,
struct isis_spftree **trees); int tree);
void isis_spf_switchover_routes(struct isis_area *area, void isis_spf_switchover_routes(struct isis_area *area,
struct isis_spftree **trees, int family, struct isis_spftree **trees, int family,
union g_addr *nexthop_ip, ifindex_t ifindex, union g_addr *nexthop_ip, ifindex_t ifindex,

View File

@ -3097,7 +3097,7 @@ void isis_area_invalidate_routes(struct isis_area *area, int levels)
void isis_area_verify_routes(struct isis_area *area) void isis_area_verify_routes(struct isis_area *area)
{ {
for (int tree = SPFTREE_IPV4; tree < SPFTREE_COUNT; tree++) 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, void isis_area_switchover_routes(struct isis_area *area, int family,