Skip to content

Commit cb9edd5

Browse files
ameryhunggregkh
authored andcommitted
net/mlx5e: RX, Fix generating skb from non-linear xdp_buff for striding RQ
[ Upstream commit 87bcef1 ] XDP programs can change the layout of an xdp_buff through bpf_xdp_adjust_tail() and bpf_xdp_adjust_head(). Therefore, the driver cannot assume the size of the linear data area nor fragments. Fix the bug in mlx5 by generating skb according to xdp_buff after XDP programs run. Currently, when handling multi-buf XDP, the mlx5 driver assumes the layout of an xdp_buff to be unchanged. That is, the linear data area continues to be empty and fragments remain the same. This may cause the driver to generate erroneous skb or triggering a kernel warning. When an XDP program added linear data through bpf_xdp_adjust_head(), the linear data will be ignored as mlx5e_build_linear_skb() builds an skb without linear data and then pull data from fragments to fill the linear data area. When an XDP program has shrunk the non-linear data through bpf_xdp_adjust_tail(), the delta passed to __pskb_pull_tail() may exceed the actual nonlinear data size and trigger the BUG_ON in it. To fix the issue, first record the original number of fragments. If the number of fragments changes after the XDP program runs, rewind the end fragment pointer by the difference and recalculate the truesize. Then, build the skb with the linear data area matching the xdp_buff. Finally, only pull data in if there is non-linear data and fill the linear part up to 256 bytes. Fixes: f52ac70 ("net/mlx5e: RX, Add XDP multi-buffer support in Striding RQ") Signed-off-by: Amery Hung <ameryhung@gmail.com> Signed-off-by: Tariq Toukan <tariqt@nvidia.com> Link: https://patch.msgid.link/1760644540-899148-3-git-send-email-tariqt@nvidia.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 0049fd6 commit cb9edd5

File tree

1 file changed

+23
-3
lines changed
  • drivers/net/ethernet/mellanox/mlx5/core

1 file changed

+23
-3
lines changed

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

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2012,6 +2012,7 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w
20122012
u32 byte_cnt = cqe_bcnt;
20132013
struct skb_shared_info *sinfo;
20142014
unsigned int truesize = 0;
2015+
u32 pg_consumed_bytes;
20152016
struct bpf_prog *prog;
20162017
struct sk_buff *skb;
20172018
u32 linear_frame_sz;
@@ -2063,7 +2064,8 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w
20632064

20642065
while (byte_cnt) {
20652066
/* Non-linear mode, hence non-XSK, which always uses PAGE_SIZE. */
2066-
u32 pg_consumed_bytes = min_t(u32, PAGE_SIZE - frag_offset, byte_cnt);
2067+
pg_consumed_bytes =
2068+
min_t(u32, PAGE_SIZE - frag_offset, byte_cnt);
20672069

20682070
if (test_bit(MLX5E_RQ_STATE_SHAMPO, &rq->state))
20692071
truesize += pg_consumed_bytes;
@@ -2079,10 +2081,15 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w
20792081
}
20802082

20812083
if (prog) {
2084+
u8 nr_frags_free, old_nr_frags = sinfo->nr_frags;
2085+
u32 len;
2086+
20822087
if (mlx5e_xdp_handle(rq, prog, mxbuf)) {
20832088
if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)) {
20842089
struct mlx5e_frag_page *pfp;
20852090

2091+
frag_page -= old_nr_frags - sinfo->nr_frags;
2092+
20862093
for (pfp = head_page; pfp < frag_page; pfp++)
20872094
pfp->frags++;
20882095

@@ -2092,9 +2099,19 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w
20922099
return NULL; /* page/packet was consumed by XDP */
20932100
}
20942101

2102+
nr_frags_free = old_nr_frags - sinfo->nr_frags;
2103+
if (unlikely(nr_frags_free)) {
2104+
frag_page -= nr_frags_free;
2105+
truesize -= (nr_frags_free - 1) * PAGE_SIZE +
2106+
ALIGN(pg_consumed_bytes,
2107+
BIT(rq->mpwqe.log_stride_sz));
2108+
}
2109+
2110+
len = mxbuf->xdp.data_end - mxbuf->xdp.data;
2111+
20952112
skb = mlx5e_build_linear_skb(
20962113
rq, mxbuf->xdp.data_hard_start, linear_frame_sz,
2097-
mxbuf->xdp.data - mxbuf->xdp.data_hard_start, 0,
2114+
mxbuf->xdp.data - mxbuf->xdp.data_hard_start, len,
20982115
mxbuf->xdp.data - mxbuf->xdp.data_meta);
20992116
if (unlikely(!skb)) {
21002117
mlx5e_page_release_fragmented(rq, &wi->linear_page);
@@ -2118,8 +2135,11 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w
21182135
do
21192136
pagep->frags++;
21202137
while (++pagep < frag_page);
2138+
2139+
headlen = min_t(u16, MLX5E_RX_MAX_HEAD - len,
2140+
skb->data_len);
2141+
__pskb_pull_tail(skb, headlen);
21212142
}
2122-
__pskb_pull_tail(skb, headlen);
21232143
} else {
21242144
dma_addr_t addr;
21252145

0 commit comments

Comments
 (0)