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;
139 /* Profile must not be NULL. */
141 return -rte_mtr_error_set(error, EINVAL,
142 RTE_MTR_ERROR_TYPE_METER_PROFILE,
143 NULL, "Meter profile is null.");
144 /* Meter profile ID must be valid. */
145 if (meter_profile_id == UINT32_MAX)
146 return -rte_mtr_error_set(error, EINVAL,
147 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
148 NULL, "Meter profile id not valid.");
149 /* Meter profile must not exist. */
150 fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id);
152 return -rte_mtr_error_set(error, EEXIST,
153 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
155 "Meter profile already exists.");
156 if (!priv->sh->meter_aso_en) {
157 /* Old version is even not supported. */
158 if (!priv->config.hca_attr.qos.flow_meter_old)
159 return -rte_mtr_error_set(error, ENOTSUP,
160 RTE_MTR_ERROR_TYPE_METER_PROFILE,
161 NULL, "Metering is not supported.");
162 /* Old FW metering only supports srTCM. */
163 if (profile->alg != RTE_MTR_SRTCM_RFC2697) {
164 return -rte_mtr_error_set(error, ENOTSUP,
165 RTE_MTR_ERROR_TYPE_METER_PROFILE,
166 NULL, "Metering algorithm is not supported.");
167 } else if (profile->srtcm_rfc2697.ebs) {
168 /* EBS is not supported for old metering. */
169 return -rte_mtr_error_set(error, ENOTSUP,
170 RTE_MTR_ERROR_TYPE_METER_PROFILE,
171 NULL, "EBS is not supported.");
173 if (profile->packet_mode)
174 return -rte_mtr_error_set(error, ENOTSUP,
175 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
176 "Metering algorithm packet mode is not supported.");
178 ls_factor = profile->packet_mode ? MLX5_MTRS_PPS_MAP_BPS_SHIFT : 0;
179 switch (profile->alg) {
180 case RTE_MTR_SRTCM_RFC2697:
181 cir = profile->srtcm_rfc2697.cir << ls_factor;
182 cbs = profile->srtcm_rfc2697.cbs << ls_factor;
183 ebs = profile->srtcm_rfc2697.ebs << ls_factor;
184 /* EBS could be zero for old metering. */
185 if (cir > 0 && cir <= MLX5_SRTCM_XIR_MAX &&
186 cbs > 0 && cbs <= MLX5_SRTCM_XBS_MAX &&
187 ebs <= MLX5_SRTCM_XBS_MAX) {
190 ret = -rte_mtr_error_set(error, ENOTSUP,
191 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
192 "Profile values out of range.");
195 case RTE_MTR_TRTCM_RFC2698:
196 cir = profile->trtcm_rfc2698.cir << ls_factor;
197 cbs = profile->trtcm_rfc2698.cbs << ls_factor;
198 pir = profile->trtcm_rfc2698.pir << ls_factor;
199 pbs = profile->trtcm_rfc2698.pbs << ls_factor;
200 if (cir > 0 && cir <= MLX5_SRTCM_XIR_MAX &&
201 cbs > 0 && cbs <= MLX5_SRTCM_XBS_MAX &&
202 pir >= cir && pir <= (MLX5_SRTCM_XIR_MAX * 2) &&
203 pbs >= cbs && pbs <= (MLX5_SRTCM_XBS_MAX * 2)) {
206 ret = -rte_mtr_error_set(error, ENOTSUP,
207 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
208 "Profile values out of range.");
211 case RTE_MTR_TRTCM_RFC4115:
212 cir = profile->trtcm_rfc4115.cir << ls_factor;
213 cbs = profile->trtcm_rfc4115.cbs << ls_factor;
214 eir = profile->trtcm_rfc4115.eir << ls_factor;
215 ebs = profile->trtcm_rfc4115.ebs << ls_factor;
216 if (cir > 0 && cir <= MLX5_SRTCM_XIR_MAX &&
217 cbs > 0 && cbs <= MLX5_SRTCM_XBS_MAX &&
218 eir <= MLX5_SRTCM_XIR_MAX && ebs <= MLX5_SRTCM_XBS_MAX) {
221 ret = -rte_mtr_error_set(error, ENOTSUP,
222 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
223 "Profile values out of range.");
227 ret = -rte_mtr_error_set(error, ENOTSUP,
228 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
229 "Unknown metering algorithm.");
236 * Calculate mantissa and exponent for cir / eir.
239 * Value to be calculated.
241 * Pointer to the mantissa.
243 * Pointer to the exp.
246 mlx5_flow_meter_xir_man_exp_calc(int64_t xir, uint8_t *man, uint8_t *exp)
249 int64_t delta = INT64_MAX;
254 for (m = 0; m <= 0xFF; m++) { /* man width 8 bit */
255 for (e = 0; e <= 0x1F; e++) { /* exp width 5bit */
256 _cir = (1000000000ULL * m) >> e;
257 if (llabs(xir - _cir) <= delta) {
258 delta = llabs(xir - _cir);
269 * Calculate mantissa and exponent for xbs.
272 * Value to be calculated.
274 * Pointer to the mantissa.
276 * Pointer to the exp.
279 mlx5_flow_meter_xbs_man_exp_calc(uint64_t xbs, uint8_t *man, uint8_t *exp)
284 /* Special case xbs == 0 ? both exp and matissa are 0. */
290 /* xbs = xbs_mantissa * 2^xbs_exponent */
291 _man = frexp(xbs, &_exp);
292 _man = _man * pow(2, MLX5_MAN_WIDTH);
293 _exp = _exp - MLX5_MAN_WIDTH;
294 *man = (uint8_t)ceil(_man);
299 * Fill the prm meter parameter.
302 * Pointer to meter profie to be converted.
304 * Pointer to the error structure.
307 * 0 on success, a negative errno value otherwise and rte_errno is set.
310 mlx5_flow_meter_param_fill(struct mlx5_flow_meter_profile *fmp,
311 struct rte_mtr_error *error)
313 struct mlx5_flow_meter_srtcm_rfc2697_prm *srtcm = &fmp->srtcm_prm;
315 uint32_t cbs_exp, cbs_man, cir_exp, cir_man;
316 uint32_t eir_exp, eir_man, ebs_exp, ebs_man;
317 uint64_t cir, cbs, eir, ebs;
319 switch (fmp->profile.alg) {
320 case RTE_MTR_SRTCM_RFC2697:
321 cir = fmp->profile.srtcm_rfc2697.cir;
322 cbs = fmp->profile.srtcm_rfc2697.cbs;
324 ebs = fmp->profile.srtcm_rfc2697.ebs;
326 case RTE_MTR_TRTCM_RFC2698:
327 MLX5_ASSERT(fmp->profile.trtcm_rfc2698.pir >
328 fmp->profile.trtcm_rfc2698.cir &&
329 fmp->profile.trtcm_rfc2698.pbs >
330 fmp->profile.trtcm_rfc2698.cbs);
331 cir = fmp->profile.trtcm_rfc2698.cir;
332 cbs = fmp->profile.trtcm_rfc2698.cbs;
333 /* EIR / EBS are filled with PIR / PBS. */
334 eir = fmp->profile.trtcm_rfc2698.pir;
335 ebs = fmp->profile.trtcm_rfc2698.pbs;
337 case RTE_MTR_TRTCM_RFC4115:
338 cir = fmp->profile.trtcm_rfc4115.cir;
339 cbs = fmp->profile.trtcm_rfc4115.cbs;
340 eir = fmp->profile.trtcm_rfc4115.eir;
341 ebs = fmp->profile.trtcm_rfc4115.ebs;
344 return -rte_mtr_error_set(error, EINVAL,
345 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
346 "Metering algorithm mode is invalid");
348 /* Adjust the values for PPS mode. */
349 if (fmp->profile.packet_mode) {
350 cir <<= MLX5_MTRS_PPS_MAP_BPS_SHIFT;
351 cbs <<= MLX5_MTRS_PPS_MAP_BPS_SHIFT;
352 eir <<= MLX5_MTRS_PPS_MAP_BPS_SHIFT;
353 ebs <<= MLX5_MTRS_PPS_MAP_BPS_SHIFT;
355 /* cir = 8G * cir_mantissa * 1/(2^cir_exponent)) Bytes/Sec */
356 mlx5_flow_meter_xir_man_exp_calc(cir, &man, &exp);
357 /* Check if cir mantissa is too large. */
358 if (exp > ASO_DSEG_XIR_EXP_MASK)
359 return -rte_mtr_error_set(error, ENOTSUP,
360 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
361 "meter profile parameter cir is not supported.");
364 /* cbs = cbs_mantissa * 2^cbs_exponent */
365 mlx5_flow_meter_xbs_man_exp_calc(cbs, &man, &exp);
366 /* Check if cbs mantissa is too large. */
367 if (exp > ASO_DSEG_EXP_MASK)
368 return -rte_mtr_error_set(error, ENOTSUP,
369 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
370 "meter profile parameter cbs is not supported.");
373 srtcm->cbs_cir = rte_cpu_to_be_32(cbs_exp << ASO_DSEG_CBS_EXP_OFFSET |
374 cbs_man << ASO_DSEG_CBS_MAN_OFFSET |
375 cir_exp << ASO_DSEG_XIR_EXP_OFFSET |
377 mlx5_flow_meter_xir_man_exp_calc(eir, &man, &exp);
378 /* Check if eir mantissa is too large. */
379 if (exp > ASO_DSEG_XIR_EXP_MASK)
380 return -rte_mtr_error_set(error, ENOTSUP,
381 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
382 "meter profile parameter eir is not supported.");
385 mlx5_flow_meter_xbs_man_exp_calc(ebs, &man, &exp);
386 /* Check if ebs mantissa is too large. */
387 if (exp > ASO_DSEG_EXP_MASK)
388 return -rte_mtr_error_set(error, ENOTSUP,
389 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
390 "meter profile parameter ebs is not supported.");
393 srtcm->ebs_eir = rte_cpu_to_be_32(ebs_exp << ASO_DSEG_EBS_EXP_OFFSET |
394 ebs_man << ASO_DSEG_EBS_MAN_OFFSET |
395 eir_exp << ASO_DSEG_XIR_EXP_OFFSET |
405 * Callback to get MTR capabilities.
408 * Pointer to Ethernet device.
410 * Pointer to save MTR capabilities.
412 * Pointer to the error structure.
415 * 0 on success, a negative errno value otherwise and rte_errno is set.
418 mlx5_flow_mtr_cap_get(struct rte_eth_dev *dev,
419 struct rte_mtr_capabilities *cap,
420 struct rte_mtr_error *error __rte_unused)
422 struct mlx5_priv *priv = dev->data->dev_private;
423 struct mlx5_hca_qos_attr *qattr = &priv->config.hca_attr.qos;
426 return -rte_mtr_error_set(error, ENOTSUP,
427 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
428 "Meter is not supported");
429 memset(cap, 0, sizeof(*cap));
430 if (priv->sh->meter_aso_en) {
431 /* 2 meters per one ASO cache line. */
432 cap->n_max = 1 << (qattr->log_max_num_meter_aso + 1);
433 cap->srtcm_rfc2697_packet_mode_supported = 1;
435 cap->n_max = 1 << qattr->log_max_flow_meter;
436 cap->srtcm_rfc2697_packet_mode_supported = 0;
438 cap->srtcm_rfc2697_byte_mode_supported = 1;
439 cap->n_shared_max = cap->n_max;
441 cap->shared_identical = 1;
442 cap->shared_n_flows_per_mtr_max = 4 << 20;
443 /* 2M flows can share the same meter. */
444 cap->chaining_n_mtrs_per_flow_max = 1; /* Chaining is not supported. */
445 cap->meter_srtcm_rfc2697_n_max = qattr->flow_meter_old ? cap->n_max : 0;
446 cap->meter_rate_max = 1ULL << 40; /* 1 Tera tokens per sec. */
447 cap->stats_mask = RTE_MTR_STATS_N_BYTES_DROPPED |
448 RTE_MTR_STATS_N_PKTS_DROPPED;
453 * Callback to add MTR profile.
456 * Pointer to Ethernet device.
457 * @param[in] meter_profile_id
460 * Pointer to meter profile detail.
462 * Pointer to the error structure.
465 * 0 on success, a negative errno value otherwise and rte_errno is set.
468 mlx5_flow_meter_profile_add(struct rte_eth_dev *dev,
469 uint32_t meter_profile_id,
470 struct rte_mtr_meter_profile *profile,
471 struct rte_mtr_error *error)
473 struct mlx5_priv *priv = dev->data->dev_private;
474 struct mlx5_flow_meter_profile *fmp;
475 union mlx5_l3t_data data;
479 return -rte_mtr_error_set(error, ENOTSUP,
480 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
481 "Meter is not supported");
482 /* Check input params. */
483 ret = mlx5_flow_meter_profile_validate(dev, meter_profile_id,
487 /* Meter profile memory allocation. */
488 fmp = mlx5_malloc(MLX5_MEM_ZERO, sizeof(struct mlx5_flow_meter_profile),
489 RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
491 return -rte_mtr_error_set(error, ENOMEM,
492 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
493 NULL, "Meter profile memory "
495 /* Fill profile info. */
496 fmp->id = meter_profile_id;
497 fmp->profile = *profile;
498 /* Fill the flow meter parameters for the PRM. */
499 ret = mlx5_flow_meter_param_fill(fmp, error);
503 ret = mlx5_l3t_set_entry(priv->mtr_profile_tbl,
504 meter_profile_id, &data);
506 return -rte_mtr_error_set(error, ENOTSUP,
507 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
508 NULL, "Meter profile insert fail.");
516 * Callback to delete MTR profile.
519 * Pointer to Ethernet device.
520 * @param[in] meter_profile_id
523 * Pointer to the error structure.
526 * 0 on success, a negative errno value otherwise and rte_errno is set.
529 mlx5_flow_meter_profile_delete(struct rte_eth_dev *dev,
530 uint32_t meter_profile_id,
531 struct rte_mtr_error *error)
533 struct mlx5_priv *priv = dev->data->dev_private;
534 struct mlx5_flow_meter_profile *fmp;
537 return -rte_mtr_error_set(error, ENOTSUP,
538 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
539 "Meter is not supported");
540 /* Meter profile must exist. */
541 fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id);
543 return -rte_mtr_error_set(error, ENOENT,
544 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
546 "Meter profile id is invalid.");
547 /* Check profile is unused. */
549 return -rte_mtr_error_set(error, EBUSY,
550 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
551 NULL, "Meter profile is in use.");
552 if (mlx5_l3t_clear_entry(priv->mtr_profile_tbl, meter_profile_id))
553 return -rte_mtr_error_set(error, EBUSY,
554 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
555 NULL, "Meter profile remove fail.");
564 * Pointer to Ethernet device.
569 * Pointer to the policy found on success, NULL otherwise.
571 struct mlx5_flow_meter_policy *
572 mlx5_flow_meter_policy_find(struct rte_eth_dev *dev,
574 uint32_t *policy_idx)
576 struct mlx5_priv *priv = dev->data->dev_private;
577 struct mlx5_flow_meter_sub_policy *sub_policy = NULL;
578 union mlx5_l3t_data data;
580 if (policy_id > MLX5_MAX_SUB_POLICY_TBL_NUM || !priv->policy_idx_tbl)
582 if (mlx5_l3t_get_entry(priv->policy_idx_tbl, policy_id, &data) ||
586 *policy_idx = data.dword;
587 sub_policy = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
589 /* Remove reference taken by the mlx5_l3t_get_entry. */
590 mlx5_l3t_clear_entry(priv->policy_idx_tbl, policy_id);
592 if (sub_policy->main_policy_id)
593 return sub_policy->main_policy;
598 * Get the last meter's policy from one meter's policy in hierarchy.
601 * Pointer to Ethernet device.
603 * Pointer to flow meter policy.
606 * Pointer to the final meter's policy, or NULL when fail.
608 struct mlx5_flow_meter_policy *
609 mlx5_flow_meter_hierarchy_get_final_policy(struct rte_eth_dev *dev,
610 struct mlx5_flow_meter_policy *policy)
612 struct mlx5_priv *priv = dev->data->dev_private;
613 struct mlx5_flow_meter_info *next_fm;
614 struct mlx5_flow_meter_policy *next_policy = policy;
616 while (next_policy->is_hierarchy) {
617 next_fm = mlx5_flow_meter_find(priv,
618 next_policy->act_cnt[RTE_COLOR_GREEN].next_mtr_id, NULL);
619 if (!next_fm || next_fm->def_policy)
621 next_policy = mlx5_flow_meter_policy_find(dev,
622 next_fm->policy_id, NULL);
623 MLX5_ASSERT(next_policy);
629 * Callback to check MTR policy action validate
632 * Pointer to Ethernet device.
634 * Pointer to meter policy action detail.
636 * Pointer to the error structure.
639 * 0 on success, a negative errno value otherwise and rte_errno is set.
642 mlx5_flow_meter_policy_validate(struct rte_eth_dev *dev,
643 struct rte_mtr_meter_policy_params *policy,
644 struct rte_mtr_error *error)
646 struct mlx5_priv *priv = dev->data->dev_private;
647 struct rte_flow_attr attr = { .transfer =
648 priv->config.dv_esw_en ? 1 : 0};
651 uint8_t domain_bitmap;
654 if (!priv->mtr_en || !priv->sh->meter_aso_en)
655 return -rte_mtr_error_set(error, ENOTSUP,
656 RTE_MTR_ERROR_TYPE_METER_POLICY,
657 NULL, "meter policy unsupported.");
658 ret = mlx5_flow_validate_mtr_acts(dev, policy->actions, &attr,
659 &is_rss, &domain_bitmap, &policy_mode, error);
666 __mlx5_flow_meter_policy_delete(struct rte_eth_dev *dev,
668 struct mlx5_flow_meter_policy *mtr_policy,
669 struct rte_mtr_error *error,
672 struct mlx5_priv *priv = dev->data->dev_private;
673 struct mlx5_flow_meter_sub_policy *sub_policy;
675 uint16_t sub_policy_num;
677 rte_spinlock_lock(&mtr_policy->sl);
678 if (mtr_policy->ref_cnt) {
679 rte_spinlock_unlock(&mtr_policy->sl);
680 return -rte_mtr_error_set(error, EBUSY,
681 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
683 "Meter policy object is being used.");
685 mlx5_flow_destroy_policy_rules(dev, mtr_policy);
686 mlx5_flow_destroy_mtr_acts(dev, mtr_policy);
687 for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
688 sub_policy_num = (mtr_policy->sub_policy_num >>
689 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i)) &
690 MLX5_MTR_SUB_POLICY_NUM_MASK;
691 if (sub_policy_num) {
692 for (j = 0; j < sub_policy_num; j++) {
693 sub_policy = mtr_policy->sub_policys[i][j];
696 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
701 if (priv->policy_idx_tbl && clear_l3t) {
702 if (mlx5_l3t_clear_entry(priv->policy_idx_tbl, policy_id)) {
703 rte_spinlock_unlock(&mtr_policy->sl);
704 return -rte_mtr_error_set(error, ENOTSUP,
705 RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL,
706 "Fail to delete policy in index table.");
709 rte_spinlock_unlock(&mtr_policy->sl);
714 * Callback to add MTR policy.
717 * Pointer to Ethernet device.
718 * @param[out] policy_id
719 * Pointer to policy id
721 * Pointer to meter policy action detail.
723 * Pointer to the error structure.
726 * 0 on success, a negative errno value otherwise and rte_errno is set.
729 mlx5_flow_meter_policy_add(struct rte_eth_dev *dev,
731 struct rte_mtr_meter_policy_params *policy,
732 struct rte_mtr_error *error)
734 struct mlx5_priv *priv = dev->data->dev_private;
735 struct rte_flow_attr attr = { .transfer =
736 priv->config.dv_esw_en ? 1 : 0};
737 uint32_t sub_policy_idx = 0;
738 uint32_t policy_idx = 0;
739 struct mlx5_flow_meter_policy *mtr_policy = NULL;
740 struct mlx5_flow_meter_sub_policy *sub_policy;
745 uint32_t policy_size = sizeof(struct mlx5_flow_meter_policy);
746 uint16_t sub_policy_num;
747 uint8_t domain_bitmap = 0;
748 union mlx5_l3t_data data;
749 bool skip_rule = false;
752 return -rte_mtr_error_set(error, ENOTSUP,
753 RTE_MTR_ERROR_TYPE_METER_POLICY,
754 NULL, "meter policy unsupported. ");
755 if (policy_id == MLX5_INVALID_POLICY_ID)
756 return -rte_mtr_error_set(error, ENOTSUP,
757 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
758 NULL, "policy ID is invalid. ");
759 if (policy_id == priv->sh->mtrmng->def_policy_id)
760 return -rte_mtr_error_set(error, EEXIST,
761 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
762 NULL, "default policy ID exists. ");
763 mtr_policy = mlx5_flow_meter_policy_find(dev, policy_id, &policy_idx);
765 return -rte_mtr_error_set(error, EEXIST,
766 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
767 NULL, "policy ID exists. ");
768 ret = mlx5_flow_validate_mtr_acts(dev, policy->actions, &attr,
769 &is_rss, &domain_bitmap,
770 &policy_mode, error);
774 return -rte_mtr_error_set(error, ENOTSUP,
775 RTE_MTR_ERROR_TYPE_METER_POLICY,
776 NULL, "fail to find policy domain.");
777 if (policy_mode == MLX5_MTR_POLICY_MODE_DEF) {
778 if (priv->sh->mtrmng->def_policy_id != MLX5_INVALID_POLICY_ID)
779 return -rte_mtr_error_set(error, EEXIST,
780 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
781 NULL, "a policy with similar actions "
782 "is already configured");
783 if (mlx5_flow_create_def_policy(dev))
784 return -rte_mtr_error_set(error, ENOTSUP,
785 RTE_MTR_ERROR_TYPE_METER_POLICY,
787 "fail to create non-terminated policy.");
788 priv->sh->mtrmng->def_policy_id = policy_id;
791 if (!priv->sh->meter_aso_en)
792 return -rte_mtr_error_set(error, ENOTSUP,
793 RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
794 "no ASO capability to support the policy ");
795 for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
796 if (!(domain_bitmap & (1 << i)))
799 * If RSS is found, it means that only the ingress domain can
800 * be supported. It is invalid to support RSS for one color
801 * and egress / transfer domain actions for another. Drop and
802 * jump action should have no impact.
806 sizeof(struct mlx5_flow_meter_sub_policy *) *
807 MLX5_MTR_RSS_MAX_SUB_POLICY;
810 policy_size += sizeof(struct mlx5_flow_meter_sub_policy *);
812 mtr_policy = mlx5_malloc(MLX5_MEM_ZERO, policy_size,
813 RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
815 return -rte_mtr_error_set(error, ENOMEM,
816 RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
817 "Memory alloc failed for meter policy.");
818 if (policy_mode == MLX5_MTR_POLICY_MODE_OG)
819 mtr_policy->skip_y = 1;
820 else if (policy_mode == MLX5_MTR_POLICY_MODE_OY)
821 mtr_policy->skip_g = 1;
822 policy_size = sizeof(struct mlx5_flow_meter_policy);
823 for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
824 if (!(domain_bitmap & (1 << i)))
826 if (i == MLX5_MTR_DOMAIN_INGRESS)
827 mtr_policy->ingress = 1;
828 if (i == MLX5_MTR_DOMAIN_EGRESS)
829 mtr_policy->egress = 1;
830 if (i == MLX5_MTR_DOMAIN_TRANSFER)
831 mtr_policy->transfer = 1;
832 sub_policy = mlx5_ipool_zmalloc
833 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
836 sub_policy_idx > MLX5_MAX_SUB_POLICY_TBL_NUM)
838 sub_policy->idx = sub_policy_idx;
839 sub_policy->main_policy = mtr_policy;
841 policy_idx = sub_policy_idx;
842 sub_policy->main_policy_id = 1;
844 mtr_policy->sub_policys[i] =
845 (struct mlx5_flow_meter_sub_policy **)
846 ((uint8_t *)mtr_policy + policy_size);
847 mtr_policy->sub_policys[i][0] = sub_policy;
848 sub_policy_num = (mtr_policy->sub_policy_num >>
849 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i)) &
850 MLX5_MTR_SUB_POLICY_NUM_MASK;
852 mtr_policy->sub_policy_num &= ~(MLX5_MTR_SUB_POLICY_NUM_MASK <<
853 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i));
854 mtr_policy->sub_policy_num |=
855 (sub_policy_num & MLX5_MTR_SUB_POLICY_NUM_MASK) <<
856 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i);
858 * If RSS is found, it means that only the ingress domain can
859 * be supported. It is invalid to support RSS for one color
860 * and egress / transfer domain actions for another. Drop and
861 * jump action should have no impact.
864 mtr_policy->is_rss = 1;
867 policy_size += sizeof(struct mlx5_flow_meter_sub_policy *);
869 rte_spinlock_init(&mtr_policy->sl);
870 ret = mlx5_flow_create_mtr_acts(dev, mtr_policy,
871 policy->actions, error);
874 if (mtr_policy->is_hierarchy) {
875 struct mlx5_flow_meter_policy *final_policy;
878 mlx5_flow_meter_hierarchy_get_final_policy(dev, mtr_policy);
881 skip_rule = (final_policy->is_rss || final_policy->is_queue);
884 * If either Green or Yellow has queue / RSS action, all the policy
885 * rules will be created later in the flow splitting stage.
887 if (!is_rss && !mtr_policy->is_queue && !skip_rule) {
888 /* Create policy rules in HW. */
889 ret = mlx5_flow_create_policy_rules(dev, mtr_policy);
893 data.dword = policy_idx;
894 if (!priv->policy_idx_tbl) {
895 priv->policy_idx_tbl = mlx5_l3t_create(MLX5_L3T_TYPE_DWORD);
896 if (!priv->policy_idx_tbl)
899 if (mlx5_l3t_set_entry(priv->policy_idx_tbl, policy_id, &data))
904 ret = __mlx5_flow_meter_policy_delete(dev, policy_id,
905 mtr_policy, error, false);
906 mlx5_free(mtr_policy);
910 return -rte_mtr_error_set(error, ENOTSUP,
911 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
912 NULL, "Failed to create devx policy.");
916 * Callback to delete MTR policy.
919 * Pointer to Ethernet device.
920 * @param[in] policy_id
923 * Pointer to the error structure.
926 * 0 on success, a negative errno value otherwise and rte_errno is set.
929 mlx5_flow_meter_policy_delete(struct rte_eth_dev *dev,
931 struct rte_mtr_error *error)
933 struct mlx5_priv *priv = dev->data->dev_private;
934 struct mlx5_flow_meter_policy *mtr_policy;
938 if (policy_id == priv->sh->mtrmng->def_policy_id) {
939 if (priv->sh->mtrmng->def_policy_ref_cnt > 0)
940 return -rte_mtr_error_set(error, ENOTSUP,
941 RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL,
942 "Meter policy object is being used.");
943 priv->sh->mtrmng->def_policy_id = MLX5_INVALID_POLICY_ID;
946 mtr_policy = mlx5_flow_meter_policy_find(dev, policy_id, &policy_idx);
948 return -rte_mtr_error_set(error, ENOTSUP,
949 RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL,
950 "Meter policy id is invalid. ");
951 ret = __mlx5_flow_meter_policy_delete(dev, policy_id, mtr_policy,
955 mlx5_free(mtr_policy);
960 * Check meter validation.
963 * Pointer to mlx5 private data structure.
964 * @param[in] meter_id
967 * Pointer to rte meter parameters.
969 * Pointer to rte meter error structure.
972 * 0 on success, a negative errno value otherwise and rte_errno is set.
975 mlx5_flow_meter_validate(struct mlx5_priv *priv, uint32_t meter_id,
976 struct rte_mtr_params *params,
977 struct rte_mtr_error *error)
979 /* Meter must use global drop action. */
980 if (!priv->sh->dr_drop_action)
981 return -rte_mtr_error_set(error, ENOTSUP,
982 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
984 "No drop action ready for meter.");
985 /* Meter params must not be NULL. */
987 return -rte_mtr_error_set(error, EINVAL,
988 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
989 NULL, "Meter object params null.");
990 /* Previous meter color is not supported. */
991 if (params->use_prev_mtr_color)
992 return -rte_mtr_error_set(error, ENOTSUP,
993 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
995 "Previous meter color "
997 if (params->meter_policy_id == MLX5_INVALID_POLICY_ID)
998 return -rte_mtr_error_set(error, ENOENT,
999 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
1000 NULL, "Meter policy id not valid.");
1001 /* Validate meter id. */
1002 if (mlx5_flow_meter_find(priv, meter_id, NULL))
1003 return -rte_mtr_error_set(error, EEXIST,
1004 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
1005 "Meter object already exists.");
1010 * Modify the flow meter action.
1013 * Pointer to mlx5 private data structure.
1015 * Pointer to flow meter to be modified.
1017 * Pointer to meter srtcm description parameter.
1018 * @param[in] modify_bits
1019 * The bit in srtcm to be updated.
1020 * @param[in] active_state
1021 * The state to be updated.
1023 * 0 on success, o negative value otherwise.
1026 mlx5_flow_meter_action_modify(struct mlx5_priv *priv,
1027 struct mlx5_flow_meter_info *fm,
1028 const struct mlx5_flow_meter_srtcm_rfc2697_prm *srtcm,
1029 uint64_t modify_bits, uint32_t active_state, uint32_t is_enable)
1031 #ifdef HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER
1032 uint32_t in[MLX5_ST_SZ_DW(flow_meter_parameters)] = { 0 };
1034 struct mlx5dv_dr_flow_meter_attr mod_attr = { 0 };
1036 struct mlx5_aso_mtr *aso_mtr = NULL;
1037 uint32_t cbs_cir, ebs_eir, val;
1039 if (priv->sh->meter_aso_en) {
1040 fm->is_enable = !!is_enable;
1041 aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
1042 ret = mlx5_aso_meter_update_by_wqe(priv->sh, aso_mtr);
1045 ret = mlx5_aso_mtr_wait(priv->sh, aso_mtr);
1049 /* Fill command parameters. */
1050 mod_attr.reg_c_index = priv->mtr_color_reg - REG_C_0;
1051 mod_attr.flow_meter_parameter = in;
1052 mod_attr.flow_meter_parameter_sz =
1053 MLX5_ST_SZ_BYTES(flow_meter_parameters);
1054 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_ACTIVE)
1055 mod_attr.active = !!active_state;
1057 mod_attr.active = 0;
1059 cbs_cir = rte_be_to_cpu_32(srtcm->cbs_cir);
1060 ebs_eir = rte_be_to_cpu_32(srtcm->ebs_eir);
1061 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS) {
1062 val = (cbs_cir >> ASO_DSEG_CBS_EXP_OFFSET) &
1064 MLX5_SET(flow_meter_parameters, attr,
1066 val = (cbs_cir >> ASO_DSEG_CBS_MAN_OFFSET) &
1068 MLX5_SET(flow_meter_parameters, attr,
1071 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR) {
1072 val = (cbs_cir >> ASO_DSEG_XIR_EXP_OFFSET) &
1074 MLX5_SET(flow_meter_parameters, attr,
1076 val = cbs_cir & ASO_DSEG_MAN_MASK;
1077 MLX5_SET(flow_meter_parameters, attr,
1080 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_EBS) {
1081 val = (ebs_eir >> ASO_DSEG_EBS_EXP_OFFSET) &
1083 MLX5_SET(flow_meter_parameters, attr,
1085 val = (ebs_eir >> ASO_DSEG_EBS_MAN_OFFSET) &
1087 MLX5_SET(flow_meter_parameters, attr,
1090 /* Apply modifications to meter only if it was created. */
1091 if (fm->meter_action) {
1092 ret = mlx5_glue->dv_modify_flow_action_meter
1093 (fm->meter_action, &mod_attr,
1094 rte_cpu_to_be_64(modify_bits));
1098 /* Update succeedded modify meter parameters. */
1099 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_ACTIVE)
1100 fm->active_state = !!active_state;
1115 mlx5_flow_meter_stats_enable_update(struct rte_eth_dev *dev,
1116 struct mlx5_flow_meter_info *fm,
1117 uint64_t stats_mask)
1120 (stats_mask & RTE_MTR_STATS_N_BYTES_DROPPED) ? 1 : 0;
1121 fm->pkts_dropped = (stats_mask & RTE_MTR_STATS_N_PKTS_DROPPED) ? 1 : 0;
1122 if (fm->bytes_dropped || fm->pkts_dropped) {
1123 if (!fm->drop_cnt) {
1124 /* Alloc policer counters. */
1125 fm->drop_cnt = mlx5_counter_alloc(dev);
1131 mlx5_counter_free(dev, fm->drop_cnt);
1139 * Create meter rules.
1142 * Pointer to Ethernet device.
1143 * @param[in] meter_id
1146 * Pointer to rte meter parameters.
1148 * Meter shared with other flow or not.
1150 * Pointer to rte meter error structure.
1153 * 0 on success, a negative errno value otherwise and rte_errno is set.
1156 mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,
1157 struct rte_mtr_params *params, int shared,
1158 struct rte_mtr_error *error)
1160 struct mlx5_priv *priv = dev->data->dev_private;
1161 struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
1162 struct mlx5_flow_meter_profile *fmp;
1163 struct mlx5_flow_meter_info *fm;
1164 struct mlx5_legacy_flow_meter *legacy_fm;
1165 struct mlx5_flow_meter_policy *mtr_policy = NULL;
1166 struct mlx5_indexed_pool_config flow_ipool_cfg = {
1170 .type = "mlx5_flow_mtr_flow_id_pool",
1172 struct mlx5_aso_mtr *aso_mtr;
1173 uint32_t mtr_idx, policy_idx;
1174 union mlx5_l3t_data data;
1176 uint8_t domain_bitmap;
1177 uint8_t mtr_id_bits;
1178 uint8_t mtr_reg_bits = priv->mtr_reg_share ?
1179 MLX5_MTR_IDLE_BITS_IN_COLOR_REG : MLX5_REG_BITS;
1182 return -rte_mtr_error_set(error, ENOTSUP,
1183 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1184 "Meter is not supported");
1185 /* Validate the parameters. */
1186 ret = mlx5_flow_meter_validate(priv, meter_id, params, error);
1189 /* Meter profile must exist. */
1190 fmp = mlx5_flow_meter_profile_find(priv, params->meter_profile_id);
1192 return -rte_mtr_error_set(error, ENOENT,
1193 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
1194 NULL, "Meter profile id not valid.");
1195 /* Meter policy must exist. */
1196 if (params->meter_policy_id == priv->sh->mtrmng->def_policy_id) {
1198 (&priv->sh->mtrmng->def_policy_ref_cnt,
1199 1, __ATOMIC_RELAXED);
1200 domain_bitmap = MLX5_MTR_ALL_DOMAIN_BIT;
1201 if (!priv->config.dv_esw_en)
1202 domain_bitmap &= ~MLX5_MTR_DOMAIN_TRANSFER_BIT;
1204 if (!priv->sh->meter_aso_en)
1205 return -rte_mtr_error_set(error, ENOTSUP,
1206 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1207 "Part of the policies cannot be "
1208 "supported without ASO ");
1209 mtr_policy = mlx5_flow_meter_policy_find(dev,
1210 params->meter_policy_id, &policy_idx);
1212 return -rte_mtr_error_set(error, ENOENT,
1213 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
1214 NULL, "Meter policy id not valid.");
1215 domain_bitmap = (mtr_policy->ingress ?
1216 MLX5_MTR_DOMAIN_INGRESS_BIT : 0) |
1217 (mtr_policy->egress ?
1218 MLX5_MTR_DOMAIN_EGRESS_BIT : 0) |
1219 (mtr_policy->transfer ?
1220 MLX5_MTR_DOMAIN_TRANSFER_BIT : 0);
1221 if (fmp->g_support && mtr_policy->skip_g)
1222 return -rte_mtr_error_set(error, ENOTSUP,
1223 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
1224 NULL, "Meter green policy is empty.");
1225 if (fmp->y_support && mtr_policy->skip_y)
1226 return -rte_mtr_error_set(error, ENOTSUP,
1227 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
1228 NULL, "Meter yellow policy is empty.");
1230 /* Allocate the flow meter memory. */
1231 if (priv->sh->meter_aso_en) {
1232 mtr_idx = mlx5_flow_mtr_alloc(dev);
1234 return -rte_mtr_error_set(error, ENOMEM,
1235 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1236 "Memory alloc failed for meter.");
1237 aso_mtr = mlx5_aso_meter_by_idx(priv, mtr_idx);
1241 return -rte_mtr_error_set(error, ENOMEM,
1242 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1243 "Unsupported profile with yellow.");
1244 legacy_fm = mlx5_ipool_zmalloc
1245 (priv->sh->ipool[MLX5_IPOOL_MTR], &mtr_idx);
1246 if (legacy_fm == NULL)
1247 return -rte_mtr_error_set(error, ENOMEM,
1248 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1249 "Memory alloc failed for meter.");
1250 legacy_fm->idx = mtr_idx;
1251 fm = &legacy_fm->fm;
1253 mtr_id_bits = MLX5_REG_BITS - __builtin_clz(mtr_idx);
1254 if ((mtr_id_bits + priv->sh->mtrmng->max_mtr_flow_bits) >
1256 DRV_LOG(ERR, "Meter number exceeds max limit.");
1259 if (mtr_id_bits > priv->sh->mtrmng->max_mtr_bits)
1260 priv->sh->mtrmng->max_mtr_bits = mtr_id_bits;
1261 /* Fill the flow meter parameters. */
1262 fm->meter_id = meter_id;
1263 fm->policy_id = params->meter_policy_id;
1265 if (mlx5_flow_meter_stats_enable_update(dev, fm, params->stats_mask))
1267 if (mlx5_flow_create_mtr_tbls(dev, fm, mtr_idx, domain_bitmap))
1269 /* Add to the flow meter list. */
1270 if (!priv->sh->meter_aso_en)
1271 TAILQ_INSERT_TAIL(fms, legacy_fm, next);
1272 /* Add to the flow meter list. */
1273 fm->active_state = 1; /* Config meter starts as active. */
1275 fm->shared = !!shared;
1276 __atomic_add_fetch(&fm->profile->ref_cnt, 1, __ATOMIC_RELAXED);
1277 if (params->meter_policy_id == priv->sh->mtrmng->def_policy_id) {
1279 fm->flow_ipool = mlx5_ipool_create(&flow_ipool_cfg);
1280 if (!fm->flow_ipool)
1283 rte_spinlock_init(&fm->sl);
1284 /* If ASO meter supported, update ASO flow meter by wqe. */
1285 if (priv->sh->meter_aso_en) {
1286 aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
1287 ret = mlx5_aso_meter_update_by_wqe(priv->sh, aso_mtr);
1290 if (!priv->mtr_idx_tbl) {
1292 mlx5_l3t_create(MLX5_L3T_TYPE_DWORD);
1293 if (!priv->mtr_idx_tbl)
1296 data.dword = mtr_idx;
1297 if (mlx5_l3t_set_entry(priv->mtr_idx_tbl, meter_id, &data))
1301 __atomic_add_fetch(&mtr_policy->ref_cnt, 1, __ATOMIC_RELAXED);
1304 mlx5_flow_destroy_mtr_tbls(dev, fm);
1305 /* Free policer counters. */
1307 mlx5_counter_free(dev, fm->drop_cnt);
1308 if (priv->sh->meter_aso_en)
1309 mlx5_flow_mtr_free(dev, mtr_idx);
1311 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR], mtr_idx);
1312 return -rte_mtr_error_set(error, ENOTSUP,
1313 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
1314 NULL, "Failed to create devx meter.");
1318 mlx5_flow_meter_params_flush(struct rte_eth_dev *dev,
1319 struct mlx5_flow_meter_info *fm,
1322 struct mlx5_priv *priv = dev->data->dev_private;
1323 struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
1324 struct mlx5_flow_meter_profile *fmp;
1325 struct mlx5_legacy_flow_meter *legacy_fm = NULL;
1326 struct mlx5_flow_meter_policy *mtr_policy;
1328 /* Meter object must not have any owner. */
1329 MLX5_ASSERT(!fm->ref_cnt);
1330 /* Get meter profile. */
1334 /* Update dependencies. */
1335 __atomic_sub_fetch(&fmp->ref_cnt, 1, __ATOMIC_RELAXED);
1337 /* Remove from list. */
1338 if (!priv->sh->meter_aso_en) {
1339 legacy_fm = container_of(fm,
1340 struct mlx5_legacy_flow_meter, fm);
1341 TAILQ_REMOVE(fms, legacy_fm, next);
1343 /* Free drop counters. */
1345 mlx5_counter_free(dev, fm->drop_cnt);
1346 /* Free meter flow table. */
1347 if (fm->flow_ipool) {
1348 mlx5_ipool_destroy(fm->flow_ipool);
1351 mlx5_flow_destroy_mtr_tbls(dev, fm);
1353 __atomic_sub_fetch(&priv->sh->mtrmng->def_policy_ref_cnt,
1354 1, __ATOMIC_RELAXED);
1355 if (priv->sh->meter_aso_en) {
1356 if (!fm->def_policy) {
1357 mtr_policy = mlx5_flow_meter_policy_find(dev,
1358 fm->policy_id, NULL);
1360 __atomic_sub_fetch(&mtr_policy->ref_cnt,
1361 1, __ATOMIC_RELAXED);
1365 if (mlx5_l3t_clear_entry(priv->mtr_idx_tbl, fm->meter_id))
1367 mlx5_flow_mtr_free(dev, mtr_idx);
1369 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR],
1376 * Destroy meter rules.
1379 * Pointer to Ethernet device.
1380 * @param[in] meter_id
1383 * Pointer to rte meter error structure.
1386 * 0 on success, a negative errno value otherwise and rte_errno is set.
1389 mlx5_flow_meter_destroy(struct rte_eth_dev *dev, uint32_t meter_id,
1390 struct rte_mtr_error *error)
1392 struct mlx5_priv *priv = dev->data->dev_private;
1393 struct mlx5_flow_meter_info *fm;
1394 uint32_t mtr_idx = 0;
1397 return -rte_mtr_error_set(error, ENOTSUP,
1398 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
1400 "Meter is not supported");
1401 /* Meter object must exist. */
1402 fm = mlx5_flow_meter_find(priv, meter_id, &mtr_idx);
1404 return -rte_mtr_error_set(error, ENOENT,
1405 RTE_MTR_ERROR_TYPE_MTR_ID,
1407 "Meter object id not valid.");
1408 /* Meter object must not have any owner. */
1409 if (fm->ref_cnt > 0)
1410 return -rte_mtr_error_set(error, EBUSY,
1411 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
1413 "Meter object is being used.");
1414 /* Destroy the meter profile. */
1415 if (mlx5_flow_meter_params_flush(dev, fm, mtr_idx))
1416 return -rte_mtr_error_set(error, EINVAL,
1417 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
1419 "MTR object meter profile invalid.");
1424 * Modify meter state.
1427 * Pointer to mlx5 private data structure.
1429 * Pointer to flow meter.
1430 * @param[in] new_state
1431 * New state to update.
1433 * Pointer to rte meter error structure.
1436 * 0 on success, a negative errno value otherwise and rte_errno is set.
1439 mlx5_flow_meter_modify_state(struct mlx5_priv *priv,
1440 struct mlx5_flow_meter_info *fm,
1442 struct rte_mtr_error *error)
1444 static const struct mlx5_flow_meter_srtcm_rfc2697_prm srtcm = {
1445 .cbs_cir = RTE_BE32(MLX5_IFC_FLOW_METER_DISABLE_CBS_CIR_VAL),
1448 uint64_t modify_bits = MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS |
1449 MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR;
1452 if (new_state == MLX5_FLOW_METER_DISABLE)
1453 ret = mlx5_flow_meter_action_modify(priv, fm,
1454 &srtcm, modify_bits, 0, 0);
1456 ret = mlx5_flow_meter_action_modify(priv, fm,
1457 &fm->profile->srtcm_prm,
1460 return -rte_mtr_error_set(error, -ret,
1461 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
1464 "Failed to enable meter." :
1465 "Failed to disable meter.");
1470 * Callback to enable flow meter.
1473 * Pointer to Ethernet device.
1474 * @param[in] meter_id
1477 * Pointer to rte meter error structure.
1480 * 0 on success, a negative errno value otherwise and rte_errno is set.
1483 mlx5_flow_meter_enable(struct rte_eth_dev *dev,
1485 struct rte_mtr_error *error)
1487 struct mlx5_priv *priv = dev->data->dev_private;
1488 struct mlx5_flow_meter_info *fm;
1492 return -rte_mtr_error_set(error, ENOTSUP,
1493 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1494 "Meter is not supported");
1495 /* Meter object must exist. */
1496 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1498 return -rte_mtr_error_set(error, ENOENT,
1499 RTE_MTR_ERROR_TYPE_MTR_ID,
1500 NULL, "Meter not found.");
1501 if (fm->active_state == MLX5_FLOW_METER_ENABLE)
1503 ret = mlx5_flow_meter_modify_state(priv, fm, MLX5_FLOW_METER_ENABLE,
1506 fm->active_state = MLX5_FLOW_METER_ENABLE;
1511 * Callback to disable flow meter.
1514 * Pointer to Ethernet device.
1515 * @param[in] meter_id
1518 * Pointer to rte meter error structure.
1521 * 0 on success, a negative errno value otherwise and rte_errno is set.
1524 mlx5_flow_meter_disable(struct rte_eth_dev *dev,
1526 struct rte_mtr_error *error)
1528 struct mlx5_priv *priv = dev->data->dev_private;
1529 struct mlx5_flow_meter_info *fm;
1533 return -rte_mtr_error_set(error, ENOTSUP,
1534 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1535 "Meter is not supported");
1536 /* Meter object must exist. */
1537 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1539 return -rte_mtr_error_set(error, ENOENT,
1540 RTE_MTR_ERROR_TYPE_MTR_ID,
1541 NULL, "Meter not found.");
1542 if (fm->active_state == MLX5_FLOW_METER_DISABLE)
1544 ret = mlx5_flow_meter_modify_state(priv, fm, MLX5_FLOW_METER_DISABLE,
1547 fm->active_state = MLX5_FLOW_METER_DISABLE;
1552 * Callback to update meter profile.
1555 * Pointer to Ethernet device.
1556 * @param[in] meter_id
1558 * @param[in] meter_profile_id
1559 * To be updated meter profile id.
1561 * Pointer to rte meter error structure.
1564 * 0 on success, a negative errno value otherwise and rte_errno is set.
1567 mlx5_flow_meter_profile_update(struct rte_eth_dev *dev,
1569 uint32_t meter_profile_id,
1570 struct rte_mtr_error *error)
1572 struct mlx5_priv *priv = dev->data->dev_private;
1573 struct mlx5_flow_meter_profile *fmp;
1574 struct mlx5_flow_meter_profile *old_fmp;
1575 struct mlx5_flow_meter_info *fm;
1576 uint64_t modify_bits = MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS |
1577 MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR;
1581 return -rte_mtr_error_set(error, ENOTSUP,
1582 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1583 "Meter is not supported");
1584 /* Meter profile must exist. */
1585 fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id);
1587 return -rte_mtr_error_set(error, ENOENT,
1588 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
1589 NULL, "Meter profile not found.");
1590 /* Meter object must exist. */
1591 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1593 return -rte_mtr_error_set(error, ENOENT,
1594 RTE_MTR_ERROR_TYPE_MTR_ID,
1595 NULL, "Meter not found.");
1596 /* MTR object already set to meter profile id. */
1597 old_fmp = fm->profile;
1600 /* Update the profile. */
1602 /* Update meter params in HW (if not disabled). */
1603 if (fm->active_state == MLX5_FLOW_METER_DISABLE)
1605 ret = mlx5_flow_meter_action_modify(priv, fm, &fm->profile->srtcm_prm,
1606 modify_bits, fm->active_state, 1);
1608 fm->profile = old_fmp;
1609 return -rte_mtr_error_set(error, -ret,
1610 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
1611 NULL, "Failed to update meter"
1612 " parmeters in hardware.");
1620 * Callback to update meter stats mask.
1623 * Pointer to Ethernet device.
1624 * @param[in] meter_id
1626 * @param[in] stats_mask
1627 * To be updated stats_mask.
1629 * Pointer to rte meter error structure.
1632 * 0 on success, a negative errno value otherwise and rte_errno is set.
1635 mlx5_flow_meter_stats_update(struct rte_eth_dev *dev,
1637 uint64_t stats_mask,
1638 struct rte_mtr_error *error)
1640 struct mlx5_priv *priv = dev->data->dev_private;
1641 struct mlx5_flow_meter_info *fm;
1644 return -rte_mtr_error_set(error, ENOTSUP,
1645 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1646 "Meter is not supported");
1647 /* Meter object must exist. */
1648 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1650 return -rte_mtr_error_set(error, ENOENT,
1651 RTE_MTR_ERROR_TYPE_MTR_ID,
1652 NULL, "Meter object id not valid.");
1653 if (mlx5_flow_meter_stats_enable_update(dev, fm, stats_mask))
1654 return -rte_mtr_error_set(error, ENOENT,
1655 RTE_MTR_ERROR_TYPE_MTR_ID,
1656 NULL, "Fail to allocate "
1657 "counter for meter.");
1662 * Callback to read meter statistics.
1665 * Pointer to Ethernet device.
1666 * @param[in] meter_id
1669 * Pointer to store the statistics.
1670 * @param[out] stats_mask
1671 * Pointer to store the stats_mask.
1673 * Statistic to be cleared after read or not.
1675 * Pointer to rte meter error structure.
1678 * 0 on success, a negative errno value otherwise and rte_errno is set.
1681 mlx5_flow_meter_stats_read(struct rte_eth_dev *dev,
1683 struct rte_mtr_stats *stats,
1684 uint64_t *stats_mask,
1686 struct rte_mtr_error *error)
1688 struct mlx5_priv *priv = dev->data->dev_private;
1689 struct mlx5_flow_meter_info *fm;
1695 return -rte_mtr_error_set(error, ENOTSUP,
1696 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1697 "Meter is not supported");
1698 /* Meter object must exist. */
1699 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1701 return -rte_mtr_error_set(error, ENOENT,
1702 RTE_MTR_ERROR_TYPE_MTR_ID,
1703 NULL, "Meter object id not valid.");
1705 if (fm->bytes_dropped)
1706 *stats_mask |= RTE_MTR_STATS_N_BYTES_DROPPED;
1707 if (fm->pkts_dropped)
1708 *stats_mask |= RTE_MTR_STATS_N_PKTS_DROPPED;
1709 memset(stats, 0, sizeof(*stats));
1711 ret = mlx5_counter_query(dev, fm->drop_cnt, clear, &pkts,
1715 /* If need to read the packets, set it. */
1716 if (fm->pkts_dropped)
1717 stats->n_pkts_dropped = pkts;
1718 /* If need to read the bytes, set it. */
1719 if (fm->bytes_dropped)
1720 stats->n_bytes_dropped = bytes;
1724 return -rte_mtr_error_set(error, ret, RTE_MTR_ERROR_TYPE_STATS, NULL,
1725 "Failed to read meter drop counters.");
1728 static const struct rte_mtr_ops mlx5_flow_mtr_ops = {
1729 .capabilities_get = mlx5_flow_mtr_cap_get,
1730 .meter_profile_add = mlx5_flow_meter_profile_add,
1731 .meter_profile_delete = mlx5_flow_meter_profile_delete,
1732 .meter_policy_validate = mlx5_flow_meter_policy_validate,
1733 .meter_policy_add = mlx5_flow_meter_policy_add,
1734 .meter_policy_delete = mlx5_flow_meter_policy_delete,
1735 .create = mlx5_flow_meter_create,
1736 .destroy = mlx5_flow_meter_destroy,
1737 .meter_enable = mlx5_flow_meter_enable,
1738 .meter_disable = mlx5_flow_meter_disable,
1739 .meter_profile_update = mlx5_flow_meter_profile_update,
1740 .meter_dscp_table_update = NULL,
1741 .stats_update = mlx5_flow_meter_stats_update,
1742 .stats_read = mlx5_flow_meter_stats_read,
1746 * Get meter operations.
1749 * Pointer to Ethernet device structure.
1751 * Pointer to set the mtr operations.
1757 mlx5_flow_meter_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)
1759 *(const struct rte_mtr_ops **)arg = &mlx5_flow_mtr_ops;
1767 * Pointer to mlx5_priv.
1771 * Pointer to Meter index.
1774 * Pointer to the meter info found on success, NULL otherwise.
1776 struct mlx5_flow_meter_info *
1777 mlx5_flow_meter_find(struct mlx5_priv *priv, uint32_t meter_id,
1780 struct mlx5_legacy_flow_meter *legacy_fm;
1781 struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
1782 struct mlx5_aso_mtr *aso_mtr;
1783 struct mlx5_aso_mtr_pools_mng *pools_mng =
1784 &priv->sh->mtrmng->pools_mng;
1785 union mlx5_l3t_data data;
1787 if (priv->sh->meter_aso_en) {
1788 rte_spinlock_lock(&pools_mng->mtrsl);
1789 if (!pools_mng->n_valid || !priv->mtr_idx_tbl) {
1790 rte_spinlock_unlock(&pools_mng->mtrsl);
1793 if (mlx5_l3t_get_entry(priv->mtr_idx_tbl, meter_id, &data) ||
1795 rte_spinlock_unlock(&pools_mng->mtrsl);
1799 *mtr_idx = data.dword;
1800 aso_mtr = mlx5_aso_meter_by_idx(priv, data.dword);
1801 /* Remove reference taken by the mlx5_l3t_get_entry. */
1802 mlx5_l3t_clear_entry(priv->mtr_idx_tbl, meter_id);
1803 rte_spinlock_unlock(&pools_mng->mtrsl);
1804 if (!aso_mtr || aso_mtr->state == ASO_METER_FREE)
1806 return &aso_mtr->fm;
1808 TAILQ_FOREACH(legacy_fm, fms, next)
1809 if (meter_id == legacy_fm->fm.meter_id) {
1811 *mtr_idx = legacy_fm->idx;
1812 return &legacy_fm->fm;
1818 * Find meter by index.
1821 * Pointer to mlx5_priv.
1826 * Pointer to the meter info found on success, NULL otherwise.
1828 struct mlx5_flow_meter_info *
1829 flow_dv_meter_find_by_idx(struct mlx5_priv *priv, uint32_t idx)
1831 struct mlx5_aso_mtr *aso_mtr;
1833 if (priv->sh->meter_aso_en) {
1834 aso_mtr = mlx5_aso_meter_by_idx(priv, idx);
1837 return &aso_mtr->fm;
1839 return mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MTR], idx);
1844 * Attach meter to flow.
1845 * Unidirectional Meter creation can only be done
1846 * when flow direction is known, i.e. when calling meter_attach.
1849 * Pointer to mlx5 private data.
1851 * Pointer to flow meter.
1853 * Pointer to flow attributes.
1854 * @param [out] error
1855 * Pointer to error structure.
1858 * 0 on success, a negative errno value otherwise and rte_errno is set.
1861 mlx5_flow_meter_attach(struct mlx5_priv *priv,
1862 struct mlx5_flow_meter_info *fm,
1863 const struct rte_flow_attr *attr,
1864 struct rte_flow_error *error)
1868 if (priv->sh->meter_aso_en) {
1869 struct mlx5_aso_mtr *aso_mtr;
1871 aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
1872 if (mlx5_aso_mtr_wait(priv->sh, aso_mtr)) {
1873 return rte_flow_error_set(error, ENOENT,
1874 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1876 "Timeout in meter configuration");
1878 rte_spinlock_lock(&fm->sl);
1879 if (fm->shared || !fm->ref_cnt) {
1882 rte_flow_error_set(error, EINVAL,
1883 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1884 "Meter cannot be shared");
1887 rte_spinlock_unlock(&fm->sl);
1889 rte_spinlock_lock(&fm->sl);
1890 if (fm->meter_action) {
1892 attr->transfer == fm->transfer &&
1893 attr->ingress == fm->ingress &&
1894 attr->egress == fm->egress) {
1897 rte_flow_error_set(error, EINVAL,
1898 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1900 "Meter attr not match." :
1901 "Meter cannot be shared.");
1905 fm->ingress = attr->ingress;
1906 fm->egress = attr->egress;
1907 fm->transfer = attr->transfer;
1909 /* This also creates the meter object. */
1910 fm->meter_action = mlx5_flow_meter_action_create(priv,
1912 if (!fm->meter_action) {
1917 rte_flow_error_set(error, EINVAL,
1918 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1919 "Meter action create failed.");
1923 rte_spinlock_unlock(&fm->sl);
1925 return ret ? -rte_errno : 0;
1929 * Detach meter from flow.
1932 * Pointer to mlx5 private data.
1934 * Pointer to flow meter.
1937 mlx5_flow_meter_detach(struct mlx5_priv *priv,
1938 struct mlx5_flow_meter_info *fm)
1940 #ifdef HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER
1941 rte_spinlock_lock(&fm->sl);
1942 MLX5_ASSERT(fm->ref_cnt);
1943 if (--fm->ref_cnt == 0 && !priv->sh->meter_aso_en) {
1944 mlx5_glue->destroy_flow_action(fm->meter_action);
1945 fm->meter_action = NULL;
1950 rte_spinlock_unlock(&fm->sl);
1958 * Flush meter with Rx queue configuration.
1961 * Pointer to Ethernet device.
1964 mlx5_flow_meter_rxq_flush(struct rte_eth_dev *dev)
1966 struct mlx5_priv *priv = dev->data->dev_private;
1967 struct mlx5_flow_meter_sub_policy *sub_policy;
1968 struct mlx5_flow_meter_policy *mtr_policy;
1970 uint32_t i, policy_idx;
1974 if (priv->policy_idx_tbl) {
1975 MLX5_L3T_FOREACH(priv->policy_idx_tbl, i, entry) {
1976 policy_idx = *(uint32_t *)entry;
1977 sub_policy = mlx5_ipool_get
1978 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
1980 if (!sub_policy || !sub_policy->main_policy)
1982 mtr_policy = sub_policy->main_policy;
1983 if (mtr_policy->is_queue || mtr_policy->is_rss)
1984 mlx5_flow_destroy_sub_policy_with_rxq(dev,
1991 * Iterate a meter hierarchy and flush all meters and policies if possible.
1994 * Pointer to Ethernet device.
1996 * Pointer to flow meter.
1997 * @param[in] mtr_idx
2000 * Pointer to rte meter error structure.
2003 * 0 on success, a negative errno value otherwise and rte_errno is set.
2006 mlx5_flow_meter_flush_hierarchy(struct rte_eth_dev *dev,
2007 struct mlx5_flow_meter_info *fm,
2009 struct rte_mtr_error *error)
2011 struct mlx5_priv *priv = dev->data->dev_private;
2012 struct mlx5_flow_meter_policy *policy;
2014 struct mlx5_flow_meter_info *next_fm;
2015 uint32_t next_mtr_idx;
2016 struct mlx5_flow_meter_policy *next_policy = NULL;
2018 policy = mlx5_flow_meter_policy_find(dev, fm->policy_id, NULL);
2019 MLX5_ASSERT(policy);
2020 while (!fm->ref_cnt && policy->is_hierarchy) {
2021 policy_id = fm->policy_id;
2022 next_fm = mlx5_flow_meter_find(priv,
2023 policy->act_cnt[RTE_COLOR_GREEN].next_mtr_id,
2026 next_policy = mlx5_flow_meter_policy_find(dev,
2029 MLX5_ASSERT(next_policy);
2031 if (mlx5_flow_meter_params_flush(dev, fm, mtr_idx))
2032 return -rte_mtr_error_set(error, ENOTSUP,
2033 RTE_MTR_ERROR_TYPE_MTR_ID,
2035 "Failed to flush meter.");
2036 if (policy->ref_cnt)
2038 if (__mlx5_flow_meter_policy_delete(dev, policy_id,
2039 policy, error, true))
2042 if (!next_fm || !next_policy)
2045 mtr_idx = next_mtr_idx;
2046 policy = next_policy;
2052 * Flush all the hierarchy meters and their policies.
2055 * Pointer to Ethernet device.
2057 * Pointer to rte meter error structure.
2060 * 0 on success, a negative errno value otherwise and rte_errno is set.
2063 mlx5_flow_meter_flush_all_hierarchies(struct rte_eth_dev *dev,
2064 struct rte_mtr_error *error)
2066 struct mlx5_priv *priv = dev->data->dev_private;
2067 struct mlx5_flow_meter_info *fm;
2068 struct mlx5_flow_meter_policy *policy;
2069 struct mlx5_flow_meter_sub_policy *sub_policy;
2070 struct mlx5_flow_meter_info *next_fm;
2071 struct mlx5_aso_mtr *aso_mtr;
2072 uint32_t mtr_idx = 0;
2073 uint32_t i, policy_idx;
2076 if (!priv->mtr_idx_tbl || !priv->policy_idx_tbl)
2078 MLX5_L3T_FOREACH(priv->mtr_idx_tbl, i, entry) {
2079 mtr_idx = *(uint32_t *)entry;
2082 aso_mtr = mlx5_aso_meter_by_idx(priv, mtr_idx);
2084 if (fm->ref_cnt || fm->def_policy)
2086 if (mlx5_flow_meter_flush_hierarchy(dev, fm, mtr_idx, error))
2089 MLX5_L3T_FOREACH(priv->policy_idx_tbl, i, entry) {
2090 policy_idx = *(uint32_t *)entry;
2091 sub_policy = mlx5_ipool_get
2092 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
2095 return -rte_mtr_error_set(error,
2097 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2098 NULL, "Meter policy invalid.");
2099 policy = sub_policy->main_policy;
2100 if (!policy || !policy->is_hierarchy || policy->ref_cnt)
2102 next_fm = mlx5_flow_meter_find(priv,
2103 policy->act_cnt[RTE_COLOR_GREEN].next_mtr_id,
2105 if (__mlx5_flow_meter_policy_delete(dev, i, policy,
2107 return -rte_mtr_error_set(error,
2109 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2110 NULL, "Meter policy invalid.");
2112 if (!next_fm || next_fm->ref_cnt || next_fm->def_policy)
2114 if (mlx5_flow_meter_flush_hierarchy(dev, next_fm,
2121 * Flush meter configuration.
2124 * Pointer to Ethernet device.
2126 * Pointer to rte meter error structure.
2129 * 0 on success, a negative errno value otherwise and rte_errno is set.
2132 mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error)
2134 struct mlx5_priv *priv = dev->data->dev_private;
2135 struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
2136 struct mlx5_flow_meter_profile *fmp;
2137 struct mlx5_legacy_flow_meter *legacy_fm;
2138 struct mlx5_flow_meter_info *fm;
2139 struct mlx5_flow_meter_sub_policy *sub_policy;
2141 uint32_t i, mtr_idx, policy_idx;
2143 struct mlx5_aso_mtr *aso_mtr;
2147 if (priv->sh->meter_aso_en) {
2148 if (mlx5_flow_meter_flush_all_hierarchies(dev, error))
2150 if (priv->mtr_idx_tbl) {
2151 MLX5_L3T_FOREACH(priv->mtr_idx_tbl, i, entry) {
2152 mtr_idx = *(uint32_t *)entry;
2155 mlx5_aso_meter_by_idx(priv, mtr_idx);
2157 (void)mlx5_flow_meter_params_flush(dev,
2161 mlx5_l3t_destroy(priv->mtr_idx_tbl);
2162 priv->mtr_idx_tbl = NULL;
2165 TAILQ_FOREACH_SAFE(legacy_fm, fms, next, tmp) {
2166 fm = &legacy_fm->fm;
2167 if (mlx5_flow_meter_params_flush(dev, fm, 0))
2168 return -rte_mtr_error_set(error, EINVAL,
2169 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
2170 NULL, "MTR object meter profile invalid.");
2173 if (priv->policy_idx_tbl) {
2174 MLX5_L3T_FOREACH(priv->policy_idx_tbl, i, entry) {
2175 policy_idx = *(uint32_t *)entry;
2176 sub_policy = mlx5_ipool_get
2177 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
2180 return -rte_mtr_error_set(error,
2182 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2184 "meter policy invalid.");
2185 if (__mlx5_flow_meter_policy_delete(dev, i,
2186 sub_policy->main_policy,
2188 return -rte_mtr_error_set(error,
2190 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2192 "meter policy invalid.");
2193 mlx5_free(sub_policy->main_policy);
2195 mlx5_l3t_destroy(priv->policy_idx_tbl);
2196 priv->policy_idx_tbl = NULL;
2198 if (priv->mtr_profile_tbl) {
2199 MLX5_L3T_FOREACH(priv->mtr_profile_tbl, i, entry) {
2201 if (mlx5_flow_meter_profile_delete(dev, fmp->id,
2203 return -rte_mtr_error_set(error, EINVAL,
2204 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2205 NULL, "Fail to destroy "
2208 mlx5_l3t_destroy(priv->mtr_profile_tbl);
2209 priv->mtr_profile_tbl = NULL;
2211 /* Delete default policy table. */
2212 mlx5_flow_destroy_def_policy(dev);
2213 if (priv->sh->refcnt == 1)
2214 mlx5_flow_destroy_mtr_drop_tbls(dev);