Skip to content

Commit f52ac70

Browse files
Tariq Toukandavem330
authored andcommitted
net/mlx5e: RX, Add XDP multi-buffer support in Striding RQ
Here we add support for multi-buffer XDP handling in Striding RQ, which is our default out-of-the-box RQ type. Before this series, loading such an XDP program would fail, until you switch to the legacy RQ (by unsetting the rx_striding_rq priv-flag). To overcome the lack of headroom and tailroom between the strides, we allocate a side page to be used for the descriptor (xdp_buff / skb) and the linear part. When an XDP program is attached, we structure the xdp_buff so that it contains no data in the linear part, and the whole packet resides in the fragments. In case of XDP_PASS, where an SKB still needs to be created, we copy up to 256 bytes to its linear part, to match the current behavior, and satisfy functions that assume finding the packet headers in the SKB linear part (like eth_type_trans). Performance testing: Packet rate test, 64 bytes, 32 channels, MTU 9000 bytes. CPU: Intel(R) Xeon(R) Platinum 8380 CPU @ 2.30GHz. NIC: ConnectX-6 Dx, at 100 Gbps. +----------+-------------+-------------+---------+ | Test | Legacy RQ | Striding RQ | Speedup | +----------+-------------+-------------+---------+ | XDP_DROP | 101,615,544 | 117,191,020 | +15% | +----------+-------------+-------------+---------+ | XDP_TX | 95,608,169 | 117,043,422 | +22% | +----------+-------------+-------------+---------+ Reviewed-by: Saeed Mahameed <[email protected]> Signed-off-by: Tariq Toukan <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 2cb0e27 commit f52ac70

File tree

5 files changed

+138
-59
lines changed

5 files changed

