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>
This commit is contained in:
Christian Franke 2018-08-01 13:23:56 +02:00
parent 321c1bbb94
commit bcd9fd5011

View File

@ -353,6 +353,7 @@ struct isis_route_info *isis_route_create(struct prefix *prefix,
route_info = rinfo_new; route_info = rinfo_new;
UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
} else { } else {
route_unlock_node(route_node);
if (isis->debugs & DEBUG_RTE_EVENTS) if (isis->debugs & DEBUG_RTE_EVENTS)
zlog_debug("ISIS-Rte (%s) route already exists: %s", zlog_debug("ISIS-Rte (%s) route already exists: %s",
area->area_tag, buff); area->area_tag, buff);
@ -379,20 +380,21 @@ struct isis_route_info *isis_route_create(struct prefix *prefix,
return route_info; return route_info;
} }
static void isis_route_delete(struct prefix *prefix, static void isis_route_delete(struct route_node *rode,
struct prefix_ipv6 *src_p,
struct route_table *table) struct route_table *table)
{ {
struct route_node *rode;
struct isis_route_info *rinfo; struct isis_route_info *rinfo;
char buff[SRCDEST2STR_BUFFER]; char buff[SRCDEST2STR_BUFFER];
struct prefix *prefix;
struct prefix_ipv6 *src_p;
/* for log */ /* for log */
srcdest2str(prefix, src_p, buff, sizeof(buff)); srcdest_rnode2str(rode, buff, sizeof(buff));
srcdest_rnode_prefixes(rode, (const struct prefix **)&prefix,
(const struct prefix **)&src_p);
rode = srcdest_rnode_get(table, prefix, src_p);
rinfo = rode->info; rinfo = rode->info;
if (rinfo == NULL) { if (rinfo == NULL) {
if (isis->debugs & DEBUG_RTE_EVENTS) if (isis->debugs & DEBUG_RTE_EVENTS)
zlog_debug( zlog_debug(
@ -409,8 +411,7 @@ static void isis_route_delete(struct prefix *prefix,
} }
isis_route_info_delete(rinfo); isis_route_info_delete(rinfo);
rode->info = NULL; rode->info = NULL;
route_unlock_node(rode);
return;
} }
static void _isis_route_verify_table(struct isis_area *area, static void _isis_route_verify_table(struct isis_area *area,
@ -454,12 +455,15 @@ static void _isis_route_verify_table(struct isis_area *area,
} }
isis_zebra_route_update(dst_p, src_p, rinfo); isis_zebra_route_update(dst_p, src_p, rinfo);
if (!CHECK_FLAG(rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE)) {
if (CHECK_FLAG(rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE))
continue;
/* Area is either L1 or L2 => we use level route tables /* Area is either L1 or L2 => we use level route tables
* directly for * directly for
* validating => no problems with deleting routes. */ * validating => no problems with deleting routes. */
if (!tables) { if (!tables) {
isis_route_delete(dst_p, src_p, table); isis_route_delete(rnode, table);
continue; continue;
} }
@ -468,14 +472,21 @@ static void _isis_route_verify_table(struct isis_area *area,
* delete node from level tables as well before deleting * delete node from level tables as well before deleting
* route info. */ * route info. */
for (int level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) { for (int level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) {
drnode = srcdest_rnode_get(tables[level - 1], drnode = srcdest_rnode_lookup(tables[level - 1],
dst_p, src_p); dst_p, src_p);
if (drnode->info == rnode->info) if (!drnode)
continue;
route_unlock_node(drnode);
if (drnode->info != rnode->info)
continue;
drnode->info = NULL; drnode->info = NULL;
route_unlock_node(drnode);
} }
isis_route_delete(dst_p, src_p, table); isis_route_delete(rnode, table);
}
} }
} }