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