Thread (16 messages) flat view 16 messages, 7 authors, 19d ago

RE: [PATCH net v3 2/3] xsk: honor XDP_TX_METADATA in zero-copy path

From: Loktionov, Aleksandr <hidden>
Date: 2026-08-21 12:22:23
Also in: bpf, intel-wired-lan, linux-arm-kernel, linux-rdma, lkml

quoted hunk ↗ jump to hunk
-----Original Message-----
From: Stanislav Fomichev <redacted>
Sent: Wednesday, August 19, 2026 6:06 PM
To: netdev@vger.kernel.org
Cc: davem@davemloft.net; edumazet@google.com; kuba@kernel.org;
pabeni@redhat.com; Nguyen, Anthony L [off-list ref];
Kitszel, Przemyslaw [off-list ref];
andrew+netdev@lunn.ch; saeedm@nvidia.com; tariqt@nvidia.com;
mbloch@nvidia.com; maxime.chevallier@bootlin.com;
mcoquelin.stm32@gmail.com; alexandre.torgue@foss.st.com; Lobakin,
Aleksander [off-list ref]; horms@kernel.org; Karlsson,
Magnus [off-list ref]; Fijalkowski, Maciej
[off-list ref]; sdf@fomichev.me; ast@kernel.org;
daniel@iogearbox.net; hawk@kernel.org; john.fastabend@gmail.com;
guoren@kernel.org; dtatulea@nvidia.com; witu@nvidia.com;
martin.lau@kernel.org; Song, Yoong Siang [off-list ref];
intel-wired-lan@lists.osuosl.org; linux-kernel@vger.kernel.org; linux-
rdma@vger.kernel.org; linux-stm32@st-md-mailman.stormreply.com; linux-
arm-kernel@lists.infradead.org; bpf@vger.kernel.org; linux-
csky@vger.kernel.org; leon@kernel.org
Subject: [PATCH net v3 2/3] xsk: honor XDP_TX_METADATA in zero-copy
path

The zero-copy path reads TX metadata whenever the UMEM has metadata
space, even if the descriptor does not set XDP_TX_METADATA. Pass
descriptor options through the metadata helpers and ignore metadata
unless the option is set.

This does not fix the existing per-WQE metadata handling for mlx5
MPWQEs.
Only the descriptor that starts a session passes through
xsk_tx_metadata_request() and configures offload state shared by the
batch.
Metadata on descriptors joining an open session is therefore not
validated and does not configure its requested offloads. In addition,
a non-NULL metadata pointer from such a descriptor is treated as a
timestamp completion request even when XDP_TXMD_FLAGS_TIMESTAMP is not
set, so its metadata union can be overwritten with an unrequested
timestamp. Fixing mixed metadata states within one MPWQE requires a
separate change.

