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