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