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_XIR_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 / eir.
201 * Value to be calculated.
203 * Pointer to the mantissa.
205 * Pointer to the exp.
208 mlx5_flow_meter_xir_man_exp_calc(int64_t xir, 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(xir - _cir) <= delta) {
220 delta = llabs(xir - _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 eir_exp, eir_man, ebs_exp, ebs_man;
279 uint64_t cir, cbs, eir, ebs;
281 if (!priv->sh->meter_aso_en) {
282 /* Legacy FW metering will only support srTCM. */
283 if (fmp->profile.alg != RTE_MTR_SRTCM_RFC2697)
284 return -rte_mtr_error_set(error, ENOTSUP,
285 RTE_MTR_ERROR_TYPE_METER_PROFILE,
286 NULL, "Metering algorithm is not supported.");
287 if (fmp->profile.packet_mode)
288 return -rte_mtr_error_set(error, ENOTSUP,
289 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
290 "Metering algorithm packet mode is not supported.");
292 switch (fmp->profile.alg) {
293 case RTE_MTR_SRTCM_RFC2697:
294 cir = fmp->profile.srtcm_rfc2697.cir;
295 cbs = fmp->profile.srtcm_rfc2697.cbs;
297 ebs = fmp->profile.srtcm_rfc2697.ebs;
299 case RTE_MTR_TRTCM_RFC2698:
300 MLX5_ASSERT(fmp->profile.trtcm_rfc2698.pir >
301 fmp->profile.trtcm_rfc2698.cir &&
302 fmp->profile.trtcm_rfc2698.pbs >
303 fmp->profile.trtcm_rfc2698.cbs);
304 cir = fmp->profile.trtcm_rfc2698.cir;
305 cbs = fmp->profile.trtcm_rfc2698.cbs;
306 /* EIR / EBS are filled with PIR / PBS. */
307 eir = fmp->profile.trtcm_rfc2698.pir;
308 ebs = fmp->profile.trtcm_rfc2698.pbs;
310 case RTE_MTR_TRTCM_RFC4115:
311 cir = fmp->profile.trtcm_rfc4115.cir;
312 cbs = fmp->profile.trtcm_rfc4115.cbs;
313 eir = fmp->profile.trtcm_rfc4115.eir;
314 ebs = fmp->profile.trtcm_rfc4115.ebs;
317 return -rte_mtr_error_set(error, EINVAL,
318 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
319 "Metering algorithm mode is invalid");
321 /* Adjust the values for PPS mode. */
322 if (fmp->profile.packet_mode) {
323 cir <<= MLX5_MTRS_PPS_MAP_BPS_SHIFT;
324 cbs <<= MLX5_MTRS_PPS_MAP_BPS_SHIFT;
325 eir <<= MLX5_MTRS_PPS_MAP_BPS_SHIFT;
326 ebs <<= MLX5_MTRS_PPS_MAP_BPS_SHIFT;
328 /* cir = 8G * cir_mantissa * 1/(2^cir_exponent)) Bytes/Sec */
329 mlx5_flow_meter_xir_man_exp_calc(cir, &man, &exp);
330 /* Check if cir mantissa is too large. */
331 if (exp > ASO_DSEG_XIR_EXP_MASK)
332 return -rte_mtr_error_set(error, ENOTSUP,
333 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
334 "meter profile parameter cir is not supported.");
337 /* cbs = cbs_mantissa * 2^cbs_exponent */
338 mlx5_flow_meter_xbs_man_exp_calc(cbs, &man, &exp);
339 /* Check if cbs mantissa is too large. */
340 if (exp > ASO_DSEG_EXP_MASK)
341 return -rte_mtr_error_set(error, ENOTSUP,
342 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
343 "meter profile parameter cbs is not supported.");
346 srtcm->cbs_cir = rte_cpu_to_be_32(cbs_exp << ASO_DSEG_CBS_EXP_OFFSET |
347 cbs_man << ASO_DSEG_CBS_MAN_OFFSET |
348 cir_exp << ASO_DSEG_XIR_EXP_OFFSET |
350 mlx5_flow_meter_xir_man_exp_calc(eir, &man, &exp);
351 /* Check if eir mantissa is too large. */
352 if (exp > ASO_DSEG_XIR_EXP_MASK)
353 return -rte_mtr_error_set(error, ENOTSUP,
354 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
355 "meter profile parameter eir is not supported.");
358 mlx5_flow_meter_xbs_man_exp_calc(ebs, &man, &exp);
359 /* Check if ebs mantissa is too large. */
360 if (exp > ASO_DSEG_EXP_MASK)
361 return -rte_mtr_error_set(error, ENOTSUP,
362 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
363 "meter profile parameter ebs is not supported.");
366 srtcm->ebs_eir = rte_cpu_to_be_32(ebs_exp << ASO_DSEG_EBS_EXP_OFFSET |
367 ebs_man << ASO_DSEG_EBS_MAN_OFFSET |
368 eir_exp << ASO_DSEG_XIR_EXP_OFFSET |
378 * Callback to get MTR capabilities.
381 * Pointer to Ethernet device.
383 * Pointer to save MTR capabilities.
385 * Pointer to the error structure.
388 * 0 on success, a negative errno value otherwise and rte_errno is set.
391 mlx5_flow_mtr_cap_get(struct rte_eth_dev *dev,
392 struct rte_mtr_capabilities *cap,
393 struct rte_mtr_error *error __rte_unused)
395 struct mlx5_priv *priv = dev->data->dev_private;
396 struct mlx5_hca_qos_attr *qattr = &priv->config.hca_attr.qos;
399 return -rte_mtr_error_set(error, ENOTSUP,
400 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
401 "Meter is not supported");
402 memset(cap, 0, sizeof(*cap));
403 if (priv->sh->meter_aso_en) {
404 /* 2 meters per one ASO cache line. */
405 cap->n_max = 1 << (qattr->log_max_num_meter_aso + 1);
406 cap->srtcm_rfc2697_packet_mode_supported = 1;
408 cap->n_max = 1 << qattr->log_max_flow_meter;
409 cap->srtcm_rfc2697_packet_mode_supported = 0;
411 cap->srtcm_rfc2697_byte_mode_supported = 1;
412 cap->n_shared_max = cap->n_max;
414 cap->shared_identical = 1;
415 cap->shared_n_flows_per_mtr_max = 4 << 20;
416 /* 2M flows can share the same meter. */
417 cap->chaining_n_mtrs_per_flow_max = 1; /* Chaining is not supported. */
418 cap->meter_srtcm_rfc2697_n_max = qattr->flow_meter_old ? cap->n_max : 0;
419 cap->meter_rate_max = 1ULL << 40; /* 1 Tera tokens per sec. */
420 cap->stats_mask = RTE_MTR_STATS_N_BYTES_DROPPED |
421 RTE_MTR_STATS_N_PKTS_DROPPED;
426 * Callback to add MTR profile.
429 * Pointer to Ethernet device.
430 * @param[in] meter_profile_id
433 * Pointer to meter profile detail.
435 * Pointer to the error structure.
438 * 0 on success, a negative errno value otherwise and rte_errno is set.
441 mlx5_flow_meter_profile_add(struct rte_eth_dev *dev,
442 uint32_t meter_profile_id,
443 struct rte_mtr_meter_profile *profile,
444 struct rte_mtr_error *error)
446 struct mlx5_priv *priv = dev->data->dev_private;
447 struct mlx5_flow_meter_profile *fmp;
448 union mlx5_l3t_data data;
452 return -rte_mtr_error_set(error, ENOTSUP,
453 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
454 "Meter is not supported");
455 /* Check input params. */
456 ret = mlx5_flow_meter_profile_validate(dev, meter_profile_id,
460 /* Meter profile memory allocation. */
461 fmp = mlx5_malloc(MLX5_MEM_ZERO, sizeof(struct mlx5_flow_meter_profile),
462 RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
464 return -rte_mtr_error_set(error, ENOMEM,
465 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
466 NULL, "Meter profile memory "
468 /* Fill profile info. */
469 fmp->id = meter_profile_id;
470 fmp->profile = *profile;
471 /* Fill the flow meter parameters for the PRM. */
472 ret = mlx5_flow_meter_param_fill(fmp, priv, error);
476 ret = mlx5_l3t_set_entry(priv->mtr_profile_tbl,
477 meter_profile_id, &data);
479 return -rte_mtr_error_set(error, ENOTSUP,
480 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
481 NULL, "Meter profile insert fail.");
489 * Callback to delete MTR profile.
492 * Pointer to Ethernet device.
493 * @param[in] meter_profile_id
496 * Pointer to the error structure.
499 * 0 on success, a negative errno value otherwise and rte_errno is set.
502 mlx5_flow_meter_profile_delete(struct rte_eth_dev *dev,
503 uint32_t meter_profile_id,
504 struct rte_mtr_error *error)
506 struct mlx5_priv *priv = dev->data->dev_private;
507 struct mlx5_flow_meter_profile *fmp;
510 return -rte_mtr_error_set(error, ENOTSUP,
511 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
512 "Meter is not supported");
513 /* Meter profile must exist. */
514 fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id);
516 return -rte_mtr_error_set(error, ENOENT,
517 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
519 "Meter profile id is invalid.");
520 /* Check profile is unused. */
522 return -rte_mtr_error_set(error, EBUSY,
523 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
524 NULL, "Meter profile is in use.");
525 if (mlx5_l3t_clear_entry(priv->mtr_profile_tbl, meter_profile_id))
526 return -rte_mtr_error_set(error, EBUSY,
527 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
528 NULL, "Meter profile remove fail.");
537 * Pointer to Ethernet device.
542 * Pointer to the policy found on success, NULL otherwise.
544 struct mlx5_flow_meter_policy *
545 mlx5_flow_meter_policy_find(struct rte_eth_dev *dev,
547 uint32_t *policy_idx)
549 struct mlx5_priv *priv = dev->data->dev_private;
550 struct mlx5_flow_meter_sub_policy *sub_policy = NULL;
551 union mlx5_l3t_data data;
553 if (policy_id > MLX5_MAX_SUB_POLICY_TBL_NUM || !priv->policy_idx_tbl)
555 if (mlx5_l3t_get_entry(priv->policy_idx_tbl, policy_id, &data) ||
559 *policy_idx = data.dword;
560 sub_policy = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
562 /* Remove reference taken by the mlx5_l3t_get_entry. */
563 mlx5_l3t_clear_entry(priv->policy_idx_tbl, policy_id);
565 if (sub_policy->main_policy_id)
566 return sub_policy->main_policy;
571 * Get the last meter's policy from one meter's policy in hierarchy.
574 * Pointer to Ethernet device.
576 * Pointer to flow meter policy.
579 * Pointer to the final meter's policy, or NULL when fail.
581 struct mlx5_flow_meter_policy *
582 mlx5_flow_meter_hierarchy_get_final_policy(struct rte_eth_dev *dev,
583 struct mlx5_flow_meter_policy *policy)
585 struct mlx5_priv *priv = dev->data->dev_private;
586 struct mlx5_flow_meter_info *next_fm;
587 struct mlx5_flow_meter_policy *next_policy = policy;
589 while (next_policy->is_hierarchy) {
590 next_fm = mlx5_flow_meter_find(priv,
591 next_policy->act_cnt[RTE_COLOR_GREEN].next_mtr_id, NULL);
592 if (!next_fm || next_fm->def_policy)
594 next_policy = mlx5_flow_meter_policy_find(dev,
595 next_fm->policy_id, NULL);
596 MLX5_ASSERT(next_policy);
602 * Callback to check MTR policy action validate
605 * Pointer to Ethernet device.
607 * Pointer to meter policy action detail.
609 * Pointer to the error structure.
612 * 0 on success, a negative errno value otherwise and rte_errno is set.
615 mlx5_flow_meter_policy_validate(struct rte_eth_dev *dev,
616 struct rte_mtr_meter_policy_params *policy,
617 struct rte_mtr_error *error)
619 struct mlx5_priv *priv = dev->data->dev_private;
620 struct rte_flow_attr attr = { .transfer =
621 priv->config.dv_esw_en ? 1 : 0};
624 uint8_t domain_bitmap;
627 if (!priv->mtr_en || !priv->sh->meter_aso_en)
628 return -rte_mtr_error_set(error, ENOTSUP,
629 RTE_MTR_ERROR_TYPE_METER_POLICY,
630 NULL, "meter policy unsupported.");
631 ret = mlx5_flow_validate_mtr_acts(dev, policy->actions, &attr,
632 &is_rss, &domain_bitmap, &policy_mode, error);
639 __mlx5_flow_meter_policy_delete(struct rte_eth_dev *dev,
641 struct mlx5_flow_meter_policy *mtr_policy,
642 struct rte_mtr_error *error,
645 struct mlx5_priv *priv = dev->data->dev_private;
646 struct mlx5_flow_meter_sub_policy *sub_policy;
648 uint16_t sub_policy_num;
650 rte_spinlock_lock(&mtr_policy->sl);
651 if (mtr_policy->ref_cnt) {
652 rte_spinlock_unlock(&mtr_policy->sl);
653 return -rte_mtr_error_set(error, EBUSY,
654 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
656 "Meter policy object is being used.");
658 mlx5_flow_destroy_policy_rules(dev, mtr_policy);
659 mlx5_flow_destroy_mtr_acts(dev, mtr_policy);
660 for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
661 sub_policy_num = (mtr_policy->sub_policy_num >>
662 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i)) &
663 MLX5_MTR_SUB_POLICY_NUM_MASK;
664 if (sub_policy_num) {
665 for (j = 0; j < sub_policy_num; j++) {
666 sub_policy = mtr_policy->sub_policys[i][j];
669 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
674 if (priv->policy_idx_tbl && clear_l3t) {
675 if (mlx5_l3t_clear_entry(priv->policy_idx_tbl, policy_id)) {
676 rte_spinlock_unlock(&mtr_policy->sl);
677 return -rte_mtr_error_set(error, ENOTSUP,
678 RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL,
679 "Fail to delete policy in index table.");
682 rte_spinlock_unlock(&mtr_policy->sl);
687 * Callback to add MTR policy.
690 * Pointer to Ethernet device.
691 * @param[out] policy_id
692 * Pointer to policy id
694 * Pointer to meter policy action detail.
696 * Pointer to the error structure.
699 * 0 on success, a negative errno value otherwise and rte_errno is set.
702 mlx5_flow_meter_policy_add(struct rte_eth_dev *dev,
704 struct rte_mtr_meter_policy_params *policy,
705 struct rte_mtr_error *error)
707 struct mlx5_priv *priv = dev->data->dev_private;
708 struct rte_flow_attr attr = { .transfer =
709 priv->config.dv_esw_en ? 1 : 0};
710 uint32_t sub_policy_idx = 0;
711 uint32_t policy_idx = 0;
712 struct mlx5_flow_meter_policy *mtr_policy = NULL;
713 struct mlx5_flow_meter_sub_policy *sub_policy;
718 uint32_t policy_size = sizeof(struct mlx5_flow_meter_policy);
719 uint16_t sub_policy_num;
720 uint8_t domain_bitmap = 0;
721 union mlx5_l3t_data data;
722 bool skip_rule = false;
725 return -rte_mtr_error_set(error, ENOTSUP,
726 RTE_MTR_ERROR_TYPE_METER_POLICY,
727 NULL, "meter policy unsupported. ");
728 if (policy_id == MLX5_INVALID_POLICY_ID)
729 return -rte_mtr_error_set(error, ENOTSUP,
730 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
731 NULL, "policy ID is invalid. ");
732 if (policy_id == priv->sh->mtrmng->def_policy_id)
733 return -rte_mtr_error_set(error, EEXIST,
734 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
735 NULL, "default policy ID exists. ");
736 mtr_policy = mlx5_flow_meter_policy_find(dev, policy_id, &policy_idx);
738 return -rte_mtr_error_set(error, EEXIST,
739 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
740 NULL, "policy ID exists. ");
741 ret = mlx5_flow_validate_mtr_acts(dev, policy->actions, &attr,
742 &is_rss, &domain_bitmap,
743 &policy_mode, error);
747 return -rte_mtr_error_set(error, ENOTSUP,
748 RTE_MTR_ERROR_TYPE_METER_POLICY,
749 NULL, "fail to find policy domain.");
750 if (policy_mode == MLX5_MTR_POLICY_MODE_DEF) {
751 if (priv->sh->mtrmng->def_policy_id != MLX5_INVALID_POLICY_ID)
752 return -rte_mtr_error_set(error, EEXIST,
753 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
754 NULL, "a policy with similar actions "
755 "is already configured");
756 if (mlx5_flow_create_def_policy(dev))
757 return -rte_mtr_error_set(error, ENOTSUP,
758 RTE_MTR_ERROR_TYPE_METER_POLICY,
760 "fail to create non-terminated policy.");
761 priv->sh->mtrmng->def_policy_id = policy_id;
764 if (!priv->sh->meter_aso_en)
765 return -rte_mtr_error_set(error, ENOTSUP,
766 RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
767 "no ASO capability to support the policy ");
768 for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
769 if (!(domain_bitmap & (1 << i)))
772 * If RSS is found, it means that only the ingress domain can
773 * be supported. It is invalid to support RSS for one color
774 * and egress / transfer domain actions for another. Drop and
775 * jump action should have no impact.
779 sizeof(struct mlx5_flow_meter_sub_policy *) *
780 MLX5_MTR_RSS_MAX_SUB_POLICY;
783 policy_size += sizeof(struct mlx5_flow_meter_sub_policy *);
785 mtr_policy = mlx5_malloc(MLX5_MEM_ZERO, policy_size,
786 RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
788 return -rte_mtr_error_set(error, ENOMEM,
789 RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
790 "Memory alloc failed for meter policy.");
791 if (policy_mode == MLX5_MTR_POLICY_MODE_OG)
792 mtr_policy->skip_y = 1;
793 else if (policy_mode == MLX5_MTR_POLICY_MODE_OY)
794 mtr_policy->skip_g = 1;
795 policy_size = sizeof(struct mlx5_flow_meter_policy);
796 for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
797 if (!(domain_bitmap & (1 << i)))
799 if (i == MLX5_MTR_DOMAIN_INGRESS)
800 mtr_policy->ingress = 1;
801 if (i == MLX5_MTR_DOMAIN_EGRESS)
802 mtr_policy->egress = 1;
803 if (i == MLX5_MTR_DOMAIN_TRANSFER)
804 mtr_policy->transfer = 1;
805 sub_policy = mlx5_ipool_zmalloc
806 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
809 sub_policy_idx > MLX5_MAX_SUB_POLICY_TBL_NUM)
811 sub_policy->idx = sub_policy_idx;
812 sub_policy->main_policy = mtr_policy;
814 policy_idx = sub_policy_idx;
815 sub_policy->main_policy_id = 1;
817 mtr_policy->sub_policys[i] =
818 (struct mlx5_flow_meter_sub_policy **)
819 ((uint8_t *)mtr_policy + policy_size);
820 mtr_policy->sub_policys[i][0] = sub_policy;
821 sub_policy_num = (mtr_policy->sub_policy_num >>
822 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i)) &
823 MLX5_MTR_SUB_POLICY_NUM_MASK;
825 mtr_policy->sub_policy_num &= ~(MLX5_MTR_SUB_POLICY_NUM_MASK <<
826 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i));
827 mtr_policy->sub_policy_num |=
828 (sub_policy_num & MLX5_MTR_SUB_POLICY_NUM_MASK) <<
829 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i);
831 * If RSS is found, it means that only the ingress domain can
832 * be supported. It is invalid to support RSS for one color
833 * and egress / transfer domain actions for another. Drop and
834 * jump action should have no impact.
837 mtr_policy->is_rss = 1;
840 policy_size += sizeof(struct mlx5_flow_meter_sub_policy *);
842 rte_spinlock_init(&mtr_policy->sl);
843 ret = mlx5_flow_create_mtr_acts(dev, mtr_policy,
844 policy->actions, error);
847 if (mtr_policy->is_hierarchy) {
848 struct mlx5_flow_meter_policy *final_policy;
851 mlx5_flow_meter_hierarchy_get_final_policy(dev, mtr_policy);
854 skip_rule = (final_policy->is_rss || final_policy->is_queue);
857 * If either Green or Yellow has queue / RSS action, all the policy
858 * rules will be created later in the flow splitting stage.
860 if (!is_rss && !mtr_policy->is_queue && !skip_rule) {
861 /* Create policy rules in HW. */
862 ret = mlx5_flow_create_policy_rules(dev, mtr_policy);
866 data.dword = policy_idx;
867 if (!priv->policy_idx_tbl) {
868 priv->policy_idx_tbl = mlx5_l3t_create(MLX5_L3T_TYPE_DWORD);
869 if (!priv->policy_idx_tbl)
872 if (mlx5_l3t_set_entry(priv->policy_idx_tbl, policy_id, &data))
877 ret = __mlx5_flow_meter_policy_delete(dev, policy_id,
878 mtr_policy, error, false);
879 mlx5_free(mtr_policy);
883 return -rte_mtr_error_set(error, ENOTSUP,
884 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
885 NULL, "Failed to create devx policy.");
889 * Callback to delete MTR policy.
892 * Pointer to Ethernet device.
893 * @param[in] policy_id
896 * Pointer to the error structure.
899 * 0 on success, a negative errno value otherwise and rte_errno is set.
902 mlx5_flow_meter_policy_delete(struct rte_eth_dev *dev,
904 struct rte_mtr_error *error)
906 struct mlx5_priv *priv = dev->data->dev_private;
907 struct mlx5_flow_meter_policy *mtr_policy;
911 if (policy_id == priv->sh->mtrmng->def_policy_id) {
912 if (priv->sh->mtrmng->def_policy_ref_cnt > 0)
913 return -rte_mtr_error_set(error, ENOTSUP,
914 RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL,
915 "Meter policy object is being used.");
916 priv->sh->mtrmng->def_policy_id = MLX5_INVALID_POLICY_ID;
919 mtr_policy = mlx5_flow_meter_policy_find(dev, policy_id, &policy_idx);
921 return -rte_mtr_error_set(error, ENOTSUP,
922 RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL,
923 "Meter policy id is invalid. ");
924 ret = __mlx5_flow_meter_policy_delete(dev, policy_id, mtr_policy,
928 mlx5_free(mtr_policy);
933 * Check meter validation.
936 * Pointer to mlx5 private data structure.
937 * @param[in] meter_id
940 * Pointer to rte meter parameters.
942 * Pointer to rte meter error structure.
945 * 0 on success, a negative errno value otherwise and rte_errno is set.
948 mlx5_flow_meter_validate(struct mlx5_priv *priv, uint32_t meter_id,
949 struct rte_mtr_params *params,
950 struct rte_mtr_error *error)
952 /* Meter must use global drop action. */
953 if (!priv->sh->dr_drop_action)
954 return -rte_mtr_error_set(error, ENOTSUP,
955 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
957 "No drop action ready for meter.");
958 /* Meter params must not be NULL. */
960 return -rte_mtr_error_set(error, EINVAL,
961 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
962 NULL, "Meter object params null.");
963 /* Previous meter color is not supported. */
964 if (params->use_prev_mtr_color)
965 return -rte_mtr_error_set(error, ENOTSUP,
966 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
968 "Previous meter color "
970 if (params->meter_policy_id == MLX5_INVALID_POLICY_ID)
971 return -rte_mtr_error_set(error, ENOENT,
972 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
973 NULL, "Meter policy id not valid.");
974 /* Validate meter id. */
975 if (mlx5_flow_meter_find(priv, meter_id, NULL))
976 return -rte_mtr_error_set(error, EEXIST,
977 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
978 "Meter object already exists.");
983 * Modify the flow meter action.
986 * Pointer to mlx5 private data structure.
988 * Pointer to flow meter to be modified.
990 * Pointer to meter srtcm description parameter.
991 * @param[in] modify_bits
992 * The bit in srtcm to be updated.
993 * @param[in] active_state
994 * The state to be updated.
996 * 0 on success, o negative value otherwise.
999 mlx5_flow_meter_action_modify(struct mlx5_priv *priv,
1000 struct mlx5_flow_meter_info *fm,
1001 const struct mlx5_flow_meter_srtcm_rfc2697_prm *srtcm,
1002 uint64_t modify_bits, uint32_t active_state, uint32_t is_enable)
1004 #ifdef HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER
1005 uint32_t in[MLX5_ST_SZ_DW(flow_meter_parameters)] = { 0 };
1007 struct mlx5dv_dr_flow_meter_attr mod_attr = { 0 };
1009 struct mlx5_aso_mtr *aso_mtr = NULL;
1010 uint32_t cbs_cir, ebs_eir, val;
1012 if (priv->sh->meter_aso_en) {
1013 fm->is_enable = !!is_enable;
1014 aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
1015 ret = mlx5_aso_meter_update_by_wqe(priv->sh, aso_mtr);
1018 ret = mlx5_aso_mtr_wait(priv->sh, aso_mtr);
1022 /* Fill command parameters. */
1023 mod_attr.reg_c_index = priv->mtr_color_reg - REG_C_0;
1024 mod_attr.flow_meter_parameter = in;
1025 mod_attr.flow_meter_parameter_sz =
1026 MLX5_ST_SZ_BYTES(flow_meter_parameters);
1027 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_ACTIVE)
1028 mod_attr.active = !!active_state;
1030 mod_attr.active = 0;
1032 cbs_cir = rte_be_to_cpu_32(srtcm->cbs_cir);
1033 ebs_eir = rte_be_to_cpu_32(srtcm->ebs_eir);
1034 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS) {
1035 val = (cbs_cir >> ASO_DSEG_CBS_EXP_OFFSET) &
1037 MLX5_SET(flow_meter_parameters, attr,
1039 val = (cbs_cir >> ASO_DSEG_CBS_MAN_OFFSET) &
1041 MLX5_SET(flow_meter_parameters, attr,
1044 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR) {
1045 val = (cbs_cir >> ASO_DSEG_XIR_EXP_OFFSET) &
1047 MLX5_SET(flow_meter_parameters, attr,
1049 val = cbs_cir & ASO_DSEG_MAN_MASK;
1050 MLX5_SET(flow_meter_parameters, attr,
1053 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_EBS) {
1054 val = (ebs_eir >> ASO_DSEG_EBS_EXP_OFFSET) &
1056 MLX5_SET(flow_meter_parameters, attr,
1058 val = (ebs_eir >> ASO_DSEG_EBS_MAN_OFFSET) &
1060 MLX5_SET(flow_meter_parameters, attr,
1063 /* Apply modifications to meter only if it was created. */
1064 if (fm->meter_action) {
1065 ret = mlx5_glue->dv_modify_flow_action_meter
1066 (fm->meter_action, &mod_attr,
1067 rte_cpu_to_be_64(modify_bits));
1071 /* Update succeedded modify meter parameters. */
1072 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_ACTIVE)
1073 fm->active_state = !!active_state;
1088 mlx5_flow_meter_stats_enable_update(struct rte_eth_dev *dev,
1089 struct mlx5_flow_meter_info *fm,
1090 uint64_t stats_mask)
1093 (stats_mask & RTE_MTR_STATS_N_BYTES_DROPPED) ? 1 : 0;
1094 fm->pkts_dropped = (stats_mask & RTE_MTR_STATS_N_PKTS_DROPPED) ? 1 : 0;
1095 if (fm->bytes_dropped || fm->pkts_dropped) {
1096 if (!fm->drop_cnt) {
1097 /* Alloc policer counters. */
1098 fm->drop_cnt = mlx5_counter_alloc(dev);
1104 mlx5_counter_free(dev, fm->drop_cnt);
1112 * Create meter rules.
1115 * Pointer to Ethernet device.
1116 * @param[in] meter_id
1119 * Pointer to rte meter parameters.
1121 * Meter shared with other flow or not.
1123 * Pointer to rte meter error structure.
1126 * 0 on success, a negative errno value otherwise and rte_errno is set.
1129 mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,
1130 struct rte_mtr_params *params, int shared,
1131 struct rte_mtr_error *error)
1133 struct mlx5_priv *priv = dev->data->dev_private;
1134 struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
1135 struct mlx5_flow_meter_profile *fmp;
1136 struct mlx5_flow_meter_info *fm;
1137 struct mlx5_legacy_flow_meter *legacy_fm;
1138 struct mlx5_flow_meter_policy *mtr_policy = NULL;
1139 struct mlx5_indexed_pool_config flow_ipool_cfg = {
1143 .type = "mlx5_flow_mtr_flow_id_pool",
1145 struct mlx5_aso_mtr *aso_mtr;
1146 uint32_t mtr_idx, policy_idx;
1147 union mlx5_l3t_data data;
1149 uint8_t domain_bitmap;
1150 uint8_t mtr_id_bits;
1151 uint8_t mtr_reg_bits = priv->mtr_reg_share ?
1152 MLX5_MTR_IDLE_BITS_IN_COLOR_REG : MLX5_REG_BITS;
1155 return -rte_mtr_error_set(error, ENOTSUP,
1156 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1157 "Meter is not supported");
1158 /* Validate the parameters. */
1159 ret = mlx5_flow_meter_validate(priv, meter_id, params, error);
1162 /* Meter profile must exist. */
1163 fmp = mlx5_flow_meter_profile_find(priv, params->meter_profile_id);
1165 return -rte_mtr_error_set(error, ENOENT,
1166 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
1167 NULL, "Meter profile id not valid.");
1168 /* Meter policy must exist. */
1169 if (params->meter_policy_id == priv->sh->mtrmng->def_policy_id) {
1171 (&priv->sh->mtrmng->def_policy_ref_cnt,
1172 1, __ATOMIC_RELAXED);
1173 domain_bitmap = MLX5_MTR_ALL_DOMAIN_BIT;
1174 if (!priv->config.dv_esw_en)
1175 domain_bitmap &= ~MLX5_MTR_DOMAIN_TRANSFER_BIT;
1177 if (!priv->sh->meter_aso_en)
1178 return -rte_mtr_error_set(error, ENOTSUP,
1179 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1180 "Part of the policies cannot be "
1181 "supported without ASO ");
1182 mtr_policy = mlx5_flow_meter_policy_find(dev,
1183 params->meter_policy_id, &policy_idx);
1185 return -rte_mtr_error_set(error, ENOENT,
1186 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
1187 NULL, "Meter policy id not valid.");
1188 domain_bitmap = (mtr_policy->ingress ?
1189 MLX5_MTR_DOMAIN_INGRESS_BIT : 0) |
1190 (mtr_policy->egress ?
1191 MLX5_MTR_DOMAIN_EGRESS_BIT : 0) |
1192 (mtr_policy->transfer ?
1193 MLX5_MTR_DOMAIN_TRANSFER_BIT : 0);
1194 if (fmp->g_support && mtr_policy->skip_g)
1195 return -rte_mtr_error_set(error, ENOTSUP,
1196 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
1197 NULL, "Meter green policy is empty.");
1198 if (fmp->y_support && mtr_policy->skip_y)
1199 return -rte_mtr_error_set(error, ENOTSUP,
1200 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
1201 NULL, "Meter yellow policy is empty.");
1203 /* Allocate the flow meter memory. */
1204 if (priv->sh->meter_aso_en) {
1205 mtr_idx = mlx5_flow_mtr_alloc(dev);
1207 return -rte_mtr_error_set(error, ENOMEM,
1208 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1209 "Memory alloc failed for meter.");
1210 aso_mtr = mlx5_aso_meter_by_idx(priv, mtr_idx);
1213 legacy_fm = mlx5_ipool_zmalloc
1214 (priv->sh->ipool[MLX5_IPOOL_MTR], &mtr_idx);
1215 if (legacy_fm == NULL)
1216 return -rte_mtr_error_set(error, ENOMEM,
1217 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1218 "Memory alloc failed for meter.");
1219 legacy_fm->idx = mtr_idx;
1220 fm = &legacy_fm->fm;
1222 mtr_id_bits = MLX5_REG_BITS - __builtin_clz(mtr_idx);
1223 if ((mtr_id_bits + priv->sh->mtrmng->max_mtr_flow_bits) >
1225 DRV_LOG(ERR, "Meter number exceeds max limit.");
1228 if (mtr_id_bits > priv->sh->mtrmng->max_mtr_bits)
1229 priv->sh->mtrmng->max_mtr_bits = mtr_id_bits;
1230 /* Fill the flow meter parameters. */
1231 fm->meter_id = meter_id;
1232 fm->policy_id = params->meter_policy_id;
1234 if (mlx5_flow_meter_stats_enable_update(dev, fm, params->stats_mask))
1236 if (mlx5_flow_create_mtr_tbls(dev, fm, mtr_idx, domain_bitmap))
1238 /* Add to the flow meter list. */
1239 if (!priv->sh->meter_aso_en)
1240 TAILQ_INSERT_TAIL(fms, legacy_fm, next);
1241 /* Add to the flow meter list. */
1242 fm->active_state = 1; /* Config meter starts as active. */
1244 fm->shared = !!shared;
1245 __atomic_add_fetch(&fm->profile->ref_cnt, 1, __ATOMIC_RELAXED);
1246 if (params->meter_policy_id == priv->sh->mtrmng->def_policy_id) {
1248 fm->flow_ipool = mlx5_ipool_create(&flow_ipool_cfg);
1249 if (!fm->flow_ipool)
1252 rte_spinlock_init(&fm->sl);
1253 /* If ASO meter supported, update ASO flow meter by wqe. */
1254 if (priv->sh->meter_aso_en) {
1255 aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
1256 ret = mlx5_aso_meter_update_by_wqe(priv->sh, aso_mtr);
1259 if (!priv->mtr_idx_tbl) {
1261 mlx5_l3t_create(MLX5_L3T_TYPE_DWORD);
1262 if (!priv->mtr_idx_tbl)
1265 data.dword = mtr_idx;
1266 if (mlx5_l3t_set_entry(priv->mtr_idx_tbl, meter_id, &data))
1270 __atomic_add_fetch(&mtr_policy->ref_cnt, 1, __ATOMIC_RELAXED);
1273 mlx5_flow_destroy_mtr_tbls(dev, fm);
1274 /* Free policer counters. */
1276 mlx5_counter_free(dev, fm->drop_cnt);
1277 if (priv->sh->meter_aso_en)
1278 mlx5_flow_mtr_free(dev, mtr_idx);
1280 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR], mtr_idx);
1281 return -rte_mtr_error_set(error, ENOTSUP,
1282 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
1283 NULL, "Failed to create devx meter.");
1287 mlx5_flow_meter_params_flush(struct rte_eth_dev *dev,
1288 struct mlx5_flow_meter_info *fm,
1291 struct mlx5_priv *priv = dev->data->dev_private;
1292 struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
1293 struct mlx5_flow_meter_profile *fmp;
1294 struct mlx5_legacy_flow_meter *legacy_fm = NULL;
1295 struct mlx5_flow_meter_policy *mtr_policy;
1297 /* Meter object must not have any owner. */
1298 MLX5_ASSERT(!fm->ref_cnt);
1299 /* Get meter profile. */
1303 /* Update dependencies. */
1304 __atomic_sub_fetch(&fmp->ref_cnt, 1, __ATOMIC_RELAXED);
1306 /* Remove from list. */
1307 if (!priv->sh->meter_aso_en) {
1308 legacy_fm = container_of(fm,
1309 struct mlx5_legacy_flow_meter, fm);
1310 TAILQ_REMOVE(fms, legacy_fm, next);
1312 /* Free drop counters. */
1314 mlx5_counter_free(dev, fm->drop_cnt);
1315 /* Free meter flow table. */
1316 if (fm->flow_ipool) {
1317 mlx5_ipool_destroy(fm->flow_ipool);
1320 mlx5_flow_destroy_mtr_tbls(dev, fm);
1322 __atomic_sub_fetch(&priv->sh->mtrmng->def_policy_ref_cnt,
1323 1, __ATOMIC_RELAXED);
1324 if (priv->sh->meter_aso_en) {
1325 if (!fm->def_policy) {
1326 mtr_policy = mlx5_flow_meter_policy_find(dev,
1327 fm->policy_id, NULL);
1329 __atomic_sub_fetch(&mtr_policy->ref_cnt,
1330 1, __ATOMIC_RELAXED);
1334 if (mlx5_l3t_clear_entry(priv->mtr_idx_tbl, fm->meter_id))
1336 mlx5_flow_mtr_free(dev, mtr_idx);
1338 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR],
1345 * Destroy meter rules.
1348 * Pointer to Ethernet device.
1349 * @param[in] meter_id
1352 * Pointer to rte meter error structure.
1355 * 0 on success, a negative errno value otherwise and rte_errno is set.
1358 mlx5_flow_meter_destroy(struct rte_eth_dev *dev, uint32_t meter_id,
1359 struct rte_mtr_error *error)
1361 struct mlx5_priv *priv = dev->data->dev_private;
1362 struct mlx5_flow_meter_info *fm;
1363 uint32_t mtr_idx = 0;
1366 return -rte_mtr_error_set(error, ENOTSUP,
1367 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
1369 "Meter is not supported");
1370 /* Meter object must exist. */
1371 fm = mlx5_flow_meter_find(priv, meter_id, &mtr_idx);
1373 return -rte_mtr_error_set(error, ENOENT,
1374 RTE_MTR_ERROR_TYPE_MTR_ID,
1376 "Meter object id not valid.");
1377 /* Meter object must not have any owner. */
1378 if (fm->ref_cnt > 0)
1379 return -rte_mtr_error_set(error, EBUSY,
1380 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
1382 "Meter object is being used.");
1383 /* Destroy the meter profile. */
1384 if (mlx5_flow_meter_params_flush(dev, fm, mtr_idx))
1385 return -rte_mtr_error_set(error, EINVAL,
1386 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
1388 "MTR object meter profile invalid.");
1393 * Modify meter state.
1396 * Pointer to mlx5 private data structure.
1398 * Pointer to flow meter.
1399 * @param[in] new_state
1400 * New state to update.
1402 * Pointer to rte meter error structure.
1405 * 0 on success, a negative errno value otherwise and rte_errno is set.
1408 mlx5_flow_meter_modify_state(struct mlx5_priv *priv,
1409 struct mlx5_flow_meter_info *fm,
1411 struct rte_mtr_error *error)
1413 static const struct mlx5_flow_meter_srtcm_rfc2697_prm srtcm = {
1414 .cbs_cir = RTE_BE32(MLX5_IFC_FLOW_METER_DISABLE_CBS_CIR_VAL),
1417 uint64_t modify_bits = MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS |
1418 MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR;
1421 if (new_state == MLX5_FLOW_METER_DISABLE)
1422 ret = mlx5_flow_meter_action_modify(priv, fm,
1423 &srtcm, modify_bits, 0, 0);
1425 ret = mlx5_flow_meter_action_modify(priv, fm,
1426 &fm->profile->srtcm_prm,
1429 return -rte_mtr_error_set(error, -ret,
1430 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
1433 "Failed to enable meter." :
1434 "Failed to disable meter.");
1439 * Callback to enable flow meter.
1442 * Pointer to Ethernet device.
1443 * @param[in] meter_id
1446 * Pointer to rte meter error structure.
1449 * 0 on success, a negative errno value otherwise and rte_errno is set.
1452 mlx5_flow_meter_enable(struct rte_eth_dev *dev,
1454 struct rte_mtr_error *error)
1456 struct mlx5_priv *priv = dev->data->dev_private;
1457 struct mlx5_flow_meter_info *fm;
1461 return -rte_mtr_error_set(error, ENOTSUP,
1462 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1463 "Meter is not supported");
1464 /* Meter object must exist. */
1465 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1467 return -rte_mtr_error_set(error, ENOENT,
1468 RTE_MTR_ERROR_TYPE_MTR_ID,
1469 NULL, "Meter not found.");
1470 if (fm->active_state == MLX5_FLOW_METER_ENABLE)
1472 ret = mlx5_flow_meter_modify_state(priv, fm, MLX5_FLOW_METER_ENABLE,
1475 fm->active_state = MLX5_FLOW_METER_ENABLE;
1480 * Callback to disable flow meter.
1483 * Pointer to Ethernet device.
1484 * @param[in] meter_id
1487 * Pointer to rte meter error structure.
1490 * 0 on success, a negative errno value otherwise and rte_errno is set.
1493 mlx5_flow_meter_disable(struct rte_eth_dev *dev,
1495 struct rte_mtr_error *error)
1497 struct mlx5_priv *priv = dev->data->dev_private;
1498 struct mlx5_flow_meter_info *fm;
1502 return -rte_mtr_error_set(error, ENOTSUP,
1503 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1504 "Meter is not supported");
1505 /* Meter object must exist. */
1506 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1508 return -rte_mtr_error_set(error, ENOENT,
1509 RTE_MTR_ERROR_TYPE_MTR_ID,
1510 NULL, "Meter not found.");
1511 if (fm->active_state == MLX5_FLOW_METER_DISABLE)
1513 ret = mlx5_flow_meter_modify_state(priv, fm, MLX5_FLOW_METER_DISABLE,
1516 fm->active_state = MLX5_FLOW_METER_DISABLE;
1521 * Callback to update meter profile.
1524 * Pointer to Ethernet device.
1525 * @param[in] meter_id
1527 * @param[in] meter_profile_id
1528 * To be updated meter profile id.
1530 * Pointer to rte meter error structure.
1533 * 0 on success, a negative errno value otherwise and rte_errno is set.
1536 mlx5_flow_meter_profile_update(struct rte_eth_dev *dev,
1538 uint32_t meter_profile_id,
1539 struct rte_mtr_error *error)
1541 struct mlx5_priv *priv = dev->data->dev_private;
1542 struct mlx5_flow_meter_profile *fmp;
1543 struct mlx5_flow_meter_profile *old_fmp;
1544 struct mlx5_flow_meter_info *fm;
1545 uint64_t modify_bits = MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS |
1546 MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR;
1550 return -rte_mtr_error_set(error, ENOTSUP,
1551 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1552 "Meter is not supported");
1553 /* Meter profile must exist. */
1554 fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id);
1556 return -rte_mtr_error_set(error, ENOENT,
1557 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
1558 NULL, "Meter profile not found.");
1559 /* Meter object must exist. */
1560 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1562 return -rte_mtr_error_set(error, ENOENT,
1563 RTE_MTR_ERROR_TYPE_MTR_ID,
1564 NULL, "Meter not found.");
1565 /* MTR object already set to meter profile id. */
1566 old_fmp = fm->profile;
1569 /* Update the profile. */
1571 /* Update meter params in HW (if not disabled). */
1572 if (fm->active_state == MLX5_FLOW_METER_DISABLE)
1574 ret = mlx5_flow_meter_action_modify(priv, fm, &fm->profile->srtcm_prm,
1575 modify_bits, fm->active_state, 1);
1577 fm->profile = old_fmp;
1578 return -rte_mtr_error_set(error, -ret,
1579 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
1580 NULL, "Failed to update meter"
1581 " parmeters in hardware.");
1589 * Callback to update meter stats mask.
1592 * Pointer to Ethernet device.
1593 * @param[in] meter_id
1595 * @param[in] stats_mask
1596 * To be updated stats_mask.
1598 * Pointer to rte meter error structure.
1601 * 0 on success, a negative errno value otherwise and rte_errno is set.
1604 mlx5_flow_meter_stats_update(struct rte_eth_dev *dev,
1606 uint64_t stats_mask,
1607 struct rte_mtr_error *error)
1609 struct mlx5_priv *priv = dev->data->dev_private;
1610 struct mlx5_flow_meter_info *fm;
1613 return -rte_mtr_error_set(error, ENOTSUP,
1614 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1615 "Meter is not supported");
1616 /* Meter object must exist. */
1617 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1619 return -rte_mtr_error_set(error, ENOENT,
1620 RTE_MTR_ERROR_TYPE_MTR_ID,
1621 NULL, "Meter object id not valid.");
1622 if (mlx5_flow_meter_stats_enable_update(dev, fm, stats_mask))
1623 return -rte_mtr_error_set(error, ENOENT,
1624 RTE_MTR_ERROR_TYPE_MTR_ID,
1625 NULL, "Fail to allocate "
1626 "counter for meter.");
1631 * Callback to read meter statistics.
1634 * Pointer to Ethernet device.
1635 * @param[in] meter_id
1638 * Pointer to store the statistics.
1639 * @param[out] stats_mask
1640 * Pointer to store the stats_mask.
1642 * Statistic to be cleared after read or not.
1644 * Pointer to rte meter error structure.
1647 * 0 on success, a negative errno value otherwise and rte_errno is set.
1650 mlx5_flow_meter_stats_read(struct rte_eth_dev *dev,
1652 struct rte_mtr_stats *stats,
1653 uint64_t *stats_mask,
1655 struct rte_mtr_error *error)
1657 struct mlx5_priv *priv = dev->data->dev_private;
1658 struct mlx5_flow_meter_info *fm;
1664 return -rte_mtr_error_set(error, ENOTSUP,
1665 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1666 "Meter is not supported");
1667 /* Meter object must exist. */
1668 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1670 return -rte_mtr_error_set(error, ENOENT,
1671 RTE_MTR_ERROR_TYPE_MTR_ID,
1672 NULL, "Meter object id not valid.");
1674 if (fm->bytes_dropped)
1675 *stats_mask |= RTE_MTR_STATS_N_BYTES_DROPPED;
1676 if (fm->pkts_dropped)
1677 *stats_mask |= RTE_MTR_STATS_N_PKTS_DROPPED;
1678 memset(stats, 0, sizeof(*stats));
1680 ret = mlx5_counter_query(dev, fm->drop_cnt, clear, &pkts,
1684 /* If need to read the packets, set it. */
1685 if (fm->pkts_dropped)
1686 stats->n_pkts_dropped = pkts;
1687 /* If need to read the bytes, set it. */
1688 if (fm->bytes_dropped)
1689 stats->n_bytes_dropped = bytes;
1693 return -rte_mtr_error_set(error, ret, RTE_MTR_ERROR_TYPE_STATS, NULL,
1694 "Failed to read meter drop counters.");
1697 static const struct rte_mtr_ops mlx5_flow_mtr_ops = {
1698 .capabilities_get = mlx5_flow_mtr_cap_get,
1699 .meter_profile_add = mlx5_flow_meter_profile_add,
1700 .meter_profile_delete = mlx5_flow_meter_profile_delete,
1701 .meter_policy_validate = mlx5_flow_meter_policy_validate,
1702 .meter_policy_add = mlx5_flow_meter_policy_add,
1703 .meter_policy_delete = mlx5_flow_meter_policy_delete,
1704 .create = mlx5_flow_meter_create,
1705 .destroy = mlx5_flow_meter_destroy,
1706 .meter_enable = mlx5_flow_meter_enable,
1707 .meter_disable = mlx5_flow_meter_disable,
1708 .meter_profile_update = mlx5_flow_meter_profile_update,
1709 .meter_dscp_table_update = NULL,
1710 .stats_update = mlx5_flow_meter_stats_update,
1711 .stats_read = mlx5_flow_meter_stats_read,
1715 * Get meter operations.
1718 * Pointer to Ethernet device structure.
1720 * Pointer to set the mtr operations.
1726 mlx5_flow_meter_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)
1728 *(const struct rte_mtr_ops **)arg = &mlx5_flow_mtr_ops;
1736 * Pointer to mlx5_priv.
1740 * Pointer to Meter index.
1743 * Pointer to the meter info found on success, NULL otherwise.
1745 struct mlx5_flow_meter_info *
1746 mlx5_flow_meter_find(struct mlx5_priv *priv, uint32_t meter_id,
1749 struct mlx5_legacy_flow_meter *legacy_fm;
1750 struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
1751 struct mlx5_aso_mtr *aso_mtr;
1752 struct mlx5_aso_mtr_pools_mng *pools_mng =
1753 &priv->sh->mtrmng->pools_mng;
1754 union mlx5_l3t_data data;
1756 if (priv->sh->meter_aso_en) {
1757 rte_spinlock_lock(&pools_mng->mtrsl);
1758 if (!pools_mng->n_valid || !priv->mtr_idx_tbl) {
1759 rte_spinlock_unlock(&pools_mng->mtrsl);
1762 if (mlx5_l3t_get_entry(priv->mtr_idx_tbl, meter_id, &data) ||
1764 rte_spinlock_unlock(&pools_mng->mtrsl);
1768 *mtr_idx = data.dword;
1769 aso_mtr = mlx5_aso_meter_by_idx(priv, data.dword);
1770 /* Remove reference taken by the mlx5_l3t_get_entry. */
1771 mlx5_l3t_clear_entry(priv->mtr_idx_tbl, meter_id);
1772 rte_spinlock_unlock(&pools_mng->mtrsl);
1773 if (!aso_mtr || aso_mtr->state == ASO_METER_FREE)
1775 return &aso_mtr->fm;
1777 TAILQ_FOREACH(legacy_fm, fms, next)
1778 if (meter_id == legacy_fm->fm.meter_id) {
1780 *mtr_idx = legacy_fm->idx;
1781 return &legacy_fm->fm;
1787 * Find meter by index.
1790 * Pointer to mlx5_priv.
1795 * Pointer to the meter info found on success, NULL otherwise.
1797 struct mlx5_flow_meter_info *
1798 flow_dv_meter_find_by_idx(struct mlx5_priv *priv, uint32_t idx)
1800 struct mlx5_aso_mtr *aso_mtr;
1802 if (priv->sh->meter_aso_en) {
1803 aso_mtr = mlx5_aso_meter_by_idx(priv, idx);
1806 return &aso_mtr->fm;
1808 return mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MTR], idx);
1813 * Attach meter to flow.
1814 * Unidirectional Meter creation can only be done
1815 * when flow direction is known, i.e. when calling meter_attach.
1818 * Pointer to mlx5 private data.
1820 * Pointer to flow meter.
1822 * Pointer to flow attributes.
1823 * @param [out] error
1824 * Pointer to error structure.
1827 * 0 on success, a negative errno value otherwise and rte_errno is set.
1830 mlx5_flow_meter_attach(struct mlx5_priv *priv,
1831 struct mlx5_flow_meter_info *fm,
1832 const struct rte_flow_attr *attr,
1833 struct rte_flow_error *error)
1837 if (priv->sh->meter_aso_en) {
1838 struct mlx5_aso_mtr *aso_mtr;
1840 aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
1841 if (mlx5_aso_mtr_wait(priv->sh, aso_mtr)) {
1842 return rte_flow_error_set(error, ENOENT,
1843 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1845 "Timeout in meter configuration");
1847 rte_spinlock_lock(&fm->sl);
1848 if (fm->shared || !fm->ref_cnt) {
1851 rte_flow_error_set(error, EINVAL,
1852 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1853 "Meter cannot be shared");
1856 rte_spinlock_unlock(&fm->sl);
1858 rte_spinlock_lock(&fm->sl);
1859 if (fm->meter_action) {
1861 attr->transfer == fm->transfer &&
1862 attr->ingress == fm->ingress &&
1863 attr->egress == fm->egress) {
1866 rte_flow_error_set(error, EINVAL,
1867 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1869 "Meter attr not match." :
1870 "Meter cannot be shared.");
1874 fm->ingress = attr->ingress;
1875 fm->egress = attr->egress;
1876 fm->transfer = attr->transfer;
1878 /* This also creates the meter object. */
1879 fm->meter_action = mlx5_flow_meter_action_create(priv,
1881 if (!fm->meter_action) {
1886 rte_flow_error_set(error, EINVAL,
1887 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1888 "Meter action create failed.");
1892 rte_spinlock_unlock(&fm->sl);
1894 return ret ? -rte_errno : 0;
1898 * Detach meter from flow.
1901 * Pointer to mlx5 private data.
1903 * Pointer to flow meter.
1906 mlx5_flow_meter_detach(struct mlx5_priv *priv,
1907 struct mlx5_flow_meter_info *fm)
1909 #ifdef HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER
1910 rte_spinlock_lock(&fm->sl);
1911 MLX5_ASSERT(fm->ref_cnt);
1912 if (--fm->ref_cnt == 0 && !priv->sh->meter_aso_en) {
1913 mlx5_glue->destroy_flow_action(fm->meter_action);
1914 fm->meter_action = NULL;
1919 rte_spinlock_unlock(&fm->sl);
1927 * Flush meter with Rx queue configuration.
1930 * Pointer to Ethernet device.
1933 mlx5_flow_meter_rxq_flush(struct rte_eth_dev *dev)
1935 struct mlx5_priv *priv = dev->data->dev_private;
1936 struct mlx5_flow_meter_sub_policy *sub_policy;
1937 struct mlx5_flow_meter_policy *mtr_policy;
1939 uint32_t i, policy_idx;
1943 if (priv->policy_idx_tbl) {
1944 MLX5_L3T_FOREACH(priv->policy_idx_tbl, i, entry) {
1945 policy_idx = *(uint32_t *)entry;
1946 sub_policy = mlx5_ipool_get
1947 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
1949 if (!sub_policy || !sub_policy->main_policy)
1951 mtr_policy = sub_policy->main_policy;
1952 if (mtr_policy->is_queue || mtr_policy->is_rss)
1953 mlx5_flow_destroy_sub_policy_with_rxq(dev,
1960 * Iterate a meter hierarchy and flush all meters and policies if possible.
1963 * Pointer to Ethernet device.
1965 * Pointer to flow meter.
1966 * @param[in] mtr_idx
1969 * Pointer to rte meter error structure.
1972 * 0 on success, a negative errno value otherwise and rte_errno is set.
1975 mlx5_flow_meter_flush_hierarchy(struct rte_eth_dev *dev,
1976 struct mlx5_flow_meter_info *fm,
1978 struct rte_mtr_error *error)
1980 struct mlx5_priv *priv = dev->data->dev_private;
1981 struct mlx5_flow_meter_policy *policy;
1983 struct mlx5_flow_meter_info *next_fm;
1984 uint32_t next_mtr_idx;
1985 struct mlx5_flow_meter_policy *next_policy = NULL;
1987 policy = mlx5_flow_meter_policy_find(dev, fm->policy_id, NULL);
1988 MLX5_ASSERT(policy);
1989 while (!fm->ref_cnt && policy->is_hierarchy) {
1990 policy_id = fm->policy_id;
1991 next_fm = mlx5_flow_meter_find(priv,
1992 policy->act_cnt[RTE_COLOR_GREEN].next_mtr_id,
1995 next_policy = mlx5_flow_meter_policy_find(dev,
1998 MLX5_ASSERT(next_policy);
2000 if (mlx5_flow_meter_params_flush(dev, fm, mtr_idx))
2001 return -rte_mtr_error_set(error, ENOTSUP,
2002 RTE_MTR_ERROR_TYPE_MTR_ID,
2004 "Failed to flush meter.");
2005 if (policy->ref_cnt)
2007 if (__mlx5_flow_meter_policy_delete(dev, policy_id,
2008 policy, error, true))
2011 if (!next_fm || !next_policy)
2014 mtr_idx = next_mtr_idx;
2015 policy = next_policy;
2021 * Flush all the hierarchy meters and their policies.
2024 * Pointer to Ethernet device.
2026 * Pointer to rte meter error structure.
2029 * 0 on success, a negative errno value otherwise and rte_errno is set.
2032 mlx5_flow_meter_flush_all_hierarchies(struct rte_eth_dev *dev,
2033 struct rte_mtr_error *error)
2035 struct mlx5_priv *priv = dev->data->dev_private;
2036 struct mlx5_flow_meter_info *fm;
2037 struct mlx5_flow_meter_policy *policy;
2038 struct mlx5_flow_meter_sub_policy *sub_policy;
2039 struct mlx5_flow_meter_info *next_fm;
2040 struct mlx5_aso_mtr *aso_mtr;
2041 uint32_t mtr_idx = 0;
2042 uint32_t i, policy_idx;
2045 if (!priv->mtr_idx_tbl || !priv->policy_idx_tbl)
2047 MLX5_L3T_FOREACH(priv->mtr_idx_tbl, i, entry) {
2048 mtr_idx = *(uint32_t *)entry;
2051 aso_mtr = mlx5_aso_meter_by_idx(priv, mtr_idx);
2053 if (fm->ref_cnt || fm->def_policy)
2055 if (mlx5_flow_meter_flush_hierarchy(dev, fm, mtr_idx, error))
2058 MLX5_L3T_FOREACH(priv->policy_idx_tbl, i, entry) {
2059 policy_idx = *(uint32_t *)entry;
2060 sub_policy = mlx5_ipool_get
2061 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
2064 return -rte_mtr_error_set(error,
2066 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2067 NULL, "Meter policy invalid.");
2068 policy = sub_policy->main_policy;
2069 if (!policy || !policy->is_hierarchy || policy->ref_cnt)
2071 next_fm = mlx5_flow_meter_find(priv,
2072 policy->act_cnt[RTE_COLOR_GREEN].next_mtr_id,
2074 if (__mlx5_flow_meter_policy_delete(dev, i, policy,
2076 return -rte_mtr_error_set(error,
2078 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2079 NULL, "Meter policy invalid.");
2081 if (!next_fm || next_fm->ref_cnt || next_fm->def_policy)
2083 if (mlx5_flow_meter_flush_hierarchy(dev, next_fm,
2090 * Flush meter configuration.
2093 * Pointer to Ethernet device.
2095 * Pointer to rte meter error structure.
2098 * 0 on success, a negative errno value otherwise and rte_errno is set.
2101 mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error)
2103 struct mlx5_priv *priv = dev->data->dev_private;
2104 struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
2105 struct mlx5_flow_meter_profile *fmp;
2106 struct mlx5_legacy_flow_meter *legacy_fm;
2107 struct mlx5_flow_meter_info *fm;
2108 struct mlx5_flow_meter_sub_policy *sub_policy;
2110 uint32_t i, mtr_idx, policy_idx;
2112 struct mlx5_aso_mtr *aso_mtr;
2116 if (priv->sh->meter_aso_en) {
2117 if (mlx5_flow_meter_flush_all_hierarchies(dev, error))
2119 if (priv->mtr_idx_tbl) {
2120 MLX5_L3T_FOREACH(priv->mtr_idx_tbl, i, entry) {
2121 mtr_idx = *(uint32_t *)entry;
2124 mlx5_aso_meter_by_idx(priv, mtr_idx);
2126 (void)mlx5_flow_meter_params_flush(dev,
2130 mlx5_l3t_destroy(priv->mtr_idx_tbl);
2131 priv->mtr_idx_tbl = NULL;
2134 TAILQ_FOREACH_SAFE(legacy_fm, fms, next, tmp) {
2135 fm = &legacy_fm->fm;
2136 if (mlx5_flow_meter_params_flush(dev, fm, 0))
2137 return -rte_mtr_error_set(error, EINVAL,
2138 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
2139 NULL, "MTR object meter profile invalid.");
2142 if (priv->policy_idx_tbl) {
2143 MLX5_L3T_FOREACH(priv->policy_idx_tbl, i, entry) {
2144 policy_idx = *(uint32_t *)entry;
2145 sub_policy = mlx5_ipool_get
2146 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
2149 return -rte_mtr_error_set(error,
2151 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2153 "meter policy invalid.");
2154 if (__mlx5_flow_meter_policy_delete(dev, i,
2155 sub_policy->main_policy,
2157 return -rte_mtr_error_set(error,
2159 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2161 "meter policy invalid.");
2162 mlx5_free(sub_policy->main_policy);
2164 mlx5_l3t_destroy(priv->policy_idx_tbl);
2165 priv->policy_idx_tbl = NULL;
2167 if (priv->mtr_profile_tbl) {
2168 MLX5_L3T_FOREACH(priv->mtr_profile_tbl, i, entry) {
2170 if (mlx5_flow_meter_profile_delete(dev, fmp->id,
2172 return -rte_mtr_error_set(error, EINVAL,
2173 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2174 NULL, "Fail to destroy "
2177 mlx5_l3t_destroy(priv->mtr_profile_tbl);
2178 priv->mtr_profile_tbl = NULL;
2180 /* Delete default policy table. */
2181 mlx5_flow_destroy_def_policy(dev);
2182 if (priv->sh->refcnt == 1)
2183 mlx5_flow_destroy_mtr_drop_tbls(dev);