[1/3] net/mlx5: add port representor action

Message ID 20231017004401.698745-2-suanmingm@nvidia.com (mailing list archive)
State Superseded, archived
Delegated to: Raslan Darawsheh
Headers
Series net/mlx5: add port representor destination to mirror |

Checks

Context Check Description
ci/loongarch-compilation warning apply patch failure
ci/checkpatch success coding style OK
ci/iol-testing warning apply patch failure

Commit Message

Suanming Mou Oct. 17, 2023, 12:43 a.m. UTC
  The packets handled by port representor action will be steered to
E-Switch manager and received by software.

This commit adds port representor action.

Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
---
 doc/guides/nics/mlx5.rst        |  6 ++++
 drivers/net/mlx5/mlx5.h         |  2 ++
 drivers/net/mlx5/mlx5_flow.h    |  4 ++-
 drivers/net/mlx5/mlx5_flow_hw.c | 55 +++++++++++++++++++++++++++++++++
 4 files changed, 66 insertions(+), 1 deletion(-)
  

Patch

diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst
index 7086f3d1d4..3c1da980e2 100644
--- a/doc/guides/nics/mlx5.rst
+++ b/doc/guides/nics/mlx5.rst
@@ -728,6 +728,12 @@  Limitations
   The flow engine of a process cannot move from active to standby mode
   if preceding active application rules are still present and vice versa.
 
