X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fmlx5%2Fmlx5_flow_meter.c;h=78eb2a60f971d3d79e0ae2e298719cf8c078e8c2;hb=919488fbfa7121887410f3863f674d99dabc7d64;hp=e97a1d77a6ecef6dd39314acd59a3fb84052470c;hpb=4443201863933b27274a2ffc0d648bebc90e6b9b;p=dpdk.git diff --git a/drivers/net/mlx5/mlx5_flow_meter.c b/drivers/net/mlx5/mlx5_flow_meter.c index e97a1d77a6..78eb2a60f9 100644 --- a/drivers/net/mlx5/mlx5_flow_meter.c +++ b/drivers/net/mlx5/mlx5_flow_meter.c @@ -91,13 +91,20 @@ mlx5_flow_meter_action_create(struct mlx5_priv *priv, static struct mlx5_flow_meter_profile * mlx5_flow_meter_profile_find(struct mlx5_priv *priv, uint32_t meter_profile_id) { - struct mlx5_mtr_profiles *fmps = &priv->flow_meter_profiles; struct mlx5_flow_meter_profile *fmp; + union mlx5_l3t_data data; + int32_t ret; - TAILQ_FOREACH(fmp, fmps, next) - if (meter_profile_id == fmp->id) - return fmp; - return NULL; + if (mlx5_l3t_get_entry(priv->mtr_profile_tbl, + meter_profile_id, &data) || !data.ptr) + return NULL; + fmp = data.ptr; + /* Remove reference taken by the mlx5_l3t_get_entry. */ + ret = mlx5_l3t_clear_entry(priv->mtr_profile_tbl, + meter_profile_id); + if (!ret || ret == -1) + return NULL; + return fmp; } /** @@ -144,13 +151,19 @@ mlx5_flow_meter_profile_validate(struct rte_eth_dev *dev, if (profile->alg == RTE_MTR_SRTCM_RFC2697) { if (priv->config.hca_attr.qos.flow_meter_old) { /* Verify support for flow meter parameters. */ - if (profile->srtcm_rfc2697.cir > 0 && - profile->srtcm_rfc2697.cir <= MLX5_SRTCM_CIR_MAX && - profile->srtcm_rfc2697.cbs > 0 && - profile->srtcm_rfc2697.cbs <= MLX5_SRTCM_CBS_MAX && - profile->srtcm_rfc2697.ebs <= MLX5_SRTCM_EBS_MAX) - return 0; - else + if (priv->sh->meter_aso_en && profile->packet_mode) { + if (profile->srtcm_rfc2697.cir > 0 && + (profile->srtcm_rfc2697.cir << + MLX5_MTRS_PPS_MAP_BPS_SHIFT) + <= MLX5_SRTCM_CIR_MAX && + profile->srtcm_rfc2697.cbs > 0 && + (profile->srtcm_rfc2697.cbs << + MLX5_MTRS_PPS_MAP_BPS_SHIFT) + <= MLX5_SRTCM_CBS_MAX && + (profile->srtcm_rfc2697.ebs << + MLX5_MTRS_PPS_MAP_BPS_SHIFT) + <= MLX5_SRTCM_EBS_MAX) + return 0; return -rte_mtr_error_set (error, ENOTSUP, RTE_MTR_ERROR_TYPE_MTR_PARAMS, @@ -158,6 +171,22 @@ mlx5_flow_meter_profile_validate(struct rte_eth_dev *dev, profile->srtcm_rfc2697.ebs ? "Metering value ebs must be 0." : "Invalid metering parameters."); + } + if (profile->srtcm_rfc2697.cir > 0 && + profile->srtcm_rfc2697.cir <= + MLX5_SRTCM_CIR_MAX && + profile->srtcm_rfc2697.cbs > 0 && + profile->srtcm_rfc2697.cbs <= + MLX5_SRTCM_CBS_MAX && + profile->srtcm_rfc2697.ebs <= + MLX5_SRTCM_EBS_MAX) + return 0; + return -rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_MTR_PARAMS, + NULL, + profile->srtcm_rfc2697.ebs ? + "Metering value ebs must be 0." : + "Invalid metering parameters."); } } return -rte_mtr_error_set(error, ENOTSUP, @@ -241,20 +270,36 @@ mlx5_flow_meter_xbs_man_exp_calc(uint64_t xbs, uint8_t *man, uint8_t *exp) */ static int mlx5_flow_meter_param_fill(struct mlx5_flow_meter_profile *fmp, - struct rte_mtr_error *error) + struct mlx5_priv *priv, struct rte_mtr_error *error) { struct mlx5_flow_meter_srtcm_rfc2697_prm *srtcm = &fmp->srtcm_prm; uint8_t man, exp; uint32_t cbs_exp, cbs_man, cir_exp, cir_man; uint32_t ebs_exp, ebs_man; + uint64_t cir, cbs, ebs; if (fmp->profile.alg != RTE_MTR_SRTCM_RFC2697) return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, "Metering algorithm not supported."); + if (!priv->sh->meter_aso_en && fmp->profile.packet_mode) + return -rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_METER_PROFILE, + NULL, "Metering algorithm packet mode not supported."); + if (priv->sh->meter_aso_en && fmp->profile.packet_mode) { + cir = fmp->profile.srtcm_rfc2697.cir << + MLX5_MTRS_PPS_MAP_BPS_SHIFT; + cbs = fmp->profile.srtcm_rfc2697.cbs << + MLX5_MTRS_PPS_MAP_BPS_SHIFT; + ebs = fmp->profile.srtcm_rfc2697.ebs << + MLX5_MTRS_PPS_MAP_BPS_SHIFT; + } else { + cir = fmp->profile.srtcm_rfc2697.cir; + cbs = fmp->profile.srtcm_rfc2697.cbs; + ebs = fmp->profile.srtcm_rfc2697.ebs; + } /* cir = 8G * cir_mantissa * 1/(2^cir_exponent)) Bytes/Sec */ - mlx5_flow_meter_cir_man_exp_calc(fmp->profile.srtcm_rfc2697.cir, - &man, &exp); + mlx5_flow_meter_cir_man_exp_calc(cir, &man, &exp); /* Check if cir mantissa is too large. */ if (exp > ASO_DSEG_CIR_EXP_MASK) return -rte_mtr_error_set(error, ENOTSUP, @@ -264,8 +309,7 @@ mlx5_flow_meter_param_fill(struct mlx5_flow_meter_profile *fmp, cir_man = man; cir_exp = exp; /* cbs = cbs_mantissa * 2^cbs_exponent */ - mlx5_flow_meter_xbs_man_exp_calc(fmp->profile.srtcm_rfc2697.cbs, - &man, &exp); + mlx5_flow_meter_xbs_man_exp_calc(cbs, &man, &exp); /* Check if cbs mantissa is too large. */ if (exp > ASO_DSEG_EXP_MASK) return -rte_mtr_error_set(error, ENOTSUP, @@ -278,8 +322,7 @@ mlx5_flow_meter_param_fill(struct mlx5_flow_meter_profile *fmp, cbs_man << ASO_DSEG_CBS_MAN_OFFSET | cir_exp << ASO_DSEG_CIR_EXP_OFFSET | cir_man); - mlx5_flow_meter_xbs_man_exp_calc(fmp->profile.srtcm_rfc2697.ebs, - &man, &exp); + mlx5_flow_meter_xbs_man_exp_calc(ebs, &man, &exp); /* Check if ebs mantissa is too large. */ if (exp > ASO_DSEG_EXP_MASK) return -rte_mtr_error_set(error, ENOTSUP, @@ -319,11 +362,15 @@ mlx5_flow_mtr_cap_get(struct rte_eth_dev *dev, RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, "Meter is not supported"); memset(cap, 0, sizeof(*cap)); - if (priv->sh->meter_aso_en) + if (priv->sh->meter_aso_en) { /* 2 meters per one ASO cache line. */ cap->n_max = 1 << (qattr->log_max_num_meter_aso + 1); - else + cap->srtcm_rfc2697_packet_mode_supported = 1; + } else { cap->n_max = 1 << qattr->log_max_flow_meter; + cap->srtcm_rfc2697_packet_mode_supported = 0; + } + cap->srtcm_rfc2697_byte_mode_supported = 1; cap->n_shared_max = cap->n_max; cap->identical = 1; cap->shared_identical = 1; @@ -359,8 +406,8 @@ mlx5_flow_meter_profile_add(struct rte_eth_dev *dev, struct rte_mtr_error *error) { struct mlx5_priv *priv = dev->data->dev_private; - struct mlx5_mtr_profiles *fmps = &priv->flow_meter_profiles; struct mlx5_flow_meter_profile *fmp; + union mlx5_l3t_data data; int ret; if (!priv->mtr_en) @@ -384,11 +431,16 @@ mlx5_flow_meter_profile_add(struct rte_eth_dev *dev, fmp->id = meter_profile_id; fmp->profile = *profile; /* Fill the flow meter parameters for the PRM. */ - ret = mlx5_flow_meter_param_fill(fmp, error); + ret = mlx5_flow_meter_param_fill(fmp, priv, error); if (ret) goto error; - /* Add to list. */ - TAILQ_INSERT_TAIL(fmps, fmp, next); + data.ptr = fmp; + ret = mlx5_l3t_set_entry(priv->mtr_profile_tbl, + meter_profile_id, &data); + if (ret) + return -rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, + NULL, "Meter profile insert fail."); return 0; error: mlx5_free(fmp); @@ -432,8 +484,10 @@ mlx5_flow_meter_profile_delete(struct rte_eth_dev *dev, return -rte_mtr_error_set(error, EBUSY, RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, NULL, "Meter profile is in use."); - /* Remove from list. */ - TAILQ_REMOVE(&priv->flow_meter_profiles, fmp, next); + if (mlx5_l3t_clear_entry(priv->mtr_profile_tbl, meter_profile_id)) + return -rte_mtr_error_set(error, EBUSY, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + NULL, "Meter profile remove fail."); mlx5_free(fmp); return 0; } @@ -458,11 +512,9 @@ mlx5_flow_meter_policy_find(struct rte_eth_dev *dev, struct mlx5_flow_meter_sub_policy *sub_policy = NULL; union mlx5_l3t_data data; - if (policy_id > MLX5_MAX_SUB_POLICY_TBL_NUM || - !priv->sh->mtrmng->policy_idx_tbl) + if (policy_id > MLX5_MAX_SUB_POLICY_TBL_NUM || !priv->policy_idx_tbl) return NULL; - if (mlx5_l3t_get_entry(priv->sh->mtrmng->policy_idx_tbl, - policy_id, &data) || + if (mlx5_l3t_get_entry(priv->policy_idx_tbl, policy_id, &data) || !data.dword) return NULL; if (policy_idx) @@ -470,14 +522,44 @@ mlx5_flow_meter_policy_find(struct rte_eth_dev *dev, sub_policy = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MTR_POLICY], data.dword); /* Remove reference taken by the mlx5_l3t_get_entry. */ - mlx5_l3t_clear_entry(priv->sh->mtrmng->policy_idx_tbl, - policy_id); + mlx5_l3t_clear_entry(priv->policy_idx_tbl, policy_id); if (sub_policy) if (sub_policy->main_policy_id) return sub_policy->main_policy; return NULL; } +/** + * Get the last meter's policy from one meter's policy in hierarchy. + * + * @param[in] dev + * Pointer to Ethernet device. + * @param[in] policy + * Pointer to flow meter policy. + * + * @return + * Pointer to the final meter's policy, or NULL when fail. + */ +struct mlx5_flow_meter_policy * +mlx5_flow_meter_hierarchy_get_final_policy(struct rte_eth_dev *dev, + struct mlx5_flow_meter_policy *policy) +{ + struct mlx5_priv *priv = dev->data->dev_private; + struct mlx5_flow_meter_info *next_fm; + struct mlx5_flow_meter_policy *next_policy = policy; + + while (next_policy->is_hierarchy) { + next_fm = mlx5_flow_meter_find(priv, + next_policy->act_cnt[RTE_COLOR_GREEN].next_mtr_id, NULL); + if (!next_fm || next_fm->def_policy) + return NULL; + next_policy = mlx5_flow_meter_policy_find(dev, + next_fm->policy_id, NULL); + MLX5_ASSERT(next_policy); + } + return next_policy; +} + /** * Callback to check MTR policy action validate * @@ -519,7 +601,8 @@ static int __mlx5_flow_meter_policy_delete(struct rte_eth_dev *dev, uint32_t policy_id, struct mlx5_flow_meter_policy *mtr_policy, - struct rte_mtr_error *error) + struct rte_mtr_error *error, + bool clear_l3t) { struct mlx5_priv *priv = dev->data->dev_private; struct mlx5_flow_meter_sub_policy *sub_policy; @@ -550,9 +633,8 @@ __mlx5_flow_meter_policy_delete(struct rte_eth_dev *dev, } } } - if (priv->sh->mtrmng->policy_idx_tbl) { - if (mlx5_l3t_clear_entry(priv->sh->mtrmng->policy_idx_tbl, - policy_id)) { + if (priv->policy_idx_tbl && clear_l3t) { + if (mlx5_l3t_clear_entry(priv->policy_idx_tbl, policy_id)) { rte_spinlock_unlock(&mtr_policy->sl); return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL, @@ -599,6 +681,7 @@ mlx5_flow_meter_policy_add(struct rte_eth_dev *dev, uint16_t sub_policy_num; uint8_t domain_bitmap = 0; union mlx5_l3t_data data; + bool skip_rule = false; if (!priv->mtr_en) return -rte_mtr_error_set(error, ENOTSUP, @@ -708,27 +791,34 @@ mlx5_flow_meter_policy_add(struct rte_eth_dev *dev, policy->actions, error); if (ret) goto policy_add_err; - if (!is_rss) { + if (mtr_policy->is_hierarchy) { + struct mlx5_flow_meter_policy *final_policy; + + final_policy = + mlx5_flow_meter_hierarchy_get_final_policy(dev, mtr_policy); + if (!final_policy) + goto policy_add_err; + skip_rule = (final_policy->is_rss || final_policy->is_queue); + } + if (!is_rss && !mtr_policy->is_queue && !skip_rule) { /* Create policy rules in HW. */ ret = mlx5_flow_create_policy_rules(dev, mtr_policy); if (ret) goto policy_add_err; } data.dword = policy_idx; - if (!priv->sh->mtrmng->policy_idx_tbl) { - priv->sh->mtrmng->policy_idx_tbl = - mlx5_l3t_create(MLX5_L3T_TYPE_DWORD); - if (!priv->sh->mtrmng->policy_idx_tbl) + if (!priv->policy_idx_tbl) { + priv->policy_idx_tbl = mlx5_l3t_create(MLX5_L3T_TYPE_DWORD); + if (!priv->policy_idx_tbl) goto policy_add_err; } - if (mlx5_l3t_set_entry(priv->sh->mtrmng->policy_idx_tbl, - policy_id, &data)) + if (mlx5_l3t_set_entry(priv->policy_idx_tbl, policy_id, &data)) goto policy_add_err; return 0; policy_add_err: if (mtr_policy) { ret = __mlx5_flow_meter_policy_delete(dev, policy_id, - mtr_policy, error); + mtr_policy, error, false); mlx5_free(mtr_policy); if (ret) return ret; @@ -775,7 +865,7 @@ mlx5_flow_meter_policy_delete(struct rte_eth_dev *dev, RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL, "Meter policy id is invalid. "); ret = __mlx5_flow_meter_policy_delete(dev, policy_id, mtr_policy, - error); + error, true); if (ret) return ret; mlx5_free(mtr_policy); @@ -1768,6 +1858,169 @@ mlx5_flow_meter_detach(struct mlx5_priv *priv, #endif } +/** + * Flush meter with Rx queue configuration. + * + * @param[in] dev + * Pointer to Ethernet device. + */ +void +mlx5_flow_meter_rxq_flush(struct rte_eth_dev *dev) +{ + struct mlx5_priv *priv = dev->data->dev_private; + struct mlx5_flow_meter_sub_policy *sub_policy; + struct mlx5_flow_meter_policy *mtr_policy; + void *entry; + uint32_t i, policy_idx; + + if (!priv->mtr_en) + return; + if (priv->policy_idx_tbl) { + MLX5_L3T_FOREACH(priv->policy_idx_tbl, i, entry) { + policy_idx = *(uint32_t *)entry; + sub_policy = mlx5_ipool_get + (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY], + policy_idx); + if (!sub_policy || !sub_policy->main_policy) + continue; + mtr_policy = sub_policy->main_policy; + if (mtr_policy->is_queue || mtr_policy->is_rss) + mlx5_flow_destroy_sub_policy_with_rxq(dev, + mtr_policy); + } + } +} + +/** + * Iterate a meter hierarchy and flush all meters and policies if possible. + * + * @param[in] dev + * Pointer to Ethernet device. + * @param[in] fm + * Pointer to flow meter. + * @param[in] mtr_idx + * .Meter's index + * @param[out] error + * Pointer to rte meter error structure. + * + * @return + * 0 on success, a negative errno value otherwise and rte_errno is set. + */ +static int +mlx5_flow_meter_flush_hierarchy(struct rte_eth_dev *dev, + struct mlx5_flow_meter_info *fm, + uint32_t mtr_idx, + struct rte_mtr_error *error) +{ + struct mlx5_priv *priv = dev->data->dev_private; + struct mlx5_flow_meter_policy *policy; + uint32_t policy_id; + struct mlx5_flow_meter_info *next_fm; + uint32_t next_mtr_idx; + struct mlx5_flow_meter_policy *next_policy = NULL; + + policy = mlx5_flow_meter_policy_find(dev, fm->policy_id, NULL); + MLX5_ASSERT(policy); + while (!fm->ref_cnt && policy->is_hierarchy) { + policy_id = fm->policy_id; + next_fm = mlx5_flow_meter_find(priv, + policy->act_cnt[RTE_COLOR_GREEN].next_mtr_id, + &next_mtr_idx); + if (next_fm) { + next_policy = mlx5_flow_meter_policy_find(dev, + next_fm->policy_id, + NULL); + MLX5_ASSERT(next_policy); + } + if (mlx5_flow_meter_params_flush(dev, fm, mtr_idx)) + return -rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_MTR_ID, + NULL, + "Failed to flush meter."); + if (policy->ref_cnt) + break; + if (__mlx5_flow_meter_policy_delete(dev, policy_id, + policy, error, true)) + return -rte_errno; + mlx5_free(policy); + if (!next_fm || !next_policy) + break; + fm = next_fm; + mtr_idx = next_mtr_idx; + policy = next_policy; + } + return 0; +} + +/** + * Flush all the hierarchy meters and their policies. + * + * @param[in] dev + * Pointer to Ethernet device. + * @param[out] error + * Pointer to rte meter error structure. + * + * @return + * 0 on success, a negative errno value otherwise and rte_errno is set. + */ +static int +mlx5_flow_meter_flush_all_hierarchies(struct rte_eth_dev *dev, + struct rte_mtr_error *error) +{ + struct mlx5_priv *priv = dev->data->dev_private; + struct mlx5_flow_meter_info *fm; + struct mlx5_flow_meter_policy *policy; + struct mlx5_flow_meter_sub_policy *sub_policy; + struct mlx5_flow_meter_info *next_fm; + struct mlx5_aso_mtr *aso_mtr; + uint32_t mtr_idx = 0; + uint32_t i, policy_idx; + void *entry; + + if (!priv->mtr_idx_tbl || !priv->policy_idx_tbl) + return 0; + MLX5_L3T_FOREACH(priv->mtr_idx_tbl, i, entry) { + mtr_idx = *(uint32_t *)entry; + if (!mtr_idx) + continue; + aso_mtr = mlx5_aso_meter_by_idx(priv, mtr_idx); + fm = &aso_mtr->fm; + if (fm->ref_cnt || fm->def_policy) + continue; + if (mlx5_flow_meter_flush_hierarchy(dev, fm, mtr_idx, error)) + return -rte_errno; + } + MLX5_L3T_FOREACH(priv->policy_idx_tbl, i, entry) { + policy_idx = *(uint32_t *)entry; + sub_policy = mlx5_ipool_get + (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY], + policy_idx); + if (!sub_policy) + return -rte_mtr_error_set(error, + EINVAL, + RTE_MTR_ERROR_TYPE_METER_POLICY_ID, + NULL, "Meter policy invalid."); + policy = sub_policy->main_policy; + if (!policy || !policy->is_hierarchy || policy->ref_cnt) + continue; + next_fm = mlx5_flow_meter_find(priv, + policy->act_cnt[RTE_COLOR_GREEN].next_mtr_id, + &mtr_idx); + if (__mlx5_flow_meter_policy_delete(dev, i, policy, + error, true)) + return -rte_mtr_error_set(error, + EINVAL, + RTE_MTR_ERROR_TYPE_METER_POLICY_ID, + NULL, "Meter policy invalid."); + mlx5_free(policy); + if (!next_fm || next_fm->ref_cnt || next_fm->def_policy) + continue; + if (mlx5_flow_meter_flush_hierarchy(dev, next_fm, + mtr_idx, error)) + return -rte_errno; + } + return 0; +} /** * Flush meter configuration. * @@ -1784,7 +2037,6 @@ mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error) { struct mlx5_priv *priv = dev->data->dev_private; struct mlx5_legacy_flow_meters *fms = &priv->flow_meters; - struct mlx5_mtr_profiles *fmps = &priv->flow_meter_profiles; struct mlx5_flow_meter_profile *fmp; struct mlx5_legacy_flow_meter *legacy_fm; struct mlx5_flow_meter_info *fm; @@ -1797,6 +2049,8 @@ mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error) if (!priv->mtr_en) return 0; if (priv->sh->meter_aso_en) { + if (mlx5_flow_meter_flush_all_hierarchies(dev, error)) + return -rte_errno; if (priv->mtr_idx_tbl) { MLX5_L3T_FOREACH(priv->mtr_idx_tbl, i, entry) { mtr_idx = *(uint32_t *)entry; @@ -1820,9 +2074,8 @@ mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error) NULL, "MTR object meter profile invalid."); } } - if (priv->sh->mtrmng->policy_idx_tbl && priv->sh->refcnt == 1) { - MLX5_L3T_FOREACH(priv->sh->mtrmng->policy_idx_tbl, - i, entry) { + if (priv->policy_idx_tbl) { + MLX5_L3T_FOREACH(priv->policy_idx_tbl, i, entry) { policy_idx = *(uint32_t *)entry; sub_policy = mlx5_ipool_get (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY], @@ -1835,7 +2088,7 @@ mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error) "meter policy invalid."); if (__mlx5_flow_meter_policy_delete(dev, i, sub_policy->main_policy, - error)) + error, true)) return -rte_mtr_error_set(error, EINVAL, RTE_MTR_ERROR_TYPE_METER_POLICY_ID, @@ -1843,15 +2096,21 @@ mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error) "meter policy invalid."); mlx5_free(sub_policy->main_policy); } - mlx5_l3t_destroy(priv->sh->mtrmng->policy_idx_tbl); - priv->sh->mtrmng->policy_idx_tbl = NULL; + mlx5_l3t_destroy(priv->policy_idx_tbl); + priv->policy_idx_tbl = NULL; } - TAILQ_FOREACH_SAFE(fmp, fmps, next, tmp) { - /* Check unused. */ - MLX5_ASSERT(!fmp->ref_cnt); - /* Remove from list. */ - TAILQ_REMOVE(&priv->flow_meter_profiles, fmp, next); - mlx5_free(fmp); + if (priv->mtr_profile_tbl) { + MLX5_L3T_FOREACH(priv->mtr_profile_tbl, i, entry) { + fmp = entry; + if (mlx5_flow_meter_profile_delete(dev, fmp->id, + error)) + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_POLICY_ID, + NULL, "Fail to destroy " + "meter profile."); + } + mlx5_l3t_destroy(priv->mtr_profile_tbl); + priv->mtr_profile_tbl = NULL; } /* Delete default policy table. */ mlx5_flow_destroy_def_policy(dev);