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