Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

xsk: avoid double checking against rx queue being full

Currently non-zc xsk rx path for multi-buffer case checks twice if xsk
rx queue has enough space for producing descriptors:
1.
if (xskq_prod_nb_free(xs->rx, num_desc) < num_desc) {
xs->rx_queue_full++;
return -ENOBUFS;
}
2.
__xsk_rcv_zc(xs, xskb, copied - meta_len, rem ? XDP_PKT_CONTD : 0);
-> err = xskq_prod_reserve_desc(xs->rx, addr, len, flags);
-> if (xskq_prod_is_full(q))

Second part is redundant as in 1. we already peeked onto rx queue and
checked that there is enough space to produce given amount of
descriptors.

Provide helper functions that will skip it and therefore optimize code.

Signed-off-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
Acked-by: Stanislav Fomichev <sdf@fomichev.me>
Reviewed-by: Jason Xing <kerneljasonxing@gmail.com>
Link: https://lore.kernel.org/r/20260218150000.301176-1-maciej.fijalkowski@intel.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Maciej Fijalkowski and committed by
Alexei Starovoitov
f620af11 8ebfe65e

+24 -6
+13 -1
net/xdp/xsk.c
··· 160 160 return 0; 161 161 } 162 162 163 + static void __xsk_rcv_zc_safe(struct xdp_sock *xs, struct xdp_buff_xsk *xskb, 164 + u32 len, u32 flags) 165 + { 166 + u64 addr; 167 + 168 + addr = xp_get_handle(xskb, xskb->pool); 169 + __xskq_prod_reserve_desc(xs->rx, addr, len, flags); 170 + 171 + xp_release(xskb); 172 + } 173 + 163 174 static int xsk_rcv_zc(struct xdp_sock *xs, struct xdp_buff *xdp, u32 len) 164 175 { 165 176 struct xdp_buff_xsk *xskb = container_of(xdp, struct xdp_buff_xsk, xdp); ··· 303 292 rem -= copied; 304 293 305 294 xskb = container_of(xsk_xdp, struct xdp_buff_xsk, xdp); 306 - __xsk_rcv_zc(xs, xskb, copied - meta_len, rem ? XDP_PKT_CONTD : 0); 295 + __xsk_rcv_zc_safe(xs, xskb, copied - meta_len, 296 + rem ? XDP_PKT_CONTD : 0); 307 297 meta_len = 0; 308 298 } while (rem); 309 299
+11 -5
net/xdp/xsk_queue.h
··· 445 445 q->cached_prod = cached_prod; 446 446 } 447 447 448 - static inline int xskq_prod_reserve_desc(struct xsk_queue *q, 449 - u64 addr, u32 len, u32 flags) 448 + static inline void __xskq_prod_reserve_desc(struct xsk_queue *q, 449 + u64 addr, u32 len, u32 flags) 450 450 { 451 451 struct xdp_rxtx_ring *ring = (struct xdp_rxtx_ring *)q->ring; 452 452 u32 idx; 453 - 454 - if (xskq_prod_is_full(q)) 455 - return -ENOBUFS; 456 453 457 454 /* A, matches D */ 458 455 idx = q->cached_prod++ & q->ring_mask; 459 456 ring->desc[idx].addr = addr; 460 457 ring->desc[idx].len = len; 461 458 ring->desc[idx].options = flags; 459 + } 460 + 461 + static inline int xskq_prod_reserve_desc(struct xsk_queue *q, 462 + u64 addr, u32 len, u32 flags) 463 + { 464 + if (xskq_prod_is_full(q)) 465 + return -ENOBUFS; 466 + 467 + __xskq_prod_reserve_desc(q, addr, len, flags); 462 468 463 469 return 0; 464 470 }