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_CIR_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_mtr_profiles *fmps = &priv->flow_meter_profiles;
95 struct mlx5_flow_meter_profile *fmp;
97 TAILQ_FOREACH(fmp, fmps, next)
98 if (meter_profile_id == fmp->id)
104 * Validate the MTR profile.
107 * Pointer to Ethernet device.
108 * @param[in] meter_profile_id
111 * Pointer to meter profile detail.
113 * Pointer to the error structure.
116 * 0 on success, a negative errno value otherwise and rte_errno is set.
119 mlx5_flow_meter_profile_validate(struct rte_eth_dev *dev,
120 uint32_t meter_profile_id,
121 struct rte_mtr_meter_profile *profile,
122 struct rte_mtr_error *error)
124 struct mlx5_priv *priv = dev->data->dev_private;
125 struct mlx5_flow_meter_profile *fmp;
127 /* Profile must not be NULL. */
129 return -rte_mtr_error_set(error, EINVAL,
130 RTE_MTR_ERROR_TYPE_METER_PROFILE,
131 NULL, "Meter profile is null.");
132 /* Meter profile ID must be valid. */
133 if (meter_profile_id == UINT32_MAX)
134 return -rte_mtr_error_set(error, EINVAL,
135 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
136 NULL, "Meter profile id not valid.");
137 /* Meter profile must not exist. */
138 fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id);
140 return -rte_mtr_error_set(error, EEXIST,
141 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
143 "Meter profile already exists.");
144 if (profile->alg == RTE_MTR_SRTCM_RFC2697) {
145 if (priv->config.hca_attr.qos.flow_meter_old) {
146 /* Verify support for flow meter parameters. */
147 if (profile->srtcm_rfc2697.cir > 0 &&
148 profile->srtcm_rfc2697.cir <= MLX5_SRTCM_CIR_MAX &&
149 profile->srtcm_rfc2697.cbs > 0 &&
150 profile->srtcm_rfc2697.cbs <= MLX5_SRTCM_CBS_MAX &&
151 profile->srtcm_rfc2697.ebs <= MLX5_SRTCM_EBS_MAX)
154 return -rte_mtr_error_set
156 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
158 profile->srtcm_rfc2697.ebs ?
159 "Metering value ebs must be 0." :
160 "Invalid metering parameters.");
163 return -rte_mtr_error_set(error, ENOTSUP,
164 RTE_MTR_ERROR_TYPE_METER_PROFILE,
165 NULL, "Metering algorithm not supported.");
169 * Calculate mantissa and exponent for cir.
172 * Value to be calculated.
174 * Pointer to the mantissa.
176 * Pointer to the exp.
179 mlx5_flow_meter_cir_man_exp_calc(int64_t cir, uint8_t *man, uint8_t *exp)
182 int64_t delta = INT64_MAX;
187 for (m = 0; m <= 0xFF; m++) { /* man width 8 bit */
188 for (e = 0; e <= 0x1F; e++) { /* exp width 5bit */
189 _cir = (1000000000ULL * m) >> e;
190 if (llabs(cir - _cir) <= delta) {
191 delta = llabs(cir - _cir);
202 * Calculate mantissa and exponent for xbs.
205 * Value to be calculated.
207 * Pointer to the mantissa.
209 * Pointer to the exp.
212 mlx5_flow_meter_xbs_man_exp_calc(uint64_t xbs, uint8_t *man, uint8_t *exp)
217 /* Special case xbs == 0 ? both exp and matissa are 0. */
223 /* xbs = xbs_mantissa * 2^xbs_exponent */
224 _man = frexp(xbs, &_exp);
225 _man = _man * pow(2, MLX5_MAN_WIDTH);
226 _exp = _exp - MLX5_MAN_WIDTH;
227 *man = (uint8_t)ceil(_man);
232 * Fill the prm meter parameter.
235 * Pointer to meter profie to be converted.
237 * Pointer to the error structure.
240 * 0 on success, a negative errno value otherwise and rte_errno is set.
243 mlx5_flow_meter_param_fill(struct mlx5_flow_meter_profile *fmp,
244 struct rte_mtr_error *error)
246 struct mlx5_flow_meter_srtcm_rfc2697_prm *srtcm = &fmp->srtcm_prm;
248 uint32_t cbs_exp, cbs_man, cir_exp, cir_man;
249 uint32_t ebs_exp, ebs_man;
251 if (fmp->profile.alg != RTE_MTR_SRTCM_RFC2697)
252 return -rte_mtr_error_set(error, ENOTSUP,
253 RTE_MTR_ERROR_TYPE_METER_PROFILE,
254 NULL, "Metering algorithm not supported.");
255 /* cir = 8G * cir_mantissa * 1/(2^cir_exponent)) Bytes/Sec */
256 mlx5_flow_meter_cir_man_exp_calc(fmp->profile.srtcm_rfc2697.cir,
258 /* Check if cir mantissa is too large. */
259 if (exp > ASO_DSEG_CIR_EXP_MASK)
260 return -rte_mtr_error_set(error, ENOTSUP,
261 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
262 "meter profile parameter cir is"
266 /* cbs = cbs_mantissa * 2^cbs_exponent */
267 mlx5_flow_meter_xbs_man_exp_calc(fmp->profile.srtcm_rfc2697.cbs,
269 /* Check if cbs mantissa is too large. */
270 if (exp > ASO_DSEG_EXP_MASK)
271 return -rte_mtr_error_set(error, ENOTSUP,
272 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
273 "meter profile parameter cbs is"
277 srtcm->cbs_cir = rte_cpu_to_be_32(cbs_exp << ASO_DSEG_CBS_EXP_OFFSET |
278 cbs_man << ASO_DSEG_CBS_MAN_OFFSET |
279 cir_exp << ASO_DSEG_CIR_EXP_OFFSET |
281 mlx5_flow_meter_xbs_man_exp_calc(fmp->profile.srtcm_rfc2697.ebs,
283 /* Check if ebs mantissa is too large. */
284 if (exp > ASO_DSEG_EXP_MASK)
285 return -rte_mtr_error_set(error, ENOTSUP,
286 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
287 "meter profile parameter ebs is"
291 srtcm->ebs_eir = rte_cpu_to_be_32(ebs_exp << ASO_DSEG_EBS_EXP_OFFSET |
292 ebs_man << ASO_DSEG_EBS_MAN_OFFSET);
297 * Callback to get MTR capabilities.
300 * Pointer to Ethernet device.
302 * Pointer to save MTR capabilities.
304 * Pointer to the error structure.
307 * 0 on success, a negative errno value otherwise and rte_errno is set.
310 mlx5_flow_mtr_cap_get(struct rte_eth_dev *dev,
311 struct rte_mtr_capabilities *cap,
312 struct rte_mtr_error *error __rte_unused)
314 struct mlx5_priv *priv = dev->data->dev_private;
315 struct mlx5_hca_qos_attr *qattr = &priv->config.hca_attr.qos;
318 return -rte_mtr_error_set(error, ENOTSUP,
319 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
320 "Meter is not supported");
321 memset(cap, 0, sizeof(*cap));
322 if (priv->sh->meter_aso_en)
323 /* 2 meters per one ASO cache line. */
324 cap->n_max = 1 << (qattr->log_max_num_meter_aso + 1);
326 cap->n_max = 1 << qattr->log_max_flow_meter;
327 cap->n_shared_max = cap->n_max;
329 cap->shared_identical = 1;
330 cap->shared_n_flows_per_mtr_max = 4 << 20;
331 /* 2M flows can share the same meter. */
332 cap->chaining_n_mtrs_per_flow_max = 1; /* Chaining is not supported. */
333 cap->meter_srtcm_rfc2697_n_max = qattr->flow_meter_old ? cap->n_max : 0;
334 cap->meter_rate_max = 1ULL << 40; /* 1 Tera tokens per sec. */
335 cap->stats_mask = RTE_MTR_STATS_N_BYTES_DROPPED |
336 RTE_MTR_STATS_N_PKTS_DROPPED;
341 * Callback to add MTR profile.
344 * Pointer to Ethernet device.
345 * @param[in] meter_profile_id
348 * Pointer to meter profile detail.
350 * Pointer to the error structure.
353 * 0 on success, a negative errno value otherwise and rte_errno is set.
356 mlx5_flow_meter_profile_add(struct rte_eth_dev *dev,
357 uint32_t meter_profile_id,
358 struct rte_mtr_meter_profile *profile,
359 struct rte_mtr_error *error)
361 struct mlx5_priv *priv = dev->data->dev_private;
362 struct mlx5_mtr_profiles *fmps = &priv->flow_meter_profiles;
363 struct mlx5_flow_meter_profile *fmp;
367 return -rte_mtr_error_set(error, ENOTSUP,
368 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
369 "Meter is not supported");
370 /* Check input params. */
371 ret = mlx5_flow_meter_profile_validate(dev, meter_profile_id,
375 /* Meter profile memory allocation. */
376 fmp = mlx5_malloc(MLX5_MEM_ZERO, sizeof(struct mlx5_flow_meter_profile),
377 RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
379 return -rte_mtr_error_set(error, ENOMEM,
380 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
381 NULL, "Meter profile memory "
383 /* Fill profile info. */
384 fmp->id = meter_profile_id;
385 fmp->profile = *profile;
386 /* Fill the flow meter parameters for the PRM. */
387 ret = mlx5_flow_meter_param_fill(fmp, error);
391 TAILQ_INSERT_TAIL(fmps, fmp, next);
399 * Callback to delete MTR profile.
402 * Pointer to Ethernet device.
403 * @param[in] meter_profile_id
406 * Pointer to the error structure.
409 * 0 on success, a negative errno value otherwise and rte_errno is set.
412 mlx5_flow_meter_profile_delete(struct rte_eth_dev *dev,
413 uint32_t meter_profile_id,
414 struct rte_mtr_error *error)
416 struct mlx5_priv *priv = dev->data->dev_private;
417 struct mlx5_flow_meter_profile *fmp;
420 return -rte_mtr_error_set(error, ENOTSUP,
421 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
422 "Meter is not supported");
423 /* Meter profile must exist. */
424 fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id);
426 return -rte_mtr_error_set(error, ENOENT,
427 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
429 "Meter profile id is invalid.");
430 /* Check profile is unused. */
432 return -rte_mtr_error_set(error, EBUSY,
433 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
434 NULL, "Meter profile is in use.");
435 /* Remove from list. */
436 TAILQ_REMOVE(&priv->flow_meter_profiles, fmp, next);
445 * Pointer to Ethernet device.
450 * Pointer to the policy found on success, NULL otherwise.
452 struct mlx5_flow_meter_policy *
453 mlx5_flow_meter_policy_find(struct rte_eth_dev *dev,
455 uint32_t *policy_idx)
457 struct mlx5_priv *priv = dev->data->dev_private;
458 struct mlx5_flow_meter_sub_policy *sub_policy = NULL;
459 union mlx5_l3t_data data;
461 if (policy_id > MLX5_MAX_SUB_POLICY_TBL_NUM ||
462 !priv->sh->mtrmng->policy_idx_tbl)
464 if (mlx5_l3t_get_entry(priv->sh->mtrmng->policy_idx_tbl,
469 *policy_idx = data.dword;
470 sub_policy = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
472 /* Remove reference taken by the mlx5_l3t_get_entry. */
473 mlx5_l3t_clear_entry(priv->sh->mtrmng->policy_idx_tbl,
476 if (sub_policy->main_policy_id)
477 return sub_policy->main_policy;
482 * Callback to check MTR policy action validate
485 * Pointer to Ethernet device.
487 * Pointer to meter policy action detail.
489 * Pointer to the error structure.
492 * 0 on success, a negative errno value otherwise and rte_errno is set.
495 mlx5_flow_meter_policy_validate(struct rte_eth_dev *dev,
496 struct rte_mtr_meter_policy_params *policy,
497 struct rte_mtr_error *error)
499 struct mlx5_priv *priv = dev->data->dev_private;
500 struct rte_flow_attr attr = { .transfer =
501 priv->config.dv_esw_en ? 1 : 0};
503 bool is_def_policy = false;
504 uint8_t domain_bitmap;
507 if (!priv->mtr_en || !priv->sh->meter_aso_en)
508 return -rte_mtr_error_set(error, ENOTSUP,
509 RTE_MTR_ERROR_TYPE_METER_POLICY,
510 NULL, "meter policy unsupported.");
511 ret = mlx5_flow_validate_mtr_acts(dev, policy->actions, &attr,
512 &is_rss, &domain_bitmap, &is_def_policy, error);
519 __mlx5_flow_meter_policy_delete(struct rte_eth_dev *dev,
521 struct mlx5_flow_meter_policy *mtr_policy,
522 struct rte_mtr_error *error)
524 struct mlx5_priv *priv = dev->data->dev_private;
525 struct mlx5_flow_meter_sub_policy *sub_policy;
527 uint16_t sub_policy_num;
529 rte_spinlock_lock(&mtr_policy->sl);
530 if (mtr_policy->ref_cnt) {
531 rte_spinlock_unlock(&mtr_policy->sl);
532 return -rte_mtr_error_set(error, EBUSY,
533 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
535 "Meter policy object is being used.");
537 mlx5_flow_destroy_policy_rules(dev, mtr_policy);
538 mlx5_flow_destroy_mtr_acts(dev, mtr_policy);
539 for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
540 sub_policy_num = (mtr_policy->sub_policy_num >>
541 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i)) &
542 MLX5_MTR_SUB_POLICY_NUM_MASK;
543 if (sub_policy_num) {
544 for (j = 0; j < sub_policy_num; j++) {
545 sub_policy = mtr_policy->sub_policys[i][j];
548 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
553 if (priv->sh->mtrmng->policy_idx_tbl) {
554 if (mlx5_l3t_clear_entry(priv->sh->mtrmng->policy_idx_tbl,
556 rte_spinlock_unlock(&mtr_policy->sl);
557 return -rte_mtr_error_set(error, ENOTSUP,
558 RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL,
559 "Fail to delete policy in index table.");
562 rte_spinlock_unlock(&mtr_policy->sl);
567 * Callback to add MTR policy.
570 * Pointer to Ethernet device.
571 * @param[out] policy_id
572 * Pointer to policy id
574 * Pointer to meter policy action detail.
576 * Pointer to the error structure.
579 * 0 on success, a negative errno value otherwise and rte_errno is set.
582 mlx5_flow_meter_policy_add(struct rte_eth_dev *dev,
584 struct rte_mtr_meter_policy_params *policy,
585 struct rte_mtr_error *error)
587 struct mlx5_priv *priv = dev->data->dev_private;
588 struct rte_flow_attr attr = { .transfer =
589 priv->config.dv_esw_en ? 1 : 0};
590 uint32_t sub_policy_idx = 0;
591 uint32_t policy_idx = 0;
592 struct mlx5_flow_meter_policy *mtr_policy = NULL;
593 struct mlx5_flow_meter_sub_policy *sub_policy;
595 bool is_def_policy = false;
598 uint32_t policy_size = sizeof(struct mlx5_flow_meter_policy);
599 uint16_t sub_policy_num;
600 uint8_t domain_bitmap = 0;
601 union mlx5_l3t_data data;
604 return -rte_mtr_error_set(error, ENOTSUP,
605 RTE_MTR_ERROR_TYPE_METER_POLICY,
606 NULL, "meter policy unsupported.");
607 if (policy_id == MLX5_INVALID_POLICY_ID)
608 return -rte_mtr_error_set(error, ENOTSUP,
609 RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL,
610 "policy ID is invalid. ");
611 if (policy_id == priv->sh->mtrmng->def_policy_id)
612 return -rte_mtr_error_set(error, EEXIST,
613 RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL,
614 "policy ID exists. ");
615 mtr_policy = mlx5_flow_meter_policy_find(dev, policy_id,
618 return -rte_mtr_error_set(error, EEXIST,
619 RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL,
620 "policy ID exists. ");
621 ret = mlx5_flow_validate_mtr_acts(dev, policy->actions, &attr,
622 &is_rss, &domain_bitmap, &is_def_policy, error);
626 return -rte_mtr_error_set(error, ENOTSUP,
627 RTE_MTR_ERROR_TYPE_METER_POLICY,
628 NULL, "fail to find policy domain.");
630 if (priv->sh->mtrmng->def_policy_id != MLX5_INVALID_POLICY_ID)
631 return -rte_mtr_error_set(error, EEXIST,
632 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
633 NULL, "a policy with similar actions "
634 "is already configured");
635 if (mlx5_flow_create_def_policy(dev))
636 return -rte_mtr_error_set(error, ENOTSUP,
637 RTE_MTR_ERROR_TYPE_METER_POLICY,
639 "fail to create non-terminated policy.");
640 priv->sh->mtrmng->def_policy_id = policy_id;
643 if (!priv->sh->meter_aso_en)
644 return -rte_mtr_error_set(error, ENOTSUP,
645 RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
646 "no ASO capability to support the policy ");
647 for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
648 if (!(domain_bitmap & (1 << i)))
652 sizeof(struct mlx5_flow_meter_sub_policy *) *
653 MLX5_MTR_RSS_MAX_SUB_POLICY;
656 policy_size += sizeof(struct mlx5_flow_meter_sub_policy *);
658 mtr_policy = mlx5_malloc(MLX5_MEM_ZERO, policy_size,
659 RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
661 return -rte_mtr_error_set(error, ENOMEM,
662 RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
663 "Memory alloc failed for meter policy.");
664 policy_size = sizeof(struct mlx5_flow_meter_policy);
665 for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
666 if (!(domain_bitmap & (1 << i)))
668 mtr_policy->ingress = (i == MLX5_MTR_DOMAIN_INGRESS) ? 1 : 0;
669 mtr_policy->egress = (i == MLX5_MTR_DOMAIN_EGRESS) ? 1 : 0;
670 mtr_policy->transfer = (i == MLX5_MTR_DOMAIN_TRANSFER) ? 1 : 0;
671 sub_policy = mlx5_ipool_zmalloc
672 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
676 if (sub_policy_idx > MLX5_MAX_SUB_POLICY_TBL_NUM)
678 sub_policy->idx = sub_policy_idx;
679 sub_policy->main_policy = mtr_policy;
681 policy_idx = sub_policy_idx;
682 sub_policy->main_policy_id = 1;
684 mtr_policy->sub_policys[i] =
685 (struct mlx5_flow_meter_sub_policy **)
686 ((uint8_t *)mtr_policy + policy_size);
687 mtr_policy->sub_policys[i][0] = sub_policy;
688 sub_policy_num = (mtr_policy->sub_policy_num >>
689 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i)) &
690 MLX5_MTR_SUB_POLICY_NUM_MASK;
692 mtr_policy->sub_policy_num &= ~(MLX5_MTR_SUB_POLICY_NUM_MASK <<
693 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i));
694 mtr_policy->sub_policy_num |=
695 (sub_policy_num & MLX5_MTR_SUB_POLICY_NUM_MASK) <<
696 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i);
698 mtr_policy->is_rss = 1;
701 policy_size += sizeof(struct mlx5_flow_meter_sub_policy *);
703 rte_spinlock_init(&mtr_policy->sl);
704 ret = mlx5_flow_create_mtr_acts(dev, mtr_policy,
705 policy->actions, error);
709 /* Create policy rules in HW. */
710 ret = mlx5_flow_create_policy_rules(dev, mtr_policy);
714 data.dword = policy_idx;
715 if (!priv->sh->mtrmng->policy_idx_tbl) {
716 priv->sh->mtrmng->policy_idx_tbl =
717 mlx5_l3t_create(MLX5_L3T_TYPE_DWORD);
718 if (!priv->sh->mtrmng->policy_idx_tbl)
721 if (mlx5_l3t_set_entry(priv->sh->mtrmng->policy_idx_tbl,
727 ret = __mlx5_flow_meter_policy_delete(dev, policy_id,
729 mlx5_free(mtr_policy);
733 return -rte_mtr_error_set(error, ENOTSUP,
734 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
735 NULL, "Failed to create devx policy.");
739 * Callback to delete MTR policy.
742 * Pointer to Ethernet device.
743 * @param[in] policy_id
746 * Pointer to the error structure.
749 * 0 on success, a negative errno value otherwise and rte_errno is set.
752 mlx5_flow_meter_policy_delete(struct rte_eth_dev *dev,
754 struct rte_mtr_error *error)
756 struct mlx5_priv *priv = dev->data->dev_private;
757 struct mlx5_flow_meter_policy *mtr_policy;
761 if (policy_id == priv->sh->mtrmng->def_policy_id) {
762 if (priv->sh->mtrmng->def_policy_ref_cnt > 0)
763 return -rte_mtr_error_set(error, ENOTSUP,
764 RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL,
765 "Meter policy object is being used.");
766 priv->sh->mtrmng->def_policy_id = MLX5_INVALID_POLICY_ID;
769 mtr_policy = mlx5_flow_meter_policy_find(dev, policy_id, &policy_idx);
771 return -rte_mtr_error_set(error, ENOTSUP,
772 RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL,
773 "Meter policy id is invalid. ");
774 ret = __mlx5_flow_meter_policy_delete(dev, policy_id, mtr_policy,
778 mlx5_free(mtr_policy);
783 * Modify the flow meter action.
786 * Pointer to mlx5 private data structure.
788 * Pointer to flow meter to be modified.
790 * Pointer to meter srtcm description parameter.
791 * @param[in] modify_bits
792 * The bit in srtcm to be updated.
793 * @param[in] active_state
794 * The state to be updated.
796 * 0 on success, o negative value otherwise.
799 mlx5_flow_meter_action_modify(struct mlx5_priv *priv,
800 struct mlx5_flow_meter_info *fm,
801 const struct mlx5_flow_meter_srtcm_rfc2697_prm *srtcm,
802 uint64_t modify_bits, uint32_t active_state, uint32_t is_enable)
804 #ifdef HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER
805 uint32_t in[MLX5_ST_SZ_DW(flow_meter_parameters)] = { 0 };
807 struct mlx5dv_dr_flow_meter_attr mod_attr = { 0 };
809 struct mlx5_aso_mtr *aso_mtr = NULL;
810 uint32_t cbs_cir, ebs_eir, val;
812 if (priv->sh->meter_aso_en) {
813 fm->is_enable = !!is_enable;
814 aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
815 ret = mlx5_aso_meter_update_by_wqe(priv->sh, aso_mtr);
818 ret = mlx5_aso_mtr_wait(priv->sh, aso_mtr);
822 /* Fill command parameters. */
823 mod_attr.reg_c_index = priv->mtr_color_reg - REG_C_0;
824 mod_attr.flow_meter_parameter = in;
825 mod_attr.flow_meter_parameter_sz =
826 MLX5_ST_SZ_BYTES(flow_meter_parameters);
827 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_ACTIVE)
828 mod_attr.active = !!active_state;
832 cbs_cir = rte_be_to_cpu_32(srtcm->cbs_cir);
833 ebs_eir = rte_be_to_cpu_32(srtcm->ebs_eir);
834 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS) {
835 val = (cbs_cir >> ASO_DSEG_CBS_EXP_OFFSET) &
837 MLX5_SET(flow_meter_parameters, attr,
839 val = (cbs_cir >> ASO_DSEG_CBS_MAN_OFFSET) &
841 MLX5_SET(flow_meter_parameters, attr,
844 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR) {
845 val = (cbs_cir >> ASO_DSEG_CIR_EXP_OFFSET) &
847 MLX5_SET(flow_meter_parameters, attr,
849 val = cbs_cir & ASO_DSEG_MAN_MASK;
850 MLX5_SET(flow_meter_parameters, attr,
853 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_EBS) {
854 val = (ebs_eir >> ASO_DSEG_EBS_EXP_OFFSET) &
856 MLX5_SET(flow_meter_parameters, attr,
858 val = (ebs_eir >> ASO_DSEG_EBS_MAN_OFFSET) &
860 MLX5_SET(flow_meter_parameters, attr,
863 /* Apply modifications to meter only if it was created. */
864 if (fm->meter_action) {
865 ret = mlx5_glue->dv_modify_flow_action_meter
866 (fm->meter_action, &mod_attr,
867 rte_cpu_to_be_64(modify_bits));
871 /* Update succeedded modify meter parameters. */
872 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_ACTIVE)
873 fm->active_state = !!active_state;
888 mlx5_flow_meter_stats_enable_update(struct mlx5_flow_meter_info *fm,
892 (stats_mask & RTE_MTR_STATS_N_BYTES_DROPPED) ? 1 : 0;
893 fm->pkts_dropped = (stats_mask & RTE_MTR_STATS_N_PKTS_DROPPED) ? 1 : 0;
897 mlx5_flow_meter_params_flush(struct rte_eth_dev *dev,
898 struct mlx5_flow_meter_info *fm,
901 struct mlx5_priv *priv = dev->data->dev_private;
902 struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
903 struct mlx5_flow_meter_profile *fmp;
904 struct mlx5_legacy_flow_meter *legacy_fm = NULL;
906 /* Meter object must not have any owner. */
907 MLX5_ASSERT(!fm->ref_cnt);
908 /* Get meter profile. */
912 /* Update dependencies. */
913 __atomic_sub_fetch(&fmp->ref_cnt, 1, __ATOMIC_RELAXED);
914 /* Remove from list. */
915 if (!priv->sh->meter_aso_en) {
916 legacy_fm = container_of(fm, struct mlx5_legacy_flow_meter, fm);
917 TAILQ_REMOVE(fms, legacy_fm, next);
919 /* Free drop counters. */
921 mlx5_counter_free(dev, fm->drop_cnt);
922 /* Free meter flow table. */
924 mlx5_ipool_destroy(fm->flow_ipool);
925 mlx5_flow_destroy_mtr_tbls(dev, fm->mfts);
926 if (priv->sh->meter_aso_en)
927 mlx5_flow_mtr_free(dev, mtr_idx);
929 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR],
935 * Destroy meter rules.
938 * Pointer to Ethernet device.
939 * @param[in] meter_id
942 * Pointer to rte meter error structure.
945 * 0 on success, a negative errno value otherwise and rte_errno is set.
948 mlx5_flow_meter_destroy(struct rte_eth_dev *dev, uint32_t meter_id,
949 struct rte_mtr_error *error)
951 struct mlx5_priv *priv = dev->data->dev_private;
952 struct mlx5_flow_meter_info *fm;
953 uint32_t mtr_idx = 0;
956 return -rte_mtr_error_set(error, ENOTSUP,
957 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
958 "Meter is not supported");
959 /* Meter object must exist. */
960 fm = mlx5_flow_meter_find(priv, meter_id, &mtr_idx);
962 return -rte_mtr_error_set(error, ENOENT,
963 RTE_MTR_ERROR_TYPE_MTR_ID,
964 NULL, "Meter object id not valid.");
965 /* Meter object must not have any owner. */
967 return -rte_mtr_error_set(error, EBUSY,
968 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
969 NULL, "Meter object is being used.");
970 if (priv->sh->meter_aso_en) {
971 if (mlx5_l3t_clear_entry(priv->mtr_idx_tbl, meter_id))
972 return -rte_mtr_error_set(error, EBUSY,
973 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
974 "Fail to delete ASO Meter in index table.");
976 /* Destroy the meter profile. */
977 if (mlx5_flow_meter_params_flush(dev, fm, mtr_idx))
978 return -rte_mtr_error_set(error, EINVAL,
979 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
980 NULL, "MTR object meter profile invalid.");
985 * Modify meter state.
988 * Pointer to mlx5 private data structure.
990 * Pointer to flow meter.
991 * @param[in] new_state
992 * New state to update.
994 * Pointer to rte meter error structure.
997 * 0 on success, a negative errno value otherwise and rte_errno is set.
1000 mlx5_flow_meter_modify_state(struct mlx5_priv *priv,
1001 struct mlx5_flow_meter_info *fm,
1003 struct rte_mtr_error *error)
1005 static const struct mlx5_flow_meter_srtcm_rfc2697_prm srtcm = {
1006 .cbs_cir = RTE_BE32(MLX5_IFC_FLOW_METER_DISABLE_CBS_CIR_VAL),
1009 uint64_t modify_bits = MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS |
1010 MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR;
1013 if (new_state == MLX5_FLOW_METER_DISABLE)
1014 ret = mlx5_flow_meter_action_modify(priv, fm,
1015 &srtcm, modify_bits, 0, 0);
1017 ret = mlx5_flow_meter_action_modify(priv, fm,
1018 &fm->profile->srtcm_prm,
1021 return -rte_mtr_error_set(error, -ret,
1022 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
1025 "Failed to enable meter." :
1026 "Failed to disable meter.");
1031 * Callback to enable flow meter.
1034 * Pointer to Ethernet device.
1035 * @param[in] meter_id
1038 * Pointer to rte meter error structure.
1041 * 0 on success, a negative errno value otherwise and rte_errno is set.
1044 mlx5_flow_meter_enable(struct rte_eth_dev *dev,
1046 struct rte_mtr_error *error)
1048 struct mlx5_priv *priv = dev->data->dev_private;
1049 struct mlx5_flow_meter_info *fm;
1053 return -rte_mtr_error_set(error, ENOTSUP,
1054 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1055 "Meter is not supported");
1056 /* Meter object must exist. */
1057 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1059 return -rte_mtr_error_set(error, ENOENT,
1060 RTE_MTR_ERROR_TYPE_MTR_ID,
1061 NULL, "Meter not found.");
1062 if (fm->active_state == MLX5_FLOW_METER_ENABLE)
1064 ret = mlx5_flow_meter_modify_state(priv, fm, MLX5_FLOW_METER_ENABLE,
1067 fm->active_state = MLX5_FLOW_METER_ENABLE;
1072 * Callback to disable flow meter.
1075 * Pointer to Ethernet device.
1076 * @param[in] meter_id
1079 * Pointer to rte meter error structure.
1082 * 0 on success, a negative errno value otherwise and rte_errno is set.
1085 mlx5_flow_meter_disable(struct rte_eth_dev *dev,
1087 struct rte_mtr_error *error)
1089 struct mlx5_priv *priv = dev->data->dev_private;
1090 struct mlx5_flow_meter_info *fm;
1094 return -rte_mtr_error_set(error, ENOTSUP,
1095 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1096 "Meter is not supported");
1097 /* Meter object must exist. */
1098 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1100 return -rte_mtr_error_set(error, ENOENT,
1101 RTE_MTR_ERROR_TYPE_MTR_ID,
1102 NULL, "Meter not found.");
1103 if (fm->active_state == MLX5_FLOW_METER_DISABLE)
1105 ret = mlx5_flow_meter_modify_state(priv, fm, MLX5_FLOW_METER_DISABLE,
1108 fm->active_state = MLX5_FLOW_METER_DISABLE;
1113 * Callback to update meter profile.
1116 * Pointer to Ethernet device.
1117 * @param[in] meter_id
1119 * @param[in] meter_profile_id
1120 * To be updated meter profile id.
1122 * Pointer to rte meter error structure.
1125 * 0 on success, a negative errno value otherwise and rte_errno is set.
1128 mlx5_flow_meter_profile_update(struct rte_eth_dev *dev,
1130 uint32_t meter_profile_id,
1131 struct rte_mtr_error *error)
1133 struct mlx5_priv *priv = dev->data->dev_private;
1134 struct mlx5_flow_meter_profile *fmp;
1135 struct mlx5_flow_meter_profile *old_fmp;
1136 struct mlx5_flow_meter_info *fm;
1137 uint64_t modify_bits = MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS |
1138 MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR;
1142 return -rte_mtr_error_set(error, ENOTSUP,
1143 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1144 "Meter is not supported");
1145 /* Meter profile must exist. */
1146 fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id);
1148 return -rte_mtr_error_set(error, ENOENT,
1149 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
1150 NULL, "Meter profile not found.");
1151 /* Meter object must exist. */
1152 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1154 return -rte_mtr_error_set(error, ENOENT,
1155 RTE_MTR_ERROR_TYPE_MTR_ID,
1156 NULL, "Meter not found.");
1157 /* MTR object already set to meter profile id. */
1158 old_fmp = fm->profile;
1161 /* Update the profile. */
1163 /* Update meter params in HW (if not disabled). */
1164 if (fm->active_state == MLX5_FLOW_METER_DISABLE)
1166 ret = mlx5_flow_meter_action_modify(priv, fm, &fm->profile->srtcm_prm,
1167 modify_bits, fm->active_state, 1);
1169 fm->profile = old_fmp;
1170 return -rte_mtr_error_set(error, -ret,
1171 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
1172 NULL, "Failed to update meter"
1173 " parmeters in hardware.");
1181 * Callback to update meter stats mask.
1184 * Pointer to Ethernet device.
1185 * @param[in] meter_id
1187 * @param[in] stats_mask
1188 * To be updated stats_mask.
1190 * Pointer to rte meter error structure.
1193 * 0 on success, a negative errno value otherwise and rte_errno is set.
1196 mlx5_flow_meter_stats_update(struct rte_eth_dev *dev,
1198 uint64_t stats_mask,
1199 struct rte_mtr_error *error)
1201 struct mlx5_priv *priv = dev->data->dev_private;
1202 struct mlx5_flow_meter_info *fm;
1205 return -rte_mtr_error_set(error, ENOTSUP,
1206 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1207 "Meter is not supported");
1208 /* Meter object must exist. */
1209 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1211 return -rte_mtr_error_set(error, ENOENT,
1212 RTE_MTR_ERROR_TYPE_MTR_ID,
1213 NULL, "Meter object id not valid.");
1214 mlx5_flow_meter_stats_enable_update(fm, stats_mask);
1219 * Callback to read meter statistics.
1222 * Pointer to Ethernet device.
1223 * @param[in] meter_id
1226 * Pointer to store the statistics.
1227 * @param[out] stats_mask
1228 * Pointer to store the stats_mask.
1230 * Statistic to be cleared after read or not.
1232 * Pointer to rte meter error structure.
1235 * 0 on success, a negative errno value otherwise and rte_errno is set.
1238 mlx5_flow_meter_stats_read(struct rte_eth_dev *dev,
1240 struct rte_mtr_stats *stats,
1241 uint64_t *stats_mask,
1243 struct rte_mtr_error *error)
1245 struct mlx5_priv *priv = dev->data->dev_private;
1246 struct mlx5_flow_meter_info *fm;
1252 return -rte_mtr_error_set(error, ENOTSUP,
1253 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1254 "Meter is not supported");
1255 /* Meter object must exist. */
1256 fm = mlx5_flow_meter_find(priv, meter_id, NULL);
1258 return -rte_mtr_error_set(error, ENOENT,
1259 RTE_MTR_ERROR_TYPE_MTR_ID,
1260 NULL, "Meter object id not valid.");
1262 if (fm->bytes_dropped)
1263 *stats_mask |= RTE_MTR_STATS_N_BYTES_DROPPED;
1264 if (fm->pkts_dropped)
1265 *stats_mask |= RTE_MTR_STATS_N_PKTS_DROPPED;
1266 memset(stats, 0, sizeof(*stats));
1268 ret = mlx5_counter_query(dev, fm->drop_cnt, clear, &pkts,
1272 /* If need to read the packets, set it. */
1273 if (fm->pkts_dropped)
1274 stats->n_pkts_dropped = pkts;
1275 /* If need to read the bytes, set it. */
1276 if (fm->bytes_dropped)
1277 stats->n_bytes_dropped = bytes;
1281 return -rte_mtr_error_set(error, ret, RTE_MTR_ERROR_TYPE_STATS, NULL,
1282 "Failed to read meter drop counters.");
1285 static const struct rte_mtr_ops mlx5_flow_mtr_ops = {
1286 .capabilities_get = mlx5_flow_mtr_cap_get,
1287 .meter_profile_add = mlx5_flow_meter_profile_add,
1288 .meter_profile_delete = mlx5_flow_meter_profile_delete,
1289 .meter_policy_validate = mlx5_flow_meter_policy_validate,
1290 .meter_policy_add = mlx5_flow_meter_policy_add,
1291 .meter_policy_delete = mlx5_flow_meter_policy_delete,
1292 .destroy = mlx5_flow_meter_destroy,
1293 .meter_enable = mlx5_flow_meter_enable,
1294 .meter_disable = mlx5_flow_meter_disable,
1295 .meter_profile_update = mlx5_flow_meter_profile_update,
1296 .meter_dscp_table_update = NULL,
1297 .stats_update = mlx5_flow_meter_stats_update,
1298 .stats_read = mlx5_flow_meter_stats_read,
1302 * Get meter operations.
1305 * Pointer to Ethernet device structure.
1307 * Pointer to set the mtr operations.
1313 mlx5_flow_meter_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)
1315 *(const struct rte_mtr_ops **)arg = &mlx5_flow_mtr_ops;
1323 * Pointer to mlx5_priv.
1327 * Pointer to Meter index.
1330 * Pointer to the profile found on success, NULL otherwise.
1332 struct mlx5_flow_meter_info *
1333 mlx5_flow_meter_find(struct mlx5_priv *priv, uint32_t meter_id,
1336 struct mlx5_legacy_flow_meter *legacy_fm;
1337 struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
1338 struct mlx5_aso_mtr *aso_mtr;
1339 struct mlx5_aso_mtr_pools_mng *pools_mng =
1340 &priv->sh->mtrmng->pools_mng;
1341 union mlx5_l3t_data data;
1343 if (priv->sh->meter_aso_en) {
1344 rte_spinlock_lock(&pools_mng->mtrsl);
1345 if (priv->mtr_idx_tbl) {
1346 if (mlx5_l3t_get_entry(priv->mtr_idx_tbl,
1349 rte_spinlock_unlock(&pools_mng->mtrsl);
1353 *mtr_idx = data.dword;
1354 aso_mtr = mlx5_aso_meter_by_idx(priv, data.dword);
1355 /* Remove reference taken by the mlx5_l3t_get_entry. */
1356 mlx5_l3t_clear_entry(priv->mtr_idx_tbl, meter_id);
1359 *mtr_idx = meter_id;
1360 aso_mtr = mlx5_aso_meter_by_idx(priv, meter_id);
1362 rte_spinlock_unlock(&pools_mng->mtrsl);
1363 if (!aso_mtr || aso_mtr->state == ASO_METER_FREE)
1365 return &aso_mtr->fm;
1367 TAILQ_FOREACH(legacy_fm, fms, next)
1368 if (meter_id == legacy_fm->meter_id) {
1370 *mtr_idx = legacy_fm->idx;
1371 return &legacy_fm->fm;
1377 * Find meter by index.
1380 * Pointer to mlx5_priv.
1385 * Pointer to the profile found on success, NULL otherwise.
1387 struct mlx5_flow_meter_info *
1388 flow_dv_meter_find_by_idx(struct mlx5_priv *priv, uint32_t idx)
1390 struct mlx5_aso_mtr *aso_mtr;
1392 if (priv->sh->meter_aso_en) {
1393 aso_mtr = mlx5_aso_meter_by_idx(priv, idx);
1394 return &aso_mtr->fm;
1396 return mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MTR], idx);
1401 * Attach meter to flow.
1402 * Unidirectional Meter creation can only be done
1403 * when flow direction is known, i.e. when calling meter_attach.
1406 * Pointer to mlx5 private data.
1408 * Pointer to flow meter.
1410 * Pointer to flow attributes.
1411 * @param [out] error
1412 * Pointer to error structure.
1415 * 0 on success, a negative errno value otherwise and rte_errno is set.
1418 mlx5_flow_meter_attach(struct mlx5_priv *priv,
1419 struct mlx5_flow_meter_info *fm,
1420 const struct rte_flow_attr *attr,
1421 struct rte_flow_error *error)
1425 if (priv->sh->meter_aso_en) {
1426 struct mlx5_aso_mtr *aso_mtr;
1428 aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
1429 if (mlx5_aso_mtr_wait(priv->sh, aso_mtr)) {
1430 return rte_flow_error_set(error, ENOENT,
1431 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1433 "Timeout in meter configuration");
1435 rte_spinlock_lock(&fm->sl);
1436 if (fm->shared || !fm->ref_cnt) {
1439 rte_flow_error_set(error, EINVAL,
1440 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1441 "Meter cannot be shared");
1444 rte_spinlock_unlock(&fm->sl);
1446 rte_spinlock_lock(&fm->sl);
1447 if (fm->meter_action) {
1449 attr->transfer == fm->transfer &&
1450 attr->ingress == fm->ingress &&
1451 attr->egress == fm->egress) {
1454 rte_flow_error_set(error, EINVAL,
1455 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1457 "Meter attr not match." :
1458 "Meter cannot be shared.");
1462 fm->ingress = attr->ingress;
1463 fm->egress = attr->egress;
1464 fm->transfer = attr->transfer;
1466 /* This also creates the meter object. */
1467 fm->meter_action = mlx5_flow_meter_action_create(priv,
1469 if (!fm->meter_action) {
1474 rte_flow_error_set(error, EINVAL,
1475 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1476 "Meter action create failed.");
1480 rte_spinlock_unlock(&fm->sl);
1482 return ret ? -rte_errno : 0;
1486 * Detach meter from flow.
1489 * Pointer to mlx5 private data.
1491 * Pointer to flow meter.
1494 mlx5_flow_meter_detach(struct mlx5_priv *priv,
1495 struct mlx5_flow_meter_info *fm)
1497 #ifdef HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER
1498 rte_spinlock_lock(&fm->sl);
1499 MLX5_ASSERT(fm->ref_cnt);
1500 if (--fm->ref_cnt == 0 && !priv->sh->meter_aso_en) {
1501 mlx5_glue->destroy_flow_action(fm->meter_action);
1502 fm->meter_action = NULL;
1507 rte_spinlock_unlock(&fm->sl);
1515 * Flush meter configuration.
1518 * Pointer to Ethernet device.
1520 * Pointer to rte meter error structure.
1523 * 0 on success, a negative errno value otherwise and rte_errno is set.
1526 mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error)
1528 struct mlx5_priv *priv = dev->data->dev_private;
1529 struct mlx5_aso_mtr_pools_mng *pools_mng =
1530 &priv->sh->mtrmng->pools_mng;
1531 struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
1532 struct mlx5_mtr_profiles *fmps = &priv->flow_meter_profiles;
1533 struct mlx5_flow_meter_profile *fmp;
1534 struct mlx5_legacy_flow_meter *legacy_fm;
1535 struct mlx5_flow_meter_info *fm;
1536 struct mlx5_aso_mtr_pool *mtr_pool;
1537 struct mlx5_flow_meter_sub_policy *sub_policy;
1539 uint32_t i, offset, mtr_idx, policy_idx;
1544 if (priv->sh->meter_aso_en) {
1545 i = pools_mng->n_valid;
1547 mtr_pool = pools_mng->pools[i];
1548 for (offset = 0; offset < MLX5_ASO_MTRS_PER_POOL;
1550 fm = &mtr_pool->mtrs[offset].fm;
1551 mtr_idx = MLX5_MAKE_MTR_IDX(i, offset);
1552 (void)mlx5_flow_meter_params_flush(dev,
1557 TAILQ_FOREACH_SAFE(legacy_fm, fms, next, tmp) {
1558 fm = &legacy_fm->fm;
1559 if (mlx5_flow_meter_params_flush(dev, fm, 0))
1560 return -rte_mtr_error_set(error, EINVAL,
1561 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
1562 NULL, "MTR object meter profile invalid.");
1565 if (priv->sh->mtrmng->policy_idx_tbl) {
1566 MLX5_L3T_FOREACH(priv->sh->mtrmng->policy_idx_tbl,
1568 policy_idx = *(uint32_t *)entry;
1569 sub_policy = mlx5_ipool_get
1570 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
1573 return -rte_mtr_error_set(error,
1575 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
1577 "meter policy invalid.");
1578 if (__mlx5_flow_meter_policy_delete(dev, i,
1579 sub_policy->main_policy,
1581 return -rte_mtr_error_set(error,
1583 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
1585 "meter policy invalid.");
1586 mlx5_free(sub_policy->main_policy);
1588 mlx5_l3t_destroy(priv->sh->mtrmng->policy_idx_tbl);
1589 priv->sh->mtrmng->policy_idx_tbl = NULL;
1591 TAILQ_FOREACH_SAFE(fmp, fmps, next, tmp) {
1593 MLX5_ASSERT(!fmp->ref_cnt);
1594 /* Remove from list. */
1595 TAILQ_REMOVE(&priv->flow_meter_profiles, fmp, next);
1598 /* Delete default policy table. */
1599 mlx5_flow_destroy_def_policy(dev);
1600 mlx5_flow_destroy_mtr_drop_tbls(dev);