1 // SPDX-License-Identifier: BSD-3-Clause
3 * Copyright 2018 Mellanox Technologies, Ltd
8 #include <rte_malloc.h>
10 #include <rte_mtr_driver.h>
12 #include <mlx5_devx_cmds.h>
13 #include <mlx5_malloc.h>
16 #include "mlx5_flow.h"
19 * Create the meter action.
22 * Pointer to mlx5_priv.
24 * Pointer to flow meter to be converted.
27 * Pointer to the meter action on success, NULL otherwise.
30 mlx5_flow_meter_action_create(struct mlx5_priv *priv,
31 struct mlx5_flow_meter_info *fm)
33 #ifdef HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER
34 struct mlx5dv_dr_flow_meter_attr mtr_init;
35 uint32_t fmp[MLX5_ST_SZ_DW(flow_meter_parameters)];
36 struct mlx5_flow_meter_srtcm_rfc2697_prm *srtcm =
37 &fm->profile->srtcm_prm;
38 uint32_t cbs_cir = rte_be_to_cpu_32(srtcm->cbs_cir);
39 uint32_t ebs_eir = rte_be_to_cpu_32(srtcm->ebs_eir);
41 enum mlx5_meter_domain domain =
42 fm->transfer ? MLX5_MTR_DOMAIN_TRANSFER :
43 fm->egress ? MLX5_MTR_DOMAIN_EGRESS :
44 MLX5_MTR_DOMAIN_INGRESS;
45 struct mlx5_flow_meter_def_policy *def_policy =
46 priv->sh->mtrmng->def_policy[domain];
48 memset(fmp, 0, MLX5_ST_SZ_BYTES(flow_meter_parameters));
49 MLX5_SET(flow_meter_parameters, fmp, valid, 1);
50 MLX5_SET(flow_meter_parameters, fmp, bucket_overflow, 1);
51 MLX5_SET(flow_meter_parameters, fmp,
52 start_color, MLX5_FLOW_COLOR_GREEN);
53 MLX5_SET(flow_meter_parameters, fmp, both_buckets_on_green, 0);
54 val = (cbs_cir >> ASO_DSEG_CBS_EXP_OFFSET) & ASO_DSEG_EXP_MASK;
55 MLX5_SET(flow_meter_parameters, fmp, cbs_exponent, val);
56 val = (cbs_cir >> ASO_DSEG_CBS_MAN_OFFSET) & ASO_DSEG_MAN_MASK;
57 MLX5_SET(flow_meter_parameters, fmp, cbs_mantissa, val);
58 val = (cbs_cir >> ASO_DSEG_CIR_EXP_OFFSET) & ASO_DSEG_EXP_MASK;
59 MLX5_SET(flow_meter_parameters, fmp, cir_exponent, val);
60 val = (cbs_cir & ASO_DSEG_MAN_MASK);
61 MLX5_SET(flow_meter_parameters, fmp, cir_mantissa, val);
62 val = (ebs_eir >> ASO_DSEG_EBS_EXP_OFFSET) & ASO_DSEG_EXP_MASK;
63 MLX5_SET(flow_meter_parameters, fmp, ebs_exponent, val);
64 val = (ebs_eir >> ASO_DSEG_EBS_MAN_OFFSET) & ASO_DSEG_MAN_MASK;
65 MLX5_SET(flow_meter_parameters, fmp, ebs_mantissa, val);
66 mtr_init.next_table = def_policy->sub_policy.tbl_rsc->obj;
67 mtr_init.reg_c_index = priv->mtr_color_reg - REG_C_0;
68 mtr_init.flow_meter_parameter = fmp;
69 mtr_init.flow_meter_parameter_sz =
70 MLX5_ST_SZ_BYTES(flow_meter_parameters);
71 mtr_init.active = fm->active_state;
72 return mlx5_glue->dv_create_flow_action_meter(&mtr_init);
81 * Find meter profile by id.
84 * Pointer to mlx5_priv.
85 * @param meter_profile_id
89 * Pointer to the profile found on success, NULL otherwise.
91 static struct mlx5_flow_meter_profile *
92 mlx5_flow_meter_profile_find(struct mlx5_priv *priv, uint32_t meter_profile_id)
94 struct mlx5_flow_meter_profile *fmp;
95 union mlx5_l3t_data data;
98 if (mlx5_l3t_get_entry(priv->mtr_profile_tbl,
99 meter_profile_id, &data) || !data.ptr)
102 /* Remove reference taken by the mlx5_l3t_get_entry. */
103 ret = mlx5_l3t_clear_entry(priv->mtr_profile_tbl,
105 if (!ret || ret == -1)
111 * Validate the MTR profile.
114 * Pointer to Ethernet device.
115 * @param[in] meter_profile_id
118 * Pointer to meter profile detail.
120 * Pointer to the error structure.
123 * 0 on success, a negative errno value otherwise and rte_errno is set.
126 mlx5_flow_meter_profile_validate(struct rte_eth_dev *dev,
127 uint32_t meter_profile_id,
128 struct rte_mtr_meter_profile *profile,
129 struct rte_mtr_error *error)
131 struct mlx5_priv *priv = dev->data->dev_private;
132 struct mlx5_flow_meter_profile *fmp;
134 /* Profile must not be NULL. */
136 return -rte_mtr_error_set(error, EINVAL,
137 RTE_MTR_ERROR_TYPE_METER_PROFILE,
138 NULL, "Meter profile is null.");
139 /* Meter profile ID must be valid. */
140 if (meter_profile_id == UINT32_MAX)
141 return -rte_mtr_error_set(error, EINVAL,
142 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
143 NULL, "Meter profile id not valid.");
144 /* Meter profile must not exist. */
145 fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id);
147 return -rte_mtr_error_set(error, EEXIST,
148 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
150 "Meter profile already exists.");
151 if (profile->alg == RTE_MTR_SRTCM_RFC2697) {
152 if (priv->config.hca_attr.qos.flow_meter_old) {
153 /* Verify support for flow meter parameters. */
154 if (priv->sh->meter_aso_en && profile->packet_mode) {
155 if (profile->srtcm_rfc2697.cir > 0 &&
156 (profile->srtcm_rfc2697.cir <<
157 MLX5_MTRS_PPS_MAP_BPS_SHIFT)
158 <= MLX5_SRTCM_CIR_MAX &&
159 profile->srtcm_rfc2697.cbs > 0 &&
160 (profile->srtcm_rfc2697.cbs <<
161 MLX5_MTRS_PPS_MAP_BPS_SHIFT)
162 <= MLX5_SRTCM_CBS_MAX &&
163 (profile->srtcm_rfc2697.ebs <<
164 MLX5_MTRS_PPS_MAP_BPS_SHIFT)
165 <= MLX5_SRTCM_EBS_MAX)
167 return -rte_mtr_error_set
169 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
171 profile->srtcm_rfc2697.ebs ?
172 "Metering value ebs must be 0." :
173 "Invalid metering parameters.");
175 if (profile->srtcm_rfc2697.cir > 0 &&
176 profile->srtcm_rfc2697.cir <=
177 MLX5_SRTCM_CIR_MAX &&
178 profile->srtcm_rfc2697.cbs > 0 &&
179 profile->srtcm_rfc2697.cbs <=
180 MLX5_SRTCM_CBS_MAX &&
181 profile->srtcm_rfc2697.ebs <=
184 return -rte_mtr_error_set(error, ENOTSUP,
185 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
187 profile->srtcm_rfc2697.ebs ?
188 "Metering value ebs must be 0." :
189 "Invalid metering parameters.");
192 return -rte_mtr_error_set(error, ENOTSUP,
193 RTE_MTR_ERROR_TYPE_METER_PROFILE,
194 NULL, "Metering algorithm not supported.");
198 * Calculate mantissa and exponent for cir.
201 * Value to be calculated.
203 * Pointer to the mantissa.
205 * Pointer to the exp.
208 mlx5_flow_meter_cir_man_exp_calc(int64_t cir, uint8_t *man, uint8_t *exp)
211 int64_t delta = INT64_MAX;
216 for (m = 0; m <= 0xFF; m++) { /* man width 8 bit */
217 for (e = 0; e <= 0x1F; e++) { /* exp width 5bit */
218 _cir = (1000000000ULL * m) >> e;
219 if (llabs(cir - _cir) <= delta) {
220 delta = llabs(cir - _cir);
231 * Calculate mantissa and exponent for xbs.
234 * Value to be calculated.
236 * Pointer to the mantissa.
238 * Pointer to the exp.
241 mlx5_flow_meter_xbs_man_exp_calc(uint64_t xbs, uint8_t *man, uint8_t *exp)
246 /* Special case xbs == 0 ? both exp and matissa are 0. */
252 /* xbs = xbs_mantissa * 2^xbs_exponent */
253 _man = frexp(xbs, &_exp);
254 _man = _man * pow(2, MLX5_MAN_WIDTH);
255 _exp = _exp - MLX5_MAN_WIDTH;
256 *man = (uint8_t)ceil(_man);
261 * Fill the prm meter parameter.
264 * Pointer to meter profie to be converted.
266 * Pointer to the error structure.
269 * 0 on success, a negative errno value otherwise and rte_errno is set.
272 mlx5_flow_meter_param_fill(struct mlx5_flow_meter_profile *fmp,
273 struct mlx5_priv *priv, struct rte_mtr_error *error)
275 struct mlx5_flow_meter_srtcm_rfc2697_prm *srtcm = &fmp->srtcm_prm;
277 uint32_t cbs_exp, cbs_man, cir_exp, cir_man;
278 uint32_t ebs_exp, ebs_man;
279 uint64_t cir, cbs, ebs;
281 if (fmp->profile.alg != RTE_MTR_SRTCM_RFC2697)
282 return -rte_mtr_error_set(error, ENOTSUP,
283 RTE_MTR_ERROR_TYPE_METER_PROFILE,
284 NULL, "Metering algorithm not supported.");
285 if (!priv->sh->meter_aso_en && fmp->profile.packet_mode)
286 return -rte_mtr_error_set(error, ENOTSUP,
287 RTE_MTR_ERROR_TYPE_METER_PROFILE,
288 NULL, "Metering algorithm packet mode not supported.");
289 if (priv->sh->meter_aso_en && fmp->profile.packet_mode) {
290 cir = fmp->profile.srtcm_rfc2697.cir <<
291 MLX5_MTRS_PPS_MAP_BPS_SHIFT;
292 cbs = fmp->profile.srtcm_rfc2697.cbs <<
293 MLX5_MTRS_PPS_MAP_BPS_SHIFT;
294 ebs = fmp->profile.srtcm_rfc2697.ebs <<
295 MLX5_MTRS_PPS_MAP_BPS_SHIFT;
297 cir = fmp->profile.srtcm_rfc2697.cir;
298 cbs = fmp->profile.srtcm_rfc2697.cbs;
299 ebs = fmp->profile.srtcm_rfc2697.ebs;
301 /* cir = 8G * cir_mantissa * 1/(2^cir_exponent)) Bytes/Sec */
302 mlx5_flow_meter_cir_man_exp_calc(cir, &man, &exp);
303 /* Check if cir mantissa is too large. */
304 if (exp > ASO_DSEG_CIR_EXP_MASK)
305 return -rte_mtr_error_set(error, ENOTSUP,
306 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
307 "meter profile parameter cir is"
311 /* cbs = cbs_mantissa * 2^cbs_exponent */
312 mlx5_flow_meter_xbs_man_exp_calc(cbs, &man, &exp);
313 /* Check if cbs mantissa is too large. */
314 if (exp > ASO_DSEG_EXP_MASK)
315 return -rte_mtr_error_set(error, ENOTSUP,
316 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
317 "meter profile parameter cbs is"
321 srtcm->cbs_cir = rte_cpu_to_be_32(cbs_exp << ASO_DSEG_CBS_EXP_OFFSET |
322 cbs_man << ASO_DSEG_CBS_MAN_OFFSET |
323 cir_exp << ASO_DSEG_CIR_EXP_OFFSET |
325 mlx5_flow_meter_xbs_man_exp_calc(ebs, &man, &exp);
326 /* Check if ebs mantissa is too large. */
327 if (exp > ASO_DSEG_EXP_MASK)
328 return -rte_mtr_error_set(error, ENOTSUP,
329 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
330 "meter profile parameter ebs is"
334 srtcm->ebs_eir = rte_cpu_to_be_32(ebs_exp << ASO_DSEG_EBS_EXP_OFFSET |
335 ebs_man << ASO_DSEG_EBS_MAN_OFFSET);
344 * Callback to get MTR capabilities.
347 * Pointer to Ethernet device.
349 * Pointer to save MTR capabilities.
351 * Pointer to the error structure.
354 * 0 on success, a negative errno value otherwise and rte_errno is set.
357 mlx5_flow_mtr_cap_get(struct rte_eth_dev *dev,
358 struct rte_mtr_capabilities *cap,
359 struct rte_mtr_error *error __rte_unused)
361 struct mlx5_priv *priv = dev->data->dev_private;
362 struct mlx5_hca_qos_attr *qattr = &priv->config.hca_attr.qos;
365 return -rte_mtr_error_set(error, ENOTSUP,
366 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
367 "Meter is not supported");
368 memset(cap, 0, sizeof(*cap));
369 if (priv->sh->meter_aso_en) {
370 /* 2 meters per one ASO cache line. */
371 cap->n_max = 1 << (qattr->log_max_num_meter_aso + 1);
372 cap->srtcm_rfc2697_packet_mode_supported = 1;
374 cap->n_max = 1 << qattr->log_max_flow_meter;
375 cap->srtcm_rfc2697_packet_mode_supported = 0;
377 cap->srtcm_rfc2697_byte_mode_supported = 1;
378 cap->n_shared_max = cap->n_max;
380 cap->shared_identical = 1;
381 cap->shared_n_flows_per_mtr_max = 4 << 20;
382 /* 2M flows can share the same meter. */
383 cap->chaining_n_mtrs_per_flow_max = 1; /* Chaining is not supported. */
384 cap->meter_srtcm_rfc2697_n_max = qattr->flow_meter_old ? cap->n_max : 0;
385 cap->meter_rate_max = 1ULL << 40; /* 1 Tera tokens per sec. */
386 cap->stats_mask = RTE_MTR_STATS_N_BYTES_DROPPED |
387 RTE_MTR_STATS_N_PKTS_DROPPED;
392 * Callback to add MTR profile.
395 * Pointer to Ethernet device.
396 * @param[in] meter_profile_id
399 * Pointer to meter profile detail.
401 * Pointer to the error structure.
404 * 0 on success, a negative errno value otherwise and rte_errno is set.
407 mlx5_flow_meter_profile_add(struct rte_eth_dev *dev,
408 uint32_t meter_profile_id,
409 struct rte_mtr_meter_profile *profile,
410 struct rte_mtr_error *error)
412 struct mlx5_priv *priv = dev->data->dev_private;
413 struct mlx5_flow_meter_profile *fmp;
414 union mlx5_l3t_data data;
418 return -rte_mtr_error_set(error, ENOTSUP,
419 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
420 "Meter is not supported");
421 /* Check input params. */
422 ret = mlx5_flow_meter_profile_validate(dev, meter_profile_id,
426 /* Meter profile memory allocation. */
427 fmp = mlx5_malloc(MLX5_MEM_ZERO, sizeof(struct mlx5_flow_meter_profile),
428 RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
430 return -rte_mtr_error_set(error, ENOMEM,
431 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
432 NULL, "Meter profile memory "
434 /* Fill profile info. */
435 fmp->id = meter_profile_id;
436 fmp->profile = *profile;
437 /* Fill the flow meter parameters for the PRM. */
438 ret = mlx5_flow_meter_param_fill(fmp, priv, error);
442 ret = mlx5_l3t_set_entry(priv->mtr_profile_tbl,
443 meter_profile_id, &data);
445 return -rte_mtr_error_set(error, ENOTSUP,
446 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
447 NULL, "Meter profile insert fail.");
455 * Callback to delete MTR profile.
458 * Pointer to Ethernet device.
459 * @param[in] meter_profile_id
462 * Pointer to the error structure.
465 * 0 on success, a negative errno value otherwise and rte_errno is set.
468 mlx5_flow_meter_profile_delete(struct rte_eth_dev *dev,
469 uint32_t meter_profile_id,
470 struct rte_mtr_error *error)
472 struct mlx5_priv *priv = dev->data->dev_private;
473 struct mlx5_flow_meter_profile *fmp;
476 return -rte_mtr_error_set(error, ENOTSUP,
477 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
478 "Meter is not supported");
479 /* Meter profile must exist. */
480 fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id);
482 return -rte_mtr_error_set(error, ENOENT,
483 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
485 "Meter profile id is invalid.");
486 /* Check profile is unused. */
488 return -rte_mtr_error_set(error, EBUSY,
489 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
490 NULL, "Meter profile is in use.");
491 if (mlx5_l3t_clear_entry(priv->mtr_profile_tbl, meter_profile_id))
492 return -rte_mtr_error_set(error, EBUSY,
493 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
494 NULL, "Meter profile remove fail.");
503 * Pointer to Ethernet device.
508 * Pointer to the policy found on success, NULL otherwise.
510 struct mlx5_flow_meter_policy *
511 mlx5_flow_meter_policy_find(struct rte_eth_dev *dev,
513 uint32_t *policy_idx)
515 struct mlx5_priv *priv = dev->data->dev_private;
516 struct mlx5_flow_meter_sub_policy *sub_policy = NULL;
517 union mlx5_l3t_data data;
519 if (policy_id > MLX5_MAX_SUB_POLICY_TBL_NUM || !priv->policy_idx_tbl)
521 if (mlx5_l3t_get_entry(priv->policy_idx_tbl, policy_id, &data) ||
525 *policy_idx = data.dword;
526 sub_policy = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
528 /* Remove reference taken by the mlx5_l3t_get_entry. */
529 mlx5_l3t_clear_entry(priv->policy_idx_tbl, policy_id);
531 if (sub_policy->main_policy_id)
532 return sub_policy->main_policy;
537 * Get the last meter's policy from one meter's policy in hierarchy.
540 * Pointer to Ethernet device.
542 * Pointer to flow meter policy.
545 * Pointer to the final meter's policy, or NULL when fail.
547 struct mlx5_flow_meter_policy *
548 mlx5_flow_meter_hierarchy_get_final_policy(struct rte_eth_dev *dev,
549 struct mlx5_flow_meter_policy *policy)
551 struct mlx5_priv *priv = dev->data->dev_private;
552 struct mlx5_flow_meter_info *next_fm;
553 struct mlx5_flow_meter_policy *next_policy = policy;
555 while (next_policy->is_hierarchy) {
556 next_fm = mlx5_flow_meter_find(priv,
557 next_policy->act_cnt[RTE_COLOR_GREEN].next_mtr_id, NULL);
558 if (!next_fm || next_fm->def_policy)
560 next_policy = mlx5_flow_meter_policy_find(dev,
561 next_fm->policy_id, NULL);
562 MLX5_ASSERT(next_policy);
568 * Callback to check MTR policy action validate
571 * Pointer to Ethernet device.
573 * Pointer to meter policy action detail.
575 * Pointer to the error structure.
578 * 0 on success, a negative errno value otherwise and rte_errno is set.
581 mlx5_flow_meter_policy_validate(struct rte_eth_dev *dev,
582 struct rte_mtr_meter_policy_params *policy,
583 struct rte_mtr_error *error)
585 struct mlx5_priv *priv = dev->data->dev_private;
586 struct rte_flow_attr attr = { .transfer =
587 priv->config.dv_esw_en ? 1 : 0};
590 uint8_t domain_bitmap;
593 if (!priv->mtr_en || !priv->sh->meter_aso_en)
594 return -rte_mtr_error_set(error, ENOTSUP,
595 RTE_MTR_ERROR_TYPE_METER_POLICY,
596 NULL, "meter policy unsupported.");
597 ret = mlx5_flow_validate_mtr_acts(dev, policy->actions, &attr,
598 &is_rss, &domain_bitmap, &policy_mode, error);
605 __mlx5_flow_meter_policy_delete(struct rte_eth_dev *dev,
607 struct mlx5_flow_meter_policy *mtr_policy,
608 struct rte_mtr_error *error,
611 struct mlx5_priv *priv = dev->data->dev_private;
612 struct mlx5_flow_meter_sub_policy *sub_policy;
614 uint16_t sub_policy_num;
616 rte_spinlock_lock(&mtr_policy->sl);
617 if (mtr_policy->ref_cnt) {
618 rte_spinlock_unlock(&mtr_policy->sl);
619 return -rte_mtr_error_set(error, EBUSY,
620 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
622 "Meter policy object is being used.");
624 mlx5_flow_destroy_policy_rules(dev, mtr_policy);
625 mlx5_flow_destroy_mtr_acts(dev, mtr_policy);
626 for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
627 sub_policy_num = (mtr_policy->sub_policy_num >>
628 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i)) &
629 MLX5_MTR_SUB_POLICY_NUM_MASK;
630 if (sub_policy_num) {
631 for (j = 0; j < sub_policy_num; j++) {
632 sub_policy = mtr_policy->sub_policys[i][j];
635 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
640 if (priv->policy_idx_tbl && clear_l3t) {
641 if (mlx5_l3t_clear_entry(priv->policy_idx_tbl, policy_id)) {
642 rte_spinlock_unlock(&mtr_policy->sl);
643 return -rte_mtr_error_set(error, ENOTSUP,
644 RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL,
645 "Fail to delete policy in index table.");
648 rte_spinlock_unlock(&mtr_policy->sl);
653 * Callback to add MTR policy.
656 * Pointer to Ethernet device.
657 * @param[out] policy_id
658 * Pointer to policy id
660 * Pointer to meter policy action detail.
662 * Pointer to the error structure.
665 * 0 on success, a negative errno value otherwise and rte_errno is set.
668 mlx5_flow_meter_policy_add(struct rte_eth_dev *dev,
670 struct rte_mtr_meter_policy_params *policy,
671 struct rte_mtr_error *error)
673 struct mlx5_priv *priv = dev->data->dev_private;
674 struct rte_flow_attr attr = { .transfer =
675 priv->config.dv_esw_en ? 1 : 0};
676 uint32_t sub_policy_idx = 0;
677 uint32_t policy_idx = 0;
678 struct mlx5_flow_meter_policy *mtr_policy = NULL;
679 struct mlx5_flow_meter_sub_policy *sub_policy;
684 uint32_t policy_size = sizeof(struct mlx5_flow_meter_policy);
685 uint16_t sub_policy_num;
686 uint8_t domain_bitmap = 0;
687 union mlx5_l3t_data data;
688 bool skip_rule = false;
691 return -rte_mtr_error_set(error, ENOTSUP,
692 RTE_MTR_ERROR_TYPE_METER_POLICY,
693 NULL, "meter policy unsupported. ");
694 if (policy_id == MLX5_INVALID_POLICY_ID)
695 return -rte_mtr_error_set(error, ENOTSUP,
696 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
697 NULL, "policy ID is invalid. ");
698 if (policy_id == priv->sh->mtrmng->def_policy_id)
699 return -rte_mtr_error_set(error, EEXIST,
700 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
701 NULL, "default policy ID exists. ");
702 mtr_policy = mlx5_flow_meter_policy_find(dev, policy_id, &policy_idx);
704 return -rte_mtr_error_set(error, EEXIST,
705 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
706 NULL, "policy ID exists. ");
707 ret = mlx5_flow_validate_mtr_acts(dev, policy->actions, &attr,
708 &is_rss, &domain_bitmap,
709 &policy_mode, error);
713 return -rte_mtr_error_set(error, ENOTSUP,
714 RTE_MTR_ERROR_TYPE_METER_POLICY,
715 NULL, "fail to find policy domain.");
716 if (policy_mode == MLX5_MTR_POLICY_MODE_DEF) {
717 if (priv->sh->mtrmng->def_policy_id != MLX5_INVALID_POLICY_ID)
718 return -rte_mtr_error_set(error, EEXIST,
719 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
720 NULL, "a policy with similar actions "
721 "is already configured");
722 if (mlx5_flow_create_def_policy(dev))
723 return -rte_mtr_error_set(error, ENOTSUP,
724 RTE_MTR_ERROR_TYPE_METER_POLICY,
726 "fail to create non-terminated policy.");
727 priv->sh->mtrmng->def_policy_id = policy_id;
730 if (!priv->sh->meter_aso_en)
731 return -rte_mtr_error_set(error, ENOTSUP,
732 RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
733 "no ASO capability to support the policy ");
734 for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
735 if (!(domain_bitmap & (1 << i)))
738 * If RSS is found, it means that only the ingress domain can
739 * be supported. It is invalid to support RSS for one color
740 * and egress / transfer domain actions for another. Drop and
741 * jump action should have no impact.
745 sizeof(struct mlx5_flow_meter_sub_policy *) *
746 MLX5_MTR_RSS_MAX_SUB_POLICY;
749 policy_size += sizeof(struct mlx5_flow_meter_sub_policy *);
751 mtr_policy = mlx5_malloc(MLX5_MEM_ZERO, policy_size,
752 RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
754 return -rte_mtr_error_set(error, ENOMEM,
755 RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
756 "Memory alloc failed for meter policy.");
757 if (policy_mode == MLX5_MTR_POLICY_MODE_OG)
758 mtr_policy->skip_y = 1;
759 else if (policy_mode == MLX5_MTR_POLICY_MODE_OY)
760 mtr_policy->skip_g = 1;
761 policy_size = sizeof(struct mlx5_flow_meter_policy);
762 for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
763 if (!(domain_bitmap & (1 << i)))
765 if (i == MLX5_MTR_DOMAIN_INGRESS)
766 mtr_policy->ingress = 1;
767 if (i == MLX5_MTR_DOMAIN_EGRESS)
768 mtr_policy->egress = 1;
769 if (i == MLX5_MTR_DOMAIN_TRANSFER)
770 mtr_policy->transfer = 1;
771 sub_policy = mlx5_ipool_zmalloc
772 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
775 sub_policy_idx > MLX5_MAX_SUB_POLICY_TBL_NUM)
777 sub_policy->idx = sub_policy_idx;
778 sub_policy->main_policy = mtr_policy;
780 policy_idx = sub_policy_idx;
781 sub_policy->main_policy_id = 1;
783 mtr_policy->sub_policys[i] =
784 (struct mlx5_flow_meter_sub_policy **)
785 ((uint8_t *)mtr_policy + policy_size);
786 mtr_policy->sub_policys[i][0] = sub_policy;
787 sub_policy_num = (mtr_policy->sub_policy_num >>
788 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i)) &
789 MLX5_MTR_SUB_POLICY_NUM_MASK;
791 mtr_policy->sub_policy_num &= ~(MLX5_MTR_SUB_POLICY_NUM_MASK <<
792 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i));
793 mtr_policy->sub_policy_num |=
794 (sub_policy_num & MLX5_MTR_SUB_POLICY_NUM_MASK) <<
795 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i);
797 * If RSS is found, it means that only the ingress domain can
798 * be supported. It is invalid to support RSS for one color
799 * and egress / transfer domain actions for another. Drop and
800 * jump action should have no impact.
803 mtr_policy->is_rss = 1;
806 policy_size += sizeof(struct mlx5_flow_meter_sub_policy *);
808 rte_spinlock_init(&mtr_policy->sl);
809 ret = mlx5_flow_create_mtr_acts(dev, mtr_policy,
810 policy->actions, error);
813 if (mtr_policy->is_hierarchy) {
814 struct mlx5_flow_meter_policy *final_policy;
817 mlx5_flow_meter_hierarchy_get_final_policy(dev, mtr_policy);
820 skip_rule = (final_policy->is_rss || final_policy->is_queue);
823 * If either Green or Yellow has queue / RSS action, all the policy
824 * rules will be created later in the flow splitting stage.
826 if (!is_rss && !mtr_policy->is_queue && !skip_rule) {
827 /* Create policy rules in HW. */
828 ret = mlx5_flow_create_policy_rules(dev, mtr_policy);
832 data.dword = policy_idx;
833 if (!priv->policy_idx_tbl) {
834 priv->policy_idx_tbl = mlx5_l3t_create(MLX5_L3T_TYPE_DWORD);
835 if (!priv->policy_idx_tbl)
838 if (mlx5_l3t_set_entry(priv->policy_idx_tbl, policy_id, &data))
843 ret = __mlx5_flow_meter_policy_delete(dev, policy_id,
844 mtr_policy, error, false);
845 mlx5_free(mtr_policy);
849 return -rte_mtr_error_set(error, ENOTSUP,
850 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
851 NULL, "Failed to create devx policy.");
855 * Callback to delete MTR policy.
858 * Pointer to Ethernet device.
859 * @param[in] policy_id
862 * Pointer to the error structure.
865 * 0 on success, a negative errno value otherwise and rte_errno is set.
868 mlx5_flow_meter_policy_delete(struct rte_eth_dev *dev,
870 struct rte_mtr_error *error)
872 struct mlx5_priv *priv = dev->data->dev_private;
873 struct mlx5_flow_meter_policy *mtr_policy;
877 if (policy_id == priv->sh->mtrmng->def_policy_id) {
878 if (priv->sh->mtrmng->def_policy_ref_cnt > 0)
879 return -rte_mtr_error_set(error, ENOTSUP,
880 RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL,
881 "Meter policy object is being used.");
882 priv->sh->mtrmng->def_policy_id = MLX5_INVALID_POLICY_ID;
885 mtr_policy = mlx5_flow_meter_policy_find(dev, policy_id, &policy_idx);
887 return -rte_mtr_error_set(error, ENOTSUP,
888 RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL,
889 "Meter policy id is invalid. ");
890 ret = __mlx5_flow_meter_policy_delete(dev, policy_id, mtr_policy,
894 mlx5_free(mtr_policy);
899 * Check meter validation.
902 * Pointer to mlx5 private data structure.
903 * @param[in] meter_id
906 * Pointer to rte meter parameters.
908 * Pointer to rte meter error structure.
911 * 0 on success, a negative errno value otherwise and rte_errno is set.
914 mlx5_flow_meter_validate(struct mlx5_priv *priv, uint32_t meter_id,
915 struct rte_mtr_params *params,
916 struct rte_mtr_error *error)
918 /* Meter must use global drop action. */
919 if (!priv->sh->dr_drop_action)
920 return -rte_mtr_error_set(error, ENOTSUP,
921 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
923 "No drop action ready for meter.");
924 /* Meter params must not be NULL. */
926 return -rte_mtr_error_set(error, EINVAL,
927 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
928 NULL, "Meter object params null.");
929 /* Previous meter color is not supported. */
930 if (params->use_prev_mtr_color)
931 return -rte_mtr_error_set(error, ENOTSUP,
932 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
934 "Previous meter color "
936 if (params->meter_policy_id == MLX5_INVALID_POLICY_ID)
937 return -rte_mtr_error_set(error, ENOENT,
938 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
939 NULL, "Meter policy id not valid.");
940 /* Validate meter id. */
941 if (mlx5_flow_meter_find(priv, meter_id, NULL))
942 return -rte_mtr_error_set(error, EEXIST,
943 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
944 "Meter object already exists.");
949 * Modify the flow meter action.
952 * Pointer to mlx5 private data structure.
954 * Pointer to flow meter to be modified.
956 * Pointer to meter srtcm description parameter.
957 * @param[in] modify_bits
958 * The bit in srtcm to be updated.
959 * @param[in] active_state
960 * The state to be updated.
962 * 0 on success, o negative value otherwise.
965 mlx5_flow_meter_action_modify(struct mlx5_priv *priv,
966 struct mlx5_flow_meter_info *fm,
967 const struct mlx5_flow_meter_srtcm_rfc2697_prm *srtcm,
968 uint64_t modify_bits, uint32_t active_state, uint32_t is_enable)
970 #ifdef HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER
971 uint32_t in[MLX5_ST_SZ_DW(flow_meter_parameters)] = { 0 };
973 struct mlx5dv_dr_flow_meter_attr mod_attr = { 0 };
975 struct mlx5_aso_mtr *aso_mtr = NULL;
976 uint32_t cbs_cir, ebs_eir, val;
978 if (priv->sh->meter_aso_en) {
979 fm->is_enable = !!is_enable;
980 aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
981 ret = mlx5_aso_meter_update_by_wqe(priv->sh, aso_mtr);
984 ret = mlx5_aso_mtr_wait(priv->sh, aso_mtr);
988 /* Fill command parameters. */
989 mod_attr.reg_c_index = priv->mtr_color_reg - REG_C_0;
990 mod_attr.flow_meter_parameter = in;
991 mod_attr.flow_meter_parameter_sz =
992 MLX5_ST_SZ_BYTES(flow_meter_parameters);
993 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_ACTIVE)
994 mod_attr.active = !!active_state;
998 cbs_cir = rte_be_to_cpu_32(srtcm->cbs_cir);
999 ebs_eir = rte_be_to_cpu_32(srtcm->ebs_eir);
1000 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS) {
1001 val = (cbs_cir >> ASO_DSEG_CBS_EXP_OFFSET) &
1003 MLX5_SET(flow_meter_parameters, attr,
1005 val = (cbs_cir >> ASO_DSEG_CBS_MAN_OFFSET) &
1007 MLX5_SET(flow_meter_parameters, attr,
1010 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR) {
1011 val = (cbs_cir >> ASO_DSEG_CIR_EXP_OFFSET) &
1013 MLX5_SET(flow_meter_parameters, attr,
1015 val = cbs_cir & ASO_DSEG_MAN_MASK;
1016 MLX5_SET(flow_meter_parameters, attr,
1019 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_EBS) {
1020 val = (ebs_eir >> ASO_DSEG_EBS_EXP_OFFSET) &
1022 MLX5_SET(flow_meter_parameters, attr,
1024 val = (ebs_eir >> ASO_DSEG_EBS_MAN_OFFSET) &
1026 MLX5_SET(flow_meter_parameters, attr,
1029 /* Apply modifications to meter only if it was created. */
1030 if (fm->meter_action) {
1031 ret = mlx5_glue->dv_modify_flow_action_meter
1032 (fm->meter_action, &mod_attr,
1033 rte_cpu_to_be_64(modify_bits));
1037 /* Update succeedded modify meter parameters. */
1038 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_ACTIVE)
1039 fm->active_state = !!active_state;
1054 mlx5_flow_meter_stats_enable_update(struct rte_eth_dev *dev,
1055 struct mlx5_flow_meter_info *fm,
1056 uint64_t stats_mask)
1059 (stats_mask & RTE_MTR_STATS_N_BYTES_DROPPED) ? 1 : 0;
1060 fm->pkts_dropped = (stats_mask & RTE_MTR_STATS_N_PKTS_DROPPED) ? 1 : 0;
1061 if (fm->bytes_dropped || fm->pkts_dropped) {
1062 if (!fm->drop_cnt) {
1063 /* Alloc policer counters. */
1064 fm->drop_cnt = mlx5_counter_alloc(dev);
1070 mlx5_counter_free(dev, fm->drop_cnt);
1078 * Create meter rules.
1081 * Pointer to Ethernet device.
1082 * @param[in] meter_id
1085 * Pointer to rte meter parameters.
1087 * Meter shared with other flow or not.
1089 * Pointer to rte meter error structure.
1092 * 0 on success, a negative errno value otherwise and rte_errno is set.
1095 mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,
1096 struct rte_mtr_params *params, int shared,
1097 struct rte_mtr_error *error)
1099 struct mlx5_priv *priv = dev->data->dev_private;
1100 struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
1101 struct mlx5_flow_meter_profile *fmp;
1102 struct mlx5_flow_meter_info *fm;
1103 struct mlx5_legacy_flow_meter *legacy_fm;
1104 struct mlx5_flow_meter_policy *mtr_policy = NULL;
1105 struct mlx5_indexed_pool_config flow_ipool_cfg = {
1109 .type = "mlx5_flow_mtr_flow_id_pool",
1111 struct mlx5_aso_mtr *aso_mtr;
1112 uint32_t mtr_idx, policy_idx;
1113 union mlx5_l3t_data data;
1115 uint8_t domain_bitmap;
1116 uint8_t mtr_id_bits;
1117 uint8_t mtr_reg_bits = priv->mtr_reg_share ?
1118 MLX5_MTR_IDLE_BITS_IN_COLOR_REG : MLX5_REG_BITS;
1121 return -rte_mtr_error_set(error, ENOTSUP,
1122 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1123 "Meter is not supported");
1124 /* Validate the parameters. */
1125 ret = mlx5_flow_meter_validate(priv, meter_id, params, error);
1128 /* Meter profile must exist. */
1129 fmp = mlx5_flow_meter_profile_find(priv, params->meter_profile_id);
1131 return -rte_mtr_error_set(error, ENOENT,
1132 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
1133 NULL, "Meter profile id not valid.");
1134 /* Meter policy must exist. */
1135 if (params->meter_policy_id == priv->sh->mtrmng->def_policy_id) {
1137 (&priv->sh->mtrmng->def_policy_ref_cnt,
1138 1, __ATOMIC_RELAXED);
1139 domain_bitmap = MLX5_MTR_ALL_DOMAIN_BIT;
1140 if (!priv->config.dv_esw_en)
1141 domain_bitmap &= ~MLX5_MTR_DOMAIN_TRANSFER_BIT;
1143 if (!priv->sh->meter_aso_en)
1144 return -rte_mtr_error_set(error, ENOTSUP,
1145 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1146 "Part of the policies cannot be "
1147 "supported without ASO ");
1148 mtr_policy = mlx5_flow_meter_policy_find(dev,
1149 params->meter_policy_id, &policy_idx);
1151 return -rte_mtr_error_set(error, ENOENT,
1152 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
1153 NULL, "Meter policy id not valid.");
1154 domain_bitmap = (mtr_policy->ingress ?
1155 MLX5_MTR_DOMAIN_INGRESS_BIT : 0) |
1156 (mtr_policy->egress ?
1157 MLX5_MTR_DOMAIN_EGRESS_BIT : 0) |
1158 (mtr_policy->transfer ?
1159 MLX5_MTR_DOMAIN_TRANSFER_BIT : 0);
1160 if (fmp->g_support && mtr_policy->skip_g)
1161 return -rte_mtr_error_set(error, ENOTSUP,
1162 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
1163 NULL, "Meter green policy is empty.");
1164 if (fmp->y_support && mtr_policy->skip_y)
1165 return -rte_mtr_error_set(error, ENOTSUP,
1166 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
1167 NULL, "Meter yellow policy is empty.");
1169 /* Allocate the flow meter memory. */
1170 if (priv->sh->meter_aso_en) {
1171 mtr_idx = mlx5_flow_mtr_alloc(dev);
1173 return -rte_mtr_error_set(error, ENOMEM,
1174 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1175 "Memory alloc failed for meter.");
1176 aso_mtr = mlx5_aso_meter_by_idx(priv, mtr_idx);
1179 legacy_fm = mlx5_ipool_zmalloc
1180 (priv->sh->ipool[MLX5_IPOOL_MTR], &mtr_idx);
1181 if (legacy_fm == NULL)
1182 return -rte_mtr_error_set(error, ENOMEM,
1183 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1184 "Memory alloc failed for meter.");
1185 legacy_fm->idx = mtr_idx;
1186 fm = &legacy_fm->fm;
1188 mtr_id_bits = MLX5_REG_BITS - __builtin_clz(mtr_idx);
1189 if ((mtr_id_bits + priv->sh->mtrmng->max_mtr_flow_bits) >
1191 DRV_LOG(ERR, "Meter number exceeds max limit.");
1194 if (mtr_id_bits > priv->sh->mtrmng->max_mtr_bits)
1195 priv->sh->mtrmng->max_mtr_bits = mtr_id_bits;
1196 /* Fill the flow meter parameters. */
1197 fm->meter_id = meter_id;
1198 fm->policy_id = params->meter_policy_id;
1200 if (mlx5_flow_meter_stats_enable_update(dev, fm, params->stats_mask))
1202 if (mlx5_flow_create_mtr_tbls(dev, fm, mtr_idx, domain_bitmap))
1204 /* Add to the flow meter list. */
1205 if (!priv->sh->meter_aso_en)
1206 TAILQ_INSERT_TAIL(fms, legacy_fm, next);
1207 /* Add to the flow meter list. */
1208 fm->active_state = 1; /* Config meter starts as active. */
1210 fm->shared = !!shared;
1211 __atomic_add_fetch(&fm->profile->ref_cnt, 1, __ATOMIC_RELAXED);
1212 if (params->meter_policy_id == priv->sh->mtrmng->def_policy_id) {
1214 fm->flow_ipool = mlx5_ipool_create(&flow_ipool_cfg);
1215 if (!fm->flow_ipool)
1218 rte_spinlock_init(&fm->sl);
1219 /* If ASO meter supported, update ASO flow meter by wqe. */
1220 if (priv->sh->meter_aso_en) {
1221 aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
1222 ret = mlx5_aso_meter_update_by_wqe(priv->sh, aso_mtr);
1225 if (!priv->mtr_idx_tbl) {
1227 mlx5_l3t_create(MLX5_L3T_TYPE_DWORD);
1228 if (!priv->mtr_idx_tbl)
1231 data.dword = mtr_idx;
1232 if (mlx5_l3t_set_entry(priv->mtr_idx_tbl, meter_id, &data))
1236 __atomic_add_fetch(&mtr_policy->ref_cnt, 1, __ATOMIC_RELAXED);
1239 mlx5_flow_destroy_mtr_tbls(dev, fm);
1240 /* Free policer counters. */
1242 mlx5_counter_free(dev, fm->drop_cnt);
1243 if (priv->sh->meter_aso_en)
1244 mlx5_flow_mtr_free(dev, mtr_idx);
1246 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR], mtr_idx);
1247 return -rte_mtr_error_set(error, ENOTSUP,
1248 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
1249 NULL, "Failed to create devx meter.");
1253 mlx5_flow_meter_params_flush(struct rte_eth_dev *dev,
1254 struct mlx5_flow_meter_info *fm,
1257 struct mlx5_priv *priv = dev->data->dev_private;
1258 struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
1259 struct mlx5_flow_meter_profile *fmp;
1260 struct mlx5_legacy_flow_meter *legacy_fm = NULL;
1261 struct mlx5_flow_meter_policy *mtr_policy;
1263 /* Meter object must not have any owner. */
1264 MLX5_ASSERT(!fm->ref_cnt);
1265 /* Get meter profile. */
1269 /* Update dependencies. */
1270 __atomic_sub_fetch(&fmp->ref_cnt, 1, __ATOMIC_RELAXED);
1272 /* Remove from list. */
1273 if (!priv->sh->meter_aso_en) {
1274 legacy_fm = container_of(fm,
1275 struct mlx5_legacy_flow_meter, fm);
1276 TAILQ_REMOVE(fms, legacy_fm, next);
1278 /* Free drop counters. */
1280 mlx5_counter_free(dev, fm->drop_cnt);
1281 /* Free meter flow table. */
1282 if (fm->flow_ipool) {
1283 mlx5_ipool_destroy(fm->flow_ipool);
1286 mlx5_flow_destroy_mtr_tbls(dev, fm);
1288 __atomic_sub_fetch(&priv->sh->mtrmng->def_policy_ref_cnt,
1289 1, __ATOMIC_RELAXED);
1290 if (priv->sh->meter_aso_en) {
1291 if (!fm->def_policy) {
1292 mtr_policy = mlx5_flow_meter_policy_find(dev,
1293 fm->policy_id, NULL);
1295 __atomic_sub_fetch(&mtr_policy->ref_cnt,
1296 1, __ATOMIC_RELAXED);
1300 if (mlx5_l3t_clear_entry(priv->mtr_idx_tbl, fm->meter_id))
1302 mlx5_flow_mtr_free(dev, mtr_idx);
1304 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR],
1311 * Destroy meter rules.
1314 * Pointer to Ethernet device.
1315 * @param[in] meter_id
1318 * Pointer to rte meter error structure.
1321 * 0 on success, a negative errno value otherwise and rte_errno is set.
1324 mlx5_flow_meter_destroy(struct rte_eth_dev *dev, uint32_t meter_id,
1325 struct rte_mtr_error *error)
1327 struct mlx5_priv *priv = dev->data->dev_private;
1328 struct mlx5_flow_meter_info *fm;
1329 uint32_t mtr_idx = 0;
1332 return -rte_mtr_error_set(error, ENOTSUP,
1333 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
1335 "Meter is not supported");
1336 /* Meter object must exist. */
1337 fm = mlx5_flow_meter_find(priv, meter_id, &mtr_idx);
1339 return -rte_mtr_error_set(error, ENOENT,
1340 RTE_MTR_ERROR_TYPE_MTR_ID,
1342 "Meter object id not valid.");
1343 /* Meter object must not have any owner. */
1344 if (fm->ref_cnt > 0)
1345 return -rte_mtr_error_set(error, EBUSY,
1346 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
1348 "Meter object is being used.");
1349 /* Destroy the meter profile. */
1350 if (mlx5_flow_meter_params_flush(dev, fm, mtr_idx))
1351 return -rte_mtr_error_set(error, EINVAL,
1352 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
1354 "MTR object meter profile invalid.");
1359 * Modify meter state.
1362 * Pointer to mlx5 private data structure.
1364 * Pointer to flow meter.
1365 * @param[in] new_state
1366 * New state to update.
1368 * Pointer to rte meter error structure.
1371 * 0 on success, a negative errno value otherwise and rte_errno is set.
1374 mlx5_flow_meter_modify_state(struct mlx5_priv *priv,
1375 struct mlx5_flow_meter_info *fm,
1377 struct rte_mtr_error *error)
1379 static const struct mlx5_flow_meter_srtcm_rfc2697_prm srtcm = {
1380 .cbs_cir = RTE_BE32(MLX5_IFC_FLOW_METER_DISABLE_CBS_CIR_VAL),
1383 uint64_t modify_bits = MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS |
1384 MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR;
1387 if (new_state == MLX5_FLOW_METER_DISABLE)
1388 ret = mlx5_flow_meter_action_modify(priv, fm,
1389 &srtcm, modify_bits, 0, 0);
1391 ret = mlx5_flow_meter_action_modify(priv, fm,
1392 &fm->profile->srtcm_prm,
1395 return -rte_mtr_error_set(error, -ret,
1396 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
1399 "Failed to enable meter." :
1400 "Failed to disable meter.");
1405 * Callback to enable flow meter.
1408 * Pointer to Ethernet device.
1409 * @param[in] meter_id
1412 * Pointer to rte meter error structure.
1415 * 0 on success, a negative errno value otherwise and rte_errno is set.
1418 mlx5_flow_meter_enable(struct rte_eth_dev *dev,
1420 struct rte_mtr_error *error)
1422 struct mlx5_priv *priv = dev->data->dev_private;
1423 struct mlx5_flow_meter_info *fm;
1427 return -rte_mtr_error_set(error, ENOTSUP,
1428 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1429 "Meter is not supported");
1430 /* Meter object must exist. */
1431 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1433 return -rte_mtr_error_set(error, ENOENT,
1434 RTE_MTR_ERROR_TYPE_MTR_ID,
1435 NULL, "Meter not found.");
1436 if (fm->active_state == MLX5_FLOW_METER_ENABLE)
1438 ret = mlx5_flow_meter_modify_state(priv, fm, MLX5_FLOW_METER_ENABLE,
1441 fm->active_state = MLX5_FLOW_METER_ENABLE;
1446 * Callback to disable flow meter.
1449 * Pointer to Ethernet device.
1450 * @param[in] meter_id
1453 * Pointer to rte meter error structure.
1456 * 0 on success, a negative errno value otherwise and rte_errno is set.
1459 mlx5_flow_meter_disable(struct rte_eth_dev *dev,
1461 struct rte_mtr_error *error)
1463 struct mlx5_priv *priv = dev->data->dev_private;
1464 struct mlx5_flow_meter_info *fm;
1468 return -rte_mtr_error_set(error, ENOTSUP,
1469 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1470 "Meter is not supported");
1471 /* Meter object must exist. */
1472 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1474 return -rte_mtr_error_set(error, ENOENT,
1475 RTE_MTR_ERROR_TYPE_MTR_ID,
1476 NULL, "Meter not found.");
1477 if (fm->active_state == MLX5_FLOW_METER_DISABLE)
1479 ret = mlx5_flow_meter_modify_state(priv, fm, MLX5_FLOW_METER_DISABLE,
1482 fm->active_state = MLX5_FLOW_METER_DISABLE;
1487 * Callback to update meter profile.
1490 * Pointer to Ethernet device.
1491 * @param[in] meter_id
1493 * @param[in] meter_profile_id
1494 * To be updated meter profile id.
1496 * Pointer to rte meter error structure.
1499 * 0 on success, a negative errno value otherwise and rte_errno is set.
1502 mlx5_flow_meter_profile_update(struct rte_eth_dev *dev,
1504 uint32_t meter_profile_id,
1505 struct rte_mtr_error *error)
1507 struct mlx5_priv *priv = dev->data->dev_private;
1508 struct mlx5_flow_meter_profile *fmp;
1509 struct mlx5_flow_meter_profile *old_fmp;
1510 struct mlx5_flow_meter_info *fm;
1511 uint64_t modify_bits = MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS |
1512 MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR;
1516 return -rte_mtr_error_set(error, ENOTSUP,
1517 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1518 "Meter is not supported");
1519 /* Meter profile must exist. */
1520 fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id);
1522 return -rte_mtr_error_set(error, ENOENT,
1523 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
1524 NULL, "Meter profile not found.");
1525 /* Meter object must exist. */
1526 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1528 return -rte_mtr_error_set(error, ENOENT,
1529 RTE_MTR_ERROR_TYPE_MTR_ID,
1530 NULL, "Meter not found.");
1531 /* MTR object already set to meter profile id. */
1532 old_fmp = fm->profile;
1535 /* Update the profile. */
1537 /* Update meter params in HW (if not disabled). */
1538 if (fm->active_state == MLX5_FLOW_METER_DISABLE)
1540 ret = mlx5_flow_meter_action_modify(priv, fm, &fm->profile->srtcm_prm,
1541 modify_bits, fm->active_state, 1);
1543 fm->profile = old_fmp;
1544 return -rte_mtr_error_set(error, -ret,
1545 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
1546 NULL, "Failed to update meter"
1547 " parmeters in hardware.");
1555 * Callback to update meter stats mask.
1558 * Pointer to Ethernet device.
1559 * @param[in] meter_id
1561 * @param[in] stats_mask
1562 * To be updated stats_mask.
1564 * Pointer to rte meter error structure.
1567 * 0 on success, a negative errno value otherwise and rte_errno is set.
1570 mlx5_flow_meter_stats_update(struct rte_eth_dev *dev,
1572 uint64_t stats_mask,
1573 struct rte_mtr_error *error)
1575 struct mlx5_priv *priv = dev->data->dev_private;
1576 struct mlx5_flow_meter_info *fm;
1579 return -rte_mtr_error_set(error, ENOTSUP,
1580 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1581 "Meter is not supported");
1582 /* Meter object must exist. */
1583 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1585 return -rte_mtr_error_set(error, ENOENT,
1586 RTE_MTR_ERROR_TYPE_MTR_ID,
1587 NULL, "Meter object id not valid.");
1588 if (mlx5_flow_meter_stats_enable_update(dev, fm, stats_mask))
1589 return -rte_mtr_error_set(error, ENOENT,
1590 RTE_MTR_ERROR_TYPE_MTR_ID,
1591 NULL, "Fail to allocate "
1592 "counter for meter.");
1597 * Callback to read meter statistics.
1600 * Pointer to Ethernet device.
1601 * @param[in] meter_id
1604 * Pointer to store the statistics.
1605 * @param[out] stats_mask
1606 * Pointer to store the stats_mask.
1608 * Statistic to be cleared after read or not.
1610 * Pointer to rte meter error structure.
1613 * 0 on success, a negative errno value otherwise and rte_errno is set.
1616 mlx5_flow_meter_stats_read(struct rte_eth_dev *dev,
1618 struct rte_mtr_stats *stats,
1619 uint64_t *stats_mask,
1621 struct rte_mtr_error *error)
1623 struct mlx5_priv *priv = dev->data->dev_private;
1624 struct mlx5_flow_meter_info *fm;
1630 return -rte_mtr_error_set(error, ENOTSUP,
1631 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1632 "Meter is not supported");
1633 /* Meter object must exist. */
1634 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1636 return -rte_mtr_error_set(error, ENOENT,
1637 RTE_MTR_ERROR_TYPE_MTR_ID,
1638 NULL, "Meter object id not valid.");
1640 if (fm->bytes_dropped)
1641 *stats_mask |= RTE_MTR_STATS_N_BYTES_DROPPED;
1642 if (fm->pkts_dropped)
1643 *stats_mask |= RTE_MTR_STATS_N_PKTS_DROPPED;
1644 memset(stats, 0, sizeof(*stats));
1646 ret = mlx5_counter_query(dev, fm->drop_cnt, clear, &pkts,
1650 /* If need to read the packets, set it. */
1651 if (fm->pkts_dropped)
1652 stats->n_pkts_dropped = pkts;
1653 /* If need to read the bytes, set it. */
1654 if (fm->bytes_dropped)
1655 stats->n_bytes_dropped = bytes;
1659 return -rte_mtr_error_set(error, ret, RTE_MTR_ERROR_TYPE_STATS, NULL,
1660 "Failed to read meter drop counters.");
1663 static const struct rte_mtr_ops mlx5_flow_mtr_ops = {
1664 .capabilities_get = mlx5_flow_mtr_cap_get,
1665 .meter_profile_add = mlx5_flow_meter_profile_add,
1666 .meter_profile_delete = mlx5_flow_meter_profile_delete,
1667 .meter_policy_validate = mlx5_flow_meter_policy_validate,
1668 .meter_policy_add = mlx5_flow_meter_policy_add,
1669 .meter_policy_delete = mlx5_flow_meter_policy_delete,
1670 .create = mlx5_flow_meter_create,
1671 .destroy = mlx5_flow_meter_destroy,
1672 .meter_enable = mlx5_flow_meter_enable,
1673 .meter_disable = mlx5_flow_meter_disable,
1674 .meter_profile_update = mlx5_flow_meter_profile_update,
1675 .meter_dscp_table_update = NULL,
1676 .stats_update = mlx5_flow_meter_stats_update,
1677 .stats_read = mlx5_flow_meter_stats_read,
1681 * Get meter operations.
1684 * Pointer to Ethernet device structure.
1686 * Pointer to set the mtr operations.
1692 mlx5_flow_meter_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)
1694 *(const struct rte_mtr_ops **)arg = &mlx5_flow_mtr_ops;
1702 * Pointer to mlx5_priv.
1706 * Pointer to Meter index.
1709 * Pointer to the meter info found on success, NULL otherwise.
1711 struct mlx5_flow_meter_info *
1712 mlx5_flow_meter_find(struct mlx5_priv *priv, uint32_t meter_id,
1715 struct mlx5_legacy_flow_meter *legacy_fm;
1716 struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
1717 struct mlx5_aso_mtr *aso_mtr;
1718 struct mlx5_aso_mtr_pools_mng *pools_mng =
1719 &priv->sh->mtrmng->pools_mng;
1720 union mlx5_l3t_data data;
1722 if (priv->sh->meter_aso_en) {
1723 rte_spinlock_lock(&pools_mng->mtrsl);
1724 if (!pools_mng->n_valid || !priv->mtr_idx_tbl) {
1725 rte_spinlock_unlock(&pools_mng->mtrsl);
1728 if (mlx5_l3t_get_entry(priv->mtr_idx_tbl, meter_id, &data) ||
1730 rte_spinlock_unlock(&pools_mng->mtrsl);
1734 *mtr_idx = data.dword;
1735 aso_mtr = mlx5_aso_meter_by_idx(priv, data.dword);
1736 /* Remove reference taken by the mlx5_l3t_get_entry. */
1737 mlx5_l3t_clear_entry(priv->mtr_idx_tbl, meter_id);
1738 rte_spinlock_unlock(&pools_mng->mtrsl);
1739 if (!aso_mtr || aso_mtr->state == ASO_METER_FREE)
1741 return &aso_mtr->fm;
1743 TAILQ_FOREACH(legacy_fm, fms, next)
1744 if (meter_id == legacy_fm->fm.meter_id) {
1746 *mtr_idx = legacy_fm->idx;
1747 return &legacy_fm->fm;
1753 * Find meter by index.
1756 * Pointer to mlx5_priv.
1761 * Pointer to the meter info found on success, NULL otherwise.
1763 struct mlx5_flow_meter_info *
1764 flow_dv_meter_find_by_idx(struct mlx5_priv *priv, uint32_t idx)
1766 struct mlx5_aso_mtr *aso_mtr;
1768 if (priv->sh->meter_aso_en) {
1769 aso_mtr = mlx5_aso_meter_by_idx(priv, idx);
1772 return &aso_mtr->fm;
1774 return mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MTR], idx);
1779 * Attach meter to flow.
1780 * Unidirectional Meter creation can only be done
1781 * when flow direction is known, i.e. when calling meter_attach.
1784 * Pointer to mlx5 private data.
1786 * Pointer to flow meter.
1788 * Pointer to flow attributes.
1789 * @param [out] error
1790 * Pointer to error structure.
1793 * 0 on success, a negative errno value otherwise and rte_errno is set.
1796 mlx5_flow_meter_attach(struct mlx5_priv *priv,
1797 struct mlx5_flow_meter_info *fm,
1798 const struct rte_flow_attr *attr,
1799 struct rte_flow_error *error)
1803 if (priv->sh->meter_aso_en) {
1804 struct mlx5_aso_mtr *aso_mtr;
1806 aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
1807 if (mlx5_aso_mtr_wait(priv->sh, aso_mtr)) {
1808 return rte_flow_error_set(error, ENOENT,
1809 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1811 "Timeout in meter configuration");
1813 rte_spinlock_lock(&fm->sl);
1814 if (fm->shared || !fm->ref_cnt) {
1817 rte_flow_error_set(error, EINVAL,
1818 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1819 "Meter cannot be shared");
1822 rte_spinlock_unlock(&fm->sl);
1824 rte_spinlock_lock(&fm->sl);
1825 if (fm->meter_action) {
1827 attr->transfer == fm->transfer &&
1828 attr->ingress == fm->ingress &&
1829 attr->egress == fm->egress) {
1832 rte_flow_error_set(error, EINVAL,
1833 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1835 "Meter attr not match." :
1836 "Meter cannot be shared.");
1840 fm->ingress = attr->ingress;
1841 fm->egress = attr->egress;
1842 fm->transfer = attr->transfer;
1844 /* This also creates the meter object. */
1845 fm->meter_action = mlx5_flow_meter_action_create(priv,
1847 if (!fm->meter_action) {
1852 rte_flow_error_set(error, EINVAL,
1853 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1854 "Meter action create failed.");
1858 rte_spinlock_unlock(&fm->sl);
1860 return ret ? -rte_errno : 0;
1864 * Detach meter from flow.
1867 * Pointer to mlx5 private data.
1869 * Pointer to flow meter.
1872 mlx5_flow_meter_detach(struct mlx5_priv *priv,
1873 struct mlx5_flow_meter_info *fm)
1875 #ifdef HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER
1876 rte_spinlock_lock(&fm->sl);
1877 MLX5_ASSERT(fm->ref_cnt);
1878 if (--fm->ref_cnt == 0 && !priv->sh->meter_aso_en) {
1879 mlx5_glue->destroy_flow_action(fm->meter_action);
1880 fm->meter_action = NULL;
1885 rte_spinlock_unlock(&fm->sl);
1893 * Flush meter with Rx queue configuration.
1896 * Pointer to Ethernet device.
1899 mlx5_flow_meter_rxq_flush(struct rte_eth_dev *dev)
1901 struct mlx5_priv *priv = dev->data->dev_private;
1902 struct mlx5_flow_meter_sub_policy *sub_policy;
1903 struct mlx5_flow_meter_policy *mtr_policy;
1905 uint32_t i, policy_idx;
1909 if (priv->policy_idx_tbl) {
1910 MLX5_L3T_FOREACH(priv->policy_idx_tbl, i, entry) {
1911 policy_idx = *(uint32_t *)entry;
1912 sub_policy = mlx5_ipool_get
1913 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
1915 if (!sub_policy || !sub_policy->main_policy)
1917 mtr_policy = sub_policy->main_policy;
1918 if (mtr_policy->is_queue || mtr_policy->is_rss)
1919 mlx5_flow_destroy_sub_policy_with_rxq(dev,
1926 * Iterate a meter hierarchy and flush all meters and policies if possible.
1929 * Pointer to Ethernet device.
1931 * Pointer to flow meter.
1932 * @param[in] mtr_idx
1935 * Pointer to rte meter error structure.
1938 * 0 on success, a negative errno value otherwise and rte_errno is set.
1941 mlx5_flow_meter_flush_hierarchy(struct rte_eth_dev *dev,
1942 struct mlx5_flow_meter_info *fm,
1944 struct rte_mtr_error *error)
1946 struct mlx5_priv *priv = dev->data->dev_private;
1947 struct mlx5_flow_meter_policy *policy;
1949 struct mlx5_flow_meter_info *next_fm;
1950 uint32_t next_mtr_idx;
1951 struct mlx5_flow_meter_policy *next_policy = NULL;
1953 policy = mlx5_flow_meter_policy_find(dev, fm->policy_id, NULL);
1954 MLX5_ASSERT(policy);
1955 while (!fm->ref_cnt && policy->is_hierarchy) {
1956 policy_id = fm->policy_id;
1957 next_fm = mlx5_flow_meter_find(priv,
1958 policy->act_cnt[RTE_COLOR_GREEN].next_mtr_id,
1961 next_policy = mlx5_flow_meter_policy_find(dev,
1964 MLX5_ASSERT(next_policy);
1966 if (mlx5_flow_meter_params_flush(dev, fm, mtr_idx))
1967 return -rte_mtr_error_set(error, ENOTSUP,
1968 RTE_MTR_ERROR_TYPE_MTR_ID,
1970 "Failed to flush meter.");
1971 if (policy->ref_cnt)
1973 if (__mlx5_flow_meter_policy_delete(dev, policy_id,
1974 policy, error, true))
1977 if (!next_fm || !next_policy)
1980 mtr_idx = next_mtr_idx;
1981 policy = next_policy;
1987 * Flush all the hierarchy meters and their policies.
1990 * Pointer to Ethernet device.
1992 * Pointer to rte meter error structure.
1995 * 0 on success, a negative errno value otherwise and rte_errno is set.
1998 mlx5_flow_meter_flush_all_hierarchies(struct rte_eth_dev *dev,
1999 struct rte_mtr_error *error)
2001 struct mlx5_priv *priv = dev->data->dev_private;
2002 struct mlx5_flow_meter_info *fm;
2003 struct mlx5_flow_meter_policy *policy;
2004 struct mlx5_flow_meter_sub_policy *sub_policy;
2005 struct mlx5_flow_meter_info *next_fm;
2006 struct mlx5_aso_mtr *aso_mtr;
2007 uint32_t mtr_idx = 0;
2008 uint32_t i, policy_idx;
2011 if (!priv->mtr_idx_tbl || !priv->policy_idx_tbl)
2013 MLX5_L3T_FOREACH(priv->mtr_idx_tbl, i, entry) {
2014 mtr_idx = *(uint32_t *)entry;
2017 aso_mtr = mlx5_aso_meter_by_idx(priv, mtr_idx);
2019 if (fm->ref_cnt || fm->def_policy)
2021 if (mlx5_flow_meter_flush_hierarchy(dev, fm, mtr_idx, error))
2024 MLX5_L3T_FOREACH(priv->policy_idx_tbl, i, entry) {
2025 policy_idx = *(uint32_t *)entry;
2026 sub_policy = mlx5_ipool_get
2027 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
2030 return -rte_mtr_error_set(error,
2032 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2033 NULL, "Meter policy invalid.");
2034 policy = sub_policy->main_policy;
2035 if (!policy || !policy->is_hierarchy || policy->ref_cnt)
2037 next_fm = mlx5_flow_meter_find(priv,
2038 policy->act_cnt[RTE_COLOR_GREEN].next_mtr_id,
2040 if (__mlx5_flow_meter_policy_delete(dev, i, policy,
2042 return -rte_mtr_error_set(error,
2044 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2045 NULL, "Meter policy invalid.");
2047 if (!next_fm || next_fm->ref_cnt || next_fm->def_policy)
2049 if (mlx5_flow_meter_flush_hierarchy(dev, next_fm,
2056 * Flush meter configuration.
2059 * Pointer to Ethernet device.
2061 * Pointer to rte meter error structure.
2064 * 0 on success, a negative errno value otherwise and rte_errno is set.
2067 mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error)
2069 struct mlx5_priv *priv = dev->data->dev_private;
2070 struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
2071 struct mlx5_flow_meter_profile *fmp;
2072 struct mlx5_legacy_flow_meter *legacy_fm;
2073 struct mlx5_flow_meter_info *fm;
2074 struct mlx5_flow_meter_sub_policy *sub_policy;
2076 uint32_t i, mtr_idx, policy_idx;
2078 struct mlx5_aso_mtr *aso_mtr;
2082 if (priv->sh->meter_aso_en) {
2083 if (mlx5_flow_meter_flush_all_hierarchies(dev, error))
2085 if (priv->mtr_idx_tbl) {
2086 MLX5_L3T_FOREACH(priv->mtr_idx_tbl, i, entry) {
2087 mtr_idx = *(uint32_t *)entry;
2090 mlx5_aso_meter_by_idx(priv, mtr_idx);
2092 (void)mlx5_flow_meter_params_flush(dev,
2096 mlx5_l3t_destroy(priv->mtr_idx_tbl);
2097 priv->mtr_idx_tbl = NULL;
2100 TAILQ_FOREACH_SAFE(legacy_fm, fms, next, tmp) {
2101 fm = &legacy_fm->fm;
2102 if (mlx5_flow_meter_params_flush(dev, fm, 0))
2103 return -rte_mtr_error_set(error, EINVAL,
2104 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
2105 NULL, "MTR object meter profile invalid.");
2108 if (priv->policy_idx_tbl) {
2109 MLX5_L3T_FOREACH(priv->policy_idx_tbl, i, entry) {
2110 policy_idx = *(uint32_t *)entry;
2111 sub_policy = mlx5_ipool_get
2112 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
2115 return -rte_mtr_error_set(error,
2117 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2119 "meter policy invalid.");
2120 if (__mlx5_flow_meter_policy_delete(dev, i,
2121 sub_policy->main_policy,
2123 return -rte_mtr_error_set(error,
2125 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2127 "meter policy invalid.");
2128 mlx5_free(sub_policy->main_policy);
2130 mlx5_l3t_destroy(priv->policy_idx_tbl);
2131 priv->policy_idx_tbl = NULL;
2133 if (priv->mtr_profile_tbl) {
2134 MLX5_L3T_FOREACH(priv->mtr_profile_tbl, i, entry) {
2136 if (mlx5_flow_meter_profile_delete(dev, fmp->id,
2138 return -rte_mtr_error_set(error, EINVAL,
2139 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2140 NULL, "Fail to destroy "
2143 mlx5_l3t_destroy(priv->mtr_profile_tbl);
2144 priv->mtr_profile_tbl = NULL;
2146 /* Delete default policy table. */
2147 mlx5_flow_destroy_def_policy(dev);
2148 if (priv->sh->refcnt == 1)
2149 mlx5_flow_destroy_mtr_drop_tbls(dev);