summaryrefslogtreecommitdiffstats
path: root/isisd
diff options
context:
space:
mode:
authorChristian Franke <chris@opensourcerouting.org>2018-08-01 13:23:56 +0200
committerChristian Franke <chris@opensourcerouting.org>2018-08-03 13:25:39 +0200
commitbcd9fd501182ccbfea47a3061c3877680c582cce (patch)
treeb1c8d417f5357196c596dc3f20cb8021cc8a4eac /isisd
parentisisd: make spf code dst-src aware (diff)
downloadfrr-bcd9fd501182ccbfea47a3061c3877680c582cce.tar.xz
frr-bcd9fd501182ccbfea47a3061c3877680c582cce.zip
isisd: fix refcounting in isis_route.c
This fixes multiple issues and inefficiencies regarding the usage of route_tables in isis_route.c and removes some memory leaks. Signed-off-by: Christian Franke <chris@opensourcerouting.org>
Diffstat (limited to 'isisd')
-rw-r--r--isisd/isis_route.c63
1 files changed, 37 insertions, 26 deletions
diff --git a/isisd/isis_route.c b/isisd/isis_route.c
index 2257ccd57..b1225ae54 100644
--- a/isisd/isis_route.c
+++ b/isisd/isis_route.c
@@ -353,6 +353,7 @@ struct isis_route_info *isis_route_create(struct prefix *prefix,
route_info = rinfo_new;
UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
} else {
+ route_unlock_node(route_node);
if (isis->debugs & DEBUG_RTE_EVENTS)
zlog_debug("ISIS-Rte (%s) route already exists: %s",
area->area_tag, buff);
@@ -379,20 +380,21 @@ struct isis_route_info *isis_route_create(struct prefix *prefix,
return route_info;
}
-static void isis_route_delete(struct prefix *prefix,
- struct prefix_ipv6 *src_p,
+static void isis_route_delete(struct route_node *rode,
struct route_table *table)
{
- struct route_node *rode;
struct isis_route_info *rinfo;
char buff[SRCDEST2STR_BUFFER];
+ struct prefix *prefix;
+ struct prefix_ipv6 *src_p;
/* for log */
- srcdest2str(prefix, src_p, buff, sizeof(buff));
+ srcdest_rnode2str(rode, buff, sizeof(buff));
- rode = srcdest_rnode_get(table, prefix, src_p);
- rinfo = rode->info;
+ srcdest_rnode_prefixes(rode, (const struct prefix **)&prefix,
+ (const struct prefix **)&src_p);
+ rinfo = rode->info;
if (rinfo == NULL) {
if (isis->debugs & DEBUG_RTE_EVENTS)
zlog_debug(
@@ -409,8 +411,7 @@ static void isis_route_delete(struct prefix *prefix,
}
isis_route_info_delete(rinfo);
rode->info = NULL;
-
- return;
+ route_unlock_node(rode);
}
static void _isis_route_verify_table(struct isis_area *area,
@@ -454,28 +455,38 @@ static void _isis_route_verify_table(struct isis_area *area,
}
isis_zebra_route_update(dst_p, src_p, rinfo);
- if (!CHECK_FLAG(rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE)) {
- /* Area is either L1 or L2 => we use level route tables
- * directly for
- * validating => no problems with deleting routes. */
- if (!tables) {
- isis_route_delete(dst_p, src_p, table);
+
+ if (CHECK_FLAG(rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE))
+ continue;
+
+ /* Area is either L1 or L2 => we use level route tables
+ * directly for
+ * validating => no problems with deleting routes. */
+ if (!tables) {
+ isis_route_delete(rnode, 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. */
+ for (int level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) {
+ drnode = srcdest_rnode_lookup(tables[level - 1],
+ dst_p, src_p);
+ if (!drnode)
continue;
- }
- /* If area is L1L2, we work with merge table and
- * therefore must
- * delete node from level tables as well before deleting
- * route info. */
- for (int level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) {
- drnode = srcdest_rnode_get(tables[level - 1],
- dst_p, src_p);
- if (drnode->info == rnode->info)
- drnode->info = NULL;
- }
+ route_unlock_node(drnode);
+
+ if (drnode->info != rnode->info)
+ continue;
- isis_route_delete(dst_p, src_p, table);
+ drnode->info = NULL;
+ route_unlock_node(drnode);
}
+
+ isis_route_delete(rnode, table);
}
}