Skip to content

Commit 7e42ce5

Browse files
author
Benjamin Poirier
committed
net/mlx5e: Reuse per-RQ XDP buffer to avoid stack zeroing overhead
JIRA: https://issues.redhat.com/browse/RHEL-72227 JIRA: https://issues.redhat.com/browse/RHEL-73520 JIRA: https://issues.redhat.com/browse/RHEL-94894 Upstream-status: v6.16-rc1 commit b66b76a Author: Carolina Jubran <cjubran@nvidia.com> Date: Wed May 14 23:03:52 2025 +0300 net/mlx5e: Reuse per-RQ XDP buffer to avoid stack zeroing overhead CONFIG_INIT_STACK_ALL_ZERO introduces a performance cost by zero-initializing all stack variables on function entry. The mlx5 XDP RX path previously allocated a struct mlx5e_xdp_buff on the stack per received CQE, resulting in measurable performance degradation under this config. This patch reuses a mlx5e_xdp_buff stored in the mlx5e_rq struct, avoiding per-CQE stack allocations and repeated zeroing. With this change, XDP_DROP and XDP_TX performance matches that of kernels built without CONFIG_INIT_STACK_ALL_ZERO. Performance was measured on a ConnectX-6Dx using a single RX channel (1 CPU at 100% usage) at ~50 Mpps. The baseline results were taken from net-next-6.15. Stack zeroing disabled: - XDP_DROP: * baseline: 31.47 Mpps * baseline + per-RQ allocation: 32.31 Mpps (+2.68%) - XDP_TX: * baseline: 12.41 Mpps * baseline + per-RQ allocation: 12.95 Mpps (+4.30%) Stack zeroing enabled: - XDP_DROP: * baseline: 24.32 Mpps * baseline + per-RQ allocation: 32.27 Mpps (+32.7%) - XDP_TX: * baseline: 11.80 Mpps * baseline + per-RQ allocation: 12.24 Mpps (+3.72%) Reported-by: Sebastiano Miano <mianosebastiano@gmail.com> Reported-by: Samuel Dobron <sdobron@redhat.com> Link: https://lore.kernel.org/all/CAMENy5pb8ea+piKLg5q5yRTMZacQqYWAoVLE1FE9WhQPq92E0g@mail.gmail.com/ Signed-off-by: Carolina Jubran <cjubran@nvidia.com> Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com> Signed-off-by: Tariq Toukan <tariqt@nvidia.com> Acked-by: Jesper Dangaard Brouer <hawk@kernel.org> Link: https://patch.msgid.link/1747253032-663457-1-git-send-email-tariqt@nvidia.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Benjamin Poirier <bpoirier@redhat.com>
1 parent 1a8ef0a commit 7e42ce5

File tree

3 files changed

+51
-43
lines changed

3 files changed

+51
-43
lines changed

drivers/net/ethernet/mellanox/mlx5/core/en.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,12 @@ struct mlx5e_xdpsq {
520520
struct mlx5e_channel *channel;
521521
} ____cacheline_aligned_in_smp;
522522

523+
struct mlx5e_xdp_buff {
524+
struct xdp_buff xdp;
525+
struct mlx5_cqe64 *cqe;
526+
struct mlx5e_rq *rq;
527+
};
528+
523529
struct mlx5e_ktls_resync_resp;
524530