+- A driver limitation for ``RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR`` action restricts
+  the ``port_id`` configuration to only accept the value 0xffff, indicating the E-Switch
+  manager. If the ``repr_matching_en`` flag is enabled, the traffic will be directed
+  to the representor of the source virtual port (SF/VF), while if it is disabled, the
+  traffic will be routed based on the steering rules in the ingress domain.
+
 
 Statistics
 ----------
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index f3b872f59c..dad3600aa0 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -1858,6 +1858,8 @@  struct mlx5_priv {
 	struct mlx5dr_action *hw_drop[2];
 	/* HW steering global tag action. */
 	struct mlx5dr_action *hw_tag[2];
+	/* HW steering global default miss action. */
+	struct mlx5dr_action *hw_def_miss;
 	/* HW steering global send to kernel action. */
 	struct mlx5dr_action *hw_send_to_kernel[MLX5DR_TABLE_TYPE_MAX];
 	/* HW steering create ongoing rte flow table list header. */
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 53c11651c8..a851c6b506 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -359,6 +359,7 @@  enum mlx5_feature_name {
 #define MLX5_FLOW_ACTION_INDIRECT_COUNT (1ull << 43)
 #define MLX5_FLOW_ACTION_INDIRECT_AGE (1ull << 44)
 #define MLX5_FLOW_ACTION_QUOTA (1ull << 46)
+#define MLX5_FLOW_ACTION_PORT_REPRESENTOR (1ull << 47)
 
 #define MLX5_FLOW_DROP_INCLUSIVE_ACTIONS \
 	(MLX5_FLOW_ACTION_COUNT | MLX5_FLOW_ACTION_SAMPLE | MLX5_FLOW_ACTION_AGE)
@@ -368,7 +369,8 @@  enum mlx5_feature_name {
 	 MLX5_FLOW_ACTION_RSS | MLX5_FLOW_ACTION_JUMP | \
 	 MLX5_FLOW_ACTION_DEFAULT_MISS | \
 	 MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY | \
-	 MLX5_FLOW_ACTION_SEND_TO_KERNEL)
+	 MLX5_FLOW_ACTION_SEND_TO_KERNEL | \
+	 MLX5_FLOW_ACTION_PORT_REPRESENTOR)
 
 #define MLX5_FLOW_FATE_ESWITCH_ACTIONS \
 	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_PORT_ID | \
diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index 5114cc1920..9feb40ddb3 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -1726,6 +1726,13 @@  __flow_hw_actions_translate(struct rte_eth_dev *dev,
 			acts->rule_acts[dr_pos].action =
 				priv->hw_drop[!!attr->group];
 			break;
+		case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
+			if (!attr->group) {
+				DRV_LOG(ERR, "Port representor is not supported in root table.");
+				goto err;
+			}
+			acts->rule_acts[dr_pos].action = priv->hw_def_miss;
+			break;
 		case RTE_FLOW_ACTION_TYPE_MARK:
 			acts->mark = true;
 			if (masks->conf &&
@@ -4140,6 +4147,36 @@  flow_hw_validate_action_modify_field(const struct rte_flow_action *action,
 				"MPLS cannot be used as destination");
 	return 0;
 }
+static int
+flow_hw_validate_action_port_representor(struct rte_eth_dev *dev __rte_unused,
+					 const struct rte_flow_actions_template_attr *attr,
+					 const struct rte_flow_action *action,
+					 const struct rte_flow_action *mask,
+					 struct rte_flow_error *error)
+{
+	const struct rte_flow_action_ethdev *action_conf = NULL;
+	const struct rte_flow_action_ethdev *mask_conf = NULL;
+
+	/* If transfer is set, port has been validated as proxy port. */
+	if (!attr->transfer)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					  "cannot use port_representor actions"
+					  " without an E-Switch");
+	if (!action || !mask)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					  "actiona and mask configuration must be set");
+	action_conf = action->conf;
+	mask_conf = mask->conf;
+	if (!mask_conf || mask_conf->port_id != MLX5_REPRESENTED_PORT_ESW_MGR ||
+	    !action_conf || action_conf->port_id != MLX5_REPRESENTED_PORT_ESW_MGR)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					  "only eswitch manager port 0xffff is"
+					  " supported");
+	return 0;
+}
 
 static int
 flow_hw_validate_action_represented_port(struct rte_eth_dev *dev,
@@ -4504,6 +4541,7 @@  flow_hw_template_expand_modify_field(struct rte_flow_action actions[],
 		case RTE_FLOW_ACTION_TYPE_QUEUE:
 		case RTE_FLOW_ACTION_TYPE_RSS:
 		case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
+		case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
 		case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
 		case RTE_FLOW_ACTION_TYPE_VOID:
 		case RTE_FLOW_ACTION_TYPE_END:
@@ -4740,6 +4778,13 @@  mlx5_flow_hw_actions_validate(struct rte_eth_dev *dev,
 				return ret;
 			action_flags |= MLX5_FLOW_ACTION_PORT_ID;
 			break;
+		case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
+			ret = flow_hw_validate_action_port_representor
+					(dev, attr, action, mask, error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_FLOW_ACTION_PORT_REPRESENTOR;
+			break;
 		case RTE_FLOW_ACTION_TYPE_AGE:
 			if (count_mask && count_mask->id)
 				fixed_cnt = true;
@@ -4818,6 +4863,7 @@  static enum mlx5dr_action_type mlx5_hw_dr_action_types[] = {
 	[RTE_FLOW_ACTION_TYPE_NVGRE_DECAP] = MLX5DR_ACTION_TYP_REFORMAT_TNL_L2_TO_L2,
 	[RTE_FLOW_ACTION_TYPE_MODIFY_FIELD] = MLX5DR_ACTION_TYP_MODIFY_HDR,
 	[RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT] = MLX5DR_ACTION_TYP_VPORT,
+	[RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR] = MLX5DR_ACTION_TYP_MISS,
 	[RTE_FLOW_ACTION_TYPE_CONNTRACK] = MLX5DR_ACTION_TYP_ASO_CT,
 	[RTE_FLOW_ACTION_TYPE_OF_POP_VLAN] = MLX5DR_ACTION_TYP_POP_VLAN,
 	[RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN] = MLX5DR_ACTION_TYP_PUSH_VLAN,
@@ -8215,6 +8261,11 @@  flow_hw_configure(struct rte_eth_dev *dev,
 			goto err;
 	}
 	if (is_proxy) {
+		/* Only supported on proxy port. */
+		priv->hw_def_miss = mlx5dr_action_create_default_miss
+			(priv->dr_ctx, MLX5DR_ACTION_FLAG_HWS_FDB);
+		if (!priv->hw_def_miss)
+			goto err;
 		ret = flow_hw_create_vport_actions(priv);
 		if (ret) {
 			rte_flow_error_set(error, -ret, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
@@ -8303,6 +8354,8 @@  flow_hw_configure(struct rte_eth_dev *dev,
 		if (priv->hw_tag[i])
 			mlx5dr_action_destroy(priv->hw_tag[i]);
 	}
+	if (priv->hw_def_miss)
+		mlx5dr_action_destroy(priv->hw_def_miss);
 	flow_hw_destroy_vlan(dev);
 	if (dr_ctx)
 		claim_zero(mlx5dr_context_close(dr_ctx));
@@ -8375,6 +8428,8 @@  flow_hw_resource_release(struct rte_eth_dev *dev)
 		if (priv->hw_tag[i])
 			mlx5dr_action_destroy(priv->hw_tag[i]);
 	}
+	if (priv->hw_def_miss)
+		mlx5dr_action_destroy(priv->hw_def_miss);
 	flow_hw_destroy_vlan(dev);
 	flow_hw_destroy_send_to_kernel_action(priv);
 	flow_hw_free_vport_actions(priv);