Skip to content

Commit 7f0b763

Browse files
author
Paolo Abeni
committed
Merge branch 'net-xdp-handle-frags-with-unreadable-memory'
Jakub Kicinski says: ==================== net: xdp: handle frags with unreadable memory Make XDP helpers compatible with unreadable memory. This is very similar to how we handle pfmemalloc frags today. Record the info in xdp_buf flags as frags get added and then update the skb once allocated. This series adds the unreadable memory metadata tracking to drivers using xdp_build_skb_from*() with no changes on the driver side - hence the only driver changes here are refactoring. Obviously, unreadable memory is incompatible with XDP today, but thanks to xdp_build_skb_from_buf() increasing number of drivers have a unified datapath, whether XDP is enabled or not. RFC: https://lore.kernel.org/20250812161528.835855-1-kuba@kernel.org ==================== Link: https://patch.msgid.link/20250905221539.2930285-1-kuba@kernel.org Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2 parents db1b600 + 6bffdc0 commit 7f0b763

File tree

8 files changed

+68
-63
lines changed

8 files changed

+68
-63
lines changed

drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -468,9 +468,8 @@ bnxt_xdp_build_skb(struct bnxt *bp, struct sk_buff *skb, u8 num_frags,
468468
if (!skb)
469469
return NULL;
470470

471-
xdp_update_skb_shared_info(skb, num_frags,
472-
sinfo->xdp_frags_size,
473-
BNXT_RX_PAGE_SIZE * num_frags,
474-
xdp_buff_is_frag_pfmemalloc(xdp));
471+
xdp_update_skb_frags_info(skb, num_frags, sinfo->xdp_frags_size,
472+
BNXT_RX_PAGE_SIZE * num_frags,
473+
xdp_buff_get_skb_flags(xdp));
475474
return skb;
476475
}