Fixes: 48eb03dd2630 ("xsk: Add TX timestamp and TX checksum offload
support")
Reviewed-by: Alexander Lobakin <aleksander.lobakin@intel.com>
Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
---
 drivers/net/ethernet/intel/igc/igc_main.c     |  3 ++-
 .../ethernet/mellanox/mlx5/core/en/xsk/tx.c   |  2 +-
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |  3 ++-
 include/net/libeth/xsk.h                      |  2 +-
 include/net/xdp_sock_drv.h                    | 22 +++++++++++-------
-
 include/net/xsk_buff_pool.h                   |  3 ++-
 net/xdp/xsk_buff_pool.c                       |  7 ++++--
 7 files changed, 26 insertions(+), 16 deletions(-)
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c
b/drivers/net/ethernet/intel/igc/igc_main.c
index 39043d8ca1bf..59067939a586 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -3074,7 +3074,8 @@ static void igc_xdp_xmit_zc(struct igc_ring
*ring)
 		olinfo_status = xdp_desc.len << IGC_ADVTXD_PAYLEN_SHIFT;

 		dma = xsk_buff_raw_get_dma(pool, xdp_desc.addr);
-		meta = xsk_buff_get_metadata(pool, xdp_desc.addr);
+		meta = xsk_buff_get_metadata(pool, xdp_desc.addr,
+					     xdp_desc.options);
 		xsk_buff_raw_dma_sync_for_device(pool, dma,
xdp_desc.len);
 		bi = &ring->tx_buffer_info[ntu];
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/tx.c
b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/tx.c
index 3d19dad8f868..d194eeddd7b5 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/tx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/tx.c
@@ -99,7 +99,7 @@ bool mlx5e_xsk_tx(struct mlx5e_xdpsq *sq, unsigned
int budget)
 		xdptxd.dma_addr = xsk_buff_raw_get_dma(pool, desc.addr);
 		xdptxd.data = xsk_buff_raw_get_data(pool, desc.addr);
 		xdptxd.len = desc.len;
-		meta = xsk_buff_get_metadata(pool, desc.addr);
+		meta = xsk_buff_get_metadata(pool, desc.addr,
desc.options);

 		xsk_buff_raw_dma_sync_for_device(pool, xdptxd.dma_addr,
xdptxd.len);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index a71f0df26378..62de03e65a90 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -2719,7 +2719,8 @@ static bool stmmac_xdp_xmit_zc(struct
stmmac_priv *priv, u32 queue, u32 budget)

 		tx_desc = stmmac_get_tx_desc(priv, tx_q, entry);
 		dma_addr = xsk_buff_raw_get_dma(pool, xdp_desc.addr);
-		meta = xsk_buff_get_metadata(pool, xdp_desc.addr);
+		meta = xsk_buff_get_metadata(pool, xdp_desc.addr,
+					     xdp_desc.options);
 		xsk_buff_raw_dma_sync_for_device(pool, dma_addr,
xdp_desc.len);

 		/* To return XDP buffer to XSK pool, we simple call diff
--git a/include/net/libeth/xsk.h b/include/net/libeth/xsk.h index
5dcc0d7f65b7..a452b7828ce4 100644
--- a/include/net/libeth/xsk.h
+++ b/include/net/libeth/xsk.h
@@ -196,7 +196,7 @@ __libeth_xsk_xmit_fill_buf_md(const struct
xdp_desc *xdesc,
 	struct libeth_xdp_tx_desc desc;
 	struct xdp_desc_ctx ctx;

-	ctx = xsk_buff_raw_get_ctx(sq->pool, xdesc->addr);
+	ctx = xsk_buff_raw_get_ctx(sq->pool, xdesc->addr, xdesc-
quoted
options);
 	desc = (typeof(desc)){
 		.addr	= ctx.dma,
 		__libeth_xdp_tx_len(xdesc->len),
diff --git a/include/net/xdp_sock_drv.h b/include/net/xdp_sock_drv.h
index b344789f5df8..d94aeb506379 100644
--- a/include/net/xdp_sock_drv.h
+++ b/include/net/xdp_sock_drv.h
@@ -240,6 +240,7 @@ static inline void *xsk_buff_raw_get_data(struct
xsk_buff_pool *pool, u64 addr)
  * xsk_buff_raw_get_ctx - get &xdp_desc context
  * @pool: XSk buff pool desc address belongs to
  * @addr: desc address (from userspace)
+ * @options: desc options (from userspace)
  *
  * Wrapper for xp_raw_get_ctx() to be used in drivers, see its kdoc
for
  * details.
@@ -248,9 +249,9 @@ static inline void *xsk_buff_raw_get_data(struct
xsk_buff_pool *pool, u64 addr)
  * pointer, if it is present (initialized to %NULL otherwise).
  */
 static inline struct xdp_desc_ctx
-xsk_buff_raw_get_ctx(const struct xsk_buff_pool *pool, u64 addr)
+xsk_buff_raw_get_ctx(const struct xsk_buff_pool *pool, u64 addr, u32
+options)
 {
-	return xp_raw_get_ctx(pool, addr);
+	return xp_raw_get_ctx(pool, addr, options);
 }

 #define XDP_TXMD_FLAGS_VALID ( \
@@ -318,18 +319,20 @@ xsk_tx_metadata_request(const struct
xsk_buff_pool *pool,  }

 static inline struct xsk_tx_metadata *
-__xsk_buff_get_metadata(const struct xsk_buff_pool *pool, void *data)
+__xsk_buff_get_metadata(const struct xsk_buff_pool *pool, void *data,
+			unsigned int options)
 {
-	if (!pool->tx_metadata_len)
+	if (!pool->tx_metadata_len || !(options & XDP_TX_METADATA))
 		return NULL;

 	return data - pool->tx_metadata_len;
 }

 static inline struct xsk_tx_metadata *
-xsk_buff_get_metadata(struct xsk_buff_pool *pool, u64 addr)
+xsk_buff_get_metadata(struct xsk_buff_pool *pool, u64 addr, u32
+options)
 {
-	return __xsk_buff_get_metadata(pool, xp_raw_get_data(pool,
addr));
+	return __xsk_buff_get_metadata(pool, xp_raw_get_data(pool,
addr),
+				       options);
 }

 static inline void xsk_buff_dma_sync_for_cpu(struct xdp_buff *xdp) @@
-510,7 +513,7 @@ static inline void *xsk_buff_raw_get_data(struct
xsk_buff_pool *pool, u64 addr)  }

 static inline struct xdp_desc_ctx
