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"
18 static int mlx5_flow_meter_disable(struct rte_eth_dev *dev,
19 uint32_t meter_id, struct rte_mtr_error *error);
22 * Create the meter action.
25 * Pointer to mlx5_priv.
27 * Pointer to flow meter to be converted.
30 * Pointer to the meter action on success, NULL otherwise.
33 mlx5_flow_meter_action_create(struct mlx5_priv *priv,
34 struct mlx5_flow_meter_info *fm)
36 #ifdef HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER
37 struct mlx5dv_dr_flow_meter_attr mtr_init;
38 uint32_t fmp[MLX5_ST_SZ_DW(flow_meter_parameters)];
39 struct mlx5_flow_meter_srtcm_rfc2697_prm *srtcm =
40 &fm->profile->srtcm_prm;
41 uint32_t cbs_cir = rte_be_to_cpu_32(srtcm->cbs_cir);
42 uint32_t ebs_eir = rte_be_to_cpu_32(srtcm->ebs_eir);
44 enum mlx5_meter_domain domain =
45 fm->transfer ? MLX5_MTR_DOMAIN_TRANSFER :
46 fm->egress ? MLX5_MTR_DOMAIN_EGRESS :
47 MLX5_MTR_DOMAIN_INGRESS;
48 struct mlx5_flow_meter_def_policy *def_policy =
49 priv->sh->mtrmng->def_policy[domain];
51 memset(fmp, 0, MLX5_ST_SZ_BYTES(flow_meter_parameters));
52 MLX5_SET(flow_meter_parameters, fmp, valid, 1);
53 MLX5_SET(flow_meter_parameters, fmp, bucket_overflow, 1);
54 MLX5_SET(flow_meter_parameters, fmp,
55 start_color, MLX5_FLOW_COLOR_GREEN);
56 MLX5_SET(flow_meter_parameters, fmp, both_buckets_on_green, 0);
57 val = (cbs_cir >> ASO_DSEG_CBS_EXP_OFFSET) & ASO_DSEG_EXP_MASK;
58 MLX5_SET(flow_meter_parameters, fmp, cbs_exponent, val);
59 val = (cbs_cir >> ASO_DSEG_CBS_MAN_OFFSET) & ASO_DSEG_MAN_MASK;
60 MLX5_SET(flow_meter_parameters, fmp, cbs_mantissa, val);
61 val = (cbs_cir >> ASO_DSEG_XIR_EXP_OFFSET) & ASO_DSEG_EXP_MASK;
62 MLX5_SET(flow_meter_parameters, fmp, cir_exponent, val);
63 val = (cbs_cir & ASO_DSEG_MAN_MASK);
64 MLX5_SET(flow_meter_parameters, fmp, cir_mantissa, val);
65 val = (ebs_eir >> ASO_DSEG_EBS_EXP_OFFSET) & ASO_DSEG_EXP_MASK;
66 MLX5_SET(flow_meter_parameters, fmp, ebs_exponent, val);
67 val = (ebs_eir >> ASO_DSEG_EBS_MAN_OFFSET) & ASO_DSEG_MAN_MASK;
68 MLX5_SET(flow_meter_parameters, fmp, ebs_mantissa, val);
69 mtr_init.next_table = def_policy->sub_policy.tbl_rsc->obj;
70 mtr_init.reg_c_index = priv->mtr_color_reg - REG_C_0;
71 mtr_init.flow_meter_parameter = fmp;
72 mtr_init.flow_meter_parameter_sz =
73 MLX5_ST_SZ_BYTES(flow_meter_parameters);
74 mtr_init.active = fm->active_state;
75 return mlx5_glue->dv_create_flow_action_meter(&mtr_init);
84 * Find meter profile by id.
87 * Pointer to mlx5_priv.
88 * @param meter_profile_id
92 * Pointer to the profile found on success, NULL otherwise.
94 static struct mlx5_flow_meter_profile *
95 mlx5_flow_meter_profile_find(struct mlx5_priv *priv, uint32_t meter_profile_id)
97 struct mlx5_flow_meter_profile *fmp;
98 union mlx5_l3t_data data;
101 if (mlx5_l3t_get_entry(priv->mtr_profile_tbl,
102 meter_profile_id, &data) || !data.ptr)
105 /* Remove reference taken by the mlx5_l3t_get_entry. */
106 ret = mlx5_l3t_clear_entry(priv->mtr_profile_tbl,
108 if (!ret || ret == -1)
114 * Validate the MTR profile.
117 * Pointer to Ethernet device.
118 * @param[in] meter_profile_id
121 * Pointer to meter profile detail.
123 * Pointer to the error structure.
126 * 0 on success, a negative errno value otherwise and rte_errno is set.
129 mlx5_flow_meter_profile_validate(struct rte_eth_dev *dev,
130 uint32_t meter_profile_id,
131 struct rte_mtr_meter_profile *profile,
132 struct rte_mtr_error *error)
134 struct mlx5_priv *priv = dev->data->dev_private;
135 struct mlx5_flow_meter_profile *fmp;
142 /* Profile must not be NULL. */
144 return -rte_mtr_error_set(error, EINVAL,
145 RTE_MTR_ERROR_TYPE_METER_PROFILE,
146 NULL, "Meter profile is null.");
147 /* Meter profile ID must be valid. */
148 if (meter_profile_id == UINT32_MAX)
149 return -rte_mtr_error_set(error, EINVAL,
150 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
151 NULL, "Meter profile id not valid.");
152 /* Meter profile must not exist. */
153 fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id);
155 return -rte_mtr_error_set(error, EEXIST,
156 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
158 "Meter profile already exists.");
159 if (!priv->sh->meter_aso_en) {
160 /* Old version is even not supported. */
161 if (!priv->sh->cdev->config.hca_attr.qos.flow_meter_old)
162 return -rte_mtr_error_set(error, ENOTSUP,
163 RTE_MTR_ERROR_TYPE_METER_PROFILE,
164 NULL, "Metering is not supported.");
165 /* Old FW metering only supports srTCM. */
166 if (profile->alg != RTE_MTR_SRTCM_RFC2697) {
167 return -rte_mtr_error_set(error, ENOTSUP,
168 RTE_MTR_ERROR_TYPE_METER_PROFILE,
169 NULL, "Metering algorithm is not supported.");
170 } else if (profile->srtcm_rfc2697.ebs) {
171 /* EBS is not supported for old metering. */
172 return -rte_mtr_error_set(error, ENOTSUP,
173 RTE_MTR_ERROR_TYPE_METER_PROFILE,
174 NULL, "EBS is not supported.");
176 if (profile->packet_mode)
177 return -rte_mtr_error_set(error, ENOTSUP,
178 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
179 "Metering algorithm packet mode is not supported.");
181 ls_factor = profile->packet_mode ? MLX5_MTRS_PPS_MAP_BPS_SHIFT : 0;
182 switch (profile->alg) {
183 case RTE_MTR_SRTCM_RFC2697:
184 cir = profile->srtcm_rfc2697.cir << ls_factor;
185 cbs = profile->srtcm_rfc2697.cbs << ls_factor;
186 ebs = profile->srtcm_rfc2697.ebs << ls_factor;
187 /* EBS could be zero for old metering. */
188 if (cir > 0 && cir <= MLX5_SRTCM_XIR_MAX &&
189 cbs > 0 && cbs <= MLX5_SRTCM_XBS_MAX &&
190 ebs <= MLX5_SRTCM_XBS_MAX) {
193 ret = -rte_mtr_error_set(error, ENOTSUP,
194 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
195 "Profile values out of range.");
198 case RTE_MTR_TRTCM_RFC2698:
199 cir = profile->trtcm_rfc2698.cir << ls_factor;
200 cbs = profile->trtcm_rfc2698.cbs << ls_factor;
201 pir = profile->trtcm_rfc2698.pir << ls_factor;
202 pbs = profile->trtcm_rfc2698.pbs << ls_factor;
203 if (cir > 0 && cir <= MLX5_SRTCM_XIR_MAX &&
204 cbs > 0 && cbs <= MLX5_SRTCM_XBS_MAX &&
205 pir >= cir && pir <= (MLX5_SRTCM_XIR_MAX * 2) &&
206 pbs >= cbs && pbs <= (MLX5_SRTCM_XBS_MAX * 2)) {
209 ret = -rte_mtr_error_set(error, ENOTSUP,
210 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
211 "Profile values out of range.");
214 case RTE_MTR_TRTCM_RFC4115:
215 cir = profile->trtcm_rfc4115.cir << ls_factor;
216 cbs = profile->trtcm_rfc4115.cbs << ls_factor;
217 eir = profile->trtcm_rfc4115.eir << ls_factor;
218 ebs = profile->trtcm_rfc4115.ebs << ls_factor;
219 if (cir > 0 && cir <= MLX5_SRTCM_XIR_MAX &&
220 cbs > 0 && cbs <= MLX5_SRTCM_XBS_MAX &&
221 eir <= MLX5_SRTCM_XIR_MAX && ebs <= MLX5_SRTCM_XBS_MAX) {
224 ret = -rte_mtr_error_set(error, ENOTSUP,
225 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
226 "Profile values out of range.");
230 ret = -rte_mtr_error_set(error, ENOTSUP,
231 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
232 "Unknown metering algorithm.");
239 * Calculate mantissa and exponent for cir / eir.
242 * Value to be calculated.
244 * Pointer to the mantissa.
246 * Pointer to the exp.
249 mlx5_flow_meter_xir_man_exp_calc(int64_t xir, uint8_t *man, uint8_t *exp)
252 int64_t delta = INT64_MAX;
257 /* Special case xir == 0 ? both exp and mantissa are 0. */
263 for (m = 0; m <= 0xFF; m++) { /* man width 8 bit */
264 for (e = 0; e <= 0x1F; e++) { /* exp width 5bit */
265 _xir = (1000000000ULL * m) >> e;
266 if (llabs(xir - _xir) <= delta) {
267 delta = llabs(xir - _xir);
278 * Calculate mantissa and exponent for xbs.
281 * Value to be calculated.
283 * Pointer to the mantissa.
285 * Pointer to the exp.
288 mlx5_flow_meter_xbs_man_exp_calc(uint64_t xbs, uint8_t *man, uint8_t *exp)
293 /* Special case xbs == 0 ? both exp and mantissa are 0. */
299 /* xbs = xbs_mantissa * 2^xbs_exponent */
300 _man = frexp(xbs, &_exp);
301 if (_exp >= MLX5_MAN_WIDTH) {
302 _man = _man * pow(2, MLX5_MAN_WIDTH);
303 _exp = _exp - MLX5_MAN_WIDTH;
305 *man = (uint8_t)ceil(_man);
310 * Fill the prm meter parameter.
313 * Pointer to meter profile to be converted.
315 * Pointer to the error structure.
318 * 0 on success, a negative errno value otherwise and rte_errno is set.
321 mlx5_flow_meter_param_fill(struct mlx5_flow_meter_profile *fmp,
322 struct rte_mtr_error *error)
324 struct mlx5_flow_meter_srtcm_rfc2697_prm *srtcm = &fmp->srtcm_prm;
326 uint32_t cbs_exp, cbs_man, cir_exp, cir_man;
327 uint32_t eir_exp, eir_man, ebs_exp, ebs_man;
328 uint64_t cir, cbs, eir, ebs;
330 switch (fmp->profile.alg) {
331 case RTE_MTR_SRTCM_RFC2697:
332 cir = fmp->profile.srtcm_rfc2697.cir;
333 cbs = fmp->profile.srtcm_rfc2697.cbs;
335 ebs = fmp->profile.srtcm_rfc2697.ebs;
337 case RTE_MTR_TRTCM_RFC2698:
338 MLX5_ASSERT(fmp->profile.trtcm_rfc2698.pir >
339 fmp->profile.trtcm_rfc2698.cir &&
340 fmp->profile.trtcm_rfc2698.pbs >
341 fmp->profile.trtcm_rfc2698.cbs);
342 cir = fmp->profile.trtcm_rfc2698.cir;
343 cbs = fmp->profile.trtcm_rfc2698.cbs;
344 /* EIR / EBS are filled with PIR / PBS. */
345 eir = fmp->profile.trtcm_rfc2698.pir;
346 ebs = fmp->profile.trtcm_rfc2698.pbs;
348 case RTE_MTR_TRTCM_RFC4115:
349 cir = fmp->profile.trtcm_rfc4115.cir;
350 cbs = fmp->profile.trtcm_rfc4115.cbs;
351 eir = fmp->profile.trtcm_rfc4115.eir;
352 ebs = fmp->profile.trtcm_rfc4115.ebs;
355 return -rte_mtr_error_set(error, EINVAL,
356 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
357 "Metering algorithm mode is invalid");
359 /* Adjust the values for PPS mode. */
360 if (fmp->profile.packet_mode) {
361 cir <<= MLX5_MTRS_PPS_MAP_BPS_SHIFT;
362 cbs <<= MLX5_MTRS_PPS_MAP_BPS_SHIFT;
363 eir <<= MLX5_MTRS_PPS_MAP_BPS_SHIFT;
364 ebs <<= MLX5_MTRS_PPS_MAP_BPS_SHIFT;
366 /* cir = 8G * cir_mantissa * 1/(2^cir_exponent)) Bytes/Sec */
367 mlx5_flow_meter_xir_man_exp_calc(cir, &man, &exp);
368 /* Check if cir mantissa is too large. */
369 if (exp > ASO_DSEG_XIR_EXP_MASK)
370 return -rte_mtr_error_set(error, ENOTSUP,
371 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
372 "meter profile parameter cir is not supported.");
375 /* cbs = cbs_mantissa * 2^cbs_exponent */
376 mlx5_flow_meter_xbs_man_exp_calc(cbs, &man, &exp);
377 /* Check if cbs mantissa is too large. */
378 if (exp > ASO_DSEG_EXP_MASK)
379 return -rte_mtr_error_set(error, ENOTSUP,
380 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
381 "meter profile parameter cbs is not supported.");
384 srtcm->cbs_cir = rte_cpu_to_be_32(cbs_exp << ASO_DSEG_CBS_EXP_OFFSET |
385 cbs_man << ASO_DSEG_CBS_MAN_OFFSET |
386 cir_exp << ASO_DSEG_XIR_EXP_OFFSET |
388 mlx5_flow_meter_xir_man_exp_calc(eir, &man, &exp);
389 /* Check if eir mantissa is too large. */
390 if (exp > ASO_DSEG_XIR_EXP_MASK)
391 return -rte_mtr_error_set(error, ENOTSUP,
392 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
393 "meter profile parameter eir is not supported.");
396 mlx5_flow_meter_xbs_man_exp_calc(ebs, &man, &exp);
397 /* Check if ebs mantissa is too large. */
398 if (exp > ASO_DSEG_EXP_MASK)
399 return -rte_mtr_error_set(error, ENOTSUP,
400 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
401 "meter profile parameter ebs is not supported.");
404 srtcm->ebs_eir = rte_cpu_to_be_32(ebs_exp << ASO_DSEG_EBS_EXP_OFFSET |
405 ebs_man << ASO_DSEG_EBS_MAN_OFFSET |
406 eir_exp << ASO_DSEG_XIR_EXP_OFFSET |
416 * Callback to get MTR capabilities.
419 * Pointer to Ethernet device.
421 * Pointer to save MTR capabilities.
423 * Pointer to the error structure.
426 * 0 on success, a negative errno value otherwise and rte_errno is set.
429 mlx5_flow_mtr_cap_get(struct rte_eth_dev *dev,
430 struct rte_mtr_capabilities *cap,
431 struct rte_mtr_error *error __rte_unused)
433 struct mlx5_priv *priv = dev->data->dev_private;
434 struct mlx5_hca_qos_attr *qattr = &priv->sh->cdev->config.hca_attr.qos;
437 return -rte_mtr_error_set(error, ENOTSUP,
438 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
439 "Meter is not supported");
440 memset(cap, 0, sizeof(*cap));
441 if (priv->sh->meter_aso_en) {
442 /* 2 meters per one ASO cache line. */
443 cap->n_max = 1 << (qattr->log_max_num_meter_aso + 1);
444 cap->srtcm_rfc2697_packet_mode_supported = 1;
445 cap->trtcm_rfc2698_packet_mode_supported = 1;
446 cap->trtcm_rfc4115_packet_mode_supported = 1;
448 cap->n_max = 1 << qattr->log_max_flow_meter;
450 cap->srtcm_rfc2697_byte_mode_supported = 1;
451 cap->trtcm_rfc2698_byte_mode_supported = 1;
452 cap->trtcm_rfc4115_byte_mode_supported = 1;
453 cap->n_shared_max = cap->n_max;
455 cap->shared_identical = 1;
456 cap->shared_n_flows_per_mtr_max = 4 << 20;
457 /* 2M flows can share the same meter. */
458 cap->chaining_n_mtrs_per_flow_max = 1; /* Chaining is not supported. */
459 cap->meter_srtcm_rfc2697_n_max = qattr->flow_meter_old ? cap->n_max : 0;
460 cap->meter_trtcm_rfc2698_n_max = qattr->flow_meter_old ? cap->n_max : 0;
461 cap->meter_trtcm_rfc4115_n_max = qattr->flow_meter_old ? cap->n_max : 0;
462 cap->meter_rate_max = 1ULL << 40; /* 1 Tera tokens per sec. */
463 cap->meter_policy_n_max = cap->n_max;
464 cap->stats_mask = RTE_MTR_STATS_N_BYTES_DROPPED |
465 RTE_MTR_STATS_N_PKTS_DROPPED;
470 * Callback to add MTR profile.
473 * Pointer to Ethernet device.
474 * @param[in] meter_profile_id
477 * Pointer to meter profile detail.
479 * Pointer to the error structure.
482 * 0 on success, a negative errno value otherwise and rte_errno is set.
485 mlx5_flow_meter_profile_add(struct rte_eth_dev *dev,
486 uint32_t meter_profile_id,
487 struct rte_mtr_meter_profile *profile,
488 struct rte_mtr_error *error)
490 struct mlx5_priv *priv = dev->data->dev_private;
491 struct mlx5_flow_meter_profile *fmp;
492 union mlx5_l3t_data data;
496 return -rte_mtr_error_set(error, ENOTSUP,
497 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
498 "Meter is not supported");
499 /* Check input params. */
500 ret = mlx5_flow_meter_profile_validate(dev, meter_profile_id,
504 /* Meter profile memory allocation. */
505 fmp = mlx5_malloc(MLX5_MEM_ZERO, sizeof(struct mlx5_flow_meter_profile),
506 RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
508 return -rte_mtr_error_set(error, ENOMEM,
509 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
510 NULL, "Meter profile memory "
512 /* Fill profile info. */
513 fmp->id = meter_profile_id;
514 fmp->profile = *profile;
515 /* Fill the flow meter parameters for the PRM. */
516 ret = mlx5_flow_meter_param_fill(fmp, error);
520 ret = mlx5_l3t_set_entry(priv->mtr_profile_tbl,
521 meter_profile_id, &data);
523 return -rte_mtr_error_set(error, ENOTSUP,
524 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
525 NULL, "Meter profile insert fail.");
533 * Callback to delete MTR profile.
536 * Pointer to Ethernet device.
537 * @param[in] meter_profile_id
540 * Pointer to the error structure.
543 * 0 on success, a negative errno value otherwise and rte_errno is set.
546 mlx5_flow_meter_profile_delete(struct rte_eth_dev *dev,
547 uint32_t meter_profile_id,
548 struct rte_mtr_error *error)
550 struct mlx5_priv *priv = dev->data->dev_private;
551 struct mlx5_flow_meter_profile *fmp;
554 return -rte_mtr_error_set(error, ENOTSUP,
555 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
556 "Meter is not supported");
557 /* Meter profile must exist. */
558 fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id);
560 return -rte_mtr_error_set(error, ENOENT,
561 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
563 "Meter profile id is invalid.");
564 /* Check profile is unused. */
566 return -rte_mtr_error_set(error, EBUSY,
567 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
568 NULL, "Meter profile is in use.");
569 if (mlx5_l3t_clear_entry(priv->mtr_profile_tbl, meter_profile_id))
570 return -rte_mtr_error_set(error, EBUSY,
571 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
572 NULL, "Meter profile remove fail.");
581 * Pointer to Ethernet device.
586 * Pointer to the policy found on success, NULL otherwise.
588 struct mlx5_flow_meter_policy *
589 mlx5_flow_meter_policy_find(struct rte_eth_dev *dev,
591 uint32_t *policy_idx)
593 struct mlx5_priv *priv = dev->data->dev_private;
594 struct mlx5_flow_meter_sub_policy *sub_policy = NULL;
595 union mlx5_l3t_data data;
597 if (policy_id > MLX5_MAX_SUB_POLICY_TBL_NUM || !priv->policy_idx_tbl)
599 if (mlx5_l3t_get_entry(priv->policy_idx_tbl, policy_id, &data) ||
603 *policy_idx = data.dword;
604 sub_policy = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
606 /* Remove reference taken by the mlx5_l3t_get_entry. */
607 mlx5_l3t_clear_entry(priv->policy_idx_tbl, policy_id);
609 if (sub_policy->main_policy_id)
610 return sub_policy->main_policy;
615 * Get the last meter's policy from one meter's policy in hierarchy.
618 * Pointer to Ethernet device.
620 * Pointer to flow meter policy.
623 * Pointer to the final meter's policy, or NULL when fail.
625 struct mlx5_flow_meter_policy *
626 mlx5_flow_meter_hierarchy_get_final_policy(struct rte_eth_dev *dev,
627 struct mlx5_flow_meter_policy *policy)
629 struct mlx5_priv *priv = dev->data->dev_private;
630 struct mlx5_flow_meter_info *next_fm;
631 struct mlx5_flow_meter_policy *next_policy = policy;
633 while (next_policy->is_hierarchy) {
634 next_fm = mlx5_flow_meter_find(priv,
635 next_policy->act_cnt[RTE_COLOR_GREEN].next_mtr_id, NULL);
636 if (!next_fm || next_fm->def_policy)
638 next_policy = mlx5_flow_meter_policy_find(dev,
639 next_fm->policy_id, NULL);
640 MLX5_ASSERT(next_policy);
646 * Callback to check MTR policy action validate
649 * Pointer to Ethernet device.
651 * Pointer to meter policy action detail.
653 * Pointer to the error structure.
656 * 0 on success, a negative errno value otherwise and rte_errno is set.
659 mlx5_flow_meter_policy_validate(struct rte_eth_dev *dev,
660 struct rte_mtr_meter_policy_params *policy,
661 struct rte_mtr_error *error)
663 struct mlx5_priv *priv = dev->data->dev_private;
664 struct rte_flow_attr attr = { .transfer = priv->sh->config.dv_esw_en ?
668 uint8_t domain_bitmap;
671 if (!priv->mtr_en || !priv->sh->meter_aso_en)
672 return -rte_mtr_error_set(error, ENOTSUP,
673 RTE_MTR_ERROR_TYPE_METER_POLICY,
674 NULL, "meter policy unsupported.");
675 ret = mlx5_flow_validate_mtr_acts(dev, policy->actions, &attr,
676 &is_rss, &domain_bitmap, &policy_mode, error);
683 __mlx5_flow_meter_policy_delete(struct rte_eth_dev *dev,
685 struct mlx5_flow_meter_policy *mtr_policy,
686 struct rte_mtr_error *error,
689 struct mlx5_priv *priv = dev->data->dev_private;
690 struct mlx5_flow_meter_sub_policy *sub_policy;
692 uint16_t sub_policy_num;
694 rte_spinlock_lock(&mtr_policy->sl);
695 if (mtr_policy->ref_cnt) {
696 rte_spinlock_unlock(&mtr_policy->sl);
697 return -rte_mtr_error_set(error, EBUSY,
698 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
700 "Meter policy object is being used.");
702 mlx5_flow_destroy_policy_rules(dev, mtr_policy);
703 mlx5_flow_destroy_mtr_acts(dev, mtr_policy);
704 for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
705 sub_policy_num = (mtr_policy->sub_policy_num >>
706 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i)) &
707 MLX5_MTR_SUB_POLICY_NUM_MASK;
708 if (sub_policy_num) {
709 for (j = 0; j < sub_policy_num; j++) {
710 sub_policy = mtr_policy->sub_policys[i][j];
713 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
718 if (priv->policy_idx_tbl && clear_l3t) {
719 if (mlx5_l3t_clear_entry(priv->policy_idx_tbl, policy_id)) {
720 rte_spinlock_unlock(&mtr_policy->sl);
721 return -rte_mtr_error_set(error, ENOTSUP,
722 RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL,
723 "Fail to delete policy in index table.");
726 rte_spinlock_unlock(&mtr_policy->sl);
731 * Callback to add MTR policy.
734 * Pointer to Ethernet device.
735 * @param[out] policy_id
736 * Pointer to policy id
738 * Pointer to meter policy action detail.
740 * Pointer to the error structure.
743 * 0 on success, a negative errno value otherwise and rte_errno is set.
746 mlx5_flow_meter_policy_add(struct rte_eth_dev *dev,
748 struct rte_mtr_meter_policy_params *policy,
749 struct rte_mtr_error *error)
751 struct mlx5_priv *priv = dev->data->dev_private;
752 struct rte_flow_attr attr = { .transfer = priv->sh->config.dv_esw_en ?
754 uint32_t sub_policy_idx = 0;
755 uint32_t policy_idx = 0;
756 struct mlx5_flow_meter_policy *mtr_policy = NULL;
757 struct mlx5_flow_meter_sub_policy *sub_policy;
762 uint32_t policy_size = sizeof(struct mlx5_flow_meter_policy);
763 uint16_t sub_policy_num;
764 uint8_t domain_bitmap = 0;
765 union mlx5_l3t_data data;
766 bool skip_rule = false;
769 return -rte_mtr_error_set(error, ENOTSUP,
770 RTE_MTR_ERROR_TYPE_METER_POLICY,
771 NULL, "meter policy unsupported. ");
772 if (policy_id == MLX5_INVALID_POLICY_ID)
773 return -rte_mtr_error_set(error, ENOTSUP,
774 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
775 NULL, "policy ID is invalid. ");
776 if (policy_id == priv->sh->mtrmng->def_policy_id)
777 return -rte_mtr_error_set(error, EEXIST,
778 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
779 NULL, "default policy ID exists. ");
780 mtr_policy = mlx5_flow_meter_policy_find(dev, policy_id, &policy_idx);
782 return -rte_mtr_error_set(error, EEXIST,
783 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
784 NULL, "policy ID exists. ");
785 ret = mlx5_flow_validate_mtr_acts(dev, policy->actions, &attr,
786 &is_rss, &domain_bitmap,
787 &policy_mode, error);
791 return -rte_mtr_error_set(error, ENOTSUP,
792 RTE_MTR_ERROR_TYPE_METER_POLICY,
793 NULL, "fail to find policy domain.");
794 if (policy_mode == MLX5_MTR_POLICY_MODE_DEF) {
795 if (priv->sh->mtrmng->def_policy_id != MLX5_INVALID_POLICY_ID)
796 return -rte_mtr_error_set(error, EEXIST,
797 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
798 NULL, "a policy with similar actions "
799 "is already configured");
800 if (mlx5_flow_create_def_policy(dev))
801 return -rte_mtr_error_set(error, ENOTSUP,
802 RTE_MTR_ERROR_TYPE_METER_POLICY,
804 "fail to create non-terminated policy.");
805 priv->sh->mtrmng->def_policy_id = policy_id;
808 if (!priv->sh->meter_aso_en)
809 return -rte_mtr_error_set(error, ENOTSUP,
810 RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
811 "no ASO capability to support the policy ");
812 for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
813 if (!(domain_bitmap & (1 << i)))
816 * If RSS is found, it means that only the ingress domain can
817 * be supported. It is invalid to support RSS for one color
818 * and egress / transfer domain actions for another. Drop and
819 * jump action should have no impact.
823 sizeof(struct mlx5_flow_meter_sub_policy *) *
824 MLX5_MTR_RSS_MAX_SUB_POLICY;
827 policy_size += sizeof(struct mlx5_flow_meter_sub_policy *);
829 mtr_policy = mlx5_malloc(MLX5_MEM_ZERO, policy_size,
830 RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
832 return -rte_mtr_error_set(error, ENOMEM,
833 RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
834 "Memory alloc failed for meter policy.");
835 if (policy_mode == MLX5_MTR_POLICY_MODE_OG)
836 mtr_policy->skip_y = 1;
837 else if (policy_mode == MLX5_MTR_POLICY_MODE_OY)
838 mtr_policy->skip_g = 1;
839 policy_size = sizeof(struct mlx5_flow_meter_policy);
840 for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
841 if (!(domain_bitmap & (1 << i)))
843 if (i == MLX5_MTR_DOMAIN_INGRESS)
844 mtr_policy->ingress = 1;
845 if (i == MLX5_MTR_DOMAIN_EGRESS)
846 mtr_policy->egress = 1;
847 if (i == MLX5_MTR_DOMAIN_TRANSFER)
848 mtr_policy->transfer = 1;
849 sub_policy = mlx5_ipool_zmalloc
850 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
853 sub_policy_idx > MLX5_MAX_SUB_POLICY_TBL_NUM)
855 sub_policy->idx = sub_policy_idx;
856 sub_policy->main_policy = mtr_policy;
858 policy_idx = sub_policy_idx;
859 sub_policy->main_policy_id = 1;
861 mtr_policy->sub_policys[i] =
862 (struct mlx5_flow_meter_sub_policy **)
863 ((uint8_t *)mtr_policy + policy_size);
864 mtr_policy->sub_policys[i][0] = sub_policy;
865 sub_policy_num = (mtr_policy->sub_policy_num >>
866 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i)) &
867 MLX5_MTR_SUB_POLICY_NUM_MASK;
869 mtr_policy->sub_policy_num &= ~(MLX5_MTR_SUB_POLICY_NUM_MASK <<
870 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i));
871 mtr_policy->sub_policy_num |=
872 (sub_policy_num & MLX5_MTR_SUB_POLICY_NUM_MASK) <<
873 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i);
875 * If RSS is found, it means that only the ingress domain can
876 * be supported. It is invalid to support RSS for one color
877 * and egress / transfer domain actions for another. Drop and
878 * jump action should have no impact.
881 mtr_policy->is_rss = 1;
884 policy_size += sizeof(struct mlx5_flow_meter_sub_policy *);
886 rte_spinlock_init(&mtr_policy->sl);
887 ret = mlx5_flow_create_mtr_acts(dev, mtr_policy,
888 policy->actions, error);
891 if (mtr_policy->is_hierarchy) {
892 struct mlx5_flow_meter_policy *final_policy;
895 mlx5_flow_meter_hierarchy_get_final_policy(dev, mtr_policy);
898 skip_rule = (final_policy->is_rss || final_policy->is_queue);
901 * If either Green or Yellow has queue / RSS action, all the policy
902 * rules will be created later in the flow splitting stage.
904 if (!is_rss && !mtr_policy->is_queue && !skip_rule) {
905 /* Create policy rules in HW. */
906 ret = mlx5_flow_create_policy_rules(dev, mtr_policy);
910 data.dword = policy_idx;
911 if (!priv->policy_idx_tbl) {
912 priv->policy_idx_tbl = mlx5_l3t_create(MLX5_L3T_TYPE_DWORD);
913 if (!priv->policy_idx_tbl)
916 if (mlx5_l3t_set_entry(priv->policy_idx_tbl, policy_id, &data))
921 ret = __mlx5_flow_meter_policy_delete(dev, policy_id,
922 mtr_policy, error, false);
923 mlx5_free(mtr_policy);
927 return -rte_mtr_error_set(error, ENOTSUP,
928 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
929 NULL, "Failed to create devx policy.");
933 * Callback to delete MTR policy.
936 * Pointer to Ethernet device.
937 * @param[in] policy_id
940 * Pointer to the error structure.
943 * 0 on success, a negative errno value otherwise and rte_errno is set.
946 mlx5_flow_meter_policy_delete(struct rte_eth_dev *dev,
948 struct rte_mtr_error *error)
950 struct mlx5_priv *priv = dev->data->dev_private;
951 struct mlx5_flow_meter_policy *mtr_policy;
955 if (policy_id == priv->sh->mtrmng->def_policy_id) {
956 if (priv->sh->mtrmng->def_policy_ref_cnt > 0)
957 return -rte_mtr_error_set(error, ENOTSUP,
958 RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL,
959 "Meter policy object is being used.");
960 priv->sh->mtrmng->def_policy_id = MLX5_INVALID_POLICY_ID;
963 mtr_policy = mlx5_flow_meter_policy_find(dev, policy_id, &policy_idx);
965 return -rte_mtr_error_set(error, ENOTSUP,
966 RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL,
967 "Meter policy id is invalid. ");
968 ret = __mlx5_flow_meter_policy_delete(dev, policy_id, mtr_policy,
972 mlx5_free(mtr_policy);
977 * Check meter validation.
980 * Pointer to mlx5 private data structure.
981 * @param[in] meter_id
984 * Pointer to rte meter parameters.
986 * Pointer to rte meter error structure.
989 * 0 on success, a negative errno value otherwise and rte_errno is set.
992 mlx5_flow_meter_validate(struct mlx5_priv *priv, uint32_t meter_id,
993 struct rte_mtr_params *params,
994 struct rte_mtr_error *error)
996 /* Meter must use global drop action. */
997 if (!priv->sh->dr_drop_action)
998 return -rte_mtr_error_set(error, ENOTSUP,
999 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
1001 "No drop action ready for meter.");
1002 /* Meter params must not be NULL. */
1004 return -rte_mtr_error_set(error, EINVAL,
1005 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
1006 NULL, "Meter object params null.");
1007 /* Previous meter color is not supported. */
1008 if (params->use_prev_mtr_color)
1009 return -rte_mtr_error_set(error, ENOTSUP,
1010 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
1012 "Previous meter color "
1014 if (params->meter_policy_id == MLX5_INVALID_POLICY_ID)
1015 return -rte_mtr_error_set(error, ENOENT,
1016 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
1017 NULL, "Meter policy id not valid.");
1018 /* Validate meter id. */
1019 if (mlx5_flow_meter_find(priv, meter_id, NULL))
1020 return -rte_mtr_error_set(error, EEXIST,
1021 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
1022 "Meter object already exists.");
1027 * Modify the flow meter action.
1030 * Pointer to mlx5 private data structure.
1032 * Pointer to flow meter to be modified.
1034 * Pointer to meter srtcm description parameter.
1035 * @param[in] modify_bits
1036 * The bit in srtcm to be updated.
1037 * @param[in] active_state
1038 * The state to be updated.
1040 * 0 on success, o negative value otherwise.
1043 mlx5_flow_meter_action_modify(struct mlx5_priv *priv,
1044 struct mlx5_flow_meter_info *fm,
1045 const struct mlx5_flow_meter_srtcm_rfc2697_prm *srtcm,
1046 uint64_t modify_bits, uint32_t active_state, uint32_t is_enable)
1048 #ifdef HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER
1049 uint32_t in[MLX5_ST_SZ_DW(flow_meter_parameters)] = { 0 };
1051 struct mlx5dv_dr_flow_meter_attr mod_attr = { 0 };
1053 struct mlx5_aso_mtr *aso_mtr = NULL;
1054 uint32_t cbs_cir, ebs_eir, val;
1056 if (priv->sh->meter_aso_en) {
1057 fm->is_enable = !!is_enable;
1058 aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
1059 ret = mlx5_aso_meter_update_by_wqe(priv->sh, aso_mtr);
1062 ret = mlx5_aso_mtr_wait(priv->sh, aso_mtr);
1066 /* Fill command parameters. */
1067 mod_attr.reg_c_index = priv->mtr_color_reg - REG_C_0;
1068 mod_attr.flow_meter_parameter = in;
1069 mod_attr.flow_meter_parameter_sz =
1070 MLX5_ST_SZ_BYTES(flow_meter_parameters);
1071 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_ACTIVE)
1072 mod_attr.active = !!active_state;
1074 mod_attr.active = 0;
1076 cbs_cir = rte_be_to_cpu_32(srtcm->cbs_cir);
1077 ebs_eir = rte_be_to_cpu_32(srtcm->ebs_eir);
1078 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS) {
1079 val = (cbs_cir >> ASO_DSEG_CBS_EXP_OFFSET) &
1081 MLX5_SET(flow_meter_parameters, attr,
1083 val = (cbs_cir >> ASO_DSEG_CBS_MAN_OFFSET) &
1085 MLX5_SET(flow_meter_parameters, attr,
1088 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR) {
1089 val = (cbs_cir >> ASO_DSEG_XIR_EXP_OFFSET) &
1091 MLX5_SET(flow_meter_parameters, attr,
1093 val = cbs_cir & ASO_DSEG_MAN_MASK;
1094 MLX5_SET(flow_meter_parameters, attr,
1097 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_EBS) {
1098 val = (ebs_eir >> ASO_DSEG_EBS_EXP_OFFSET) &
1100 MLX5_SET(flow_meter_parameters, attr,
1102 val = (ebs_eir >> ASO_DSEG_EBS_MAN_OFFSET) &
1104 MLX5_SET(flow_meter_parameters, attr,
1107 /* Apply modifications to meter only if it was created. */
1108 if (fm->meter_action) {
1109 ret = mlx5_glue->dv_modify_flow_action_meter
1110 (fm->meter_action, &mod_attr,
1111 rte_cpu_to_be_64(modify_bits));
1115 /* Update succeeded modify meter parameters. */
1116 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_ACTIVE)
1117 fm->active_state = !!active_state;
1132 mlx5_flow_meter_stats_enable_update(struct rte_eth_dev *dev,
1133 struct mlx5_flow_meter_info *fm,
1134 uint64_t stats_mask)
1137 (stats_mask & RTE_MTR_STATS_N_BYTES_DROPPED) ? 1 : 0;
1138 fm->pkts_dropped = (stats_mask & RTE_MTR_STATS_N_PKTS_DROPPED) ? 1 : 0;
1139 if (fm->bytes_dropped || fm->pkts_dropped) {
1140 if (!fm->drop_cnt) {
1141 /* Alloc policer counters. */
1142 fm->drop_cnt = mlx5_counter_alloc(dev);
1148 mlx5_counter_free(dev, fm->drop_cnt);
1156 * Create meter rules.
1159 * Pointer to Ethernet device.
1160 * @param[in] meter_id
1163 * Pointer to rte meter parameters.
1165 * Meter shared with other flow or not.
1167 * Pointer to rte meter error structure.
1170 * 0 on success, a negative errno value otherwise and rte_errno is set.
1173 mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,
1174 struct rte_mtr_params *params, int shared,
1175 struct rte_mtr_error *error)
1177 struct mlx5_priv *priv = dev->data->dev_private;
1178 struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
1179 struct mlx5_flow_meter_profile *fmp;
1180 struct mlx5_flow_meter_info *fm;
1181 /* GCC fails to infer legacy_fm is set when !priv->sh->meter_aso_en. */
1182 struct mlx5_legacy_flow_meter *legacy_fm = NULL;
1183 struct mlx5_flow_meter_policy *mtr_policy = NULL;
1184 struct mlx5_indexed_pool_config flow_ipool_cfg = {
1188 .type = "mlx5_flow_mtr_flow_id_pool",
1190 struct mlx5_aso_mtr *aso_mtr;
1191 uint32_t mtr_idx, policy_idx;
1192 union mlx5_l3t_data data;
1194 uint8_t domain_bitmap;
1195 uint8_t mtr_id_bits;
1196 uint8_t mtr_reg_bits = priv->mtr_reg_share ?
1197 MLX5_MTR_IDLE_BITS_IN_COLOR_REG : MLX5_REG_BITS;
1200 return -rte_mtr_error_set(error, ENOTSUP,
1201 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1202 "Meter is not supported");
1203 /* Validate the parameters. */
1204 ret = mlx5_flow_meter_validate(priv, meter_id, params, error);
1207 /* Meter profile must exist. */
1208 fmp = mlx5_flow_meter_profile_find(priv, params->meter_profile_id);
1210 return -rte_mtr_error_set(error, ENOENT,
1211 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
1212 NULL, "Meter profile id not valid.");
1213 /* Meter policy must exist. */
1214 if (params->meter_policy_id == priv->sh->mtrmng->def_policy_id) {
1216 (&priv->sh->mtrmng->def_policy_ref_cnt,
1217 1, __ATOMIC_RELAXED);
1218 domain_bitmap = MLX5_MTR_ALL_DOMAIN_BIT;
1219 if (!priv->sh->config.dv_esw_en)
1220 domain_bitmap &= ~MLX5_MTR_DOMAIN_TRANSFER_BIT;
1222 if (!priv->sh->meter_aso_en)
1223 return -rte_mtr_error_set(error, ENOTSUP,
1224 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1225 "Part of the policies cannot be "
1226 "supported without ASO ");
1227 mtr_policy = mlx5_flow_meter_policy_find(dev,
1228 params->meter_policy_id, &policy_idx);
1230 return -rte_mtr_error_set(error, ENOENT,
1231 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
1232 NULL, "Meter policy id not valid.");
1233 domain_bitmap = (mtr_policy->ingress ?
1234 MLX5_MTR_DOMAIN_INGRESS_BIT : 0) |
1235 (mtr_policy->egress ?
1236 MLX5_MTR_DOMAIN_EGRESS_BIT : 0) |
1237 (mtr_policy->transfer ?
1238 MLX5_MTR_DOMAIN_TRANSFER_BIT : 0);
1239 if (fmp->g_support && mtr_policy->skip_g)
1240 return -rte_mtr_error_set(error, ENOTSUP,
1241 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
1242 NULL, "Meter green policy is empty.");
1243 if (fmp->y_support && mtr_policy->skip_y)
1244 return -rte_mtr_error_set(error, ENOTSUP,
1245 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
1246 NULL, "Meter yellow policy is empty.");
1248 /* Allocate the flow meter memory. */
1249 if (priv->sh->meter_aso_en) {
1250 mtr_idx = mlx5_flow_mtr_alloc(dev);
1252 return -rte_mtr_error_set(error, ENOMEM,
1253 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1254 "Memory alloc failed for meter.");
1255 aso_mtr = mlx5_aso_meter_by_idx(priv, mtr_idx);
1259 return -rte_mtr_error_set(error, ENOMEM,
1260 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1261 "Unsupported profile with yellow.");
1262 legacy_fm = mlx5_ipool_zmalloc
1263 (priv->sh->ipool[MLX5_IPOOL_MTR], &mtr_idx);
1264 if (legacy_fm == NULL)
1265 return -rte_mtr_error_set(error, ENOMEM,
1266 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1267 "Memory alloc failed for meter.");
1268 legacy_fm->idx = mtr_idx;
1269 fm = &legacy_fm->fm;
1271 mtr_id_bits = MLX5_REG_BITS - __builtin_clz(mtr_idx);
1272 if ((mtr_id_bits + priv->sh->mtrmng->max_mtr_flow_bits) >
1274 DRV_LOG(ERR, "Meter number exceeds max limit.");
1277 if (mtr_id_bits > priv->sh->mtrmng->max_mtr_bits)
1278 priv->sh->mtrmng->max_mtr_bits = mtr_id_bits;
1279 /* Fill the flow meter parameters. */
1280 fm->meter_id = meter_id;
1281 fm->policy_id = params->meter_policy_id;
1283 if (mlx5_flow_meter_stats_enable_update(dev, fm, params->stats_mask))
1285 if (mlx5_flow_create_mtr_tbls(dev, fm, mtr_idx, domain_bitmap))
1287 /* Add to the flow meter list. */
1288 if (!priv->sh->meter_aso_en) {
1289 MLX5_ASSERT(legacy_fm != NULL);
1290 TAILQ_INSERT_TAIL(fms, legacy_fm, next);
1292 /* Add to the flow meter list. */
1293 fm->active_state = 1; /* Config meter starts as active. */
1294 fm->is_enable = params->meter_enable;
1295 fm->shared = !!shared;
1296 __atomic_add_fetch(&fm->profile->ref_cnt, 1, __ATOMIC_RELAXED);
1297 if (params->meter_policy_id == priv->sh->mtrmng->def_policy_id) {
1299 fm->flow_ipool = mlx5_ipool_create(&flow_ipool_cfg);
1300 if (!fm->flow_ipool)
1303 rte_spinlock_init(&fm->sl);
1304 /* If ASO meter supported, update ASO flow meter by wqe. */
1305 if (priv->sh->meter_aso_en) {
1306 aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
1307 ret = mlx5_aso_meter_update_by_wqe(priv->sh, aso_mtr);
1310 if (!priv->mtr_idx_tbl) {
1312 mlx5_l3t_create(MLX5_L3T_TYPE_DWORD);
1313 if (!priv->mtr_idx_tbl)
1316 data.dword = mtr_idx;
1317 if (mlx5_l3t_set_entry(priv->mtr_idx_tbl, meter_id, &data))
1319 } else if (!params->meter_enable && mlx5_flow_meter_disable(dev, meter_id, error)) {
1322 fm->active_state = params->meter_enable;
1324 __atomic_add_fetch(&mtr_policy->ref_cnt, 1, __ATOMIC_RELAXED);
1327 mlx5_flow_destroy_mtr_tbls(dev, fm);
1328 /* Free policer counters. */
1330 mlx5_counter_free(dev, fm->drop_cnt);
1331 if (priv->sh->meter_aso_en)
1332 mlx5_flow_mtr_free(dev, mtr_idx);
1334 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR], mtr_idx);
1335 return -rte_mtr_error_set(error, ENOTSUP,
1336 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
1337 NULL, "Failed to create devx meter.");
1341 mlx5_flow_meter_params_flush(struct rte_eth_dev *dev,
1342 struct mlx5_flow_meter_info *fm,
1345 struct mlx5_priv *priv = dev->data->dev_private;
1346 struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
1347 struct mlx5_flow_meter_profile *fmp;
1348 struct mlx5_legacy_flow_meter *legacy_fm = NULL;
1349 struct mlx5_flow_meter_policy *mtr_policy;
1351 /* Meter object must not have any owner. */
1352 MLX5_ASSERT(!fm->ref_cnt);
1353 /* Get meter profile. */
1357 /* Update dependencies. */
1358 __atomic_sub_fetch(&fmp->ref_cnt, 1, __ATOMIC_RELAXED);
1360 /* Remove from list. */
1361 if (!priv->sh->meter_aso_en) {
1362 legacy_fm = container_of(fm,
1363 struct mlx5_legacy_flow_meter, fm);
1364 TAILQ_REMOVE(fms, legacy_fm, next);
1366 /* Free drop counters. */
1368 mlx5_counter_free(dev, fm->drop_cnt);
1369 /* Free meter flow table. */
1370 if (fm->flow_ipool) {
1371 mlx5_ipool_destroy(fm->flow_ipool);
1374 mlx5_flow_destroy_mtr_tbls(dev, fm);
1376 __atomic_sub_fetch(&priv->sh->mtrmng->def_policy_ref_cnt,
1377 1, __ATOMIC_RELAXED);
1378 if (priv->sh->meter_aso_en) {
1379 if (!fm->def_policy) {
1380 mtr_policy = mlx5_flow_meter_policy_find(dev,
1381 fm->policy_id, NULL);
1383 __atomic_sub_fetch(&mtr_policy->ref_cnt,
1384 1, __ATOMIC_RELAXED);
1388 if (mlx5_l3t_clear_entry(priv->mtr_idx_tbl, fm->meter_id))
1390 mlx5_flow_mtr_free(dev, mtr_idx);
1392 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR],
1399 * Destroy meter rules.
1402 * Pointer to Ethernet device.
1403 * @param[in] meter_id
1406 * Pointer to rte meter error structure.
1409 * 0 on success, a negative errno value otherwise and rte_errno is set.
1412 mlx5_flow_meter_destroy(struct rte_eth_dev *dev, uint32_t meter_id,
1413 struct rte_mtr_error *error)
1415 struct mlx5_priv *priv = dev->data->dev_private;
1416 struct mlx5_flow_meter_info *fm;
1417 uint32_t mtr_idx = 0;
1420 return -rte_mtr_error_set(error, ENOTSUP,
1421 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
1423 "Meter is not supported");
1424 /* Meter object must exist. */
1425 fm = mlx5_flow_meter_find(priv, meter_id, &mtr_idx);
1427 return -rte_mtr_error_set(error, ENOENT,
1428 RTE_MTR_ERROR_TYPE_MTR_ID,
1430 "Meter object id not valid.");
1431 /* Meter object must not have any owner. */
1432 if (fm->ref_cnt > 0)
1433 return -rte_mtr_error_set(error, EBUSY,
1434 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
1436 "Meter object is being used.");
1437 /* Destroy the meter profile. */
1438 if (mlx5_flow_meter_params_flush(dev, fm, mtr_idx))
1439 return -rte_mtr_error_set(error, EINVAL,
1440 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
1442 "MTR object meter profile invalid.");
1447 * Modify meter state.
1450 * Pointer to mlx5 private data structure.
1452 * Pointer to flow meter.
1453 * @param[in] new_state
1454 * New state to update.
1456 * Pointer to rte meter error structure.
1459 * 0 on success, a negative errno value otherwise and rte_errno is set.
1462 mlx5_flow_meter_modify_state(struct mlx5_priv *priv,
1463 struct mlx5_flow_meter_info *fm,
1465 struct rte_mtr_error *error)
1467 static const struct mlx5_flow_meter_srtcm_rfc2697_prm srtcm = {
1468 .cbs_cir = RTE_BE32(MLX5_IFC_FLOW_METER_DISABLE_CBS_CIR_VAL),
1471 uint64_t modify_bits = MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS |
1472 MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR;
1475 if (new_state == MLX5_FLOW_METER_DISABLE)
1476 ret = mlx5_flow_meter_action_modify(priv, fm,
1477 &srtcm, modify_bits, 0, 0);
1479 ret = mlx5_flow_meter_action_modify(priv, fm,
1480 &fm->profile->srtcm_prm,
1483 return -rte_mtr_error_set(error, -ret,
1484 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
1487 "Failed to enable meter." :
1488 "Failed to disable meter.");
1493 * Callback to enable flow meter.
1496 * Pointer to Ethernet device.
1497 * @param[in] meter_id
1500 * Pointer to rte meter error structure.
1503 * 0 on success, a negative errno value otherwise and rte_errno is set.
1506 mlx5_flow_meter_enable(struct rte_eth_dev *dev,
1508 struct rte_mtr_error *error)
1510 struct mlx5_priv *priv = dev->data->dev_private;
1511 struct mlx5_flow_meter_info *fm;
1515 return -rte_mtr_error_set(error, ENOTSUP,
1516 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1517 "Meter is not supported");
1518 /* Meter object must exist. */
1519 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1521 return -rte_mtr_error_set(error, ENOENT,
1522 RTE_MTR_ERROR_TYPE_MTR_ID,
1523 NULL, "Meter not found.");
1524 if (fm->active_state == MLX5_FLOW_METER_ENABLE)
1526 ret = mlx5_flow_meter_modify_state(priv, fm, MLX5_FLOW_METER_ENABLE,
1529 fm->active_state = MLX5_FLOW_METER_ENABLE;
1534 * Callback to disable flow meter.
1537 * Pointer to Ethernet device.
1538 * @param[in] meter_id
1541 * Pointer to rte meter error structure.
1544 * 0 on success, a negative errno value otherwise and rte_errno is set.
1547 mlx5_flow_meter_disable(struct rte_eth_dev *dev,
1549 struct rte_mtr_error *error)
1551 struct mlx5_priv *priv = dev->data->dev_private;
1552 struct mlx5_flow_meter_info *fm;
1556 return -rte_mtr_error_set(error, ENOTSUP,
1557 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1558 "Meter is not supported");
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 if (fm->active_state == MLX5_FLOW_METER_DISABLE)
1567 ret = mlx5_flow_meter_modify_state(priv, fm, MLX5_FLOW_METER_DISABLE,
1570 fm->active_state = MLX5_FLOW_METER_DISABLE;
1575 * Callback to update meter profile.
1578 * Pointer to Ethernet device.
1579 * @param[in] meter_id
1581 * @param[in] meter_profile_id
1582 * To be updated meter profile id.
1584 * Pointer to rte meter error structure.
1587 * 0 on success, a negative errno value otherwise and rte_errno is set.
1590 mlx5_flow_meter_profile_update(struct rte_eth_dev *dev,
1592 uint32_t meter_profile_id,
1593 struct rte_mtr_error *error)
1595 struct mlx5_priv *priv = dev->data->dev_private;
1596 struct mlx5_flow_meter_profile *fmp;
1597 struct mlx5_flow_meter_profile *old_fmp;
1598 struct mlx5_flow_meter_info *fm;
1599 uint64_t modify_bits = MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS |
1600 MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR;
1604 return -rte_mtr_error_set(error, ENOTSUP,
1605 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1606 "Meter is not supported");
1607 /* Meter profile must exist. */
1608 fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id);
1610 return -rte_mtr_error_set(error, ENOENT,
1611 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
1612 NULL, "Meter profile not found.");
1613 /* Meter object must exist. */
1614 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1616 return -rte_mtr_error_set(error, ENOENT,
1617 RTE_MTR_ERROR_TYPE_MTR_ID,
1618 NULL, "Meter not found.");
1619 /* MTR object already set to meter profile id. */
1620 old_fmp = fm->profile;
1623 /* Update the profile. */
1625 /* Update meter params in HW (if not disabled). */
1626 if (fm->active_state == MLX5_FLOW_METER_DISABLE)
1628 ret = mlx5_flow_meter_action_modify(priv, fm, &fm->profile->srtcm_prm,
1629 modify_bits, fm->active_state, 1);
1631 fm->profile = old_fmp;
1632 return -rte_mtr_error_set(error, -ret,
1633 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
1634 NULL, "Failed to update meter"
1635 " parameters in hardware.");
1643 * Callback to update meter stats mask.
1646 * Pointer to Ethernet device.
1647 * @param[in] meter_id
1649 * @param[in] stats_mask
1650 * To be updated stats_mask.
1652 * Pointer to rte meter error structure.
1655 * 0 on success, a negative errno value otherwise and rte_errno is set.
1658 mlx5_flow_meter_stats_update(struct rte_eth_dev *dev,
1660 uint64_t stats_mask,
1661 struct rte_mtr_error *error)
1663 struct mlx5_priv *priv = dev->data->dev_private;
1664 struct mlx5_flow_meter_info *fm;
1667 return -rte_mtr_error_set(error, ENOTSUP,
1668 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1669 "Meter is not supported");
1670 /* Meter object must exist. */
1671 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1673 return -rte_mtr_error_set(error, ENOENT,
1674 RTE_MTR_ERROR_TYPE_MTR_ID,
1675 NULL, "Meter object id not valid.");
1676 if (mlx5_flow_meter_stats_enable_update(dev, fm, stats_mask))
1677 return -rte_mtr_error_set(error, ENOENT,
1678 RTE_MTR_ERROR_TYPE_MTR_ID,
1679 NULL, "Fail to allocate "
1680 "counter for meter.");
1685 * Callback to read meter statistics.
1688 * Pointer to Ethernet device.
1689 * @param[in] meter_id
1692 * Pointer to store the statistics.
1693 * @param[out] stats_mask
1694 * Pointer to store the stats_mask.
1696 * Statistic to be cleared after read or not.
1698 * Pointer to rte meter error structure.
1701 * 0 on success, a negative errno value otherwise and rte_errno is set.
1704 mlx5_flow_meter_stats_read(struct rte_eth_dev *dev,
1706 struct rte_mtr_stats *stats,
1707 uint64_t *stats_mask,
1709 struct rte_mtr_error *error)
1711 struct mlx5_priv *priv = dev->data->dev_private;
1712 struct mlx5_flow_meter_info *fm;
1718 return -rte_mtr_error_set(error, ENOTSUP,
1719 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1720 "Meter is not supported");
1721 /* Meter object must exist. */
1722 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1724 return -rte_mtr_error_set(error, ENOENT,
1725 RTE_MTR_ERROR_TYPE_MTR_ID,
1726 NULL, "Meter object id not valid.");
1728 if (fm->bytes_dropped)
1729 *stats_mask |= RTE_MTR_STATS_N_BYTES_DROPPED;
1730 if (fm->pkts_dropped)
1731 *stats_mask |= RTE_MTR_STATS_N_PKTS_DROPPED;
1732 memset(stats, 0, sizeof(*stats));
1734 ret = mlx5_counter_query(dev, fm->drop_cnt, clear, &pkts,
1738 /* If need to read the packets, set it. */
1739 if (fm->pkts_dropped)
1740 stats->n_pkts_dropped = pkts;
1741 /* If need to read the bytes, set it. */
1742 if (fm->bytes_dropped)
1743 stats->n_bytes_dropped = bytes;
1747 return -rte_mtr_error_set(error, ret, RTE_MTR_ERROR_TYPE_STATS, NULL,
1748 "Failed to read meter drop counters.");
1751 static const struct rte_mtr_ops mlx5_flow_mtr_ops = {
1752 .capabilities_get = mlx5_flow_mtr_cap_get,
1753 .meter_profile_add = mlx5_flow_meter_profile_add,
1754 .meter_profile_delete = mlx5_flow_meter_profile_delete,
1755 .meter_policy_validate = mlx5_flow_meter_policy_validate,
1756 .meter_policy_add = mlx5_flow_meter_policy_add,
1757 .meter_policy_delete = mlx5_flow_meter_policy_delete,
1758 .create = mlx5_flow_meter_create,
1759 .destroy = mlx5_flow_meter_destroy,
1760 .meter_enable = mlx5_flow_meter_enable,
1761 .meter_disable = mlx5_flow_meter_disable,
1762 .meter_profile_update = mlx5_flow_meter_profile_update,
1763 .meter_dscp_table_update = NULL,
1764 .stats_update = mlx5_flow_meter_stats_update,
1765 .stats_read = mlx5_flow_meter_stats_read,
1769 * Get meter operations.
1772 * Pointer to Ethernet device structure.
1774 * Pointer to set the mtr operations.
1780 mlx5_flow_meter_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)
1782 *(const struct rte_mtr_ops **)arg = &mlx5_flow_mtr_ops;
1790 * Pointer to mlx5_priv.
1794 * Pointer to Meter index.
1797 * Pointer to the meter info found on success, NULL otherwise.
1799 struct mlx5_flow_meter_info *
1800 mlx5_flow_meter_find(struct mlx5_priv *priv, uint32_t meter_id,
1803 struct mlx5_legacy_flow_meter *legacy_fm;
1804 struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
1805 struct mlx5_aso_mtr *aso_mtr;
1806 struct mlx5_aso_mtr_pools_mng *pools_mng =
1807 &priv->sh->mtrmng->pools_mng;
1808 union mlx5_l3t_data data;
1811 if (priv->sh->meter_aso_en) {
1812 rte_rwlock_read_lock(&pools_mng->resize_mtrwl);
1813 n_valid = pools_mng->n_valid;
1814 rte_rwlock_read_unlock(&pools_mng->resize_mtrwl);
1815 if (!n_valid || !priv->mtr_idx_tbl ||
1816 (mlx5_l3t_get_entry(priv->mtr_idx_tbl, meter_id, &data) ||
1820 *mtr_idx = data.dword;
1821 aso_mtr = mlx5_aso_meter_by_idx(priv, data.dword);
1822 /* Remove reference taken by the mlx5_l3t_get_entry. */
1823 mlx5_l3t_clear_entry(priv->mtr_idx_tbl, meter_id);
1824 if (!aso_mtr || aso_mtr->state == ASO_METER_FREE)
1826 return &aso_mtr->fm;
1828 TAILQ_FOREACH(legacy_fm, fms, next)
1829 if (meter_id == legacy_fm->fm.meter_id) {
1831 *mtr_idx = legacy_fm->idx;
1832 return &legacy_fm->fm;
1838 * Find meter by index.
1841 * Pointer to mlx5_priv.
1846 * Pointer to the meter info found on success, NULL otherwise.
1848 struct mlx5_flow_meter_info *
1849 flow_dv_meter_find_by_idx(struct mlx5_priv *priv, uint32_t idx)
1851 struct mlx5_aso_mtr *aso_mtr;
1853 if (priv->sh->meter_aso_en) {
1854 aso_mtr = mlx5_aso_meter_by_idx(priv, idx);
1857 return &aso_mtr->fm;
1859 return mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MTR], idx);
1864 * Attach meter to flow.
1865 * Unidirectional Meter creation can only be done
1866 * when flow direction is known, i.e. when calling meter_attach.
1869 * Pointer to mlx5 private data.
1871 * Pointer to flow meter.
1873 * Pointer to flow attributes.
1874 * @param [out] error
1875 * Pointer to error structure.
1878 * 0 on success, a negative errno value otherwise and rte_errno is set.
1881 mlx5_flow_meter_attach(struct mlx5_priv *priv,
1882 struct mlx5_flow_meter_info *fm,
1883 const struct rte_flow_attr *attr,
1884 struct rte_flow_error *error)
1888 if (priv->sh->meter_aso_en) {
1889 struct mlx5_aso_mtr *aso_mtr;
1891 aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
1892 if (mlx5_aso_mtr_wait(priv->sh, aso_mtr)) {
1893 return rte_flow_error_set(error, ENOENT,
1894 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1896 "Timeout in meter configuration");
1898 rte_spinlock_lock(&fm->sl);
1899 if (fm->shared || !fm->ref_cnt) {
1902 rte_flow_error_set(error, EINVAL,
1903 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1904 "Meter cannot be shared");
1907 rte_spinlock_unlock(&fm->sl);
1909 rte_spinlock_lock(&fm->sl);
1910 if (fm->meter_action) {
1912 attr->transfer == fm->transfer &&
1913 attr->ingress == fm->ingress &&
1914 attr->egress == fm->egress) {
1917 rte_flow_error_set(error, EINVAL,
1918 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1920 "Meter attr not match." :
1921 "Meter cannot be shared.");
1925 fm->ingress = attr->ingress;
1926 fm->egress = attr->egress;
1927 fm->transfer = attr->transfer;
1929 /* This also creates the meter object. */
1930 fm->meter_action = mlx5_flow_meter_action_create(priv,
1932 if (!fm->meter_action) {
1937 rte_flow_error_set(error, EINVAL,
1938 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1939 "Meter action create failed.");
1943 rte_spinlock_unlock(&fm->sl);
1945 return ret ? -rte_errno : 0;
1949 * Detach meter from flow.
1952 * Pointer to mlx5 private data.
1954 * Pointer to flow meter.
1957 mlx5_flow_meter_detach(struct mlx5_priv *priv,
1958 struct mlx5_flow_meter_info *fm)
1960 #ifdef HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER
1961 rte_spinlock_lock(&fm->sl);
1962 MLX5_ASSERT(fm->ref_cnt);
1963 if (--fm->ref_cnt == 0 && !priv->sh->meter_aso_en) {
1964 mlx5_glue->destroy_flow_action(fm->meter_action);
1965 fm->meter_action = NULL;
1970 rte_spinlock_unlock(&fm->sl);
1978 * Flush meter with Rx queue configuration.
1981 * Pointer to Ethernet device.
1984 mlx5_flow_meter_rxq_flush(struct rte_eth_dev *dev)
1986 struct mlx5_priv *priv = dev->data->dev_private;
1987 struct mlx5_flow_meter_sub_policy *sub_policy;
1988 struct mlx5_flow_meter_policy *mtr_policy;
1990 uint32_t i, policy_idx;
1994 if (priv->policy_idx_tbl) {
1995 MLX5_L3T_FOREACH(priv->policy_idx_tbl, i, entry) {
1996 policy_idx = *(uint32_t *)entry;
1997 sub_policy = mlx5_ipool_get
1998 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
2000 if (!sub_policy || !sub_policy->main_policy)
2002 mtr_policy = sub_policy->main_policy;
2003 if (mtr_policy->is_queue || mtr_policy->is_rss)
2004 mlx5_flow_destroy_sub_policy_with_rxq(dev,
2011 * Iterate a meter hierarchy and flush all meters and policies if possible.
2014 * Pointer to Ethernet device.
2016 * Pointer to flow meter.
2017 * @param[in] mtr_idx
2020 * Pointer to rte meter error structure.
2023 * 0 on success, a negative errno value otherwise and rte_errno is set.
2026 mlx5_flow_meter_flush_hierarchy(struct rte_eth_dev *dev,
2027 struct mlx5_flow_meter_info *fm,
2029 struct rte_mtr_error *error)
2031 struct mlx5_priv *priv = dev->data->dev_private;
2032 struct mlx5_flow_meter_policy *policy;
2034 struct mlx5_flow_meter_info *next_fm;
2035 uint32_t next_mtr_idx;
2036 struct mlx5_flow_meter_policy *next_policy = NULL;
2038 policy = mlx5_flow_meter_policy_find(dev, fm->policy_id, NULL);
2039 MLX5_ASSERT(policy);
2040 while (!fm->ref_cnt && policy->is_hierarchy) {
2041 policy_id = fm->policy_id;
2042 next_fm = mlx5_flow_meter_find(priv,
2043 policy->act_cnt[RTE_COLOR_GREEN].next_mtr_id,
2046 next_policy = mlx5_flow_meter_policy_find(dev,
2049 MLX5_ASSERT(next_policy);
2051 if (mlx5_flow_meter_params_flush(dev, fm, mtr_idx))
2052 return -rte_mtr_error_set(error, ENOTSUP,
2053 RTE_MTR_ERROR_TYPE_MTR_ID,
2055 "Failed to flush meter.");
2056 if (policy->ref_cnt)
2058 if (__mlx5_flow_meter_policy_delete(dev, policy_id,
2059 policy, error, true))
2062 if (!next_fm || !next_policy)
2065 mtr_idx = next_mtr_idx;
2066 policy = next_policy;
2072 * Flush all the hierarchy meters and their policies.
2075 * Pointer to Ethernet device.
2077 * Pointer to rte meter error structure.
2080 * 0 on success, a negative errno value otherwise and rte_errno is set.
2083 mlx5_flow_meter_flush_all_hierarchies(struct rte_eth_dev *dev,
2084 struct rte_mtr_error *error)
2086 struct mlx5_priv *priv = dev->data->dev_private;
2087 struct mlx5_flow_meter_info *fm;
2088 struct mlx5_flow_meter_policy *policy;
2089 struct mlx5_flow_meter_sub_policy *sub_policy;
2090 struct mlx5_flow_meter_info *next_fm;
2091 struct mlx5_aso_mtr *aso_mtr;
2092 uint32_t mtr_idx = 0;
2093 uint32_t i, policy_idx;
2096 if (!priv->mtr_idx_tbl || !priv->policy_idx_tbl)
2098 MLX5_L3T_FOREACH(priv->mtr_idx_tbl, i, entry) {
2099 mtr_idx = *(uint32_t *)entry;
2102 aso_mtr = mlx5_aso_meter_by_idx(priv, mtr_idx);
2104 if (fm->ref_cnt || fm->def_policy)
2106 if (mlx5_flow_meter_flush_hierarchy(dev, fm, mtr_idx, error))
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,
2118 NULL, "Meter policy invalid.");
2119 policy = sub_policy->main_policy;
2120 if (!policy || !policy->is_hierarchy || policy->ref_cnt)
2122 next_fm = mlx5_flow_meter_find(priv,
2123 policy->act_cnt[RTE_COLOR_GREEN].next_mtr_id,
2125 if (__mlx5_flow_meter_policy_delete(dev, i, policy,
2127 return -rte_mtr_error_set(error,
2129 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2130 NULL, "Meter policy invalid.");
2132 if (!next_fm || next_fm->ref_cnt || next_fm->def_policy)
2134 if (mlx5_flow_meter_flush_hierarchy(dev, next_fm,
2141 * Flush meter configuration.
2144 * Pointer to Ethernet device.
2146 * Pointer to rte meter error structure.
2149 * 0 on success, a negative errno value otherwise and rte_errno is set.
2152 mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error)
2154 struct mlx5_priv *priv = dev->data->dev_private;
2155 struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
2156 struct mlx5_flow_meter_profile *fmp;
2157 struct mlx5_legacy_flow_meter *legacy_fm;
2158 struct mlx5_flow_meter_info *fm;
2159 struct mlx5_flow_meter_sub_policy *sub_policy;
2161 uint32_t i, mtr_idx, policy_idx;
2163 struct mlx5_aso_mtr *aso_mtr;
2167 if (priv->sh->meter_aso_en) {
2168 if (mlx5_flow_meter_flush_all_hierarchies(dev, error))
2170 if (priv->mtr_idx_tbl) {
2171 MLX5_L3T_FOREACH(priv->mtr_idx_tbl, i, entry) {
2172 mtr_idx = *(uint32_t *)entry;
2175 mlx5_aso_meter_by_idx(priv, mtr_idx);
2177 (void)mlx5_flow_meter_params_flush(dev,
2181 mlx5_l3t_destroy(priv->mtr_idx_tbl);
2182 priv->mtr_idx_tbl = NULL;
2185 RTE_TAILQ_FOREACH_SAFE(legacy_fm, fms, next, tmp) {
2186 fm = &legacy_fm->fm;
2187 if (mlx5_flow_meter_params_flush(dev, fm, 0))
2188 return -rte_mtr_error_set(error, EINVAL,
2189 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
2190 NULL, "MTR object meter profile invalid.");
2193 if (priv->policy_idx_tbl) {
2194 MLX5_L3T_FOREACH(priv->policy_idx_tbl, i, entry) {
2195 policy_idx = *(uint32_t *)entry;
2196 sub_policy = mlx5_ipool_get
2197 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
2200 return -rte_mtr_error_set(error,
2202 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2204 "meter policy invalid.");
2205 if (__mlx5_flow_meter_policy_delete(dev, i,
2206 sub_policy->main_policy,
2208 return -rte_mtr_error_set(error,
2210 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2212 "meter policy invalid.");
2213 mlx5_free(sub_policy->main_policy);
2215 mlx5_l3t_destroy(priv->policy_idx_tbl);
2216 priv->policy_idx_tbl = NULL;
2218 if (priv->mtr_profile_tbl) {
2219 MLX5_L3T_FOREACH(priv->mtr_profile_tbl, i, entry) {
2221 if (mlx5_flow_meter_profile_delete(dev, fmp->id,
2223 return -rte_mtr_error_set(error, EINVAL,
2224 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2225 NULL, "Fail to destroy "
2228 mlx5_l3t_destroy(priv->mtr_profile_tbl);
2229 priv->mtr_profile_tbl = NULL;
2231 /* Delete default policy table. */
2232 mlx5_flow_destroy_def_policy(dev);
2233 if (priv->sh->refcnt == 1)
2234 mlx5_flow_destroy_mtr_drop_tbls(dev);