From 6d9b7c85af57305ec2bd5907124478867edcc60b Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 2 Nov 2026 12:46:04 +0100 Subject: [PATCH] net: stmmac: set XDP metadata length on the page_pool RX path stmmac_rx() initializes the XDP buffer with the metadata area valid, so an XDP program can reserve metadata with bpf_xdp_adjust_meta() and write it in [xdp->data_meta, xdp->data), for example to export the RX hardware timestamp obtained from the metadata kfunc. When such a frame is passed to the stack, the skb is built in place around the same page with napi_build_skb(), but skb_metadata_set() is never called. napi_build_skb() clears skb_shared_info up to dataref, which includes meta_len, so skb_metadata_len() stays zero. The stack and TC BPF then see an empty metadata range even though the bytes are present in the skb headroom. The AF_XDP zero-copy path already records the length in stmmac_construct_skb_zc(). Record the metadata length after reserving the headroom and adding the frame data. No copy is needed because the skb is built over the buffer the XDP program wrote to. With the length recorded, the software VLAN stripping path can move the metadata together with the MAC header, as it already does for zero-copy frames. Fixes: e3f9c3e34840 ("net: stmmac: add Rx HWTS metadata to XDP receive pkt") Signed-off-by: Lorenzo Bianconi Reviewed-by: Daniel Machon Reviewed-by: Nicolai Buchwitz Reviewed-by: Maxime Chevallier Link: https://patch.msgid.link/20261102-stmmac_meatada_pp_path-v1-1-d93cc4f9a864@oss.qualcomm.com Signed-off-by: Paolo Abeni --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 7ffed295eb14..a2177777727e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -6017,7 +6017,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) } if (!skb) { - unsigned int head_pad_len; + unsigned int metasize; /* XDP program may expand or reduce tail */ buf1_len = ctx.xdp.data_end - ctx.xdp.data; @@ -6034,10 +6034,14 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) } /* XDP program may adjust header */ - head_pad_len = ctx.xdp.data - ctx.xdp.data_hard_start; - skb_reserve(skb, head_pad_len); + skb_reserve(skb, + ctx.xdp.data - ctx.xdp.data_hard_start); skb_put(skb, buf1_len); skb_mark_for_recycle(skb); + + metasize = ctx.xdp.data - ctx.xdp.data_meta; + if (metasize) + skb_metadata_set(skb, metasize); buf->page = NULL; } else if (buf1_len) { dma_sync_single_for_cpu(priv->device, buf->addr,