This is very close to what I suggested you explore.
But one piece is missing:
Registering fields in this metadata area should be managed through the dynamic mbuf fields API.
Without a central registry, only one module can use the new metadata area; it cannot be used by multiple modules without coordination.
And instead of rolling your own registry of fields in the metadata area, just reuse the dynamic mbuf fields machinery.
I agree with your proposed mbuf layout.
There will be a performance cost for accessing the mbuf private data: rte_mbuf_to_priv() will change from adding a simple constant offset (sizeof(struct rte_mbuf)) to adding the value of a global variable holding the offset, reflecting the startup-time configured metadata area size.
The global variable will be hot in the cache when working on mbuf bursts, so I think this performance cost will be insignificant.
Venlig hilsen / Kind regards,
-Morten Brørup
From: Randy Tice (rtice) [mailto:rtice@cisco.com]
Sent: Tuesday, 29 September 2026 16.45
To: Konstantin Ananyev; Morten Brørup; dev@dpdk.org
Cc: Bruce Richardson; Harman Kalra; Stephen Hemminger
Subject: Re: [PATCH v3 1/1] mbuf: add optional no-copy dynamic field storage
Hi all,
Thanks for the discussion. We are now where I had hoped we’d get to during
RFC but we are here.
Konstantin, I understand your concern about making sizeof(struct rte_mbuf)
depend on a build-time option. That can create different mbuf layouts between
DPDK builds that otherwise present the same ABI/version, which is not a good
property for a core public structure.
After thinking through this again, I think the current patch may be trying too
hard to make this a dynamic-field allocator feature. The actual requirement is
simpler: a fixed global per-mbuf metadata area that is present in every
pktmbuf object, separate from ordinary application private data, and not
copied by mbuf copy/clone helpers.
The mbuf structure change would look roughly like this:
struct rte_mbuf {
...
uint32_t dynfield1[9]; /**< Reserved for dynamic fields. */
+
+ alignas(RTE_CACHE_LINE_SIZE)
+ uint8_t metadata[];
+ /**< Optional cache-line-aligned per-mbuf metadata area. */
};
Since this is a flexible array member, it does not change sizeof(struct
rte_mbuf). The object layout would become:
struct rte_mbuf fixed header
global per-mbuf metadata area
application private data
packet data buffer
With that layout, this could be sized at EAL init time rather than by a build
option, for example:
--mbuf-metadata-size=256
That avoids creating different DPDK builds with different mbuf struct sizes or
different build-time ABI expectations. The configured size would be part of
the process/runtime configuration instead of requiring applications,
libraries, and package providers to agree on a compile-time define.
The official mbuf helpers would account for this area before ordinary
priv_size, so application private data remains available and does not overlap
with the global metadata area.
This would also avoid changing the existing dynamic-field allocator and copy
semantics. The area would not be part of the dynamic-field registry; it would
be explicit per-mbuf metadata storage for applications that deliberately
enable it.
That seems to address the main concerns:
- sizeof(struct rte_mbuf) remains fixed for ABI purposes.
- the metadata area is globally present across pktmbuf pools when enabled.
- ordinary priv_size remains separate and available.
- dynamic-field allocator/copy behavior remains unchanged.
- users that do not enable the EAL option pay no extra per-mbuf storage cost.
- applications do not need to be built against a different mbuf-size define.
If this direction is acceptable, I can take a look at what it means in
practice for EAL configuration, mbuf layout helpers, pool constructors, and
places that currently do direct object-layout math.
Thanks,
-rt