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> --- 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 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); -- 2.34.1