Skip to content

Commit

Permalink
isisd: merge algorithm tables
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
slankdev authored and louis-6wind committed Sep 12, 2022
1 parent ff535a7 commit 9222664
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 27 deletions.
67 changes: 49 additions & 18 deletions isisd/isis_route.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,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");
Expand Down Expand Up @@ -720,21 +721,20 @@ 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) {
isis_route_delete(area, rnode, table);
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;

Expand All @@ -751,10 +751,34 @@ 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);
int tables_next = 1;
int level = area->is_type == IS_LEVEL_1 ? ISIS_LEVEL1 : ISIS_LEVEL2;
struct listnode *node;
struct flex_algo *fa;
struct route_table *tables[SR_ALGORITHM_COUNT] = {table};
struct route_table *tables_backup[SR_ALGORITHM_COUNT] = {table_backup};
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++;
}

_isis_route_verify_merge(area, tables, tables_backup, tree);
}

/* Function to validate route tables for L1L2 areas. In this case we can't use
Expand All @@ -771,20 +795,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;
Expand All @@ -800,8 +831,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 =
Expand Down
4 changes: 2 additions & 2 deletions isisd/isis_route.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,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,
Expand Down
9 changes: 5 additions & 4 deletions isisd/isis_spf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1884,19 +1884,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);
}
}

Expand Down
4 changes: 2 additions & 2 deletions isisd/isis_spf.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,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_spftree_del(struct isis_spftree *spftree);
void spftree_area_init(struct isis_area *area);
void spftree_area_del(struct isis_area *area);
Expand Down
2 changes: 1 addition & 1 deletion isisd/isisd.c
Original file line number Diff line number Diff line change
Expand Up @@ -3100,7 +3100,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);
}

static void area_resign_level(struct isis_area *area, int level)
Expand Down

0 comments on commit 9222664

Please sign in to comment.