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 matissa 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 matissa are 0. */
296 /* xbs = xbs_mantissa * 2^xbs_exponent */
297 _man = frexp(xbs, &_exp);
298 _man = _man * pow(2, MLX5_MAN_WIDTH);
299 _exp = _exp - MLX5_MAN_WIDTH;
300 *man = (uint8_t)ceil(_man);
305 * Fill the prm meter parameter.
308 * Pointer to meter profie to be converted.
310 * Pointer to the error structure.
313 * 0 on success, a negative errno value otherwise and rte_errno is set.
316 mlx5_flow_meter_param_fill(struct mlx5_flow_meter_profile *fmp,
317 struct rte_mtr_error *error)
319 struct mlx5_flow_meter_srtcm_rfc2697_prm *srtcm = &fmp->srtcm_prm;
321 uint32_t cbs_exp, cbs_man, cir_exp, cir_man;
322 uint32_t eir_exp, eir_man, ebs_exp, ebs_man;
323 uint64_t cir, cbs, eir, ebs;
325 switch (fmp->profile.alg) {
326 case RTE_MTR_SRTCM_RFC2697:
327 cir = fmp->profile.srtcm_rfc2697.cir;
328 cbs = fmp->profile.srtcm_rfc2697.cbs;
330 ebs = fmp->profile.srtcm_rfc2697.ebs;
332 case RTE_MTR_TRTCM_RFC2698:
333 MLX5_ASSERT(fmp->profile.trtcm_rfc2698.pir >
334 fmp->profile.trtcm_rfc2698.cir &&
335 fmp->profile.trtcm_rfc2698.pbs >
336 fmp->profile.trtcm_rfc2698.cbs);
337 cir = fmp->profile.trtcm_rfc2698.cir;
338 cbs = fmp->profile.trtcm_rfc2698.cbs;
339 /* EIR / EBS are filled with PIR / PBS. */
340 eir = fmp->profile.trtcm_rfc2698.pir;
341 ebs = fmp->profile.trtcm_rfc2698.pbs;
343 case RTE_MTR_TRTCM_RFC4115:
344 cir = fmp->profile.trtcm_rfc4115.cir;
345 cbs = fmp->profile.trtcm_rfc4115.cbs;
346 eir = fmp->profile.trtcm_rfc4115.eir;
347 ebs = fmp->profile.trtcm_rfc4115.ebs;
350 return -rte_mtr_error_set(error, EINVAL,
351 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
352 "Metering algorithm mode is invalid");
354 /* Adjust the values for PPS mode. */
355 if (fmp->profile.packet_mode) {
356 cir <<= MLX5_MTRS_PPS_MAP_BPS_SHIFT;
357 cbs <<= MLX5_MTRS_PPS_MAP_BPS_SHIFT;
358 eir <<= MLX5_MTRS_PPS_MAP_BPS_SHIFT;
359 ebs <<= MLX5_MTRS_PPS_MAP_BPS_SHIFT;
361 /* cir = 8G * cir_mantissa * 1/(2^cir_exponent)) Bytes/Sec */
362 mlx5_flow_meter_xir_man_exp_calc(cir, &man, &exp);
363 /* Check if cir mantissa is too large. */
364 if (exp > ASO_DSEG_XIR_EXP_MASK)
365 return -rte_mtr_error_set(error, ENOTSUP,
366 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
367 "meter profile parameter cir is not supported.");
370 /* cbs = cbs_mantissa * 2^cbs_exponent */
371 mlx5_flow_meter_xbs_man_exp_calc(cbs, &man, &exp);
372 /* Check if cbs mantissa is too large. */
373 if (exp > ASO_DSEG_EXP_MASK)
374 return -rte_mtr_error_set(error, ENOTSUP,
375 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
376 "meter profile parameter cbs is not supported.");
379 srtcm->cbs_cir = rte_cpu_to_be_32(cbs_exp << ASO_DSEG_CBS_EXP_OFFSET |
380 cbs_man << ASO_DSEG_CBS_MAN_OFFSET |
381 cir_exp << ASO_DSEG_XIR_EXP_OFFSET |
383 mlx5_flow_meter_xir_man_exp_calc(eir, &man, &exp);
384 /* Check if eir mantissa is too large. */
385 if (exp > ASO_DSEG_XIR_EXP_MASK)
386 return -rte_mtr_error_set(error, ENOTSUP,
387 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
388 "meter profile parameter eir is not supported.");
391 mlx5_flow_meter_xbs_man_exp_calc(ebs, &man, &exp);
392 /* Check if ebs mantissa is too large. */
393 if (exp > ASO_DSEG_EXP_MASK)
394 return -rte_mtr_error_set(error, ENOTSUP,
395 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
396 "meter profile parameter ebs is not supported.");
399 srtcm->ebs_eir = rte_cpu_to_be_32(ebs_exp << ASO_DSEG_EBS_EXP_OFFSET |
400 ebs_man << ASO_DSEG_EBS_MAN_OFFSET |
401 eir_exp << ASO_DSEG_XIR_EXP_OFFSET |
411 * Callback to get MTR capabilities.
414 * Pointer to Ethernet device.
416 * Pointer to save MTR capabilities.
418 * Pointer to the error structure.
421 * 0 on success, a negative errno value otherwise and rte_errno is set.
424 mlx5_flow_mtr_cap_get(struct rte_eth_dev *dev,
425 struct rte_mtr_capabilities *cap,
426 struct rte_mtr_error *error __rte_unused)
428 struct mlx5_priv *priv = dev->data->dev_private;
429 struct mlx5_hca_qos_attr *qattr = &priv->config.hca_attr.qos;
432 return -rte_mtr_error_set(error, ENOTSUP,
433 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
434 "Meter is not supported");
435 memset(cap, 0, sizeof(*cap));
436 if (priv->sh->meter_aso_en) {
437 /* 2 meters per one ASO cache line. */
438 cap->n_max = 1 << (qattr->log_max_num_meter_aso + 1);
439 cap->srtcm_rfc2697_packet_mode_supported = 1;
441 cap->n_max = 1 << qattr->log_max_flow_meter;
442 cap->srtcm_rfc2697_packet_mode_supported = 0;
444 cap->srtcm_rfc2697_byte_mode_supported = 1;
445 cap->n_shared_max = cap->n_max;
447 cap->shared_identical = 1;
448 cap->shared_n_flows_per_mtr_max = 4 << 20;
449 /* 2M flows can share the same meter. */
450 cap->chaining_n_mtrs_per_flow_max = 1; /* Chaining is not supported. */
451 cap->meter_srtcm_rfc2697_n_max = qattr->flow_meter_old ? cap->n_max : 0;
452 cap->meter_rate_max = 1ULL << 40; /* 1 Tera tokens per sec. */
453 cap->stats_mask = RTE_MTR_STATS_N_BYTES_DROPPED |
454 RTE_MTR_STATS_N_PKTS_DROPPED;
459 * Callback to add MTR profile.
462 * Pointer to Ethernet device.
463 * @param[in] meter_profile_id
466 * Pointer to meter profile detail.
468 * Pointer to the error structure.
471 * 0 on success, a negative errno value otherwise and rte_errno is set.
474 mlx5_flow_meter_profile_add(struct rte_eth_dev *dev,
475 uint32_t meter_profile_id,
476 struct rte_mtr_meter_profile *profile,
477 struct rte_mtr_error *error)
479 struct mlx5_priv *priv = dev->data->dev_private;
480 struct mlx5_flow_meter_profile *fmp;
481 union mlx5_l3t_data data;
485 return -rte_mtr_error_set(error, ENOTSUP,
486 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
487 "Meter is not supported");
488 /* Check input params. */
489 ret = mlx5_flow_meter_profile_validate(dev, meter_profile_id,
493 /* Meter profile memory allocation. */
494 fmp = mlx5_malloc(MLX5_MEM_ZERO, sizeof(struct mlx5_flow_meter_profile),
495 RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
497 return -rte_mtr_error_set(error, ENOMEM,
498 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
499 NULL, "Meter profile memory "
501 /* Fill profile info. */
502 fmp->id = meter_profile_id;
503 fmp->profile = *profile;
504 /* Fill the flow meter parameters for the PRM. */
505 ret = mlx5_flow_meter_param_fill(fmp, error);
509 ret = mlx5_l3t_set_entry(priv->mtr_profile_tbl,
510 meter_profile_id, &data);
512 return -rte_mtr_error_set(error, ENOTSUP,
513 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
514 NULL, "Meter profile insert fail.");
522 * Callback to delete MTR profile.
525 * Pointer to Ethernet device.
526 * @param[in] meter_profile_id
529 * Pointer to the error structure.
532 * 0 on success, a negative errno value otherwise and rte_errno is set.
535 mlx5_flow_meter_profile_delete(struct rte_eth_dev *dev,
536 uint32_t meter_profile_id,
537 struct rte_mtr_error *error)
539 struct mlx5_priv *priv = dev->data->dev_private;
540 struct mlx5_flow_meter_profile *fmp;
543 return -rte_mtr_error_set(error, ENOTSUP,
544 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
545 "Meter is not supported");
546 /* Meter profile must exist. */
547 fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id);
549 return -rte_mtr_error_set(error, ENOENT,
550 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
552 "Meter profile id is invalid.");
553 /* Check profile is unused. */
555 return -rte_mtr_error_set(error, EBUSY,
556 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
557 NULL, "Meter profile is in use.");
558 if (mlx5_l3t_clear_entry(priv->mtr_profile_tbl, meter_profile_id))
559 return -rte_mtr_error_set(error, EBUSY,
560 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
561 NULL, "Meter profile remove fail.");
570 * Pointer to Ethernet device.
575 * Pointer to the policy found on success, NULL otherwise.
577 struct mlx5_flow_meter_policy *
578 mlx5_flow_meter_policy_find(struct rte_eth_dev *dev,
580 uint32_t *policy_idx)
582 struct mlx5_priv *priv = dev->data->dev_private;
583 struct mlx5_flow_meter_sub_policy *sub_policy = NULL;
584 union mlx5_l3t_data data;
586 if (policy_id > MLX5_MAX_SUB_POLICY_TBL_NUM || !priv->policy_idx_tbl)
588 if (mlx5_l3t_get_entry(priv->policy_idx_tbl, policy_id, &data) ||
592 *policy_idx = data.dword;
593 sub_policy = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
595 /* Remove reference taken by the mlx5_l3t_get_entry. */
596 mlx5_l3t_clear_entry(priv->policy_idx_tbl, policy_id);
598 if (sub_policy->main_policy_id)
599 return sub_policy->main_policy;
604 * Get the last meter's policy from one meter's policy in hierarchy.
607 * Pointer to Ethernet device.
609 * Pointer to flow meter policy.
612 * Pointer to the final meter's policy, or NULL when fail.
614 struct mlx5_flow_meter_policy *
615 mlx5_flow_meter_hierarchy_get_final_policy(struct rte_eth_dev *dev,
616 struct mlx5_flow_meter_policy *policy)
618 struct mlx5_priv *priv = dev->data->dev_private;
619 struct mlx5_flow_meter_info *next_fm;
620 struct mlx5_flow_meter_policy *next_policy = policy;
622 while (next_policy->is_hierarchy) {
623 next_fm = mlx5_flow_meter_find(priv,
624 next_policy->act_cnt[RTE_COLOR_GREEN].next_mtr_id, NULL);
625 if (!next_fm || next_fm->def_policy)
627 next_policy = mlx5_flow_meter_policy_find(dev,
628 next_fm->policy_id, NULL);
629 MLX5_ASSERT(next_policy);
635 * Callback to check MTR policy action validate
638 * Pointer to Ethernet device.
640 * Pointer to meter policy action detail.
642 * Pointer to the error structure.
645 * 0 on success, a negative errno value otherwise and rte_errno is set.
648 mlx5_flow_meter_policy_validate(struct rte_eth_dev *dev,
649 struct rte_mtr_meter_policy_params *policy,
650 struct rte_mtr_error *error)
652 struct mlx5_priv *priv = dev->data->dev_private;
653 struct rte_flow_attr attr = { .transfer =
654 priv->config.dv_esw_en ? 1 : 0};
657 uint8_t domain_bitmap;
660 if (!priv->mtr_en || !priv->sh->meter_aso_en)
661 return -rte_mtr_error_set(error, ENOTSUP,
662 RTE_MTR_ERROR_TYPE_METER_POLICY,
663 NULL, "meter policy unsupported.");
664 ret = mlx5_flow_validate_mtr_acts(dev, policy->actions, &attr,
665 &is_rss, &domain_bitmap, &policy_mode, error);
672 __mlx5_flow_meter_policy_delete(struct rte_eth_dev *dev,
674 struct mlx5_flow_meter_policy *mtr_policy,
675 struct rte_mtr_error *error,
678 struct mlx5_priv *priv = dev->data->dev_private;
679 struct mlx5_flow_meter_sub_policy *sub_policy;
681 uint16_t sub_policy_num;
683 rte_spinlock_lock(&mtr_policy->sl);
684 if (mtr_policy->ref_cnt) {
685 rte_spinlock_unlock(&mtr_policy->sl);
686 return -rte_mtr_error_set(error, EBUSY,
687 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
689 "Meter policy object is being used.");
691 mlx5_flow_destroy_policy_rules(dev, mtr_policy);
692 mlx5_flow_destroy_mtr_acts(dev, mtr_policy);
693 for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
694 sub_policy_num = (mtr_policy->sub_policy_num >>
695 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i)) &
696 MLX5_MTR_SUB_POLICY_NUM_MASK;
697 if (sub_policy_num) {
698 for (j = 0; j < sub_policy_num; j++) {
699 sub_policy = mtr_policy->sub_policys[i][j];
702 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
707 if (priv->policy_idx_tbl && clear_l3t) {
708 if (mlx5_l3t_clear_entry(priv->policy_idx_tbl, policy_id)) {
709 rte_spinlock_unlock(&mtr_policy->sl);
710 return -rte_mtr_error_set(error, ENOTSUP,
711 RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL,
712 "Fail to delete policy in index table.");
715 rte_spinlock_unlock(&mtr_policy->sl);
720 * Callback to add MTR policy.
723 * Pointer to Ethernet device.
724 * @param[out] policy_id
725 * Pointer to policy id
727 * Pointer to meter policy action detail.
729 * Pointer to the error structure.
732 * 0 on success, a negative errno value otherwise and rte_errno is set.
735 mlx5_flow_meter_policy_add(struct rte_eth_dev *dev,
737 struct rte_mtr_meter_policy_params *policy,
738 struct rte_mtr_error *error)
740 struct mlx5_priv *priv = dev->data->dev_private;
741 struct rte_flow_attr attr = { .transfer =
742 priv->config.dv_esw_en ? 1 : 0};
743 uint32_t sub_policy_idx = 0;
744 uint32_t policy_idx = 0;
745 struct mlx5_flow_meter_policy *mtr_policy = NULL;
746 struct mlx5_flow_meter_sub_policy *sub_policy;
751 uint32_t policy_size = sizeof(struct mlx5_flow_meter_policy);
752 uint16_t sub_policy_num;
753 uint8_t domain_bitmap = 0;
754 union mlx5_l3t_data data;
755 bool skip_rule = false;
758 return -rte_mtr_error_set(error, ENOTSUP,
759 RTE_MTR_ERROR_TYPE_METER_POLICY,
760 NULL, "meter policy unsupported. ");
761 if (policy_id == MLX5_INVALID_POLICY_ID)
762 return -rte_mtr_error_set(error, ENOTSUP,
763 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
764 NULL, "policy ID is invalid. ");
765 if (policy_id == priv->sh->mtrmng->def_policy_id)
766 return -rte_mtr_error_set(error, EEXIST,
767 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
768 NULL, "default policy ID exists. ");
769 mtr_policy = mlx5_flow_meter_policy_find(dev, policy_id, &policy_idx);
771 return -rte_mtr_error_set(error, EEXIST,
772 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
773 NULL, "policy ID exists. ");
774 ret = mlx5_flow_validate_mtr_acts(dev, policy->actions, &attr,
775 &is_rss, &domain_bitmap,
776 &policy_mode, error);
780 return -rte_mtr_error_set(error, ENOTSUP,
781 RTE_MTR_ERROR_TYPE_METER_POLICY,
782 NULL, "fail to find policy domain.");
783 if (policy_mode == MLX5_MTR_POLICY_MODE_DEF) {
784 if (priv->sh->mtrmng->def_policy_id != MLX5_INVALID_POLICY_ID)
785 return -rte_mtr_error_set(error, EEXIST,
786 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
787 NULL, "a policy with similar actions "
788 "is already configured");
789 if (mlx5_flow_create_def_policy(dev))
790 return -rte_mtr_error_set(error, ENOTSUP,
791 RTE_MTR_ERROR_TYPE_METER_POLICY,
793 "fail to create non-terminated policy.");
794 priv->sh->mtrmng->def_policy_id = policy_id;
797 if (!priv->sh->meter_aso_en)
798 return -rte_mtr_error_set(error, ENOTSUP,
799 RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
800 "no ASO capability to support the policy ");
801 for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
802 if (!(domain_bitmap & (1 << i)))
805 * If RSS is found, it means that only the ingress domain can
806 * be supported. It is invalid to support RSS for one color
807 * and egress / transfer domain actions for another. Drop and
808 * jump action should have no impact.
812 sizeof(struct mlx5_flow_meter_sub_policy *) *
813 MLX5_MTR_RSS_MAX_SUB_POLICY;
816 policy_size += sizeof(struct mlx5_flow_meter_sub_policy *);
818 mtr_policy = mlx5_malloc(MLX5_MEM_ZERO, policy_size,
819 RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
821 return -rte_mtr_error_set(error, ENOMEM,
822 RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
823 "Memory alloc failed for meter policy.");
824 if (policy_mode == MLX5_MTR_POLICY_MODE_OG)
825 mtr_policy->skip_y = 1;
826 else if (policy_mode == MLX5_MTR_POLICY_MODE_OY)
827 mtr_policy->skip_g = 1;
828 policy_size = sizeof(struct mlx5_flow_meter_policy);
829 for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
830 if (!(domain_bitmap & (1 << i)))
832 if (i == MLX5_MTR_DOMAIN_INGRESS)
833 mtr_policy->ingress = 1;
834 if (i == MLX5_MTR_DOMAIN_EGRESS)
835 mtr_policy->egress = 1;
836 if (i == MLX5_MTR_DOMAIN_TRANSFER)
837 mtr_policy->transfer = 1;
838 sub_policy = mlx5_ipool_zmalloc
839 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
842 sub_policy_idx > MLX5_MAX_SUB_POLICY_TBL_NUM)
844 sub_policy->idx = sub_policy_idx;
845 sub_policy->main_policy = mtr_policy;
847 policy_idx = sub_policy_idx;
848 sub_policy->main_policy_id = 1;
850 mtr_policy->sub_policys[i] =
851 (struct mlx5_flow_meter_sub_policy **)
852 ((uint8_t *)mtr_policy + policy_size);
853 mtr_policy->sub_policys[i][0] = sub_policy;
854 sub_policy_num = (mtr_policy->sub_policy_num >>
855 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i)) &
856 MLX5_MTR_SUB_POLICY_NUM_MASK;
858 mtr_policy->sub_policy_num &= ~(MLX5_MTR_SUB_POLICY_NUM_MASK <<
859 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i));
860 mtr_policy->sub_policy_num |=
861 (sub_policy_num & MLX5_MTR_SUB_POLICY_NUM_MASK) <<
862 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i);
864 * If RSS is found, it means that only the ingress domain can
865 * be supported. It is invalid to support RSS for one color
866 * and egress / transfer domain actions for another. Drop and
867 * jump action should have no impact.
870 mtr_policy->is_rss = 1;
873 policy_size += sizeof(struct mlx5_flow_meter_sub_policy *);
875 rte_spinlock_init(&mtr_policy->sl);
876 ret = mlx5_flow_create_mtr_acts(dev, mtr_policy,
877 policy->actions, error);
880 if (mtr_policy->is_hierarchy) {
881 struct mlx5_flow_meter_policy *final_policy;
884 mlx5_flow_meter_hierarchy_get_final_policy(dev, mtr_policy);
887 skip_rule = (final_policy->is_rss || final_policy->is_queue);
890 * If either Green or Yellow has queue / RSS action, all the policy
891 * rules will be created later in the flow splitting stage.
893 if (!is_rss && !mtr_policy->is_queue && !skip_rule) {
894 /* Create policy rules in HW. */
895 ret = mlx5_flow_create_policy_rules(dev, mtr_policy);
899 data.dword = policy_idx;
900 if (!priv->policy_idx_tbl) {
901 priv->policy_idx_tbl = mlx5_l3t_create(MLX5_L3T_TYPE_DWORD);
902 if (!priv->policy_idx_tbl)
905 if (mlx5_l3t_set_entry(priv->policy_idx_tbl, policy_id, &data))
910 ret = __mlx5_flow_meter_policy_delete(dev, policy_id,
911 mtr_policy, error, false);
912 mlx5_free(mtr_policy);
916 return -rte_mtr_error_set(error, ENOTSUP,
917 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
918 NULL, "Failed to create devx policy.");
922 * Callback to delete MTR policy.
925 * Pointer to Ethernet device.
926 * @param[in] policy_id
929 * Pointer to the error structure.
932 * 0 on success, a negative errno value otherwise and rte_errno is set.
935 mlx5_flow_meter_policy_delete(struct rte_eth_dev *dev,
937 struct rte_mtr_error *error)
939 struct mlx5_priv *priv = dev->data->dev_private;
940 struct mlx5_flow_meter_policy *mtr_policy;
944 if (policy_id == priv->sh->mtrmng->def_policy_id) {
945 if (priv->sh->mtrmng->def_policy_ref_cnt > 0)
946 return -rte_mtr_error_set(error, ENOTSUP,
947 RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL,
948 "Meter policy object is being used.");
949 priv->sh->mtrmng->def_policy_id = MLX5_INVALID_POLICY_ID;
952 mtr_policy = mlx5_flow_meter_policy_find(dev, policy_id, &policy_idx);
954 return -rte_mtr_error_set(error, ENOTSUP,
955 RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL,
956 "Meter policy id is invalid. ");
957 ret = __mlx5_flow_meter_policy_delete(dev, policy_id, mtr_policy,
961 mlx5_free(mtr_policy);
966 * Check meter validation.
969 * Pointer to mlx5 private data structure.
970 * @param[in] meter_id
973 * Pointer to rte meter parameters.
975 * Pointer to rte meter error structure.
978 * 0 on success, a negative errno value otherwise and rte_errno is set.
981 mlx5_flow_meter_validate(struct mlx5_priv *priv, uint32_t meter_id,
982 struct rte_mtr_params *params,
983 struct rte_mtr_error *error)
985 /* Meter must use global drop action. */
986 if (!priv->sh->dr_drop_action)
987 return -rte_mtr_error_set(error, ENOTSUP,
988 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
990 "No drop action ready for meter.");
991 /* Meter params must not be NULL. */
993 return -rte_mtr_error_set(error, EINVAL,
994 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
995 NULL, "Meter object params null.");
996 /* Previous meter color is not supported. */
997 if (params->use_prev_mtr_color)
998 return -rte_mtr_error_set(error, ENOTSUP,
999 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
1001 "Previous meter color "
1003 if (params->meter_policy_id == MLX5_INVALID_POLICY_ID)
1004 return -rte_mtr_error_set(error, ENOENT,
1005 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
1006 NULL, "Meter policy id not valid.");
1007 /* Validate meter id. */
1008 if (mlx5_flow_meter_find(priv, meter_id, NULL))
1009 return -rte_mtr_error_set(error, EEXIST,
1010 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
1011 "Meter object already exists.");
1016 * Modify the flow meter action.
1019 * Pointer to mlx5 private data structure.
1021 * Pointer to flow meter to be modified.
1023 * Pointer to meter srtcm description parameter.
1024 * @param[in] modify_bits
1025 * The bit in srtcm to be updated.
1026 * @param[in] active_state
1027 * The state to be updated.
1029 * 0 on success, o negative value otherwise.
1032 mlx5_flow_meter_action_modify(struct mlx5_priv *priv,
1033 struct mlx5_flow_meter_info *fm,
1034 const struct mlx5_flow_meter_srtcm_rfc2697_prm *srtcm,
1035 uint64_t modify_bits, uint32_t active_state, uint32_t is_enable)
1037 #ifdef HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER
1038 uint32_t in[MLX5_ST_SZ_DW(flow_meter_parameters)] = { 0 };
1040 struct mlx5dv_dr_flow_meter_attr mod_attr = { 0 };
1042 struct mlx5_aso_mtr *aso_mtr = NULL;
1043 uint32_t cbs_cir, ebs_eir, val;
1045 if (priv->sh->meter_aso_en) {
1046 fm->is_enable = !!is_enable;
1047 aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
1048 ret = mlx5_aso_meter_update_by_wqe(priv->sh, aso_mtr);
1051 ret = mlx5_aso_mtr_wait(priv->sh, aso_mtr);
1055 /* Fill command parameters. */
1056 mod_attr.reg_c_index = priv->mtr_color_reg - REG_C_0;
1057 mod_attr.flow_meter_parameter = in;
1058 mod_attr.flow_meter_parameter_sz =
1059 MLX5_ST_SZ_BYTES(flow_meter_parameters);
1060 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_ACTIVE)
1061 mod_attr.active = !!active_state;
1063 mod_attr.active = 0;
1065 cbs_cir = rte_be_to_cpu_32(srtcm->cbs_cir);
1066 ebs_eir = rte_be_to_cpu_32(srtcm->ebs_eir);
1067 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS) {
1068 val = (cbs_cir >> ASO_DSEG_CBS_EXP_OFFSET) &
1070 MLX5_SET(flow_meter_parameters, attr,
1072 val = (cbs_cir >> ASO_DSEG_CBS_MAN_OFFSET) &
1074 MLX5_SET(flow_meter_parameters, attr,
1077 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR) {
1078 val = (cbs_cir >> ASO_DSEG_XIR_EXP_OFFSET) &
1080 MLX5_SET(flow_meter_parameters, attr,
1082 val = cbs_cir & ASO_DSEG_MAN_MASK;
1083 MLX5_SET(flow_meter_parameters, attr,
1086 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_EBS) {
1087 val = (ebs_eir >> ASO_DSEG_EBS_EXP_OFFSET) &
1089 MLX5_SET(flow_meter_parameters, attr,
1091 val = (ebs_eir >> ASO_DSEG_EBS_MAN_OFFSET) &
1093 MLX5_SET(flow_meter_parameters, attr,
1096 /* Apply modifications to meter only if it was created. */
1097 if (fm->meter_action) {
1098 ret = mlx5_glue->dv_modify_flow_action_meter
1099 (fm->meter_action, &mod_attr,
1100 rte_cpu_to_be_64(modify_bits));
1104 /* Update succeedded modify meter parameters. */
1105 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_ACTIVE)
1106 fm->active_state = !!active_state;
1121 mlx5_flow_meter_stats_enable_update(struct rte_eth_dev *dev,
1122 struct mlx5_flow_meter_info *fm,
1123 uint64_t stats_mask)
1126 (stats_mask & RTE_MTR_STATS_N_BYTES_DROPPED) ? 1 : 0;
1127 fm->pkts_dropped = (stats_mask & RTE_MTR_STATS_N_PKTS_DROPPED) ? 1 : 0;
1128 if (fm->bytes_dropped || fm->pkts_dropped) {
1129 if (!fm->drop_cnt) {
1130 /* Alloc policer counters. */
1131 fm->drop_cnt = mlx5_counter_alloc(dev);
1137 mlx5_counter_free(dev, fm->drop_cnt);
1145 * Create meter rules.
1148 * Pointer to Ethernet device.
1149 * @param[in] meter_id
1152 * Pointer to rte meter parameters.
1154 * Meter shared with other flow or not.
1156 * Pointer to rte meter error structure.
1159 * 0 on success, a negative errno value otherwise and rte_errno is set.
1162 mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,
1163 struct rte_mtr_params *params, int shared,
1164 struct rte_mtr_error *error)
1166 struct mlx5_priv *priv = dev->data->dev_private;
1167 struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
1168 struct mlx5_flow_meter_profile *fmp;
1169 struct mlx5_flow_meter_info *fm;
1170 struct mlx5_legacy_flow_meter *legacy_fm;
1171 struct mlx5_flow_meter_policy *mtr_policy = NULL;
1172 struct mlx5_indexed_pool_config flow_ipool_cfg = {
1176 .type = "mlx5_flow_mtr_flow_id_pool",
1178 struct mlx5_aso_mtr *aso_mtr;
1179 uint32_t mtr_idx, policy_idx;
1180 union mlx5_l3t_data data;
1182 uint8_t domain_bitmap;
1183 uint8_t mtr_id_bits;
1184 uint8_t mtr_reg_bits = priv->mtr_reg_share ?
1185 MLX5_MTR_IDLE_BITS_IN_COLOR_REG : MLX5_REG_BITS;
1188 return -rte_mtr_error_set(error, ENOTSUP,
1189 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1190 "Meter is not supported");
1191 /* Validate the parameters. */
1192 ret = mlx5_flow_meter_validate(priv, meter_id, params, error);
1195 /* Meter profile must exist. */
1196 fmp = mlx5_flow_meter_profile_find(priv, params->meter_profile_id);
1198 return -rte_mtr_error_set(error, ENOENT,
1199 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
1200 NULL, "Meter profile id not valid.");
1201 /* Meter policy must exist. */
1202 if (params->meter_policy_id == priv->sh->mtrmng->def_policy_id) {
1204 (&priv->sh->mtrmng->def_policy_ref_cnt,
1205 1, __ATOMIC_RELAXED);
1206 domain_bitmap = MLX5_MTR_ALL_DOMAIN_BIT;
1207 if (!priv->config.dv_esw_en)
1208 domain_bitmap &= ~MLX5_MTR_DOMAIN_TRANSFER_BIT;
1210 if (!priv->sh->meter_aso_en)
1211 return -rte_mtr_error_set(error, ENOTSUP,
1212 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1213 "Part of the policies cannot be "
1214 "supported without ASO ");
1215 mtr_policy = mlx5_flow_meter_policy_find(dev,
1216 params->meter_policy_id, &policy_idx);
1218 return -rte_mtr_error_set(error, ENOENT,
1219 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
1220 NULL, "Meter policy id not valid.");
1221 domain_bitmap = (mtr_policy->ingress ?
1222 MLX5_MTR_DOMAIN_INGRESS_BIT : 0) |
1223 (mtr_policy->egress ?
1224 MLX5_MTR_DOMAIN_EGRESS_BIT : 0) |
1225 (mtr_policy->transfer ?
1226 MLX5_MTR_DOMAIN_TRANSFER_BIT : 0);
1227 if (fmp->g_support && mtr_policy->skip_g)
1228 return -rte_mtr_error_set(error, ENOTSUP,
1229 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
1230 NULL, "Meter green policy is empty.");
1231 if (fmp->y_support && mtr_policy->skip_y)
1232 return -rte_mtr_error_set(error, ENOTSUP,
1233 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
1234 NULL, "Meter yellow policy is empty.");
1236 /* Allocate the flow meter memory. */
1237 if (priv->sh->meter_aso_en) {
1238 mtr_idx = mlx5_flow_mtr_alloc(dev);
1240 return -rte_mtr_error_set(error, ENOMEM,
1241 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1242 "Memory alloc failed for meter.");
1243 aso_mtr = mlx5_aso_meter_by_idx(priv, mtr_idx);
1247 return -rte_mtr_error_set(error, ENOMEM,
1248 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1249 "Unsupported profile with yellow.");
1250 legacy_fm = mlx5_ipool_zmalloc
1251 (priv->sh->ipool[MLX5_IPOOL_MTR], &mtr_idx);
1252 if (legacy_fm == NULL)
1253 return -rte_mtr_error_set(error, ENOMEM,
1254 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1255 "Memory alloc failed for meter.");
1256 legacy_fm->idx = mtr_idx;
1257 fm = &legacy_fm->fm;
1259 mtr_id_bits = MLX5_REG_BITS - __builtin_clz(mtr_idx);
1260 if ((mtr_id_bits + priv->sh->mtrmng->max_mtr_flow_bits) >
1262 DRV_LOG(ERR, "Meter number exceeds max limit.");
1265 if (mtr_id_bits > priv->sh->mtrmng->max_mtr_bits)
1266 priv->sh->mtrmng->max_mtr_bits = mtr_id_bits;
1267 /* Fill the flow meter parameters. */
1268 fm->meter_id = meter_id;
1269 fm->policy_id = params->meter_policy_id;
1271 if (mlx5_flow_meter_stats_enable_update(dev, fm, params->stats_mask))
1273 if (mlx5_flow_create_mtr_tbls(dev, fm, mtr_idx, domain_bitmap))
1275 /* Add to the flow meter list. */
1276 if (!priv->sh->meter_aso_en)
1277 TAILQ_INSERT_TAIL(fms, legacy_fm, next);
1278 /* Add to the flow meter list. */
1279 fm->active_state = 1; /* Config meter starts as active. */
1281 fm->shared = !!shared;
1282 __atomic_add_fetch(&fm->profile->ref_cnt, 1, __ATOMIC_RELAXED);
1283 if (params->meter_policy_id == priv->sh->mtrmng->def_policy_id) {
1285 fm->flow_ipool = mlx5_ipool_create(&flow_ipool_cfg);
1286 if (!fm->flow_ipool)
1289 rte_spinlock_init(&fm->sl);
1290 /* If ASO meter supported, update ASO flow meter by wqe. */
1291 if (priv->sh->meter_aso_en) {
1292 aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
1293 ret = mlx5_aso_meter_update_by_wqe(priv->sh, aso_mtr);
1296 if (!priv->mtr_idx_tbl) {
1298 mlx5_l3t_create(MLX5_L3T_TYPE_DWORD);
1299 if (!priv->mtr_idx_tbl)
1302 data.dword = mtr_idx;
1303 if (mlx5_l3t_set_entry(priv->mtr_idx_tbl, meter_id, &data))
1307 __atomic_add_fetch(&mtr_policy->ref_cnt, 1, __ATOMIC_RELAXED);
1310 mlx5_flow_destroy_mtr_tbls(dev, fm);
1311 /* Free policer counters. */
1313 mlx5_counter_free(dev, fm->drop_cnt);
1314 if (priv->sh->meter_aso_en)
1315 mlx5_flow_mtr_free(dev, mtr_idx);
1317 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR], mtr_idx);
1318 return -rte_mtr_error_set(error, ENOTSUP,
1319 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
1320 NULL, "Failed to create devx meter.");
1324 mlx5_flow_meter_params_flush(struct rte_eth_dev *dev,
1325 struct mlx5_flow_meter_info *fm,
1328 struct mlx5_priv *priv = dev->data->dev_private;
1329 struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
1330 struct mlx5_flow_meter_profile *fmp;
1331 struct mlx5_legacy_flow_meter *legacy_fm = NULL;
1332 struct mlx5_flow_meter_policy *mtr_policy;
1334 /* Meter object must not have any owner. */
1335 MLX5_ASSERT(!fm->ref_cnt);
1336 /* Get meter profile. */
1340 /* Update dependencies. */
1341 __atomic_sub_fetch(&fmp->ref_cnt, 1, __ATOMIC_RELAXED);
1343 /* Remove from list. */
1344 if (!priv->sh->meter_aso_en) {
1345 legacy_fm = container_of(fm,
1346 struct mlx5_legacy_flow_meter, fm);
1347 TAILQ_REMOVE(fms, legacy_fm, next);
1349 /* Free drop counters. */
1351 mlx5_counter_free(dev, fm->drop_cnt);
1352 /* Free meter flow table. */
1353 if (fm->flow_ipool) {
1354 mlx5_ipool_destroy(fm->flow_ipool);
1357 mlx5_flow_destroy_mtr_tbls(dev, fm);
1359 __atomic_sub_fetch(&priv->sh->mtrmng->def_policy_ref_cnt,
1360 1, __ATOMIC_RELAXED);
1361 if (priv->sh->meter_aso_en) {
1362 if (!fm->def_policy) {
1363 mtr_policy = mlx5_flow_meter_policy_find(dev,
1364 fm->policy_id, NULL);
1366 __atomic_sub_fetch(&mtr_policy->ref_cnt,
1367 1, __ATOMIC_RELAXED);
1371 if (mlx5_l3t_clear_entry(priv->mtr_idx_tbl, fm->meter_id))
1373 mlx5_flow_mtr_free(dev, mtr_idx);
1375 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR],
1382 * Destroy meter rules.
1385 * Pointer to Ethernet device.
1386 * @param[in] meter_id
1389 * Pointer to rte meter error structure.
1392 * 0 on success, a negative errno value otherwise and rte_errno is set.
1395 mlx5_flow_meter_destroy(struct rte_eth_dev *dev, uint32_t meter_id,
1396 struct rte_mtr_error *error)
1398 struct mlx5_priv *priv = dev->data->dev_private;
1399 struct mlx5_flow_meter_info *fm;
1400 uint32_t mtr_idx = 0;
1403 return -rte_mtr_error_set(error, ENOTSUP,
1404 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
1406 "Meter is not supported");
1407 /* Meter object must exist. */
1408 fm = mlx5_flow_meter_find(priv, meter_id, &mtr_idx);
1410 return -rte_mtr_error_set(error, ENOENT,
1411 RTE_MTR_ERROR_TYPE_MTR_ID,
1413 "Meter object id not valid.");
1414 /* Meter object must not have any owner. */
1415 if (fm->ref_cnt > 0)
1416 return -rte_mtr_error_set(error, EBUSY,
1417 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
1419 "Meter object is being used.");
1420 /* Destroy the meter profile. */
1421 if (mlx5_flow_meter_params_flush(dev, fm, mtr_idx))
1422 return -rte_mtr_error_set(error, EINVAL,
1423 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
1425 "MTR object meter profile invalid.");
1430 * Modify meter state.
1433 * Pointer to mlx5 private data structure.
1435 * Pointer to flow meter.
1436 * @param[in] new_state
1437 * New state to update.
1439 * Pointer to rte meter error structure.
1442 * 0 on success, a negative errno value otherwise and rte_errno is set.
1445 mlx5_flow_meter_modify_state(struct mlx5_priv *priv,
1446 struct mlx5_flow_meter_info *fm,
1448 struct rte_mtr_error *error)
1450 static const struct mlx5_flow_meter_srtcm_rfc2697_prm srtcm = {
1451 .cbs_cir = RTE_BE32(MLX5_IFC_FLOW_METER_DISABLE_CBS_CIR_VAL),
1454 uint64_t modify_bits = MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS |
1455 MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR;
1458 if (new_state == MLX5_FLOW_METER_DISABLE)
1459 ret = mlx5_flow_meter_action_modify(priv, fm,
1460 &srtcm, modify_bits, 0, 0);
1462 ret = mlx5_flow_meter_action_modify(priv, fm,
1463 &fm->profile->srtcm_prm,
1466 return -rte_mtr_error_set(error, -ret,
1467 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
1470 "Failed to enable meter." :
1471 "Failed to disable meter.");
1476 * Callback to enable flow meter.
1479 * Pointer to Ethernet device.
1480 * @param[in] meter_id
1483 * Pointer to rte meter error structure.
1486 * 0 on success, a negative errno value otherwise and rte_errno is set.
1489 mlx5_flow_meter_enable(struct rte_eth_dev *dev,
1491 struct rte_mtr_error *error)
1493 struct mlx5_priv *priv = dev->data->dev_private;
1494 struct mlx5_flow_meter_info *fm;
1498 return -rte_mtr_error_set(error, ENOTSUP,
1499 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1500 "Meter is not supported");
1501 /* Meter object must exist. */
1502 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1504 return -rte_mtr_error_set(error, ENOENT,
1505 RTE_MTR_ERROR_TYPE_MTR_ID,
1506 NULL, "Meter not found.");
1507 if (fm->active_state == MLX5_FLOW_METER_ENABLE)
1509 ret = mlx5_flow_meter_modify_state(priv, fm, MLX5_FLOW_METER_ENABLE,
1512 fm->active_state = MLX5_FLOW_METER_ENABLE;
1517 * Callback to disable flow meter.
1520 * Pointer to Ethernet device.
1521 * @param[in] meter_id
1524 * Pointer to rte meter error structure.
1527 * 0 on success, a negative errno value otherwise and rte_errno is set.
1530 mlx5_flow_meter_disable(struct rte_eth_dev *dev,
1532 struct rte_mtr_error *error)
1534 struct mlx5_priv *priv = dev->data->dev_private;
1535 struct mlx5_flow_meter_info *fm;
1539 return -rte_mtr_error_set(error, ENOTSUP,
1540 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1541 "Meter is not supported");
1542 /* Meter object must exist. */
1543 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1545 return -rte_mtr_error_set(error, ENOENT,
1546 RTE_MTR_ERROR_TYPE_MTR_ID,
1547 NULL, "Meter not found.");
1548 if (fm->active_state == MLX5_FLOW_METER_DISABLE)
1550 ret = mlx5_flow_meter_modify_state(priv, fm, MLX5_FLOW_METER_DISABLE,
1553 fm->active_state = MLX5_FLOW_METER_DISABLE;
1558 * Callback to update meter profile.
1561 * Pointer to Ethernet device.
1562 * @param[in] meter_id
1564 * @param[in] meter_profile_id
1565 * To be updated meter profile id.
1567 * Pointer to rte meter error structure.
1570 * 0 on success, a negative errno value otherwise and rte_errno is set.
1573 mlx5_flow_meter_profile_update(struct rte_eth_dev *dev,
1575 uint32_t meter_profile_id,
1576 struct rte_mtr_error *error)
1578 struct mlx5_priv *priv = dev->data->dev_private;
1579 struct mlx5_flow_meter_profile *fmp;
1580 struct mlx5_flow_meter_profile *old_fmp;
1581 struct mlx5_flow_meter_info *fm;
1582 uint64_t modify_bits = MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS |
1583 MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR;
1587 return -rte_mtr_error_set(error, ENOTSUP,
1588 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1589 "Meter is not supported");
1590 /* Meter profile must exist. */
1591 fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id);
1593 return -rte_mtr_error_set(error, ENOENT,
1594 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
1595 NULL, "Meter profile not found.");
1596 /* Meter object must exist. */
1597 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1599 return -rte_mtr_error_set(error, ENOENT,
1600 RTE_MTR_ERROR_TYPE_MTR_ID,
1601 NULL, "Meter not found.");
1602 /* MTR object already set to meter profile id. */
1603 old_fmp = fm->profile;
1606 /* Update the profile. */
1608 /* Update meter params in HW (if not disabled). */
1609 if (fm->active_state == MLX5_FLOW_METER_DISABLE)
1611 ret = mlx5_flow_meter_action_modify(priv, fm, &fm->profile->srtcm_prm,
1612 modify_bits, fm->active_state, 1);
1614 fm->profile = old_fmp;
1615 return -rte_mtr_error_set(error, -ret,
1616 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
1617 NULL, "Failed to update meter"
1618 " parmeters in hardware.");
1626 * Callback to update meter stats mask.
1629 * Pointer to Ethernet device.
1630 * @param[in] meter_id
1632 * @param[in] stats_mask
1633 * To be updated stats_mask.
1635 * Pointer to rte meter error structure.
1638 * 0 on success, a negative errno value otherwise and rte_errno is set.
1641 mlx5_flow_meter_stats_update(struct rte_eth_dev *dev,
1643 uint64_t stats_mask,
1644 struct rte_mtr_error *error)
1646 struct mlx5_priv *priv = dev->data->dev_private;
1647 struct mlx5_flow_meter_info *fm;
1650 return -rte_mtr_error_set(error, ENOTSUP,
1651 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1652 "Meter is not supported");
1653 /* Meter object must exist. */
1654 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1656 return -rte_mtr_error_set(error, ENOENT,
1657 RTE_MTR_ERROR_TYPE_MTR_ID,
1658 NULL, "Meter object id not valid.");
1659 if (mlx5_flow_meter_stats_enable_update(dev, fm, stats_mask))
1660 return -rte_mtr_error_set(error, ENOENT,
1661 RTE_MTR_ERROR_TYPE_MTR_ID,
1662 NULL, "Fail to allocate "
1663 "counter for meter.");
1668 * Callback to read meter statistics.
1671 * Pointer to Ethernet device.
1672 * @param[in] meter_id
1675 * Pointer to store the statistics.
1676 * @param[out] stats_mask
1677 * Pointer to store the stats_mask.
1679 * Statistic to be cleared after read or not.
1681 * Pointer to rte meter error structure.
1684 * 0 on success, a negative errno value otherwise and rte_errno is set.
1687 mlx5_flow_meter_stats_read(struct rte_eth_dev *dev,
1689 struct rte_mtr_stats *stats,
1690 uint64_t *stats_mask,
1692 struct rte_mtr_error *error)
1694 struct mlx5_priv *priv = dev->data->dev_private;
1695 struct mlx5_flow_meter_info *fm;
1701 return -rte_mtr_error_set(error, ENOTSUP,
1702 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1703 "Meter is not supported");
1704 /* Meter object must exist. */
1705 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1707 return -rte_mtr_error_set(error, ENOENT,
1708 RTE_MTR_ERROR_TYPE_MTR_ID,
1709 NULL, "Meter object id not valid.");
1711 if (fm->bytes_dropped)
1712 *stats_mask |= RTE_MTR_STATS_N_BYTES_DROPPED;
1713 if (fm->pkts_dropped)
1714 *stats_mask |= RTE_MTR_STATS_N_PKTS_DROPPED;
1715 memset(stats, 0, sizeof(*stats));
1717 ret = mlx5_counter_query(dev, fm->drop_cnt, clear, &pkts,
1721 /* If need to read the packets, set it. */
1722 if (fm->pkts_dropped)
1723 stats->n_pkts_dropped = pkts;
1724 /* If need to read the bytes, set it. */
1725 if (fm->bytes_dropped)
1726 stats->n_bytes_dropped = bytes;
1730 return -rte_mtr_error_set(error, ret, RTE_MTR_ERROR_TYPE_STATS, NULL,
1731 "Failed to read meter drop counters.");
1734 static const struct rte_mtr_ops mlx5_flow_mtr_ops = {
1735 .capabilities_get = mlx5_flow_mtr_cap_get,
1736 .meter_profile_add = mlx5_flow_meter_profile_add,
1737 .meter_profile_delete = mlx5_flow_meter_profile_delete,
1738 .meter_policy_validate = mlx5_flow_meter_policy_validate,
1739 .meter_policy_add = mlx5_flow_meter_policy_add,
1740 .meter_policy_delete = mlx5_flow_meter_policy_delete,
1741 .create = mlx5_flow_meter_create,
1742 .destroy = mlx5_flow_meter_destroy,
1743 .meter_enable = mlx5_flow_meter_enable,
1744 .meter_disable = mlx5_flow_meter_disable,
1745 .meter_profile_update = mlx5_flow_meter_profile_update,
1746 .meter_dscp_table_update = NULL,
1747 .stats_update = mlx5_flow_meter_stats_update,
1748 .stats_read = mlx5_flow_meter_stats_read,
1752 * Get meter operations.
1755 * Pointer to Ethernet device structure.
1757 * Pointer to set the mtr operations.
1763 mlx5_flow_meter_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)
1765 *(const struct rte_mtr_ops **)arg = &mlx5_flow_mtr_ops;
1773 * Pointer to mlx5_priv.
1777 * Pointer to Meter index.
1780 * Pointer to the meter info found on success, NULL otherwise.
1782 struct mlx5_flow_meter_info *
1783 mlx5_flow_meter_find(struct mlx5_priv *priv, uint32_t meter_id,
1786 struct mlx5_legacy_flow_meter *legacy_fm;
1787 struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
1788 struct mlx5_aso_mtr *aso_mtr;
1789 struct mlx5_aso_mtr_pools_mng *pools_mng =
1790 &priv->sh->mtrmng->pools_mng;
1791 union mlx5_l3t_data data;
1793 if (priv->sh->meter_aso_en) {
1794 rte_spinlock_lock(&pools_mng->mtrsl);
1795 if (!pools_mng->n_valid || !priv->mtr_idx_tbl) {
1796 rte_spinlock_unlock(&pools_mng->mtrsl);
1799 if (mlx5_l3t_get_entry(priv->mtr_idx_tbl, meter_id, &data) ||
1801 rte_spinlock_unlock(&pools_mng->mtrsl);
1805 *mtr_idx = data.dword;
1806 aso_mtr = mlx5_aso_meter_by_idx(priv, data.dword);
1807 /* Remove reference taken by the mlx5_l3t_get_entry. */
1808 mlx5_l3t_clear_entry(priv->mtr_idx_tbl, meter_id);
1809 rte_spinlock_unlock(&pools_mng->mtrsl);
1810 if (!aso_mtr || aso_mtr->state == ASO_METER_FREE)
1812 return &aso_mtr->fm;
1814 TAILQ_FOREACH(legacy_fm, fms, next)
1815 if (meter_id == legacy_fm->fm.meter_id) {
1817 *mtr_idx = legacy_fm->idx;
1818 return &legacy_fm->fm;
1824 * Find meter by index.
1827 * Pointer to mlx5_priv.
1832 * Pointer to the meter info found on success, NULL otherwise.
1834 struct mlx5_flow_meter_info *
1835 flow_dv_meter_find_by_idx(struct mlx5_priv *priv, uint32_t idx)
1837 struct mlx5_aso_mtr *aso_mtr;
1839 if (priv->sh->meter_aso_en) {
1840 aso_mtr = mlx5_aso_meter_by_idx(priv, idx);
1843 return &aso_mtr->fm;
1845 return mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MTR], idx);
1850 * Attach meter to flow.
1851 * Unidirectional Meter creation can only be done
1852 * when flow direction is known, i.e. when calling meter_attach.
1855 * Pointer to mlx5 private data.
1857 * Pointer to flow meter.
1859 * Pointer to flow attributes.
1860 * @param [out] error
1861 * Pointer to error structure.
1864 * 0 on success, a negative errno value otherwise and rte_errno is set.
1867 mlx5_flow_meter_attach(struct mlx5_priv *priv,
1868 struct mlx5_flow_meter_info *fm,
1869 const struct rte_flow_attr *attr,
1870 struct rte_flow_error *error)
1874 if (priv->sh->meter_aso_en) {
1875 struct mlx5_aso_mtr *aso_mtr;
1877 aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
1878 if (mlx5_aso_mtr_wait(priv->sh, aso_mtr)) {
1879 return rte_flow_error_set(error, ENOENT,
1880 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1882 "Timeout in meter configuration");
1884 rte_spinlock_lock(&fm->sl);
1885 if (fm->shared || !fm->ref_cnt) {
1888 rte_flow_error_set(error, EINVAL,
1889 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1890 "Meter cannot be shared");
1893 rte_spinlock_unlock(&fm->sl);
1895 rte_spinlock_lock(&fm->sl);
1896 if (fm->meter_action) {
1898 attr->transfer == fm->transfer &&
1899 attr->ingress == fm->ingress &&
1900 attr->egress == fm->egress) {
1903 rte_flow_error_set(error, EINVAL,
1904 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1906 "Meter attr not match." :
1907 "Meter cannot be shared.");
1911 fm->ingress = attr->ingress;
1912 fm->egress = attr->egress;
1913 fm->transfer = attr->transfer;
1915 /* This also creates the meter object. */
1916 fm->meter_action = mlx5_flow_meter_action_create(priv,
1918 if (!fm->meter_action) {
1923 rte_flow_error_set(error, EINVAL,
1924 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1925 "Meter action create failed.");
1929 rte_spinlock_unlock(&fm->sl);
1931 return ret ? -rte_errno : 0;
1935 * Detach meter from flow.
1938 * Pointer to mlx5 private data.
1940 * Pointer to flow meter.
1943 mlx5_flow_meter_detach(struct mlx5_priv *priv,
1944 struct mlx5_flow_meter_info *fm)
1946 #ifdef HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER
1947 rte_spinlock_lock(&fm->sl);
1948 MLX5_ASSERT(fm->ref_cnt);
1949 if (--fm->ref_cnt == 0 && !priv->sh->meter_aso_en) {
1950 mlx5_glue->destroy_flow_action(fm->meter_action);
1951 fm->meter_action = NULL;
1956 rte_spinlock_unlock(&fm->sl);
1964 * Flush meter with Rx queue configuration.
1967 * Pointer to Ethernet device.
1970 mlx5_flow_meter_rxq_flush(struct rte_eth_dev *dev)
1972 struct mlx5_priv *priv = dev->data->dev_private;
1973 struct mlx5_flow_meter_sub_policy *sub_policy;
1974 struct mlx5_flow_meter_policy *mtr_policy;
1976 uint32_t i, policy_idx;
1980 if (priv->policy_idx_tbl) {
1981 MLX5_L3T_FOREACH(priv->policy_idx_tbl, i, entry) {
1982 policy_idx = *(uint32_t *)entry;
1983 sub_policy = mlx5_ipool_get
1984 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
1986 if (!sub_policy || !sub_policy->main_policy)
1988 mtr_policy = sub_policy->main_policy;
1989 if (mtr_policy->is_queue || mtr_policy->is_rss)
1990 mlx5_flow_destroy_sub_policy_with_rxq(dev,
1997 * Iterate a meter hierarchy and flush all meters and policies if possible.
2000 * Pointer to Ethernet device.
2002 * Pointer to flow meter.
2003 * @param[in] mtr_idx
2006 * Pointer to rte meter error structure.
2009 * 0 on success, a negative errno value otherwise and rte_errno is set.
2012 mlx5_flow_meter_flush_hierarchy(struct rte_eth_dev *dev,
2013 struct mlx5_flow_meter_info *fm,
2015 struct rte_mtr_error *error)
2017 struct mlx5_priv *priv = dev->data->dev_private;
2018 struct mlx5_flow_meter_policy *policy;
2020 struct mlx5_flow_meter_info *next_fm;
2021 uint32_t next_mtr_idx;
2022 struct mlx5_flow_meter_policy *next_policy = NULL;
2024 policy = mlx5_flow_meter_policy_find(dev, fm->policy_id, NULL);
2025 MLX5_ASSERT(policy);
2026 while (!fm->ref_cnt && policy->is_hierarchy) {
2027 policy_id = fm->policy_id;
2028 next_fm = mlx5_flow_meter_find(priv,
2029 policy->act_cnt[RTE_COLOR_GREEN].next_mtr_id,
2032 next_policy = mlx5_flow_meter_policy_find(dev,
2035 MLX5_ASSERT(next_policy);
2037 if (mlx5_flow_meter_params_flush(dev, fm, mtr_idx))
2038 return -rte_mtr_error_set(error, ENOTSUP,
2039 RTE_MTR_ERROR_TYPE_MTR_ID,
2041 "Failed to flush meter.");
2042 if (policy->ref_cnt)
2044 if (__mlx5_flow_meter_policy_delete(dev, policy_id,
2045 policy, error, true))
2048 if (!next_fm || !next_policy)
2051 mtr_idx = next_mtr_idx;
2052 policy = next_policy;
2058 * Flush all the hierarchy meters and their policies.
2061 * Pointer to Ethernet device.
2063 * Pointer to rte meter error structure.
2066 * 0 on success, a negative errno value otherwise and rte_errno is set.
2069 mlx5_flow_meter_flush_all_hierarchies(struct rte_eth_dev *dev,
2070 struct rte_mtr_error *error)
2072 struct mlx5_priv *priv = dev->data->dev_private;
2073 struct mlx5_flow_meter_info *fm;
2074 struct mlx5_flow_meter_policy *policy;
2075 struct mlx5_flow_meter_sub_policy *sub_policy;
2076 struct mlx5_flow_meter_info *next_fm;
2077 struct mlx5_aso_mtr *aso_mtr;
2078 uint32_t mtr_idx = 0;
2079 uint32_t i, policy_idx;
2082 if (!priv->mtr_idx_tbl || !priv->policy_idx_tbl)
2084 MLX5_L3T_FOREACH(priv->mtr_idx_tbl, i, entry) {
2085 mtr_idx = *(uint32_t *)entry;
2088 aso_mtr = mlx5_aso_meter_by_idx(priv, mtr_idx);
2090 if (fm->ref_cnt || fm->def_policy)
2092 if (mlx5_flow_meter_flush_hierarchy(dev, fm, mtr_idx, error))
2095 MLX5_L3T_FOREACH(priv->policy_idx_tbl, i, entry) {
2096 policy_idx = *(uint32_t *)entry;
2097 sub_policy = mlx5_ipool_get
2098 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
2101 return -rte_mtr_error_set(error,
2103 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2104 NULL, "Meter policy invalid.");
2105 policy = sub_policy->main_policy;
2106 if (!policy || !policy->is_hierarchy || policy->ref_cnt)
2108 next_fm = mlx5_flow_meter_find(priv,
2109 policy->act_cnt[RTE_COLOR_GREEN].next_mtr_id,
2111 if (__mlx5_flow_meter_policy_delete(dev, i, policy,
2113 return -rte_mtr_error_set(error,
2115 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2116 NULL, "Meter policy invalid.");
2118 if (!next_fm || next_fm->ref_cnt || next_fm->def_policy)
2120 if (mlx5_flow_meter_flush_hierarchy(dev, next_fm,
2127 * Flush meter configuration.
2130 * Pointer to Ethernet device.
2132 * Pointer to rte meter error structure.
2135 * 0 on success, a negative errno value otherwise and rte_errno is set.
2138 mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error)
2140 struct mlx5_priv *priv = dev->data->dev_private;
2141 struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
2142 struct mlx5_flow_meter_profile *fmp;
2143 struct mlx5_legacy_flow_meter *legacy_fm;
2144 struct mlx5_flow_meter_info *fm;
2145 struct mlx5_flow_meter_sub_policy *sub_policy;
2147 uint32_t i, mtr_idx, policy_idx;
2149 struct mlx5_aso_mtr *aso_mtr;
2153 if (priv->sh->meter_aso_en) {
2154 if (mlx5_flow_meter_flush_all_hierarchies(dev, error))
2156 if (priv->mtr_idx_tbl) {
2157 MLX5_L3T_FOREACH(priv->mtr_idx_tbl, i, entry) {
2158 mtr_idx = *(uint32_t *)entry;
2161 mlx5_aso_meter_by_idx(priv, mtr_idx);
2163 (void)mlx5_flow_meter_params_flush(dev,
2167 mlx5_l3t_destroy(priv->mtr_idx_tbl);
2168 priv->mtr_idx_tbl = NULL;
2171 RTE_TAILQ_FOREACH_SAFE(legacy_fm, fms, next, tmp) {
2172 fm = &legacy_fm->fm;
2173 if (mlx5_flow_meter_params_flush(dev, fm, 0))
2174 return -rte_mtr_error_set(error, EINVAL,
2175 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
2176 NULL, "MTR object meter profile invalid.");
2179 if (priv->policy_idx_tbl) {
2180 MLX5_L3T_FOREACH(priv->policy_idx_tbl, i, entry) {
2181 policy_idx = *(uint32_t *)entry;
2182 sub_policy = mlx5_ipool_get
2183 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
2186 return -rte_mtr_error_set(error,
2188 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2190 "meter policy invalid.");
2191 if (__mlx5_flow_meter_policy_delete(dev, i,
2192 sub_policy->main_policy,
2194 return -rte_mtr_error_set(error,
2196 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2198 "meter policy invalid.");
2199 mlx5_free(sub_policy->main_policy);
2201 mlx5_l3t_destroy(priv->policy_idx_tbl);
2202 priv->policy_idx_tbl = NULL;
2204 if (priv->mtr_profile_tbl) {
2205 MLX5_L3T_FOREACH(priv->mtr_profile_tbl, i, entry) {
2207 if (mlx5_flow_meter_profile_delete(dev, fmp->id,
2209 return -rte_mtr_error_set(error, EINVAL,
2210 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2211 NULL, "Fail to destroy "
2214 mlx5_l3t_destroy(priv->mtr_profile_tbl);
2215 priv->mtr_profile_tbl = NULL;
2217 /* Delete default policy table. */
2218 mlx5_flow_destroy_def_policy(dev);
2219 if (priv->sh->refcnt == 1)
2220 mlx5_flow_destroy_mtr_drop_tbls(dev);