diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst index d331e48ce7..8775777072 100644 --- a/doc/guides/nics/mlx5.rst +++ b/doc/guides/nics/mlx5.rst @@ -473,6 +473,10 @@ Limitations - meter profile packet mode is supported. - meter profiles of RFC2697, RFC2698 and RFC4115 are supported. - RFC4115 implementation is following MEF, meaning yellow traffic may reclaim unused green bandwidth when green token bucket is full. + - When using DV flow engine (``dv_flow_en`` = 1), + if meter has drop count + or meter hierarchy contains any meter that uses drop count, + it cannot be used by flow rule matching all ports. - Integrity: diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index d3babdbb61..95ecbea39e 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -775,6 +775,8 @@ struct mlx5_flow_meter_policy { /* Is queue action in policy table. */ uint32_t is_hierarchy:1; /* Is meter action in policy table. */ + uint32_t hierarchy_drop_cnt:1; + /* Is any meter in hierarchy contains drop_cnt. */ uint32_t skip_y:1; /* If yellow color policy is skipped. */ uint32_t skip_g:1; diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index e93b6e144c..2038c4a6c0 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -5338,6 +5338,7 @@ flow_meter_split_prep(struct rte_eth_dev *dev, switch (item_type) { case RTE_FLOW_ITEM_TYPE_PORT_ID: case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT: + if (mlx5_flow_get_item_vport_id(dev, items, &flow_src_port, NULL, error)) return -rte_errno; if (!fm->def_policy && wks->policy->is_hierarchy && flow_src_port != priv->representor_id) { @@ -11012,6 +11013,8 @@ int16_t mlx5_flow_get_esw_manager_vport_id(struct rte_eth_dev *dev) * The src port id match item. * @param[out] vport_id * Pointer to put the vport id. + * @param[out] all_ports + * Indicate if the item matches all ports. * @param[out] error * Pointer to error structure. * @@ -11021,6 +11024,7 @@ int16_t mlx5_flow_get_esw_manager_vport_id(struct rte_eth_dev *dev) int mlx5_flow_get_item_vport_id(struct rte_eth_dev *dev, const struct rte_flow_item *item, uint16_t *vport_id, + bool *all_ports, struct rte_flow_error *error) { struct mlx5_priv *port_priv; @@ -11032,8 +11036,13 @@ int mlx5_flow_get_item_vport_id(struct rte_eth_dev *dev, return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC, NULL, "Incorrect item type."); pid_v = item->spec; - if (!pid_v) + if (!pid_v) { + if (all_ports) + *all_ports = (item->type == RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT); return 0; + } + if (all_ports) + *all_ports = false; esw_mgr_port = (item->type == RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT) ? MLX5_REPRESENTED_PORT_ESW_MGR : MLX5_PORT_ESW_MGR; if (pid_v->id == esw_mgr_port) { diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h index 2f265763a9..0fa1735b1a 100644 --- a/drivers/net/mlx5/mlx5_flow.h +++ b/drivers/net/mlx5/mlx5_flow.h @@ -2087,6 +2087,7 @@ int16_t mlx5_flow_get_esw_manager_vport_id(struct rte_eth_dev *dev); int mlx5_flow_get_item_vport_id(struct rte_eth_dev *dev, const struct rte_flow_item *item, uint16_t *vport_id, + bool *all_ports, struct rte_flow_error *error); #endif /* RTE_PMD_MLX5_FLOW_H_ */ diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c index ec6274f670..91f287af5c 100644 --- a/drivers/net/mlx5/mlx5_flow_dv.c +++ b/drivers/net/mlx5/mlx5_flow_dv.c @@ -5245,6 +5245,8 @@ mlx5_flow_validate_action_meter(struct rte_eth_dev *dev, struct mlx5_flow_meter_info *fm; struct mlx5_flow_meter_policy *mtr_policy; struct mlx5_flow_mtr_mng *mtrmng = priv->sh->mtrmng; + uint16_t flow_src_port = priv->representor_id; + bool all_ports = false; if (!am) return rte_flow_error_set(error, EINVAL, @@ -5307,27 +5309,34 @@ mlx5_flow_validate_action_meter(struct rte_eth_dev *dev, "Flow attributes domain " "have a conflict with current " "meter domain attributes"); - if (attr->transfer && mtr_policy->dev) { - /** - * When policy has fate action of port_id, - * the flow should have the same src port as policy. - */ - struct mlx5_priv *policy_port_priv = - mtr_policy->dev->data->dev_private; - uint16_t flow_src_port = priv->representor_id; + if (port_id_item) { + if (mlx5_flow_get_item_vport_id(dev, port_id_item, &flow_src_port, + &all_ports, error)) + return -rte_errno; + } + if (attr->transfer) { + if (mtr_policy->dev) { + /** + * When policy has fate action of port_id, + * the flow should have the same src port as policy. + */ + struct mlx5_priv *policy_port_priv = + mtr_policy->dev->data->dev_private; - if (port_id_item) { - if (mlx5_flow_get_item_vport_id(dev, port_id_item, - &flow_src_port, error)) - return -rte_errno; + if (all_ports || flow_src_port != policy_port_priv->representor_id) + return rte_flow_error_set(error, + rte_errno, + RTE_FLOW_ERROR_TYPE_ITEM_SPEC, + NULL, + "Flow and meter policy " + "have different src port."); } - if (flow_src_port != policy_port_priv->representor_id) - return rte_flow_error_set(error, - rte_errno, - RTE_FLOW_ERROR_TYPE_ITEM_SPEC, - NULL, - "Flow and meter policy " - "have different src port."); + /* When flow matching all src ports, meter should not have drop count. */ + if (all_ports && (fm->drop_cnt || mtr_policy->hierarchy_drop_cnt)) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM_SPEC, NULL, + "Meter drop count not supported " + "when matching all ports."); } else if (mtr_policy->is_rss) { struct mlx5_flow_meter_policy *fp; struct mlx5_meter_policy_action_container *acg; @@ -16251,6 +16260,8 @@ __flow_dv_create_domain_policy_acts(struct rte_eth_dev *dev, mtr_policy->dev = next_policy->dev; if (next_policy->mark) mtr_policy->mark = 1; + if (next_fm->drop_cnt || next_policy->hierarchy_drop_cnt) + mtr_policy->hierarchy_drop_cnt = 1; action_flags |= MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY; break;