Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2018 Mellanox Technologies, Ltd
3 : : */
4 : : #include <math.h>
5 : :
6 : : #include <rte_tailq.h>
7 : : #include <rte_malloc.h>
8 : : #include <rte_mtr.h>
9 : : #include <rte_mtr_driver.h>
10 : :
11 : : #include <mlx5_devx_cmds.h>
12 : : #include <mlx5_malloc.h>
13 : :
14 : : #include "mlx5.h"
15 : : #include "mlx5_flow.h"
16 : :
17 : : #ifdef HAVE_MLX5_HWS_SUPPORT
18 : :
19 : : static void
20 : 0 : mlx5_flow_meter_uninit_guest(struct rte_eth_dev *dev)
21 : : {
22 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
23 : :
24 [ # # ]: 0 : if (priv->hws_mpool) {
25 [ # # ]: 0 : if (priv->hws_mpool->action) {
26 : 0 : claim_zero(mlx5dr_action_destroy(priv->hws_mpool->action));
27 : 0 : priv->hws_mpool->action = NULL;
28 : : }
29 : 0 : priv->hws_mpool->devx_obj = NULL;
30 : 0 : priv->hws_mpool->idx_pool = NULL;
31 : 0 : mlx5_free(priv->hws_mpool);
32 : 0 : priv->hws_mpool = NULL;
33 : : }
34 : 0 : }
35 : :
36 : : void
37 : 0 : mlx5_flow_meter_uninit(struct rte_eth_dev *dev)
38 : : {
39 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
40 : :
41 [ # # ]: 0 : if (priv->shared_host) {
42 : 0 : mlx5_flow_meter_uninit_guest(dev);
43 : 0 : return;
44 : : }
45 [ # # ]: 0 : if (priv->mtr_policy_arr) {
46 : 0 : mlx5_free(priv->mtr_policy_arr);
47 : 0 : priv->mtr_policy_arr = NULL;
48 : : }
49 [ # # ]: 0 : if (priv->mtr_profile_arr) {
50 : 0 : mlx5_free(priv->mtr_profile_arr);
51 : 0 : priv->mtr_profile_arr = NULL;
52 : : }
53 [ # # ]: 0 : if (priv->hws_mpool) {
54 : 0 : mlx5_aso_mtr_queue_uninit(priv->sh, priv->hws_mpool, NULL);
55 : 0 : mlx5_ipool_destroy(priv->hws_mpool->idx_pool);
56 : 0 : mlx5_free(priv->hws_mpool);
57 : 0 : priv->hws_mpool = NULL;
58 : : }
59 [ # # ]: 0 : if (priv->mtr_bulk.aso) {
60 : 0 : mlx5_free(priv->mtr_bulk.aso);
61 : 0 : priv->mtr_bulk.aso = NULL;
62 : 0 : priv->mtr_bulk.size = 0;
63 : 0 : mlx5_aso_queue_uninit(priv->sh, ASO_OPC_MOD_POLICER);
64 : : }
65 [ # # ]: 0 : if (priv->mtr_bulk.action) {
66 : 0 : mlx5dr_action_destroy(priv->mtr_bulk.action);
67 : 0 : priv->mtr_bulk.action = NULL;
68 : : }
69 [ # # ]: 0 : if (priv->mtr_bulk.devx_obj) {
70 : 0 : claim_zero(mlx5_devx_cmd_destroy(priv->mtr_bulk.devx_obj));
71 : 0 : priv->mtr_bulk.devx_obj = NULL;
72 : : }
73 : : }
74 : :
75 : : static int
76 : 0 : mlx5_flow_meter_init_guest(struct rte_eth_dev *dev)
77 : : {
78 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
79 : 0 : struct rte_eth_dev *host_dev = priv->shared_host;
80 : 0 : struct mlx5_priv *host_priv = host_dev->data->dev_private;
81 : : int reg_id = 0;
82 : : uint32_t flags;
83 : : int ret = 0;
84 : :
85 : : MLX5_ASSERT(priv->shared_host);
86 : 0 : reg_id = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, NULL);
87 [ # # ]: 0 : if (reg_id < 0) {
88 : 0 : rte_errno = ENOMEM;
89 : : ret = -rte_errno;
90 : 0 : DRV_LOG(ERR, "Meter register is not available.");
91 : 0 : goto err;
92 : : }
93 : 0 : priv->hws_mpool = mlx5_malloc(MLX5_MEM_ZERO, sizeof(struct mlx5_aso_mtr_pool),
94 : : RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
95 [ # # ]: 0 : if (!priv->hws_mpool) {
96 : 0 : rte_errno = ENOMEM;
97 : : ret = -rte_errno;
98 : 0 : DRV_LOG(ERR, "Meter ipool allocation failed.");
99 : 0 : goto err;
100 : : }
101 : : MLX5_ASSERT(host_priv->hws_mpool->idx_pool);
102 : : MLX5_ASSERT(host_priv->hws_mpool->devx_obj);
103 : 0 : priv->hws_mpool->idx_pool = host_priv->hws_mpool->idx_pool;
104 : 0 : priv->hws_mpool->devx_obj = host_priv->hws_mpool->devx_obj;
105 : : flags = MLX5DR_ACTION_FLAG_HWS_RX | MLX5DR_ACTION_FLAG_HWS_TX;
106 [ # # # # ]: 0 : if (priv->sh->config.dv_esw_en && priv->master)
107 : 0 : flags |= (is_unified_fdb(priv) ?
108 : : (MLX5DR_ACTION_FLAG_HWS_FDB_RX |
109 : : MLX5DR_ACTION_FLAG_HWS_FDB_TX |
110 [ # # ]: 0 : MLX5DR_ACTION_FLAG_HWS_FDB_UNIFIED) :
111 : : MLX5DR_ACTION_FLAG_HWS_FDB);
112 : 0 : priv->hws_mpool->action = mlx5dr_action_create_aso_meter
113 : : (priv->dr_ctx, (struct mlx5dr_devx_obj *)priv->hws_mpool->devx_obj,
114 : 0 : reg_id - REG_C_0, flags);
115 [ # # ]: 0 : if (!priv->hws_mpool->action) {
116 : 0 : rte_errno = ENOMEM;
117 : : ret = -rte_errno;
118 : 0 : DRV_LOG(ERR, "Meter action creation failed.");
119 : 0 : goto err;
120 : : }
121 : : return 0;
122 : 0 : err:
123 : 0 : mlx5_flow_meter_uninit(dev);
124 : 0 : return ret;
125 : : }
126 : :
127 : : int
128 : 0 : mlx5_flow_meter_init(struct rte_eth_dev *dev,
129 : : uint32_t nb_meters,
130 : : uint32_t nb_meter_profiles,
131 : : uint32_t nb_meter_policies,
132 : : uint32_t nb_queues)
133 : : {
134 [ # # ]: 0 : struct mlx5_priv *priv = dev->data->dev_private;
135 : : struct mlx5_devx_obj *dcs = NULL;
136 : : uint32_t log_obj_size;
137 : : int ret = 0;
138 : : int reg_id;
139 : : struct mlx5_aso_mtr *aso;
140 : : uint32_t i;
141 : : struct rte_flow_error error;
142 : : uint32_t flags;
143 : : uint32_t nb_mtrs = rte_align32pow2(nb_meters);
144 : 0 : struct mlx5_indexed_pool_config cfg = {
145 : : .size = sizeof(struct mlx5_aso_mtr),
146 : : .trunk_size = 1 << 12,
147 : : .per_core_cache = 1 << 13,
148 : : .need_lock = 1,
149 : 0 : .release_mem_en = !!priv->sh->config.reclaim_mode,
150 : : .malloc = mlx5_malloc,
151 : : .max_idx = nb_meters,
152 : : .free = mlx5_free,
153 : : .type = "mlx5_hw_mtr_mark_action",
154 : : };
155 : :
156 [ # # ]: 0 : if (priv->shared_host)
157 : 0 : return mlx5_flow_meter_init_guest(dev);
158 [ # # ]: 0 : if (!nb_meters) {
159 : : ret = ENOTSUP;
160 : 0 : rte_flow_error_set(&error, ENOMEM,
161 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
162 : : NULL, "Meter configuration is invalid.");
163 : 0 : goto err;
164 : : }
165 [ # # # # ]: 0 : if (!priv->mtr_en || !priv->sh->meter_aso_en) {
166 : : ret = ENOTSUP;
167 : 0 : rte_flow_error_set(&error, ENOMEM,
168 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
169 : : NULL, "Meter ASO is not supported.");
170 : 0 : goto err;
171 : : }
172 : 0 : priv->mtr_config.nb_meters = nb_meters;
173 [ # # ]: 0 : log_obj_size = rte_log2_u32(nb_meters >> 1);
174 : 0 : dcs = mlx5_devx_cmd_create_flow_meter_aso_obj
175 : 0 : (priv->sh->cdev->ctx, priv->sh->cdev->pdn,
176 : : log_obj_size);
177 [ # # ]: 0 : if (!dcs) {
178 : : ret = ENOMEM;
179 : 0 : rte_flow_error_set(&error, ENOMEM,
180 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
181 : : NULL, "Meter ASO object allocation failed.");
182 : 0 : goto err;
183 : : }
184 : 0 : priv->mtr_bulk.devx_obj = dcs;
185 : 0 : reg_id = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, NULL);
186 [ # # ]: 0 : if (reg_id < 0) {
187 : : ret = ENOTSUP;
188 : 0 : rte_flow_error_set(&error, ENOMEM,
189 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
190 : : NULL, "Meter register is not available.");
191 : 0 : goto err;
192 : : }
193 : : flags = MLX5DR_ACTION_FLAG_HWS_RX | MLX5DR_ACTION_FLAG_HWS_TX;
194 [ # # # # ]: 0 : if (priv->sh->config.dv_esw_en && priv->master) {
195 : 0 : flags |= ((is_unified_fdb(priv)) ?
196 : : (MLX5DR_ACTION_FLAG_HWS_FDB_RX |
197 : : MLX5DR_ACTION_FLAG_HWS_FDB_TX |
198 [ # # ]: 0 : MLX5DR_ACTION_FLAG_HWS_FDB_UNIFIED) :
199 : : MLX5DR_ACTION_FLAG_HWS_FDB);
200 : : }
201 : :
202 : 0 : priv->mtr_bulk.action = mlx5dr_action_create_aso_meter
203 : : (priv->dr_ctx, (struct mlx5dr_devx_obj *)dcs,
204 : 0 : reg_id - REG_C_0, flags);
205 [ # # ]: 0 : if (!priv->mtr_bulk.action) {
206 : : ret = ENOMEM;
207 : 0 : rte_flow_error_set(&error, ENOMEM,
208 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
209 : : NULL, "Meter action creation failed.");
210 : 0 : goto err;
211 : : }
212 : 0 : priv->mtr_bulk.aso = mlx5_malloc(MLX5_MEM_ZERO,
213 : : sizeof(struct mlx5_aso_mtr) *
214 : : nb_meters,
215 : : RTE_CACHE_LINE_SIZE,
216 : : SOCKET_ID_ANY);
217 [ # # ]: 0 : if (!priv->mtr_bulk.aso) {
218 : : ret = ENOMEM;
219 : 0 : rte_flow_error_set(&error, ENOMEM,
220 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
221 : : NULL, "Meter bulk ASO allocation failed.");
222 : 0 : goto err;
223 : : }
224 : 0 : priv->mtr_bulk.size = nb_meters;
225 : : aso = priv->mtr_bulk.aso;
226 [ # # ]: 0 : for (i = 0; i < priv->mtr_bulk.size; i++) {
227 : 0 : aso->type = ASO_METER_DIRECT;
228 : 0 : aso->state = ASO_METER_WAIT;
229 : 0 : aso->offset = i;
230 : 0 : aso++;
231 : : }
232 : 0 : priv->hws_mpool = mlx5_malloc(MLX5_MEM_ZERO,
233 : : sizeof(struct mlx5_aso_mtr_pool),
234 : : RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
235 [ # # ]: 0 : if (!priv->hws_mpool) {
236 : : ret = ENOMEM;
237 : 0 : rte_flow_error_set(&error, ENOMEM,
238 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
239 : : NULL, "Meter ipool allocation failed.");
240 : 0 : goto err;
241 : : }
242 : 0 : priv->hws_mpool->devx_obj = priv->mtr_bulk.devx_obj;
243 : 0 : priv->hws_mpool->action = priv->mtr_bulk.action;
244 : 0 : priv->hws_mpool->nb_sq = nb_queues;
245 [ # # ]: 0 : if (mlx5_aso_mtr_queue_init(priv->sh, priv->hws_mpool,
246 : 0 : &priv->sh->mtrmng->pools_mng, nb_queues)) {
247 : : ret = ENOMEM;
248 : 0 : rte_flow_error_set(&error, ENOMEM,
249 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
250 : : NULL, "Meter ASO queue allocation failed.");
251 : 0 : goto err;
252 : : }
253 : : /*
254 : : * No need for local cache if Meter number is a small number.
255 : : * Since flow insertion rate will be very limited in that case.
256 : : * Here let's set the number to less than default trunk size 4K.
257 : : */
258 [ # # ]: 0 : if (nb_mtrs <= cfg.trunk_size) {
259 : 0 : cfg.per_core_cache = 0;
260 : 0 : cfg.trunk_size = nb_mtrs;
261 [ # # ]: 0 : } else if (nb_mtrs <= MLX5_HW_IPOOL_SIZE_THRESHOLD) {
262 : 0 : cfg.per_core_cache = MLX5_HW_IPOOL_CACHE_MIN;
263 : : }
264 : 0 : priv->hws_mpool->idx_pool = mlx5_ipool_create(&cfg);
265 [ # # ]: 0 : if (nb_meter_profiles) {
266 : 0 : priv->mtr_config.nb_meter_profiles = nb_meter_profiles;
267 : 0 : priv->mtr_profile_arr =
268 : 0 : mlx5_malloc(MLX5_MEM_ZERO,
269 : : sizeof(struct mlx5_flow_meter_profile) *
270 : : nb_meter_profiles,
271 : : RTE_CACHE_LINE_SIZE,
272 : : SOCKET_ID_ANY);
273 [ # # ]: 0 : if (!priv->mtr_profile_arr) {
274 : : ret = ENOMEM;
275 : 0 : rte_flow_error_set(&error, ENOMEM,
276 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
277 : : NULL, "Meter profile allocation failed.");
278 : 0 : goto err;
279 : : }
280 : : }
281 [ # # ]: 0 : if (nb_meter_policies) {
282 : 0 : priv->mtr_config.nb_meter_policies = nb_meter_policies;
283 : 0 : priv->mtr_policy_arr =
284 : 0 : mlx5_malloc(MLX5_MEM_ZERO,
285 : : sizeof(struct mlx5_flow_meter_policy) *
286 : : nb_meter_policies,
287 : : RTE_CACHE_LINE_SIZE,
288 : : SOCKET_ID_ANY);
289 [ # # ]: 0 : if (!priv->mtr_policy_arr) {
290 : : ret = ENOMEM;
291 : 0 : rte_flow_error_set(&error, ENOMEM,
292 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
293 : : NULL, "Meter policy allocation failed.");
294 : 0 : goto err;
295 : : }
296 : : }
297 : : return 0;
298 : 0 : err:
299 : 0 : mlx5_flow_meter_uninit(dev);
300 : 0 : return ret;
301 : : }
302 : :
303 : : #endif /* HAVE_MLX5_HWS_SUPPORT */
304 : :
305 : : static int mlx5_flow_meter_disable(struct rte_eth_dev *dev,
306 : : uint32_t meter_id, struct rte_mtr_error *error);
307 : :
308 : : /**
309 : : * Create the meter action.
310 : : *
311 : : * @param priv
312 : : * Pointer to mlx5_priv.
313 : : * @param[in] fm
314 : : * Pointer to flow meter to be converted.
315 : : *
316 : : * @return
317 : : * Pointer to the meter action on success, NULL otherwise.
318 : : */
319 : : static void *
320 : 0 : mlx5_flow_meter_action_create(struct mlx5_priv *priv,
321 : : struct mlx5_flow_meter_info *fm)
322 : : {
323 : : #ifdef HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER
324 : : struct mlx5dv_dr_flow_meter_attr mtr_init;
325 : : uint32_t fmp[MLX5_ST_SZ_DW(flow_meter_parameters)];
326 : : struct mlx5_flow_meter_srtcm_rfc2697_prm *srtcm =
327 : 0 : &fm->profile->srtcm_prm;
328 [ # # ]: 0 : uint32_t cbs_cir = rte_be_to_cpu_32(srtcm->cbs_cir);
329 [ # # ]: 0 : uint32_t ebs_eir = rte_be_to_cpu_32(srtcm->ebs_eir);
330 : : uint32_t val;
331 : : enum mlx5_meter_domain domain =
332 [ # # ]: 0 : fm->transfer ? MLX5_MTR_DOMAIN_TRANSFER :
333 : 0 : fm->egress ? MLX5_MTR_DOMAIN_EGRESS :
334 : : MLX5_MTR_DOMAIN_INGRESS;
335 : 0 : struct mlx5_flow_meter_def_policy *def_policy =
336 : 0 : priv->sh->mtrmng->def_policy[domain];
337 : :
338 : : memset(fmp, 0, MLX5_ST_SZ_BYTES(flow_meter_parameters));
339 : : MLX5_SET(flow_meter_parameters, fmp, valid, 1);
340 [ # # ]: 0 : MLX5_SET(flow_meter_parameters, fmp, bucket_overflow, 1);
341 [ # # ]: 0 : MLX5_SET(flow_meter_parameters, fmp,
342 : : start_color, MLX5_FLOW_COLOR_GREEN);
343 [ # # ]: 0 : MLX5_SET(flow_meter_parameters, fmp, both_buckets_on_green, 0);
344 : 0 : val = (cbs_cir >> ASO_DSEG_CBS_EXP_OFFSET) & ASO_DSEG_EXP_MASK;
345 : 0 : MLX5_SET(flow_meter_parameters, fmp, cbs_exponent, val);
346 : 0 : val = (cbs_cir >> ASO_DSEG_CBS_MAN_OFFSET) & ASO_DSEG_MAN_MASK;
347 [ # # ]: 0 : MLX5_SET(flow_meter_parameters, fmp, cbs_mantissa, val);
348 : 0 : val = (cbs_cir >> ASO_DSEG_XIR_EXP_OFFSET) & ASO_DSEG_EXP_MASK;
349 [ # # ]: 0 : MLX5_SET(flow_meter_parameters, fmp, cir_exponent, val);
350 : 0 : val = (cbs_cir & ASO_DSEG_MAN_MASK);
351 [ # # ]: 0 : MLX5_SET(flow_meter_parameters, fmp, cir_mantissa, val);
352 : 0 : val = (ebs_eir >> ASO_DSEG_EBS_EXP_OFFSET) & ASO_DSEG_EXP_MASK;
353 : 0 : MLX5_SET(flow_meter_parameters, fmp, ebs_exponent, val);
354 : 0 : val = (ebs_eir >> ASO_DSEG_EBS_MAN_OFFSET) & ASO_DSEG_MAN_MASK;
355 [ # # ]: 0 : MLX5_SET(flow_meter_parameters, fmp, ebs_mantissa, val);
356 : 0 : mtr_init.next_table = def_policy->sub_policy.tbl_rsc->obj;
357 : 0 : mtr_init.reg_c_index = priv->sh->registers.aso_reg - REG_C_0;
358 : 0 : mtr_init.flow_meter_parameter = fmp;
359 : 0 : mtr_init.flow_meter_parameter_sz =
360 : : MLX5_ST_SZ_BYTES(flow_meter_parameters);
361 : 0 : mtr_init.active = fm->active_state;
362 : 0 : return mlx5_glue->dv_create_flow_action_meter(&mtr_init);
363 : : #else
364 : : (void)priv;
365 : : (void)fm;
366 : : return NULL;
367 : : #endif
368 : : }
369 : :
370 : : /**
371 : : * Find meter profile by id.
372 : : *
373 : : * @param priv
374 : : * Pointer to mlx5_priv.
375 : : * @param meter_profile_id
376 : : * Meter profile id.
377 : : *
378 : : * @return
379 : : * Pointer to the profile found on success, NULL otherwise.
380 : : */
381 : : static struct mlx5_flow_meter_profile *
382 : 0 : mlx5_flow_meter_profile_find(struct mlx5_priv *priv, uint32_t meter_profile_id)
383 : : {
384 : : struct mlx5_flow_meter_profile *fmp;
385 : : union mlx5_l3t_data data;
386 : : int32_t ret;
387 : :
388 [ # # ]: 0 : if (priv->mtr_profile_arr)
389 : 0 : return &priv->mtr_profile_arr[meter_profile_id];
390 [ # # # # ]: 0 : if (!priv->mtr_profile_tbl ||
391 [ # # ]: 0 : mlx5_l3t_get_entry(priv->mtr_profile_tbl, meter_profile_id, &data) || !data.ptr)
392 : 0 : return NULL;
393 : : fmp = data.ptr;
394 : : /* Remove reference taken by the mlx5_l3t_get_entry. */
395 : 0 : ret = mlx5_l3t_clear_entry(priv->mtr_profile_tbl,
396 : : meter_profile_id);
397 [ # # ]: 0 : if (!ret || ret == -1)
398 : 0 : return NULL;
399 : : return fmp;
400 : : }
401 : :
402 : : /**
403 : : * Validate the MTR profile.
404 : : *
405 : : * @param[in] dev
406 : : * Pointer to Ethernet device.
407 : : * @param[in] meter_profile_id
408 : : * Meter profile id.
409 : : * @param[in] profile
410 : : * Pointer to meter profile detail.
411 : : * @param[out] error
412 : : * Pointer to the error structure.
413 : : *
414 : : * @return
415 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
416 : : */
417 : : static int
418 : 0 : mlx5_flow_meter_profile_validate(struct rte_eth_dev *dev,
419 : : uint32_t meter_profile_id,
420 : : struct rte_mtr_meter_profile *profile,
421 : : struct rte_mtr_error *error)
422 : : {
423 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
424 : : struct mlx5_flow_meter_profile *fmp;
425 : : uint32_t ls_factor;
426 : : int ret;
427 : : uint64_t cir, cbs;
428 : : uint64_t eir, ebs;
429 : : uint64_t pir, pbs;
430 : :
431 : : /* Profile must not be NULL. */
432 [ # # ]: 0 : if (profile == NULL)
433 : 0 : return -rte_mtr_error_set(error, EINVAL,
434 : : RTE_MTR_ERROR_TYPE_METER_PROFILE,
435 : : NULL, "Meter profile is null.");
436 : : /* Meter profile ID must be valid. */
437 [ # # ]: 0 : if (priv->mtr_profile_arr) {
438 [ # # ]: 0 : if (meter_profile_id >= priv->mtr_config.nb_meter_profiles)
439 : 0 : return -rte_mtr_error_set(error, EINVAL,
440 : : RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
441 : : NULL, "Meter profile id not valid.");
442 : 0 : fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id);
443 : : /* Meter profile must not exist. */
444 [ # # ]: 0 : if (fmp->initialized)
445 : 0 : return -rte_mtr_error_set(error, EEXIST,
446 : : RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
447 : : NULL, "Meter profile already exists.");
448 : : } else {
449 [ # # ]: 0 : if (meter_profile_id == UINT32_MAX)
450 : 0 : return -rte_mtr_error_set(error, EINVAL,
451 : : RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
452 : : NULL, "Meter profile id not valid.");
453 : 0 : fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id);
454 : : /* Meter profile must not exist. */
455 [ # # ]: 0 : if (fmp)
456 : 0 : return -rte_mtr_error_set(error, EEXIST,
457 : : RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
458 : : NULL, "Meter profile already exists.");
459 : : }
460 [ # # ]: 0 : if (!priv->sh->meter_aso_en) {
461 : : /* Old version is even not supported. */
462 [ # # ]: 0 : if (!priv->sh->cdev->config.hca_attr.qos.flow_meter_old)
463 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
464 : : RTE_MTR_ERROR_TYPE_METER_PROFILE,
465 : : NULL, "Metering is not supported.");
466 : : /* Old FW metering only supports srTCM. */
467 [ # # ]: 0 : if (profile->alg != RTE_MTR_SRTCM_RFC2697) {
468 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
469 : : RTE_MTR_ERROR_TYPE_METER_PROFILE,
470 : : NULL, "Metering algorithm is not supported.");
471 [ # # ]: 0 : } else if (profile->srtcm_rfc2697.ebs) {
472 : : /* EBS is not supported for old metering. */
473 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
474 : : RTE_MTR_ERROR_TYPE_METER_PROFILE,
475 : : NULL, "EBS is not supported.");
476 : : }
477 [ # # ]: 0 : if (profile->packet_mode)
478 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
479 : : RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
480 : : "Metering algorithm packet mode is not supported.");
481 : : }
482 [ # # ]: 0 : ls_factor = profile->packet_mode ? MLX5_MTRS_PPS_MAP_BPS_SHIFT : 0;
483 [ # # # # ]: 0 : switch (profile->alg) {
484 : 0 : case RTE_MTR_SRTCM_RFC2697:
485 : 0 : cir = profile->srtcm_rfc2697.cir << ls_factor;
486 : 0 : cbs = profile->srtcm_rfc2697.cbs << ls_factor;
487 : 0 : ebs = profile->srtcm_rfc2697.ebs << ls_factor;
488 : : /* EBS could be zero for old metering. */
489 [ # # ]: 0 : if (cir > 0 && cir <= MLX5_SRTCM_XIR_MAX &&
490 [ # # # # ]: 0 : cbs > 0 && cbs <= MLX5_SRTCM_XBS_MAX &&
491 : : ebs <= MLX5_SRTCM_XBS_MAX) {
492 : : ret = 0;
493 : : } else {
494 : : ret = -rte_mtr_error_set(error, ENOTSUP,
495 : : RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
496 : : "Profile values out of range.");
497 : : }
498 : : break;
499 : 0 : case RTE_MTR_TRTCM_RFC2698:
500 : 0 : cir = profile->trtcm_rfc2698.cir << ls_factor;
501 : 0 : cbs = profile->trtcm_rfc2698.cbs << ls_factor;
502 : 0 : pir = profile->trtcm_rfc2698.pir << ls_factor;
503 : 0 : pbs = profile->trtcm_rfc2698.pbs << ls_factor;
504 [ # # ]: 0 : if (cir > 0 && cir <= MLX5_SRTCM_XIR_MAX &&
505 [ # # ]: 0 : cbs > 0 && cbs <= MLX5_SRTCM_XBS_MAX &&
506 [ # # ]: 0 : pir >= cir && pir <= (MLX5_SRTCM_XIR_MAX * 2) &&
507 [ # # ]: 0 : pbs >= cbs && pbs <= (MLX5_SRTCM_XBS_MAX * 2)) {
508 : : ret = 0;
509 : : } else {
510 : : ret = -rte_mtr_error_set(error, ENOTSUP,
511 : : RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
512 : : "Profile values out of range.");
513 : : }
514 : : break;
515 : 0 : case RTE_MTR_TRTCM_RFC4115:
516 : 0 : cir = profile->trtcm_rfc4115.cir << ls_factor;
517 : 0 : cbs = profile->trtcm_rfc4115.cbs << ls_factor;
518 : 0 : eir = profile->trtcm_rfc4115.eir << ls_factor;
519 : 0 : ebs = profile->trtcm_rfc4115.ebs << ls_factor;
520 [ # # ]: 0 : if (cir > 0 && cir <= MLX5_SRTCM_XIR_MAX &&
521 [ # # ]: 0 : cbs > 0 && cbs <= MLX5_SRTCM_XBS_MAX &&
522 [ # # ]: 0 : eir <= MLX5_SRTCM_XIR_MAX && ebs <= MLX5_SRTCM_XBS_MAX) {
523 : : ret = 0;
524 : : } else {
525 : : ret = -rte_mtr_error_set(error, ENOTSUP,
526 : : RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
527 : : "Profile values out of range.");
528 : : }
529 : : break;
530 : : default:
531 : : ret = -rte_mtr_error_set(error, ENOTSUP,
532 : : RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
533 : : "Unknown metering algorithm.");
534 : 0 : break;
535 : : }
536 : : return ret;
537 : : }
538 : :
539 : : /*
540 : : * Calculate mantissa and exponent for cir / eir.
541 : : *
542 : : * @param[in] xir
543 : : * Value to be calculated.
544 : : * @param[out] man
545 : : * Pointer to the mantissa.
546 : : * @param[out] exp
547 : : * Pointer to the exp.
548 : : */
549 : : static inline void
550 : : mlx5_flow_meter_xir_man_exp_calc(int64_t xir, uint8_t *man, uint8_t *exp)
551 : : {
552 : : int64_t _xir;
553 : : int64_t delta = INT64_MAX;
554 : : uint8_t _man = 0;
555 : : uint8_t _exp = 0;
556 : : uint64_t m, e;
557 : :
558 : : /* Special case xir == 0 ? both exp and mantissa are 0. */
559 : 0 : if (xir == 0) {
560 : 0 : *man = 0;
561 : 0 : *exp = 0;
562 : 0 : return;
563 : : }
564 [ # # # # ]: 0 : for (m = 0; m <= 0xFF; m++) { /* man width 8 bit */
565 [ # # # # ]: 0 : for (e = 0; e <= 0x1F; e++) { /* exp width 5bit */
566 : 0 : _xir = (1000000000ULL * m) >> e;
567 [ # # # # ]: 0 : if (llabs(xir - _xir) <= delta) {
568 : : delta = llabs(xir - _xir);
569 : 0 : _man = m;
570 : 0 : _exp = e;
571 : : }
572 : : }
573 : : }
574 : 0 : *man = _man;
575 : 0 : *exp = _exp;
576 : : }
577 : :
578 : : /*
579 : : * Calculate mantissa and exponent for xbs.
580 : : *
581 : : * @param[in] xbs
582 : : * Value to be calculated.
583 : : * @param[out] man
584 : : * Pointer to the mantissa.
585 : : * @param[out] exp
586 : : * Pointer to the exp.
587 : : */
588 : : static inline void
589 : 0 : mlx5_flow_meter_xbs_man_exp_calc(uint64_t xbs, uint8_t *man, uint8_t *exp)
590 : : {
591 : : int _exp;
592 : : double _man;
593 : :
594 : : /* Special case xbs == 0 ? both exp and mantissa are 0. */
595 [ # # ]: 0 : if (xbs == 0) {
596 : 0 : *man = 0;
597 : 0 : *exp = 0;
598 : 0 : return;
599 : : }
600 : : /* xbs = xbs_mantissa * 2^xbs_exponent */
601 : 0 : _man = frexp(xbs, &_exp);
602 [ # # ]: 0 : if (_exp >= MLX5_MAN_WIDTH) {
603 : 0 : _man = _man * pow(2, MLX5_MAN_WIDTH);
604 : 0 : _exp = _exp - MLX5_MAN_WIDTH;
605 : : }
606 : 0 : *man = (uint8_t)ceil(_man);
607 : 0 : *exp = _exp;
608 : : }
609 : :
610 : : /**
611 : : * Fill the prm meter parameter.
612 : : *
613 : : * @param[in,out] fmp
614 : : * Pointer to meter profile to be converted.
615 : : * @param[out] error
616 : : * Pointer to the error structure.
617 : : *
618 : : * @return
619 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
620 : : */
621 : : static int
622 : 0 : mlx5_flow_meter_param_fill(struct mlx5_flow_meter_profile *fmp,
623 : : struct rte_mtr_error *error)
624 : : {
625 : : struct mlx5_flow_meter_srtcm_rfc2697_prm *srtcm = &fmp->srtcm_prm;
626 : : uint8_t man, exp;
627 : : uint32_t cbs_exp, cbs_man, cir_exp, cir_man;
628 : : uint32_t eir_exp, eir_man, ebs_exp, ebs_man;
629 : : uint64_t cir, cbs, eir, ebs;
630 : :
631 [ # # # # ]: 0 : switch (fmp->profile.alg) {
632 : 0 : case RTE_MTR_SRTCM_RFC2697:
633 : 0 : cir = fmp->profile.srtcm_rfc2697.cir;
634 : 0 : cbs = fmp->profile.srtcm_rfc2697.cbs;
635 : : eir = 0;
636 : 0 : ebs = fmp->profile.srtcm_rfc2697.ebs;
637 : 0 : break;
638 : 0 : case RTE_MTR_TRTCM_RFC2698:
639 : : MLX5_ASSERT(fmp->profile.trtcm_rfc2698.pir >
640 : : fmp->profile.trtcm_rfc2698.cir &&
641 : : fmp->profile.trtcm_rfc2698.pbs >
642 : : fmp->profile.trtcm_rfc2698.cbs);
643 : 0 : cir = fmp->profile.trtcm_rfc2698.cir;
644 : 0 : cbs = fmp->profile.trtcm_rfc2698.cbs;
645 : : /* EIR / EBS are filled with PIR / PBS. */
646 : 0 : eir = fmp->profile.trtcm_rfc2698.pir;
647 : 0 : ebs = fmp->profile.trtcm_rfc2698.pbs;
648 : 0 : break;
649 : 0 : case RTE_MTR_TRTCM_RFC4115:
650 : 0 : cir = fmp->profile.trtcm_rfc4115.cir;
651 : 0 : cbs = fmp->profile.trtcm_rfc4115.cbs;
652 : 0 : eir = fmp->profile.trtcm_rfc4115.eir;
653 : 0 : ebs = fmp->profile.trtcm_rfc4115.ebs;
654 : 0 : break;
655 : : default:
656 : 0 : return -rte_mtr_error_set(error, EINVAL,
657 : : RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
658 : : "Metering algorithm mode is invalid");
659 : : }
660 : : /* Adjust the values for PPS mode. */
661 [ # # ]: 0 : if (fmp->profile.packet_mode) {
662 : 0 : cir <<= MLX5_MTRS_PPS_MAP_BPS_SHIFT;
663 : 0 : cbs <<= MLX5_MTRS_PPS_MAP_BPS_SHIFT;
664 : 0 : eir <<= MLX5_MTRS_PPS_MAP_BPS_SHIFT;
665 : 0 : ebs <<= MLX5_MTRS_PPS_MAP_BPS_SHIFT;
666 : : }
667 : : /* cir = 8G * cir_mantissa * 1/(2^cir_exponent)) Bytes/Sec */
668 [ # # ]: 0 : mlx5_flow_meter_xir_man_exp_calc(cir, &man, &exp);
669 : : /* Check if cir mantissa is too large. */
670 [ # # ]: 0 : if (exp > ASO_DSEG_XIR_EXP_MASK)
671 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
672 : : RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
673 : : "meter profile parameter cir is not supported.");
674 : 0 : cir_man = man;
675 : 0 : cir_exp = exp;
676 : : /* cbs = cbs_mantissa * 2^cbs_exponent */
677 : 0 : mlx5_flow_meter_xbs_man_exp_calc(cbs, &man, &exp);
678 : : /* Check if cbs mantissa is too large. */
679 [ # # ]: 0 : if (exp > ASO_DSEG_EXP_MASK)
680 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
681 : : RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
682 : : "meter profile parameter cbs is not supported.");
683 : 0 : cbs_man = man;
684 : 0 : cbs_exp = exp;
685 [ # # ]: 0 : srtcm->cbs_cir = rte_cpu_to_be_32(cbs_exp << ASO_DSEG_CBS_EXP_OFFSET |
686 : : cbs_man << ASO_DSEG_CBS_MAN_OFFSET |
687 : : cir_exp << ASO_DSEG_XIR_EXP_OFFSET |
688 : : cir_man);
689 [ # # ]: 0 : mlx5_flow_meter_xir_man_exp_calc(eir, &man, &exp);
690 : : /* Check if eir mantissa is too large. */
691 [ # # ]: 0 : if (exp > ASO_DSEG_XIR_EXP_MASK)
692 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
693 : : RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
694 : : "meter profile parameter eir is not supported.");
695 : 0 : eir_man = man;
696 : 0 : eir_exp = exp;
697 : 0 : mlx5_flow_meter_xbs_man_exp_calc(ebs, &man, &exp);
698 : : /* Check if ebs mantissa is too large. */
699 [ # # ]: 0 : if (exp > ASO_DSEG_EXP_MASK)
700 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
701 : : RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
702 : : "meter profile parameter ebs is not supported.");
703 : 0 : ebs_man = man;
704 : 0 : ebs_exp = exp;
705 [ # # ]: 0 : srtcm->ebs_eir = rte_cpu_to_be_32(ebs_exp << ASO_DSEG_EBS_EXP_OFFSET |
706 : : ebs_man << ASO_DSEG_EBS_MAN_OFFSET |
707 : : eir_exp << ASO_DSEG_XIR_EXP_OFFSET |
708 : : eir_man);
709 [ # # ]: 0 : if (srtcm->cbs_cir)
710 : 0 : fmp->g_support = 1;
711 [ # # ]: 0 : if (srtcm->ebs_eir)
712 : 0 : fmp->y_support = 1;
713 : : return 0;
714 : : }
715 : :
716 : : /**
717 : : * Callback to get MTR maximum objects number.
718 : : *
719 : : * @param[in] priv
720 : : * Pointer to Ethernet device.
721 : : *
722 : : * @return
723 : : * Max number of meters.
724 : : */
725 : : uint32_t
726 : 0 : mlx5_flow_mtr_max_get(struct mlx5_priv *priv)
727 : : {
728 : 0 : struct mlx5_hca_qos_attr *qattr = &priv->sh->cdev->config.hca_attr.qos;
729 : :
730 : : /* Max number of meters. */
731 : 0 : return ((priv->sh->meter_aso_en) ?
732 [ # # ]: 0 : 1 << (qattr->log_max_num_meter_aso + 1) :
733 : 0 : qattr->log_max_flow_meter);
734 : : }
735 : :
736 : : /**
737 : : * Callback to get MTR capabilities.
738 : : *
739 : : * @param[in] dev
740 : : * Pointer to Ethernet device.
741 : : * @param[out] cap
742 : : * Pointer to save MTR capabilities.
743 : : * @param[out] error
744 : : * Pointer to the error structure.
745 : : *
746 : : * @return
747 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
748 : : */
749 : : static int
750 : 0 : mlx5_flow_mtr_cap_get(struct rte_eth_dev *dev,
751 : : struct rte_mtr_capabilities *cap,
752 : : struct rte_mtr_error *error __rte_unused)
753 : : {
754 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
755 [ # # ]: 0 : struct mlx5_hca_qos_attr *qattr = &priv->sh->cdev->config.hca_attr.qos;
756 : :
757 [ # # # # ]: 0 : if (mlx5_hws_active(dev) && !mlx5_hw_ctx_validate(dev, NULL))
758 : 0 : return -rte_mtr_error_set(error, EINVAL,
759 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
760 : : "non-template flow engine was not configured");
761 [ # # ]: 0 : if (!priv->mtr_en)
762 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
763 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
764 : : "Meter is not supported");
765 : : memset(cap, 0, sizeof(*cap));
766 : 0 : cap->n_max = mlx5_flow_mtr_max_get(priv);
767 [ # # ]: 0 : if (priv->sh->meter_aso_en) {
768 : 0 : cap->srtcm_rfc2697_packet_mode_supported = 1;
769 : 0 : cap->trtcm_rfc2698_packet_mode_supported = 1;
770 : 0 : cap->trtcm_rfc4115_packet_mode_supported = 1;
771 : : }
772 : 0 : cap->srtcm_rfc2697_byte_mode_supported = 1;
773 : 0 : cap->trtcm_rfc2698_byte_mode_supported = 1;
774 : 0 : cap->trtcm_rfc4115_byte_mode_supported = 1;
775 : 0 : cap->n_shared_max = cap->n_max;
776 : 0 : cap->identical = 1;
777 : 0 : cap->shared_identical = 1;
778 : 0 : cap->shared_n_flows_per_mtr_max = 4 << 20;
779 : : /* 2M flows can share the same meter. */
780 : 0 : cap->chaining_n_mtrs_per_flow_max = 1; /* Chaining is not supported. */
781 [ # # ]: 0 : cap->meter_srtcm_rfc2697_n_max = qattr->flow_meter_old ? cap->n_max : 0;
782 : 0 : cap->meter_trtcm_rfc2698_n_max = qattr->flow_meter_old ? cap->n_max : 0;
783 : 0 : cap->meter_trtcm_rfc4115_n_max = qattr->flow_meter_old ? cap->n_max : 0;
784 : 0 : cap->meter_rate_max = 1ULL << 40; /* 1 Tera tokens per sec. */
785 : 0 : cap->meter_policy_n_max = cap->n_max;
786 : 0 : cap->stats_mask = RTE_MTR_STATS_N_BYTES_DROPPED |
787 : : RTE_MTR_STATS_N_PKTS_DROPPED;
788 : 0 : return 0;
789 : : }
790 : :
791 : : /**
792 : : * Callback to add MTR profile.
793 : : *
794 : : * @param[in] dev
795 : : * Pointer to Ethernet device.
796 : : * @param[in] meter_profile_id
797 : : * Meter profile id.
798 : : * @param[in] profile
799 : : * Pointer to meter profile detail.
800 : : * @param[out] error
801 : : * Pointer to the error structure.
802 : : *
803 : : * @return
804 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
805 : : */
806 : : static int
807 : 0 : mlx5_flow_meter_profile_add(struct rte_eth_dev *dev,
808 : : uint32_t meter_profile_id,
809 : : struct rte_mtr_meter_profile *profile,
810 : : struct rte_mtr_error *error)
811 : : {
812 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
813 : : struct mlx5_flow_meter_profile *fmp;
814 : : union mlx5_l3t_data data;
815 : : int ret;
816 : :
817 [ # # ]: 0 : if (!priv->mtr_en)
818 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
819 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
820 : : "Meter is not supported");
821 : : /* Check input params. */
822 : 0 : ret = mlx5_flow_meter_profile_validate(dev, meter_profile_id,
823 : : profile, error);
824 [ # # ]: 0 : if (ret)
825 : : return ret;
826 : : /* Meter profile memory allocation. */
827 : 0 : fmp = mlx5_malloc(MLX5_MEM_ZERO, sizeof(struct mlx5_flow_meter_profile),
828 : : RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
829 [ # # ]: 0 : if (fmp == NULL)
830 : 0 : return -rte_mtr_error_set(error, ENOMEM,
831 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED,
832 : : NULL, "Meter profile memory "
833 : : "alloc failed.");
834 : : /* Fill profile info. */
835 : 0 : fmp->id = meter_profile_id;
836 : 0 : fmp->profile = *profile;
837 : : /* Fill the flow meter parameters for the PRM. */
838 : 0 : ret = mlx5_flow_meter_param_fill(fmp, error);
839 [ # # ]: 0 : if (ret)
840 : 0 : goto error;
841 : 0 : data.ptr = fmp;
842 : 0 : ret = mlx5_l3t_set_entry(priv->mtr_profile_tbl,
843 : : meter_profile_id, &data);
844 [ # # ]: 0 : if (ret)
845 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
846 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED,
847 : : NULL, "Meter profile insert fail.");
848 : : return 0;
849 : : error:
850 : 0 : mlx5_free(fmp);
851 : 0 : return ret;
852 : : }
853 : :
854 : : /**
855 : : * Callback to delete MTR profile.
856 : : *
857 : : * @param[in] dev
858 : : * Pointer to Ethernet device.
859 : : * @param[in] meter_profile_id
860 : : * Meter profile id.
861 : : * @param[out] error
862 : : * Pointer to the error structure.
863 : : *
864 : : * @return
865 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
866 : : */
867 : : static int
868 : 0 : mlx5_flow_meter_profile_delete(struct rte_eth_dev *dev,
869 : : uint32_t meter_profile_id,
870 : : struct rte_mtr_error *error)
871 : : {
872 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
873 : : struct mlx5_flow_meter_profile *fmp;
874 : :
875 [ # # ]: 0 : if (!priv->mtr_en)
876 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
877 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
878 : : "Meter is not supported");
879 : : /* Meter profile must exist. */
880 : 0 : fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id);
881 [ # # ]: 0 : if (fmp == NULL)
882 : 0 : return -rte_mtr_error_set(error, ENOENT,
883 : : RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
884 : : &meter_profile_id,
885 : : "Meter profile id is invalid.");
886 : : /* Check profile is unused. */
887 [ # # ]: 0 : if (fmp->ref_cnt)
888 : 0 : return -rte_mtr_error_set(error, EBUSY,
889 : : RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
890 : : NULL, "Meter profile is in use.");
891 [ # # ]: 0 : if (mlx5_l3t_clear_entry(priv->mtr_profile_tbl, meter_profile_id))
892 : 0 : return -rte_mtr_error_set(error, EBUSY,
893 : : RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
894 : : NULL, "Meter profile remove fail.");
895 : 0 : mlx5_free(fmp);
896 : 0 : return 0;
897 : : }
898 : :
899 : : /**
900 : : * Callback to get MTR profile.
901 : : *
902 : : * @param[in] dev
903 : : * Pointer to Ethernet device.
904 : : * @param[in] meter_profile_id
905 : : * Meter profile id.
906 : : * @param[out] error
907 : : * Pointer to the error structure.
908 : : *
909 : : * @return
910 : : * A valid handle in case of success, NULL otherwise.
911 : : */
912 : : static struct rte_flow_meter_profile *
913 : 0 : mlx5_flow_meter_profile_get(struct rte_eth_dev *dev,
914 : : uint32_t meter_profile_id,
915 : : struct rte_mtr_error *error)
916 : : {
917 [ # # ]: 0 : struct mlx5_priv *priv = dev->data->dev_private;
918 : :
919 [ # # # # ]: 0 : if (mlx5_hws_active(dev) && !mlx5_hw_ctx_validate(dev, NULL)) {
920 : : rte_mtr_error_set(error, EINVAL,
921 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
922 : : "non-template flow engine was not configured");
923 : 0 : return NULL;
924 : : }
925 [ # # ]: 0 : if (!priv->mtr_en) {
926 : : rte_mtr_error_set(error, ENOTSUP,
927 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
928 : : "Meter is not supported");
929 : 0 : return NULL;
930 : : }
931 : 0 : return (void *)(uintptr_t)mlx5_flow_meter_profile_find(priv,
932 : : meter_profile_id);
933 : : }
934 : :
935 : : #if defined(HAVE_MLX5_HWS_SUPPORT)
936 : : /**
937 : : * Callback to add MTR profile with HWS.
938 : : *
939 : : * @param[in] dev
940 : : * Pointer to Ethernet device.
941 : : * @param[in] meter_profile_id
942 : : * Meter profile id.
943 : : * @param[in] profile
944 : : * Pointer to meter profile detail.
945 : : * @param[out] error
946 : : * Pointer to the error structure.
947 : : *
948 : : * @return
949 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
950 : : */
951 : : static int
952 : 0 : mlx5_flow_meter_profile_hws_add(struct rte_eth_dev *dev,
953 : : uint32_t meter_profile_id,
954 : : struct rte_mtr_meter_profile *profile,
955 : : struct rte_mtr_error *error)
956 : : {
957 [ # # ]: 0 : struct mlx5_priv *priv = dev->data->dev_private;
958 : : struct mlx5_flow_meter_profile *fmp;
959 : : int ret;
960 : :
961 [ # # # # ]: 0 : if (mlx5_hws_active(dev) && !mlx5_hw_ctx_validate(dev, NULL))
962 : 0 : return -rte_mtr_error_set(error, EINVAL,
963 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
964 : : "non-template flow engine was not configured");
965 [ # # ]: 0 : if (priv->shared_host)
966 : 0 : return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
967 : : "Meter profiles cannot be created on guest port");
968 [ # # ]: 0 : if (!priv->mtr_profile_arr)
969 : 0 : return mlx5_flow_meter_profile_add(dev, meter_profile_id, profile, error);
970 : : /* Check input params. */
971 : 0 : ret = mlx5_flow_meter_profile_validate(dev, meter_profile_id,
972 : : profile, error);
973 [ # # ]: 0 : if (ret)
974 : : return ret;
975 : 0 : fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id);
976 : : /* Fill profile info. */
977 : 0 : fmp->id = meter_profile_id;
978 : 0 : fmp->profile = *profile;
979 : 0 : fmp->initialized = 1;
980 : : /* Fill the flow meter parameters for the PRM. */
981 : 0 : return mlx5_flow_meter_param_fill(fmp, error);
982 : : }
983 : :
984 : : /**
985 : : * Callback to delete MTR profile with HWS.
986 : : *
987 : : * @param[in] dev
988 : : * Pointer to Ethernet device.
989 : : * @param[in] meter_profile_id
990 : : * Meter profile id.
991 : : * @param[out] error
992 : : * Pointer to the error structure.
993 : : *
994 : : * @return
995 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
996 : : */
997 : : static int
998 : 0 : mlx5_flow_meter_profile_hws_delete(struct rte_eth_dev *dev,
999 : : uint32_t meter_profile_id,
1000 : : struct rte_mtr_error *error)
1001 : : {
1002 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
1003 : : struct mlx5_flow_meter_profile *fmp;
1004 : :
1005 [ # # ]: 0 : if (priv->shared_host)
1006 : 0 : return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1007 : : "Meter profiles cannot be destroyed through guest port");
1008 [ # # ]: 0 : if (!priv->mtr_profile_arr)
1009 : 0 : return mlx5_flow_meter_profile_delete(dev, meter_profile_id, error);
1010 : : /* Meter profile must exist. */
1011 : 0 : fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id);
1012 [ # # ]: 0 : if (!fmp->initialized)
1013 : 0 : return -rte_mtr_error_set(error, ENOENT,
1014 : : RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
1015 : : &meter_profile_id,
1016 : : "Meter profile id is invalid.");
1017 : : /* Check profile is unused. */
1018 [ # # ]: 0 : if (fmp->ref_cnt)
1019 : 0 : return -rte_mtr_error_set(error, EBUSY,
1020 : : RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
1021 : : NULL, "Meter profile is in use.");
1022 : : memset(fmp, 0, sizeof(struct mlx5_flow_meter_profile));
1023 : 0 : return 0;
1024 : : }
1025 : : #endif
1026 : :
1027 : : /**
1028 : : * Find policy by id.
1029 : : *
1030 : : * @param[in] dev
1031 : : * Pointer to Ethernet device.
1032 : : * @param policy_id
1033 : : * Policy id.
1034 : : *
1035 : : * @return
1036 : : * Pointer to the policy found on success, NULL otherwise.
1037 : : */
1038 : : struct mlx5_flow_meter_policy *
1039 : 0 : mlx5_flow_meter_policy_find(struct rte_eth_dev *dev,
1040 : : uint32_t policy_id,
1041 : : uint32_t *policy_idx)
1042 : : {
1043 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
1044 : : struct mlx5_flow_meter_sub_policy *sub_policy = NULL;
1045 : : union mlx5_l3t_data data;
1046 : :
1047 [ # # ]: 0 : if (priv->mtr_policy_arr) {
1048 [ # # ]: 0 : if (policy_idx)
1049 : 0 : *policy_idx = policy_id;
1050 : 0 : return &priv->mtr_policy_arr[policy_id];
1051 : : }
1052 [ # # # # ]: 0 : if (policy_id > MLX5_MAX_SUB_POLICY_TBL_NUM || !priv->policy_idx_tbl)
1053 : : return NULL;
1054 [ # # ]: 0 : if (mlx5_l3t_get_entry(priv->policy_idx_tbl, policy_id, &data) ||
1055 [ # # ]: 0 : !data.dword)
1056 : : return NULL;
1057 [ # # ]: 0 : if (policy_idx)
1058 : 0 : *policy_idx = data.dword;
1059 : 0 : sub_policy = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
1060 : : data.dword);
1061 : : /* Remove reference taken by the mlx5_l3t_get_entry. */
1062 : 0 : mlx5_l3t_clear_entry(priv->policy_idx_tbl, policy_id);
1063 [ # # ]: 0 : if (sub_policy)
1064 [ # # ]: 0 : if (sub_policy->main_policy_id)
1065 : 0 : return sub_policy->main_policy;
1066 : : return NULL;
1067 : : }
1068 : :
1069 : : /**
1070 : : * Get the next meter from one meter's policy in hierarchy chain.
1071 : : * Lock free, mutex should be acquired by caller.
1072 : : *
1073 : : * @param[in] priv
1074 : : * Pointer to mlx5_priv.
1075 : : * @param[in] policy
1076 : : * Pointer to flow meter policy.
1077 : : * @param[out] mtr_idx
1078 : : * Pointer to Meter index.
1079 : : *
1080 : : * @return
1081 : : * Pointer to the next meter, or NULL when fail.
1082 : : */
1083 : : struct mlx5_flow_meter_info *
1084 : 0 : mlx5_flow_meter_hierarchy_next_meter(struct mlx5_priv *priv,
1085 : : struct mlx5_flow_meter_policy *policy,
1086 : : uint32_t *mtr_idx)
1087 : : {
1088 : : int i;
1089 : :
1090 [ # # ]: 0 : for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) {
1091 [ # # ]: 0 : if (policy->act_cnt[i].fate_action == MLX5_FLOW_FATE_MTR)
1092 : 0 : return mlx5_flow_meter_find(priv,
1093 : : policy->act_cnt[i].next_mtr_id,
1094 : : mtr_idx);
1095 : : }
1096 : : return NULL;
1097 : : }
1098 : :
1099 : : /**
1100 : : * Get the last meter's policy from one meter's policy in hierarchy.
1101 : : *
1102 : : * @param[in] dev
1103 : : * Pointer to Ethernet device.
1104 : : * @param[in] policy
1105 : : * Pointer to flow meter policy.
1106 : : *
1107 : : * @return
1108 : : * Pointer to the final meter's policy, or NULL when fail.
1109 : : */
1110 : : struct mlx5_flow_meter_policy *
1111 : 0 : mlx5_flow_meter_hierarchy_get_final_policy(struct rte_eth_dev *dev,
1112 : : struct mlx5_flow_meter_policy *policy)
1113 : : {
1114 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
1115 : : struct mlx5_flow_meter_info *next_fm;
1116 : : struct mlx5_flow_meter_policy *next_policy = policy;
1117 : :
1118 [ # # ]: 0 : while (next_policy->is_hierarchy) {
1119 : 0 : rte_spinlock_lock(&next_policy->sl);
1120 : 0 : next_fm = mlx5_flow_meter_hierarchy_next_meter(priv, next_policy, NULL);
1121 : : rte_spinlock_unlock(&next_policy->sl);
1122 [ # # # # ]: 0 : if (!next_fm || next_fm->def_policy)
1123 : : return NULL;
1124 : 0 : next_policy = mlx5_flow_meter_policy_find(dev,
1125 : : next_fm->policy_id, NULL);
1126 : : MLX5_ASSERT(next_policy);
1127 : : }
1128 : : return next_policy;
1129 : : }
1130 : :
1131 : : /**
1132 : : * Callback to check MTR policy action validate
1133 : : *
1134 : : * @param[in] dev
1135 : : * Pointer to Ethernet device.
1136 : : * @param[in] actions
1137 : : * Pointer to meter policy action detail.
1138 : : * @param[out] error
1139 : : * Pointer to the error structure.
1140 : : *
1141 : : * @return
1142 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
1143 : : */
1144 : : static int
1145 : 0 : mlx5_flow_meter_policy_validate(struct rte_eth_dev *dev,
1146 : : struct rte_mtr_meter_policy_params *policy,
1147 : : struct rte_mtr_error *error)
1148 : : {
1149 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
1150 : 0 : struct rte_flow_attr attr = { .transfer = priv->sh->config.dv_esw_en ?
1151 : 0 : 1 : 0 };
1152 : 0 : bool is_rss = false;
1153 : : uint8_t policy_mode;
1154 : : uint8_t domain_bitmap;
1155 : : int ret;
1156 : :
1157 [ # # # # ]: 0 : if (!priv->mtr_en || !priv->sh->meter_aso_en)
1158 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
1159 : : RTE_MTR_ERROR_TYPE_METER_POLICY,
1160 : : NULL, "meter policy unsupported.");
1161 : 0 : ret = mlx5_flow_validate_mtr_acts(dev, policy->actions, &attr,
1162 : : &is_rss, &domain_bitmap, &policy_mode, error);
1163 [ # # ]: 0 : if (ret)
1164 : 0 : return ret;
1165 : : return 0;
1166 : : }
1167 : :
1168 : : static int
1169 : 0 : __mlx5_flow_meter_policy_delete(struct rte_eth_dev *dev,
1170 : : uint32_t policy_id,
1171 : : struct mlx5_flow_meter_policy *mtr_policy,
1172 : : struct rte_mtr_error *error,
1173 : : bool clear_l3t)
1174 : : {
1175 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
1176 : : struct mlx5_flow_meter_sub_policy *sub_policy;
1177 : : uint32_t i, j;
1178 : : uint16_t sub_policy_num;
1179 : :
1180 : 0 : rte_spinlock_lock(&mtr_policy->sl);
1181 [ # # ]: 0 : if (mtr_policy->ref_cnt) {
1182 : : rte_spinlock_unlock(&mtr_policy->sl);
1183 : 0 : return -rte_mtr_error_set(error, EBUSY,
1184 : : RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
1185 : : NULL,
1186 : : "Meter policy object is being used.");
1187 : : }
1188 : 0 : mlx5_flow_destroy_policy_rules(dev, mtr_policy);
1189 : 0 : mlx5_flow_destroy_mtr_acts(dev, mtr_policy);
1190 [ # # ]: 0 : for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
1191 : 0 : sub_policy_num = (mtr_policy->sub_policy_num >>
1192 : 0 : (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i)) &
1193 : : MLX5_MTR_SUB_POLICY_NUM_MASK;
1194 [ # # ]: 0 : if (sub_policy_num) {
1195 [ # # ]: 0 : for (j = 0; j < sub_policy_num; j++) {
1196 : 0 : sub_policy = mtr_policy->sub_policys[i][j];
1197 [ # # ]: 0 : if (sub_policy)
1198 : 0 : mlx5_ipool_free
1199 : 0 : (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
1200 : 0 : sub_policy->idx);
1201 : : }
1202 : : }
1203 : : }
1204 [ # # # # ]: 0 : if (priv->policy_idx_tbl && clear_l3t) {
1205 [ # # ]: 0 : if (mlx5_l3t_clear_entry(priv->policy_idx_tbl, policy_id)) {
1206 : : rte_spinlock_unlock(&mtr_policy->sl);
1207 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
1208 : : RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL,
1209 : : "Fail to delete policy in index table.");
1210 : : }
1211 : : }
1212 : : rte_spinlock_unlock(&mtr_policy->sl);
1213 : 0 : return 0;
1214 : : }
1215 : :
1216 : : /**
1217 : : * Callback to add MTR policy.
1218 : : *
1219 : : * @param[in] dev
1220 : : * Pointer to Ethernet device.
1221 : : * @param[out] policy_id
1222 : : * Pointer to policy id
1223 : : * @param[in] actions
1224 : : * Pointer to meter policy action detail.
1225 : : * @param[out] error
1226 : : * Pointer to the error structure.
1227 : : *
1228 : : * @return
1229 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
1230 : : */
1231 : : static int
1232 : 0 : mlx5_flow_meter_policy_add(struct rte_eth_dev *dev,
1233 : : uint32_t policy_id,
1234 : : struct rte_mtr_meter_policy_params *policy,
1235 : : struct rte_mtr_error *error)
1236 : : {
1237 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
1238 : 0 : struct rte_flow_attr attr = { .transfer = priv->sh->config.dv_esw_en ?
1239 : 0 : 1 : 0 };
1240 : 0 : uint32_t sub_policy_idx = 0;
1241 : 0 : uint32_t policy_idx = 0;
1242 : : struct mlx5_flow_meter_policy *mtr_policy = NULL;
1243 : : struct mlx5_flow_meter_sub_policy *sub_policy;
1244 : 0 : bool is_rss = false;
1245 : : uint8_t policy_mode;
1246 : : uint32_t i;
1247 : : int ret;
1248 : : uint32_t policy_size = sizeof(struct mlx5_flow_meter_policy);
1249 : : uint16_t sub_policy_num;
1250 : 0 : uint8_t domain_bitmap = 0;
1251 : : union mlx5_l3t_data data;
1252 : : bool skip_rule = false;
1253 : :
1254 [ # # ]: 0 : if (!priv->mtr_en)
1255 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
1256 : : RTE_MTR_ERROR_TYPE_METER_POLICY,
1257 : : NULL, "meter policy unsupported. ");
1258 [ # # ]: 0 : if (policy_id == MLX5_INVALID_POLICY_ID)
1259 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
1260 : : RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
1261 : : NULL, "policy ID is invalid. ");
1262 [ # # ]: 0 : if (policy_id == priv->sh->mtrmng->def_policy_id)
1263 : 0 : return -rte_mtr_error_set(error, EEXIST,
1264 : : RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
1265 : : NULL, "default policy ID exists. ");
1266 : 0 : mtr_policy = mlx5_flow_meter_policy_find(dev, policy_id, &policy_idx);
1267 [ # # ]: 0 : if (mtr_policy)
1268 : 0 : return -rte_mtr_error_set(error, EEXIST,
1269 : : RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
1270 : : NULL, "policy ID exists. ");
1271 : 0 : ret = mlx5_flow_validate_mtr_acts(dev, policy->actions, &attr,
1272 : : &is_rss, &domain_bitmap,
1273 : : &policy_mode, error);
1274 [ # # ]: 0 : if (ret)
1275 : : return ret;
1276 [ # # ]: 0 : if (!domain_bitmap)
1277 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
1278 : : RTE_MTR_ERROR_TYPE_METER_POLICY,
1279 : : NULL, "fail to find policy domain.");
1280 [ # # ]: 0 : if (policy_mode == MLX5_MTR_POLICY_MODE_DEF) {
1281 [ # # ]: 0 : if (priv->sh->mtrmng->def_policy_id != MLX5_INVALID_POLICY_ID)
1282 : 0 : return -rte_mtr_error_set(error, EEXIST,
1283 : : RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
1284 : : NULL, "a policy with similar actions "
1285 : : "is already configured");
1286 [ # # ]: 0 : if (mlx5_flow_create_def_policy(dev))
1287 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
1288 : : RTE_MTR_ERROR_TYPE_METER_POLICY,
1289 : : NULL,
1290 : : "fail to create non-terminated policy.");
1291 : 0 : priv->sh->mtrmng->def_policy_id = policy_id;
1292 : 0 : return 0;
1293 : : }
1294 [ # # ]: 0 : if (!priv->sh->meter_aso_en)
1295 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
1296 : : RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
1297 : : "no ASO capability to support the policy ");
1298 [ # # ]: 0 : for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
1299 [ # # ]: 0 : if (!(domain_bitmap & (1 << i)))
1300 : 0 : continue;
1301 : : /*
1302 : : * If RSS is found, it means that only the ingress domain can
1303 : : * be supported. It is invalid to support RSS for one color
1304 : : * and egress / transfer domain actions for another. Drop and
1305 : : * jump action should have no impact.
1306 : : */
1307 [ # # ]: 0 : if (is_rss) {
1308 : 0 : policy_size +=
1309 : : sizeof(struct mlx5_flow_meter_sub_policy *) *
1310 : : MLX5_MTR_RSS_MAX_SUB_POLICY;
1311 : 0 : break;
1312 : : }
1313 : 0 : policy_size += sizeof(struct mlx5_flow_meter_sub_policy *);
1314 : : }
1315 : 0 : mtr_policy = mlx5_malloc(MLX5_MEM_ZERO, policy_size,
1316 : : RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
1317 [ # # ]: 0 : if (!mtr_policy)
1318 : 0 : return -rte_mtr_error_set(error, ENOMEM,
1319 : : RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
1320 : : "Memory alloc failed for meter policy.");
1321 [ # # ]: 0 : if (policy_mode == MLX5_MTR_POLICY_MODE_OG)
1322 : 0 : mtr_policy->skip_y = 1;
1323 [ # # ]: 0 : else if (policy_mode == MLX5_MTR_POLICY_MODE_OY)
1324 : 0 : mtr_policy->skip_g = 1;
1325 : : policy_size = sizeof(struct mlx5_flow_meter_policy);
1326 [ # # ]: 0 : for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
1327 [ # # ]: 0 : if (!(domain_bitmap & (1 << i)))
1328 : 0 : continue;
1329 [ # # ]: 0 : if (i == MLX5_MTR_DOMAIN_INGRESS)
1330 : 0 : mtr_policy->ingress = 1;
1331 [ # # ]: 0 : if (i == MLX5_MTR_DOMAIN_EGRESS)
1332 : 0 : mtr_policy->egress = 1;
1333 [ # # ]: 0 : if (i == MLX5_MTR_DOMAIN_TRANSFER)
1334 : 0 : mtr_policy->transfer = 1;
1335 : 0 : sub_policy = mlx5_ipool_zmalloc
1336 : 0 : (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
1337 : : &sub_policy_idx);
1338 [ # # ]: 0 : if (!sub_policy ||
1339 [ # # ]: 0 : sub_policy_idx > MLX5_MAX_SUB_POLICY_TBL_NUM)
1340 : 0 : goto policy_add_err;
1341 : 0 : sub_policy->idx = sub_policy_idx;
1342 : 0 : sub_policy->main_policy = mtr_policy;
1343 [ # # ]: 0 : if (!policy_idx) {
1344 : 0 : policy_idx = sub_policy_idx;
1345 : 0 : sub_policy->main_policy_id = 1;
1346 : : }
1347 : 0 : mtr_policy->sub_policys[i] =
1348 : 0 : (struct mlx5_flow_meter_sub_policy **)
1349 : : ((uint8_t *)mtr_policy + policy_size);
1350 : 0 : mtr_policy->sub_policys[i][0] = sub_policy;
1351 : 0 : sub_policy_num = (mtr_policy->sub_policy_num >>
1352 : 0 : (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i)) &
1353 : : MLX5_MTR_SUB_POLICY_NUM_MASK;
1354 : 0 : sub_policy_num++;
1355 : 0 : mtr_policy->sub_policy_num &= ~(MLX5_MTR_SUB_POLICY_NUM_MASK <<
1356 : : (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i));
1357 : 0 : mtr_policy->sub_policy_num |=
1358 : 0 : (sub_policy_num & MLX5_MTR_SUB_POLICY_NUM_MASK) <<
1359 : : (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i);
1360 : : /*
1361 : : * If RSS is found, it means that only the ingress domain can
1362 : : * be supported. It is invalid to support RSS for one color
1363 : : * and egress / transfer domain actions for another. Drop and
1364 : : * jump action should have no impact.
1365 : : */
1366 [ # # ]: 0 : if (is_rss) {
1367 : 0 : mtr_policy->is_rss = 1;
1368 : 0 : break;
1369 : : }
1370 : 0 : policy_size += sizeof(struct mlx5_flow_meter_sub_policy *);
1371 : : }
1372 : : rte_spinlock_init(&mtr_policy->sl);
1373 : 0 : ret = mlx5_flow_create_mtr_acts(dev, mtr_policy,
1374 : : policy->actions, &attr, error);
1375 [ # # ]: 0 : if (ret)
1376 : 0 : goto policy_add_err;
1377 [ # # ]: 0 : if (mtr_policy->is_hierarchy) {
1378 : : struct mlx5_flow_meter_policy *final_policy;
1379 : :
1380 : : final_policy =
1381 : 0 : mlx5_flow_meter_hierarchy_get_final_policy(dev, mtr_policy);
1382 [ # # ]: 0 : if (!final_policy)
1383 : 0 : goto policy_add_err;
1384 : 0 : skip_rule = (final_policy->is_rss || final_policy->is_queue);
1385 : : }
1386 : : /*
1387 : : * If either Green or Yellow has queue / RSS action, all the policy
1388 : : * rules will be created later in the flow splitting stage.
1389 : : */
1390 [ # # # # : 0 : if (!is_rss && !mtr_policy->is_queue && !skip_rule) {
# # ]
1391 : : /* Create policy rules in HW. */
1392 : 0 : ret = mlx5_flow_create_policy_rules(dev, mtr_policy);
1393 [ # # ]: 0 : if (ret)
1394 : 0 : goto policy_add_err;
1395 : : }
1396 : 0 : data.dword = policy_idx;
1397 [ # # ]: 0 : if (!priv->policy_idx_tbl) {
1398 : 0 : priv->policy_idx_tbl = mlx5_l3t_create(MLX5_L3T_TYPE_DWORD);
1399 [ # # ]: 0 : if (!priv->policy_idx_tbl)
1400 : 0 : goto policy_add_err;
1401 : : }
1402 [ # # ]: 0 : if (mlx5_l3t_set_entry(priv->policy_idx_tbl, policy_id, &data))
1403 : 0 : goto policy_add_err;
1404 : : return 0;
1405 : 0 : policy_add_err:
1406 : : if (mtr_policy) {
1407 : 0 : ret = __mlx5_flow_meter_policy_delete(dev, policy_id,
1408 : : mtr_policy, error, false);
1409 : 0 : mlx5_free(mtr_policy);
1410 [ # # ]: 0 : if (ret)
1411 : : return ret;
1412 : : }
1413 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
1414 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED,
1415 : : NULL, "Failed to create devx policy.");
1416 : : }
1417 : :
1418 : : /**
1419 : : * Callback to delete MTR policy.
1420 : : *
1421 : : * @param[in] dev
1422 : : * Pointer to Ethernet device.
1423 : : * @param[in] policy_id
1424 : : * Meter policy id.
1425 : : * @param[out] error
1426 : : * Pointer to the error structure.
1427 : : *
1428 : : * @return
1429 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
1430 : : */
1431 : : static int
1432 : 0 : mlx5_flow_meter_policy_delete(struct rte_eth_dev *dev,
1433 : : uint32_t policy_id,
1434 : : struct rte_mtr_error *error)
1435 : : {
1436 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
1437 : : struct mlx5_flow_meter_policy *mtr_policy;
1438 : : uint32_t policy_idx;
1439 : : int ret;
1440 : :
1441 [ # # ]: 0 : if (policy_id == priv->sh->mtrmng->def_policy_id) {
1442 [ # # ]: 0 : if (priv->sh->mtrmng->def_policy_ref_cnt > 0)
1443 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
1444 : : RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL,
1445 : : "Meter policy object is being used.");
1446 : 0 : priv->sh->mtrmng->def_policy_id = MLX5_INVALID_POLICY_ID;
1447 : 0 : return 0;
1448 : : }
1449 : 0 : mtr_policy = mlx5_flow_meter_policy_find(dev, policy_id, &policy_idx);
1450 [ # # ]: 0 : if (!mtr_policy)
1451 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
1452 : : RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL,
1453 : : "Meter policy id is invalid. ");
1454 : 0 : ret = __mlx5_flow_meter_policy_delete(dev, policy_id, mtr_policy,
1455 : : error, true);
1456 [ # # ]: 0 : if (ret)
1457 : : return ret;
1458 : 0 : mlx5_free(mtr_policy);
1459 : 0 : return 0;
1460 : : }
1461 : :
1462 : : /**
1463 : : * Callback to get MTR policy.
1464 : : *
1465 : : * @param[in] dev
1466 : : * Pointer to Ethernet device.
1467 : : * @param[in] policy_id
1468 : : * Meter policy id.
1469 : : * @param[out] error
1470 : : * Pointer to the error structure.
1471 : : *
1472 : : * @return
1473 : : * A valid handle in case of success, NULL otherwise.
1474 : : */
1475 : : static struct rte_flow_meter_policy *
1476 : 0 : mlx5_flow_meter_policy_get(struct rte_eth_dev *dev,
1477 : : uint32_t policy_id,
1478 : : struct rte_mtr_error *error)
1479 : : {
1480 [ # # ]: 0 : struct mlx5_priv *priv = dev->data->dev_private;
1481 : : uint32_t policy_idx;
1482 : :
1483 [ # # # # ]: 0 : if (mlx5_hws_active(dev) && !mlx5_hw_ctx_validate(dev, NULL)) {
1484 : : rte_mtr_error_set(error, EINVAL,
1485 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1486 : : "non-template flow engine was not configured");
1487 : 0 : return NULL;
1488 : : }
1489 [ # # ]: 0 : if (!priv->mtr_en) {
1490 : : rte_mtr_error_set(error, ENOTSUP,
1491 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1492 : : "Meter is not supported");
1493 : 0 : return NULL;
1494 : : }
1495 : 0 : return (void *)(uintptr_t)mlx5_flow_meter_policy_find(dev, policy_id,
1496 : : &policy_idx);
1497 : : }
1498 : :
1499 : : /**
1500 : : * Check meter validation.
1501 : : *
1502 : : * @param[in] priv
1503 : : * Pointer to mlx5 private data structure.
1504 : : * @param[in] meter_id
1505 : : * Meter id.
1506 : : * @param[in] params
1507 : : * Pointer to rte meter parameters.
1508 : : * @param[out] error
1509 : : * Pointer to rte meter error structure.
1510 : : *
1511 : : * @return
1512 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
1513 : : */
1514 : : static int
1515 : 0 : mlx5_flow_meter_validate(struct mlx5_priv *priv, uint32_t meter_id,
1516 : : struct rte_mtr_params *params,
1517 : : struct rte_mtr_error *error)
1518 : : {
1519 : : /* Meter must use global drop action. */
1520 [ # # ]: 0 : if (!priv->sh->dr_drop_action)
1521 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
1522 : : RTE_MTR_ERROR_TYPE_MTR_PARAMS,
1523 : : NULL,
1524 : : "No drop action ready for meter.");
1525 : : /* Meter params must not be NULL. */
1526 [ # # ]: 0 : if (params == NULL)
1527 : 0 : return -rte_mtr_error_set(error, EINVAL,
1528 : : RTE_MTR_ERROR_TYPE_MTR_PARAMS,
1529 : : NULL, "Meter object params null.");
1530 : : /* Previous meter color is not supported. */
1531 [ # # # # ]: 0 : if (params->use_prev_mtr_color && !priv->sh->meter_aso_en)
1532 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
1533 : : RTE_MTR_ERROR_TYPE_MTR_PARAMS,
1534 : : NULL,
1535 : : "Previous meter color "
1536 : : "not supported.");
1537 [ # # ]: 0 : if (params->meter_policy_id == MLX5_INVALID_POLICY_ID)
1538 : 0 : return -rte_mtr_error_set(error, ENOENT,
1539 : : RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
1540 : : NULL, "Meter policy id not valid.");
1541 : : /* Validate meter id. */
1542 [ # # ]: 0 : if (mlx5_flow_meter_find(priv, meter_id, NULL))
1543 : 0 : return -rte_mtr_error_set(error, EEXIST,
1544 : : RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
1545 : : "Meter object already exists.");
1546 : : return 0;
1547 : : }
1548 : :
1549 : : /**
1550 : : * Modify the flow meter action.
1551 : : *
1552 : : * @param[in] priv
1553 : : * Pointer to mlx5 private data structure.
1554 : : * @param[in] fm
1555 : : * Pointer to flow meter to be modified.
1556 : : * @param[in] srtcm
1557 : : * Pointer to meter srtcm description parameter.
1558 : : * @param[in] modify_bits
1559 : : * The bit in srtcm to be updated.
1560 : : * @param[in] active_state
1561 : : * The state to be updated.
1562 : : * @return
1563 : : * 0 on success, o negative value otherwise.
1564 : : */
1565 : : static int
1566 : 0 : mlx5_flow_meter_action_modify(struct mlx5_priv *priv,
1567 : : struct mlx5_flow_meter_info *fm,
1568 : : const struct mlx5_flow_meter_srtcm_rfc2697_prm *srtcm,
1569 : : uint64_t modify_bits, uint32_t active_state, uint32_t is_enable)
1570 : : {
1571 : : #ifdef HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER
1572 : 0 : struct mlx5_dev_ctx_shared *sh = priv->sh;
1573 : 0 : uint32_t in[MLX5_ST_SZ_DW(flow_meter_parameters)] = { 0 };
1574 : : uint32_t *attr;
1575 : 0 : struct mlx5dv_dr_flow_meter_attr mod_attr = { 0 };
1576 : : int ret;
1577 : : struct mlx5_aso_mtr *aso_mtr = NULL;
1578 : : uint32_t cbs_cir, ebs_eir, val;
1579 : :
1580 [ # # ]: 0 : if (sh->meter_aso_en) {
1581 : 0 : fm->is_enable = !!is_enable;
1582 : 0 : aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
1583 : 0 : aso_mtr->state = ASO_METER_WAIT;
1584 : 0 : ret = mlx5_aso_meter_update_by_wqe(priv, MLX5_HW_INV_QUEUE,
1585 : : aso_mtr, &priv->mtr_bulk,
1586 : : NULL, true);
1587 [ # # ]: 0 : if (ret)
1588 : : return ret;
1589 : 0 : ret = mlx5_aso_mtr_wait(priv, aso_mtr, false);
1590 [ # # ]: 0 : if (ret)
1591 : 0 : return ret;
1592 : : } else {
1593 : : /* Fill command parameters. */
1594 : 0 : mod_attr.reg_c_index = sh->registers.aso_reg - REG_C_0;
1595 : 0 : mod_attr.flow_meter_parameter = in;
1596 : 0 : mod_attr.flow_meter_parameter_sz =
1597 : : MLX5_ST_SZ_BYTES(flow_meter_parameters);
1598 [ # # ]: 0 : if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_ACTIVE)
1599 : 0 : mod_attr.active = !!active_state;
1600 : : else
1601 : : mod_attr.active = 0;
1602 : : attr = in;
1603 [ # # ]: 0 : cbs_cir = rte_be_to_cpu_32(srtcm->cbs_cir);
1604 [ # # ]: 0 : ebs_eir = rte_be_to_cpu_32(srtcm->ebs_eir);
1605 [ # # ]: 0 : if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS) {
1606 : 0 : val = (cbs_cir >> ASO_DSEG_CBS_EXP_OFFSET) &
1607 : : ASO_DSEG_EXP_MASK;
1608 : 0 : MLX5_SET(flow_meter_parameters, attr,
1609 : : cbs_exponent, val);
1610 : 0 : val = (cbs_cir >> ASO_DSEG_CBS_MAN_OFFSET) &
1611 : : ASO_DSEG_MAN_MASK;
1612 [ # # ]: 0 : MLX5_SET(flow_meter_parameters, attr,
1613 : : cbs_mantissa, val);
1614 : : }
1615 [ # # ]: 0 : if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR) {
1616 : 0 : val = (cbs_cir >> ASO_DSEG_XIR_EXP_OFFSET) &
1617 : : ASO_DSEG_EXP_MASK;
1618 [ # # ]: 0 : MLX5_SET(flow_meter_parameters, attr,
1619 : : cir_exponent, val);
1620 : 0 : val = cbs_cir & ASO_DSEG_MAN_MASK;
1621 [ # # ]: 0 : MLX5_SET(flow_meter_parameters, attr,
1622 : : cir_mantissa, val);
1623 : : }
1624 [ # # ]: 0 : if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_EBS) {
1625 : 0 : val = (ebs_eir >> ASO_DSEG_EBS_EXP_OFFSET) &
1626 : : ASO_DSEG_EXP_MASK;
1627 : 0 : MLX5_SET(flow_meter_parameters, attr,
1628 : : ebs_exponent, val);
1629 : 0 : val = (ebs_eir >> ASO_DSEG_EBS_MAN_OFFSET) &
1630 : : ASO_DSEG_MAN_MASK;
1631 [ # # ]: 0 : MLX5_SET(flow_meter_parameters, attr,
1632 : : ebs_mantissa, val);
1633 : : }
1634 : : /* Apply modifications to meter only if it was created. */
1635 [ # # ]: 0 : if (fm->meter_action_g) {
1636 : 0 : ret = mlx5_glue->dv_modify_flow_action_meter
1637 : : (fm->meter_action_g, &mod_attr,
1638 [ # # ]: 0 : rte_cpu_to_be_64(modify_bits));
1639 [ # # ]: 0 : if (ret)
1640 : : return ret;
1641 : : }
1642 : : /* Update succeeded modify meter parameters. */
1643 [ # # ]: 0 : if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_ACTIVE)
1644 : 0 : fm->active_state = !!active_state;
1645 : : }
1646 : : return 0;
1647 : : #else
1648 : : (void)priv;
1649 : : (void)fm;
1650 : : (void)srtcm;
1651 : : (void)modify_bits;
1652 : : (void)active_state;
1653 : : (void)is_enable;
1654 : : return -ENOTSUP;
1655 : : #endif
1656 : : }
1657 : :
1658 : : static int
1659 : 0 : mlx5_flow_meter_stats_enable_update(struct rte_eth_dev *dev,
1660 : : struct mlx5_flow_meter_info *fm,
1661 : : uint64_t stats_mask)
1662 : : {
1663 : 0 : fm->bytes_dropped =
1664 : 0 : (stats_mask & RTE_MTR_STATS_N_BYTES_DROPPED) ? 1 : 0;
1665 : 0 : fm->pkts_dropped = (stats_mask & RTE_MTR_STATS_N_PKTS_DROPPED) ? 1 : 0;
1666 [ # # ]: 0 : if (fm->bytes_dropped || fm->pkts_dropped) {
1667 [ # # ]: 0 : if (!fm->drop_cnt) {
1668 : : /* Alloc policer counters. */
1669 : 0 : fm->drop_cnt = mlx5_counter_alloc(dev);
1670 [ # # ]: 0 : if (!fm->drop_cnt)
1671 : 0 : return -1;
1672 : : }
1673 : : } else {
1674 [ # # ]: 0 : if (fm->drop_cnt) {
1675 : 0 : mlx5_counter_free(dev, fm->drop_cnt);
1676 : 0 : fm->drop_cnt = 0;
1677 : : }
1678 : : }
1679 : : return 0;
1680 : : }
1681 : :
1682 : : /**
1683 : : * Create meter rules.
1684 : : *
1685 : : * @param[in] dev
1686 : : * Pointer to Ethernet device.
1687 : : * @param[in] meter_id
1688 : : * Meter id.
1689 : : * @param[in] params
1690 : : * Pointer to rte meter parameters.
1691 : : * @param[in] shared
1692 : : * Meter shared with other flow or not.
1693 : : * @param[out] error
1694 : : * Pointer to rte meter error structure.
1695 : : *
1696 : : * @return
1697 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
1698 : : */
1699 : : static int
1700 : 0 : mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,
1701 : : struct rte_mtr_params *params, int shared,
1702 : : struct rte_mtr_error *error)
1703 : : {
1704 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
1705 : : struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
1706 : : struct mlx5_flow_meter_profile *fmp;
1707 : : struct mlx5_flow_meter_info *fm;
1708 : : /* GCC fails to infer legacy_fm is set when !priv->sh->meter_aso_en. */
1709 : : struct mlx5_legacy_flow_meter *legacy_fm = NULL;
1710 : : struct mlx5_flow_meter_policy *mtr_policy = NULL;
1711 : 0 : struct mlx5_indexed_pool_config flow_ipool_cfg = {
1712 : : .size = 0,
1713 : : .trunk_size = 64,
1714 : : .need_lock = 1,
1715 : : .type = "mlx5_flow_mtr_flow_id_pool",
1716 : : };
1717 : : struct mlx5_aso_mtr *aso_mtr;
1718 : : uint32_t mtr_idx, policy_idx;
1719 : : union mlx5_l3t_data data;
1720 : : int ret;
1721 : : uint8_t domain_bitmap;
1722 : : uint8_t mtr_id_bits;
1723 [ # # ]: 0 : uint8_t mtr_reg_bits = priv->mtr_reg_share ?
1724 : : MLX5_MTR_IDLE_BITS_IN_COLOR_REG : MLX5_REG_BITS;
1725 : :
1726 [ # # ]: 0 : if (!priv->mtr_en)
1727 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
1728 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1729 : : "Meter is not supported");
1730 : : /* Validate the parameters. */
1731 : 0 : ret = mlx5_flow_meter_validate(priv, meter_id, params, error);
1732 [ # # ]: 0 : if (ret)
1733 : : return ret;
1734 : : /* Meter profile must exist. */
1735 : 0 : fmp = mlx5_flow_meter_profile_find(priv, params->meter_profile_id);
1736 [ # # ]: 0 : if (fmp == NULL)
1737 : 0 : return -rte_mtr_error_set(error, ENOENT,
1738 : : RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
1739 : : NULL, "Meter profile id not valid.");
1740 : : /* Meter policy must exist. */
1741 [ # # ]: 0 : if (params->meter_policy_id == priv->sh->mtrmng->def_policy_id) {
1742 : 0 : rte_atomic_fetch_add_explicit
1743 : : (&priv->sh->mtrmng->def_policy_ref_cnt,
1744 : : 1, rte_memory_order_relaxed);
1745 : : domain_bitmap = MLX5_MTR_ALL_DOMAIN_BIT;
1746 [ # # ]: 0 : if (!priv->sh->config.dv_esw_en)
1747 : : domain_bitmap &= ~MLX5_MTR_DOMAIN_TRANSFER_BIT;
1748 : : } else {
1749 [ # # ]: 0 : if (!priv->sh->meter_aso_en)
1750 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
1751 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1752 : : "Part of the policies cannot be "
1753 : : "supported without ASO ");
1754 : 0 : mtr_policy = mlx5_flow_meter_policy_find(dev,
1755 : : params->meter_policy_id, &policy_idx);
1756 [ # # ]: 0 : if (!mtr_policy)
1757 : 0 : return -rte_mtr_error_set(error, ENOENT,
1758 : : RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
1759 : : NULL, "Meter policy id not valid.");
1760 : 0 : domain_bitmap = (mtr_policy->ingress ?
1761 : 0 : MLX5_MTR_DOMAIN_INGRESS_BIT : 0) |
1762 : : (mtr_policy->egress ?
1763 : : MLX5_MTR_DOMAIN_EGRESS_BIT : 0) |
1764 : : (mtr_policy->transfer ?
1765 : : MLX5_MTR_DOMAIN_TRANSFER_BIT : 0);
1766 [ # # # # ]: 0 : if (fmp->g_support && mtr_policy->skip_g)
1767 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
1768 : : RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
1769 : : NULL, "Meter green policy is empty.");
1770 [ # # # # ]: 0 : if (fmp->y_support && mtr_policy->skip_y)
1771 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
1772 : : RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
1773 : : NULL, "Meter yellow policy is empty.");
1774 : : }
1775 : : /* Allocate the flow meter memory. */
1776 [ # # ]: 0 : if (priv->sh->meter_aso_en) {
1777 : 0 : mtr_idx = mlx5_flow_mtr_alloc(dev);
1778 [ # # ]: 0 : if (!mtr_idx)
1779 : 0 : return -rte_mtr_error_set(error, ENOMEM,
1780 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1781 : : "Memory alloc failed for meter.");
1782 : 0 : aso_mtr = mlx5_aso_meter_by_idx(priv, mtr_idx);
1783 : 0 : fm = &aso_mtr->fm;
1784 : : } else {
1785 [ # # ]: 0 : if (fmp->y_support)
1786 : 0 : return -rte_mtr_error_set(error, ENOMEM,
1787 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1788 : : "Unsupported profile with yellow.");
1789 : 0 : legacy_fm = mlx5_ipool_zmalloc
1790 : : (priv->sh->ipool[MLX5_IPOOL_MTR], &mtr_idx);
1791 [ # # ]: 0 : if (legacy_fm == NULL)
1792 : 0 : return -rte_mtr_error_set(error, ENOMEM,
1793 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1794 : : "Memory alloc failed for meter.");
1795 : 0 : legacy_fm->idx = mtr_idx;
1796 : 0 : fm = &legacy_fm->fm;
1797 : : }
1798 [ # # ]: 0 : mtr_id_bits = MLX5_REG_BITS - rte_clz32(mtr_idx);
1799 [ # # ]: 0 : if ((mtr_id_bits + priv->sh->mtrmng->max_mtr_flow_bits) >
1800 : : mtr_reg_bits) {
1801 : 0 : DRV_LOG(ERR, "Meter number exceeds max limit.");
1802 : 0 : goto error;
1803 : : }
1804 [ # # ]: 0 : if (mtr_id_bits > priv->sh->mtrmng->max_mtr_bits)
1805 : 0 : priv->sh->mtrmng->max_mtr_bits = mtr_id_bits;
1806 : : /* Fill the flow meter parameters. */
1807 : 0 : fm->meter_id = meter_id;
1808 : 0 : fm->policy_id = params->meter_policy_id;
1809 : 0 : fm->profile = fmp;
1810 [ # # ]: 0 : if (mlx5_flow_meter_stats_enable_update(dev, fm, params->stats_mask))
1811 : 0 : goto error;
1812 [ # # ]: 0 : if (mlx5_flow_create_mtr_tbls(dev, fm, mtr_idx, domain_bitmap))
1813 : 0 : goto error;
1814 : : /* Add to the flow meter list. */
1815 [ # # ]: 0 : if (!priv->sh->meter_aso_en) {
1816 : : MLX5_ASSERT(legacy_fm != NULL);
1817 : 0 : TAILQ_INSERT_TAIL(fms, legacy_fm, next);
1818 : : }
1819 : : /* Add to the flow meter list. */
1820 : 0 : fm->active_state = 1; /* Config meter starts as active. */
1821 : 0 : fm->is_enable = params->meter_enable;
1822 : 0 : fm->shared = !!shared;
1823 : 0 : fm->color_aware = !!params->use_prev_mtr_color;
1824 : 0 : rte_atomic_fetch_add_explicit(&fm->profile->ref_cnt, 1, rte_memory_order_relaxed);
1825 [ # # ]: 0 : if (params->meter_policy_id == priv->sh->mtrmng->def_policy_id) {
1826 : 0 : fm->def_policy = 1;
1827 : 0 : fm->flow_ipool = mlx5_ipool_create(&flow_ipool_cfg);
1828 [ # # ]: 0 : if (!fm->flow_ipool)
1829 : 0 : goto error;
1830 : : }
1831 : : rte_spinlock_init(&fm->sl);
1832 : : /* If ASO meter supported, update ASO flow meter by wqe. */
1833 [ # # ]: 0 : if (priv->sh->meter_aso_en) {
1834 : 0 : aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
1835 : 0 : aso_mtr->state = ASO_METER_WAIT;
1836 : 0 : ret = mlx5_aso_meter_update_by_wqe(priv, MLX5_HW_INV_QUEUE,
1837 : : aso_mtr, &priv->mtr_bulk, NULL, true);
1838 [ # # ]: 0 : if (ret)
1839 : 0 : goto error;
1840 [ # # ]: 0 : if (!priv->mtr_idx_tbl) {
1841 : 0 : priv->mtr_idx_tbl =
1842 : 0 : mlx5_l3t_create(MLX5_L3T_TYPE_DWORD);
1843 [ # # ]: 0 : if (!priv->mtr_idx_tbl)
1844 : 0 : goto error;
1845 : : }
1846 : 0 : data.dword = mtr_idx;
1847 [ # # ]: 0 : if (mlx5_l3t_set_entry(priv->mtr_idx_tbl, meter_id, &data))
1848 : 0 : goto error;
1849 [ # # # # ]: 0 : } else if (!params->meter_enable && mlx5_flow_meter_disable(dev, meter_id, error)) {
1850 : 0 : goto error;
1851 : : }
1852 : 0 : fm->active_state = params->meter_enable;
1853 [ # # ]: 0 : if (mtr_policy)
1854 : 0 : rte_atomic_fetch_add_explicit(&mtr_policy->ref_cnt, 1, rte_memory_order_relaxed);
1855 : : return 0;
1856 : 0 : error:
1857 : 0 : mlx5_flow_destroy_mtr_tbls(dev, fm);
1858 : : /* Free policer counters. */
1859 [ # # ]: 0 : if (fm->drop_cnt)
1860 : 0 : mlx5_counter_free(dev, fm->drop_cnt);
1861 [ # # ]: 0 : if (priv->sh->meter_aso_en)
1862 : 0 : mlx5_flow_mtr_free(dev, mtr_idx);
1863 : : else
1864 : 0 : mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR], mtr_idx);
1865 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
1866 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED,
1867 : : NULL, "Failed to create devx meter.");
1868 : : }
1869 : :
1870 : : static int
1871 : 0 : mlx5_flow_meter_params_flush(struct rte_eth_dev *dev,
1872 : : struct mlx5_flow_meter_info *fm,
1873 : : uint32_t mtr_idx)
1874 : : {
1875 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
1876 : : struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
1877 : : struct mlx5_flow_meter_profile *fmp;
1878 : : struct mlx5_legacy_flow_meter *legacy_fm = NULL;
1879 : : struct mlx5_flow_meter_policy *mtr_policy;
1880 : :
1881 : : /* Meter object must not have any owner. */
1882 : : MLX5_ASSERT(!fm->ref_cnt);
1883 : : /* Get meter profile. */
1884 : 0 : fmp = fm->profile;
1885 [ # # ]: 0 : if (fmp == NULL)
1886 : : return -1;
1887 : : /* Update dependencies. */
1888 : 0 : rte_atomic_fetch_sub_explicit(&fmp->ref_cnt, 1, rte_memory_order_relaxed);
1889 : 0 : fm->profile = NULL;
1890 : : /* Remove from list. */
1891 [ # # ]: 0 : if (!priv->sh->meter_aso_en) {
1892 : : legacy_fm = container_of(fm,
1893 : : struct mlx5_legacy_flow_meter, fm);
1894 [ # # ]: 0 : TAILQ_REMOVE(fms, legacy_fm, next);
1895 : : }
1896 : : /* Free drop counters. */
1897 [ # # ]: 0 : if (fm->drop_cnt)
1898 : 0 : mlx5_counter_free(dev, fm->drop_cnt);
1899 : : /* Free meter flow table. */
1900 [ # # ]: 0 : if (fm->flow_ipool) {
1901 : 0 : mlx5_ipool_destroy(fm->flow_ipool);
1902 : 0 : fm->flow_ipool = 0;
1903 : : }
1904 : 0 : mlx5_flow_destroy_mtr_tbls(dev, fm);
1905 [ # # ]: 0 : if (fm->def_policy)
1906 : 0 : rte_atomic_fetch_sub_explicit(&priv->sh->mtrmng->def_policy_ref_cnt,
1907 : : 1, rte_memory_order_relaxed);
1908 [ # # ]: 0 : if (priv->sh->meter_aso_en) {
1909 [ # # ]: 0 : if (!fm->def_policy) {
1910 : 0 : mtr_policy = mlx5_flow_meter_policy_find(dev,
1911 : : fm->policy_id, NULL);
1912 [ # # ]: 0 : if (mtr_policy)
1913 : 0 : rte_atomic_fetch_sub_explicit(&mtr_policy->ref_cnt,
1914 : : 1, rte_memory_order_relaxed);
1915 : 0 : fm->policy_id = 0;
1916 : : }
1917 : 0 : fm->def_policy = 0;
1918 [ # # ]: 0 : if (mlx5_l3t_clear_entry(priv->mtr_idx_tbl, fm->meter_id))
1919 : : return -1;
1920 : 0 : mlx5_flow_mtr_free(dev, mtr_idx);
1921 : : } else {
1922 : 0 : mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR],
1923 : : legacy_fm->idx);
1924 : : }
1925 : : return 0;
1926 : : }
1927 : :
1928 : : /**
1929 : : * Destroy meter rules.
1930 : : *
1931 : : * @param[in] dev
1932 : : * Pointer to Ethernet device.
1933 : : * @param[in] meter_id
1934 : : * Meter id.
1935 : : * @param[out] error
1936 : : * Pointer to rte meter error structure.
1937 : : *
1938 : : * @return
1939 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
1940 : : */
1941 : : static int
1942 : 0 : mlx5_flow_meter_destroy(struct rte_eth_dev *dev, uint32_t meter_id,
1943 : : struct rte_mtr_error *error)
1944 : : {
1945 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
1946 : : struct mlx5_flow_meter_info *fm;
1947 : 0 : uint32_t mtr_idx = 0;
1948 : :
1949 [ # # ]: 0 : if (!priv->mtr_en)
1950 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
1951 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED,
1952 : : NULL,
1953 : : "Meter is not supported");
1954 : : /* Meter object must exist. */
1955 : 0 : fm = mlx5_flow_meter_find(priv, meter_id, &mtr_idx);
1956 [ # # ]: 0 : if (fm == NULL)
1957 : 0 : return -rte_mtr_error_set(error, ENOENT,
1958 : : RTE_MTR_ERROR_TYPE_MTR_ID,
1959 : : NULL,
1960 : : "Meter object id not valid.");
1961 : : /* Meter object must not have any owner. */
1962 [ # # ]: 0 : if (fm->ref_cnt > 0)
1963 : 0 : return -rte_mtr_error_set(error, EBUSY,
1964 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED,
1965 : : NULL,
1966 : : "Meter object is being used.");
1967 : : /* Destroy the meter profile. */
1968 [ # # ]: 0 : if (mlx5_flow_meter_params_flush(dev, fm, mtr_idx))
1969 : 0 : return -rte_mtr_error_set(error, EINVAL,
1970 : : RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
1971 : : NULL,
1972 : : "MTR object meter profile invalid.");
1973 : : return 0;
1974 : : }
1975 : :
1976 : : /**
1977 : : * Modify meter state.
1978 : : *
1979 : : * @param[in] priv
1980 : : * Pointer to mlx5 private data structure.
1981 : : * @param[in] fm
1982 : : * Pointer to flow meter.
1983 : : * @param[in] new_state
1984 : : * New state to update.
1985 : : * @param[out] error
1986 : : * Pointer to rte meter error structure.
1987 : : *
1988 : : * @return
1989 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
1990 : : */
1991 : : static int
1992 : 0 : mlx5_flow_meter_modify_state(struct mlx5_priv *priv,
1993 : : struct mlx5_flow_meter_info *fm,
1994 : : uint32_t new_state,
1995 : : struct rte_mtr_error *error)
1996 : : {
1997 : : static const struct mlx5_flow_meter_srtcm_rfc2697_prm srtcm = {
1998 : : .cbs_cir = RTE_BE32(MLX5_IFC_FLOW_METER_DISABLE_CBS_CIR_VAL),
1999 : : .ebs_eir = 0,
2000 : : };
2001 : : uint64_t modify_bits = MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS |
2002 : : MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR;
2003 : : int ret;
2004 : :
2005 [ # # ]: 0 : if (new_state == MLX5_FLOW_METER_DISABLE)
2006 : 0 : ret = mlx5_flow_meter_action_modify(priv, fm,
2007 : : &srtcm, modify_bits, 0, 0);
2008 : : else
2009 : 0 : ret = mlx5_flow_meter_action_modify(priv, fm,
2010 : 0 : &fm->profile->srtcm_prm,
2011 : : modify_bits, 0, 1);
2012 [ # # ]: 0 : if (ret)
2013 [ # # # # ]: 0 : return -rte_mtr_error_set(error, -ret,
2014 : : RTE_MTR_ERROR_TYPE_MTR_PARAMS,
2015 : : NULL,
2016 : : new_state ?
2017 : : "Failed to enable meter." :
2018 : : "Failed to disable meter.");
2019 : : return 0;
2020 : : }
2021 : :
2022 : : /**
2023 : : * Callback to enable flow meter.
2024 : : *
2025 : : * @param[in] dev
2026 : : * Pointer to Ethernet device.
2027 : : * @param[in] meter_id
2028 : : * Meter id.
2029 : : * @param[out] error
2030 : : * Pointer to rte meter error structure.
2031 : : *
2032 : : * @return
2033 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
2034 : : */
2035 : : static int
2036 : 0 : mlx5_flow_meter_enable(struct rte_eth_dev *dev,
2037 : : uint32_t meter_id,
2038 : : struct rte_mtr_error *error)
2039 : : {
2040 [ # # ]: 0 : struct mlx5_priv *priv = dev->data->dev_private;
2041 : : struct mlx5_flow_meter_info *fm;
2042 : : int ret;
2043 : :
2044 [ # # # # ]: 0 : if (mlx5_hws_active(dev) && !mlx5_hw_ctx_validate(dev, NULL))
2045 : 0 : return -rte_mtr_error_set(error, EINVAL,
2046 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
2047 : : "non-template flow engine was not configured");
2048 [ # # ]: 0 : if (!priv->mtr_en)
2049 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
2050 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
2051 : : "Meter is not supported");
2052 : : /* Meter object must exist. */
2053 : 0 : fm = mlx5_flow_meter_find(priv, meter_id, NULL);
2054 [ # # ]: 0 : if (fm == NULL)
2055 : 0 : return -rte_mtr_error_set(error, ENOENT,
2056 : : RTE_MTR_ERROR_TYPE_MTR_ID,
2057 : : NULL, "Meter not found.");
2058 [ # # ]: 0 : if (fm->active_state == MLX5_FLOW_METER_ENABLE)
2059 : : return 0;
2060 : 0 : ret = mlx5_flow_meter_modify_state(priv, fm, MLX5_FLOW_METER_ENABLE,
2061 : : error);
2062 [ # # ]: 0 : if (!ret)
2063 : 0 : fm->active_state = MLX5_FLOW_METER_ENABLE;
2064 : : return ret;
2065 : : }
2066 : :
2067 : : /**
2068 : : * Callback to disable flow meter.
2069 : : *
2070 : : * @param[in] dev
2071 : : * Pointer to Ethernet device.
2072 : : * @param[in] meter_id
2073 : : * Meter id.
2074 : : * @param[out] error
2075 : : * Pointer to rte meter error structure.
2076 : : *
2077 : : * @return
2078 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
2079 : : */
2080 : : static int
2081 : 0 : mlx5_flow_meter_disable(struct rte_eth_dev *dev,
2082 : : uint32_t meter_id,
2083 : : struct rte_mtr_error *error)
2084 : : {
2085 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
2086 : : struct mlx5_flow_meter_info *fm;
2087 : : int ret;
2088 : :
2089 [ # # ]: 0 : if (!priv->mtr_en)
2090 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
2091 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
2092 : : "Meter is not supported");
2093 : : /* Meter object must exist. */
2094 : 0 : fm = mlx5_flow_meter_find(priv, meter_id, NULL);
2095 [ # # ]: 0 : if (fm == NULL)
2096 : 0 : return -rte_mtr_error_set(error, ENOENT,
2097 : : RTE_MTR_ERROR_TYPE_MTR_ID,
2098 : : NULL, "Meter not found.");
2099 [ # # ]: 0 : if (fm->active_state == MLX5_FLOW_METER_DISABLE)
2100 : : return 0;
2101 : 0 : ret = mlx5_flow_meter_modify_state(priv, fm, MLX5_FLOW_METER_DISABLE,
2102 : : error);
2103 [ # # ]: 0 : if (!ret)
2104 : 0 : fm->active_state = MLX5_FLOW_METER_DISABLE;
2105 : : return ret;
2106 : : }
2107 : :
2108 : : /**
2109 : : * Callback to update meter profile.
2110 : : *
2111 : : * @param[in] dev
2112 : : * Pointer to Ethernet device.
2113 : : * @param[in] meter_id
2114 : : * Meter id.
2115 : : * @param[in] meter_profile_id
2116 : : * To be updated meter profile id.
2117 : : * @param[out] error
2118 : : * Pointer to rte meter error structure.
2119 : : *
2120 : : * @return
2121 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
2122 : : */
2123 : : static int
2124 : 0 : mlx5_flow_meter_profile_update(struct rte_eth_dev *dev,
2125 : : uint32_t meter_id,
2126 : : uint32_t meter_profile_id,
2127 : : struct rte_mtr_error *error)
2128 : : {
2129 [ # # ]: 0 : struct mlx5_priv *priv = dev->data->dev_private;
2130 : : struct mlx5_flow_meter_profile *fmp;
2131 : : struct mlx5_flow_meter_profile *old_fmp;
2132 : : struct mlx5_flow_meter_info *fm;
2133 : : uint64_t modify_bits = MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS |
2134 : : MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR;
2135 : : int ret;
2136 : :
2137 [ # # # # ]: 0 : if (mlx5_hws_active(dev) && !mlx5_hw_ctx_validate(dev, NULL))
2138 : 0 : return -rte_mtr_error_set(error, EINVAL,
2139 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
2140 : : "non-template flow engine was not configured");
2141 [ # # ]: 0 : if (!priv->mtr_en)
2142 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
2143 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
2144 : : "Meter is not supported");
2145 : : /* Meter profile must exist. */
2146 : 0 : fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id);
2147 [ # # ]: 0 : if (fmp == NULL)
2148 : 0 : return -rte_mtr_error_set(error, ENOENT,
2149 : : RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
2150 : : NULL, "Meter profile not found.");
2151 : : /* Meter object must exist. */
2152 : 0 : fm = mlx5_flow_meter_find(priv, meter_id, NULL);
2153 [ # # ]: 0 : if (fm == NULL)
2154 : 0 : return -rte_mtr_error_set(error, ENOENT,
2155 : : RTE_MTR_ERROR_TYPE_MTR_ID,
2156 : : NULL, "Meter not found.");
2157 : : /* MTR object already set to meter profile id. */
2158 : 0 : old_fmp = fm->profile;
2159 [ # # ]: 0 : if (fmp == old_fmp)
2160 : : return 0;
2161 : : /* Update the profile. */
2162 : 0 : fm->profile = fmp;
2163 : : /* Update meter params in HW (if not disabled). */
2164 [ # # ]: 0 : if (fm->active_state == MLX5_FLOW_METER_DISABLE)
2165 : 0 : goto dec_ref_cnt;
2166 : 0 : ret = mlx5_flow_meter_action_modify(priv, fm, &fm->profile->srtcm_prm,
2167 : 0 : modify_bits, fm->active_state, 1);
2168 [ # # ]: 0 : if (ret) {
2169 : 0 : fm->profile = old_fmp;
2170 [ # # ]: 0 : return -rte_mtr_error_set(error, -ret,
2171 : : RTE_MTR_ERROR_TYPE_MTR_PARAMS,
2172 : : NULL, "Failed to update meter"
2173 : : " parameters in hardware.");
2174 : : }
2175 : 0 : dec_ref_cnt:
2176 : 0 : old_fmp->ref_cnt--;
2177 : 0 : fmp->ref_cnt++;
2178 : 0 : return 0;
2179 : : }
2180 : :
2181 : : /**
2182 : : * Callback to update meter stats mask.
2183 : : *
2184 : : * @param[in] dev
2185 : : * Pointer to Ethernet device.
2186 : : * @param[in] meter_id
2187 : : * Meter id.
2188 : : * @param[in] stats_mask
2189 : : * To be updated stats_mask.
2190 : : * @param[out] error
2191 : : * Pointer to rte meter error structure.
2192 : : *
2193 : : * @return
2194 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
2195 : : */
2196 : : static int
2197 : 0 : mlx5_flow_meter_stats_update(struct rte_eth_dev *dev,
2198 : : uint32_t meter_id,
2199 : : uint64_t stats_mask,
2200 : : struct rte_mtr_error *error)
2201 : : {
2202 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
2203 : : struct mlx5_flow_meter_info *fm;
2204 : :
2205 [ # # ]: 0 : if (!priv->mtr_en)
2206 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
2207 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
2208 : : "Meter is not supported");
2209 : : /* Meter object must exist. */
2210 : 0 : fm = mlx5_flow_meter_find(priv, meter_id, NULL);
2211 [ # # ]: 0 : if (fm == NULL)
2212 : 0 : return -rte_mtr_error_set(error, ENOENT,
2213 : : RTE_MTR_ERROR_TYPE_MTR_ID,
2214 : : NULL, "Meter object id not valid.");
2215 [ # # ]: 0 : if (mlx5_flow_meter_stats_enable_update(dev, fm, stats_mask))
2216 : 0 : return -rte_mtr_error_set(error, ENOENT,
2217 : : RTE_MTR_ERROR_TYPE_MTR_ID,
2218 : : NULL, "Fail to allocate "
2219 : : "counter for meter.");
2220 : : return 0;
2221 : : }
2222 : :
2223 : : /**
2224 : : * Callback to read meter statistics.
2225 : : *
2226 : : * @param[in] dev
2227 : : * Pointer to Ethernet device.
2228 : : * @param[in] meter_id
2229 : : * Meter id.
2230 : : * @param[out] stats
2231 : : * Pointer to store the statistics.
2232 : : * @param[out] stats_mask
2233 : : * Pointer to store the stats_mask.
2234 : : * @param[in] clear
2235 : : * Statistic to be cleared after read or not.
2236 : : * @param[out] error
2237 : : * Pointer to rte meter error structure.
2238 : : *
2239 : : * @return
2240 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
2241 : : */
2242 : : static int
2243 : 0 : mlx5_flow_meter_stats_read(struct rte_eth_dev *dev,
2244 : : uint32_t meter_id,
2245 : : struct rte_mtr_stats *stats,
2246 : : uint64_t *stats_mask,
2247 : : int clear,
2248 : : struct rte_mtr_error *error)
2249 : : {
2250 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
2251 : : struct mlx5_flow_meter_info *fm;
2252 : : uint64_t pkts;
2253 : : uint64_t bytes;
2254 : : int ret = 0;
2255 : :
2256 [ # # ]: 0 : if (!priv->mtr_en)
2257 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
2258 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
2259 : : "Meter is not supported");
2260 : : /* Meter object must exist. */
2261 : 0 : fm = mlx5_flow_meter_find(priv, meter_id, NULL);
2262 [ # # ]: 0 : if (fm == NULL)
2263 : 0 : return -rte_mtr_error_set(error, ENOENT,
2264 : : RTE_MTR_ERROR_TYPE_MTR_ID,
2265 : : NULL, "Meter object id not valid.");
2266 : 0 : *stats_mask = 0;
2267 [ # # ]: 0 : if (fm->bytes_dropped)
2268 : 0 : *stats_mask |= RTE_MTR_STATS_N_BYTES_DROPPED;
2269 [ # # ]: 0 : if (fm->pkts_dropped)
2270 : 0 : *stats_mask |= RTE_MTR_STATS_N_PKTS_DROPPED;
2271 : : memset(stats, 0, sizeof(*stats));
2272 [ # # ]: 0 : if (fm->drop_cnt) {
2273 : 0 : ret = mlx5_counter_query(dev, fm->drop_cnt, clear, &pkts,
2274 : : &bytes, NULL);
2275 [ # # ]: 0 : if (ret)
2276 [ # # ]: 0 : goto error;
2277 : : /* If need to read the packets, set it. */
2278 [ # # ]: 0 : if (fm->pkts_dropped)
2279 : 0 : stats->n_pkts_dropped = pkts;
2280 : : /* If need to read the bytes, set it. */
2281 [ # # ]: 0 : if (fm->bytes_dropped)
2282 : 0 : stats->n_bytes_dropped = bytes;
2283 : : }
2284 : : return 0;
2285 : : error:
2286 : 0 : return -rte_mtr_error_set(error, ret, RTE_MTR_ERROR_TYPE_STATS, NULL,
2287 : : "Failed to read meter drop counters.");
2288 : : }
2289 : :
2290 : : static const struct rte_mtr_ops mlx5_flow_mtr_ops = {
2291 : : .capabilities_get = mlx5_flow_mtr_cap_get,
2292 : : .meter_profile_add = mlx5_flow_meter_profile_add,
2293 : : .meter_profile_delete = mlx5_flow_meter_profile_delete,
2294 : : .meter_profile_get = mlx5_flow_meter_profile_get,
2295 : : .meter_policy_validate = mlx5_flow_meter_policy_validate,
2296 : : .meter_policy_add = mlx5_flow_meter_policy_add,
2297 : : .meter_policy_delete = mlx5_flow_meter_policy_delete,
2298 : : .meter_policy_get = mlx5_flow_meter_policy_get,
2299 : : .create = mlx5_flow_meter_create,
2300 : : .destroy = mlx5_flow_meter_destroy,
2301 : : .meter_enable = mlx5_flow_meter_enable,
2302 : : .meter_disable = mlx5_flow_meter_disable,
2303 : : .meter_profile_update = mlx5_flow_meter_profile_update,
2304 : : .meter_dscp_table_update = NULL,
2305 : : .stats_update = mlx5_flow_meter_stats_update,
2306 : : .stats_read = mlx5_flow_meter_stats_read,
2307 : : };
2308 : :
2309 : : #if defined(HAVE_MLX5_HWS_SUPPORT)
2310 : : static const struct rte_mtr_ops mlx5_flow_mtr_hws_ops = {
2311 : : .capabilities_get = mlx5_flow_mtr_cap_get,
2312 : : .meter_profile_add = mlx5_flow_meter_profile_hws_add,
2313 : : .meter_profile_delete = mlx5_flow_meter_profile_hws_delete,
2314 : : .meter_profile_get = mlx5_flow_meter_profile_get,
2315 : : .meter_profile_update = mlx5_flow_meter_profile_update,
2316 : : .meter_dscp_table_update = NULL,
2317 : : .stats_update = NULL,
2318 : : .stats_read = NULL,
2319 : : };
2320 : : #endif
2321 : :
2322 : : /**
2323 : : * Get meter operations.
2324 : : *
2325 : : * @param dev
2326 : : * Pointer to Ethernet device structure.
2327 : : * @param arg
2328 : : * Pointer to set the mtr operations.
2329 : : *
2330 : : * @return
2331 : : * Always 0.
2332 : : */
2333 : : int
2334 : 0 : mlx5_flow_meter_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)
2335 : : {
2336 : : #if defined(HAVE_MLX5_HWS_SUPPORT)
2337 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
2338 : :
2339 [ # # ]: 0 : if (priv->sh->config.dv_flow_en == 2)
2340 : 0 : *(const struct rte_mtr_ops **)arg = &mlx5_flow_mtr_hws_ops;
2341 : : else
2342 : 0 : *(const struct rte_mtr_ops **)arg = &mlx5_flow_mtr_ops;
2343 : : #else
2344 : : *(const struct rte_mtr_ops **)arg = &mlx5_flow_mtr_ops;
2345 : : #endif
2346 : 0 : return 0;
2347 : : }
2348 : :
2349 : : /**
2350 : : * Find meter by id.
2351 : : *
2352 : : * @param priv
2353 : : * Pointer to mlx5_priv.
2354 : : * @param meter_id
2355 : : * Meter id.
2356 : : * @param mtr_idx
2357 : : * Pointer to Meter index.
2358 : : *
2359 : : * @return
2360 : : * Pointer to the meter info found on success, NULL otherwise.
2361 : : */
2362 : : struct mlx5_flow_meter_info *
2363 : 0 : mlx5_flow_meter_find(struct mlx5_priv *priv, uint32_t meter_id,
2364 : : uint32_t *mtr_idx)
2365 : : {
2366 : : struct mlx5_legacy_flow_meter *legacy_fm;
2367 : : struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
2368 : : struct mlx5_aso_mtr *aso_mtr;
2369 : : struct mlx5_aso_mtr_pools_mng *pools_mng =
2370 : 0 : &priv->sh->mtrmng->pools_mng;
2371 : : union mlx5_l3t_data data;
2372 : : uint16_t n_valid;
2373 : :
2374 [ # # ]: 0 : if (priv->mtr_bulk.aso) {
2375 [ # # ]: 0 : if (mtr_idx)
2376 : 0 : *mtr_idx = meter_id;
2377 : 0 : aso_mtr = priv->mtr_bulk.aso + meter_id;
2378 : 0 : return &aso_mtr->fm;
2379 : : }
2380 [ # # ]: 0 : if (priv->sh->meter_aso_en) {
2381 : 0 : rte_rwlock_read_lock(&pools_mng->resize_mtrwl);
2382 [ # # ]: 0 : n_valid = pools_mng->n_valid;
2383 : : rte_rwlock_read_unlock(&pools_mng->resize_mtrwl);
2384 [ # # # # : 0 : if (!n_valid || !priv->mtr_idx_tbl ||
# # ]
2385 : 0 : (mlx5_l3t_get_entry(priv->mtr_idx_tbl, meter_id, &data) ||
2386 [ # # ]: 0 : !data.dword))
2387 : 0 : return NULL;
2388 [ # # ]: 0 : if (mtr_idx)
2389 : 0 : *mtr_idx = data.dword;
2390 : 0 : aso_mtr = mlx5_aso_meter_by_idx(priv, data.dword);
2391 : : /* Remove reference taken by the mlx5_l3t_get_entry. */
2392 : 0 : mlx5_l3t_clear_entry(priv->mtr_idx_tbl, meter_id);
2393 [ # # # # ]: 0 : if (!aso_mtr || aso_mtr->state == ASO_METER_FREE)
2394 : : return NULL;
2395 : 0 : return &aso_mtr->fm;
2396 : : }
2397 [ # # ]: 0 : TAILQ_FOREACH(legacy_fm, fms, next)
2398 [ # # ]: 0 : if (meter_id == legacy_fm->fm.meter_id) {
2399 [ # # ]: 0 : if (mtr_idx)
2400 : 0 : *mtr_idx = legacy_fm->idx;
2401 : 0 : return &legacy_fm->fm;
2402 : : }
2403 : : return NULL;
2404 : : }
2405 : :
2406 : : /**
2407 : : * Find meter by index.
2408 : : *
2409 : : * @param priv
2410 : : * Pointer to mlx5_priv.
2411 : : * @param idx
2412 : : * Meter index.
2413 : : *
2414 : : * @return
2415 : : * Pointer to the meter info found on success, NULL otherwise.
2416 : : */
2417 : : struct mlx5_flow_meter_info *
2418 : 0 : mlx5_flow_dv_meter_find_by_idx(struct mlx5_priv *priv, uint32_t idx)
2419 : : {
2420 : : struct mlx5_aso_mtr *aso_mtr;
2421 : :
2422 [ # # ]: 0 : if (priv->sh->meter_aso_en) {
2423 : 0 : aso_mtr = mlx5_aso_meter_by_idx(priv, idx);
2424 [ # # ]: 0 : if (!aso_mtr)
2425 : : return NULL;
2426 : 0 : return &aso_mtr->fm;
2427 : : } else {
2428 : 0 : return mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MTR], idx);
2429 : : }
2430 : : }
2431 : :
2432 : : /**
2433 : : * Attach meter to flow.
2434 : : * Unidirectional Meter creation can only be done
2435 : : * when flow direction is known, i.e. when calling meter_attach.
2436 : : *
2437 : : * @param [in] priv
2438 : : * Pointer to mlx5 private data.
2439 : : * @param[in] fm
2440 : : * Pointer to flow meter.
2441 : : * @param [in] attr
2442 : : * Pointer to flow attributes.
2443 : : * @param [out] error
2444 : : * Pointer to error structure.
2445 : : *
2446 : : * @return
2447 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
2448 : : */
2449 : : int
2450 : 0 : mlx5_flow_meter_attach(struct mlx5_priv *priv,
2451 : : struct mlx5_flow_meter_info *fm,
2452 : : const struct rte_flow_attr *attr,
2453 : : struct rte_flow_error *error)
2454 : : {
2455 : : int ret = 0;
2456 : :
2457 [ # # ]: 0 : if (priv->sh->meter_aso_en) {
2458 : : struct mlx5_aso_mtr *aso_mtr;
2459 : :
2460 : 0 : aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
2461 [ # # ]: 0 : if (mlx5_aso_mtr_wait(priv, aso_mtr, false)) {
2462 : 0 : return rte_flow_error_set(error, ENOENT,
2463 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
2464 : : NULL,
2465 : : "Timeout in meter configuration");
2466 : : }
2467 : 0 : rte_spinlock_lock(&fm->sl);
2468 [ # # # # ]: 0 : if (fm->shared || !fm->ref_cnt) {
2469 : 0 : fm->ref_cnt++;
2470 : : } else {
2471 : 0 : rte_flow_error_set(error, EINVAL,
2472 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
2473 : : "Meter cannot be shared");
2474 : : ret = -1;
2475 : : }
2476 : : rte_spinlock_unlock(&fm->sl);
2477 : : } else {
2478 : 0 : rte_spinlock_lock(&fm->sl);
2479 [ # # ]: 0 : if (fm->meter_action_g) {
2480 [ # # ]: 0 : if (fm->shared &&
2481 [ # # ]: 0 : attr->transfer == fm->transfer &&
2482 [ # # ]: 0 : attr->ingress == fm->ingress &&
2483 : : attr->egress == fm->egress) {
2484 : 0 : fm->ref_cnt++;
2485 : : } else {
2486 [ # # ]: 0 : rte_flow_error_set(error, EINVAL,
2487 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
2488 : : fm->shared ?
2489 : : "Meter attr not match." :
2490 : : "Meter cannot be shared.");
2491 : : ret = -1;
2492 : : }
2493 : : } else {
2494 : 0 : fm->ingress = attr->ingress;
2495 : 0 : fm->egress = attr->egress;
2496 : 0 : fm->transfer = attr->transfer;
2497 : 0 : fm->ref_cnt = 1;
2498 : : /* This also creates the meter object. */
2499 : 0 : fm->meter_action_g = mlx5_flow_meter_action_create(priv,
2500 : : fm);
2501 [ # # ]: 0 : if (!fm->meter_action_g) {
2502 : 0 : fm->ref_cnt = 0;
2503 : 0 : fm->ingress = 0;
2504 : 0 : fm->egress = 0;
2505 : 0 : fm->transfer = 0;
2506 : 0 : rte_flow_error_set(error, EINVAL,
2507 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
2508 : : "Meter action create failed.");
2509 : : ret = -1;
2510 : : }
2511 : : }
2512 : : rte_spinlock_unlock(&fm->sl);
2513 : : }
2514 [ # # ]: 0 : return ret ? -rte_errno : 0;
2515 : : }
2516 : :
2517 : : /**
2518 : : * Detach meter from flow.
2519 : : *
2520 : : * @param [in] priv
2521 : : * Pointer to mlx5 private data.
2522 : : * @param [in] fm
2523 : : * Pointer to flow meter.
2524 : : */
2525 : : void
2526 : 0 : mlx5_flow_meter_detach(struct mlx5_priv *priv,
2527 : : struct mlx5_flow_meter_info *fm)
2528 : : {
2529 : : #ifdef HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER
2530 : 0 : rte_spinlock_lock(&fm->sl);
2531 : : MLX5_ASSERT(fm->ref_cnt);
2532 [ # # # # ]: 0 : if (--fm->ref_cnt == 0 && !priv->sh->meter_aso_en) {
2533 : 0 : mlx5_glue->destroy_flow_action(fm->meter_action_g);
2534 : 0 : fm->meter_action_g = NULL;
2535 : 0 : fm->ingress = 0;
2536 : 0 : fm->egress = 0;
2537 : 0 : fm->transfer = 0;
2538 : : }
2539 : : rte_spinlock_unlock(&fm->sl);
2540 : : #else
2541 : : (void)priv;
2542 : : (void)fm;
2543 : : #endif
2544 : 0 : }
2545 : :
2546 : : /**
2547 : : * Flush meter with Rx queue configuration.
2548 : : *
2549 : : * @param[in] dev
2550 : : * Pointer to Ethernet device.
2551 : : */
2552 : : void
2553 : 0 : mlx5_flow_meter_rxq_flush(struct rte_eth_dev *dev)
2554 : : {
2555 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
2556 : : struct mlx5_flow_meter_sub_policy *sub_policy;
2557 : : struct mlx5_flow_meter_policy *mtr_policy;
2558 : : void *entry;
2559 : : uint32_t i, policy_idx;
2560 : :
2561 [ # # ]: 0 : if (!priv->mtr_en)
2562 : 0 : return;
2563 [ # # ]: 0 : if (priv->policy_idx_tbl) {
2564 [ # # ]: 0 : MLX5_L3T_FOREACH(priv->policy_idx_tbl, i, entry) {
2565 : 0 : policy_idx = *(uint32_t *)entry;
2566 : 0 : sub_policy = mlx5_ipool_get
2567 : 0 : (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
2568 : : policy_idx);
2569 [ # # # # ]: 0 : if (!sub_policy || !sub_policy->main_policy)
2570 : 0 : continue;
2571 : : mtr_policy = sub_policy->main_policy;
2572 [ # # ]: 0 : if (mtr_policy->is_queue || mtr_policy->is_rss)
2573 : 0 : mlx5_flow_destroy_sub_policy_with_rxq(dev,
2574 : : mtr_policy);
2575 : : }
2576 : : }
2577 : : }
2578 : :
2579 : : /**
2580 : : * Iterate a meter hierarchy and flush all meters and policies if possible.
2581 : : *
2582 : : * @param[in] dev
2583 : : * Pointer to Ethernet device.
2584 : : * @param[in] fm
2585 : : * Pointer to flow meter.
2586 : : * @param[in] mtr_idx
2587 : : * .Meter's index
2588 : : * @param[out] error
2589 : : * Pointer to rte meter error structure.
2590 : : *
2591 : : * @return
2592 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
2593 : : */
2594 : : static int
2595 : 0 : mlx5_flow_meter_flush_hierarchy(struct rte_eth_dev *dev,
2596 : : struct mlx5_flow_meter_info *fm,
2597 : : uint32_t mtr_idx,
2598 : : struct rte_mtr_error *error)
2599 : : {
2600 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
2601 : : struct mlx5_flow_meter_policy *policy;
2602 : : uint32_t policy_id;
2603 : : struct mlx5_flow_meter_info *next_fm;
2604 : : uint32_t next_mtr_idx;
2605 : : struct mlx5_flow_meter_policy *next_policy = NULL;
2606 : :
2607 : 0 : policy = mlx5_flow_meter_policy_find(dev, fm->policy_id, NULL);
2608 : : MLX5_ASSERT(policy);
2609 [ # # # # ]: 0 : while (!fm->ref_cnt && policy->is_hierarchy) {
2610 : 0 : policy_id = fm->policy_id;
2611 : 0 : next_fm = mlx5_flow_meter_hierarchy_next_meter(priv, policy, &next_mtr_idx);
2612 [ # # ]: 0 : if (next_fm) {
2613 : 0 : next_policy = mlx5_flow_meter_policy_find(dev,
2614 : : next_fm->policy_id,
2615 : : NULL);
2616 : : MLX5_ASSERT(next_policy);
2617 : : }
2618 [ # # ]: 0 : if (mlx5_flow_meter_params_flush(dev, fm, mtr_idx))
2619 : 0 : return -rte_mtr_error_set(error, ENOTSUP,
2620 : : RTE_MTR_ERROR_TYPE_MTR_ID,
2621 : : NULL,
2622 : : "Failed to flush meter.");
2623 [ # # ]: 0 : if (policy->ref_cnt)
2624 : : break;
2625 [ # # ]: 0 : if (__mlx5_flow_meter_policy_delete(dev, policy_id,
2626 : : policy, error, true))
2627 : 0 : return -rte_errno;
2628 : 0 : mlx5_free(policy);
2629 [ # # ]: 0 : if (!next_fm || !next_policy)
2630 : : break;
2631 : : fm = next_fm;
2632 : 0 : mtr_idx = next_mtr_idx;
2633 : : policy = next_policy;
2634 : : }
2635 : : return 0;
2636 : : }
2637 : :
2638 : : /**
2639 : : * Flush all the hierarchy meters and their policies.
2640 : : *
2641 : : * @param[in] dev
2642 : : * Pointer to Ethernet device.
2643 : : * @param[out] error
2644 : : * Pointer to rte meter error structure.
2645 : : *
2646 : : * @return
2647 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
2648 : : */
2649 : : static int
2650 : 0 : mlx5_flow_meter_flush_all_hierarchies(struct rte_eth_dev *dev,
2651 : : struct rte_mtr_error *error)
2652 : : {
2653 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
2654 : : struct mlx5_flow_meter_info *fm;
2655 : : struct mlx5_flow_meter_policy *policy;
2656 : : struct mlx5_flow_meter_sub_policy *sub_policy;
2657 : : struct mlx5_flow_meter_info *next_fm;
2658 : : struct mlx5_aso_mtr *aso_mtr;
2659 : 0 : uint32_t mtr_idx = 0;
2660 : : uint32_t i, policy_idx;
2661 : : void *entry;
2662 : :
2663 [ # # # # ]: 0 : if (!priv->mtr_idx_tbl || !priv->policy_idx_tbl)
2664 : : return 0;
2665 [ # # ]: 0 : MLX5_L3T_FOREACH(priv->mtr_idx_tbl, i, entry) {
2666 : 0 : mtr_idx = *(uint32_t *)entry;
2667 [ # # ]: 0 : if (!mtr_idx)
2668 : 0 : continue;
2669 : 0 : aso_mtr = mlx5_aso_meter_by_idx(priv, mtr_idx);
2670 : 0 : fm = &aso_mtr->fm;
2671 [ # # # # ]: 0 : if (fm->ref_cnt || fm->def_policy)
2672 : 0 : continue;
2673 [ # # ]: 0 : if (mlx5_flow_meter_flush_hierarchy(dev, fm, mtr_idx, error))
2674 : 0 : return -rte_errno;
2675 : : }
2676 [ # # ]: 0 : MLX5_L3T_FOREACH(priv->policy_idx_tbl, i, entry) {
2677 : 0 : policy_idx = *(uint32_t *)entry;
2678 : 0 : sub_policy = mlx5_ipool_get
2679 : 0 : (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
2680 : : policy_idx);
2681 [ # # ]: 0 : if (!sub_policy)
2682 : 0 : return -rte_mtr_error_set(error,
2683 : : EINVAL,
2684 : : RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2685 : : NULL, "Meter policy invalid.");
2686 : 0 : policy = sub_policy->main_policy;
2687 [ # # # # : 0 : if (!policy || !policy->is_hierarchy || policy->ref_cnt)
# # ]
2688 : 0 : continue;
2689 : 0 : next_fm = mlx5_flow_meter_hierarchy_next_meter(priv, policy, &mtr_idx);
2690 [ # # ]: 0 : if (__mlx5_flow_meter_policy_delete(dev, i, policy,
2691 : : error, true))
2692 : 0 : return -rte_mtr_error_set(error,
2693 : : EINVAL,
2694 : : RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2695 : : NULL, "Meter policy invalid.");
2696 : 0 : mlx5_free(policy);
2697 [ # # # # : 0 : if (!next_fm || next_fm->ref_cnt || next_fm->def_policy)
# # ]
2698 : 0 : continue;
2699 [ # # ]: 0 : if (mlx5_flow_meter_flush_hierarchy(dev, next_fm,
2700 : : mtr_idx, error))
2701 : 0 : return -rte_errno;
2702 : : }
2703 : : return 0;
2704 : : }
2705 : : /**
2706 : : * Flush meter configuration.
2707 : : *
2708 : : * @param[in] dev
2709 : : * Pointer to Ethernet device.
2710 : : * @param[out] error
2711 : : * Pointer to rte meter error structure.
2712 : : *
2713 : : * @return
2714 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
2715 : : */
2716 : : int
2717 : 0 : mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error)
2718 : : {
2719 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
2720 : : struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
2721 : : struct mlx5_flow_meter_profile *fmp;
2722 : : struct mlx5_legacy_flow_meter *legacy_fm;
2723 : : struct mlx5_flow_meter_info *fm;
2724 : : struct mlx5_flow_meter_sub_policy *sub_policy;
2725 : : void *tmp;
2726 : : uint32_t i, mtr_idx, policy_idx;
2727 : : void *entry;
2728 : : struct mlx5_aso_mtr *aso_mtr;
2729 : :
2730 [ # # ]: 0 : if (!priv->mtr_en)
2731 : : return 0;
2732 [ # # ]: 0 : if (priv->sh->meter_aso_en) {
2733 [ # # ]: 0 : if (mlx5_flow_meter_flush_all_hierarchies(dev, error))
2734 : 0 : return -rte_errno;
2735 [ # # ]: 0 : if (priv->mtr_idx_tbl) {
2736 [ # # ]: 0 : MLX5_L3T_FOREACH(priv->mtr_idx_tbl, i, entry) {
2737 : 0 : mtr_idx = *(uint32_t *)entry;
2738 [ # # ]: 0 : if (mtr_idx) {
2739 : : aso_mtr =
2740 : 0 : mlx5_aso_meter_by_idx(priv, mtr_idx);
2741 : 0 : fm = &aso_mtr->fm;
2742 : 0 : (void)mlx5_flow_meter_params_flush(dev,
2743 : : fm, mtr_idx);
2744 : : }
2745 : : }
2746 : 0 : mlx5_l3t_destroy(priv->mtr_idx_tbl);
2747 : 0 : priv->mtr_idx_tbl = NULL;
2748 : : }
2749 : : } else {
2750 [ # # ]: 0 : RTE_TAILQ_FOREACH_SAFE(legacy_fm, fms, next, tmp) {
2751 : 0 : fm = &legacy_fm->fm;
2752 [ # # ]: 0 : if (mlx5_flow_meter_params_flush(dev, fm, 0))
2753 : 0 : return -rte_mtr_error_set(error, EINVAL,
2754 : : RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
2755 : : NULL, "MTR object meter profile invalid.");
2756 : : }
2757 : : }
2758 [ # # ]: 0 : if (priv->policy_idx_tbl) {
2759 [ # # ]: 0 : MLX5_L3T_FOREACH(priv->policy_idx_tbl, i, entry) {
2760 : 0 : policy_idx = *(uint32_t *)entry;
2761 : 0 : sub_policy = mlx5_ipool_get
2762 : 0 : (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
2763 : : policy_idx);
2764 [ # # ]: 0 : if (!sub_policy)
2765 : 0 : return -rte_mtr_error_set(error,
2766 : : EINVAL,
2767 : : RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2768 : : NULL, "MTR object "
2769 : : "meter policy invalid.");
2770 [ # # ]: 0 : if (__mlx5_flow_meter_policy_delete(dev, i,
2771 : 0 : sub_policy->main_policy,
2772 : : error, true))
2773 : 0 : return -rte_mtr_error_set(error,
2774 : : EINVAL,
2775 : : RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2776 : : NULL, "MTR object "
2777 : : "meter policy invalid.");
2778 : 0 : mlx5_free(sub_policy->main_policy);
2779 : : }
2780 : 0 : mlx5_l3t_destroy(priv->policy_idx_tbl);
2781 : 0 : priv->policy_idx_tbl = NULL;
2782 : : }
2783 [ # # ]: 0 : if (priv->mtr_profile_tbl) {
2784 [ # # ]: 0 : MLX5_L3T_FOREACH(priv->mtr_profile_tbl, i, entry) {
2785 : : fmp = entry;
2786 [ # # ]: 0 : if (mlx5_flow_meter_profile_delete(dev, fmp->id,
2787 : : error))
2788 : 0 : return -rte_mtr_error_set(error, EINVAL,
2789 : : RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
2790 : : NULL, "Fail to destroy "
2791 : : "meter profile.");
2792 : : }
2793 : 0 : mlx5_l3t_destroy(priv->mtr_profile_tbl);
2794 : 0 : priv->mtr_profile_tbl = NULL;
2795 : : }
2796 : : #if defined(HAVE_MLX5_HWS_SUPPORT)
2797 [ # # ]: 0 : if (priv->mtr_profile_arr) {
2798 [ # # ]: 0 : for (i = 0; i < priv->mtr_config.nb_meter_profiles; i++) {
2799 : 0 : fmp = mlx5_flow_meter_profile_find(priv, i);
2800 [ # # ]: 0 : if (fmp->initialized) {
2801 : 0 : mlx5_flow_meter_profile_hws_delete(dev, i,
2802 : : error);
2803 : : }
2804 : : }
2805 : : }
2806 : : #endif
2807 : : /* Delete default policy table. */
2808 : 0 : mlx5_flow_destroy_def_policy(dev);
2809 [ # # ]: 0 : if (priv->sh->refcnt == 1)
2810 : 0 : mlx5_flow_destroy_mtr_drop_tbls(dev);
2811 : : #ifdef HAVE_MLX5_HWS_SUPPORT
2812 : : /* Destroy HWS configuration. */
2813 : 0 : mlx5_flow_meter_uninit(dev);
2814 : : #endif
2815 : 0 : return 0;
2816 : : }
|