From 1c5064044fbe5bfa0bc1f33041b52414964bbd89 Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Fri, 17 Jul 2020 15:11:49 +0800 Subject: [PATCH] net/mlx5: create and destroy eCPRI flex parser eCPRI protocol has unified format layout for the variants, over ETH layer (including .1Q) and UDP layer. The common header of the message has 4 bytes fixed length, and the message payload layers are different based on the type field. Now only type #0, #2 and #5 will be supported, and 2 bytes are needed. When creating the flex parser, the header will be extended to 8 bytes and 2 DW samples are needed. The 1st DW starts from offset 0 and will be used for the type field of the common header. The 2nd DW starts from offset 4 and will be used for the physical channel ID, real-time control ID or measurement ID fields. The parser will be created once a flow with eCPRI item is observed for the first time. After creating, it will remain in the system and HW until the device is stopped. Right now, there is no need to destroy the eCPRI flex parser after the last flow with eCPRI item is destroyed. This is to get rid of the alternate states of creating and destroying eCPRI flex parser with a single eCPRI flow. Signed-off-by: Bing Zhao Acked-by: Viacheslav Ovsiienko --- drivers/net/mlx5/mlx5.c | 64 ++++++++++++++++++++++++++++++++- drivers/net/mlx5/mlx5.h | 1 + drivers/net/mlx5/mlx5_flow_dv.c | 3 +- 3 files changed, 66 insertions(+), 2 deletions(-) diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c index 1ba5e0c90c..8fcb78a792 100644 --- a/drivers/net/mlx5/mlx5.c +++ b/drivers/net/mlx5/mlx5.c @@ -643,11 +643,71 @@ mlx5_flex_parser_ecpri_alloc(struct rte_eth_dev *dev) struct mlx5_priv *priv = dev->data->dev_private; struct mlx5_flex_parser_profiles *prf = &priv->sh->fp[MLX5_FLEX_PARSER_ECPRI_0]; + struct mlx5_devx_graph_node_attr node = { + .modify_field_select = 0, + }; + uint32_t ids[8]; + int ret; - (void)prf; + node.header_length_mode = MLX5_GRAPH_NODE_LEN_FIXED; + /* 8 bytes now: 4B common header + 4B message body header. */ + node.header_length_base_value = 0x8; + /* After MAC layer: Ether / VLAN. */ + node.in[0].arc_parse_graph_node = MLX5_GRAPH_ARC_NODE_MAC; + /* Type of compared condition should be 0xAEFE in the L2 layer. */ + node.in[0].compare_condition_value = RTE_ETHER_TYPE_ECPRI; + /* Sample #0: type in common header. */ + node.sample[0].flow_match_sample_en = 1; + /* Fixed offset. */ + node.sample[0].flow_match_sample_offset_mode = 0x0; + /* Only the 2nd byte will be used. */ + node.sample[0].flow_match_sample_field_base_offset = 0x0; + /* Sample #1: message payload. */ + node.sample[1].flow_match_sample_en = 1; + /* Fixed offset. */ + node.sample[1].flow_match_sample_offset_mode = 0x0; + /* + * Only the first two bytes will be used right now, and its offset will + * start after the common header that with the length of a DW(u32). + */ + node.sample[1].flow_match_sample_field_base_offset = sizeof(uint32_t); + prf->obj = mlx5_devx_cmd_create_flex_parser(priv->sh->ctx, &node); + if (!prf->obj) { + DRV_LOG(ERR, "Failed to create flex parser node object."); + return (rte_errno == 0) ? -ENODEV : -rte_errno; + } + prf->num = 2; + ret = mlx5_devx_cmd_query_parse_samples(prf->obj, ids, prf->num); + if (ret) { + DRV_LOG(ERR, "Failed to query sample IDs."); + return (rte_errno == 0) ? -ENODEV : -rte_errno; + } + prf->offset[0] = 0x0; + prf->offset[1] = sizeof(uint32_t); + prf->ids[0] = ids[0]; + prf->ids[1] = ids[1]; return 0; } +/* + * Destroy the flex parser node, including the parser itself, input / output + * arcs and DW samples. Resources could be reused then. + * + * @param dev + * Pointer to Ethernet device structure. + */ +static void +mlx5_flex_parser_ecpri_release(struct rte_eth_dev *dev) +{ + struct mlx5_priv *priv = dev->data->dev_private; + struct mlx5_flex_parser_profiles *prf = + &priv->sh->fp[MLX5_FLEX_PARSER_ECPRI_0]; + + if (prf->obj) + mlx5_devx_cmd_destroy(prf->obj); + prf->obj = NULL; +} + /** * Allocate shared device context. If there is multiport device the * master and representors will share this context, if there is single @@ -1231,6 +1291,8 @@ mlx5_dev_close(struct rte_eth_dev *dev) rte_wmb(); /* Disable datapath on secondary process. */ mlx5_mp_req_stop_rxtx(dev); + /* Free the eCPRI flex parser resource. */ + mlx5_flex_parser_ecpri_release(dev); if (priv->rxqs != NULL) { /* XXX race condition if mlx5_rx_burst() is still running. */ usleep(1000); diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 61abe4a51f..2e61d0cba4 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -1025,6 +1025,7 @@ int mlx5_os_get_stats_n(struct rte_eth_dev *dev); void mlx5_os_stats_init(struct rte_eth_dev *dev); void mlx5_os_set_reg_mr_cb(mlx5_reg_mr_t *reg_mr_cb, mlx5_dereg_mr_t *dereg_mr_cb); + /* mlx5_txpp.c */ int mlx5_txpp_start(struct rte_eth_dev *dev); diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c index a9202d5cad..555c62a3bb 100644 --- a/drivers/net/mlx5/mlx5_flow_dv.c +++ b/drivers/net/mlx5/mlx5_flow_dv.c @@ -8671,10 +8671,11 @@ __flow_dv_translate(struct rte_eth_dev *dev, break; case RTE_FLOW_ITEM_TYPE_ECPRI: if (!mlx5_flex_parser_ecpri_exist(dev)) { + /* Create it only the first time to be used. */ ret = mlx5_flex_parser_ecpri_alloc(dev); if (ret) return rte_flow_error_set - (error, ret, + (error, -ret, RTE_FLOW_ERROR_TYPE_ITEM, NULL, "cannot create eCPRI parser"); -- 2.20.1