diff options
author | Ole Troan <ot@cisco.com> | 2019-06-16 23:26:56 +0200 |
---|---|---|
committer | Damjan Marion <dmarion@me.com> | 2019-06-18 13:55:11 +0000 |
commit | ae945592b299b14b8d293b4c77b7d851a4f8ea11 (patch) | |
tree | 9acf5d2a6fc0d1857e1748eca8d9eb76dd2d2fa4 | |
parent | 4d0c663c0a63d3be6789185d6f60a4b4d1e7d207 (diff) |
stats: fix memory leakage when adding / deleting interfaces
This fixes two leaks in registering errors in the stats segment.
- The error name created by vlib_register_errors() was not freed.
- Duplicate error names (when interface readded) was added to the vector.
Change-Id: If5fe371e8059cf6678fc785cbf673707b4f4a655
Type: fix
Signed-off-by: Ole Troan <ot@cisco.com>
-rw-r--r-- | src/vlib/error.c | 7 | ||||
-rw-r--r-- | src/vpp/stats/stat_segment.c | 36 |
2 files changed, 30 insertions, 13 deletions
diff --git a/src/vlib/error.c b/src/vlib/error.c index ca5b87c95b9..9bd928c6d0f 100644 --- a/src/vlib/error.c +++ b/src/vlib/error.c @@ -140,10 +140,11 @@ VLIB_REGISTER_NODE (misc_drop_buffers_node,static) = { }; /* *INDENT-ON* */ -void vlib_stats_register_error_index (u8 *, u64 *, u64) +void vlib_stats_register_error_index (void *, u8 *, u64 *, u64) __attribute__ ((weak)); void -vlib_stats_register_error_index (u8 * notused, u64 * notused2, u64 notused3) +vlib_stats_register_error_index (void *noutused, u8 * notused2, + u64 * notused3, u64 notused4) { }; @@ -211,7 +212,7 @@ vlib_register_errors (vlib_main_t * vm, { error_name = format (0, "/err/%v/%s%c", n->name, error_strings[i], 0); /* Note: error_name consumed by the following call */ - vlib_stats_register_error_index (error_name, em->counters, + vlib_stats_register_error_index (oldheap, error_name, em->counters, n->error_heap_index + i); } } diff --git a/src/vpp/stats/stat_segment.c b/src/vpp/stats/stat_segment.c index 793936bf08f..fade1f7051c 100644 --- a/src/vpp/stats/stat_segment.c +++ b/src/vpp/stats/stat_segment.c @@ -141,7 +141,8 @@ vlib_stats_pop_heap (void *cm_arg, void *oldheap, stat_directory_type_t type) } void -vlib_stats_register_error_index (u8 * name, u64 * em_vec, u64 index) +vlib_stats_register_error_index (void *oldheap, u8 * name, u64 * em_vec, + u64 index) { stat_segment_main_t *sm = &stat_segment_main; stat_segment_shared_header_t *shared_header = sm->shared_header; @@ -151,17 +152,32 @@ vlib_stats_register_error_index (u8 * name, u64 * em_vec, u64 index) ASSERT (shared_header); vlib_stat_segment_lock (); + u32 next_vector_index = vec_len (sm->directory_vector); + clib_mem_set_heap (oldheap); /* Exit stats segment */ - memcpy (e.name, name, vec_len (name)); - e.name[vec_len (name)] = '\0'; - e.type = STAT_DIR_TYPE_ERROR_INDEX; - e.offset = index; - e.offset_vector = 0; - vec_add1 (sm->directory_vector, e); + u32 vector_index = lookup_or_create_hash_index (oldheap, (char *) name, + next_vector_index); - /* Warn clients to refresh any pointers they might be holding */ - shared_header->directory_offset = - stat_segment_offset (shared_header, sm->directory_vector); + /* Back to stats segment */ + clib_mem_set_heap (sm->heap); /* Re-enter stat segment */ + + if (next_vector_index == vector_index) + { + memcpy (e.name, name, vec_len (name)); + e.name[vec_len (name)] = '\0'; + e.type = STAT_DIR_TYPE_ERROR_INDEX; + e.offset = index; + e.offset_vector = 0; + vec_add1 (sm->directory_vector, e); + + /* Warn clients to refresh any pointers they might be holding */ + shared_header->directory_offset = + stat_segment_offset (shared_header, sm->directory_vector); + } + else + { + vec_free (name); + } vlib_stat_segment_unlock (); } |