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 <suanmi...@nvidia.com>
Acked-by: Ori Kam <or...@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(-)

diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst
index 84e3c1358c..632fb6e87a 100644
--- a/doc/guides/nics/mlx5.rst
+++ b/doc/guides/nics/mlx5.rst
@@ -743,6 +743,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 1fec295476..f3423933c0 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -361,6 +361,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)
@@ -370,7 +371,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 1777cda9f7..813a035e77 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,
@@ -8219,6 +8265,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,
@@ -8307,6 +8358,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));
@@ -8379,6 +8432,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);
-- 
2.34.1

Reply via email to