[PATCH v2 1/1] mbuf: add optional dynfield3 storage
Randy L Tice
rtice at cisco.com
Fri Sep 25 21:31:08 CEST 2026
From: Randy L Tice <rtice at cisco.com>
Date: Thu, 03 Sep 2026 09:13:28 -0400
Add build-time support for optional cache-line-aligned dynamic-field
storage at the end of struct rte_mbuf.
The mbuf_dynfield3_size Meson option sets RTE_MBUF_DYNFIELD3_SIZE
in rte_build_config.h. A non-zero value enables the extra area. The
storage is represented as uint64_t elements for 32-bit and 64-bit
build consistency.
When enabled, dynfield3 is made available to the mbuf dynamic field
allocator. The mbuf_dynfield3_copy option controls whether the area is
copied by the generic mbuf dynamic-field copy helper, and defaults to
false.
Validate that the configured size is non-negative, is a multiple of
sizeof(uint64_t), and reserves a multiple of the cache line size.
Signed-off-by: Randy L Tice <rtice at cisco.com>
---
app/test/test_mbuf.c | 5 +++--
config/meson.build | 16 ++++++++++++++++
doc/guides/rel_notes/release_26_11.rst | 15 +++++++++++++++
lib/mbuf/rte_mbuf.h | 6 ++++++
lib/mbuf/rte_mbuf_core.h | 17 +++++++++++++++++
lib/mbuf/rte_mbuf_dyn.c | 3 +++
meson_options.txt | 4 ++++
7 files changed, 64 insertions(+), 2 deletions(-)
diff --git a/app/test/test_mbuf.c b/app/test/test_mbuf.c
index db23259745..9f3b396a61 100644
--- a/app/test/test_mbuf.c
+++ b/app/test/test_mbuf.c
@@ -2776,8 +2776,9 @@ test_mbuf(void)
struct rte_mempool *pktmbuf_pool = NULL;
struct rte_mempool *pktmbuf_pool2 = NULL;
-
- RTE_BUILD_BUG_ON(sizeof(struct rte_mbuf) != RTE_CACHE_LINE_MIN_SIZE * 2);
+ RTE_BUILD_BUG_ON(sizeof(struct rte_mbuf) !=
+ RTE_CACHE_LINE_MIN_SIZE * 2 +
+ RTE_MBUF_DYNFIELD3_SIZE);
/* create pktmbuf pool if it does not exist */
pktmbuf_pool = rte_pktmbuf_pool_create("test_pktmbuf_pool",
diff --git a/config/meson.build b/config/meson.build
index 344f68822b..dd857e065f 100644
--- a/config/meson.build
+++ b/config/meson.build
@@ -384,6 +384,19 @@ dpdk_conf.set('RTE_LIBEAL_USE_HPET', get_option('use_hpet'))
dpdk_conf.set('RTE_ENABLE_STDATOMIC', get_option('enable_stdatomic'))
dpdk_conf.set('RTE_ENABLE_TRACE_FP', get_option('enable_trace_fp'))
dpdk_conf.set('RTE_PKTMBUF_HEADROOM', get_option('pkt_mbuf_headroom'))
+mbuf_dynfield3_size = get_option('mbuf_dynfield3_size')
+if mbuf_dynfield3_size < 0
+ error('mbuf_dynfield3_size must be greater than or equal to 0')
+endif
+if mbuf_dynfield3_size % cc.sizeof('uint64_t', prefix: '#include <stdint.h>') != 0
+ error('mbuf_dynfield3_size must be a multiple of sizeof(uint64_t)')
+endif
+mbuf_dynfield3_copy = get_option('mbuf_dynfield3_copy')
+if mbuf_dynfield3_copy and mbuf_dynfield3_size == 0
+ error('mbuf_dynfield3_copy requires mbuf_dynfield3_size greater than 0')
+endif
+dpdk_conf.set('RTE_MBUF_DYNFIELD3_SIZE', mbuf_dynfield3_size)
+dpdk_conf.set10('RTE_MBUF_DYNFIELD3_COPY', mbuf_dynfield3_copy)
# values which have defaults which may be overridden
dpdk_conf.set('RTE_MAX_VFIO_GROUPS', 64)
dpdk_conf.set('RTE_DRIVER_MEMPOOL_BUCKET_SIZE_KB', 64)
@@ -395,6 +408,9 @@ dpdk_conf.set10('RTE_IOVA_IN_MBUF', get_option('enable_iova_as_pa'))
compile_time_cpuflags = []
subdir(arch_subdir)
+if mbuf_dynfield3_size % dpdk_conf.get('RTE_CACHE_LINE_SIZE') != 0
+ error('mbuf_dynfield3_size must be a multiple of RTE_CACHE_LINE_SIZE')
+endif
dpdk_conf.set('RTE_COMPILE_TIME_CPUFLAGS', ','.join(compile_time_cpuflags))
# apply cross-specific options
diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst
index dec96ccbc7..2d0fb6660c 100644
--- a/doc/guides/rel_notes/release_26_11.rst
+++ b/doc/guides/rel_notes/release_26_11.rst
@@ -60,6 +60,15 @@ New Features
Added the experimental ``rte_cpu_socket_id()`` function
to map an OS logical CPU ID to the NUMA socket containing that CPU.
+* **Added optional extra mbuf dynamic field storage.**
+
+ Added ``mbuf_dynfield3_size`` build option to enable a
+ cache-line-aligned ``dynfield3`` area in ``struct rte_mbuf``.
+ The configured size is defined as ``RTE_MBUF_DYNFIELD3_SIZE``
+ in ``rte_build_config.h``.
+ The area is not copied by generic mbuf copy or clone operations
+ unless ``mbuf_dynfield3_copy`` is enabled.
+
* **Added TPID support to VLAN tag insertion.**
Added ``rte_vlan_insert_tpid()`` to the net library.
@@ -338,6 +347,12 @@ Known Issues
Also, make sure to start the actual text at the margin.
=======================================================
+* **Some drivers may require changes for enlarged mbufs.**
+
+ Enabling ``mbuf_dynfield3_size`` with a non-zero value increases
+ ``sizeof(struct rte_mbuf)``. Drivers or applications that assume a
+ fixed mbuf size may require follow-up changes.
+
Tested Platforms
----------------
diff --git a/lib/mbuf/rte_mbuf.h b/lib/mbuf/rte_mbuf.h
index 60ec8158cd..97360d6549 100644
--- a/lib/mbuf/rte_mbuf.h
+++ b/lib/mbuf/rte_mbuf.h
@@ -1231,6 +1231,12 @@ rte_mbuf_dynfield_copy(struct rte_mbuf *mdst, const struct rte_mbuf *msrc)
mdst->dynfield2 = msrc->dynfield2;
#endif
memcpy(&mdst->dynfield1, msrc->dynfield1, sizeof(mdst->dynfield1));
+#if RTE_MBUF_DYNFIELD3_SIZE > 0
+ if (RTE_MBUF_DYNFIELD3_COPY)
+ memcpy(RTE_PTR_ADD(mdst, RTE_MBUF_DYNFIELD3_OFFSET),
+ RTE_PTR_ADD(msrc, RTE_MBUF_DYNFIELD3_OFFSET),
+ RTE_MBUF_DYNFIELD3_SIZE);
+#endif
}
/* internal */
diff --git a/lib/mbuf/rte_mbuf_core.h b/lib/mbuf/rte_mbuf_core.h
index 98b0bd9ca7..5069984269 100644
--- a/lib/mbuf/rte_mbuf_core.h
+++ b/lib/mbuf/rte_mbuf_core.h
@@ -17,6 +17,7 @@
*/
#include <stdalign.h>
+#include <stddef.h>
#include <stdint.h>
#include <rte_byteorder.h>
@@ -26,6 +27,9 @@
extern "C" {
#endif
+#define RTE_MBUF_DYNFIELD3_CNT \
+ (RTE_MBUF_DYNFIELD3_SIZE / sizeof(uint64_t))
+
/*
* Packet Offload Features Flags. It also carry packet type information.
* Critical resources. Both rx/tx shared these bits. Be cautious on any change
@@ -686,8 +690,21 @@ struct __rte_cache_aligned rte_mbuf {
uint16_t timesync;
uint32_t dynfield1[9]; /**< Reserved for dynamic fields. */
+
+#if RTE_MBUF_DYNFIELD3_SIZE > 0
+ alignas(RTE_CACHE_LINE_SIZE)
+ uint64_t dynfield3[RTE_MBUF_DYNFIELD3_CNT];
+ /**< Reserved cache-line-aligned space for dynamic fields. */
+#endif /* RTE_MBUF_DYNFIELD3_SIZE > 0 */
};
+#if RTE_MBUF_DYNFIELD3_SIZE > 0
+#define RTE_MBUF_DYNFIELD3_OFFSET \
+ offsetof(struct rte_mbuf, dynfield3)
+#else
+#define RTE_MBUF_DYNFIELD3_OFFSET 0
+#endif
+
/**
* Function typedef of callback to free externally attached buffer.
*/
diff --git a/lib/mbuf/rte_mbuf_dyn.c b/lib/mbuf/rte_mbuf_dyn.c
index 5987c9dee8..b42fe6377d 100644
--- a/lib/mbuf/rte_mbuf_dyn.c
+++ b/lib/mbuf/rte_mbuf_dyn.c
@@ -135,6 +135,9 @@ init_shared_mem(void)
#if !RTE_IOVA_IN_MBUF
mark_free(dynfield2);
#endif
+#if RTE_MBUF_DYNFIELD3_SIZE > 0
+ mark_free(dynfield3);
+#endif
/* init free_flags */
for (mask = RTE_MBUF_F_FIRST_FREE; mask <= RTE_MBUF_F_LAST_FREE; mask <<= 1)
diff --git a/meson_options.txt b/meson_options.txt
index e28d24054c..579c434b9a 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -44,6 +44,10 @@ option('max_numa_nodes', type: 'string', value: 'default', description:
'Set the highest NUMA node supported by EAL; "default" is different per-arch, "detect" detects the highest NUMA node on the build machine.')
option('enable_iova_as_pa', type: 'boolean', value: true, description:
'Support the use of physical addresses for IO addresses, such as used by UIO or VFIO in no-IOMMU mode. When disabled, DPDK can only run with IOMMU support for address mappings, but will have more space available in the mbuf structure.')
+option('mbuf_dynfield3_size', type: 'integer', value: 0, description:
+ 'Size of optional extra mbuf dynamic field area, in bytes.')
+option('mbuf_dynfield3_copy', type: 'boolean', value: false, description:
+ 'Copy optional extra mbuf dynamic field area during mbuf copy/clone.')
option('mbuf_refcnt_atomic', type: 'boolean', value: true, description:
'Atomically access the mbuf refcnt.')
option('platform', type: 'string', value: 'native', description:
--
2.35.6
More information about the dev
mailing list