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 /* Special case xir == 0 ? both exp and mantissa are 0. */
260 for (m = 0; m <= 0xFF; m++) { /* man width 8 bit */
261 for (e = 0; e <= 0x1F; e++) { /* exp width 5bit */
262 _xir = (1000000000ULL * m) >> e;
263 if (llabs(xir - _xir) <= delta) {
264 delta = llabs(xir - _xir);
275 * Calculate mantissa and exponent for xbs.
278 * Value to be calculated.
280 * Pointer to the mantissa.
282 * Pointer to the exp.
285 mlx5_flow_meter_xbs_man_exp_calc(uint64_t xbs, uint8_t *man, uint8_t *exp)
290 /* Special case xbs == 0 ? both exp and mantissa are 0. */
296 /* xbs = xbs_mantissa * 2^xbs_exponent */
297 _man = frexp(xbs, &_exp);
298 if (_exp >= MLX5_MAN_WIDTH) {
299 _man = _man * pow(2, MLX5_MAN_WIDTH);
300 _exp = _exp - MLX5_MAN_WIDTH;
302 *man = (uint8_t)ceil(_man);
307 * Fill the prm meter parameter.
310 * Pointer to meter profile to be converted.
312 * Pointer to the error structure.
315 * 0 on success, a negative errno value otherwise and rte_errno is set.
318 mlx5_flow_meter_param_fill(struct mlx5_flow_meter_profile *fmp,
319 struct rte_mtr_error *error)
321 struct mlx5_flow_meter_srtcm_rfc2697_prm *srtcm = &fmp->srtcm_prm;
323 uint32_t cbs_exp, cbs_man, cir_exp, cir_man;
324 uint32_t eir_exp, eir_man, ebs_exp, ebs_man;
325 uint64_t cir, cbs, eir, ebs;
327 switch (fmp->profile.alg) {
328 case RTE_MTR_SRTCM_RFC2697:
329 cir = fmp->profile.srtcm_rfc2697.cir;
330 cbs = fmp->profile.srtcm_rfc2697.cbs;
332 ebs = fmp->profile.srtcm_rfc2697.ebs;
334 case RTE_MTR_TRTCM_RFC2698:
335 MLX5_ASSERT(fmp->profile.trtcm_rfc2698.pir >
336 fmp->profile.trtcm_rfc2698.cir &&
337 fmp->profile.trtcm_rfc2698.pbs >
338 fmp->profile.trtcm_rfc2698.cbs);
339 cir = fmp->profile.trtcm_rfc2698.cir;
340 cbs = fmp->profile.trtcm_rfc2698.cbs;
341 /* EIR / EBS are filled with PIR / PBS. */
342 eir = fmp->profile.trtcm_rfc2698.pir;
343 ebs = fmp->profile.trtcm_rfc2698.pbs;
345 case RTE_MTR_TRTCM_RFC4115:
346 cir = fmp->profile.trtcm_rfc4115.cir;
347 cbs = fmp->profile.trtcm_rfc4115.cbs;
348 eir = fmp->profile.trtcm_rfc4115.eir;
349 ebs = fmp->profile.trtcm_rfc4115.ebs;
352 return -rte_mtr_error_set(error, EINVAL,
353 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
354 "Metering algorithm mode is invalid");
356 /* Adjust the values for PPS mode. */
357 if (fmp->profile.packet_mode) {
358 cir <<= MLX5_MTRS_PPS_MAP_BPS_SHIFT;
359 cbs <<= MLX5_MTRS_PPS_MAP_BPS_SHIFT;
360 eir <<= MLX5_MTRS_PPS_MAP_BPS_SHIFT;
361 ebs <<= MLX5_MTRS_PPS_MAP_BPS_SHIFT;
363 /* cir = 8G * cir_mantissa * 1/(2^cir_exponent)) Bytes/Sec */
364 mlx5_flow_meter_xir_man_exp_calc(cir, &man, &exp);
365 /* Check if cir mantissa is too large. */
366 if (exp > ASO_DSEG_XIR_EXP_MASK)
367 return -rte_mtr_error_set(error, ENOTSUP,
368 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
369 "meter profile parameter cir is not supported.");
372 /* cbs = cbs_mantissa * 2^cbs_exponent */
373 mlx5_flow_meter_xbs_man_exp_calc(cbs, &man, &exp);
374 /* Check if cbs mantissa is too large. */
375 if (exp > ASO_DSEG_EXP_MASK)
376 return -rte_mtr_error_set(error, ENOTSUP,
377 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
378 "meter profile parameter cbs is not supported.");
381 srtcm->cbs_cir = rte_cpu_to_be_32(cbs_exp << ASO_DSEG_CBS_EXP_OFFSET |
382 cbs_man << ASO_DSEG_CBS_MAN_OFFSET |
383 cir_exp << ASO_DSEG_XIR_EXP_OFFSET |
385 mlx5_flow_meter_xir_man_exp_calc(eir, &man, &exp);
386 /* Check if eir mantissa is too large. */
387 if (exp > ASO_DSEG_XIR_EXP_MASK)
388 return -rte_mtr_error_set(error, ENOTSUP,
389 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
390 "meter profile parameter eir is not supported.");
393 mlx5_flow_meter_xbs_man_exp_calc(ebs, &man, &exp);
394 /* Check if ebs mantissa is too large. */
395 if (exp > ASO_DSEG_EXP_MASK)
396 return -rte_mtr_error_set(error, ENOTSUP,
397 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
398 "meter profile parameter ebs is not supported.");
401 srtcm->ebs_eir = rte_cpu_to_be_32(ebs_exp << ASO_DSEG_EBS_EXP_OFFSET |
402 ebs_man << ASO_DSEG_EBS_MAN_OFFSET |
403 eir_exp << ASO_DSEG_XIR_EXP_OFFSET |
413 * Callback to get MTR capabilities.
416 * Pointer to Ethernet device.
418 * Pointer to save MTR capabilities.
420 * Pointer to the error structure.
423 * 0 on success, a negative errno value otherwise and rte_errno is set.
426 mlx5_flow_mtr_cap_get(struct rte_eth_dev *dev,
427 struct rte_mtr_capabilities *cap,
428 struct rte_mtr_error *error __rte_unused)
430 struct mlx5_priv *priv = dev->data->dev_private;
431 struct mlx5_hca_qos_attr *qattr = &priv->config.hca_attr.qos;
434 return -rte_mtr_error_set(error, ENOTSUP,
435 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
436 "Meter is not supported");
437 memset(cap, 0, sizeof(*cap));
438 if (priv->sh->meter_aso_en) {
439 /* 2 meters per one ASO cache line. */
440 cap->n_max = 1 << (qattr->log_max_num_meter_aso + 1);
441 cap->srtcm_rfc2697_packet_mode_supported = 1;
443 cap->n_max = 1 << qattr->log_max_flow_meter;
444 cap->srtcm_rfc2697_packet_mode_supported = 0;
446 cap->srtcm_rfc2697_byte_mode_supported = 1;
447 cap->n_shared_max = cap->n_max;
449 cap->shared_identical = 1;
450 cap->shared_n_flows_per_mtr_max = 4 << 20;
451 /* 2M flows can share the same meter. */
452 cap->chaining_n_mtrs_per_flow_max = 1; /* Chaining is not supported. */
453 cap->meter_srtcm_rfc2697_n_max = qattr->flow_meter_old ? cap->n_max : 0;
454 cap->meter_rate_max = 1ULL << 40; /* 1 Tera tokens per sec. */
455 cap->stats_mask = RTE_MTR_STATS_N_BYTES_DROPPED |
456 RTE_MTR_STATS_N_PKTS_DROPPED;
461 * Callback to add MTR profile.
464 * Pointer to Ethernet device.
465 * @param[in] meter_profile_id
468 * Pointer to meter profile detail.
470 * Pointer to the error structure.
473 * 0 on success, a negative errno value otherwise and rte_errno is set.
476 mlx5_flow_meter_profile_add(struct rte_eth_dev *dev,
477 uint32_t meter_profile_id,
478 struct rte_mtr_meter_profile *profile,
479 struct rte_mtr_error *error)
481 struct mlx5_priv *priv = dev->data->dev_private;
482 struct mlx5_flow_meter_profile *fmp;
483 union mlx5_l3t_data data;
487 return -rte_mtr_error_set(error, ENOTSUP,
488 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
489 "Meter is not supported");
490 /* Check input params. */
491 ret = mlx5_flow_meter_profile_validate(dev, meter_profile_id,
495 /* Meter profile memory allocation. */
496 fmp = mlx5_malloc(MLX5_MEM_ZERO, sizeof(struct mlx5_flow_meter_profile),
497 RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
499 return -rte_mtr_error_set(error, ENOMEM,
500 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
501 NULL, "Meter profile memory "
503 /* Fill profile info. */
504 fmp->id = meter_profile_id;
505 fmp->profile = *profile;
506 /* Fill the flow meter parameters for the PRM. */
507 ret = mlx5_flow_meter_param_fill(fmp, error);
511 ret = mlx5_l3t_set_entry(priv->mtr_profile_tbl,
512 meter_profile_id, &data);
514 return -rte_mtr_error_set(error, ENOTSUP,
515 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
516 NULL, "Meter profile insert fail.");
524 * Callback to delete MTR profile.
527 * Pointer to Ethernet device.
528 * @param[in] meter_profile_id
531 * Pointer to the error structure.
534 * 0 on success, a negative errno value otherwise and rte_errno is set.
537 mlx5_flow_meter_profile_delete(struct rte_eth_dev *dev,
538 uint32_t meter_profile_id,
539 struct rte_mtr_error *error)
541 struct mlx5_priv *priv = dev->data->dev_private;
542 struct mlx5_flow_meter_profile *fmp;
545 return -rte_mtr_error_set(error, ENOTSUP,
546 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
547 "Meter is not supported");
548 /* Meter profile must exist. */
549 fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id);
551 return -rte_mtr_error_set(error, ENOENT,
552 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
554 "Meter profile id is invalid.");
555 /* Check profile is unused. */
557 return -rte_mtr_error_set(error, EBUSY,
558 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
559 NULL, "Meter profile is in use.");
560 if (mlx5_l3t_clear_entry(priv->mtr_profile_tbl, meter_profile_id))
561 return -rte_mtr_error_set(error, EBUSY,
562 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
563 NULL, "Meter profile remove fail.");
572 * Pointer to Ethernet device.
577 * Pointer to the policy found on success, NULL otherwise.
579 struct mlx5_flow_meter_policy *
580 mlx5_flow_meter_policy_find(struct rte_eth_dev *dev,
582 uint32_t *policy_idx)
584 struct mlx5_priv *priv = dev->data->dev_private;
585 struct mlx5_flow_meter_sub_policy *sub_policy = NULL;
586 union mlx5_l3t_data data;
588 if (policy_id > MLX5_MAX_SUB_POLICY_TBL_NUM || !priv->policy_idx_tbl)
590 if (mlx5_l3t_get_entry(priv->policy_idx_tbl, policy_id, &data) ||
594 *policy_idx = data.dword;
595 sub_policy = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
597 /* Remove reference taken by the mlx5_l3t_get_entry. */
598 mlx5_l3t_clear_entry(priv->policy_idx_tbl, policy_id);
600 if (sub_policy->main_policy_id)
601 return sub_policy->main_policy;
606 * Get the last meter's policy from one meter's policy in hierarchy.
609 * Pointer to Ethernet device.
611 * Pointer to flow meter policy.
614 * Pointer to the final meter's policy, or NULL when fail.
616 struct mlx5_flow_meter_policy *
617 mlx5_flow_meter_hierarchy_get_final_policy(struct rte_eth_dev *dev,
618 struct mlx5_flow_meter_policy *policy)
620 struct mlx5_priv *priv = dev->data->dev_private;
621 struct mlx5_flow_meter_info *next_fm;
622 struct mlx5_flow_meter_policy *next_policy = policy;
624 while (next_policy->is_hierarchy) {
625 next_fm = mlx5_flow_meter_find(priv,
626 next_policy->act_cnt[RTE_COLOR_GREEN].next_mtr_id, NULL);
627 if (!next_fm || next_fm->def_policy)
629 next_policy = mlx5_flow_meter_policy_find(dev,
630 next_fm->policy_id, NULL);
631 MLX5_ASSERT(next_policy);
637 * Callback to check MTR policy action validate
640 * Pointer to Ethernet device.
642 * Pointer to meter policy action detail.
644 * Pointer to the error structure.
647 * 0 on success, a negative errno value otherwise and rte_errno is set.
650 mlx5_flow_meter_policy_validate(struct rte_eth_dev *dev,
651 struct rte_mtr_meter_policy_params *policy,
652 struct rte_mtr_error *error)
654 struct mlx5_priv *priv = dev->data->dev_private;
655 struct rte_flow_attr attr = { .transfer =
656 priv->config.dv_esw_en ? 1 : 0};
659 uint8_t domain_bitmap;
662 if (!priv->mtr_en || !priv->sh->meter_aso_en)
663 return -rte_mtr_error_set(error, ENOTSUP,
664 RTE_MTR_ERROR_TYPE_METER_POLICY,
665 NULL, "meter policy unsupported.");
666 ret = mlx5_flow_validate_mtr_acts(dev, policy->actions, &attr,
667 &is_rss, &domain_bitmap, &policy_mode, error);
674 __mlx5_flow_meter_policy_delete(struct rte_eth_dev *dev,
676 struct mlx5_flow_meter_policy *mtr_policy,
677 struct rte_mtr_error *error,
680 struct mlx5_priv *priv = dev->data->dev_private;
681 struct mlx5_flow_meter_sub_policy *sub_policy;
683 uint16_t sub_policy_num;
685 rte_spinlock_lock(&mtr_policy->sl);
686 if (mtr_policy->ref_cnt) {
687 rte_spinlock_unlock(&mtr_policy->sl);
688 return -rte_mtr_error_set(error, EBUSY,
689 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
691 "Meter policy object is being used.");
693 mlx5_flow_destroy_policy_rules(dev, mtr_policy);
694 mlx5_flow_destroy_mtr_acts(dev, mtr_policy);
695 for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
696 sub_policy_num = (mtr_policy->sub_policy_num >>
697 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i)) &
698 MLX5_MTR_SUB_POLICY_NUM_MASK;
699 if (sub_policy_num) {
700 for (j = 0; j < sub_policy_num; j++) {
701 sub_policy = mtr_policy->sub_policys[i][j];
704 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
709 if (priv->policy_idx_tbl && clear_l3t) {
710 if (mlx5_l3t_clear_entry(priv->policy_idx_tbl, policy_id)) {
711 rte_spinlock_unlock(&mtr_policy->sl);
712 return -rte_mtr_error_set(error, ENOTSUP,
713 RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL,
714 "Fail to delete policy in index table.");
717 rte_spinlock_unlock(&mtr_policy->sl);
722 * Callback to add MTR policy.
725 * Pointer to Ethernet device.
726 * @param[out] policy_id
727 * Pointer to policy id
729 * Pointer to meter policy action detail.
731 * Pointer to the error structure.
734 * 0 on success, a negative errno value otherwise and rte_errno is set.
737 mlx5_flow_meter_policy_add(struct rte_eth_dev *dev,
739 struct rte_mtr_meter_policy_params *policy,
740 struct rte_mtr_error *error)
742 struct mlx5_priv *priv = dev->data->dev_private;
743 struct rte_flow_attr attr = { .transfer =
744 priv->config.dv_esw_en ? 1 : 0};
745 uint32_t sub_policy_idx = 0;
746 uint32_t policy_idx = 0;
747 struct mlx5_flow_meter_policy *mtr_policy = NULL;
748 struct mlx5_flow_meter_sub_policy *sub_policy;
753 uint32_t policy_size = sizeof(struct mlx5_flow_meter_policy);
754 uint16_t sub_policy_num;
755 uint8_t domain_bitmap = 0;
756 union mlx5_l3t_data data;
757 bool skip_rule = false;
760 return -rte_mtr_error_set(error, ENOTSUP,
761 RTE_MTR_ERROR_TYPE_METER_POLICY,
762 NULL, "meter policy unsupported. ");
763 if (policy_id == MLX5_INVALID_POLICY_ID)
764 return -rte_mtr_error_set(error, ENOTSUP,
765 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
766 NULL, "policy ID is invalid. ");
767 if (policy_id == priv->sh->mtrmng->def_policy_id)
768 return -rte_mtr_error_set(error, EEXIST,
769 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
770 NULL, "default policy ID exists. ");
771 mtr_policy = mlx5_flow_meter_policy_find(dev, policy_id, &policy_idx);
773 return -rte_mtr_error_set(error, EEXIST,
774 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
775 NULL, "policy ID exists. ");
776 ret = mlx5_flow_validate_mtr_acts(dev, policy->actions, &attr,
777 &is_rss, &domain_bitmap,
778 &policy_mode, error);
782 return -rte_mtr_error_set(error, ENOTSUP,
783 RTE_MTR_ERROR_TYPE_METER_POLICY,
784 NULL, "fail to find policy domain.");
785 if (policy_mode == MLX5_MTR_POLICY_MODE_DEF) {
786 if (priv->sh->mtrmng->def_policy_id != MLX5_INVALID_POLICY_ID)
787 return -rte_mtr_error_set(error, EEXIST,
788 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
789 NULL, "a policy with similar actions "
790 "is already configured");
791 if (mlx5_flow_create_def_policy(dev))
792 return -rte_mtr_error_set(error, ENOTSUP,
793 RTE_MTR_ERROR_TYPE_METER_POLICY,
795 "fail to create non-terminated policy.");
796 priv->sh->mtrmng->def_policy_id = policy_id;
799 if (!priv->sh->meter_aso_en)
800 return -rte_mtr_error_set(error, ENOTSUP,
801 RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
802 "no ASO capability to support the policy ");
803 for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
804 if (!(domain_bitmap & (1 << i)))
807 * If RSS is found, it means that only the ingress domain can
808 * be supported. It is invalid to support RSS for one color
809 * and egress / transfer domain actions for another. Drop and
810 * jump action should have no impact.
814 sizeof(struct mlx5_flow_meter_sub_policy *) *
815 MLX5_MTR_RSS_MAX_SUB_POLICY;
818 policy_size += sizeof(struct mlx5_flow_meter_sub_policy *);
820 mtr_policy = mlx5_malloc(MLX5_MEM_ZERO, policy_size,
821 RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
823 return -rte_mtr_error_set(error, ENOMEM,
824 RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
825 "Memory alloc failed for meter policy.");
826 if (policy_mode == MLX5_MTR_POLICY_MODE_OG)
827 mtr_policy->skip_y = 1;
828 else if (policy_mode == MLX5_MTR_POLICY_MODE_OY)
829 mtr_policy->skip_g = 1;
830 policy_size = sizeof(struct mlx5_flow_meter_policy);
831 for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
832 if (!(domain_bitmap & (1 << i)))
834 if (i == MLX5_MTR_DOMAIN_INGRESS)
835 mtr_policy->ingress = 1;
836 if (i == MLX5_MTR_DOMAIN_EGRESS)
837 mtr_policy->egress = 1;
838 if (i == MLX5_MTR_DOMAIN_TRANSFER)
839 mtr_policy->transfer = 1;
840 sub_policy = mlx5_ipool_zmalloc
841 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
844 sub_policy_idx > MLX5_MAX_SUB_POLICY_TBL_NUM)
846 sub_policy->idx = sub_policy_idx;
847 sub_policy->main_policy = mtr_policy;
849 policy_idx = sub_policy_idx;
850 sub_policy->main_policy_id = 1;
852 mtr_policy->sub_policys[i] =
853 (struct mlx5_flow_meter_sub_policy **)
854 ((uint8_t *)mtr_policy + policy_size);
855 mtr_policy->sub_policys[i][0] = sub_policy;
856 sub_policy_num = (mtr_policy->sub_policy_num >>
857 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i)) &
858 MLX5_MTR_SUB_POLICY_NUM_MASK;
860 mtr_policy->sub_policy_num &= ~(MLX5_MTR_SUB_POLICY_NUM_MASK <<
861 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i));
862 mtr_policy->sub_policy_num |=
863 (sub_policy_num & MLX5_MTR_SUB_POLICY_NUM_MASK) <<
864 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i);
866 * If RSS is found, it means that only the ingress domain can
867 * be supported. It is invalid to support RSS for one color
868 * and egress / transfer domain actions for another. Drop and
869 * jump action should have no impact.
872 mtr_policy->is_rss = 1;
875 policy_size += sizeof(struct mlx5_flow_meter_sub_policy *);
877 rte_spinlock_init(&mtr_policy->sl);
878 ret = mlx5_flow_create_mtr_acts(dev, mtr_policy,
879 policy->actions, error);
882 if (mtr_policy->is_hierarchy) {
883 struct mlx5_flow_meter_policy *final_policy;
886 mlx5_flow_meter_hierarchy_get_final_policy(dev, mtr_policy);
889 skip_rule = (final_policy->is_rss || final_policy->is_queue);
892 * If either Green or Yellow has queue / RSS action, all the policy
893 * rules will be created later in the flow splitting stage.
895 if (!is_rss && !mtr_policy->is_queue && !skip_rule) {
896 /* Create policy rules in HW. */
897 ret = mlx5_flow_create_policy_rules(dev, mtr_policy);
901 data.dword = policy_idx;
902 if (!priv->policy_idx_tbl) {
903 priv->policy_idx_tbl = mlx5_l3t_create(MLX5_L3T_TYPE_DWORD);
904 if (!priv->policy_idx_tbl)
907 if (mlx5_l3t_set_entry(priv->policy_idx_tbl, policy_id, &data))
912 ret = __mlx5_flow_meter_policy_delete(dev, policy_id,
913 mtr_policy, error, false);
914 mlx5_free(mtr_policy);
918 return -rte_mtr_error_set(error, ENOTSUP,
919 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
920 NULL, "Failed to create devx policy.");
924 * Callback to delete MTR policy.
927 * Pointer to Ethernet device.
928 * @param[in] policy_id
931 * Pointer to the error structure.
934 * 0 on success, a negative errno value otherwise and rte_errno is set.
937 mlx5_flow_meter_policy_delete(struct rte_eth_dev *dev,
939 struct rte_mtr_error *error)
941 struct mlx5_priv *priv = dev->data->dev_private;
942 struct mlx5_flow_meter_policy *mtr_policy;
946 if (policy_id == priv->sh->mtrmng->def_policy_id) {
947 if (priv->sh->mtrmng->def_policy_ref_cnt > 0)
948 return -rte_mtr_error_set(error, ENOTSUP,
949 RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL,
950 "Meter policy object is being used.");
951 priv->sh->mtrmng->def_policy_id = MLX5_INVALID_POLICY_ID;
954 mtr_policy = mlx5_flow_meter_policy_find(dev, policy_id, &policy_idx);
956 return -rte_mtr_error_set(error, ENOTSUP,
957 RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL,
958 "Meter policy id is invalid. ");
959 ret = __mlx5_flow_meter_policy_delete(dev, policy_id, mtr_policy,
963 mlx5_free(mtr_policy);
968 * Check meter validation.
971 * Pointer to mlx5 private data structure.
972 * @param[in] meter_id
975 * Pointer to rte meter parameters.
977 * Pointer to rte meter error structure.
980 * 0 on success, a negative errno value otherwise and rte_errno is set.
983 mlx5_flow_meter_validate(struct mlx5_priv *priv, uint32_t meter_id,
984 struct rte_mtr_params *params,
985 struct rte_mtr_error *error)
987 /* Meter must use global drop action. */
988 if (!priv->sh->dr_drop_action)
989 return -rte_mtr_error_set(error, ENOTSUP,
990 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
992 "No drop action ready for meter.");
993 /* Meter params must not be NULL. */
995 return -rte_mtr_error_set(error, EINVAL,
996 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
997 NULL, "Meter object params null.");
998 /* Previous meter color is not supported. */
999 if (params->use_prev_mtr_color)
1000 return -rte_mtr_error_set(error, ENOTSUP,
1001 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
1003 "Previous meter color "
1005 if (params->meter_policy_id == MLX5_INVALID_POLICY_ID)
1006 return -rte_mtr_error_set(error, ENOENT,
1007 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
1008 NULL, "Meter policy id not valid.");
1009 /* Validate meter id. */
1010 if (mlx5_flow_meter_find(priv, meter_id, NULL))
1011 return -rte_mtr_error_set(error, EEXIST,
1012 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
1013 "Meter object already exists.");
1018 * Modify the flow meter action.
1021 * Pointer to mlx5 private data structure.
1023 * Pointer to flow meter to be modified.
1025 * Pointer to meter srtcm description parameter.
1026 * @param[in] modify_bits
1027 * The bit in srtcm to be updated.
1028 * @param[in] active_state
1029 * The state to be updated.
1031 * 0 on success, o negative value otherwise.
1034 mlx5_flow_meter_action_modify(struct mlx5_priv *priv,
1035 struct mlx5_flow_meter_info *fm,
1036 const struct mlx5_flow_meter_srtcm_rfc2697_prm *srtcm,
1037 uint64_t modify_bits, uint32_t active_state, uint32_t is_enable)
1039 #ifdef HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER
1040 uint32_t in[MLX5_ST_SZ_DW(flow_meter_parameters)] = { 0 };
1042 struct mlx5dv_dr_flow_meter_attr mod_attr = { 0 };
1044 struct mlx5_aso_mtr *aso_mtr = NULL;
1045 uint32_t cbs_cir, ebs_eir, val;
1047 if (priv->sh->meter_aso_en) {
1048 fm->is_enable = !!is_enable;
1049 aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
1050 ret = mlx5_aso_meter_update_by_wqe(priv->sh, aso_mtr);
1053 ret = mlx5_aso_mtr_wait(priv->sh, aso_mtr);
1057 /* Fill command parameters. */
1058 mod_attr.reg_c_index = priv->mtr_color_reg - REG_C_0;
1059 mod_attr.flow_meter_parameter = in;
1060 mod_attr.flow_meter_parameter_sz =
1061 MLX5_ST_SZ_BYTES(flow_meter_parameters);
1062 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_ACTIVE)
1063 mod_attr.active = !!active_state;
1065 mod_attr.active = 0;
1067 cbs_cir = rte_be_to_cpu_32(srtcm->cbs_cir);
1068 ebs_eir = rte_be_to_cpu_32(srtcm->ebs_eir);
1069 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS) {
1070 val = (cbs_cir >> ASO_DSEG_CBS_EXP_OFFSET) &
1072 MLX5_SET(flow_meter_parameters, attr,
1074 val = (cbs_cir >> ASO_DSEG_CBS_MAN_OFFSET) &
1076 MLX5_SET(flow_meter_parameters, attr,
1079 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR) {
1080 val = (cbs_cir >> ASO_DSEG_XIR_EXP_OFFSET) &
1082 MLX5_SET(flow_meter_parameters, attr,
1084 val = cbs_cir & ASO_DSEG_MAN_MASK;
1085 MLX5_SET(flow_meter_parameters, attr,
1088 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_EBS) {
1089 val = (ebs_eir >> ASO_DSEG_EBS_EXP_OFFSET) &
1091 MLX5_SET(flow_meter_parameters, attr,
1093 val = (ebs_eir >> ASO_DSEG_EBS_MAN_OFFSET) &
1095 MLX5_SET(flow_meter_parameters, attr,
1098 /* Apply modifications to meter only if it was created. */
1099 if (fm->meter_action) {
1100 ret = mlx5_glue->dv_modify_flow_action_meter
1101 (fm->meter_action, &mod_attr,
1102 rte_cpu_to_be_64(modify_bits));
1106 /* Update succeeded modify meter parameters. */
1107 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_ACTIVE)
1108 fm->active_state = !!active_state;
1123 mlx5_flow_meter_stats_enable_update(struct rte_eth_dev *dev,
1124 struct mlx5_flow_meter_info *fm,
1125 uint64_t stats_mask)
1128 (stats_mask & RTE_MTR_STATS_N_BYTES_DROPPED) ? 1 : 0;
1129 fm->pkts_dropped = (stats_mask & RTE_MTR_STATS_N_PKTS_DROPPED) ? 1 : 0;
1130 if (fm->bytes_dropped || fm->pkts_dropped) {
1131 if (!fm->drop_cnt) {
1132 /* Alloc policer counters. */
1133 fm->drop_cnt = mlx5_counter_alloc(dev);
1139 mlx5_counter_free(dev, fm->drop_cnt);
1147 * Create meter rules.
1150 * Pointer to Ethernet device.
1151 * @param[in] meter_id
1154 * Pointer to rte meter parameters.
1156 * Meter shared with other flow or not.
1158 * Pointer to rte meter error structure.
1161 * 0 on success, a negative errno value otherwise and rte_errno is set.
1164 mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,
1165 struct rte_mtr_params *params, int shared,
1166 struct rte_mtr_error *error)
1168 struct mlx5_priv *priv = dev->data->dev_private;
1169 struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
1170 struct mlx5_flow_meter_profile *fmp;
1171 struct mlx5_flow_meter_info *fm;
1172 /* GCC fails to infer legacy_fm is set when !priv->sh->meter_aso_en. */
1173 struct mlx5_legacy_flow_meter *legacy_fm = NULL;
1174 struct mlx5_flow_meter_policy *mtr_policy = NULL;
1175 struct mlx5_indexed_pool_config flow_ipool_cfg = {
1179 .type = "mlx5_flow_mtr_flow_id_pool",
1181 struct mlx5_aso_mtr *aso_mtr;
1182 uint32_t mtr_idx, policy_idx;
1183 union mlx5_l3t_data data;
1185 uint8_t domain_bitmap;
1186 uint8_t mtr_id_bits;
1187 uint8_t mtr_reg_bits = priv->mtr_reg_share ?
1188 MLX5_MTR_IDLE_BITS_IN_COLOR_REG : MLX5_REG_BITS;
1191 return -rte_mtr_error_set(error, ENOTSUP,
1192 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1193 "Meter is not supported");
1194 /* Validate the parameters. */
1195 ret = mlx5_flow_meter_validate(priv, meter_id, params, error);
1198 /* Meter profile must exist. */
1199 fmp = mlx5_flow_meter_profile_find(priv, params->meter_profile_id);
1201 return -rte_mtr_error_set(error, ENOENT,
1202 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
1203 NULL, "Meter profile id not valid.");
1204 /* Meter policy must exist. */
1205 if (params->meter_policy_id == priv->sh->mtrmng->def_policy_id) {
1207 (&priv->sh->mtrmng->def_policy_ref_cnt,
1208 1, __ATOMIC_RELAXED);
1209 domain_bitmap = MLX5_MTR_ALL_DOMAIN_BIT;
1210 if (!priv->config.dv_esw_en)
1211 domain_bitmap &= ~MLX5_MTR_DOMAIN_TRANSFER_BIT;
1213 if (!priv->sh->meter_aso_en)
1214 return -rte_mtr_error_set(error, ENOTSUP,
1215 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1216 "Part of the policies cannot be "
1217 "supported without ASO ");
1218 mtr_policy = mlx5_flow_meter_policy_find(dev,
1219 params->meter_policy_id, &policy_idx);
1221 return -rte_mtr_error_set(error, ENOENT,
1222 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
1223 NULL, "Meter policy id not valid.");
1224 domain_bitmap = (mtr_policy->ingress ?
1225 MLX5_MTR_DOMAIN_INGRESS_BIT : 0) |
1226 (mtr_policy->egress ?
1227 MLX5_MTR_DOMAIN_EGRESS_BIT : 0) |
1228 (mtr_policy->transfer ?
1229 MLX5_MTR_DOMAIN_TRANSFER_BIT : 0);
1230 if (fmp->g_support && mtr_policy->skip_g)
1231 return -rte_mtr_error_set(error, ENOTSUP,
1232 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
1233 NULL, "Meter green policy is empty.");
1234 if (fmp->y_support && mtr_policy->skip_y)
1235 return -rte_mtr_error_set(error, ENOTSUP,
1236 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
1237 NULL, "Meter yellow policy is empty.");
1239 /* Allocate the flow meter memory. */
1240 if (priv->sh->meter_aso_en) {
1241 mtr_idx = mlx5_flow_mtr_alloc(dev);
1243 return -rte_mtr_error_set(error, ENOMEM,
1244 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1245 "Memory alloc failed for meter.");
1246 aso_mtr = mlx5_aso_meter_by_idx(priv, mtr_idx);
1250 return -rte_mtr_error_set(error, ENOMEM,
1251 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1252 "Unsupported profile with yellow.");
1253 legacy_fm = mlx5_ipool_zmalloc
1254 (priv->sh->ipool[MLX5_IPOOL_MTR], &mtr_idx);
1255 if (legacy_fm == NULL)
1256 return -rte_mtr_error_set(error, ENOMEM,
1257 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1258 "Memory alloc failed for meter.");
1259 legacy_fm->idx = mtr_idx;
1260 fm = &legacy_fm->fm;
1262 mtr_id_bits = MLX5_REG_BITS - __builtin_clz(mtr_idx);
1263 if ((mtr_id_bits + priv->sh->mtrmng->max_mtr_flow_bits) >
1265 DRV_LOG(ERR, "Meter number exceeds max limit.");
1268 if (mtr_id_bits > priv->sh->mtrmng->max_mtr_bits)
1269 priv->sh->mtrmng->max_mtr_bits = mtr_id_bits;
1270 /* Fill the flow meter parameters. */
1271 fm->meter_id = meter_id;
1272 fm->policy_id = params->meter_policy_id;
1274 if (mlx5_flow_meter_stats_enable_update(dev, fm, params->stats_mask))
1276 if (mlx5_flow_create_mtr_tbls(dev, fm, mtr_idx, domain_bitmap))
1278 /* Add to the flow meter list. */
1279 if (!priv->sh->meter_aso_en) {
1280 MLX5_ASSERT(legacy_fm != NULL);
1281 TAILQ_INSERT_TAIL(fms, legacy_fm, next);
1283 /* Add to the flow meter list. */
1284 fm->active_state = 1; /* Config meter starts as active. */
1286 fm->shared = !!shared;
1287 __atomic_add_fetch(&fm->profile->ref_cnt, 1, __ATOMIC_RELAXED);
1288 if (params->meter_policy_id == priv->sh->mtrmng->def_policy_id) {
1290 fm->flow_ipool = mlx5_ipool_create(&flow_ipool_cfg);
1291 if (!fm->flow_ipool)
1294 rte_spinlock_init(&fm->sl);
1295 /* If ASO meter supported, update ASO flow meter by wqe. */
1296 if (priv->sh->meter_aso_en) {
1297 aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
1298 ret = mlx5_aso_meter_update_by_wqe(priv->sh, aso_mtr);
1301 if (!priv->mtr_idx_tbl) {
1303 mlx5_l3t_create(MLX5_L3T_TYPE_DWORD);
1304 if (!priv->mtr_idx_tbl)
1307 data.dword = mtr_idx;
1308 if (mlx5_l3t_set_entry(priv->mtr_idx_tbl, meter_id, &data))
1312 __atomic_add_fetch(&mtr_policy->ref_cnt, 1, __ATOMIC_RELAXED);
1315 mlx5_flow_destroy_mtr_tbls(dev, fm);
1316 /* Free policer counters. */
1318 mlx5_counter_free(dev, fm->drop_cnt);
1319 if (priv->sh->meter_aso_en)
1320 mlx5_flow_mtr_free(dev, mtr_idx);
1322 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR], mtr_idx);
1323 return -rte_mtr_error_set(error, ENOTSUP,
1324 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
1325 NULL, "Failed to create devx meter.");
1329 mlx5_flow_meter_params_flush(struct rte_eth_dev *dev,
1330 struct mlx5_flow_meter_info *fm,
1333 struct mlx5_priv *priv = dev->data->dev_private;
1334 struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
1335 struct mlx5_flow_meter_profile *fmp;
1336 struct mlx5_legacy_flow_meter *legacy_fm = NULL;
1337 struct mlx5_flow_meter_policy *mtr_policy;
1339 /* Meter object must not have any owner. */
1340 MLX5_ASSERT(!fm->ref_cnt);
1341 /* Get meter profile. */
1345 /* Update dependencies. */
1346 __atomic_sub_fetch(&fmp->ref_cnt, 1, __ATOMIC_RELAXED);
1348 /* Remove from list. */
1349 if (!priv->sh->meter_aso_en) {
1350 legacy_fm = container_of(fm,
1351 struct mlx5_legacy_flow_meter, fm);
1352 TAILQ_REMOVE(fms, legacy_fm, next);
1354 /* Free drop counters. */
1356 mlx5_counter_free(dev, fm->drop_cnt);
1357 /* Free meter flow table. */
1358 if (fm->flow_ipool) {
1359 mlx5_ipool_destroy(fm->flow_ipool);
1362 mlx5_flow_destroy_mtr_tbls(dev, fm);
1364 __atomic_sub_fetch(&priv->sh->mtrmng->def_policy_ref_cnt,
1365 1, __ATOMIC_RELAXED);
1366 if (priv->sh->meter_aso_en) {
1367 if (!fm->def_policy) {
1368 mtr_policy = mlx5_flow_meter_policy_find(dev,
1369 fm->policy_id, NULL);
1371 __atomic_sub_fetch(&mtr_policy->ref_cnt,
1372 1, __ATOMIC_RELAXED);
1376 if (mlx5_l3t_clear_entry(priv->mtr_idx_tbl, fm->meter_id))
1378 mlx5_flow_mtr_free(dev, mtr_idx);
1380 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR],
1387 * Destroy meter rules.
1390 * Pointer to Ethernet device.
1391 * @param[in] meter_id
1394 * Pointer to rte meter error structure.
1397 * 0 on success, a negative errno value otherwise and rte_errno is set.
1400 mlx5_flow_meter_destroy(struct rte_eth_dev *dev, uint32_t meter_id,
1401 struct rte_mtr_error *error)
1403 struct mlx5_priv *priv = dev->data->dev_private;
1404 struct mlx5_flow_meter_info *fm;
1405 uint32_t mtr_idx = 0;
1408 return -rte_mtr_error_set(error, ENOTSUP,
1409 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
1411 "Meter is not supported");
1412 /* Meter object must exist. */
1413 fm = mlx5_flow_meter_find(priv, meter_id, &mtr_idx);
1415 return -rte_mtr_error_set(error, ENOENT,
1416 RTE_MTR_ERROR_TYPE_MTR_ID,
1418 "Meter object id not valid.");
1419 /* Meter object must not have any owner. */
1420 if (fm->ref_cnt > 0)
1421 return -rte_mtr_error_set(error, EBUSY,
1422 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
1424 "Meter object is being used.");
1425 /* Destroy the meter profile. */
1426 if (mlx5_flow_meter_params_flush(dev, fm, mtr_idx))
1427 return -rte_mtr_error_set(error, EINVAL,
1428 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
1430 "MTR object meter profile invalid.");
1435 * Modify meter state.
1438 * Pointer to mlx5 private data structure.
1440 * Pointer to flow meter.
1441 * @param[in] new_state
1442 * New state to update.
1444 * Pointer to rte meter error structure.
1447 * 0 on success, a negative errno value otherwise and rte_errno is set.
1450 mlx5_flow_meter_modify_state(struct mlx5_priv *priv,
1451 struct mlx5_flow_meter_info *fm,
1453 struct rte_mtr_error *error)
1455 static const struct mlx5_flow_meter_srtcm_rfc2697_prm srtcm = {
1456 .cbs_cir = RTE_BE32(MLX5_IFC_FLOW_METER_DISABLE_CBS_CIR_VAL),
1459 uint64_t modify_bits = MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS |
1460 MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR;
1463 if (new_state == MLX5_FLOW_METER_DISABLE)
1464 ret = mlx5_flow_meter_action_modify(priv, fm,
1465 &srtcm, modify_bits, 0, 0);
1467 ret = mlx5_flow_meter_action_modify(priv, fm,
1468 &fm->profile->srtcm_prm,
1471 return -rte_mtr_error_set(error, -ret,
1472 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
1475 "Failed to enable meter." :
1476 "Failed to disable meter.");
1481 * Callback to enable flow meter.
1484 * Pointer to Ethernet device.
1485 * @param[in] meter_id
1488 * Pointer to rte meter error structure.
1491 * 0 on success, a negative errno value otherwise and rte_errno is set.
1494 mlx5_flow_meter_enable(struct rte_eth_dev *dev,
1496 struct rte_mtr_error *error)
1498 struct mlx5_priv *priv = dev->data->dev_private;
1499 struct mlx5_flow_meter_info *fm;
1503 return -rte_mtr_error_set(error, ENOTSUP,
1504 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1505 "Meter is not supported");
1506 /* Meter object must exist. */
1507 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1509 return -rte_mtr_error_set(error, ENOENT,
1510 RTE_MTR_ERROR_TYPE_MTR_ID,
1511 NULL, "Meter not found.");
1512 if (fm->active_state == MLX5_FLOW_METER_ENABLE)
1514 ret = mlx5_flow_meter_modify_state(priv, fm, MLX5_FLOW_METER_ENABLE,
1517 fm->active_state = MLX5_FLOW_METER_ENABLE;
1522 * Callback to disable flow meter.
1525 * Pointer to Ethernet device.
1526 * @param[in] meter_id
1529 * Pointer to rte meter error structure.
1532 * 0 on success, a negative errno value otherwise and rte_errno is set.
1535 mlx5_flow_meter_disable(struct rte_eth_dev *dev,
1537 struct rte_mtr_error *error)
1539 struct mlx5_priv *priv = dev->data->dev_private;
1540 struct mlx5_flow_meter_info *fm;
1544 return -rte_mtr_error_set(error, ENOTSUP,
1545 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1546 "Meter is not supported");
1547 /* Meter object must exist. */
1548 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1550 return -rte_mtr_error_set(error, ENOENT,
1551 RTE_MTR_ERROR_TYPE_MTR_ID,
1552 NULL, "Meter not found.");
1553 if (fm->active_state == MLX5_FLOW_METER_DISABLE)
1555 ret = mlx5_flow_meter_modify_state(priv, fm, MLX5_FLOW_METER_DISABLE,
1558 fm->active_state = MLX5_FLOW_METER_DISABLE;
1563 * Callback to update meter profile.
1566 * Pointer to Ethernet device.
1567 * @param[in] meter_id
1569 * @param[in] meter_profile_id
1570 * To be updated meter profile id.
1572 * Pointer to rte meter error structure.
1575 * 0 on success, a negative errno value otherwise and rte_errno is set.
1578 mlx5_flow_meter_profile_update(struct rte_eth_dev *dev,
1580 uint32_t meter_profile_id,
1581 struct rte_mtr_error *error)
1583 struct mlx5_priv *priv = dev->data->dev_private;
1584 struct mlx5_flow_meter_profile *fmp;
1585 struct mlx5_flow_meter_profile *old_fmp;
1586 struct mlx5_flow_meter_info *fm;
1587 uint64_t modify_bits = MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS |
1588 MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR;
1592 return -rte_mtr_error_set(error, ENOTSUP,
1593 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1594 "Meter is not supported");
1595 /* Meter profile must exist. */
1596 fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id);
1598 return -rte_mtr_error_set(error, ENOENT,
1599 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
1600 NULL, "Meter profile not found.");
1601 /* Meter object must exist. */
1602 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1604 return -rte_mtr_error_set(error, ENOENT,
1605 RTE_MTR_ERROR_TYPE_MTR_ID,
1606 NULL, "Meter not found.");
1607 /* MTR object already set to meter profile id. */
1608 old_fmp = fm->profile;
1611 /* Update the profile. */
1613 /* Update meter params in HW (if not disabled). */
1614 if (fm->active_state == MLX5_FLOW_METER_DISABLE)
1616 ret = mlx5_flow_meter_action_modify(priv, fm, &fm->profile->srtcm_prm,
1617 modify_bits, fm->active_state, 1);
1619 fm->profile = old_fmp;
1620 return -rte_mtr_error_set(error, -ret,
1621 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
1622 NULL, "Failed to update meter"
1623 " parameters in hardware.");
1631 * Callback to update meter stats mask.
1634 * Pointer to Ethernet device.
1635 * @param[in] meter_id
1637 * @param[in] stats_mask
1638 * To be updated stats_mask.
1640 * Pointer to rte meter error structure.
1643 * 0 on success, a negative errno value otherwise and rte_errno is set.
1646 mlx5_flow_meter_stats_update(struct rte_eth_dev *dev,
1648 uint64_t stats_mask,
1649 struct rte_mtr_error *error)
1651 struct mlx5_priv *priv = dev->data->dev_private;
1652 struct mlx5_flow_meter_info *fm;
1655 return -rte_mtr_error_set(error, ENOTSUP,
1656 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1657 "Meter is not supported");
1658 /* Meter object must exist. */
1659 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1661 return -rte_mtr_error_set(error, ENOENT,
1662 RTE_MTR_ERROR_TYPE_MTR_ID,
1663 NULL, "Meter object id not valid.");
1664 if (mlx5_flow_meter_stats_enable_update(dev, fm, stats_mask))
1665 return -rte_mtr_error_set(error, ENOENT,
1666 RTE_MTR_ERROR_TYPE_MTR_ID,
1667 NULL, "Fail to allocate "
1668 "counter for meter.");
1673 * Callback to read meter statistics.
1676 * Pointer to Ethernet device.
1677 * @param[in] meter_id
1680 * Pointer to store the statistics.
1681 * @param[out] stats_mask
1682 * Pointer to store the stats_mask.
1684 * Statistic to be cleared after read or not.
1686 * Pointer to rte meter error structure.
1689 * 0 on success, a negative errno value otherwise and rte_errno is set.
1692 mlx5_flow_meter_stats_read(struct rte_eth_dev *dev,
1694 struct rte_mtr_stats *stats,
1695 uint64_t *stats_mask,
1697 struct rte_mtr_error *error)
1699 struct mlx5_priv *priv = dev->data->dev_private;
1700 struct mlx5_flow_meter_info *fm;
1706 return -rte_mtr_error_set(error, ENOTSUP,
1707 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1708 "Meter is not supported");
1709 /* Meter object must exist. */
1710 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1712 return -rte_mtr_error_set(error, ENOENT,
1713 RTE_MTR_ERROR_TYPE_MTR_ID,
1714 NULL, "Meter object id not valid.");
1716 if (fm->bytes_dropped)
1717 *stats_mask |= RTE_MTR_STATS_N_BYTES_DROPPED;
1718 if (fm->pkts_dropped)
1719 *stats_mask |= RTE_MTR_STATS_N_PKTS_DROPPED;
1720 memset(stats, 0, sizeof(*stats));
1722 ret = mlx5_counter_query(dev, fm->drop_cnt, clear, &pkts,
1726 /* If need to read the packets, set it. */
1727 if (fm->pkts_dropped)
1728 stats->n_pkts_dropped = pkts;
1729 /* If need to read the bytes, set it. */
1730 if (fm->bytes_dropped)
1731 stats->n_bytes_dropped = bytes;
1735 return -rte_mtr_error_set(error, ret, RTE_MTR_ERROR_TYPE_STATS, NULL,
1736 "Failed to read meter drop counters.");
1739 static const struct rte_mtr_ops mlx5_flow_mtr_ops = {
1740 .capabilities_get = mlx5_flow_mtr_cap_get,
1741 .meter_profile_add = mlx5_flow_meter_profile_add,
1742 .meter_profile_delete = mlx5_flow_meter_profile_delete,
1743 .meter_policy_validate = mlx5_flow_meter_policy_validate,
1744 .meter_policy_add = mlx5_flow_meter_policy_add,
1745 .meter_policy_delete = mlx5_flow_meter_policy_delete,
1746 .create = mlx5_flow_meter_create,
1747 .destroy = mlx5_flow_meter_destroy,
1748 .meter_enable = mlx5_flow_meter_enable,
1749 .meter_disable = mlx5_flow_meter_disable,
1750 .meter_profile_update = mlx5_flow_meter_profile_update,
1751 .meter_dscp_table_update = NULL,
1752 .stats_update = mlx5_flow_meter_stats_update,
1753 .stats_read = mlx5_flow_meter_stats_read,
1757 * Get meter operations.
1760 * Pointer to Ethernet device structure.
1762 * Pointer to set the mtr operations.
1768 mlx5_flow_meter_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)
1770 *(const struct rte_mtr_ops **)arg = &mlx5_flow_mtr_ops;
1778 * Pointer to mlx5_priv.
1782 * Pointer to Meter index.
1785 * Pointer to the meter info found on success, NULL otherwise.
1787 struct mlx5_flow_meter_info *
1788 mlx5_flow_meter_find(struct mlx5_priv *priv, uint32_t meter_id,
1791 struct mlx5_legacy_flow_meter *legacy_fm;
1792 struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
1793 struct mlx5_aso_mtr *aso_mtr;
1794 struct mlx5_aso_mtr_pools_mng *pools_mng =
1795 &priv->sh->mtrmng->pools_mng;
1796 union mlx5_l3t_data data;
1799 if (priv->sh->meter_aso_en) {
1800 rte_rwlock_read_lock(&pools_mng->resize_mtrwl);
1801 n_valid = pools_mng->n_valid;
1802 rte_rwlock_read_unlock(&pools_mng->resize_mtrwl);
1803 if (!n_valid || !priv->mtr_idx_tbl ||
1804 (mlx5_l3t_get_entry(priv->mtr_idx_tbl, meter_id, &data) ||
1808 *mtr_idx = data.dword;
1809 aso_mtr = mlx5_aso_meter_by_idx(priv, data.dword);
1810 /* Remove reference taken by the mlx5_l3t_get_entry. */
1811 mlx5_l3t_clear_entry(priv->mtr_idx_tbl, meter_id);
1812 if (!aso_mtr || aso_mtr->state == ASO_METER_FREE)
1814 return &aso_mtr->fm;
1816 TAILQ_FOREACH(legacy_fm, fms, next)
1817 if (meter_id == legacy_fm->fm.meter_id) {
1819 *mtr_idx = legacy_fm->idx;
1820 return &legacy_fm->fm;
1826 * Find meter by index.
1829 * Pointer to mlx5_priv.
1834 * Pointer to the meter info found on success, NULL otherwise.
1836 struct mlx5_flow_meter_info *
1837 flow_dv_meter_find_by_idx(struct mlx5_priv *priv, uint32_t idx)
1839 struct mlx5_aso_mtr *aso_mtr;
1841 if (priv->sh->meter_aso_en) {
1842 aso_mtr = mlx5_aso_meter_by_idx(priv, idx);
1845 return &aso_mtr->fm;
1847 return mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MTR], idx);
1852 * Attach meter to flow.
1853 * Unidirectional Meter creation can only be done
1854 * when flow direction is known, i.e. when calling meter_attach.
1857 * Pointer to mlx5 private data.
1859 * Pointer to flow meter.
1861 * Pointer to flow attributes.
1862 * @param [out] error
1863 * Pointer to error structure.
1866 * 0 on success, a negative errno value otherwise and rte_errno is set.
1869 mlx5_flow_meter_attach(struct mlx5_priv *priv,
1870 struct mlx5_flow_meter_info *fm,
1871 const struct rte_flow_attr *attr,
1872 struct rte_flow_error *error)
1876 if (priv->sh->meter_aso_en) {
1877 struct mlx5_aso_mtr *aso_mtr;
1879 aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
1880 if (mlx5_aso_mtr_wait(priv->sh, aso_mtr)) {
1881 return rte_flow_error_set(error, ENOENT,
1882 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1884 "Timeout in meter configuration");
1886 rte_spinlock_lock(&fm->sl);
1887 if (fm->shared || !fm->ref_cnt) {
1890 rte_flow_error_set(error, EINVAL,
1891 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1892 "Meter cannot be shared");
1895 rte_spinlock_unlock(&fm->sl);
1897 rte_spinlock_lock(&fm->sl);
1898 if (fm->meter_action) {
1900 attr->transfer == fm->transfer &&
1901 attr->ingress == fm->ingress &&
1902 attr->egress == fm->egress) {
1905 rte_flow_error_set(error, EINVAL,
1906 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1908 "Meter attr not match." :
1909 "Meter cannot be shared.");
1913 fm->ingress = attr->ingress;
1914 fm->egress = attr->egress;
1915 fm->transfer = attr->transfer;
1917 /* This also creates the meter object. */
1918 fm->meter_action = mlx5_flow_meter_action_create(priv,
1920 if (!fm->meter_action) {
1925 rte_flow_error_set(error, EINVAL,
1926 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1927 "Meter action create failed.");
1931 rte_spinlock_unlock(&fm->sl);
1933 return ret ? -rte_errno : 0;
1937 * Detach meter from flow.
1940 * Pointer to mlx5 private data.
1942 * Pointer to flow meter.
1945 mlx5_flow_meter_detach(struct mlx5_priv *priv,
1946 struct mlx5_flow_meter_info *fm)
1948 #ifdef HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER
1949 rte_spinlock_lock(&fm->sl);
1950 MLX5_ASSERT(fm->ref_cnt);
1951 if (--fm->ref_cnt == 0 && !priv->sh->meter_aso_en) {
1952 mlx5_glue->destroy_flow_action(fm->meter_action);
1953 fm->meter_action = NULL;
1958 rte_spinlock_unlock(&fm->sl);
1966 * Flush meter with Rx queue configuration.
1969 * Pointer to Ethernet device.
1972 mlx5_flow_meter_rxq_flush(struct rte_eth_dev *dev)
1974 struct mlx5_priv *priv = dev->data->dev_private;
1975 struct mlx5_flow_meter_sub_policy *sub_policy;
1976 struct mlx5_flow_meter_policy *mtr_policy;
1978 uint32_t i, policy_idx;
1982 if (priv->policy_idx_tbl) {
1983 MLX5_L3T_FOREACH(priv->policy_idx_tbl, i, entry) {
1984 policy_idx = *(uint32_t *)entry;
1985 sub_policy = mlx5_ipool_get
1986 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
1988 if (!sub_policy || !sub_policy->main_policy)
1990 mtr_policy = sub_policy->main_policy;
1991 if (mtr_policy->is_queue || mtr_policy->is_rss)
1992 mlx5_flow_destroy_sub_policy_with_rxq(dev,
1999 * Iterate a meter hierarchy and flush all meters and policies if possible.
2002 * Pointer to Ethernet device.
2004 * Pointer to flow meter.
2005 * @param[in] mtr_idx
2008 * Pointer to rte meter error structure.
2011 * 0 on success, a negative errno value otherwise and rte_errno is set.
2014 mlx5_flow_meter_flush_hierarchy(struct rte_eth_dev *dev,
2015 struct mlx5_flow_meter_info *fm,
2017 struct rte_mtr_error *error)
2019 struct mlx5_priv *priv = dev->data->dev_private;
2020 struct mlx5_flow_meter_policy *policy;
2022 struct mlx5_flow_meter_info *next_fm;
2023 uint32_t next_mtr_idx;
2024 struct mlx5_flow_meter_policy *next_policy = NULL;
2026 policy = mlx5_flow_meter_policy_find(dev, fm->policy_id, NULL);
2027 MLX5_ASSERT(policy);
2028 while (!fm->ref_cnt && policy->is_hierarchy) {
2029 policy_id = fm->policy_id;
2030 next_fm = mlx5_flow_meter_find(priv,
2031 policy->act_cnt[RTE_COLOR_GREEN].next_mtr_id,
2034 next_policy = mlx5_flow_meter_policy_find(dev,
2037 MLX5_ASSERT(next_policy);
2039 if (mlx5_flow_meter_params_flush(dev, fm, mtr_idx))
2040 return -rte_mtr_error_set(error, ENOTSUP,
2041 RTE_MTR_ERROR_TYPE_MTR_ID,
2043 "Failed to flush meter.");
2044 if (policy->ref_cnt)
2046 if (__mlx5_flow_meter_policy_delete(dev, policy_id,
2047 policy, error, true))
2050 if (!next_fm || !next_policy)
2053 mtr_idx = next_mtr_idx;
2054 policy = next_policy;
2060 * Flush all the hierarchy meters and their policies.
2063 * Pointer to Ethernet device.
2065 * Pointer to rte meter error structure.
2068 * 0 on success, a negative errno value otherwise and rte_errno is set.
2071 mlx5_flow_meter_flush_all_hierarchies(struct rte_eth_dev *dev,
2072 struct rte_mtr_error *error)
2074 struct mlx5_priv *priv = dev->data->dev_private;
2075 struct mlx5_flow_meter_info *fm;
2076 struct mlx5_flow_meter_policy *policy;
2077 struct mlx5_flow_meter_sub_policy *sub_policy;
2078 struct mlx5_flow_meter_info *next_fm;
2079 struct mlx5_aso_mtr *aso_mtr;
2080 uint32_t mtr_idx = 0;
2081 uint32_t i, policy_idx;
2084 if (!priv->mtr_idx_tbl || !priv->policy_idx_tbl)
2086 MLX5_L3T_FOREACH(priv->mtr_idx_tbl, i, entry) {
2087 mtr_idx = *(uint32_t *)entry;
2090 aso_mtr = mlx5_aso_meter_by_idx(priv, mtr_idx);
2092 if (fm->ref_cnt || fm->def_policy)
2094 if (mlx5_flow_meter_flush_hierarchy(dev, fm, mtr_idx, error))
2097 MLX5_L3T_FOREACH(priv->policy_idx_tbl, i, entry) {
2098 policy_idx = *(uint32_t *)entry;
2099 sub_policy = mlx5_ipool_get
2100 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
2103 return -rte_mtr_error_set(error,
2105 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2106 NULL, "Meter policy invalid.");
2107 policy = sub_policy->main_policy;
2108 if (!policy || !policy->is_hierarchy || policy->ref_cnt)
2110 next_fm = mlx5_flow_meter_find(priv,
2111 policy->act_cnt[RTE_COLOR_GREEN].next_mtr_id,
2113 if (__mlx5_flow_meter_policy_delete(dev, i, policy,
2115 return -rte_mtr_error_set(error,
2117 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2118 NULL, "Meter policy invalid.");
2120 if (!next_fm || next_fm->ref_cnt || next_fm->def_policy)
2122 if (mlx5_flow_meter_flush_hierarchy(dev, next_fm,
2129 * Flush meter configuration.
2132 * Pointer to Ethernet device.
2134 * Pointer to rte meter error structure.
2137 * 0 on success, a negative errno value otherwise and rte_errno is set.
2140 mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error)
2142 struct mlx5_priv *priv = dev->data->dev_private;
2143 struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
2144 struct mlx5_flow_meter_profile *fmp;
2145 struct mlx5_legacy_flow_meter *legacy_fm;
2146 struct mlx5_flow_meter_info *fm;
2147 struct mlx5_flow_meter_sub_policy *sub_policy;
2149 uint32_t i, mtr_idx, policy_idx;
2151 struct mlx5_aso_mtr *aso_mtr;
2155 if (priv->sh->meter_aso_en) {
2156 if (mlx5_flow_meter_flush_all_hierarchies(dev, error))
2158 if (priv->mtr_idx_tbl) {
2159 MLX5_L3T_FOREACH(priv->mtr_idx_tbl, i, entry) {
2160 mtr_idx = *(uint32_t *)entry;
2163 mlx5_aso_meter_by_idx(priv, mtr_idx);
2165 (void)mlx5_flow_meter_params_flush(dev,
2169 mlx5_l3t_destroy(priv->mtr_idx_tbl);
2170 priv->mtr_idx_tbl = NULL;
2173 RTE_TAILQ_FOREACH_SAFE(legacy_fm, fms, next, tmp) {
2174 fm = &legacy_fm->fm;
2175 if (mlx5_flow_meter_params_flush(dev, fm, 0))
2176 return -rte_mtr_error_set(error, EINVAL,
2177 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
2178 NULL, "MTR object meter profile invalid.");
2181 if (priv->policy_idx_tbl) {
2182 MLX5_L3T_FOREACH(priv->policy_idx_tbl, i, entry) {
2183 policy_idx = *(uint32_t *)entry;
2184 sub_policy = mlx5_ipool_get
2185 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
2188 return -rte_mtr_error_set(error,
2190 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2192 "meter policy invalid.");
2193 if (__mlx5_flow_meter_policy_delete(dev, i,
2194 sub_policy->main_policy,
2196 return -rte_mtr_error_set(error,
2198 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2200 "meter policy invalid.");
2201 mlx5_free(sub_policy->main_policy);
2203 mlx5_l3t_destroy(priv->policy_idx_tbl);
2204 priv->policy_idx_tbl = NULL;
2206 if (priv->mtr_profile_tbl) {
2207 MLX5_L3T_FOREACH(priv->mtr_profile_tbl, i, entry) {
2209 if (mlx5_flow_meter_profile_delete(dev, fmp->id,
2211 return -rte_mtr_error_set(error, EINVAL,
2212 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2213 NULL, "Fail to destroy "
2216 mlx5_l3t_destroy(priv->mtr_profile_tbl);
2217 priv->mtr_profile_tbl = NULL;
2219 /* Delete default policy table. */
2220 mlx5_flow_destroy_def_policy(dev);
2221 if (priv->sh->refcnt == 1)
2222 mlx5_flow_destroy_mtr_drop_tbls(dev);