+138
-59
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,7 @@ union mlx5e_alloc_units {
587587
struct mlx5e_mpw_info {
588588
u16 consumed_strides;
589589
DECLARE_BITMAP(skip_release_bitmap, MLX5_MPWRQ_MAX_PAGES_PER_WQE);
590+
struct mlx5e_frag_page linear_page;
590591
union mlx5e_alloc_units alloc_units;
591592
};
592593

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

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,20 @@ static bool mlx5e_verify_rx_mpwqe_strides(struct mlx5_core_dev *mdev,
323323
return log_num_strides >= MLX5_MPWQE_LOG_NUM_STRIDES_BASE;
324324
}
325325

326+
bool mlx5e_verify_params_rx_mpwqe_strides(struct mlx5_core_dev *mdev,
327+
struct mlx5e_params *params,
328+
struct mlx5e_xsk_param *xsk)
329+
{
330+
u8 log_wqe_num_of_strides = mlx5e_mpwqe_get_log_num_strides(mdev, params, xsk);
331+
u8 log_wqe_stride_size = mlx5e_mpwqe_get_log_stride_size(mdev, params, xsk);
332+
enum mlx5e_mpwrq_umr_mode umr_mode = mlx5e_mpwrq_umr_mode(mdev, xsk);
333+
u8 page_shift = mlx5e_mpwrq_page_shift(mdev, xsk);
334+
335+
return mlx5e_verify_rx_mpwqe_strides(mdev, log_wqe_stride_size,
336+
log_wqe_num_of_strides,
337+
page_shift, umr_mode);
338+
}
339+
326340
bool mlx5e_rx_mpwqe_is_linear_skb(struct mlx5_core_dev *mdev,
327341
struct mlx5e_params *params,
328342
struct mlx5e_xsk_param *xsk)
@@ -405,6 +419,10 @@ u8 mlx5e_mpwqe_get_log_stride_size(struct mlx5_core_dev *mdev,
405419
if (mlx5e_rx_mpwqe_is_linear_skb(mdev, params, xsk))
406420
return order_base_2(mlx5e_rx_get_linear_stride_sz(mdev, params, xsk, true));
407421

422+
/* XDP in mlx5e doesn't support multiple packets per page. */
423+
if (params->xdp_prog)
424+
return PAGE_SHIFT;
425+
408426
return MLX5_MPWRQ_DEF_LOG_STRIDE_SZ(mdev);
409427
}
410428

@@ -575,9 +593,6 @@ int mlx5e_mpwrq_validate_regular(struct mlx5_core_dev *mdev, struct mlx5e_params
575593
if (!mlx5e_check_fragmented_striding_rq_cap(mdev, page_shift, umr_mode))
576594
return -EOPNOTSUPP;
577595

578-
if (params->xdp_prog && !mlx5e_rx_mpwqe_is_linear_skb(mdev, params, NULL))
579-
return -EINVAL;
580-
581596
return 0;
582597
}
583598

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,9 @@ int mlx5e_build_channel_param(struct mlx5_core_dev *mdev,
153153

154154
u16 mlx5e_calc_sq_stop_room(struct mlx5_core_dev *mdev, struct mlx5e_params *params);
155155
int mlx5e_validate_params(struct mlx5_core_dev *mdev, struct mlx5e_params *params);
156+
bool mlx5e_verify_params_rx_mpwqe_strides(struct mlx5_core_dev *mdev,
157+
struct mlx5e_params *params,
158+
struct mlx5e_xsk_param *xsk);
156159

157160
static inline void mlx5e_params_print_info(struct mlx5_core_dev *mdev,
158161
struct mlx5e_params *params)

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

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,9 @@ static int mlx5e_alloc_rq(struct mlx5e_params *params,
803803
pool_size = rq->mpwqe.pages_per_wqe <<
804804
mlx5e_mpwqe_get_log_rq_size(mdev, params, xsk);
805805

806+
if (!mlx5e_rx_mpwqe_is_linear_skb(mdev, params, xsk) && params->xdp_prog)
807+
pool_size *= 2; /* additional page per packet for the linear part */
808+
806809
rq->mpwqe.log_stride_sz = mlx5e_mpwqe_get_log_stride_size(mdev, params, xsk);
807810
rq->mpwqe.num_strides =
808811
BIT(mlx5e_mpwqe_get_log_num_strides(mdev, params, xsk));
@@ -4060,10 +4063,9 @@ void mlx5e_set_xdp_feature(struct net_device *netdev)
40604063

40614064
val = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
40624065
NETDEV_XDP_ACT_XSK_ZEROCOPY |
4066+
NETDEV_XDP_ACT_RX_SG |
40634067
NETDEV_XDP_ACT_NDO_XMIT |
40644068
NETDEV_XDP_ACT_NDO_XMIT_SG;
4065-
if (params->rq_wq_type == MLX5_WQ_TYPE_CYCLIC)
4066-
val |= NETDEV_XDP_ACT_RX_SG;
40674069
xdp_set_features_flag(netdev, val);
40684070
}
40694071

@@ -4261,23 +4263,20 @@ static bool mlx5e_params_validate_xdp(struct net_device *netdev,
42614263
mlx5e_rx_is_linear_skb(mdev, params, NULL) :
42624264
mlx5e_rx_mpwqe_is_linear_skb(mdev, params, NULL);
42634265

4264-
/* XDP affects striding RQ parameters. Block XDP if striding RQ won't be
4265-
* supported with the new parameters: if PAGE_SIZE is bigger than
4266-
* MLX5_MPWQE_LOG_STRIDE_SZ_MAX, striding RQ can't be used, even though
4267-
* the MTU is small enough for the linear mode, because XDP uses strides
4268-
* of PAGE_SIZE on regular RQs.
4269-
*/
4270-
if (!is_linear && params->rq_wq_type != MLX5_WQ_TYPE_CYCLIC) {
4271-
netdev_warn(netdev, "XDP is not allowed with striding RQ and MTU(%d) > %d\n",
4272-
params->sw_mtu,
4273-
mlx5e_xdp_max_mtu(params, NULL));
4274-
return false;
4275-
}
4276-
if (!is_linear && !params->xdp_prog->aux->xdp_has_frags) {
4277-
netdev_warn(netdev, "MTU(%d) > %d, too big for an XDP program not aware of multi buffer\n",
4278-
params->sw_mtu,
4279-
mlx5e_xdp_max_mtu(params, NULL));
4280-
return false;
4266+
if (!is_linear) {
4267+
if (!params->xdp_prog->aux->xdp_has_frags) {
4268+
netdev_warn(netdev, "MTU(%d) > %d, too big for an XDP program not aware of multi buffer\n",
4269+
params->sw_mtu,
4270+
mlx5e_xdp_max_mtu(params, NULL));
4271+
return false;
4272+
}
4273+
if (params->rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ &&
4274+
!mlx5e_verify_params_rx_mpwqe_strides(mdev, params, NULL)) {
4275+
netdev_warn(netdev, "XDP is not allowed with striding RQ and MTU(%d) > %d\n",
4276+
params->sw_mtu,
4277+
mlx5e_xdp_max_mtu(params, NULL));
4278+
return false;
4279+
}
42814280
}
42824281

42834282
return true;

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

Lines changed: 98 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1982,36 +1982,51 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w
19821982
struct skb_shared_info *sinfo;
19831983
struct mlx5e_xdp_buff mxbuf;
19841984
unsigned int truesize = 0;
1985+
struct bpf_prog *prog;
19851986
struct sk_buff *skb;
19861987
u32 linear_frame_sz;
19871988
u16 linear_data_len;
1988-
dma_addr_t addr;
19891989
u16 linear_hr;
19901990
void *va;
19911991

1992-
skb = napi_alloc_skb(rq->cq.napi,
1993-
ALIGN(MLX5E_RX_MAX_HEAD, sizeof(long)));
1994-
if (unlikely(!skb)) {
1995-
rq->stats->buff_alloc_err++;
1996-
return NULL;
1997-
}
1998-
1999-
va = skb->head;
2000-
net_prefetchw(skb->data);
1992+
prog = rcu_dereference(rq->xdp_prog);
20011993

2002-
frag_offset += headlen;
2003-
byte_cnt -= headlen;
2004-
linear_hr = skb_headroom(skb);
2005-
linear_data_len = headlen;
2006-
linear_frame_sz = MLX5_SKB_FRAG_SZ(skb_end_offset(skb));
2007-
if (unlikely(frag_offset >= PAGE_SIZE)) {
2008-
frag_page++;
2009-
frag_offset -= PAGE_SIZE;
1994+
if (prog) {
1995+
/* area for bpf_xdp_[store|load]_bytes */
1996+
net_prefetchw(page_address(frag_page->page) + frag_offset);
1997+
if (unlikely(mlx5e_page_alloc_fragmented(rq, &wi->linear_page))) {
1998+
rq->stats->buff_alloc_err++;
1999+
return NULL;
2000+
}
2001+
va = page_address(wi->linear_page.page);
2002+
net_prefetchw(va); /* xdp_frame data area */
2003+
linear_hr = XDP_PACKET_HEADROOM;
2004+
linear_data_len = 0;
2005+
linear_frame_sz = MLX5_SKB_FRAG_SZ(linear_hr + MLX5E_RX_MAX_HEAD);
2006+
} else {
2007+
skb = napi_alloc_skb(rq->cq.napi,
2008+
ALIGN(MLX5E_RX_MAX_HEAD, sizeof(long)));
2009+
if (unlikely(!skb)) {
2010+
rq->stats->buff_alloc_err++;
2011+
return NULL;
2012+
}
2013+
skb_mark_for_recycle(skb);
2014+
va = skb->head;
2015+
net_prefetchw(va); /* xdp_frame data area */
2016+
net_prefetchw(skb->data);
2017+
2018+
frag_offset += headlen;
2019+
byte_cnt -= headlen;
2020+
linear_hr = skb_headroom(skb);
2021+
linear_data_len = headlen;
2022+
linear_frame_sz = MLX5_SKB_FRAG_SZ(skb_end_offset(skb));
2023+
if (unlikely(frag_offset >= PAGE_SIZE)) {
2024+
frag_page++;
2025+
frag_offset -= PAGE_SIZE;
2026+
}
20102027
}
20112028

2012-
skb_mark_for_recycle(skb);
20132029
mlx5e_fill_mxbuf(rq, cqe, va, linear_hr, linear_frame_sz, linear_data_len, &mxbuf);
2014-
net_prefetch(mxbuf.xdp.data);
20152030

20162031
sinfo = xdp_get_shared_info_from_buff(&mxbuf.xdp);
20172032

@@ -2030,25 +2045,71 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w
20302045
frag_offset = 0;
20312046
frag_page++;
20322047
}
2033-
if (xdp_buff_has_frags(&mxbuf.xdp)) {
2034-
struct mlx5e_frag_page *pagep;
20352048

2036-
xdp_update_skb_shared_info(skb, sinfo->nr_frags,
2037-
sinfo->xdp_frags_size, truesize,
2038-
xdp_buff_is_frag_pfmemalloc(&mxbuf.xdp));
2049+
if (prog) {
2050+
if (mlx5e_xdp_handle(rq, prog, &mxbuf)) {
2051+
if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)) {
2052+
int i;
2053+
2054+
for (i = 0; i < sinfo->nr_frags; i++)
2055+
/* non-atomic */
2056+
__set_bit(page_idx + i, wi->skip_release_bitmap);
2057+
return NULL;
2058+
}
2059+
mlx5e_page_release_fragmented(rq, &wi->linear_page);
2060+
return NULL; /* page/packet was consumed by XDP */
2061+
}
2062+
2063+
skb = mlx5e_build_linear_skb(rq, mxbuf.xdp.data_hard_start,
2064+
linear_frame_sz,
2065+
mxbuf.xdp.data - mxbuf.xdp.data_hard_start, 0,
2066+
mxbuf.xdp.data - mxbuf.xdp.data_meta);
2067+
if (unlikely(!skb)) {
2068+
mlx5e_page_release_fragmented(rq, &wi->linear_page);
2069+
return NULL;
2070+
}
20392071

2040-
pagep = frag_page - sinfo->nr_frags;
2041-
do
2042-
pagep->frags++;
2043-
while (++pagep < frag_page);
2044-
}
2045-
/* copy header */
2046-
addr = page_pool_get_dma_addr(head_page->page);
2047-
mlx5e_copy_skb_header(rq, skb, head_page->page, addr,
2048-
head_offset, head_offset, headlen);
2049-
/* skb linear part was allocated with headlen and aligned to long */
2050-
skb->tail += headlen;
2051-
skb->len += headlen;
2072+
skb_mark_for_recycle(skb);
2073+
wi->linear_page.frags++;
2074+
mlx5e_page_release_fragmented(rq, &wi->linear_page);
2075+
2076+
if (xdp_buff_has_frags(&mxbuf.xdp)) {
2077+
struct mlx5e_frag_page *pagep;
2078+
2079+
/* sinfo->nr_frags is reset by build_skb, calculate again. */
2080+
xdp_update_skb_shared_info(skb, frag_page - head_page,
2081+
sinfo->xdp_frags_size, truesize,
2082+
xdp_buff_is_frag_pfmemalloc(&mxbuf.xdp));
2083+
2084+
pagep = head_page;
2085+
do
2086+
pagep->frags++;
2087+
while (++pagep < frag_page);
2088+
}
2089+
__pskb_pull_tail(skb, headlen);
2090+
} else {
2091+
dma_addr_t addr;
2092+
2093+
if (xdp_buff_has_frags(&mxbuf.xdp)) {
2094+
struct mlx5e_frag_page *pagep;
2095+
2096+
xdp_update_skb_shared_info(skb, sinfo->nr_frags,
2097+
sinfo->xdp_frags_size, truesize,
2098+
xdp_buff_is_frag_pfmemalloc(&mxbuf.xdp));
2099+
2100+
pagep = frag_page - sinfo->nr_frags;
2101+
do
2102+
pagep->frags++;
2103+
while (++pagep < frag_page);
2104+
}
2105+
/* copy header */
2106+
addr = page_pool_get_dma_addr(head_page->page);
2107+
mlx5e_copy_skb_header(rq, skb, head_page->page, addr,
2108+
head_offset, head_offset, headlen);
2109+
/* skb linear part was allocated with headlen and aligned to long */
2110+
skb->tail += headlen;
2111+
skb->len += headlen;
2112+
}
20522113

20532114
return skb;
20542115
}

0 commit comments

Comments
 (0)