summaryrefslogtreecommitdiffstats
path: root/isisd
diff options
context:
space:
mode:
authorChristian Franke <chris@opensourcerouting.org>2018-07-24 17:40:24 +0200
committerChristian Franke <chris@opensourcerouting.org>2018-08-03 13:25:39 +0200
commit3dace42de964a00429681544167679083b52807a (patch)
tree94d7cc43a4ac55777f739efd67c189033f8a730f /isisd
parentisisd: learn and advertise IPv6 dst-src routes (diff)
downloadfrr-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.c147
-rw-r--r--isisd/isis_route.h16
-rw-r--r--isisd/isis_spf.c45
-rw-r--r--isisd/isis_spf.h3
-rw-r--r--isisd/isisd.c64
-rw-r--r--isisd/isisd.h5
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);