summaryrefslogtreecommitdiff
path: root/isisd/isis_route.c
diff options
context:
space:
mode:
Diffstat (limited to 'isisd/isis_route.c')
-rw-r--r--isisd/isis_route.c147
1 files changed, 36 insertions, 111 deletions
diff --git a/isisd/isis_route.c b/isisd/isis_route.c
index c98e16e2bd..b6fb90b6dd 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]);
-}