lib: fix route map northbound memory leak

Keep a list of hook contexts used by northbound so we don't lose the
pointer when free()ing the route map index entry data.

Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org>
This commit is contained in:
Rafael Zalamena 2019-10-14 23:29:19 -03:00
parent 91835f1fd2
commit 54a35ff48b
3 changed files with 47 additions and 10 deletions

View file

@ -909,6 +909,7 @@ static struct route_map_index *route_map_index_new(void)
new = XCALLOC(MTYPE_ROUTE_MAP_INDEX, sizeof(struct route_map_index)); new = XCALLOC(MTYPE_ROUTE_MAP_INDEX, sizeof(struct route_map_index));
new->exitpolicy = RMAP_EXIT; /* Default to Cisco-style */ new->exitpolicy = RMAP_EXIT; /* Default to Cisco-style */
TAILQ_INIT(&new->rhclist);
QOBJ_REG(new, route_map_index); QOBJ_REG(new, route_map_index);
return new; return new;
} }
@ -924,6 +925,10 @@ void route_map_index_delete(struct route_map_index *index, int notify)
zlog_debug("Deleting route-map %s sequence %d", zlog_debug("Deleting route-map %s sequence %d",
index->map->name, index->pref); index->map->name, index->pref);
/* Free route map northbound hook contexts. */
while (!TAILQ_EMPTY(&index->rhclist))
routemap_hook_context_free(TAILQ_FIRST(&index->rhclist));
/* Free route match. */ /* Free route match. */
while ((rule = index->match_list.head) != NULL) while ((rule = index->match_list.head) != NULL)
route_map_rule_delete(&index->match_list, rule); route_map_rule_delete(&index->match_list, rule);

View file

@ -162,6 +162,9 @@ struct route_map_rule_list {
struct route_map_rule *tail; struct route_map_rule *tail;
}; };
/* Forward struct declaration: the complete can be found later this file. */
struct routemap_hook_context;
/* Route map index structure. */ /* Route map index structure. */
struct route_map_index { struct route_map_index {
struct route_map *map; struct route_map *map;
@ -194,6 +197,9 @@ struct route_map_index {
uint64_t applied; uint64_t applied;
uint64_t applied_clear; uint64_t applied_clear;
/* List of match/sets contexts. */
TAILQ_HEAD(, routemap_hook_context) rhclist;
QOBJ_FIELDS QOBJ_FIELDS
}; };
DECLARE_QOBJ_TYPE(route_map_index) DECLARE_QOBJ_TYPE(route_map_index)
@ -660,6 +666,7 @@ struct routemap_hook_context {
route_map_event_t rhc_event; route_map_event_t rhc_event;
routemap_set_hook_fun rhc_shook; routemap_set_hook_fun rhc_shook;
routemap_match_hook_fun rhc_mhook; routemap_match_hook_fun rhc_mhook;
TAILQ_ENTRY(routemap_hook_context) rhc_entry;
}; };
int lib_route_map_entry_match_destroy(enum nb_event event, int lib_route_map_entry_match_destroy(enum nb_event event,
@ -667,6 +674,10 @@ int lib_route_map_entry_match_destroy(enum nb_event event,
int lib_route_map_entry_set_destroy(enum nb_event event, int lib_route_map_entry_set_destroy(enum nb_event event,
const struct lyd_node *dnode); const struct lyd_node *dnode);
struct routemap_hook_context *
routemap_hook_context_insert(struct route_map_index *rmi);
void routemap_hook_context_free(struct routemap_hook_context *rhc);
extern const struct frr_yang_module_info frr_route_map_info; extern const struct frr_yang_module_info frr_route_map_info;
/* routemap_cli.c */ /* routemap_cli.c */

View file

@ -74,6 +74,30 @@ int lib_route_map_entry_set_destroy(enum nb_event event,
return NB_OK; return NB_OK;
} }
/*
* Auxiliary hook context list manipulation functions.
*/
struct routemap_hook_context *
routemap_hook_context_insert(struct route_map_index *rmi)
{
struct routemap_hook_context *rhc;
rhc = XCALLOC(MTYPE_TMP, sizeof(*rhc));
rhc->rhc_rmi = rmi;
TAILQ_INSERT_TAIL(&rmi->rhclist, rhc, rhc_entry);
return rhc;
}
void
routemap_hook_context_free(struct routemap_hook_context *rhc)
{
struct route_map_index *rmi = rhc->rhc_rmi;
TAILQ_REMOVE(&rmi->rhclist, rhc, rhc_entry);
XFREE(MTYPE_TMP, rhc);
}
/* /*
* XPath: /frr-route-map:lib/route-map * XPath: /frr-route-map:lib/route-map
*/ */
@ -436,20 +460,17 @@ lib_route_map_entry_match_condition_create(enum nb_event event,
union nb_resource *resource) union nb_resource *resource)
{ {
struct routemap_hook_context *rhc; struct routemap_hook_context *rhc;
struct route_map_index *rmi;
switch (event) { switch (event) {
case NB_EV_VALIDATE: case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
/* NOTHING */ /* NOTHING */
break; break;
case NB_EV_PREPARE:
resource->ptr = XCALLOC(MTYPE_TMP, sizeof(*rhc));
break;
case NB_EV_ABORT:
XFREE(MTYPE_TMP, resource->ptr);
break;
case NB_EV_APPLY: case NB_EV_APPLY:
rhc = resource->ptr; rmi = nb_running_get_entry(dnode, NULL, true);
rhc->rhc_rmi = nb_running_get_entry(dnode, NULL, true); rhc = routemap_hook_context_insert(rmi);
nb_running_set_entry(dnode, rhc); nb_running_set_entry(dnode, rhc);
break; break;
} }
@ -469,7 +490,7 @@ lib_route_map_entry_match_condition_destroy(enum nb_event event,
rv = lib_route_map_entry_match_destroy(event, dnode); rv = lib_route_map_entry_match_destroy(event, dnode);
rhc = nb_running_unset_entry(dnode); rhc = nb_running_unset_entry(dnode);
XFREE(MTYPE_TMP, rhc); routemap_hook_context_free(rhc);
return rv; return rv;
} }
@ -893,7 +914,7 @@ static int lib_route_map_entry_set_action_destroy(enum nb_event event,
rv = lib_route_map_entry_set_destroy(event, dnode); rv = lib_route_map_entry_set_destroy(event, dnode);
rhc = nb_running_unset_entry(dnode); rhc = nb_running_unset_entry(dnode);
XFREE(MTYPE_TMP, rhc); routemap_hook_context_free(rhc);
return rv; return rv;
} }