525531
struct mlx5e_icosq {
@@ -716,6 +722,7 @@ struct mlx5e_rq {
716722
struct mlx5e_xdpsq *xdpsq;
717723
DECLARE_BITMAP(flags, 8);
718724
struct page_pool *page_pool;
725+
struct mlx5e_xdp_buff mxbuf;
719726

720727
/* AF_XDP zero-copy */
721728
struct xsk_buff_pool *xsk_pool;

drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,6 @@
4545
(MLX5E_XDP_INLINE_WQE_MAX_DS_CNT * MLX5_SEND_WQE_DS - \
4646
sizeof(struct mlx5_wqe_inline_seg))
4747

48-
struct mlx5e_xdp_buff {
49-
struct xdp_buff xdp;
50-
struct mlx5_cqe64 *cqe;
51-
struct mlx5e_rq *rq;
52-
};
53-
5448
/* XDP packets can be transmitted in different ways. On completion, we need to
5549
* distinguish between them to clean up things in a proper way.
5650
*/

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

Lines changed: 44 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1684,17 +1684,17 @@ mlx5e_skb_from_cqe_linear(struct mlx5e_rq *rq, struct mlx5e_wqe_frag_info *wi,
16841684

16851685
prog = rcu_dereference(rq->xdp_prog);
16861686
if (prog) {
1687-
struct mlx5e_xdp_buff mxbuf;
1687+
struct mlx5e_xdp_buff *mxbuf = &rq->mxbuf;
16881688

16891689
net_prefetchw(va); /* xdp_frame data area */
16901690
mlx5e_fill_mxbuf(rq, cqe, va, rx_headroom, rq->buff.frame0_sz,
1691-
cqe_bcnt, &mxbuf);
1692-
if (mlx5e_xdp_handle(rq, prog, &mxbuf))
1691+
cqe_bcnt, mxbuf);
1692+
if (mlx5e_xdp_handle(rq, prog, mxbuf))
16931693
return NULL; /* page/packet was consumed by XDP */
16941694

1695-
rx_headroom = mxbuf.xdp.data - mxbuf.xdp.data_hard_start;
1696-
metasize = mxbuf.xdp.data - mxbuf.xdp.data_meta;
1697-
cqe_bcnt = mxbuf.xdp.data_end - mxbuf.xdp.data;
1695+
rx_headroom = mxbuf->xdp.data - mxbuf->xdp.data_hard_start;
1696+
metasize = mxbuf->xdp.data - mxbuf->xdp.data_meta;
1697+
cqe_bcnt = mxbuf->xdp.data_end - mxbuf->xdp.data;
16981698
}
16991699
frag_size = MLX5_SKB_FRAG_SZ(rx_headroom + cqe_bcnt);
17001700
skb = mlx5e_build_linear_skb(rq, va, frag_size, rx_headroom, cqe_bcnt, metasize);
@@ -1713,11 +1713,11 @@ mlx5e_skb_from_cqe_nonlinear(struct mlx5e_rq *rq, struct mlx5e_wqe_frag_info *wi
17131713
struct mlx5_cqe64 *cqe, u32 cqe_bcnt)
17141714
{
17151715
struct mlx5e_rq_frag_info *frag_info = &rq->wqe.info.arr[0];
1716+
struct mlx5e_xdp_buff *mxbuf = &rq->mxbuf;
17161717
struct mlx5e_wqe_frag_info *head_wi = wi;
17171718
u16 rx_headroom = rq->buff.headroom;
17181719
struct mlx5e_frag_page *frag_page;
17191720
struct skb_shared_info *sinfo;
1720-
struct mlx5e_xdp_buff mxbuf;
17211721
u32 frag_consumed_bytes;
17221722
struct bpf_prog *prog;
17231723
struct sk_buff *skb;
@@ -1737,8 +1737,8 @@ mlx5e_skb_from_cqe_nonlinear(struct mlx5e_rq *rq, struct mlx5e_wqe_frag_info *wi
17371737
net_prefetch(va + rx_headroom);
17381738

17391739
mlx5e_fill_mxbuf(rq, cqe, va, rx_headroom, rq->buff.frame0_sz,
1740-
frag_consumed_bytes, &mxbuf);
1741-
sinfo = xdp_get_shared_info_from_buff(&mxbuf.xdp);
1740+
frag_consumed_bytes, mxbuf);
1741+
sinfo = xdp_get_shared_info_from_buff(&mxbuf->xdp);
17421742
truesize = 0;
17431743

17441744
cqe_bcnt -= frag_consumed_bytes;
@@ -1750,8 +1750,9 @@ mlx5e_skb_from_cqe_nonlinear(struct mlx5e_rq *rq, struct mlx5e_wqe_frag_info *wi
17501750

17511751
frag_consumed_bytes = min_t(u32, frag_info->frag_size, cqe_bcnt);
17521752

1753-
mlx5e_add_skb_shared_info_frag(rq, sinfo, &mxbuf.xdp, frag_page,
1754-
wi->offset, frag_consumed_bytes);
1753+
mlx5e_add_skb_shared_info_frag(rq, sinfo, &mxbuf->xdp,
1754+
frag_page, wi->offset,
1755+
frag_consumed_bytes);
17551756
truesize += frag_info->frag_stride;
17561757

17571758
cqe_bcnt -= frag_consumed_bytes;
@@ -1760,7 +1761,7 @@ mlx5e_skb_from_cqe_nonlinear(struct mlx5e_rq *rq, struct mlx5e_wqe_frag_info *wi
17601761
}
17611762

17621763
prog = rcu_dereference(rq->xdp_prog);
1763-
if (prog && mlx5e_xdp_handle(rq, prog, &mxbuf)) {
1764+
if (prog && mlx5e_xdp_handle(rq, prog, mxbuf)) {
17641765
if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)) {
17651766
struct mlx5e_wqe_frag_info *pwi;
17661767

@@ -1770,21 +1771,23 @@ mlx5e_skb_from_cqe_nonlinear(struct mlx5e_rq *rq, struct mlx5e_wqe_frag_info *wi
17701771
return NULL; /* page/packet was consumed by XDP */
17711772
}
17721773

1773-
skb = mlx5e_build_linear_skb(rq, mxbuf.xdp.data_hard_start, rq->buff.frame0_sz,
1774-
mxbuf.xdp.data - mxbuf.xdp.data_hard_start,
1775-
mxbuf.xdp.data_end - mxbuf.xdp.data,
1776-
mxbuf.xdp.data - mxbuf.xdp.data_meta);
1774+
skb = mlx5e_build_linear_skb(
1775+
rq, mxbuf->xdp.data_hard_start, rq->buff.frame0_sz,
1776+
mxbuf->xdp.data - mxbuf->xdp.data_hard_start,
1777+
mxbuf->xdp.data_end - mxbuf->xdp.data,
1778+
mxbuf->xdp.data - mxbuf->xdp.data_meta);
17771779
if (unlikely(!skb))
17781780
return NULL;
17791781

17801782
skb_mark_for_recycle(skb);
17811783
head_wi->frag_page->frags++;
17821784

1783-
if (xdp_buff_has_frags(&mxbuf.xdp)) {
1785+
if (xdp_buff_has_frags(&mxbuf->xdp)) {
17841786
/* sinfo->nr_frags is reset by build_skb, calculate again. */
17851787
xdp_update_skb_shared_info(skb, wi - head_wi - 1,
17861788
sinfo->xdp_frags_size, truesize,
1787-
xdp_buff_is_frag_pfmemalloc(&mxbuf.xdp));
1789+
xdp_buff_is_frag_pfmemalloc(
1790+
&mxbuf->xdp));
17881791

17891792
for (struct mlx5e_wqe_frag_info *pwi = head_wi + 1; pwi < wi; pwi++)
17901793
pwi->frag_page->frags++;
@@ -1984,10 +1987,10 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w
19841987
struct mlx5e_frag_page *frag_page = &wi->alloc_units.frag_pages[page_idx];
19851988
u16 headlen = min_t(u16, MLX5E_RX_MAX_HEAD, cqe_bcnt);
19861989
struct mlx5e_frag_page *head_page = frag_page;
1990+
struct mlx5e_xdp_buff *mxbuf = &rq->mxbuf;
19871991
u32 frag_offset = head_offset;
19881992
u32 byte_cnt = cqe_bcnt;
19891993
struct skb_shared_info *sinfo;
1990-
struct mlx5e_xdp_buff mxbuf;
19911994
unsigned int truesize = 0;
19921995
struct bpf_prog *prog;
19931996
struct sk_buff *skb;
@@ -2033,9 +2036,10 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w
20332036
}
20342037
}
20352038

2036-
mlx5e_fill_mxbuf(rq, cqe, va, linear_hr, linear_frame_sz, linear_data_len, &mxbuf);
2039+
mlx5e_fill_mxbuf(rq, cqe, va, linear_hr, linear_frame_sz,
2040+
linear_data_len, mxbuf);
20372041

2038-
sinfo = xdp_get_shared_info_from_buff(&mxbuf.xdp);
2042+
sinfo = xdp_get_shared_info_from_buff(&mxbuf->xdp);
20392043

20402044
while (byte_cnt) {
20412045
/* Non-linear mode, hence non-XSK, which always uses PAGE_SIZE. */
@@ -2046,15 +2050,16 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w
20462050
else
20472051
truesize += ALIGN(pg_consumed_bytes, BIT(rq->mpwqe.log_stride_sz));
20482052

2049-
mlx5e_add_skb_shared_info_frag(rq, sinfo, &mxbuf.xdp, frag_page, frag_offset,
2053+
mlx5e_add_skb_shared_info_frag(rq, sinfo, &mxbuf->xdp,
2054+
frag_page, frag_offset,
20502055
pg_consumed_bytes);
20512056
byte_cnt -= pg_consumed_bytes;
20522057
frag_offset = 0;
20532058
frag_page++;
20542059
}
20552060

20562061
if (prog) {
2057-
if (mlx5e_xdp_handle(rq, prog, &mxbuf)) {
2062+
if (mlx5e_xdp_handle(rq, prog, mxbuf)) {
20582063
if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)) {
20592064
struct mlx5e_frag_page *pfp;
20602065

@@ -2067,10 +2072,10 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w
20672072
return NULL; /* page/packet was consumed by XDP */
20682073
}
20692074

2070-
skb = mlx5e_build_linear_skb(rq, mxbuf.xdp.data_hard_start,
2071-
linear_frame_sz,
2072-
mxbuf.xdp.data - mxbuf.xdp.data_hard_start, 0,
2073-
mxbuf.xdp.data - mxbuf.xdp.data_meta);
2075+
skb = mlx5e_build_linear_skb(
2076+
rq, mxbuf->xdp.data_hard_start, linear_frame_sz,
2077+
mxbuf->xdp.data - mxbuf->xdp.data_hard_start, 0,
2078+
mxbuf->xdp.data - mxbuf->xdp.data_meta);
20742079
if (unlikely(!skb)) {
20752080
mlx5e_page_release_fragmented(rq, &wi->linear_page);
20762081
return NULL;
@@ -2080,13 +2085,14 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w
20802085
wi->linear_page.frags++;
20812086
mlx5e_page_release_fragmented(rq, &wi->linear_page);
20822087

2083-
if (xdp_buff_has_frags(&mxbuf.xdp)) {
2088+
if (xdp_buff_has_frags(&mxbuf->xdp)) {
20842089
struct mlx5e_frag_page *pagep;
20852090

20862091
/* sinfo->nr_frags is reset by build_skb, calculate again. */
20872092
xdp_update_skb_shared_info(skb, frag_page - head_page,
20882093
sinfo->xdp_frags_size, truesize,
2089-
xdp_buff_is_frag_pfmemalloc(&mxbuf.xdp));
2094+
xdp_buff_is_frag_pfmemalloc(
2095+
&mxbuf->xdp));
20902096

20912097
pagep = head_page;
20922098
do
@@ -2097,12 +2103,13 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w
20972103
} else {
20982104
dma_addr_t addr;
20992105

2100-
if (xdp_buff_has_frags(&mxbuf.xdp)) {
2106+
if (xdp_buff_has_frags(&mxbuf->xdp)) {
21012107
struct mlx5e_frag_page *pagep;
21022108

21032109
xdp_update_skb_shared_info(skb, sinfo->nr_frags,
21042110
sinfo->xdp_frags_size, truesize,
2105-
xdp_buff_is_frag_pfmemalloc(&mxbuf.xdp));
2111+
xdp_buff_is_frag_pfmemalloc(
2112+
&mxbuf->xdp));
21062113

21072114
pagep = frag_page - sinfo->nr_frags;
21082115
do
@@ -2152,20 +2159,20 @@ mlx5e_skb_from_cqe_mpwrq_linear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi,
21522159

21532160
prog = rcu_dereference(rq->xdp_prog);
21542161
if (prog) {
2155-
struct mlx5e_xdp_buff mxbuf;
2162+
struct mlx5e_xdp_buff *mxbuf = &rq->mxbuf;
21562163

21572164
net_prefetchw(va); /* xdp_frame data area */
21582165
mlx5e_fill_mxbuf(rq, cqe, va, rx_headroom, rq->buff.frame0_sz,
2159-
cqe_bcnt, &mxbuf);
2160-
if (mlx5e_xdp_handle(rq, prog, &mxbuf)) {
2166+
cqe_bcnt, mxbuf);
2167+
if (mlx5e_xdp_handle(rq, prog, mxbuf)) {
21612168
if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags))
21622169
frag_page->frags++;
21632170
return NULL; /* page/packet was consumed by XDP */
21642171
}
21652172

2166-
rx_headroom = mxbuf.xdp.data - mxbuf.xdp.data_hard_start;
2167-
metasize = mxbuf.xdp.data - mxbuf.xdp.data_meta;
2168-
cqe_bcnt = mxbuf.xdp.data_end - mxbuf.xdp.data;
2173+
rx_headroom = mxbuf->xdp.data - mxbuf->xdp.data_hard_start;
2174+
metasize = mxbuf->xdp.data - mxbuf->xdp.data_meta;
2175+
cqe_bcnt = mxbuf->xdp.data_end - mxbuf->xdp.data;
21692176
}
21702177
frag_size = MLX5_SKB_FRAG_SZ(rx_headroom + cqe_bcnt);
21712178
skb = mlx5e_build_linear_skb(rq, va, frag_size, rx_headroom, cqe_bcnt, metasize);

0 commit comments

Comments
 (0)