diff options
author | Christian Franke <chris@opensourcerouting.org> | 2018-08-01 13:23:56 +0200 |
---|---|---|
committer | Christian Franke <chris@opensourcerouting.org> | 2018-08-03 13:25:39 +0200 |
commit | bcd9fd501182ccbfea47a3061c3877680c582cce (patch) | |
tree | b1c8d417f5357196c596dc3f20cb8021cc8a4eac /isisd | |
parent | isisd: make spf code dst-src aware (diff) | |
download | frr-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.c | 63 |
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); } } |