Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2020 Intel Corporation
3 : : */
4 : : #include <stdlib.h>
5 : : #include <stdio.h>
6 : : #include <errno.h>
7 : : #include <dlfcn.h>
8 : :
9 : : #include <eal_export.h>
10 : : #include <rte_tailq.h>
11 : : #include <rte_eal_memconfig.h>
12 : : #include <rte_jhash.h>
13 : : #include <rte_hash_crc.h>
14 : :
15 : : #include <rte_swx_port_ethdev.h>
16 : : #include <rte_swx_port_fd.h>
17 : : #include <rte_swx_port_ring.h>
18 : : #include "rte_swx_port_source_sink.h"
19 : :
20 : : #include <rte_swx_table_em.h>
21 : : #include <rte_swx_table_wm.h>
22 : :
23 : : #include "rte_swx_pipeline_internal.h"
24 : : #include "rte_swx_pipeline_spec.h"
25 : :
26 : : #define CHECK(condition, err_code) \
27 : : do { \
28 : : if (!(condition)) \
29 : : return -(err_code); \
30 : : } while (0)
31 : :
32 : : #define CHECK_NAME(name, err_code) \
33 : : CHECK((name) && \
34 : : (name)[0] && \
35 : : (strnlen((name), RTE_SWX_NAME_SIZE) < RTE_SWX_NAME_SIZE), \
36 : : err_code)
37 : :
38 : : #define CHECK_INSTRUCTION(instr, err_code) \
39 : : CHECK((instr) && \
40 : : (instr)[0] && \
41 : : (strnlen((instr), RTE_SWX_INSTRUCTION_SIZE) < \
42 : : RTE_SWX_INSTRUCTION_SIZE), \
43 : : err_code)
44 : :
45 : : /*
46 : : * Environment.
47 : : */
48 : : #ifndef RTE_SWX_PIPELINE_HUGE_PAGES_DISABLE
49 : :
50 : : #include <rte_malloc.h>
51 : :
52 : : static void *
53 : : env_malloc(size_t size, size_t alignment, int numa_node)
54 : : {
55 : 0 : return rte_zmalloc_socket(NULL, size, alignment, numa_node);
56 : : }
57 : :
58 : : static void
59 : : env_free(void *start, size_t size __rte_unused)
60 : : {
61 : 0 : rte_free(start);
62 : : }
63 : :
64 : : #else
65 : :
66 : : #include <numa.h>
67 : :
68 : : static void *
69 : : env_malloc(size_t size, size_t alignment __rte_unused, int numa_node)
70 : : {
71 : : void *start;
72 : :
73 : : if (numa_available() == -1)
74 : : return NULL;
75 : :
76 : : start = numa_alloc_onnode(size, numa_node);
77 : : if (!start)
78 : : return NULL;
79 : :
80 : : memset(start, 0, size);
81 : : return start;
82 : : }
83 : :
84 : : static void
85 : : env_free(void *start, size_t size)
86 : : {
87 : : if (numa_available() == -1)
88 : : return;
89 : :
90 : : numa_free(start, size);
91 : : }
92 : :
93 : : #endif
94 : :
95 : : /*
96 : : * Struct.
97 : : */
98 : : static struct struct_type *
99 : : struct_type_find(struct rte_swx_pipeline *p, const char *name)
100 : : {
101 : : struct struct_type *elem;
102 : :
103 [ # # # # : 0 : TAILQ_FOREACH(elem, &p->struct_types, node)
# # # # #
# # # ]
104 [ # # # # : 0 : if (strcmp(elem->name, name) == 0)
# # # # #
# # # ]
105 : : return elem;
106 : :
107 : : return NULL;
108 : : }
109 : :
110 : : static struct field *
111 : 0 : struct_type_field_find(struct struct_type *st, const char *name)
112 : : {
113 : : uint32_t i;
114 : :
115 [ # # ]: 0 : for (i = 0; i < st->n_fields; i++) {
116 : 0 : struct field *f = &st->fields[i];
117 : :
118 [ # # ]: 0 : if (strcmp(f->name, name) == 0)
119 : 0 : return f;
120 : : }
121 : :
122 : : return NULL;
123 : : }
124 : :
125 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_pipeline_struct_type_register, 20.11)
126 : : int
127 : 0 : rte_swx_pipeline_struct_type_register(struct rte_swx_pipeline *p,
128 : : const char *name,
129 : : struct rte_swx_field_params *fields,
130 : : uint32_t n_fields,
131 : : int last_field_has_variable_size)
132 : : {
133 : : struct struct_type *st;
134 : : uint32_t i;
135 : :
136 [ # # ]: 0 : CHECK(p, EINVAL);
137 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
138 [ # # ]: 0 : CHECK(fields, EINVAL);
139 [ # # ]: 0 : CHECK(n_fields, EINVAL);
140 : :
141 [ # # ]: 0 : for (i = 0; i < n_fields; i++) {
142 : 0 : struct rte_swx_field_params *f = &fields[i];
143 : : uint32_t j;
144 : :
145 [ # # # # : 0 : CHECK_NAME(f->name, EINVAL);
# # ]
146 [ # # ]: 0 : CHECK(f->n_bits, EINVAL);
147 [ # # ]: 0 : CHECK((f->n_bits & 7) == 0, EINVAL);
148 : :
149 [ # # ]: 0 : for (j = 0; j < i; j++) {
150 : 0 : struct rte_swx_field_params *f_prev = &fields[j];
151 : :
152 [ # # ]: 0 : CHECK(strcmp(f->name, f_prev->name), EINVAL);
153 : : }
154 : : }
155 : :
156 [ # # ]: 0 : CHECK(!struct_type_find(p, name), EEXIST);
157 : :
158 : : /* Node allocation. */
159 : 0 : st = calloc(1, sizeof(struct struct_type));
160 [ # # ]: 0 : CHECK(st, ENOMEM);
161 : :
162 : 0 : st->fields = calloc(n_fields, sizeof(struct field));
163 [ # # ]: 0 : if (!st->fields) {
164 : 0 : free(st);
165 : 0 : CHECK(0, ENOMEM);
166 : : }
167 : :
168 : : /* Node initialization. */
169 : 0 : strcpy(st->name, name);
170 [ # # ]: 0 : for (i = 0; i < n_fields; i++) {
171 : 0 : struct field *dst = &st->fields[i];
172 : 0 : struct rte_swx_field_params *src = &fields[i];
173 [ # # # # ]: 0 : int var_size = ((i == n_fields - 1) && last_field_has_variable_size) ? 1 : 0;
174 : :
175 [ # # ]: 0 : strcpy(dst->name, src->name);
176 : 0 : dst->n_bits = src->n_bits;
177 : 0 : dst->offset = st->n_bits;
178 : 0 : dst->var_size = var_size;
179 : :
180 : 0 : st->n_bits += src->n_bits;
181 [ # # ]: 0 : st->n_bits_min += var_size ? 0 : src->n_bits;
182 : : }
183 : 0 : st->n_fields = n_fields;
184 : 0 : st->var_size = last_field_has_variable_size;
185 : :
186 : : /* Node add to tailq. */
187 : 0 : TAILQ_INSERT_TAIL(&p->struct_types, st, node);
188 : :
189 : 0 : return 0;
190 : : }
191 : :
192 : : static int
193 : 0 : struct_build(struct rte_swx_pipeline *p)
194 : : {
195 : : uint32_t i;
196 : :
197 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
198 : : struct thread *t = &p->threads[i];
199 : :
200 : 0 : t->structs = calloc(p->n_structs, sizeof(uint8_t *));
201 [ # # ]: 0 : CHECK(t->structs, ENOMEM);
202 : : }
203 : :
204 : : return 0;
205 : : }
206 : :
207 : : static void
208 : : struct_build_free(struct rte_swx_pipeline *p)
209 : : {
210 : : uint32_t i;
211 : :
212 [ # # # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
213 : : struct thread *t = &p->threads[i];
214 : :
215 : 0 : free(t->structs);
216 : 0 : t->structs = NULL;
217 : : }
218 : : }
219 : :
220 : : static void
221 : 0 : struct_free(struct rte_swx_pipeline *p)
222 : : {
223 : : struct_build_free(p);
224 : :
225 : : /* Struct types. */
226 : 0 : for ( ; ; ) {
227 : : struct struct_type *elem;
228 : :
229 : 0 : elem = TAILQ_FIRST(&p->struct_types);
230 [ # # ]: 0 : if (!elem)
231 : : break;
232 : :
233 [ # # ]: 0 : TAILQ_REMOVE(&p->struct_types, elem, node);
234 : 0 : free(elem->fields);
235 : 0 : free(elem);
236 : : }
237 : 0 : }
238 : :
239 : : /*
240 : : * Input port.
241 : : */
242 : : static struct port_in_type *
243 : 0 : port_in_type_find(struct rte_swx_pipeline *p, const char *name)
244 : : {
245 : : struct port_in_type *elem;
246 : :
247 [ # # ]: 0 : if (!name)
248 : : return NULL;
249 : :
250 [ # # ]: 0 : TAILQ_FOREACH(elem, &p->port_in_types, node)
251 [ # # ]: 0 : if (strcmp(elem->name, name) == 0)
252 : 0 : return elem;
253 : :
254 : : return NULL;
255 : : }
256 : :
257 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_pipeline_port_in_type_register, 20.11)
258 : : int
259 : 0 : rte_swx_pipeline_port_in_type_register(struct rte_swx_pipeline *p,
260 : : const char *name,
261 : : struct rte_swx_port_in_ops *ops)
262 : : {
263 : : struct port_in_type *elem;
264 : :
265 [ # # ]: 0 : CHECK(p, EINVAL);
266 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
267 [ # # ]: 0 : CHECK(ops, EINVAL);
268 [ # # ]: 0 : CHECK(ops->create, EINVAL);
269 [ # # ]: 0 : CHECK(ops->free, EINVAL);
270 [ # # ]: 0 : CHECK(ops->pkt_rx, EINVAL);
271 [ # # ]: 0 : CHECK(ops->stats_read, EINVAL);
272 : :
273 [ # # ]: 0 : CHECK(!port_in_type_find(p, name), EEXIST);
274 : :
275 : : /* Node allocation. */
276 : 0 : elem = calloc(1, sizeof(struct port_in_type));
277 [ # # ]: 0 : CHECK(elem, ENOMEM);
278 : :
279 : : /* Node initialization. */
280 : 0 : strcpy(elem->name, name);
281 : 0 : memcpy(&elem->ops, ops, sizeof(*ops));
282 : :
283 : : /* Node add to tailq. */
284 : 0 : TAILQ_INSERT_TAIL(&p->port_in_types, elem, node);
285 : :
286 : 0 : return 0;
287 : : }
288 : :
289 : : static struct port_in *
290 : : port_in_find(struct rte_swx_pipeline *p, uint32_t port_id)
291 : : {
292 : : struct port_in *port;
293 : :
294 [ # # # # : 0 : TAILQ_FOREACH(port, &p->ports_in, node)
# # ]
295 [ # # # # : 0 : if (port->id == port_id)
# # ]
296 : : return port;
297 : :
298 : : return NULL;
299 : : }
300 : :
301 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_pipeline_port_in_config, 20.11)
302 : : int
303 : 0 : rte_swx_pipeline_port_in_config(struct rte_swx_pipeline *p,
304 : : uint32_t port_id,
305 : : const char *port_type_name,
306 : : void *args)
307 : : {
308 : : struct port_in_type *type = NULL;
309 : : struct port_in *port = NULL;
310 : : void *obj = NULL;
311 : :
312 [ # # ]: 0 : CHECK(p, EINVAL);
313 : :
314 [ # # ]: 0 : CHECK(!port_in_find(p, port_id), EINVAL);
315 : :
316 [ # # # # : 0 : CHECK_NAME(port_type_name, EINVAL);
# # ]
317 : 0 : type = port_in_type_find(p, port_type_name);
318 [ # # ]: 0 : CHECK(type, EINVAL);
319 : :
320 : 0 : obj = type->ops.create(args);
321 [ # # ]: 0 : CHECK(obj, ENODEV);
322 : :
323 : : /* Node allocation. */
324 : 0 : port = calloc(1, sizeof(struct port_in));
325 [ # # ]: 0 : CHECK(port, ENOMEM);
326 : :
327 : : /* Node initialization. */
328 : 0 : port->type = type;
329 : 0 : port->obj = obj;
330 : 0 : port->id = port_id;
331 : :
332 : : /* Node add to tailq. */
333 : 0 : TAILQ_INSERT_TAIL(&p->ports_in, port, node);
334 [ # # ]: 0 : if (p->n_ports_in < port_id + 1)
335 : 0 : p->n_ports_in = port_id + 1;
336 : :
337 : : return 0;
338 : : }
339 : :
340 : : static int
341 : 0 : port_in_build(struct rte_swx_pipeline *p)
342 : : {
343 : : struct port_in *port;
344 : : uint32_t i;
345 : :
346 [ # # ]: 0 : CHECK(p->n_ports_in, EINVAL);
347 : :
348 [ # # ]: 0 : for (i = 0; i < p->n_ports_in; i++)
349 [ # # ]: 0 : CHECK(port_in_find(p, i), EINVAL);
350 : :
351 : 0 : p->in = calloc(p->n_ports_in, sizeof(struct port_in_runtime));
352 [ # # ]: 0 : CHECK(p->in, ENOMEM);
353 : :
354 [ # # ]: 0 : TAILQ_FOREACH(port, &p->ports_in, node) {
355 : 0 : struct port_in_runtime *in = &p->in[port->id];
356 : :
357 : 0 : in->pkt_rx = port->type->ops.pkt_rx;
358 : 0 : in->obj = port->obj;
359 : : }
360 : :
361 : : return 0;
362 : : }
363 : :
364 : : static void
365 : : port_in_build_free(struct rte_swx_pipeline *p)
366 : : {
367 : 0 : free(p->in);
368 : 0 : p->in = NULL;
369 : 0 : }
370 : :
371 : : static void
372 : 0 : port_in_free(struct rte_swx_pipeline *p)
373 : : {
374 : : port_in_build_free(p);
375 : :
376 : : /* Input ports. */
377 : 0 : for ( ; ; ) {
378 : : struct port_in *port;
379 : :
380 : 0 : port = TAILQ_FIRST(&p->ports_in);
381 [ # # ]: 0 : if (!port)
382 : : break;
383 : :
384 [ # # ]: 0 : TAILQ_REMOVE(&p->ports_in, port, node);
385 : 0 : port->type->ops.free(port->obj);
386 : 0 : free(port);
387 : : }
388 : :
389 : : /* Input port types. */
390 : 0 : for ( ; ; ) {
391 : : struct port_in_type *elem;
392 : :
393 : 0 : elem = TAILQ_FIRST(&p->port_in_types);
394 [ # # ]: 0 : if (!elem)
395 : : break;
396 : :
397 [ # # ]: 0 : TAILQ_REMOVE(&p->port_in_types, elem, node);
398 : 0 : free(elem);
399 : : }
400 : 0 : }
401 : :
402 : : /*
403 : : * Output port.
404 : : */
405 : : static struct port_out_type *
406 : 0 : port_out_type_find(struct rte_swx_pipeline *p, const char *name)
407 : : {
408 : : struct port_out_type *elem;
409 : :
410 [ # # ]: 0 : if (!name)
411 : : return NULL;
412 : :
413 [ # # ]: 0 : TAILQ_FOREACH(elem, &p->port_out_types, node)
414 [ # # ]: 0 : if (!strcmp(elem->name, name))
415 : 0 : return elem;
416 : :
417 : : return NULL;
418 : : }
419 : :
420 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_pipeline_port_out_type_register, 20.11)
421 : : int
422 : 0 : rte_swx_pipeline_port_out_type_register(struct rte_swx_pipeline *p,
423 : : const char *name,
424 : : struct rte_swx_port_out_ops *ops)
425 : : {
426 : : struct port_out_type *elem;
427 : :
428 [ # # ]: 0 : CHECK(p, EINVAL);
429 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
430 [ # # ]: 0 : CHECK(ops, EINVAL);
431 [ # # ]: 0 : CHECK(ops->create, EINVAL);
432 [ # # ]: 0 : CHECK(ops->free, EINVAL);
433 [ # # ]: 0 : CHECK(ops->pkt_tx, EINVAL);
434 [ # # ]: 0 : CHECK(ops->pkt_fast_clone_tx, EINVAL);
435 [ # # ]: 0 : CHECK(ops->pkt_clone_tx, EINVAL);
436 [ # # ]: 0 : CHECK(ops->stats_read, EINVAL);
437 : :
438 [ # # ]: 0 : CHECK(!port_out_type_find(p, name), EEXIST);
439 : :
440 : : /* Node allocation. */
441 : 0 : elem = calloc(1, sizeof(struct port_out_type));
442 [ # # ]: 0 : CHECK(elem, ENOMEM);
443 : :
444 : : /* Node initialization. */
445 : 0 : strcpy(elem->name, name);
446 : 0 : memcpy(&elem->ops, ops, sizeof(*ops));
447 : :
448 : : /* Node add to tailq. */
449 : 0 : TAILQ_INSERT_TAIL(&p->port_out_types, elem, node);
450 : :
451 : 0 : return 0;
452 : : }
453 : :
454 : : static struct port_out *
455 : : port_out_find(struct rte_swx_pipeline *p, uint32_t port_id)
456 : : {
457 : : struct port_out *port;
458 : :
459 [ # # # # : 0 : TAILQ_FOREACH(port, &p->ports_out, node)
# # ]
460 [ # # # # : 0 : if (port->id == port_id)
# # ]
461 : : return port;
462 : :
463 : : return NULL;
464 : : }
465 : :
466 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_pipeline_port_out_config, 20.11)
467 : : int
468 : 0 : rte_swx_pipeline_port_out_config(struct rte_swx_pipeline *p,
469 : : uint32_t port_id,
470 : : const char *port_type_name,
471 : : void *args)
472 : : {
473 : : struct port_out_type *type = NULL;
474 : : struct port_out *port = NULL;
475 : : void *obj = NULL;
476 : :
477 [ # # ]: 0 : CHECK(p, EINVAL);
478 : :
479 [ # # ]: 0 : CHECK(!port_out_find(p, port_id), EINVAL);
480 : :
481 [ # # # # : 0 : CHECK_NAME(port_type_name, EINVAL);
# # ]
482 : 0 : type = port_out_type_find(p, port_type_name);
483 [ # # ]: 0 : CHECK(type, EINVAL);
484 : :
485 : 0 : obj = type->ops.create(args);
486 [ # # ]: 0 : CHECK(obj, ENODEV);
487 : :
488 : : /* Node allocation. */
489 : 0 : port = calloc(1, sizeof(struct port_out));
490 [ # # ]: 0 : CHECK(port, ENOMEM);
491 : :
492 : : /* Node initialization. */
493 : 0 : port->type = type;
494 : 0 : port->obj = obj;
495 : 0 : port->id = port_id;
496 : :
497 : : /* Node add to tailq. */
498 : 0 : TAILQ_INSERT_TAIL(&p->ports_out, port, node);
499 [ # # ]: 0 : if (p->n_ports_out < port_id + 1)
500 : 0 : p->n_ports_out = port_id + 1;
501 : :
502 : : return 0;
503 : : }
504 : :
505 : : static int
506 : 0 : port_out_build(struct rte_swx_pipeline *p)
507 : : {
508 : : struct port_out *port;
509 : : uint32_t i;
510 : :
511 [ # # ]: 0 : CHECK(p->n_ports_out, EINVAL);
512 : :
513 [ # # ]: 0 : for (i = 0; i < p->n_ports_out; i++)
514 [ # # ]: 0 : CHECK(port_out_find(p, i), EINVAL);
515 : :
516 : 0 : p->out = calloc(p->n_ports_out, sizeof(struct port_out_runtime));
517 [ # # ]: 0 : CHECK(p->out, ENOMEM);
518 : :
519 [ # # ]: 0 : TAILQ_FOREACH(port, &p->ports_out, node) {
520 : 0 : struct port_out_runtime *out = &p->out[port->id];
521 : :
522 : 0 : out->pkt_tx = port->type->ops.pkt_tx;
523 : 0 : out->pkt_fast_clone_tx = port->type->ops.pkt_fast_clone_tx;
524 : 0 : out->pkt_clone_tx = port->type->ops.pkt_clone_tx;
525 : 0 : out->flush = port->type->ops.flush;
526 : 0 : out->obj = port->obj;
527 : : }
528 : :
529 : : return 0;
530 : : }
531 : :
532 : : static void
533 : : port_out_build_free(struct rte_swx_pipeline *p)
534 : : {
535 : 0 : free(p->out);
536 : 0 : p->out = NULL;
537 : 0 : }
538 : :
539 : : static void
540 : 0 : port_out_free(struct rte_swx_pipeline *p)
541 : : {
542 : : port_out_build_free(p);
543 : :
544 : : /* Output ports. */
545 : 0 : for ( ; ; ) {
546 : : struct port_out *port;
547 : :
548 : 0 : port = TAILQ_FIRST(&p->ports_out);
549 [ # # ]: 0 : if (!port)
550 : : break;
551 : :
552 [ # # ]: 0 : TAILQ_REMOVE(&p->ports_out, port, node);
553 : 0 : port->type->ops.free(port->obj);
554 : 0 : free(port);
555 : : }
556 : :
557 : : /* Output port types. */
558 : 0 : for ( ; ; ) {
559 : : struct port_out_type *elem;
560 : :
561 : 0 : elem = TAILQ_FIRST(&p->port_out_types);
562 [ # # ]: 0 : if (!elem)
563 : : break;
564 : :
565 [ # # ]: 0 : TAILQ_REMOVE(&p->port_out_types, elem, node);
566 : 0 : free(elem);
567 : : }
568 : 0 : }
569 : :
570 : : /*
571 : : * Packet mirroring.
572 : : */
573 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_pipeline_mirroring_config, 20.11)
574 : : int
575 : 0 : rte_swx_pipeline_mirroring_config(struct rte_swx_pipeline *p,
576 : : struct rte_swx_pipeline_mirroring_params *params)
577 : : {
578 [ # # ]: 0 : CHECK(p, EINVAL);
579 [ # # ]: 0 : CHECK(params, EINVAL);
580 [ # # ]: 0 : CHECK(params->n_slots, EINVAL);
581 [ # # ]: 0 : CHECK(params->n_sessions, EINVAL);
582 [ # # ]: 0 : CHECK(!p->build_done, EEXIST);
583 : :
584 : 0 : p->n_mirroring_slots = rte_align32pow2(params->n_slots);
585 [ # # ]: 0 : if (p->n_mirroring_slots > 64)
586 : 0 : p->n_mirroring_slots = 64;
587 : :
588 : 0 : p->n_mirroring_sessions = rte_align32pow2(params->n_sessions);
589 : :
590 : 0 : return 0;
591 : : }
592 : :
593 : : static void
594 : 0 : mirroring_build_free(struct rte_swx_pipeline *p)
595 : : {
596 : : uint32_t i;
597 : :
598 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
599 : : struct thread *t = &p->threads[i];
600 : :
601 : : /* mirroring_slots. */
602 : 0 : free(t->mirroring_slots);
603 : 0 : t->mirroring_slots = NULL;
604 : : }
605 : :
606 : : /* mirroring_sessions. */
607 : 0 : free(p->mirroring_sessions);
608 : 0 : p->mirroring_sessions = NULL;
609 : 0 : }
610 : :
611 : : static void
612 : : mirroring_free(struct rte_swx_pipeline *p)
613 : : {
614 : 0 : mirroring_build_free(p);
615 : : }
616 : :
617 : : static int
618 : 0 : mirroring_build(struct rte_swx_pipeline *p)
619 : : {
620 : : uint32_t i;
621 : :
622 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
623 : : struct thread *t = &p->threads[i];
624 : :
625 : : /* mirroring_slots. */
626 : 0 : t->mirroring_slots = calloc(p->n_mirroring_slots, sizeof(uint32_t));
627 [ # # ]: 0 : if (!t->mirroring_slots)
628 : 0 : goto error;
629 : : }
630 : :
631 : : /* mirroring_sessions. */
632 : 0 : p->mirroring_sessions = calloc(p->n_mirroring_sessions, sizeof(struct mirroring_session));
633 [ # # ]: 0 : if (!p->mirroring_sessions)
634 : 0 : goto error;
635 : :
636 : : return 0;
637 : :
638 : 0 : error:
639 : 0 : mirroring_build_free(p);
640 : 0 : return -ENOMEM;
641 : : }
642 : :
643 : : /*
644 : : * Extern object.
645 : : */
646 : : static struct extern_type *
647 : : extern_type_find(struct rte_swx_pipeline *p, const char *name)
648 : : {
649 : : struct extern_type *elem;
650 : :
651 [ # # # # : 0 : TAILQ_FOREACH(elem, &p->extern_types, node)
# # ]
652 [ # # # # : 0 : if (strcmp(elem->name, name) == 0)
# # ]
653 : : return elem;
654 : :
655 : : return NULL;
656 : : }
657 : :
658 : : static struct extern_type_member_func *
659 : : extern_type_member_func_find(struct extern_type *type, const char *name)
660 : : {
661 : : struct extern_type_member_func *elem;
662 : :
663 [ # # # # ]: 0 : TAILQ_FOREACH(elem, &type->funcs, node)
664 [ # # # # ]: 0 : if (strcmp(elem->name, name) == 0)
665 : : return elem;
666 : :
667 : : return NULL;
668 : : }
669 : :
670 : : static struct extern_obj *
671 : : extern_obj_find(struct rte_swx_pipeline *p, const char *name)
672 : : {
673 : : struct extern_obj *elem;
674 : :
675 [ # # # # : 0 : TAILQ_FOREACH(elem, &p->extern_objs, node)
# # ]
676 [ # # # # : 0 : if (strcmp(elem->name, name) == 0)
# # ]
677 : : return elem;
678 : :
679 : : return NULL;
680 : : }
681 : :
682 : : static struct extern_type_member_func *
683 : 0 : extern_obj_member_func_parse(struct rte_swx_pipeline *p,
684 : : const char *name,
685 : : struct extern_obj **obj)
686 : : {
687 : : struct extern_obj *object;
688 : : struct extern_type_member_func *func;
689 : : char *object_name, *func_name;
690 : :
691 [ # # # # ]: 0 : if (name[0] != 'e' || name[1] != '.')
692 : : return NULL;
693 : :
694 : 0 : object_name = strdup(&name[2]);
695 [ # # ]: 0 : if (!object_name)
696 : : return NULL;
697 : :
698 : 0 : func_name = strchr(object_name, '.');
699 [ # # ]: 0 : if (!func_name) {
700 : 0 : free(object_name);
701 : 0 : return NULL;
702 : : }
703 : :
704 : 0 : *func_name = 0;
705 : 0 : func_name++;
706 : :
707 : : object = extern_obj_find(p, object_name);
708 [ # # ]: 0 : if (!object) {
709 : 0 : free(object_name);
710 : 0 : return NULL;
711 : : }
712 : :
713 : 0 : func = extern_type_member_func_find(object->type, func_name);
714 [ # # ]: 0 : if (!func) {
715 : 0 : free(object_name);
716 : 0 : return NULL;
717 : : }
718 : :
719 [ # # ]: 0 : if (obj)
720 : 0 : *obj = object;
721 : :
722 : 0 : free(object_name);
723 : 0 : return func;
724 : : }
725 : :
726 : : static struct field *
727 : 0 : extern_obj_mailbox_field_parse(struct rte_swx_pipeline *p,
728 : : const char *name,
729 : : struct extern_obj **object)
730 : : {
731 : : struct extern_obj *obj;
732 : : struct field *f;
733 : : char *obj_name, *field_name;
734 : :
735 [ # # # # ]: 0 : if ((name[0] != 'e') || (name[1] != '.'))
736 : : return NULL;
737 : :
738 : 0 : obj_name = strdup(&name[2]);
739 [ # # ]: 0 : if (!obj_name)
740 : : return NULL;
741 : :
742 : 0 : field_name = strchr(obj_name, '.');
743 [ # # ]: 0 : if (!field_name) {
744 : 0 : free(obj_name);
745 : 0 : return NULL;
746 : : }
747 : :
748 : 0 : *field_name = 0;
749 : 0 : field_name++;
750 : :
751 : : obj = extern_obj_find(p, obj_name);
752 [ # # ]: 0 : if (!obj) {
753 : 0 : free(obj_name);
754 : 0 : return NULL;
755 : : }
756 : :
757 : 0 : f = struct_type_field_find(obj->type->mailbox_struct_type, field_name);
758 [ # # ]: 0 : if (!f) {
759 : 0 : free(obj_name);
760 : 0 : return NULL;
761 : : }
762 : :
763 [ # # ]: 0 : if (object)
764 : 0 : *object = obj;
765 : :
766 : 0 : free(obj_name);
767 : 0 : return f;
768 : : }
769 : :
770 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_pipeline_extern_type_register, 20.11)
771 : : int
772 : 0 : rte_swx_pipeline_extern_type_register(struct rte_swx_pipeline *p,
773 : : const char *name,
774 : : const char *mailbox_struct_type_name,
775 : : rte_swx_extern_type_constructor_t constructor,
776 : : rte_swx_extern_type_destructor_t destructor)
777 : : {
778 : : struct extern_type *elem;
779 : : struct struct_type *mailbox_struct_type;
780 : :
781 [ # # ]: 0 : CHECK(p, EINVAL);
782 : :
783 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
784 [ # # ]: 0 : CHECK(!extern_type_find(p, name), EEXIST);
785 : :
786 [ # # # # : 0 : CHECK_NAME(mailbox_struct_type_name, EINVAL);
# # ]
787 : : mailbox_struct_type = struct_type_find(p, mailbox_struct_type_name);
788 [ # # ]: 0 : CHECK(mailbox_struct_type, EINVAL);
789 [ # # ]: 0 : CHECK(!mailbox_struct_type->var_size, EINVAL);
790 : :
791 [ # # ]: 0 : CHECK(constructor, EINVAL);
792 [ # # ]: 0 : CHECK(destructor, EINVAL);
793 : :
794 : : /* Node allocation. */
795 : 0 : elem = calloc(1, sizeof(struct extern_type));
796 [ # # ]: 0 : CHECK(elem, ENOMEM);
797 : :
798 : : /* Node initialization. */
799 : 0 : strcpy(elem->name, name);
800 : 0 : elem->mailbox_struct_type = mailbox_struct_type;
801 : 0 : elem->constructor = constructor;
802 : 0 : elem->destructor = destructor;
803 : 0 : TAILQ_INIT(&elem->funcs);
804 : :
805 : : /* Node add to tailq. */
806 : 0 : TAILQ_INSERT_TAIL(&p->extern_types, elem, node);
807 : :
808 : 0 : return 0;
809 : : }
810 : :
811 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_pipeline_extern_type_member_func_register, 20.11)
812 : : int
813 : 0 : rte_swx_pipeline_extern_type_member_func_register(struct rte_swx_pipeline *p,
814 : : const char *extern_type_name,
815 : : const char *name,
816 : : rte_swx_extern_type_member_func_t member_func)
817 : : {
818 : : struct extern_type *type;
819 : : struct extern_type_member_func *type_member;
820 : :
821 [ # # ]: 0 : CHECK(p, EINVAL);
822 : :
823 [ # # # # : 0 : CHECK_NAME(extern_type_name, EINVAL);
# # ]
824 : : type = extern_type_find(p, extern_type_name);
825 [ # # ]: 0 : CHECK(type, EINVAL);
826 [ # # ]: 0 : CHECK(type->n_funcs < RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX, ENOSPC);
827 : :
828 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
829 [ # # ]: 0 : CHECK(!extern_type_member_func_find(type, name), EEXIST);
830 : :
831 [ # # ]: 0 : CHECK(member_func, EINVAL);
832 : :
833 : : /* Node allocation. */
834 : 0 : type_member = calloc(1, sizeof(struct extern_type_member_func));
835 [ # # ]: 0 : CHECK(type_member, ENOMEM);
836 : :
837 : : /* Node initialization. */
838 : 0 : strcpy(type_member->name, name);
839 : 0 : type_member->func = member_func;
840 : 0 : type_member->id = type->n_funcs;
841 : :
842 : : /* Node add to tailq. */
843 : 0 : TAILQ_INSERT_TAIL(&type->funcs, type_member, node);
844 : 0 : type->n_funcs++;
845 : :
846 : 0 : return 0;
847 : : }
848 : :
849 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_pipeline_extern_object_config, 20.11)
850 : : int
851 : 0 : rte_swx_pipeline_extern_object_config(struct rte_swx_pipeline *p,
852 : : const char *extern_type_name,
853 : : const char *name,
854 : : const char *args)
855 : : {
856 : : struct extern_type *type;
857 : : struct extern_obj *obj;
858 : : void *obj_handle;
859 : :
860 [ # # ]: 0 : CHECK(p, EINVAL);
861 : :
862 [ # # # # : 0 : CHECK_NAME(extern_type_name, EINVAL);
# # ]
863 : : type = extern_type_find(p, extern_type_name);
864 [ # # ]: 0 : CHECK(type, EINVAL);
865 : :
866 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
867 [ # # ]: 0 : CHECK(!extern_obj_find(p, name), EEXIST);
868 : :
869 : : /* Node allocation. */
870 : 0 : obj = calloc(1, sizeof(struct extern_obj));
871 [ # # ]: 0 : CHECK(obj, ENOMEM);
872 : :
873 : : /* Object construction. */
874 : 0 : obj_handle = type->constructor(args);
875 [ # # ]: 0 : if (!obj_handle) {
876 : 0 : free(obj);
877 : 0 : CHECK(0, ENODEV);
878 : : }
879 : :
880 : : /* Node initialization. */
881 : 0 : strcpy(obj->name, name);
882 : 0 : obj->type = type;
883 : 0 : obj->obj = obj_handle;
884 : 0 : obj->struct_id = p->n_structs;
885 : 0 : obj->id = p->n_extern_objs;
886 : :
887 : : /* Node add to tailq. */
888 : 0 : TAILQ_INSERT_TAIL(&p->extern_objs, obj, node);
889 : 0 : p->n_extern_objs++;
890 : 0 : p->n_structs++;
891 : :
892 : 0 : return 0;
893 : : }
894 : :
895 : : static int
896 : 0 : extern_obj_build(struct rte_swx_pipeline *p)
897 : : {
898 : : uint32_t i;
899 : :
900 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
901 : : struct thread *t = &p->threads[i];
902 : : struct extern_obj *obj;
903 : :
904 : 0 : t->extern_objs = calloc(p->n_extern_objs,
905 : : sizeof(struct extern_obj_runtime));
906 [ # # ]: 0 : CHECK(t->extern_objs, ENOMEM);
907 : :
908 [ # # ]: 0 : TAILQ_FOREACH(obj, &p->extern_objs, node) {
909 : 0 : struct extern_obj_runtime *r =
910 : 0 : &t->extern_objs[obj->id];
911 : : struct extern_type_member_func *func;
912 : 0 : uint32_t mailbox_size =
913 : 0 : obj->type->mailbox_struct_type->n_bits / 8;
914 : :
915 : 0 : r->obj = obj->obj;
916 : :
917 : 0 : r->mailbox = calloc(1, mailbox_size);
918 [ # # ]: 0 : CHECK(r->mailbox, ENOMEM);
919 : :
920 [ # # ]: 0 : TAILQ_FOREACH(func, &obj->type->funcs, node)
921 : 0 : r->funcs[func->id] = func->func;
922 : :
923 : 0 : t->structs[obj->struct_id] = r->mailbox;
924 : : }
925 : : }
926 : :
927 : : return 0;
928 : : }
929 : :
930 : : static void
931 : 0 : extern_obj_build_free(struct rte_swx_pipeline *p)
932 : : {
933 : : uint32_t i;
934 : :
935 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
936 : : struct thread *t = &p->threads[i];
937 : : uint32_t j;
938 : :
939 [ # # ]: 0 : if (!t->extern_objs)
940 : 0 : continue;
941 : :
942 [ # # ]: 0 : for (j = 0; j < p->n_extern_objs; j++) {
943 : 0 : struct extern_obj_runtime *r = &t->extern_objs[j];
944 : :
945 : 0 : free(r->mailbox);
946 : : }
947 : :
948 : 0 : free(t->extern_objs);
949 : 0 : t->extern_objs = NULL;
950 : : }
951 : 0 : }
952 : :
953 : : static void
954 : 0 : extern_obj_free(struct rte_swx_pipeline *p)
955 : : {
956 : 0 : extern_obj_build_free(p);
957 : :
958 : : /* Extern objects. */
959 : 0 : for ( ; ; ) {
960 : : struct extern_obj *elem;
961 : :
962 : 0 : elem = TAILQ_FIRST(&p->extern_objs);
963 [ # # ]: 0 : if (!elem)
964 : : break;
965 : :
966 [ # # ]: 0 : TAILQ_REMOVE(&p->extern_objs, elem, node);
967 [ # # ]: 0 : if (elem->obj)
968 : 0 : elem->type->destructor(elem->obj);
969 : 0 : free(elem);
970 : : }
971 : :
972 : : /* Extern types. */
973 : 0 : for ( ; ; ) {
974 : : struct extern_type *elem;
975 : :
976 : 0 : elem = TAILQ_FIRST(&p->extern_types);
977 [ # # ]: 0 : if (!elem)
978 : : break;
979 : :
980 [ # # ]: 0 : TAILQ_REMOVE(&p->extern_types, elem, node);
981 : :
982 : 0 : for ( ; ; ) {
983 : : struct extern_type_member_func *func;
984 : :
985 : 0 : func = TAILQ_FIRST(&elem->funcs);
986 [ # # ]: 0 : if (!func)
987 : : break;
988 : :
989 [ # # ]: 0 : TAILQ_REMOVE(&elem->funcs, func, node);
990 : 0 : free(func);
991 : : }
992 : :
993 : 0 : free(elem);
994 : : }
995 : 0 : }
996 : :
997 : : /*
998 : : * Extern function.
999 : : */
1000 : : static struct extern_func *
1001 : : extern_func_find(struct rte_swx_pipeline *p, const char *name)
1002 : : {
1003 : : struct extern_func *elem;
1004 : :
1005 [ # # # # : 0 : TAILQ_FOREACH(elem, &p->extern_funcs, node)
# # ]
1006 [ # # # # : 0 : if (strcmp(elem->name, name) == 0)
# # ]
1007 : : return elem;
1008 : :
1009 : : return NULL;
1010 : : }
1011 : :
1012 : : static struct extern_func *
1013 : 0 : extern_func_parse(struct rte_swx_pipeline *p,
1014 : : const char *name)
1015 : : {
1016 [ # # # # ]: 0 : if (name[0] != 'f' || name[1] != '.')
1017 : : return NULL;
1018 : :
1019 : 0 : return extern_func_find(p, &name[2]);
1020 : : }
1021 : :
1022 : : static struct field *
1023 : 0 : extern_func_mailbox_field_parse(struct rte_swx_pipeline *p,
1024 : : const char *name,
1025 : : struct extern_func **function)
1026 : : {
1027 : : struct extern_func *func;
1028 : : struct field *f;
1029 : : char *func_name, *field_name;
1030 : :
1031 [ # # # # ]: 0 : if ((name[0] != 'f') || (name[1] != '.'))
1032 : : return NULL;
1033 : :
1034 : 0 : func_name = strdup(&name[2]);
1035 [ # # ]: 0 : if (!func_name)
1036 : : return NULL;
1037 : :
1038 : 0 : field_name = strchr(func_name, '.');
1039 [ # # ]: 0 : if (!field_name) {
1040 : 0 : free(func_name);
1041 : 0 : return NULL;
1042 : : }
1043 : :
1044 : 0 : *field_name = 0;
1045 : 0 : field_name++;
1046 : :
1047 : : func = extern_func_find(p, func_name);
1048 [ # # ]: 0 : if (!func) {
1049 : 0 : free(func_name);
1050 : 0 : return NULL;
1051 : : }
1052 : :
1053 : 0 : f = struct_type_field_find(func->mailbox_struct_type, field_name);
1054 [ # # ]: 0 : if (!f) {
1055 : 0 : free(func_name);
1056 : 0 : return NULL;
1057 : : }
1058 : :
1059 [ # # ]: 0 : if (function)
1060 : 0 : *function = func;
1061 : :
1062 : 0 : free(func_name);
1063 : 0 : return f;
1064 : : }
1065 : :
1066 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_pipeline_extern_func_register, 20.11)
1067 : : int
1068 : 0 : rte_swx_pipeline_extern_func_register(struct rte_swx_pipeline *p,
1069 : : const char *name,
1070 : : const char *mailbox_struct_type_name,
1071 : : rte_swx_extern_func_t func)
1072 : : {
1073 : : struct extern_func *f;
1074 : : struct struct_type *mailbox_struct_type;
1075 : :
1076 [ # # ]: 0 : CHECK(p, EINVAL);
1077 : :
1078 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
1079 [ # # ]: 0 : CHECK(!extern_func_find(p, name), EEXIST);
1080 : :
1081 [ # # # # : 0 : CHECK_NAME(mailbox_struct_type_name, EINVAL);
# # ]
1082 : : mailbox_struct_type = struct_type_find(p, mailbox_struct_type_name);
1083 [ # # ]: 0 : CHECK(mailbox_struct_type, EINVAL);
1084 [ # # ]: 0 : CHECK(!mailbox_struct_type->var_size, EINVAL);
1085 : :
1086 [ # # ]: 0 : CHECK(func, EINVAL);
1087 : :
1088 : : /* Node allocation. */
1089 : 0 : f = calloc(1, sizeof(struct extern_func));
1090 : : CHECK(func, ENOMEM);
1091 : :
1092 : : /* Node initialization. */
1093 : 0 : strcpy(f->name, name);
1094 : 0 : f->mailbox_struct_type = mailbox_struct_type;
1095 : 0 : f->func = func;
1096 : 0 : f->struct_id = p->n_structs;
1097 : 0 : f->id = p->n_extern_funcs;
1098 : :
1099 : : /* Node add to tailq. */
1100 : 0 : TAILQ_INSERT_TAIL(&p->extern_funcs, f, node);
1101 : 0 : p->n_extern_funcs++;
1102 : 0 : p->n_structs++;
1103 : :
1104 : 0 : return 0;
1105 : : }
1106 : :
1107 : : static int
1108 : 0 : extern_func_build(struct rte_swx_pipeline *p)
1109 : : {
1110 : : uint32_t i;
1111 : :
1112 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1113 : : struct thread *t = &p->threads[i];
1114 : : struct extern_func *func;
1115 : :
1116 : : /* Memory allocation. */
1117 : 0 : t->extern_funcs = calloc(p->n_extern_funcs,
1118 : : sizeof(struct extern_func_runtime));
1119 [ # # ]: 0 : CHECK(t->extern_funcs, ENOMEM);
1120 : :
1121 : : /* Extern function. */
1122 [ # # ]: 0 : TAILQ_FOREACH(func, &p->extern_funcs, node) {
1123 : 0 : struct extern_func_runtime *r =
1124 : 0 : &t->extern_funcs[func->id];
1125 : 0 : uint32_t mailbox_size =
1126 : 0 : func->mailbox_struct_type->n_bits / 8;
1127 : :
1128 : 0 : r->func = func->func;
1129 : :
1130 : 0 : r->mailbox = calloc(1, mailbox_size);
1131 [ # # ]: 0 : CHECK(r->mailbox, ENOMEM);
1132 : :
1133 : 0 : t->structs[func->struct_id] = r->mailbox;
1134 : : }
1135 : : }
1136 : :
1137 : : return 0;
1138 : : }
1139 : :
1140 : : static void
1141 : 0 : extern_func_build_free(struct rte_swx_pipeline *p)
1142 : : {
1143 : : uint32_t i;
1144 : :
1145 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1146 : : struct thread *t = &p->threads[i];
1147 : : uint32_t j;
1148 : :
1149 [ # # ]: 0 : if (!t->extern_funcs)
1150 : 0 : continue;
1151 : :
1152 [ # # ]: 0 : for (j = 0; j < p->n_extern_funcs; j++) {
1153 : 0 : struct extern_func_runtime *r = &t->extern_funcs[j];
1154 : :
1155 : 0 : free(r->mailbox);
1156 : : }
1157 : :
1158 : 0 : free(t->extern_funcs);
1159 : 0 : t->extern_funcs = NULL;
1160 : : }
1161 : 0 : }
1162 : :
1163 : : static void
1164 : 0 : extern_func_free(struct rte_swx_pipeline *p)
1165 : : {
1166 : 0 : extern_func_build_free(p);
1167 : :
1168 : 0 : for ( ; ; ) {
1169 : : struct extern_func *elem;
1170 : :
1171 : 0 : elem = TAILQ_FIRST(&p->extern_funcs);
1172 [ # # ]: 0 : if (!elem)
1173 : : break;
1174 : :
1175 [ # # ]: 0 : TAILQ_REMOVE(&p->extern_funcs, elem, node);
1176 : 0 : free(elem);
1177 : : }
1178 : 0 : }
1179 : :
1180 : : /*
1181 : : * Hash function.
1182 : : */
1183 : : static struct hash_func *
1184 : : hash_func_find(struct rte_swx_pipeline *p, const char *name)
1185 : : {
1186 : : struct hash_func *elem;
1187 : :
1188 [ # # # # : 0 : TAILQ_FOREACH(elem, &p->hash_funcs, node)
# # # # ]
1189 [ # # # # : 0 : if (strcmp(elem->name, name) == 0)
# # # # ]
1190 : : return elem;
1191 : :
1192 : : return NULL;
1193 : : }
1194 : :
1195 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_pipeline_hash_func_register, 22.07)
1196 : : int
1197 : 0 : rte_swx_pipeline_hash_func_register(struct rte_swx_pipeline *p,
1198 : : const char *name,
1199 : : rte_swx_hash_func_t func)
1200 : : {
1201 : : struct hash_func *f;
1202 : :
1203 [ # # ]: 0 : CHECK(p, EINVAL);
1204 : :
1205 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
1206 [ # # ]: 0 : CHECK(!hash_func_find(p, name), EEXIST);
1207 : :
1208 [ # # ]: 0 : CHECK(func, EINVAL);
1209 : :
1210 : : /* Node allocation. */
1211 : 0 : f = calloc(1, sizeof(struct hash_func));
1212 : : CHECK(func, ENOMEM);
1213 : :
1214 : : /* Node initialization. */
1215 : 0 : strcpy(f->name, name);
1216 : 0 : f->func = func;
1217 : 0 : f->id = p->n_hash_funcs;
1218 : :
1219 : : /* Node add to tailq. */
1220 : 0 : TAILQ_INSERT_TAIL(&p->hash_funcs, f, node);
1221 : 0 : p->n_hash_funcs++;
1222 : :
1223 : 0 : return 0;
1224 : : }
1225 : :
1226 : : static int
1227 : 0 : hash_func_build(struct rte_swx_pipeline *p)
1228 : : {
1229 : : struct hash_func *func;
1230 : :
1231 : : /* Memory allocation. */
1232 : 0 : p->hash_func_runtime = calloc(p->n_hash_funcs, sizeof(struct hash_func_runtime));
1233 [ # # ]: 0 : CHECK(p->hash_func_runtime, ENOMEM);
1234 : :
1235 : : /* Hash function. */
1236 [ # # ]: 0 : TAILQ_FOREACH(func, &p->hash_funcs, node) {
1237 : 0 : struct hash_func_runtime *r = &p->hash_func_runtime[func->id];
1238 : :
1239 : 0 : r->func = func->func;
1240 : : }
1241 : :
1242 : : return 0;
1243 : : }
1244 : :
1245 : : static void
1246 : : hash_func_build_free(struct rte_swx_pipeline *p)
1247 : : {
1248 : 0 : free(p->hash_func_runtime);
1249 : 0 : p->hash_func_runtime = NULL;
1250 : 0 : }
1251 : :
1252 : : static void
1253 : 0 : hash_func_free(struct rte_swx_pipeline *p)
1254 : : {
1255 : : hash_func_build_free(p);
1256 : :
1257 : 0 : for ( ; ; ) {
1258 : : struct hash_func *elem;
1259 : :
1260 : 0 : elem = TAILQ_FIRST(&p->hash_funcs);
1261 [ # # ]: 0 : if (!elem)
1262 : : break;
1263 : :
1264 [ # # ]: 0 : TAILQ_REMOVE(&p->hash_funcs, elem, node);
1265 : 0 : free(elem);
1266 : : }
1267 : 0 : }
1268 : :
1269 : : /*
1270 : : * RSS.
1271 : : */
1272 : : static struct rss *
1273 : : rss_find(struct rte_swx_pipeline *p, const char *name)
1274 : : {
1275 : : struct rss *elem;
1276 : :
1277 [ # # # # : 0 : TAILQ_FOREACH(elem, &p->rss, node)
# # # # #
# ]
1278 [ # # # # : 0 : if (strcmp(elem->name, name) == 0)
# # # # #
# ]
1279 : : return elem;
1280 : :
1281 : : return NULL;
1282 : : }
1283 : :
1284 : : static struct rss *
1285 : : rss_find_by_id(struct rte_swx_pipeline *p, uint32_t rss_obj_id)
1286 : : {
1287 : : struct rss *elem;
1288 : :
1289 [ # # ]: 0 : TAILQ_FOREACH(elem, &p->rss, node)
1290 [ # # ]: 0 : if (elem->id == rss_obj_id)
1291 : : return elem;
1292 : :
1293 : : return NULL;
1294 : : }
1295 : :
1296 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_pipeline_rss_config, 23.03)
1297 : : int
1298 : 0 : rte_swx_pipeline_rss_config(struct rte_swx_pipeline *p, const char *name)
1299 : : {
1300 : : struct rss *r;
1301 : :
1302 [ # # ]: 0 : CHECK(p, EINVAL);
1303 : :
1304 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
1305 [ # # ]: 0 : CHECK(!rss_find(p, name), EEXIST);
1306 : :
1307 : : /* Memory allocation. */
1308 : 0 : r = calloc(1, sizeof(struct rss));
1309 [ # # ]: 0 : CHECK(r, ENOMEM);
1310 : :
1311 : : /* Node initialization. */
1312 : 0 : strcpy(r->name, name);
1313 : 0 : r->id = p->n_rss;
1314 : :
1315 : : /* Node add to tailq. */
1316 : 0 : TAILQ_INSERT_TAIL(&p->rss, r, node);
1317 : 0 : p->n_rss++;
1318 : :
1319 : 0 : return 0;
1320 : : }
1321 : :
1322 : : static void
1323 : 0 : rss_build_free(struct rte_swx_pipeline *p)
1324 : : {
1325 : : uint32_t i;
1326 : :
1327 [ # # ]: 0 : if (!p->rss_runtime)
1328 : : return;
1329 : :
1330 [ # # ]: 0 : for (i = 0; i < p->n_rss; i++)
1331 : 0 : free(p->rss_runtime[i]);
1332 : :
1333 : 0 : free(p->rss_runtime);
1334 : 0 : p->rss_runtime = NULL;
1335 : : }
1336 : :
1337 : : static const struct {
1338 : : uint32_t key_size;
1339 : : uint8_t key[4];
1340 : : } rss_runtime_default = {
1341 : : .key_size = 4,
1342 : : .key = {0, 0, 0, 0},
1343 : : };
1344 : :
1345 : : static int
1346 : 0 : rss_build(struct rte_swx_pipeline *p)
1347 : : {
1348 : : uint32_t i;
1349 : : int status = 0;
1350 : :
1351 : : /* Memory allocation. */
1352 : 0 : p->rss_runtime = calloc(p->n_rss, sizeof(struct rss_runtime *));
1353 [ # # ]: 0 : if (!p->rss_runtime) {
1354 : : status = -ENOMEM;
1355 : 0 : goto error;
1356 : : }
1357 : :
1358 : : /* RSS. */
1359 [ # # ]: 0 : for (i = 0; i < p->n_rss; i++) {
1360 : 0 : p->rss_runtime[i] = malloc(sizeof(rss_runtime_default));
1361 [ # # ]: 0 : if (!p->rss_runtime[i]) {
1362 : : status = -ENOMEM;
1363 : 0 : goto error;
1364 : : }
1365 : :
1366 : : memcpy(p->rss_runtime[i], &rss_runtime_default, sizeof(rss_runtime_default));
1367 : : }
1368 : :
1369 : : return 0;
1370 : :
1371 : 0 : error:
1372 : 0 : rss_build_free(p);
1373 : 0 : return status;
1374 : : }
1375 : :
1376 : : static void
1377 : 0 : rss_free(struct rte_swx_pipeline *p)
1378 : : {
1379 : 0 : rss_build_free(p);
1380 : :
1381 : 0 : for ( ; ; ) {
1382 : : struct rss *elem;
1383 : :
1384 : 0 : elem = TAILQ_FIRST(&p->rss);
1385 [ # # ]: 0 : if (!elem)
1386 : : break;
1387 : :
1388 [ # # ]: 0 : TAILQ_REMOVE(&p->rss, elem, node);
1389 : 0 : free(elem);
1390 : : }
1391 : 0 : }
1392 : :
1393 : : /*
1394 : : * Header.
1395 : : */
1396 : : static struct header *
1397 : : header_find(struct rte_swx_pipeline *p, const char *name)
1398 : : {
1399 : : struct header *elem;
1400 : :
1401 [ # # # # : 0 : TAILQ_FOREACH(elem, &p->headers, node)
# # ]
1402 [ # # # # : 0 : if (strcmp(elem->name, name) == 0)
# # ]
1403 : : return elem;
1404 : :
1405 : : return NULL;
1406 : : }
1407 : :
1408 : : static struct header *
1409 : : header_find_by_struct_id(struct rte_swx_pipeline *p, uint32_t struct_id)
1410 : : {
1411 : : struct header *elem;
1412 : :
1413 [ # # # # ]: 0 : TAILQ_FOREACH(elem, &p->headers, node)
1414 [ # # # # ]: 0 : if (elem->struct_id == struct_id)
1415 : : return elem;
1416 : :
1417 : : return NULL;
1418 : : }
1419 : :
1420 : : static struct header *
1421 : 0 : header_parse(struct rte_swx_pipeline *p,
1422 : : const char *name)
1423 : : {
1424 [ # # # # ]: 0 : if (name[0] != 'h' || name[1] != '.')
1425 : : return NULL;
1426 : :
1427 : 0 : return header_find(p, &name[2]);
1428 : : }
1429 : :
1430 : : static struct field *
1431 : 0 : header_field_parse(struct rte_swx_pipeline *p,
1432 : : const char *name,
1433 : : struct header **header)
1434 : : {
1435 : : struct header *h;
1436 : : struct field *f;
1437 : : char *header_name, *field_name;
1438 : :
1439 [ # # # # ]: 0 : if ((name[0] != 'h') || (name[1] != '.'))
1440 : : return NULL;
1441 : :
1442 : 0 : header_name = strdup(&name[2]);
1443 [ # # ]: 0 : if (!header_name)
1444 : : return NULL;
1445 : :
1446 : 0 : field_name = strchr(header_name, '.');
1447 [ # # ]: 0 : if (!field_name) {
1448 : 0 : free(header_name);
1449 : 0 : return NULL;
1450 : : }
1451 : :
1452 : 0 : *field_name = 0;
1453 : 0 : field_name++;
1454 : :
1455 : : h = header_find(p, header_name);
1456 [ # # ]: 0 : if (!h) {
1457 : 0 : free(header_name);
1458 : 0 : return NULL;
1459 : : }
1460 : :
1461 : 0 : f = struct_type_field_find(h->st, field_name);
1462 [ # # ]: 0 : if (!f) {
1463 : 0 : free(header_name);
1464 : 0 : return NULL;
1465 : : }
1466 : :
1467 [ # # ]: 0 : if (header)
1468 : 0 : *header = h;
1469 : :
1470 : 0 : free(header_name);
1471 : 0 : return f;
1472 : : }
1473 : :
1474 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_pipeline_packet_header_register, 20.11)
1475 : : int
1476 : 0 : rte_swx_pipeline_packet_header_register(struct rte_swx_pipeline *p,
1477 : : const char *name,
1478 : : const char *struct_type_name)
1479 : : {
1480 : : struct struct_type *st;
1481 : : struct header *h;
1482 : : size_t n_headers_max;
1483 : :
1484 [ # # ]: 0 : CHECK(p, EINVAL);
1485 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
1486 [ # # # # : 0 : CHECK_NAME(struct_type_name, EINVAL);
# # ]
1487 : :
1488 [ # # ]: 0 : CHECK(!header_find(p, name), EEXIST);
1489 : :
1490 : : st = struct_type_find(p, struct_type_name);
1491 [ # # ]: 0 : CHECK(st, EINVAL);
1492 : :
1493 : : n_headers_max = RTE_SIZEOF_FIELD(struct thread, valid_headers) * 8;
1494 [ # # ]: 0 : CHECK(p->n_headers < n_headers_max, ENOSPC);
1495 : :
1496 : : /* Node allocation. */
1497 : 0 : h = calloc(1, sizeof(struct header));
1498 [ # # ]: 0 : CHECK(h, ENOMEM);
1499 : :
1500 : : /* Node initialization. */
1501 : 0 : strcpy(h->name, name);
1502 : 0 : h->st = st;
1503 : 0 : h->struct_id = p->n_structs;
1504 : 0 : h->id = p->n_headers;
1505 : :
1506 : : /* Node add to tailq. */
1507 : 0 : TAILQ_INSERT_TAIL(&p->headers, h, node);
1508 : 0 : p->n_headers++;
1509 : 0 : p->n_structs++;
1510 : :
1511 : 0 : return 0;
1512 : : }
1513 : :
1514 : : static int
1515 : 0 : header_build(struct rte_swx_pipeline *p)
1516 : : {
1517 : : struct header *h;
1518 : : uint32_t n_bytes = 0, i;
1519 : :
1520 [ # # ]: 0 : TAILQ_FOREACH(h, &p->headers, node) {
1521 : 0 : n_bytes += h->st->n_bits / 8;
1522 : : }
1523 : :
1524 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1525 : : struct thread *t = &p->threads[i];
1526 : : uint32_t offset = 0;
1527 : :
1528 : 0 : t->headers = calloc(p->n_headers,
1529 : : sizeof(struct header_runtime));
1530 [ # # ]: 0 : CHECK(t->headers, ENOMEM);
1531 : :
1532 : 0 : t->headers_out = calloc(p->n_headers,
1533 : : sizeof(struct header_out_runtime));
1534 [ # # ]: 0 : CHECK(t->headers_out, ENOMEM);
1535 : :
1536 : 0 : t->header_storage = calloc(1, n_bytes);
1537 [ # # ]: 0 : CHECK(t->header_storage, ENOMEM);
1538 : :
1539 : 0 : t->header_out_storage = calloc(1, n_bytes);
1540 [ # # ]: 0 : CHECK(t->header_out_storage, ENOMEM);
1541 : :
1542 [ # # ]: 0 : TAILQ_FOREACH(h, &p->headers, node) {
1543 : : uint8_t *header_storage;
1544 : 0 : uint32_t n_bytes = h->st->n_bits / 8;
1545 : :
1546 : 0 : header_storage = &t->header_storage[offset];
1547 : 0 : offset += n_bytes;
1548 : :
1549 : 0 : t->headers[h->id].ptr0 = header_storage;
1550 : 0 : t->headers[h->id].n_bytes = n_bytes;
1551 : :
1552 : 0 : t->structs[h->struct_id] = header_storage;
1553 : : }
1554 : : }
1555 : :
1556 : : return 0;
1557 : : }
1558 : :
1559 : : static void
1560 : 0 : header_build_free(struct rte_swx_pipeline *p)
1561 : : {
1562 : : uint32_t i;
1563 : :
1564 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1565 : : struct thread *t = &p->threads[i];
1566 : :
1567 : 0 : free(t->headers_out);
1568 : 0 : t->headers_out = NULL;
1569 : :
1570 : 0 : free(t->headers);
1571 : 0 : t->headers = NULL;
1572 : :
1573 : 0 : free(t->header_out_storage);
1574 : 0 : t->header_out_storage = NULL;
1575 : :
1576 : 0 : free(t->header_storage);
1577 : 0 : t->header_storage = NULL;
1578 : : }
1579 : 0 : }
1580 : :
1581 : : static void
1582 : 0 : header_free(struct rte_swx_pipeline *p)
1583 : : {
1584 : 0 : header_build_free(p);
1585 : :
1586 : 0 : for ( ; ; ) {
1587 : : struct header *elem;
1588 : :
1589 : 0 : elem = TAILQ_FIRST(&p->headers);
1590 [ # # ]: 0 : if (!elem)
1591 : : break;
1592 : :
1593 [ # # ]: 0 : TAILQ_REMOVE(&p->headers, elem, node);
1594 : 0 : free(elem);
1595 : : }
1596 : 0 : }
1597 : :
1598 : : /*
1599 : : * Meta-data.
1600 : : */
1601 : : static struct field *
1602 : 0 : metadata_field_parse(struct rte_swx_pipeline *p, const char *name)
1603 : : {
1604 [ # # ]: 0 : if (!p->metadata_st)
1605 : : return NULL;
1606 : :
1607 [ # # # # ]: 0 : if (name[0] != 'm' || name[1] != '.')
1608 : : return NULL;
1609 : :
1610 : 0 : return struct_type_field_find(p->metadata_st, &name[2]);
1611 : : }
1612 : :
1613 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_pipeline_packet_metadata_register, 20.11)
1614 : : int
1615 : 0 : rte_swx_pipeline_packet_metadata_register(struct rte_swx_pipeline *p,
1616 : : const char *struct_type_name)
1617 : : {
1618 : : struct struct_type *st = NULL;
1619 : :
1620 [ # # ]: 0 : CHECK(p, EINVAL);
1621 : :
1622 [ # # # # : 0 : CHECK_NAME(struct_type_name, EINVAL);
# # ]
1623 : : st = struct_type_find(p, struct_type_name);
1624 [ # # ]: 0 : CHECK(st, EINVAL);
1625 [ # # ]: 0 : CHECK(!st->var_size, EINVAL);
1626 [ # # ]: 0 : CHECK(!p->metadata_st, EINVAL);
1627 : :
1628 : 0 : p->metadata_st = st;
1629 : 0 : p->metadata_struct_id = p->n_structs;
1630 : :
1631 : 0 : p->n_structs++;
1632 : :
1633 : 0 : return 0;
1634 : : }
1635 : :
1636 : : static int
1637 : 0 : metadata_build(struct rte_swx_pipeline *p)
1638 : : {
1639 : 0 : uint32_t n_bytes = p->metadata_st->n_bits / 8;
1640 : : uint32_t i;
1641 : :
1642 : : /* Thread-level initialization. */
1643 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1644 : : struct thread *t = &p->threads[i];
1645 : : uint8_t *metadata;
1646 : :
1647 : 0 : metadata = calloc(1, n_bytes);
1648 [ # # ]: 0 : CHECK(metadata, ENOMEM);
1649 : :
1650 : 0 : t->metadata = metadata;
1651 : 0 : t->structs[p->metadata_struct_id] = metadata;
1652 : : }
1653 : :
1654 : : return 0;
1655 : : }
1656 : :
1657 : : static void
1658 : : metadata_build_free(struct rte_swx_pipeline *p)
1659 : : {
1660 : : uint32_t i;
1661 : :
1662 [ # # # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1663 : : struct thread *t = &p->threads[i];
1664 : :
1665 : 0 : free(t->metadata);
1666 : 0 : t->metadata = NULL;
1667 : : }
1668 : : }
1669 : :
1670 : : static void
1671 : : metadata_free(struct rte_swx_pipeline *p)
1672 : : {
1673 : : metadata_build_free(p);
1674 : : }
1675 : :
1676 : : /*
1677 : : * Instruction.
1678 : : */
1679 : : static int
1680 : : instruction_is_tx(enum instruction_type type)
1681 : : {
1682 [ # # ]: 0 : switch (type) {
1683 : : case INSTR_TX:
1684 : : case INSTR_TX_I:
1685 : : case INSTR_DROP:
1686 : : return 1;
1687 : :
1688 : : default:
1689 : : return 0;
1690 : : }
1691 : : }
1692 : :
1693 : : static int
1694 : : instruction_does_tx(struct instruction *instr)
1695 : : {
1696 [ # # # # ]: 0 : switch (instr->type) {
1697 : : case INSTR_TX:
1698 : : case INSTR_TX_I:
1699 : : case INSTR_DROP:
1700 : : case INSTR_HDR_EMIT_TX:
1701 : : case INSTR_HDR_EMIT2_TX:
1702 : : case INSTR_HDR_EMIT3_TX:
1703 : : case INSTR_HDR_EMIT4_TX:
1704 : : case INSTR_HDR_EMIT5_TX:
1705 : : case INSTR_HDR_EMIT6_TX:
1706 : : case INSTR_HDR_EMIT7_TX:
1707 : : case INSTR_HDR_EMIT8_TX:
1708 : : return 1;
1709 : : default:
1710 : : return 0;
1711 : : }
1712 : : }
1713 : :
1714 : : static int
1715 : : instruction_is_jmp(struct instruction *instr)
1716 : : {
1717 [ # # # # ]: 0 : switch (instr->type) {
1718 : : case INSTR_JMP:
1719 : : case INSTR_JMP_VALID:
1720 : : case INSTR_JMP_INVALID:
1721 : : case INSTR_JMP_HIT:
1722 : : case INSTR_JMP_MISS:
1723 : : case INSTR_JMP_ACTION_HIT:
1724 : : case INSTR_JMP_ACTION_MISS:
1725 : : case INSTR_JMP_EQ:
1726 : : case INSTR_JMP_EQ_MH:
1727 : : case INSTR_JMP_EQ_HM:
1728 : : case INSTR_JMP_EQ_HH:
1729 : : case INSTR_JMP_EQ_I:
1730 : : case INSTR_JMP_NEQ:
1731 : : case INSTR_JMP_NEQ_MH:
1732 : : case INSTR_JMP_NEQ_HM:
1733 : : case INSTR_JMP_NEQ_HH:
1734 : : case INSTR_JMP_NEQ_I:
1735 : : case INSTR_JMP_LT:
1736 : : case INSTR_JMP_LT_MH:
1737 : : case INSTR_JMP_LT_HM:
1738 : : case INSTR_JMP_LT_HH:
1739 : : case INSTR_JMP_LT_MI:
1740 : : case INSTR_JMP_LT_HI:
1741 : : case INSTR_JMP_GT:
1742 : : case INSTR_JMP_GT_MH:
1743 : : case INSTR_JMP_GT_HM:
1744 : : case INSTR_JMP_GT_HH:
1745 : : case INSTR_JMP_GT_MI:
1746 : : case INSTR_JMP_GT_HI:
1747 : : return 1;
1748 : :
1749 : : default:
1750 : : return 0;
1751 : : }
1752 : : }
1753 : :
1754 : : static int
1755 : : instruction_does_thread_yield(struct instruction *instr)
1756 : : {
1757 : 0 : switch (instr->type) {
1758 : : case INSTR_RX:
1759 : : case INSTR_TABLE:
1760 : : case INSTR_TABLE_AF:
1761 : : case INSTR_SELECTOR:
1762 : : case INSTR_LEARNER:
1763 : : case INSTR_LEARNER_AF:
1764 : : case INSTR_EXTERN_OBJ:
1765 : : case INSTR_EXTERN_FUNC:
1766 : : return 1;
1767 : : default:
1768 : : return 0;
1769 : : }
1770 : : }
1771 : :
1772 : : static struct field *
1773 : : action_field_parse(struct action *action, const char *name);
1774 : :
1775 : : static struct field *
1776 : 0 : struct_field_parse(struct rte_swx_pipeline *p,
1777 : : struct action *action,
1778 : : const char *name,
1779 : : uint32_t *struct_id)
1780 : : {
1781 : : struct field *f;
1782 : :
1783 [ # # # # : 0 : switch (name[0]) {
# # ]
1784 : 0 : case 'h':
1785 : : {
1786 : : struct header *header;
1787 : :
1788 : 0 : f = header_field_parse(p, name, &header);
1789 [ # # ]: 0 : if (!f)
1790 : : return NULL;
1791 : :
1792 : 0 : *struct_id = header->struct_id;
1793 : 0 : return f;
1794 : : }
1795 : :
1796 : 0 : case 'm':
1797 : : {
1798 : 0 : f = metadata_field_parse(p, name);
1799 [ # # ]: 0 : if (!f)
1800 : : return NULL;
1801 : :
1802 : 0 : *struct_id = p->metadata_struct_id;
1803 : 0 : return f;
1804 : : }
1805 : :
1806 : 0 : case 't':
1807 : : {
1808 [ # # ]: 0 : if (!action)
1809 : : return NULL;
1810 : :
1811 : 0 : f = action_field_parse(action, name);
1812 [ # # ]: 0 : if (!f)
1813 : : return NULL;
1814 : :
1815 : 0 : *struct_id = 0;
1816 : 0 : return f;
1817 : : }
1818 : :
1819 : 0 : case 'e':
1820 : : {
1821 : : struct extern_obj *obj;
1822 : :
1823 : 0 : f = extern_obj_mailbox_field_parse(p, name, &obj);
1824 [ # # ]: 0 : if (!f)
1825 : : return NULL;
1826 : :
1827 : 0 : *struct_id = obj->struct_id;
1828 : 0 : return f;
1829 : : }
1830 : :
1831 : 0 : case 'f':
1832 : : {
1833 : : struct extern_func *func;
1834 : :
1835 : 0 : f = extern_func_mailbox_field_parse(p, name, &func);
1836 [ # # ]: 0 : if (!f)
1837 : : return NULL;
1838 : :
1839 : 0 : *struct_id = func->struct_id;
1840 : 0 : return f;
1841 : : }
1842 : :
1843 : : default:
1844 : : return NULL;
1845 : : }
1846 : : }
1847 : :
1848 : : /*
1849 : : * rx.
1850 : : */
1851 : : static int
1852 : 0 : instr_rx_translate(struct rte_swx_pipeline *p,
1853 : : struct action *action,
1854 : : char **tokens,
1855 : : int n_tokens,
1856 : : struct instruction *instr,
1857 : : struct instruction_data *data __rte_unused)
1858 : : {
1859 : : struct field *f;
1860 : :
1861 [ # # ]: 0 : CHECK(!action, EINVAL);
1862 [ # # ]: 0 : CHECK(n_tokens == 2, EINVAL);
1863 : :
1864 : 0 : f = metadata_field_parse(p, tokens[1]);
1865 [ # # ]: 0 : CHECK(f, EINVAL);
1866 [ # # ]: 0 : CHECK(f->n_bits <= 64, EINVAL);
1867 : :
1868 : 0 : instr->type = INSTR_RX;
1869 : 0 : instr->io.io.offset = f->offset / 8;
1870 : 0 : instr->io.io.n_bits = f->n_bits;
1871 : 0 : return 0;
1872 : : }
1873 : :
1874 : : /*
1875 : : * tx.
1876 : : */
1877 : : static int
1878 : 0 : instr_tx_translate(struct rte_swx_pipeline *p,
1879 : : struct action *action __rte_unused,
1880 : : char **tokens,
1881 : : int n_tokens,
1882 : : struct instruction *instr,
1883 : : struct instruction_data *data __rte_unused)
1884 : : {
1885 : 0 : char *port = tokens[1];
1886 : : struct field *f;
1887 : : uint32_t port_val;
1888 : :
1889 [ # # ]: 0 : CHECK(n_tokens == 2, EINVAL);
1890 : :
1891 : 0 : f = metadata_field_parse(p, port);
1892 [ # # ]: 0 : if (f) {
1893 [ # # ]: 0 : CHECK(f->n_bits <= 64, EINVAL);
1894 : 0 : instr->type = INSTR_TX;
1895 : 0 : instr->io.io.offset = f->offset / 8;
1896 : 0 : instr->io.io.n_bits = f->n_bits;
1897 : 0 : return 0;
1898 : : }
1899 : :
1900 : : /* TX_I. */
1901 : 0 : port_val = strtoul(port, &port, 0);
1902 [ # # ]: 0 : CHECK(!port[0], EINVAL);
1903 : :
1904 : 0 : instr->type = INSTR_TX_I;
1905 : 0 : instr->io.io.val = port_val;
1906 : 0 : return 0;
1907 : : }
1908 : :
1909 : : static int
1910 : : instr_drop_translate(struct rte_swx_pipeline *p __rte_unused,
1911 : : struct action *action __rte_unused,
1912 : : char **tokens __rte_unused,
1913 : : int n_tokens,
1914 : : struct instruction *instr,
1915 : : struct instruction_data *data __rte_unused)
1916 : : {
1917 : 0 : CHECK(n_tokens == 1, EINVAL);
1918 : :
1919 : : /* DROP. */
1920 : 0 : instr->type = INSTR_DROP;
1921 : 0 : return 0;
1922 : : }
1923 : :
1924 : : static inline void
1925 : 0 : instr_tx_exec(struct rte_swx_pipeline *p)
1926 : : {
1927 : 0 : struct thread *t = &p->threads[p->thread_id];
1928 : 0 : struct instruction *ip = t->ip;
1929 : :
1930 : 0 : __instr_tx_exec(p, t, ip);
1931 : :
1932 : : /* Thread. */
1933 : : thread_ip_reset(p, t);
1934 : 0 : instr_rx_exec(p);
1935 : 0 : }
1936 : :
1937 : : static inline void
1938 : 0 : instr_tx_i_exec(struct rte_swx_pipeline *p)
1939 : : {
1940 : 0 : struct thread *t = &p->threads[p->thread_id];
1941 : 0 : struct instruction *ip = t->ip;
1942 : :
1943 : 0 : __instr_tx_i_exec(p, t, ip);
1944 : :
1945 : : /* Thread. */
1946 : : thread_ip_reset(p, t);
1947 : 0 : instr_rx_exec(p);
1948 : 0 : }
1949 : :
1950 : : static inline void
1951 : 0 : instr_drop_exec(struct rte_swx_pipeline *p)
1952 : : {
1953 : 0 : struct thread *t = &p->threads[p->thread_id];
1954 : 0 : struct instruction *ip = t->ip;
1955 : :
1956 : 0 : __instr_drop_exec(p, t, ip);
1957 : :
1958 : : /* Thread. */
1959 : : thread_ip_reset(p, t);
1960 : 0 : instr_rx_exec(p);
1961 : 0 : }
1962 : :
1963 : : /*
1964 : : * mirror.
1965 : : */
1966 : : static int
1967 : 0 : instr_mirror_translate(struct rte_swx_pipeline *p,
1968 : : struct action *action,
1969 : : char **tokens,
1970 : : int n_tokens,
1971 : : struct instruction *instr,
1972 : : struct instruction_data *data __rte_unused)
1973 : : {
1974 : 0 : char *dst = tokens[1], *src = tokens[2];
1975 : : struct field *fdst, *fsrc;
1976 : 0 : uint32_t dst_struct_id = 0, src_struct_id = 0;
1977 : :
1978 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
1979 : :
1980 : 0 : fdst = struct_field_parse(p, action, dst, &dst_struct_id);
1981 [ # # ]: 0 : CHECK(fdst, EINVAL);
1982 [ # # ]: 0 : CHECK(dst[0] != 'h', EINVAL);
1983 [ # # # # ]: 0 : CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
1984 : :
1985 : 0 : fsrc = struct_field_parse(p, action, src, &src_struct_id);
1986 [ # # ]: 0 : CHECK(fsrc, EINVAL);
1987 [ # # ]: 0 : CHECK(src[0] != 'h', EINVAL);
1988 [ # # # # ]: 0 : CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
1989 : :
1990 : 0 : instr->type = INSTR_MIRROR;
1991 : 0 : instr->mirror.dst.struct_id = (uint8_t)dst_struct_id;
1992 : 0 : instr->mirror.dst.n_bits = fdst->n_bits;
1993 : 0 : instr->mirror.dst.offset = fdst->offset / 8;
1994 : 0 : instr->mirror.src.struct_id = (uint8_t)src_struct_id;
1995 : 0 : instr->mirror.src.n_bits = fsrc->n_bits;
1996 : 0 : instr->mirror.src.offset = fsrc->offset / 8;
1997 : :
1998 : 0 : return 0;
1999 : : }
2000 : :
2001 : : static inline void
2002 : 0 : instr_mirror_exec(struct rte_swx_pipeline *p)
2003 : : {
2004 : 0 : struct thread *t = &p->threads[p->thread_id];
2005 : 0 : struct instruction *ip = t->ip;
2006 : :
2007 : 0 : __instr_mirror_exec(p, t, ip);
2008 : :
2009 : : /* Thread. */
2010 : : thread_ip_inc(p);
2011 : 0 : }
2012 : :
2013 : : /*
2014 : : * recirculate.
2015 : : */
2016 : : static int
2017 : : instr_recirculate_translate(struct rte_swx_pipeline *p __rte_unused,
2018 : : struct action *action __rte_unused,
2019 : : char **tokens __rte_unused,
2020 : : int n_tokens,
2021 : : struct instruction *instr,
2022 : : struct instruction_data *data __rte_unused)
2023 : : {
2024 : 0 : CHECK(n_tokens == 1, EINVAL);
2025 : :
2026 : 0 : instr->type = INSTR_RECIRCULATE;
2027 : 0 : return 0;
2028 : : }
2029 : :
2030 : : static int
2031 : : instr_recircid_translate(struct rte_swx_pipeline *p,
2032 : : struct action *action __rte_unused,
2033 : : char **tokens,
2034 : : int n_tokens,
2035 : : struct instruction *instr,
2036 : : struct instruction_data *data __rte_unused)
2037 : : {
2038 : : struct field *f;
2039 : :
2040 : 0 : CHECK(n_tokens == 2, EINVAL);
2041 : :
2042 : 0 : f = metadata_field_parse(p, tokens[1]);
2043 [ # # ]: 0 : CHECK(f, EINVAL);
2044 [ # # ]: 0 : CHECK(f->n_bits <= 64, EINVAL);
2045 : :
2046 : 0 : instr->type = INSTR_RECIRCID;
2047 : 0 : instr->io.io.offset = f->offset / 8;
2048 : 0 : instr->io.io.n_bits = f->n_bits;
2049 : 0 : return 0;
2050 : : }
2051 : :
2052 : : static inline void
2053 : 0 : instr_recirculate_exec(struct rte_swx_pipeline *p)
2054 : : {
2055 : 0 : struct thread *t = &p->threads[p->thread_id];
2056 : 0 : struct instruction *ip = t->ip;
2057 : :
2058 : : __instr_recirculate_exec(p, t, ip);
2059 : :
2060 : : /* Thread. */
2061 : : thread_ip_inc(p);
2062 : 0 : }
2063 : :
2064 : : static inline void
2065 : 0 : instr_recircid_exec(struct rte_swx_pipeline *p)
2066 : : {
2067 : 0 : struct thread *t = &p->threads[p->thread_id];
2068 : 0 : struct instruction *ip = t->ip;
2069 : :
2070 : : __instr_recircid_exec(p, t, ip);
2071 : :
2072 : : /* Thread. */
2073 : : thread_ip_inc(p);
2074 : 0 : }
2075 : :
2076 : : /*
2077 : : * extract.
2078 : : */
2079 : : static int
2080 : 0 : instr_hdr_extract_translate(struct rte_swx_pipeline *p,
2081 : : struct action *action,
2082 : : char **tokens,
2083 : : int n_tokens,
2084 : : struct instruction *instr,
2085 : : struct instruction_data *data __rte_unused)
2086 : : {
2087 : : struct header *h;
2088 : :
2089 [ # # ]: 0 : CHECK(!action, EINVAL);
2090 [ # # ]: 0 : CHECK((n_tokens == 2) || (n_tokens == 3), EINVAL);
2091 : :
2092 : 0 : h = header_parse(p, tokens[1]);
2093 [ # # ]: 0 : CHECK(h, EINVAL);
2094 : :
2095 [ # # ]: 0 : if (n_tokens == 2) {
2096 [ # # ]: 0 : CHECK(!h->st->var_size, EINVAL);
2097 : :
2098 : 0 : instr->type = INSTR_HDR_EXTRACT;
2099 : 0 : instr->io.hdr.header_id[0] = h->id;
2100 : 0 : instr->io.hdr.struct_id[0] = h->struct_id;
2101 : 0 : instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
2102 : : } else {
2103 : : struct field *mf;
2104 : :
2105 [ # # ]: 0 : CHECK(h->st->var_size, EINVAL);
2106 : :
2107 : 0 : mf = metadata_field_parse(p, tokens[2]);
2108 [ # # ]: 0 : CHECK(mf, EINVAL);
2109 [ # # ]: 0 : CHECK(mf->n_bits <= 64, EINVAL);
2110 : :
2111 : 0 : instr->type = INSTR_HDR_EXTRACT_M;
2112 : 0 : instr->io.io.offset = mf->offset / 8;
2113 : 0 : instr->io.io.n_bits = mf->n_bits;
2114 : 0 : instr->io.hdr.header_id[0] = h->id;
2115 : 0 : instr->io.hdr.struct_id[0] = h->struct_id;
2116 : 0 : instr->io.hdr.n_bytes[0] = h->st->n_bits_min / 8;
2117 : : }
2118 : :
2119 : : return 0;
2120 : : }
2121 : :
2122 : : static int
2123 : 0 : instr_hdr_lookahead_translate(struct rte_swx_pipeline *p,
2124 : : struct action *action,
2125 : : char **tokens,
2126 : : int n_tokens,
2127 : : struct instruction *instr,
2128 : : struct instruction_data *data __rte_unused)
2129 : : {
2130 : : struct header *h;
2131 : :
2132 [ # # ]: 0 : CHECK(!action, EINVAL);
2133 [ # # ]: 0 : CHECK(n_tokens == 2, EINVAL);
2134 : :
2135 : 0 : h = header_parse(p, tokens[1]);
2136 [ # # ]: 0 : CHECK(h, EINVAL);
2137 [ # # ]: 0 : CHECK(!h->st->var_size, EINVAL);
2138 : :
2139 : 0 : instr->type = INSTR_HDR_LOOKAHEAD;
2140 : 0 : instr->io.hdr.header_id[0] = h->id;
2141 : 0 : instr->io.hdr.struct_id[0] = h->struct_id;
2142 : 0 : instr->io.hdr.n_bytes[0] = 0; /* Unused. */
2143 : :
2144 : 0 : return 0;
2145 : : }
2146 : :
2147 : : static inline void
2148 : 0 : instr_hdr_extract_exec(struct rte_swx_pipeline *p)
2149 : : {
2150 : 0 : struct thread *t = &p->threads[p->thread_id];
2151 : 0 : struct instruction *ip = t->ip;
2152 : :
2153 : : __instr_hdr_extract_exec(p, t, ip);
2154 : :
2155 : : /* Thread. */
2156 : : thread_ip_inc(p);
2157 : 0 : }
2158 : :
2159 : : static inline void
2160 : 0 : instr_hdr_extract2_exec(struct rte_swx_pipeline *p)
2161 : : {
2162 : 0 : struct thread *t = &p->threads[p->thread_id];
2163 : 0 : struct instruction *ip = t->ip;
2164 : :
2165 : : __instr_hdr_extract2_exec(p, t, ip);
2166 : :
2167 : : /* Thread. */
2168 : : thread_ip_inc(p);
2169 : 0 : }
2170 : :
2171 : : static inline void
2172 : 0 : instr_hdr_extract3_exec(struct rte_swx_pipeline *p)
2173 : : {
2174 : 0 : struct thread *t = &p->threads[p->thread_id];
2175 : 0 : struct instruction *ip = t->ip;
2176 : :
2177 : : __instr_hdr_extract3_exec(p, t, ip);
2178 : :
2179 : : /* Thread. */
2180 : : thread_ip_inc(p);
2181 : 0 : }
2182 : :
2183 : : static inline void
2184 : 0 : instr_hdr_extract4_exec(struct rte_swx_pipeline *p)
2185 : : {
2186 : 0 : struct thread *t = &p->threads[p->thread_id];
2187 : 0 : struct instruction *ip = t->ip;
2188 : :
2189 : : __instr_hdr_extract4_exec(p, t, ip);
2190 : :
2191 : : /* Thread. */
2192 : : thread_ip_inc(p);
2193 : 0 : }
2194 : :
2195 : : static inline void
2196 : 0 : instr_hdr_extract5_exec(struct rte_swx_pipeline *p)
2197 : : {
2198 : 0 : struct thread *t = &p->threads[p->thread_id];
2199 : 0 : struct instruction *ip = t->ip;
2200 : :
2201 : : __instr_hdr_extract5_exec(p, t, ip);
2202 : :
2203 : : /* Thread. */
2204 : : thread_ip_inc(p);
2205 : 0 : }
2206 : :
2207 : : static inline void
2208 : 0 : instr_hdr_extract6_exec(struct rte_swx_pipeline *p)
2209 : : {
2210 : 0 : struct thread *t = &p->threads[p->thread_id];
2211 : 0 : struct instruction *ip = t->ip;
2212 : :
2213 : : __instr_hdr_extract6_exec(p, t, ip);
2214 : :
2215 : : /* Thread. */
2216 : : thread_ip_inc(p);
2217 : 0 : }
2218 : :
2219 : : static inline void
2220 : 0 : instr_hdr_extract7_exec(struct rte_swx_pipeline *p)
2221 : : {
2222 : 0 : struct thread *t = &p->threads[p->thread_id];
2223 : 0 : struct instruction *ip = t->ip;
2224 : :
2225 : : __instr_hdr_extract7_exec(p, t, ip);
2226 : :
2227 : : /* Thread. */
2228 : : thread_ip_inc(p);
2229 : 0 : }
2230 : :
2231 : : static inline void
2232 : 0 : instr_hdr_extract8_exec(struct rte_swx_pipeline *p)
2233 : : {
2234 : 0 : struct thread *t = &p->threads[p->thread_id];
2235 : 0 : struct instruction *ip = t->ip;
2236 : :
2237 : : __instr_hdr_extract8_exec(p, t, ip);
2238 : :
2239 : : /* Thread. */
2240 : : thread_ip_inc(p);
2241 : 0 : }
2242 : :
2243 : : static inline void
2244 : 0 : instr_hdr_extract_m_exec(struct rte_swx_pipeline *p)
2245 : : {
2246 : 0 : struct thread *t = &p->threads[p->thread_id];
2247 : 0 : struct instruction *ip = t->ip;
2248 : :
2249 : 0 : __instr_hdr_extract_m_exec(p, t, ip);
2250 : :
2251 : : /* Thread. */
2252 : : thread_ip_inc(p);
2253 : 0 : }
2254 : :
2255 : : static inline void
2256 : 0 : instr_hdr_lookahead_exec(struct rte_swx_pipeline *p)
2257 : : {
2258 : 0 : struct thread *t = &p->threads[p->thread_id];
2259 : 0 : struct instruction *ip = t->ip;
2260 : :
2261 : : __instr_hdr_lookahead_exec(p, t, ip);
2262 : :
2263 : : /* Thread. */
2264 : : thread_ip_inc(p);
2265 : 0 : }
2266 : :
2267 : : /*
2268 : : * emit.
2269 : : */
2270 : : static int
2271 : 0 : instr_hdr_emit_translate(struct rte_swx_pipeline *p,
2272 : : struct action *action __rte_unused,
2273 : : char **tokens,
2274 : : int n_tokens,
2275 : : struct instruction *instr,
2276 : : struct instruction_data *data __rte_unused)
2277 : : {
2278 : : struct header *h;
2279 : :
2280 [ # # ]: 0 : CHECK(n_tokens == 2, EINVAL);
2281 : :
2282 : 0 : h = header_parse(p, tokens[1]);
2283 [ # # ]: 0 : CHECK(h, EINVAL);
2284 : :
2285 : 0 : instr->type = INSTR_HDR_EMIT;
2286 : 0 : instr->io.hdr.header_id[0] = h->id;
2287 : 0 : instr->io.hdr.struct_id[0] = h->struct_id;
2288 : 0 : instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
2289 : 0 : return 0;
2290 : : }
2291 : :
2292 : : static inline void
2293 : 0 : instr_hdr_emit_exec(struct rte_swx_pipeline *p)
2294 : : {
2295 : 0 : struct thread *t = &p->threads[p->thread_id];
2296 : 0 : struct instruction *ip = t->ip;
2297 : :
2298 : : __instr_hdr_emit_exec(p, t, ip);
2299 : :
2300 : : /* Thread. */
2301 : : thread_ip_inc(p);
2302 : 0 : }
2303 : :
2304 : : static inline void
2305 : 0 : instr_hdr_emit_tx_exec(struct rte_swx_pipeline *p)
2306 : : {
2307 : 0 : struct thread *t = &p->threads[p->thread_id];
2308 : 0 : struct instruction *ip = t->ip;
2309 : :
2310 : 0 : __instr_hdr_emit_tx_exec(p, t, ip);
2311 : :
2312 : : /* Thread. */
2313 : : thread_ip_reset(p, t);
2314 : 0 : instr_rx_exec(p);
2315 : 0 : }
2316 : :
2317 : : static inline void
2318 : 0 : instr_hdr_emit2_tx_exec(struct rte_swx_pipeline *p)
2319 : : {
2320 : 0 : struct thread *t = &p->threads[p->thread_id];
2321 : 0 : struct instruction *ip = t->ip;
2322 : :
2323 : 0 : __instr_hdr_emit2_tx_exec(p, t, ip);
2324 : :
2325 : : /* Thread. */
2326 : : thread_ip_reset(p, t);
2327 : 0 : instr_rx_exec(p);
2328 : 0 : }
2329 : :
2330 : : static inline void
2331 : 0 : instr_hdr_emit3_tx_exec(struct rte_swx_pipeline *p)
2332 : : {
2333 : 0 : struct thread *t = &p->threads[p->thread_id];
2334 : 0 : struct instruction *ip = t->ip;
2335 : :
2336 : 0 : __instr_hdr_emit3_tx_exec(p, t, ip);
2337 : :
2338 : : /* Thread. */
2339 : : thread_ip_reset(p, t);
2340 : 0 : instr_rx_exec(p);
2341 : 0 : }
2342 : :
2343 : : static inline void
2344 : 0 : instr_hdr_emit4_tx_exec(struct rte_swx_pipeline *p)
2345 : : {
2346 : 0 : struct thread *t = &p->threads[p->thread_id];
2347 : 0 : struct instruction *ip = t->ip;
2348 : :
2349 : 0 : __instr_hdr_emit4_tx_exec(p, t, ip);
2350 : :
2351 : : /* Thread. */
2352 : : thread_ip_reset(p, t);
2353 : 0 : instr_rx_exec(p);
2354 : 0 : }
2355 : :
2356 : : static inline void
2357 : 0 : instr_hdr_emit5_tx_exec(struct rte_swx_pipeline *p)
2358 : : {
2359 : 0 : struct thread *t = &p->threads[p->thread_id];
2360 : 0 : struct instruction *ip = t->ip;
2361 : :
2362 : 0 : __instr_hdr_emit5_tx_exec(p, t, ip);
2363 : :
2364 : : /* Thread. */
2365 : : thread_ip_reset(p, t);
2366 : 0 : instr_rx_exec(p);
2367 : 0 : }
2368 : :
2369 : : static inline void
2370 : 0 : instr_hdr_emit6_tx_exec(struct rte_swx_pipeline *p)
2371 : : {
2372 : 0 : struct thread *t = &p->threads[p->thread_id];
2373 : 0 : struct instruction *ip = t->ip;
2374 : :
2375 : 0 : __instr_hdr_emit6_tx_exec(p, t, ip);
2376 : :
2377 : : /* Thread. */
2378 : : thread_ip_reset(p, t);
2379 : 0 : instr_rx_exec(p);
2380 : 0 : }
2381 : :
2382 : : static inline void
2383 : 0 : instr_hdr_emit7_tx_exec(struct rte_swx_pipeline *p)
2384 : : {
2385 : 0 : struct thread *t = &p->threads[p->thread_id];
2386 : 0 : struct instruction *ip = t->ip;
2387 : :
2388 : 0 : __instr_hdr_emit7_tx_exec(p, t, ip);
2389 : :
2390 : : /* Thread. */
2391 : : thread_ip_reset(p, t);
2392 : 0 : instr_rx_exec(p);
2393 : 0 : }
2394 : :
2395 : : static inline void
2396 : 0 : instr_hdr_emit8_tx_exec(struct rte_swx_pipeline *p)
2397 : : {
2398 : 0 : struct thread *t = &p->threads[p->thread_id];
2399 : 0 : struct instruction *ip = t->ip;
2400 : :
2401 : 0 : __instr_hdr_emit8_tx_exec(p, t, ip);
2402 : :
2403 : : /* Thread. */
2404 : : thread_ip_reset(p, t);
2405 : 0 : instr_rx_exec(p);
2406 : 0 : }
2407 : :
2408 : : /*
2409 : : * validate.
2410 : : */
2411 : : static int
2412 : : instr_hdr_validate_translate(struct rte_swx_pipeline *p,
2413 : : struct action *action __rte_unused,
2414 : : char **tokens,
2415 : : int n_tokens,
2416 : : struct instruction *instr,
2417 : : struct instruction_data *data __rte_unused)
2418 : : {
2419 : : struct header *h;
2420 : :
2421 : 0 : CHECK(n_tokens == 2, EINVAL);
2422 : :
2423 : 0 : h = header_parse(p, tokens[1]);
2424 [ # # ]: 0 : CHECK(h, EINVAL);
2425 : :
2426 : 0 : instr->type = INSTR_HDR_VALIDATE;
2427 : 0 : instr->valid.header_id = h->id;
2428 : 0 : instr->valid.struct_id = h->struct_id;
2429 : 0 : return 0;
2430 : : }
2431 : :
2432 : : static inline void
2433 : 0 : instr_hdr_validate_exec(struct rte_swx_pipeline *p)
2434 : : {
2435 : 0 : struct thread *t = &p->threads[p->thread_id];
2436 [ # # ]: 0 : struct instruction *ip = t->ip;
2437 : :
2438 : : __instr_hdr_validate_exec(p, t, ip);
2439 : :
2440 : : /* Thread. */
2441 : : thread_ip_inc(p);
2442 : 0 : }
2443 : :
2444 : : /*
2445 : : * invalidate.
2446 : : */
2447 : : static int
2448 : : instr_hdr_invalidate_translate(struct rte_swx_pipeline *p,
2449 : : struct action *action __rte_unused,
2450 : : char **tokens,
2451 : : int n_tokens,
2452 : : struct instruction *instr,
2453 : : struct instruction_data *data __rte_unused)
2454 : : {
2455 : : struct header *h;
2456 : :
2457 : 0 : CHECK(n_tokens == 2, EINVAL);
2458 : :
2459 : 0 : h = header_parse(p, tokens[1]);
2460 [ # # ]: 0 : CHECK(h, EINVAL);
2461 : :
2462 : 0 : instr->type = INSTR_HDR_INVALIDATE;
2463 : 0 : instr->valid.header_id = h->id;
2464 : 0 : return 0;
2465 : : }
2466 : :
2467 : : static inline void
2468 : 0 : instr_hdr_invalidate_exec(struct rte_swx_pipeline *p)
2469 : : {
2470 : 0 : struct thread *t = &p->threads[p->thread_id];
2471 : 0 : struct instruction *ip = t->ip;
2472 : :
2473 : : __instr_hdr_invalidate_exec(p, t, ip);
2474 : :
2475 : : /* Thread. */
2476 : : thread_ip_inc(p);
2477 : 0 : }
2478 : :
2479 : : /*
2480 : : * table.
2481 : : */
2482 : : static struct table *
2483 : : table_find(struct rte_swx_pipeline *p, const char *name);
2484 : :
2485 : : static struct selector *
2486 : : selector_find(struct rte_swx_pipeline *p, const char *name);
2487 : :
2488 : : static struct learner *
2489 : : learner_find(struct rte_swx_pipeline *p, const char *name);
2490 : :
2491 : : static int
2492 : 0 : instr_table_translate(struct rte_swx_pipeline *p,
2493 : : struct action *action,
2494 : : char **tokens,
2495 : : int n_tokens,
2496 : : struct instruction *instr,
2497 : : struct instruction_data *data __rte_unused)
2498 : : {
2499 : : struct table *t;
2500 : : struct selector *s;
2501 : : struct learner *l;
2502 : :
2503 [ # # ]: 0 : CHECK(!action, EINVAL);
2504 [ # # ]: 0 : CHECK(n_tokens == 2, EINVAL);
2505 : :
2506 : 0 : t = table_find(p, tokens[1]);
2507 [ # # ]: 0 : if (t) {
2508 : 0 : instr->type = INSTR_TABLE;
2509 : 0 : instr->table.table_id = t->id;
2510 : 0 : return 0;
2511 : : }
2512 : :
2513 : : s = selector_find(p, tokens[1]);
2514 [ # # ]: 0 : if (s) {
2515 : 0 : instr->type = INSTR_SELECTOR;
2516 : 0 : instr->table.table_id = s->id;
2517 : 0 : return 0;
2518 : : }
2519 : :
2520 : : l = learner_find(p, tokens[1]);
2521 [ # # ]: 0 : if (l) {
2522 : 0 : instr->type = INSTR_LEARNER;
2523 : 0 : instr->table.table_id = l->id;
2524 : 0 : return 0;
2525 : : }
2526 : :
2527 : : CHECK(0, EINVAL);
2528 : : }
2529 : :
2530 : : static inline void
2531 : 0 : instr_table_exec(struct rte_swx_pipeline *p)
2532 : : {
2533 : 0 : struct thread *t = &p->threads[p->thread_id];
2534 : 0 : struct instruction *ip = t->ip;
2535 : 0 : uint32_t table_id = ip->table.table_id;
2536 : 0 : struct rte_swx_table_state *ts = &t->table_state[table_id];
2537 : 0 : struct table_runtime *table = &t->tables[table_id];
2538 : 0 : struct table_statistics *stats = &p->table_stats[table_id];
2539 : : uint64_t action_id, n_pkts_hit, n_pkts_action;
2540 : : uint8_t *action_data;
2541 : : size_t entry_id;
2542 : : int done, hit;
2543 : :
2544 : : /* Table. */
2545 : 0 : done = table->func(ts->obj,
2546 : : table->mailbox,
2547 : : table->key,
2548 : : &action_id,
2549 : : &action_data,
2550 : : &entry_id,
2551 : : &hit);
2552 [ # # ]: 0 : if (!done) {
2553 : : /* Thread. */
2554 : : TRACE("[Thread %2u] table %u (not finalized)\n",
2555 : : p->thread_id,
2556 : : table_id);
2557 : :
2558 : : thread_yield(p);
2559 : 0 : return;
2560 : : }
2561 : :
2562 [ # # ]: 0 : action_id = hit ? action_id : ts->default_action_id;
2563 [ # # ]: 0 : action_data = hit ? action_data : ts->default_action_data;
2564 [ # # ]: 0 : entry_id = hit ? (1 + entry_id) : 0;
2565 : 0 : n_pkts_hit = stats->n_pkts_hit[hit];
2566 : 0 : n_pkts_action = stats->n_pkts_action[action_id];
2567 : :
2568 : : TRACE("[Thread %2u] table %u (%s, action %u)\n",
2569 : : p->thread_id,
2570 : : table_id,
2571 : : hit ? "hit" : "miss",
2572 : : (uint32_t)action_id);
2573 : :
2574 : 0 : t->action_id = action_id;
2575 : 0 : t->structs[0] = action_data;
2576 : 0 : t->entry_id = entry_id;
2577 : 0 : t->hit = hit;
2578 : 0 : stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2579 : 0 : stats->n_pkts_action[action_id] = n_pkts_action + 1;
2580 : :
2581 : : /* Thread. */
2582 : 0 : thread_ip_action_call(p, t, action_id);
2583 : : }
2584 : :
2585 : : static inline void
2586 : 0 : instr_table_af_exec(struct rte_swx_pipeline *p)
2587 : : {
2588 : 0 : struct thread *t = &p->threads[p->thread_id];
2589 : 0 : struct instruction *ip = t->ip;
2590 : 0 : uint32_t table_id = ip->table.table_id;
2591 : 0 : struct rte_swx_table_state *ts = &t->table_state[table_id];
2592 : 0 : struct table_runtime *table = &t->tables[table_id];
2593 : 0 : struct table_statistics *stats = &p->table_stats[table_id];
2594 : : uint64_t action_id, n_pkts_hit, n_pkts_action;
2595 : : uint8_t *action_data;
2596 : : size_t entry_id;
2597 : : action_func_t action_func;
2598 : : int done, hit;
2599 : :
2600 : : /* Table. */
2601 : 0 : done = table->func(ts->obj,
2602 : : table->mailbox,
2603 : : table->key,
2604 : : &action_id,
2605 : : &action_data,
2606 : : &entry_id,
2607 : : &hit);
2608 [ # # ]: 0 : if (!done) {
2609 : : /* Thread. */
2610 : : TRACE("[Thread %2u] table %u (not finalized)\n",
2611 : : p->thread_id,
2612 : : table_id);
2613 : :
2614 : : thread_yield(p);
2615 : 0 : return;
2616 : : }
2617 : :
2618 [ # # ]: 0 : action_id = hit ? action_id : ts->default_action_id;
2619 [ # # ]: 0 : action_data = hit ? action_data : ts->default_action_data;
2620 [ # # ]: 0 : entry_id = hit ? (1 + entry_id) : 0;
2621 : 0 : action_func = p->action_funcs[action_id];
2622 : 0 : n_pkts_hit = stats->n_pkts_hit[hit];
2623 : 0 : n_pkts_action = stats->n_pkts_action[action_id];
2624 : :
2625 : : TRACE("[Thread %2u] table %u (%s, action %u)\n",
2626 : : p->thread_id,
2627 : : table_id,
2628 : : hit ? "hit" : "miss",
2629 : : (uint32_t)action_id);
2630 : :
2631 : 0 : t->action_id = action_id;
2632 : 0 : t->structs[0] = action_data;
2633 : 0 : t->entry_id = entry_id;
2634 : 0 : t->hit = hit;
2635 : 0 : stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2636 : 0 : stats->n_pkts_action[action_id] = n_pkts_action + 1;
2637 : :
2638 : : /* Thread. */
2639 : : thread_ip_inc(p);
2640 : :
2641 : : /* Action. */
2642 : 0 : action_func(p);
2643 : : }
2644 : :
2645 : : static inline void
2646 : 0 : instr_selector_exec(struct rte_swx_pipeline *p)
2647 : : {
2648 : 0 : struct thread *t = &p->threads[p->thread_id];
2649 : 0 : struct instruction *ip = t->ip;
2650 : 0 : uint32_t selector_id = ip->table.table_id;
2651 : 0 : struct rte_swx_table_state *ts = &t->table_state[p->n_tables + selector_id];
2652 : 0 : struct selector_runtime *selector = &t->selectors[selector_id];
2653 : 0 : struct selector_statistics *stats = &p->selector_stats[selector_id];
2654 : 0 : uint64_t n_pkts = stats->n_pkts;
2655 : : int done;
2656 : :
2657 : : /* Table. */
2658 : 0 : done = rte_swx_table_selector_select(ts->obj,
2659 : : selector->mailbox,
2660 : : selector->group_id_buffer,
2661 : : selector->selector_buffer,
2662 : : selector->member_id_buffer);
2663 [ # # ]: 0 : if (!done) {
2664 : : /* Thread. */
2665 : : TRACE("[Thread %2u] selector %u (not finalized)\n",
2666 : : p->thread_id,
2667 : : selector_id);
2668 : :
2669 : : thread_yield(p);
2670 : 0 : return;
2671 : : }
2672 : :
2673 : :
2674 : : TRACE("[Thread %2u] selector %u\n",
2675 : : p->thread_id,
2676 : : selector_id);
2677 : :
2678 : 0 : stats->n_pkts = n_pkts + 1;
2679 : :
2680 : : /* Thread. */
2681 : : thread_ip_inc(p);
2682 : : }
2683 : :
2684 : : static inline void
2685 : 0 : instr_learner_exec(struct rte_swx_pipeline *p)
2686 : : {
2687 : 0 : struct thread *t = &p->threads[p->thread_id];
2688 : 0 : struct instruction *ip = t->ip;
2689 : 0 : uint32_t learner_id = ip->table.table_id;
2690 : 0 : struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2691 : 0 : p->n_selectors + learner_id];
2692 : 0 : struct learner_runtime *l = &t->learners[learner_id];
2693 : 0 : struct learner_statistics *stats = &p->learner_stats[learner_id];
2694 : : uint64_t action_id, n_pkts_hit, n_pkts_action, time;
2695 : : uint8_t *action_data;
2696 : : size_t entry_id;
2697 : : int done, hit;
2698 : :
2699 : : /* Table. */
2700 : : time = rte_get_tsc_cycles();
2701 : :
2702 : 0 : done = rte_swx_table_learner_lookup(ts->obj,
2703 : : l->mailbox,
2704 : : time,
2705 : : l->key,
2706 : : &action_id,
2707 : : &action_data,
2708 : : &entry_id,
2709 : : &hit);
2710 [ # # ]: 0 : if (!done) {
2711 : : /* Thread. */
2712 : : TRACE("[Thread %2u] learner %u (not finalized)\n",
2713 : : p->thread_id,
2714 : : learner_id);
2715 : :
2716 : : thread_yield(p);
2717 : 0 : return;
2718 : : }
2719 : :
2720 [ # # ]: 0 : action_id = hit ? action_id : ts->default_action_id;
2721 [ # # ]: 0 : action_data = hit ? action_data : ts->default_action_data;
2722 [ # # ]: 0 : entry_id = hit ? (1 + entry_id) : 0;
2723 : 0 : n_pkts_hit = stats->n_pkts_hit[hit];
2724 : 0 : n_pkts_action = stats->n_pkts_action[action_id];
2725 : :
2726 : : TRACE("[Thread %2u] learner %u (%s, action %u)\n",
2727 : : p->thread_id,
2728 : : learner_id,
2729 : : hit ? "hit" : "miss",
2730 : : (uint32_t)action_id);
2731 : :
2732 : 0 : t->action_id = action_id;
2733 : 0 : t->structs[0] = action_data;
2734 : 0 : t->entry_id = entry_id;
2735 : 0 : t->hit = hit;
2736 : 0 : t->learner_id = learner_id;
2737 : 0 : t->time = time;
2738 : 0 : stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2739 : 0 : stats->n_pkts_action[action_id] = n_pkts_action + 1;
2740 : :
2741 : : /* Thread. */
2742 : 0 : thread_ip_action_call(p, t, action_id);
2743 : : }
2744 : :
2745 : : static inline void
2746 : 0 : instr_learner_af_exec(struct rte_swx_pipeline *p)
2747 : : {
2748 : 0 : struct thread *t = &p->threads[p->thread_id];
2749 : 0 : struct instruction *ip = t->ip;
2750 : 0 : uint32_t learner_id = ip->table.table_id;
2751 : 0 : struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2752 : 0 : p->n_selectors + learner_id];
2753 : 0 : struct learner_runtime *l = &t->learners[learner_id];
2754 : 0 : struct learner_statistics *stats = &p->learner_stats[learner_id];
2755 : : uint64_t action_id, n_pkts_hit, n_pkts_action, time;
2756 : : uint8_t *action_data;
2757 : : size_t entry_id;
2758 : : action_func_t action_func;
2759 : : int done, hit;
2760 : :
2761 : : /* Table. */
2762 : : time = rte_get_tsc_cycles();
2763 : :
2764 : 0 : done = rte_swx_table_learner_lookup(ts->obj,
2765 : : l->mailbox,
2766 : : time,
2767 : : l->key,
2768 : : &action_id,
2769 : : &action_data,
2770 : : &entry_id,
2771 : : &hit);
2772 [ # # ]: 0 : if (!done) {
2773 : : /* Thread. */
2774 : : TRACE("[Thread %2u] learner %u (not finalized)\n",
2775 : : p->thread_id,
2776 : : learner_id);
2777 : :
2778 : : thread_yield(p);
2779 : 0 : return;
2780 : : }
2781 : :
2782 [ # # ]: 0 : action_id = hit ? action_id : ts->default_action_id;
2783 [ # # ]: 0 : action_data = hit ? action_data : ts->default_action_data;
2784 [ # # ]: 0 : entry_id = hit ? (1 + entry_id) : 0;
2785 : 0 : action_func = p->action_funcs[action_id];
2786 : 0 : n_pkts_hit = stats->n_pkts_hit[hit];
2787 : 0 : n_pkts_action = stats->n_pkts_action[action_id];
2788 : :
2789 : : TRACE("[Thread %2u] learner %u (%s, action %u)\n",
2790 : : p->thread_id,
2791 : : learner_id,
2792 : : hit ? "hit" : "miss",
2793 : : (uint32_t)action_id);
2794 : :
2795 : 0 : t->action_id = action_id;
2796 : 0 : t->structs[0] = action_data;
2797 : 0 : t->entry_id = entry_id;
2798 : 0 : t->hit = hit;
2799 : 0 : t->learner_id = learner_id;
2800 : 0 : t->time = time;
2801 : 0 : stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2802 : 0 : stats->n_pkts_action[action_id] = n_pkts_action + 1;
2803 : :
2804 : : /* Thread. */
2805 : : thread_ip_inc(p);
2806 : :
2807 : : /* Action */
2808 : 0 : action_func(p);
2809 : : }
2810 : :
2811 : : /*
2812 : : * learn.
2813 : : */
2814 : : static struct action *
2815 : : action_find(struct rte_swx_pipeline *p, const char *name);
2816 : :
2817 : : static int
2818 : : action_has_nbo_args(struct action *a);
2819 : :
2820 : : static int
2821 : : learner_action_args_check(struct rte_swx_pipeline *p, struct action *a, const char *mf_name);
2822 : :
2823 : : static int
2824 : 0 : instr_learn_translate(struct rte_swx_pipeline *p,
2825 : : struct action *action,
2826 : : char **tokens,
2827 : : int n_tokens,
2828 : : struct instruction *instr,
2829 : : struct instruction_data *data __rte_unused)
2830 : : {
2831 : : struct action *a;
2832 : : struct field *mf_first_arg = NULL, *mf_timeout_id = NULL;
2833 : : const char *mf_first_arg_name, *mf_timeout_id_name;
2834 : :
2835 [ # # ]: 0 : CHECK(action, EINVAL);
2836 [ # # ]: 0 : CHECK((n_tokens == 3) || (n_tokens == 4), EINVAL);
2837 : :
2838 : : /* Action. */
2839 : 0 : a = action_find(p, tokens[1]);
2840 [ # # ]: 0 : CHECK(a, EINVAL);
2841 [ # # ]: 0 : CHECK(!action_has_nbo_args(a), EINVAL);
2842 : :
2843 : : /* Action first argument. */
2844 [ # # ]: 0 : mf_first_arg_name = (n_tokens == 4) ? tokens[2] : NULL;
2845 [ # # ]: 0 : CHECK(!learner_action_args_check(p, a, mf_first_arg_name), EINVAL);
2846 : :
2847 [ # # ]: 0 : if (mf_first_arg_name) {
2848 : 0 : mf_first_arg = metadata_field_parse(p, mf_first_arg_name);
2849 [ # # ]: 0 : CHECK(mf_first_arg, EINVAL);
2850 [ # # ]: 0 : CHECK(mf_first_arg->n_bits <= 64, EINVAL);
2851 : : }
2852 : :
2853 : : /* Timeout ID. */
2854 [ # # ]: 0 : mf_timeout_id_name = (n_tokens == 4) ? tokens[3] : tokens[2];
2855 [ # # # # : 0 : CHECK_NAME(mf_timeout_id_name, EINVAL);
# # ]
2856 : 0 : mf_timeout_id = metadata_field_parse(p, mf_timeout_id_name);
2857 [ # # ]: 0 : CHECK(mf_timeout_id, EINVAL);
2858 [ # # ]: 0 : CHECK(mf_timeout_id->n_bits <= 64, EINVAL);
2859 : :
2860 : : /* Instruction. */
2861 : 0 : instr->type = INSTR_LEARNER_LEARN;
2862 : 0 : instr->learn.action_id = a->id;
2863 [ # # ]: 0 : instr->learn.mf_first_arg_offset = mf_first_arg ? (mf_first_arg->offset / 8) : 0;
2864 : 0 : instr->learn.mf_timeout_id_offset = mf_timeout_id->offset / 8;
2865 : 0 : instr->learn.mf_timeout_id_n_bits = mf_timeout_id->n_bits;
2866 : :
2867 : 0 : return 0;
2868 : : }
2869 : :
2870 : : static inline void
2871 : 0 : instr_learn_exec(struct rte_swx_pipeline *p)
2872 : : {
2873 : 0 : struct thread *t = &p->threads[p->thread_id];
2874 : 0 : struct instruction *ip = t->ip;
2875 : :
2876 : 0 : __instr_learn_exec(p, t, ip);
2877 : :
2878 : : /* Thread. */
2879 : : thread_ip_inc(p);
2880 : 0 : }
2881 : :
2882 : : /*
2883 : : * rearm.
2884 : : */
2885 : : static int
2886 : 0 : instr_rearm_translate(struct rte_swx_pipeline *p,
2887 : : struct action *action,
2888 : : char **tokens,
2889 : : int n_tokens,
2890 : : struct instruction *instr,
2891 : : struct instruction_data *data __rte_unused)
2892 : : {
2893 : : struct field *mf_timeout_id;
2894 : : const char *mf_timeout_id_name;
2895 : :
2896 [ # # ]: 0 : CHECK(action, EINVAL);
2897 [ # # ]: 0 : CHECK((n_tokens == 1) || (n_tokens == 2), EINVAL);
2898 : :
2899 : : /* INSTR_LEARNER_REARM. */
2900 [ # # ]: 0 : if (n_tokens == 1) {
2901 : 0 : instr->type = INSTR_LEARNER_REARM;
2902 : 0 : return 0;
2903 : : }
2904 : :
2905 : : /* INSTR_LEARNER_REARM_NEW. */
2906 : 0 : mf_timeout_id_name = tokens[1];
2907 [ # # # # : 0 : CHECK_NAME(mf_timeout_id_name, EINVAL);
# # ]
2908 : 0 : mf_timeout_id = metadata_field_parse(p, mf_timeout_id_name);
2909 [ # # ]: 0 : CHECK(mf_timeout_id, EINVAL);
2910 [ # # ]: 0 : CHECK(mf_timeout_id->n_bits <= 64, EINVAL);
2911 : :
2912 : 0 : instr->type = INSTR_LEARNER_REARM_NEW;
2913 : 0 : instr->learn.mf_timeout_id_offset = mf_timeout_id->offset / 8;
2914 : 0 : instr->learn.mf_timeout_id_n_bits = mf_timeout_id->n_bits;
2915 : :
2916 : 0 : return 0;
2917 : : }
2918 : :
2919 : : static inline void
2920 : 0 : instr_rearm_exec(struct rte_swx_pipeline *p)
2921 : : {
2922 : 0 : struct thread *t = &p->threads[p->thread_id];
2923 : 0 : struct instruction *ip = t->ip;
2924 : :
2925 : 0 : __instr_rearm_exec(p, t, ip);
2926 : :
2927 : : /* Thread. */
2928 : : thread_ip_inc(p);
2929 : 0 : }
2930 : :
2931 : : static inline void
2932 : 0 : instr_rearm_new_exec(struct rte_swx_pipeline *p)
2933 : : {
2934 : 0 : struct thread *t = &p->threads[p->thread_id];
2935 : 0 : struct instruction *ip = t->ip;
2936 : :
2937 : 0 : __instr_rearm_new_exec(p, t, ip);
2938 : :
2939 : : /* Thread. */
2940 : : thread_ip_inc(p);
2941 : 0 : }
2942 : :
2943 : : /*
2944 : : * forget.
2945 : : */
2946 : : static int
2947 : : instr_forget_translate(struct rte_swx_pipeline *p __rte_unused,
2948 : : struct action *action,
2949 : : char **tokens __rte_unused,
2950 : : int n_tokens,
2951 : : struct instruction *instr,
2952 : : struct instruction_data *data __rte_unused)
2953 : : {
2954 : 0 : CHECK(action, EINVAL);
2955 [ # # ]: 0 : CHECK(n_tokens == 1, EINVAL);
2956 : :
2957 : 0 : instr->type = INSTR_LEARNER_FORGET;
2958 : :
2959 : 0 : return 0;
2960 : : }
2961 : :
2962 : : static inline void
2963 : 0 : instr_forget_exec(struct rte_swx_pipeline *p)
2964 : : {
2965 : 0 : struct thread *t = &p->threads[p->thread_id];
2966 : 0 : struct instruction *ip = t->ip;
2967 : :
2968 : 0 : __instr_forget_exec(p, t, ip);
2969 : :
2970 : : /* Thread. */
2971 : : thread_ip_inc(p);
2972 : 0 : }
2973 : :
2974 : : /*
2975 : : * entryid.
2976 : : */
2977 : : static int
2978 : : instr_entryid_translate(struct rte_swx_pipeline *p,
2979 : : struct action *action __rte_unused,
2980 : : char **tokens,
2981 : : int n_tokens,
2982 : : struct instruction *instr,
2983 : : struct instruction_data *data __rte_unused)
2984 : : {
2985 : : struct field *f;
2986 : :
2987 : 0 : CHECK(n_tokens == 2, EINVAL);
2988 : :
2989 : 0 : f = metadata_field_parse(p, tokens[1]);
2990 [ # # ]: 0 : CHECK(f, EINVAL);
2991 [ # # ]: 0 : CHECK(f->n_bits <= 64, EINVAL);
2992 : :
2993 : 0 : instr->type = INSTR_ENTRYID;
2994 : 0 : instr->mov.dst.n_bits = f->n_bits;
2995 : 0 : instr->mov.dst.offset = f->offset / 8;
2996 : 0 : return 0;
2997 : : }
2998 : :
2999 : : static inline void
3000 : 0 : instr_entryid_exec(struct rte_swx_pipeline *p)
3001 : : {
3002 : 0 : struct thread *t = &p->threads[p->thread_id];
3003 : 0 : struct instruction *ip = t->ip;
3004 : :
3005 : : __instr_entryid_exec(p, t, ip);
3006 : :
3007 : : /* Thread. */
3008 : : thread_ip_inc(p);
3009 : 0 : }
3010 : :
3011 : : /*
3012 : : * extern.
3013 : : */
3014 : : static int
3015 : 0 : instr_extern_translate(struct rte_swx_pipeline *p,
3016 : : struct action *action __rte_unused,
3017 : : char **tokens,
3018 : : int n_tokens,
3019 : : struct instruction *instr,
3020 : : struct instruction_data *data __rte_unused)
3021 : : {
3022 : 0 : char *token = tokens[1];
3023 : :
3024 [ # # ]: 0 : CHECK(n_tokens == 2, EINVAL);
3025 : :
3026 [ # # ]: 0 : if (token[0] == 'e') {
3027 : : struct extern_obj *obj;
3028 : : struct extern_type_member_func *func;
3029 : :
3030 : 0 : func = extern_obj_member_func_parse(p, token, &obj);
3031 [ # # ]: 0 : CHECK(func, EINVAL);
3032 : :
3033 : 0 : instr->type = INSTR_EXTERN_OBJ;
3034 : 0 : instr->ext_obj.ext_obj_id = obj->id;
3035 : 0 : instr->ext_obj.func_id = func->id;
3036 : :
3037 : 0 : return 0;
3038 : : }
3039 : :
3040 [ # # ]: 0 : if (token[0] == 'f') {
3041 : : struct extern_func *func;
3042 : :
3043 : 0 : func = extern_func_parse(p, token);
3044 [ # # ]: 0 : CHECK(func, EINVAL);
3045 : :
3046 : 0 : instr->type = INSTR_EXTERN_FUNC;
3047 : 0 : instr->ext_func.ext_func_id = func->id;
3048 : :
3049 : 0 : return 0;
3050 : : }
3051 : :
3052 : : CHECK(0, EINVAL);
3053 : : }
3054 : :
3055 : : static inline void
3056 : 0 : instr_extern_obj_exec(struct rte_swx_pipeline *p)
3057 : : {
3058 : 0 : struct thread *t = &p->threads[p->thread_id];
3059 : 0 : struct instruction *ip = t->ip;
3060 : : uint32_t done;
3061 : :
3062 : : /* Extern object member function execute. */
3063 : : done = __instr_extern_obj_exec(p, t, ip);
3064 : :
3065 : : /* Thread. */
3066 : : thread_ip_inc_cond(t, done);
3067 : 0 : thread_yield_cond(p, done ^ 1);
3068 : 0 : }
3069 : :
3070 : : static inline void
3071 : 0 : instr_extern_func_exec(struct rte_swx_pipeline *p)
3072 : : {
3073 : 0 : struct thread *t = &p->threads[p->thread_id];
3074 : 0 : struct instruction *ip = t->ip;
3075 : : uint32_t done;
3076 : :
3077 : : /* Extern function execute. */
3078 : : done = __instr_extern_func_exec(p, t, ip);
3079 : :
3080 : : /* Thread. */
3081 : : thread_ip_inc_cond(t, done);
3082 : 0 : thread_yield_cond(p, done ^ 1);
3083 : 0 : }
3084 : :
3085 : : /*
3086 : : * hash.
3087 : : */
3088 : : static int
3089 : 0 : instr_hash_translate(struct rte_swx_pipeline *p,
3090 : : struct action *action,
3091 : : char **tokens,
3092 : : int n_tokens,
3093 : : struct instruction *instr,
3094 : : struct instruction_data *data __rte_unused)
3095 : : {
3096 : : struct hash_func *func;
3097 : : struct field *dst, *src_first, *src_last;
3098 : 0 : uint32_t src_struct_id_first = 0, src_struct_id_last = 0;
3099 : :
3100 [ # # ]: 0 : CHECK(n_tokens == 5, EINVAL);
3101 : :
3102 : 0 : func = hash_func_find(p, tokens[1]);
3103 [ # # ]: 0 : CHECK(func, EINVAL);
3104 : :
3105 : 0 : dst = metadata_field_parse(p, tokens[2]);
3106 [ # # ]: 0 : CHECK(dst, EINVAL);
3107 [ # # ]: 0 : CHECK(dst->n_bits <= 64, EINVAL);
3108 : :
3109 : 0 : src_first = struct_field_parse(p, action, tokens[3], &src_struct_id_first);
3110 [ # # ]: 0 : CHECK(src_first, EINVAL);
3111 : :
3112 : 0 : src_last = struct_field_parse(p, action, tokens[4], &src_struct_id_last);
3113 [ # # ]: 0 : CHECK(src_last, EINVAL);
3114 [ # # ]: 0 : CHECK(!src_last->var_size, EINVAL);
3115 [ # # ]: 0 : CHECK(src_struct_id_first == src_struct_id_last, EINVAL);
3116 : :
3117 : 0 : instr->type = INSTR_HASH_FUNC;
3118 : 0 : instr->hash_func.hash_func_id = (uint8_t)func->id;
3119 : 0 : instr->hash_func.dst.offset = (uint8_t)dst->offset / 8;
3120 : 0 : instr->hash_func.dst.n_bits = (uint8_t)dst->n_bits;
3121 : 0 : instr->hash_func.src.struct_id = (uint8_t)src_struct_id_first;
3122 : 0 : instr->hash_func.src.offset = (uint16_t)src_first->offset / 8;
3123 : 0 : instr->hash_func.src.n_bytes = (uint16_t)((src_last->offset + src_last->n_bits -
3124 : 0 : src_first->offset) / 8);
3125 : :
3126 : 0 : return 0;
3127 : : }
3128 : :
3129 : : static inline void
3130 : 0 : instr_hash_func_exec(struct rte_swx_pipeline *p)
3131 : : {
3132 : 0 : struct thread *t = &p->threads[p->thread_id];
3133 : 0 : struct instruction *ip = t->ip;
3134 : :
3135 : : /* Extern function execute. */
3136 : 0 : __instr_hash_func_exec(p, t, ip);
3137 : :
3138 : : /* Thread. */
3139 : : thread_ip_inc(p);
3140 : 0 : }
3141 : :
3142 : : /*
3143 : : * rss.
3144 : : */
3145 : : static int
3146 : 0 : instr_rss_translate(struct rte_swx_pipeline *p,
3147 : : struct action *action,
3148 : : char **tokens,
3149 : : int n_tokens,
3150 : : struct instruction *instr,
3151 : : struct instruction_data *data __rte_unused)
3152 : : {
3153 : : struct rss *rss;
3154 : : struct field *dst, *src_first, *src_last;
3155 : 0 : uint32_t src_struct_id_first = 0, src_struct_id_last = 0;
3156 : :
3157 [ # # ]: 0 : CHECK(n_tokens == 5, EINVAL);
3158 : :
3159 : 0 : rss = rss_find(p, tokens[1]);
3160 [ # # ]: 0 : CHECK(rss, EINVAL);
3161 : :
3162 : 0 : dst = metadata_field_parse(p, tokens[2]);
3163 [ # # ]: 0 : CHECK(dst, EINVAL);
3164 [ # # ]: 0 : CHECK(dst->n_bits <= 64, EINVAL);
3165 : :
3166 : 0 : src_first = struct_field_parse(p, action, tokens[3], &src_struct_id_first);
3167 [ # # ]: 0 : CHECK(src_first, EINVAL);
3168 : :
3169 : 0 : src_last = struct_field_parse(p, action, tokens[4], &src_struct_id_last);
3170 [ # # ]: 0 : CHECK(src_last, EINVAL);
3171 [ # # ]: 0 : CHECK(!src_last->var_size, EINVAL);
3172 [ # # ]: 0 : CHECK(src_struct_id_first == src_struct_id_last, EINVAL);
3173 : :
3174 : 0 : instr->type = INSTR_RSS;
3175 : 0 : instr->rss.rss_obj_id = (uint8_t)rss->id;
3176 : 0 : instr->rss.dst.offset = (uint8_t)dst->offset / 8;
3177 : 0 : instr->rss.dst.n_bits = (uint8_t)dst->n_bits;
3178 : 0 : instr->rss.src.struct_id = (uint8_t)src_struct_id_first;
3179 : 0 : instr->rss.src.offset = (uint16_t)src_first->offset / 8;
3180 : 0 : instr->rss.src.n_bytes = (uint16_t)((src_last->offset + src_last->n_bits -
3181 : 0 : src_first->offset) / 8);
3182 : :
3183 : 0 : return 0;
3184 : : }
3185 : :
3186 : : static inline void
3187 : 0 : instr_rss_exec(struct rte_swx_pipeline *p)
3188 : : {
3189 : 0 : struct thread *t = &p->threads[p->thread_id];
3190 : 0 : struct instruction *ip = t->ip;
3191 : :
3192 : : /* Extern function execute. */
3193 : 0 : __instr_rss_exec(p, t, ip);
3194 : :
3195 : : /* Thread. */
3196 : : thread_ip_inc(p);
3197 : 0 : }
3198 : :
3199 : : /*
3200 : : * mov.
3201 : : */
3202 : : static int
3203 : 0 : instr_mov_translate(struct rte_swx_pipeline *p,
3204 : : struct action *action,
3205 : : char **tokens,
3206 : : int n_tokens,
3207 : : struct instruction *instr,
3208 : : struct instruction_data *data __rte_unused)
3209 : : {
3210 : 0 : char *dst = tokens[1], *src = tokens[2];
3211 : : struct field *fdst, *fsrc;
3212 : : uint64_t src_val;
3213 : 0 : uint32_t dst_struct_id = 0, src_struct_id = 0;
3214 : :
3215 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
3216 : :
3217 : 0 : fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3218 [ # # ]: 0 : CHECK(fdst, EINVAL);
3219 [ # # ]: 0 : CHECK(!fdst->var_size, EINVAL);
3220 : :
3221 : : /* MOV, MOV_MH, MOV_HM, MOV_HH, MOV16, MOVDMA. */
3222 : 0 : fsrc = struct_field_parse(p, action, src, &src_struct_id);
3223 [ # # ]: 0 : if (fsrc) {
3224 [ # # ]: 0 : CHECK(!fsrc->var_size, EINVAL);
3225 : :
3226 [ # # # # ]: 0 : if (fdst->n_bits <= 64 && fsrc->n_bits <= 64) {
3227 : 0 : instr->type = INSTR_MOV;
3228 [ # # # # ]: 0 : if (dst[0] != 'h' && src[0] == 'h')
3229 : 0 : instr->type = INSTR_MOV_MH;
3230 [ # # # # ]: 0 : if (dst[0] == 'h' && src[0] != 'h')
3231 : 0 : instr->type = INSTR_MOV_HM;
3232 [ # # # # ]: 0 : if (dst[0] == 'h' && src[0] == 'h')
3233 : 0 : instr->type = INSTR_MOV_HH;
3234 : : } else {
3235 : : /* The big fields (field with size > 64 bits) are always expected in NBO,
3236 : : * regardless of their type (H or MEFT). In case a big field is involved as
3237 : : * either dst or src, the other field must also be NBO.
3238 : : *
3239 : : * In case the dst field is big, the src field must be either a big field
3240 : : * (of the same or different size as dst) or a small H field. Similarly,
3241 : : * in case the src field is big, the dst field must be either a big field
3242 : : * (of the same or different size as src) or a small H field. Any other case
3243 : : * involving a big field as either dst or src is rejected.
3244 : : */
3245 [ # # # # ]: 0 : CHECK(fdst->n_bits > 64 || dst[0] == 'h', EINVAL);
3246 [ # # # # ]: 0 : CHECK(fsrc->n_bits > 64 || src[0] == 'h', EINVAL);
3247 : :
3248 : 0 : instr->type = INSTR_MOV_DMA;
3249 [ # # # # ]: 0 : if (fdst->n_bits == 128 && fsrc->n_bits == 128)
3250 : 0 : instr->type = INSTR_MOV_128;
3251 : :
3252 [ # # # # ]: 0 : if (fdst->n_bits == 128 && fsrc->n_bits == 64)
3253 : 0 : instr->type = INSTR_MOV_128_64;
3254 [ # # # # ]: 0 : if (fdst->n_bits == 64 && fsrc->n_bits == 128)
3255 : 0 : instr->type = INSTR_MOV_64_128;
3256 : :
3257 [ # # # # ]: 0 : if (fdst->n_bits == 128 && fsrc->n_bits == 32)
3258 : 0 : instr->type = INSTR_MOV_128_32;
3259 [ # # # # ]: 0 : if (fdst->n_bits == 32 && fsrc->n_bits == 128)
3260 : 0 : instr->type = INSTR_MOV_32_128;
3261 : : }
3262 : :
3263 : 0 : instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
3264 : 0 : instr->mov.dst.n_bits = fdst->n_bits;
3265 : 0 : instr->mov.dst.offset = fdst->offset / 8;
3266 : 0 : instr->mov.src.struct_id = (uint8_t)src_struct_id;
3267 : 0 : instr->mov.src.n_bits = fsrc->n_bits;
3268 : 0 : instr->mov.src.offset = fsrc->offset / 8;
3269 : 0 : return 0;
3270 : : }
3271 : :
3272 : : /* MOV_I. */
3273 [ # # ]: 0 : CHECK(fdst->n_bits <= 64, EINVAL);
3274 : 0 : src_val = strtoull(src, &src, 0);
3275 [ # # ]: 0 : CHECK(!src[0], EINVAL);
3276 : :
3277 [ # # ]: 0 : if (dst[0] == 'h')
3278 [ # # ]: 0 : src_val = hton64(src_val) >> (64 - fdst->n_bits);
3279 : :
3280 : 0 : instr->type = INSTR_MOV_I;
3281 : 0 : instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
3282 : 0 : instr->mov.dst.n_bits = fdst->n_bits;
3283 : 0 : instr->mov.dst.offset = fdst->offset / 8;
3284 : 0 : instr->mov.src_val = src_val;
3285 : 0 : return 0;
3286 : : }
3287 : :
3288 : : static inline void
3289 : 0 : instr_mov_exec(struct rte_swx_pipeline *p)
3290 : : {
3291 : 0 : struct thread *t = &p->threads[p->thread_id];
3292 : 0 : struct instruction *ip = t->ip;
3293 : :
3294 : 0 : __instr_mov_exec(p, t, ip);
3295 : :
3296 : : /* Thread. */
3297 : : thread_ip_inc(p);
3298 : 0 : }
3299 : :
3300 : : static inline void
3301 : 0 : instr_mov_mh_exec(struct rte_swx_pipeline *p)
3302 : : {
3303 : 0 : struct thread *t = &p->threads[p->thread_id];
3304 : 0 : struct instruction *ip = t->ip;
3305 : :
3306 : 0 : __instr_mov_mh_exec(p, t, ip);
3307 : :
3308 : : /* Thread. */
3309 : : thread_ip_inc(p);
3310 : 0 : }
3311 : :
3312 : : static inline void
3313 : 0 : instr_mov_hm_exec(struct rte_swx_pipeline *p)
3314 : : {
3315 : 0 : struct thread *t = &p->threads[p->thread_id];
3316 : 0 : struct instruction *ip = t->ip;
3317 : :
3318 : 0 : __instr_mov_hm_exec(p, t, ip);
3319 : :
3320 : : /* Thread. */
3321 : : thread_ip_inc(p);
3322 : 0 : }
3323 : :
3324 : : static inline void
3325 : 0 : instr_mov_hh_exec(struct rte_swx_pipeline *p)
3326 : : {
3327 : 0 : struct thread *t = &p->threads[p->thread_id];
3328 : 0 : struct instruction *ip = t->ip;
3329 : :
3330 : 0 : __instr_mov_hh_exec(p, t, ip);
3331 : :
3332 : : /* Thread. */
3333 : : thread_ip_inc(p);
3334 : 0 : }
3335 : :
3336 : : static inline void
3337 : 0 : instr_mov_dma_exec(struct rte_swx_pipeline *p)
3338 : : {
3339 : 0 : struct thread *t = &p->threads[p->thread_id];
3340 : 0 : struct instruction *ip = t->ip;
3341 : :
3342 : 0 : __instr_mov_dma_exec(p, t, ip);
3343 : :
3344 : : /* Thread. */
3345 : : thread_ip_inc(p);
3346 : 0 : }
3347 : :
3348 : : static inline void
3349 : 0 : instr_mov_128_exec(struct rte_swx_pipeline *p)
3350 : : {
3351 : 0 : struct thread *t = &p->threads[p->thread_id];
3352 : 0 : struct instruction *ip = t->ip;
3353 : :
3354 : : __instr_mov_128_exec(p, t, ip);
3355 : :
3356 : : /* Thread. */
3357 : : thread_ip_inc(p);
3358 : 0 : }
3359 : :
3360 : : static inline void
3361 : 0 : instr_mov_128_64_exec(struct rte_swx_pipeline *p)
3362 : : {
3363 : 0 : struct thread *t = &p->threads[p->thread_id];
3364 : 0 : struct instruction *ip = t->ip;
3365 : :
3366 : : __instr_mov_128_64_exec(p, t, ip);
3367 : :
3368 : : /* Thread. */
3369 : : thread_ip_inc(p);
3370 : 0 : }
3371 : :
3372 : : static inline void
3373 : 0 : instr_mov_64_128_exec(struct rte_swx_pipeline *p)
3374 : : {
3375 : 0 : struct thread *t = &p->threads[p->thread_id];
3376 : 0 : struct instruction *ip = t->ip;
3377 : :
3378 : : __instr_mov_64_128_exec(p, t, ip);
3379 : :
3380 : : /* Thread. */
3381 : : thread_ip_inc(p);
3382 : 0 : }
3383 : :
3384 : : static inline void
3385 : 0 : instr_mov_128_32_exec(struct rte_swx_pipeline *p)
3386 : : {
3387 : 0 : struct thread *t = &p->threads[p->thread_id];
3388 : 0 : struct instruction *ip = t->ip;
3389 : :
3390 : : __instr_mov_128_32_exec(p, t, ip);
3391 : :
3392 : : /* Thread. */
3393 : : thread_ip_inc(p);
3394 : 0 : }
3395 : :
3396 : : static inline void
3397 : 0 : instr_mov_32_128_exec(struct rte_swx_pipeline *p)
3398 : : {
3399 : 0 : struct thread *t = &p->threads[p->thread_id];
3400 : 0 : struct instruction *ip = t->ip;
3401 : :
3402 : : __instr_mov_32_128_exec(p, t, ip);
3403 : :
3404 : : /* Thread. */
3405 : : thread_ip_inc(p);
3406 : 0 : }
3407 : :
3408 : : static inline void
3409 : 0 : instr_mov_i_exec(struct rte_swx_pipeline *p)
3410 : : {
3411 : 0 : struct thread *t = &p->threads[p->thread_id];
3412 : 0 : struct instruction *ip = t->ip;
3413 : :
3414 : : __instr_mov_i_exec(p, t, ip);
3415 : :
3416 : : /* Thread. */
3417 : : thread_ip_inc(p);
3418 : 0 : }
3419 : :
3420 : : /*
3421 : : * movh.
3422 : : */
3423 : : static int
3424 : 0 : instr_movh_translate(struct rte_swx_pipeline *p,
3425 : : struct action *action,
3426 : : char **tokens,
3427 : : int n_tokens,
3428 : : struct instruction *instr,
3429 : : struct instruction_data *data __rte_unused)
3430 : : {
3431 : 0 : char *dst = tokens[1], *src = tokens[2];
3432 : : struct field *fdst, *fsrc;
3433 : 0 : uint32_t dst_struct_id = 0, src_struct_id = 0;
3434 : :
3435 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
3436 : :
3437 : 0 : fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3438 [ # # ]: 0 : CHECK(fdst, EINVAL);
3439 [ # # ]: 0 : CHECK(!fdst->var_size, EINVAL);
3440 : :
3441 : 0 : fsrc = struct_field_parse(p, action, src, &src_struct_id);
3442 [ # # ]: 0 : CHECK(fsrc, EINVAL);
3443 [ # # ]: 0 : CHECK(!fsrc->var_size, EINVAL);
3444 : :
3445 : : /* MOVH_64_128, MOVH_128_64. */
3446 [ # # # # : 0 : if ((dst[0] == 'h' && fdst->n_bits == 64 && fsrc->n_bits == 128) ||
# # ]
3447 [ # # # # : 0 : (fdst->n_bits == 128 && src[0] == 'h' && fsrc->n_bits == 64)) {
# # ]
3448 : 0 : instr->type = INSTR_MOVH;
3449 : :
3450 : 0 : instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
3451 : 0 : instr->mov.dst.n_bits = fdst->n_bits;
3452 : 0 : instr->mov.dst.offset = fdst->offset / 8;
3453 : :
3454 : 0 : instr->mov.src.struct_id = (uint8_t)src_struct_id;
3455 : 0 : instr->mov.src.n_bits = fsrc->n_bits;
3456 : 0 : instr->mov.src.offset = fsrc->offset / 8;
3457 : 0 : return 0;
3458 : : }
3459 : :
3460 : : CHECK(0, EINVAL);
3461 : : }
3462 : :
3463 : : static inline void
3464 : 0 : instr_movh_exec(struct rte_swx_pipeline *p)
3465 : : {
3466 : 0 : struct thread *t = &p->threads[p->thread_id];
3467 : 0 : struct instruction *ip = t->ip;
3468 : :
3469 : : __instr_movh_exec(p, t, ip);
3470 : :
3471 : : /* Thread. */
3472 : : thread_ip_inc(p);
3473 : 0 : }
3474 : :
3475 : : /*
3476 : : * dma.
3477 : : */
3478 : : static inline void
3479 : 0 : instr_dma_ht_exec(struct rte_swx_pipeline *p)
3480 : : {
3481 : 0 : struct thread *t = &p->threads[p->thread_id];
3482 : 0 : struct instruction *ip = t->ip;
3483 : :
3484 : : __instr_dma_ht_exec(p, t, ip);
3485 : :
3486 : : /* Thread. */
3487 : : thread_ip_inc(p);
3488 : 0 : }
3489 : :
3490 : : static inline void
3491 : 0 : instr_dma_ht2_exec(struct rte_swx_pipeline *p)
3492 : : {
3493 : 0 : struct thread *t = &p->threads[p->thread_id];
3494 : 0 : struct instruction *ip = t->ip;
3495 : :
3496 : : __instr_dma_ht2_exec(p, t, ip);
3497 : :
3498 : : /* Thread. */
3499 : : thread_ip_inc(p);
3500 : 0 : }
3501 : :
3502 : : static inline void
3503 : 0 : instr_dma_ht3_exec(struct rte_swx_pipeline *p)
3504 : : {
3505 : 0 : struct thread *t = &p->threads[p->thread_id];
3506 : 0 : struct instruction *ip = t->ip;
3507 : :
3508 : : __instr_dma_ht3_exec(p, t, ip);
3509 : :
3510 : : /* Thread. */
3511 : : thread_ip_inc(p);
3512 : 0 : }
3513 : :
3514 : : static inline void
3515 : 0 : instr_dma_ht4_exec(struct rte_swx_pipeline *p)
3516 : : {
3517 : 0 : struct thread *t = &p->threads[p->thread_id];
3518 : 0 : struct instruction *ip = t->ip;
3519 : :
3520 : : __instr_dma_ht4_exec(p, t, ip);
3521 : :
3522 : : /* Thread. */
3523 : : thread_ip_inc(p);
3524 : 0 : }
3525 : :
3526 : : static inline void
3527 : 0 : instr_dma_ht5_exec(struct rte_swx_pipeline *p)
3528 : : {
3529 : 0 : struct thread *t = &p->threads[p->thread_id];
3530 : 0 : struct instruction *ip = t->ip;
3531 : :
3532 : : __instr_dma_ht5_exec(p, t, ip);
3533 : :
3534 : : /* Thread. */
3535 : : thread_ip_inc(p);
3536 : 0 : }
3537 : :
3538 : : static inline void
3539 : 0 : instr_dma_ht6_exec(struct rte_swx_pipeline *p)
3540 : : {
3541 : 0 : struct thread *t = &p->threads[p->thread_id];
3542 : 0 : struct instruction *ip = t->ip;
3543 : :
3544 : : __instr_dma_ht6_exec(p, t, ip);
3545 : :
3546 : : /* Thread. */
3547 : : thread_ip_inc(p);
3548 : 0 : }
3549 : :
3550 : : static inline void
3551 : 0 : instr_dma_ht7_exec(struct rte_swx_pipeline *p)
3552 : : {
3553 : 0 : struct thread *t = &p->threads[p->thread_id];
3554 : 0 : struct instruction *ip = t->ip;
3555 : :
3556 : : __instr_dma_ht7_exec(p, t, ip);
3557 : :
3558 : : /* Thread. */
3559 : : thread_ip_inc(p);
3560 : 0 : }
3561 : :
3562 : : static inline void
3563 : 0 : instr_dma_ht8_exec(struct rte_swx_pipeline *p)
3564 : : {
3565 : 0 : struct thread *t = &p->threads[p->thread_id];
3566 : 0 : struct instruction *ip = t->ip;
3567 : :
3568 : : __instr_dma_ht8_exec(p, t, ip);
3569 : :
3570 : : /* Thread. */
3571 : : thread_ip_inc(p);
3572 : 0 : }
3573 : :
3574 : : /*
3575 : : * alu.
3576 : : */
3577 : : static int
3578 : 0 : instr_alu_add_translate(struct rte_swx_pipeline *p,
3579 : : struct action *action,
3580 : : char **tokens,
3581 : : int n_tokens,
3582 : : struct instruction *instr,
3583 : : struct instruction_data *data __rte_unused)
3584 : : {
3585 : 0 : char *dst = tokens[1], *src = tokens[2];
3586 : : struct field *fdst, *fsrc;
3587 : : uint64_t src_val;
3588 : 0 : uint32_t dst_struct_id = 0, src_struct_id = 0;
3589 : :
3590 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
3591 : :
3592 : 0 : fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3593 [ # # ]: 0 : CHECK(fdst, EINVAL);
3594 [ # # # # ]: 0 : CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
3595 : :
3596 : : /* ADD, ADD_HM, ADD_MH, ADD_HH. */
3597 : 0 : fsrc = struct_field_parse(p, action, src, &src_struct_id);
3598 [ # # ]: 0 : if (fsrc) {
3599 [ # # # # ]: 0 : CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
3600 : :
3601 : 0 : instr->type = INSTR_ALU_ADD;
3602 [ # # # # ]: 0 : if (dst[0] == 'h' && src[0] != 'h')
3603 : 0 : instr->type = INSTR_ALU_ADD_HM;
3604 [ # # # # ]: 0 : if (dst[0] != 'h' && src[0] == 'h')
3605 : 0 : instr->type = INSTR_ALU_ADD_MH;
3606 [ # # # # ]: 0 : if (dst[0] == 'h' && src[0] == 'h')
3607 : 0 : instr->type = INSTR_ALU_ADD_HH;
3608 : :
3609 : 0 : instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3610 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
3611 : 0 : instr->alu.dst.offset = fdst->offset / 8;
3612 : 0 : instr->alu.src.struct_id = (uint8_t)src_struct_id;
3613 : 0 : instr->alu.src.n_bits = fsrc->n_bits;
3614 : 0 : instr->alu.src.offset = fsrc->offset / 8;
3615 : 0 : return 0;
3616 : : }
3617 : :
3618 : : /* ADD_MI, ADD_HI. */
3619 : 0 : src_val = strtoull(src, &src, 0);
3620 [ # # ]: 0 : CHECK(!src[0], EINVAL);
3621 : :
3622 : 0 : instr->type = INSTR_ALU_ADD_MI;
3623 [ # # ]: 0 : if (dst[0] == 'h')
3624 : 0 : instr->type = INSTR_ALU_ADD_HI;
3625 : :
3626 : 0 : instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3627 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
3628 : 0 : instr->alu.dst.offset = fdst->offset / 8;
3629 : 0 : instr->alu.src_val = src_val;
3630 : 0 : return 0;
3631 : : }
3632 : :
3633 : : static int
3634 : 0 : instr_alu_sub_translate(struct rte_swx_pipeline *p,
3635 : : struct action *action,
3636 : : char **tokens,
3637 : : int n_tokens,
3638 : : struct instruction *instr,
3639 : : struct instruction_data *data __rte_unused)
3640 : : {
3641 : 0 : char *dst = tokens[1], *src = tokens[2];
3642 : : struct field *fdst, *fsrc;
3643 : : uint64_t src_val;
3644 : 0 : uint32_t dst_struct_id = 0, src_struct_id = 0;
3645 : :
3646 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
3647 : :
3648 : 0 : fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3649 [ # # ]: 0 : CHECK(fdst, EINVAL);
3650 [ # # # # ]: 0 : CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
3651 : :
3652 : : /* SUB, SUB_HM, SUB_MH, SUB_HH. */
3653 : 0 : fsrc = struct_field_parse(p, action, src, &src_struct_id);
3654 [ # # ]: 0 : if (fsrc) {
3655 [ # # # # ]: 0 : CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
3656 : :
3657 : 0 : instr->type = INSTR_ALU_SUB;
3658 [ # # # # ]: 0 : if (dst[0] == 'h' && src[0] != 'h')
3659 : 0 : instr->type = INSTR_ALU_SUB_HM;
3660 [ # # # # ]: 0 : if (dst[0] != 'h' && src[0] == 'h')
3661 : 0 : instr->type = INSTR_ALU_SUB_MH;
3662 [ # # # # ]: 0 : if (dst[0] == 'h' && src[0] == 'h')
3663 : 0 : instr->type = INSTR_ALU_SUB_HH;
3664 : :
3665 : 0 : instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3666 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
3667 : 0 : instr->alu.dst.offset = fdst->offset / 8;
3668 : 0 : instr->alu.src.struct_id = (uint8_t)src_struct_id;
3669 : 0 : instr->alu.src.n_bits = fsrc->n_bits;
3670 : 0 : instr->alu.src.offset = fsrc->offset / 8;
3671 : 0 : return 0;
3672 : : }
3673 : :
3674 : : /* SUB_MI, SUB_HI. */
3675 : 0 : src_val = strtoull(src, &src, 0);
3676 [ # # ]: 0 : CHECK(!src[0], EINVAL);
3677 : :
3678 : 0 : instr->type = INSTR_ALU_SUB_MI;
3679 [ # # ]: 0 : if (dst[0] == 'h')
3680 : 0 : instr->type = INSTR_ALU_SUB_HI;
3681 : :
3682 : 0 : instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3683 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
3684 : 0 : instr->alu.dst.offset = fdst->offset / 8;
3685 : 0 : instr->alu.src_val = src_val;
3686 : 0 : return 0;
3687 : : }
3688 : :
3689 : : static int
3690 : 0 : instr_alu_ckadd_translate(struct rte_swx_pipeline *p,
3691 : : struct action *action __rte_unused,
3692 : : char **tokens,
3693 : : int n_tokens,
3694 : : struct instruction *instr,
3695 : : struct instruction_data *data __rte_unused)
3696 : : {
3697 : 0 : char *dst = tokens[1], *src = tokens[2];
3698 : : struct header *hdst, *hsrc;
3699 : : struct field *fdst, *fsrc;
3700 : :
3701 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
3702 : :
3703 : 0 : fdst = header_field_parse(p, dst, &hdst);
3704 [ # # ]: 0 : CHECK(fdst, EINVAL);
3705 [ # # # # ]: 0 : CHECK(!fdst->var_size && (fdst->n_bits == 16), EINVAL);
3706 : :
3707 : : /* CKADD_FIELD. */
3708 : 0 : fsrc = header_field_parse(p, src, &hsrc);
3709 [ # # ]: 0 : if (fsrc) {
3710 [ # # # # ]: 0 : CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
3711 : :
3712 : 0 : instr->type = INSTR_ALU_CKADD_FIELD;
3713 : 0 : instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
3714 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
3715 : 0 : instr->alu.dst.offset = fdst->offset / 8;
3716 : 0 : instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
3717 : 0 : instr->alu.src.n_bits = fsrc->n_bits;
3718 : 0 : instr->alu.src.offset = fsrc->offset / 8;
3719 : 0 : return 0;
3720 : : }
3721 : :
3722 : : /* CKADD_STRUCT, CKADD_STRUCT20. */
3723 : 0 : hsrc = header_parse(p, src);
3724 [ # # ]: 0 : CHECK(hsrc, EINVAL);
3725 : :
3726 : 0 : instr->type = INSTR_ALU_CKADD_STRUCT;
3727 [ # # # # ]: 0 : if (!hsrc->st->var_size && ((hsrc->st->n_bits / 8) == 20))
3728 : 0 : instr->type = INSTR_ALU_CKADD_STRUCT20;
3729 : :
3730 : 0 : instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
3731 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
3732 : 0 : instr->alu.dst.offset = fdst->offset / 8;
3733 : 0 : instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
3734 : 0 : instr->alu.src.n_bits = (uint8_t)hsrc->id; /* The src header ID is stored here. */
3735 : 0 : instr->alu.src.offset = 0; /* Unused. */
3736 : 0 : return 0;
3737 : : }
3738 : :
3739 : : static int
3740 : 0 : instr_alu_cksub_translate(struct rte_swx_pipeline *p,
3741 : : struct action *action __rte_unused,
3742 : : char **tokens,
3743 : : int n_tokens,
3744 : : struct instruction *instr,
3745 : : struct instruction_data *data __rte_unused)
3746 : : {
3747 : 0 : char *dst = tokens[1], *src = tokens[2];
3748 : : struct header *hdst, *hsrc;
3749 : : struct field *fdst, *fsrc;
3750 : :
3751 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
3752 : :
3753 : 0 : fdst = header_field_parse(p, dst, &hdst);
3754 [ # # ]: 0 : CHECK(fdst, EINVAL);
3755 [ # # # # ]: 0 : CHECK(!fdst->var_size && (fdst->n_bits == 16), EINVAL);
3756 : :
3757 : 0 : fsrc = header_field_parse(p, src, &hsrc);
3758 [ # # ]: 0 : CHECK(fsrc, EINVAL);
3759 [ # # # # ]: 0 : CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
3760 : :
3761 : 0 : instr->type = INSTR_ALU_CKSUB_FIELD;
3762 : 0 : instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
3763 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
3764 : 0 : instr->alu.dst.offset = fdst->offset / 8;
3765 : 0 : instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
3766 : 0 : instr->alu.src.n_bits = fsrc->n_bits;
3767 : 0 : instr->alu.src.offset = fsrc->offset / 8;
3768 : 0 : return 0;
3769 : : }
3770 : :
3771 : : static int
3772 : 0 : instr_alu_shl_translate(struct rte_swx_pipeline *p,
3773 : : struct action *action,
3774 : : char **tokens,
3775 : : int n_tokens,
3776 : : struct instruction *instr,
3777 : : struct instruction_data *data __rte_unused)
3778 : : {
3779 : 0 : char *dst = tokens[1], *src = tokens[2];
3780 : : struct field *fdst, *fsrc;
3781 : : uint64_t src_val;
3782 : 0 : uint32_t dst_struct_id = 0, src_struct_id = 0;
3783 : :
3784 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
3785 : :
3786 : 0 : fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3787 [ # # ]: 0 : CHECK(fdst, EINVAL);
3788 [ # # # # ]: 0 : CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
3789 : :
3790 : : /* SHL, SHL_HM, SHL_MH, SHL_HH. */
3791 : 0 : fsrc = struct_field_parse(p, action, src, &src_struct_id);
3792 [ # # ]: 0 : if (fsrc) {
3793 [ # # # # ]: 0 : CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
3794 : :
3795 : 0 : instr->type = INSTR_ALU_SHL;
3796 [ # # # # ]: 0 : if (dst[0] == 'h' && src[0] != 'h')
3797 : 0 : instr->type = INSTR_ALU_SHL_HM;
3798 [ # # # # ]: 0 : if (dst[0] != 'h' && src[0] == 'h')
3799 : 0 : instr->type = INSTR_ALU_SHL_MH;
3800 [ # # # # ]: 0 : if (dst[0] == 'h' && src[0] == 'h')
3801 : 0 : instr->type = INSTR_ALU_SHL_HH;
3802 : :
3803 : 0 : instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3804 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
3805 : 0 : instr->alu.dst.offset = fdst->offset / 8;
3806 : 0 : instr->alu.src.struct_id = (uint8_t)src_struct_id;
3807 : 0 : instr->alu.src.n_bits = fsrc->n_bits;
3808 : 0 : instr->alu.src.offset = fsrc->offset / 8;
3809 : 0 : return 0;
3810 : : }
3811 : :
3812 : : /* SHL_MI, SHL_HI. */
3813 : 0 : src_val = strtoull(src, &src, 0);
3814 [ # # ]: 0 : CHECK(!src[0], EINVAL);
3815 : :
3816 : 0 : instr->type = INSTR_ALU_SHL_MI;
3817 [ # # ]: 0 : if (dst[0] == 'h')
3818 : 0 : instr->type = INSTR_ALU_SHL_HI;
3819 : :
3820 : 0 : instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3821 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
3822 : 0 : instr->alu.dst.offset = fdst->offset / 8;
3823 : 0 : instr->alu.src_val = src_val;
3824 : 0 : return 0;
3825 : : }
3826 : :
3827 : : static int
3828 : 0 : instr_alu_shr_translate(struct rte_swx_pipeline *p,
3829 : : struct action *action,
3830 : : char **tokens,
3831 : : int n_tokens,
3832 : : struct instruction *instr,
3833 : : struct instruction_data *data __rte_unused)
3834 : : {
3835 : 0 : char *dst = tokens[1], *src = tokens[2];
3836 : : struct field *fdst, *fsrc;
3837 : : uint64_t src_val;
3838 : 0 : uint32_t dst_struct_id = 0, src_struct_id = 0;
3839 : :
3840 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
3841 : :
3842 : 0 : fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3843 [ # # ]: 0 : CHECK(fdst, EINVAL);
3844 [ # # # # ]: 0 : CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
3845 : :
3846 : : /* SHR, SHR_HM, SHR_MH, SHR_HH. */
3847 : 0 : fsrc = struct_field_parse(p, action, src, &src_struct_id);
3848 [ # # ]: 0 : if (fsrc) {
3849 [ # # # # ]: 0 : CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
3850 : :
3851 : 0 : instr->type = INSTR_ALU_SHR;
3852 [ # # # # ]: 0 : if (dst[0] == 'h' && src[0] != 'h')
3853 : 0 : instr->type = INSTR_ALU_SHR_HM;
3854 [ # # # # ]: 0 : if (dst[0] != 'h' && src[0] == 'h')
3855 : 0 : instr->type = INSTR_ALU_SHR_MH;
3856 [ # # # # ]: 0 : if (dst[0] == 'h' && src[0] == 'h')
3857 : 0 : instr->type = INSTR_ALU_SHR_HH;
3858 : :
3859 : 0 : instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3860 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
3861 : 0 : instr->alu.dst.offset = fdst->offset / 8;
3862 : 0 : instr->alu.src.struct_id = (uint8_t)src_struct_id;
3863 : 0 : instr->alu.src.n_bits = fsrc->n_bits;
3864 : 0 : instr->alu.src.offset = fsrc->offset / 8;
3865 : 0 : return 0;
3866 : : }
3867 : :
3868 : : /* SHR_MI, SHR_HI. */
3869 : 0 : src_val = strtoull(src, &src, 0);
3870 [ # # ]: 0 : CHECK(!src[0], EINVAL);
3871 : :
3872 : 0 : instr->type = INSTR_ALU_SHR_MI;
3873 [ # # ]: 0 : if (dst[0] == 'h')
3874 : 0 : instr->type = INSTR_ALU_SHR_HI;
3875 : :
3876 : 0 : instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3877 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
3878 : 0 : instr->alu.dst.offset = fdst->offset / 8;
3879 : 0 : instr->alu.src_val = src_val;
3880 : 0 : return 0;
3881 : : }
3882 : :
3883 : : static int
3884 : 0 : instr_alu_and_translate(struct rte_swx_pipeline *p,
3885 : : struct action *action,
3886 : : char **tokens,
3887 : : int n_tokens,
3888 : : struct instruction *instr,
3889 : : struct instruction_data *data __rte_unused)
3890 : : {
3891 : 0 : char *dst = tokens[1], *src = tokens[2];
3892 : : struct field *fdst, *fsrc;
3893 : : uint64_t src_val;
3894 : 0 : uint32_t dst_struct_id = 0, src_struct_id = 0;
3895 : :
3896 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
3897 : :
3898 : 0 : fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3899 [ # # ]: 0 : CHECK(fdst, EINVAL);
3900 [ # # # # ]: 0 : CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
3901 : :
3902 : : /* AND, AND_MH, AND_HM, AND_HH. */
3903 : 0 : fsrc = struct_field_parse(p, action, src, &src_struct_id);
3904 [ # # ]: 0 : if (fsrc) {
3905 [ # # # # ]: 0 : CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
3906 : :
3907 : 0 : instr->type = INSTR_ALU_AND;
3908 [ # # # # ]: 0 : if (dst[0] != 'h' && src[0] == 'h')
3909 : 0 : instr->type = INSTR_ALU_AND_MH;
3910 [ # # # # ]: 0 : if (dst[0] == 'h' && src[0] != 'h')
3911 : 0 : instr->type = INSTR_ALU_AND_HM;
3912 [ # # # # ]: 0 : if (dst[0] == 'h' && src[0] == 'h')
3913 : 0 : instr->type = INSTR_ALU_AND_HH;
3914 : :
3915 : 0 : instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3916 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
3917 : 0 : instr->alu.dst.offset = fdst->offset / 8;
3918 : 0 : instr->alu.src.struct_id = (uint8_t)src_struct_id;
3919 : 0 : instr->alu.src.n_bits = fsrc->n_bits;
3920 : 0 : instr->alu.src.offset = fsrc->offset / 8;
3921 : 0 : return 0;
3922 : : }
3923 : :
3924 : : /* AND_I. */
3925 : 0 : src_val = strtoull(src, &src, 0);
3926 [ # # ]: 0 : CHECK(!src[0], EINVAL);
3927 : :
3928 [ # # ]: 0 : if (dst[0] == 'h')
3929 [ # # ]: 0 : src_val = hton64(src_val) >> (64 - fdst->n_bits);
3930 : :
3931 : 0 : instr->type = INSTR_ALU_AND_I;
3932 : 0 : instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3933 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
3934 : 0 : instr->alu.dst.offset = fdst->offset / 8;
3935 : 0 : instr->alu.src_val = src_val;
3936 : 0 : return 0;
3937 : : }
3938 : :
3939 : : static int
3940 : 0 : instr_alu_or_translate(struct rte_swx_pipeline *p,
3941 : : struct action *action,
3942 : : char **tokens,
3943 : : int n_tokens,
3944 : : struct instruction *instr,
3945 : : struct instruction_data *data __rte_unused)
3946 : : {
3947 : 0 : char *dst = tokens[1], *src = tokens[2];
3948 : : struct field *fdst, *fsrc;
3949 : : uint64_t src_val;
3950 : 0 : uint32_t dst_struct_id = 0, src_struct_id = 0;
3951 : :
3952 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
3953 : :
3954 : 0 : fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3955 [ # # ]: 0 : CHECK(fdst, EINVAL);
3956 [ # # # # ]: 0 : CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
3957 : :
3958 : : /* OR, OR_MH, OR_HM, OR_HH. */
3959 : 0 : fsrc = struct_field_parse(p, action, src, &src_struct_id);
3960 [ # # ]: 0 : if (fsrc) {
3961 [ # # # # ]: 0 : CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
3962 : :
3963 : 0 : instr->type = INSTR_ALU_OR;
3964 [ # # # # ]: 0 : if (dst[0] != 'h' && src[0] == 'h')
3965 : 0 : instr->type = INSTR_ALU_OR_MH;
3966 [ # # # # ]: 0 : if (dst[0] == 'h' && src[0] != 'h')
3967 : 0 : instr->type = INSTR_ALU_OR_HM;
3968 [ # # # # ]: 0 : if (dst[0] == 'h' && src[0] == 'h')
3969 : 0 : instr->type = INSTR_ALU_OR_HH;
3970 : :
3971 : 0 : instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3972 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
3973 : 0 : instr->alu.dst.offset = fdst->offset / 8;
3974 : 0 : instr->alu.src.struct_id = (uint8_t)src_struct_id;
3975 : 0 : instr->alu.src.n_bits = fsrc->n_bits;
3976 : 0 : instr->alu.src.offset = fsrc->offset / 8;
3977 : 0 : return 0;
3978 : : }
3979 : :
3980 : : /* OR_I. */
3981 : 0 : src_val = strtoull(src, &src, 0);
3982 [ # # ]: 0 : CHECK(!src[0], EINVAL);
3983 : :
3984 [ # # ]: 0 : if (dst[0] == 'h')
3985 [ # # ]: 0 : src_val = hton64(src_val) >> (64 - fdst->n_bits);
3986 : :
3987 : 0 : instr->type = INSTR_ALU_OR_I;
3988 : 0 : instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3989 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
3990 : 0 : instr->alu.dst.offset = fdst->offset / 8;
3991 : 0 : instr->alu.src_val = src_val;
3992 : 0 : return 0;
3993 : : }
3994 : :
3995 : : static int
3996 : 0 : instr_alu_xor_translate(struct rte_swx_pipeline *p,
3997 : : struct action *action,
3998 : : char **tokens,
3999 : : int n_tokens,
4000 : : struct instruction *instr,
4001 : : struct instruction_data *data __rte_unused)
4002 : : {
4003 : 0 : char *dst = tokens[1], *src = tokens[2];
4004 : : struct field *fdst, *fsrc;
4005 : : uint64_t src_val;
4006 : 0 : uint32_t dst_struct_id = 0, src_struct_id = 0;
4007 : :
4008 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
4009 : :
4010 : 0 : fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4011 [ # # ]: 0 : CHECK(fdst, EINVAL);
4012 [ # # # # ]: 0 : CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
4013 : :
4014 : : /* XOR, XOR_MH, XOR_HM, XOR_HH. */
4015 : 0 : fsrc = struct_field_parse(p, action, src, &src_struct_id);
4016 [ # # ]: 0 : if (fsrc) {
4017 [ # # # # ]: 0 : CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
4018 : :
4019 : 0 : instr->type = INSTR_ALU_XOR;
4020 [ # # # # ]: 0 : if (dst[0] != 'h' && src[0] == 'h')
4021 : 0 : instr->type = INSTR_ALU_XOR_MH;
4022 [ # # # # ]: 0 : if (dst[0] == 'h' && src[0] != 'h')
4023 : 0 : instr->type = INSTR_ALU_XOR_HM;
4024 [ # # # # ]: 0 : if (dst[0] == 'h' && src[0] == 'h')
4025 : 0 : instr->type = INSTR_ALU_XOR_HH;
4026 : :
4027 : 0 : instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4028 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
4029 : 0 : instr->alu.dst.offset = fdst->offset / 8;
4030 : 0 : instr->alu.src.struct_id = (uint8_t)src_struct_id;
4031 : 0 : instr->alu.src.n_bits = fsrc->n_bits;
4032 : 0 : instr->alu.src.offset = fsrc->offset / 8;
4033 : 0 : return 0;
4034 : : }
4035 : :
4036 : : /* XOR_I. */
4037 : 0 : src_val = strtoull(src, &src, 0);
4038 [ # # ]: 0 : CHECK(!src[0], EINVAL);
4039 : :
4040 [ # # ]: 0 : if (dst[0] == 'h')
4041 [ # # ]: 0 : src_val = hton64(src_val) >> (64 - fdst->n_bits);
4042 : :
4043 : 0 : instr->type = INSTR_ALU_XOR_I;
4044 : 0 : instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4045 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
4046 : 0 : instr->alu.dst.offset = fdst->offset / 8;
4047 : 0 : instr->alu.src_val = src_val;
4048 : 0 : return 0;
4049 : : }
4050 : :
4051 : : static inline void
4052 : 0 : instr_alu_add_exec(struct rte_swx_pipeline *p)
4053 : : {
4054 : 0 : struct thread *t = &p->threads[p->thread_id];
4055 : 0 : struct instruction *ip = t->ip;
4056 : :
4057 : : /* Structs */
4058 : 0 : __instr_alu_add_exec(p, t, ip);
4059 : :
4060 : : /* Thread. */
4061 : : thread_ip_inc(p);
4062 : 0 : }
4063 : :
4064 : : static inline void
4065 : 0 : instr_alu_add_mh_exec(struct rte_swx_pipeline *p)
4066 : : {
4067 : 0 : struct thread *t = &p->threads[p->thread_id];
4068 : 0 : struct instruction *ip = t->ip;
4069 : :
4070 : : /* Structs. */
4071 : 0 : __instr_alu_add_mh_exec(p, t, ip);
4072 : :
4073 : : /* Thread. */
4074 : : thread_ip_inc(p);
4075 : 0 : }
4076 : :
4077 : : static inline void
4078 : 0 : instr_alu_add_hm_exec(struct rte_swx_pipeline *p)
4079 : : {
4080 : 0 : struct thread *t = &p->threads[p->thread_id];
4081 : 0 : struct instruction *ip = t->ip;
4082 : :
4083 : : /* Structs. */
4084 : 0 : __instr_alu_add_hm_exec(p, t, ip);
4085 : :
4086 : : /* Thread. */
4087 : : thread_ip_inc(p);
4088 : 0 : }
4089 : :
4090 : : static inline void
4091 : 0 : instr_alu_add_hh_exec(struct rte_swx_pipeline *p)
4092 : : {
4093 : 0 : struct thread *t = &p->threads[p->thread_id];
4094 : 0 : struct instruction *ip = t->ip;
4095 : :
4096 : : /* Structs. */
4097 : 0 : __instr_alu_add_hh_exec(p, t, ip);
4098 : :
4099 : : /* Thread. */
4100 : : thread_ip_inc(p);
4101 : 0 : }
4102 : :
4103 : : static inline void
4104 : 0 : instr_alu_add_mi_exec(struct rte_swx_pipeline *p)
4105 : : {
4106 : 0 : struct thread *t = &p->threads[p->thread_id];
4107 : 0 : struct instruction *ip = t->ip;
4108 : :
4109 : : /* Structs. */
4110 : : __instr_alu_add_mi_exec(p, t, ip);
4111 : :
4112 : : /* Thread. */
4113 : : thread_ip_inc(p);
4114 : 0 : }
4115 : :
4116 : : static inline void
4117 : 0 : instr_alu_add_hi_exec(struct rte_swx_pipeline *p)
4118 : : {
4119 : 0 : struct thread *t = &p->threads[p->thread_id];
4120 : 0 : struct instruction *ip = t->ip;
4121 : :
4122 : : /* Structs. */
4123 : 0 : __instr_alu_add_hi_exec(p, t, ip);
4124 : :
4125 : : /* Thread. */
4126 : : thread_ip_inc(p);
4127 : 0 : }
4128 : :
4129 : : static inline void
4130 : 0 : instr_alu_sub_exec(struct rte_swx_pipeline *p)
4131 : : {
4132 : 0 : struct thread *t = &p->threads[p->thread_id];
4133 : 0 : struct instruction *ip = t->ip;
4134 : :
4135 : : /* Structs. */
4136 : 0 : __instr_alu_sub_exec(p, t, ip);
4137 : :
4138 : : /* Thread. */
4139 : : thread_ip_inc(p);
4140 : 0 : }
4141 : :
4142 : : static inline void
4143 : 0 : instr_alu_sub_mh_exec(struct rte_swx_pipeline *p)
4144 : : {
4145 : 0 : struct thread *t = &p->threads[p->thread_id];
4146 : 0 : struct instruction *ip = t->ip;
4147 : :
4148 : : /* Structs. */
4149 : 0 : __instr_alu_sub_mh_exec(p, t, ip);
4150 : :
4151 : : /* Thread. */
4152 : : thread_ip_inc(p);
4153 : 0 : }
4154 : :
4155 : : static inline void
4156 : 0 : instr_alu_sub_hm_exec(struct rte_swx_pipeline *p)
4157 : : {
4158 : 0 : struct thread *t = &p->threads[p->thread_id];
4159 : 0 : struct instruction *ip = t->ip;
4160 : :
4161 : : /* Structs. */
4162 : 0 : __instr_alu_sub_hm_exec(p, t, ip);
4163 : :
4164 : : /* Thread. */
4165 : : thread_ip_inc(p);
4166 : 0 : }
4167 : :
4168 : : static inline void
4169 : 0 : instr_alu_sub_hh_exec(struct rte_swx_pipeline *p)
4170 : : {
4171 : 0 : struct thread *t = &p->threads[p->thread_id];
4172 : 0 : struct instruction *ip = t->ip;
4173 : :
4174 : : /* Structs. */
4175 : 0 : __instr_alu_sub_hh_exec(p, t, ip);
4176 : :
4177 : : /* Thread. */
4178 : : thread_ip_inc(p);
4179 : 0 : }
4180 : :
4181 : : static inline void
4182 : 0 : instr_alu_sub_mi_exec(struct rte_swx_pipeline *p)
4183 : : {
4184 : 0 : struct thread *t = &p->threads[p->thread_id];
4185 : 0 : struct instruction *ip = t->ip;
4186 : :
4187 : : /* Structs. */
4188 : : __instr_alu_sub_mi_exec(p, t, ip);
4189 : :
4190 : : /* Thread. */
4191 : : thread_ip_inc(p);
4192 : 0 : }
4193 : :
4194 : : static inline void
4195 : 0 : instr_alu_sub_hi_exec(struct rte_swx_pipeline *p)
4196 : : {
4197 : 0 : struct thread *t = &p->threads[p->thread_id];
4198 : 0 : struct instruction *ip = t->ip;
4199 : :
4200 : : /* Structs. */
4201 : 0 : __instr_alu_sub_hi_exec(p, t, ip);
4202 : :
4203 : : /* Thread. */
4204 : : thread_ip_inc(p);
4205 : 0 : }
4206 : :
4207 : : static inline void
4208 : 0 : instr_alu_shl_exec(struct rte_swx_pipeline *p)
4209 : : {
4210 : 0 : struct thread *t = &p->threads[p->thread_id];
4211 : 0 : struct instruction *ip = t->ip;
4212 : :
4213 : : /* Structs. */
4214 : 0 : __instr_alu_shl_exec(p, t, ip);
4215 : :
4216 : : /* Thread. */
4217 : : thread_ip_inc(p);
4218 : 0 : }
4219 : :
4220 : : static inline void
4221 : 0 : instr_alu_shl_mh_exec(struct rte_swx_pipeline *p)
4222 : : {
4223 : 0 : struct thread *t = &p->threads[p->thread_id];
4224 : 0 : struct instruction *ip = t->ip;
4225 : :
4226 : : /* Structs. */
4227 : 0 : __instr_alu_shl_mh_exec(p, t, ip);
4228 : :
4229 : : /* Thread. */
4230 : : thread_ip_inc(p);
4231 : 0 : }
4232 : :
4233 : : static inline void
4234 : 0 : instr_alu_shl_hm_exec(struct rte_swx_pipeline *p)
4235 : : {
4236 : 0 : struct thread *t = &p->threads[p->thread_id];
4237 : 0 : struct instruction *ip = t->ip;
4238 : :
4239 : : /* Structs. */
4240 : 0 : __instr_alu_shl_hm_exec(p, t, ip);
4241 : :
4242 : : /* Thread. */
4243 : : thread_ip_inc(p);
4244 : 0 : }
4245 : :
4246 : : static inline void
4247 : 0 : instr_alu_shl_hh_exec(struct rte_swx_pipeline *p)
4248 : : {
4249 : 0 : struct thread *t = &p->threads[p->thread_id];
4250 : 0 : struct instruction *ip = t->ip;
4251 : :
4252 : : /* Structs. */
4253 : 0 : __instr_alu_shl_hh_exec(p, t, ip);
4254 : :
4255 : : /* Thread. */
4256 : : thread_ip_inc(p);
4257 : 0 : }
4258 : :
4259 : : static inline void
4260 : 0 : instr_alu_shl_mi_exec(struct rte_swx_pipeline *p)
4261 : : {
4262 : 0 : struct thread *t = &p->threads[p->thread_id];
4263 : 0 : struct instruction *ip = t->ip;
4264 : :
4265 : : /* Structs. */
4266 : : __instr_alu_shl_mi_exec(p, t, ip);
4267 : :
4268 : : /* Thread. */
4269 : : thread_ip_inc(p);
4270 : 0 : }
4271 : :
4272 : : static inline void
4273 : 0 : instr_alu_shl_hi_exec(struct rte_swx_pipeline *p)
4274 : : {
4275 : 0 : struct thread *t = &p->threads[p->thread_id];
4276 : 0 : struct instruction *ip = t->ip;
4277 : :
4278 : : /* Structs. */
4279 : 0 : __instr_alu_shl_hi_exec(p, t, ip);
4280 : :
4281 : : /* Thread. */
4282 : : thread_ip_inc(p);
4283 : 0 : }
4284 : :
4285 : : static inline void
4286 : 0 : instr_alu_shr_exec(struct rte_swx_pipeline *p)
4287 : : {
4288 : 0 : struct thread *t = &p->threads[p->thread_id];
4289 : 0 : struct instruction *ip = t->ip;
4290 : :
4291 : : /* Structs. */
4292 : 0 : __instr_alu_shr_exec(p, t, ip);
4293 : :
4294 : : /* Thread. */
4295 : : thread_ip_inc(p);
4296 : 0 : }
4297 : :
4298 : : static inline void
4299 : 0 : instr_alu_shr_mh_exec(struct rte_swx_pipeline *p)
4300 : : {
4301 : 0 : struct thread *t = &p->threads[p->thread_id];
4302 : 0 : struct instruction *ip = t->ip;
4303 : :
4304 : : /* Structs. */
4305 : 0 : __instr_alu_shr_mh_exec(p, t, ip);
4306 : :
4307 : : /* Thread. */
4308 : : thread_ip_inc(p);
4309 : 0 : }
4310 : :
4311 : : static inline void
4312 : 0 : instr_alu_shr_hm_exec(struct rte_swx_pipeline *p)
4313 : : {
4314 : 0 : struct thread *t = &p->threads[p->thread_id];
4315 : 0 : struct instruction *ip = t->ip;
4316 : :
4317 : : /* Structs. */
4318 : 0 : __instr_alu_shr_hm_exec(p, t, ip);
4319 : :
4320 : : /* Thread. */
4321 : : thread_ip_inc(p);
4322 : 0 : }
4323 : :
4324 : : static inline void
4325 : 0 : instr_alu_shr_hh_exec(struct rte_swx_pipeline *p)
4326 : : {
4327 : 0 : struct thread *t = &p->threads[p->thread_id];
4328 : 0 : struct instruction *ip = t->ip;
4329 : :
4330 : : /* Structs. */
4331 : 0 : __instr_alu_shr_hh_exec(p, t, ip);
4332 : :
4333 : : /* Thread. */
4334 : : thread_ip_inc(p);
4335 : 0 : }
4336 : :
4337 : : static inline void
4338 : 0 : instr_alu_shr_mi_exec(struct rte_swx_pipeline *p)
4339 : : {
4340 : 0 : struct thread *t = &p->threads[p->thread_id];
4341 : 0 : struct instruction *ip = t->ip;
4342 : :
4343 : : /* Structs. */
4344 : : __instr_alu_shr_mi_exec(p, t, ip);
4345 : :
4346 : : /* Thread. */
4347 : : thread_ip_inc(p);
4348 : 0 : }
4349 : :
4350 : : static inline void
4351 : 0 : instr_alu_shr_hi_exec(struct rte_swx_pipeline *p)
4352 : : {
4353 : 0 : struct thread *t = &p->threads[p->thread_id];
4354 : 0 : struct instruction *ip = t->ip;
4355 : :
4356 : : /* Structs. */
4357 : 0 : __instr_alu_shr_hi_exec(p, t, ip);
4358 : :
4359 : : /* Thread. */
4360 : : thread_ip_inc(p);
4361 : 0 : }
4362 : :
4363 : : static inline void
4364 : 0 : instr_alu_and_exec(struct rte_swx_pipeline *p)
4365 : : {
4366 : 0 : struct thread *t = &p->threads[p->thread_id];
4367 : 0 : struct instruction *ip = t->ip;
4368 : :
4369 : : /* Structs. */
4370 : 0 : __instr_alu_and_exec(p, t, ip);
4371 : :
4372 : : /* Thread. */
4373 : : thread_ip_inc(p);
4374 : 0 : }
4375 : :
4376 : : static inline void
4377 : 0 : instr_alu_and_mh_exec(struct rte_swx_pipeline *p)
4378 : : {
4379 : 0 : struct thread *t = &p->threads[p->thread_id];
4380 : 0 : struct instruction *ip = t->ip;
4381 : :
4382 : : /* Structs. */
4383 : 0 : __instr_alu_and_mh_exec(p, t, ip);
4384 : :
4385 : : /* Thread. */
4386 : : thread_ip_inc(p);
4387 : 0 : }
4388 : :
4389 : : static inline void
4390 : 0 : instr_alu_and_hm_exec(struct rte_swx_pipeline *p)
4391 : : {
4392 : 0 : struct thread *t = &p->threads[p->thread_id];
4393 : 0 : struct instruction *ip = t->ip;
4394 : :
4395 : : /* Structs. */
4396 : 0 : __instr_alu_and_hm_exec(p, t, ip);
4397 : :
4398 : : /* Thread. */
4399 : : thread_ip_inc(p);
4400 : 0 : }
4401 : :
4402 : : static inline void
4403 : 0 : instr_alu_and_hh_exec(struct rte_swx_pipeline *p)
4404 : : {
4405 : 0 : struct thread *t = &p->threads[p->thread_id];
4406 : 0 : struct instruction *ip = t->ip;
4407 : :
4408 : : /* Structs. */
4409 : 0 : __instr_alu_and_hh_exec(p, t, ip);
4410 : :
4411 : : /* Thread. */
4412 : : thread_ip_inc(p);
4413 : 0 : }
4414 : :
4415 : : static inline void
4416 : 0 : instr_alu_and_i_exec(struct rte_swx_pipeline *p)
4417 : : {
4418 : 0 : struct thread *t = &p->threads[p->thread_id];
4419 : 0 : struct instruction *ip = t->ip;
4420 : :
4421 : : /* Structs. */
4422 : : __instr_alu_and_i_exec(p, t, ip);
4423 : :
4424 : : /* Thread. */
4425 : : thread_ip_inc(p);
4426 : 0 : }
4427 : :
4428 : : static inline void
4429 : 0 : instr_alu_or_exec(struct rte_swx_pipeline *p)
4430 : : {
4431 : 0 : struct thread *t = &p->threads[p->thread_id];
4432 : 0 : struct instruction *ip = t->ip;
4433 : :
4434 : : /* Structs. */
4435 : 0 : __instr_alu_or_exec(p, t, ip);
4436 : :
4437 : : /* Thread. */
4438 : : thread_ip_inc(p);
4439 : 0 : }
4440 : :
4441 : : static inline void
4442 : 0 : instr_alu_or_mh_exec(struct rte_swx_pipeline *p)
4443 : : {
4444 : 0 : struct thread *t = &p->threads[p->thread_id];
4445 : 0 : struct instruction *ip = t->ip;
4446 : :
4447 : : /* Structs. */
4448 : 0 : __instr_alu_or_mh_exec(p, t, ip);
4449 : :
4450 : : /* Thread. */
4451 : : thread_ip_inc(p);
4452 : 0 : }
4453 : :
4454 : : static inline void
4455 : 0 : instr_alu_or_hm_exec(struct rte_swx_pipeline *p)
4456 : : {
4457 : 0 : struct thread *t = &p->threads[p->thread_id];
4458 : 0 : struct instruction *ip = t->ip;
4459 : :
4460 : : /* Structs. */
4461 : 0 : __instr_alu_or_hm_exec(p, t, ip);
4462 : :
4463 : : /* Thread. */
4464 : : thread_ip_inc(p);
4465 : 0 : }
4466 : :
4467 : : static inline void
4468 : 0 : instr_alu_or_hh_exec(struct rte_swx_pipeline *p)
4469 : : {
4470 : 0 : struct thread *t = &p->threads[p->thread_id];
4471 : 0 : struct instruction *ip = t->ip;
4472 : :
4473 : : /* Structs. */
4474 : 0 : __instr_alu_or_hh_exec(p, t, ip);
4475 : :
4476 : : /* Thread. */
4477 : : thread_ip_inc(p);
4478 : 0 : }
4479 : :
4480 : : static inline void
4481 : 0 : instr_alu_or_i_exec(struct rte_swx_pipeline *p)
4482 : : {
4483 : 0 : struct thread *t = &p->threads[p->thread_id];
4484 : 0 : struct instruction *ip = t->ip;
4485 : :
4486 : : /* Structs. */
4487 : : __instr_alu_or_i_exec(p, t, ip);
4488 : :
4489 : : /* Thread. */
4490 : : thread_ip_inc(p);
4491 : 0 : }
4492 : :
4493 : : static inline void
4494 : 0 : instr_alu_xor_exec(struct rte_swx_pipeline *p)
4495 : : {
4496 : 0 : struct thread *t = &p->threads[p->thread_id];
4497 : 0 : struct instruction *ip = t->ip;
4498 : :
4499 : : /* Structs. */
4500 : 0 : __instr_alu_xor_exec(p, t, ip);
4501 : :
4502 : : /* Thread. */
4503 : : thread_ip_inc(p);
4504 : 0 : }
4505 : :
4506 : : static inline void
4507 : 0 : instr_alu_xor_mh_exec(struct rte_swx_pipeline *p)
4508 : : {
4509 : 0 : struct thread *t = &p->threads[p->thread_id];
4510 : 0 : struct instruction *ip = t->ip;
4511 : :
4512 : : /* Structs. */
4513 : 0 : __instr_alu_xor_mh_exec(p, t, ip);
4514 : :
4515 : : /* Thread. */
4516 : : thread_ip_inc(p);
4517 : 0 : }
4518 : :
4519 : : static inline void
4520 : 0 : instr_alu_xor_hm_exec(struct rte_swx_pipeline *p)
4521 : : {
4522 : 0 : struct thread *t = &p->threads[p->thread_id];
4523 : 0 : struct instruction *ip = t->ip;
4524 : :
4525 : : /* Structs. */
4526 : 0 : __instr_alu_xor_hm_exec(p, t, ip);
4527 : :
4528 : : /* Thread. */
4529 : : thread_ip_inc(p);
4530 : 0 : }
4531 : :
4532 : : static inline void
4533 : 0 : instr_alu_xor_hh_exec(struct rte_swx_pipeline *p)
4534 : : {
4535 : 0 : struct thread *t = &p->threads[p->thread_id];
4536 : 0 : struct instruction *ip = t->ip;
4537 : :
4538 : : /* Structs. */
4539 : 0 : __instr_alu_xor_hh_exec(p, t, ip);
4540 : :
4541 : : /* Thread. */
4542 : : thread_ip_inc(p);
4543 : 0 : }
4544 : :
4545 : : static inline void
4546 : 0 : instr_alu_xor_i_exec(struct rte_swx_pipeline *p)
4547 : : {
4548 : 0 : struct thread *t = &p->threads[p->thread_id];
4549 : 0 : struct instruction *ip = t->ip;
4550 : :
4551 : : /* Structs. */
4552 : : __instr_alu_xor_i_exec(p, t, ip);
4553 : :
4554 : : /* Thread. */
4555 : : thread_ip_inc(p);
4556 : 0 : }
4557 : :
4558 : : static inline void
4559 : 0 : instr_alu_ckadd_field_exec(struct rte_swx_pipeline *p)
4560 : : {
4561 : 0 : struct thread *t = &p->threads[p->thread_id];
4562 : 0 : struct instruction *ip = t->ip;
4563 : :
4564 : : /* Structs. */
4565 : 0 : __instr_alu_ckadd_field_exec(p, t, ip);
4566 : :
4567 : : /* Thread. */
4568 : : thread_ip_inc(p);
4569 : 0 : }
4570 : :
4571 : : static inline void
4572 : 0 : instr_alu_cksub_field_exec(struct rte_swx_pipeline *p)
4573 : : {
4574 : 0 : struct thread *t = &p->threads[p->thread_id];
4575 : 0 : struct instruction *ip = t->ip;
4576 : :
4577 : : /* Structs. */
4578 : 0 : __instr_alu_cksub_field_exec(p, t, ip);
4579 : :
4580 : : /* Thread. */
4581 : : thread_ip_inc(p);
4582 : 0 : }
4583 : :
4584 : : static inline void
4585 : 0 : instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline *p)
4586 : : {
4587 : 0 : struct thread *t = &p->threads[p->thread_id];
4588 : 0 : struct instruction *ip = t->ip;
4589 : :
4590 : : /* Structs. */
4591 : 0 : __instr_alu_ckadd_struct20_exec(p, t, ip);
4592 : :
4593 : : /* Thread. */
4594 : : thread_ip_inc(p);
4595 : 0 : }
4596 : :
4597 : : static inline void
4598 : 0 : instr_alu_ckadd_struct_exec(struct rte_swx_pipeline *p)
4599 : : {
4600 : 0 : struct thread *t = &p->threads[p->thread_id];
4601 : 0 : struct instruction *ip = t->ip;
4602 : :
4603 : : /* Structs. */
4604 : 0 : __instr_alu_ckadd_struct_exec(p, t, ip);
4605 : :
4606 : : /* Thread. */
4607 : : thread_ip_inc(p);
4608 : 0 : }
4609 : :
4610 : : /*
4611 : : * Register array.
4612 : : */
4613 : : static struct regarray *
4614 : : regarray_find(struct rte_swx_pipeline *p, const char *name);
4615 : :
4616 : : static int
4617 : 0 : instr_regprefetch_translate(struct rte_swx_pipeline *p,
4618 : : struct action *action,
4619 : : char **tokens,
4620 : : int n_tokens,
4621 : : struct instruction *instr,
4622 : : struct instruction_data *data __rte_unused)
4623 : : {
4624 : 0 : char *regarray = tokens[1], *idx = tokens[2];
4625 : : struct regarray *r;
4626 : : struct field *fidx;
4627 : : uint32_t idx_struct_id, idx_val;
4628 : :
4629 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
4630 : :
4631 : : r = regarray_find(p, regarray);
4632 [ # # ]: 0 : CHECK(r, EINVAL);
4633 : :
4634 : : /* REGPREFETCH_RH, REGPREFETCH_RM. */
4635 : 0 : fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4636 [ # # ]: 0 : if (fidx) {
4637 [ # # # # ]: 0 : CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
4638 : :
4639 : 0 : instr->type = INSTR_REGPREFETCH_RM;
4640 [ # # ]: 0 : if (idx[0] == 'h')
4641 : 0 : instr->type = INSTR_REGPREFETCH_RH;
4642 : :
4643 : 0 : instr->regarray.regarray_id = r->id;
4644 : 0 : instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4645 : 0 : instr->regarray.idx.n_bits = fidx->n_bits;
4646 : 0 : instr->regarray.idx.offset = fidx->offset / 8;
4647 : 0 : instr->regarray.dstsrc_val = 0; /* Unused. */
4648 : 0 : return 0;
4649 : : }
4650 : :
4651 : : /* REGPREFETCH_RI. */
4652 : 0 : idx_val = strtoul(idx, &idx, 0);
4653 [ # # ]: 0 : CHECK(!idx[0], EINVAL);
4654 : :
4655 : 0 : instr->type = INSTR_REGPREFETCH_RI;
4656 : 0 : instr->regarray.regarray_id = r->id;
4657 : 0 : instr->regarray.idx_val = idx_val;
4658 : 0 : instr->regarray.dstsrc_val = 0; /* Unused. */
4659 : 0 : return 0;
4660 : : }
4661 : :
4662 : : static int
4663 : 0 : instr_regrd_translate(struct rte_swx_pipeline *p,
4664 : : struct action *action,
4665 : : char **tokens,
4666 : : int n_tokens,
4667 : : struct instruction *instr,
4668 : : struct instruction_data *data __rte_unused)
4669 : : {
4670 : 0 : char *dst = tokens[1], *regarray = tokens[2], *idx = tokens[3];
4671 : : struct regarray *r;
4672 : : struct field *fdst, *fidx;
4673 : : uint32_t dst_struct_id, idx_struct_id, idx_val;
4674 : :
4675 [ # # ]: 0 : CHECK(n_tokens == 4, EINVAL);
4676 : :
4677 : : r = regarray_find(p, regarray);
4678 [ # # ]: 0 : CHECK(r, EINVAL);
4679 : :
4680 : 0 : fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4681 [ # # ]: 0 : CHECK(fdst, EINVAL);
4682 [ # # # # ]: 0 : CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
4683 : :
4684 : : /* REGRD_HRH, REGRD_HRM, REGRD_MRH, REGRD_MRM. */
4685 : 0 : fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4686 [ # # ]: 0 : if (fidx) {
4687 [ # # # # ]: 0 : CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
4688 : :
4689 : 0 : instr->type = INSTR_REGRD_MRM;
4690 [ # # # # ]: 0 : if (dst[0] == 'h' && idx[0] != 'h')
4691 : 0 : instr->type = INSTR_REGRD_HRM;
4692 [ # # # # ]: 0 : if (dst[0] != 'h' && idx[0] == 'h')
4693 : 0 : instr->type = INSTR_REGRD_MRH;
4694 [ # # # # ]: 0 : if (dst[0] == 'h' && idx[0] == 'h')
4695 : 0 : instr->type = INSTR_REGRD_HRH;
4696 : :
4697 : 0 : instr->regarray.regarray_id = r->id;
4698 : 0 : instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4699 : 0 : instr->regarray.idx.n_bits = fidx->n_bits;
4700 : 0 : instr->regarray.idx.offset = fidx->offset / 8;
4701 : 0 : instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
4702 : 0 : instr->regarray.dstsrc.n_bits = fdst->n_bits;
4703 : 0 : instr->regarray.dstsrc.offset = fdst->offset / 8;
4704 : 0 : return 0;
4705 : : }
4706 : :
4707 : : /* REGRD_MRI, REGRD_HRI. */
4708 : 0 : idx_val = strtoul(idx, &idx, 0);
4709 [ # # ]: 0 : CHECK(!idx[0], EINVAL);
4710 : :
4711 : 0 : instr->type = INSTR_REGRD_MRI;
4712 [ # # ]: 0 : if (dst[0] == 'h')
4713 : 0 : instr->type = INSTR_REGRD_HRI;
4714 : :
4715 : 0 : instr->regarray.regarray_id = r->id;
4716 : 0 : instr->regarray.idx_val = idx_val;
4717 : 0 : instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
4718 : 0 : instr->regarray.dstsrc.n_bits = fdst->n_bits;
4719 : 0 : instr->regarray.dstsrc.offset = fdst->offset / 8;
4720 : 0 : return 0;
4721 : : }
4722 : :
4723 : : static int
4724 : 0 : instr_regwr_translate(struct rte_swx_pipeline *p,
4725 : : struct action *action,
4726 : : char **tokens,
4727 : : int n_tokens,
4728 : : struct instruction *instr,
4729 : : struct instruction_data *data __rte_unused)
4730 : : {
4731 : 0 : char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
4732 : : struct regarray *r;
4733 : : struct field *fidx, *fsrc;
4734 : : uint64_t src_val;
4735 : : uint32_t idx_struct_id, idx_val, src_struct_id;
4736 : :
4737 [ # # ]: 0 : CHECK(n_tokens == 4, EINVAL);
4738 : :
4739 : : r = regarray_find(p, regarray);
4740 [ # # ]: 0 : CHECK(r, EINVAL);
4741 : :
4742 : : /* REGWR_RHH, REGWR_RHM, REGWR_RMH, REGWR_RMM. */
4743 : 0 : fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4744 : 0 : fsrc = struct_field_parse(p, action, src, &src_struct_id);
4745 [ # # ]: 0 : if (fidx && fsrc) {
4746 [ # # # # ]: 0 : CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
4747 [ # # # # ]: 0 : CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
4748 : :
4749 : 0 : instr->type = INSTR_REGWR_RMM;
4750 [ # # # # ]: 0 : if (idx[0] == 'h' && src[0] != 'h')
4751 : 0 : instr->type = INSTR_REGWR_RHM;
4752 [ # # # # ]: 0 : if (idx[0] != 'h' && src[0] == 'h')
4753 : 0 : instr->type = INSTR_REGWR_RMH;
4754 [ # # # # ]: 0 : if (idx[0] == 'h' && src[0] == 'h')
4755 : 0 : instr->type = INSTR_REGWR_RHH;
4756 : :
4757 : 0 : instr->regarray.regarray_id = r->id;
4758 : 0 : instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4759 : 0 : instr->regarray.idx.n_bits = fidx->n_bits;
4760 : 0 : instr->regarray.idx.offset = fidx->offset / 8;
4761 : 0 : instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4762 : 0 : instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4763 : 0 : instr->regarray.dstsrc.offset = fsrc->offset / 8;
4764 : 0 : return 0;
4765 : : }
4766 : :
4767 : : /* REGWR_RHI, REGWR_RMI. */
4768 [ # # ]: 0 : if (fidx && !fsrc) {
4769 [ # # # # ]: 0 : CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
4770 : :
4771 : 0 : src_val = strtoull(src, &src, 0);
4772 [ # # ]: 0 : CHECK(!src[0], EINVAL);
4773 : :
4774 : 0 : instr->type = INSTR_REGWR_RMI;
4775 [ # # ]: 0 : if (idx[0] == 'h')
4776 : 0 : instr->type = INSTR_REGWR_RHI;
4777 : :
4778 : 0 : instr->regarray.regarray_id = r->id;
4779 : 0 : instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4780 : 0 : instr->regarray.idx.n_bits = fidx->n_bits;
4781 : 0 : instr->regarray.idx.offset = fidx->offset / 8;
4782 : 0 : instr->regarray.dstsrc_val = src_val;
4783 : 0 : return 0;
4784 : : }
4785 : :
4786 : : /* REGWR_RIH, REGWR_RIM. */
4787 [ # # ]: 0 : if (!fidx && fsrc) {
4788 : 0 : idx_val = strtoul(idx, &idx, 0);
4789 [ # # ]: 0 : CHECK(!idx[0], EINVAL);
4790 : :
4791 [ # # # # ]: 0 : CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
4792 : :
4793 : 0 : instr->type = INSTR_REGWR_RIM;
4794 [ # # ]: 0 : if (src[0] == 'h')
4795 : 0 : instr->type = INSTR_REGWR_RIH;
4796 : :
4797 : 0 : instr->regarray.regarray_id = r->id;
4798 : 0 : instr->regarray.idx_val = idx_val;
4799 : 0 : instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4800 : 0 : instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4801 : 0 : instr->regarray.dstsrc.offset = fsrc->offset / 8;
4802 : 0 : return 0;
4803 : : }
4804 : :
4805 : : /* REGWR_RII. */
4806 : 0 : src_val = strtoull(src, &src, 0);
4807 [ # # ]: 0 : CHECK(!src[0], EINVAL);
4808 : :
4809 : 0 : idx_val = strtoul(idx, &idx, 0);
4810 [ # # ]: 0 : CHECK(!idx[0], EINVAL);
4811 : :
4812 : 0 : instr->type = INSTR_REGWR_RII;
4813 : 0 : instr->regarray.idx_val = idx_val;
4814 : 0 : instr->regarray.dstsrc_val = src_val;
4815 : :
4816 : 0 : return 0;
4817 : : }
4818 : :
4819 : : static int
4820 : 0 : instr_regadd_translate(struct rte_swx_pipeline *p,
4821 : : struct action *action,
4822 : : char **tokens,
4823 : : int n_tokens,
4824 : : struct instruction *instr,
4825 : : struct instruction_data *data __rte_unused)
4826 : : {
4827 : 0 : char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
4828 : : struct regarray *r;
4829 : : struct field *fidx, *fsrc;
4830 : : uint64_t src_val;
4831 : : uint32_t idx_struct_id, idx_val, src_struct_id;
4832 : :
4833 [ # # ]: 0 : CHECK(n_tokens == 4, EINVAL);
4834 : :
4835 : : r = regarray_find(p, regarray);
4836 [ # # ]: 0 : CHECK(r, EINVAL);
4837 : :
4838 : : /* REGADD_RHH, REGADD_RHM, REGADD_RMH, REGADD_RMM. */
4839 : 0 : fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4840 : 0 : fsrc = struct_field_parse(p, action, src, &src_struct_id);
4841 [ # # ]: 0 : if (fidx && fsrc) {
4842 [ # # # # ]: 0 : CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
4843 [ # # # # ]: 0 : CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
4844 : :
4845 : 0 : instr->type = INSTR_REGADD_RMM;
4846 [ # # # # ]: 0 : if (idx[0] == 'h' && src[0] != 'h')
4847 : 0 : instr->type = INSTR_REGADD_RHM;
4848 [ # # # # ]: 0 : if (idx[0] != 'h' && src[0] == 'h')
4849 : 0 : instr->type = INSTR_REGADD_RMH;
4850 [ # # # # ]: 0 : if (idx[0] == 'h' && src[0] == 'h')
4851 : 0 : instr->type = INSTR_REGADD_RHH;
4852 : :
4853 : 0 : instr->regarray.regarray_id = r->id;
4854 : 0 : instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4855 : 0 : instr->regarray.idx.n_bits = fidx->n_bits;
4856 : 0 : instr->regarray.idx.offset = fidx->offset / 8;
4857 : 0 : instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4858 : 0 : instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4859 : 0 : instr->regarray.dstsrc.offset = fsrc->offset / 8;
4860 : 0 : return 0;
4861 : : }
4862 : :
4863 : : /* REGADD_RHI, REGADD_RMI. */
4864 [ # # ]: 0 : if (fidx && !fsrc) {
4865 [ # # # # ]: 0 : CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
4866 : :
4867 : 0 : src_val = strtoull(src, &src, 0);
4868 [ # # ]: 0 : CHECK(!src[0], EINVAL);
4869 : :
4870 : 0 : instr->type = INSTR_REGADD_RMI;
4871 [ # # ]: 0 : if (idx[0] == 'h')
4872 : 0 : instr->type = INSTR_REGADD_RHI;
4873 : :
4874 : 0 : instr->regarray.regarray_id = r->id;
4875 : 0 : instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4876 : 0 : instr->regarray.idx.n_bits = fidx->n_bits;
4877 : 0 : instr->regarray.idx.offset = fidx->offset / 8;
4878 : 0 : instr->regarray.dstsrc_val = src_val;
4879 : 0 : return 0;
4880 : : }
4881 : :
4882 : : /* REGADD_RIH, REGADD_RIM. */
4883 [ # # ]: 0 : if (!fidx && fsrc) {
4884 : 0 : idx_val = strtoul(idx, &idx, 0);
4885 [ # # ]: 0 : CHECK(!idx[0], EINVAL);
4886 : :
4887 [ # # # # ]: 0 : CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
4888 : :
4889 : 0 : instr->type = INSTR_REGADD_RIM;
4890 [ # # ]: 0 : if (src[0] == 'h')
4891 : 0 : instr->type = INSTR_REGADD_RIH;
4892 : :
4893 : 0 : instr->regarray.regarray_id = r->id;
4894 : 0 : instr->regarray.idx_val = idx_val;
4895 : 0 : instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4896 : 0 : instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4897 : 0 : instr->regarray.dstsrc.offset = fsrc->offset / 8;
4898 : 0 : return 0;
4899 : : }
4900 : :
4901 : : /* REGADD_RII. */
4902 : 0 : src_val = strtoull(src, &src, 0);
4903 [ # # ]: 0 : CHECK(!src[0], EINVAL);
4904 : :
4905 : 0 : idx_val = strtoul(idx, &idx, 0);
4906 [ # # ]: 0 : CHECK(!idx[0], EINVAL);
4907 : :
4908 : 0 : instr->type = INSTR_REGADD_RII;
4909 : 0 : instr->regarray.idx_val = idx_val;
4910 : 0 : instr->regarray.dstsrc_val = src_val;
4911 : 0 : return 0;
4912 : : }
4913 : :
4914 : : static inline void
4915 : 0 : instr_regprefetch_rh_exec(struct rte_swx_pipeline *p)
4916 : : {
4917 : 0 : struct thread *t = &p->threads[p->thread_id];
4918 : 0 : struct instruction *ip = t->ip;
4919 : :
4920 : : /* Structs. */
4921 : 0 : __instr_regprefetch_rh_exec(p, t, ip);
4922 : :
4923 : : /* Thread. */
4924 : : thread_ip_inc(p);
4925 : 0 : }
4926 : :
4927 : : static inline void
4928 : 0 : instr_regprefetch_rm_exec(struct rte_swx_pipeline *p)
4929 : : {
4930 : 0 : struct thread *t = &p->threads[p->thread_id];
4931 : 0 : struct instruction *ip = t->ip;
4932 : :
4933 : : /* Structs. */
4934 : 0 : __instr_regprefetch_rm_exec(p, t, ip);
4935 : :
4936 : : /* Thread. */
4937 : : thread_ip_inc(p);
4938 : 0 : }
4939 : :
4940 : : static inline void
4941 : 0 : instr_regprefetch_ri_exec(struct rte_swx_pipeline *p)
4942 : : {
4943 : 0 : struct thread *t = &p->threads[p->thread_id];
4944 : 0 : struct instruction *ip = t->ip;
4945 : :
4946 : : /* Structs. */
4947 : : __instr_regprefetch_ri_exec(p, t, ip);
4948 : :
4949 : : /* Thread. */
4950 : : thread_ip_inc(p);
4951 : 0 : }
4952 : :
4953 : : static inline void
4954 : 0 : instr_regrd_hrh_exec(struct rte_swx_pipeline *p)
4955 : : {
4956 : 0 : struct thread *t = &p->threads[p->thread_id];
4957 : 0 : struct instruction *ip = t->ip;
4958 : :
4959 : : /* Structs. */
4960 : 0 : __instr_regrd_hrh_exec(p, t, ip);
4961 : :
4962 : : /* Thread. */
4963 : : thread_ip_inc(p);
4964 : 0 : }
4965 : :
4966 : : static inline void
4967 : 0 : instr_regrd_hrm_exec(struct rte_swx_pipeline *p)
4968 : : {
4969 : 0 : struct thread *t = &p->threads[p->thread_id];
4970 : 0 : struct instruction *ip = t->ip;
4971 : :
4972 : : /* Structs. */
4973 : 0 : __instr_regrd_hrm_exec(p, t, ip);
4974 : :
4975 : : /* Thread. */
4976 : : thread_ip_inc(p);
4977 : 0 : }
4978 : :
4979 : : static inline void
4980 : 0 : instr_regrd_mrh_exec(struct rte_swx_pipeline *p)
4981 : : {
4982 : 0 : struct thread *t = &p->threads[p->thread_id];
4983 : 0 : struct instruction *ip = t->ip;
4984 : :
4985 : : /* Structs. */
4986 : 0 : __instr_regrd_mrh_exec(p, t, ip);
4987 : :
4988 : : /* Thread. */
4989 : : thread_ip_inc(p);
4990 : 0 : }
4991 : :
4992 : : static inline void
4993 : 0 : instr_regrd_mrm_exec(struct rte_swx_pipeline *p)
4994 : : {
4995 : 0 : struct thread *t = &p->threads[p->thread_id];
4996 : 0 : struct instruction *ip = t->ip;
4997 : :
4998 : : /* Structs. */
4999 : 0 : __instr_regrd_mrm_exec(p, t, ip);
5000 : :
5001 : : /* Thread. */
5002 : : thread_ip_inc(p);
5003 : 0 : }
5004 : :
5005 : : static inline void
5006 : 0 : instr_regrd_hri_exec(struct rte_swx_pipeline *p)
5007 : : {
5008 : 0 : struct thread *t = &p->threads[p->thread_id];
5009 : 0 : struct instruction *ip = t->ip;
5010 : :
5011 : : /* Structs. */
5012 : 0 : __instr_regrd_hri_exec(p, t, ip);
5013 : :
5014 : : /* Thread. */
5015 : : thread_ip_inc(p);
5016 : 0 : }
5017 : :
5018 : : static inline void
5019 : 0 : instr_regrd_mri_exec(struct rte_swx_pipeline *p)
5020 : : {
5021 : 0 : struct thread *t = &p->threads[p->thread_id];
5022 : 0 : struct instruction *ip = t->ip;
5023 : :
5024 : : /* Structs. */
5025 : 0 : __instr_regrd_mri_exec(p, t, ip);
5026 : :
5027 : : /* Thread. */
5028 : : thread_ip_inc(p);
5029 : 0 : }
5030 : :
5031 : : static inline void
5032 : 0 : instr_regwr_rhh_exec(struct rte_swx_pipeline *p)
5033 : : {
5034 : 0 : struct thread *t = &p->threads[p->thread_id];
5035 : 0 : struct instruction *ip = t->ip;
5036 : :
5037 : : /* Structs. */
5038 : 0 : __instr_regwr_rhh_exec(p, t, ip);
5039 : :
5040 : : /* Thread. */
5041 : : thread_ip_inc(p);
5042 : 0 : }
5043 : :
5044 : : static inline void
5045 : 0 : instr_regwr_rhm_exec(struct rte_swx_pipeline *p)
5046 : : {
5047 : 0 : struct thread *t = &p->threads[p->thread_id];
5048 : 0 : struct instruction *ip = t->ip;
5049 : :
5050 : : /* Structs. */
5051 : 0 : __instr_regwr_rhm_exec(p, t, ip);
5052 : :
5053 : : /* Thread. */
5054 : : thread_ip_inc(p);
5055 : 0 : }
5056 : :
5057 : : static inline void
5058 : 0 : instr_regwr_rmh_exec(struct rte_swx_pipeline *p)
5059 : : {
5060 : 0 : struct thread *t = &p->threads[p->thread_id];
5061 : 0 : struct instruction *ip = t->ip;
5062 : :
5063 : : /* Structs. */
5064 : 0 : __instr_regwr_rmh_exec(p, t, ip);
5065 : :
5066 : : /* Thread. */
5067 : : thread_ip_inc(p);
5068 : 0 : }
5069 : :
5070 : : static inline void
5071 : 0 : instr_regwr_rmm_exec(struct rte_swx_pipeline *p)
5072 : : {
5073 : 0 : struct thread *t = &p->threads[p->thread_id];
5074 : 0 : struct instruction *ip = t->ip;
5075 : :
5076 : : /* Structs. */
5077 : 0 : __instr_regwr_rmm_exec(p, t, ip);
5078 : :
5079 : : /* Thread. */
5080 : : thread_ip_inc(p);
5081 : 0 : }
5082 : :
5083 : : static inline void
5084 : 0 : instr_regwr_rhi_exec(struct rte_swx_pipeline *p)
5085 : : {
5086 : 0 : struct thread *t = &p->threads[p->thread_id];
5087 : 0 : struct instruction *ip = t->ip;
5088 : :
5089 : : /* Structs. */
5090 : 0 : __instr_regwr_rhi_exec(p, t, ip);
5091 : :
5092 : : /* Thread. */
5093 : : thread_ip_inc(p);
5094 : 0 : }
5095 : :
5096 : : static inline void
5097 : 0 : instr_regwr_rmi_exec(struct rte_swx_pipeline *p)
5098 : : {
5099 : 0 : struct thread *t = &p->threads[p->thread_id];
5100 : 0 : struct instruction *ip = t->ip;
5101 : :
5102 : : /* Structs. */
5103 : 0 : __instr_regwr_rmi_exec(p, t, ip);
5104 : :
5105 : : /* Thread. */
5106 : : thread_ip_inc(p);
5107 : 0 : }
5108 : :
5109 : : static inline void
5110 : 0 : instr_regwr_rih_exec(struct rte_swx_pipeline *p)
5111 : : {
5112 : 0 : struct thread *t = &p->threads[p->thread_id];
5113 : 0 : struct instruction *ip = t->ip;
5114 : :
5115 : : /* Structs. */
5116 : 0 : __instr_regwr_rih_exec(p, t, ip);
5117 : :
5118 : : /* Thread. */
5119 : : thread_ip_inc(p);
5120 : 0 : }
5121 : :
5122 : : static inline void
5123 : 0 : instr_regwr_rim_exec(struct rte_swx_pipeline *p)
5124 : : {
5125 : 0 : struct thread *t = &p->threads[p->thread_id];
5126 : 0 : struct instruction *ip = t->ip;
5127 : :
5128 : : /* Structs. */
5129 : 0 : __instr_regwr_rim_exec(p, t, ip);
5130 : :
5131 : : /* Thread. */
5132 : : thread_ip_inc(p);
5133 : 0 : }
5134 : :
5135 : : static inline void
5136 : 0 : instr_regwr_rii_exec(struct rte_swx_pipeline *p)
5137 : : {
5138 : 0 : struct thread *t = &p->threads[p->thread_id];
5139 : 0 : struct instruction *ip = t->ip;
5140 : :
5141 : : /* Structs. */
5142 : : __instr_regwr_rii_exec(p, t, ip);
5143 : :
5144 : : /* Thread. */
5145 : : thread_ip_inc(p);
5146 : 0 : }
5147 : :
5148 : : static inline void
5149 : 0 : instr_regadd_rhh_exec(struct rte_swx_pipeline *p)
5150 : : {
5151 : 0 : struct thread *t = &p->threads[p->thread_id];
5152 : 0 : struct instruction *ip = t->ip;
5153 : :
5154 : : /* Structs. */
5155 : 0 : __instr_regadd_rhh_exec(p, t, ip);
5156 : :
5157 : : /* Thread. */
5158 : : thread_ip_inc(p);
5159 : 0 : }
5160 : :
5161 : : static inline void
5162 : 0 : instr_regadd_rhm_exec(struct rte_swx_pipeline *p)
5163 : : {
5164 : 0 : struct thread *t = &p->threads[p->thread_id];
5165 : 0 : struct instruction *ip = t->ip;
5166 : :
5167 : : /* Structs. */
5168 : 0 : __instr_regadd_rhm_exec(p, t, ip);
5169 : :
5170 : : /* Thread. */
5171 : : thread_ip_inc(p);
5172 : 0 : }
5173 : :
5174 : : static inline void
5175 : 0 : instr_regadd_rmh_exec(struct rte_swx_pipeline *p)
5176 : : {
5177 : 0 : struct thread *t = &p->threads[p->thread_id];
5178 : 0 : struct instruction *ip = t->ip;
5179 : :
5180 : : /* Structs. */
5181 : 0 : __instr_regadd_rmh_exec(p, t, ip);
5182 : :
5183 : : /* Thread. */
5184 : : thread_ip_inc(p);
5185 : 0 : }
5186 : :
5187 : : static inline void
5188 : 0 : instr_regadd_rmm_exec(struct rte_swx_pipeline *p)
5189 : : {
5190 : 0 : struct thread *t = &p->threads[p->thread_id];
5191 : 0 : struct instruction *ip = t->ip;
5192 : :
5193 : : /* Structs. */
5194 : 0 : __instr_regadd_rmm_exec(p, t, ip);
5195 : :
5196 : : /* Thread. */
5197 : : thread_ip_inc(p);
5198 : 0 : }
5199 : :
5200 : : static inline void
5201 : 0 : instr_regadd_rhi_exec(struct rte_swx_pipeline *p)
5202 : : {
5203 : 0 : struct thread *t = &p->threads[p->thread_id];
5204 : 0 : struct instruction *ip = t->ip;
5205 : :
5206 : : /* Structs. */
5207 : 0 : __instr_regadd_rhi_exec(p, t, ip);
5208 : :
5209 : : /* Thread. */
5210 : : thread_ip_inc(p);
5211 : 0 : }
5212 : :
5213 : : static inline void
5214 : 0 : instr_regadd_rmi_exec(struct rte_swx_pipeline *p)
5215 : : {
5216 : 0 : struct thread *t = &p->threads[p->thread_id];
5217 : 0 : struct instruction *ip = t->ip;
5218 : :
5219 : : /* Structs. */
5220 : 0 : __instr_regadd_rmi_exec(p, t, ip);
5221 : :
5222 : : /* Thread. */
5223 : : thread_ip_inc(p);
5224 : 0 : }
5225 : :
5226 : : static inline void
5227 : 0 : instr_regadd_rih_exec(struct rte_swx_pipeline *p)
5228 : : {
5229 : 0 : struct thread *t = &p->threads[p->thread_id];
5230 : 0 : struct instruction *ip = t->ip;
5231 : :
5232 : : /* Structs. */
5233 : 0 : __instr_regadd_rih_exec(p, t, ip);
5234 : :
5235 : : /* Thread. */
5236 : : thread_ip_inc(p);
5237 : 0 : }
5238 : :
5239 : : static inline void
5240 : 0 : instr_regadd_rim_exec(struct rte_swx_pipeline *p)
5241 : : {
5242 : 0 : struct thread *t = &p->threads[p->thread_id];
5243 : 0 : struct instruction *ip = t->ip;
5244 : :
5245 : : /* Structs. */
5246 : 0 : __instr_regadd_rim_exec(p, t, ip);
5247 : :
5248 : : /* Thread. */
5249 : : thread_ip_inc(p);
5250 : 0 : }
5251 : :
5252 : : static inline void
5253 : 0 : instr_regadd_rii_exec(struct rte_swx_pipeline *p)
5254 : : {
5255 : 0 : struct thread *t = &p->threads[p->thread_id];
5256 : 0 : struct instruction *ip = t->ip;
5257 : :
5258 : : /* Structs. */
5259 : : __instr_regadd_rii_exec(p, t, ip);
5260 : :
5261 : : /* Thread. */
5262 : : thread_ip_inc(p);
5263 : 0 : }
5264 : :
5265 : : /*
5266 : : * metarray.
5267 : : */
5268 : : static struct metarray *
5269 : : metarray_find(struct rte_swx_pipeline *p, const char *name);
5270 : :
5271 : : static int
5272 : 0 : instr_metprefetch_translate(struct rte_swx_pipeline *p,
5273 : : struct action *action,
5274 : : char **tokens,
5275 : : int n_tokens,
5276 : : struct instruction *instr,
5277 : : struct instruction_data *data __rte_unused)
5278 : : {
5279 : 0 : char *metarray = tokens[1], *idx = tokens[2];
5280 : : struct metarray *m;
5281 : : struct field *fidx;
5282 : : uint32_t idx_struct_id, idx_val;
5283 : :
5284 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
5285 : :
5286 : : m = metarray_find(p, metarray);
5287 [ # # ]: 0 : CHECK(m, EINVAL);
5288 : :
5289 : : /* METPREFETCH_H, METPREFETCH_M. */
5290 : 0 : fidx = struct_field_parse(p, action, idx, &idx_struct_id);
5291 [ # # ]: 0 : if (fidx) {
5292 [ # # # # ]: 0 : CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
5293 : :
5294 : 0 : instr->type = INSTR_METPREFETCH_M;
5295 [ # # ]: 0 : if (idx[0] == 'h')
5296 : 0 : instr->type = INSTR_METPREFETCH_H;
5297 : :
5298 : 0 : instr->meter.metarray_id = m->id;
5299 : 0 : instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
5300 : 0 : instr->meter.idx.n_bits = fidx->n_bits;
5301 : 0 : instr->meter.idx.offset = fidx->offset / 8;
5302 : 0 : return 0;
5303 : : }
5304 : :
5305 : : /* METPREFETCH_I. */
5306 : 0 : idx_val = strtoul(idx, &idx, 0);
5307 [ # # ]: 0 : CHECK(!idx[0], EINVAL);
5308 : :
5309 : 0 : instr->type = INSTR_METPREFETCH_I;
5310 : 0 : instr->meter.metarray_id = m->id;
5311 : 0 : instr->meter.idx_val = idx_val;
5312 : 0 : return 0;
5313 : : }
5314 : :
5315 : : static int
5316 : 0 : instr_meter_translate(struct rte_swx_pipeline *p,
5317 : : struct action *action,
5318 : : char **tokens,
5319 : : int n_tokens,
5320 : : struct instruction *instr,
5321 : : struct instruction_data *data __rte_unused)
5322 : : {
5323 : 0 : char *metarray = tokens[1], *idx = tokens[2], *length = tokens[3];
5324 : 0 : char *color_in = tokens[4], *color_out = tokens[5];
5325 : : struct metarray *m;
5326 : : struct field *fidx, *flength, *fcin, *fcout;
5327 : : uint32_t idx_struct_id, length_struct_id;
5328 : : uint32_t color_in_struct_id, color_out_struct_id;
5329 : :
5330 [ # # ]: 0 : CHECK(n_tokens == 6, EINVAL);
5331 : :
5332 : : m = metarray_find(p, metarray);
5333 [ # # ]: 0 : CHECK(m, EINVAL);
5334 : :
5335 : 0 : fidx = struct_field_parse(p, action, idx, &idx_struct_id);
5336 : :
5337 : 0 : flength = struct_field_parse(p, action, length, &length_struct_id);
5338 [ # # ]: 0 : CHECK(flength, EINVAL);
5339 [ # # # # ]: 0 : CHECK(!flength->var_size && (flength->n_bits <= 64), EINVAL);
5340 : :
5341 : 0 : fcin = struct_field_parse(p, action, color_in, &color_in_struct_id);
5342 : :
5343 : 0 : fcout = struct_field_parse(p, NULL, color_out, &color_out_struct_id);
5344 [ # # ]: 0 : CHECK(fcout, EINVAL);
5345 [ # # # # ]: 0 : CHECK(!fcout->var_size && (fcout->n_bits <= 64), EINVAL);
5346 : :
5347 : : /* index = HMEFT, length = HMEFT, color_in = MEFT, color_out = MEF. */
5348 [ # # ]: 0 : if (fidx && fcin) {
5349 [ # # # # ]: 0 : CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
5350 [ # # # # ]: 0 : CHECK(!fcin->var_size && (fcin->n_bits <= 64), EINVAL);
5351 : :
5352 : 0 : instr->type = INSTR_METER_MMM;
5353 [ # # # # ]: 0 : if (idx[0] == 'h' && length[0] == 'h')
5354 : 0 : instr->type = INSTR_METER_HHM;
5355 [ # # # # ]: 0 : if (idx[0] == 'h' && length[0] != 'h')
5356 : 0 : instr->type = INSTR_METER_HMM;
5357 [ # # # # ]: 0 : if (idx[0] != 'h' && length[0] == 'h')
5358 : 0 : instr->type = INSTR_METER_MHM;
5359 : :
5360 : 0 : instr->meter.metarray_id = m->id;
5361 : :
5362 : 0 : instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
5363 : 0 : instr->meter.idx.n_bits = fidx->n_bits;
5364 : 0 : instr->meter.idx.offset = fidx->offset / 8;
5365 : :
5366 : 0 : instr->meter.length.struct_id = (uint8_t)length_struct_id;
5367 : 0 : instr->meter.length.n_bits = flength->n_bits;
5368 : 0 : instr->meter.length.offset = flength->offset / 8;
5369 : :
5370 : 0 : instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
5371 : 0 : instr->meter.color_in.n_bits = fcin->n_bits;
5372 : 0 : instr->meter.color_in.offset = fcin->offset / 8;
5373 : :
5374 : 0 : instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5375 : 0 : instr->meter.color_out.n_bits = fcout->n_bits;
5376 : 0 : instr->meter.color_out.offset = fcout->offset / 8;
5377 : : }
5378 : :
5379 : : /* index = HMEFT, length = HMEFT, color_in = I, color_out = MEF. */
5380 [ # # ]: 0 : if (fidx && !fcin) {
5381 : : uint32_t color_in_val;
5382 : :
5383 [ # # # # ]: 0 : CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
5384 : :
5385 : 0 : color_in_val = strtoul(color_in, &color_in, 0);
5386 [ # # ]: 0 : CHECK(!color_in[0], EINVAL);
5387 : :
5388 : 0 : instr->type = INSTR_METER_MMI;
5389 [ # # # # ]: 0 : if (idx[0] == 'h' && length[0] == 'h')
5390 : 0 : instr->type = INSTR_METER_HHI;
5391 [ # # # # ]: 0 : if (idx[0] == 'h' && length[0] != 'h')
5392 : 0 : instr->type = INSTR_METER_HMI;
5393 [ # # # # ]: 0 : if (idx[0] != 'h' && length[0] == 'h')
5394 : 0 : instr->type = INSTR_METER_MHI;
5395 : :
5396 : 0 : instr->meter.metarray_id = m->id;
5397 : :
5398 : 0 : instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
5399 : 0 : instr->meter.idx.n_bits = fidx->n_bits;
5400 : 0 : instr->meter.idx.offset = fidx->offset / 8;
5401 : :
5402 : 0 : instr->meter.length.struct_id = (uint8_t)length_struct_id;
5403 : 0 : instr->meter.length.n_bits = flength->n_bits;
5404 : 0 : instr->meter.length.offset = flength->offset / 8;
5405 : :
5406 : 0 : instr->meter.color_in_val = color_in_val;
5407 : :
5408 : 0 : instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5409 : 0 : instr->meter.color_out.n_bits = fcout->n_bits;
5410 : 0 : instr->meter.color_out.offset = fcout->offset / 8;
5411 : : }
5412 : :
5413 : : /* index = I, length = HMEFT, color_in = MEFT, color_out = MEF. */
5414 [ # # ]: 0 : if (!fidx && fcin) {
5415 : : uint32_t idx_val;
5416 : :
5417 : 0 : idx_val = strtoul(idx, &idx, 0);
5418 [ # # ]: 0 : CHECK(!idx[0], EINVAL);
5419 : :
5420 [ # # # # ]: 0 : CHECK(!fcin->var_size && (fcin->n_bits <= 64), EINVAL);
5421 : :
5422 : 0 : instr->type = INSTR_METER_IMM;
5423 [ # # ]: 0 : if (length[0] == 'h')
5424 : 0 : instr->type = INSTR_METER_IHM;
5425 : :
5426 : 0 : instr->meter.metarray_id = m->id;
5427 : :
5428 : 0 : instr->meter.idx_val = idx_val;
5429 : :
5430 : 0 : instr->meter.length.struct_id = (uint8_t)length_struct_id;
5431 : 0 : instr->meter.length.n_bits = flength->n_bits;
5432 : 0 : instr->meter.length.offset = flength->offset / 8;
5433 : :
5434 : 0 : instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
5435 : 0 : instr->meter.color_in.n_bits = fcin->n_bits;
5436 : 0 : instr->meter.color_in.offset = fcin->offset / 8;
5437 : :
5438 : 0 : instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5439 : 0 : instr->meter.color_out.n_bits = fcout->n_bits;
5440 : 0 : instr->meter.color_out.offset = fcout->offset / 8;
5441 : : }
5442 : :
5443 : : /* index = I, length = HMEFT, color_in = I, color_out = MEF. */
5444 [ # # ]: 0 : if (!fidx && !fcin) {
5445 : : uint32_t idx_val, color_in_val;
5446 : :
5447 : 0 : idx_val = strtoul(idx, &idx, 0);
5448 [ # # ]: 0 : CHECK(!idx[0], EINVAL);
5449 : :
5450 : 0 : color_in_val = strtoul(color_in, &color_in, 0);
5451 [ # # ]: 0 : CHECK(!color_in[0], EINVAL);
5452 : :
5453 : 0 : instr->type = INSTR_METER_IMI;
5454 [ # # ]: 0 : if (length[0] == 'h')
5455 : 0 : instr->type = INSTR_METER_IHI;
5456 : :
5457 : 0 : instr->meter.metarray_id = m->id;
5458 : :
5459 : 0 : instr->meter.idx_val = idx_val;
5460 : :
5461 : 0 : instr->meter.length.struct_id = (uint8_t)length_struct_id;
5462 : 0 : instr->meter.length.n_bits = flength->n_bits;
5463 : 0 : instr->meter.length.offset = flength->offset / 8;
5464 : :
5465 : 0 : instr->meter.color_in_val = color_in_val;
5466 : :
5467 : 0 : instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5468 : 0 : instr->meter.color_out.n_bits = fcout->n_bits;
5469 : 0 : instr->meter.color_out.offset = fcout->offset / 8;
5470 : : }
5471 : :
5472 : : return 0;
5473 : : }
5474 : :
5475 : : static inline void
5476 : 0 : instr_metprefetch_h_exec(struct rte_swx_pipeline *p)
5477 : : {
5478 : 0 : struct thread *t = &p->threads[p->thread_id];
5479 : 0 : struct instruction *ip = t->ip;
5480 : :
5481 : : /* Structs. */
5482 : : __instr_metprefetch_h_exec(p, t, ip);
5483 : :
5484 : : /* Thread. */
5485 : : thread_ip_inc(p);
5486 : 0 : }
5487 : :
5488 : : static inline void
5489 : 0 : instr_metprefetch_m_exec(struct rte_swx_pipeline *p)
5490 : : {
5491 : 0 : struct thread *t = &p->threads[p->thread_id];
5492 : 0 : struct instruction *ip = t->ip;
5493 : :
5494 : : /* Structs. */
5495 : 0 : __instr_metprefetch_m_exec(p, t, ip);
5496 : :
5497 : : /* Thread. */
5498 : : thread_ip_inc(p);
5499 : 0 : }
5500 : :
5501 : : static inline void
5502 : 0 : instr_metprefetch_i_exec(struct rte_swx_pipeline *p)
5503 : : {
5504 : 0 : struct thread *t = &p->threads[p->thread_id];
5505 : 0 : struct instruction *ip = t->ip;
5506 : :
5507 : : /* Structs. */
5508 : : __instr_metprefetch_i_exec(p, t, ip);
5509 : :
5510 : : /* Thread. */
5511 : : thread_ip_inc(p);
5512 : 0 : }
5513 : :
5514 : : static inline void
5515 : 0 : instr_meter_hhm_exec(struct rte_swx_pipeline *p)
5516 : : {
5517 : 0 : struct thread *t = &p->threads[p->thread_id];
5518 : 0 : struct instruction *ip = t->ip;
5519 : :
5520 : : /* Structs. */
5521 : 0 : __instr_meter_hhm_exec(p, t, ip);
5522 : :
5523 : : /* Thread. */
5524 : : thread_ip_inc(p);
5525 : 0 : }
5526 : :
5527 : : static inline void
5528 : 0 : instr_meter_hhi_exec(struct rte_swx_pipeline *p)
5529 : : {
5530 : 0 : struct thread *t = &p->threads[p->thread_id];
5531 : 0 : struct instruction *ip = t->ip;
5532 : :
5533 : : /* Structs. */
5534 : 0 : __instr_meter_hhi_exec(p, t, ip);
5535 : :
5536 : : /* Thread. */
5537 : : thread_ip_inc(p);
5538 : 0 : }
5539 : :
5540 : : static inline void
5541 : 0 : instr_meter_hmm_exec(struct rte_swx_pipeline *p)
5542 : : {
5543 : 0 : struct thread *t = &p->threads[p->thread_id];
5544 : 0 : struct instruction *ip = t->ip;
5545 : :
5546 : : /* Structs. */
5547 : 0 : __instr_meter_hmm_exec(p, t, ip);
5548 : :
5549 : : /* Thread. */
5550 : : thread_ip_inc(p);
5551 : 0 : }
5552 : :
5553 : : static inline void
5554 : 0 : instr_meter_hmi_exec(struct rte_swx_pipeline *p)
5555 : : {
5556 : 0 : struct thread *t = &p->threads[p->thread_id];
5557 : 0 : struct instruction *ip = t->ip;
5558 : :
5559 : : /* Structs. */
5560 : 0 : __instr_meter_hmi_exec(p, t, ip);
5561 : :
5562 : : /* Thread. */
5563 : : thread_ip_inc(p);
5564 : 0 : }
5565 : :
5566 : : static inline void
5567 : 0 : instr_meter_mhm_exec(struct rte_swx_pipeline *p)
5568 : : {
5569 : 0 : struct thread *t = &p->threads[p->thread_id];
5570 : 0 : struct instruction *ip = t->ip;
5571 : :
5572 : : /* Structs. */
5573 : 0 : __instr_meter_mhm_exec(p, t, ip);
5574 : :
5575 : : /* Thread. */
5576 : : thread_ip_inc(p);
5577 : 0 : }
5578 : :
5579 : : static inline void
5580 : 0 : instr_meter_mhi_exec(struct rte_swx_pipeline *p)
5581 : : {
5582 : 0 : struct thread *t = &p->threads[p->thread_id];
5583 : 0 : struct instruction *ip = t->ip;
5584 : :
5585 : : /* Structs. */
5586 : 0 : __instr_meter_mhi_exec(p, t, ip);
5587 : :
5588 : : /* Thread. */
5589 : : thread_ip_inc(p);
5590 : 0 : }
5591 : :
5592 : : static inline void
5593 : 0 : instr_meter_mmm_exec(struct rte_swx_pipeline *p)
5594 : : {
5595 : 0 : struct thread *t = &p->threads[p->thread_id];
5596 : 0 : struct instruction *ip = t->ip;
5597 : :
5598 : : /* Structs. */
5599 : 0 : __instr_meter_mmm_exec(p, t, ip);
5600 : :
5601 : : /* Thread. */
5602 : : thread_ip_inc(p);
5603 : 0 : }
5604 : :
5605 : : static inline void
5606 : 0 : instr_meter_mmi_exec(struct rte_swx_pipeline *p)
5607 : : {
5608 : 0 : struct thread *t = &p->threads[p->thread_id];
5609 : 0 : struct instruction *ip = t->ip;
5610 : :
5611 : : /* Structs. */
5612 : 0 : __instr_meter_mmi_exec(p, t, ip);
5613 : :
5614 : : /* Thread. */
5615 : : thread_ip_inc(p);
5616 : 0 : }
5617 : :
5618 : : static inline void
5619 : 0 : instr_meter_ihm_exec(struct rte_swx_pipeline *p)
5620 : : {
5621 : 0 : struct thread *t = &p->threads[p->thread_id];
5622 : 0 : struct instruction *ip = t->ip;
5623 : :
5624 : : /* Structs. */
5625 : 0 : __instr_meter_ihm_exec(p, t, ip);
5626 : :
5627 : : /* Thread. */
5628 : : thread_ip_inc(p);
5629 : 0 : }
5630 : :
5631 : : static inline void
5632 : 0 : instr_meter_ihi_exec(struct rte_swx_pipeline *p)
5633 : : {
5634 : 0 : struct thread *t = &p->threads[p->thread_id];
5635 : 0 : struct instruction *ip = t->ip;
5636 : :
5637 : : /* Structs. */
5638 : 0 : __instr_meter_ihi_exec(p, t, ip);
5639 : :
5640 : : /* Thread. */
5641 : : thread_ip_inc(p);
5642 : 0 : }
5643 : :
5644 : : static inline void
5645 : 0 : instr_meter_imm_exec(struct rte_swx_pipeline *p)
5646 : : {
5647 : 0 : struct thread *t = &p->threads[p->thread_id];
5648 : 0 : struct instruction *ip = t->ip;
5649 : :
5650 : : /* Structs. */
5651 : 0 : __instr_meter_imm_exec(p, t, ip);
5652 : :
5653 : : /* Thread. */
5654 : : thread_ip_inc(p);
5655 : 0 : }
5656 : :
5657 : : static inline void
5658 : 0 : instr_meter_imi_exec(struct rte_swx_pipeline *p)
5659 : : {
5660 : 0 : struct thread *t = &p->threads[p->thread_id];
5661 : 0 : struct instruction *ip = t->ip;
5662 : :
5663 : : /* Structs. */
5664 : 0 : __instr_meter_imi_exec(p, t, ip);
5665 : :
5666 : : /* Thread. */
5667 : : thread_ip_inc(p);
5668 : 0 : }
5669 : :
5670 : : /*
5671 : : * jmp.
5672 : : */
5673 : : static int
5674 : : instr_jmp_translate(struct rte_swx_pipeline *p __rte_unused,
5675 : : struct action *action __rte_unused,
5676 : : char **tokens,
5677 : : int n_tokens,
5678 : : struct instruction *instr,
5679 : : struct instruction_data *data)
5680 : : {
5681 : 0 : CHECK(n_tokens == 2, EINVAL);
5682 : :
5683 : 0 : strcpy(data->jmp_label, tokens[1]);
5684 : :
5685 : 0 : instr->type = INSTR_JMP;
5686 : 0 : instr->jmp.ip = NULL; /* Resolved later. */
5687 : 0 : return 0;
5688 : : }
5689 : :
5690 : : static int
5691 : 0 : instr_jmp_valid_translate(struct rte_swx_pipeline *p,
5692 : : struct action *action __rte_unused,
5693 : : char **tokens,
5694 : : int n_tokens,
5695 : : struct instruction *instr,
5696 : : struct instruction_data *data)
5697 : : {
5698 : : struct header *h;
5699 : :
5700 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
5701 : :
5702 : 0 : strcpy(data->jmp_label, tokens[1]);
5703 : :
5704 : 0 : h = header_parse(p, tokens[2]);
5705 [ # # ]: 0 : CHECK(h, EINVAL);
5706 : :
5707 : 0 : instr->type = INSTR_JMP_VALID;
5708 : 0 : instr->jmp.ip = NULL; /* Resolved later. */
5709 : 0 : instr->jmp.header_id = h->id;
5710 : 0 : return 0;
5711 : : }
5712 : :
5713 : : static int
5714 : 0 : instr_jmp_invalid_translate(struct rte_swx_pipeline *p,
5715 : : struct action *action __rte_unused,
5716 : : char **tokens,
5717 : : int n_tokens,
5718 : : struct instruction *instr,
5719 : : struct instruction_data *data)
5720 : : {
5721 : : struct header *h;
5722 : :
5723 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
5724 : :
5725 : 0 : strcpy(data->jmp_label, tokens[1]);
5726 : :
5727 : 0 : h = header_parse(p, tokens[2]);
5728 [ # # ]: 0 : CHECK(h, EINVAL);
5729 : :
5730 : 0 : instr->type = INSTR_JMP_INVALID;
5731 : 0 : instr->jmp.ip = NULL; /* Resolved later. */
5732 : 0 : instr->jmp.header_id = h->id;
5733 : 0 : return 0;
5734 : : }
5735 : :
5736 : : static int
5737 : : instr_jmp_hit_translate(struct rte_swx_pipeline *p __rte_unused,
5738 : : struct action *action,
5739 : : char **tokens,
5740 : : int n_tokens,
5741 : : struct instruction *instr,
5742 : : struct instruction_data *data)
5743 : : {
5744 : 0 : CHECK(!action, EINVAL);
5745 [ # # ]: 0 : CHECK(n_tokens == 2, EINVAL);
5746 : :
5747 : 0 : strcpy(data->jmp_label, tokens[1]);
5748 : :
5749 : 0 : instr->type = INSTR_JMP_HIT;
5750 : 0 : instr->jmp.ip = NULL; /* Resolved later. */
5751 : 0 : return 0;
5752 : : }
5753 : :
5754 : : static int
5755 : : instr_jmp_miss_translate(struct rte_swx_pipeline *p __rte_unused,
5756 : : struct action *action,
5757 : : char **tokens,
5758 : : int n_tokens,
5759 : : struct instruction *instr,
5760 : : struct instruction_data *data)
5761 : : {
5762 : 0 : CHECK(!action, EINVAL);
5763 [ # # ]: 0 : CHECK(n_tokens == 2, EINVAL);
5764 : :
5765 : 0 : strcpy(data->jmp_label, tokens[1]);
5766 : :
5767 : 0 : instr->type = INSTR_JMP_MISS;
5768 : 0 : instr->jmp.ip = NULL; /* Resolved later. */
5769 : 0 : return 0;
5770 : : }
5771 : :
5772 : : static int
5773 : 0 : instr_jmp_action_hit_translate(struct rte_swx_pipeline *p,
5774 : : struct action *action,
5775 : : char **tokens,
5776 : : int n_tokens,
5777 : : struct instruction *instr,
5778 : : struct instruction_data *data)
5779 : : {
5780 : : struct action *a;
5781 : :
5782 [ # # ]: 0 : CHECK(!action, EINVAL);
5783 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
5784 : :
5785 : 0 : strcpy(data->jmp_label, tokens[1]);
5786 : :
5787 : 0 : a = action_find(p, tokens[2]);
5788 [ # # ]: 0 : CHECK(a, EINVAL);
5789 : :
5790 : 0 : instr->type = INSTR_JMP_ACTION_HIT;
5791 : 0 : instr->jmp.ip = NULL; /* Resolved later. */
5792 : 0 : instr->jmp.action_id = a->id;
5793 : 0 : return 0;
5794 : : }
5795 : :
5796 : : static int
5797 : 0 : instr_jmp_action_miss_translate(struct rte_swx_pipeline *p,
5798 : : struct action *action,
5799 : : char **tokens,
5800 : : int n_tokens,
5801 : : struct instruction *instr,
5802 : : struct instruction_data *data)
5803 : : {
5804 : : struct action *a;
5805 : :
5806 [ # # ]: 0 : CHECK(!action, EINVAL);
5807 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
5808 : :
5809 : 0 : strcpy(data->jmp_label, tokens[1]);
5810 : :
5811 : 0 : a = action_find(p, tokens[2]);
5812 [ # # ]: 0 : CHECK(a, EINVAL);
5813 : :
5814 : 0 : instr->type = INSTR_JMP_ACTION_MISS;
5815 : 0 : instr->jmp.ip = NULL; /* Resolved later. */
5816 : 0 : instr->jmp.action_id = a->id;
5817 : 0 : return 0;
5818 : : }
5819 : :
5820 : : static int
5821 : 0 : instr_jmp_eq_translate(struct rte_swx_pipeline *p,
5822 : : struct action *action,
5823 : : char **tokens,
5824 : : int n_tokens,
5825 : : struct instruction *instr,
5826 : : struct instruction_data *data)
5827 : : {
5828 : 0 : char *a = tokens[2], *b = tokens[3];
5829 : : struct field *fa, *fb;
5830 : : uint64_t b_val;
5831 : : uint32_t a_struct_id, b_struct_id;
5832 : :
5833 [ # # ]: 0 : CHECK(n_tokens == 4, EINVAL);
5834 : :
5835 : 0 : strcpy(data->jmp_label, tokens[1]);
5836 : :
5837 : 0 : fa = struct_field_parse(p, action, a, &a_struct_id);
5838 [ # # ]: 0 : CHECK(fa, EINVAL);
5839 [ # # # # ]: 0 : CHECK(!fa->var_size && (fa->n_bits <= 64), EINVAL);
5840 : :
5841 : : /* JMP_EQ, JMP_EQ_MH, JMP_EQ_HM, JMP_EQ_HH. */
5842 : 0 : fb = struct_field_parse(p, action, b, &b_struct_id);
5843 [ # # ]: 0 : if (fb) {
5844 [ # # # # ]: 0 : CHECK(!fb->var_size && (fb->n_bits <= 64), EINVAL);
5845 : :
5846 : 0 : instr->type = INSTR_JMP_EQ;
5847 [ # # # # ]: 0 : if (a[0] != 'h' && b[0] == 'h')
5848 : 0 : instr->type = INSTR_JMP_EQ_MH;
5849 [ # # # # ]: 0 : if (a[0] == 'h' && b[0] != 'h')
5850 : 0 : instr->type = INSTR_JMP_EQ_HM;
5851 [ # # # # ]: 0 : if (a[0] == 'h' && b[0] == 'h')
5852 : 0 : instr->type = INSTR_JMP_EQ_HH;
5853 : 0 : instr->jmp.ip = NULL; /* Resolved later. */
5854 : :
5855 : 0 : instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5856 : 0 : instr->jmp.a.n_bits = fa->n_bits;
5857 : 0 : instr->jmp.a.offset = fa->offset / 8;
5858 : 0 : instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5859 : 0 : instr->jmp.b.n_bits = fb->n_bits;
5860 : 0 : instr->jmp.b.offset = fb->offset / 8;
5861 : 0 : return 0;
5862 : : }
5863 : :
5864 : : /* JMP_EQ_I. */
5865 : 0 : b_val = strtoull(b, &b, 0);
5866 [ # # ]: 0 : CHECK(!b[0], EINVAL);
5867 : :
5868 [ # # ]: 0 : if (a[0] == 'h')
5869 [ # # ]: 0 : b_val = hton64(b_val) >> (64 - fa->n_bits);
5870 : :
5871 : 0 : instr->type = INSTR_JMP_EQ_I;
5872 : 0 : instr->jmp.ip = NULL; /* Resolved later. */
5873 : 0 : instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5874 : 0 : instr->jmp.a.n_bits = fa->n_bits;
5875 : 0 : instr->jmp.a.offset = fa->offset / 8;
5876 : 0 : instr->jmp.b_val = b_val;
5877 : 0 : return 0;
5878 : : }
5879 : :
5880 : : static int
5881 : 0 : instr_jmp_neq_translate(struct rte_swx_pipeline *p,
5882 : : struct action *action,
5883 : : char **tokens,
5884 : : int n_tokens,
5885 : : struct instruction *instr,
5886 : : struct instruction_data *data)
5887 : : {
5888 : 0 : char *a = tokens[2], *b = tokens[3];
5889 : : struct field *fa, *fb;
5890 : : uint64_t b_val;
5891 : : uint32_t a_struct_id, b_struct_id;
5892 : :
5893 [ # # ]: 0 : CHECK(n_tokens == 4, EINVAL);
5894 : :
5895 : 0 : strcpy(data->jmp_label, tokens[1]);
5896 : :
5897 : 0 : fa = struct_field_parse(p, action, a, &a_struct_id);
5898 [ # # ]: 0 : CHECK(fa, EINVAL);
5899 [ # # # # ]: 0 : CHECK(!fa->var_size && (fa->n_bits <= 64), EINVAL);
5900 : :
5901 : : /* JMP_NEQ, JMP_NEQ_MH, JMP_NEQ_HM, JMP_NEQ_HH. */
5902 : 0 : fb = struct_field_parse(p, action, b, &b_struct_id);
5903 [ # # ]: 0 : if (fb) {
5904 [ # # # # ]: 0 : CHECK(!fb->var_size && (fb->n_bits <= 64), EINVAL);
5905 : :
5906 : 0 : instr->type = INSTR_JMP_NEQ;
5907 [ # # # # ]: 0 : if (a[0] != 'h' && b[0] == 'h')
5908 : 0 : instr->type = INSTR_JMP_NEQ_MH;
5909 [ # # # # ]: 0 : if (a[0] == 'h' && b[0] != 'h')
5910 : 0 : instr->type = INSTR_JMP_NEQ_HM;
5911 [ # # # # ]: 0 : if (a[0] == 'h' && b[0] == 'h')
5912 : 0 : instr->type = INSTR_JMP_NEQ_HH;
5913 : 0 : instr->jmp.ip = NULL; /* Resolved later. */
5914 : :
5915 : 0 : instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5916 : 0 : instr->jmp.a.n_bits = fa->n_bits;
5917 : 0 : instr->jmp.a.offset = fa->offset / 8;
5918 : 0 : instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5919 : 0 : instr->jmp.b.n_bits = fb->n_bits;
5920 : 0 : instr->jmp.b.offset = fb->offset / 8;
5921 : 0 : return 0;
5922 : : }
5923 : :
5924 : : /* JMP_NEQ_I. */
5925 : 0 : b_val = strtoull(b, &b, 0);
5926 [ # # ]: 0 : CHECK(!b[0], EINVAL);
5927 : :
5928 [ # # ]: 0 : if (a[0] == 'h')
5929 [ # # ]: 0 : b_val = hton64(b_val) >> (64 - fa->n_bits);
5930 : :
5931 : 0 : instr->type = INSTR_JMP_NEQ_I;
5932 : 0 : instr->jmp.ip = NULL; /* Resolved later. */
5933 : 0 : instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5934 : 0 : instr->jmp.a.n_bits = fa->n_bits;
5935 : 0 : instr->jmp.a.offset = fa->offset / 8;
5936 : 0 : instr->jmp.b_val = b_val;
5937 : 0 : return 0;
5938 : : }
5939 : :
5940 : : static int
5941 : 0 : instr_jmp_lt_translate(struct rte_swx_pipeline *p,
5942 : : struct action *action,
5943 : : char **tokens,
5944 : : int n_tokens,
5945 : : struct instruction *instr,
5946 : : struct instruction_data *data)
5947 : : {
5948 : 0 : char *a = tokens[2], *b = tokens[3];
5949 : : struct field *fa, *fb;
5950 : : uint64_t b_val;
5951 : : uint32_t a_struct_id, b_struct_id;
5952 : :
5953 [ # # ]: 0 : CHECK(n_tokens == 4, EINVAL);
5954 : :
5955 : 0 : strcpy(data->jmp_label, tokens[1]);
5956 : :
5957 : 0 : fa = struct_field_parse(p, action, a, &a_struct_id);
5958 [ # # ]: 0 : CHECK(fa, EINVAL);
5959 [ # # # # ]: 0 : CHECK(!fa->var_size && (fa->n_bits <= 64), EINVAL);
5960 : :
5961 : : /* JMP_LT, JMP_LT_MH, JMP_LT_HM, JMP_LT_HH. */
5962 : 0 : fb = struct_field_parse(p, action, b, &b_struct_id);
5963 [ # # ]: 0 : if (fb) {
5964 [ # # # # ]: 0 : CHECK(!fb->var_size && (fb->n_bits <= 64), EINVAL);
5965 : :
5966 : 0 : instr->type = INSTR_JMP_LT;
5967 [ # # # # ]: 0 : if (a[0] == 'h' && b[0] != 'h')
5968 : 0 : instr->type = INSTR_JMP_LT_HM;
5969 [ # # # # ]: 0 : if (a[0] != 'h' && b[0] == 'h')
5970 : 0 : instr->type = INSTR_JMP_LT_MH;
5971 [ # # # # ]: 0 : if (a[0] == 'h' && b[0] == 'h')
5972 : 0 : instr->type = INSTR_JMP_LT_HH;
5973 : 0 : instr->jmp.ip = NULL; /* Resolved later. */
5974 : :
5975 : 0 : instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5976 : 0 : instr->jmp.a.n_bits = fa->n_bits;
5977 : 0 : instr->jmp.a.offset = fa->offset / 8;
5978 : 0 : instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5979 : 0 : instr->jmp.b.n_bits = fb->n_bits;
5980 : 0 : instr->jmp.b.offset = fb->offset / 8;
5981 : 0 : return 0;
5982 : : }
5983 : :
5984 : : /* JMP_LT_MI, JMP_LT_HI. */
5985 : 0 : b_val = strtoull(b, &b, 0);
5986 [ # # ]: 0 : CHECK(!b[0], EINVAL);
5987 : :
5988 : 0 : instr->type = INSTR_JMP_LT_MI;
5989 [ # # ]: 0 : if (a[0] == 'h')
5990 : 0 : instr->type = INSTR_JMP_LT_HI;
5991 : 0 : instr->jmp.ip = NULL; /* Resolved later. */
5992 : :
5993 : 0 : instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5994 : 0 : instr->jmp.a.n_bits = fa->n_bits;
5995 : 0 : instr->jmp.a.offset = fa->offset / 8;
5996 : 0 : instr->jmp.b_val = b_val;
5997 : 0 : return 0;
5998 : : }
5999 : :
6000 : : static int
6001 : 0 : instr_jmp_gt_translate(struct rte_swx_pipeline *p,
6002 : : struct action *action,
6003 : : char **tokens,
6004 : : int n_tokens,
6005 : : struct instruction *instr,
6006 : : struct instruction_data *data)
6007 : : {
6008 : 0 : char *a = tokens[2], *b = tokens[3];
6009 : : struct field *fa, *fb;
6010 : : uint64_t b_val;
6011 : : uint32_t a_struct_id, b_struct_id;
6012 : :
6013 [ # # ]: 0 : CHECK(n_tokens == 4, EINVAL);
6014 : :
6015 : 0 : strcpy(data->jmp_label, tokens[1]);
6016 : :
6017 : 0 : fa = struct_field_parse(p, action, a, &a_struct_id);
6018 [ # # ]: 0 : CHECK(fa, EINVAL);
6019 [ # # # # ]: 0 : CHECK(!fa->var_size && (fa->n_bits <= 64), EINVAL);
6020 : :
6021 : : /* JMP_GT, JMP_GT_MH, JMP_GT_HM, JMP_GT_HH. */
6022 : 0 : fb = struct_field_parse(p, action, b, &b_struct_id);
6023 [ # # ]: 0 : if (fb) {
6024 [ # # # # ]: 0 : CHECK(!fb->var_size && (fb->n_bits <= 64), EINVAL);
6025 : :
6026 : 0 : instr->type = INSTR_JMP_GT;
6027 [ # # # # ]: 0 : if (a[0] == 'h' && b[0] != 'h')
6028 : 0 : instr->type = INSTR_JMP_GT_HM;
6029 [ # # # # ]: 0 : if (a[0] != 'h' && b[0] == 'h')
6030 : 0 : instr->type = INSTR_JMP_GT_MH;
6031 [ # # # # ]: 0 : if (a[0] == 'h' && b[0] == 'h')
6032 : 0 : instr->type = INSTR_JMP_GT_HH;
6033 : 0 : instr->jmp.ip = NULL; /* Resolved later. */
6034 : :
6035 : 0 : instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6036 : 0 : instr->jmp.a.n_bits = fa->n_bits;
6037 : 0 : instr->jmp.a.offset = fa->offset / 8;
6038 : 0 : instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6039 : 0 : instr->jmp.b.n_bits = fb->n_bits;
6040 : 0 : instr->jmp.b.offset = fb->offset / 8;
6041 : 0 : return 0;
6042 : : }
6043 : :
6044 : : /* JMP_GT_MI, JMP_GT_HI. */
6045 : 0 : b_val = strtoull(b, &b, 0);
6046 [ # # ]: 0 : CHECK(!b[0], EINVAL);
6047 : :
6048 : 0 : instr->type = INSTR_JMP_GT_MI;
6049 [ # # ]: 0 : if (a[0] == 'h')
6050 : 0 : instr->type = INSTR_JMP_GT_HI;
6051 : 0 : instr->jmp.ip = NULL; /* Resolved later. */
6052 : :
6053 : 0 : instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6054 : 0 : instr->jmp.a.n_bits = fa->n_bits;
6055 : 0 : instr->jmp.a.offset = fa->offset / 8;
6056 : 0 : instr->jmp.b_val = b_val;
6057 : 0 : return 0;
6058 : : }
6059 : :
6060 : : static inline void
6061 : 0 : instr_jmp_exec(struct rte_swx_pipeline *p)
6062 : : {
6063 : 0 : struct thread *t = &p->threads[p->thread_id];
6064 : 0 : struct instruction *ip = t->ip;
6065 : :
6066 : : TRACE("[Thread %2u] jmp\n", p->thread_id);
6067 : :
6068 : 0 : thread_ip_set(t, ip->jmp.ip);
6069 : 0 : }
6070 : :
6071 : : static inline void
6072 : 0 : instr_jmp_valid_exec(struct rte_swx_pipeline *p)
6073 : : {
6074 : 0 : struct thread *t = &p->threads[p->thread_id];
6075 : 0 : struct instruction *ip = t->ip;
6076 : 0 : uint32_t header_id = ip->jmp.header_id;
6077 : :
6078 : : TRACE("[Thread %2u] jmpv\n", p->thread_id);
6079 : :
6080 [ # # ]: 0 : t->ip = HEADER_VALID(t, header_id) ? ip->jmp.ip : (t->ip + 1);
6081 : 0 : }
6082 : :
6083 : : static inline void
6084 : 0 : instr_jmp_invalid_exec(struct rte_swx_pipeline *p)
6085 : : {
6086 : 0 : struct thread *t = &p->threads[p->thread_id];
6087 : 0 : struct instruction *ip = t->ip;
6088 : 0 : uint32_t header_id = ip->jmp.header_id;
6089 : :
6090 : : TRACE("[Thread %2u] jmpnv\n", p->thread_id);
6091 : :
6092 [ # # ]: 0 : t->ip = HEADER_VALID(t, header_id) ? (t->ip + 1) : ip->jmp.ip;
6093 : 0 : }
6094 : :
6095 : : static inline void
6096 : 0 : instr_jmp_hit_exec(struct rte_swx_pipeline *p)
6097 : : {
6098 : 0 : struct thread *t = &p->threads[p->thread_id];
6099 : 0 : struct instruction *ip = t->ip;
6100 : 0 : struct instruction *ip_next[] = {t->ip + 1, ip->jmp.ip};
6101 : :
6102 : : TRACE("[Thread %2u] jmph\n", p->thread_id);
6103 : :
6104 : 0 : t->ip = ip_next[t->hit];
6105 : 0 : }
6106 : :
6107 : : static inline void
6108 : 0 : instr_jmp_miss_exec(struct rte_swx_pipeline *p)
6109 : : {
6110 : 0 : struct thread *t = &p->threads[p->thread_id];
6111 : 0 : struct instruction *ip = t->ip;
6112 : 0 : struct instruction *ip_next[] = {ip->jmp.ip, t->ip + 1};
6113 : :
6114 : : TRACE("[Thread %2u] jmpnh\n", p->thread_id);
6115 : :
6116 : 0 : t->ip = ip_next[t->hit];
6117 : 0 : }
6118 : :
6119 : : static inline void
6120 : 0 : instr_jmp_action_hit_exec(struct rte_swx_pipeline *p)
6121 : : {
6122 : 0 : struct thread *t = &p->threads[p->thread_id];
6123 : 0 : struct instruction *ip = t->ip;
6124 : :
6125 : : TRACE("[Thread %2u] jmpa\n", p->thread_id);
6126 : :
6127 [ # # ]: 0 : t->ip = (ip->jmp.action_id == t->action_id) ? ip->jmp.ip : (t->ip + 1);
6128 : 0 : }
6129 : :
6130 : : static inline void
6131 : 0 : instr_jmp_action_miss_exec(struct rte_swx_pipeline *p)
6132 : : {
6133 : 0 : struct thread *t = &p->threads[p->thread_id];
6134 : 0 : struct instruction *ip = t->ip;
6135 : :
6136 : : TRACE("[Thread %2u] jmpna\n", p->thread_id);
6137 : :
6138 [ # # ]: 0 : t->ip = (ip->jmp.action_id == t->action_id) ? (t->ip + 1) : ip->jmp.ip;
6139 : 0 : }
6140 : :
6141 : : static inline void
6142 : 0 : instr_jmp_eq_exec(struct rte_swx_pipeline *p)
6143 : : {
6144 : 0 : struct thread *t = &p->threads[p->thread_id];
6145 : 0 : struct instruction *ip = t->ip;
6146 : :
6147 : : TRACE("[Thread %2u] jmpeq\n", p->thread_id);
6148 : :
6149 [ # # ]: 0 : JMP_CMP(t, ip, ==);
6150 : 0 : }
6151 : :
6152 : : static inline void
6153 : 0 : instr_jmp_eq_mh_exec(struct rte_swx_pipeline *p)
6154 : : {
6155 : 0 : struct thread *t = &p->threads[p->thread_id];
6156 : 0 : struct instruction *ip = t->ip;
6157 : :
6158 : : TRACE("[Thread %2u] jmpeq (mh)\n", p->thread_id);
6159 : :
6160 [ # # # # ]: 0 : JMP_CMP_MH(t, ip, ==);
6161 : 0 : }
6162 : :
6163 : : static inline void
6164 : 0 : instr_jmp_eq_hm_exec(struct rte_swx_pipeline *p)
6165 : : {
6166 : 0 : struct thread *t = &p->threads[p->thread_id];
6167 : 0 : struct instruction *ip = t->ip;
6168 : :
6169 : : TRACE("[Thread %2u] jmpeq (hm)\n", p->thread_id);
6170 : :
6171 [ # # # # ]: 0 : JMP_CMP_HM(t, ip, ==);
6172 : 0 : }
6173 : :
6174 : : static inline void
6175 : 0 : instr_jmp_eq_hh_exec(struct rte_swx_pipeline *p)
6176 : : {
6177 : 0 : struct thread *t = &p->threads[p->thread_id];
6178 : 0 : struct instruction *ip = t->ip;
6179 : :
6180 : : TRACE("[Thread %2u] jmpeq (hh)\n", p->thread_id);
6181 : :
6182 [ # # ]: 0 : JMP_CMP_HH_FAST(t, ip, ==);
6183 : 0 : }
6184 : :
6185 : : static inline void
6186 : 0 : instr_jmp_eq_i_exec(struct rte_swx_pipeline *p)
6187 : : {
6188 : 0 : struct thread *t = &p->threads[p->thread_id];
6189 : 0 : struct instruction *ip = t->ip;
6190 : :
6191 : : TRACE("[Thread %2u] jmpeq (i)\n", p->thread_id);
6192 : :
6193 [ # # ]: 0 : JMP_CMP_I(t, ip, ==);
6194 : 0 : }
6195 : :
6196 : : static inline void
6197 : 0 : instr_jmp_neq_exec(struct rte_swx_pipeline *p)
6198 : : {
6199 : 0 : struct thread *t = &p->threads[p->thread_id];
6200 : 0 : struct instruction *ip = t->ip;
6201 : :
6202 : : TRACE("[Thread %2u] jmpneq\n", p->thread_id);
6203 : :
6204 [ # # ]: 0 : JMP_CMP(t, ip, !=);
6205 : 0 : }
6206 : :
6207 : : static inline void
6208 : 0 : instr_jmp_neq_mh_exec(struct rte_swx_pipeline *p)
6209 : : {
6210 : 0 : struct thread *t = &p->threads[p->thread_id];
6211 : 0 : struct instruction *ip = t->ip;
6212 : :
6213 : : TRACE("[Thread %2u] jmpneq (mh)\n", p->thread_id);
6214 : :
6215 [ # # # # ]: 0 : JMP_CMP_MH(t, ip, !=);
6216 : 0 : }
6217 : :
6218 : : static inline void
6219 : 0 : instr_jmp_neq_hm_exec(struct rte_swx_pipeline *p)
6220 : : {
6221 : 0 : struct thread *t = &p->threads[p->thread_id];
6222 : 0 : struct instruction *ip = t->ip;
6223 : :
6224 : : TRACE("[Thread %2u] jmpneq (hm)\n", p->thread_id);
6225 : :
6226 [ # # # # ]: 0 : JMP_CMP_HM(t, ip, !=);
6227 : 0 : }
6228 : :
6229 : : static inline void
6230 : 0 : instr_jmp_neq_hh_exec(struct rte_swx_pipeline *p)
6231 : : {
6232 : 0 : struct thread *t = &p->threads[p->thread_id];
6233 : 0 : struct instruction *ip = t->ip;
6234 : :
6235 : : TRACE("[Thread %2u] jmpneq (hh)\n", p->thread_id);
6236 : :
6237 [ # # ]: 0 : JMP_CMP_HH_FAST(t, ip, !=);
6238 : 0 : }
6239 : :
6240 : : static inline void
6241 : 0 : instr_jmp_neq_i_exec(struct rte_swx_pipeline *p)
6242 : : {
6243 : 0 : struct thread *t = &p->threads[p->thread_id];
6244 : 0 : struct instruction *ip = t->ip;
6245 : :
6246 : : TRACE("[Thread %2u] jmpneq (i)\n", p->thread_id);
6247 : :
6248 [ # # ]: 0 : JMP_CMP_I(t, ip, !=);
6249 : 0 : }
6250 : :
6251 : : static inline void
6252 : 0 : instr_jmp_lt_exec(struct rte_swx_pipeline *p)
6253 : : {
6254 : 0 : struct thread *t = &p->threads[p->thread_id];
6255 : 0 : struct instruction *ip = t->ip;
6256 : :
6257 : : TRACE("[Thread %2u] jmplt\n", p->thread_id);
6258 : :
6259 [ # # ]: 0 : JMP_CMP(t, ip, <);
6260 : 0 : }
6261 : :
6262 : : static inline void
6263 : 0 : instr_jmp_lt_mh_exec(struct rte_swx_pipeline *p)
6264 : : {
6265 : 0 : struct thread *t = &p->threads[p->thread_id];
6266 : 0 : struct instruction *ip = t->ip;
6267 : :
6268 : : TRACE("[Thread %2u] jmplt (mh)\n", p->thread_id);
6269 : :
6270 [ # # # # ]: 0 : JMP_CMP_MH(t, ip, <);
6271 : 0 : }
6272 : :
6273 : : static inline void
6274 : 0 : instr_jmp_lt_hm_exec(struct rte_swx_pipeline *p)
6275 : : {
6276 : 0 : struct thread *t = &p->threads[p->thread_id];
6277 : 0 : struct instruction *ip = t->ip;
6278 : :
6279 : : TRACE("[Thread %2u] jmplt (hm)\n", p->thread_id);
6280 : :
6281 [ # # # # ]: 0 : JMP_CMP_HM(t, ip, <);
6282 : 0 : }
6283 : :
6284 : : static inline void
6285 : 0 : instr_jmp_lt_hh_exec(struct rte_swx_pipeline *p)
6286 : : {
6287 : 0 : struct thread *t = &p->threads[p->thread_id];
6288 : 0 : struct instruction *ip = t->ip;
6289 : :
6290 : : TRACE("[Thread %2u] jmplt (hh)\n", p->thread_id);
6291 : :
6292 [ # # # # : 0 : JMP_CMP_HH(t, ip, <);
# # ]
6293 : 0 : }
6294 : :
6295 : : static inline void
6296 : 0 : instr_jmp_lt_mi_exec(struct rte_swx_pipeline *p)
6297 : : {
6298 : 0 : struct thread *t = &p->threads[p->thread_id];
6299 : 0 : struct instruction *ip = t->ip;
6300 : :
6301 : : TRACE("[Thread %2u] jmplt (mi)\n", p->thread_id);
6302 : :
6303 [ # # ]: 0 : JMP_CMP_MI(t, ip, <);
6304 : 0 : }
6305 : :
6306 : : static inline void
6307 : 0 : instr_jmp_lt_hi_exec(struct rte_swx_pipeline *p)
6308 : : {
6309 : 0 : struct thread *t = &p->threads[p->thread_id];
6310 : 0 : struct instruction *ip = t->ip;
6311 : :
6312 : : TRACE("[Thread %2u] jmplt (hi)\n", p->thread_id);
6313 : :
6314 [ # # # # ]: 0 : JMP_CMP_HI(t, ip, <);
6315 : 0 : }
6316 : :
6317 : : static inline void
6318 : 0 : instr_jmp_gt_exec(struct rte_swx_pipeline *p)
6319 : : {
6320 : 0 : struct thread *t = &p->threads[p->thread_id];
6321 : 0 : struct instruction *ip = t->ip;
6322 : :
6323 : : TRACE("[Thread %2u] jmpgt\n", p->thread_id);
6324 : :
6325 [ # # ]: 0 : JMP_CMP(t, ip, >);
6326 : 0 : }
6327 : :
6328 : : static inline void
6329 : 0 : instr_jmp_gt_mh_exec(struct rte_swx_pipeline *p)
6330 : : {
6331 : 0 : struct thread *t = &p->threads[p->thread_id];
6332 : 0 : struct instruction *ip = t->ip;
6333 : :
6334 : : TRACE("[Thread %2u] jmpgt (mh)\n", p->thread_id);
6335 : :
6336 [ # # # # ]: 0 : JMP_CMP_MH(t, ip, >);
6337 : 0 : }
6338 : :
6339 : : static inline void
6340 : 0 : instr_jmp_gt_hm_exec(struct rte_swx_pipeline *p)
6341 : : {
6342 : 0 : struct thread *t = &p->threads[p->thread_id];
6343 : 0 : struct instruction *ip = t->ip;
6344 : :
6345 : : TRACE("[Thread %2u] jmpgt (hm)\n", p->thread_id);
6346 : :
6347 [ # # # # ]: 0 : JMP_CMP_HM(t, ip, >);
6348 : 0 : }
6349 : :
6350 : : static inline void
6351 : 0 : instr_jmp_gt_hh_exec(struct rte_swx_pipeline *p)
6352 : : {
6353 : 0 : struct thread *t = &p->threads[p->thread_id];
6354 : 0 : struct instruction *ip = t->ip;
6355 : :
6356 : : TRACE("[Thread %2u] jmpgt (hh)\n", p->thread_id);
6357 : :
6358 [ # # # # : 0 : JMP_CMP_HH(t, ip, >);
# # ]
6359 : 0 : }
6360 : :
6361 : : static inline void
6362 : 0 : instr_jmp_gt_mi_exec(struct rte_swx_pipeline *p)
6363 : : {
6364 : 0 : struct thread *t = &p->threads[p->thread_id];
6365 : 0 : struct instruction *ip = t->ip;
6366 : :
6367 : : TRACE("[Thread %2u] jmpgt (mi)\n", p->thread_id);
6368 : :
6369 [ # # ]: 0 : JMP_CMP_MI(t, ip, >);
6370 : 0 : }
6371 : :
6372 : : static inline void
6373 : 0 : instr_jmp_gt_hi_exec(struct rte_swx_pipeline *p)
6374 : : {
6375 : 0 : struct thread *t = &p->threads[p->thread_id];
6376 : 0 : struct instruction *ip = t->ip;
6377 : :
6378 : : TRACE("[Thread %2u] jmpgt (hi)\n", p->thread_id);
6379 : :
6380 [ # # # # ]: 0 : JMP_CMP_HI(t, ip, >);
6381 : 0 : }
6382 : :
6383 : : /*
6384 : : * return.
6385 : : */
6386 : : static int
6387 : : instr_return_translate(struct rte_swx_pipeline *p __rte_unused,
6388 : : struct action *action,
6389 : : char **tokens __rte_unused,
6390 : : int n_tokens,
6391 : : struct instruction *instr,
6392 : : struct instruction_data *data __rte_unused)
6393 : : {
6394 : 0 : CHECK(action, EINVAL);
6395 [ # # ]: 0 : CHECK(n_tokens == 1, EINVAL);
6396 : :
6397 : 0 : instr->type = INSTR_RETURN;
6398 : 0 : return 0;
6399 : : }
6400 : :
6401 : : static inline void
6402 : 0 : instr_return_exec(struct rte_swx_pipeline *p)
6403 : : {
6404 : 0 : struct thread *t = &p->threads[p->thread_id];
6405 : :
6406 : : TRACE("[Thread %2u] return\n", p->thread_id);
6407 : :
6408 : 0 : t->ip = t->ret;
6409 : 0 : }
6410 : :
6411 : : static int
6412 : 0 : instr_translate(struct rte_swx_pipeline *p,
6413 : : struct action *action,
6414 : : char *string,
6415 : : struct instruction *instr,
6416 : : struct instruction_data *data)
6417 : : {
6418 : : char *tokens[RTE_SWX_INSTRUCTION_TOKENS_MAX];
6419 : : int n_tokens = 0, tpos = 0;
6420 : :
6421 : : /* Parse the instruction string into tokens. */
6422 : 0 : for ( ; ; ) {
6423 : : char *token;
6424 : :
6425 : 0 : token = strtok_r(string, " \t\v", &string);
6426 [ # # ]: 0 : if (!token)
6427 : : break;
6428 : :
6429 [ # # ]: 0 : CHECK(n_tokens < RTE_SWX_INSTRUCTION_TOKENS_MAX, EINVAL);
6430 [ # # # # ]: 0 : CHECK_NAME(token, EINVAL);
6431 : :
6432 : 0 : tokens[n_tokens] = token;
6433 : 0 : n_tokens++;
6434 : : }
6435 : :
6436 [ # # ]: 0 : CHECK(n_tokens, EINVAL);
6437 : :
6438 : : /* Handle the optional instruction label. */
6439 [ # # # # ]: 0 : if ((n_tokens >= 2) && !strcmp(tokens[1], ":")) {
6440 [ # # ]: 0 : strcpy(data->label, tokens[0]);
6441 : :
6442 : : tpos += 2;
6443 [ # # ]: 0 : CHECK(n_tokens - tpos, EINVAL);
6444 : : }
6445 : :
6446 : : /* Identify the instruction type. */
6447 [ # # ]: 0 : if (!strcmp(tokens[tpos], "rx"))
6448 : 0 : return instr_rx_translate(p,
6449 : : action,
6450 : : &tokens[tpos],
6451 : : n_tokens - tpos,
6452 : : instr,
6453 : : data);
6454 : :
6455 [ # # ]: 0 : if (!strcmp(tokens[tpos], "tx"))
6456 : 0 : return instr_tx_translate(p,
6457 : : action,
6458 : : &tokens[tpos],
6459 : : n_tokens - tpos,
6460 : : instr,
6461 : : data);
6462 : :
6463 [ # # ]: 0 : if (!strcmp(tokens[tpos], "drop"))
6464 [ # # ]: 0 : return instr_drop_translate(p,
6465 : : action,
6466 : : &tokens[tpos],
6467 : : n_tokens - tpos,
6468 : : instr,
6469 : : data);
6470 : :
6471 [ # # ]: 0 : if (!strcmp(tokens[tpos], "mirror"))
6472 : 0 : return instr_mirror_translate(p,
6473 : : action,
6474 : : &tokens[tpos],
6475 : : n_tokens - tpos,
6476 : : instr,
6477 : : data);
6478 : :
6479 [ # # ]: 0 : if (!strcmp(tokens[tpos], "recirculate"))
6480 [ # # ]: 0 : return instr_recirculate_translate(p,
6481 : : action,
6482 : : &tokens[tpos],
6483 : : n_tokens - tpos,
6484 : : instr,
6485 : : data);
6486 : :
6487 [ # # ]: 0 : if (!strcmp(tokens[tpos], "recircid"))
6488 [ # # ]: 0 : return instr_recircid_translate(p,
6489 : : action,
6490 : : &tokens[tpos],
6491 : : n_tokens - tpos,
6492 : : instr,
6493 : : data);
6494 : :
6495 [ # # ]: 0 : if (!strcmp(tokens[tpos], "extract"))
6496 : 0 : return instr_hdr_extract_translate(p,
6497 : : action,
6498 : : &tokens[tpos],
6499 : : n_tokens - tpos,
6500 : : instr,
6501 : : data);
6502 : :
6503 [ # # ]: 0 : if (!strcmp(tokens[tpos], "lookahead"))
6504 : 0 : return instr_hdr_lookahead_translate(p,
6505 : : action,
6506 : : &tokens[tpos],
6507 : : n_tokens - tpos,
6508 : : instr,
6509 : : data);
6510 : :
6511 [ # # ]: 0 : if (!strcmp(tokens[tpos], "emit"))
6512 : 0 : return instr_hdr_emit_translate(p,
6513 : : action,
6514 : : &tokens[tpos],
6515 : : n_tokens - tpos,
6516 : : instr,
6517 : : data);
6518 : :
6519 [ # # ]: 0 : if (!strcmp(tokens[tpos], "validate"))
6520 [ # # ]: 0 : return instr_hdr_validate_translate(p,
6521 : : action,
6522 : : &tokens[tpos],
6523 : : n_tokens - tpos,
6524 : : instr,
6525 : : data);
6526 : :
6527 [ # # ]: 0 : if (!strcmp(tokens[tpos], "invalidate"))
6528 [ # # ]: 0 : return instr_hdr_invalidate_translate(p,
6529 : : action,
6530 : : &tokens[tpos],
6531 : : n_tokens - tpos,
6532 : : instr,
6533 : : data);
6534 : :
6535 [ # # ]: 0 : if (!strcmp(tokens[tpos], "mov"))
6536 : 0 : return instr_mov_translate(p,
6537 : : action,
6538 : : &tokens[tpos],
6539 : : n_tokens - tpos,
6540 : : instr,
6541 : : data);
6542 : :
6543 [ # # ]: 0 : if (!strcmp(tokens[tpos], "movh"))
6544 : 0 : return instr_movh_translate(p,
6545 : : action,
6546 : : &tokens[tpos],
6547 : : n_tokens - tpos,
6548 : : instr,
6549 : : data);
6550 : :
6551 [ # # ]: 0 : if (!strcmp(tokens[tpos], "add"))
6552 : 0 : return instr_alu_add_translate(p,
6553 : : action,
6554 : : &tokens[tpos],
6555 : : n_tokens - tpos,
6556 : : instr,
6557 : : data);
6558 : :
6559 [ # # ]: 0 : if (!strcmp(tokens[tpos], "sub"))
6560 : 0 : return instr_alu_sub_translate(p,
6561 : : action,
6562 : : &tokens[tpos],
6563 : : n_tokens - tpos,
6564 : : instr,
6565 : : data);
6566 : :
6567 [ # # ]: 0 : if (!strcmp(tokens[tpos], "ckadd"))
6568 : 0 : return instr_alu_ckadd_translate(p,
6569 : : action,
6570 : : &tokens[tpos],
6571 : : n_tokens - tpos,
6572 : : instr,
6573 : : data);
6574 : :
6575 [ # # ]: 0 : if (!strcmp(tokens[tpos], "cksub"))
6576 : 0 : return instr_alu_cksub_translate(p,
6577 : : action,
6578 : : &tokens[tpos],
6579 : : n_tokens - tpos,
6580 : : instr,
6581 : : data);
6582 : :
6583 [ # # ]: 0 : if (!strcmp(tokens[tpos], "and"))
6584 : 0 : return instr_alu_and_translate(p,
6585 : : action,
6586 : : &tokens[tpos],
6587 : : n_tokens - tpos,
6588 : : instr,
6589 : : data);
6590 : :
6591 [ # # ]: 0 : if (!strcmp(tokens[tpos], "or"))
6592 : 0 : return instr_alu_or_translate(p,
6593 : : action,
6594 : : &tokens[tpos],
6595 : : n_tokens - tpos,
6596 : : instr,
6597 : : data);
6598 : :
6599 [ # # ]: 0 : if (!strcmp(tokens[tpos], "xor"))
6600 : 0 : return instr_alu_xor_translate(p,
6601 : : action,
6602 : : &tokens[tpos],
6603 : : n_tokens - tpos,
6604 : : instr,
6605 : : data);
6606 : :
6607 [ # # ]: 0 : if (!strcmp(tokens[tpos], "shl"))
6608 : 0 : return instr_alu_shl_translate(p,
6609 : : action,
6610 : : &tokens[tpos],
6611 : : n_tokens - tpos,
6612 : : instr,
6613 : : data);
6614 : :
6615 [ # # ]: 0 : if (!strcmp(tokens[tpos], "shr"))
6616 : 0 : return instr_alu_shr_translate(p,
6617 : : action,
6618 : : &tokens[tpos],
6619 : : n_tokens - tpos,
6620 : : instr,
6621 : : data);
6622 : :
6623 [ # # ]: 0 : if (!strcmp(tokens[tpos], "regprefetch"))
6624 : 0 : return instr_regprefetch_translate(p,
6625 : : action,
6626 : : &tokens[tpos],
6627 : : n_tokens - tpos,
6628 : : instr,
6629 : : data);
6630 : :
6631 [ # # ]: 0 : if (!strcmp(tokens[tpos], "regrd"))
6632 : 0 : return instr_regrd_translate(p,
6633 : : action,
6634 : : &tokens[tpos],
6635 : : n_tokens - tpos,
6636 : : instr,
6637 : : data);
6638 : :
6639 [ # # ]: 0 : if (!strcmp(tokens[tpos], "regwr"))
6640 : 0 : return instr_regwr_translate(p,
6641 : : action,
6642 : : &tokens[tpos],
6643 : : n_tokens - tpos,
6644 : : instr,
6645 : : data);
6646 : :
6647 [ # # ]: 0 : if (!strcmp(tokens[tpos], "regadd"))
6648 : 0 : return instr_regadd_translate(p,
6649 : : action,
6650 : : &tokens[tpos],
6651 : : n_tokens - tpos,
6652 : : instr,
6653 : : data);
6654 : :
6655 [ # # ]: 0 : if (!strcmp(tokens[tpos], "metprefetch"))
6656 : 0 : return instr_metprefetch_translate(p,
6657 : : action,
6658 : : &tokens[tpos],
6659 : : n_tokens - tpos,
6660 : : instr,
6661 : : data);
6662 : :
6663 [ # # ]: 0 : if (!strcmp(tokens[tpos], "meter"))
6664 : 0 : return instr_meter_translate(p,
6665 : : action,
6666 : : &tokens[tpos],
6667 : : n_tokens - tpos,
6668 : : instr,
6669 : : data);
6670 : :
6671 [ # # ]: 0 : if (!strcmp(tokens[tpos], "table"))
6672 : 0 : return instr_table_translate(p,
6673 : : action,
6674 : : &tokens[tpos],
6675 : : n_tokens - tpos,
6676 : : instr,
6677 : : data);
6678 : :
6679 [ # # ]: 0 : if (!strcmp(tokens[tpos], "learn"))
6680 : 0 : return instr_learn_translate(p,
6681 : : action,
6682 : : &tokens[tpos],
6683 : : n_tokens - tpos,
6684 : : instr,
6685 : : data);
6686 [ # # ]: 0 : if (!strcmp(tokens[tpos], "rearm"))
6687 : 0 : return instr_rearm_translate(p,
6688 : : action,
6689 : : &tokens[tpos],
6690 : : n_tokens - tpos,
6691 : : instr,
6692 : : data);
6693 : :
6694 [ # # ]: 0 : if (!strcmp(tokens[tpos], "forget"))
6695 [ # # ]: 0 : return instr_forget_translate(p,
6696 : : action,
6697 : : &tokens[tpos],
6698 : : n_tokens - tpos,
6699 : : instr,
6700 : : data);
6701 : :
6702 [ # # ]: 0 : if (!strcmp(tokens[tpos], "entryid"))
6703 [ # # ]: 0 : return instr_entryid_translate(p,
6704 : : action,
6705 : : &tokens[tpos],
6706 : : n_tokens - tpos,
6707 : : instr,
6708 : : data);
6709 : :
6710 [ # # ]: 0 : if (!strcmp(tokens[tpos], "extern"))
6711 : 0 : return instr_extern_translate(p,
6712 : : action,
6713 : : &tokens[tpos],
6714 : : n_tokens - tpos,
6715 : : instr,
6716 : : data);
6717 : :
6718 [ # # ]: 0 : if (!strcmp(tokens[tpos], "hash"))
6719 : 0 : return instr_hash_translate(p,
6720 : : action,
6721 : : &tokens[tpos],
6722 : : n_tokens - tpos,
6723 : : instr,
6724 : : data);
6725 : :
6726 [ # # ]: 0 : if (!strcmp(tokens[tpos], "rss"))
6727 : 0 : return instr_rss_translate(p,
6728 : : action,
6729 : : &tokens[tpos],
6730 : : n_tokens - tpos,
6731 : : instr,
6732 : : data);
6733 : :
6734 [ # # ]: 0 : if (!strcmp(tokens[tpos], "jmp"))
6735 [ # # ]: 0 : return instr_jmp_translate(p,
6736 : : action,
6737 : : &tokens[tpos],
6738 : : n_tokens - tpos,
6739 : : instr,
6740 : : data);
6741 : :
6742 [ # # ]: 0 : if (!strcmp(tokens[tpos], "jmpv"))
6743 : 0 : return instr_jmp_valid_translate(p,
6744 : : action,
6745 : : &tokens[tpos],
6746 : : n_tokens - tpos,
6747 : : instr,
6748 : : data);
6749 : :
6750 [ # # ]: 0 : if (!strcmp(tokens[tpos], "jmpnv"))
6751 : 0 : return instr_jmp_invalid_translate(p,
6752 : : action,
6753 : : &tokens[tpos],
6754 : : n_tokens - tpos,
6755 : : instr,
6756 : : data);
6757 : :
6758 [ # # ]: 0 : if (!strcmp(tokens[tpos], "jmph"))
6759 [ # # ]: 0 : return instr_jmp_hit_translate(p,
6760 : : action,
6761 : : &tokens[tpos],
6762 : : n_tokens - tpos,
6763 : : instr,
6764 : : data);
6765 : :
6766 [ # # ]: 0 : if (!strcmp(tokens[tpos], "jmpnh"))
6767 [ # # ]: 0 : return instr_jmp_miss_translate(p,
6768 : : action,
6769 : : &tokens[tpos],
6770 : : n_tokens - tpos,
6771 : : instr,
6772 : : data);
6773 : :
6774 [ # # ]: 0 : if (!strcmp(tokens[tpos], "jmpa"))
6775 : 0 : return instr_jmp_action_hit_translate(p,
6776 : : action,
6777 : : &tokens[tpos],
6778 : : n_tokens - tpos,
6779 : : instr,
6780 : : data);
6781 : :
6782 [ # # ]: 0 : if (!strcmp(tokens[tpos], "jmpna"))
6783 : 0 : return instr_jmp_action_miss_translate(p,
6784 : : action,
6785 : : &tokens[tpos],
6786 : : n_tokens - tpos,
6787 : : instr,
6788 : : data);
6789 : :
6790 [ # # ]: 0 : if (!strcmp(tokens[tpos], "jmpeq"))
6791 : 0 : return instr_jmp_eq_translate(p,
6792 : : action,
6793 : : &tokens[tpos],
6794 : : n_tokens - tpos,
6795 : : instr,
6796 : : data);
6797 : :
6798 [ # # ]: 0 : if (!strcmp(tokens[tpos], "jmpneq"))
6799 : 0 : return instr_jmp_neq_translate(p,
6800 : : action,
6801 : : &tokens[tpos],
6802 : : n_tokens - tpos,
6803 : : instr,
6804 : : data);
6805 : :
6806 [ # # ]: 0 : if (!strcmp(tokens[tpos], "jmplt"))
6807 : 0 : return instr_jmp_lt_translate(p,
6808 : : action,
6809 : : &tokens[tpos],
6810 : : n_tokens - tpos,
6811 : : instr,
6812 : : data);
6813 : :
6814 [ # # ]: 0 : if (!strcmp(tokens[tpos], "jmpgt"))
6815 : 0 : return instr_jmp_gt_translate(p,
6816 : : action,
6817 : : &tokens[tpos],
6818 : : n_tokens - tpos,
6819 : : instr,
6820 : : data);
6821 : :
6822 [ # # ]: 0 : if (!strcmp(tokens[tpos], "return"))
6823 [ # # ]: 0 : return instr_return_translate(p,
6824 : : action,
6825 : : &tokens[tpos],
6826 : : n_tokens - tpos,
6827 : : instr,
6828 : : data);
6829 : :
6830 : : return -EINVAL;
6831 : : }
6832 : :
6833 : : static struct instruction_data *
6834 : : label_find(struct instruction_data *data, uint32_t n, const char *label)
6835 : : {
6836 : : uint32_t i;
6837 : :
6838 [ # # # # ]: 0 : for (i = 0; i < n; i++)
6839 [ # # # # ]: 0 : if (!strcmp(label, data[i].label))
6840 : : return &data[i];
6841 : :
6842 : : return NULL;
6843 : : }
6844 : :
6845 : : static uint32_t
6846 : 0 : label_is_used(struct instruction_data *data, uint32_t n, const char *label)
6847 : : {
6848 : : uint32_t count = 0, i;
6849 : :
6850 [ # # ]: 0 : if (!label[0])
6851 : : return 0;
6852 : :
6853 [ # # ]: 0 : for (i = 0; i < n; i++)
6854 [ # # ]: 0 : if (!strcmp(label, data[i].jmp_label))
6855 : 0 : count++;
6856 : :
6857 : : return count;
6858 : : }
6859 : :
6860 : : static int
6861 : 0 : instr_label_check(struct instruction_data *instruction_data,
6862 : : uint32_t n_instructions)
6863 : : {
6864 : : uint32_t i;
6865 : :
6866 : : /* Check that all instruction labels are unique. */
6867 [ # # ]: 0 : for (i = 0; i < n_instructions; i++) {
6868 : 0 : struct instruction_data *data = &instruction_data[i];
6869 : 0 : char *label = data->label;
6870 : : uint32_t j;
6871 : :
6872 [ # # ]: 0 : if (!label[0])
6873 : 0 : continue;
6874 : :
6875 [ # # ]: 0 : for (j = i + 1; j < n_instructions; j++)
6876 [ # # ]: 0 : CHECK(strcmp(label, instruction_data[j].label), EINVAL);
6877 : : }
6878 : :
6879 : : /* Check that no jump instruction (either conditional or not) can jump to itself (loop). */
6880 [ # # ]: 0 : for (i = 0; i < n_instructions; i++) {
6881 : 0 : struct instruction_data *data = &instruction_data[i];
6882 : 0 : char *label = data->label;
6883 : 0 : char *jmp_label = data->jmp_label;
6884 : :
6885 : : /* Continue if this instruction does not have a label or it is not a jump. */
6886 [ # # # # ]: 0 : if (!label[0] || !jmp_label[0])
6887 : 0 : continue;
6888 : :
6889 [ # # ]: 0 : CHECK(strcmp(label, jmp_label), EINVAL);
6890 : : }
6891 : :
6892 : : /* Get users for each instruction label. */
6893 [ # # ]: 0 : for (i = 0; i < n_instructions; i++) {
6894 : 0 : struct instruction_data *data = &instruction_data[i];
6895 : 0 : char *label = data->label;
6896 : :
6897 : 0 : data->n_users = label_is_used(instruction_data,
6898 : : n_instructions,
6899 : : label);
6900 : : }
6901 : :
6902 : : return 0;
6903 : : }
6904 : :
6905 : : static int
6906 : 0 : instr_jmp_resolve(struct instruction *instructions,
6907 : : struct instruction_data *instruction_data,
6908 : : uint32_t n_instructions)
6909 : : {
6910 : : uint32_t i;
6911 : :
6912 [ # # ]: 0 : for (i = 0; i < n_instructions; i++) {
6913 : 0 : struct instruction *instr = &instructions[i];
6914 [ # # ]: 0 : struct instruction_data *data = &instruction_data[i];
6915 : : struct instruction_data *found;
6916 : :
6917 : 0 : if (!instruction_is_jmp(instr))
6918 : 0 : continue;
6919 : :
6920 : : found = label_find(instruction_data,
6921 : : n_instructions,
6922 : 0 : data->jmp_label);
6923 [ # # ]: 0 : CHECK(found, EINVAL);
6924 : :
6925 : 0 : instr->jmp.ip = &instructions[found - instruction_data];
6926 : : }
6927 : :
6928 : : return 0;
6929 : : }
6930 : :
6931 : : static int
6932 : 0 : instr_verify(struct rte_swx_pipeline *p __rte_unused,
6933 : : struct action *a,
6934 : : struct instruction *instr,
6935 : : struct instruction_data *data __rte_unused,
6936 : : uint32_t n_instructions)
6937 : : {
6938 [ # # ]: 0 : if (!a) {
6939 : : enum instruction_type type;
6940 : : uint32_t i;
6941 : :
6942 : : /* Check that the first instruction is rx. */
6943 [ # # ]: 0 : CHECK(instr[0].type == INSTR_RX, EINVAL);
6944 : :
6945 : : /* Check that there is at least one tx instruction. */
6946 [ # # ]: 0 : for (i = 0; i < n_instructions; i++) {
6947 [ # # ]: 0 : type = instr[i].type;
6948 : :
6949 : : if (instruction_is_tx(type))
6950 : : break;
6951 : : }
6952 [ # # ]: 0 : CHECK(i < n_instructions, EINVAL);
6953 : :
6954 : : /* Check that the last instruction is either tx or unconditional
6955 : : * jump.
6956 : : */
6957 [ # # ]: 0 : type = instr[n_instructions - 1].type;
6958 [ # # ]: 0 : CHECK(instruction_is_tx(type) || (type == INSTR_JMP), EINVAL);
6959 : : }
6960 : :
6961 [ # # ]: 0 : if (a) {
6962 : : enum instruction_type type;
6963 : : uint32_t i;
6964 : :
6965 : : /* Check that there is at least one return or tx instruction. */
6966 [ # # ]: 0 : for (i = 0; i < n_instructions; i++) {
6967 : 0 : type = instr[i].type;
6968 : :
6969 [ # # ]: 0 : if ((type == INSTR_RETURN) || instruction_is_tx(type))
6970 : : break;
6971 : : }
6972 [ # # ]: 0 : CHECK(i < n_instructions, EINVAL);
6973 : : }
6974 : :
6975 : : return 0;
6976 : : }
6977 : :
6978 : : static uint32_t
6979 : 0 : instr_compact(struct instruction *instructions,
6980 : : struct instruction_data *instruction_data,
6981 : : uint32_t n_instructions)
6982 : : {
6983 : : uint32_t i, pos = 0;
6984 : :
6985 : : /* Eliminate the invalid instructions that have been optimized out. */
6986 [ # # ]: 0 : for (i = 0; i < n_instructions; i++) {
6987 : 0 : struct instruction *instr = &instructions[i];
6988 : 0 : struct instruction_data *data = &instruction_data[i];
6989 : :
6990 [ # # ]: 0 : if (data->invalid)
6991 : 0 : continue;
6992 : :
6993 [ # # ]: 0 : if (i != pos) {
6994 : 0 : memcpy(&instructions[pos], instr, sizeof(*instr));
6995 : 0 : memcpy(&instruction_data[pos], data, sizeof(*data));
6996 : : }
6997 : :
6998 : 0 : pos++;
6999 : : }
7000 : :
7001 : 0 : return pos;
7002 : : }
7003 : :
7004 : : static int
7005 : 0 : instr_pattern_extract_many_search(struct instruction *instr,
7006 : : struct instruction_data *data,
7007 : : uint32_t n_instr,
7008 : : uint32_t *n_pattern_instr)
7009 : : {
7010 : : uint32_t i;
7011 : :
7012 [ # # ]: 0 : for (i = 0; i < n_instr; i++) {
7013 [ # # ]: 0 : if (data[i].invalid)
7014 : : break;
7015 : :
7016 [ # # ]: 0 : if (instr[i].type != INSTR_HDR_EXTRACT)
7017 : : break;
7018 : :
7019 [ # # ]: 0 : if (i == RTE_DIM(instr->io.hdr.header_id))
7020 : : break;
7021 : :
7022 [ # # # # ]: 0 : if (i && data[i].n_users)
7023 : : break;
7024 : : }
7025 : :
7026 [ # # ]: 0 : if (i < 2)
7027 : : return 0;
7028 : :
7029 : 0 : *n_pattern_instr = i;
7030 : 0 : return 1;
7031 : : }
7032 : :
7033 : : static void
7034 : : instr_pattern_extract_many_replace(struct instruction *instr,
7035 : : struct instruction_data *data,
7036 : : uint32_t n_instr)
7037 : : {
7038 : : uint32_t i;
7039 : :
7040 [ # # ]: 0 : for (i = 1; i < n_instr; i++) {
7041 : 0 : instr[0].type++;
7042 : 0 : instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
7043 : 0 : instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
7044 : 0 : instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
7045 : :
7046 : 0 : data[i].invalid = 1;
7047 : : }
7048 : : }
7049 : :
7050 : : static uint32_t
7051 : 0 : instr_pattern_extract_many_optimize(struct instruction *instructions,
7052 : : struct instruction_data *instruction_data,
7053 : : uint32_t n_instructions)
7054 : : {
7055 : : uint32_t i;
7056 : :
7057 [ # # ]: 0 : for (i = 0; i < n_instructions; ) {
7058 : 0 : struct instruction *instr = &instructions[i];
7059 : 0 : struct instruction_data *data = &instruction_data[i];
7060 : 0 : uint32_t n_instr = 0;
7061 : : int detected;
7062 : :
7063 : : /* Extract many. */
7064 : 0 : detected = instr_pattern_extract_many_search(instr,
7065 : : data,
7066 : : n_instructions - i,
7067 : : &n_instr);
7068 [ # # ]: 0 : if (detected) {
7069 : 0 : instr_pattern_extract_many_replace(instr,
7070 : : data,
7071 : : n_instr);
7072 : 0 : i += n_instr;
7073 : 0 : continue;
7074 : : }
7075 : :
7076 : : /* No pattern starting at the current instruction. */
7077 : 0 : i++;
7078 : : }
7079 : :
7080 : : /* Eliminate the invalid instructions that have been optimized out. */
7081 : 0 : n_instructions = instr_compact(instructions,
7082 : : instruction_data,
7083 : : n_instructions);
7084 : :
7085 : 0 : return n_instructions;
7086 : : }
7087 : :
7088 : : static int
7089 : 0 : instr_pattern_emit_many_tx_search(struct instruction *instr,
7090 : : struct instruction_data *data,
7091 : : uint32_t n_instr,
7092 : : uint32_t *n_pattern_instr)
7093 : : {
7094 : : uint32_t i;
7095 : :
7096 [ # # ]: 0 : for (i = 0; i < n_instr; i++) {
7097 [ # # ]: 0 : if (data[i].invalid)
7098 : : break;
7099 : :
7100 [ # # ]: 0 : if (instr[i].type != INSTR_HDR_EMIT)
7101 : : break;
7102 : :
7103 [ # # ]: 0 : if (i == RTE_DIM(instr->io.hdr.header_id))
7104 : : break;
7105 : :
7106 [ # # # # ]: 0 : if (i && data[i].n_users)
7107 : : break;
7108 : : }
7109 : :
7110 [ # # ]: 0 : if (!i)
7111 : : return 0;
7112 : :
7113 [ # # ]: 0 : if (instr[i].type != INSTR_TX)
7114 : : return 0;
7115 : :
7116 [ # # ]: 0 : if (data[i].n_users)
7117 : : return 0;
7118 : :
7119 : 0 : i++;
7120 : :
7121 : 0 : *n_pattern_instr = i;
7122 : 0 : return 1;
7123 : : }
7124 : :
7125 : : static void
7126 : 0 : instr_pattern_emit_many_tx_replace(struct instruction *instr,
7127 : : struct instruction_data *data,
7128 : : uint32_t n_instr)
7129 : : {
7130 : : uint32_t i;
7131 : :
7132 : : /* Any emit instruction in addition to the first one. */
7133 [ # # ]: 0 : for (i = 1; i < n_instr - 1; i++) {
7134 : 0 : instr[0].type++;
7135 : 0 : instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
7136 : 0 : instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
7137 : 0 : instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
7138 : :
7139 : 0 : data[i].invalid = 1;
7140 : : }
7141 : :
7142 : : /* The TX instruction is the last one in the pattern. */
7143 : 0 : instr[0].type++;
7144 : 0 : instr[0].io.io.offset = instr[i].io.io.offset;
7145 : 0 : instr[0].io.io.n_bits = instr[i].io.io.n_bits;
7146 : 0 : data[i].invalid = 1;
7147 : 0 : }
7148 : :
7149 : : static uint32_t
7150 : 0 : instr_pattern_emit_many_tx_optimize(struct instruction *instructions,
7151 : : struct instruction_data *instruction_data,
7152 : : uint32_t n_instructions)
7153 : : {
7154 : : uint32_t i;
7155 : :
7156 [ # # ]: 0 : for (i = 0; i < n_instructions; ) {
7157 : 0 : struct instruction *instr = &instructions[i];
7158 : 0 : struct instruction_data *data = &instruction_data[i];
7159 : 0 : uint32_t n_instr = 0;
7160 : : int detected;
7161 : :
7162 : : /* Emit many + TX. */
7163 : 0 : detected = instr_pattern_emit_many_tx_search(instr,
7164 : : data,
7165 : : n_instructions - i,
7166 : : &n_instr);
7167 [ # # ]: 0 : if (detected) {
7168 : 0 : instr_pattern_emit_many_tx_replace(instr,
7169 : : data,
7170 : : n_instr);
7171 : 0 : i += n_instr;
7172 : 0 : continue;
7173 : : }
7174 : :
7175 : : /* No pattern starting at the current instruction. */
7176 : 0 : i++;
7177 : : }
7178 : :
7179 : : /* Eliminate the invalid instructions that have been optimized out. */
7180 : 0 : n_instructions = instr_compact(instructions,
7181 : : instruction_data,
7182 : : n_instructions);
7183 : :
7184 : 0 : return n_instructions;
7185 : : }
7186 : :
7187 : : static uint32_t
7188 : : action_arg_src_mov_count(struct action *a,
7189 : : uint32_t arg_id,
7190 : : struct instruction *instructions,
7191 : : struct instruction_data *instruction_data,
7192 : : uint32_t n_instructions);
7193 : :
7194 : : static int
7195 : 0 : instr_pattern_validate_mov_all_search(struct rte_swx_pipeline *p,
7196 : : struct action *a,
7197 : : struct instruction *instr,
7198 : : struct instruction_data *data,
7199 : : uint32_t n_instr,
7200 : : struct instruction *instructions,
7201 : : struct instruction_data *instruction_data,
7202 : : uint32_t n_instructions,
7203 : : uint32_t *n_pattern_instr)
7204 : : {
7205 : : struct header *h;
7206 : : uint32_t src_field_id, i, j;
7207 : :
7208 : : /* Prerequisites. */
7209 [ # # # # ]: 0 : if (!a || !a->st)
7210 : : return 0;
7211 : :
7212 : : /* First instruction: HDR_VALIDATE. Second instruction: MOV_HM, MOV_DMA or MOV_128. */
7213 [ # # ]: 0 : if (data[0].invalid ||
7214 [ # # # # ]: 0 : (instr[0].type != INSTR_HDR_VALIDATE) ||
7215 : 0 : (n_instr < 2) ||
7216 [ # # ]: 0 : data[1].invalid ||
7217 [ # # ]: 0 : (instr[1].type != INSTR_MOV_HM &&
7218 [ # # ]: 0 : instr[1].type != INSTR_MOV_DMA &&
7219 : 0 : instr[1].type != INSTR_MOV_128) ||
7220 [ # # ]: 0 : instr[1].mov.src.struct_id)
7221 : : return 0;
7222 : :
7223 : 0 : h = header_find_by_struct_id(p, instr[0].valid.struct_id);
7224 [ # # ]: 0 : if (!h ||
7225 [ # # ]: 0 : h->st->var_size ||
7226 [ # # ]: 0 : (n_instr < 1 + h->st->n_fields))
7227 : : return 0;
7228 : :
7229 [ # # ]: 0 : for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
7230 [ # # ]: 0 : if (instr[1].mov.src.offset == a->st->fields[src_field_id].offset / 8)
7231 : : break;
7232 : :
7233 [ # # ]: 0 : if (src_field_id + h->st->n_fields > a->st->n_fields)
7234 : : return 0;
7235 : :
7236 : : /* Second and subsequent instructions: MOV_HM. */
7237 [ # # ]: 0 : for (i = 0; i < h->st->n_fields; i++)
7238 [ # # ]: 0 : if (data[1 + i].invalid ||
7239 [ # # ]: 0 : data[1 + i].n_users ||
7240 [ # # ]: 0 : (instr[1 + i].type != INSTR_MOV_HM &&
7241 [ # # ]: 0 : instr[1 + i].type != INSTR_MOV_DMA &&
7242 : 0 : instr[1 + i].type != INSTR_MOV_128) ||
7243 [ # # ]: 0 : (instr[1 + i].mov.dst.struct_id != h->struct_id) ||
7244 [ # # ]: 0 : (instr[1 + i].mov.dst.offset != h->st->fields[i].offset / 8) ||
7245 [ # # ]: 0 : (instr[1 + i].mov.dst.n_bits != h->st->fields[i].n_bits) ||
7246 [ # # ]: 0 : instr[1 + i].mov.src.struct_id ||
7247 [ # # ]: 0 : (instr[1 + i].mov.src.offset != a->st->fields[src_field_id + i].offset / 8) ||
7248 [ # # # # ]: 0 : (instr[1 + i].mov.src.n_bits != a->st->fields[src_field_id + i].n_bits) ||
7249 : : (instr[1 + i].mov.dst.n_bits != instr[1 + i].mov.src.n_bits))
7250 : : return 0;
7251 : :
7252 : : /* Check that none of the action args that are used as source for this
7253 : : * DMA transfer are not used as source in any other mov instruction.
7254 : : */
7255 [ # # ]: 0 : for (j = src_field_id; j < src_field_id + h->st->n_fields; j++) {
7256 : : uint32_t n_users;
7257 : :
7258 : 0 : n_users = action_arg_src_mov_count(a,
7259 : : j,
7260 : : instructions,
7261 : : instruction_data,
7262 : : n_instructions);
7263 [ # # ]: 0 : if (n_users > 1)
7264 : : return 0;
7265 : : }
7266 : :
7267 : 0 : *n_pattern_instr = 1 + h->st->n_fields;
7268 : 0 : return 1;
7269 : : }
7270 : :
7271 : : static void
7272 : 0 : instr_pattern_validate_mov_all_replace(struct rte_swx_pipeline *p,
7273 : : struct action *a,
7274 : : struct instruction *instr,
7275 : : struct instruction_data *data,
7276 : : uint32_t n_instr)
7277 : : {
7278 : : struct header *h;
7279 : : uint32_t src_field_id, src_offset, i;
7280 : :
7281 : : /* Read from the instructions before they are modified. */
7282 : 0 : h = header_find_by_struct_id(p, instr[1].mov.dst.struct_id);
7283 [ # # ]: 0 : if (!h)
7284 : : return;
7285 : :
7286 : 0 : src_offset = instr[1].mov.src.offset;
7287 : :
7288 [ # # ]: 0 : for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
7289 [ # # ]: 0 : if (src_offset == a->st->fields[src_field_id].offset / 8)
7290 : : break;
7291 : :
7292 : : /* Modify the instructions. */
7293 : 0 : instr[0].type = INSTR_DMA_HT;
7294 : 0 : instr[0].dma.dst.header_id[0] = h->id;
7295 : 0 : instr[0].dma.dst.struct_id[0] = h->struct_id;
7296 : 0 : instr[0].dma.src.offset[0] = (uint8_t)src_offset;
7297 : 0 : instr[0].dma.n_bytes[0] = h->st->n_bits / 8;
7298 : :
7299 [ # # ]: 0 : for (i = 1; i < n_instr; i++)
7300 : 0 : data[i].invalid = 1;
7301 : :
7302 : : /* Update the endianness of the action arguments to header endianness. */
7303 [ # # ]: 0 : for (i = 0; i < h->st->n_fields; i++)
7304 : 0 : a->args_endianness[src_field_id + i] = 1;
7305 : : }
7306 : :
7307 : : static uint32_t
7308 : 0 : instr_pattern_validate_mov_all_optimize(struct rte_swx_pipeline *p,
7309 : : struct action *a,
7310 : : struct instruction *instructions,
7311 : : struct instruction_data *instruction_data,
7312 : : uint32_t n_instructions)
7313 : : {
7314 : : uint32_t i;
7315 : :
7316 [ # # # # ]: 0 : if (!a || !a->st)
7317 : : return n_instructions;
7318 : :
7319 [ # # ]: 0 : for (i = 0; i < n_instructions; ) {
7320 : 0 : struct instruction *instr = &instructions[i];
7321 : 0 : struct instruction_data *data = &instruction_data[i];
7322 : 0 : uint32_t n_instr = 0;
7323 : : int detected;
7324 : :
7325 : : /* Validate + mov all. */
7326 : 0 : detected = instr_pattern_validate_mov_all_search(p,
7327 : : a,
7328 : : instr,
7329 : : data,
7330 : : n_instructions - i,
7331 : : instructions,
7332 : : instruction_data,
7333 : : n_instructions,
7334 : : &n_instr);
7335 [ # # ]: 0 : if (detected) {
7336 : 0 : instr_pattern_validate_mov_all_replace(p, a, instr, data, n_instr);
7337 : 0 : i += n_instr;
7338 : 0 : continue;
7339 : : }
7340 : :
7341 : : /* No pattern starting at the current instruction. */
7342 : 0 : i++;
7343 : : }
7344 : :
7345 : : /* Eliminate the invalid instructions that have been optimized out. */
7346 : 0 : n_instructions = instr_compact(instructions,
7347 : : instruction_data,
7348 : : n_instructions);
7349 : :
7350 : 0 : return n_instructions;
7351 : : }
7352 : :
7353 : : static int
7354 : 0 : instr_pattern_dma_many_search(struct instruction *instr,
7355 : : struct instruction_data *data,
7356 : : uint32_t n_instr,
7357 : : uint32_t *n_pattern_instr)
7358 : : {
7359 : : uint32_t i;
7360 : :
7361 [ # # ]: 0 : for (i = 0; i < n_instr; i++) {
7362 [ # # ]: 0 : if (data[i].invalid)
7363 : : break;
7364 : :
7365 [ # # ]: 0 : if (instr[i].type != INSTR_DMA_HT)
7366 : : break;
7367 : :
7368 [ # # ]: 0 : if (i == RTE_DIM(instr->dma.dst.header_id))
7369 : : break;
7370 : :
7371 [ # # # # ]: 0 : if (i && data[i].n_users)
7372 : : break;
7373 : : }
7374 : :
7375 [ # # ]: 0 : if (i < 2)
7376 : : return 0;
7377 : :
7378 : 0 : *n_pattern_instr = i;
7379 : 0 : return 1;
7380 : : }
7381 : :
7382 : : static void
7383 : 0 : instr_pattern_dma_many_replace(struct instruction *instr,
7384 : : struct instruction_data *data,
7385 : : uint32_t n_instr)
7386 : : {
7387 : : uint32_t i;
7388 : :
7389 [ # # ]: 0 : for (i = 1; i < n_instr; i++) {
7390 : 0 : instr[0].type++;
7391 : 0 : instr[0].dma.dst.header_id[i] = instr[i].dma.dst.header_id[0];
7392 : 0 : instr[0].dma.dst.struct_id[i] = instr[i].dma.dst.struct_id[0];
7393 : 0 : instr[0].dma.src.offset[i] = instr[i].dma.src.offset[0];
7394 : 0 : instr[0].dma.n_bytes[i] = instr[i].dma.n_bytes[0];
7395 : :
7396 : 0 : data[i].invalid = 1;
7397 : : }
7398 : 0 : }
7399 : :
7400 : : static uint32_t
7401 : 0 : instr_pattern_dma_many_optimize(struct instruction *instructions,
7402 : : struct instruction_data *instruction_data,
7403 : : uint32_t n_instructions)
7404 : : {
7405 : : uint32_t i;
7406 : :
7407 [ # # ]: 0 : for (i = 0; i < n_instructions; ) {
7408 : 0 : struct instruction *instr = &instructions[i];
7409 : 0 : struct instruction_data *data = &instruction_data[i];
7410 : 0 : uint32_t n_instr = 0;
7411 : : int detected;
7412 : :
7413 : : /* DMA many. */
7414 : 0 : detected = instr_pattern_dma_many_search(instr,
7415 : : data,
7416 : : n_instructions - i,
7417 : : &n_instr);
7418 [ # # ]: 0 : if (detected) {
7419 : 0 : instr_pattern_dma_many_replace(instr, data, n_instr);
7420 : 0 : i += n_instr;
7421 : 0 : continue;
7422 : : }
7423 : :
7424 : : /* No pattern starting at the current instruction. */
7425 : 0 : i++;
7426 : : }
7427 : :
7428 : : /* Eliminate the invalid instructions that have been optimized out. */
7429 : 0 : n_instructions = instr_compact(instructions,
7430 : : instruction_data,
7431 : : n_instructions);
7432 : :
7433 : 0 : return n_instructions;
7434 : : }
7435 : :
7436 : : static uint32_t
7437 : 0 : instr_optimize(struct rte_swx_pipeline *p,
7438 : : struct action *a,
7439 : : struct instruction *instructions,
7440 : : struct instruction_data *instruction_data,
7441 : : uint32_t n_instructions)
7442 : : {
7443 : : /* Extract many. */
7444 : 0 : n_instructions = instr_pattern_extract_many_optimize(instructions,
7445 : : instruction_data,
7446 : : n_instructions);
7447 : :
7448 : : /* Emit many + TX. */
7449 : 0 : n_instructions = instr_pattern_emit_many_tx_optimize(instructions,
7450 : : instruction_data,
7451 : : n_instructions);
7452 : :
7453 : : /* Validate + mov all. */
7454 : 0 : n_instructions = instr_pattern_validate_mov_all_optimize(p,
7455 : : a,
7456 : : instructions,
7457 : : instruction_data,
7458 : : n_instructions);
7459 : :
7460 : : /* DMA many. */
7461 : 0 : n_instructions = instr_pattern_dma_many_optimize(instructions,
7462 : : instruction_data,
7463 : : n_instructions);
7464 : :
7465 : 0 : return n_instructions;
7466 : : }
7467 : :
7468 : : static int
7469 : 0 : instruction_config(struct rte_swx_pipeline *p,
7470 : : struct action *a,
7471 : : const char **instructions,
7472 : : uint32_t n_instructions)
7473 : : {
7474 : : struct instruction *instr = NULL;
7475 : : struct instruction_data *data = NULL;
7476 : : int err = 0;
7477 : : uint32_t i;
7478 : :
7479 [ # # ]: 0 : CHECK(n_instructions, EINVAL);
7480 [ # # ]: 0 : CHECK(instructions, EINVAL);
7481 [ # # ]: 0 : for (i = 0; i < n_instructions; i++)
7482 [ # # # # : 0 : CHECK_INSTRUCTION(instructions[i], EINVAL);
# # ]
7483 : :
7484 : : /* Memory allocation. */
7485 : 0 : instr = calloc(n_instructions, sizeof(struct instruction));
7486 [ # # ]: 0 : if (!instr) {
7487 : : err = -ENOMEM;
7488 : 0 : goto error;
7489 : : }
7490 : :
7491 : 0 : data = calloc(n_instructions, sizeof(struct instruction_data));
7492 [ # # ]: 0 : if (!data) {
7493 : : err = -ENOMEM;
7494 : 0 : goto error;
7495 : : }
7496 : :
7497 [ # # ]: 0 : for (i = 0; i < n_instructions; i++) {
7498 : 0 : char *string = strdup(instructions[i]);
7499 [ # # ]: 0 : if (!string) {
7500 : : err = -ENOMEM;
7501 : 0 : goto error;
7502 : : }
7503 : :
7504 : 0 : err = instr_translate(p, a, string, &instr[i], &data[i]);
7505 [ # # ]: 0 : if (err) {
7506 : 0 : free(string);
7507 : 0 : goto error;
7508 : : }
7509 : :
7510 : 0 : free(string);
7511 : : }
7512 : :
7513 : 0 : err = instr_label_check(data, n_instructions);
7514 [ # # ]: 0 : if (err)
7515 : 0 : goto error;
7516 : :
7517 : 0 : err = instr_verify(p, a, instr, data, n_instructions);
7518 [ # # ]: 0 : if (err)
7519 : 0 : goto error;
7520 : :
7521 : 0 : n_instructions = instr_optimize(p, a, instr, data, n_instructions);
7522 : :
7523 : 0 : err = instr_jmp_resolve(instr, data, n_instructions);
7524 [ # # ]: 0 : if (err)
7525 : 0 : goto error;
7526 : :
7527 [ # # ]: 0 : if (a) {
7528 : 0 : a->instructions = instr;
7529 : 0 : a->instruction_data = data;
7530 : 0 : a->n_instructions = n_instructions;
7531 : : } else {
7532 : 0 : p->instructions = instr;
7533 : 0 : p->instruction_data = data;
7534 : 0 : p->n_instructions = n_instructions;
7535 : : }
7536 : :
7537 : : return 0;
7538 : :
7539 : 0 : error:
7540 : 0 : free(data);
7541 : 0 : free(instr);
7542 : 0 : return err;
7543 : : }
7544 : :
7545 : : static instr_exec_t instruction_table[] = {
7546 : : [INSTR_RX] = instr_rx_exec,
7547 : : [INSTR_TX] = instr_tx_exec,
7548 : : [INSTR_TX_I] = instr_tx_i_exec,
7549 : : [INSTR_DROP] = instr_drop_exec,
7550 : : [INSTR_MIRROR] = instr_mirror_exec,
7551 : : [INSTR_RECIRCULATE] = instr_recirculate_exec,
7552 : : [INSTR_RECIRCID] = instr_recircid_exec,
7553 : :
7554 : : [INSTR_HDR_EXTRACT] = instr_hdr_extract_exec,
7555 : : [INSTR_HDR_EXTRACT2] = instr_hdr_extract2_exec,
7556 : : [INSTR_HDR_EXTRACT3] = instr_hdr_extract3_exec,
7557 : : [INSTR_HDR_EXTRACT4] = instr_hdr_extract4_exec,
7558 : : [INSTR_HDR_EXTRACT5] = instr_hdr_extract5_exec,
7559 : : [INSTR_HDR_EXTRACT6] = instr_hdr_extract6_exec,
7560 : : [INSTR_HDR_EXTRACT7] = instr_hdr_extract7_exec,
7561 : : [INSTR_HDR_EXTRACT8] = instr_hdr_extract8_exec,
7562 : : [INSTR_HDR_EXTRACT_M] = instr_hdr_extract_m_exec,
7563 : : [INSTR_HDR_LOOKAHEAD] = instr_hdr_lookahead_exec,
7564 : :
7565 : : [INSTR_HDR_EMIT] = instr_hdr_emit_exec,
7566 : : [INSTR_HDR_EMIT_TX] = instr_hdr_emit_tx_exec,
7567 : : [INSTR_HDR_EMIT2_TX] = instr_hdr_emit2_tx_exec,
7568 : : [INSTR_HDR_EMIT3_TX] = instr_hdr_emit3_tx_exec,
7569 : : [INSTR_HDR_EMIT4_TX] = instr_hdr_emit4_tx_exec,
7570 : : [INSTR_HDR_EMIT5_TX] = instr_hdr_emit5_tx_exec,
7571 : : [INSTR_HDR_EMIT6_TX] = instr_hdr_emit6_tx_exec,
7572 : : [INSTR_HDR_EMIT7_TX] = instr_hdr_emit7_tx_exec,
7573 : : [INSTR_HDR_EMIT8_TX] = instr_hdr_emit8_tx_exec,
7574 : :
7575 : : [INSTR_HDR_VALIDATE] = instr_hdr_validate_exec,
7576 : : [INSTR_HDR_INVALIDATE] = instr_hdr_invalidate_exec,
7577 : :
7578 : : [INSTR_MOV] = instr_mov_exec,
7579 : : [INSTR_MOV_MH] = instr_mov_mh_exec,
7580 : : [INSTR_MOV_HM] = instr_mov_hm_exec,
7581 : : [INSTR_MOV_HH] = instr_mov_hh_exec,
7582 : : [INSTR_MOV_DMA] = instr_mov_dma_exec,
7583 : : [INSTR_MOV_128] = instr_mov_128_exec,
7584 : : [INSTR_MOV_128_64] = instr_mov_128_64_exec,
7585 : : [INSTR_MOV_64_128] = instr_mov_64_128_exec,
7586 : : [INSTR_MOV_128_32] = instr_mov_128_32_exec,
7587 : : [INSTR_MOV_32_128] = instr_mov_32_128_exec,
7588 : : [INSTR_MOV_I] = instr_mov_i_exec,
7589 : :
7590 : : [INSTR_MOVH] = instr_movh_exec,
7591 : :
7592 : : [INSTR_DMA_HT] = instr_dma_ht_exec,
7593 : : [INSTR_DMA_HT2] = instr_dma_ht2_exec,
7594 : : [INSTR_DMA_HT3] = instr_dma_ht3_exec,
7595 : : [INSTR_DMA_HT4] = instr_dma_ht4_exec,
7596 : : [INSTR_DMA_HT5] = instr_dma_ht5_exec,
7597 : : [INSTR_DMA_HT6] = instr_dma_ht6_exec,
7598 : : [INSTR_DMA_HT7] = instr_dma_ht7_exec,
7599 : : [INSTR_DMA_HT8] = instr_dma_ht8_exec,
7600 : :
7601 : : [INSTR_ALU_ADD] = instr_alu_add_exec,
7602 : : [INSTR_ALU_ADD_MH] = instr_alu_add_mh_exec,
7603 : : [INSTR_ALU_ADD_HM] = instr_alu_add_hm_exec,
7604 : : [INSTR_ALU_ADD_HH] = instr_alu_add_hh_exec,
7605 : : [INSTR_ALU_ADD_MI] = instr_alu_add_mi_exec,
7606 : : [INSTR_ALU_ADD_HI] = instr_alu_add_hi_exec,
7607 : :
7608 : : [INSTR_ALU_SUB] = instr_alu_sub_exec,
7609 : : [INSTR_ALU_SUB_MH] = instr_alu_sub_mh_exec,
7610 : : [INSTR_ALU_SUB_HM] = instr_alu_sub_hm_exec,
7611 : : [INSTR_ALU_SUB_HH] = instr_alu_sub_hh_exec,
7612 : : [INSTR_ALU_SUB_MI] = instr_alu_sub_mi_exec,
7613 : : [INSTR_ALU_SUB_HI] = instr_alu_sub_hi_exec,
7614 : :
7615 : : [INSTR_ALU_CKADD_FIELD] = instr_alu_ckadd_field_exec,
7616 : : [INSTR_ALU_CKADD_STRUCT] = instr_alu_ckadd_struct_exec,
7617 : : [INSTR_ALU_CKADD_STRUCT20] = instr_alu_ckadd_struct20_exec,
7618 : : [INSTR_ALU_CKSUB_FIELD] = instr_alu_cksub_field_exec,
7619 : :
7620 : : [INSTR_ALU_AND] = instr_alu_and_exec,
7621 : : [INSTR_ALU_AND_MH] = instr_alu_and_mh_exec,
7622 : : [INSTR_ALU_AND_HM] = instr_alu_and_hm_exec,
7623 : : [INSTR_ALU_AND_HH] = instr_alu_and_hh_exec,
7624 : : [INSTR_ALU_AND_I] = instr_alu_and_i_exec,
7625 : :
7626 : : [INSTR_ALU_OR] = instr_alu_or_exec,
7627 : : [INSTR_ALU_OR_MH] = instr_alu_or_mh_exec,
7628 : : [INSTR_ALU_OR_HM] = instr_alu_or_hm_exec,
7629 : : [INSTR_ALU_OR_HH] = instr_alu_or_hh_exec,
7630 : : [INSTR_ALU_OR_I] = instr_alu_or_i_exec,
7631 : :
7632 : : [INSTR_ALU_XOR] = instr_alu_xor_exec,
7633 : : [INSTR_ALU_XOR_MH] = instr_alu_xor_mh_exec,
7634 : : [INSTR_ALU_XOR_HM] = instr_alu_xor_hm_exec,
7635 : : [INSTR_ALU_XOR_HH] = instr_alu_xor_hh_exec,
7636 : : [INSTR_ALU_XOR_I] = instr_alu_xor_i_exec,
7637 : :
7638 : : [INSTR_ALU_SHL] = instr_alu_shl_exec,
7639 : : [INSTR_ALU_SHL_MH] = instr_alu_shl_mh_exec,
7640 : : [INSTR_ALU_SHL_HM] = instr_alu_shl_hm_exec,
7641 : : [INSTR_ALU_SHL_HH] = instr_alu_shl_hh_exec,
7642 : : [INSTR_ALU_SHL_MI] = instr_alu_shl_mi_exec,
7643 : : [INSTR_ALU_SHL_HI] = instr_alu_shl_hi_exec,
7644 : :
7645 : : [INSTR_ALU_SHR] = instr_alu_shr_exec,
7646 : : [INSTR_ALU_SHR_MH] = instr_alu_shr_mh_exec,
7647 : : [INSTR_ALU_SHR_HM] = instr_alu_shr_hm_exec,
7648 : : [INSTR_ALU_SHR_HH] = instr_alu_shr_hh_exec,
7649 : : [INSTR_ALU_SHR_MI] = instr_alu_shr_mi_exec,
7650 : : [INSTR_ALU_SHR_HI] = instr_alu_shr_hi_exec,
7651 : :
7652 : : [INSTR_REGPREFETCH_RH] = instr_regprefetch_rh_exec,
7653 : : [INSTR_REGPREFETCH_RM] = instr_regprefetch_rm_exec,
7654 : : [INSTR_REGPREFETCH_RI] = instr_regprefetch_ri_exec,
7655 : :
7656 : : [INSTR_REGRD_HRH] = instr_regrd_hrh_exec,
7657 : : [INSTR_REGRD_HRM] = instr_regrd_hrm_exec,
7658 : : [INSTR_REGRD_MRH] = instr_regrd_mrh_exec,
7659 : : [INSTR_REGRD_MRM] = instr_regrd_mrm_exec,
7660 : : [INSTR_REGRD_HRI] = instr_regrd_hri_exec,
7661 : : [INSTR_REGRD_MRI] = instr_regrd_mri_exec,
7662 : :
7663 : : [INSTR_REGWR_RHH] = instr_regwr_rhh_exec,
7664 : : [INSTR_REGWR_RHM] = instr_regwr_rhm_exec,
7665 : : [INSTR_REGWR_RMH] = instr_regwr_rmh_exec,
7666 : : [INSTR_REGWR_RMM] = instr_regwr_rmm_exec,
7667 : : [INSTR_REGWR_RHI] = instr_regwr_rhi_exec,
7668 : : [INSTR_REGWR_RMI] = instr_regwr_rmi_exec,
7669 : : [INSTR_REGWR_RIH] = instr_regwr_rih_exec,
7670 : : [INSTR_REGWR_RIM] = instr_regwr_rim_exec,
7671 : : [INSTR_REGWR_RII] = instr_regwr_rii_exec,
7672 : :
7673 : : [INSTR_REGADD_RHH] = instr_regadd_rhh_exec,
7674 : : [INSTR_REGADD_RHM] = instr_regadd_rhm_exec,
7675 : : [INSTR_REGADD_RMH] = instr_regadd_rmh_exec,
7676 : : [INSTR_REGADD_RMM] = instr_regadd_rmm_exec,
7677 : : [INSTR_REGADD_RHI] = instr_regadd_rhi_exec,
7678 : : [INSTR_REGADD_RMI] = instr_regadd_rmi_exec,
7679 : : [INSTR_REGADD_RIH] = instr_regadd_rih_exec,
7680 : : [INSTR_REGADD_RIM] = instr_regadd_rim_exec,
7681 : : [INSTR_REGADD_RII] = instr_regadd_rii_exec,
7682 : :
7683 : : [INSTR_METPREFETCH_H] = instr_metprefetch_h_exec,
7684 : : [INSTR_METPREFETCH_M] = instr_metprefetch_m_exec,
7685 : : [INSTR_METPREFETCH_I] = instr_metprefetch_i_exec,
7686 : :
7687 : : [INSTR_METER_HHM] = instr_meter_hhm_exec,
7688 : : [INSTR_METER_HHI] = instr_meter_hhi_exec,
7689 : : [INSTR_METER_HMM] = instr_meter_hmm_exec,
7690 : : [INSTR_METER_HMI] = instr_meter_hmi_exec,
7691 : : [INSTR_METER_MHM] = instr_meter_mhm_exec,
7692 : : [INSTR_METER_MHI] = instr_meter_mhi_exec,
7693 : : [INSTR_METER_MMM] = instr_meter_mmm_exec,
7694 : : [INSTR_METER_MMI] = instr_meter_mmi_exec,
7695 : : [INSTR_METER_IHM] = instr_meter_ihm_exec,
7696 : : [INSTR_METER_IHI] = instr_meter_ihi_exec,
7697 : : [INSTR_METER_IMM] = instr_meter_imm_exec,
7698 : : [INSTR_METER_IMI] = instr_meter_imi_exec,
7699 : :
7700 : : [INSTR_TABLE] = instr_table_exec,
7701 : : [INSTR_TABLE_AF] = instr_table_af_exec,
7702 : : [INSTR_SELECTOR] = instr_selector_exec,
7703 : : [INSTR_LEARNER] = instr_learner_exec,
7704 : : [INSTR_LEARNER_AF] = instr_learner_af_exec,
7705 : : [INSTR_LEARNER_LEARN] = instr_learn_exec,
7706 : : [INSTR_LEARNER_REARM] = instr_rearm_exec,
7707 : : [INSTR_LEARNER_REARM_NEW] = instr_rearm_new_exec,
7708 : : [INSTR_LEARNER_FORGET] = instr_forget_exec,
7709 : : [INSTR_ENTRYID] = instr_entryid_exec,
7710 : :
7711 : : [INSTR_EXTERN_OBJ] = instr_extern_obj_exec,
7712 : : [INSTR_EXTERN_FUNC] = instr_extern_func_exec,
7713 : : [INSTR_HASH_FUNC] = instr_hash_func_exec,
7714 : : [INSTR_RSS] = instr_rss_exec,
7715 : :
7716 : : [INSTR_JMP] = instr_jmp_exec,
7717 : : [INSTR_JMP_VALID] = instr_jmp_valid_exec,
7718 : : [INSTR_JMP_INVALID] = instr_jmp_invalid_exec,
7719 : : [INSTR_JMP_HIT] = instr_jmp_hit_exec,
7720 : : [INSTR_JMP_MISS] = instr_jmp_miss_exec,
7721 : : [INSTR_JMP_ACTION_HIT] = instr_jmp_action_hit_exec,
7722 : : [INSTR_JMP_ACTION_MISS] = instr_jmp_action_miss_exec,
7723 : :
7724 : : [INSTR_JMP_EQ] = instr_jmp_eq_exec,
7725 : : [INSTR_JMP_EQ_MH] = instr_jmp_eq_mh_exec,
7726 : : [INSTR_JMP_EQ_HM] = instr_jmp_eq_hm_exec,
7727 : : [INSTR_JMP_EQ_HH] = instr_jmp_eq_hh_exec,
7728 : : [INSTR_JMP_EQ_I] = instr_jmp_eq_i_exec,
7729 : :
7730 : : [INSTR_JMP_NEQ] = instr_jmp_neq_exec,
7731 : : [INSTR_JMP_NEQ_MH] = instr_jmp_neq_mh_exec,
7732 : : [INSTR_JMP_NEQ_HM] = instr_jmp_neq_hm_exec,
7733 : : [INSTR_JMP_NEQ_HH] = instr_jmp_neq_hh_exec,
7734 : : [INSTR_JMP_NEQ_I] = instr_jmp_neq_i_exec,
7735 : :
7736 : : [INSTR_JMP_LT] = instr_jmp_lt_exec,
7737 : : [INSTR_JMP_LT_MH] = instr_jmp_lt_mh_exec,
7738 : : [INSTR_JMP_LT_HM] = instr_jmp_lt_hm_exec,
7739 : : [INSTR_JMP_LT_HH] = instr_jmp_lt_hh_exec,
7740 : : [INSTR_JMP_LT_MI] = instr_jmp_lt_mi_exec,
7741 : : [INSTR_JMP_LT_HI] = instr_jmp_lt_hi_exec,
7742 : :
7743 : : [INSTR_JMP_GT] = instr_jmp_gt_exec,
7744 : : [INSTR_JMP_GT_MH] = instr_jmp_gt_mh_exec,
7745 : : [INSTR_JMP_GT_HM] = instr_jmp_gt_hm_exec,
7746 : : [INSTR_JMP_GT_HH] = instr_jmp_gt_hh_exec,
7747 : : [INSTR_JMP_GT_MI] = instr_jmp_gt_mi_exec,
7748 : : [INSTR_JMP_GT_HI] = instr_jmp_gt_hi_exec,
7749 : :
7750 : : [INSTR_RETURN] = instr_return_exec,
7751 : : };
7752 : :
7753 : : static int
7754 : 0 : instruction_table_build(struct rte_swx_pipeline *p)
7755 : : {
7756 : 0 : p->instruction_table = calloc(RTE_SWX_PIPELINE_INSTRUCTION_TABLE_SIZE_MAX,
7757 : : sizeof(struct instr_exec_t *));
7758 [ # # ]: 0 : if (!p->instruction_table)
7759 : : return -EINVAL;
7760 : :
7761 : : memcpy(p->instruction_table, instruction_table, sizeof(instruction_table));
7762 : :
7763 : 0 : return 0;
7764 : : }
7765 : :
7766 : : static void
7767 : : instruction_table_build_free(struct rte_swx_pipeline *p)
7768 : : {
7769 [ # # ]: 0 : if (!p->instruction_table)
7770 : : return;
7771 : :
7772 : 0 : free(p->instruction_table);
7773 : 0 : p->instruction_table = NULL;
7774 : : }
7775 : :
7776 : : static void
7777 : : instruction_table_free(struct rte_swx_pipeline *p)
7778 : : {
7779 : : instruction_table_build_free(p);
7780 : : }
7781 : :
7782 : : static inline void
7783 : : instr_exec(struct rte_swx_pipeline *p)
7784 : : {
7785 : 0 : struct thread *t = &p->threads[p->thread_id];
7786 : 0 : struct instruction *ip = t->ip;
7787 : 0 : instr_exec_t instr = p->instruction_table[ip->type];
7788 : :
7789 : 0 : instr(p);
7790 : : }
7791 : :
7792 : : /*
7793 : : * Action.
7794 : : */
7795 : : static struct action *
7796 : 0 : action_find(struct rte_swx_pipeline *p, const char *name)
7797 : : {
7798 : : struct action *elem;
7799 : :
7800 [ # # ]: 0 : if (!name)
7801 : : return NULL;
7802 : :
7803 [ # # ]: 0 : TAILQ_FOREACH(elem, &p->actions, node)
7804 [ # # ]: 0 : if (strcmp(elem->name, name) == 0)
7805 : 0 : return elem;
7806 : :
7807 : : return NULL;
7808 : : }
7809 : :
7810 : : static struct action *
7811 : : action_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7812 : : {
7813 : : struct action *action = NULL;
7814 : :
7815 [ # # # # ]: 0 : TAILQ_FOREACH(action, &p->actions, node)
7816 [ # # # # ]: 0 : if (action->id == id)
7817 : : return action;
7818 : :
7819 : : return NULL;
7820 : : }
7821 : :
7822 : : static struct field *
7823 : : action_field_find(struct action *a, const char *name)
7824 : : {
7825 : 0 : return a->st ? struct_type_field_find(a->st, name) : NULL;
7826 : : }
7827 : :
7828 : : static struct field *
7829 : 0 : action_field_parse(struct action *action, const char *name)
7830 : : {
7831 [ # # # # ]: 0 : if (name[0] != 't' || name[1] != '.')
7832 : : return NULL;
7833 : :
7834 [ # # ]: 0 : return action_field_find(action, &name[2]);
7835 : : }
7836 : :
7837 : : static int
7838 : : action_has_nbo_args(struct action *a)
7839 : : {
7840 : : uint32_t i;
7841 : :
7842 : : /* Return if the action does not have any args. */
7843 [ # # ]: 0 : if (!a->st)
7844 : : return 0; /* FALSE */
7845 : :
7846 [ # # ]: 0 : for (i = 0; i < a->st->n_fields; i++)
7847 [ # # ]: 0 : if (a->args_endianness[i])
7848 : : return 1; /* TRUE */
7849 : :
7850 : : return 0; /* FALSE */
7851 : : }
7852 : :
7853 : : static int
7854 : : action_does_learning(struct action *a)
7855 : : {
7856 : : uint32_t i;
7857 : :
7858 [ # # ]: 0 : for (i = 0; i < a->n_instructions; i++)
7859 [ # # ]: 0 : switch (a->instructions[i].type) {
7860 : : case INSTR_LEARNER_LEARN:
7861 : : return 1; /* TRUE */
7862 : :
7863 : : case INSTR_LEARNER_FORGET:
7864 : : return 1; /* TRUE */
7865 : :
7866 : 0 : default:
7867 : : continue;
7868 : : }
7869 : :
7870 : : return 0; /* FALSE */
7871 : : }
7872 : :
7873 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_pipeline_action_config, 20.11)
7874 : : int
7875 : 0 : rte_swx_pipeline_action_config(struct rte_swx_pipeline *p,
7876 : : const char *name,
7877 : : const char *args_struct_type_name,
7878 : : const char **instructions,
7879 : : uint32_t n_instructions)
7880 : : {
7881 : : struct struct_type *args_struct_type = NULL;
7882 : : struct action *a = NULL;
7883 : : int status = 0;
7884 : :
7885 [ # # ]: 0 : CHECK(p, EINVAL);
7886 : :
7887 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
7888 [ # # ]: 0 : CHECK(!action_find(p, name), EEXIST);
7889 : :
7890 [ # # ]: 0 : if (args_struct_type_name) {
7891 [ # # # # ]: 0 : CHECK_NAME(args_struct_type_name, EINVAL);
7892 : : args_struct_type = struct_type_find(p, args_struct_type_name);
7893 [ # # ]: 0 : CHECK(args_struct_type, EINVAL);
7894 [ # # ]: 0 : CHECK(!args_struct_type->var_size, EINVAL);
7895 : : }
7896 : :
7897 : : /* Node allocation. */
7898 : 0 : a = calloc(1, sizeof(struct action));
7899 [ # # ]: 0 : if (!a) {
7900 : : status = -ENOMEM;
7901 : 0 : goto error;
7902 : : }
7903 : :
7904 [ # # ]: 0 : if (args_struct_type) {
7905 : 0 : a->args_endianness = calloc(args_struct_type->n_fields, sizeof(int));
7906 [ # # ]: 0 : if (!a->args_endianness) {
7907 : : status = -ENOMEM;
7908 : 0 : goto error;
7909 : : }
7910 : : }
7911 : :
7912 : : /* Node initialization. */
7913 : 0 : strcpy(a->name, name);
7914 : 0 : a->st = args_struct_type;
7915 : 0 : a->id = p->n_actions;
7916 : :
7917 : : /* Instruction translation. */
7918 : 0 : status = instruction_config(p, a, instructions, n_instructions);
7919 [ # # ]: 0 : if (status)
7920 : 0 : goto error;
7921 : :
7922 : : /* Node add to tailq. */
7923 : 0 : TAILQ_INSERT_TAIL(&p->actions, a, node);
7924 : 0 : p->n_actions++;
7925 : :
7926 : 0 : return 0;
7927 : :
7928 : 0 : error:
7929 [ # # ]: 0 : if (!a)
7930 : : return status;
7931 : :
7932 : 0 : free(a->args_endianness);
7933 : 0 : free(a->instructions);
7934 : 0 : free(a->instruction_data);
7935 : 0 : free(a);
7936 : :
7937 : 0 : return status;
7938 : : }
7939 : :
7940 : : static int
7941 : 0 : action_build(struct rte_swx_pipeline *p)
7942 : : {
7943 : : struct action *action;
7944 : :
7945 : : /* p->action_instructions. */
7946 : 0 : p->action_instructions = calloc(p->n_actions, sizeof(struct instruction *));
7947 [ # # ]: 0 : CHECK(p->action_instructions, ENOMEM);
7948 : :
7949 [ # # ]: 0 : TAILQ_FOREACH(action, &p->actions, node)
7950 : 0 : p->action_instructions[action->id] = action->instructions;
7951 : :
7952 : : /* p->action_funcs. */
7953 : 0 : p->action_funcs = calloc(p->n_actions, sizeof(action_func_t));
7954 [ # # ]: 0 : CHECK(p->action_funcs, ENOMEM);
7955 : :
7956 : : return 0;
7957 : : }
7958 : :
7959 : : static void
7960 : : action_build_free(struct rte_swx_pipeline *p)
7961 : : {
7962 : 0 : free(p->action_funcs);
7963 : 0 : p->action_funcs = NULL;
7964 : :
7965 : 0 : free(p->action_instructions);
7966 [ # # ]: 0 : p->action_instructions = NULL;
7967 : 0 : }
7968 : :
7969 : : static void
7970 : 0 : action_free(struct rte_swx_pipeline *p)
7971 : : {
7972 : : action_build_free(p);
7973 : :
7974 : 0 : for ( ; ; ) {
7975 : : struct action *action;
7976 : :
7977 : 0 : action = TAILQ_FIRST(&p->actions);
7978 [ # # ]: 0 : if (!action)
7979 : : break;
7980 : :
7981 [ # # ]: 0 : TAILQ_REMOVE(&p->actions, action, node);
7982 : 0 : free(action->args_endianness);
7983 : 0 : free(action->instructions);
7984 : 0 : free(action->instruction_data);
7985 : 0 : free(action);
7986 : : }
7987 : 0 : }
7988 : :
7989 : : static uint32_t
7990 : 0 : action_arg_src_mov_count(struct action *a,
7991 : : uint32_t arg_id,
7992 : : struct instruction *instructions,
7993 : : struct instruction_data *instruction_data,
7994 : : uint32_t n_instructions)
7995 : : {
7996 : : uint32_t offset, n_users = 0, i;
7997 : :
7998 [ # # ]: 0 : if (!a->st ||
7999 [ # # ]: 0 : (arg_id >= a->st->n_fields) ||
8000 : 0 : !instructions ||
8001 [ # # # # ]: 0 : !instruction_data ||
8002 : : !n_instructions)
8003 : : return 0;
8004 : :
8005 : 0 : offset = a->st->fields[arg_id].offset / 8;
8006 : :
8007 [ # # ]: 0 : for (i = 0; i < n_instructions; i++) {
8008 : 0 : struct instruction *instr = &instructions[i];
8009 : 0 : struct instruction_data *data = &instruction_data[i];
8010 : :
8011 [ # # ]: 0 : if (data->invalid ||
8012 [ # # ]: 0 : ((instr->type != INSTR_MOV) && (instr->type != INSTR_MOV_HM)) ||
8013 [ # # ]: 0 : instr->mov.src.struct_id ||
8014 [ # # ]: 0 : (instr->mov.src.offset != offset))
8015 : 0 : continue;
8016 : :
8017 : 0 : n_users++;
8018 : : }
8019 : :
8020 : : return n_users;
8021 : : }
8022 : :
8023 : : static int
8024 : : char_to_hex(char c, uint8_t *val)
8025 : : {
8026 : 0 : if (c >= '0' && c <= '9') {
8027 : : *val = c - '0';
8028 : : return 0;
8029 : : }
8030 : :
8031 [ # # # # ]: 0 : if (c >= 'A' && c <= 'F') {
8032 : 0 : *val = c - 'A' + 10;
8033 : : return 0;
8034 : : }
8035 : :
8036 [ # # # # ]: 0 : if (c >= 'a' && c <= 'f') {
8037 : 0 : *val = c - 'a' + 10;
8038 : : return 0;
8039 : : }
8040 : :
8041 : : return -EINVAL;
8042 : : }
8043 : :
8044 : : static int
8045 : 0 : hex_string_parse(char *src, uint8_t *dst, uint32_t n_dst_bytes)
8046 : : {
8047 : : uint32_t i;
8048 : :
8049 : : /* Check input arguments. */
8050 [ # # # # : 0 : if (!src || !src[0] || !dst || !n_dst_bytes)
# # ]
8051 : : return -EINVAL;
8052 : :
8053 : : /* Skip any leading "0x" or "0X" in the src string. */
8054 [ # # # # ]: 0 : if ((src[0] == '0') && (src[1] == 'x' || src[1] == 'X'))
8055 : 0 : src += 2;
8056 : :
8057 : : /* Convert each group of two hex characters in the src string to one byte in dst array. */
8058 [ # # ]: 0 : for (i = 0; i < n_dst_bytes; i++) {
8059 : : uint8_t a, b;
8060 : : int status;
8061 : :
8062 [ # # ]: 0 : status = char_to_hex(*src, &a);
8063 : : if (status)
8064 : : return status;
8065 : : src++;
8066 : :
8067 [ # # ]: 0 : status = char_to_hex(*src, &b);
8068 : : if (status)
8069 : : return status;
8070 : 0 : src++;
8071 : :
8072 : 0 : dst[i] = a * 16 + b;
8073 : : }
8074 : :
8075 : : /* Check for the end of the src string. */
8076 [ # # ]: 0 : if (*src)
8077 : 0 : return -EINVAL;
8078 : :
8079 : : return 0;
8080 : : }
8081 : :
8082 : : #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
8083 : : #define field_ntoh(val, n_bits) (ntoh64((val) << (64 - n_bits)))
8084 : : #define field_hton(val, n_bits) (hton64((val) << (64 - n_bits)))
8085 : : #else
8086 : : #define field_ntoh(val, n_bits) (val)
8087 : : #define field_hton(val, n_bits) (val)
8088 : : #endif
8089 : :
8090 : : #define ACTION_ARGS_TOKENS_MAX 256
8091 : :
8092 : : static int
8093 : 0 : action_args_parse(struct action *a, const char *args, uint8_t *data)
8094 : : {
8095 : : char *tokens[ACTION_ARGS_TOKENS_MAX], *s0 = NULL, *s;
8096 : : uint32_t n_tokens = 0, offset = 0, i;
8097 : : int status = 0;
8098 : :
8099 : : /* Checks. */
8100 [ # # # # : 0 : if (!a->st || !args || !args[0]) {
# # ]
8101 : : status = -EINVAL;
8102 : 0 : goto error;
8103 : : }
8104 : :
8105 : : /* Memory allocation. */
8106 : 0 : s0 = strdup(args);
8107 [ # # ]: 0 : if (!s0) {
8108 : : status = -ENOMEM;
8109 : 0 : goto error;
8110 : : }
8111 : :
8112 : : /* Parse the string into tokens. */
8113 : 0 : for (s = s0; ; ) {
8114 : : char *token;
8115 : :
8116 : 0 : token = strtok_r(s, " \f\n\r\t\v", &s);
8117 [ # # ]: 0 : if (!token)
8118 : : break;
8119 : :
8120 [ # # ]: 0 : if (n_tokens >= RTE_DIM(tokens)) {
8121 : : status = -EINVAL;
8122 : 0 : goto error;
8123 : : }
8124 : :
8125 : 0 : tokens[n_tokens] = token;
8126 : 0 : n_tokens++;
8127 : : }
8128 : :
8129 : : /* More checks. */
8130 [ # # ]: 0 : if (n_tokens != a->st->n_fields * 2) {
8131 : : status = -EINVAL;
8132 : 0 : goto error;
8133 : : }
8134 : :
8135 : : /* Process the action arguments. */
8136 [ # # ]: 0 : for (i = 0; i < a->st->n_fields; i++) {
8137 : 0 : struct field *f = &a->st->fields[i];
8138 : 0 : char *arg_name = tokens[i * 2];
8139 : 0 : char *arg_val = tokens[i * 2 + 1];
8140 : :
8141 [ # # ]: 0 : if (strcmp(arg_name, f->name)) {
8142 : : status = -EINVAL;
8143 : 0 : goto error;
8144 : : }
8145 : :
8146 [ # # ]: 0 : if (f->n_bits <= 64) {
8147 : : uint64_t val;
8148 : :
8149 : 0 : val = strtoull(arg_val, &arg_val, 0);
8150 [ # # ]: 0 : if (arg_val[0]) {
8151 : : status = -EINVAL;
8152 : 0 : goto error;
8153 : : }
8154 : :
8155 : : /* Endianness conversion. */
8156 [ # # ]: 0 : if (a->args_endianness[i])
8157 [ # # ]: 0 : val = field_hton(val, f->n_bits);
8158 : :
8159 : : /* Copy to entry. */
8160 : 0 : memcpy(&data[offset], (uint8_t *)&val, f->n_bits / 8);
8161 : : } else {
8162 : 0 : status = hex_string_parse(arg_val, &data[offset], f->n_bits / 8);
8163 [ # # ]: 0 : if (status)
8164 : 0 : goto error;
8165 : : }
8166 : :
8167 : 0 : offset += f->n_bits / 8;
8168 : : }
8169 : :
8170 : 0 : error:
8171 : 0 : free(s0);
8172 : 0 : return status;
8173 : : }
8174 : :
8175 : : /*
8176 : : * Table.
8177 : : */
8178 : : static struct table_type *
8179 : : table_type_find(struct rte_swx_pipeline *p, const char *name)
8180 : : {
8181 : : struct table_type *elem;
8182 : :
8183 [ # # ]: 0 : TAILQ_FOREACH(elem, &p->table_types, node)
8184 [ # # ]: 0 : if (strcmp(elem->name, name) == 0)
8185 : : return elem;
8186 : :
8187 : : return NULL;
8188 : : }
8189 : :
8190 : : static struct table_type *
8191 : 0 : table_type_resolve(struct rte_swx_pipeline *p,
8192 : : const char *recommended_type_name,
8193 : : enum rte_swx_table_match_type match_type)
8194 : : {
8195 : : struct table_type *elem;
8196 : :
8197 : : /* Only consider the recommended type if the match type is correct. */
8198 [ # # ]: 0 : if (recommended_type_name)
8199 [ # # ]: 0 : TAILQ_FOREACH(elem, &p->table_types, node)
8200 [ # # ]: 0 : if (!strcmp(elem->name, recommended_type_name) &&
8201 [ # # ]: 0 : (elem->match_type == match_type))
8202 : 0 : return elem;
8203 : :
8204 : : /* Ignore the recommended type and get the first element with this match
8205 : : * type.
8206 : : */
8207 [ # # ]: 0 : TAILQ_FOREACH(elem, &p->table_types, node)
8208 [ # # ]: 0 : if (elem->match_type == match_type)
8209 : 0 : return elem;
8210 : :
8211 : : return NULL;
8212 : : }
8213 : :
8214 : : static struct table *
8215 : : table_find(struct rte_swx_pipeline *p, const char *name)
8216 : : {
8217 : : struct table *elem;
8218 : :
8219 [ # # # # : 0 : TAILQ_FOREACH(elem, &p->tables, node)
# # # # #
# # # #
# ]
8220 [ # # # # : 0 : if (strcmp(elem->name, name) == 0)
# # # # #
# # # #
# ]
8221 : : return elem;
8222 : :
8223 : : return NULL;
8224 : : }
8225 : :
8226 : : static struct table *
8227 : : table_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8228 : : {
8229 : : struct table *table = NULL;
8230 : :
8231 [ # # # # : 0 : TAILQ_FOREACH(table, &p->tables, node)
# # # # #
# ]
8232 [ # # # # : 0 : if (table->id == id)
# # # # #
# ]
8233 : : return table;
8234 : :
8235 : : return NULL;
8236 : : }
8237 : :
8238 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_pipeline_table_type_register, 20.11)
8239 : : int
8240 : 0 : rte_swx_pipeline_table_type_register(struct rte_swx_pipeline *p,
8241 : : const char *name,
8242 : : enum rte_swx_table_match_type match_type,
8243 : : struct rte_swx_table_ops *ops)
8244 : : {
8245 : : struct table_type *elem;
8246 : :
8247 [ # # ]: 0 : CHECK(p, EINVAL);
8248 : :
8249 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
8250 [ # # ]: 0 : CHECK(!table_type_find(p, name), EEXIST);
8251 : :
8252 [ # # ]: 0 : CHECK(ops, EINVAL);
8253 [ # # ]: 0 : CHECK(ops->create, EINVAL);
8254 [ # # ]: 0 : CHECK(ops->lkp, EINVAL);
8255 [ # # ]: 0 : CHECK(ops->free, EINVAL);
8256 : :
8257 : : /* Node allocation. */
8258 : 0 : elem = calloc(1, sizeof(struct table_type));
8259 [ # # ]: 0 : CHECK(elem, ENOMEM);
8260 : :
8261 : : /* Node initialization. */
8262 : 0 : strcpy(elem->name, name);
8263 : 0 : elem->match_type = match_type;
8264 : 0 : memcpy(&elem->ops, ops, sizeof(*ops));
8265 : :
8266 : : /* Node add to tailq. */
8267 : 0 : TAILQ_INSERT_TAIL(&p->table_types, elem, node);
8268 : :
8269 : 0 : return 0;
8270 : : }
8271 : :
8272 : : static int
8273 : 0 : table_match_type_resolve(struct rte_swx_match_field_params *fields,
8274 : : uint32_t n_fields,
8275 : : int contiguous_fields,
8276 : : enum rte_swx_table_match_type *match_type)
8277 : : {
8278 : : uint32_t n_fields_em = 0, n_fields_lpm = 0, i;
8279 : :
8280 [ # # ]: 0 : for (i = 0; i < n_fields; i++) {
8281 : 0 : struct rte_swx_match_field_params *f = &fields[i];
8282 : :
8283 [ # # ]: 0 : if (f->match_type == RTE_SWX_TABLE_MATCH_EXACT)
8284 : 0 : n_fields_em++;
8285 : :
8286 [ # # ]: 0 : if (f->match_type == RTE_SWX_TABLE_MATCH_LPM)
8287 : 0 : n_fields_lpm++;
8288 : : }
8289 : :
8290 [ # # # # ]: 0 : if ((n_fields_lpm > 1) ||
8291 [ # # ]: 0 : (n_fields_lpm && (n_fields_em != n_fields - 1)))
8292 : : return -EINVAL;
8293 : :
8294 : 0 : *match_type = ((n_fields_em == n_fields) && contiguous_fields) ?
8295 [ # # ]: 0 : RTE_SWX_TABLE_MATCH_EXACT :
8296 : : RTE_SWX_TABLE_MATCH_WILDCARD;
8297 : :
8298 : 0 : return 0;
8299 : : }
8300 : :
8301 : : static int
8302 : 0 : table_match_fields_check(struct rte_swx_pipeline *p,
8303 : : struct rte_swx_pipeline_table_params *params,
8304 : : struct header **header,
8305 : : int *contiguous_fields)
8306 : : {
8307 : 0 : struct header *h0 = NULL;
8308 : : struct field *hf, *mf;
8309 : : uint32_t *offset = NULL, *n_bits = NULL, n_fields_with_valid_next = 0, i;
8310 : : int status = 0;
8311 : :
8312 : : /* Return if no match fields. */
8313 [ # # ]: 0 : if (!params->n_fields) {
8314 [ # # ]: 0 : if (params->fields) {
8315 : : status = -EINVAL;
8316 : 0 : goto end;
8317 : : }
8318 : :
8319 [ # # ]: 0 : if (header)
8320 : 0 : *header = NULL;
8321 : :
8322 [ # # ]: 0 : if (contiguous_fields)
8323 : 0 : *contiguous_fields = 0;
8324 : :
8325 : 0 : return 0;
8326 : : }
8327 : :
8328 : : /* Memory allocation. */
8329 : 0 : offset = calloc(params->n_fields, sizeof(uint32_t));
8330 : 0 : n_bits = calloc(params->n_fields, sizeof(uint32_t));
8331 [ # # ]: 0 : if (!offset || !n_bits) {
8332 : : status = -ENOMEM;
8333 : 0 : goto end;
8334 : : }
8335 : :
8336 : : /* Check that all the match fields belong to either the same header or
8337 : : * to the meta-data.
8338 : : */
8339 : 0 : hf = header_field_parse(p, params->fields[0].name, &h0);
8340 : 0 : mf = metadata_field_parse(p, params->fields[0].name);
8341 [ # # # # : 0 : if ((!hf && !mf) || (hf && hf->var_size)) {
# # ]
8342 : : status = -EINVAL;
8343 : 0 : goto end;
8344 : : }
8345 : :
8346 [ # # ]: 0 : offset[0] = h0 ? hf->offset : mf->offset;
8347 [ # # ]: 0 : n_bits[0] = h0 ? hf->n_bits : mf->n_bits;
8348 : :
8349 [ # # ]: 0 : for (i = 1; i < params->n_fields; i++)
8350 [ # # ]: 0 : if (h0) {
8351 : : struct header *h;
8352 : :
8353 : 0 : hf = header_field_parse(p, params->fields[i].name, &h);
8354 [ # # # # : 0 : if (!hf || (h->id != h0->id) || hf->var_size) {
# # ]
8355 : : status = -EINVAL;
8356 : 0 : goto end;
8357 : : }
8358 : :
8359 : 0 : offset[i] = hf->offset;
8360 : 0 : n_bits[i] = hf->n_bits;
8361 : : } else {
8362 : 0 : mf = metadata_field_parse(p, params->fields[i].name);
8363 [ # # ]: 0 : if (!mf) {
8364 : : status = -EINVAL;
8365 : 0 : goto end;
8366 : : }
8367 : :
8368 : 0 : offset[i] = mf->offset;
8369 : 0 : n_bits[i] = mf->n_bits;
8370 : : }
8371 : :
8372 : : /* Check that there are no duplicated match fields. */
8373 [ # # ]: 0 : for (i = 0; i < params->n_fields; i++) {
8374 : : uint32_t j;
8375 : :
8376 [ # # ]: 0 : for (j = 0; j < i; j++)
8377 [ # # ]: 0 : if (offset[j] == offset[i]) {
8378 : : status = -EINVAL;
8379 : 0 : goto end;
8380 : : }
8381 : : }
8382 : :
8383 : : /* Detect if the match fields are contiguous or not. */
8384 [ # # ]: 0 : for (i = 0; i < params->n_fields; i++) {
8385 : 0 : uint32_t offset_next = offset[i] + n_bits[i];
8386 : : uint32_t j;
8387 : :
8388 [ # # ]: 0 : for (j = 0; j < params->n_fields; j++)
8389 [ # # ]: 0 : if (offset[j] == offset_next) {
8390 : 0 : n_fields_with_valid_next++;
8391 : 0 : break;
8392 : : }
8393 : : }
8394 : :
8395 : : /* Return. */
8396 [ # # ]: 0 : if (header)
8397 : 0 : *header = h0;
8398 : :
8399 [ # # ]: 0 : if (contiguous_fields)
8400 : 0 : *contiguous_fields = (n_fields_with_valid_next == params->n_fields - 1) ? 1 : 0;
8401 : :
8402 : 0 : end:
8403 : 0 : free(offset);
8404 : 0 : free(n_bits);
8405 : 0 : return status;
8406 : : }
8407 : :
8408 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_pipeline_table_config, 20.11)
8409 : : int
8410 : 0 : rte_swx_pipeline_table_config(struct rte_swx_pipeline *p,
8411 : : const char *name,
8412 : : struct rte_swx_pipeline_table_params *params,
8413 : : const char *recommended_table_type_name,
8414 : : const char *args,
8415 : : uint32_t size)
8416 : : {
8417 : : struct table_type *type = NULL;
8418 : : struct table *t = NULL;
8419 : : struct action *default_action;
8420 : 0 : struct header *header = NULL;
8421 : : struct hash_func *hf = NULL;
8422 : : uint32_t action_data_size_max = 0, i;
8423 : 0 : int contiguous_fields = 0, status = 0;
8424 : :
8425 [ # # ]: 0 : CHECK(p, EINVAL);
8426 : :
8427 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
8428 [ # # ]: 0 : CHECK(!table_find(p, name), EEXIST);
8429 [ # # ]: 0 : CHECK(!selector_find(p, name), EEXIST);
8430 [ # # ]: 0 : CHECK(!learner_find(p, name), EEXIST);
8431 : :
8432 [ # # ]: 0 : CHECK(params, EINVAL);
8433 : :
8434 : : /* Match checks. */
8435 : 0 : status = table_match_fields_check(p, params, &header, &contiguous_fields);
8436 [ # # ]: 0 : if (status)
8437 : : return status;
8438 : :
8439 : : /* Action checks. */
8440 [ # # ]: 0 : CHECK(params->n_actions, EINVAL);
8441 [ # # ]: 0 : CHECK(params->action_names, EINVAL);
8442 [ # # ]: 0 : for (i = 0; i < params->n_actions; i++) {
8443 : 0 : const char *action_name = params->action_names[i];
8444 : : struct action *a;
8445 : : uint32_t action_data_size;
8446 : : int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
8447 : :
8448 [ # # # # : 0 : CHECK_NAME(action_name, EINVAL);
# # ]
8449 : :
8450 : 0 : a = action_find(p, action_name);
8451 [ # # ]: 0 : CHECK(a, EINVAL);
8452 [ # # ]: 0 : CHECK(!action_does_learning(a), EINVAL);
8453 : :
8454 [ # # ]: 0 : action_data_size = a->st ? a->st->n_bits / 8 : 0;
8455 : : if (action_data_size > action_data_size_max)
8456 : : action_data_size_max = action_data_size;
8457 : :
8458 [ # # ]: 0 : if (params->action_is_for_table_entries)
8459 : 0 : action_is_for_table_entries = params->action_is_for_table_entries[i];
8460 [ # # ]: 0 : if (params->action_is_for_default_entry)
8461 : 0 : action_is_for_default_entry = params->action_is_for_default_entry[i];
8462 [ # # ]: 0 : CHECK(action_is_for_table_entries || action_is_for_default_entry, EINVAL);
8463 : : }
8464 : :
8465 [ # # # # : 0 : CHECK_NAME(params->default_action_name, EINVAL);
# # ]
8466 [ # # ]: 0 : for (i = 0; i < p->n_actions; i++)
8467 [ # # ]: 0 : if (!strcmp(params->action_names[i],
8468 : : params->default_action_name))
8469 : : break;
8470 [ # # ]: 0 : CHECK(i < params->n_actions, EINVAL);
8471 [ # # # # ]: 0 : CHECK(!params->action_is_for_default_entry || params->action_is_for_default_entry[i],
8472 : : EINVAL);
8473 : :
8474 : 0 : default_action = action_find(p, params->default_action_name);
8475 [ # # # # ]: 0 : CHECK((default_action->st && params->default_action_args) || !params->default_action_args,
8476 : : EINVAL);
8477 : :
8478 : : /* Hash function checks. */
8479 [ # # ]: 0 : if (params->hash_func_name) {
8480 : : hf = hash_func_find(p, params->hash_func_name);
8481 [ # # ]: 0 : CHECK(hf, EINVAL);
8482 : : }
8483 : :
8484 : : /* Table type checks. */
8485 [ # # ]: 0 : if (recommended_table_type_name)
8486 [ # # # # ]: 0 : CHECK_NAME(recommended_table_type_name, EINVAL);
8487 : :
8488 [ # # ]: 0 : if (params->n_fields) {
8489 : : enum rte_swx_table_match_type match_type;
8490 : :
8491 : 0 : status = table_match_type_resolve(params->fields,
8492 : : params->n_fields,
8493 : : contiguous_fields,
8494 : : &match_type);
8495 [ # # ]: 0 : if (status)
8496 : 0 : return status;
8497 : :
8498 : 0 : type = table_type_resolve(p, recommended_table_type_name, match_type);
8499 [ # # ]: 0 : CHECK(type, EINVAL);
8500 : : }
8501 : :
8502 : : /* Memory allocation. */
8503 : 0 : t = calloc(1, sizeof(struct table));
8504 [ # # ]: 0 : if (!t) {
8505 : : status = -ENOMEM;
8506 : 0 : goto error;
8507 : : }
8508 : :
8509 : 0 : t->fields = calloc(params->n_fields, sizeof(struct match_field));
8510 [ # # ]: 0 : if (!t->fields) {
8511 : : status = -ENOMEM;
8512 : 0 : goto error;
8513 : : }
8514 : :
8515 : 0 : t->actions = calloc(params->n_actions, sizeof(struct action *));
8516 [ # # ]: 0 : if (!t->actions) {
8517 : : status = -ENOMEM;
8518 : 0 : goto error;
8519 : : }
8520 : :
8521 [ # # ]: 0 : if (action_data_size_max) {
8522 : 0 : t->default_action_data = calloc(1, action_data_size_max);
8523 [ # # ]: 0 : if (!t->default_action_data) {
8524 : : status = -ENOMEM;
8525 : 0 : goto error;
8526 : : }
8527 : : }
8528 : :
8529 : 0 : t->action_is_for_table_entries = calloc(params->n_actions, sizeof(int));
8530 [ # # ]: 0 : if (!t->action_is_for_table_entries) {
8531 : : status = -ENOMEM;
8532 : 0 : goto error;
8533 : : }
8534 : :
8535 : 0 : t->action_is_for_default_entry = calloc(params->n_actions, sizeof(int));
8536 [ # # ]: 0 : if (!t->action_is_for_default_entry) {
8537 : : status = -ENOMEM;
8538 : 0 : goto error;
8539 : : }
8540 : :
8541 : : /* Node initialization. */
8542 [ # # ]: 0 : strcpy(t->name, name);
8543 [ # # # # ]: 0 : if (args && args[0])
8544 : 0 : strcpy(t->args, args);
8545 : 0 : t->type = type;
8546 : :
8547 [ # # ]: 0 : for (i = 0; i < params->n_fields; i++) {
8548 : 0 : struct rte_swx_match_field_params *field = ¶ms->fields[i];
8549 : 0 : struct match_field *f = &t->fields[i];
8550 : :
8551 : 0 : f->match_type = field->match_type;
8552 : 0 : f->field = header ?
8553 [ # # ]: 0 : header_field_parse(p, field->name, NULL) :
8554 : 0 : metadata_field_parse(p, field->name);
8555 : : }
8556 : 0 : t->n_fields = params->n_fields;
8557 : 0 : t->header = header;
8558 : :
8559 [ # # ]: 0 : for (i = 0; i < params->n_actions; i++) {
8560 : : int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
8561 : :
8562 [ # # ]: 0 : if (params->action_is_for_table_entries)
8563 : 0 : action_is_for_table_entries = params->action_is_for_table_entries[i];
8564 [ # # ]: 0 : if (params->action_is_for_default_entry)
8565 : 0 : action_is_for_default_entry = params->action_is_for_default_entry[i];
8566 : :
8567 : 0 : t->actions[i] = action_find(p, params->action_names[i]);
8568 : 0 : t->action_is_for_table_entries[i] = action_is_for_table_entries;
8569 : 0 : t->action_is_for_default_entry[i] = action_is_for_default_entry;
8570 : : }
8571 : 0 : t->default_action = default_action;
8572 [ # # ]: 0 : if (default_action->st) {
8573 : 0 : status = action_args_parse(default_action,
8574 : : params->default_action_args,
8575 : : t->default_action_data);
8576 [ # # ]: 0 : if (status)
8577 : 0 : goto error;
8578 : : }
8579 : :
8580 : 0 : t->n_actions = params->n_actions;
8581 : 0 : t->default_action_is_const = params->default_action_is_const;
8582 : 0 : t->action_data_size_max = action_data_size_max;
8583 : :
8584 : 0 : t->hf = hf;
8585 : 0 : t->size = size;
8586 : 0 : t->id = p->n_tables;
8587 : :
8588 : : /* Node add to tailq. */
8589 : 0 : TAILQ_INSERT_TAIL(&p->tables, t, node);
8590 : 0 : p->n_tables++;
8591 : :
8592 : 0 : return 0;
8593 : :
8594 : 0 : error:
8595 [ # # ]: 0 : if (!t)
8596 : : return status;
8597 : :
8598 : 0 : free(t->action_is_for_default_entry);
8599 : 0 : free(t->action_is_for_table_entries);
8600 : 0 : free(t->default_action_data);
8601 : 0 : free(t->actions);
8602 : 0 : free(t->fields);
8603 : 0 : free(t);
8604 : :
8605 : 0 : return status;
8606 : : }
8607 : :
8608 : : static uint32_t
8609 : : table_params_offset_get(struct table *table)
8610 : : {
8611 : : struct field *first;
8612 : : uint32_t i;
8613 : :
8614 : 0 : first = table->fields[0].field;
8615 : :
8616 [ # # ]: 0 : for (i = 1; i < table->n_fields; i++) {
8617 : 0 : struct field *f = table->fields[i].field;
8618 : :
8619 [ # # ]: 0 : if (f->offset < first->offset)
8620 : : first = f;
8621 : : }
8622 : :
8623 : 0 : return first->offset / 8;
8624 : : }
8625 : :
8626 : : static struct rte_swx_table_params *
8627 : 0 : table_params_get(struct table *table)
8628 : : {
8629 : : struct rte_swx_table_params *params;
8630 : : struct field *first, *last;
8631 : : uint8_t *key_mask;
8632 : : uint32_t key_size, key_offset, action_data_size, i;
8633 : :
8634 : : /* Memory allocation. */
8635 : 0 : params = calloc(1, sizeof(struct rte_swx_table_params));
8636 [ # # ]: 0 : if (!params)
8637 : : return NULL;
8638 : :
8639 : : /* Find first (smallest offset) and last (biggest offset) match fields. */
8640 : 0 : first = table->fields[0].field;
8641 : : last = table->fields[0].field;
8642 : :
8643 [ # # ]: 0 : for (i = 0; i < table->n_fields; i++) {
8644 : 0 : struct field *f = table->fields[i].field;
8645 : :
8646 [ # # ]: 0 : if (f->offset < first->offset)
8647 : : first = f;
8648 : :
8649 [ # # ]: 0 : if (f->offset > last->offset)
8650 : : last = f;
8651 : : }
8652 : :
8653 : : /* Key offset and size. */
8654 : 0 : key_offset = first->offset / 8;
8655 : 0 : key_size = (last->offset + last->n_bits - first->offset) / 8;
8656 : :
8657 : : /* Memory allocation. */
8658 : 0 : key_mask = calloc(1, key_size);
8659 [ # # ]: 0 : if (!key_mask) {
8660 : 0 : free(params);
8661 : 0 : return NULL;
8662 : : }
8663 : :
8664 : : /* Key mask. */
8665 [ # # ]: 0 : for (i = 0; i < table->n_fields; i++) {
8666 : 0 : struct field *f = table->fields[i].field;
8667 : 0 : uint32_t start = (f->offset - first->offset) / 8;
8668 : 0 : size_t size = f->n_bits / 8;
8669 : :
8670 : 0 : memset(&key_mask[start], 0xFF, size);
8671 : : }
8672 : :
8673 : : /* Action data size. */
8674 : : action_data_size = 0;
8675 [ # # ]: 0 : for (i = 0; i < table->n_actions; i++) {
8676 : 0 : struct action *action = table->actions[i];
8677 [ # # ]: 0 : uint32_t ads = action->st ? action->st->n_bits / 8 : 0;
8678 : :
8679 : : if (ads > action_data_size)
8680 : : action_data_size = ads;
8681 : : }
8682 : :
8683 : : /* Fill in. */
8684 : 0 : params->match_type = table->type->match_type;
8685 : 0 : params->key_size = key_size;
8686 : 0 : params->key_offset = key_offset;
8687 : 0 : params->key_mask0 = key_mask;
8688 : 0 : params->action_data_size = action_data_size;
8689 [ # # ]: 0 : params->hash_func = table->hf ? table->hf->func : NULL;
8690 : 0 : params->n_keys_max = table->size;
8691 : :
8692 : 0 : return params;
8693 : : }
8694 : :
8695 : : static void
8696 : 0 : table_params_free(struct rte_swx_table_params *params)
8697 : : {
8698 [ # # ]: 0 : if (!params)
8699 : : return;
8700 : :
8701 : 0 : free(params->key_mask0);
8702 : 0 : free(params);
8703 : : }
8704 : :
8705 : : static int
8706 : 0 : table_stub_lkp(void *table __rte_unused,
8707 : : void *mailbox __rte_unused,
8708 : : uint8_t **key __rte_unused,
8709 : : uint64_t *action_id __rte_unused,
8710 : : uint8_t **action_data __rte_unused,
8711 : : size_t *entry_id __rte_unused,
8712 : : int *hit)
8713 : : {
8714 : 0 : *hit = 0;
8715 : 0 : return 1; /* DONE. */
8716 : : }
8717 : :
8718 : : static int
8719 : 0 : table_build(struct rte_swx_pipeline *p)
8720 : : {
8721 : : uint32_t i;
8722 : :
8723 : : /* Per pipeline: table statistics. */
8724 : 0 : p->table_stats = calloc(p->n_tables, sizeof(struct table_statistics));
8725 [ # # ]: 0 : CHECK(p->table_stats, ENOMEM);
8726 : :
8727 [ # # ]: 0 : for (i = 0; i < p->n_tables; i++) {
8728 : 0 : p->table_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
8729 [ # # ]: 0 : CHECK(p->table_stats[i].n_pkts_action, ENOMEM);
8730 : : }
8731 : :
8732 : : /* Per thread: table runt-time. */
8733 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8734 : : struct thread *t = &p->threads[i];
8735 : : struct table *table;
8736 : :
8737 : 0 : t->tables = calloc(p->n_tables, sizeof(struct table_runtime));
8738 [ # # ]: 0 : CHECK(t->tables, ENOMEM);
8739 : :
8740 [ # # ]: 0 : TAILQ_FOREACH(table, &p->tables, node) {
8741 : 0 : struct table_runtime *r = &t->tables[table->id];
8742 : :
8743 [ # # ]: 0 : if (table->type) {
8744 : : uint64_t size;
8745 : :
8746 : 0 : size = table->type->ops.mailbox_size_get();
8747 : :
8748 : : /* r->func. */
8749 : 0 : r->func = table->type->ops.lkp;
8750 : :
8751 : : /* r->mailbox. */
8752 [ # # ]: 0 : if (size) {
8753 : 0 : r->mailbox = calloc(1, size);
8754 [ # # ]: 0 : CHECK(r->mailbox, ENOMEM);
8755 : : }
8756 : :
8757 : : /* r->key. */
8758 : 0 : r->key = table->header ?
8759 [ # # ]: 0 : &t->structs[table->header->struct_id] :
8760 : 0 : &t->structs[p->metadata_struct_id];
8761 : : } else {
8762 : 0 : r->func = table_stub_lkp;
8763 : : }
8764 : : }
8765 : : }
8766 : :
8767 : : return 0;
8768 : : }
8769 : :
8770 : : static void
8771 : 0 : table_build_free(struct rte_swx_pipeline *p)
8772 : : {
8773 : : uint32_t i;
8774 : :
8775 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8776 : : struct thread *t = &p->threads[i];
8777 : : uint32_t j;
8778 : :
8779 [ # # ]: 0 : if (!t->tables)
8780 : 0 : continue;
8781 : :
8782 [ # # ]: 0 : for (j = 0; j < p->n_tables; j++) {
8783 : 0 : struct table_runtime *r = &t->tables[j];
8784 : :
8785 : 0 : free(r->mailbox);
8786 : : }
8787 : :
8788 : 0 : free(t->tables);
8789 : 0 : t->tables = NULL;
8790 : : }
8791 : :
8792 [ # # ]: 0 : if (p->table_stats) {
8793 [ # # ]: 0 : for (i = 0; i < p->n_tables; i++)
8794 : 0 : free(p->table_stats[i].n_pkts_action);
8795 : :
8796 : 0 : free(p->table_stats);
8797 : 0 : p->table_stats = NULL;
8798 : : }
8799 : 0 : }
8800 : :
8801 : : static void
8802 : 0 : table_free(struct rte_swx_pipeline *p)
8803 : : {
8804 : 0 : table_build_free(p);
8805 : :
8806 : : /* Tables. */
8807 : 0 : for ( ; ; ) {
8808 : : struct table *elem;
8809 : :
8810 : 0 : elem = TAILQ_FIRST(&p->tables);
8811 [ # # ]: 0 : if (!elem)
8812 : : break;
8813 : :
8814 [ # # ]: 0 : TAILQ_REMOVE(&p->tables, elem, node);
8815 : 0 : free(elem->fields);
8816 : 0 : free(elem->actions);
8817 : 0 : free(elem->default_action_data);
8818 : 0 : free(elem);
8819 : : }
8820 : :
8821 : : /* Table types. */
8822 : 0 : for ( ; ; ) {
8823 : : struct table_type *elem;
8824 : :
8825 : 0 : elem = TAILQ_FIRST(&p->table_types);
8826 [ # # ]: 0 : if (!elem)
8827 : : break;
8828 : :
8829 [ # # ]: 0 : TAILQ_REMOVE(&p->table_types, elem, node);
8830 : 0 : free(elem);
8831 : : }
8832 : 0 : }
8833 : :
8834 : : /*
8835 : : * Selector.
8836 : : */
8837 : : static struct selector *
8838 : : selector_find(struct rte_swx_pipeline *p, const char *name)
8839 : : {
8840 : : struct selector *s;
8841 : :
8842 [ # # # # : 0 : TAILQ_FOREACH(s, &p->selectors, node)
# # # # #
# ]
8843 [ # # # # : 0 : if (strcmp(s->name, name) == 0)
# # # # #
# ]
8844 : : return s;
8845 : :
8846 : : return NULL;
8847 : : }
8848 : :
8849 : : static struct selector *
8850 : : selector_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8851 : : {
8852 : : struct selector *s = NULL;
8853 : :
8854 [ # # # # : 0 : TAILQ_FOREACH(s, &p->selectors, node)
# # # # ]
8855 [ # # # # : 0 : if (s->id == id)
# # # # ]
8856 : : return s;
8857 : :
8858 : : return NULL;
8859 : : }
8860 : :
8861 : : static int
8862 : 0 : selector_fields_check(struct rte_swx_pipeline *p,
8863 : : struct rte_swx_pipeline_selector_params *params,
8864 : : struct header **header)
8865 : : {
8866 : 0 : struct header *h0 = NULL;
8867 : : struct field *hf, *mf;
8868 : : uint32_t i;
8869 : :
8870 : : /* Return if no selector fields. */
8871 [ # # # # ]: 0 : if (!params->n_selector_fields || !params->selector_field_names)
8872 : : return -EINVAL;
8873 : :
8874 : : /* Check that all the selector fields either belong to the same header
8875 : : * or are all meta-data fields.
8876 : : */
8877 : 0 : hf = header_field_parse(p, params->selector_field_names[0], &h0);
8878 : 0 : mf = metadata_field_parse(p, params->selector_field_names[0]);
8879 [ # # ]: 0 : if (!hf && !mf)
8880 : : return -EINVAL;
8881 : :
8882 [ # # ]: 0 : for (i = 1; i < params->n_selector_fields; i++)
8883 [ # # ]: 0 : if (h0) {
8884 : : struct header *h;
8885 : :
8886 : 0 : hf = header_field_parse(p, params->selector_field_names[i], &h);
8887 [ # # # # ]: 0 : if (!hf || (h->id != h0->id))
8888 : 0 : return -EINVAL;
8889 : : } else {
8890 : 0 : mf = metadata_field_parse(p, params->selector_field_names[i]);
8891 [ # # ]: 0 : if (!mf)
8892 : : return -EINVAL;
8893 : : }
8894 : :
8895 : : /* Check that there are no duplicated match fields. */
8896 [ # # ]: 0 : for (i = 0; i < params->n_selector_fields; i++) {
8897 : 0 : const char *field_name = params->selector_field_names[i];
8898 : : uint32_t j;
8899 : :
8900 [ # # ]: 0 : for (j = i + 1; j < params->n_selector_fields; j++)
8901 [ # # ]: 0 : if (!strcmp(params->selector_field_names[j], field_name))
8902 : : return -EINVAL;
8903 : : }
8904 : :
8905 : : /* Return. */
8906 [ # # ]: 0 : if (header)
8907 : 0 : *header = h0;
8908 : :
8909 : : return 0;
8910 : : }
8911 : :
8912 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_pipeline_selector_config, 21.08)
8913 : : int
8914 : 0 : rte_swx_pipeline_selector_config(struct rte_swx_pipeline *p,
8915 : : const char *name,
8916 : : struct rte_swx_pipeline_selector_params *params)
8917 : : {
8918 : : struct selector *s;
8919 : 0 : struct header *selector_header = NULL;
8920 : : struct field *group_id_field, *member_id_field;
8921 : : uint32_t i;
8922 : : int status = 0;
8923 : :
8924 [ # # ]: 0 : CHECK(p, EINVAL);
8925 : :
8926 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
8927 [ # # ]: 0 : CHECK(!table_find(p, name), EEXIST);
8928 [ # # ]: 0 : CHECK(!selector_find(p, name), EEXIST);
8929 [ # # ]: 0 : CHECK(!learner_find(p, name), EEXIST);
8930 : :
8931 [ # # ]: 0 : CHECK(params, EINVAL);
8932 : :
8933 [ # # # # : 0 : CHECK_NAME(params->group_id_field_name, EINVAL);
# # ]
8934 : 0 : group_id_field = metadata_field_parse(p, params->group_id_field_name);
8935 [ # # ]: 0 : CHECK(group_id_field, EINVAL);
8936 : :
8937 [ # # ]: 0 : for (i = 0; i < params->n_selector_fields; i++) {
8938 : 0 : const char *field_name = params->selector_field_names[i];
8939 : :
8940 [ # # # # : 0 : CHECK_NAME(field_name, EINVAL);
# # ]
8941 : : }
8942 : 0 : status = selector_fields_check(p, params, &selector_header);
8943 [ # # ]: 0 : if (status)
8944 : : return status;
8945 : :
8946 [ # # # # : 0 : CHECK_NAME(params->member_id_field_name, EINVAL);
# # ]
8947 : 0 : member_id_field = metadata_field_parse(p, params->member_id_field_name);
8948 [ # # ]: 0 : CHECK(member_id_field, EINVAL);
8949 : :
8950 [ # # ]: 0 : CHECK(params->n_groups_max, EINVAL);
8951 : :
8952 [ # # ]: 0 : CHECK(params->n_members_per_group_max, EINVAL);
8953 : :
8954 : : /* Memory allocation. */
8955 : 0 : s = calloc(1, sizeof(struct selector));
8956 [ # # ]: 0 : if (!s) {
8957 : : status = -ENOMEM;
8958 : 0 : goto error;
8959 : : }
8960 : :
8961 : 0 : s->selector_fields = calloc(params->n_selector_fields, sizeof(struct field *));
8962 [ # # ]: 0 : if (!s->selector_fields) {
8963 : : status = -ENOMEM;
8964 : 0 : goto error;
8965 : : }
8966 : :
8967 : : /* Node initialization. */
8968 : 0 : strcpy(s->name, name);
8969 : :
8970 : 0 : s->group_id_field = group_id_field;
8971 : :
8972 [ # # ]: 0 : for (i = 0; i < params->n_selector_fields; i++) {
8973 : 0 : const char *field_name = params->selector_field_names[i];
8974 : :
8975 : 0 : s->selector_fields[i] = selector_header ?
8976 [ # # ]: 0 : header_field_parse(p, field_name, NULL) :
8977 : 0 : metadata_field_parse(p, field_name);
8978 : : }
8979 : :
8980 : 0 : s->n_selector_fields = params->n_selector_fields;
8981 : :
8982 : 0 : s->selector_header = selector_header;
8983 : :
8984 : 0 : s->member_id_field = member_id_field;
8985 : :
8986 : 0 : s->n_groups_max = params->n_groups_max;
8987 : :
8988 : 0 : s->n_members_per_group_max = params->n_members_per_group_max;
8989 : :
8990 : 0 : s->id = p->n_selectors;
8991 : :
8992 : : /* Node add to tailq. */
8993 : 0 : TAILQ_INSERT_TAIL(&p->selectors, s, node);
8994 : 0 : p->n_selectors++;
8995 : :
8996 : 0 : return 0;
8997 : :
8998 : 0 : error:
8999 [ # # ]: 0 : if (!s)
9000 : : return status;
9001 : :
9002 : 0 : free(s->selector_fields);
9003 : :
9004 : 0 : free(s);
9005 : :
9006 : 0 : return status;
9007 : : }
9008 : :
9009 : : static void
9010 : 0 : selector_params_free(struct rte_swx_table_selector_params *params)
9011 : : {
9012 [ # # ]: 0 : if (!params)
9013 : : return;
9014 : :
9015 : 0 : free(params->selector_mask);
9016 : :
9017 : 0 : free(params);
9018 : : }
9019 : :
9020 : : static struct rte_swx_table_selector_params *
9021 : 0 : selector_table_params_get(struct selector *s)
9022 : : {
9023 : : struct rte_swx_table_selector_params *params = NULL;
9024 : : struct field *first, *last;
9025 : : uint32_t i;
9026 : :
9027 : : /* Memory allocation. */
9028 : 0 : params = calloc(1, sizeof(struct rte_swx_table_selector_params));
9029 [ # # ]: 0 : if (!params)
9030 : 0 : goto error;
9031 : :
9032 : : /* Group ID. */
9033 : 0 : params->group_id_offset = s->group_id_field->offset / 8;
9034 : :
9035 : : /* Find first (smallest offset) and last (biggest offset) selector fields. */
9036 : 0 : first = s->selector_fields[0];
9037 : : last = s->selector_fields[0];
9038 : :
9039 [ # # ]: 0 : for (i = 0; i < s->n_selector_fields; i++) {
9040 : 0 : struct field *f = s->selector_fields[i];
9041 : :
9042 [ # # ]: 0 : if (f->offset < first->offset)
9043 : : first = f;
9044 : :
9045 [ # # ]: 0 : if (f->offset > last->offset)
9046 : : last = f;
9047 : : }
9048 : :
9049 : : /* Selector offset and size. */
9050 : 0 : params->selector_offset = first->offset / 8;
9051 : 0 : params->selector_size = (last->offset + last->n_bits - first->offset) / 8;
9052 : :
9053 : : /* Memory allocation. */
9054 : 0 : params->selector_mask = calloc(1, params->selector_size);
9055 [ # # ]: 0 : if (!params->selector_mask)
9056 : 0 : goto error;
9057 : :
9058 : : /* Selector mask. */
9059 [ # # ]: 0 : for (i = 0; i < s->n_selector_fields; i++) {
9060 : 0 : struct field *f = s->selector_fields[i];
9061 : 0 : uint32_t start = (f->offset - first->offset) / 8;
9062 : 0 : size_t size = f->n_bits / 8;
9063 : :
9064 : 0 : memset(¶ms->selector_mask[start], 0xFF, size);
9065 : : }
9066 : :
9067 : : /* Member ID. */
9068 : 0 : params->member_id_offset = s->member_id_field->offset / 8;
9069 : :
9070 : : /* Maximum number of groups. */
9071 : 0 : params->n_groups_max = s->n_groups_max;
9072 : :
9073 : : /* Maximum number of members per group. */
9074 : 0 : params->n_members_per_group_max = s->n_members_per_group_max;
9075 : :
9076 : 0 : return params;
9077 : :
9078 : 0 : error:
9079 : 0 : selector_params_free(params);
9080 : 0 : return NULL;
9081 : : }
9082 : :
9083 : : static void
9084 : 0 : selector_build_free(struct rte_swx_pipeline *p)
9085 : : {
9086 : : uint32_t i;
9087 : :
9088 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9089 : : struct thread *t = &p->threads[i];
9090 : : uint32_t j;
9091 : :
9092 [ # # ]: 0 : if (!t->selectors)
9093 : 0 : continue;
9094 : :
9095 [ # # ]: 0 : for (j = 0; j < p->n_selectors; j++) {
9096 : 0 : struct selector_runtime *r = &t->selectors[j];
9097 : :
9098 : 0 : free(r->mailbox);
9099 : : }
9100 : :
9101 : 0 : free(t->selectors);
9102 : 0 : t->selectors = NULL;
9103 : : }
9104 : :
9105 : 0 : free(p->selector_stats);
9106 : 0 : p->selector_stats = NULL;
9107 : 0 : }
9108 : :
9109 : : static int
9110 : 0 : selector_build(struct rte_swx_pipeline *p)
9111 : : {
9112 : : uint32_t i;
9113 : : int status = 0;
9114 : :
9115 : : /* Per pipeline: selector statistics. */
9116 : 0 : p->selector_stats = calloc(p->n_selectors, sizeof(struct selector_statistics));
9117 [ # # ]: 0 : if (!p->selector_stats) {
9118 : : status = -ENOMEM;
9119 : 0 : goto error;
9120 : : }
9121 : :
9122 : : /* Per thread: selector run-time. */
9123 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9124 : : struct thread *t = &p->threads[i];
9125 : : struct selector *s;
9126 : :
9127 : 0 : t->selectors = calloc(p->n_selectors, sizeof(struct selector_runtime));
9128 [ # # ]: 0 : if (!t->selectors) {
9129 : : status = -ENOMEM;
9130 : 0 : goto error;
9131 : : }
9132 : :
9133 [ # # ]: 0 : TAILQ_FOREACH(s, &p->selectors, node) {
9134 : 0 : struct selector_runtime *r = &t->selectors[s->id];
9135 : : uint64_t size;
9136 : :
9137 : : /* r->mailbox. */
9138 : 0 : size = rte_swx_table_selector_mailbox_size_get();
9139 [ # # ]: 0 : if (size) {
9140 : 0 : r->mailbox = calloc(1, size);
9141 [ # # ]: 0 : if (!r->mailbox) {
9142 : : status = -ENOMEM;
9143 : 0 : goto error;
9144 : : }
9145 : : }
9146 : :
9147 : : /* r->group_id_buffer. */
9148 : 0 : r->group_id_buffer = &t->structs[p->metadata_struct_id];
9149 : :
9150 : : /* r->selector_buffer. */
9151 : 0 : r->selector_buffer = s->selector_header ?
9152 [ # # ]: 0 : &t->structs[s->selector_header->struct_id] :
9153 : : &t->structs[p->metadata_struct_id];
9154 : :
9155 : : /* r->member_id_buffer. */
9156 : 0 : r->member_id_buffer = &t->structs[p->metadata_struct_id];
9157 : : }
9158 : : }
9159 : :
9160 : : return 0;
9161 : :
9162 : 0 : error:
9163 : 0 : selector_build_free(p);
9164 : 0 : return status;
9165 : : }
9166 : :
9167 : : static void
9168 : 0 : selector_free(struct rte_swx_pipeline *p)
9169 : : {
9170 : 0 : selector_build_free(p);
9171 : :
9172 : : /* Selector tables. */
9173 : 0 : for ( ; ; ) {
9174 : : struct selector *elem;
9175 : :
9176 : 0 : elem = TAILQ_FIRST(&p->selectors);
9177 [ # # ]: 0 : if (!elem)
9178 : : break;
9179 : :
9180 [ # # ]: 0 : TAILQ_REMOVE(&p->selectors, elem, node);
9181 : 0 : free(elem->selector_fields);
9182 : 0 : free(elem);
9183 : : }
9184 : 0 : }
9185 : :
9186 : : /*
9187 : : * Learner table.
9188 : : */
9189 : : static struct learner *
9190 : : learner_find(struct rte_swx_pipeline *p, const char *name)
9191 : : {
9192 : : struct learner *l;
9193 : :
9194 [ # # # # : 0 : TAILQ_FOREACH(l, &p->learners, node)
# # # # #
# # # #
# ]
9195 [ # # # # : 0 : if (!strcmp(l->name, name))
# # # # #
# # # #
# ]
9196 : : return l;
9197 : :
9198 : : return NULL;
9199 : : }
9200 : :
9201 : : static struct learner *
9202 : : learner_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9203 : : {
9204 : : struct learner *l = NULL;
9205 : :
9206 [ # # # # : 0 : TAILQ_FOREACH(l, &p->learners, node)
# # # # #
# ]
9207 [ # # # # : 0 : if (l->id == id)
# # # # #
# ]
9208 : : return l;
9209 : :
9210 : : return NULL;
9211 : : }
9212 : :
9213 : : static int
9214 : 0 : learner_match_fields_check(struct rte_swx_pipeline *p,
9215 : : struct rte_swx_pipeline_learner_params *params,
9216 : : struct header **header)
9217 : : {
9218 : 0 : struct header *h0 = NULL;
9219 : : struct field *hf, *mf;
9220 : : uint32_t *offset = NULL, *n_bits = NULL, n_fields_with_valid_next = 0, i;
9221 : : int status = 0;
9222 : :
9223 : : /* Return if no match fields. */
9224 [ # # # # ]: 0 : if (!params->n_fields || !params->field_names)
9225 : : return -EINVAL;
9226 : :
9227 : : /* Memory allocation. */
9228 : 0 : offset = calloc(params->n_fields, sizeof(uint32_t));
9229 : 0 : n_bits = calloc(params->n_fields, sizeof(uint32_t));
9230 [ # # ]: 0 : if (!offset || !n_bits) {
9231 : : status = -ENOMEM;
9232 : 0 : goto end;
9233 : : }
9234 : :
9235 : : /* Check that all the match fields either belong to the same header
9236 : : * or are all meta-data fields.
9237 : : */
9238 : 0 : hf = header_field_parse(p, params->field_names[0], &h0);
9239 : 0 : mf = metadata_field_parse(p, params->field_names[0]);
9240 [ # # # # : 0 : if ((!hf && !mf) || (hf && hf->var_size)) {
# # ]
9241 : : status = -EINVAL;
9242 : 0 : goto end;
9243 : : }
9244 : :
9245 [ # # ]: 0 : offset[0] = h0 ? hf->offset : mf->offset;
9246 [ # # ]: 0 : n_bits[0] = h0 ? hf->n_bits : mf->n_bits;
9247 : :
9248 [ # # ]: 0 : for (i = 1; i < params->n_fields; i++)
9249 [ # # ]: 0 : if (h0) {
9250 : : struct header *h;
9251 : :
9252 : 0 : hf = header_field_parse(p, params->field_names[i], &h);
9253 [ # # # # : 0 : if (!hf || (h->id != h0->id) || hf->var_size) {
# # ]
9254 : : status = -EINVAL;
9255 : 0 : goto end;
9256 : : }
9257 : :
9258 : 0 : offset[i] = hf->offset;
9259 : 0 : n_bits[i] = hf->n_bits;
9260 : : } else {
9261 : 0 : mf = metadata_field_parse(p, params->field_names[i]);
9262 [ # # ]: 0 : if (!mf) {
9263 : : status = -EINVAL;
9264 : 0 : goto end;
9265 : : }
9266 : :
9267 : 0 : offset[i] = mf->offset;
9268 : 0 : n_bits[i] = mf->n_bits;
9269 : : }
9270 : :
9271 : : /* Check that there are no duplicated match fields. */
9272 [ # # ]: 0 : for (i = 0; i < params->n_fields; i++) {
9273 : 0 : const char *field_name = params->field_names[i];
9274 : : uint32_t j;
9275 : :
9276 [ # # ]: 0 : for (j = i + 1; j < params->n_fields; j++)
9277 [ # # ]: 0 : if (!strcmp(params->field_names[j], field_name)) {
9278 : : status = -EINVAL;
9279 : 0 : goto end;
9280 : : }
9281 : : }
9282 : :
9283 : : /* Check that the match fields are contiguous. */
9284 [ # # ]: 0 : for (i = 0; i < params->n_fields; i++) {
9285 : 0 : uint32_t offset_next = offset[i] + n_bits[i];
9286 : : uint32_t j;
9287 : :
9288 [ # # ]: 0 : for (j = 0; j < params->n_fields; j++)
9289 [ # # ]: 0 : if (offset[j] == offset_next) {
9290 : 0 : n_fields_with_valid_next++;
9291 : 0 : break;
9292 : : }
9293 : : }
9294 : :
9295 [ # # ]: 0 : if (n_fields_with_valid_next != params->n_fields - 1) {
9296 : : status = -EINVAL;
9297 : 0 : goto end;
9298 : : }
9299 : :
9300 : : /* Return. */
9301 [ # # ]: 0 : if (header)
9302 : 0 : *header = h0;
9303 : :
9304 : 0 : end:
9305 : 0 : free(offset);
9306 : 0 : free(n_bits);
9307 : 0 : return status;
9308 : : }
9309 : :
9310 : : static int
9311 : 0 : learner_action_args_check(struct rte_swx_pipeline *p, struct action *a, const char *mf_name)
9312 : : {
9313 : 0 : struct struct_type *mst = p->metadata_st, *ast = a->st;
9314 : : struct field *mf, *af;
9315 : : uint32_t mf_pos, i;
9316 : :
9317 [ # # ]: 0 : if (!ast) {
9318 [ # # ]: 0 : if (mf_name)
9319 : : return -EINVAL;
9320 : :
9321 : 0 : return 0;
9322 : : }
9323 : :
9324 : : /* Check that mf_name is the name of a valid meta-data field. */
9325 [ # # # # : 0 : CHECK_NAME(mf_name, EINVAL);
# # ]
9326 : 0 : mf = metadata_field_parse(p, mf_name);
9327 [ # # ]: 0 : CHECK(mf, EINVAL);
9328 : :
9329 : : /* Check that there are enough meta-data fields, starting with the mf_name field, to cover
9330 : : * all the action arguments.
9331 : : */
9332 : 0 : mf_pos = mf - mst->fields;
9333 [ # # ]: 0 : CHECK(mst->n_fields - mf_pos >= ast->n_fields, EINVAL);
9334 : :
9335 : : /* Check that the size of each of the identified meta-data fields matches exactly the size
9336 : : * of the corresponding action argument.
9337 : : */
9338 [ # # ]: 0 : for (i = 0; i < ast->n_fields; i++) {
9339 : 0 : mf = &mst->fields[mf_pos + i];
9340 : 0 : af = &ast->fields[i];
9341 : :
9342 [ # # ]: 0 : CHECK(mf->n_bits == af->n_bits, EINVAL);
9343 : : }
9344 : :
9345 : : return 0;
9346 : : }
9347 : :
9348 : : static int
9349 : 0 : learner_action_learning_check(struct rte_swx_pipeline *p,
9350 : : struct action *action,
9351 : : const char **action_names,
9352 : : uint32_t n_actions)
9353 : : {
9354 : : uint32_t i;
9355 : :
9356 : : /* For each "learn" instruction of the current action, check that the learned action (i.e.
9357 : : * the action passed as argument to the "learn" instruction) is also enabled for the
9358 : : * current learner table.
9359 : : */
9360 [ # # ]: 0 : for (i = 0; i < action->n_instructions; i++) {
9361 : 0 : struct instruction *instr = &action->instructions[i];
9362 : : uint32_t found = 0, j;
9363 : :
9364 [ # # ]: 0 : if (instr->type != INSTR_LEARNER_LEARN)
9365 : 0 : continue;
9366 : :
9367 [ # # ]: 0 : for (j = 0; j < n_actions; j++) {
9368 : : struct action *a;
9369 : :
9370 : 0 : a = action_find(p, action_names[j]);
9371 [ # # ]: 0 : if (!a)
9372 : : return -EINVAL;
9373 : :
9374 [ # # ]: 0 : if (a->id == instr->learn.action_id)
9375 : : found = 1;
9376 : : }
9377 : :
9378 [ # # ]: 0 : if (!found)
9379 : : return -EINVAL;
9380 : : }
9381 : :
9382 : : return 0;
9383 : : }
9384 : :
9385 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_pipeline_learner_config, 21.11)
9386 : : int
9387 : 0 : rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p,
9388 : : const char *name,
9389 : : struct rte_swx_pipeline_learner_params *params,
9390 : : uint32_t size,
9391 : : uint32_t *timeout,
9392 : : uint32_t n_timeouts)
9393 : : {
9394 : : struct learner *l = NULL;
9395 : : struct action *default_action;
9396 : 0 : struct header *header = NULL;
9397 : : struct hash_func *hf = NULL;
9398 : : uint32_t action_data_size_max = 0, i;
9399 : : int status = 0;
9400 : :
9401 [ # # ]: 0 : CHECK(p, EINVAL);
9402 : :
9403 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
9404 [ # # ]: 0 : CHECK(!table_find(p, name), EEXIST);
9405 [ # # ]: 0 : CHECK(!selector_find(p, name), EEXIST);
9406 [ # # ]: 0 : CHECK(!learner_find(p, name), EEXIST);
9407 : :
9408 [ # # ]: 0 : CHECK(params, EINVAL);
9409 : :
9410 : : /* Match checks. */
9411 : 0 : status = learner_match_fields_check(p, params, &header);
9412 [ # # ]: 0 : if (status)
9413 : : return status;
9414 : :
9415 : : /* Action checks. */
9416 [ # # ]: 0 : CHECK(params->n_actions, EINVAL);
9417 [ # # ]: 0 : CHECK(params->action_names, EINVAL);
9418 [ # # ]: 0 : for (i = 0; i < params->n_actions; i++) {
9419 : 0 : const char *action_name = params->action_names[i];
9420 : : struct action *a;
9421 : : uint32_t action_data_size;
9422 : : int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
9423 : :
9424 [ # # # # : 0 : CHECK_NAME(action_name, EINVAL);
# # ]
9425 : :
9426 : 0 : a = action_find(p, action_name);
9427 [ # # ]: 0 : CHECK(a, EINVAL);
9428 : :
9429 : 0 : status = learner_action_learning_check(p,
9430 : : a,
9431 : : params->action_names,
9432 : : params->n_actions);
9433 [ # # ]: 0 : if (status)
9434 : 0 : return status;
9435 : :
9436 [ # # ]: 0 : action_data_size = a->st ? a->st->n_bits / 8 : 0;
9437 : : if (action_data_size > action_data_size_max)
9438 : : action_data_size_max = action_data_size;
9439 : :
9440 [ # # ]: 0 : if (params->action_is_for_table_entries)
9441 : 0 : action_is_for_table_entries = params->action_is_for_table_entries[i];
9442 [ # # ]: 0 : if (params->action_is_for_default_entry)
9443 : 0 : action_is_for_default_entry = params->action_is_for_default_entry[i];
9444 [ # # ]: 0 : CHECK(action_is_for_table_entries || action_is_for_default_entry, EINVAL);
9445 : : }
9446 : :
9447 [ # # # # : 0 : CHECK_NAME(params->default_action_name, EINVAL);
# # ]
9448 [ # # ]: 0 : for (i = 0; i < p->n_actions; i++)
9449 [ # # ]: 0 : if (!strcmp(params->action_names[i],
9450 : : params->default_action_name))
9451 : : break;
9452 [ # # ]: 0 : CHECK(i < params->n_actions, EINVAL);
9453 [ # # # # ]: 0 : CHECK(!params->action_is_for_default_entry || params->action_is_for_default_entry[i],
9454 : : EINVAL);
9455 : :
9456 : 0 : default_action = action_find(p, params->default_action_name);
9457 [ # # # # ]: 0 : CHECK((default_action->st && params->default_action_args) || !params->default_action_args,
9458 : : EINVAL);
9459 : :
9460 : : /* Hash function checks. */
9461 [ # # ]: 0 : if (params->hash_func_name) {
9462 : : hf = hash_func_find(p, params->hash_func_name);
9463 [ # # ]: 0 : CHECK(hf, EINVAL);
9464 : : }
9465 : :
9466 : : /* Any other checks. */
9467 [ # # ]: 0 : CHECK(size, EINVAL);
9468 [ # # ]: 0 : CHECK(timeout, EINVAL);
9469 [ # # ]: 0 : CHECK(n_timeouts && (n_timeouts <= RTE_SWX_TABLE_LEARNER_N_KEY_TIMEOUTS_MAX), EINVAL);
9470 : :
9471 : : /* Memory allocation. */
9472 : 0 : l = calloc(1, sizeof(struct learner));
9473 [ # # ]: 0 : if (!l) {
9474 : : status = -ENOMEM;
9475 : 0 : goto error;
9476 : : }
9477 : :
9478 : 0 : l->fields = calloc(params->n_fields, sizeof(struct field *));
9479 [ # # ]: 0 : if (!l->fields) {
9480 : : status = -ENOMEM;
9481 : 0 : goto error;
9482 : : }
9483 : :
9484 : 0 : l->actions = calloc(params->n_actions, sizeof(struct action *));
9485 [ # # ]: 0 : if (!l->actions) {
9486 : : status = -ENOMEM;
9487 : 0 : goto error;
9488 : : }
9489 : :
9490 [ # # ]: 0 : if (action_data_size_max) {
9491 : 0 : l->default_action_data = calloc(1, action_data_size_max);
9492 [ # # ]: 0 : if (!l->default_action_data) {
9493 : : status = -ENOMEM;
9494 : 0 : goto error;
9495 : : }
9496 : : }
9497 : :
9498 : 0 : l->action_is_for_table_entries = calloc(params->n_actions, sizeof(int));
9499 [ # # ]: 0 : if (!l->action_is_for_table_entries) {
9500 : : status = -ENOMEM;
9501 : 0 : goto error;
9502 : : }
9503 : :
9504 : 0 : l->action_is_for_default_entry = calloc(params->n_actions, sizeof(int));
9505 [ # # ]: 0 : if (!l->action_is_for_default_entry) {
9506 : : status = -ENOMEM;
9507 : 0 : goto error;
9508 : : }
9509 : :
9510 : : /* Node initialization. */
9511 : 0 : strcpy(l->name, name);
9512 : :
9513 [ # # ]: 0 : for (i = 0; i < params->n_fields; i++) {
9514 : 0 : const char *field_name = params->field_names[i];
9515 : :
9516 : 0 : l->fields[i] = header ?
9517 [ # # ]: 0 : header_field_parse(p, field_name, NULL) :
9518 : 0 : metadata_field_parse(p, field_name);
9519 : : }
9520 : :
9521 : 0 : l->n_fields = params->n_fields;
9522 : :
9523 : 0 : l->header = header;
9524 : :
9525 [ # # ]: 0 : for (i = 0; i < params->n_actions; i++) {
9526 : : int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
9527 : :
9528 [ # # ]: 0 : if (params->action_is_for_table_entries)
9529 : 0 : action_is_for_table_entries = params->action_is_for_table_entries[i];
9530 [ # # ]: 0 : if (params->action_is_for_default_entry)
9531 : 0 : action_is_for_default_entry = params->action_is_for_default_entry[i];
9532 : :
9533 : 0 : l->actions[i] = action_find(p, params->action_names[i]);
9534 : 0 : l->action_is_for_table_entries[i] = action_is_for_table_entries;
9535 : 0 : l->action_is_for_default_entry[i] = action_is_for_default_entry;
9536 : : }
9537 : :
9538 : 0 : l->default_action = default_action;
9539 : :
9540 [ # # ]: 0 : if (default_action->st) {
9541 : 0 : status = action_args_parse(default_action,
9542 : : params->default_action_args,
9543 : : l->default_action_data);
9544 [ # # ]: 0 : if (status)
9545 : 0 : goto error;
9546 : : }
9547 : :
9548 : 0 : l->n_actions = params->n_actions;
9549 : :
9550 : 0 : l->default_action_is_const = params->default_action_is_const;
9551 : :
9552 : 0 : l->action_data_size_max = action_data_size_max;
9553 : :
9554 : 0 : l->hf = hf;
9555 : :
9556 : 0 : l->size = size;
9557 : :
9558 [ # # ]: 0 : for (i = 0; i < n_timeouts; i++)
9559 : 0 : l->timeout[i] = timeout[i];
9560 : :
9561 : 0 : l->n_timeouts = n_timeouts;
9562 : :
9563 : 0 : l->id = p->n_learners;
9564 : :
9565 : : /* Node add to tailq. */
9566 : 0 : TAILQ_INSERT_TAIL(&p->learners, l, node);
9567 : 0 : p->n_learners++;
9568 : :
9569 : 0 : return 0;
9570 : :
9571 : 0 : error:
9572 [ # # ]: 0 : if (!l)
9573 : : return status;
9574 : :
9575 : 0 : free(l->action_is_for_default_entry);
9576 : 0 : free(l->action_is_for_table_entries);
9577 : 0 : free(l->default_action_data);
9578 : 0 : free(l->actions);
9579 : 0 : free(l->fields);
9580 : 0 : free(l);
9581 : :
9582 : 0 : return status;
9583 : : }
9584 : :
9585 : : static uint32_t
9586 : : learner_params_offset_get(struct learner *l)
9587 : : {
9588 : : struct field *first;
9589 : : uint32_t i;
9590 : :
9591 : 0 : first = l->fields[0];
9592 : :
9593 [ # # ]: 0 : for (i = 1; i < l->n_fields; i++) {
9594 : 0 : struct field *f = l->fields[i];
9595 : :
9596 [ # # ]: 0 : if (f->offset < first->offset)
9597 : : first = f;
9598 : : }
9599 : :
9600 : 0 : return first->offset / 8;
9601 : : }
9602 : :
9603 : : static void
9604 : 0 : learner_params_free(struct rte_swx_table_learner_params *params)
9605 : : {
9606 [ # # ]: 0 : if (!params)
9607 : : return;
9608 : :
9609 : 0 : free(params->key_mask0);
9610 : :
9611 : 0 : free(params->key_timeout);
9612 : :
9613 : 0 : free(params);
9614 : : }
9615 : :
9616 : : static struct rte_swx_table_learner_params *
9617 : 0 : learner_params_get(struct learner *l)
9618 : : {
9619 : : struct rte_swx_table_learner_params *params = NULL;
9620 : : struct field *first, *last;
9621 : : uint32_t i;
9622 : :
9623 : : /* Memory allocation. */
9624 : 0 : params = calloc(1, sizeof(struct rte_swx_table_learner_params));
9625 [ # # ]: 0 : if (!params)
9626 : 0 : goto error;
9627 : :
9628 : : /* Find first (smallest offset) and last (biggest offset) match fields. */
9629 : 0 : first = l->fields[0];
9630 : : last = l->fields[0];
9631 : :
9632 [ # # ]: 0 : for (i = 0; i < l->n_fields; i++) {
9633 : 0 : struct field *f = l->fields[i];
9634 : :
9635 [ # # ]: 0 : if (f->offset < first->offset)
9636 : : first = f;
9637 : :
9638 [ # # ]: 0 : if (f->offset > last->offset)
9639 : : last = f;
9640 : : }
9641 : :
9642 : : /* Key offset and size. */
9643 : 0 : params->key_offset = first->offset / 8;
9644 : 0 : params->key_size = (last->offset + last->n_bits - first->offset) / 8;
9645 : :
9646 : : /* Memory allocation. */
9647 : 0 : params->key_mask0 = calloc(1, params->key_size);
9648 [ # # ]: 0 : if (!params->key_mask0)
9649 : 0 : goto error;
9650 : :
9651 : : /* Key mask. */
9652 [ # # ]: 0 : for (i = 0; i < l->n_fields; i++) {
9653 : 0 : struct field *f = l->fields[i];
9654 : 0 : uint32_t start = (f->offset - first->offset) / 8;
9655 : 0 : size_t size = f->n_bits / 8;
9656 : :
9657 : 0 : memset(¶ms->key_mask0[start], 0xFF, size);
9658 : : }
9659 : :
9660 : : /* Action data size. */
9661 : 0 : params->action_data_size = l->action_data_size_max;
9662 : :
9663 : : /* Hash function. */
9664 [ # # ]: 0 : params->hash_func = l->hf ? l->hf->func : NULL;
9665 : :
9666 : : /* Maximum number of keys. */
9667 : 0 : params->n_keys_max = l->size;
9668 : :
9669 : : /* Memory allocation. */
9670 : 0 : params->key_timeout = calloc(l->n_timeouts, sizeof(uint32_t));
9671 [ # # ]: 0 : if (!params->key_timeout)
9672 : 0 : goto error;
9673 : :
9674 : : /* Timeout. */
9675 [ # # ]: 0 : for (i = 0; i < l->n_timeouts; i++)
9676 : 0 : params->key_timeout[i] = l->timeout[i];
9677 : :
9678 : 0 : params->n_key_timeouts = l->n_timeouts;
9679 : :
9680 : 0 : return params;
9681 : :
9682 : 0 : error:
9683 : 0 : learner_params_free(params);
9684 : 0 : return NULL;
9685 : : }
9686 : :
9687 : : static void
9688 : 0 : learner_build_free(struct rte_swx_pipeline *p)
9689 : : {
9690 : : uint32_t i;
9691 : :
9692 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9693 : : struct thread *t = &p->threads[i];
9694 : : uint32_t j;
9695 : :
9696 [ # # ]: 0 : if (!t->learners)
9697 : 0 : continue;
9698 : :
9699 [ # # ]: 0 : for (j = 0; j < p->n_learners; j++) {
9700 : 0 : struct learner_runtime *r = &t->learners[j];
9701 : :
9702 : 0 : free(r->mailbox);
9703 : : }
9704 : :
9705 : 0 : free(t->learners);
9706 : 0 : t->learners = NULL;
9707 : : }
9708 : :
9709 [ # # ]: 0 : if (p->learner_stats) {
9710 [ # # ]: 0 : for (i = 0; i < p->n_learners; i++)
9711 : 0 : free(p->learner_stats[i].n_pkts_action);
9712 : :
9713 : 0 : free(p->learner_stats);
9714 : 0 : p->learner_stats = NULL;
9715 : : }
9716 : 0 : }
9717 : :
9718 : : static int
9719 : 0 : learner_build(struct rte_swx_pipeline *p)
9720 : : {
9721 : : uint32_t i;
9722 : : int status = 0;
9723 : :
9724 : : /* Per pipeline: learner statistics. */
9725 : 0 : p->learner_stats = calloc(p->n_learners, sizeof(struct learner_statistics));
9726 [ # # ]: 0 : CHECK(p->learner_stats, ENOMEM);
9727 : :
9728 [ # # ]: 0 : for (i = 0; i < p->n_learners; i++) {
9729 : 0 : p->learner_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
9730 [ # # ]: 0 : CHECK(p->learner_stats[i].n_pkts_action, ENOMEM);
9731 : : }
9732 : :
9733 : : /* Per thread: learner run-time. */
9734 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9735 : : struct thread *t = &p->threads[i];
9736 : : struct learner *l;
9737 : :
9738 : 0 : t->learners = calloc(p->n_learners, sizeof(struct learner_runtime));
9739 [ # # ]: 0 : if (!t->learners) {
9740 : : status = -ENOMEM;
9741 : 0 : goto error;
9742 : : }
9743 : :
9744 [ # # ]: 0 : TAILQ_FOREACH(l, &p->learners, node) {
9745 : 0 : struct learner_runtime *r = &t->learners[l->id];
9746 : : uint64_t size;
9747 : :
9748 : : /* r->mailbox. */
9749 : 0 : size = rte_swx_table_learner_mailbox_size_get();
9750 [ # # ]: 0 : if (size) {
9751 : 0 : r->mailbox = calloc(1, size);
9752 [ # # ]: 0 : if (!r->mailbox) {
9753 : : status = -ENOMEM;
9754 : 0 : goto error;
9755 : : }
9756 : : }
9757 : :
9758 : : /* r->key. */
9759 : 0 : r->key = l->header ?
9760 [ # # ]: 0 : &t->structs[l->header->struct_id] :
9761 : 0 : &t->structs[p->metadata_struct_id];
9762 : : }
9763 : : }
9764 : :
9765 : : return 0;
9766 : :
9767 : 0 : error:
9768 : 0 : learner_build_free(p);
9769 : 0 : return status;
9770 : : }
9771 : :
9772 : : static void
9773 : 0 : learner_free(struct rte_swx_pipeline *p)
9774 : : {
9775 : 0 : learner_build_free(p);
9776 : :
9777 : : /* Learner tables. */
9778 : 0 : for ( ; ; ) {
9779 : : struct learner *l;
9780 : :
9781 : 0 : l = TAILQ_FIRST(&p->learners);
9782 [ # # ]: 0 : if (!l)
9783 : : break;
9784 : :
9785 [ # # ]: 0 : TAILQ_REMOVE(&p->learners, l, node);
9786 : 0 : free(l->fields);
9787 : 0 : free(l->actions);
9788 : 0 : free(l->default_action_data);
9789 : 0 : free(l);
9790 : : }
9791 : 0 : }
9792 : :
9793 : : /*
9794 : : * Table state.
9795 : : */
9796 : : static int
9797 : 0 : table_state_build(struct rte_swx_pipeline *p)
9798 : : {
9799 : : struct table *table;
9800 : : struct selector *s;
9801 : : struct learner *l;
9802 : :
9803 : 0 : p->table_state = calloc(p->n_tables + p->n_selectors + p->n_learners,
9804 : : sizeof(struct rte_swx_table_state));
9805 [ # # ]: 0 : CHECK(p->table_state, ENOMEM);
9806 : :
9807 [ # # ]: 0 : TAILQ_FOREACH(table, &p->tables, node) {
9808 : 0 : struct rte_swx_table_state *ts = &p->table_state[table->id];
9809 : :
9810 [ # # ]: 0 : if (table->type) {
9811 : : struct rte_swx_table_params *params;
9812 : :
9813 : : /* ts->obj. */
9814 : 0 : params = table_params_get(table);
9815 [ # # ]: 0 : CHECK(params, ENOMEM);
9816 : :
9817 : 0 : ts->obj = table->type->ops.create(params,
9818 : : NULL,
9819 : 0 : table->args,
9820 : : p->numa_node);
9821 : :
9822 : 0 : table_params_free(params);
9823 [ # # ]: 0 : CHECK(ts->obj, ENODEV);
9824 : : }
9825 : :
9826 : : /* ts->default_action_data. */
9827 [ # # ]: 0 : if (table->action_data_size_max) {
9828 : 0 : ts->default_action_data =
9829 : 0 : malloc(table->action_data_size_max);
9830 [ # # ]: 0 : CHECK(ts->default_action_data, ENOMEM);
9831 : :
9832 : : memcpy(ts->default_action_data,
9833 : 0 : table->default_action_data,
9834 : : table->action_data_size_max);
9835 : : }
9836 : :
9837 : : /* ts->default_action_id. */
9838 : 0 : ts->default_action_id = table->default_action->id;
9839 : : }
9840 : :
9841 [ # # ]: 0 : TAILQ_FOREACH(s, &p->selectors, node) {
9842 : 0 : struct rte_swx_table_state *ts = &p->table_state[p->n_tables + s->id];
9843 : : struct rte_swx_table_selector_params *params;
9844 : :
9845 : : /* ts->obj. */
9846 : 0 : params = selector_table_params_get(s);
9847 [ # # ]: 0 : CHECK(params, ENOMEM);
9848 : :
9849 : 0 : ts->obj = rte_swx_table_selector_create(params, NULL, p->numa_node);
9850 : :
9851 : 0 : selector_params_free(params);
9852 [ # # ]: 0 : CHECK(ts->obj, ENODEV);
9853 : : }
9854 : :
9855 [ # # ]: 0 : TAILQ_FOREACH(l, &p->learners, node) {
9856 : 0 : struct rte_swx_table_state *ts = &p->table_state[p->n_tables +
9857 : 0 : p->n_selectors + l->id];
9858 : : struct rte_swx_table_learner_params *params;
9859 : :
9860 : : /* ts->obj. */
9861 : 0 : params = learner_params_get(l);
9862 [ # # ]: 0 : CHECK(params, ENOMEM);
9863 : :
9864 : 0 : ts->obj = rte_swx_table_learner_create(params, p->numa_node);
9865 : 0 : learner_params_free(params);
9866 [ # # ]: 0 : CHECK(ts->obj, ENODEV);
9867 : :
9868 : : /* ts->default_action_data. */
9869 [ # # ]: 0 : if (l->action_data_size_max) {
9870 : 0 : ts->default_action_data = malloc(l->action_data_size_max);
9871 [ # # ]: 0 : CHECK(ts->default_action_data, ENOMEM);
9872 : :
9873 : : memcpy(ts->default_action_data,
9874 : 0 : l->default_action_data,
9875 : : l->action_data_size_max);
9876 : : }
9877 : :
9878 : : /* ts->default_action_id. */
9879 : 0 : ts->default_action_id = l->default_action->id;
9880 : : }
9881 : :
9882 : : return 0;
9883 : : }
9884 : :
9885 : : static void
9886 : 0 : table_state_build_free(struct rte_swx_pipeline *p)
9887 : : {
9888 : : uint32_t i;
9889 : :
9890 [ # # ]: 0 : if (!p->table_state)
9891 : : return;
9892 : :
9893 [ # # ]: 0 : for (i = 0; i < p->n_tables; i++) {
9894 : 0 : struct rte_swx_table_state *ts = &p->table_state[i];
9895 : : struct table *table = table_find_by_id(p, i);
9896 : :
9897 : : /* ts->obj. */
9898 [ # # # # ]: 0 : if (table->type && ts->obj)
9899 : 0 : table->type->ops.free(ts->obj);
9900 : :
9901 : : /* ts->default_action_data. */
9902 : 0 : free(ts->default_action_data);
9903 : : }
9904 : :
9905 [ # # ]: 0 : for (i = 0; i < p->n_selectors; i++) {
9906 : 0 : struct rte_swx_table_state *ts = &p->table_state[p->n_tables + i];
9907 : :
9908 : : /* ts->obj. */
9909 : 0 : rte_swx_table_selector_free(ts->obj);
9910 : : }
9911 : :
9912 [ # # ]: 0 : for (i = 0; i < p->n_learners; i++) {
9913 : 0 : struct rte_swx_table_state *ts = &p->table_state[p->n_tables + p->n_selectors + i];
9914 : :
9915 : : /* ts->obj. */
9916 : 0 : rte_swx_table_learner_free(ts->obj);
9917 : :
9918 : : /* ts->default_action_data. */
9919 : 0 : free(ts->default_action_data);
9920 : : }
9921 : :
9922 : 0 : free(p->table_state);
9923 : 0 : p->table_state = NULL;
9924 : : }
9925 : :
9926 : : static void
9927 : : table_state_free(struct rte_swx_pipeline *p)
9928 : : {
9929 : 0 : table_state_build_free(p);
9930 : : }
9931 : :
9932 : : /*
9933 : : * Register array.
9934 : : */
9935 : : static struct regarray *
9936 : : regarray_find(struct rte_swx_pipeline *p, const char *name)
9937 : : {
9938 : : struct regarray *elem;
9939 : :
9940 [ # # # # : 0 : TAILQ_FOREACH(elem, &p->regarrays, node)
# # # # #
# # # #
# ]
9941 [ # # # # : 0 : if (!strcmp(elem->name, name))
# # # # #
# # # #
# ]
9942 : : return elem;
9943 : :
9944 : : return NULL;
9945 : : }
9946 : :
9947 : : static struct regarray *
9948 : : regarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9949 : : {
9950 : : struct regarray *elem = NULL;
9951 : :
9952 [ # # # # ]: 0 : TAILQ_FOREACH(elem, &p->regarrays, node)
9953 [ # # # # ]: 0 : if (elem->id == id)
9954 : : return elem;
9955 : :
9956 : : return NULL;
9957 : : }
9958 : :
9959 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_pipeline_regarray_config, 21.05)
9960 : : int
9961 : 0 : rte_swx_pipeline_regarray_config(struct rte_swx_pipeline *p,
9962 : : const char *name,
9963 : : uint32_t size,
9964 : : uint64_t init_val)
9965 : : {
9966 : : struct regarray *r;
9967 : :
9968 [ # # ]: 0 : CHECK(p, EINVAL);
9969 : :
9970 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
9971 [ # # ]: 0 : CHECK(!regarray_find(p, name), EEXIST);
9972 : :
9973 [ # # ]: 0 : CHECK(size, EINVAL);
9974 : : size = rte_align32pow2(size);
9975 : :
9976 : : /* Memory allocation. */
9977 : 0 : r = calloc(1, sizeof(struct regarray));
9978 [ # # ]: 0 : CHECK(r, ENOMEM);
9979 : :
9980 : : /* Node initialization. */
9981 : 0 : strcpy(r->name, name);
9982 : 0 : r->init_val = init_val;
9983 : 0 : r->size = size;
9984 : 0 : r->id = p->n_regarrays;
9985 : :
9986 : : /* Node add to tailq. */
9987 : 0 : TAILQ_INSERT_TAIL(&p->regarrays, r, node);
9988 : 0 : p->n_regarrays++;
9989 : :
9990 : 0 : return 0;
9991 : : }
9992 : :
9993 : : static int
9994 : 0 : regarray_build(struct rte_swx_pipeline *p)
9995 : : {
9996 : : struct regarray *regarray;
9997 : :
9998 [ # # ]: 0 : if (!p->n_regarrays)
9999 : : return 0;
10000 : :
10001 : 0 : p->regarray_runtime = calloc(p->n_regarrays, sizeof(struct regarray_runtime));
10002 [ # # ]: 0 : CHECK(p->regarray_runtime, ENOMEM);
10003 : :
10004 [ # # ]: 0 : TAILQ_FOREACH(regarray, &p->regarrays, node) {
10005 : 0 : struct regarray_runtime *r = &p->regarray_runtime[regarray->id];
10006 : : uint32_t i;
10007 : :
10008 : 0 : r->regarray = env_malloc(regarray->size * sizeof(uint64_t),
10009 : : RTE_CACHE_LINE_SIZE,
10010 : : p->numa_node);
10011 [ # # ]: 0 : CHECK(r->regarray, ENOMEM);
10012 : :
10013 [ # # ]: 0 : if (regarray->init_val)
10014 [ # # ]: 0 : for (i = 0; i < regarray->size; i++)
10015 : 0 : r->regarray[i] = regarray->init_val;
10016 : :
10017 : 0 : r->size_mask = regarray->size - 1;
10018 : : }
10019 : :
10020 : : return 0;
10021 : : }
10022 : :
10023 : : static void
10024 : 0 : regarray_build_free(struct rte_swx_pipeline *p)
10025 : : {
10026 : : uint32_t i;
10027 : :
10028 [ # # ]: 0 : if (!p->regarray_runtime)
10029 : : return;
10030 : :
10031 [ # # ]: 0 : for (i = 0; i < p->n_regarrays; i++) {
10032 : : struct regarray *regarray = regarray_find_by_id(p, i);
10033 : 0 : struct regarray_runtime *r = &p->regarray_runtime[i];
10034 : :
10035 : 0 : env_free(r->regarray, regarray->size * sizeof(uint64_t));
10036 : : }
10037 : :
10038 : 0 : free(p->regarray_runtime);
10039 : 0 : p->regarray_runtime = NULL;
10040 : : }
10041 : :
10042 : : static void
10043 : 0 : regarray_free(struct rte_swx_pipeline *p)
10044 : : {
10045 : 0 : regarray_build_free(p);
10046 : :
10047 : 0 : for ( ; ; ) {
10048 : : struct regarray *elem;
10049 : :
10050 : 0 : elem = TAILQ_FIRST(&p->regarrays);
10051 [ # # ]: 0 : if (!elem)
10052 : : break;
10053 : :
10054 [ # # ]: 0 : TAILQ_REMOVE(&p->regarrays, elem, node);
10055 : 0 : free(elem);
10056 : : }
10057 : 0 : }
10058 : :
10059 : : /*
10060 : : * Meter array.
10061 : : */
10062 : : static struct meter_profile *
10063 : : meter_profile_find(struct rte_swx_pipeline *p, const char *name)
10064 : : {
10065 : : struct meter_profile *elem;
10066 : :
10067 [ # # # # : 0 : TAILQ_FOREACH(elem, &p->meter_profiles, node)
# # ]
10068 [ # # # # : 0 : if (!strcmp(elem->name, name))
# # ]
10069 : : return elem;
10070 : :
10071 : : return NULL;
10072 : : }
10073 : :
10074 : : static struct metarray *
10075 : : metarray_find(struct rte_swx_pipeline *p, const char *name)
10076 : : {
10077 : : struct metarray *elem;
10078 : :
10079 [ # # # # : 0 : TAILQ_FOREACH(elem, &p->metarrays, node)
# # # # #
# # # ]
10080 [ # # # # : 0 : if (!strcmp(elem->name, name))
# # # # #
# # # ]
10081 : : return elem;
10082 : :
10083 : : return NULL;
10084 : : }
10085 : :
10086 : : static struct metarray *
10087 : : metarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
10088 : : {
10089 : : struct metarray *elem = NULL;
10090 : :
10091 [ # # # # ]: 0 : TAILQ_FOREACH(elem, &p->metarrays, node)
10092 [ # # # # ]: 0 : if (elem->id == id)
10093 : : return elem;
10094 : :
10095 : : return NULL;
10096 : : }
10097 : :
10098 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_pipeline_metarray_config, 21.05)
10099 : : int
10100 : 0 : rte_swx_pipeline_metarray_config(struct rte_swx_pipeline *p,
10101 : : const char *name,
10102 : : uint32_t size)
10103 : : {
10104 : : struct metarray *m;
10105 : :
10106 [ # # ]: 0 : CHECK(p, EINVAL);
10107 : :
10108 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
10109 [ # # ]: 0 : CHECK(!metarray_find(p, name), EEXIST);
10110 : :
10111 [ # # ]: 0 : CHECK(size, EINVAL);
10112 : : size = rte_align32pow2(size);
10113 : :
10114 : : /* Memory allocation. */
10115 : 0 : m = calloc(1, sizeof(struct metarray));
10116 [ # # ]: 0 : CHECK(m, ENOMEM);
10117 : :
10118 : : /* Node initialization. */
10119 : 0 : strcpy(m->name, name);
10120 : 0 : m->size = size;
10121 : 0 : m->id = p->n_metarrays;
10122 : :
10123 : : /* Node add to tailq. */
10124 : 0 : TAILQ_INSERT_TAIL(&p->metarrays, m, node);
10125 : 0 : p->n_metarrays++;
10126 : :
10127 : 0 : return 0;
10128 : : }
10129 : :
10130 : : struct meter_profile meter_profile_default = {
10131 : : .node = {0},
10132 : : .name = "",
10133 : : .params = {0},
10134 : :
10135 : : .profile = {
10136 : : .cbs = 10000,
10137 : : .pbs = 10000,
10138 : : .cir_period = 1,
10139 : : .cir_bytes_per_period = 1,
10140 : : .pir_period = 1,
10141 : : .pir_bytes_per_period = 1,
10142 : : },
10143 : :
10144 : : .n_users = 0,
10145 : : };
10146 : :
10147 : : static void
10148 : 0 : meter_init(struct meter *m)
10149 : : {
10150 : : memset(m, 0, sizeof(struct meter));
10151 : 0 : rte_meter_trtcm_config(&m->m, &meter_profile_default.profile);
10152 : 0 : m->profile = &meter_profile_default;
10153 : 0 : m->color_mask = RTE_COLOR_GREEN;
10154 : :
10155 : 0 : meter_profile_default.n_users++;
10156 : 0 : }
10157 : :
10158 : : static int
10159 : 0 : metarray_build(struct rte_swx_pipeline *p)
10160 : : {
10161 : : struct metarray *m;
10162 : :
10163 [ # # ]: 0 : if (!p->n_metarrays)
10164 : : return 0;
10165 : :
10166 : 0 : p->metarray_runtime = calloc(p->n_metarrays, sizeof(struct metarray_runtime));
10167 [ # # ]: 0 : CHECK(p->metarray_runtime, ENOMEM);
10168 : :
10169 [ # # ]: 0 : TAILQ_FOREACH(m, &p->metarrays, node) {
10170 : 0 : struct metarray_runtime *r = &p->metarray_runtime[m->id];
10171 : : uint32_t i;
10172 : :
10173 : 0 : r->metarray = env_malloc(m->size * sizeof(struct meter),
10174 : : RTE_CACHE_LINE_SIZE,
10175 : : p->numa_node);
10176 [ # # ]: 0 : CHECK(r->metarray, ENOMEM);
10177 : :
10178 [ # # ]: 0 : for (i = 0; i < m->size; i++)
10179 : 0 : meter_init(&r->metarray[i]);
10180 : :
10181 : 0 : r->size_mask = m->size - 1;
10182 : : }
10183 : :
10184 : : return 0;
10185 : : }
10186 : :
10187 : : static void
10188 : 0 : metarray_build_free(struct rte_swx_pipeline *p)
10189 : : {
10190 : : uint32_t i;
10191 : :
10192 [ # # ]: 0 : if (!p->metarray_runtime)
10193 : : return;
10194 : :
10195 [ # # ]: 0 : for (i = 0; i < p->n_metarrays; i++) {
10196 : : struct metarray *m = metarray_find_by_id(p, i);
10197 : 0 : struct metarray_runtime *r = &p->metarray_runtime[i];
10198 : :
10199 : 0 : env_free(r->metarray, m->size * sizeof(struct meter));
10200 : : }
10201 : :
10202 : 0 : free(p->metarray_runtime);
10203 : 0 : p->metarray_runtime = NULL;
10204 : : }
10205 : :
10206 : : static void
10207 : 0 : metarray_free(struct rte_swx_pipeline *p)
10208 : : {
10209 : 0 : metarray_build_free(p);
10210 : :
10211 : : /* Meter arrays. */
10212 : 0 : for ( ; ; ) {
10213 : : struct metarray *elem;
10214 : :
10215 : 0 : elem = TAILQ_FIRST(&p->metarrays);
10216 [ # # ]: 0 : if (!elem)
10217 : : break;
10218 : :
10219 [ # # ]: 0 : TAILQ_REMOVE(&p->metarrays, elem, node);
10220 : 0 : free(elem);
10221 : : }
10222 : :
10223 : : /* Meter profiles. */
10224 : 0 : for ( ; ; ) {
10225 : : struct meter_profile *elem;
10226 : :
10227 : 0 : elem = TAILQ_FIRST(&p->meter_profiles);
10228 [ # # ]: 0 : if (!elem)
10229 : : break;
10230 : :
10231 [ # # ]: 0 : TAILQ_REMOVE(&p->meter_profiles, elem, node);
10232 : 0 : free(elem);
10233 : : }
10234 : 0 : }
10235 : :
10236 : : /*
10237 : : * Pipeline.
10238 : : */
10239 : :
10240 : : /* Global list of pipeline instances. */
10241 : : TAILQ_HEAD(rte_swx_pipeline_list, rte_tailq_entry);
10242 : :
10243 : : static struct rte_tailq_elem rte_swx_pipeline_tailq = {
10244 : : .name = "RTE_SWX_PIPELINE",
10245 : : };
10246 : :
10247 [ - + ]: 252 : EAL_REGISTER_TAILQ(rte_swx_pipeline_tailq)
10248 : :
10249 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_pipeline_find, 22.11)
10250 : : struct rte_swx_pipeline *
10251 : 0 : rte_swx_pipeline_find(const char *name)
10252 : : {
10253 : : struct rte_swx_pipeline_list *pipeline_list;
10254 : : struct rte_tailq_entry *te = NULL;
10255 : :
10256 [ # # # # : 0 : if (!name || !name[0] || (strnlen(name, RTE_SWX_NAME_SIZE) >= RTE_SWX_NAME_SIZE))
# # ]
10257 : : return NULL;
10258 : :
10259 : 0 : pipeline_list = RTE_TAILQ_CAST(rte_swx_pipeline_tailq.head, rte_swx_pipeline_list);
10260 : :
10261 : 0 : rte_mcfg_tailq_read_lock();
10262 : :
10263 [ # # ]: 0 : TAILQ_FOREACH(te, pipeline_list, next) {
10264 : 0 : struct rte_swx_pipeline *p = (struct rte_swx_pipeline *)te->data;
10265 : :
10266 [ # # ]: 0 : if (!strncmp(name, p->name, sizeof(p->name))) {
10267 : 0 : rte_mcfg_tailq_read_unlock();
10268 : 0 : return p;
10269 : : }
10270 : : }
10271 : :
10272 : 0 : rte_mcfg_tailq_read_unlock();
10273 : 0 : return NULL;
10274 : : }
10275 : :
10276 : : static int
10277 : 0 : pipeline_register(struct rte_swx_pipeline *p)
10278 : : {
10279 : : struct rte_swx_pipeline_list *pipeline_list;
10280 : : struct rte_tailq_entry *te = NULL;
10281 : :
10282 : 0 : pipeline_list = RTE_TAILQ_CAST(rte_swx_pipeline_tailq.head, rte_swx_pipeline_list);
10283 : :
10284 : 0 : rte_mcfg_tailq_write_lock();
10285 : :
10286 [ # # ]: 0 : TAILQ_FOREACH(te, pipeline_list, next) {
10287 : 0 : struct rte_swx_pipeline *pipeline = (struct rte_swx_pipeline *)te->data;
10288 : :
10289 [ # # ]: 0 : if (!strncmp(p->name, pipeline->name, sizeof(p->name))) {
10290 : 0 : rte_mcfg_tailq_write_unlock();
10291 : 0 : return -EEXIST;
10292 : : }
10293 : : }
10294 : :
10295 : 0 : te = calloc(1, sizeof(struct rte_tailq_entry));
10296 [ # # ]: 0 : if (!te) {
10297 : 0 : rte_mcfg_tailq_write_unlock();
10298 : 0 : return -ENOMEM;
10299 : : }
10300 : :
10301 : 0 : te->data = (void *)p;
10302 : 0 : TAILQ_INSERT_TAIL(pipeline_list, te, next);
10303 : 0 : rte_mcfg_tailq_write_unlock();
10304 : 0 : return 0;
10305 : : }
10306 : :
10307 : : static void
10308 : 0 : pipeline_unregister(struct rte_swx_pipeline *p)
10309 : : {
10310 : : struct rte_swx_pipeline_list *pipeline_list;
10311 : : struct rte_tailq_entry *te = NULL;
10312 : :
10313 : 0 : pipeline_list = RTE_TAILQ_CAST(rte_swx_pipeline_tailq.head, rte_swx_pipeline_list);
10314 : :
10315 : 0 : rte_mcfg_tailq_write_lock();
10316 : :
10317 [ # # ]: 0 : TAILQ_FOREACH(te, pipeline_list, next) {
10318 [ # # ]: 0 : if (te->data == (void *)p) {
10319 [ # # ]: 0 : TAILQ_REMOVE(pipeline_list, te, next);
10320 : 0 : rte_mcfg_tailq_write_unlock();
10321 : 0 : free(te);
10322 : 0 : return;
10323 : : }
10324 : : }
10325 : :
10326 : 0 : rte_mcfg_tailq_write_unlock();
10327 : : }
10328 : :
10329 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_pipeline_free, 20.11)
10330 : : void
10331 : 0 : rte_swx_pipeline_free(struct rte_swx_pipeline *p)
10332 : : {
10333 : : void *lib;
10334 : :
10335 [ # # ]: 0 : if (!p)
10336 : : return;
10337 : :
10338 [ # # ]: 0 : if (p->name[0])
10339 : 0 : pipeline_unregister(p);
10340 : :
10341 : 0 : lib = p->lib;
10342 : :
10343 : 0 : free(p->instruction_data);
10344 : 0 : free(p->instructions);
10345 : :
10346 : 0 : metarray_free(p);
10347 : 0 : regarray_free(p);
10348 : : table_state_free(p);
10349 : 0 : learner_free(p);
10350 : 0 : selector_free(p);
10351 : 0 : table_free(p);
10352 : 0 : action_free(p);
10353 : : instruction_table_free(p);
10354 : : metadata_free(p);
10355 : 0 : header_free(p);
10356 : 0 : rss_free(p);
10357 : 0 : hash_func_free(p);
10358 : 0 : extern_func_free(p);
10359 : 0 : extern_obj_free(p);
10360 : : mirroring_free(p);
10361 : 0 : port_out_free(p);
10362 : 0 : port_in_free(p);
10363 : 0 : struct_free(p);
10364 : :
10365 : 0 : free(p);
10366 : :
10367 [ # # ]: 0 : if (lib)
10368 : 0 : dlclose(lib);
10369 : : }
10370 : :
10371 : : static int
10372 : 0 : port_in_types_register(struct rte_swx_pipeline *p)
10373 : : {
10374 : : int status;
10375 : :
10376 : 0 : status = rte_swx_pipeline_port_in_type_register(p,
10377 : : "ethdev",
10378 : : &rte_swx_port_ethdev_reader_ops);
10379 [ # # ]: 0 : if (status)
10380 : : return status;
10381 : :
10382 : 0 : status = rte_swx_pipeline_port_in_type_register(p,
10383 : : "ring",
10384 : : &rte_swx_port_ring_reader_ops);
10385 [ # # ]: 0 : if (status)
10386 : : return status;
10387 : :
10388 : : #ifdef RTE_PORT_PCAP
10389 : 0 : status = rte_swx_pipeline_port_in_type_register(p,
10390 : : "source",
10391 : : &rte_swx_port_source_ops);
10392 [ # # ]: 0 : if (status)
10393 : : return status;
10394 : : #endif
10395 : :
10396 : 0 : status = rte_swx_pipeline_port_in_type_register(p,
10397 : : "fd",
10398 : : &rte_swx_port_fd_reader_ops);
10399 [ # # ]: 0 : if (status)
10400 : 0 : return status;
10401 : :
10402 : : return 0;
10403 : : }
10404 : :
10405 : : static int
10406 : 0 : port_out_types_register(struct rte_swx_pipeline *p)
10407 : : {
10408 : : int status;
10409 : :
10410 : 0 : status = rte_swx_pipeline_port_out_type_register(p,
10411 : : "ethdev",
10412 : : &rte_swx_port_ethdev_writer_ops);
10413 [ # # ]: 0 : if (status)
10414 : : return status;
10415 : :
10416 : 0 : status = rte_swx_pipeline_port_out_type_register(p,
10417 : : "ring",
10418 : : &rte_swx_port_ring_writer_ops);
10419 [ # # ]: 0 : if (status)
10420 : : return status;
10421 : :
10422 : 0 : status = rte_swx_pipeline_port_out_type_register(p,
10423 : : "sink",
10424 : : &rte_swx_port_sink_ops);
10425 [ # # ]: 0 : if (status)
10426 : : return status;
10427 : :
10428 : 0 : status = rte_swx_pipeline_port_out_type_register(p,
10429 : : "fd",
10430 : : &rte_swx_port_fd_writer_ops);
10431 [ # # ]: 0 : if (status)
10432 : 0 : return status;
10433 : :
10434 : : return 0;
10435 : : }
10436 : :
10437 : : static int
10438 : 0 : table_types_register(struct rte_swx_pipeline *p)
10439 : : {
10440 : : int status;
10441 : :
10442 : 0 : status = rte_swx_pipeline_table_type_register(p,
10443 : : "exact",
10444 : : RTE_SWX_TABLE_MATCH_EXACT,
10445 : : &rte_swx_table_exact_match_ops);
10446 [ # # ]: 0 : if (status)
10447 : : return status;
10448 : :
10449 : 0 : status = rte_swx_pipeline_table_type_register(p,
10450 : : "wildcard",
10451 : : RTE_SWX_TABLE_MATCH_WILDCARD,
10452 : : &rte_swx_table_wildcard_match_ops);
10453 [ # # ]: 0 : if (status)
10454 : 0 : return status;
10455 : :
10456 : : return 0;
10457 : : }
10458 : :
10459 : : static int
10460 : 0 : hash_funcs_register(struct rte_swx_pipeline *p)
10461 : : {
10462 : : int status;
10463 : :
10464 : 0 : status = rte_swx_pipeline_hash_func_register(p, "jhash", rte_jhash);
10465 [ # # ]: 0 : if (status)
10466 : : return status;
10467 : :
10468 : 0 : status = rte_swx_pipeline_hash_func_register(p, "crc32", rte_hash_crc);
10469 [ # # ]: 0 : if (status)
10470 : 0 : return status;
10471 : :
10472 : : return 0;
10473 : : }
10474 : :
10475 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_pipeline_config, 20.11)
10476 : : int
10477 : 0 : rte_swx_pipeline_config(struct rte_swx_pipeline **p, const char *name, int numa_node)
10478 : : {
10479 : : struct rte_swx_pipeline *pipeline = NULL;
10480 : : int status = 0;
10481 : :
10482 : : /* Check input parameters. */
10483 [ # # ]: 0 : CHECK(p, EINVAL);
10484 [ # # # # ]: 0 : CHECK(!name || (strnlen(name, RTE_SWX_NAME_SIZE) < RTE_SWX_NAME_SIZE), EINVAL);
10485 : :
10486 : : /* Memory allocation. */
10487 : 0 : pipeline = calloc(1, sizeof(struct rte_swx_pipeline));
10488 [ # # ]: 0 : if (!pipeline) {
10489 : : status = -ENOMEM;
10490 : 0 : goto error;
10491 : : }
10492 : :
10493 : : /* Initialization. */
10494 [ # # ]: 0 : if (name)
10495 : 0 : strcpy(pipeline->name, name);
10496 : :
10497 : 0 : TAILQ_INIT(&pipeline->struct_types);
10498 : 0 : TAILQ_INIT(&pipeline->port_in_types);
10499 : 0 : TAILQ_INIT(&pipeline->ports_in);
10500 : 0 : TAILQ_INIT(&pipeline->port_out_types);
10501 : 0 : TAILQ_INIT(&pipeline->ports_out);
10502 : 0 : TAILQ_INIT(&pipeline->extern_types);
10503 : 0 : TAILQ_INIT(&pipeline->extern_objs);
10504 : 0 : TAILQ_INIT(&pipeline->extern_funcs);
10505 : 0 : TAILQ_INIT(&pipeline->hash_funcs);
10506 : 0 : TAILQ_INIT(&pipeline->rss);
10507 : 0 : TAILQ_INIT(&pipeline->headers);
10508 : 0 : TAILQ_INIT(&pipeline->actions);
10509 : 0 : TAILQ_INIT(&pipeline->table_types);
10510 : 0 : TAILQ_INIT(&pipeline->tables);
10511 : 0 : TAILQ_INIT(&pipeline->selectors);
10512 : 0 : TAILQ_INIT(&pipeline->learners);
10513 : 0 : TAILQ_INIT(&pipeline->regarrays);
10514 : 0 : TAILQ_INIT(&pipeline->meter_profiles);
10515 : 0 : TAILQ_INIT(&pipeline->metarrays);
10516 : :
10517 : 0 : pipeline->n_structs = 1; /* Struct 0 is reserved for action_data. */
10518 : 0 : pipeline->n_mirroring_slots = RTE_SWX_PACKET_MIRRORING_SLOTS_DEFAULT;
10519 : 0 : pipeline->n_mirroring_sessions = RTE_SWX_PACKET_MIRRORING_SESSIONS_DEFAULT;
10520 : 0 : pipeline->numa_node = numa_node;
10521 : :
10522 : 0 : status = port_in_types_register(pipeline);
10523 [ # # ]: 0 : if (status)
10524 : 0 : goto error;
10525 : :
10526 : 0 : status = port_out_types_register(pipeline);
10527 [ # # ]: 0 : if (status)
10528 : 0 : goto error;
10529 : :
10530 : 0 : status = table_types_register(pipeline);
10531 [ # # ]: 0 : if (status)
10532 : 0 : goto error;
10533 : :
10534 : 0 : status = hash_funcs_register(pipeline);
10535 [ # # ]: 0 : if (status)
10536 : 0 : goto error;
10537 : :
10538 [ # # ]: 0 : if (pipeline->name[0]) {
10539 : 0 : status = pipeline_register(pipeline);
10540 [ # # ]: 0 : if (status)
10541 : 0 : goto error;
10542 : : }
10543 : :
10544 : 0 : *p = pipeline;
10545 : 0 : return 0;
10546 : :
10547 : 0 : error:
10548 : 0 : rte_swx_pipeline_free(pipeline);
10549 : 0 : return status;
10550 : : }
10551 : :
10552 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_pipeline_instructions_config, 20.11)
10553 : : int
10554 : 0 : rte_swx_pipeline_instructions_config(struct rte_swx_pipeline *p,
10555 : : const char **instructions,
10556 : : uint32_t n_instructions)
10557 : : {
10558 : : int err;
10559 : : uint32_t i;
10560 : :
10561 : 0 : err = instruction_config(p, NULL, instructions, n_instructions);
10562 [ # # ]: 0 : if (err)
10563 : : return err;
10564 : :
10565 : : /* Thread instruction pointer reset. */
10566 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
10567 : : struct thread *t = &p->threads[i];
10568 : :
10569 : : thread_ip_reset(p, t);
10570 : : }
10571 : :
10572 : : return 0;
10573 : : }
10574 : :
10575 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_pipeline_build, 20.11)
10576 : : int
10577 : 0 : rte_swx_pipeline_build(struct rte_swx_pipeline *p)
10578 : : {
10579 : 0 : struct rte_swx_port_sink_params drop_port_params = {
10580 : : .file_name = NULL,
10581 : : };
10582 : : int status;
10583 : :
10584 [ # # ]: 0 : CHECK(p, EINVAL);
10585 [ # # ]: 0 : CHECK(p->build_done == 0, EEXIST);
10586 : :
10587 : 0 : status = port_in_build(p);
10588 [ # # ]: 0 : if (status)
10589 : 0 : goto error;
10590 : :
10591 : : /* Drop port. */
10592 : 0 : status = rte_swx_pipeline_port_out_config(p,
10593 : : p->n_ports_out,
10594 : : "sink",
10595 : : &drop_port_params);
10596 [ # # ]: 0 : if (status)
10597 : 0 : goto error;
10598 : :
10599 : 0 : status = port_out_build(p);
10600 [ # # ]: 0 : if (status)
10601 : 0 : goto error;
10602 : :
10603 : 0 : status = mirroring_build(p);
10604 [ # # ]: 0 : if (status)
10605 : 0 : goto error;
10606 : :
10607 : 0 : status = struct_build(p);
10608 [ # # ]: 0 : if (status)
10609 : 0 : goto error;
10610 : :
10611 : 0 : status = extern_obj_build(p);
10612 [ # # ]: 0 : if (status)
10613 : 0 : goto error;
10614 : :
10615 : 0 : status = extern_func_build(p);
10616 [ # # ]: 0 : if (status)
10617 : 0 : goto error;
10618 : :
10619 : 0 : status = hash_func_build(p);
10620 [ # # ]: 0 : if (status)
10621 : 0 : goto error;
10622 : :
10623 : 0 : status = rss_build(p);
10624 [ # # ]: 0 : if (status)
10625 : 0 : goto error;
10626 : :
10627 : 0 : status = header_build(p);
10628 [ # # ]: 0 : if (status)
10629 : 0 : goto error;
10630 : :
10631 : 0 : status = metadata_build(p);
10632 [ # # ]: 0 : if (status)
10633 : 0 : goto error;
10634 : :
10635 : 0 : status = instruction_table_build(p);
10636 [ # # ]: 0 : if (status)
10637 : 0 : goto error;
10638 : :
10639 : 0 : status = action_build(p);
10640 [ # # ]: 0 : if (status)
10641 : 0 : goto error;
10642 : :
10643 : 0 : status = table_build(p);
10644 [ # # ]: 0 : if (status)
10645 : 0 : goto error;
10646 : :
10647 : 0 : status = selector_build(p);
10648 [ # # ]: 0 : if (status)
10649 : 0 : goto error;
10650 : :
10651 : 0 : status = learner_build(p);
10652 [ # # ]: 0 : if (status)
10653 : 0 : goto error;
10654 : :
10655 : 0 : status = table_state_build(p);
10656 [ # # ]: 0 : if (status)
10657 : 0 : goto error;
10658 : :
10659 : 0 : status = regarray_build(p);
10660 [ # # ]: 0 : if (status)
10661 : 0 : goto error;
10662 : :
10663 : 0 : status = metarray_build(p);
10664 [ # # ]: 0 : if (status)
10665 : 0 : goto error;
10666 : :
10667 : 0 : p->build_done = 1;
10668 : :
10669 : 0 : return 0;
10670 : :
10671 : 0 : error:
10672 : 0 : metarray_build_free(p);
10673 : 0 : regarray_build_free(p);
10674 : 0 : table_state_build_free(p);
10675 : 0 : learner_build_free(p);
10676 : 0 : selector_build_free(p);
10677 : 0 : table_build_free(p);
10678 : : action_build_free(p);
10679 : : instruction_table_build_free(p);
10680 : : metadata_build_free(p);
10681 : 0 : header_build_free(p);
10682 : 0 : rss_build_free(p);
10683 : : hash_func_build_free(p);
10684 : 0 : extern_func_build_free(p);
10685 : 0 : extern_obj_build_free(p);
10686 : 0 : mirroring_build_free(p);
10687 : : port_out_build_free(p);
10688 : : port_in_build_free(p);
10689 : : struct_build_free(p);
10690 : :
10691 : : return status;
10692 : : }
10693 : :
10694 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_pipeline_run, 20.11)
10695 : : void
10696 : 0 : rte_swx_pipeline_run(struct rte_swx_pipeline *p, uint32_t n_instructions)
10697 : : {
10698 : : uint32_t i;
10699 : :
10700 [ # # ]: 0 : for (i = 0; i < n_instructions; i++)
10701 : : instr_exec(p);
10702 : 0 : }
10703 : :
10704 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_pipeline_flush, 20.11)
10705 : : void
10706 : 0 : rte_swx_pipeline_flush(struct rte_swx_pipeline *p)
10707 : : {
10708 : : uint32_t i;
10709 : :
10710 [ # # ]: 0 : for (i = 0; i < p->n_ports_out; i++) {
10711 : 0 : struct port_out_runtime *port = &p->out[i];
10712 : :
10713 [ # # ]: 0 : if (port->flush)
10714 : 0 : port->flush(port->obj);
10715 : : }
10716 : 0 : }
10717 : :
10718 : : /*
10719 : : * Control.
10720 : : */
10721 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_pipeline_info_get, 20.11)
10722 : : int
10723 : 0 : rte_swx_ctl_pipeline_info_get(struct rte_swx_pipeline *p,
10724 : : struct rte_swx_ctl_pipeline_info *pipeline)
10725 : : {
10726 : : struct action *action;
10727 : : struct table *table;
10728 : : uint32_t n_actions = 0, n_tables = 0;
10729 : :
10730 [ # # ]: 0 : if (!p || !pipeline)
10731 : : return -EINVAL;
10732 : :
10733 [ # # ]: 0 : TAILQ_FOREACH(action, &p->actions, node)
10734 : 0 : n_actions++;
10735 : :
10736 [ # # ]: 0 : TAILQ_FOREACH(table, &p->tables, node)
10737 : 0 : n_tables++;
10738 : :
10739 : 0 : strcpy(pipeline->name, p->name);
10740 : 0 : pipeline->n_ports_in = p->n_ports_in;
10741 : 0 : pipeline->n_ports_out = p->n_ports_out;
10742 : 0 : pipeline->n_mirroring_slots = p->n_mirroring_slots;
10743 : 0 : pipeline->n_mirroring_sessions = p->n_mirroring_sessions;
10744 : 0 : pipeline->n_actions = n_actions;
10745 : 0 : pipeline->n_tables = n_tables;
10746 : 0 : pipeline->n_selectors = p->n_selectors;
10747 : 0 : pipeline->n_learners = p->n_learners;
10748 : 0 : pipeline->n_regarrays = p->n_regarrays;
10749 : 0 : pipeline->n_metarrays = p->n_metarrays;
10750 : 0 : pipeline->n_rss = p->n_rss;
10751 : :
10752 : 0 : return 0;
10753 : : }
10754 : :
10755 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_pipeline_numa_node_get, 20.11)
10756 : : int
10757 : 0 : rte_swx_ctl_pipeline_numa_node_get(struct rte_swx_pipeline *p, int *numa_node)
10758 : : {
10759 [ # # ]: 0 : if (!p || !numa_node)
10760 : : return -EINVAL;
10761 : :
10762 : 0 : *numa_node = p->numa_node;
10763 : 0 : return 0;
10764 : : }
10765 : :
10766 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_action_info_get, 20.11)
10767 : : int
10768 : 0 : rte_swx_ctl_action_info_get(struct rte_swx_pipeline *p,
10769 : : uint32_t action_id,
10770 : : struct rte_swx_ctl_action_info *action)
10771 : : {
10772 : : struct action *a = NULL;
10773 : :
10774 [ # # # # : 0 : if (!p || (action_id >= p->n_actions) || !action)
# # ]
10775 : : return -EINVAL;
10776 : :
10777 : : a = action_find_by_id(p, action_id);
10778 [ # # ]: 0 : if (!a)
10779 : : return -EINVAL;
10780 : :
10781 [ # # ]: 0 : strcpy(action->name, a->name);
10782 [ # # ]: 0 : action->n_args = a->st ? a->st->n_fields : 0;
10783 : 0 : return 0;
10784 : : }
10785 : :
10786 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_action_arg_info_get, 20.11)
10787 : : int
10788 : 0 : rte_swx_ctl_action_arg_info_get(struct rte_swx_pipeline *p,
10789 : : uint32_t action_id,
10790 : : uint32_t action_arg_id,
10791 : : struct rte_swx_ctl_action_arg_info *action_arg)
10792 : : {
10793 : : struct action *a = NULL;
10794 : : struct field *arg = NULL;
10795 : :
10796 [ # # # # : 0 : if (!p || (action_id >= p->n_actions) || !action_arg)
# # ]
10797 : : return -EINVAL;
10798 : :
10799 : : a = action_find_by_id(p, action_id);
10800 [ # # # # : 0 : if (!a || !a->st || (action_arg_id >= a->st->n_fields))
# # ]
10801 : : return -EINVAL;
10802 : :
10803 : 0 : arg = &a->st->fields[action_arg_id];
10804 : 0 : strcpy(action_arg->name, arg->name);
10805 : 0 : action_arg->n_bits = arg->n_bits;
10806 : 0 : action_arg->is_network_byte_order = a->args_endianness[action_arg_id];
10807 : :
10808 : 0 : return 0;
10809 : : }
10810 : :
10811 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_table_info_get, 20.11)
10812 : : int
10813 : 0 : rte_swx_ctl_table_info_get(struct rte_swx_pipeline *p,
10814 : : uint32_t table_id,
10815 : : struct rte_swx_ctl_table_info *table)
10816 : : {
10817 : : struct table *t = NULL;
10818 : :
10819 [ # # ]: 0 : if (!p || !table)
10820 : : return -EINVAL;
10821 : :
10822 : : t = table_find_by_id(p, table_id);
10823 [ # # ]: 0 : if (!t)
10824 : : return -EINVAL;
10825 : :
10826 [ # # ]: 0 : strcpy(table->name, t->name);
10827 : 0 : strcpy(table->args, t->args);
10828 : 0 : table->n_match_fields = t->n_fields;
10829 : 0 : table->n_actions = t->n_actions;
10830 : 0 : table->default_action_is_const = t->default_action_is_const;
10831 [ # # ]: 0 : table->hash_func = t->hf ? t->hf->func : NULL;
10832 : 0 : table->size = t->size;
10833 : 0 : return 0;
10834 : : }
10835 : :
10836 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_table_match_field_info_get, 20.11)
10837 : : int
10838 : 0 : rte_swx_ctl_table_match_field_info_get(struct rte_swx_pipeline *p,
10839 : : uint32_t table_id,
10840 : : uint32_t match_field_id,
10841 : : struct rte_swx_ctl_table_match_field_info *match_field)
10842 : : {
10843 : : struct table *t;
10844 : : struct match_field *f;
10845 : :
10846 [ # # # # : 0 : if (!p || (table_id >= p->n_tables) || !match_field)
# # ]
10847 : : return -EINVAL;
10848 : :
10849 : : t = table_find_by_id(p, table_id);
10850 [ # # # # ]: 0 : if (!t || (match_field_id >= t->n_fields))
10851 : : return -EINVAL;
10852 : :
10853 : 0 : f = &t->fields[match_field_id];
10854 : 0 : match_field->match_type = f->match_type;
10855 : 0 : match_field->is_header = t->header ? 1 : 0;
10856 : 0 : match_field->n_bits = f->field->n_bits;
10857 : 0 : match_field->offset = f->field->offset;
10858 : :
10859 : 0 : return 0;
10860 : : }
10861 : :
10862 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_table_action_info_get, 20.11)
10863 : : int
10864 : 0 : rte_swx_ctl_table_action_info_get(struct rte_swx_pipeline *p,
10865 : : uint32_t table_id,
10866 : : uint32_t table_action_id,
10867 : : struct rte_swx_ctl_table_action_info *table_action)
10868 : : {
10869 : : struct table *t;
10870 : :
10871 [ # # # # : 0 : if (!p || (table_id >= p->n_tables) || !table_action)
# # ]
10872 : : return -EINVAL;
10873 : :
10874 : : t = table_find_by_id(p, table_id);
10875 [ # # # # ]: 0 : if (!t || (table_action_id >= t->n_actions))
10876 : : return -EINVAL;
10877 : :
10878 : 0 : table_action->action_id = t->actions[table_action_id]->id;
10879 : :
10880 : 0 : table_action->action_is_for_table_entries = t->action_is_for_table_entries[table_action_id];
10881 : 0 : table_action->action_is_for_default_entry = t->action_is_for_default_entry[table_action_id];
10882 : :
10883 : 0 : return 0;
10884 : : }
10885 : :
10886 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_table_ops_get, 20.11)
10887 : : int
10888 : 0 : rte_swx_ctl_table_ops_get(struct rte_swx_pipeline *p,
10889 : : uint32_t table_id,
10890 : : struct rte_swx_table_ops *table_ops,
10891 : : int *is_stub)
10892 : : {
10893 : : struct table *t;
10894 : :
10895 [ # # # # ]: 0 : if (!p || (table_id >= p->n_tables))
10896 : : return -EINVAL;
10897 : :
10898 : : t = table_find_by_id(p, table_id);
10899 [ # # ]: 0 : if (!t)
10900 : : return -EINVAL;
10901 : :
10902 [ # # ]: 0 : if (t->type) {
10903 [ # # ]: 0 : if (table_ops)
10904 : 0 : memcpy(table_ops, &t->type->ops, sizeof(*table_ops));
10905 : 0 : *is_stub = 0;
10906 : : } else {
10907 : 0 : *is_stub = 1;
10908 : : }
10909 : :
10910 : : return 0;
10911 : : }
10912 : :
10913 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_selector_info_get, 21.08)
10914 : : int
10915 : 0 : rte_swx_ctl_selector_info_get(struct rte_swx_pipeline *p,
10916 : : uint32_t selector_id,
10917 : : struct rte_swx_ctl_selector_info *selector)
10918 : : {
10919 : : struct selector *s = NULL;
10920 : :
10921 [ # # ]: 0 : if (!p || !selector)
10922 : : return -EINVAL;
10923 : :
10924 : : s = selector_find_by_id(p, selector_id);
10925 [ # # ]: 0 : if (!s)
10926 : : return -EINVAL;
10927 : :
10928 : 0 : strcpy(selector->name, s->name);
10929 : :
10930 : 0 : selector->n_selector_fields = s->n_selector_fields;
10931 : 0 : selector->n_groups_max = s->n_groups_max;
10932 : 0 : selector->n_members_per_group_max = s->n_members_per_group_max;
10933 : :
10934 : 0 : return 0;
10935 : : }
10936 : :
10937 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_selector_group_id_field_info_get, 21.08)
10938 : : int
10939 : 0 : rte_swx_ctl_selector_group_id_field_info_get(struct rte_swx_pipeline *p,
10940 : : uint32_t selector_id,
10941 : : struct rte_swx_ctl_table_match_field_info *field)
10942 : : {
10943 : : struct selector *s;
10944 : :
10945 [ # # # # : 0 : if (!p || (selector_id >= p->n_selectors) || !field)
# # ]
10946 : : return -EINVAL;
10947 : :
10948 : : s = selector_find_by_id(p, selector_id);
10949 [ # # ]: 0 : if (!s)
10950 : : return -EINVAL;
10951 : :
10952 : 0 : field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10953 : 0 : field->is_header = 0;
10954 : 0 : field->n_bits = s->group_id_field->n_bits;
10955 : 0 : field->offset = s->group_id_field->offset;
10956 : :
10957 : 0 : return 0;
10958 : : }
10959 : :
10960 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_selector_field_info_get, 21.08)
10961 : : int
10962 : 0 : rte_swx_ctl_selector_field_info_get(struct rte_swx_pipeline *p,
10963 : : uint32_t selector_id,
10964 : : uint32_t selector_field_id,
10965 : : struct rte_swx_ctl_table_match_field_info *field)
10966 : : {
10967 : : struct selector *s;
10968 : : struct field *f;
10969 : :
10970 [ # # # # : 0 : if (!p || (selector_id >= p->n_selectors) || !field)
# # ]
10971 : : return -EINVAL;
10972 : :
10973 : : s = selector_find_by_id(p, selector_id);
10974 [ # # # # ]: 0 : if (!s || (selector_field_id >= s->n_selector_fields))
10975 : : return -EINVAL;
10976 : :
10977 : 0 : f = s->selector_fields[selector_field_id];
10978 : 0 : field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10979 : 0 : field->is_header = s->selector_header ? 1 : 0;
10980 : 0 : field->n_bits = f->n_bits;
10981 : 0 : field->offset = f->offset;
10982 : :
10983 : 0 : return 0;
10984 : : }
10985 : :
10986 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_selector_member_id_field_info_get, 21.08)
10987 : : int
10988 : 0 : rte_swx_ctl_selector_member_id_field_info_get(struct rte_swx_pipeline *p,
10989 : : uint32_t selector_id,
10990 : : struct rte_swx_ctl_table_match_field_info *field)
10991 : : {
10992 : : struct selector *s;
10993 : :
10994 [ # # # # : 0 : if (!p || (selector_id >= p->n_selectors) || !field)
# # ]
10995 : : return -EINVAL;
10996 : :
10997 : : s = selector_find_by_id(p, selector_id);
10998 [ # # ]: 0 : if (!s)
10999 : : return -EINVAL;
11000 : :
11001 : 0 : field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
11002 : 0 : field->is_header = 0;
11003 : 0 : field->n_bits = s->member_id_field->n_bits;
11004 : 0 : field->offset = s->member_id_field->offset;
11005 : :
11006 : 0 : return 0;
11007 : : }
11008 : :
11009 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_learner_info_get, 21.11)
11010 : : int
11011 : 0 : rte_swx_ctl_learner_info_get(struct rte_swx_pipeline *p,
11012 : : uint32_t learner_id,
11013 : : struct rte_swx_ctl_learner_info *learner)
11014 : : {
11015 : : struct learner *l = NULL;
11016 : :
11017 [ # # ]: 0 : if (!p || !learner)
11018 : : return -EINVAL;
11019 : :
11020 : : l = learner_find_by_id(p, learner_id);
11021 [ # # ]: 0 : if (!l)
11022 : : return -EINVAL;
11023 : :
11024 : 0 : strcpy(learner->name, l->name);
11025 : :
11026 : 0 : learner->n_match_fields = l->n_fields;
11027 : 0 : learner->n_actions = l->n_actions;
11028 : 0 : learner->default_action_is_const = l->default_action_is_const;
11029 : 0 : learner->size = l->size;
11030 : 0 : learner->n_key_timeouts = l->n_timeouts;
11031 : :
11032 : 0 : return 0;
11033 : : }
11034 : :
11035 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_learner_match_field_info_get, 21.11)
11036 : : int
11037 : 0 : rte_swx_ctl_learner_match_field_info_get(struct rte_swx_pipeline *p,
11038 : : uint32_t learner_id,
11039 : : uint32_t match_field_id,
11040 : : struct rte_swx_ctl_table_match_field_info *match_field)
11041 : : {
11042 : : struct learner *l;
11043 : : struct field *f;
11044 : :
11045 [ # # # # : 0 : if (!p || (learner_id >= p->n_learners) || !match_field)
# # ]
11046 : : return -EINVAL;
11047 : :
11048 : : l = learner_find_by_id(p, learner_id);
11049 [ # # # # ]: 0 : if (!l || (match_field_id >= l->n_fields))
11050 : : return -EINVAL;
11051 : :
11052 : 0 : f = l->fields[match_field_id];
11053 : 0 : match_field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
11054 : 0 : match_field->is_header = l->header ? 1 : 0;
11055 : 0 : match_field->n_bits = f->n_bits;
11056 : 0 : match_field->offset = f->offset;
11057 : :
11058 : 0 : return 0;
11059 : : }
11060 : :
11061 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_learner_action_info_get, 21.11)
11062 : : int
11063 : 0 : rte_swx_ctl_learner_action_info_get(struct rte_swx_pipeline *p,
11064 : : uint32_t learner_id,
11065 : : uint32_t learner_action_id,
11066 : : struct rte_swx_ctl_table_action_info *learner_action)
11067 : : {
11068 : : struct learner *l;
11069 : :
11070 [ # # # # : 0 : if (!p || (learner_id >= p->n_learners) || !learner_action)
# # ]
11071 : : return -EINVAL;
11072 : :
11073 : : l = learner_find_by_id(p, learner_id);
11074 [ # # # # ]: 0 : if (!l || (learner_action_id >= l->n_actions))
11075 : : return -EINVAL;
11076 : :
11077 : 0 : learner_action->action_id = l->actions[learner_action_id]->id;
11078 : :
11079 : 0 : learner_action->action_is_for_table_entries =
11080 : 0 : l->action_is_for_table_entries[learner_action_id];
11081 : :
11082 : 0 : learner_action->action_is_for_default_entry =
11083 : 0 : l->action_is_for_default_entry[learner_action_id];
11084 : :
11085 : 0 : return 0;
11086 : : }
11087 : :
11088 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_pipeline_learner_timeout_get, 22.07)
11089 : : int
11090 : 0 : rte_swx_ctl_pipeline_learner_timeout_get(struct rte_swx_pipeline *p,
11091 : : uint32_t learner_id,
11092 : : uint32_t timeout_id,
11093 : : uint32_t *timeout)
11094 : : {
11095 : : struct learner *l;
11096 : :
11097 [ # # # # : 0 : if (!p || (learner_id >= p->n_learners) || !timeout)
# # ]
11098 : : return -EINVAL;
11099 : :
11100 : : l = learner_find_by_id(p, learner_id);
11101 [ # # # # ]: 0 : if (!l || (timeout_id >= l->n_timeouts))
11102 : : return -EINVAL;
11103 : :
11104 : 0 : *timeout = l->timeout[timeout_id];
11105 : 0 : return 0;
11106 : : }
11107 : :
11108 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_pipeline_learner_timeout_set, 22.07)
11109 : : int
11110 : 0 : rte_swx_ctl_pipeline_learner_timeout_set(struct rte_swx_pipeline *p,
11111 : : uint32_t learner_id,
11112 : : uint32_t timeout_id,
11113 : : uint32_t timeout)
11114 : : {
11115 : : struct learner *l;
11116 : : struct rte_swx_table_state *ts;
11117 : : int status;
11118 : :
11119 [ # # # # : 0 : if (!p || (learner_id >= p->n_learners) || !timeout)
# # ]
11120 : : return -EINVAL;
11121 : :
11122 : : l = learner_find_by_id(p, learner_id);
11123 [ # # # # ]: 0 : if (!l || (timeout_id >= l->n_timeouts))
11124 : : return -EINVAL;
11125 : :
11126 [ # # ]: 0 : if (!p->build_done)
11127 : : return -EINVAL;
11128 : :
11129 : 0 : ts = &p->table_state[p->n_tables + p->n_selectors + l->id];
11130 : :
11131 : 0 : status = rte_swx_table_learner_timeout_update(ts->obj, timeout_id, timeout);
11132 [ # # ]: 0 : if (status)
11133 : : return -EINVAL;
11134 : :
11135 : 0 : l->timeout[timeout_id] = timeout;
11136 : :
11137 : 0 : return 0;
11138 : : }
11139 : :
11140 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_pipeline_table_state_get, 20.11)
11141 : : int
11142 : 0 : rte_swx_pipeline_table_state_get(struct rte_swx_pipeline *p,
11143 : : struct rte_swx_table_state **table_state)
11144 : : {
11145 [ # # # # ]: 0 : if (!p || !table_state || !p->build_done)
11146 : : return -EINVAL;
11147 : :
11148 : 0 : *table_state = p->table_state;
11149 : 0 : return 0;
11150 : : }
11151 : :
11152 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_pipeline_table_state_set, 20.11)
11153 : : int
11154 : 0 : rte_swx_pipeline_table_state_set(struct rte_swx_pipeline *p,
11155 : : struct rte_swx_table_state *table_state)
11156 : : {
11157 [ # # # # ]: 0 : if (!p || !table_state || !p->build_done)
11158 : : return -EINVAL;
11159 : :
11160 : 0 : p->table_state = table_state;
11161 : 0 : return 0;
11162 : : }
11163 : :
11164 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_pipeline_port_in_stats_read, 20.11)
11165 : : int
11166 : 0 : rte_swx_ctl_pipeline_port_in_stats_read(struct rte_swx_pipeline *p,
11167 : : uint32_t port_id,
11168 : : struct rte_swx_port_in_stats *stats)
11169 : : {
11170 : : struct port_in *port;
11171 : :
11172 [ # # ]: 0 : if (!p || !stats)
11173 : : return -EINVAL;
11174 : :
11175 : : port = port_in_find(p, port_id);
11176 [ # # ]: 0 : if (!port)
11177 : : return -EINVAL;
11178 : :
11179 : 0 : port->type->ops.stats_read(port->obj, stats);
11180 : 0 : return 0;
11181 : : }
11182 : :
11183 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_pipeline_port_out_stats_read, 20.11)
11184 : : int
11185 : 0 : rte_swx_ctl_pipeline_port_out_stats_read(struct rte_swx_pipeline *p,
11186 : : uint32_t port_id,
11187 : : struct rte_swx_port_out_stats *stats)
11188 : : {
11189 : : struct port_out *port;
11190 : :
11191 [ # # ]: 0 : if (!p || !stats)
11192 : : return -EINVAL;
11193 : :
11194 : : port = port_out_find(p, port_id);
11195 [ # # ]: 0 : if (!port)
11196 : : return -EINVAL;
11197 : :
11198 : 0 : port->type->ops.stats_read(port->obj, stats);
11199 : 0 : return 0;
11200 : : }
11201 : :
11202 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_pipeline_table_stats_read, 21.05)
11203 : : int
11204 : 0 : rte_swx_ctl_pipeline_table_stats_read(struct rte_swx_pipeline *p,
11205 : : const char *table_name,
11206 : : struct rte_swx_table_stats *stats)
11207 : : {
11208 : : struct table *table;
11209 : : struct table_statistics *table_stats;
11210 : :
11211 [ # # # # : 0 : if (!p || !table_name || !table_name[0] || !stats || !stats->n_pkts_action)
# # # # ]
11212 : : return -EINVAL;
11213 : :
11214 : : table = table_find(p, table_name);
11215 [ # # ]: 0 : if (!table)
11216 : : return -EINVAL;
11217 : :
11218 : 0 : table_stats = &p->table_stats[table->id];
11219 : :
11220 : 0 : memcpy(stats->n_pkts_action,
11221 : 0 : table_stats->n_pkts_action,
11222 : 0 : p->n_actions * sizeof(uint64_t));
11223 : :
11224 : 0 : stats->n_pkts_hit = table_stats->n_pkts_hit[1];
11225 : 0 : stats->n_pkts_miss = table_stats->n_pkts_hit[0];
11226 : :
11227 : 0 : return 0;
11228 : : }
11229 : :
11230 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_pipeline_selector_stats_read, 21.08)
11231 : : int
11232 : 0 : rte_swx_ctl_pipeline_selector_stats_read(struct rte_swx_pipeline *p,
11233 : : const char *selector_name,
11234 : : struct rte_swx_pipeline_selector_stats *stats)
11235 : : {
11236 : : struct selector *s;
11237 : :
11238 [ # # # # : 0 : if (!p || !selector_name || !selector_name[0] || !stats)
# # ]
11239 : : return -EINVAL;
11240 : :
11241 : : s = selector_find(p, selector_name);
11242 [ # # ]: 0 : if (!s)
11243 : : return -EINVAL;
11244 : :
11245 : 0 : stats->n_pkts = p->selector_stats[s->id].n_pkts;
11246 : :
11247 : 0 : return 0;
11248 : : }
11249 : :
11250 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_pipeline_learner_stats_read, 21.11)
11251 : : int
11252 : 0 : rte_swx_ctl_pipeline_learner_stats_read(struct rte_swx_pipeline *p,
11253 : : const char *learner_name,
11254 : : struct rte_swx_learner_stats *stats)
11255 : : {
11256 : : struct learner *l;
11257 : : struct learner_statistics *learner_stats;
11258 : :
11259 [ # # # # : 0 : if (!p || !learner_name || !learner_name[0] || !stats || !stats->n_pkts_action)
# # # # ]
11260 : : return -EINVAL;
11261 : :
11262 : : l = learner_find(p, learner_name);
11263 [ # # ]: 0 : if (!l)
11264 : : return -EINVAL;
11265 : :
11266 : 0 : learner_stats = &p->learner_stats[l->id];
11267 : :
11268 : 0 : memcpy(stats->n_pkts_action,
11269 : 0 : learner_stats->n_pkts_action,
11270 : 0 : p->n_actions * sizeof(uint64_t));
11271 : :
11272 : 0 : stats->n_pkts_hit = learner_stats->n_pkts_hit[1];
11273 : 0 : stats->n_pkts_miss = learner_stats->n_pkts_hit[0];
11274 : :
11275 : 0 : stats->n_pkts_learn_ok = learner_stats->n_pkts_learn[0];
11276 : 0 : stats->n_pkts_learn_err = learner_stats->n_pkts_learn[1];
11277 : :
11278 : 0 : stats->n_pkts_rearm = learner_stats->n_pkts_rearm;
11279 : 0 : stats->n_pkts_forget = learner_stats->n_pkts_forget;
11280 : :
11281 : 0 : return 0;
11282 : : }
11283 : :
11284 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_regarray_info_get, 21.05)
11285 : : int
11286 : 0 : rte_swx_ctl_regarray_info_get(struct rte_swx_pipeline *p,
11287 : : uint32_t regarray_id,
11288 : : struct rte_swx_ctl_regarray_info *regarray)
11289 : : {
11290 : : struct regarray *r;
11291 : :
11292 [ # # ]: 0 : if (!p || !regarray)
11293 : : return -EINVAL;
11294 : :
11295 : : r = regarray_find_by_id(p, regarray_id);
11296 [ # # ]: 0 : if (!r)
11297 : : return -EINVAL;
11298 : :
11299 : 0 : strcpy(regarray->name, r->name);
11300 : 0 : regarray->size = r->size;
11301 : 0 : return 0;
11302 : : }
11303 : :
11304 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_pipeline_regarray_read, 21.05)
11305 : : int
11306 : 0 : rte_swx_ctl_pipeline_regarray_read(struct rte_swx_pipeline *p,
11307 : : const char *regarray_name,
11308 : : uint32_t regarray_index,
11309 : : uint64_t *value)
11310 : : {
11311 : : struct regarray *regarray;
11312 : : struct regarray_runtime *r;
11313 : :
11314 [ # # # # ]: 0 : if (!p || !regarray_name || !value)
11315 : : return -EINVAL;
11316 : :
11317 : : regarray = regarray_find(p, regarray_name);
11318 [ # # # # ]: 0 : if (!regarray || (regarray_index >= regarray->size))
11319 : : return -EINVAL;
11320 : :
11321 : 0 : r = &p->regarray_runtime[regarray->id];
11322 : 0 : *value = r->regarray[regarray_index];
11323 : 0 : return 0;
11324 : : }
11325 : :
11326 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_pipeline_regarray_write, 21.05)
11327 : : int
11328 : 0 : rte_swx_ctl_pipeline_regarray_write(struct rte_swx_pipeline *p,
11329 : : const char *regarray_name,
11330 : : uint32_t regarray_index,
11331 : : uint64_t value)
11332 : : {
11333 : : struct regarray *regarray;
11334 : : struct regarray_runtime *r;
11335 : :
11336 [ # # ]: 0 : if (!p || !regarray_name)
11337 : : return -EINVAL;
11338 : :
11339 : : regarray = regarray_find(p, regarray_name);
11340 [ # # # # ]: 0 : if (!regarray || (regarray_index >= regarray->size))
11341 : : return -EINVAL;
11342 : :
11343 : 0 : r = &p->regarray_runtime[regarray->id];
11344 : 0 : r->regarray[regarray_index] = value;
11345 : 0 : return 0;
11346 : : }
11347 : :
11348 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_metarray_info_get, 21.05)
11349 : : int
11350 : 0 : rte_swx_ctl_metarray_info_get(struct rte_swx_pipeline *p,
11351 : : uint32_t metarray_id,
11352 : : struct rte_swx_ctl_metarray_info *metarray)
11353 : : {
11354 : : struct metarray *m;
11355 : :
11356 [ # # ]: 0 : if (!p || !metarray)
11357 : : return -EINVAL;
11358 : :
11359 : : m = metarray_find_by_id(p, metarray_id);
11360 [ # # ]: 0 : if (!m)
11361 : : return -EINVAL;
11362 : :
11363 : 0 : strcpy(metarray->name, m->name);
11364 : 0 : metarray->size = m->size;
11365 : 0 : return 0;
11366 : : }
11367 : :
11368 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_meter_profile_add, 21.05)
11369 : : int
11370 : 0 : rte_swx_ctl_meter_profile_add(struct rte_swx_pipeline *p,
11371 : : const char *name,
11372 : : struct rte_meter_trtcm_params *params)
11373 : : {
11374 : : struct meter_profile *mp;
11375 : : int status;
11376 : :
11377 [ # # ]: 0 : CHECK(p, EINVAL);
11378 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
11379 [ # # ]: 0 : CHECK(params, EINVAL);
11380 [ # # ]: 0 : CHECK(!meter_profile_find(p, name), EEXIST);
11381 : :
11382 : : /* Node allocation. */
11383 : 0 : mp = calloc(1, sizeof(struct meter_profile));
11384 [ # # ]: 0 : CHECK(mp, ENOMEM);
11385 : :
11386 : : /* Node initialization. */
11387 : 0 : strcpy(mp->name, name);
11388 : 0 : memcpy(&mp->params, params, sizeof(struct rte_meter_trtcm_params));
11389 : 0 : status = rte_meter_trtcm_profile_config(&mp->profile, params);
11390 [ # # ]: 0 : if (status) {
11391 : 0 : free(mp);
11392 : 0 : CHECK(0, EINVAL);
11393 : : }
11394 : :
11395 : : /* Node add to tailq. */
11396 : 0 : TAILQ_INSERT_TAIL(&p->meter_profiles, mp, node);
11397 : :
11398 : 0 : return 0;
11399 : : }
11400 : :
11401 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_meter_profile_delete, 21.05)
11402 : : int
11403 : 0 : rte_swx_ctl_meter_profile_delete(struct rte_swx_pipeline *p,
11404 : : const char *name)
11405 : : {
11406 : : struct meter_profile *mp;
11407 : :
11408 [ # # ]: 0 : CHECK(p, EINVAL);
11409 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
11410 : :
11411 : : mp = meter_profile_find(p, name);
11412 [ # # ]: 0 : CHECK(mp, EINVAL);
11413 [ # # ]: 0 : CHECK(!mp->n_users, EBUSY);
11414 : :
11415 : : /* Remove node from tailq. */
11416 [ # # ]: 0 : TAILQ_REMOVE(&p->meter_profiles, mp, node);
11417 : 0 : free(mp);
11418 : :
11419 : 0 : return 0;
11420 : : }
11421 : :
11422 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_meter_reset, 21.05)
11423 : : int
11424 : 0 : rte_swx_ctl_meter_reset(struct rte_swx_pipeline *p,
11425 : : const char *metarray_name,
11426 : : uint32_t metarray_index)
11427 : : {
11428 : : struct meter_profile *mp_old;
11429 : : struct metarray *metarray;
11430 : : struct metarray_runtime *metarray_runtime;
11431 : : struct meter *m;
11432 : :
11433 [ # # ]: 0 : CHECK(p, EINVAL);
11434 [ # # # # : 0 : CHECK_NAME(metarray_name, EINVAL);
# # ]
11435 : :
11436 : : metarray = metarray_find(p, metarray_name);
11437 [ # # ]: 0 : CHECK(metarray, EINVAL);
11438 [ # # ]: 0 : CHECK(metarray_index < metarray->size, EINVAL);
11439 : :
11440 : 0 : metarray_runtime = &p->metarray_runtime[metarray->id];
11441 : 0 : m = &metarray_runtime->metarray[metarray_index];
11442 : 0 : mp_old = m->profile;
11443 : :
11444 : 0 : meter_init(m);
11445 : :
11446 : 0 : mp_old->n_users--;
11447 : :
11448 : 0 : return 0;
11449 : : }
11450 : :
11451 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_meter_set, 21.05)
11452 : : int
11453 : 0 : rte_swx_ctl_meter_set(struct rte_swx_pipeline *p,
11454 : : const char *metarray_name,
11455 : : uint32_t metarray_index,
11456 : : const char *profile_name)
11457 : : {
11458 : : struct meter_profile *mp, *mp_old;
11459 : : struct metarray *metarray;
11460 : : struct metarray_runtime *metarray_runtime;
11461 : : struct meter *m;
11462 : :
11463 [ # # ]: 0 : CHECK(p, EINVAL);
11464 [ # # # # : 0 : CHECK_NAME(metarray_name, EINVAL);
# # ]
11465 : :
11466 : : metarray = metarray_find(p, metarray_name);
11467 [ # # ]: 0 : CHECK(metarray, EINVAL);
11468 [ # # ]: 0 : CHECK(metarray_index < metarray->size, EINVAL);
11469 : :
11470 : : mp = meter_profile_find(p, profile_name);
11471 [ # # ]: 0 : CHECK(mp, EINVAL);
11472 : :
11473 : 0 : metarray_runtime = &p->metarray_runtime[metarray->id];
11474 : 0 : m = &metarray_runtime->metarray[metarray_index];
11475 : 0 : mp_old = m->profile;
11476 : :
11477 : : memset(m, 0, sizeof(struct meter));
11478 : 0 : rte_meter_trtcm_config(&m->m, &mp->profile);
11479 : 0 : m->profile = mp;
11480 : 0 : m->color_mask = RTE_COLORS;
11481 : :
11482 : 0 : mp->n_users++;
11483 : 0 : mp_old->n_users--;
11484 : :
11485 : 0 : return 0;
11486 : : }
11487 : :
11488 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_meter_stats_read, 21.05)
11489 : : int
11490 : 0 : rte_swx_ctl_meter_stats_read(struct rte_swx_pipeline *p,
11491 : : const char *metarray_name,
11492 : : uint32_t metarray_index,
11493 : : struct rte_swx_ctl_meter_stats *stats)
11494 : : {
11495 : : struct metarray *metarray;
11496 : : struct metarray_runtime *metarray_runtime;
11497 : : struct meter *m;
11498 : :
11499 [ # # ]: 0 : CHECK(p, EINVAL);
11500 [ # # # # : 0 : CHECK_NAME(metarray_name, EINVAL);
# # ]
11501 : :
11502 : : metarray = metarray_find(p, metarray_name);
11503 [ # # ]: 0 : CHECK(metarray, EINVAL);
11504 [ # # ]: 0 : CHECK(metarray_index < metarray->size, EINVAL);
11505 : :
11506 [ # # ]: 0 : CHECK(stats, EINVAL);
11507 : :
11508 : 0 : metarray_runtime = &p->metarray_runtime[metarray->id];
11509 : 0 : m = &metarray_runtime->metarray[metarray_index];
11510 : :
11511 : 0 : memcpy(stats->n_pkts, m->n_pkts, sizeof(m->n_pkts));
11512 : 0 : memcpy(stats->n_bytes, m->n_bytes, sizeof(m->n_bytes));
11513 : :
11514 : 0 : return 0;
11515 : : }
11516 : :
11517 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_pipeline_mirroring_session_set, 20.11)
11518 : : int
11519 : 0 : rte_swx_ctl_pipeline_mirroring_session_set(struct rte_swx_pipeline *p,
11520 : : uint32_t session_id,
11521 : : struct rte_swx_pipeline_mirroring_session_params *params)
11522 : : {
11523 : : struct mirroring_session *s;
11524 : :
11525 [ # # ]: 0 : CHECK(p, EINVAL);
11526 [ # # ]: 0 : CHECK(p->build_done, EEXIST);
11527 [ # # ]: 0 : CHECK(session_id < p->n_mirroring_sessions, EINVAL);
11528 [ # # ]: 0 : CHECK(params, EINVAL);
11529 [ # # ]: 0 : CHECK(params->port_id < p->n_ports_out, EINVAL);
11530 : :
11531 : 0 : s = &p->mirroring_sessions[session_id];
11532 : 0 : s->port_id = params->port_id;
11533 : 0 : s->fast_clone = params->fast_clone;
11534 [ # # ]: 0 : s->truncation_length = params->truncation_length ? params->truncation_length : UINT32_MAX;
11535 : :
11536 : 0 : return 0;
11537 : : }
11538 : :
11539 : : static int
11540 : 0 : rte_swx_ctl_pipeline_table_lookup(struct rte_swx_pipeline *p,
11541 : : const char *table_name,
11542 : : uint8_t *key,
11543 : : uint64_t *action_id,
11544 : : uint8_t **action_data,
11545 : : size_t *entry_id,
11546 : : int *hit)
11547 : : {
11548 : : struct table *t;
11549 : : void *mailbox = NULL;
11550 : :
11551 : : /* Check input arguments. */
11552 [ # # ]: 0 : if (!p ||
11553 [ # # # # ]: 0 : !p->build_done ||
11554 : 0 : !table_name ||
11555 [ # # ]: 0 : !table_name[0] ||
11556 : 0 : !key ||
11557 [ # # # # ]: 0 : !entry_id ||
11558 : : !hit)
11559 : : return -EINVAL;
11560 : :
11561 : : /* Find the table. */
11562 : : t = table_find(p, table_name);
11563 [ # # ]: 0 : if (!t)
11564 : : return -EINVAL;
11565 : :
11566 [ # # ]: 0 : if (!t->type) {
11567 : 0 : *hit = 0;
11568 : 0 : return 0;
11569 : : }
11570 : :
11571 : : /* Setup mailbox. */
11572 [ # # ]: 0 : if (t->type->ops.mailbox_size_get) {
11573 : : uint64_t mailbox_size;
11574 : :
11575 : 0 : mailbox_size = t->type->ops.mailbox_size_get();
11576 [ # # ]: 0 : if (mailbox_size) {
11577 : 0 : mailbox = calloc(1, mailbox_size);
11578 [ # # ]: 0 : if (!mailbox)
11579 : : return -ENOMEM;
11580 : : }
11581 : : }
11582 : :
11583 : : /* Table lookup operation. */
11584 : 0 : key -= table_params_offset_get(t);
11585 : :
11586 : : for ( ; ; ) {
11587 : 0 : struct rte_swx_table_state *ts = &p->table_state[t->id];
11588 : : int done;
11589 : :
11590 : 0 : done = t->type->ops.lkp(ts->obj,
11591 : : mailbox,
11592 : : &key,
11593 : : action_id,
11594 : : action_data,
11595 : : entry_id,
11596 : : hit);
11597 [ # # ]: 0 : if (done)
11598 : : break;
11599 : : }
11600 : :
11601 : : /* Free mailbox. */
11602 : 0 : free(mailbox);
11603 : :
11604 : 0 : return 0;
11605 : : }
11606 : :
11607 : : static int
11608 : 0 : rte_swx_ctl_pipeline_learner_lookup(struct rte_swx_pipeline *p,
11609 : : const char *learner_name,
11610 : : uint8_t *key,
11611 : : uint64_t *action_id,
11612 : : uint8_t **action_data,
11613 : : size_t *entry_id,
11614 : : int *hit)
11615 : : {
11616 : : struct learner *l;
11617 : : void *mailbox = NULL;
11618 : : uint64_t mailbox_size, time;
11619 : :
11620 : : /* Check input arguments. */
11621 [ # # ]: 0 : if (!p ||
11622 [ # # # # ]: 0 : !p->build_done ||
11623 : 0 : !learner_name ||
11624 [ # # ]: 0 : !learner_name[0] ||
11625 : 0 : !key ||
11626 [ # # # # ]: 0 : !entry_id ||
11627 : : !hit)
11628 : : return -EINVAL;
11629 : :
11630 : : /* Find the learner table. */
11631 : : l = learner_find(p, learner_name);
11632 [ # # ]: 0 : if (!l)
11633 : : return -EINVAL;
11634 : :
11635 : : /* Setup mailbox. */
11636 : 0 : mailbox_size = rte_swx_table_learner_mailbox_size_get();
11637 [ # # ]: 0 : if (mailbox_size) {
11638 : 0 : mailbox = calloc(1, mailbox_size);
11639 [ # # ]: 0 : if (!mailbox)
11640 : : return -ENOMEM;
11641 : : }
11642 : :
11643 : : /* Learner table lookup operation. */
11644 : 0 : key -= learner_params_offset_get(l);
11645 : :
11646 : : time = rte_get_tsc_cycles();
11647 : :
11648 : : for ( ; ; ) {
11649 : 0 : uint32_t pos = p->n_tables + p->n_selectors + l->id;
11650 : 0 : struct rte_swx_table_state *ts = &p->table_state[pos];
11651 : : int done;
11652 : :
11653 : 0 : done = rte_swx_table_learner_lookup(ts->obj,
11654 : : mailbox,
11655 : : time,
11656 : : &key,
11657 : : action_id,
11658 : : action_data,
11659 : : entry_id,
11660 : : hit);
11661 [ # # ]: 0 : if (done)
11662 : : break;
11663 : : }
11664 : :
11665 : : /* Free mailbox. */
11666 : 0 : free(mailbox);
11667 : :
11668 : 0 : return 0;
11669 : : }
11670 : :
11671 : : static int
11672 : 0 : rte_swx_ctl_pipeline_table_entry_id_get(struct rte_swx_pipeline *p,
11673 : : const char *table_name,
11674 : : uint8_t *table_key,
11675 : : size_t *table_entry_id)
11676 : : {
11677 : : struct table *t;
11678 : : struct learner *l;
11679 : : uint64_t action_id;
11680 : : uint8_t *action_data;
11681 : 0 : size_t entry_id = 0;
11682 : 0 : int hit = 0, status;
11683 : :
11684 : : /* Check input arguments. */
11685 [ # # ]: 0 : if (!p ||
11686 [ # # # # ]: 0 : !p->build_done ||
11687 : 0 : !table_name ||
11688 [ # # ]: 0 : !table_name[0] ||
11689 : 0 : !table_key ||
11690 [ # # ]: 0 : !table_entry_id)
11691 : : return -EINVAL;
11692 : :
11693 : : t = table_find(p, table_name);
11694 : : l = learner_find(p, table_name);
11695 [ # # ]: 0 : if (!t && !l)
11696 : : return -EINVAL;
11697 : :
11698 : : /* Table lookup operation. */
11699 [ # # ]: 0 : if (t)
11700 : 0 : status = rte_swx_ctl_pipeline_table_lookup(p,
11701 : : table_name,
11702 : : table_key,
11703 : : &action_id,
11704 : : &action_data,
11705 : : &entry_id,
11706 : : &hit);
11707 : : else
11708 : 0 : status = rte_swx_ctl_pipeline_learner_lookup(p,
11709 : : table_name,
11710 : : table_key,
11711 : : &action_id,
11712 : : &action_data,
11713 : : &entry_id,
11714 : : &hit);
11715 [ # # ]: 0 : if (status)
11716 : : return status;
11717 : :
11718 : : /* Reserve entry ID 0 for the table default entry. */
11719 [ # # ]: 0 : *table_entry_id = hit ? (1 + entry_id) : 0;
11720 : :
11721 : 0 : return 0;
11722 : : }
11723 : :
11724 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_pipeline_regarray_read_with_key, 22.11)
11725 : : int
11726 : 0 : rte_swx_ctl_pipeline_regarray_read_with_key(struct rte_swx_pipeline *p,
11727 : : const char *regarray_name,
11728 : : const char *table_name,
11729 : : uint8_t *table_key,
11730 : : uint64_t *value)
11731 : : {
11732 : 0 : size_t entry_id = 0;
11733 : : int status;
11734 : :
11735 : 0 : status = rte_swx_ctl_pipeline_table_entry_id_get(p, table_name, table_key, &entry_id);
11736 [ # # ]: 0 : if (status)
11737 : : return status;
11738 : :
11739 : 0 : return rte_swx_ctl_pipeline_regarray_read(p, regarray_name, entry_id, value);
11740 : : }
11741 : :
11742 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_pipeline_regarray_write_with_key, 22.11)
11743 : : int
11744 : 0 : rte_swx_ctl_pipeline_regarray_write_with_key(struct rte_swx_pipeline *p,
11745 : : const char *regarray_name,
11746 : : const char *table_name,
11747 : : uint8_t *table_key,
11748 : : uint64_t value)
11749 : : {
11750 : 0 : size_t entry_id = 0;
11751 : : int status;
11752 : :
11753 : 0 : status = rte_swx_ctl_pipeline_table_entry_id_get(p, table_name, table_key, &entry_id);
11754 [ # # ]: 0 : if (status)
11755 : : return status;
11756 : :
11757 : 0 : return rte_swx_ctl_pipeline_regarray_write(p, regarray_name, entry_id, value);
11758 : : }
11759 : :
11760 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_meter_reset_with_key, 22.11)
11761 : : int
11762 : 0 : rte_swx_ctl_meter_reset_with_key(struct rte_swx_pipeline *p,
11763 : : const char *metarray_name,
11764 : : const char *table_name,
11765 : : uint8_t *table_key)
11766 : : {
11767 : 0 : size_t entry_id = 0;
11768 : : int status;
11769 : :
11770 : 0 : status = rte_swx_ctl_pipeline_table_entry_id_get(p, table_name, table_key, &entry_id);
11771 [ # # ]: 0 : if (status)
11772 : : return status;
11773 : :
11774 : 0 : return rte_swx_ctl_meter_reset(p, metarray_name, entry_id);
11775 : : }
11776 : :
11777 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_meter_set_with_key, 22.11)
11778 : : int
11779 : 0 : rte_swx_ctl_meter_set_with_key(struct rte_swx_pipeline *p,
11780 : : const char *metarray_name,
11781 : : const char *table_name,
11782 : : uint8_t *table_key,
11783 : : const char *profile_name)
11784 : : {
11785 : 0 : size_t entry_id = 0;
11786 : : int status;
11787 : :
11788 : 0 : status = rte_swx_ctl_pipeline_table_entry_id_get(p, table_name, table_key, &entry_id);
11789 [ # # ]: 0 : if (status)
11790 : : return status;
11791 : :
11792 : 0 : return rte_swx_ctl_meter_set(p, metarray_name, entry_id, profile_name);
11793 : : }
11794 : :
11795 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_meter_stats_read_with_key, 22.11)
11796 : : int
11797 : 0 : rte_swx_ctl_meter_stats_read_with_key(struct rte_swx_pipeline *p,
11798 : : const char *metarray_name,
11799 : : const char *table_name,
11800 : : uint8_t *table_key,
11801 : : struct rte_swx_ctl_meter_stats *stats)
11802 : : {
11803 : 0 : size_t entry_id = 0;
11804 : : int status;
11805 : :
11806 : 0 : status = rte_swx_ctl_pipeline_table_entry_id_get(p, table_name, table_key, &entry_id);
11807 [ # # ]: 0 : if (status)
11808 : : return status;
11809 : :
11810 : 0 : return rte_swx_ctl_meter_stats_read(p, metarray_name, entry_id, stats);
11811 : : }
11812 : :
11813 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_rss_info_get, 23.03)
11814 : : int
11815 : 0 : rte_swx_ctl_rss_info_get(struct rte_swx_pipeline *p,
11816 : : uint32_t rss_obj_id,
11817 : : struct rte_swx_ctl_rss_info *info)
11818 : : {
11819 : : struct rss *rss;
11820 : :
11821 : : /* Check the input arguments. */
11822 [ # # ]: 0 : if (!p || !info)
11823 : : return -EINVAL;
11824 : :
11825 : : rss = rss_find_by_id(p, rss_obj_id);
11826 [ # # ]: 0 : if (!rss)
11827 : : return -EINVAL;
11828 : :
11829 : : /* Read from the internal data structures. */
11830 : 0 : strcpy(info->name, rss->name);
11831 : 0 : return 0;
11832 : : }
11833 : :
11834 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_pipeline_rss_key_size_read, 23.03)
11835 : : int
11836 : 0 : rte_swx_ctl_pipeline_rss_key_size_read(struct rte_swx_pipeline *p,
11837 : : const char *rss_name,
11838 : : uint32_t *key_size)
11839 : : {
11840 : : struct rss *rss;
11841 : : struct rss_runtime *r;
11842 : :
11843 : : /* Check the input arguments. */
11844 [ # # ]: 0 : CHECK(p, EINVAL);
11845 : :
11846 [ # # # # : 0 : CHECK_NAME(rss_name, EINVAL);
# # ]
11847 : : rss = rss_find(p, rss_name);
11848 [ # # ]: 0 : CHECK(rss, EINVAL);
11849 : 0 : r = p->rss_runtime[rss->id];
11850 : :
11851 [ # # ]: 0 : CHECK(key_size, EINVAL);
11852 : :
11853 : : /* Read from the internal data structures. */
11854 : 0 : *key_size = r->key_size;
11855 : :
11856 : 0 : return 0;
11857 : : }
11858 : :
11859 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_pipeline_rss_key_read, 23.03)
11860 : : int
11861 : 0 : rte_swx_ctl_pipeline_rss_key_read(struct rte_swx_pipeline *p,
11862 : : const char *rss_name,
11863 : : uint8_t *key)
11864 : : {
11865 : : struct rss *rss;
11866 : : struct rss_runtime *r;
11867 : :
11868 : : /* Check the input arguments. */
11869 [ # # ]: 0 : CHECK(p, EINVAL);
11870 : :
11871 [ # # # # : 0 : CHECK_NAME(rss_name, EINVAL);
# # ]
11872 : : rss = rss_find(p, rss_name);
11873 [ # # ]: 0 : CHECK(rss, EINVAL);
11874 : 0 : r = p->rss_runtime[rss->id];
11875 : :
11876 [ # # ]: 0 : CHECK(key, EINVAL);
11877 : :
11878 : : /* Read from the internal data structures. */
11879 : 0 : memcpy(key, r->key, r->key_size);
11880 : :
11881 : 0 : return 0;
11882 : : }
11883 : :
11884 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_ctl_pipeline_rss_key_write, 23.03)
11885 : : int
11886 : 0 : rte_swx_ctl_pipeline_rss_key_write(struct rte_swx_pipeline *p,
11887 : : const char *rss_name,
11888 : : uint32_t key_size,
11889 : : uint8_t *key)
11890 : : {
11891 : : struct rss *rss;
11892 : : struct rss_runtime *r, *r_new;
11893 : :
11894 : : /* Check the input arguments. */
11895 [ # # ]: 0 : CHECK(p, EINVAL);
11896 : :
11897 [ # # # # : 0 : CHECK_NAME(rss_name, EINVAL);
# # ]
11898 : : rss = rss_find(p, rss_name);
11899 [ # # ]: 0 : CHECK(rss, EINVAL);
11900 : 0 : r = p->rss_runtime[rss->id];
11901 : :
11902 [ # # ]: 0 : CHECK(key_size >= 4, EINVAL);
11903 [ # # ]: 0 : CHECK(key, EINVAL);
11904 : :
11905 : : /* Allocate new RSS run-time entry. */
11906 : 0 : r_new = malloc(sizeof(struct rss_runtime) + key_size * sizeof(uint32_t));
11907 [ # # ]: 0 : if (!r_new)
11908 : : return -ENOMEM;
11909 : :
11910 : : /* Fill in the new RSS run-time entry. */
11911 : 0 : r_new->key_size = key_size;
11912 : 0 : memcpy(r_new->key, key, key_size);
11913 : :
11914 : : /* Commit the RSS run-time change atomically. */
11915 : 0 : p->rss_runtime[rss->id] = r_new;
11916 : :
11917 : : /* Free the old RSS run-time entry. */
11918 : 0 : free(r);
11919 : :
11920 : 0 : return 0;
11921 : : }
11922 : :
11923 : : /*
11924 : : * Pipeline compilation.
11925 : : */
11926 : : static const char *
11927 : 0 : instr_type_to_name(struct instruction *instr)
11928 : : {
11929 [ # # # # : 0 : switch (instr->type) {
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
11930 : : case INSTR_RX: return "INSTR_RX";
11931 : :
11932 : 0 : case INSTR_TX: return "INSTR_TX";
11933 : 0 : case INSTR_TX_I: return "INSTR_TX_I";
11934 : 0 : case INSTR_DROP: return "INSTR_DROP";
11935 : 0 : case INSTR_MIRROR: return "INSTR_MIRROR";
11936 : 0 : case INSTR_RECIRCULATE: return "INSTR_RECIRCULATE";
11937 : 0 : case INSTR_RECIRCID: return "INSTR_RECIRCID";
11938 : :
11939 : 0 : case INSTR_HDR_EXTRACT: return "INSTR_HDR_EXTRACT";
11940 : 0 : case INSTR_HDR_EXTRACT2: return "INSTR_HDR_EXTRACT2";
11941 : 0 : case INSTR_HDR_EXTRACT3: return "INSTR_HDR_EXTRACT3";
11942 : 0 : case INSTR_HDR_EXTRACT4: return "INSTR_HDR_EXTRACT4";
11943 : 0 : case INSTR_HDR_EXTRACT5: return "INSTR_HDR_EXTRACT5";
11944 : 0 : case INSTR_HDR_EXTRACT6: return "INSTR_HDR_EXTRACT6";
11945 : 0 : case INSTR_HDR_EXTRACT7: return "INSTR_HDR_EXTRACT7";
11946 : 0 : case INSTR_HDR_EXTRACT8: return "INSTR_HDR_EXTRACT8";
11947 : :
11948 : 0 : case INSTR_HDR_EXTRACT_M: return "INSTR_HDR_EXTRACT_M";
11949 : :
11950 : 0 : case INSTR_HDR_LOOKAHEAD: return "INSTR_HDR_LOOKAHEAD";
11951 : :
11952 : 0 : case INSTR_HDR_EMIT: return "INSTR_HDR_EMIT";
11953 : 0 : case INSTR_HDR_EMIT_TX: return "INSTR_HDR_EMIT_TX";
11954 : 0 : case INSTR_HDR_EMIT2_TX: return "INSTR_HDR_EMIT2_TX";
11955 : 0 : case INSTR_HDR_EMIT3_TX: return "INSTR_HDR_EMIT3_TX";
11956 : 0 : case INSTR_HDR_EMIT4_TX: return "INSTR_HDR_EMIT4_TX";
11957 : 0 : case INSTR_HDR_EMIT5_TX: return "INSTR_HDR_EMIT5_TX";
11958 : 0 : case INSTR_HDR_EMIT6_TX: return "INSTR_HDR_EMIT6_TX";
11959 : 0 : case INSTR_HDR_EMIT7_TX: return "INSTR_HDR_EMIT7_TX";
11960 : 0 : case INSTR_HDR_EMIT8_TX: return "INSTR_HDR_EMIT8_TX";
11961 : :
11962 : 0 : case INSTR_HDR_VALIDATE: return "INSTR_HDR_VALIDATE";
11963 : 0 : case INSTR_HDR_INVALIDATE: return "INSTR_HDR_INVALIDATE";
11964 : :
11965 : 0 : case INSTR_MOV: return "INSTR_MOV";
11966 : 0 : case INSTR_MOV_MH: return "INSTR_MOV_MH";
11967 : 0 : case INSTR_MOV_HM: return "INSTR_MOV_HM";
11968 : 0 : case INSTR_MOV_HH: return "INSTR_MOV_HH";
11969 : 0 : case INSTR_MOV_DMA: return "INSTR_MOV_DMA";
11970 : 0 : case INSTR_MOV_128: return "INSTR_MOV_128";
11971 : 0 : case INSTR_MOV_128_64: return "INSTR_MOV_128_64";
11972 : 0 : case INSTR_MOV_64_128: return "INSTR_MOV_64_128";
11973 : 0 : case INSTR_MOV_128_32: return "INSTR_MOV_128_32";
11974 : 0 : case INSTR_MOV_32_128: return "INSTR_MOV_32_128";
11975 : 0 : case INSTR_MOV_I: return "INSTR_MOV_I";
11976 : :
11977 : 0 : case INSTR_MOVH: return "INSTR_MOVH";
11978 : :
11979 : 0 : case INSTR_DMA_HT: return "INSTR_DMA_HT";
11980 : 0 : case INSTR_DMA_HT2: return "INSTR_DMA_HT2";
11981 : 0 : case INSTR_DMA_HT3: return "INSTR_DMA_HT3";
11982 : 0 : case INSTR_DMA_HT4: return "INSTR_DMA_HT4";
11983 : 0 : case INSTR_DMA_HT5: return "INSTR_DMA_HT5";
11984 : 0 : case INSTR_DMA_HT6: return "INSTR_DMA_HT6";
11985 : 0 : case INSTR_DMA_HT7: return "INSTR_DMA_HT7";
11986 : 0 : case INSTR_DMA_HT8: return "INSTR_DMA_HT8";
11987 : :
11988 : 0 : case INSTR_ALU_ADD: return "INSTR_ALU_ADD";
11989 : 0 : case INSTR_ALU_ADD_MH: return "INSTR_ALU_ADD_MH";
11990 : 0 : case INSTR_ALU_ADD_HM: return "INSTR_ALU_ADD_HM";
11991 : 0 : case INSTR_ALU_ADD_HH: return "INSTR_ALU_ADD_HH";
11992 : 0 : case INSTR_ALU_ADD_MI: return "INSTR_ALU_ADD_MI";
11993 : 0 : case INSTR_ALU_ADD_HI: return "INSTR_ALU_ADD_HI";
11994 : :
11995 : 0 : case INSTR_ALU_SUB: return "INSTR_ALU_SUB";
11996 : 0 : case INSTR_ALU_SUB_MH: return "INSTR_ALU_SUB_MH";
11997 : 0 : case INSTR_ALU_SUB_HM: return "INSTR_ALU_SUB_HM";
11998 : 0 : case INSTR_ALU_SUB_HH: return "INSTR_ALU_SUB_HH";
11999 : 0 : case INSTR_ALU_SUB_MI: return "INSTR_ALU_SUB_MI";
12000 : 0 : case INSTR_ALU_SUB_HI: return "INSTR_ALU_SUB_HI";
12001 : :
12002 : 0 : case INSTR_ALU_CKADD_FIELD: return "INSTR_ALU_CKADD_FIELD";
12003 : 0 : case INSTR_ALU_CKADD_STRUCT20: return "INSTR_ALU_CKADD_STRUCT20";
12004 : 0 : case INSTR_ALU_CKADD_STRUCT: return "INSTR_ALU_CKADD_STRUCT";
12005 : 0 : case INSTR_ALU_CKSUB_FIELD: return "INSTR_ALU_CKSUB_FIELD";
12006 : :
12007 : 0 : case INSTR_ALU_AND: return "INSTR_ALU_AND";
12008 : 0 : case INSTR_ALU_AND_MH: return "INSTR_ALU_AND_MH";
12009 : 0 : case INSTR_ALU_AND_HM: return "INSTR_ALU_AND_HM";
12010 : 0 : case INSTR_ALU_AND_HH: return "INSTR_ALU_AND_HH";
12011 : 0 : case INSTR_ALU_AND_I: return "INSTR_ALU_AND_I";
12012 : :
12013 : 0 : case INSTR_ALU_OR: return "INSTR_ALU_OR";
12014 : 0 : case INSTR_ALU_OR_MH: return "INSTR_ALU_OR_MH";
12015 : 0 : case INSTR_ALU_OR_HM: return "INSTR_ALU_OR_HM";
12016 : 0 : case INSTR_ALU_OR_HH: return "INSTR_ALU_OR_HH";
12017 : 0 : case INSTR_ALU_OR_I: return "INSTR_ALU_OR_I";
12018 : :
12019 : 0 : case INSTR_ALU_XOR: return "INSTR_ALU_XOR";
12020 : 0 : case INSTR_ALU_XOR_MH: return "INSTR_ALU_XOR_MH";
12021 : 0 : case INSTR_ALU_XOR_HM: return "INSTR_ALU_XOR_HM";
12022 : 0 : case INSTR_ALU_XOR_HH: return "INSTR_ALU_XOR_HH";
12023 : 0 : case INSTR_ALU_XOR_I: return "INSTR_ALU_XOR_I";
12024 : :
12025 : 0 : case INSTR_ALU_SHL: return "INSTR_ALU_SHL";
12026 : 0 : case INSTR_ALU_SHL_MH: return "INSTR_ALU_SHL_MH";
12027 : 0 : case INSTR_ALU_SHL_HM: return "INSTR_ALU_SHL_HM";
12028 : 0 : case INSTR_ALU_SHL_HH: return "INSTR_ALU_SHL_HH";
12029 : 0 : case INSTR_ALU_SHL_MI: return "INSTR_ALU_SHL_MI";
12030 : 0 : case INSTR_ALU_SHL_HI: return "INSTR_ALU_SHL_HI";
12031 : :
12032 : 0 : case INSTR_ALU_SHR: return "INSTR_ALU_SHR";
12033 : 0 : case INSTR_ALU_SHR_MH: return "INSTR_ALU_SHR_MH";
12034 : 0 : case INSTR_ALU_SHR_HM: return "INSTR_ALU_SHR_HM";
12035 : 0 : case INSTR_ALU_SHR_HH: return "INSTR_ALU_SHR_HH";
12036 : 0 : case INSTR_ALU_SHR_MI: return "INSTR_ALU_SHR_MI";
12037 : 0 : case INSTR_ALU_SHR_HI: return "INSTR_ALU_SHR_HI";
12038 : :
12039 : 0 : case INSTR_REGPREFETCH_RH: return "INSTR_REGPREFETCH_RH";
12040 : 0 : case INSTR_REGPREFETCH_RM: return "INSTR_REGPREFETCH_RM";
12041 : 0 : case INSTR_REGPREFETCH_RI: return "INSTR_REGPREFETCH_RI";
12042 : :
12043 : 0 : case INSTR_REGRD_HRH: return "INSTR_REGRD_HRH";
12044 : 0 : case INSTR_REGRD_HRM: return "INSTR_REGRD_HRM";
12045 : 0 : case INSTR_REGRD_HRI: return "INSTR_REGRD_HRI";
12046 : 0 : case INSTR_REGRD_MRH: return "INSTR_REGRD_MRH";
12047 : 0 : case INSTR_REGRD_MRM: return "INSTR_REGRD_MRM";
12048 : 0 : case INSTR_REGRD_MRI: return "INSTR_REGRD_MRI";
12049 : :
12050 : 0 : case INSTR_REGWR_RHH: return "INSTR_REGWR_RHH";
12051 : 0 : case INSTR_REGWR_RHM: return "INSTR_REGWR_RHM";
12052 : 0 : case INSTR_REGWR_RHI: return "INSTR_REGWR_RHI";
12053 : 0 : case INSTR_REGWR_RMH: return "INSTR_REGWR_RMH";
12054 : 0 : case INSTR_REGWR_RMM: return "INSTR_REGWR_RMM";
12055 : 0 : case INSTR_REGWR_RMI: return "INSTR_REGWR_RMI";
12056 : 0 : case INSTR_REGWR_RIH: return "INSTR_REGWR_RIH";
12057 : 0 : case INSTR_REGWR_RIM: return "INSTR_REGWR_RIM";
12058 : 0 : case INSTR_REGWR_RII: return "INSTR_REGWR_RII";
12059 : :
12060 : 0 : case INSTR_REGADD_RHH: return "INSTR_REGADD_RHH";
12061 : 0 : case INSTR_REGADD_RHM: return "INSTR_REGADD_RHM";
12062 : 0 : case INSTR_REGADD_RHI: return "INSTR_REGADD_RHI";
12063 : 0 : case INSTR_REGADD_RMH: return "INSTR_REGADD_RMH";
12064 : 0 : case INSTR_REGADD_RMM: return "INSTR_REGADD_RMM";
12065 : 0 : case INSTR_REGADD_RMI: return "INSTR_REGADD_RMI";
12066 : 0 : case INSTR_REGADD_RIH: return "INSTR_REGADD_RIH";
12067 : 0 : case INSTR_REGADD_RIM: return "INSTR_REGADD_RIM";
12068 : 0 : case INSTR_REGADD_RII: return "INSTR_REGADD_RII";
12069 : :
12070 : 0 : case INSTR_METPREFETCH_H: return "INSTR_METPREFETCH_H";
12071 : 0 : case INSTR_METPREFETCH_M: return "INSTR_METPREFETCH_M";
12072 : 0 : case INSTR_METPREFETCH_I: return "INSTR_METPREFETCH_I";
12073 : :
12074 : 0 : case INSTR_METER_HHM: return "INSTR_METER_HHM";
12075 : 0 : case INSTR_METER_HHI: return "INSTR_METER_HHI";
12076 : 0 : case INSTR_METER_HMM: return "INSTR_METER_HMM";
12077 : 0 : case INSTR_METER_HMI: return "INSTR_METER_HMI";
12078 : 0 : case INSTR_METER_MHM: return "INSTR_METER_MHM";
12079 : 0 : case INSTR_METER_MHI: return "INSTR_METER_MHI";
12080 : 0 : case INSTR_METER_MMM: return "INSTR_METER_MMM";
12081 : 0 : case INSTR_METER_MMI: return "INSTR_METER_MMI";
12082 : 0 : case INSTR_METER_IHM: return "INSTR_METER_IHM";
12083 : 0 : case INSTR_METER_IHI: return "INSTR_METER_IHI";
12084 : 0 : case INSTR_METER_IMM: return "INSTR_METER_IMM";
12085 : 0 : case INSTR_METER_IMI: return "INSTR_METER_IMI";
12086 : :
12087 : 0 : case INSTR_TABLE: return "INSTR_TABLE";
12088 : 0 : case INSTR_TABLE_AF: return "INSTR_TABLE_AF";
12089 : 0 : case INSTR_SELECTOR: return "INSTR_SELECTOR";
12090 : 0 : case INSTR_LEARNER: return "INSTR_LEARNER";
12091 : 0 : case INSTR_LEARNER_AF: return "INSTR_LEARNER_AF";
12092 : :
12093 : 0 : case INSTR_LEARNER_LEARN: return "INSTR_LEARNER_LEARN";
12094 : 0 : case INSTR_LEARNER_REARM: return "INSTR_LEARNER_REARM";
12095 : 0 : case INSTR_LEARNER_REARM_NEW: return "INSTR_LEARNER_REARM_NEW";
12096 : 0 : case INSTR_LEARNER_FORGET: return "INSTR_LEARNER_FORGET";
12097 : 0 : case INSTR_ENTRYID: return "INSTR_ENTRYID";
12098 : :
12099 : 0 : case INSTR_EXTERN_OBJ: return "INSTR_EXTERN_OBJ";
12100 : 0 : case INSTR_EXTERN_FUNC: return "INSTR_EXTERN_FUNC";
12101 : 0 : case INSTR_HASH_FUNC: return "INSTR_HASH_FUNC";
12102 : 0 : case INSTR_RSS: return "INSTR_RSS";
12103 : :
12104 : 0 : case INSTR_JMP: return "INSTR_JMP";
12105 : 0 : case INSTR_JMP_VALID: return "INSTR_JMP_VALID";
12106 : 0 : case INSTR_JMP_INVALID: return "INSTR_JMP_INVALID";
12107 : 0 : case INSTR_JMP_HIT: return "INSTR_JMP_HIT";
12108 : 0 : case INSTR_JMP_MISS: return "INSTR_JMP_MISS";
12109 : 0 : case INSTR_JMP_ACTION_HIT: return "INSTR_JMP_ACTION_HIT";
12110 : 0 : case INSTR_JMP_ACTION_MISS: return "INSTR_JMP_ACTION_MISS";
12111 : 0 : case INSTR_JMP_EQ: return "INSTR_JMP_EQ";
12112 : 0 : case INSTR_JMP_EQ_MH: return "INSTR_JMP_EQ_MH";
12113 : 0 : case INSTR_JMP_EQ_HM: return "INSTR_JMP_EQ_HM";
12114 : 0 : case INSTR_JMP_EQ_HH: return "INSTR_JMP_EQ_HH";
12115 : 0 : case INSTR_JMP_EQ_I: return "INSTR_JMP_EQ_I";
12116 : 0 : case INSTR_JMP_NEQ: return "INSTR_JMP_NEQ";
12117 : 0 : case INSTR_JMP_NEQ_MH: return "INSTR_JMP_NEQ_MH";
12118 : 0 : case INSTR_JMP_NEQ_HM: return "INSTR_JMP_NEQ_HM";
12119 : 0 : case INSTR_JMP_NEQ_HH: return "INSTR_JMP_NEQ_HH";
12120 : 0 : case INSTR_JMP_NEQ_I: return "INSTR_JMP_NEQ_I";
12121 : 0 : case INSTR_JMP_LT: return "INSTR_JMP_LT";
12122 : 0 : case INSTR_JMP_LT_MH: return "INSTR_JMP_LT_MH";
12123 : 0 : case INSTR_JMP_LT_HM: return "INSTR_JMP_LT_HM";
12124 : 0 : case INSTR_JMP_LT_HH: return "INSTR_JMP_LT_HH";
12125 : 0 : case INSTR_JMP_LT_MI: return "INSTR_JMP_LT_MI";
12126 : 0 : case INSTR_JMP_LT_HI: return "INSTR_JMP_LT_HI";
12127 : 0 : case INSTR_JMP_GT: return "INSTR_JMP_GT";
12128 : 0 : case INSTR_JMP_GT_MH: return "INSTR_JMP_GT_MH";
12129 : 0 : case INSTR_JMP_GT_HM: return "INSTR_JMP_GT_HM";
12130 : 0 : case INSTR_JMP_GT_HH: return "INSTR_JMP_GT_HH";
12131 : 0 : case INSTR_JMP_GT_MI: return "INSTR_JMP_GT_MI";
12132 : 0 : case INSTR_JMP_GT_HI: return "INSTR_JMP_GT_HI";
12133 : :
12134 : 0 : case INSTR_RETURN: return "INSTR_RETURN";
12135 : :
12136 : 0 : default: return "INSTR_UNKNOWN";
12137 : : }
12138 : : }
12139 : :
12140 : : typedef void
12141 : : (*instruction_export_t)(struct instruction *, FILE *);
12142 : :
12143 : : static void
12144 : 0 : instr_io_export(struct instruction *instr, FILE *f)
12145 : : {
12146 : : uint32_t n_io = 0, n_io_imm = 0, n_hdrs = 0, i;
12147 : :
12148 : : /* n_io, n_io_imm, n_hdrs. */
12149 : 0 : if (instr->type == INSTR_RX ||
12150 [ # # ]: 0 : instr->type == INSTR_TX ||
12151 : 0 : instr->type == INSTR_HDR_EXTRACT_M ||
12152 [ # # ]: 0 : (instr->type >= INSTR_HDR_EMIT_TX && instr->type <= INSTR_HDR_EMIT8_TX))
12153 : : n_io = 1;
12154 : :
12155 [ # # ]: 0 : if (instr->type == INSTR_TX_I)
12156 : : n_io_imm = 1;
12157 : :
12158 [ # # ]: 0 : if (instr->type >= INSTR_HDR_EXTRACT && instr->type <= INSTR_HDR_EXTRACT8)
12159 : 0 : n_hdrs = 1 + (instr->type - INSTR_HDR_EXTRACT);
12160 : :
12161 : 0 : if (instr->type == INSTR_HDR_EXTRACT_M ||
12162 [ # # ]: 0 : instr->type == INSTR_HDR_LOOKAHEAD ||
12163 : : instr->type == INSTR_HDR_EMIT)
12164 : : n_hdrs = 1;
12165 : :
12166 [ # # ]: 0 : if (instr->type >= INSTR_HDR_EMIT_TX && instr->type <= INSTR_HDR_EMIT8_TX)
12167 : 0 : n_hdrs = 1 + (instr->type - INSTR_HDR_EMIT_TX);
12168 : :
12169 : : /* instr. */
12170 : 0 : fprintf(f,
12171 : : "\t{\n"
12172 : : "\t\t.type = %s,\n",
12173 : : instr_type_to_name(instr));
12174 : :
12175 : : /* instr.io. */
12176 [ # # ]: 0 : if (n_io || n_io_imm || n_hdrs)
12177 : : fprintf(f,
12178 : : "\t\t.io = {\n");
12179 : :
12180 : : /* instr.io.io. */
12181 [ # # ]: 0 : if (n_io)
12182 : 0 : fprintf(f,
12183 : : "\t\t\t.io = {\n"
12184 : : "\t\t\t\t.offset = %u,\n"
12185 : : "\t\t\t\t.n_bits = %u,\n"
12186 : : "\t\t\t},\n",
12187 : 0 : instr->io.io.offset,
12188 : 0 : instr->io.io.n_bits);
12189 : :
12190 [ # # ]: 0 : if (n_io_imm)
12191 : 0 : fprintf(f,
12192 : : "\t\t\t.io = {\n"
12193 : : "\t\t\t\t.val = %u,\n"
12194 : : "\t\t\t},\n",
12195 : : instr->io.io.val);
12196 : :
12197 : : /* instr.io.hdr. */
12198 [ # # ]: 0 : if (n_hdrs) {
12199 : : fprintf(f,
12200 : : "\t\t.hdr = {\n");
12201 : :
12202 : : /* instr.io.hdr.header_id. */
12203 : : fprintf(f,
12204 : : "\t\t\t.header_id = {");
12205 : :
12206 [ # # ]: 0 : for (i = 0; i < n_hdrs; i++)
12207 : 0 : fprintf(f,
12208 : : "%u, ",
12209 : 0 : instr->io.hdr.header_id[i]);
12210 : :
12211 : : fprintf(f,
12212 : : "},\n");
12213 : :
12214 : : /* instr.io.hdr.struct_id. */
12215 : : fprintf(f,
12216 : : "\t\t\t.struct_id = {");
12217 : :
12218 [ # # ]: 0 : for (i = 0; i < n_hdrs; i++)
12219 : 0 : fprintf(f,
12220 : : "%u, ",
12221 : 0 : instr->io.hdr.struct_id[i]);
12222 : :
12223 : : fprintf(f,
12224 : : "},\n");
12225 : :
12226 : : /* instr.io.hdr.n_bytes. */
12227 : : fprintf(f,
12228 : : "\t\t\t.n_bytes = {");
12229 : :
12230 [ # # ]: 0 : for (i = 0; i < n_hdrs; i++)
12231 : 0 : fprintf(f,
12232 : : "%u, ",
12233 : 0 : instr->io.hdr.n_bytes[i]);
12234 : :
12235 : : fprintf(f,
12236 : : "},\n");
12237 : :
12238 : : /* instr.io.hdr - closing curly brace. */
12239 : : fprintf(f,
12240 : : "\t\t\t}\n,");
12241 : : }
12242 : :
12243 : : /* instr.io - closing curly brace. */
12244 [ # # ]: 0 : if (n_io || n_io_imm || n_hdrs)
12245 : : fprintf(f,
12246 : : "\t\t},\n");
12247 : :
12248 : : /* instr - closing curly brace. */
12249 : : fprintf(f,
12250 : : "\t},\n");
12251 : 0 : }
12252 : :
12253 : : static void
12254 : 0 : instr_mirror_export(struct instruction *instr, FILE *f)
12255 : : {
12256 : 0 : fprintf(f,
12257 : : "\t{\n"
12258 : : "\t\t.type = %s,\n"
12259 : : "\t\t.mirror = {\n"
12260 : : "\t\t\t.dst = {\n"
12261 : : "\t\t\t\t.struct_id = %u,\n"
12262 : : "\t\t\t\t.n_bits = %u,\n"
12263 : : "\t\t\t\t.offset = %u,\n"
12264 : : "\t\t\t}\n,"
12265 : : "\t\t\t.src = {\n"
12266 : : "\t\t\t\t.struct_id = %u,\n"
12267 : : "\t\t\t\t.n_bits = %u,\n"
12268 : : "\t\t\t\t.offset = %u,\n"
12269 : : "\t\t\t}\n,"
12270 : : "\t\t},\n"
12271 : : "\t},\n",
12272 : : instr_type_to_name(instr),
12273 : 0 : instr->mirror.dst.struct_id,
12274 : 0 : instr->mirror.dst.n_bits,
12275 : 0 : instr->mirror.dst.offset,
12276 : 0 : instr->mirror.src.struct_id,
12277 : 0 : instr->mirror.src.n_bits,
12278 : 0 : instr->mirror.src.offset);
12279 : 0 : }
12280 : :
12281 : : static void
12282 : 0 : instr_recirculate_export(struct instruction *instr, FILE *f)
12283 : : {
12284 : 0 : fprintf(f,
12285 : : "\t{\n"
12286 : : "\t\t.type = %s,\n"
12287 : : "\t},\n",
12288 : : instr_type_to_name(instr));
12289 : 0 : }
12290 : :
12291 : : static void
12292 : 0 : instr_recircid_export(struct instruction *instr, FILE *f)
12293 : : {
12294 : 0 : fprintf(f,
12295 : : "\t{\n"
12296 : : "\t\t.type = %s,\n"
12297 : : "\t\t.io = {\n"
12298 : : "\t\t\t.io = {\n"
12299 : : "\t\t\t\t.offset = %u,\n"
12300 : : "\t\t\t\t.n_bits = %u,\n"
12301 : : "\t\t\t},\n"
12302 : : "\t\t},\n"
12303 : : "\t},\n",
12304 : : instr_type_to_name(instr),
12305 : 0 : instr->io.io.offset,
12306 : 0 : instr->io.io.n_bits);
12307 : 0 : }
12308 : :
12309 : : static void
12310 : 0 : instr_hdr_validate_export(struct instruction *instr, FILE *f)
12311 : : {
12312 : 0 : fprintf(f,
12313 : : "\t{\n"
12314 : : "\t\t.type = %s,\n"
12315 : : "\t\t.valid = {\n"
12316 : : "\t\t\t.header_id = %u,\n"
12317 : : "\t\t\t.struct_id = %u,\n"
12318 : : "\t\t},\n"
12319 : : "\t},\n",
12320 : : instr_type_to_name(instr),
12321 : 0 : instr->valid.header_id,
12322 : 0 : instr->valid.struct_id);
12323 : 0 : }
12324 : :
12325 : : static void
12326 : 0 : instr_mov_export(struct instruction *instr, FILE *f)
12327 : : {
12328 [ # # ]: 0 : if (instr->type != INSTR_MOV_I)
12329 : 0 : fprintf(f,
12330 : : "\t{\n"
12331 : : "\t\t.type = %s,\n"
12332 : : "\t\t.mov = {\n"
12333 : : "\t\t\t.dst = {\n"
12334 : : "\t\t\t\t.struct_id = %u,\n"
12335 : : "\t\t\t\t.n_bits = %u,\n"
12336 : : "\t\t\t\t.offset = %u,\n"
12337 : : "\t\t\t},\n"
12338 : : "\t\t\t.src = {\n"
12339 : : "\t\t\t\t.struct_id = %u,\n"
12340 : : "\t\t\t\t.n_bits = %u,\n"
12341 : : "\t\t\t\t.offset = %u,\n"
12342 : : "\t\t\t},\n"
12343 : : "\t\t},\n"
12344 : : "\t},\n",
12345 : : instr_type_to_name(instr),
12346 : 0 : instr->mov.dst.struct_id,
12347 : 0 : instr->mov.dst.n_bits,
12348 : 0 : instr->mov.dst.offset,
12349 : 0 : instr->mov.src.struct_id,
12350 : 0 : instr->mov.src.n_bits,
12351 : 0 : instr->mov.src.offset);
12352 : : else
12353 : 0 : fprintf(f,
12354 : : "\t{\n"
12355 : : "\t\t.type = %s,\n"
12356 : : "\t\t.mov = {\n"
12357 : : "\t\t\t.dst = {\n"
12358 : : "\t\t\t\t.struct_id = %u,\n"
12359 : : "\t\t\t\t.n_bits = %u,\n"
12360 : : "\t\t\t\t.offset = %u,\n"
12361 : : "\t\t\t}\n,"
12362 : : "\t\t\t.src_val = %" PRIu64 ",\n"
12363 : : "\t\t},\n"
12364 : : "\t},\n",
12365 : : instr_type_to_name(instr),
12366 : 0 : instr->mov.dst.struct_id,
12367 : 0 : instr->mov.dst.n_bits,
12368 : 0 : instr->mov.dst.offset,
12369 : : instr->mov.src_val);
12370 : 0 : }
12371 : :
12372 : : static void
12373 : 0 : instr_movh_export(struct instruction *instr, FILE *f)
12374 : : {
12375 : 0 : fprintf(f,
12376 : : "\t{\n"
12377 : : "\t\t.type = %s,\n"
12378 : : "\t\t.mov = {\n"
12379 : : "\t\t\t.dst = {\n"
12380 : : "\t\t\t\t.struct_id = %u,\n"
12381 : : "\t\t\t\t.n_bits = %u,\n"
12382 : : "\t\t\t\t.offset = %u,\n"
12383 : : "\t\t\t},\n"
12384 : : "\t\t\t.src = {\n"
12385 : : "\t\t\t\t.struct_id = %u,\n"
12386 : : "\t\t\t\t.n_bits = %u,\n"
12387 : : "\t\t\t\t.offset = %u,\n"
12388 : : "\t\t\t},\n"
12389 : : "\t\t},\n"
12390 : : "\t},\n",
12391 : : instr_type_to_name(instr),
12392 : 0 : instr->mov.dst.struct_id,
12393 : 0 : instr->mov.dst.n_bits,
12394 : 0 : instr->mov.dst.offset,
12395 : 0 : instr->mov.src.struct_id,
12396 : 0 : instr->mov.src.n_bits,
12397 : 0 : instr->mov.src.offset);
12398 : 0 : }
12399 : :
12400 : : static void
12401 : 0 : instr_dma_ht_export(struct instruction *instr, FILE *f)
12402 : : {
12403 : : uint32_t n_dma = 0, i;
12404 : :
12405 : : /* n_dma. */
12406 : 0 : n_dma = 1 + (instr->type - INSTR_DMA_HT);
12407 : :
12408 : : /* instr. */
12409 : 0 : fprintf(f,
12410 : : "\t{\n"
12411 : : "\t\t.type = %s,\n",
12412 : : instr_type_to_name(instr));
12413 : :
12414 : : /* instr.dma. */
12415 : : fprintf(f,
12416 : : "\t\t.dma = {\n");
12417 : :
12418 : : /* instr.dma.dst. */
12419 : : fprintf(f,
12420 : : "\t\t\t.dst = {\n");
12421 : :
12422 : : /* instr.dma.dst.header_id. */
12423 : : fprintf(f,
12424 : : "\t\t\t\t.header_id = {");
12425 : :
12426 [ # # ]: 0 : for (i = 0; i < n_dma; i++)
12427 : 0 : fprintf(f,
12428 : : "%u, ",
12429 : 0 : instr->dma.dst.header_id[i]);
12430 : :
12431 : : fprintf(f,
12432 : : "},\n");
12433 : :
12434 : : /* instr.dma.dst.struct_id. */
12435 : : fprintf(f,
12436 : : "\t\t\t\t.struct_id = {");
12437 : :
12438 [ # # ]: 0 : for (i = 0; i < n_dma; i++)
12439 : 0 : fprintf(f,
12440 : : "%u, ",
12441 : 0 : instr->dma.dst.struct_id[i]);
12442 : :
12443 : : fprintf(f,
12444 : : "},\n");
12445 : :
12446 : : /* instr.dma.dst - closing curly brace. */
12447 : : fprintf(f,
12448 : : "\t\t\t},\n");
12449 : :
12450 : : /* instr.dma.src. */
12451 : : fprintf(f,
12452 : : "\t\t\t.src = {\n");
12453 : :
12454 : : /* instr.dma.src.offset. */
12455 : : fprintf(f,
12456 : : "\t\t\t\t.offset = {");
12457 : :
12458 [ # # ]: 0 : for (i = 0; i < n_dma; i++)
12459 : 0 : fprintf(f,
12460 : : "%u, ",
12461 : 0 : instr->dma.src.offset[i]);
12462 : :
12463 : : fprintf(f,
12464 : : "},\n");
12465 : :
12466 : : /* instr.dma.src - closing curly brace. */
12467 : : fprintf(f,
12468 : : "\t\t\t},\n");
12469 : :
12470 : : /* instr.dma.n_bytes. */
12471 : : fprintf(f,
12472 : : "\t\t\t.n_bytes = {");
12473 : :
12474 [ # # ]: 0 : for (i = 0; i < n_dma; i++)
12475 : 0 : fprintf(f,
12476 : : "%u, ",
12477 : 0 : instr->dma.n_bytes[i]);
12478 : :
12479 : : fprintf(f,
12480 : : "},\n");
12481 : :
12482 : : /* instr.dma - closing curly brace. */
12483 : : fprintf(f,
12484 : : "\t\t},\n");
12485 : :
12486 : : /* instr - closing curly brace. */
12487 : : fprintf(f,
12488 : : "\t},\n");
12489 : 0 : }
12490 : :
12491 : : static void
12492 : 0 : instr_alu_export(struct instruction *instr, FILE *f)
12493 : : {
12494 : : int imm = 0;
12495 : :
12496 : 0 : if (instr->type == INSTR_ALU_ADD_MI ||
12497 [ # # ]: 0 : instr->type == INSTR_ALU_ADD_HI ||
12498 : : instr->type == INSTR_ALU_SUB_MI ||
12499 : : instr->type == INSTR_ALU_SUB_HI ||
12500 : : instr->type == INSTR_ALU_SHL_MI ||
12501 : : instr->type == INSTR_ALU_SHL_HI ||
12502 : : instr->type == INSTR_ALU_SHR_MI ||
12503 : : instr->type == INSTR_ALU_SHR_HI ||
12504 : : instr->type == INSTR_ALU_AND_I ||
12505 : : instr->type == INSTR_ALU_OR_I ||
12506 : : instr->type == INSTR_ALU_XOR_I)
12507 : : imm = 1;
12508 : :
12509 : : if (!imm)
12510 : 0 : fprintf(f,
12511 : : "\t{\n"
12512 : : "\t\t.type = %s,\n"
12513 : : "\t\t.alu = {\n"
12514 : : "\t\t\t.dst = {\n"
12515 : : "\t\t\t\t.struct_id = %u,\n"
12516 : : "\t\t\t\t.n_bits = %u,\n"
12517 : : "\t\t\t\t.offset = %u,\n"
12518 : : "\t\t\t},\n"
12519 : : "\t\t\t.src = {\n"
12520 : : "\t\t\t\t.struct_id = %u,\n"
12521 : : "\t\t\t\t.n_bits = %u,\n"
12522 : : "\t\t\t\t.offset = %u,\n"
12523 : : "\t\t\t},\n"
12524 : : "\t\t},\n"
12525 : : "\t},\n",
12526 : : instr_type_to_name(instr),
12527 : 0 : instr->alu.dst.struct_id,
12528 : 0 : instr->alu.dst.n_bits,
12529 : 0 : instr->alu.dst.offset,
12530 : 0 : instr->alu.src.struct_id,
12531 : 0 : instr->alu.src.n_bits,
12532 : 0 : instr->alu.src.offset);
12533 : : else
12534 : 0 : fprintf(f,
12535 : : "\t{\n"
12536 : : "\t\t.type = %s,\n"
12537 : : "\t\t.alu = {\n"
12538 : : "\t\t\t.dst = {\n"
12539 : : "\t\t\t\t.struct_id = %u,\n"
12540 : : "\t\t\t\t.n_bits = %u,\n"
12541 : : "\t\t\t\t.offset = %u,\n"
12542 : : "\t\t\t}\n,"
12543 : : "\t\t\t.src_val = %" PRIu64 ",\n"
12544 : : "\t\t},\n"
12545 : : "\t},\n",
12546 : : instr_type_to_name(instr),
12547 : 0 : instr->alu.dst.struct_id,
12548 : 0 : instr->alu.dst.n_bits,
12549 : 0 : instr->alu.dst.offset,
12550 : : instr->alu.src_val);
12551 : 0 : }
12552 : :
12553 : : static void
12554 : 0 : instr_hash_export(struct instruction *instr, FILE *f)
12555 : : {
12556 : 0 : fprintf(f,
12557 : : "\t{\n"
12558 : : "\t\t.type = %s,\n"
12559 : : "\t\t.hash_func = {\n"
12560 : : "\t\t\t.hash_func_id = %u,\n"
12561 : : "\t\t\t.dst = {\n"
12562 : : "\t\t\t\t.offset = %u,\n"
12563 : : "\t\t\t\t.n_bits = %u,\n"
12564 : : "\t\t\t},\n"
12565 : : "\t\t\t.src = {\n"
12566 : : "\t\t\t\t.struct_id = %u,\n"
12567 : : "\t\t\t\t.offset = %u,\n"
12568 : : "\t\t\t\t.n_bytes = %u,\n"
12569 : : "\t\t\t},\n"
12570 : : "\t\t},\n"
12571 : : "\t},\n",
12572 : : instr_type_to_name(instr),
12573 : 0 : instr->hash_func.hash_func_id,
12574 : 0 : instr->hash_func.dst.offset,
12575 : 0 : instr->hash_func.dst.n_bits,
12576 : 0 : instr->hash_func.src.struct_id,
12577 : 0 : instr->hash_func.src.offset,
12578 : 0 : instr->hash_func.src.n_bytes);
12579 : 0 : }
12580 : :
12581 : : static void
12582 : 0 : instr_rss_export(struct instruction *instr, FILE *f)
12583 : : {
12584 : 0 : fprintf(f,
12585 : : "\t{\n"
12586 : : "\t\t.type = %s,\n"
12587 : : "\t\t.rss = {\n"
12588 : : "\t\t\t.rss_obj_id = %u,\n"
12589 : : "\t\t\t.dst = {\n"
12590 : : "\t\t\t\t.offset = %u,\n"
12591 : : "\t\t\t\t.n_bits = %u,\n"
12592 : : "\t\t\t},\n"
12593 : : "\t\t\t.src = {\n"
12594 : : "\t\t\t\t.struct_id = %u,\n"
12595 : : "\t\t\t\t.offset = %u,\n"
12596 : : "\t\t\t\t.n_bytes = %u,\n"
12597 : : "\t\t\t},\n"
12598 : : "\t\t},\n"
12599 : : "\t},\n",
12600 : : instr_type_to_name(instr),
12601 : 0 : instr->rss.rss_obj_id,
12602 : 0 : instr->rss.dst.offset,
12603 : 0 : instr->rss.dst.n_bits,
12604 : 0 : instr->rss.src.struct_id,
12605 : 0 : instr->rss.src.offset,
12606 : 0 : instr->rss.src.n_bytes);
12607 : 0 : }
12608 : :
12609 : : static void
12610 : 0 : instr_reg_export(struct instruction *instr __rte_unused, FILE *f __rte_unused)
12611 : : {
12612 : : int prefetch = 0, idx_imm = 0, src_imm = 0;
12613 : :
12614 : 0 : if (instr->type == INSTR_REGPREFETCH_RH ||
12615 [ # # ]: 0 : instr->type == INSTR_REGPREFETCH_RM ||
12616 : : instr->type == INSTR_REGPREFETCH_RI)
12617 : : prefetch = 1;
12618 : :
12619 : : /* index is the 3rd operand for the regrd instruction and the 2nd
12620 : : * operand for the regwr and regadd instructions.
12621 : : */
12622 [ # # ]: 0 : if (instr->type == INSTR_REGPREFETCH_RI ||
12623 : : instr->type == INSTR_REGRD_HRI ||
12624 : : instr->type == INSTR_REGRD_MRI ||
12625 : : instr->type == INSTR_REGWR_RIH ||
12626 : : instr->type == INSTR_REGWR_RIM ||
12627 : : instr->type == INSTR_REGWR_RII ||
12628 : : instr->type == INSTR_REGADD_RIH ||
12629 : : instr->type == INSTR_REGADD_RIM ||
12630 : : instr->type == INSTR_REGADD_RII)
12631 : : idx_imm = 1;
12632 : :
12633 : : /* src is the 3rd operand for the regwr and regadd instructions. */
12634 [ # # ]: 0 : if (instr->type == INSTR_REGWR_RHI ||
12635 : : instr->type == INSTR_REGWR_RMI ||
12636 : : instr->type == INSTR_REGWR_RII ||
12637 : : instr->type == INSTR_REGADD_RHI ||
12638 : : instr->type == INSTR_REGADD_RMI ||
12639 : : instr->type == INSTR_REGADD_RII)
12640 : : src_imm = 1;
12641 : :
12642 : : /* instr.regarray.regarray_id. */
12643 : 0 : fprintf(f,
12644 : : "\t{\n"
12645 : : "\t\t.type = %s,\n"
12646 : : "\t\t.regarray = {\n"
12647 : : "\t\t\t.regarray_id = %u,\n",
12648 : : instr_type_to_name(instr),
12649 : 0 : instr->regarray.regarray_id);
12650 : :
12651 : : /* instr.regarray.idx / instr.regarray.idx_val. */
12652 [ # # ]: 0 : if (!idx_imm)
12653 : 0 : fprintf(f,
12654 : : "\t\t\t\t.idx = {\n"
12655 : : "\t\t\t\t\t.struct_id = %u,\n"
12656 : : "\t\t\t\t\t.n_bits = %u,\n"
12657 : : "\t\t\t\t\t.offset = %u,\n"
12658 : : "\t\t\t\t},\n",
12659 : 0 : instr->regarray.idx.struct_id,
12660 : 0 : instr->regarray.idx.n_bits,
12661 : 0 : instr->regarray.idx.offset);
12662 : : else
12663 : 0 : fprintf(f,
12664 : : "\t\t\t\t.idx_val = %u,\n",
12665 : : instr->regarray.idx_val);
12666 : :
12667 : : /* instr.regarray.dstsrc / instr.regarray.dstsrc_val. */
12668 [ # # ]: 0 : if (!prefetch) {
12669 [ # # ]: 0 : if (!src_imm)
12670 : 0 : fprintf(f,
12671 : : "\t\t\t\t.dstsrc = {\n"
12672 : : "\t\t\t\t\t.struct_id = %u,\n"
12673 : : "\t\t\t\t\t.n_bits = %u,\n"
12674 : : "\t\t\t\t\t.offset = %u,\n"
12675 : : "\t\t\t\t},\n",
12676 : 0 : instr->regarray.dstsrc.struct_id,
12677 : 0 : instr->regarray.dstsrc.n_bits,
12678 : 0 : instr->regarray.dstsrc.offset);
12679 : : else
12680 : 0 : fprintf(f,
12681 : : "\t\t\t\t.dstsrc_val = %" PRIu64 ",\n",
12682 : : instr->regarray.dstsrc_val);
12683 : : }
12684 : :
12685 : : /* instr.regarray and instr - closing curly braces. */
12686 : : fprintf(f,
12687 : : "\t\t},\n"
12688 : : "\t},\n");
12689 : 0 : }
12690 : :
12691 : : static void
12692 : 0 : instr_meter_export(struct instruction *instr __rte_unused, FILE *f __rte_unused)
12693 : : {
12694 : : int prefetch = 0, idx_imm = 0, color_in_imm = 0;
12695 : :
12696 : 0 : if (instr->type == INSTR_METPREFETCH_H ||
12697 [ # # ]: 0 : instr->type == INSTR_METPREFETCH_M ||
12698 : : instr->type == INSTR_METPREFETCH_I)
12699 : : prefetch = 1;
12700 : :
12701 : : /* idx_imm. */
12702 [ # # ]: 0 : if (instr->type == INSTR_METPREFETCH_I ||
12703 [ # # ]: 0 : instr->type == INSTR_METER_IHM ||
12704 [ # # ]: 0 : instr->type == INSTR_METER_IHI ||
12705 [ # # ]: 0 : instr->type == INSTR_METER_IMM ||
12706 : : instr->type == INSTR_METER_IMI)
12707 : : idx_imm = 1;
12708 : :
12709 : : /* color_in_imm. */
12710 [ # # ]: 0 : if (instr->type == INSTR_METER_HHI ||
12711 : : instr->type == INSTR_METER_HMI ||
12712 : : instr->type == INSTR_METER_MHI ||
12713 : : instr->type == INSTR_METER_MMI ||
12714 : : instr->type == INSTR_METER_IHI ||
12715 : : instr->type == INSTR_METER_IMI)
12716 : : color_in_imm = 1;
12717 : :
12718 : : /* instr.meter.metarray_id. */
12719 : 0 : fprintf(f,
12720 : : "\t{\n"
12721 : : "\t\t.type = %s,\n"
12722 : : "\t\t.meter = {\n"
12723 : : "\t\t\t.metarray_id = %u,\n",
12724 : : instr_type_to_name(instr),
12725 : 0 : instr->meter.metarray_id);
12726 : :
12727 : : /* instr.meter.idx / instr.meter.idx_val. */
12728 [ # # ]: 0 : if (!idx_imm)
12729 : 0 : fprintf(f,
12730 : : "\t\t\t.idx = {\n"
12731 : : "\t\t\t\t.struct_id = %u,\n"
12732 : : "\t\t\t\t.n_bits = %u,\n"
12733 : : "\t\t\t\t.offset = %u,\n"
12734 : : "\t\t\t},\n",
12735 : 0 : instr->meter.idx.struct_id,
12736 : 0 : instr->meter.idx.n_bits,
12737 : 0 : instr->meter.idx.offset);
12738 : : else
12739 : 0 : fprintf(f,
12740 : : "\t\t\t.idx_val = %u,\n",
12741 : : instr->meter.idx_val);
12742 : :
12743 [ # # ]: 0 : if (!prefetch) {
12744 : : /* instr.meter.length. */
12745 : 0 : fprintf(f,
12746 : : "\t\t\t.length = {\n"
12747 : : "\t\t\t\t.struct_id = %u,\n"
12748 : : "\t\t\t\t.n_bits = %u,\n"
12749 : : "\t\t\t\t.offset = %u,\n"
12750 : : "\t\t\t},\n",
12751 : 0 : instr->meter.length.struct_id,
12752 : 0 : instr->meter.length.n_bits,
12753 : 0 : instr->meter.length.offset);
12754 : :
12755 : : /* instr.meter.color_in / instr.meter.color_in_val. */
12756 [ # # ]: 0 : if (!color_in_imm)
12757 : 0 : fprintf(f,
12758 : : "\t\t\t.color_in = {\n"
12759 : : "\t\t\t\t.struct_id = %u,\n"
12760 : : "\t\t\t\t.n_bits = %u,\n"
12761 : : "\t\t\t\t.offset = %u,\n"
12762 : : "\t\t\t},\n",
12763 : 0 : instr->meter.color_in.struct_id,
12764 : 0 : instr->meter.color_in.n_bits,
12765 : 0 : instr->meter.color_in.offset);
12766 : : else
12767 : : fprintf(f,
12768 : : "\t\t\t.color_in_val = %u,\n",
12769 : 0 : (uint32_t)instr->meter.color_in_val);
12770 : :
12771 : : /* instr.meter.color_out. */
12772 : 0 : fprintf(f,
12773 : : "\t\t\t.color_out = {\n"
12774 : : "\t\t\t\t.struct_id = %u,\n"
12775 : : "\t\t\t\t.n_bits = %u,\n"
12776 : : "\t\t\t\t.offset = %u,\n"
12777 : : "\t\t\t},\n",
12778 : 0 : instr->meter.color_out.struct_id,
12779 : 0 : instr->meter.color_out.n_bits,
12780 : 0 : instr->meter.color_out.offset);
12781 : : }
12782 : :
12783 : : /* instr.meter and instr - closing curly braces. */
12784 : : fprintf(f,
12785 : : "\t\t},\n"
12786 : : "\t},\n");
12787 : 0 : }
12788 : :
12789 : : static void
12790 : 0 : instr_table_export(struct instruction *instr,
12791 : : FILE *f)
12792 : : {
12793 : 0 : fprintf(f,
12794 : : "\t{\n"
12795 : : "\t\t.type = %s,\n"
12796 : : "\t\t.table = {\n"
12797 : : "\t\t\t.table_id = %u,\n"
12798 : : "\t\t},\n"
12799 : : "\t},\n",
12800 : : instr_type_to_name(instr),
12801 : 0 : instr->table.table_id);
12802 : 0 : }
12803 : :
12804 : : static void
12805 : 0 : instr_learn_export(struct instruction *instr, FILE *f)
12806 : : {
12807 : 0 : fprintf(f,
12808 : : "\t{\n"
12809 : : "\t\t.type = %s,\n"
12810 : : "\t\t.learn = {\n"
12811 : : "\t\t\t.action_id = %u,\n"
12812 : : "\t\t\t.mf_first_arg_offset = %u,\n"
12813 : : "\t\t\t.mf_timeout_id_offset = %u,\n"
12814 : : "\t\t\t.mf_timeout_id_n_bits = %u,\n"
12815 : : "\t\t},\n"
12816 : : "\t},\n",
12817 : : instr_type_to_name(instr),
12818 : 0 : instr->learn.action_id,
12819 : 0 : instr->learn.mf_first_arg_offset,
12820 : 0 : instr->learn.mf_timeout_id_offset,
12821 : 0 : instr->learn.mf_timeout_id_n_bits);
12822 : 0 : }
12823 : :
12824 : : static void
12825 : 0 : instr_rearm_export(struct instruction *instr, FILE *f)
12826 : : {
12827 [ # # ]: 0 : if (instr->type == INSTR_LEARNER_REARM)
12828 : 0 : fprintf(f,
12829 : : "\t{\n"
12830 : : "\t\t.type = %s,\n"
12831 : : "\t},\n",
12832 : : instr_type_to_name(instr));
12833 : : else
12834 : 0 : fprintf(f,
12835 : : "\t{\n"
12836 : : "\t\t.type = %s,\n"
12837 : : "\t\t.learn = {\n"
12838 : : "\t\t\t.mf_timeout_id_offset = %u,\n"
12839 : : "\t\t\t.mf_timeout_id_n_bits = %u,\n"
12840 : : "\t\t},\n"
12841 : : "\t},\n",
12842 : : instr_type_to_name(instr),
12843 : 0 : instr->learn.mf_timeout_id_offset,
12844 : 0 : instr->learn.mf_timeout_id_n_bits);
12845 : 0 : }
12846 : :
12847 : : static void
12848 : 0 : instr_forget_export(struct instruction *instr, FILE *f)
12849 : : {
12850 : 0 : fprintf(f,
12851 : : "\t{\n"
12852 : : "\t\t.type = %s,\n"
12853 : : "\t},\n",
12854 : : instr_type_to_name(instr));
12855 : 0 : }
12856 : :
12857 : : static void
12858 : 0 : instr_entryid_export(struct instruction *instr, FILE *f)
12859 : : {
12860 : 0 : fprintf(f,
12861 : : "\t{\n"
12862 : : "\t\t.type = %s,\n"
12863 : : "\t\t.mov = {\n"
12864 : : "\t\t\t.dst = {\n"
12865 : : "\t\t\t\t.n_bits = %u,\n"
12866 : : "\t\t\t\t.offset = %u,\n"
12867 : : "\t\t\t},\n"
12868 : : "\t\t},\n"
12869 : : "\t},\n",
12870 : : instr_type_to_name(instr),
12871 : 0 : instr->mov.dst.n_bits,
12872 : 0 : instr->mov.dst.offset);
12873 : 0 : }
12874 : :
12875 : : static void
12876 : 0 : instr_extern_export(struct instruction *instr, FILE *f)
12877 : : {
12878 [ # # ]: 0 : if (instr->type == INSTR_EXTERN_OBJ)
12879 : 0 : fprintf(f,
12880 : : "\t{\n"
12881 : : "\t\t.type = %s,\n"
12882 : : "\t\t.ext_obj = {\n"
12883 : : "\t\t\t.ext_obj_id = %u,\n"
12884 : : "\t\t\t.func_id = %u,\n"
12885 : : "\t\t},\n"
12886 : : "\t},\n",
12887 : : instr_type_to_name(instr),
12888 : 0 : instr->ext_obj.ext_obj_id,
12889 : 0 : instr->ext_obj.func_id);
12890 : : else
12891 : 0 : fprintf(f,
12892 : : "\t{\n"
12893 : : "\t\t.type = %s,\n"
12894 : : "\t\t.ext_func = {\n"
12895 : : "\t\t\t.ext_func_id = %u,\n"
12896 : : "\t\t},\n"
12897 : : "\t},\n",
12898 : : instr_type_to_name(instr),
12899 : 0 : instr->ext_func.ext_func_id);
12900 : 0 : }
12901 : :
12902 : : static void
12903 : 0 : instr_jmp_export(struct instruction *instr, FILE *f __rte_unused)
12904 : : {
12905 : 0 : fprintf(f,
12906 : : "\t{\n"
12907 : : "\t\t.type = %s,\n"
12908 : : "\t\t.jmp = {\n"
12909 : : "\t\t\t.ip = NULL,\n",
12910 : : instr_type_to_name(instr));
12911 : :
12912 [ # # # # : 0 : switch (instr->type) {
# ]
12913 : 0 : case INSTR_JMP_VALID:
12914 : : case INSTR_JMP_INVALID:
12915 : 0 : fprintf(f,
12916 : : "\t\t\t.header_id = %u,\n",
12917 : 0 : instr->jmp.header_id);
12918 : : break;
12919 : :
12920 : 0 : case INSTR_JMP_ACTION_HIT:
12921 : : case INSTR_JMP_ACTION_MISS:
12922 : 0 : fprintf(f,
12923 : : "\t\t\t.action_id = %u,\n",
12924 : 0 : instr->jmp.action_id);
12925 : : break;
12926 : :
12927 : 0 : case INSTR_JMP_EQ:
12928 : : case INSTR_JMP_EQ_MH:
12929 : : case INSTR_JMP_EQ_HM:
12930 : : case INSTR_JMP_EQ_HH:
12931 : : case INSTR_JMP_NEQ:
12932 : : case INSTR_JMP_NEQ_MH:
12933 : : case INSTR_JMP_NEQ_HM:
12934 : : case INSTR_JMP_NEQ_HH:
12935 : : case INSTR_JMP_LT:
12936 : : case INSTR_JMP_LT_MH:
12937 : : case INSTR_JMP_LT_HM:
12938 : : case INSTR_JMP_LT_HH:
12939 : : case INSTR_JMP_GT:
12940 : : case INSTR_JMP_GT_MH:
12941 : : case INSTR_JMP_GT_HM:
12942 : : case INSTR_JMP_GT_HH:
12943 : 0 : fprintf(f,
12944 : : "\t\t\t.a = {\n"
12945 : : "\t\t\t\t.struct_id = %u,\n"
12946 : : "\t\t\t\t.n_bits = %u,\n"
12947 : : "\t\t\t\t.offset = %u,\n"
12948 : : "\t\t\t},\n"
12949 : : "\t\t\t.b = {\n"
12950 : : "\t\t\t\t.struct_id = %u,\n"
12951 : : "\t\t\t\t.n_bits = %u,\n"
12952 : : "\t\t\t\t.offset = %u,\n"
12953 : : "\t\t\t},\n",
12954 : 0 : instr->jmp.a.struct_id,
12955 : 0 : instr->jmp.a.n_bits,
12956 : 0 : instr->jmp.a.offset,
12957 : 0 : instr->jmp.b.struct_id,
12958 : 0 : instr->jmp.b.n_bits,
12959 : 0 : instr->jmp.b.offset);
12960 : : break;
12961 : :
12962 : 0 : case INSTR_JMP_EQ_I:
12963 : : case INSTR_JMP_NEQ_I:
12964 : : case INSTR_JMP_LT_MI:
12965 : : case INSTR_JMP_LT_HI:
12966 : : case INSTR_JMP_GT_MI:
12967 : : case INSTR_JMP_GT_HI:
12968 : 0 : fprintf(f,
12969 : : "\t\t\t.a = {\n"
12970 : : "\t\t\t\t.struct_id = %u,\n"
12971 : : "\t\t\t\t.n_bits = %u,\n"
12972 : : "\t\t\t\t.offset = %u,\n"
12973 : : "\t\t\t}\n,"
12974 : : "\t\t\t.b_val = %" PRIu64 ",\n",
12975 : 0 : instr->jmp.a.struct_id,
12976 : 0 : instr->jmp.a.n_bits,
12977 : 0 : instr->jmp.a.offset,
12978 : : instr->jmp.b_val);
12979 : : break;
12980 : :
12981 : : default:
12982 : : break;
12983 : : }
12984 : :
12985 : : fprintf(f,
12986 : : "\t\t},\n"
12987 : : "\t},\n");
12988 : 0 : }
12989 : :
12990 : : static void
12991 : 0 : instr_return_export(struct instruction *instr,
12992 : : FILE *f)
12993 : : {
12994 : 0 : fprintf(f,
12995 : : "\t{\n"
12996 : : "\t\t.type = %s,\n",
12997 : : instr_type_to_name(instr));
12998 : :
12999 : : fprintf(f,
13000 : : "\t},\n");
13001 : 0 : }
13002 : :
13003 : : static instruction_export_t export_table[] = {
13004 : : [INSTR_RX] = instr_io_export,
13005 : :
13006 : : [INSTR_TX] = instr_io_export,
13007 : : [INSTR_TX_I] = instr_io_export,
13008 : : [INSTR_DROP] = instr_io_export,
13009 : : [INSTR_MIRROR] = instr_mirror_export,
13010 : : [INSTR_RECIRCULATE] = instr_recirculate_export,
13011 : : [INSTR_RECIRCID] = instr_recircid_export,
13012 : :
13013 : : [INSTR_HDR_EXTRACT] = instr_io_export,
13014 : : [INSTR_HDR_EXTRACT2] = instr_io_export,
13015 : : [INSTR_HDR_EXTRACT3] = instr_io_export,
13016 : : [INSTR_HDR_EXTRACT4] = instr_io_export,
13017 : : [INSTR_HDR_EXTRACT5] = instr_io_export,
13018 : : [INSTR_HDR_EXTRACT6] = instr_io_export,
13019 : : [INSTR_HDR_EXTRACT7] = instr_io_export,
13020 : : [INSTR_HDR_EXTRACT8] = instr_io_export,
13021 : :
13022 : : [INSTR_HDR_EXTRACT_M] = instr_io_export,
13023 : :
13024 : : [INSTR_HDR_LOOKAHEAD] = instr_io_export,
13025 : :
13026 : : [INSTR_HDR_EMIT] = instr_io_export,
13027 : : [INSTR_HDR_EMIT_TX] = instr_io_export,
13028 : : [INSTR_HDR_EMIT2_TX] = instr_io_export,
13029 : : [INSTR_HDR_EMIT3_TX] = instr_io_export,
13030 : : [INSTR_HDR_EMIT4_TX] = instr_io_export,
13031 : : [INSTR_HDR_EMIT5_TX] = instr_io_export,
13032 : : [INSTR_HDR_EMIT6_TX] = instr_io_export,
13033 : : [INSTR_HDR_EMIT7_TX] = instr_io_export,
13034 : : [INSTR_HDR_EMIT8_TX] = instr_io_export,
13035 : :
13036 : : [INSTR_HDR_VALIDATE] = instr_hdr_validate_export,
13037 : : [INSTR_HDR_INVALIDATE] = instr_hdr_validate_export,
13038 : :
13039 : : [INSTR_MOV] = instr_mov_export,
13040 : : [INSTR_MOV_MH] = instr_mov_export,
13041 : : [INSTR_MOV_HM] = instr_mov_export,
13042 : : [INSTR_MOV_HH] = instr_mov_export,
13043 : : [INSTR_MOV_DMA] = instr_mov_export,
13044 : : [INSTR_MOV_128] = instr_mov_export,
13045 : : [INSTR_MOV_128_64] = instr_mov_export,
13046 : : [INSTR_MOV_64_128] = instr_mov_export,
13047 : : [INSTR_MOV_128_32] = instr_mov_export,
13048 : : [INSTR_MOV_32_128] = instr_mov_export,
13049 : : [INSTR_MOV_I] = instr_mov_export,
13050 : :
13051 : : [INSTR_MOVH] = instr_movh_export,
13052 : :
13053 : : [INSTR_DMA_HT] = instr_dma_ht_export,
13054 : : [INSTR_DMA_HT2] = instr_dma_ht_export,
13055 : : [INSTR_DMA_HT3] = instr_dma_ht_export,
13056 : : [INSTR_DMA_HT4] = instr_dma_ht_export,
13057 : : [INSTR_DMA_HT5] = instr_dma_ht_export,
13058 : : [INSTR_DMA_HT6] = instr_dma_ht_export,
13059 : : [INSTR_DMA_HT7] = instr_dma_ht_export,
13060 : : [INSTR_DMA_HT8] = instr_dma_ht_export,
13061 : :
13062 : : [INSTR_ALU_ADD] = instr_alu_export,
13063 : : [INSTR_ALU_ADD_MH] = instr_alu_export,
13064 : : [INSTR_ALU_ADD_HM] = instr_alu_export,
13065 : : [INSTR_ALU_ADD_HH] = instr_alu_export,
13066 : : [INSTR_ALU_ADD_MI] = instr_alu_export,
13067 : : [INSTR_ALU_ADD_HI] = instr_alu_export,
13068 : :
13069 : : [INSTR_ALU_SUB] = instr_alu_export,
13070 : : [INSTR_ALU_SUB_MH] = instr_alu_export,
13071 : : [INSTR_ALU_SUB_HM] = instr_alu_export,
13072 : : [INSTR_ALU_SUB_HH] = instr_alu_export,
13073 : : [INSTR_ALU_SUB_MI] = instr_alu_export,
13074 : : [INSTR_ALU_SUB_HI] = instr_alu_export,
13075 : :
13076 : : [INSTR_ALU_CKADD_FIELD] = instr_alu_export,
13077 : : [INSTR_ALU_CKADD_STRUCT] = instr_alu_export,
13078 : : [INSTR_ALU_CKADD_STRUCT20] = instr_alu_export,
13079 : : [INSTR_ALU_CKSUB_FIELD] = instr_alu_export,
13080 : :
13081 : : [INSTR_ALU_AND] = instr_alu_export,
13082 : : [INSTR_ALU_AND_MH] = instr_alu_export,
13083 : : [INSTR_ALU_AND_HM] = instr_alu_export,
13084 : : [INSTR_ALU_AND_HH] = instr_alu_export,
13085 : : [INSTR_ALU_AND_I] = instr_alu_export,
13086 : :
13087 : : [INSTR_ALU_OR] = instr_alu_export,
13088 : : [INSTR_ALU_OR_MH] = instr_alu_export,
13089 : : [INSTR_ALU_OR_HM] = instr_alu_export,
13090 : : [INSTR_ALU_OR_HH] = instr_alu_export,
13091 : : [INSTR_ALU_OR_I] = instr_alu_export,
13092 : :
13093 : : [INSTR_ALU_XOR] = instr_alu_export,
13094 : : [INSTR_ALU_XOR_MH] = instr_alu_export,
13095 : : [INSTR_ALU_XOR_HM] = instr_alu_export,
13096 : : [INSTR_ALU_XOR_HH] = instr_alu_export,
13097 : : [INSTR_ALU_XOR_I] = instr_alu_export,
13098 : :
13099 : : [INSTR_ALU_SHL] = instr_alu_export,
13100 : : [INSTR_ALU_SHL_MH] = instr_alu_export,
13101 : : [INSTR_ALU_SHL_HM] = instr_alu_export,
13102 : : [INSTR_ALU_SHL_HH] = instr_alu_export,
13103 : : [INSTR_ALU_SHL_MI] = instr_alu_export,
13104 : : [INSTR_ALU_SHL_HI] = instr_alu_export,
13105 : :
13106 : : [INSTR_ALU_SHR] = instr_alu_export,
13107 : : [INSTR_ALU_SHR_MH] = instr_alu_export,
13108 : : [INSTR_ALU_SHR_HM] = instr_alu_export,
13109 : : [INSTR_ALU_SHR_HH] = instr_alu_export,
13110 : : [INSTR_ALU_SHR_MI] = instr_alu_export,
13111 : : [INSTR_ALU_SHR_HI] = instr_alu_export,
13112 : :
13113 : : [INSTR_REGPREFETCH_RH] = instr_reg_export,
13114 : : [INSTR_REGPREFETCH_RM] = instr_reg_export,
13115 : : [INSTR_REGPREFETCH_RI] = instr_reg_export,
13116 : :
13117 : : [INSTR_REGRD_HRH] = instr_reg_export,
13118 : : [INSTR_REGRD_HRM] = instr_reg_export,
13119 : : [INSTR_REGRD_MRH] = instr_reg_export,
13120 : : [INSTR_REGRD_MRM] = instr_reg_export,
13121 : : [INSTR_REGRD_HRI] = instr_reg_export,
13122 : : [INSTR_REGRD_MRI] = instr_reg_export,
13123 : :
13124 : : [INSTR_REGWR_RHH] = instr_reg_export,
13125 : : [INSTR_REGWR_RHM] = instr_reg_export,
13126 : : [INSTR_REGWR_RMH] = instr_reg_export,
13127 : : [INSTR_REGWR_RMM] = instr_reg_export,
13128 : : [INSTR_REGWR_RHI] = instr_reg_export,
13129 : : [INSTR_REGWR_RMI] = instr_reg_export,
13130 : : [INSTR_REGWR_RIH] = instr_reg_export,
13131 : : [INSTR_REGWR_RIM] = instr_reg_export,
13132 : : [INSTR_REGWR_RII] = instr_reg_export,
13133 : :
13134 : : [INSTR_REGADD_RHH] = instr_reg_export,
13135 : : [INSTR_REGADD_RHM] = instr_reg_export,
13136 : : [INSTR_REGADD_RMH] = instr_reg_export,
13137 : : [INSTR_REGADD_RMM] = instr_reg_export,
13138 : : [INSTR_REGADD_RHI] = instr_reg_export,
13139 : : [INSTR_REGADD_RMI] = instr_reg_export,
13140 : : [INSTR_REGADD_RIH] = instr_reg_export,
13141 : : [INSTR_REGADD_RIM] = instr_reg_export,
13142 : : [INSTR_REGADD_RII] = instr_reg_export,
13143 : :
13144 : : [INSTR_METPREFETCH_H] = instr_meter_export,
13145 : : [INSTR_METPREFETCH_M] = instr_meter_export,
13146 : : [INSTR_METPREFETCH_I] = instr_meter_export,
13147 : :
13148 : : [INSTR_METER_HHM] = instr_meter_export,
13149 : : [INSTR_METER_HHI] = instr_meter_export,
13150 : : [INSTR_METER_HMM] = instr_meter_export,
13151 : : [INSTR_METER_HMI] = instr_meter_export,
13152 : : [INSTR_METER_MHM] = instr_meter_export,
13153 : : [INSTR_METER_MHI] = instr_meter_export,
13154 : : [INSTR_METER_MMM] = instr_meter_export,
13155 : : [INSTR_METER_MMI] = instr_meter_export,
13156 : : [INSTR_METER_IHM] = instr_meter_export,
13157 : : [INSTR_METER_IHI] = instr_meter_export,
13158 : : [INSTR_METER_IMM] = instr_meter_export,
13159 : : [INSTR_METER_IMI] = instr_meter_export,
13160 : :
13161 : : [INSTR_TABLE] = instr_table_export,
13162 : : [INSTR_TABLE_AF] = instr_table_export,
13163 : : [INSTR_SELECTOR] = instr_table_export,
13164 : : [INSTR_LEARNER] = instr_table_export,
13165 : : [INSTR_LEARNER_AF] = instr_table_export,
13166 : :
13167 : : [INSTR_LEARNER_LEARN] = instr_learn_export,
13168 : : [INSTR_LEARNER_REARM] = instr_rearm_export,
13169 : : [INSTR_LEARNER_REARM_NEW] = instr_rearm_export,
13170 : : [INSTR_LEARNER_FORGET] = instr_forget_export,
13171 : : [INSTR_ENTRYID] = instr_entryid_export,
13172 : :
13173 : : [INSTR_EXTERN_OBJ] = instr_extern_export,
13174 : : [INSTR_EXTERN_FUNC] = instr_extern_export,
13175 : : [INSTR_HASH_FUNC] = instr_hash_export,
13176 : : [INSTR_RSS] = instr_rss_export,
13177 : :
13178 : : [INSTR_JMP] = instr_jmp_export,
13179 : : [INSTR_JMP_VALID] = instr_jmp_export,
13180 : : [INSTR_JMP_INVALID] = instr_jmp_export,
13181 : : [INSTR_JMP_HIT] = instr_jmp_export,
13182 : : [INSTR_JMP_MISS] = instr_jmp_export,
13183 : : [INSTR_JMP_ACTION_HIT] = instr_jmp_export,
13184 : : [INSTR_JMP_ACTION_MISS] = instr_jmp_export,
13185 : :
13186 : : [INSTR_JMP_EQ] = instr_jmp_export,
13187 : : [INSTR_JMP_EQ_MH] = instr_jmp_export,
13188 : : [INSTR_JMP_EQ_HM] = instr_jmp_export,
13189 : : [INSTR_JMP_EQ_HH] = instr_jmp_export,
13190 : : [INSTR_JMP_EQ_I] = instr_jmp_export,
13191 : :
13192 : : [INSTR_JMP_NEQ] = instr_jmp_export,
13193 : : [INSTR_JMP_NEQ_MH] = instr_jmp_export,
13194 : : [INSTR_JMP_NEQ_HM] = instr_jmp_export,
13195 : : [INSTR_JMP_NEQ_HH] = instr_jmp_export,
13196 : : [INSTR_JMP_NEQ_I] = instr_jmp_export,
13197 : :
13198 : : [INSTR_JMP_LT] = instr_jmp_export,
13199 : : [INSTR_JMP_LT_MH] = instr_jmp_export,
13200 : : [INSTR_JMP_LT_HM] = instr_jmp_export,
13201 : : [INSTR_JMP_LT_HH] = instr_jmp_export,
13202 : : [INSTR_JMP_LT_MI] = instr_jmp_export,
13203 : : [INSTR_JMP_LT_HI] = instr_jmp_export,
13204 : :
13205 : : [INSTR_JMP_GT] = instr_jmp_export,
13206 : : [INSTR_JMP_GT_MH] = instr_jmp_export,
13207 : : [INSTR_JMP_GT_HM] = instr_jmp_export,
13208 : : [INSTR_JMP_GT_HH] = instr_jmp_export,
13209 : : [INSTR_JMP_GT_MI] = instr_jmp_export,
13210 : : [INSTR_JMP_GT_HI] = instr_jmp_export,
13211 : :
13212 : : [INSTR_RETURN] = instr_return_export,
13213 : : };
13214 : :
13215 : : static void
13216 : 0 : action_data_codegen(struct action *a, FILE *f)
13217 : : {
13218 : : uint32_t i;
13219 : :
13220 : : fprintf(f,
13221 : : "static const struct instruction action_%s_instructions[] = {\n",
13222 : 0 : a->name);
13223 : :
13224 [ # # ]: 0 : for (i = 0; i < a->n_instructions; i++) {
13225 : 0 : struct instruction *instr = &a->instructions[i];
13226 : 0 : instruction_export_t func = export_table[instr->type];
13227 : :
13228 : 0 : func(instr, f);
13229 : : }
13230 : :
13231 : : fprintf(f, "};\n");
13232 : 0 : }
13233 : :
13234 : : static const char *
13235 : 0 : instr_type_to_func(struct instruction *instr)
13236 : : {
13237 [ # # # # : 0 : switch (instr->type) {
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
13238 : : case INSTR_RX: return NULL;
13239 : :
13240 : 0 : case INSTR_TX: return "__instr_tx_exec";
13241 : 0 : case INSTR_TX_I: return "__instr_tx_i_exec";
13242 : 0 : case INSTR_DROP: return "__instr_drop_exec";
13243 : 0 : case INSTR_MIRROR: return "__instr_mirror_exec";
13244 : 0 : case INSTR_RECIRCULATE: return "__instr_recirculate_exec";
13245 : 0 : case INSTR_RECIRCID: return "__instr_recircid_exec";
13246 : :
13247 : 0 : case INSTR_HDR_EXTRACT: return "__instr_hdr_extract_exec";
13248 : 0 : case INSTR_HDR_EXTRACT2: return "__instr_hdr_extract2_exec";
13249 : 0 : case INSTR_HDR_EXTRACT3: return "__instr_hdr_extract3_exec";
13250 : 0 : case INSTR_HDR_EXTRACT4: return "__instr_hdr_extract4_exec";
13251 : 0 : case INSTR_HDR_EXTRACT5: return "__instr_hdr_extract5_exec";
13252 : 0 : case INSTR_HDR_EXTRACT6: return "__instr_hdr_extract6_exec";
13253 : 0 : case INSTR_HDR_EXTRACT7: return "__instr_hdr_extract7_exec";
13254 : 0 : case INSTR_HDR_EXTRACT8: return "__instr_hdr_extract8_exec";
13255 : :
13256 : 0 : case INSTR_HDR_EXTRACT_M: return "__instr_hdr_extract_m_exec";
13257 : :
13258 : 0 : case INSTR_HDR_LOOKAHEAD: return "__instr_hdr_lookahead_exec";
13259 : :
13260 : 0 : case INSTR_HDR_EMIT: return "__instr_hdr_emit_exec";
13261 : 0 : case INSTR_HDR_EMIT_TX: return "__instr_hdr_emit_tx_exec";
13262 : 0 : case INSTR_HDR_EMIT2_TX: return "__instr_hdr_emit2_tx_exec";
13263 : 0 : case INSTR_HDR_EMIT3_TX: return "__instr_hdr_emit3_tx_exec";
13264 : 0 : case INSTR_HDR_EMIT4_TX: return "__instr_hdr_emit4_tx_exec";
13265 : 0 : case INSTR_HDR_EMIT5_TX: return "__instr_hdr_emit5_tx_exec";
13266 : 0 : case INSTR_HDR_EMIT6_TX: return "__instr_hdr_emit6_tx_exec";
13267 : 0 : case INSTR_HDR_EMIT7_TX: return "__instr_hdr_emit7_tx_exec";
13268 : 0 : case INSTR_HDR_EMIT8_TX: return "__instr_hdr_emit8_tx_exec";
13269 : :
13270 : 0 : case INSTR_HDR_VALIDATE: return "__instr_hdr_validate_exec";
13271 : 0 : case INSTR_HDR_INVALIDATE: return "__instr_hdr_invalidate_exec";
13272 : :
13273 : 0 : case INSTR_MOV: return "__instr_mov_exec";
13274 : 0 : case INSTR_MOV_MH: return "__instr_mov_mh_exec";
13275 : 0 : case INSTR_MOV_HM: return "__instr_mov_hm_exec";
13276 : 0 : case INSTR_MOV_HH: return "__instr_mov_hh_exec";
13277 : 0 : case INSTR_MOV_DMA: return "__instr_mov_dma_exec";
13278 : 0 : case INSTR_MOV_128: return "__instr_mov_128_exec";
13279 : 0 : case INSTR_MOV_128_64: return "__instr_mov_128_64_exec";
13280 : 0 : case INSTR_MOV_64_128: return "__instr_mov_64_128_exec";
13281 : 0 : case INSTR_MOV_128_32: return "__instr_mov_128_32_exec";
13282 : 0 : case INSTR_MOV_32_128: return "__instr_mov_32_128_exec";
13283 : 0 : case INSTR_MOV_I: return "__instr_mov_i_exec";
13284 : :
13285 : 0 : case INSTR_MOVH: return "__instr_movh_exec";
13286 : :
13287 : 0 : case INSTR_DMA_HT: return "__instr_dma_ht_exec";
13288 : 0 : case INSTR_DMA_HT2: return "__instr_dma_ht2_exec";
13289 : 0 : case INSTR_DMA_HT3: return "__instr_dma_ht3_exec";
13290 : 0 : case INSTR_DMA_HT4: return "__instr_dma_ht4_exec";
13291 : 0 : case INSTR_DMA_HT5: return "__instr_dma_ht5_exec";
13292 : 0 : case INSTR_DMA_HT6: return "__instr_dma_ht6_exec";
13293 : 0 : case INSTR_DMA_HT7: return "__instr_dma_ht7_exec";
13294 : 0 : case INSTR_DMA_HT8: return "__instr_dma_ht8_exec";
13295 : :
13296 : 0 : case INSTR_ALU_ADD: return "__instr_alu_add_exec";
13297 : 0 : case INSTR_ALU_ADD_MH: return "__instr_alu_add_mh_exec";
13298 : 0 : case INSTR_ALU_ADD_HM: return "__instr_alu_add_hm_exec";
13299 : 0 : case INSTR_ALU_ADD_HH: return "__instr_alu_add_hh_exec";
13300 : 0 : case INSTR_ALU_ADD_MI: return "__instr_alu_add_mi_exec";
13301 : 0 : case INSTR_ALU_ADD_HI: return "__instr_alu_add_hi_exec";
13302 : :
13303 : 0 : case INSTR_ALU_SUB: return "__instr_alu_sub_exec";
13304 : 0 : case INSTR_ALU_SUB_MH: return "__instr_alu_sub_mh_exec";
13305 : 0 : case INSTR_ALU_SUB_HM: return "__instr_alu_sub_hm_exec";
13306 : 0 : case INSTR_ALU_SUB_HH: return "__instr_alu_sub_hh_exec";
13307 : 0 : case INSTR_ALU_SUB_MI: return "__instr_alu_sub_mi_exec";
13308 : 0 : case INSTR_ALU_SUB_HI: return "__instr_alu_sub_hi_exec";
13309 : :
13310 : 0 : case INSTR_ALU_CKADD_FIELD: return "__instr_alu_ckadd_field_exec";
13311 : 0 : case INSTR_ALU_CKADD_STRUCT20: return "__instr_alu_ckadd_struct20_exec";
13312 : 0 : case INSTR_ALU_CKADD_STRUCT: return "__instr_alu_ckadd_struct_exec";
13313 : 0 : case INSTR_ALU_CKSUB_FIELD: return "__instr_alu_cksub_field_exec";
13314 : :
13315 : 0 : case INSTR_ALU_AND: return "__instr_alu_and_exec";
13316 : 0 : case INSTR_ALU_AND_MH: return "__instr_alu_and_mh_exec";
13317 : 0 : case INSTR_ALU_AND_HM: return "__instr_alu_and_hm_exec";
13318 : 0 : case INSTR_ALU_AND_HH: return "__instr_alu_and_hh_exec";
13319 : 0 : case INSTR_ALU_AND_I: return "__instr_alu_and_i_exec";
13320 : :
13321 : 0 : case INSTR_ALU_OR: return "__instr_alu_or_exec";
13322 : 0 : case INSTR_ALU_OR_MH: return "__instr_alu_or_mh_exec";
13323 : 0 : case INSTR_ALU_OR_HM: return "__instr_alu_or_hm_exec";
13324 : 0 : case INSTR_ALU_OR_HH: return "__instr_alu_or_hh_exec";
13325 : 0 : case INSTR_ALU_OR_I: return "__instr_alu_or_i_exec";
13326 : :
13327 : 0 : case INSTR_ALU_XOR: return "__instr_alu_xor_exec";
13328 : 0 : case INSTR_ALU_XOR_MH: return "__instr_alu_xor_mh_exec";
13329 : 0 : case INSTR_ALU_XOR_HM: return "__instr_alu_xor_hm_exec";
13330 : 0 : case INSTR_ALU_XOR_HH: return "__instr_alu_xor_hh_exec";
13331 : 0 : case INSTR_ALU_XOR_I: return "__instr_alu_xor_i_exec";
13332 : :
13333 : 0 : case INSTR_ALU_SHL: return "__instr_alu_shl_exec";
13334 : 0 : case INSTR_ALU_SHL_MH: return "__instr_alu_shl_mh_exec";
13335 : 0 : case INSTR_ALU_SHL_HM: return "__instr_alu_shl_hm_exec";
13336 : 0 : case INSTR_ALU_SHL_HH: return "__instr_alu_shl_hh_exec";
13337 : 0 : case INSTR_ALU_SHL_MI: return "__instr_alu_shl_mi_exec";
13338 : 0 : case INSTR_ALU_SHL_HI: return "__instr_alu_shl_hi_exec";
13339 : :
13340 : 0 : case INSTR_ALU_SHR: return "__instr_alu_shr_exec";
13341 : 0 : case INSTR_ALU_SHR_MH: return "__instr_alu_shr_mh_exec";
13342 : 0 : case INSTR_ALU_SHR_HM: return "__instr_alu_shr_hm_exec";
13343 : 0 : case INSTR_ALU_SHR_HH: return "__instr_alu_shr_hh_exec";
13344 : 0 : case INSTR_ALU_SHR_MI: return "__instr_alu_shr_mi_exec";
13345 : 0 : case INSTR_ALU_SHR_HI: return "__instr_alu_shr_hi_exec";
13346 : :
13347 : 0 : case INSTR_REGPREFETCH_RH: return "__instr_regprefetch_rh_exec";
13348 : 0 : case INSTR_REGPREFETCH_RM: return "__instr_regprefetch_rm_exec";
13349 : 0 : case INSTR_REGPREFETCH_RI: return "__instr_regprefetch_ri_exec";
13350 : :
13351 : 0 : case INSTR_REGRD_HRH: return "__instr_regrd_hrh_exec";
13352 : 0 : case INSTR_REGRD_HRM: return "__instr_regrd_hrm_exec";
13353 : 0 : case INSTR_REGRD_HRI: return "__instr_regrd_hri_exec";
13354 : 0 : case INSTR_REGRD_MRH: return "__instr_regrd_mrh_exec";
13355 : 0 : case INSTR_REGRD_MRM: return "__instr_regrd_mrm_exec";
13356 : 0 : case INSTR_REGRD_MRI: return "__instr_regrd_mri_exec";
13357 : :
13358 : 0 : case INSTR_REGWR_RHH: return "__instr_regwr_rhh_exec";
13359 : 0 : case INSTR_REGWR_RHM: return "__instr_regwr_rhm_exec";
13360 : 0 : case INSTR_REGWR_RHI: return "__instr_regwr_rhi_exec";
13361 : 0 : case INSTR_REGWR_RMH: return "__instr_regwr_rmh_exec";
13362 : 0 : case INSTR_REGWR_RMM: return "__instr_regwr_rmm_exec";
13363 : 0 : case INSTR_REGWR_RMI: return "__instr_regwr_rmi_exec";
13364 : 0 : case INSTR_REGWR_RIH: return "__instr_regwr_rih_exec";
13365 : 0 : case INSTR_REGWR_RIM: return "__instr_regwr_rim_exec";
13366 : 0 : case INSTR_REGWR_RII: return "__instr_regwr_rii_exec";
13367 : :
13368 : 0 : case INSTR_REGADD_RHH: return "__instr_regadd_rhh_exec";
13369 : 0 : case INSTR_REGADD_RHM: return "__instr_regadd_rhm_exec";
13370 : 0 : case INSTR_REGADD_RHI: return "__instr_regadd_rhi_exec";
13371 : 0 : case INSTR_REGADD_RMH: return "__instr_regadd_rmh_exec";
13372 : 0 : case INSTR_REGADD_RMM: return "__instr_regadd_rmm_exec";
13373 : 0 : case INSTR_REGADD_RMI: return "__instr_regadd_rmi_exec";
13374 : 0 : case INSTR_REGADD_RIH: return "__instr_regadd_rih_exec";
13375 : 0 : case INSTR_REGADD_RIM: return "__instr_regadd_rim_exec";
13376 : 0 : case INSTR_REGADD_RII: return "__instr_regadd_rii_exec";
13377 : :
13378 : 0 : case INSTR_METPREFETCH_H: return "__instr_metprefetch_h_exec";
13379 : 0 : case INSTR_METPREFETCH_M: return "__instr_metprefetch_m_exec";
13380 : 0 : case INSTR_METPREFETCH_I: return "__instr_metprefetch_i_exec";
13381 : :
13382 : 0 : case INSTR_METER_HHM: return "__instr_meter_hhm_exec";
13383 : 0 : case INSTR_METER_HHI: return "__instr_meter_hhi_exec";
13384 : 0 : case INSTR_METER_HMM: return "__instr_meter_hmm_exec";
13385 : 0 : case INSTR_METER_HMI: return "__instr_meter_hmi_exec";
13386 : 0 : case INSTR_METER_MHM: return "__instr_meter_mhm_exec";
13387 : 0 : case INSTR_METER_MHI: return "__instr_meter_mhi_exec";
13388 : 0 : case INSTR_METER_MMM: return "__instr_meter_mmm_exec";
13389 : 0 : case INSTR_METER_MMI: return "__instr_meter_mmi_exec";
13390 : 0 : case INSTR_METER_IHM: return "__instr_meter_ihm_exec";
13391 : 0 : case INSTR_METER_IHI: return "__instr_meter_ihi_exec";
13392 : 0 : case INSTR_METER_IMM: return "__instr_meter_imm_exec";
13393 : 0 : case INSTR_METER_IMI: return "__instr_meter_imi_exec";
13394 : :
13395 : : case INSTR_TABLE: return NULL;
13396 : : case INSTR_TABLE_AF: return NULL;
13397 : : case INSTR_SELECTOR: return NULL;
13398 : : case INSTR_LEARNER: return NULL;
13399 : : case INSTR_LEARNER_AF: return NULL;
13400 : :
13401 : 0 : case INSTR_LEARNER_LEARN: return "__instr_learn_exec";
13402 : 0 : case INSTR_LEARNER_REARM: return "__instr_rearm_exec";
13403 : 0 : case INSTR_LEARNER_REARM_NEW: return "__instr_rearm_new_exec";
13404 : 0 : case INSTR_LEARNER_FORGET: return "__instr_forget_exec";
13405 : 0 : case INSTR_ENTRYID: return "__instr_entryid_exec";
13406 : :
13407 : : case INSTR_EXTERN_OBJ: return NULL;
13408 : : case INSTR_EXTERN_FUNC: return NULL;
13409 : 0 : case INSTR_HASH_FUNC: return "__instr_hash_func_exec";
13410 : 0 : case INSTR_RSS: return "__instr_rss_exec";
13411 : :
13412 : : case INSTR_JMP: return NULL;
13413 : : case INSTR_JMP_VALID: return NULL;
13414 : : case INSTR_JMP_INVALID: return NULL;
13415 : : case INSTR_JMP_HIT: return NULL;
13416 : : case INSTR_JMP_MISS: return NULL;
13417 : : case INSTR_JMP_ACTION_HIT: return NULL;
13418 : : case INSTR_JMP_ACTION_MISS: return NULL;
13419 : : case INSTR_JMP_EQ: return NULL;
13420 : : case INSTR_JMP_EQ_MH: return NULL;
13421 : : case INSTR_JMP_EQ_HM: return NULL;
13422 : : case INSTR_JMP_EQ_HH: return NULL;
13423 : : case INSTR_JMP_EQ_I: return NULL;
13424 : : case INSTR_JMP_NEQ: return NULL;
13425 : : case INSTR_JMP_NEQ_MH: return NULL;
13426 : : case INSTR_JMP_NEQ_HM: return NULL;
13427 : : case INSTR_JMP_NEQ_HH: return NULL;
13428 : : case INSTR_JMP_NEQ_I: return NULL;
13429 : : case INSTR_JMP_LT: return NULL;
13430 : : case INSTR_JMP_LT_MH: return NULL;
13431 : : case INSTR_JMP_LT_HM: return NULL;
13432 : : case INSTR_JMP_LT_HH: return NULL;
13433 : : case INSTR_JMP_LT_MI: return NULL;
13434 : : case INSTR_JMP_LT_HI: return NULL;
13435 : : case INSTR_JMP_GT: return NULL;
13436 : : case INSTR_JMP_GT_MH: return NULL;
13437 : : case INSTR_JMP_GT_HM: return NULL;
13438 : : case INSTR_JMP_GT_HH: return NULL;
13439 : : case INSTR_JMP_GT_MI: return NULL;
13440 : : case INSTR_JMP_GT_HI: return NULL;
13441 : :
13442 : : case INSTR_RETURN: return NULL;
13443 : :
13444 : : default: return NULL;
13445 : : }
13446 : : }
13447 : :
13448 : : static void
13449 : 0 : action_instr_does_tx_codegen(struct action *a,
13450 : : uint32_t instr_pos,
13451 : : struct instruction *instr,
13452 : : FILE *f)
13453 : : {
13454 : 0 : fprintf(f,
13455 : : "%s(p, t, &action_%s_instructions[%u]);\n"
13456 : : "\tthread_ip_reset(p, t);\n"
13457 : : "\tinstr_rx_exec(p);\n"
13458 : : "\treturn;\n",
13459 : : instr_type_to_func(instr),
13460 : 0 : a->name,
13461 : : instr_pos);
13462 : 0 : }
13463 : :
13464 : : static void
13465 : : action_instr_extern_obj_codegen(struct action *a,
13466 : : uint32_t instr_pos,
13467 : : FILE *f)
13468 : : {
13469 : : fprintf(f,
13470 : : "while (!__instr_extern_obj_exec(p, t, &action_%s_instructions[%u]));\n",
13471 : : a->name,
13472 : : instr_pos);
13473 : : }
13474 : :
13475 : : static void
13476 : : action_instr_extern_func_codegen(struct action *a,
13477 : : uint32_t instr_pos,
13478 : : FILE *f)
13479 : : {
13480 : : fprintf(f,
13481 : : "while (!__instr_extern_func_exec(p, t, &action_%s_instructions[%u]));\n",
13482 : : a->name,
13483 : : instr_pos);
13484 : : }
13485 : :
13486 : : static void
13487 : 0 : action_instr_jmp_codegen(struct action *a,
13488 : : uint32_t instr_pos,
13489 : : struct instruction *instr,
13490 : : struct instruction_data *data,
13491 : : FILE *f)
13492 : : {
13493 [ # # # # : 0 : switch (instr->type) {
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
13494 : 0 : case INSTR_JMP:
13495 : : fprintf(f,
13496 : : "goto %s;\n",
13497 : 0 : data->jmp_label);
13498 : : return;
13499 : :
13500 : 0 : case INSTR_JMP_VALID:
13501 : : fprintf(f,
13502 : : "if (HEADER_VALID(t, action_%s_instructions[%u].jmp.header_id))\n"
13503 : : "\t\tgoto %s;\n",
13504 : 0 : a->name,
13505 : : instr_pos,
13506 : 0 : data->jmp_label);
13507 : : return;
13508 : :
13509 : 0 : case INSTR_JMP_INVALID:
13510 : : fprintf(f,
13511 : : "if (!HEADER_VALID(t, action_%s_instructions[%u].jmp.header_id))\n"
13512 : : "\t\tgoto %s;\n",
13513 : 0 : a->name,
13514 : : instr_pos,
13515 : 0 : data->jmp_label);
13516 : : return;
13517 : :
13518 : 0 : case INSTR_JMP_HIT:
13519 : : fprintf(f,
13520 : : "if (t->hit)\n"
13521 : : "\t\tgoto %s;\n",
13522 : 0 : data->jmp_label);
13523 : : return;
13524 : :
13525 : 0 : case INSTR_JMP_MISS:
13526 : : fprintf(f,
13527 : : "if (!t->hit)\n"
13528 : : "\t\tgoto %s;\n",
13529 : 0 : data->jmp_label);
13530 : : return;
13531 : :
13532 : 0 : case INSTR_JMP_ACTION_HIT:
13533 : : fprintf(f,
13534 : : "if (t->action_id == action_%s_instructions[%u].jmp.action_id)\n"
13535 : : "\t\tgoto %s;\n",
13536 : 0 : a->name,
13537 : : instr_pos,
13538 : 0 : data->jmp_label);
13539 : : return;
13540 : :
13541 : 0 : case INSTR_JMP_ACTION_MISS:
13542 : : fprintf(f,
13543 : : "if (t->action_id != action_%s_instructions[%u].jmp.action_id)\n"
13544 : : "\t\tgoto %s;\n",
13545 : 0 : a->name,
13546 : : instr_pos,
13547 : 0 : data->jmp_label);
13548 : : return;
13549 : :
13550 : 0 : case INSTR_JMP_EQ:
13551 : : fprintf(f,
13552 : : "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) == "
13553 : : "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
13554 : : "\t\tgoto %s;\n",
13555 : : a->name,
13556 : : instr_pos,
13557 : 0 : a->name,
13558 : : instr_pos,
13559 : 0 : data->jmp_label);
13560 : : return;
13561 : :
13562 : 0 : case INSTR_JMP_EQ_MH:
13563 : : fprintf(f,
13564 : : "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) == "
13565 : : "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
13566 : : "\t\tgoto %s;\n",
13567 : : a->name,
13568 : : instr_pos,
13569 : 0 : a->name,
13570 : : instr_pos,
13571 : 0 : data->jmp_label);
13572 : : return;
13573 : :
13574 : 0 : case INSTR_JMP_EQ_HM:
13575 : : fprintf(f,
13576 : : "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) == "
13577 : : "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
13578 : : "\t\tgoto %s;\n",
13579 : : a->name,
13580 : : instr_pos,
13581 : 0 : a->name,
13582 : : instr_pos,
13583 : 0 : data->jmp_label);
13584 : : return;
13585 : :
13586 : 0 : case INSTR_JMP_EQ_HH:
13587 : : fprintf(f,
13588 : : "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) == "
13589 : : "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
13590 : : "\t\tgoto %s;\n",
13591 : : a->name,
13592 : : instr_pos,
13593 : 0 : a->name,
13594 : : instr_pos,
13595 : 0 : data->jmp_label);
13596 : : return;
13597 : :
13598 : 0 : case INSTR_JMP_EQ_I:
13599 : : fprintf(f,
13600 : : "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) == "
13601 : : "action_%s_instructions[%u].jmp.b_val)\n"
13602 : : "\t\tgoto %s;\n",
13603 : : a->name,
13604 : : instr_pos,
13605 : 0 : a->name,
13606 : : instr_pos,
13607 : 0 : data->jmp_label);
13608 : : return;
13609 : :
13610 : 0 : case INSTR_JMP_NEQ:
13611 : : fprintf(f,
13612 : : "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) != "
13613 : : "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
13614 : : "\t\tgoto %s;\n",
13615 : : a->name,
13616 : : instr_pos,
13617 : 0 : a->name,
13618 : : instr_pos,
13619 : 0 : data->jmp_label);
13620 : : return;
13621 : :
13622 : 0 : case INSTR_JMP_NEQ_MH:
13623 : : fprintf(f,
13624 : : "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) != "
13625 : : "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
13626 : : "\t\tgoto %s;\n",
13627 : : a->name,
13628 : : instr_pos,
13629 : 0 : a->name,
13630 : : instr_pos,
13631 : 0 : data->jmp_label);
13632 : : return;
13633 : :
13634 : 0 : case INSTR_JMP_NEQ_HM:
13635 : : fprintf(f,
13636 : : "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) != "
13637 : : "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
13638 : : "\t\tgoto %s;\n",
13639 : : a->name,
13640 : : instr_pos,
13641 : 0 : a->name,
13642 : : instr_pos,
13643 : 0 : data->jmp_label);
13644 : : return;
13645 : :
13646 : 0 : case INSTR_JMP_NEQ_HH:
13647 : : fprintf(f,
13648 : : "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) != "
13649 : : "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
13650 : : "\t\tgoto %s;\n",
13651 : : a->name,
13652 : : instr_pos,
13653 : 0 : a->name,
13654 : : instr_pos,
13655 : 0 : data->jmp_label);
13656 : : return;
13657 : :
13658 : 0 : case INSTR_JMP_NEQ_I:
13659 : : fprintf(f,
13660 : : "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) != "
13661 : : "action_%s_instructions[%u].jmp.b_val)\n"
13662 : : "\t\tgoto %s;\n",
13663 : : a->name,
13664 : : instr_pos,
13665 : 0 : a->name,
13666 : : instr_pos,
13667 : 0 : data->jmp_label);
13668 : : return;
13669 : :
13670 : 0 : case INSTR_JMP_LT:
13671 : : fprintf(f,
13672 : : "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) < "
13673 : : "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
13674 : : "\t\tgoto %s;\n",
13675 : : a->name,
13676 : : instr_pos,
13677 : 0 : a->name,
13678 : : instr_pos,
13679 : 0 : data->jmp_label);
13680 : : return;
13681 : :
13682 : 0 : case INSTR_JMP_LT_MH:
13683 : : fprintf(f,
13684 : : "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) < "
13685 : : "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
13686 : : "\t\tgoto %s;\n",
13687 : : a->name,
13688 : : instr_pos,
13689 : 0 : a->name,
13690 : : instr_pos,
13691 : 0 : data->jmp_label);
13692 : : return;
13693 : :
13694 : 0 : case INSTR_JMP_LT_HM:
13695 : : fprintf(f,
13696 : : "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) < "
13697 : : "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
13698 : : "\t\tgoto %s;\n",
13699 : : a->name,
13700 : : instr_pos,
13701 : 0 : a->name,
13702 : : instr_pos,
13703 : 0 : data->jmp_label);
13704 : : return;
13705 : :
13706 : 0 : case INSTR_JMP_LT_HH:
13707 : : fprintf(f,
13708 : : "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) < "
13709 : : "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
13710 : : "\t\tgoto %s;\n",
13711 : : a->name,
13712 : : instr_pos,
13713 : 0 : a->name,
13714 : : instr_pos,
13715 : 0 : data->jmp_label);
13716 : : return;
13717 : :
13718 : 0 : case INSTR_JMP_LT_MI:
13719 : : fprintf(f,
13720 : : "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) < "
13721 : : "action_%s_instructions[%u].jmp.b_val)\n"
13722 : : "\t\tgoto %s;\n",
13723 : : a->name,
13724 : : instr_pos,
13725 : 0 : a->name,
13726 : : instr_pos,
13727 : 0 : data->jmp_label);
13728 : : return;
13729 : :
13730 : 0 : case INSTR_JMP_LT_HI:
13731 : : fprintf(f,
13732 : : "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) < "
13733 : : "action_%s_instructions[%u].jmp.b_val)\n"
13734 : : "\t\tgoto %s;\n",
13735 : : a->name,
13736 : : instr_pos,
13737 : 0 : a->name,
13738 : : instr_pos,
13739 : 0 : data->jmp_label);
13740 : : return;
13741 : :
13742 : 0 : case INSTR_JMP_GT:
13743 : : fprintf(f,
13744 : : "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) > "
13745 : : "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
13746 : : "\t\tgoto %s;\n",
13747 : : a->name,
13748 : : instr_pos,
13749 : 0 : a->name,
13750 : : instr_pos,
13751 : 0 : data->jmp_label);
13752 : : return;
13753 : :
13754 : 0 : case INSTR_JMP_GT_MH:
13755 : : fprintf(f,
13756 : : "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) > "
13757 : : "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
13758 : : "\t\tgoto %s;\n",
13759 : : a->name,
13760 : : instr_pos,
13761 : 0 : a->name,
13762 : : instr_pos,
13763 : 0 : data->jmp_label);
13764 : : return;
13765 : :
13766 : 0 : case INSTR_JMP_GT_HM:
13767 : : fprintf(f,
13768 : : "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) > "
13769 : : "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
13770 : : "\t\tgoto %s;\n",
13771 : : a->name,
13772 : : instr_pos,
13773 : 0 : a->name,
13774 : : instr_pos,
13775 : 0 : data->jmp_label);
13776 : : return;
13777 : :
13778 : 0 : case INSTR_JMP_GT_HH:
13779 : : fprintf(f,
13780 : : "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) > "
13781 : : "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
13782 : : "\t\tgoto %s;\n",
13783 : : a->name,
13784 : : instr_pos,
13785 : 0 : a->name,
13786 : : instr_pos,
13787 : 0 : data->jmp_label);
13788 : : return;
13789 : :
13790 : 0 : case INSTR_JMP_GT_MI:
13791 : : fprintf(f,
13792 : : "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) > "
13793 : : "action_%s_instructions[%u].jmp.b_val)\n"
13794 : : "\t\tgoto %s;\n",
13795 : : a->name,
13796 : : instr_pos,
13797 : 0 : a->name,
13798 : : instr_pos,
13799 : 0 : data->jmp_label);
13800 : : return;
13801 : :
13802 : 0 : case INSTR_JMP_GT_HI:
13803 : : fprintf(f,
13804 : : "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) > "
13805 : : "action_%s_instructions[%u].jmp.b_val)\n"
13806 : : "\t\tgoto %s;\n",
13807 : : a->name,
13808 : : instr_pos,
13809 : 0 : a->name,
13810 : : instr_pos,
13811 : 0 : data->jmp_label);
13812 : : return;
13813 : :
13814 : : default:
13815 : : return;
13816 : : }
13817 : : }
13818 : :
13819 : : static void
13820 : : action_instr_return_codegen(FILE *f)
13821 : : {
13822 : : fprintf(f,
13823 : : "return;\n");
13824 : : }
13825 : :
13826 : : static void
13827 : 0 : action_instr_codegen(struct action *a, FILE *f)
13828 : : {
13829 : : uint32_t i;
13830 : :
13831 : : fprintf(f,
13832 : : "void\n"
13833 : : "action_%s_run(struct rte_swx_pipeline *p)\n"
13834 : : "{\n"
13835 : : "\tstruct thread *t = &p->threads[p->thread_id];\n"
13836 : : "\n",
13837 : 0 : a->name);
13838 : :
13839 [ # # ]: 0 : for (i = 0; i < a->n_instructions; i++) {
13840 : 0 : struct instruction *instr = &a->instructions[i];
13841 : 0 : struct instruction_data *data = &a->instruction_data[i];
13842 : :
13843 : : /* Label, if present. */
13844 [ # # ]: 0 : if (data->label[0])
13845 : 0 : fprintf(f, "\n%s : ", data->label);
13846 : : else
13847 : : fprintf(f, "\n\t");
13848 : :
13849 : : /* TX instruction type. */
13850 : 0 : if (instruction_does_tx(instr)) {
13851 : 0 : action_instr_does_tx_codegen(a, i, instr, f);
13852 : 0 : continue;
13853 : : }
13854 : :
13855 : : /* Extern object/function instruction type. */
13856 [ # # ]: 0 : if (instr->type == INSTR_EXTERN_OBJ) {
13857 : : action_instr_extern_obj_codegen(a, i, f);
13858 : 0 : continue;
13859 : : }
13860 : :
13861 [ # # ]: 0 : if (instr->type == INSTR_EXTERN_FUNC) {
13862 : : action_instr_extern_func_codegen(a, i, f);
13863 : 0 : continue;
13864 : : }
13865 : :
13866 : : /* Jump instruction type. */
13867 : 0 : if (instruction_is_jmp(instr)) {
13868 : 0 : action_instr_jmp_codegen(a, i, instr, data, f);
13869 : 0 : continue;
13870 : : }
13871 : :
13872 : : /* Return instruction type. */
13873 [ # # ]: 0 : if (instr->type == INSTR_RETURN) {
13874 : : action_instr_return_codegen(f);
13875 : 0 : continue;
13876 : : }
13877 : :
13878 : : /* Any other instruction type. */
13879 : 0 : fprintf(f,
13880 : : "%s(p, t, &action_%s_instructions[%u]);\n",
13881 : : instr_type_to_func(instr),
13882 : : a->name,
13883 : : i);
13884 : : }
13885 : :
13886 : : fprintf(f, "}\n\n");
13887 : 0 : }
13888 : :
13889 : : struct instruction_group {
13890 : : TAILQ_ENTRY(instruction_group) node;
13891 : :
13892 : : uint32_t group_id;
13893 : :
13894 : : uint32_t first_instr_id;
13895 : :
13896 : : uint32_t last_instr_id;
13897 : :
13898 : : instr_exec_t func;
13899 : : };
13900 : :
13901 : : TAILQ_HEAD(instruction_group_list, instruction_group);
13902 : :
13903 : : static struct instruction_group *
13904 : : instruction_group_list_group_find(struct instruction_group_list *igl, uint32_t instruction_id)
13905 : : {
13906 : : struct instruction_group *g;
13907 : :
13908 [ # # # # : 0 : TAILQ_FOREACH(g, igl, node)
# # # # ]
13909 [ # # # # : 0 : if ((g->first_instr_id <= instruction_id) && (instruction_id <= g->last_instr_id))
# # # # #
# # # # #
# # ]
13910 : : return g;
13911 : :
13912 : : return NULL;
13913 : : }
13914 : :
13915 : : static void
13916 : 0 : instruction_group_list_free(struct instruction_group_list *igl)
13917 : : {
13918 [ # # ]: 0 : if (!igl)
13919 : : return;
13920 : :
13921 : 0 : for ( ; ; ) {
13922 : : struct instruction_group *g;
13923 : :
13924 : 0 : g = TAILQ_FIRST(igl);
13925 [ # # ]: 0 : if (!g)
13926 : : break;
13927 : :
13928 [ # # ]: 0 : TAILQ_REMOVE(igl, g, node);
13929 : 0 : free(g);
13930 : : }
13931 : :
13932 : 0 : free(igl);
13933 : : }
13934 : :
13935 : : static struct instruction_group_list *
13936 : 0 : instruction_group_list_create(struct rte_swx_pipeline *p)
13937 : : {
13938 : : struct instruction_group_list *igl = NULL;
13939 : : struct instruction_group *g = NULL;
13940 : : uint32_t n_groups = 0, i;
13941 : :
13942 [ # # # # : 0 : if (!p || !p->instructions || !p->instruction_data || !p->n_instructions)
# # # # ]
13943 : 0 : goto error;
13944 : :
13945 : : /* List init. */
13946 : 0 : igl = calloc(1, sizeof(struct instruction_group_list));
13947 [ # # ]: 0 : if (!igl)
13948 : 0 : goto error;
13949 : :
13950 : 0 : TAILQ_INIT(igl);
13951 : :
13952 : : /* Allocate the first group. */
13953 : 0 : g = calloc(1, sizeof(struct instruction_group));
13954 [ # # ]: 0 : if (!g)
13955 : 0 : goto error;
13956 : :
13957 : : /* Iteration 1: Separate the instructions into groups based on the thread yield
13958 : : * instructions. Do not worry about the jump instructions at this point.
13959 : : */
13960 [ # # ]: 0 : for (i = 0; i < p->n_instructions; i++) {
13961 [ # # ]: 0 : struct instruction *instr = &p->instructions[i];
13962 : :
13963 : : /* Check for thread yield instructions. */
13964 : 0 : if (!instruction_does_thread_yield(instr))
13965 : 0 : continue;
13966 : :
13967 : : /* If the current group contains at least one instruction, then finalize it (with
13968 : : * the previous instruction), add it to the list and allocate a new group (that
13969 : : * starts with the current instruction).
13970 : : */
13971 [ # # ]: 0 : if (i - g->first_instr_id) {
13972 : : /* Finalize the group. */
13973 : 0 : g->last_instr_id = i - 1;
13974 : :
13975 : : /* Add the group to the list. Advance the number of groups. */
13976 : 0 : TAILQ_INSERT_TAIL(igl, g, node);
13977 : 0 : n_groups++;
13978 : :
13979 : : /* Allocate a new group. */
13980 : 0 : g = calloc(1, sizeof(struct instruction_group));
13981 [ # # ]: 0 : if (!g)
13982 : 0 : goto error;
13983 : :
13984 : : /* Initialize the new group. */
13985 : 0 : g->group_id = n_groups;
13986 : 0 : g->first_instr_id = i;
13987 : : }
13988 : :
13989 : : /* Finalize the current group (with the current instruction, therefore this group
13990 : : * contains just the current thread yield instruction), add it to the list and
13991 : : * allocate a new group (that starts with the next instruction).
13992 : : */
13993 : :
13994 : : /* Finalize the group. */
13995 : 0 : g->last_instr_id = i;
13996 : :
13997 : : /* Add the group to the list. Advance the number of groups. */
13998 : 0 : TAILQ_INSERT_TAIL(igl, g, node);
13999 : 0 : n_groups++;
14000 : :
14001 : : /* Allocate a new group. */
14002 : 0 : g = calloc(1, sizeof(struct instruction_group));
14003 [ # # ]: 0 : if (!g)
14004 : 0 : goto error;
14005 : :
14006 : : /* Initialize the new group. */
14007 : 0 : g->group_id = n_groups;
14008 : 0 : g->first_instr_id = i + 1;
14009 : : }
14010 : :
14011 : : /* Handle the last group. */
14012 [ # # ]: 0 : if (i - g->first_instr_id) {
14013 : : /* Finalize the group. */
14014 : 0 : g->last_instr_id = i - 1;
14015 : :
14016 : : /* Add the group to the list. Advance the number of groups. */
14017 : 0 : TAILQ_INSERT_TAIL(igl, g, node);
14018 : 0 : n_groups++;
14019 : : } else
14020 : 0 : free(g);
14021 : :
14022 : : g = NULL;
14023 : :
14024 : : /* Iteration 2: Handle jumps. If the current group contains an instruction which represents
14025 : : * the destination of a jump instruction located in a different group ("far jump"), then the
14026 : : * current group has to be split, so that the instruction representing the far jump
14027 : : * destination is at the start of its group.
14028 : : */
14029 : : for ( ; ; ) {
14030 : : int is_modified = 0;
14031 : :
14032 [ # # ]: 0 : for (i = 0; i < p->n_instructions; i++) {
14033 : 0 : struct instruction_data *data = &p->instruction_data[i];
14034 : : struct instruction_group *g;
14035 : : uint32_t j;
14036 : :
14037 : : /* Continue when the current instruction is not a jump destination. */
14038 [ # # ]: 0 : if (!data->n_users)
14039 : 0 : continue;
14040 : :
14041 : : g = instruction_group_list_group_find(igl, i);
14042 [ # # ]: 0 : if (!g)
14043 : 0 : goto error;
14044 : :
14045 : : /* Find out all the jump instructions with this destination. */
14046 [ # # ]: 0 : for (j = 0; j < p->n_instructions; j++) {
14047 : 0 : struct instruction *jmp_instr = &p->instructions[j];
14048 [ # # ]: 0 : struct instruction_data *jmp_data = &p->instruction_data[j];
14049 : : struct instruction_group *jmp_g, *new_g;
14050 : :
14051 : : /* Continue when not a jump instruction. Even when jump instruction,
14052 : : * continue when the jump destination is not this instruction.
14053 : : */
14054 : 0 : if (!instruction_is_jmp(jmp_instr) ||
14055 [ # # ]: 0 : strcmp(jmp_data->jmp_label, data->label))
14056 : 0 : continue;
14057 : :
14058 : : jmp_g = instruction_group_list_group_find(igl, j);
14059 [ # # ]: 0 : if (!jmp_g)
14060 : 0 : goto error;
14061 : :
14062 : : /* Continue when both the jump instruction and the jump destination
14063 : : * instruction are in the same group. Even when in different groups,
14064 : : * still continue if the jump destination instruction is already the
14065 : : * first instruction of its group.
14066 : : */
14067 [ # # # # ]: 0 : if ((jmp_g->group_id == g->group_id) || (g->first_instr_id == i))
14068 : 0 : continue;
14069 : :
14070 : : /* Split the group of the current jump destination instruction to
14071 : : * make this instruction the first instruction of a new group.
14072 : : */
14073 : 0 : new_g = calloc(1, sizeof(struct instruction_group));
14074 [ # # ]: 0 : if (!new_g)
14075 : 0 : goto error;
14076 : :
14077 : 0 : new_g->group_id = n_groups;
14078 : 0 : new_g->first_instr_id = i;
14079 : 0 : new_g->last_instr_id = g->last_instr_id;
14080 : :
14081 : 0 : g->last_instr_id = i - 1;
14082 : :
14083 [ # # ]: 0 : TAILQ_INSERT_AFTER(igl, g, new_g, node);
14084 : 0 : n_groups++;
14085 : : is_modified = 1;
14086 : :
14087 : : /* The decision to split this group (to make the current instruction
14088 : : * the first instruction of a new group) is already taken and fully
14089 : : * implemented, so no need to search for more reasons to do it.
14090 : : */
14091 : 0 : break;
14092 : : }
14093 : : }
14094 : :
14095 : : /* Re-evaluate everything, as at least one group got split, so some jumps that were
14096 : : * previously considered local (i.e. the jump destination is in the same group as
14097 : : * the jump instruction) can now be "far jumps" (i.e. the jump destination is in a
14098 : : * different group than the jump instruction). Wost case scenario: each instruction
14099 : : * that is a jump destination ends up as the first instruction of its group.
14100 : : */
14101 [ # # ]: 0 : if (!is_modified)
14102 : : break;
14103 : : }
14104 : :
14105 : : /* Re-assign the group IDs to be in incremental order. */
14106 : : i = 0;
14107 [ # # ]: 0 : TAILQ_FOREACH(g, igl, node) {
14108 : 0 : g->group_id = i;
14109 : :
14110 : 0 : i++;
14111 : : }
14112 : :
14113 : : return igl;
14114 : :
14115 : 0 : error:
14116 : 0 : instruction_group_list_free(igl);
14117 : :
14118 : : free(g);
14119 : :
14120 : 0 : return NULL;
14121 : : }
14122 : :
14123 : : static void
14124 : : pipeline_instr_does_tx_codegen(struct rte_swx_pipeline *p __rte_unused,
14125 : : uint32_t instr_pos,
14126 : : struct instruction *instr,
14127 : : FILE *f)
14128 : : {
14129 : 0 : fprintf(f,
14130 : : "%s(p, t, &pipeline_instructions[%u]);\n"
14131 : : "\tthread_ip_reset(p, t);\n"
14132 : : "\tinstr_rx_exec(p);\n"
14133 : : "\treturn;\n",
14134 : : instr_type_to_func(instr),
14135 : : instr_pos);
14136 : : }
14137 : :
14138 : : static int
14139 : 0 : pipeline_instr_jmp_codegen(struct rte_swx_pipeline *p,
14140 : : struct instruction_group_list *igl,
14141 : : uint32_t jmp_instr_id,
14142 : : struct instruction *jmp_instr,
14143 : : struct instruction_data *jmp_data,
14144 : : FILE *f)
14145 : : {
14146 : : struct instruction_group *jmp_g, *g;
14147 : : struct instruction_data *data;
14148 : : uint32_t instr_id;
14149 : :
14150 [ # # # # : 0 : switch (jmp_instr->type) {
# # # # #
# # # # #
# # # # #
# # # # #
# # # #
# ]
14151 : : case INSTR_JMP:
14152 : : break;
14153 : :
14154 : : case INSTR_JMP_VALID:
14155 : : fprintf(f,
14156 : : "if (HEADER_VALID(t, pipeline_instructions[%u].jmp.header_id))",
14157 : : jmp_instr_id);
14158 : : break;
14159 : :
14160 : : case INSTR_JMP_INVALID:
14161 : : fprintf(f,
14162 : : "if (!HEADER_VALID(t, pipeline_instructions[%u].jmp.header_id))",
14163 : : jmp_instr_id);
14164 : : break;
14165 : :
14166 : : case INSTR_JMP_HIT:
14167 : : fprintf(f,
14168 : : "if (t->hit)\n");
14169 : : break;
14170 : :
14171 : : case INSTR_JMP_MISS:
14172 : : fprintf(f,
14173 : : "if (!t->hit)\n");
14174 : : break;
14175 : :
14176 : : case INSTR_JMP_ACTION_HIT:
14177 : : fprintf(f,
14178 : : "if (t->action_id == pipeline_instructions[%u].jmp.action_id)",
14179 : : jmp_instr_id);
14180 : : break;
14181 : :
14182 : : case INSTR_JMP_ACTION_MISS:
14183 : : fprintf(f,
14184 : : "if (t->action_id != pipeline_instructions[%u].jmp.action_id)",
14185 : : jmp_instr_id);
14186 : : break;
14187 : :
14188 : : case INSTR_JMP_EQ:
14189 : : fprintf(f,
14190 : : "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) == "
14191 : : "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
14192 : : jmp_instr_id,
14193 : : jmp_instr_id);
14194 : : break;
14195 : :
14196 : : case INSTR_JMP_EQ_MH:
14197 : : fprintf(f,
14198 : : "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) == "
14199 : : "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
14200 : : jmp_instr_id,
14201 : : jmp_instr_id);
14202 : : break;
14203 : :
14204 : : case INSTR_JMP_EQ_HM:
14205 : : fprintf(f,
14206 : : "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) == "
14207 : : "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
14208 : : jmp_instr_id,
14209 : : jmp_instr_id);
14210 : : break;
14211 : :
14212 : : case INSTR_JMP_EQ_HH:
14213 : : fprintf(f,
14214 : : "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) == "
14215 : : "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
14216 : : jmp_instr_id,
14217 : : jmp_instr_id);
14218 : : break;
14219 : :
14220 : : case INSTR_JMP_EQ_I:
14221 : : fprintf(f,
14222 : : "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) == "
14223 : : "pipeline_instructions[%u].jmp.b_val)",
14224 : : jmp_instr_id,
14225 : : jmp_instr_id);
14226 : : break;
14227 : :
14228 : : case INSTR_JMP_NEQ:
14229 : : fprintf(f,
14230 : : "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) != "
14231 : : "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
14232 : : jmp_instr_id,
14233 : : jmp_instr_id);
14234 : : break;
14235 : :
14236 : : case INSTR_JMP_NEQ_MH:
14237 : : fprintf(f,
14238 : : "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) != "
14239 : : "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
14240 : : jmp_instr_id,
14241 : : jmp_instr_id);
14242 : : break;
14243 : :
14244 : : case INSTR_JMP_NEQ_HM:
14245 : : fprintf(f,
14246 : : "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) != "
14247 : : "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
14248 : : jmp_instr_id,
14249 : : jmp_instr_id);
14250 : : break;
14251 : :
14252 : : case INSTR_JMP_NEQ_HH:
14253 : : fprintf(f,
14254 : : "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) != "
14255 : : "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
14256 : : jmp_instr_id,
14257 : : jmp_instr_id);
14258 : : break;
14259 : :
14260 : : case INSTR_JMP_NEQ_I:
14261 : : fprintf(f,
14262 : : "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) != "
14263 : : "pipeline_instructions[%u].jmp.b_val)",
14264 : : jmp_instr_id,
14265 : : jmp_instr_id);
14266 : : break;
14267 : :
14268 : : case INSTR_JMP_LT:
14269 : : fprintf(f,
14270 : : "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) < "
14271 : : "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
14272 : : jmp_instr_id,
14273 : : jmp_instr_id);
14274 : : break;
14275 : :
14276 : : case INSTR_JMP_LT_MH:
14277 : : fprintf(f,
14278 : : "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) < "
14279 : : "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
14280 : : jmp_instr_id,
14281 : : jmp_instr_id);
14282 : : break;
14283 : :
14284 : : case INSTR_JMP_LT_HM:
14285 : : fprintf(f,
14286 : : "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) < "
14287 : : "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
14288 : : jmp_instr_id,
14289 : : jmp_instr_id);
14290 : : break;
14291 : :
14292 : : case INSTR_JMP_LT_HH:
14293 : : fprintf(f,
14294 : : "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) < "
14295 : : "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
14296 : : jmp_instr_id,
14297 : : jmp_instr_id);
14298 : : break;
14299 : :
14300 : : case INSTR_JMP_LT_MI:
14301 : : fprintf(f,
14302 : : "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) < "
14303 : : "pipeline_instructions[%u].jmp.b_val)",
14304 : : jmp_instr_id,
14305 : : jmp_instr_id);
14306 : : break;
14307 : :
14308 : : case INSTR_JMP_LT_HI:
14309 : : fprintf(f,
14310 : : "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) < "
14311 : : "pipeline_instructions[%u].jmp.b_val)",
14312 : : jmp_instr_id,
14313 : : jmp_instr_id);
14314 : : break;
14315 : :
14316 : : case INSTR_JMP_GT:
14317 : : fprintf(f,
14318 : : "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) > "
14319 : : "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
14320 : : jmp_instr_id,
14321 : : jmp_instr_id);
14322 : : break;
14323 : :
14324 : : case INSTR_JMP_GT_MH:
14325 : : fprintf(f,
14326 : : "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) > "
14327 : : "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
14328 : : jmp_instr_id,
14329 : : jmp_instr_id);
14330 : : break;
14331 : :
14332 : : case INSTR_JMP_GT_HM:
14333 : : fprintf(f,
14334 : : "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) > "
14335 : : "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
14336 : : jmp_instr_id,
14337 : : jmp_instr_id);
14338 : : break;
14339 : :
14340 : : case INSTR_JMP_GT_HH:
14341 : : fprintf(f,
14342 : : "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) > "
14343 : : "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
14344 : : jmp_instr_id,
14345 : : jmp_instr_id);
14346 : : break;
14347 : :
14348 : : case INSTR_JMP_GT_MI:
14349 : : fprintf(f,
14350 : : "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) > "
14351 : : "pipeline_instructions[%u].jmp.b_val)",
14352 : : jmp_instr_id,
14353 : : jmp_instr_id);
14354 : : break;
14355 : :
14356 : : case INSTR_JMP_GT_HI:
14357 : : fprintf(f,
14358 : : "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) > "
14359 : : "pipeline_instructions[%u].jmp.b_val)",
14360 : : jmp_instr_id,
14361 : : jmp_instr_id);
14362 : : break;
14363 : :
14364 : : default:
14365 : : break;
14366 : : }
14367 : :
14368 : : /* Find the instruction group of the jump instruction. */
14369 : : jmp_g = instruction_group_list_group_find(igl, jmp_instr_id);
14370 [ # # ]: 0 : if (!jmp_g)
14371 : : return -EINVAL;
14372 : :
14373 : : /* Find the instruction group of the jump destination instruction. */
14374 : 0 : data = label_find(p->instruction_data, p->n_instructions, jmp_data->jmp_label);
14375 [ # # ]: 0 : if (!data)
14376 : : return -EINVAL;
14377 : :
14378 : 0 : instr_id = data - p->instruction_data;
14379 : :
14380 : : g = instruction_group_list_group_find(igl, instr_id);
14381 [ # # ]: 0 : if (!g)
14382 : : return -EINVAL;
14383 : :
14384 : : /* Code generation for "near" jump (same instruction group) or "far" jump (different
14385 : : * instruction group).
14386 : : */
14387 [ # # ]: 0 : if (g->group_id == jmp_g->group_id)
14388 : : fprintf(f,
14389 : : "\n\t\tgoto %s;\n",
14390 : : jmp_data->jmp_label);
14391 : : else
14392 : : fprintf(f,
14393 : : " {\n"
14394 : : "\t\tthread_ip_set(t, &p->instructions[%u]);\n"
14395 : : "\t\treturn;\n"
14396 : : "\t}\n\n",
14397 : : g->group_id);
14398 : :
14399 : : return 0;
14400 : : }
14401 : :
14402 : : static void
14403 : 0 : instruction_group_list_codegen(struct instruction_group_list *igl,
14404 : : struct rte_swx_pipeline *p,
14405 : : FILE *f)
14406 : : {
14407 : : struct instruction_group *g;
14408 : : uint32_t i;
14409 : : int is_required = 0;
14410 : :
14411 : : /* Check if code generation is required. */
14412 [ # # ]: 0 : TAILQ_FOREACH(g, igl, node)
14413 [ # # ]: 0 : if (g->first_instr_id < g->last_instr_id)
14414 : : is_required = 1;
14415 : :
14416 [ # # ]: 0 : if (!is_required)
14417 : : return;
14418 : :
14419 : : /* Generate the code for the pipeline instruction array. */
14420 : : fprintf(f,
14421 : : "static const struct instruction pipeline_instructions[] = {\n");
14422 : :
14423 [ # # ]: 0 : for (i = 0; i < p->n_instructions; i++) {
14424 : 0 : struct instruction *instr = &p->instructions[i];
14425 : 0 : instruction_export_t func = export_table[instr->type];
14426 : :
14427 : 0 : func(instr, f);
14428 : : }
14429 : :
14430 : : fprintf(f, "};\n\n");
14431 : :
14432 : : /* Generate the code for the pipeline functions: one function for each instruction group
14433 : : * that contains more than one instruction.
14434 : : */
14435 [ # # ]: 0 : TAILQ_FOREACH(g, igl, node) {
14436 : : struct instruction *last_instr;
14437 : : uint32_t j;
14438 : :
14439 : : /* Skip if group contains a single instruction. */
14440 [ # # ]: 0 : if (g->last_instr_id == g->first_instr_id)
14441 : 0 : continue;
14442 : :
14443 : : /* Generate new pipeline function. */
14444 : 0 : fprintf(f,
14445 : : "void\n"
14446 : : "pipeline_func_%u(struct rte_swx_pipeline *p)\n"
14447 : : "{\n"
14448 : : "\tstruct thread *t = &p->threads[p->thread_id];\n"
14449 : : "\n",
14450 : : g->group_id);
14451 : :
14452 : : /* Generate the code for each pipeline instruction. */
14453 [ # # ]: 0 : for (j = g->first_instr_id; j <= g->last_instr_id; j++) {
14454 : 0 : struct instruction *instr = &p->instructions[j];
14455 : 0 : struct instruction_data *data = &p->instruction_data[j];
14456 : :
14457 : : /* Label, if present. */
14458 [ # # ]: 0 : if (data->label[0])
14459 : 0 : fprintf(f, "\n%s : ", data->label);
14460 : : else
14461 : : fprintf(f, "\n\t");
14462 : :
14463 : : /* TX instruction type. */
14464 : 0 : if (instruction_does_tx(instr)) {
14465 : : pipeline_instr_does_tx_codegen(p, j, instr, f);
14466 : 0 : continue;
14467 : : }
14468 : :
14469 : : /* Jump instruction type. */
14470 : 0 : if (instruction_is_jmp(instr)) {
14471 : 0 : pipeline_instr_jmp_codegen(p, igl, j, instr, data, f);
14472 : 0 : continue;
14473 : : }
14474 : :
14475 : : /* Any other instruction type. */
14476 : 0 : fprintf(f,
14477 : : "%s(p, t, &pipeline_instructions[%u]);\n",
14478 : : instr_type_to_func(instr),
14479 : : j);
14480 : : }
14481 : :
14482 : : /* Finalize the generated pipeline function. For some instructions such as TX,
14483 : : * emit-many-and-TX and unconditional jump, the next instruction has been already
14484 : : * decided unconditionally and the instruction pointer of the current thread set
14485 : : * accordingly; for all the other instructions, the instruction pointer must be
14486 : : * incremented now.
14487 : : */
14488 [ # # ]: 0 : last_instr = &p->instructions[g->last_instr_id];
14489 : :
14490 [ # # ]: 0 : if (!instruction_does_tx(last_instr) && (last_instr->type != INSTR_JMP))
14491 : : fprintf(f,
14492 : : "thread_ip_inc(p);\n");
14493 : :
14494 : : fprintf(f,
14495 : : "}\n"
14496 : : "\n");
14497 : : }
14498 : : }
14499 : :
14500 : : static uint32_t
14501 : : instruction_group_list_custom_instructions_count(struct instruction_group_list *igl)
14502 : : {
14503 : : struct instruction_group *g;
14504 : : uint32_t n_custom_instr = 0;
14505 : :
14506 : : /* Groups with a single instruction: no function is generated for this group, the group
14507 : : * keeps its current instruction. Groups with more than two instructions: one function and
14508 : : * the associated custom instruction get generated for each such group.
14509 : : */
14510 [ # # ]: 0 : TAILQ_FOREACH(g, igl, node) {
14511 [ # # ]: 0 : if (g->first_instr_id == g->last_instr_id)
14512 : 0 : continue;
14513 : :
14514 : 0 : n_custom_instr++;
14515 : : }
14516 : :
14517 : : return n_custom_instr;
14518 : : }
14519 : :
14520 : : static int
14521 : : pipeline_adjust_check(struct rte_swx_pipeline *p __rte_unused,
14522 : : struct instruction_group_list *igl)
14523 : : {
14524 : : uint32_t n_custom_instr = instruction_group_list_custom_instructions_count(igl);
14525 : :
14526 : : /* Check that enough space is available within the pipeline instruction table to store all
14527 : : * the custom instructions.
14528 : : */
14529 [ # # ]: 0 : if (INSTR_CUSTOM_0 + n_custom_instr > RTE_SWX_PIPELINE_INSTRUCTION_TABLE_SIZE_MAX)
14530 : : return -ENOSPC;
14531 : :
14532 : : return 0;
14533 : : }
14534 : :
14535 : : static void
14536 : 0 : pipeline_adjust(struct rte_swx_pipeline *p, struct instruction_group_list *igl)
14537 : : {
14538 : : struct instruction_group *g;
14539 : : uint32_t i;
14540 : :
14541 : : /* Pipeline table instructions. */
14542 [ # # ]: 0 : for (i = 0; i < p->n_instructions; i++) {
14543 : 0 : struct instruction *instr = &p->instructions[i];
14544 : :
14545 [ # # ]: 0 : if (instr->type == INSTR_TABLE)
14546 : 0 : instr->type = INSTR_TABLE_AF;
14547 : :
14548 [ # # ]: 0 : if (instr->type == INSTR_LEARNER)
14549 : 0 : instr->type = INSTR_LEARNER_AF;
14550 : : }
14551 : :
14552 : : /* Pipeline custom instructions. */
14553 : : i = 0;
14554 [ # # ]: 0 : TAILQ_FOREACH(g, igl, node) {
14555 : 0 : struct instruction *instr = &p->instructions[g->first_instr_id];
14556 : : uint32_t j;
14557 : :
14558 [ # # ]: 0 : if (g->first_instr_id == g->last_instr_id)
14559 : 0 : continue;
14560 : :
14561 : : /* Install a new custom instruction. */
14562 : 0 : p->instruction_table[INSTR_CUSTOM_0 + i] = g->func;
14563 : :
14564 : : /* First instruction of the group: change its type to the new custom instruction. */
14565 : 0 : instr->type = INSTR_CUSTOM_0 + i;
14566 : :
14567 : : /* All the subsequent instructions of the group: invalidate. */
14568 [ # # ]: 0 : for (j = g->first_instr_id + 1; j <= g->last_instr_id; j++) {
14569 : 0 : struct instruction_data *data = &p->instruction_data[j];
14570 : :
14571 : 0 : data->invalid = 1;
14572 : : }
14573 : :
14574 : 0 : i++;
14575 : : }
14576 : :
14577 : : /* Remove the invalidated instructions. */
14578 : 0 : p->n_instructions = instr_compact(p->instructions, p->instruction_data, p->n_instructions);
14579 : :
14580 : : /* Resolve the jump destination for any "standalone" jump instructions (i.e. those jump
14581 : : * instructions that are the only instruction within their group, so they were left
14582 : : * unmodified).
14583 : : */
14584 : 0 : instr_jmp_resolve(p->instructions, p->instruction_data, p->n_instructions);
14585 : 0 : }
14586 : :
14587 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_pipeline_codegen, 22.11)
14588 : : int
14589 : 0 : rte_swx_pipeline_codegen(FILE *spec_file,
14590 : : FILE *code_file,
14591 : : uint32_t *err_line,
14592 : : const char **err_msg)
14593 : :
14594 : : {
14595 : 0 : struct rte_swx_pipeline *p = NULL;
14596 : : struct pipeline_spec *s = NULL;
14597 : : struct instruction_group_list *igl = NULL;
14598 : : struct action *a;
14599 : : int status = 0;
14600 : :
14601 : : /* Check input arguments. */
14602 [ # # ]: 0 : if (!spec_file || !code_file) {
14603 [ # # ]: 0 : if (err_line)
14604 : 0 : *err_line = 0;
14605 [ # # ]: 0 : if (err_msg)
14606 : 0 : *err_msg = "Invalid input argument.";
14607 : : status = -EINVAL;
14608 : 0 : goto free;
14609 : : }
14610 : :
14611 : : /* Pipeline configuration. */
14612 : 0 : s = pipeline_spec_parse(spec_file, err_line, err_msg);
14613 [ # # ]: 0 : if (!s) {
14614 : : status = -EINVAL;
14615 : 0 : goto free;
14616 : : }
14617 : :
14618 : 0 : status = rte_swx_pipeline_config(&p, NULL, 0);
14619 [ # # ]: 0 : if (status) {
14620 [ # # ]: 0 : if (err_line)
14621 : 0 : *err_line = 0;
14622 [ # # ]: 0 : if (err_msg)
14623 : 0 : *err_msg = "Pipeline configuration error.";
14624 : 0 : goto free;
14625 : : }
14626 : :
14627 : 0 : status = pipeline_spec_configure(p, s, err_msg);
14628 [ # # ]: 0 : if (status) {
14629 [ # # ]: 0 : if (err_line)
14630 : 0 : *err_line = 0;
14631 : 0 : goto free;
14632 : : }
14633 : :
14634 : : /*
14635 : : * Pipeline code generation.
14636 : : */
14637 : :
14638 : : /* Instruction Group List (IGL) computation: the pipeline configuration must be done first,
14639 : : * but there is no need for the pipeline build to be done as well.
14640 : : */
14641 : 0 : igl = instruction_group_list_create(p);
14642 [ # # ]: 0 : if (!igl) {
14643 [ # # ]: 0 : if (err_line)
14644 : 0 : *err_line = 0;
14645 [ # # ]: 0 : if (err_msg)
14646 : 0 : *err_msg = "Memory allocation failed.";
14647 : : status = -ENOMEM;
14648 : 0 : goto free;
14649 : : }
14650 : :
14651 : : /* Header file inclusion. */
14652 : : fprintf(code_file, "#include \"rte_swx_pipeline_internal.h\"\n");
14653 : : fprintf(code_file, "#include \"rte_swx_pipeline_spec.h\"\n\n");
14654 : :
14655 : : /* Code generation for the pipeline specification. */
14656 : 0 : pipeline_spec_codegen(code_file, s);
14657 : : fprintf(code_file, "\n");
14658 : :
14659 : : /* Code generation for the action instructions. */
14660 [ # # ]: 0 : TAILQ_FOREACH(a, &p->actions, node) {
14661 : 0 : fprintf(code_file, "/**\n * Action %s\n */\n\n", a->name);
14662 : :
14663 : 0 : action_data_codegen(a, code_file);
14664 : : fprintf(code_file, "\n");
14665 : :
14666 : 0 : action_instr_codegen(a, code_file);
14667 : : fprintf(code_file, "\n");
14668 : : }
14669 : :
14670 : : /* Code generation for the pipeline instructions. */
14671 : 0 : instruction_group_list_codegen(igl, p, code_file);
14672 : :
14673 : 0 : free:
14674 : 0 : instruction_group_list_free(igl);
14675 : 0 : rte_swx_pipeline_free(p);
14676 : 0 : pipeline_spec_free(s);
14677 : :
14678 : 0 : return status;
14679 : : }
14680 : :
14681 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_pipeline_build_from_lib, 22.11)
14682 : : int
14683 : 0 : rte_swx_pipeline_build_from_lib(struct rte_swx_pipeline **pipeline,
14684 : : const char *name,
14685 : : const char *lib_file_name,
14686 : : FILE *iospec_file,
14687 : : int numa_node)
14688 : : {
14689 : 0 : struct rte_swx_pipeline *p = NULL;
14690 : : void *lib = NULL;
14691 : : struct pipeline_iospec *sio = NULL;
14692 : : struct pipeline_spec *s = NULL;
14693 : : struct instruction_group_list *igl = NULL;
14694 : : struct action *a;
14695 : : struct instruction_group *g;
14696 : : int status = 0;
14697 : :
14698 : : /* Check input arguments. */
14699 : 0 : if (!pipeline ||
14700 [ # # ]: 0 : !name ||
14701 [ # # # # ]: 0 : !name[0] ||
14702 : 0 : !lib_file_name ||
14703 [ # # # # ]: 0 : !lib_file_name[0] ||
14704 : : !iospec_file) {
14705 : : status = -EINVAL;
14706 : 0 : goto free;
14707 : : }
14708 : :
14709 : : /* Open the library. */
14710 : 0 : lib = dlopen(lib_file_name, RTLD_LAZY);
14711 [ # # ]: 0 : if (!lib) {
14712 : : status = -EIO;
14713 : 0 : goto free;
14714 : : }
14715 : :
14716 : : /* Get the pipeline specification structures. */
14717 : 0 : s = dlsym(lib, "pipeline_spec");
14718 [ # # ]: 0 : if (!s) {
14719 : : status = -EINVAL;
14720 : 0 : goto free;
14721 : : }
14722 : :
14723 : 0 : sio = pipeline_iospec_parse(iospec_file, NULL, NULL);
14724 [ # # ]: 0 : if (!sio) {
14725 : : status = -EINVAL;
14726 : 0 : goto free;
14727 : : }
14728 : :
14729 : : /* Pipeline configuration based on the specification structures. */
14730 : 0 : status = rte_swx_pipeline_config(&p, name, numa_node);
14731 [ # # ]: 0 : if (status)
14732 : 0 : goto free;
14733 : :
14734 : 0 : status = pipeline_iospec_configure(p, sio, NULL);
14735 [ # # ]: 0 : if (status)
14736 : 0 : goto free;
14737 : :
14738 : 0 : status = pipeline_spec_configure(p, s, NULL);
14739 [ # # ]: 0 : if (status)
14740 : 0 : goto free;
14741 : :
14742 : : /* Pipeline build. */
14743 : 0 : status = rte_swx_pipeline_build(p);
14744 [ # # ]: 0 : if (status)
14745 : 0 : goto free;
14746 : :
14747 : : /* Action instructions. */
14748 [ # # ]: 0 : TAILQ_FOREACH(a, &p->actions, node) {
14749 : : char name[RTE_SWX_NAME_SIZE * 2];
14750 : :
14751 : 0 : snprintf(name, sizeof(name), "action_%s_run", a->name);
14752 : :
14753 : 0 : p->action_funcs[a->id] = dlsym(lib, name);
14754 [ # # ]: 0 : if (!p->action_funcs[a->id]) {
14755 : : status = -EINVAL;
14756 : 0 : goto free;
14757 : : }
14758 : : }
14759 : :
14760 : : /* Pipeline instructions. */
14761 : 0 : igl = instruction_group_list_create(p);
14762 [ # # ]: 0 : if (!igl) {
14763 : : status = -ENOMEM;
14764 : 0 : goto free;
14765 : : }
14766 : :
14767 [ # # ]: 0 : TAILQ_FOREACH(g, igl, node) {
14768 : : char name[RTE_SWX_NAME_SIZE * 2];
14769 : :
14770 [ # # ]: 0 : if (g->first_instr_id == g->last_instr_id)
14771 : 0 : continue;
14772 : :
14773 : 0 : snprintf(name, sizeof(name), "pipeline_func_%u", g->group_id);
14774 : :
14775 : 0 : g->func = dlsym(lib, name);
14776 [ # # ]: 0 : if (!g->func) {
14777 : : status = -EINVAL;
14778 : 0 : goto free;
14779 : : }
14780 : : }
14781 : :
14782 : 0 : status = pipeline_adjust_check(p, igl);
14783 : : if (status)
14784 : 0 : goto free;
14785 : :
14786 : 0 : pipeline_adjust(p, igl);
14787 : :
14788 : 0 : p->lib = lib;
14789 : :
14790 : 0 : *pipeline = p;
14791 : :
14792 : 0 : free:
14793 : 0 : instruction_group_list_free(igl);
14794 : :
14795 : 0 : pipeline_iospec_free(sio);
14796 : :
14797 [ # # ]: 0 : if (status) {
14798 : 0 : rte_swx_pipeline_free(p);
14799 : :
14800 [ # # ]: 0 : if (lib)
14801 : 0 : dlclose(lib);
14802 : : }
14803 : :
14804 : 0 : return status;
14805 : : }
|