[dpdk-dev] [PATCH 5/5] net/mlx5: create and destroy eCPRI flex parser

Bing Zhao bingz at mellanox.com
Wed Jul 8 16:43:07 CEST 2020


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 <bingz at mellanox.com>
---
 drivers/net/mlx5/mlx5.c         | 76 +++++++++++++++++++++++++++++++++++++++++
 drivers/net/mlx5/mlx5.h         |  3 ++
 drivers/net/mlx5/mlx5_flow_dv.c | 35 +++----------------
 3 files changed, 83 insertions(+), 31 deletions(-)

diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 07c6add..4f6274d 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -597,6 +597,80 @@ struct mlx5_flow_id_pool *
 		mlx5_ipool_destroy(sh->ipool[i]);
 }
 
+bool
+mlx5_flex_parser_ecpri_exist(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];
+
+	return !!prf->obj;
+}
+
+int
+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;
+
+	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 = 0x2;
+	/* 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. */
+	node.sample[1].flow_match_sample_field_base_offset = 0x4;
+	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] = 0x4;
+	prf->ids[0] = ids[0];
+	prf->ids[1] = ids[1];
+	return 0;
+}
+
+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;
+	return;
+}
+
+
 /**
  * Allocate shared device context. If there is multiport device the
  * master and representors will share this context, if there is single
@@ -1158,6 +1232,8 @@ struct mlx5_dev_ctx_shared *
 	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 07cbaf4..42a8bd5 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -734,6 +734,8 @@ int mlx5_dev_check_sibling_config(struct mlx5_priv *priv,
 int mlx5_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu);
 int mlx5_hairpin_cap_get(struct rte_eth_dev *dev,
 			 struct rte_eth_hairpin_cap *cap);
+bool mlx5_flex_parser_ecpri_exist(struct rte_eth_dev *dev);
+int mlx5_flex_parser_ecpri_alloc(struct rte_eth_dev *dev);
 
 /* mlx5_ethdev.c */
 
@@ -957,4 +959,5 @@ int mlx5_os_read_dev_stat(struct mlx5_priv *priv,
 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);
+
 #endif /* RTE_PMD_MLX5_H_ */
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 523d778..987c635 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -4779,34 +4779,6 @@ struct field_modify_info modify_tcp[] = {
 				  cnt, next);
 }
 
-static inline bool
-flow_dv_flex_parser_ecpri_exist(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];
-
-	return !!prf->obj;
-}
-
-
-static int
-flow_dv_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];
-
-	return 0;
-}
-
-static void
-flow_dv_flex_parser_ecpri_release(struct rte_eth_dev *dev)
-{
-	(void)dev;
-	return;
-}
-
 /**
  * Verify the @p attributes will be correctly understood by the NIC and store
  * them in the @p flow if everything is correct.
@@ -8688,11 +8660,12 @@ struct field_modify_info modify_tcp[] = {
 			last_item = MLX5_FLOW_LAYER_GTP;
 			break;
 		case RTE_FLOW_ITEM_TYPE_ECPRI:
-			if (!flow_dv_flex_parser_ecpri_exist(dev)) {
-				ret = flow_dv_flex_parser_ecpri_alloc(dev);
+			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");
-- 
1.8.3.1



More information about the dev mailing list