Skip to content

Commit b5503b9

Browse files
Saeed Mahameeddavem330
authored andcommitted
net/mlx5e: XDP TX forwarding support
Adding support for XDP_TX forwarding from xdp program. Using XDP, now user can loop packets out of the same port. We create a dedicated TX SQ for each channel that will serve XDP programs that return XDP_TX action to loop packets back to the wire directly from the channel RQ RX path. For that RX pages will now need to be mapped bi-directionally, and on XDP_TX action we will sync the page back to device then queue it into SQ for transmission. The XDP xmit frame function will report back to the RX path if the page was consumed (transmitted), if so, RX path will forget about that page as if it were released to the stack. Later on, on XDP TX completion, the page will be released back to the page cache. For simplicity this patch will hit a doorbell on every XDP TX packet. Next patch will introduce a xmit more like mechanism that will queue up more than one packet into SQ w/o notifying the hardware, once RX napi loop is done we will hit doorbell once for all XDP TX packets form the previous loop. This should drastically improve XDP TX performance. Signed-off-by: Saeed Mahameed <[email protected]> Signed-off-by: Tariq Toukan <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent f10b7cc commit b5503b9

File tree

6 files changed

+304
-36
lines changed

6 files changed

+304
-36
lines changed

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

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,15 @@
104104
#define MLX5E_ICOSQ_MAX_WQEBBS \
105105
(DIV_ROUND_UP(sizeof(struct mlx5e_umr_wqe), MLX5_SEND_WQE_BB))
106106

107+
#define MLX5E_XDP_MIN_INLINE (ETH_HLEN + VLAN_HLEN)
108+
#define MLX5E_XDP_IHS_DS_COUNT \
109+
DIV_ROUND_UP(MLX5E_XDP_MIN_INLINE - 2, MLX5_SEND_WQE_DS)
110+
#define MLX5E_XDP_TX_DS_COUNT \
111+
(MLX5E_XDP_IHS_DS_COUNT + \
112+
(sizeof(struct mlx5e_tx_wqe) / MLX5_SEND_WQE_DS) + 1 /* SG DS */)
113+
#define MLX5E_XDP_TX_WQEBBS \
114+
DIV_ROUND_UP(MLX5E_XDP_TX_DS_COUNT, MLX5_SEND_WQEBB_NUM_DS)
115+
107116
#define MLX5E_NUM_MAIN_GROUPS 9
108117

