summaryrefslogtreecommitdiffstats
path: root/nhrpd/nhrp_cache.c
diff options
context:
space:
mode:
authorReuben Dowle <reuben.dowle@4rf.com>2020-12-07 04:35:13 +0100
committerReuben Dowle <reuben.dowle@4rf.com>2020-12-16 22:17:13 +0100
commitee72f0a0eb93038ef6dfd01fed9f32e24c5de2a1 (patch)
tree6d5313869a1bfa59546eec1470e7f3ab9ff12762 /nhrpd/nhrp_cache.c
parentnhrpd: Only create one child sa (diff)
downloadfrr-ee72f0a0eb93038ef6dfd01fed9f32e24c5de2a1.tar.xz
frr-ee72f0a0eb93038ef6dfd01fed9f32e24c5de2a1.zip
nhrpd: Cleanup resources when interface is deleted
Currently when an interface is deleted from configuration, associated resources are not freed. This causes memory leaks and crashes. To reproduce this issue: * Connect to a DMVPN hub * Outside of frr, delete the underlying GRE interface * Use 'no interface xxx' to delete the interface containing nhrp configurations Signed-off-by: Reuben Dowle <reuben.dowle@4rf.com>
Diffstat (limited to 'nhrpd/nhrp_cache.c')
-rwxr-xr-x[-rw-r--r--]nhrpd/nhrp_cache.c42
1 files changed, 40 insertions, 2 deletions
diff --git a/nhrpd/nhrp_cache.c b/nhrpd/nhrp_cache.c
index 1c8fee8b0..0b5a0427e 100644..100755
--- a/nhrpd/nhrp_cache.c
+++ b/nhrpd/nhrp_cache.c
@@ -69,12 +69,13 @@ static void nhrp_cache_free(struct nhrp_cache *c)
{
struct nhrp_interface *nifp = c->ifp->info;
- zassert(c->cur.type == NHRP_CACHE_INVALID && c->cur.peer == NULL);
- zassert(c->new.type == NHRP_CACHE_INVALID && c->new.peer == NULL);
+ debugf(NHRP_DEBUG_COMMON, "Deleting cache entry");
nhrp_cache_counts[c->cur.type]--;
notifier_call(&c->notifier_list, NOTIFY_CACHE_DELETE);
zassert(!notifier_active(&c->notifier_list));
hash_release(nifp->cache_hash, c);
+ THREAD_OFF(c->t_timeout);
+ THREAD_OFF(c->t_auth);
XFREE(MTYPE_NHRP_CACHE, c);
}
@@ -140,6 +141,41 @@ struct nhrp_cache_config *nhrp_cache_config_get(struct interface *ifp,
create ? nhrp_cache_config_alloc : NULL);
}
+static void do_nhrp_cache_free(struct hash_bucket *hb,
+ void *arg __attribute__((__unused__)))
+{
+ struct nhrp_cache *c = hb->data;
+
+ nhrp_cache_free(c);
+}
+
+static void do_nhrp_cache_config_free(struct hash_bucket *hb,
+ void *arg __attribute__((__unused__)))
+{
+ struct nhrp_cache_config *cc = hb->data;
+
+ nhrp_cache_config_free(cc);
+}
+
+void nhrp_cache_interface_del(struct interface *ifp)
+{
+ struct nhrp_interface *nifp = ifp->info;
+
+ debugf(NHRP_DEBUG_COMMON, "Cleaning up undeleted cache entries (%lu)",
+ nifp->cache_hash ? nifp->cache_hash->count : 0);
+
+ if (nifp->cache_hash) {
+ hash_iterate(nifp->cache_hash, do_nhrp_cache_free, NULL);
+ hash_free(nifp->cache_hash);
+ }
+
+ if (nifp->cache_config_hash) {
+ hash_iterate(nifp->cache_config_hash, do_nhrp_cache_config_free,
+ NULL);
+ hash_free(nifp->cache_config_hash);
+ }
+}
+
struct nhrp_cache *nhrp_cache_get(struct interface *ifp,
union sockunion *remote_addr, int create)
{
@@ -164,6 +200,7 @@ struct nhrp_cache *nhrp_cache_get(struct interface *ifp,
static int nhrp_cache_do_free(struct thread *t)
{
struct nhrp_cache *c = THREAD_ARG(t);
+
c->t_timeout = NULL;
nhrp_cache_free(c);
return 0;
@@ -172,6 +209,7 @@ static int nhrp_cache_do_free(struct thread *t)
static int nhrp_cache_do_timeout(struct thread *t)
{
struct nhrp_cache *c = THREAD_ARG(t);
+
c->t_timeout = NULL;
if (c->cur.type != NHRP_CACHE_INVALID)
nhrp_cache_update_binding(c, c->cur.type, -1, NULL, 0, NULL);