-xsk_buff_raw_get_ctx(const struct xsk_buff_pool *pool, u64 addr)
+xsk_buff_raw_get_ctx(const struct xsk_buff_pool *pool, u64 addr, u32
+options)
 {
 	return (struct xdp_desc_ctx){ };
 }
@@ -530,13 +533,14 @@ xsk_tx_metadata_request(const struct
xsk_buff_pool *pool,  }

 static inline struct xsk_tx_metadata *
-__xsk_buff_get_metadata(const struct xsk_buff_pool *pool, void *data)
+__xsk_buff_get_metadata(const struct xsk_buff_pool *pool, void *data,
+			unsigned int options)
 {
 	return NULL;
 }

 static inline struct xsk_tx_metadata *
-xsk_buff_get_metadata(struct xsk_buff_pool *pool, u64 addr)
+xsk_buff_get_metadata(struct xsk_buff_pool *pool, u64 addr, u32
+options)
 {
 	return NULL;
 }
diff --git a/include/net/xsk_buff_pool.h b/include/net/xsk_buff_pool.h
index 2bb1d122b1bc..a7df573784fd 100644
--- a/include/net/xsk_buff_pool.h
+++ b/include/net/xsk_buff_pool.h
@@ -154,7 +154,8 @@ struct xdp_desc_ctx {
 	struct xsk_tx_metadata *meta;
 };

-struct xdp_desc_ctx xp_raw_get_ctx(const struct xsk_buff_pool *pool,
u64 addr);
+struct xdp_desc_ctx xp_raw_get_ctx(const struct xsk_buff_pool *pool,
u64 addr,
+				   u32 options);

 static inline dma_addr_t xp_get_dma(struct xdp_buff_xsk *xskb)  {
diff --git a/net/xdp/xsk_buff_pool.c b/net/xdp/xsk_buff_pool.c index
78c14f106395..9d2d94f1fb75 100644
--- a/net/xdp/xsk_buff_pool.c
+++ b/net/xdp/xsk_buff_pool.c
@@ -763,6 +763,7 @@ EXPORT_SYMBOL(xp_raw_get_dma);
  * xp_raw_get_ctx - get &xdp_desc context
  * @pool: XSk buff pool desc address belongs to
  * @addr: desc address (from userspace)
+ * @options: desc options (from userspace)
  *
  * Helper for getting desc's DMA address and metadata pointer, if
present.
  * Saves one call on hotpath and double calculation of the actual
address.
@@ -771,14 +772,16 @@ EXPORT_SYMBOL(xp_raw_get_dma);
  * Return: new &xdp_desc_ctx struct containing desc's DMA address and
metadata
  * pointer, if it is present (initialized to %NULL otherwise).
  */
-struct xdp_desc_ctx xp_raw_get_ctx(const struct xsk_buff_pool *pool,
u64 addr)
+struct xdp_desc_ctx xp_raw_get_ctx(const struct xsk_buff_pool *pool,
u64 addr,
+				   u32 options)
 {
 	struct xdp_desc_ctx ret;

 	addr = __xp_raw_get_addr(pool, addr);

 	ret.dma = __xp_raw_get_dma(pool, addr);
-	ret.meta = __xsk_buff_get_metadata(pool,
__xp_raw_get_data(pool, addr));
+	ret.meta = __xsk_buff_get_metadata(pool,
__xp_raw_get_data(pool, addr),
+					   options);

 	return ret;
 }
--
2.53.0-Meta
Reviewed-by: Aleksandr Loktionov <redacted>
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help