109118
static inline u16 mlx5_min_rx_wqes(int wq_type, u32 wq_size)
@@ -319,6 +328,7 @@ struct mlx5e_rq {
319328
struct {
320329
u8 page_order;
321330
u32 wqe_sz; /* wqe data buffer size */
331+
u8 map_dir; /* dma map direction */
322332
} buff;
323333
__be32 mkey_be;
324334

@@ -384,14 +394,15 @@ enum {
384394
MLX5E_SQ_STATE_BF_ENABLE,
385395
};
386396

387-
struct mlx5e_ico_wqe_info {
397+
struct mlx5e_sq_wqe_info {
388398
u8 opcode;
389399
u8 num_wqebbs;
390400
};
391401

392402
enum mlx5e_sq_type {
393403
MLX5E_SQ_TXQ,
394-
MLX5E_SQ_ICO
404+
MLX5E_SQ_ICO,
405+
MLX5E_SQ_XDP
395406
};
396407

397408
struct mlx5e_sq {
@@ -418,7 +429,11 @@ struct mlx5e_sq {
418429
struct mlx5e_sq_dma *dma_fifo;
419430
struct mlx5e_tx_wqe_info *wqe_info;
420431
} txq;
421-
struct mlx5e_ico_wqe_info *ico_wqe;
432+
struct mlx5e_sq_wqe_info *ico_wqe;
433+
struct {
434+
struct mlx5e_sq_wqe_info *wqe_info;
435+
struct mlx5e_dma_info *di;
436+
} xdp;
422437
} db;
423438

424439
/* read only */
@@ -458,8 +473,10 @@ enum channel_flags {
458473
struct mlx5e_channel {
459474
/* data path */
460475
struct mlx5e_rq rq;
476+
struct mlx5e_sq xdp_sq;
461477
struct mlx5e_sq sq[MLX5E_MAX_NUM_TC];
462478
struct mlx5e_sq icosq; /* internal control operations */
479+
bool xdp;
463480
struct napi_struct napi;
464481
struct device *pdev;
465482
struct net_device *netdev;
@@ -688,7 +705,7 @@ void mlx5e_cq_error_event(struct mlx5_core_cq *mcq, enum mlx5_event event);
688705
int mlx5e_napi_poll(struct napi_struct *napi, int budget);
689706
bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq, int napi_budget);
690707
int mlx5e_poll_rx_cq(struct mlx5e_cq *cq, int budget);
691-
void mlx5e_free_tx_descs(struct mlx5e_sq *sq);
708+
void mlx5e_free_sq_descs(struct mlx5e_sq *sq);
692709

693710
void mlx5e_page_release(struct mlx5e_rq *rq, struct mlx5e_dma_info *dma_info,
694711
bool recycle);

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

Lines changed: 85 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ struct mlx5e_cq_param {
6464
struct mlx5e_channel_param {
6565
struct mlx5e_rq_param rq;
6666
struct mlx5e_sq_param sq;
67+
struct mlx5e_sq_param xdp_sq;
6768
struct mlx5e_sq_param icosq;
6869
struct mlx5e_cq_param rx_cq;
6970
struct mlx5e_cq_param tx_cq;
@@ -180,6 +181,8 @@ static void mlx5e_update_sw_counters(struct mlx5e_priv *priv)
180181
s->rx_csum_complete += rq_stats->csum_complete;
181182
s->rx_csum_unnecessary_inner += rq_stats->csum_unnecessary_inner;
182183
s->rx_xdp_drop += rq_stats->xdp_drop;
184+
s->rx_xdp_tx += rq_stats->xdp_tx;
185+
s->rx_xdp_tx_full += rq_stats->xdp_tx_full;
183186
s->rx_wqe_err += rq_stats->wqe_err;
184187
s->rx_mpwqe_filler += rq_stats->mpwqe_filler;
185188
s->rx_buff_alloc_err += rq_stats->buff_alloc_err;
@@ -478,6 +481,10 @@ static int mlx5e_create_rq(struct mlx5e_channel *c,
478481
rq->priv = c->priv;
479482
rq->xdp_prog = priv->xdp_prog;
480483

484+
rq->buff.map_dir = DMA_FROM_DEVICE;
485+
if (rq->xdp_prog)
486+
rq->buff.map_dir = DMA_BIDIRECTIONAL;
487+
481488
switch (priv->params.rq_wq_type) {
482489
case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
483490
rq->handle_rx_cqe = mlx5e_handle_rx_cqe_mpwrq;
@@ -765,6 +772,28 @@ static void mlx5e_close_rq(struct mlx5e_rq *rq)
765772
mlx5e_destroy_rq(rq);
766773
}
767774

775+
static void mlx5e_free_sq_xdp_db(struct mlx5e_sq *sq)
776+
{
777+
kfree(sq->db.xdp.di);
778+
kfree(sq->db.xdp.wqe_info);
779+
}
780+
781+
static int mlx5e_alloc_sq_xdp_db(struct mlx5e_sq *sq, int numa)
782+
{
783+
int wq_sz = mlx5_wq_cyc_get_size(&sq->wq);
784+
785+
sq->db.xdp.di = kzalloc_node(sizeof(*sq->db.xdp.di) * wq_sz,
786+
GFP_KERNEL, numa);
787+
sq->db.xdp.wqe_info = kzalloc_node(sizeof(*sq->db.xdp.wqe_info) * wq_sz,
788+
GFP_KERNEL, numa);
789+
if (!sq->db.xdp.di || !sq->db.xdp.wqe_info) {
790+
mlx5e_free_sq_xdp_db(sq);
791+
return -ENOMEM;
792+
}
793+
794+
return 0;
795+
}
796+
768797
static void mlx5e_free_sq_ico_db(struct mlx5e_sq *sq)
769798
{
770799
kfree(sq->db.ico_wqe);
@@ -819,6 +848,9 @@ static void mlx5e_free_sq_db(struct mlx5e_sq *sq)
819848
case MLX5E_SQ_ICO:
820849
mlx5e_free_sq_ico_db(sq);
821850
break;
851+
case MLX5E_SQ_XDP:
852+
mlx5e_free_sq_xdp_db(sq);
853+
break;
822854
}
823855
}
824856

@@ -829,11 +861,24 @@ static int mlx5e_alloc_sq_db(struct mlx5e_sq *sq, int numa)
829861
return mlx5e_alloc_sq_txq_db(sq, numa);
830862
case MLX5E_SQ_ICO:
831863
return mlx5e_alloc_sq_ico_db(sq, numa);
864+
case MLX5E_SQ_XDP:
865+
return mlx5e_alloc_sq_xdp_db(sq, numa);
832866
}
833867

834868
return 0;
835869
}
836870

871+
static int mlx5e_sq_get_max_wqebbs(u8 sq_type)
872+
{
873+
switch (sq_type) {
874+
case MLX5E_SQ_ICO:
875+
return MLX5E_ICOSQ_MAX_WQEBBS;
876+
case MLX5E_SQ_XDP:
877+
return MLX5E_XDP_TX_WQEBBS;
878+
}
879+
return MLX5_SEND_WQE_MAX_WQEBBS;
880+
}
881+
837882
static int mlx5e_create_sq(struct mlx5e_channel *c,
838883
int tc,
839884
struct mlx5e_sq_param *param,
@@ -844,7 +889,6 @@ static int mlx5e_create_sq(struct mlx5e_channel *c,
844889

845890
void *sqc = param->sqc;
846891
void *sqc_wq = MLX5_ADDR_OF(sqc, sqc, wq);
847-
u16 sq_max_wqebbs;
848892
int err;
849893

850894
sq->type = param->type;
@@ -882,7 +926,6 @@ static int mlx5e_create_sq(struct mlx5e_channel *c,
882926
if (err)
883927
goto err_sq_wq_destroy;
884928

885-
sq_max_wqebbs = MLX5_SEND_WQE_MAX_WQEBBS;
886929
if (sq->type == MLX5E_SQ_TXQ) {
887930
int txq_ix;
888931

@@ -891,10 +934,7 @@ static int mlx5e_create_sq(struct mlx5e_channel *c,
891934
priv->txq_to_sq_map[txq_ix] = sq;
892935
}
893936

894-
if (sq->type == MLX5E_SQ_ICO)
895-
sq_max_wqebbs = MLX5E_ICOSQ_MAX_WQEBBS;
896-
897-
sq->edge = (sq->wq.sz_m1 + 1) - sq_max_wqebbs;
937+
sq->edge = (sq->wq.sz_m1 + 1) - mlx5e_sq_get_max_wqebbs(sq->type);
898938
sq->bf_budget = MLX5E_SQ_BF_BUDGET;
899939

900940
return 0;
@@ -1068,7 +1108,7 @@ static void mlx5e_close_sq(struct mlx5e_sq *sq)
10681108
}
10691109

10701110
mlx5e_disable_sq(sq);
1071-
mlx5e_free_tx_descs(sq);
1111+
mlx5e_free_sq_descs(sq);
10721112
mlx5e_destroy_sq(sq);
10731113
}
10741114

@@ -1429,14 +1469,31 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,
14291469
}
14301470
}
14311471

1472+
if (priv->xdp_prog) {
1473+
/* XDP SQ CQ params are same as normal TXQ sq CQ params */
1474+
err = mlx5e_open_cq(c, &cparam->tx_cq, &c->xdp_sq.cq,
1475+
priv->params.tx_cq_moderation);
1476+
if (err)
1477+
goto err_close_sqs;
1478+
1479+
err = mlx5e_open_sq(c, 0, &cparam->xdp_sq, &c->xdp_sq);
1480+
if (err) {
1481+
mlx5e_close_cq(&c->xdp_sq.cq);
1482+
goto err_close_sqs;
1483+
}
1484+
}
1485+
1486+
c->xdp = !!priv->xdp_prog;
14321487
err = mlx5e_open_rq(c, &cparam->rq, &c->rq);
14331488
if (err)
1434-
goto err_close_sqs;
1489+
goto err_close_xdp_sq;
14351490

14361491
netif_set_xps_queue(netdev, get_cpu_mask(c->cpu), ix);
14371492
*cp = c;
14381493

14391494
return 0;
1495+
err_close_xdp_sq:
1496+
mlx5e_close_sq(&c->xdp_sq);
14401497

14411498
err_close_sqs:
14421499
mlx5e_close_sqs(c);
@@ -1465,9 +1522,13 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,
14651522
static void mlx5e_close_channel(struct mlx5e_channel *c)
14661523
{
14671524
mlx5e_close_rq(&c->rq);
1525+
if (c->xdp)
1526+
mlx5e_close_sq(&c->xdp_sq);
14681527
mlx5e_close_sqs(c);
14691528
mlx5e_close_sq(&c->icosq);
14701529
napi_disable(&c->napi);
1530+
if (c->xdp)
1531+
mlx5e_close_cq(&c->xdp_sq.cq);
14711532
mlx5e_close_cq(&c->rq.cq);
14721533
mlx5e_close_tx_cqs(c);
14731534
mlx5e_close_cq(&c->icosq.cq);
@@ -1618,12 +1679,28 @@ static void mlx5e_build_icosq_param(struct mlx5e_priv *priv,
16181679
param->type = MLX5E_SQ_ICO;
16191680
}
16201681

1682+
static void mlx5e_build_xdpsq_param(struct mlx5e_priv *priv,
1683+
struct mlx5e_sq_param *param)
1684+
{
1685+
void *sqc = param->sqc;
1686+
void *wq = MLX5_ADDR_OF(sqc, sqc, wq);
1687+
1688+
mlx5e_build_sq_param_common(priv, param);
1689+
MLX5_SET(wq, wq, log_wq_sz, priv->params.log_sq_size);
1690+
1691+
param->max_inline = priv->params.tx_max_inline;
1692+
/* FOR XDP SQs will support only L2 inline mode */
1693+
param->min_inline_mode = MLX5_INLINE_MODE_NONE;
1694+
param->type = MLX5E_SQ_XDP;
1695+
}
1696+
16211697
static void mlx5e_build_channel_param(struct mlx5e_priv *priv, struct mlx5e_channel_param *cparam)
16221698
{
16231699
u8 icosq_log_wq_sz = MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE;
16241700

16251701
mlx5e_build_rq_param(priv, &cparam->rq);
16261702
mlx5e_build_sq_param(priv, &cparam->sq);
1703+
mlx5e_build_xdpsq_param(priv, &cparam->xdp_sq);
16271704
mlx5e_build_icosq_param(priv, &cparam->icosq, icosq_log_wq_sz);
16281705
mlx5e_build_rx_cq_param(priv, &cparam->rx_cq);
16291706
mlx5e_build_tx_cq_param(priv, &cparam->tx_cq);

0 commit comments

Comments
 (0)