diff --git a/daemon/kernel.c b/daemon/kernel.c
index fa773d720..69abb7494 100644
--- a/daemon/kernel.c
+++ b/daemon/kernel.c
@@ -8,13 +8,17 @@
 #include <unistd.h>
 #include <glib.h>
 #include <errno.h>
+#include <sys/mman.h>
 
 #include "helpers.h"
 #include "log.h"
+#include "bufferpool.h"
+#include "main.h"
 
 #include "xt_RTPENGINE.h"
 
 #define PREFIX "/proc/rtpengine"
+#define MMAP_PAGE_SIZE (4096 * 16)
 
 struct kernel_interface kernel;
 
@@ -53,6 +57,15 @@ static bool kernel_delete_table(unsigned int id) {
 	return kernel_action_table("del", id);
 }
 
+static void *kernel_alloc(size_t len) {
+	void *b = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, kernel.fd, 0);
+	assert(b != NULL && b != MAP_FAILED);
+	return b;
+}
+static void kernel_free(void *p, size_t len) {
+	munmap(p, len);
+}
+
 static int kernel_open_table(unsigned int id) {
 	char s[64];
 	int saved_errno;
@@ -124,6 +137,8 @@ bool kernel_setup_table(unsigned int id) {
 	kernel.table = id;
 	kernel.is_open = true;
 
+	shm_bufferpool = bufferpool_new2(kernel_alloc, kernel_free, MMAP_PAGE_SIZE);
+
 	return true;
 }
 
diff --git a/daemon/main.c b/daemon/main.c
index 3564d741a..43fdb30b0 100644
--- a/daemon/main.c
+++ b/daemon/main.c
@@ -78,6 +78,7 @@ static GQueue rtpe_cli = G_QUEUE_INIT;
 
 GQueue rtpe_control_ng = G_QUEUE_INIT;
 GQueue rtpe_control_ng_tcp = G_QUEUE_INIT;
+struct bufferpool *shm_bufferpool;
 
 struct rtpengine_config rtpe_config = {
 	// non-zero defaults
@@ -1239,6 +1240,26 @@ static void clib_loop(void) {
 }
 #endif
 
+static void kernel_setup(void) {
+	if (rtpe_config.kernel_table < 0)
+		goto fallback;
+#ifndef WITHOUT_NFTABLES
+	const char *err = nftables_setup(rtpe_config.nftables_chain, rtpe_config.nftables_base_chain,
+			(nftables_args) {.table = rtpe_config.kernel_table,
+			.append = rtpe_config.nftables_append,
+			.family = rtpe_config.nftables_family});
+	if (err)
+		die("Failed to create nftables chains or rules: %s (%s)", err, strerror(errno));
+#endif
+	if (!kernel_setup_table(rtpe_config.kernel_table) && rtpe_config.no_fallback)
+		die("Userspace fallback disallowed - exiting");
+	return;
+
+fallback:
+	shm_bufferpool = bufferpool_new(g_malloc, g_free, 4096); // fallback userspace bufferpool
+}
+
+
 static void init_everything(void) {
 	bufferpool_init();
 	gettimeofday(&rtpe_now, NULL);
@@ -1258,6 +1279,7 @@ static void init_everything(void) {
 	dtls_init();
 	ice_init();
 	crypto_init_main();
+	kernel_setup();
 	interfaces_init(&rtpe_config.interfaces);
 	iptables_init();
 	control_ng_init();
@@ -1282,27 +1304,11 @@ static void init_everything(void) {
 }
 
 
-static void kernel_setup(void) {
-	if (rtpe_config.kernel_table < 0)
-		return;
-#ifndef WITHOUT_NFTABLES
-	const char *err = nftables_setup(rtpe_config.nftables_chain, rtpe_config.nftables_base_chain,
-			(nftables_args) {.table = rtpe_config.kernel_table,
-			.append = rtpe_config.nftables_append,
-			.family = rtpe_config.nftables_family});
-	if (err)
-		die("Failed to create nftables chains or rules: %s (%s)", err, strerror(errno));
-#endif
-	if (!kernel_setup_table(rtpe_config.kernel_table) && rtpe_config.no_fallback)
-		die("Userspace fallback disallowed - exiting");
-}
-
 static void create_everything(void) {
 	struct timeval tmp_tv;
 
 	gettimeofday(&rtpe_now, NULL);
 
-	kernel_setup();
 
 	// either one global poller, or one per thread for media sockets plus one for control sockets
 #ifdef HAVE_LIBURING
@@ -1596,6 +1602,7 @@ int main(int argc, char **argv) {
 	nftables_shutdown(rtpe_config.nftables_chain, rtpe_config.nftables_base_chain,
 			(nftables_args){.family = rtpe_config.nftables_family});
 #endif
+	bufferpool_destroy(shm_bufferpool);
 	kernel_shutdown_table();
 	bufferpool_cleanup();
 
diff --git a/include/main.h b/include/main.h
index 8f31f60da..37731d63e 100644
--- a/include/main.h
+++ b/include/main.h
@@ -225,6 +225,7 @@ extern struct rtpengine_config initial_rtpe_config;
 extern GQueue rtpe_control_ng;
 extern GQueue rtpe_control_ng_tcp;
 
+extern struct bufferpool *shm_bufferpool;
 
 
 #endif
diff --git a/t/test-stats.c b/t/test-stats.c
index d0f8c0f4b..28540431f 100644
--- a/t/test-stats.c
+++ b/t/test-stats.c
@@ -22,6 +22,7 @@ unsigned int num_media_pollers = 1;
 unsigned int rtpe_poller_rr_iter;
 GString *dtmf_logs;
 GQueue rtpe_control_ng = G_QUEUE_INIT;
+struct bufferpool *shm_bufferpool;
 
 static void __assert_g_string_eq(GString *a, const char *b, unsigned int line) {
 	if (strcmp(a->str, b) == 0) {
diff --git a/t/test-transcode.c b/t/test-transcode.c
index dc4a942a8..dca9d3130 100644
--- a/t/test-transcode.c
+++ b/t/test-transcode.c
@@ -19,6 +19,7 @@ unsigned int num_media_pollers;
 unsigned int rtpe_poller_rr_iter;
 GString *dtmf_logs;
 GQueue rtpe_control_ng = G_QUEUE_INIT;
+struct bufferpool *shm_bufferpool;
 
 static str *sdup(char *s) {
 	str r = STR_INIT(s);