drivers/net/ethernet/intel/i40e/i40e_txrx.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2151,10 +2151,10 @@ static struct sk_buff *i40e_construct_skb(struct i40e_ring *rx_ring,
21512151
memcpy(&skinfo->frags[skinfo->nr_frags], &sinfo->frags[0],
21522152
sizeof(skb_frag_t) * nr_frags);
21532153

2154-
xdp_update_skb_shared_info(skb, skinfo->nr_frags + nr_frags,
2155-
sinfo->xdp_frags_size,
2156-
nr_frags * xdp->frame_sz,
2157-
xdp_buff_is_frag_pfmemalloc(xdp));
2154+
xdp_update_skb_frags_info(skb, skinfo->nr_frags + nr_frags,
2155+
sinfo->xdp_frags_size,
2156+
nr_frags * xdp->frame_sz,
2157+
xdp_buff_get_skb_flags(xdp));
21582158

21592159
/* First buffer has already been processed, so bump ntc */
21602160
if (++rx_ring->next_to_clean == rx_ring->count)
@@ -2206,10 +2206,9 @@ static struct sk_buff *i40e_build_skb(struct i40e_ring *rx_ring,
22062206
skb_metadata_set(skb, metasize);
22072207

22082208
if (unlikely(xdp_buff_has_frags(xdp))) {
2209-
xdp_update_skb_shared_info(skb, nr_frags,
2210-
sinfo->xdp_frags_size,
2211-
nr_frags * xdp->frame_sz,
2212-
xdp_buff_is_frag_pfmemalloc(xdp));
2209+
xdp_update_skb_frags_info(skb, nr_frags, sinfo->xdp_frags_size,
2210+
nr_frags * xdp->frame_sz,
2211+
xdp_buff_get_skb_flags(xdp));
22132212

22142213
i40e_process_rx_buffs(rx_ring, I40E_XDP_PASS, xdp);
22152214
} else {

drivers/net/ethernet/intel/ice/ice_txrx.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,10 +1035,9 @@ ice_build_skb(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp)
10351035
skb_metadata_set(skb, metasize);
10361036

10371037
if (unlikely(xdp_buff_has_frags(xdp)))
1038-
xdp_update_skb_shared_info(skb, nr_frags,
1039-
sinfo->xdp_frags_size,
1040-
nr_frags * xdp->frame_sz,
1041-
xdp_buff_is_frag_pfmemalloc(xdp));
1038+
xdp_update_skb_frags_info(skb, nr_frags, sinfo->xdp_frags_size,
1039+
nr_frags * xdp->frame_sz,
1040+
xdp_buff_get_skb_flags(xdp));
10421041

10431042
return skb;
10441043
}
@@ -1115,10 +1114,10 @@ ice_construct_skb(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp)
11151114
memcpy(&skinfo->frags[skinfo->nr_frags], &sinfo->frags[0],
11161115
sizeof(skb_frag_t) * nr_frags);
11171116

1118-
xdp_update_skb_shared_info(skb, skinfo->nr_frags + nr_frags,
1119-
sinfo->xdp_frags_size,
1120-
nr_frags * xdp->frame_sz,
1121-
xdp_buff_is_frag_pfmemalloc(xdp));
1117+
xdp_update_skb_frags_info(skb, skinfo->nr_frags + nr_frags,
1118+
sinfo->xdp_frags_size,
1119+
nr_frags * xdp->frame_sz,
1120+
xdp_buff_get_skb_flags(xdp));
11221121
}
11231122

11241123
return skb;

drivers/net/ethernet/marvell/mvneta.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2416,10 +2416,9 @@ mvneta_swbm_build_skb(struct mvneta_port *pp, struct page_pool *pool,
24162416
skb->ip_summed = mvneta_rx_csum(pp, desc_status);
24172417

24182418
if (unlikely(xdp_buff_has_frags(xdp)))
2419-
xdp_update_skb_shared_info(skb, num_frags,
2420-
sinfo->xdp_frags_size,
2421-
num_frags * xdp->frame_sz,
2422-
xdp_buff_is_frag_pfmemalloc(xdp));
2419+
xdp_update_skb_frags_info(skb, num_frags, sinfo->xdp_frags_size,
2420+
num_frags * xdp->frame_sz,
2421+
xdp_buff_get_skb_flags(xdp));
24232422

24242423
return skb;
24252424
}

drivers/net/ethernet/mellanox/mlx5/core/en_rx.c

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1796,10 +1796,9 @@ mlx5e_skb_from_cqe_nonlinear(struct mlx5e_rq *rq, struct mlx5e_wqe_frag_info *wi
17961796

17971797
if (xdp_buff_has_frags(&mxbuf->xdp)) {
17981798
/* sinfo->nr_frags is reset by build_skb, calculate again. */
1799-
xdp_update_skb_shared_info(skb, wi - head_wi - 1,
1800-
sinfo->xdp_frags_size, truesize,
1801-
xdp_buff_is_frag_pfmemalloc(
1802-
&mxbuf->xdp));
1799+
xdp_update_skb_frags_info(skb, wi - head_wi - 1,
1800+
sinfo->xdp_frags_size, truesize,
1801+
xdp_buff_get_skb_flags(&mxbuf->xdp));
18031802

18041803
for (struct mlx5e_wqe_frag_info *pwi = head_wi + 1; pwi < wi; pwi++)
18051804
pwi->frag_page->frags++;
@@ -2105,10 +2104,10 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w
21052104
struct mlx5e_frag_page *pagep;
21062105

21072106
/* sinfo->nr_frags is reset by build_skb, calculate again. */
2108-
xdp_update_skb_shared_info(skb, frag_page - head_page,
2109-
sinfo->xdp_frags_size, truesize,
2110-
xdp_buff_is_frag_pfmemalloc(
2111-
&mxbuf->xdp));
2107+
xdp_update_skb_frags_info(skb, frag_page - head_page,
2108+
sinfo->xdp_frags_size,
2109+
truesize,
2110+
xdp_buff_get_skb_flags(&mxbuf->xdp));
21122111

21132112
pagep = head_page;
21142113
do
@@ -2122,10 +2121,10 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w
21222121
if (xdp_buff_has_frags(&mxbuf->xdp)) {
21232122
struct mlx5e_frag_page *pagep;
21242123

2125-
xdp_update_skb_shared_info(skb, sinfo->nr_frags,
2126-
sinfo->xdp_frags_size, truesize,
2127-
xdp_buff_is_frag_pfmemalloc(
2128-
&mxbuf->xdp));
2124+
xdp_update_skb_frags_info(skb, sinfo->nr_frags,
2125+
sinfo->xdp_frags_size,
2126+
truesize,
2127+
xdp_buff_get_skb_flags(&mxbuf->xdp));
21292128

21302129
pagep = frag_page - sinfo->nr_frags;
21312130
do

drivers/net/virtio_net.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2185,10 +2185,9 @@ static struct sk_buff *build_skb_from_xdp_buff(struct net_device *dev,
21852185
skb_metadata_set(skb, metasize);
21862186

21872187
if (unlikely(xdp_buff_has_frags(xdp)))
2188-
xdp_update_skb_shared_info(skb, nr_frags,
2189-
sinfo->xdp_frags_size,
2190-
xdp_frags_truesz,
2191-
xdp_buff_is_frag_pfmemalloc(xdp));
2188+
xdp_update_skb_frags_info(skb, nr_frags, sinfo->xdp_frags_size,
2189+
xdp_frags_truesz,
2190+
xdp_buff_get_skb_flags(xdp));
21922191

21932192
return skb;
21942193
}

include/net/xdp.h

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ enum xdp_buff_flags {
7676
XDP_FLAGS_FRAGS_PF_MEMALLOC = BIT(1), /* xdp paged memory is under
7777
* pressure
7878
*/
79+
/* frags have unreadable mem, this can't be true for real XDP packets,
80+
* but drivers may use XDP helpers to construct Rx pkt state even when
81+
* XDP program is not attached.
82+
*/
83+
XDP_FLAGS_FRAGS_UNREADABLE = BIT(2),
7984
};
8085

8186
struct xdp_buff {
@@ -116,15 +121,19 @@ static __always_inline void xdp_buff_clear_frags_flag(struct xdp_buff *xdp)
116121
xdp->flags &= ~XDP_FLAGS_HAS_FRAGS;
117122
}
118123

119-
static __always_inline bool
120-
xdp_buff_is_frag_pfmemalloc(const struct xdp_buff *xdp)
124+
static __always_inline void xdp_buff_set_frag_pfmemalloc(struct xdp_buff *xdp)
121125
{
122-
return !!(xdp->flags & XDP_FLAGS_FRAGS_PF_MEMALLOC);
126+
xdp->flags |= XDP_FLAGS_FRAGS_PF_MEMALLOC;
123127
}
124128

125-
static __always_inline void xdp_buff_set_frag_pfmemalloc(struct xdp_buff *xdp)
129+
static __always_inline void xdp_buff_set_frag_unreadable(struct xdp_buff *xdp)
126130
{
127-
xdp->flags |= XDP_FLAGS_FRAGS_PF_MEMALLOC;
131+
xdp->flags |= XDP_FLAGS_FRAGS_UNREADABLE;
132+
}
133+
134+
static __always_inline u32 xdp_buff_get_skb_flags(const struct xdp_buff *xdp)
135+
{
136+
return xdp->flags;
128137
}
129138

130139
static __always_inline void
@@ -271,6 +280,8 @@ static inline bool xdp_buff_add_frag(struct xdp_buff *xdp, netmem_ref netmem,
271280

272281
if (unlikely(netmem_is_pfmemalloc(netmem)))
273282
xdp_buff_set_frag_pfmemalloc(xdp);
283+
if (unlikely(netmem_is_net_iov(netmem)))
284+
xdp_buff_set_frag_unreadable(xdp);
274285

275286
return true;
276287
}
@@ -294,10 +305,10 @@ static __always_inline bool xdp_frame_has_frags(const struct xdp_frame *frame)
294305
return !!(frame->flags & XDP_FLAGS_HAS_FRAGS);
295306
}
296307

297-
static __always_inline bool
298-
xdp_frame_is_frag_pfmemalloc(const struct xdp_frame *frame)
308+
static __always_inline u32
309+
xdp_frame_get_skb_flags(const struct xdp_frame *frame)
299310
{
300-
return !!(frame->flags & XDP_FLAGS_FRAGS_PF_MEMALLOC);
311+
return frame->flags;
301312
}
302313

303314
#define XDP_BULK_QUEUE_SIZE 16
@@ -334,9 +345,9 @@ static inline void xdp_scrub_frame(struct xdp_frame *frame)
334345
}
335346

336347
static inline void
337-
xdp_update_skb_shared_info(struct sk_buff *skb, u8 nr_frags,
338-
unsigned int size, unsigned int truesize,
339-
bool pfmemalloc)
348+
xdp_update_skb_frags_info(struct sk_buff *skb, u8 nr_frags,
349+
unsigned int size, unsigned int truesize,
350+
u32 xdp_flags)
340351
{
341352
struct skb_shared_info *sinfo = skb_shinfo(skb);
342353

@@ -350,7 +361,8 @@ xdp_update_skb_shared_info(struct sk_buff *skb, u8 nr_frags,
350361
skb->len += size;
351362
skb->data_len += size;
352363
skb->truesize += truesize;
353-
skb->pfmemalloc |= pfmemalloc;
364+
skb->pfmemalloc |= !!(xdp_flags & XDP_FLAGS_FRAGS_PF_MEMALLOC);
365+
skb->unreadable |= !!(xdp_flags & XDP_FLAGS_FRAGS_UNREADABLE);
354366
}
355367

356368
/* Avoids inlining WARN macro in fast-path */

net/core/xdp.c

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -663,9 +663,8 @@ struct sk_buff *xdp_build_skb_from_buff(const struct xdp_buff *xdp)
663663
u32 tsize;
664664

665665
tsize = sinfo->xdp_frags_truesize ? : nr_frags * xdp->frame_sz;
666-
xdp_update_skb_shared_info(skb, nr_frags,
667-
sinfo->xdp_frags_size, tsize,
668-
xdp_buff_is_frag_pfmemalloc(xdp));
666+
xdp_update_skb_frags_info(skb, nr_frags, sinfo->xdp_frags_size,
667+
tsize, xdp_buff_get_skb_flags(xdp));
669668
}
670669

671670
skb->protocol = eth_type_trans(skb, rxq->dev);
@@ -692,7 +691,7 @@ static noinline bool xdp_copy_frags_from_zc(struct sk_buff *skb,
692691
struct skb_shared_info *sinfo = skb_shinfo(skb);
693692
const struct skb_shared_info *xinfo;
694693
u32 nr_frags, tsize = 0;
695-
bool pfmemalloc = false;
694+
u32 flags = 0;
696695

697696
xinfo = xdp_get_shared_info_from_buff(xdp);
698697
nr_frags = xinfo->nr_frags;
@@ -714,11 +713,12 @@ static noinline bool xdp_copy_frags_from_zc(struct sk_buff *skb,
714713
__skb_fill_page_desc_noacc(sinfo, i, page, offset, len);
715714

716715
tsize += truesize;
717-
pfmemalloc |= page_is_pfmemalloc(page);
716+
if (page_is_pfmemalloc(page))
717+
flags |= XDP_FLAGS_FRAGS_PF_MEMALLOC;
718718
}
719719

720-
xdp_update_skb_shared_info(skb, nr_frags, xinfo->xdp_frags_size,
721-
tsize, pfmemalloc);
720+
xdp_update_skb_frags_info(skb, nr_frags, xinfo->xdp_frags_size, tsize,
721+
flags);
722722

723723
return true;
724724
}
@@ -823,10 +823,9 @@ struct sk_buff *__xdp_build_skb_from_frame(struct xdp_frame *xdpf,
823823
skb_metadata_set(skb, xdpf->metasize);
824824

825825
if (unlikely(xdp_frame_has_frags(xdpf)))
826-
xdp_update_skb_shared_info(skb, nr_frags,
827-
sinfo->xdp_frags_size,
828-
nr_frags * xdpf->frame_sz,
829-
xdp_frame_is_frag_pfmemalloc(xdpf));
826+
xdp_update_skb_frags_info(skb, nr_frags, sinfo->xdp_frags_size,
827+
nr_frags * xdpf->frame_sz,
828+
xdp_frame_get_skb_flags(xdpf));
830829

831830
/* Essential SKB info: protocol and skb->dev */
832831
skb->protocol = eth_type_trans(skb, dev);

0 commit comments

Comments
 (0)