summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/vpp/CMakeLists.txt8
-rw-r--r--src/vpp/mem/mem.c121
-rw-r--r--src/vpp/mem/mem.md21
-rw-r--r--src/vppinfra/mem_dlmalloc.c12
4 files changed, 157 insertions, 5 deletions
diff --git a/src/vpp/CMakeLists.txt b/src/vpp/CMakeLists.txt
index ae1e4d76c02..0a8ec31601b 100644
--- a/src/vpp/CMakeLists.txt
+++ b/src/vpp/CMakeLists.txt
@@ -124,5 +124,13 @@ add_vpp_executable(vpp_prometheus_export
DEPENDS api_headers
)
+##############################################################################
+# vppmem_preload library
+##############################################################################
+add_vpp_library(vppmem_preload
+ SOURCES mem/mem.c
+ LINK_LIBRARIES vppinfra
+)
+
install(FILES conf/startup.conf DESTINATION etc/vpp COMPONENT vpp)
install(FILES conf/80-vpp.conf DESTINATION etc/sysctl.d COMPONENT vpp)
diff --git a/src/vpp/mem/mem.c b/src/vpp/mem/mem.c
new file mode 100644
index 00000000000..d438c970447
--- /dev/null
+++ b/src/vpp/mem/mem.c
@@ -0,0 +1,121 @@
+#include <stdio.h>
+#include <vppinfra/mem.h>
+
+extern void * __libc_malloc (size_t);
+extern void __libc_free (void *);
+extern void * __libc_calloc (size_t, size_t);
+extern void * __libc_realloc (void *, size_t);
+extern void * __libc_valloc (size_t);
+extern void * __libc_memalign (size_t, size_t);
+extern void * __libc_pvalloc (size_t);
+
+__thread u64 vpp_mem_no_vpp_heap;
+
+static void no_heap (void)
+{
+ vpp_mem_no_vpp_heap++;
+
+ if (1 == vpp_mem_no_vpp_heap)
+ fprintf (stderr, "vpp mem: libc allocation requested but no vpp heap ready, defaulting to libc.\n");
+}
+
+static_always_inline int
+check_vpp_heap (void)
+{
+ if (PREDICT_TRUE (clib_mem_get_per_cpu_heap () != 0))
+ return 1;
+
+ no_heap ();
+ return 0;
+}
+
+void *
+malloc(size_t size)
+{
+ if (!check_vpp_heap ())
+ return __libc_malloc (size);
+
+ return clib_mem_alloc (size);
+}
+
+void
+free(void *p)
+{
+ if (!p)
+ return;
+
+ if (!check_vpp_heap ())
+ return __libc_free (p);
+
+ clib_mem_free (p);
+}
+
+void *
+calloc(size_t nmemb, size_t size)
+{
+ void * p;
+
+ if (!check_vpp_heap ())
+ return __libc_calloc (nmemb, size);
+
+ p = clib_mem_alloc (nmemb * size);
+ clib_memset (p, 0, nmemb * size);
+ return p;
+}
+
+void *
+realloc(void *p, size_t size)
+{
+ if (!check_vpp_heap ())
+ return __libc_realloc (p, size);
+
+ return clib_mem_realloc (p, size, clib_mem_size (p));
+}
+
+int
+posix_memalign(void **memptr, size_t alignment, size_t size)
+{
+ if (!check_vpp_heap ())
+ *memptr = __libc_memalign (alignment, size);
+ else
+ *memptr = clib_mem_alloc_aligned (size, alignment);
+ return 0;
+}
+
+void *
+aligned_alloc(size_t alignment, size_t size)
+{
+ if (!check_vpp_heap ())
+ return __libc_memalign (alignment, size);
+
+ return clib_mem_alloc_aligned (size, alignment);
+}
+
+void *
+valloc(size_t size)
+{
+ if (!check_vpp_heap ())
+ return __libc_valloc (size);
+
+ return clib_mem_alloc_aligned (size, clib_mem_get_page_size ());
+}
+
+void *memalign(size_t alignment, size_t size)
+{
+ if (!check_vpp_heap ())
+ return __libc_memalign (alignment, size);
+
+ return clib_mem_alloc_aligned (size, alignment);
+}
+
+void *
+pvalloc(size_t size)
+{
+ uword pagesz;
+
+ if (!check_vpp_heap ())
+ return __libc_pvalloc (size);
+
+ pagesz = clib_mem_get_page_size ();
+ return clib_mem_alloc_aligned (round_pow2 (size, pagesz), pagesz);
+}
diff --git a/src/vpp/mem/mem.md b/src/vpp/mem/mem.md
new file mode 100644
index 00000000000..84ab820e5e5
--- /dev/null
+++ b/src/vpp/mem/mem.md
@@ -0,0 +1,21 @@
+# VPP mem preload {#mempreload_doc}
+
+Internal VPP memory allocations rely on VPP main-heap, however when using
+external libraries, esp. in plugins (eg. OpenSSL library used by the IKEv2
+plugin), those external libraries usually manages memory using the standard
+libc `malloc()`/`free()`/... calls. This, in turn, makes use of the default
+libc heap.
+
+VPP has no knowledge of this heap and tools such as memory traces cannot be
+used.
+
+In order to enable the use of standard VPP debugging tools, this library
+replaces standard libc memory management calls with version using VPP
+main-heap.
+
+To use it, you need to use the `LD_PRELOAD` mechanism, eg.
+```
+~# LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libvppmem_preload.so /usr/bin/vpp -c /etc/vpp/startup.conf
+```
+
+You can then use tools such as memory traces as usual.
diff --git a/src/vppinfra/mem_dlmalloc.c b/src/vppinfra/mem_dlmalloc.c
index df1489fd8d8..bc6561a738e 100644
--- a/src/vppinfra/mem_dlmalloc.c
+++ b/src/vppinfra/mem_dlmalloc.c
@@ -74,17 +74,17 @@ mheap_get_trace (uword offset, uword size)
/* Spurious Coverity warnings be gone. */
clib_memset (&trace, 0, sizeof (trace));
- /* Skip our frame and mspace_get_aligned's frame */
- n_callers = clib_backtrace (trace.callers, ARRAY_LEN (trace.callers), 2);
- if (n_callers == 0)
- return;
-
clib_spinlock_lock (&tm->lock);
/* Turn off tracing to avoid embarrassment... */
save_enabled = tm->enabled;
tm->enabled = 0;
+ /* Skip our frame and mspace_get_aligned's frame */
+ n_callers = clib_backtrace (trace.callers, ARRAY_LEN (trace.callers), 2);
+ if (n_callers == 0)
+ goto out;
+
if (!tm->trace_by_callers)
tm->trace_by_callers =
hash_create_shmem (0, sizeof (trace.callers), sizeof (uword));
@@ -137,6 +137,8 @@ mheap_get_trace (uword offset, uword size)
t->n_bytes += size;
t->offset = offset; /* keep a sample to autopsy */
hash_set (tm->trace_index_by_offset, offset, t - tm->traces);
+
+out:
tm->enabled = save_enabled;
clib_spinlock_unlock (&tm->lock);
}