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_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 =

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.
* 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,

View File

@ -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);
}
}

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_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,

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)
{
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,