Skip to content

Commit 282c0c7

Browse files
Maxim Mikityanskiyborkmann
authored andcommitted
net/mlx5e: Allow XSK frames smaller than a page
Relax the requirements to the XSK frame size to allow it to be smaller than a page and even not a power of two. The current implementation can work in this mode, both with Striding RQ and without it. The code that checks `mtu + headroom <= XSK frame size` is modified accordingly. Any frame size between 2048 and PAGE_SIZE is accepted. Functions that worked with pages only now work with XSK frames, even if their size is different from PAGE_SIZE. With XSK queues, regardless of the frame size, Striding RQ uses the stride size of PAGE_SIZE, and UMR MTTs are posted using starting addresses of frames, but PAGE_SIZE as page size. MTU guarantees that no packet data will overlap with other frames. UMR MTT size is made equal to the stride size of the RQ, because UMEM frames may come in random order, and we need to handle them one by one. PAGE_SIZE is just a power of two that is bigger than any allowed XSK frame size, and also it doesn't require making additional changes to the code. Signed-off-by: Maxim Mikityanskiy <[email protected]> Reviewed-by: Saeed Mahameed <[email protected]> Acked-by: Jonathan Lemon <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]>
1 parent beb3e4b commit 282c0c7

File tree

4 files changed

+32
-10
lines changed

4 files changed

+32
-10
lines changed

drivers/net/ethernet/mellanox/mlx5/core/en/params.c

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,33 @@ u16 mlx5e_get_linear_rq_headroom(struct mlx5e_params *params,
2525
return headroom;
2626
}
2727

28-
u32 mlx5e_rx_get_linear_frag_sz(struct mlx5e_params *params,
29-
struct mlx5e_xsk_param *xsk)
28+
u32 mlx5e_rx_get_min_frag_sz(struct mlx5e_params *params,
29+
struct mlx5e_xsk_param *xsk)
3030
{
3131
u32 hw_mtu = MLX5E_SW2HW_MTU(params, params->sw_mtu);
3232
u16 linear_rq_headroom = mlx5e_get_linear_rq_headroom(params, xsk);
33-
u32 frag_sz = linear_rq_headroom + hw_mtu;
33+
34+
return linear_rq_headroom + hw_mtu;
35+
}
36+
37+
u32 mlx5e_rx_get_linear_frag_sz(struct mlx5e_params *params,
38+
struct mlx5e_xsk_param *xsk)
39+
{
40+
u32 frag_sz = mlx5e_rx_get_min_frag_sz(params, xsk);
3441

3542
/* AF_XDP doesn't build SKBs in place. */
3643
if (!xsk)
3744
frag_sz = MLX5_SKB_FRAG_SZ(frag_sz);
3845

39-
/* XDP in mlx5e doesn't support multiple packets per page. */
46+
/* XDP in mlx5e doesn't support multiple packets per page. AF_XDP is a
47+
* special case. It can run with frames smaller than a page, as it
48+
* doesn't allocate pages dynamically. However, here we pretend that
49+
* fragments are page-sized: it allows to treat XSK frames like pages
50+
* by redirecting alloc and free operations to XSK rings and by using
51+
* the fact there are no multiple packets per "page" (which is a frame).
52+
* The latter is important, because frames may come in a random order,
53+
* and we will have trouble assemblying a real page of multiple frames.
54+
*/
4055
if (mlx5e_rx_is_xdp(params, xsk))
4156
frag_sz = max_t(u32, frag_sz, PAGE_SIZE);
4257

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ static inline bool mlx5e_qid_validate(const struct mlx5e_profile *profile,
7676

7777
u16 mlx5e_get_linear_rq_headroom(struct mlx5e_params *params,
7878
struct mlx5e_xsk_param *xsk);
79+
u32 mlx5e_rx_get_min_frag_sz(struct mlx5e_params *params,
80+
struct mlx5e_xsk_param *xsk);
7981
u32 mlx5e_rx_get_linear_frag_sz(struct mlx5e_params *params,
8082
struct mlx5e_xsk_param *xsk);
8183
u8 mlx5e_mpwqe_log_pkts_per_wqe(struct mlx5e_params *params,

drivers/net/ethernet/mellanox/mlx5/core/en/xsk/rx.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ struct sk_buff *mlx5e_xsk_skb_from_cqe_mpwrq_linear(struct mlx5e_rq *rq,
105105

106106
/* head_offset is not used in this function, because di->xsk.data and
107107
* di->addr point directly to the necessary place. Furthermore, in the
108-
* current implementation, one page = one packet = one frame, so
108+
* current implementation, UMR pages are mapped to XSK frames, so
109109
* head_offset should always be 0.
110110
*/
111111
WARN_ON_ONCE(head_offset);

drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,23 @@
44
#include "setup.h"
55
#include "en/params.h"
66

7+
/* It matches XDP_UMEM_MIN_CHUNK_SIZE, but as this constant is private and may
8+
* change unexpectedly, and mlx5e has a minimum valid stride size for striding
9+
* RQ, keep this check in the driver.
10+
*/
11+
#define MLX5E_MIN_XSK_CHUNK_SIZE 2048
12+
713
bool mlx5e_validate_xsk_param(struct mlx5e_params *params,
814
struct mlx5e_xsk_param *xsk,
915
struct mlx5_core_dev *mdev)
1016
{
11-
/* AF_XDP doesn't support frames larger than PAGE_SIZE, and the current
12-
* mlx5e XDP implementation doesn't support multiple packets per page.
13-
*/
14-
if (xsk->chunk_size != PAGE_SIZE)
17+
/* AF_XDP doesn't support frames larger than PAGE_SIZE. */
18+
if (xsk->chunk_size > PAGE_SIZE ||
19+
xsk->chunk_size < MLX5E_MIN_XSK_CHUNK_SIZE)
1520
return false;
1621

1722
/* Current MTU and XSK headroom don't allow packets to fit the frames. */
18-
if (mlx5e_rx_get_linear_frag_sz(params, xsk) > xsk->chunk_size)
23+
if (mlx5e_rx_get_min_frag_sz(params, xsk) > xsk->chunk_size)
1924
return false;
2025

2126
/* frag_sz is different for regular and XSK RQs, so ensure that linear

0 commit comments

Comments
 (0)