From: Randy L Tice <[email protected]>
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_cnt Meson option sets RTE_MBUF_DYNFIELD3_CNT in
rte_build_config.h. A non-zero value enables the extra area.

When enabled, dynfield3 is made available to the mbuf dynamic field
allocator and is copied by the generic mbuf dynamic-field copy helper.
This extends the existing Dynamic Mbuf Fields backing storage without
changing the default mbuf layout.

Validate that the configured element count is non-negative and that the
reserved space is a multiple of the cache line size.

Signed-off-by: Randy L Tice <[email protected]>
---
 app/test/test_mbuf.c                   |  5 +++--
 config/meson.build                     | 10 ++++++++++
 doc/guides/rel_notes/release_26_11.rst | 15 +++++++++++++++
 lib/mbuf/rte_mbuf.h                    |  3 +++
 lib/mbuf/rte_mbuf_core.h               | 16 ++++++++++++++++
 lib/mbuf/rte_mbuf_dyn.c                |  3 +++
 meson_options.txt                      |  2 ++
 7 files changed, 52 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..e500a7b075 100644
--- a/config/meson.build
+++ b/config/meson.build
@@ -384,6 +384,11 @@ 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_cnt = get_option('mbuf_dynfield3_cnt')
+if mbuf_dynfield3_cnt < 0
+    error('mbuf_dynfield3_cnt must be greater than or equal to 0')
+endif
+dpdk_conf.set('RTE_MBUF_DYNFIELD3_CNT', mbuf_dynfield3_cnt)
 # 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 +400,11 @@ dpdk_conf.set10('RTE_IOVA_IN_MBUF', 
get_option('enable_iova_as_pa'))
 
 compile_time_cpuflags = []
 subdir(arch_subdir)
+mbuf_dynfield3_size = mbuf_dynfield3_cnt * cc.sizeof('uintptr_t',
+        prefix: '#include <stdint.h>')
+if mbuf_dynfield3_size % dpdk_conf.get('RTE_CACHE_LINE_SIZE') != 0
+    error('mbuf_dynfield3_cnt must reserve 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..abe82e7e3f 100644
--- a/doc/guides/rel_notes/release_26_11.rst
+++ b/doc/guides/rel_notes/release_26_11.rst
@@ -60,6 +60,13 @@ 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_cnt`` build option to reserve a
+  cache-line-aligned ``dynfield3`` area in ``struct rte_mbuf``.
+  The value is defined as ``RTE_MBUF_DYNFIELD3_CNT`` in
+  ``rte_build_config.h``; a non-zero value enables the extra area.
+
 * **Added TPID support to VLAN tag insertion.**
 
   Added ``rte_vlan_insert_tpid()`` to the net library.
@@ -338,6 +345,14 @@ Known Issues
    Also, make sure to start the actual text at the margin.
    =======================================================
 
+* **Some drivers may require changes for enlarged mbufs.**
+
+  Enabling ``mbuf_dynfield3_cnt`` with a non-zero value increases
+  ``sizeof(struct rte_mbuf)``. Drivers or applications that assume a
+  fixed mbuf size may require follow-up changes. The
+  ``mempool/octeontx`` driver currently asserts that
+  ``sizeof(struct rte_mbuf)`` does not exceed its fixed buffer offset.
+
 
 Tested Platforms
 ----------------
diff --git a/lib/mbuf/rte_mbuf.h b/lib/mbuf/rte_mbuf.h
index 60ec8158cd..6a567a9e43 100644
--- a/lib/mbuf/rte_mbuf.h
+++ b/lib/mbuf/rte_mbuf.h
@@ -1231,6 +1231,9 @@ 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_CNT > 0
+       memcpy(&mdst->dynfield3, msrc->dynfield3, sizeof(mdst->dynfield3));
+#endif
 }
 
 /* internal */
diff --git a/lib/mbuf/rte_mbuf_core.h b/lib/mbuf/rte_mbuf_core.h
index 98b0bd9ca7..bb57397bb6 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>
@@ -686,8 +687,23 @@ struct __rte_cache_aligned rte_mbuf {
        uint16_t timesync;
 
        uint32_t dynfield1[9]; /**< Reserved for dynamic fields. */
+
+#if RTE_MBUF_DYNFIELD3_CNT > 0
+       alignas(RTE_CACHE_LINE_SIZE)
+       uintptr_t dynfield3[RTE_MBUF_DYNFIELD3_CNT];
+       /**< Reserved for dynamic fields. */
+#endif /* RTE_MBUF_DYNFIELD3_CNT > 0 */
 };
 
+#define RTE_MBUF_DYNFIELD3_SIZE \
+       (RTE_MBUF_DYNFIELD3_CNT * sizeof(uintptr_t))
+#if RTE_MBUF_DYNFIELD3_CNT > 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..dcbe0a8416 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_CNT > 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..337f9e5e49 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -44,6 +44,8 @@ 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_cnt', type: 'integer', value: 0, description:
+       'Size of optional extra mbuf dynamic field area, in uintptr_t units.')
 option('mbuf_refcnt_atomic', type: 'boolean', value: true, description:
        'Atomically access the mbuf refcnt.')
 option('platform', type: 'string', value: 'native', description:
-- 
2.35.6

Reply via email to