Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (c) 2021 NVIDIA Corporation & Affiliates
3 : : */
4 : : #include <rte_malloc.h>
5 : : #include <mlx5_devx_cmds.h>
6 : : #include <mlx5_malloc.h>
7 : : #include "mlx5.h"
8 : : #include "mlx5_flow.h"
9 : :
10 : : static_assert(sizeof(uint32_t) * CHAR_BIT >= MLX5_PORT_FLEX_ITEM_NUM,
11 : : "Flex item maximal number exceeds uint32_t bit width");
12 : :
13 : : /**
14 : : * Routine called once on port initialization to init flex item
15 : : * related infrastructure initialization
16 : : *
17 : : * @param dev
18 : : * Ethernet device to perform flex item initialization
19 : : *
20 : : * @return
21 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
22 : : */
23 : : int
24 : 0 : mlx5_flex_item_port_init(struct rte_eth_dev *dev)
25 : : {
26 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
27 : :
28 : : rte_spinlock_init(&priv->flex_item_sl);
29 : : MLX5_ASSERT(!priv->flex_item_map);
30 : 0 : return 0;
31 : : }
32 : :
33 : : /**
34 : : * Routine called once on port close to perform flex item
35 : : * related infrastructure cleanup.
36 : : *
37 : : * @param dev
38 : : * Ethernet device to perform cleanup
39 : : */
40 : : void
41 : 0 : mlx5_flex_item_port_cleanup(struct rte_eth_dev *dev)
42 : : {
43 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
44 : : uint32_t i;
45 : :
46 [ # # # # ]: 0 : for (i = 0; i < MLX5_PORT_FLEX_ITEM_NUM && priv->flex_item_map ; i++) {
47 [ # # ]: 0 : if (priv->flex_item_map & (1 << i)) {
48 : : struct mlx5_flex_item *flex = &priv->flex_item[i];
49 : :
50 : 0 : claim_zero(mlx5_list_unregister
51 : : (priv->sh->flex_parsers_dv,
52 : : &flex->devx_fp->entry));
53 : 0 : flex->devx_fp = NULL;
54 : 0 : flex->refcnt = 0;
55 : 0 : priv->flex_item_map &= ~(1 << i);
56 : : }
57 : : }
58 : 0 : }
59 : :
60 : : static int
61 : : mlx5_flex_index(struct mlx5_priv *priv, struct mlx5_flex_item *item)
62 : : {
63 : 0 : uintptr_t start = (uintptr_t)&priv->flex_item[0];
64 : 0 : uintptr_t entry = (uintptr_t)item;
65 : 0 : uintptr_t idx = (entry - start) / sizeof(struct mlx5_flex_item);
66 : :
67 : 0 : if (entry < start ||
68 [ # # ]: 0 : idx >= MLX5_PORT_FLEX_ITEM_NUM ||
69 [ # # # # : 0 : (entry - start) % sizeof(struct mlx5_flex_item) ||
# # ]
70 [ # # # # : 0 : !(priv->flex_item_map & (1u << idx)))
# # ]
71 : : return -1;
72 : 0 : return (int)idx;
73 : : }
74 : :
75 : : static struct mlx5_flex_item *
76 : 0 : mlx5_flex_alloc(struct mlx5_priv *priv)
77 : : {
78 : : struct mlx5_flex_item *item = NULL;
79 : :
80 : 0 : rte_spinlock_lock(&priv->flex_item_sl);
81 [ # # ]: 0 : if (~priv->flex_item_map) {
82 [ # # ]: 0 : uint32_t idx = rte_bsf32(~priv->flex_item_map);
83 : :
84 [ # # ]: 0 : if (idx < MLX5_PORT_FLEX_ITEM_NUM) {
85 : 0 : item = &priv->flex_item[idx];
86 : : MLX5_ASSERT(!item->refcnt);
87 : : MLX5_ASSERT(!item->devx_fp);
88 : 0 : item->devx_fp = NULL;
89 : 0 : __atomic_store_n(&item->refcnt, 0, __ATOMIC_RELEASE);
90 : 0 : priv->flex_item_map |= 1u << idx;
91 : : }
92 : : }
93 : : rte_spinlock_unlock(&priv->flex_item_sl);
94 : 0 : return item;
95 : : }
96 : :
97 : : static void
98 [ # # ]: 0 : mlx5_flex_free(struct mlx5_priv *priv, struct mlx5_flex_item *item)
99 : : {
100 : : int idx = mlx5_flex_index(priv, item);
101 : :
102 : : MLX5_ASSERT(idx >= 0 &&
103 : : idx < MLX5_PORT_FLEX_ITEM_NUM &&
104 : : (priv->flex_item_map & (1u << idx)));
105 [ # # ]: 0 : if (idx >= 0) {
106 : 0 : rte_spinlock_lock(&priv->flex_item_sl);
107 : : MLX5_ASSERT(!item->refcnt);
108 : : MLX5_ASSERT(!item->devx_fp);
109 : 0 : item->devx_fp = NULL;
110 : 0 : __atomic_store_n(&item->refcnt, 0, __ATOMIC_RELEASE);
111 : 0 : priv->flex_item_map &= ~(1u << idx);
112 : : rte_spinlock_unlock(&priv->flex_item_sl);
113 : : }
114 : 0 : }
115 : :
116 : : static uint32_t
117 : 0 : mlx5_flex_get_bitfield(const struct rte_flow_item_flex *item,
118 : : uint32_t pos, uint32_t width, uint32_t shift)
119 : : {
120 : 0 : const uint8_t *ptr = item->pattern + pos / CHAR_BIT;
121 : : uint32_t val, vbits;
122 : :
123 : : /* Proceed the bitfield start byte. */
124 : : MLX5_ASSERT(width <= sizeof(uint32_t) * CHAR_BIT && width);
125 : : MLX5_ASSERT(width + shift <= sizeof(uint32_t) * CHAR_BIT);
126 [ # # ]: 0 : if (item->length <= pos / CHAR_BIT)
127 : : return 0;
128 : 0 : val = *ptr++ >> (pos % CHAR_BIT);
129 : 0 : vbits = CHAR_BIT - pos % CHAR_BIT;
130 : 0 : pos = (pos + vbits) / CHAR_BIT;
131 : 0 : vbits = RTE_MIN(vbits, width);
132 : 0 : val &= RTE_BIT32(vbits) - 1;
133 [ # # # # ]: 0 : while (vbits < width && pos < item->length) {
134 : 0 : uint32_t part = RTE_MIN(width - vbits, (uint32_t)CHAR_BIT);
135 : 0 : uint32_t tmp = *ptr++;
136 : :
137 : 0 : pos++;
138 : 0 : tmp &= RTE_BIT32(part) - 1;
139 : 0 : val |= tmp << vbits;
140 : 0 : vbits += part;
141 : : }
142 : 0 : return rte_bswap32(val <<= shift);
143 : : }
144 : :
145 : : #define SET_FP_MATCH_SAMPLE_ID(x, def, msk, val, sid) \
146 : : do { \
147 : : uint32_t tmp, out = (def); \
148 : : tmp = MLX5_GET(fte_match_set_misc4, misc4_v, \
149 : : prog_sample_field_value_##x); \
150 : : tmp = (tmp & ~out) | (val); \
151 : : MLX5_SET(fte_match_set_misc4, misc4_v, \
152 : : prog_sample_field_value_##x, tmp); \
153 : : tmp = MLX5_GET(fte_match_set_misc4, misc4_m, \
154 : : prog_sample_field_value_##x); \
155 : : tmp = (tmp & ~out) | (msk); \
156 : : MLX5_SET(fte_match_set_misc4, misc4_m, \
157 : : prog_sample_field_value_##x, tmp); \
158 : : tmp = tmp ? (sid) : 0; \
159 : : MLX5_SET(fte_match_set_misc4, misc4_v, \
160 : : prog_sample_field_id_##x, tmp);\
161 : : MLX5_SET(fte_match_set_misc4, misc4_m, \
162 : : prog_sample_field_id_##x, tmp); \
163 : : } while (0)
164 : :
165 : : __rte_always_inline static void
166 : : mlx5_flex_set_match_sample(void *misc4_m, void *misc4_v,
167 : : uint32_t def, uint32_t mask, uint32_t value,
168 : : uint32_t sample_id, uint32_t id)
169 : : {
170 : 0 : switch (id) {
171 : 0 : case 0:
172 [ # # # # : 0 : SET_FP_MATCH_SAMPLE_ID(0, def, mask, value, sample_id);
# # # # #
# # # #
# ]
173 : 0 : break;
174 : 0 : case 1:
175 [ # # # # : 0 : SET_FP_MATCH_SAMPLE_ID(1, def, mask, value, sample_id);
# # # # #
# # # #
# ]
176 : 0 : break;
177 : 0 : case 2:
178 [ # # # # : 0 : SET_FP_MATCH_SAMPLE_ID(2, def, mask, value, sample_id);
# # # # #
# # # #
# ]
179 : 0 : break;
180 : 0 : case 3:
181 [ # # # # : 0 : SET_FP_MATCH_SAMPLE_ID(3, def, mask, value, sample_id);
# # # # #
# # # #
# ]
182 : 0 : break;
183 : 0 : case 4:
184 [ # # # # : 0 : SET_FP_MATCH_SAMPLE_ID(4, def, mask, value, sample_id);
# # # # #
# # # #
# ]
185 : 0 : break;
186 : 0 : case 5:
187 [ # # # # : 0 : SET_FP_MATCH_SAMPLE_ID(5, def, mask, value, sample_id);
# # # # #
# # # #
# ]
188 : 0 : break;
189 : 0 : case 6:
190 [ # # # # : 0 : SET_FP_MATCH_SAMPLE_ID(6, def, mask, value, sample_id);
# # # # #
# # # #
# ]
191 : 0 : break;
192 : 0 : case 7:
193 [ # # # # : 0 : SET_FP_MATCH_SAMPLE_ID(7, def, mask, value, sample_id);
# # # # #
# # # #
# ]
194 : 0 : break;
195 : : default:
196 : : MLX5_ASSERT(false);
197 : : break;
198 : : }
199 : : #undef SET_FP_MATCH_SAMPLE_ID
200 : : }
201 : :
202 : : /**
203 : : * Get the flex parser sample id and corresponding mask
204 : : * per shift and width information.
205 : : *
206 : : * @param[in] tp
207 : : * Mlx5 flex item sample mapping handle.
208 : : * @param[in] idx
209 : : * Mapping index.
210 : : * @param[in, out] pos
211 : : * Where to search the value and mask.
212 : : * @param[in] is_inner
213 : : * For inner matching or not.
214 : : * @param[in, def] def
215 : : * Mask generated by mapping shift and width.
216 : : *
217 : : * @return
218 : : * 0 on success, -1 to ignore.
219 : : */
220 : : int
221 : 0 : mlx5_flex_get_sample_id(const struct mlx5_flex_item *tp,
222 : : uint32_t idx, uint32_t *pos,
223 : : bool is_inner, uint32_t *def)
224 : : {
225 : 0 : const struct mlx5_flex_pattern_field *map = tp->map + idx;
226 : 0 : uint32_t id = map->reg_id;
227 : :
228 : 0 : *def = (RTE_BIT64(map->width) - 1) << map->shift;
229 : : /* Skip placeholders for DUMMY fields. */
230 [ # # ]: 0 : if (id == MLX5_INVALID_SAMPLE_REG_ID) {
231 : 0 : *pos += map->width;
232 : 0 : return -1;
233 : : }
234 : : MLX5_ASSERT(map->width);
235 : : MLX5_ASSERT(id < tp->devx_fp->num_samples);
236 [ # # # # ]: 0 : if (tp->tunnel_mode == FLEX_TUNNEL_MODE_MULTI && is_inner) {
237 : 0 : uint32_t num_samples = tp->devx_fp->num_samples / 2;
238 : :
239 : : MLX5_ASSERT(tp->devx_fp->num_samples % 2 == 0);
240 : : MLX5_ASSERT(id < num_samples);
241 : 0 : id += num_samples;
242 : : }
243 : 0 : return id;
244 : : }
245 : :
246 : : /**
247 : : * Get the flex parser mapping value per definer format_select_dw.
248 : : *
249 : : * @param[in] item
250 : : * Rte flex item pointer.
251 : : * @param[in] flex
252 : : * Mlx5 flex item sample mapping handle.
253 : : * @param[in] byte_off
254 : : * Mlx5 flex item format_select_dw.
255 : : * @param[in] is_mask
256 : : * Spec or mask.
257 : : * @param[in] tunnel
258 : : * Tunnel mode or not.
259 : : * @param[in, def] value
260 : : * Value calculated for this flex parser, either spec or mask.
261 : : *
262 : : * @return
263 : : * 0 on success, -1 for error.
264 : : */
265 : : int
266 : 0 : mlx5_flex_get_parser_value_per_byte_off(const struct rte_flow_item_flex *item,
267 : : void *flex, uint32_t byte_off,
268 : : bool is_mask, bool tunnel, uint32_t *value)
269 : : {
270 : : struct mlx5_flex_pattern_field *map;
271 : : struct mlx5_flex_item *tp = flex;
272 : : uint32_t def, i, pos, val;
273 : : int id;
274 : :
275 : 0 : *value = 0;
276 [ # # # # ]: 0 : for (i = 0, pos = 0; i < tp->mapnum && pos < item->length * CHAR_BIT; i++) {
277 : 0 : map = tp->map + i;
278 : 0 : id = mlx5_flex_get_sample_id(tp, i, &pos, tunnel, &def);
279 [ # # ]: 0 : if (id == -1)
280 : 0 : continue;
281 [ # # # # ]: 0 : if (id >= (int)tp->devx_fp->num_samples || id >= MLX5_GRAPH_NODE_SAMPLE_NUM)
282 : : return -1;
283 [ # # ]: 0 : if (byte_off == tp->devx_fp->sample_info[id].sample_dw_data * sizeof(uint32_t)) {
284 : 0 : val = mlx5_flex_get_bitfield(item, pos, map->width, map->shift);
285 [ # # ]: 0 : if (is_mask)
286 : 0 : val &= RTE_BE32(def);
287 : 0 : *value |= val;
288 : : }
289 : 0 : pos += map->width;
290 : : }
291 : : return 0;
292 : : }
293 : :
294 : : /**
295 : : * Translate item pattern into matcher fields according to translation
296 : : * array.
297 : : *
298 : : * @param dev
299 : : * Ethernet device to translate flex item on.
300 : : * @param[in, out] matcher
301 : : * Flow matcher to configure
302 : : * @param[in, out] key
303 : : * Flow matcher value.
304 : : * @param[in] item
305 : : * Flow pattern to translate.
306 : : * @param[in] is_inner
307 : : * Inner Flex Item (follows after tunnel header).
308 : : *
309 : : * @return
310 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
311 : : */
312 : : void
313 : 0 : mlx5_flex_flow_translate_item(struct rte_eth_dev *dev,
314 : : void *matcher, void *key,
315 : : const struct rte_flow_item *item,
316 : : bool is_inner)
317 : : {
318 : : const struct rte_flow_item_flex *spec, *mask;
319 : : void *misc4_m = MLX5_ADDR_OF(fte_match_param, matcher,
320 : : misc_parameters_4);
321 : : void *misc4_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_4);
322 : : struct mlx5_flex_item *tp;
323 : 0 : uint32_t i, pos = 0;
324 : : uint32_t sample_id;
325 : :
326 : : RTE_SET_USED(dev);
327 : : MLX5_ASSERT(item->spec && item->mask);
328 : 0 : spec = item->spec;
329 : 0 : mask = item->mask;
330 : 0 : tp = (struct mlx5_flex_item *)spec->handle;
331 [ # # ]: 0 : for (i = 0; i < tp->mapnum; i++) {
332 : 0 : struct mlx5_flex_pattern_field *map = tp->map + i;
333 : : uint32_t val, msk, def;
334 : 0 : int id = mlx5_flex_get_sample_id(tp, i, &pos, is_inner, &def);
335 : :
336 [ # # ]: 0 : if (id == -1)
337 : 0 : continue;
338 : : MLX5_ASSERT(id < (int)tp->devx_fp->num_samples);
339 [ # # # # ]: 0 : if (id >= (int)tp->devx_fp->num_samples ||
340 : : id >= MLX5_GRAPH_NODE_SAMPLE_NUM)
341 : 0 : return;
342 : 0 : val = mlx5_flex_get_bitfield(spec, pos, map->width, map->shift);
343 : 0 : msk = mlx5_flex_get_bitfield(mask, pos, map->width, map->shift);
344 : 0 : sample_id = tp->devx_fp->sample_ids[id];
345 : 0 : mlx5_flex_set_match_sample(misc4_m, misc4_v,
346 [ # # # # : 0 : def, msk & def, val & msk & def,
# # # #
# ]
347 : : sample_id, id);
348 : 0 : pos += map->width;
349 : : }
350 : : }
351 : :
352 : : /**
353 : : * Convert flex item handle (from the RTE flow) to flex item index on port.
354 : : * Optionally can increment flex item object reference count.
355 : : *
356 : : * @param dev
357 : : * Ethernet device to acquire flex item on.
358 : : * @param[in] handle
359 : : * Flow item handle from item spec.
360 : : * @param[in] acquire
361 : : * If set - increment reference counter.
362 : : *
363 : : * @return
364 : : * >=0 - index on success, a negative errno value otherwise
365 : : * and rte_errno is set.
366 : : */
367 : : int
368 : 0 : mlx5_flex_acquire_index(struct rte_eth_dev *dev,
369 : : struct rte_flow_item_flex_handle *handle,
370 : : bool acquire)
371 : : {
372 [ # # ]: 0 : struct mlx5_priv *priv = dev->data->dev_private;
373 : : struct mlx5_flex_item *flex = (struct mlx5_flex_item *)handle;
374 : : int ret = mlx5_flex_index(priv, flex);
375 : :
376 [ # # ]: 0 : if (ret < 0) {
377 : 0 : errno = -EINVAL;
378 : 0 : rte_errno = EINVAL;
379 : 0 : return ret;
380 : : }
381 [ # # ]: 0 : if (acquire)
382 : 0 : __atomic_fetch_add(&flex->refcnt, 1, __ATOMIC_RELEASE);
383 : : return ret;
384 : : }
385 : :
386 : : /**
387 : : * Release flex item index on port - decrements reference counter by index.
388 : : *
389 : : * @param dev
390 : : * Ethernet device to acquire flex item on.
391 : : * @param[in] index
392 : : * Flow item index.
393 : : *
394 : : * @return
395 : : * 0 - on success, a negative errno value otherwise and rte_errno is set.
396 : : */
397 : : int
398 : 0 : mlx5_flex_release_index(struct rte_eth_dev *dev,
399 : : int index)
400 : : {
401 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
402 : : struct mlx5_flex_item *flex;
403 : :
404 [ # # ]: 0 : if (index >= MLX5_PORT_FLEX_ITEM_NUM ||
405 [ # # ]: 0 : !(priv->flex_item_map & (1u << index))) {
406 : 0 : errno = EINVAL;
407 : 0 : rte_errno = -EINVAL;
408 : 0 : return -EINVAL;
409 : : }
410 : 0 : flex = priv->flex_item + index;
411 [ # # ]: 0 : if (flex->refcnt <= 1) {
412 : : MLX5_ASSERT(false);
413 : 0 : errno = EINVAL;
414 : 0 : rte_errno = -EINVAL;
415 : 0 : return -EINVAL;
416 : : }
417 : 0 : __atomic_fetch_sub(&flex->refcnt, 1, __ATOMIC_RELEASE);
418 : 0 : return 0;
419 : : }
420 : :
421 : : /*
422 : : * Calculate largest mask value for a given shift.
423 : : *
424 : : * shift mask
425 : : * ------- ---------------
426 : : * 0 b111100 0x3C
427 : : * 1 b111110 0x3E
428 : : * 2 b111111 0x3F
429 : : * 3 b011111 0x1F
430 : : * 4 b001111 0x0F
431 : : * 5 b000111 0x07
432 : : */
433 : : static uint8_t
434 : : mlx5_flex_hdr_len_mask(uint8_t shift,
435 : : const struct mlx5_hca_flex_attr *attr)
436 : : {
437 : : uint32_t base_mask;
438 : 0 : int diff = shift - MLX5_PARSE_GRAPH_NODE_HDR_LEN_SHIFT_DWORD;
439 : :
440 : : base_mask = mlx5_hca_parse_graph_node_base_hdr_len_mask(attr);
441 [ # # # # : 0 : return diff == 0 ? base_mask :
# # # # ]
442 : 0 : diff < 0 ? (base_mask << -diff) & base_mask : base_mask >> diff;
443 : : }
444 : :
445 : : static int
446 : 0 : mlx5_flex_translate_length(struct mlx5_hca_flex_attr *attr,
447 : : const struct rte_flow_item_flex_conf *conf,
448 : : struct mlx5_flex_parser_devx *devx,
449 : : struct rte_flow_error *error)
450 : : {
451 : : const struct rte_flow_item_flex_field *field = &conf->next_header;
452 : : struct mlx5_devx_graph_node_attr *node = &devx->devx_conf;
453 : : uint32_t len_width, mask;
454 : :
455 [ # # ]: 0 : if (field->field_base % CHAR_BIT)
456 : 0 : return rte_flow_error_set
457 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
458 : : "not byte aligned header length field");
459 [ # # # # : 0 : switch (field->field_mode) {
# ]
460 : 0 : case FIELD_MODE_DUMMY:
461 : 0 : return rte_flow_error_set
462 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
463 : : "invalid header length field mode (DUMMY)");
464 : 0 : case FIELD_MODE_FIXED:
465 [ # # ]: 0 : if (!(attr->header_length_mode &
466 : : RTE_BIT32(MLX5_GRAPH_NODE_LEN_FIXED)))
467 : 0 : return rte_flow_error_set
468 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
469 : : "unsupported header length field mode (FIXED)");
470 [ # # ]: 0 : if (field->field_size ||
471 [ # # # # ]: 0 : field->offset_mask || field->offset_shift)
472 : 0 : return rte_flow_error_set
473 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
474 : : "invalid fields for fixed mode");
475 [ # # ]: 0 : if (field->field_base < 0)
476 : 0 : return rte_flow_error_set
477 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
478 : : "negative header length field base (FIXED)");
479 : 0 : node->header_length_mode = MLX5_GRAPH_NODE_LEN_FIXED;
480 : 0 : break;
481 : 0 : case FIELD_MODE_OFFSET:
482 [ # # ]: 0 : if (!(attr->header_length_mode &
483 : : RTE_BIT32(MLX5_GRAPH_NODE_LEN_FIELD)))
484 : 0 : return rte_flow_error_set
485 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
486 : : "unsupported header length field mode (OFFSET)");
487 [ # # ]: 0 : if (!field->field_size)
488 : 0 : return rte_flow_error_set
489 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
490 : : "field size is a must for offset mode");
491 [ # # ]: 0 : if (field->field_size + field->offset_base < attr->header_length_mask_width)
492 : 0 : return rte_flow_error_set
493 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
494 : : "field size plus offset_base is too small");
495 : 0 : node->header_length_mode = MLX5_GRAPH_NODE_LEN_FIELD;
496 [ # # ]: 0 : if (field->offset_mask == 0 ||
497 [ # # ]: 0 : !rte_is_power_of_2(field->offset_mask + 1))
498 : 0 : return rte_flow_error_set
499 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
500 : : "invalid length field offset mask (OFFSET)");
501 : : len_width = rte_fls_u32(field->offset_mask);
502 [ # # ]: 0 : if (len_width > attr->header_length_mask_width)
503 : 0 : return rte_flow_error_set
504 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
505 : : "length field offset mask too wide (OFFSET)");
506 [ # # ]: 0 : mask = mlx5_flex_hdr_len_mask(field->offset_shift, attr);
507 [ # # ]: 0 : if (mask < field->offset_mask)
508 : 0 : return rte_flow_error_set
509 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
510 : : "length field shift too big (OFFSET)");
511 : 0 : node->header_length_field_mask = RTE_MIN(mask,
512 : : field->offset_mask);
513 : 0 : break;
514 : 0 : case FIELD_MODE_BITMASK:
515 [ # # ]: 0 : if (!(attr->header_length_mode &
516 : : RTE_BIT32(MLX5_GRAPH_NODE_LEN_BITMASK)))
517 : 0 : return rte_flow_error_set
518 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
519 : : "unsupported header length field mode (BITMASK)");
520 [ # # ]: 0 : if (attr->header_length_mask_width < field->field_size)
521 : 0 : return rte_flow_error_set
522 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
523 : : "header length field width exceeds limit");
524 : 0 : node->header_length_mode = MLX5_GRAPH_NODE_LEN_BITMASK;
525 [ # # ]: 0 : mask = mlx5_flex_hdr_len_mask(field->offset_shift, attr);
526 [ # # ]: 0 : if (mask < field->offset_mask)
527 : 0 : return rte_flow_error_set
528 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
529 : : "length field shift too big (BITMASK)");
530 : 0 : node->header_length_field_mask = RTE_MIN(mask,
531 : : field->offset_mask);
532 : 0 : break;
533 : 0 : default:
534 : 0 : return rte_flow_error_set
535 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
536 : : "unknown header length field mode");
537 : : }
538 [ # # ]: 0 : if (field->field_base / CHAR_BIT >= 0 &&
539 [ # # ]: 0 : field->field_base / CHAR_BIT > attr->max_base_header_length)
540 : 0 : return rte_flow_error_set
541 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
542 : : "header length field base exceeds limit");
543 : 0 : node->header_length_base_value = field->field_base / CHAR_BIT;
544 [ # # ]: 0 : if (field->field_mode == FIELD_MODE_OFFSET ||
545 : : field->field_mode == FIELD_MODE_BITMASK) {
546 [ # # ]: 0 : if (field->offset_shift > 15 || field->offset_shift < 0)
547 : 0 : return rte_flow_error_set
548 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
549 : : "header length field shift exceeds limit");
550 : 0 : node->header_length_field_shift = field->offset_shift;
551 : 0 : node->header_length_field_offset = field->offset_base;
552 : : }
553 [ # # ]: 0 : if (field->field_mode == FIELD_MODE_OFFSET) {
554 [ # # ]: 0 : if (field->field_size > attr->header_length_mask_width) {
555 : 0 : node->header_length_field_offset +=
556 : 0 : field->field_size - attr->header_length_mask_width;
557 [ # # ]: 0 : } else if (field->field_size < attr->header_length_mask_width) {
558 : 0 : node->header_length_field_offset -=
559 : 0 : attr->header_length_mask_width - field->field_size;
560 : 0 : node->header_length_field_mask =
561 : 0 : RTE_MIN(node->header_length_field_mask,
562 : : (1u << field->field_size) - 1);
563 : : }
564 : : }
565 : : return 0;
566 : : }
567 : :
568 : : static int
569 : 0 : mlx5_flex_translate_next(struct mlx5_hca_flex_attr *attr,
570 : : const struct rte_flow_item_flex_conf *conf,
571 : : struct mlx5_flex_parser_devx *devx,
572 : : struct rte_flow_error *error)
573 : : {
574 : : const struct rte_flow_item_flex_field *field = &conf->next_protocol;
575 : : struct mlx5_devx_graph_node_attr *node = &devx->devx_conf;
576 : :
577 [ # # # # : 0 : switch (field->field_mode) {
# ]
578 : 0 : case FIELD_MODE_DUMMY:
579 [ # # ]: 0 : if (conf->nb_outputs)
580 : 0 : return rte_flow_error_set
581 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
582 : : "next protocol field is required (DUMMY)");
583 : : return 0;
584 : : case FIELD_MODE_FIXED:
585 : : break;
586 : 0 : case FIELD_MODE_OFFSET:
587 : 0 : return rte_flow_error_set
588 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
589 : : "unsupported next protocol field mode (OFFSET)");
590 : : break;
591 : 0 : case FIELD_MODE_BITMASK:
592 : 0 : return rte_flow_error_set
593 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
594 : : "unsupported next protocol field mode (BITMASK)");
595 : 0 : default:
596 : 0 : return rte_flow_error_set
597 : : (error, EINVAL,
598 : : RTE_FLOW_ERROR_TYPE_ITEM, NULL,
599 : : "unknown next protocol field mode");
600 : : }
601 : : MLX5_ASSERT(field->field_mode == FIELD_MODE_FIXED);
602 [ # # ]: 0 : if (!conf->nb_outputs)
603 : 0 : return rte_flow_error_set
604 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
605 : : "out link(s) is required if next field present");
606 [ # # ]: 0 : if (attr->max_next_header_offset < field->field_base)
607 : 0 : return rte_flow_error_set
608 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
609 : : "next protocol field base exceeds limit");
610 [ # # ]: 0 : if (field->offset_shift)
611 : 0 : return rte_flow_error_set
612 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
613 : : "unsupported next protocol field shift");
614 : 0 : node->next_header_field_offset = field->field_base;
615 : 0 : node->next_header_field_size = field->field_size;
616 : 0 : return 0;
617 : : }
618 : :
619 : : /* Helper structure to handle field bit intervals. */
620 : : struct mlx5_flex_field_cover {
621 : : uint16_t num;
622 : : int32_t start[MLX5_FLEX_ITEM_MAPPING_NUM];
623 : : int32_t end[MLX5_FLEX_ITEM_MAPPING_NUM];
624 : : uint8_t mapped[MLX5_FLEX_ITEM_MAPPING_NUM / CHAR_BIT + 1];
625 : : };
626 : :
627 : : static void
628 : 0 : mlx5_flex_insert_field(struct mlx5_flex_field_cover *cover,
629 : : uint16_t num, int32_t start, int32_t end)
630 : : {
631 : : MLX5_ASSERT(num < MLX5_FLEX_ITEM_MAPPING_NUM);
632 : : MLX5_ASSERT(num <= cover->num);
633 [ # # ]: 0 : if (num < cover->num) {
634 : 0 : memmove(&cover->start[num + 1], &cover->start[num],
635 : 0 : (cover->num - num) * sizeof(int32_t));
636 : 0 : memmove(&cover->end[num + 1], &cover->end[num],
637 : 0 : (cover->num - num) * sizeof(int32_t));
638 : : }
639 : 0 : cover->start[num] = start;
640 : 0 : cover->end[num] = end;
641 : 0 : cover->num++;
642 : 0 : }
643 : :
644 : : static void
645 : 0 : mlx5_flex_merge_field(struct mlx5_flex_field_cover *cover, uint16_t num)
646 : : {
647 : : uint32_t i, del = 0;
648 : : int32_t end;
649 : :
650 : : MLX5_ASSERT(num < MLX5_FLEX_ITEM_MAPPING_NUM);
651 : : MLX5_ASSERT(num < (cover->num - 1));
652 : 0 : end = cover->end[num];
653 [ # # ]: 0 : for (i = num + 1; i < cover->num; i++) {
654 [ # # ]: 0 : if (end < cover->start[i])
655 : : break;
656 : 0 : del++;
657 [ # # ]: 0 : if (end <= cover->end[i]) {
658 : 0 : cover->end[num] = cover->end[i];
659 : 0 : break;
660 : : }
661 : : }
662 [ # # ]: 0 : if (del) {
663 : : MLX5_ASSERT(del < (cover->num - 1u - num));
664 : 0 : cover->num -= del;
665 : : MLX5_ASSERT(cover->num > num);
666 [ # # ]: 0 : if ((cover->num - num) > 1) {
667 : 0 : memmove(&cover->start[num + 1],
668 : 0 : &cover->start[num + 1 + del],
669 : 0 : (cover->num - num - 1) * sizeof(int32_t));
670 : 0 : memmove(&cover->end[num + 1],
671 : 0 : &cover->end[num + 1 + del],
672 : 0 : (cover->num - num - 1) * sizeof(int32_t));
673 : : }
674 : : }
675 : 0 : }
676 : :
677 : : /*
678 : : * Validate the sample field and update interval array
679 : : * if parameters match with the 'match" field.
680 : : * Returns:
681 : : * < 0 - error
682 : : * == 0 - no match, interval array not updated
683 : : * > 0 - match, interval array updated
684 : : */
685 : : static int
686 : 0 : mlx5_flex_cover_sample(struct mlx5_flex_field_cover *cover,
687 : : struct rte_flow_item_flex_field *field,
688 : : struct rte_flow_item_flex_field *match,
689 : : struct mlx5_hca_flex_attr *attr,
690 : : struct rte_flow_error *error)
691 : : {
692 : : int32_t start, end;
693 : : uint32_t i;
694 : :
695 [ # # # # : 0 : switch (field->field_mode) {
# ]
696 : : case FIELD_MODE_DUMMY:
697 : : return 0;
698 : 0 : case FIELD_MODE_FIXED:
699 [ # # ]: 0 : if (!(attr->sample_offset_mode &
700 : : RTE_BIT32(MLX5_GRAPH_SAMPLE_OFFSET_FIXED)))
701 : 0 : return rte_flow_error_set
702 : : (error, EINVAL,
703 : : RTE_FLOW_ERROR_TYPE_ITEM, NULL,
704 : : "unsupported sample field mode (FIXED)");
705 [ # # ]: 0 : if (field->offset_shift)
706 : 0 : return rte_flow_error_set
707 : : (error, EINVAL,
708 : : RTE_FLOW_ERROR_TYPE_ITEM, NULL,
709 : : "invalid sample field shift (FIXED");
710 [ # # ]: 0 : if (field->field_base < 0)
711 : 0 : return rte_flow_error_set
712 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
713 : : "invalid sample field base (FIXED)");
714 [ # # ]: 0 : if (field->field_base / CHAR_BIT > attr->max_sample_base_offset)
715 : 0 : return rte_flow_error_set
716 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
717 : : "sample field base exceeds limit (FIXED)");
718 : : break;
719 : 0 : case FIELD_MODE_OFFSET:
720 [ # # ]: 0 : if (!(attr->sample_offset_mode &
721 : : RTE_BIT32(MLX5_GRAPH_SAMPLE_OFFSET_FIELD)))
722 : 0 : return rte_flow_error_set
723 : : (error, EINVAL,
724 : : RTE_FLOW_ERROR_TYPE_ITEM, NULL,
725 : : "unsupported sample field mode (OFFSET)");
726 [ # # ]: 0 : if (field->field_base / CHAR_BIT >= 0 &&
727 [ # # ]: 0 : field->field_base / CHAR_BIT > attr->max_sample_base_offset)
728 : 0 : return rte_flow_error_set
729 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
730 : : "sample field base exceeds limit");
731 : : break;
732 : 0 : case FIELD_MODE_BITMASK:
733 [ # # ]: 0 : if (!(attr->sample_offset_mode &
734 : : RTE_BIT32(MLX5_GRAPH_SAMPLE_OFFSET_BITMASK)))
735 : 0 : return rte_flow_error_set
736 : : (error, EINVAL,
737 : : RTE_FLOW_ERROR_TYPE_ITEM, NULL,
738 : : "unsupported sample field mode (BITMASK)");
739 [ # # ]: 0 : if (field->field_base / CHAR_BIT >= 0 &&
740 [ # # ]: 0 : field->field_base / CHAR_BIT > attr->max_sample_base_offset)
741 : 0 : return rte_flow_error_set
742 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
743 : : "sample field base exceeds limit");
744 : : break;
745 : 0 : default:
746 : 0 : return rte_flow_error_set
747 : : (error, EINVAL,
748 : : RTE_FLOW_ERROR_TYPE_ITEM, NULL,
749 : : "unknown data sample field mode");
750 : : }
751 [ # # ]: 0 : if (!match) {
752 [ # # ]: 0 : if (!field->field_size)
753 : 0 : return rte_flow_error_set
754 : : (error, EINVAL,
755 : : RTE_FLOW_ERROR_TYPE_ITEM, NULL,
756 : : "zero sample field width");
757 [ # # ]: 0 : if (field->field_id)
758 : 0 : DRV_LOG(DEBUG, "sample field id hint ignored");
759 : : } else {
760 [ # # ]: 0 : if (field->field_mode != match->field_mode ||
761 [ # # ]: 0 : field->offset_base | match->offset_base ||
762 [ # # ]: 0 : field->offset_mask | match->offset_mask ||
763 [ # # ]: 0 : field->offset_shift | match->offset_shift)
764 : : return 0;
765 : : }
766 : 0 : start = field->field_base;
767 : 0 : end = start + field->field_size;
768 : : /* Add the new or similar field to interval array. */
769 [ # # ]: 0 : if (!cover->num) {
770 : 0 : cover->start[cover->num] = start;
771 : 0 : cover->end[cover->num] = end;
772 : 0 : cover->num = 1;
773 : 0 : return 1;
774 : : }
775 [ # # ]: 0 : for (i = 0; i < cover->num; i++) {
776 [ # # ]: 0 : if (start > cover->end[i]) {
777 [ # # ]: 0 : if (i >= (cover->num - 1u)) {
778 : 0 : mlx5_flex_insert_field(cover, cover->num,
779 : : start, end);
780 : 0 : break;
781 : : }
782 : : continue;
783 : : }
784 [ # # ]: 0 : if (end < cover->start[i]) {
785 : 0 : mlx5_flex_insert_field(cover, i, start, end);
786 : 0 : break;
787 : : }
788 [ # # ]: 0 : if (start < cover->start[i])
789 : 0 : cover->start[i] = start;
790 [ # # ]: 0 : if (end > cover->end[i]) {
791 : 0 : cover->end[i] = end;
792 [ # # ]: 0 : if (i < (cover->num - 1u))
793 : 0 : mlx5_flex_merge_field(cover, i);
794 : : }
795 : : break;
796 : : }
797 : : return 1;
798 : : }
799 : :
800 : : static void
801 [ # # # ]: 0 : mlx5_flex_config_sample(struct mlx5_devx_match_sample_attr *na,
802 : : struct rte_flow_item_flex_field *field,
803 : : enum rte_flow_item_flex_tunnel_mode tunnel_mode)
804 : : {
805 : : memset(na, 0, sizeof(struct mlx5_devx_match_sample_attr));
806 : 0 : na->flow_match_sample_en = 1;
807 [ # # # ]: 0 : switch (field->field_mode) {
808 : : case FIELD_MODE_FIXED:
809 : : na->flow_match_sample_offset_mode =
810 : : MLX5_GRAPH_SAMPLE_OFFSET_FIXED;
811 : : break;
812 : 0 : case FIELD_MODE_OFFSET:
813 : 0 : na->flow_match_sample_offset_mode =
814 : : MLX5_GRAPH_SAMPLE_OFFSET_FIELD;
815 : 0 : na->flow_match_sample_field_offset = field->offset_base;
816 : 0 : na->flow_match_sample_field_offset_mask = field->offset_mask;
817 : 0 : na->flow_match_sample_field_offset_shift = field->offset_shift;
818 : 0 : break;
819 : 0 : case FIELD_MODE_BITMASK:
820 : 0 : na->flow_match_sample_offset_mode =
821 : : MLX5_GRAPH_SAMPLE_OFFSET_BITMASK;
822 : 0 : na->flow_match_sample_field_offset = field->offset_base;
823 : 0 : na->flow_match_sample_field_offset_mask = field->offset_mask;
824 : 0 : na->flow_match_sample_field_offset_shift = field->offset_shift;
825 : 0 : break;
826 : : default:
827 : : MLX5_ASSERT(false);
828 : : break;
829 : : }
830 [ # # # ]: 0 : switch (tunnel_mode) {
831 : 0 : case FLEX_TUNNEL_MODE_SINGLE:
832 : : /* Fallthrough */
833 : : case FLEX_TUNNEL_MODE_TUNNEL:
834 : 0 : na->flow_match_sample_tunnel_mode =
835 : : MLX5_GRAPH_SAMPLE_TUNNEL_FIRST;
836 : 0 : break;
837 : : case FLEX_TUNNEL_MODE_MULTI:
838 : : /* Fallthrough */
839 : : case FLEX_TUNNEL_MODE_OUTER:
840 : : na->flow_match_sample_tunnel_mode =
841 : : MLX5_GRAPH_SAMPLE_TUNNEL_OUTER;
842 : : break;
843 : 0 : case FLEX_TUNNEL_MODE_INNER:
844 : 0 : na->flow_match_sample_tunnel_mode =
845 : : MLX5_GRAPH_SAMPLE_TUNNEL_INNER;
846 : 0 : break;
847 : : default:
848 : : MLX5_ASSERT(false);
849 : : break;
850 : : }
851 : 0 : }
852 : :
853 : : /* Map specified field to set/subset of allocated sample registers. */
854 : : static int
855 : 0 : mlx5_flex_map_sample(struct rte_flow_item_flex_field *field,
856 : : struct mlx5_flex_parser_devx *parser,
857 : : struct mlx5_flex_item *item,
858 : : struct rte_flow_error *error)
859 : : {
860 : : struct mlx5_devx_match_sample_attr node;
861 : 0 : int32_t start = field->field_base;
862 : 0 : int32_t end = start + field->field_size;
863 : : struct mlx5_flex_pattern_field *trans;
864 : : uint32_t i, done_bits = 0;
865 : :
866 [ # # ]: 0 : if (field->field_mode == FIELD_MODE_DUMMY) {
867 : : done_bits = field->field_size;
868 [ # # ]: 0 : while (done_bits) {
869 : 0 : uint32_t part = RTE_MIN(done_bits,
870 : : sizeof(uint32_t) * CHAR_BIT);
871 [ # # ]: 0 : if (item->mapnum >= MLX5_FLEX_ITEM_MAPPING_NUM)
872 : 0 : return rte_flow_error_set
873 : : (error,
874 : : EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
875 : : "too many flex item pattern translations");
876 : : trans = &item->map[item->mapnum];
877 : 0 : trans->reg_id = MLX5_INVALID_SAMPLE_REG_ID;
878 : 0 : trans->shift = 0;
879 : 0 : trans->width = part;
880 : 0 : item->mapnum++;
881 : 0 : done_bits -= part;
882 : : }
883 : : return 0;
884 : : }
885 : 0 : mlx5_flex_config_sample(&node, field, item->tunnel_mode);
886 [ # # ]: 0 : for (i = 0; i < parser->num_samples; i++) {
887 : 0 : struct mlx5_devx_match_sample_attr *sample =
888 : : &parser->devx_conf.sample[i];
889 : : int32_t reg_start, reg_end;
890 : : int32_t cov_start, cov_end;
891 : :
892 : : MLX5_ASSERT(sample->flow_match_sample_en);
893 [ # # ]: 0 : if (!sample->flow_match_sample_en)
894 : : break;
895 : 0 : node.flow_match_sample_field_base_offset =
896 : 0 : sample->flow_match_sample_field_base_offset;
897 [ # # ]: 0 : if (memcmp(&node, sample, sizeof(node)))
898 : 0 : continue;
899 : 0 : reg_start = (int8_t)sample->flow_match_sample_field_base_offset;
900 : 0 : reg_start *= CHAR_BIT;
901 : 0 : reg_end = reg_start + 32;
902 [ # # ]: 0 : if (end <= reg_start || start >= reg_end)
903 : 0 : continue;
904 : 0 : cov_start = RTE_MAX(reg_start, start);
905 : 0 : cov_end = RTE_MIN(reg_end, end);
906 : : MLX5_ASSERT(cov_end > cov_start);
907 : 0 : done_bits += cov_end - cov_start;
908 [ # # ]: 0 : if (item->mapnum >= MLX5_FLEX_ITEM_MAPPING_NUM)
909 : 0 : return rte_flow_error_set
910 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
911 : : "too many flex item pattern translations");
912 : : trans = &item->map[item->mapnum];
913 : 0 : item->mapnum++;
914 : 0 : trans->reg_id = i;
915 : 0 : trans->shift = cov_start - reg_start;
916 : 0 : trans->width = cov_end - cov_start;
917 : : }
918 [ # # ]: 0 : if (done_bits != field->field_size) {
919 : : MLX5_ASSERT(false);
920 : 0 : return rte_flow_error_set
921 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
922 : : "failed to map field to sample register");
923 : : }
924 : : return 0;
925 : : }
926 : :
927 : : /* Allocate sample registers for the specified field type and interval array. */
928 : : static int
929 : 0 : mlx5_flex_alloc_sample(struct mlx5_flex_field_cover *cover,
930 : : struct mlx5_flex_parser_devx *parser,
931 : : struct mlx5_flex_item *item,
932 : : struct rte_flow_item_flex_field *field,
933 : : struct mlx5_hca_flex_attr *attr,
934 : : struct rte_flow_error *error)
935 : : {
936 : : struct mlx5_devx_match_sample_attr node;
937 : : uint32_t idx = 0;
938 : :
939 : 0 : mlx5_flex_config_sample(&node, field, item->tunnel_mode);
940 [ # # ]: 0 : while (idx < cover->num) {
941 : : int32_t start, end;
942 : :
943 : : /*
944 : : * Sample base offsets are in bytes, should be aligned
945 : : * to 32-bit as required by firmware for samples.
946 : : */
947 : 0 : start = RTE_ALIGN_FLOOR(cover->start[idx],
948 : : sizeof(uint32_t) * CHAR_BIT);
949 : 0 : node.flow_match_sample_field_base_offset =
950 : 0 : (start / CHAR_BIT) & 0xFF;
951 : : /* Allocate sample register. */
952 [ # # ]: 0 : if (parser->num_samples >= MLX5_GRAPH_NODE_SAMPLE_NUM ||
953 [ # # ]: 0 : parser->num_samples >= attr->max_num_sample ||
954 [ # # ]: 0 : parser->num_samples >= attr->max_num_prog_sample)
955 : 0 : return rte_flow_error_set
956 : : (error, EINVAL,
957 : : RTE_FLOW_ERROR_TYPE_ITEM, NULL,
958 : : "no sample registers to handle all flex item fields");
959 : 0 : parser->devx_conf.sample[parser->num_samples] = node;
960 : 0 : parser->num_samples++;
961 : : /* Remove or update covered intervals. */
962 : 0 : end = start + 32;
963 [ # # ]: 0 : while (idx < cover->num) {
964 [ # # ]: 0 : if (end >= cover->end[idx]) {
965 : 0 : idx++;
966 : 0 : continue;
967 : : }
968 [ # # ]: 0 : if (end > cover->start[idx])
969 : 0 : cover->start[idx] = end;
970 : : break;
971 : : }
972 : : }
973 : : return 0;
974 : : }
975 : :
976 : : static int
977 : 0 : mlx5_flex_translate_sample(struct mlx5_hca_flex_attr *attr,
978 : : const struct rte_flow_item_flex_conf *conf,
979 : : struct mlx5_flex_parser_devx *parser,
980 : : struct mlx5_flex_item *item,
981 : : struct rte_flow_error *error)
982 : : {
983 : : struct mlx5_flex_field_cover cover;
984 : : uint32_t i, j;
985 : : int ret;
986 : :
987 [ # # ]: 0 : switch (conf->tunnel) {
988 : : case FLEX_TUNNEL_MODE_SINGLE:
989 : : /* Fallthrough */
990 : : case FLEX_TUNNEL_MODE_OUTER:
991 : : /* Fallthrough */
992 : : case FLEX_TUNNEL_MODE_INNER:
993 : : /* Fallthrough */
994 : : case FLEX_TUNNEL_MODE_MULTI:
995 : : /* Fallthrough */
996 : : case FLEX_TUNNEL_MODE_TUNNEL:
997 : : break;
998 : 0 : default:
999 : 0 : return rte_flow_error_set
1000 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
1001 : : "unrecognized tunnel mode");
1002 : : }
1003 : 0 : item->tunnel_mode = conf->tunnel;
1004 [ # # ]: 0 : if (conf->nb_samples > MLX5_FLEX_ITEM_MAPPING_NUM)
1005 : 0 : return rte_flow_error_set
1006 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
1007 : : "sample field number exceeds limit");
1008 : : /*
1009 : : * The application can specify fields smaller or bigger than 32 bits
1010 : : * covered with single sample register and it can specify field
1011 : : * offsets in any order.
1012 : : *
1013 : : * Gather all similar fields together, build array of bit intervals
1014 : : * in ascending order and try to cover with the smallest set of sample
1015 : : * registers.
1016 : : */
1017 : : memset(&cover, 0, sizeof(cover));
1018 [ # # ]: 0 : for (i = 0; i < conf->nb_samples; i++) {
1019 : 0 : struct rte_flow_item_flex_field *fl = conf->sample_data + i;
1020 : :
1021 : : /* Check whether field was covered in the previous iteration. */
1022 [ # # ]: 0 : if (cover.mapped[i / CHAR_BIT] & (1u << (i % CHAR_BIT)))
1023 : 0 : continue;
1024 [ # # ]: 0 : if (fl->field_mode == FIELD_MODE_DUMMY)
1025 : 0 : continue;
1026 : : /* Build an interval array for the field and similar ones */
1027 : 0 : cover.num = 0;
1028 : : /* Add the first field to array unconditionally. */
1029 : 0 : ret = mlx5_flex_cover_sample(&cover, fl, NULL, attr, error);
1030 [ # # ]: 0 : if (ret < 0)
1031 : 0 : return ret;
1032 : : MLX5_ASSERT(ret > 0);
1033 : 0 : cover.mapped[i / CHAR_BIT] |= 1u << (i % CHAR_BIT);
1034 [ # # ]: 0 : for (j = i + 1; j < conf->nb_samples; j++) {
1035 : : struct rte_flow_item_flex_field *ft;
1036 : :
1037 : : /* Add field to array if its type matches. */
1038 : 0 : ft = conf->sample_data + j;
1039 : 0 : ret = mlx5_flex_cover_sample(&cover, ft, fl,
1040 : : attr, error);
1041 [ # # ]: 0 : if (ret < 0)
1042 : 0 : return ret;
1043 [ # # ]: 0 : if (!ret)
1044 : 0 : continue;
1045 : 0 : cover.mapped[j / CHAR_BIT] |= 1u << (j % CHAR_BIT);
1046 : : }
1047 : : /* Allocate sample registers to cover array of intervals. */
1048 : 0 : ret = mlx5_flex_alloc_sample(&cover, parser, item,
1049 : : fl, attr, error);
1050 [ # # ]: 0 : if (ret)
1051 : 0 : return ret;
1052 : : }
1053 : : /* Build the item pattern translating data on flow creation. */
1054 : 0 : item->mapnum = 0;
1055 : 0 : memset(&item->map, 0, sizeof(item->map));
1056 [ # # ]: 0 : for (i = 0; i < conf->nb_samples; i++) {
1057 : 0 : struct rte_flow_item_flex_field *fl = conf->sample_data + i;
1058 : :
1059 : 0 : ret = mlx5_flex_map_sample(fl, parser, item, error);
1060 [ # # ]: 0 : if (ret) {
1061 : : MLX5_ASSERT(false);
1062 : 0 : return ret;
1063 : : }
1064 : : }
1065 [ # # ]: 0 : if (conf->tunnel == FLEX_TUNNEL_MODE_MULTI) {
1066 : : /*
1067 : : * In FLEX_TUNNEL_MODE_MULTI tunnel mode PMD creates 2 sets
1068 : : * of samples. The first set is for outer and the second set
1069 : : * for inner flex flow item. Outer and inner samples differ
1070 : : * only in tunnel_mode.
1071 : : */
1072 [ # # ]: 0 : if (parser->num_samples > MLX5_GRAPH_NODE_SAMPLE_NUM / 2)
1073 : 0 : return rte_flow_error_set
1074 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
1075 : : "no sample registers for inner");
1076 : 0 : rte_memcpy(parser->devx_conf.sample + parser->num_samples,
1077 : 0 : parser->devx_conf.sample,
1078 [ # # ]: 0 : parser->num_samples *
1079 : : sizeof(parser->devx_conf.sample[0]));
1080 [ # # ]: 0 : for (i = 0; i < parser->num_samples; i++) {
1081 : 0 : struct mlx5_devx_match_sample_attr *sm = i +
1082 : 0 : parser->devx_conf.sample + parser->num_samples;
1083 : :
1084 : 0 : sm->flow_match_sample_tunnel_mode =
1085 : : MLX5_GRAPH_SAMPLE_TUNNEL_INNER;
1086 : : }
1087 : 0 : parser->num_samples *= 2;
1088 : : }
1089 : : return 0;
1090 : : }
1091 : :
1092 : : static int
1093 : 0 : mlx5_flex_arc_type(enum rte_flow_item_type type, int in)
1094 : : {
1095 [ # # # # : 0 : switch (type) {
# # # # #
# ]
1096 : : case RTE_FLOW_ITEM_TYPE_ETH:
1097 : : return MLX5_GRAPH_ARC_NODE_MAC;
1098 : 0 : case RTE_FLOW_ITEM_TYPE_IPV4:
1099 [ # # ]: 0 : return in ? MLX5_GRAPH_ARC_NODE_IP : MLX5_GRAPH_ARC_NODE_IPV4;
1100 : 0 : case RTE_FLOW_ITEM_TYPE_IPV6:
1101 [ # # ]: 0 : return in ? MLX5_GRAPH_ARC_NODE_IP : MLX5_GRAPH_ARC_NODE_IPV6;
1102 : 0 : case RTE_FLOW_ITEM_TYPE_UDP:
1103 : 0 : return MLX5_GRAPH_ARC_NODE_UDP;
1104 : 0 : case RTE_FLOW_ITEM_TYPE_TCP:
1105 : 0 : return MLX5_GRAPH_ARC_NODE_TCP;
1106 : 0 : case RTE_FLOW_ITEM_TYPE_MPLS:
1107 : 0 : return MLX5_GRAPH_ARC_NODE_MPLS;
1108 : 0 : case RTE_FLOW_ITEM_TYPE_GRE:
1109 : 0 : return MLX5_GRAPH_ARC_NODE_GRE;
1110 : 0 : case RTE_FLOW_ITEM_TYPE_GENEVE:
1111 : 0 : return MLX5_GRAPH_ARC_NODE_GENEVE;
1112 : 0 : case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
1113 : 0 : return MLX5_GRAPH_ARC_NODE_VXLAN_GPE;
1114 : 0 : default:
1115 : 0 : return -EINVAL;
1116 : : }
1117 : : }
1118 : :
1119 : : static int
1120 : 0 : mlx5_flex_arc_in_eth(const struct rte_flow_item *item,
1121 : : struct rte_flow_error *error)
1122 : : {
1123 : 0 : const struct rte_flow_item_eth *spec = item->spec;
1124 : 0 : const struct rte_flow_item_eth *mask = item->mask;
1125 : 0 : struct rte_flow_item_eth eth = { .hdr.ether_type = RTE_BE16(0xFFFF) };
1126 : :
1127 [ # # ]: 0 : if (memcmp(mask, ð, sizeof(struct rte_flow_item_eth))) {
1128 : 0 : return rte_flow_error_set
1129 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item,
1130 : : "invalid eth item mask");
1131 : : }
1132 [ # # ]: 0 : return rte_be_to_cpu_16(spec->hdr.ether_type);
1133 : : }
1134 : :
1135 : : static int
1136 : 0 : mlx5_flex_arc_in_udp(const struct rte_flow_item *item,
1137 : : struct rte_flow_error *error)
1138 : : {
1139 : 0 : const struct rte_flow_item_udp *spec = item->spec;
1140 : 0 : const struct rte_flow_item_udp *mask = item->mask;
1141 : 0 : struct rte_flow_item_udp udp = { .hdr.dst_port = RTE_BE16(0xFFFF) };
1142 : :
1143 [ # # ]: 0 : if (memcmp(mask, &udp, sizeof(struct rte_flow_item_udp))) {
1144 : 0 : return rte_flow_error_set
1145 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item,
1146 : : "invalid eth item mask");
1147 : : }
1148 [ # # ]: 0 : return rte_be_to_cpu_16(spec->hdr.dst_port);
1149 : : }
1150 : :
1151 : : static int
1152 : 0 : mlx5_flex_arc_in_ipv6(const struct rte_flow_item *item,
1153 : : struct rte_flow_error *error)
1154 : : {
1155 : 0 : const struct rte_flow_item_ipv6 *spec = item->spec;
1156 : 0 : const struct rte_flow_item_ipv6 *mask = item->mask;
1157 : 0 : struct rte_flow_item_ipv6 ip = { .hdr.proto = 0xff };
1158 : :
1159 [ # # ]: 0 : if (memcmp(mask, &ip, sizeof(struct rte_flow_item_ipv6))) {
1160 : 0 : return rte_flow_error_set
1161 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item,
1162 : : "invalid ipv6 item mask, full mask is desired");
1163 : : }
1164 : 0 : return spec->hdr.proto;
1165 : : }
1166 : :
1167 : : static int
1168 : 0 : mlx5_flex_translate_arc_in(struct mlx5_hca_flex_attr *attr,
1169 : : const struct rte_flow_item_flex_conf *conf,
1170 : : struct mlx5_flex_parser_devx *devx,
1171 : : struct mlx5_flex_item *item,
1172 : : struct rte_flow_error *error)
1173 : : {
1174 : : struct mlx5_devx_graph_node_attr *node = &devx->devx_conf;
1175 : : uint32_t i;
1176 : :
1177 : : RTE_SET_USED(item);
1178 [ # # ]: 0 : if (conf->nb_inputs > attr->max_num_arc_in)
1179 : 0 : return rte_flow_error_set
1180 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
1181 : : "too many input links");
1182 [ # # ]: 0 : for (i = 0; i < conf->nb_inputs; i++) {
1183 : 0 : struct mlx5_devx_graph_arc_attr *arc = node->in + i;
1184 : 0 : struct rte_flow_item_flex_link *link = conf->input_link + i;
1185 : 0 : const struct rte_flow_item *rte_item = &link->item;
1186 : : int arc_type;
1187 : : int ret;
1188 : :
1189 [ # # # # : 0 : if (!rte_item->spec || !rte_item->mask || rte_item->last)
# # ]
1190 : 0 : return rte_flow_error_set
1191 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
1192 : : "invalid flex item IN arc format");
1193 : 0 : arc_type = mlx5_flex_arc_type(rte_item->type, true);
1194 [ # # # # ]: 0 : if (arc_type < 0 || !(attr->node_in & RTE_BIT32(arc_type)))
1195 : 0 : return rte_flow_error_set
1196 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
1197 : : "unsupported flex item IN arc type");
1198 : 0 : arc->arc_parse_graph_node = arc_type;
1199 : 0 : arc->start_inner_tunnel = 0;
1200 : : /*
1201 : : * Configure arc IN condition value. The value location depends
1202 : : * on protocol. Current FW version supports IP & UDP for IN
1203 : : * arcs only, and locations for these protocols are defined.
1204 : : * Add more protocols when available.
1205 : : */
1206 [ # # # # ]: 0 : switch (rte_item->type) {
1207 : 0 : case RTE_FLOW_ITEM_TYPE_ETH:
1208 : 0 : ret = mlx5_flex_arc_in_eth(rte_item, error);
1209 : 0 : break;
1210 : 0 : case RTE_FLOW_ITEM_TYPE_UDP:
1211 : 0 : ret = mlx5_flex_arc_in_udp(rte_item, error);
1212 : 0 : break;
1213 : 0 : case RTE_FLOW_ITEM_TYPE_IPV6:
1214 : 0 : ret = mlx5_flex_arc_in_ipv6(rte_item, error);
1215 : 0 : break;
1216 : 0 : default:
1217 : : MLX5_ASSERT(false);
1218 : 0 : return rte_flow_error_set
1219 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
1220 : : "unsupported flex item IN arc type");
1221 : : }
1222 [ # # ]: 0 : if (ret < 0)
1223 : 0 : return ret;
1224 : 0 : arc->compare_condition_value = (uint16_t)ret;
1225 : : }
1226 : : return 0;
1227 : : }
1228 : :
1229 : : static int
1230 : 0 : mlx5_flex_translate_arc_out(struct mlx5_hca_flex_attr *attr,
1231 : : const struct rte_flow_item_flex_conf *conf,
1232 : : struct mlx5_flex_parser_devx *devx,
1233 : : struct mlx5_flex_item *item,
1234 : : struct rte_flow_error *error)
1235 : : {
1236 : : struct mlx5_devx_graph_node_attr *node = &devx->devx_conf;
1237 : 0 : bool is_tunnel = conf->tunnel == FLEX_TUNNEL_MODE_TUNNEL;
1238 : : uint32_t i;
1239 : :
1240 : : RTE_SET_USED(item);
1241 [ # # ]: 0 : if (conf->nb_outputs > attr->max_num_arc_out)
1242 : 0 : return rte_flow_error_set
1243 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
1244 : : "too many output links");
1245 [ # # ]: 0 : for (i = 0; i < conf->nb_outputs; i++) {
1246 : 0 : struct mlx5_devx_graph_arc_attr *arc = node->out + i;
1247 : 0 : struct rte_flow_item_flex_link *link = conf->output_link + i;
1248 : : const struct rte_flow_item *rte_item = &link->item;
1249 : : int arc_type;
1250 : :
1251 [ # # # # : 0 : if (rte_item->spec || rte_item->mask || rte_item->last)
# # ]
1252 : 0 : return rte_flow_error_set
1253 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
1254 : : "flex node: invalid OUT arc format");
1255 : 0 : arc_type = mlx5_flex_arc_type(rte_item->type, false);
1256 [ # # # # ]: 0 : if (arc_type < 0 || !(attr->node_out & RTE_BIT32(arc_type)))
1257 : 0 : return rte_flow_error_set
1258 : : (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
1259 : : "unsupported flex item OUT arc type");
1260 : 0 : arc->arc_parse_graph_node = arc_type;
1261 : 0 : arc->start_inner_tunnel = !!is_tunnel;
1262 : 0 : arc->compare_condition_value = link->next;
1263 : : }
1264 : : return 0;
1265 : : }
1266 : :
1267 : : /* Translate RTE flex item API configuration into flaex parser settings. */
1268 : : static int
1269 : 0 : mlx5_flex_translate_conf(struct rte_eth_dev *dev,
1270 : : const struct rte_flow_item_flex_conf *conf,
1271 : : struct mlx5_flex_parser_devx *devx,
1272 : : struct mlx5_flex_item *item,
1273 : : struct rte_flow_error *error)
1274 : : {
1275 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
1276 : 0 : struct mlx5_hca_flex_attr *attr = &priv->sh->cdev->config.hca_attr.flex;
1277 : : int ret;
1278 : :
1279 : 0 : ret = mlx5_flex_translate_length(attr, conf, devx, error);
1280 [ # # ]: 0 : if (ret)
1281 : : return ret;
1282 : 0 : ret = mlx5_flex_translate_next(attr, conf, devx, error);
1283 [ # # ]: 0 : if (ret)
1284 : : return ret;
1285 : 0 : ret = mlx5_flex_translate_sample(attr, conf, devx, item, error);
1286 [ # # ]: 0 : if (ret)
1287 : : return ret;
1288 : 0 : ret = mlx5_flex_translate_arc_in(attr, conf, devx, item, error);
1289 [ # # ]: 0 : if (ret)
1290 : : return ret;
1291 : 0 : ret = mlx5_flex_translate_arc_out(attr, conf, devx, item, error);
1292 [ # # ]: 0 : if (ret)
1293 : 0 : return ret;
1294 : : return 0;
1295 : : }
1296 : :
1297 : : /**
1298 : : * Create the flex item with specified configuration over the Ethernet device.
1299 : : *
1300 : : * @param dev
1301 : : * Ethernet device to create flex item on.
1302 : : * @param[in] conf
1303 : : * Flex item configuration.
1304 : : * @param[out] error
1305 : : * Perform verbose error reporting if not NULL. PMDs initialize this
1306 : : * structure in case of error only.
1307 : : *
1308 : : * @return
1309 : : * Non-NULL opaque pointer on success, NULL otherwise and rte_errno is set.
1310 : : */
1311 : : struct rte_flow_item_flex_handle *
1312 : 0 : flow_dv_item_create(struct rte_eth_dev *dev,
1313 : : const struct rte_flow_item_flex_conf *conf,
1314 : : struct rte_flow_error *error)
1315 : : {
1316 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
1317 : 0 : struct mlx5_flex_parser_devx devx_config = { .devx_obj = NULL };
1318 : : struct mlx5_flex_item *flex;
1319 : : struct mlx5_list_entry *ent;
1320 : :
1321 : : MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
1322 : 0 : flex = mlx5_flex_alloc(priv);
1323 [ # # ]: 0 : if (!flex) {
1324 : 0 : rte_flow_error_set(error, ENOMEM,
1325 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1326 : : "too many flex items created on the port");
1327 : 0 : return NULL;
1328 : : }
1329 [ # # ]: 0 : if (mlx5_flex_translate_conf(dev, conf, &devx_config, flex, error))
1330 : 0 : goto error;
1331 : 0 : ent = mlx5_list_register(priv->sh->flex_parsers_dv, &devx_config);
1332 [ # # ]: 0 : if (!ent) {
1333 : 0 : rte_flow_error_set(error, ENOMEM,
1334 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1335 : : "flex item creation failure");
1336 : 0 : goto error;
1337 : : }
1338 : 0 : flex->devx_fp = container_of(ent, struct mlx5_flex_parser_devx, entry);
1339 : : /* Mark initialized flex item valid. */
1340 : 0 : __atomic_fetch_add(&flex->refcnt, 1, __ATOMIC_RELEASE);
1341 : 0 : return (struct rte_flow_item_flex_handle *)flex;
1342 : :
1343 : 0 : error:
1344 : 0 : mlx5_flex_free(priv, flex);
1345 : 0 : return NULL;
1346 : : }
1347 : :
1348 : : /**
1349 : : * Release the flex item on the specified Ethernet device.
1350 : : *
1351 : : * @param dev
1352 : : * Ethernet device to destroy flex item on.
1353 : : * @param[in] handle
1354 : : * Handle of the item existing on the specified device.
1355 : : * @param[out] error
1356 : : * Perform verbose error reporting if not NULL. PMDs initialize this
1357 : : * structure in case of error only.
1358 : : *
1359 : : * @return
1360 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
1361 : : */
1362 : : int
1363 : 0 : flow_dv_item_release(struct rte_eth_dev *dev,
1364 : : const struct rte_flow_item_flex_handle *handle,
1365 : : struct rte_flow_error *error)
1366 : : {
1367 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
1368 : : struct mlx5_flex_item *flex =
1369 : : (struct mlx5_flex_item *)(uintptr_t)handle;
1370 : : uint32_t old_refcnt = 1;
1371 : : int rc;
1372 : :
1373 : : MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
1374 : 0 : rte_spinlock_lock(&priv->flex_item_sl);
1375 [ # # ]: 0 : if (mlx5_flex_index(priv, flex) < 0) {
1376 : : rte_spinlock_unlock(&priv->flex_item_sl);
1377 : 0 : return rte_flow_error_set(error, EINVAL,
1378 : : RTE_FLOW_ERROR_TYPE_ITEM, NULL,
1379 : : "invalid flex item handle value");
1380 : : }
1381 [ # # ]: 0 : if (!__atomic_compare_exchange_n(&flex->refcnt, &old_refcnt, 0, 0,
1382 : : __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)) {
1383 : : rte_spinlock_unlock(&priv->flex_item_sl);
1384 : 0 : return rte_flow_error_set(error, EBUSY,
1385 : : RTE_FLOW_ERROR_TYPE_ITEM, NULL,
1386 : : "flex item has flow references");
1387 : : }
1388 : : /* Flex item is marked as invalid, we can leave locked section. */
1389 : : rte_spinlock_unlock(&priv->flex_item_sl);
1390 : : MLX5_ASSERT(flex->devx_fp);
1391 : 0 : rc = mlx5_list_unregister(priv->sh->flex_parsers_dv,
1392 : 0 : &flex->devx_fp->entry);
1393 : 0 : flex->devx_fp = NULL;
1394 : 0 : mlx5_flex_free(priv, flex);
1395 [ # # ]: 0 : if (rc < 0)
1396 : 0 : return rte_flow_error_set(error, EBUSY,
1397 : : RTE_FLOW_ERROR_TYPE_ITEM, NULL,
1398 : : "flex item release failure");
1399 : : return 0;
1400 : : }
1401 : :
1402 : : /* DevX flex parser list callbacks. */
1403 : : struct mlx5_list_entry *
1404 : 0 : mlx5_flex_parser_create_cb(void *list_ctx, void *ctx)
1405 : : {
1406 : : struct mlx5_dev_ctx_shared *sh = list_ctx;
1407 : : struct mlx5_flex_parser_devx *fp, *conf = ctx;
1408 : : uint32_t i;
1409 : 0 : uint8_t sample_info = sh->cdev->config.hca_attr.flex.query_match_sample_info;
1410 : : int ret;
1411 : :
1412 : 0 : fp = mlx5_malloc(MLX5_MEM_ZERO, sizeof(struct mlx5_flex_parser_devx),
1413 : : 0, SOCKET_ID_ANY);
1414 [ # # ]: 0 : if (!fp)
1415 : : return NULL;
1416 : : /* Copy the requested configurations. */
1417 : 0 : fp->num_samples = conf->num_samples;
1418 : 0 : memcpy(&fp->devx_conf, &conf->devx_conf, sizeof(fp->devx_conf));
1419 : : /* Create DevX flex parser. */
1420 : 0 : fp->devx_obj = mlx5_devx_cmd_create_flex_parser(sh->cdev->ctx,
1421 : : &fp->devx_conf);
1422 [ # # ]: 0 : if (!fp->devx_obj)
1423 : 0 : goto error;
1424 : : /* Query the firmware assigned sample ids. */
1425 : 0 : ret = mlx5_devx_cmd_query_parse_samples(fp->devx_obj,
1426 : 0 : fp->sample_ids,
1427 : : fp->num_samples,
1428 : : &fp->anchor_id);
1429 [ # # ]: 0 : if (ret)
1430 : 0 : goto error;
1431 : : /* Query sample information per ID. */
1432 [ # # # # ]: 0 : for (i = 0; i < fp->num_samples && sample_info; i++) {
1433 : 0 : ret = mlx5_devx_cmd_match_sample_info_query(sh->cdev->ctx, fp->sample_ids[i],
1434 : : &fp->sample_info[i]);
1435 [ # # ]: 0 : if (ret)
1436 : 0 : goto error;
1437 : : }
1438 : 0 : DRV_LOG(DEBUG, "DEVx flex parser %p created, samples num: %u",
1439 : : (const void *)fp, fp->num_samples);
1440 : 0 : return &fp->entry;
1441 : 0 : error:
1442 [ # # ]: 0 : if (fp->devx_obj)
1443 : 0 : mlx5_devx_cmd_destroy((void *)(uintptr_t)fp->devx_obj);
1444 : : if (fp)
1445 : 0 : mlx5_free(fp);
1446 : 0 : return NULL;
1447 : : }
1448 : :
1449 : : int
1450 : 0 : mlx5_flex_parser_match_cb(void *list_ctx,
1451 : : struct mlx5_list_entry *iter, void *ctx)
1452 : : {
1453 : : struct mlx5_flex_parser_devx *fp =
1454 : : container_of(iter, struct mlx5_flex_parser_devx, entry);
1455 : : struct mlx5_flex_parser_devx *org =
1456 : : container_of(ctx, struct mlx5_flex_parser_devx, entry);
1457 : :
1458 : : RTE_SET_USED(list_ctx);
1459 [ # # ]: 0 : return !iter || !ctx || memcmp(&fp->devx_conf,
1460 [ # # ]: 0 : &org->devx_conf,
1461 : : sizeof(fp->devx_conf));
1462 : : }
1463 : :
1464 : : void
1465 : 0 : mlx5_flex_parser_remove_cb(void *list_ctx, struct mlx5_list_entry *entry)
1466 : : {
1467 : : struct mlx5_flex_parser_devx *fp =
1468 : : container_of(entry, struct mlx5_flex_parser_devx, entry);
1469 : :
1470 : : RTE_SET_USED(list_ctx);
1471 : : MLX5_ASSERT(fp->devx_obj);
1472 : 0 : claim_zero(mlx5_devx_cmd_destroy(fp->devx_obj));
1473 : 0 : DRV_LOG(DEBUG, "DEVx flex parser %p destroyed", (const void *)fp);
1474 : 0 : mlx5_free(entry);
1475 : 0 : }
1476 : :
1477 : : struct mlx5_list_entry *
1478 : 0 : mlx5_flex_parser_clone_cb(void *list_ctx,
1479 : : struct mlx5_list_entry *entry, void *ctx)
1480 : : {
1481 : : struct mlx5_flex_parser_devx *fp;
1482 : :
1483 : : RTE_SET_USED(list_ctx);
1484 : : RTE_SET_USED(entry);
1485 : 0 : fp = mlx5_malloc(0, sizeof(struct mlx5_flex_parser_devx),
1486 : : 0, SOCKET_ID_ANY);
1487 [ # # ]: 0 : if (!fp)
1488 : : return NULL;
1489 : : memcpy(fp, ctx, sizeof(struct mlx5_flex_parser_devx));
1490 : 0 : return &fp->entry;
1491 : : }
1492 : :
1493 : : void
1494 : 0 : mlx5_flex_parser_clone_free_cb(void *list_ctx, struct mlx5_list_entry *entry)
1495 : : {
1496 : : struct mlx5_flex_parser_devx *fp =
1497 : : container_of(entry, struct mlx5_flex_parser_devx, entry);
1498 : : RTE_SET_USED(list_ctx);
1499 : 0 : mlx5_free(fp);
1500 : 0 : }
|