From: Alexander Kozyrev <akozy...@nvidia.com> Add ability to create an indirect action handle for METER_MARK. It allows to share one Meter between several different actions.
Signed-off-by: Alexander Kozyrev <akozy...@nvidia.com> --- drivers/net/mlx5/mlx5_flow.c | 6 ++ drivers/net/mlx5/mlx5_flow.h | 25 ++++- drivers/net/mlx5/mlx5_flow_hw.c | 160 +++++++++++++++++++++++++++++++- 3 files changed, 183 insertions(+), 8 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index cbf9c31984..9627ffc979 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -4221,6 +4221,12 @@ flow_action_handles_translate(struct rte_eth_dev *dev, MLX5_RTE_FLOW_ACTION_TYPE_COUNT; translated[handle->index].conf = (void *)(uintptr_t)idx; break; + case MLX5_INDIRECT_ACTION_TYPE_METER_MARK: + translated[handle->index].type = + (enum rte_flow_action_type) + MLX5_RTE_FLOW_ACTION_TYPE_METER_MARK; + translated[handle->index].conf = (void *)(uintptr_t)idx; + break; case MLX5_INDIRECT_ACTION_TYPE_AGE: if (priv->sh->flow_hit_aso_en) { translated[handle->index].type = diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h index e1eb0ab697..30b8e1df99 100644 --- a/drivers/net/mlx5/mlx5_flow.h +++ b/drivers/net/mlx5/mlx5_flow.h @@ -47,6 +47,7 @@ enum mlx5_rte_flow_action_type { MLX5_RTE_FLOW_ACTION_TYPE_COUNT, MLX5_RTE_FLOW_ACTION_TYPE_JUMP, MLX5_RTE_FLOW_ACTION_TYPE_RSS, + MLX5_RTE_FLOW_ACTION_TYPE_METER_MARK, }; /* Private (internal) Field IDs for MODIFY_FIELD action. */ @@ -55,22 +56,35 @@ enum mlx5_rte_flow_field_id { MLX5_RTE_FLOW_FIELD_META_REG, }; -#define MLX5_INDIRECT_ACTION_TYPE_OFFSET 30 +#define MLX5_INDIRECT_ACTION_TYPE_OFFSET 29 enum { MLX5_INDIRECT_ACTION_TYPE_RSS, MLX5_INDIRECT_ACTION_TYPE_AGE, MLX5_INDIRECT_ACTION_TYPE_COUNT, MLX5_INDIRECT_ACTION_TYPE_CT, + MLX5_INDIRECT_ACTION_TYPE_METER_MARK, }; -/* Now, the maximal ports will be supported is 256, action number is 4M. */ -#define MLX5_INDIRECT_ACT_CT_MAX_PORT 0x100 +enum MLX5_SET_MATCHER { + MLX5_SET_MATCHER_SW_V = 1 << 0, + MLX5_SET_MATCHER_SW_M = 1 << 1, + MLX5_SET_MATCHER_HS_V = 1 << 2, + MLX5_SET_MATCHER_HS_M = 1 << 3, +}; + +#define MLX5_SET_MATCHER_SW (MLX5_SET_MATCHER_SW_V | MLX5_SET_MATCHER_SW_M) +#define MLX5_SET_MATCHER_HS (MLX5_SET_MATCHER_HS_V | MLX5_SET_MATCHER_HS_M) +#define MLX5_SET_MATCHER_V (MLX5_SET_MATCHER_SW_V | MLX5_SET_MATCHER_HS_V) +#define MLX5_SET_MATCHER_M (MLX5_SET_MATCHER_SW_M | MLX5_SET_MATCHER_HS_M) + +/* Now, the maximal ports will be supported is 16, action number is 32M. */ +#define MLX5_ACTION_CTX_CT_MAX_PORT 0x10 #define MLX5_INDIRECT_ACT_CT_OWNER_SHIFT 22 #define MLX5_INDIRECT_ACT_CT_OWNER_MASK (MLX5_INDIRECT_ACT_CT_MAX_PORT - 1) -/* 30-31: type, 22-29: owner port, 0-21: index. */ +/* 29-31: type, 25-28: owner port, 0-24: index */ #define MLX5_INDIRECT_ACT_CT_GEN_IDX(owner, index) \ ((MLX5_INDIRECT_ACTION_TYPE_CT << MLX5_INDIRECT_ACTION_TYPE_OFFSET) | \ (((owner) & MLX5_INDIRECT_ACT_CT_OWNER_MASK) << \ @@ -1159,6 +1173,9 @@ struct mlx5_action_construct_data { struct { uint32_t id; } shared_counter; + struct { + uint32_t id; + } shared_meter; }; }; diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c index 90a6c0c78f..e114bf11c1 100644 --- a/drivers/net/mlx5/mlx5_flow_hw.c +++ b/drivers/net/mlx5/mlx5_flow_hw.c @@ -615,6 +615,42 @@ __flow_hw_act_data_shared_cnt_append(struct mlx5_priv *priv, return 0; } +/** + * Append shared meter_mark action to the dynamic action list. + * + * @param[in] priv + * Pointer to the port private data structure. + * @param[in] acts + * Pointer to the template HW steering DR actions. + * @param[in] type + * Action type. + * @param[in] action_src + * Offset of source rte flow action. + * @param[in] action_dst + * Offset of destination DR action. + * @param[in] mtr_id + * Shared meter id. + * + * @return + * 0 on success, negative value otherwise and rte_errno is set. + */ +static __rte_always_inline int +__flow_hw_act_data_shared_mtr_append(struct mlx5_priv *priv, + struct mlx5_hw_actions *acts, + enum rte_flow_action_type type, + uint16_t action_src, + uint16_t action_dst, + cnt_id_t mtr_id) +{ struct mlx5_action_construct_data *act_data; + + act_data = __flow_hw_act_data_alloc(priv, type, action_src, action_dst); + if (!act_data) + return -1; + act_data->type = type; + act_data->shared_meter.id = mtr_id; + LIST_INSERT_HEAD(&acts->act_list, act_data, next); + return 0; +} /** * Translate shared indirect action. @@ -668,6 +704,13 @@ flow_hw_shared_action_translate(struct rte_eth_dev *dev, if (flow_hw_ct_compile(dev, idx, &acts->rule_acts[action_dst])) return -1; break; + case MLX5_INDIRECT_ACTION_TYPE_METER_MARK: + if (__flow_hw_act_data_shared_mtr_append(priv, acts, + (enum rte_flow_action_type) + MLX5_RTE_FLOW_ACTION_TYPE_METER_MARK, + action_src, action_dst, idx)) + return -1; + break; default: DRV_LOG(WARNING, "Unsupported shared action type:%d", type); break; @@ -1682,8 +1725,10 @@ flow_hw_shared_action_construct(struct rte_eth_dev *dev, struct mlx5dr_rule_action *rule_act) { struct mlx5_priv *priv = dev->data->dev_private; + struct mlx5_aso_mtr_pool *pool = priv->hws_mpool; struct mlx5_action_construct_data act_data; struct mlx5_shared_action_rss *shared_rss; + struct mlx5_aso_mtr *aso_mtr; uint32_t act_idx = (uint32_t)(uintptr_t)action->conf; uint32_t type = act_idx >> MLX5_INDIRECT_ACTION_TYPE_OFFSET; uint32_t idx = act_idx & @@ -1719,6 +1764,17 @@ flow_hw_shared_action_construct(struct rte_eth_dev *dev, if (flow_hw_ct_compile(dev, idx, rule_act)) return -1; break; + case MLX5_INDIRECT_ACTION_TYPE_METER_MARK: + /* Find ASO object. */ + aso_mtr = mlx5_ipool_get(pool->idx_pool, idx); + if (!aso_mtr) + return -1; + rule_act->action = pool->action; + rule_act->aso_meter.offset = aso_mtr->offset; + rule_act->aso_meter.init_color = + (enum mlx5dr_action_aso_meter_color) + rte_col_2_mlx5_col(aso_mtr->init_color); + break; default: DRV_LOG(WARNING, "Unsupported shared action type:%d", type); break; @@ -1856,6 +1912,7 @@ flow_hw_actions_construct(struct rte_eth_dev *dev, uint32_t queue) { struct mlx5_priv *priv = dev->data->dev_private; + struct mlx5_aso_mtr_pool *pool = priv->hws_mpool; struct rte_flow_template_table *table = job->flow->table; struct mlx5_action_construct_data *act_data; const struct rte_flow_actions_template *at = hw_at->action_template; @@ -2065,6 +2122,21 @@ flow_hw_actions_construct(struct rte_eth_dev *dev, &rule_acts[act_data->action_dst])) return -1; break; + case MLX5_RTE_FLOW_ACTION_TYPE_METER_MARK: + mtr_id = act_data->shared_meter.id & + ((1u << MLX5_INDIRECT_ACTION_TYPE_OFFSET) - 1); + /* Find ASO object. */ + aso_mtr = mlx5_ipool_get(pool->idx_pool, mtr_id); + if (!aso_mtr) + return -1; + rule_acts[act_data->action_dst].action = + pool->action; + rule_acts[act_data->action_dst].aso_meter.offset = + aso_mtr->offset; + rule_acts[act_data->action_dst].aso_meter.init_color = + (enum mlx5dr_action_aso_meter_color) + rte_col_2_mlx5_col(aso_mtr->init_color); + break; case RTE_FLOW_ACTION_TYPE_METER_MARK: ret = flow_hw_meter_mark_compile(dev, act_data->action_dst, action, @@ -3252,6 +3324,11 @@ flow_hw_dr_actions_template_handle_shared(const struct rte_flow_action *mask, action_types[*curr_off] = MLX5DR_ACTION_TYP_ASO_CT; *curr_off = *curr_off + 1; break; + case RTE_FLOW_ACTION_TYPE_METER_MARK: + at->actions_off[action_src] = *curr_off; + action_types[*curr_off] = MLX5DR_ACTION_TYP_ASO_METER; + *curr_off = *curr_off + 1; + break; default: DRV_LOG(WARNING, "Unsupported shared action type: %d", type); return -EINVAL; @@ -5793,7 +5870,9 @@ flow_hw_action_handle_create(struct rte_eth_dev *dev, uint32_t queue, { struct rte_flow_action_handle *handle = NULL; struct mlx5_priv *priv = dev->data->dev_private; + struct mlx5_aso_mtr *aso_mtr; cnt_id_t cnt_id; + uint32_t mtr_id; RTE_SET_USED(queue); RTE_SET_USED(attr); @@ -5812,6 +5891,14 @@ flow_hw_action_handle_create(struct rte_eth_dev *dev, uint32_t queue, case RTE_FLOW_ACTION_TYPE_CONNTRACK: handle = flow_hw_conntrack_create(dev, queue, action->conf, error); break; + case RTE_FLOW_ACTION_TYPE_METER_MARK: + aso_mtr = flow_hw_meter_mark_alloc(dev, action); + if (!aso_mtr) + break; + mtr_id = (MLX5_INDIRECT_ACTION_TYPE_METER_MARK << + MLX5_INDIRECT_ACTION_TYPE_OFFSET) | (aso_mtr->fm.meter_id); + handle = (struct rte_flow_action_handle *)(uintptr_t)mtr_id; + break; default: handle = flow_dv_action_create(dev, conf, action, error); } @@ -5847,18 +5934,58 @@ flow_hw_action_handle_update(struct rte_eth_dev *dev, uint32_t queue, void *user_data, struct rte_flow_error *error) { - uint32_t act_idx = (uint32_t)(uintptr_t)handle; - uint32_t type = act_idx >> MLX5_INDIRECT_ACTION_TYPE_OFFSET; - RTE_SET_USED(queue); RTE_SET_USED(attr); RTE_SET_USED(user_data); + struct mlx5_priv *priv = dev->data->dev_private; + struct mlx5_aso_mtr_pool *pool = priv->hws_mpool; + const struct rte_flow_update_meter_mark *upd_meter_mark = + (const struct rte_flow_update_meter_mark *)update; + const struct rte_flow_action_meter_mark *meter_mark; + struct mlx5_aso_mtr *aso_mtr; + struct mlx5_flow_meter_info *fm; + uint32_t act_idx = (uint32_t)(uintptr_t)handle; + uint32_t type = act_idx >> MLX5_INDIRECT_ACTION_TYPE_OFFSET; + uint32_t idx = act_idx & ((1u << MLX5_INDIRECT_ACTION_TYPE_OFFSET) - 1); + switch (type) { case MLX5_INDIRECT_ACTION_TYPE_CT: return flow_hw_conntrack_update(dev, queue, update, act_idx, error); + case MLX5_INDIRECT_ACTION_TYPE_METER_MARK: + meter_mark = &upd_meter_mark->meter_mark; + /* Find ASO object. */ + aso_mtr = mlx5_ipool_get(pool->idx_pool, idx); + if (!aso_mtr) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, "Invalid meter_mark update index"); + fm = &aso_mtr->fm; + if (upd_meter_mark->profile_valid) + fm->profile = (struct mlx5_flow_meter_profile *) + (meter_mark->profile); + if (upd_meter_mark->color_mode_valid) + fm->color_aware = meter_mark->color_mode; + if (upd_meter_mark->init_color_valid) + aso_mtr->init_color = (meter_mark->color_mode) ? + meter_mark->init_color : RTE_COLOR_GREEN; + if (upd_meter_mark->state_valid) + fm->is_enable = meter_mark->state; + /* Update ASO flow meter by wqe. */ + if (mlx5_aso_meter_update_by_wqe(priv->sh, aso_mtr, + &priv->mtr_bulk)) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, "Unable to update ASO meter WQE"); + /* Wait for ASO object completion. */ + if (mlx5_aso_mtr_wait(priv->sh, aso_mtr)) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, "Unable to wait for ASO meter CQE"); + return 0; default: - return flow_dv_action_update(dev, handle, update, error); + break; } + return flow_dv_action_update(dev, handle, update, error); } /** @@ -5889,7 +6016,11 @@ flow_hw_action_handle_destroy(struct rte_eth_dev *dev, uint32_t queue, { uint32_t act_idx = (uint32_t)(uintptr_t)handle; uint32_t type = act_idx >> MLX5_INDIRECT_ACTION_TYPE_OFFSET; + uint32_t idx = act_idx & ((1u << MLX5_INDIRECT_ACTION_TYPE_OFFSET) - 1); struct mlx5_priv *priv = dev->data->dev_private; + struct mlx5_aso_mtr_pool *pool = priv->hws_mpool; + struct mlx5_aso_mtr *aso_mtr; + struct mlx5_flow_meter_info *fm; RTE_SET_USED(queue); RTE_SET_USED(attr); @@ -5899,6 +6030,27 @@ flow_hw_action_handle_destroy(struct rte_eth_dev *dev, uint32_t queue, return mlx5_hws_cnt_shared_put(priv->hws_cpool, &act_idx); case MLX5_INDIRECT_ACTION_TYPE_CT: return flow_hw_conntrack_destroy(dev, act_idx, error); + case MLX5_INDIRECT_ACTION_TYPE_METER_MARK: + aso_mtr = mlx5_ipool_get(pool->idx_pool, idx); + if (!aso_mtr) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, "Invalid meter_mark destroy index"); + fm = &aso_mtr->fm; + fm->is_enable = 0; + /* Update ASO flow meter by wqe. */ + if (mlx5_aso_meter_update_by_wqe(priv->sh, aso_mtr, + &priv->mtr_bulk)) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, "Unable to update ASO meter WQE"); + /* Wait for ASO object completion. */ + if (mlx5_aso_mtr_wait(priv->sh, aso_mtr)) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, "Unable to wait for ASO meter CQE"); + mlx5_ipool_free(pool->idx_pool, idx); + return 0; default: return flow_dv_action_destroy(dev, handle, error); } -- 2.25.1