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 <rte_tailq.h>
10 : : #include <rte_eal_memconfig.h>
11 : : #include <rte_jhash.h>
12 : : #include <rte_hash_crc.h>
13 : :
14 : : #include <rte_swx_port_ethdev.h>
15 : : #include <rte_swx_port_fd.h>
16 : : #include <rte_swx_port_ring.h>
17 : : #include "rte_swx_port_source_sink.h"
18 : :
19 : : #include <rte_swx_table_em.h>
20 : : #include <rte_swx_table_wm.h>
21 : :
22 : : #include "rte_swx_pipeline_internal.h"
23 : : #include "rte_swx_pipeline_spec.h"
24 : :
25 : : #define CHECK(condition, err_code) \
26 : : do { \
27 : : if (!(condition)) \
28 : : return -(err_code); \
29 : : } while (0)
30 : :
31 : : #define CHECK_NAME(name, err_code) \
32 : : CHECK((name) && \
33 : : (name)[0] && \
34 : : (strnlen((name), RTE_SWX_NAME_SIZE) < RTE_SWX_NAME_SIZE), \
35 : : err_code)
36 : :
37 : : #define CHECK_INSTRUCTION(instr, err_code) \
38 : : CHECK((instr) && \
39 : : (instr)[0] && \
40 : : (strnlen((instr), RTE_SWX_INSTRUCTION_SIZE) < \
41 : : RTE_SWX_INSTRUCTION_SIZE), \
42 : : err_code)
43 : :
44 : : /*
45 : : * Environment.
46 : : */
47 : : #ifndef RTE_SWX_PIPELINE_HUGE_PAGES_DISABLE
48 : :
49 : : #include <rte_malloc.h>
50 : :
51 : : static void *
52 : : env_malloc(size_t size, size_t alignment, int numa_node)
53 : : {
54 : 0 : return rte_zmalloc_socket(NULL, size, alignment, numa_node);
55 : : }
56 : :
57 : : static void
58 : : env_free(void *start, size_t size __rte_unused)
59 : : {
60 : 0 : rte_free(start);
61 : : }
62 : :
63 : : #else
64 : :
65 : : #include <numa.h>
66 : :
67 : : static void *
68 : : env_malloc(size_t size, size_t alignment __rte_unused, int numa_node)
69 : : {
70 : : void *start;
71 : :
72 : : if (numa_available() == -1)
73 : : return NULL;
74 : :
75 : : start = numa_alloc_onnode(size, numa_node);
76 : : if (!start)
77 : : return NULL;
78 : :
79 : : memset(start, 0, size);
80 : : return start;
81 : : }
82 : :
83 : : static void
84 : : env_free(void *start, size_t size)
85 : : {
86 : : if (numa_available() == -1)
87 : : return;
88 : :
89 : : numa_free(start, size);
90 : : }
91 : :
92 : : #endif
93 : :
94 : : /*
95 : : * Struct.
96 : : */
97 : : static struct struct_type *
98 : : struct_type_find(struct rte_swx_pipeline *p, const char *name)
99 : : {
100 : : struct struct_type *elem;
101 : :
102 [ # # # # : 0 : TAILQ_FOREACH(elem, &p->struct_types, node)
# # # # #
# # # ]
103 [ # # # # : 0 : if (strcmp(elem->name, name) == 0)
# # # # #
# # # ]
104 : : return elem;
105 : :
106 : : return NULL;
107 : : }
108 : :
109 : : static struct field *
110 : 0 : struct_type_field_find(struct struct_type *st, const char *name)
111 : : {
112 : : uint32_t i;
113 : :
114 [ # # ]: 0 : for (i = 0; i < st->n_fields; i++) {
115 : 0 : struct field *f = &st->fields[i];
116 : :
117 [ # # ]: 0 : if (strcmp(f->name, name) == 0)
118 : 0 : return f;
119 : : }
120 : :
121 : : return NULL;
122 : : }
123 : :
124 : : int
125 : 0 : rte_swx_pipeline_struct_type_register(struct rte_swx_pipeline *p,
126 : : const char *name,
127 : : struct rte_swx_field_params *fields,
128 : : uint32_t n_fields,
129 : : int last_field_has_variable_size)
130 : : {
131 : : struct struct_type *st;
132 : : uint32_t i;
133 : :
134 [ # # ]: 0 : CHECK(p, EINVAL);
135 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
136 [ # # ]: 0 : CHECK(fields, EINVAL);
137 [ # # ]: 0 : CHECK(n_fields, EINVAL);
138 : :
139 [ # # ]: 0 : for (i = 0; i < n_fields; i++) {
140 : 0 : struct rte_swx_field_params *f = &fields[i];
141 : : uint32_t j;
142 : :
143 [ # # # # : 0 : CHECK_NAME(f->name, EINVAL);
# # ]
144 [ # # ]: 0 : CHECK(f->n_bits, EINVAL);
145 [ # # ]: 0 : CHECK((f->n_bits & 7) == 0, EINVAL);
146 : :
147 [ # # ]: 0 : for (j = 0; j < i; j++) {
148 : 0 : struct rte_swx_field_params *f_prev = &fields[j];
149 : :
150 [ # # ]: 0 : CHECK(strcmp(f->name, f_prev->name), EINVAL);
151 : : }
152 : : }
153 : :
154 [ # # ]: 0 : CHECK(!struct_type_find(p, name), EEXIST);
155 : :
156 : : /* Node allocation. */
157 : 0 : st = calloc(1, sizeof(struct struct_type));
158 [ # # ]: 0 : CHECK(st, ENOMEM);
159 : :
160 : 0 : st->fields = calloc(n_fields, sizeof(struct field));
161 [ # # ]: 0 : if (!st->fields) {
162 : 0 : free(st);
163 : 0 : CHECK(0, ENOMEM);
164 : : }
165 : :
166 : : /* Node initialization. */
167 : 0 : strcpy(st->name, name);
168 [ # # ]: 0 : for (i = 0; i < n_fields; i++) {
169 : 0 : struct field *dst = &st->fields[i];
170 : 0 : struct rte_swx_field_params *src = &fields[i];
171 [ # # # # ]: 0 : int var_size = ((i == n_fields - 1) && last_field_has_variable_size) ? 1 : 0;
172 : :
173 [ # # ]: 0 : strcpy(dst->name, src->name);
174 : 0 : dst->n_bits = src->n_bits;
175 : 0 : dst->offset = st->n_bits;
176 : 0 : dst->var_size = var_size;
177 : :
178 : 0 : st->n_bits += src->n_bits;
179 [ # # ]: 0 : st->n_bits_min += var_size ? 0 : src->n_bits;
180 : : }
181 : 0 : st->n_fields = n_fields;
182 : 0 : st->var_size = last_field_has_variable_size;
183 : :
184 : : /* Node add to tailq. */
185 : 0 : TAILQ_INSERT_TAIL(&p->struct_types, st, node);
186 : :
187 : 0 : return 0;
188 : : }
189 : :
190 : : static int
191 : 0 : struct_build(struct rte_swx_pipeline *p)
192 : : {
193 : : uint32_t i;
194 : :
195 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
196 : : struct thread *t = &p->threads[i];
197 : :
198 : 0 : t->structs = calloc(p->n_structs, sizeof(uint8_t *));
199 [ # # ]: 0 : CHECK(t->structs, ENOMEM);
200 : : }
201 : :
202 : : return 0;
203 : : }
204 : :
205 : : static void
206 : : struct_build_free(struct rte_swx_pipeline *p)
207 : : {
208 : : uint32_t i;
209 : :
210 [ # # # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
211 : : struct thread *t = &p->threads[i];
212 : :
213 : 0 : free(t->structs);
214 : 0 : t->structs = NULL;
215 : : }
216 : : }
217 : :
218 : : static void
219 : 0 : struct_free(struct rte_swx_pipeline *p)
220 : : {
221 : : struct_build_free(p);
222 : :
223 : : /* Struct types. */
224 : 0 : for ( ; ; ) {
225 : : struct struct_type *elem;
226 : :
227 : 0 : elem = TAILQ_FIRST(&p->struct_types);
228 [ # # ]: 0 : if (!elem)
229 : : break;
230 : :
231 [ # # ]: 0 : TAILQ_REMOVE(&p->struct_types, elem, node);
232 : 0 : free(elem->fields);
233 : 0 : free(elem);
234 : : }
235 : 0 : }
236 : :
237 : : /*
238 : : * Input port.
239 : : */
240 : : static struct port_in_type *
241 : 0 : port_in_type_find(struct rte_swx_pipeline *p, const char *name)
242 : : {
243 : : struct port_in_type *elem;
244 : :
245 [ # # ]: 0 : if (!name)
246 : : return NULL;
247 : :
248 [ # # ]: 0 : TAILQ_FOREACH(elem, &p->port_in_types, node)
249 [ # # ]: 0 : if (strcmp(elem->name, name) == 0)
250 : 0 : return elem;
251 : :
252 : : return NULL;
253 : : }
254 : :
255 : : int
256 : 0 : rte_swx_pipeline_port_in_type_register(struct rte_swx_pipeline *p,
257 : : const char *name,
258 : : struct rte_swx_port_in_ops *ops)
259 : : {
260 : : struct port_in_type *elem;
261 : :
262 [ # # ]: 0 : CHECK(p, EINVAL);
263 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
264 [ # # ]: 0 : CHECK(ops, EINVAL);
265 [ # # ]: 0 : CHECK(ops->create, EINVAL);
266 [ # # ]: 0 : CHECK(ops->free, EINVAL);
267 [ # # ]: 0 : CHECK(ops->pkt_rx, EINVAL);
268 [ # # ]: 0 : CHECK(ops->stats_read, EINVAL);
269 : :
270 [ # # ]: 0 : CHECK(!port_in_type_find(p, name), EEXIST);
271 : :
272 : : /* Node allocation. */
273 : 0 : elem = calloc(1, sizeof(struct port_in_type));
274 [ # # ]: 0 : CHECK(elem, ENOMEM);
275 : :
276 : : /* Node initialization. */
277 : 0 : strcpy(elem->name, name);
278 : 0 : memcpy(&elem->ops, ops, sizeof(*ops));
279 : :
280 : : /* Node add to tailq. */
281 : 0 : TAILQ_INSERT_TAIL(&p->port_in_types, elem, node);
282 : :
283 : 0 : return 0;
284 : : }
285 : :
286 : : static struct port_in *
287 : : port_in_find(struct rte_swx_pipeline *p, uint32_t port_id)
288 : : {
289 : : struct port_in *port;
290 : :
291 [ # # # # : 0 : TAILQ_FOREACH(port, &p->ports_in, node)
# # ]
292 [ # # # # : 0 : if (port->id == port_id)
# # ]
293 : : return port;
294 : :
295 : : return NULL;
296 : : }
297 : :
298 : : int
299 : 0 : rte_swx_pipeline_port_in_config(struct rte_swx_pipeline *p,
300 : : uint32_t port_id,
301 : : const char *port_type_name,
302 : : void *args)
303 : : {
304 : : struct port_in_type *type = NULL;
305 : : struct port_in *port = NULL;
306 : : void *obj = NULL;
307 : :
308 [ # # ]: 0 : CHECK(p, EINVAL);
309 : :
310 [ # # ]: 0 : CHECK(!port_in_find(p, port_id), EINVAL);
311 : :
312 [ # # # # : 0 : CHECK_NAME(port_type_name, EINVAL);
# # ]
313 : 0 : type = port_in_type_find(p, port_type_name);
314 [ # # ]: 0 : CHECK(type, EINVAL);
315 : :
316 : 0 : obj = type->ops.create(args);
317 [ # # ]: 0 : CHECK(obj, ENODEV);
318 : :
319 : : /* Node allocation. */
320 : 0 : port = calloc(1, sizeof(struct port_in));
321 [ # # ]: 0 : CHECK(port, ENOMEM);
322 : :
323 : : /* Node initialization. */
324 : 0 : port->type = type;
325 : 0 : port->obj = obj;
326 : 0 : port->id = port_id;
327 : :
328 : : /* Node add to tailq. */
329 : 0 : TAILQ_INSERT_TAIL(&p->ports_in, port, node);
330 [ # # ]: 0 : if (p->n_ports_in < port_id + 1)
331 : 0 : p->n_ports_in = port_id + 1;
332 : :
333 : : return 0;
334 : : }
335 : :
336 : : static int
337 : 0 : port_in_build(struct rte_swx_pipeline *p)
338 : : {
339 : : struct port_in *port;
340 : : uint32_t i;
341 : :
342 [ # # ]: 0 : CHECK(p->n_ports_in, EINVAL);
343 : :
344 [ # # ]: 0 : for (i = 0; i < p->n_ports_in; i++)
345 [ # # ]: 0 : CHECK(port_in_find(p, i), EINVAL);
346 : :
347 : 0 : p->in = calloc(p->n_ports_in, sizeof(struct port_in_runtime));
348 [ # # ]: 0 : CHECK(p->in, ENOMEM);
349 : :
350 [ # # ]: 0 : TAILQ_FOREACH(port, &p->ports_in, node) {
351 : 0 : struct port_in_runtime *in = &p->in[port->id];
352 : :
353 : 0 : in->pkt_rx = port->type->ops.pkt_rx;
354 : 0 : in->obj = port->obj;
355 : : }
356 : :
357 : : return 0;
358 : : }
359 : :
360 : : static void
361 : : port_in_build_free(struct rte_swx_pipeline *p)
362 : : {
363 : 0 : free(p->in);
364 : 0 : p->in = NULL;
365 : 0 : }
366 : :
367 : : static void
368 : 0 : port_in_free(struct rte_swx_pipeline *p)
369 : : {
370 : : port_in_build_free(p);
371 : :
372 : : /* Input ports. */
373 : 0 : for ( ; ; ) {
374 : : struct port_in *port;
375 : :
376 : 0 : port = TAILQ_FIRST(&p->ports_in);
377 [ # # ]: 0 : if (!port)
378 : : break;
379 : :
380 [ # # ]: 0 : TAILQ_REMOVE(&p->ports_in, port, node);
381 : 0 : port->type->ops.free(port->obj);
382 : 0 : free(port);
383 : : }
384 : :
385 : : /* Input port types. */
386 : 0 : for ( ; ; ) {
387 : : struct port_in_type *elem;
388 : :
389 : 0 : elem = TAILQ_FIRST(&p->port_in_types);
390 [ # # ]: 0 : if (!elem)
391 : : break;
392 : :
393 [ # # ]: 0 : TAILQ_REMOVE(&p->port_in_types, elem, node);
394 : 0 : free(elem);
395 : : }
396 : 0 : }
397 : :
398 : : /*
399 : : * Output port.
400 : : */
401 : : static struct port_out_type *
402 : 0 : port_out_type_find(struct rte_swx_pipeline *p, const char *name)
403 : : {
404 : : struct port_out_type *elem;
405 : :
406 [ # # ]: 0 : if (!name)
407 : : return NULL;
408 : :
409 [ # # ]: 0 : TAILQ_FOREACH(elem, &p->port_out_types, node)
410 [ # # ]: 0 : if (!strcmp(elem->name, name))
411 : 0 : return elem;
412 : :
413 : : return NULL;
414 : : }
415 : :
416 : : int
417 : 0 : rte_swx_pipeline_port_out_type_register(struct rte_swx_pipeline *p,
418 : : const char *name,
419 : : struct rte_swx_port_out_ops *ops)
420 : : {
421 : : struct port_out_type *elem;
422 : :
423 [ # # ]: 0 : CHECK(p, EINVAL);
424 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
425 [ # # ]: 0 : CHECK(ops, EINVAL);
426 [ # # ]: 0 : CHECK(ops->create, EINVAL);
427 [ # # ]: 0 : CHECK(ops->free, EINVAL);
428 [ # # ]: 0 : CHECK(ops->pkt_tx, EINVAL);
429 [ # # ]: 0 : CHECK(ops->pkt_fast_clone_tx, EINVAL);
430 [ # # ]: 0 : CHECK(ops->pkt_clone_tx, EINVAL);
431 [ # # ]: 0 : CHECK(ops->stats_read, EINVAL);
432 : :
433 [ # # ]: 0 : CHECK(!port_out_type_find(p, name), EEXIST);
434 : :
435 : : /* Node allocation. */
436 : 0 : elem = calloc(1, sizeof(struct port_out_type));
437 [ # # ]: 0 : CHECK(elem, ENOMEM);
438 : :
439 : : /* Node initialization. */
440 : 0 : strcpy(elem->name, name);
441 : 0 : memcpy(&elem->ops, ops, sizeof(*ops));
442 : :
443 : : /* Node add to tailq. */
444 : 0 : TAILQ_INSERT_TAIL(&p->port_out_types, elem, node);
445 : :
446 : 0 : return 0;
447 : : }
448 : :
449 : : static struct port_out *
450 : : port_out_find(struct rte_swx_pipeline *p, uint32_t port_id)
451 : : {
452 : : struct port_out *port;
453 : :
454 [ # # # # : 0 : TAILQ_FOREACH(port, &p->ports_out, node)
# # ]
455 [ # # # # : 0 : if (port->id == port_id)
# # ]
456 : : return port;
457 : :
458 : : return NULL;
459 : : }
460 : :
461 : : int
462 : 0 : rte_swx_pipeline_port_out_config(struct rte_swx_pipeline *p,
463 : : uint32_t port_id,
464 : : const char *port_type_name,
465 : : void *args)
466 : : {
467 : : struct port_out_type *type = NULL;
468 : : struct port_out *port = NULL;
469 : : void *obj = NULL;
470 : :
471 [ # # ]: 0 : CHECK(p, EINVAL);
472 : :
473 [ # # ]: 0 : CHECK(!port_out_find(p, port_id), EINVAL);
474 : :
475 [ # # # # : 0 : CHECK_NAME(port_type_name, EINVAL);
# # ]
476 : 0 : type = port_out_type_find(p, port_type_name);
477 [ # # ]: 0 : CHECK(type, EINVAL);
478 : :
479 : 0 : obj = type->ops.create(args);
480 [ # # ]: 0 : CHECK(obj, ENODEV);
481 : :
482 : : /* Node allocation. */
483 : 0 : port = calloc(1, sizeof(struct port_out));
484 [ # # ]: 0 : CHECK(port, ENOMEM);
485 : :
486 : : /* Node initialization. */
487 : 0 : port->type = type;
488 : 0 : port->obj = obj;
489 : 0 : port->id = port_id;
490 : :
491 : : /* Node add to tailq. */
492 : 0 : TAILQ_INSERT_TAIL(&p->ports_out, port, node);
493 [ # # ]: 0 : if (p->n_ports_out < port_id + 1)
494 : 0 : p->n_ports_out = port_id + 1;
495 : :
496 : : return 0;
497 : : }
498 : :
499 : : static int
500 : 0 : port_out_build(struct rte_swx_pipeline *p)
501 : : {
502 : : struct port_out *port;
503 : : uint32_t i;
504 : :
505 [ # # ]: 0 : CHECK(p->n_ports_out, EINVAL);
506 : :
507 [ # # ]: 0 : for (i = 0; i < p->n_ports_out; i++)
508 [ # # ]: 0 : CHECK(port_out_find(p, i), EINVAL);
509 : :
510 : 0 : p->out = calloc(p->n_ports_out, sizeof(struct port_out_runtime));
511 [ # # ]: 0 : CHECK(p->out, ENOMEM);
512 : :
513 [ # # ]: 0 : TAILQ_FOREACH(port, &p->ports_out, node) {
514 : 0 : struct port_out_runtime *out = &p->out[port->id];
515 : :
516 : 0 : out->pkt_tx = port->type->ops.pkt_tx;
517 : 0 : out->pkt_fast_clone_tx = port->type->ops.pkt_fast_clone_tx;
518 : 0 : out->pkt_clone_tx = port->type->ops.pkt_clone_tx;
519 : 0 : out->flush = port->type->ops.flush;
520 : 0 : out->obj = port->obj;
521 : : }
522 : :
523 : : return 0;
524 : : }
525 : :
526 : : static void
527 : : port_out_build_free(struct rte_swx_pipeline *p)
528 : : {
529 : 0 : free(p->out);
530 : 0 : p->out = NULL;
531 : 0 : }
532 : :
533 : : static void
534 : 0 : port_out_free(struct rte_swx_pipeline *p)
535 : : {
536 : : port_out_build_free(p);
537 : :
538 : : /* Output ports. */
539 : 0 : for ( ; ; ) {
540 : : struct port_out *port;
541 : :
542 : 0 : port = TAILQ_FIRST(&p->ports_out);
543 [ # # ]: 0 : if (!port)
544 : : break;
545 : :
546 [ # # ]: 0 : TAILQ_REMOVE(&p->ports_out, port, node);
547 : 0 : port->type->ops.free(port->obj);
548 : 0 : free(port);
549 : : }
550 : :
551 : : /* Output port types. */
552 : 0 : for ( ; ; ) {
553 : : struct port_out_type *elem;
554 : :
555 : 0 : elem = TAILQ_FIRST(&p->port_out_types);
556 [ # # ]: 0 : if (!elem)
557 : : break;
558 : :
559 [ # # ]: 0 : TAILQ_REMOVE(&p->port_out_types, elem, node);
560 : 0 : free(elem);
561 : : }
562 : 0 : }
563 : :
564 : : /*
565 : : * Packet mirroring.
566 : : */
567 : : int
568 : 0 : rte_swx_pipeline_mirroring_config(struct rte_swx_pipeline *p,
569 : : struct rte_swx_pipeline_mirroring_params *params)
570 : : {
571 [ # # ]: 0 : CHECK(p, EINVAL);
572 [ # # ]: 0 : CHECK(params, EINVAL);
573 [ # # ]: 0 : CHECK(params->n_slots, EINVAL);
574 [ # # ]: 0 : CHECK(params->n_sessions, EINVAL);
575 [ # # ]: 0 : CHECK(!p->build_done, EEXIST);
576 : :
577 : 0 : p->n_mirroring_slots = rte_align32pow2(params->n_slots);
578 [ # # ]: 0 : if (p->n_mirroring_slots > 64)
579 : 0 : p->n_mirroring_slots = 64;
580 : :
581 : 0 : p->n_mirroring_sessions = rte_align32pow2(params->n_sessions);
582 : :
583 : 0 : return 0;
584 : : }
585 : :
586 : : static void
587 : 0 : mirroring_build_free(struct rte_swx_pipeline *p)
588 : : {
589 : : uint32_t i;
590 : :
591 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
592 : : struct thread *t = &p->threads[i];
593 : :
594 : : /* mirroring_slots. */
595 : 0 : free(t->mirroring_slots);
596 : 0 : t->mirroring_slots = NULL;
597 : : }
598 : :
599 : : /* mirroring_sessions. */
600 : 0 : free(p->mirroring_sessions);
601 : 0 : p->mirroring_sessions = NULL;
602 : 0 : }
603 : :
604 : : static void
605 : : mirroring_free(struct rte_swx_pipeline *p)
606 : : {
607 : 0 : mirroring_build_free(p);
608 : : }
609 : :
610 : : static int
611 : 0 : mirroring_build(struct rte_swx_pipeline *p)
612 : : {
613 : : uint32_t i;
614 : :
615 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
616 : : struct thread *t = &p->threads[i];
617 : :
618 : : /* mirroring_slots. */
619 : 0 : t->mirroring_slots = calloc(p->n_mirroring_slots, sizeof(uint32_t));
620 [ # # ]: 0 : if (!t->mirroring_slots)
621 : 0 : goto error;
622 : : }
623 : :
624 : : /* mirroring_sessions. */
625 : 0 : p->mirroring_sessions = calloc(p->n_mirroring_sessions, sizeof(struct mirroring_session));
626 [ # # ]: 0 : if (!p->mirroring_sessions)
627 : 0 : goto error;
628 : :
629 : : return 0;
630 : :
631 : 0 : error:
632 : 0 : mirroring_build_free(p);
633 : 0 : return -ENOMEM;
634 : : }
635 : :
636 : : /*
637 : : * Extern object.
638 : : */
639 : : static struct extern_type *
640 : : extern_type_find(struct rte_swx_pipeline *p, const char *name)
641 : : {
642 : : struct extern_type *elem;
643 : :
644 [ # # # # : 0 : TAILQ_FOREACH(elem, &p->extern_types, node)
# # ]
645 [ # # # # : 0 : if (strcmp(elem->name, name) == 0)
# # ]
646 : : return elem;
647 : :
648 : : return NULL;
649 : : }
650 : :
651 : : static struct extern_type_member_func *
652 : : extern_type_member_func_find(struct extern_type *type, const char *name)
653 : : {
654 : : struct extern_type_member_func *elem;
655 : :
656 [ # # # # ]: 0 : TAILQ_FOREACH(elem, &type->funcs, node)
657 [ # # # # ]: 0 : if (strcmp(elem->name, name) == 0)
658 : : return elem;
659 : :
660 : : return NULL;
661 : : }
662 : :
663 : : static struct extern_obj *
664 : : extern_obj_find(struct rte_swx_pipeline *p, const char *name)
665 : : {
666 : : struct extern_obj *elem;
667 : :
668 [ # # # # : 0 : TAILQ_FOREACH(elem, &p->extern_objs, node)
# # ]
669 [ # # # # : 0 : if (strcmp(elem->name, name) == 0)
# # ]
670 : : return elem;
671 : :
672 : : return NULL;
673 : : }
674 : :
675 : : static struct extern_type_member_func *
676 : 0 : extern_obj_member_func_parse(struct rte_swx_pipeline *p,
677 : : const char *name,
678 : : struct extern_obj **obj)
679 : : {
680 : : struct extern_obj *object;
681 : : struct extern_type_member_func *func;
682 : : char *object_name, *func_name;
683 : :
684 [ # # # # ]: 0 : if (name[0] != 'e' || name[1] != '.')
685 : : return NULL;
686 : :
687 : 0 : object_name = strdup(&name[2]);
688 [ # # ]: 0 : if (!object_name)
689 : : return NULL;
690 : :
691 : 0 : func_name = strchr(object_name, '.');
692 [ # # ]: 0 : if (!func_name) {
693 : 0 : free(object_name);
694 : 0 : return NULL;
695 : : }
696 : :
697 : 0 : *func_name = 0;
698 : 0 : func_name++;
699 : :
700 : : object = extern_obj_find(p, object_name);
701 [ # # ]: 0 : if (!object) {
702 : 0 : free(object_name);
703 : 0 : return NULL;
704 : : }
705 : :
706 : 0 : func = extern_type_member_func_find(object->type, func_name);
707 [ # # ]: 0 : if (!func) {
708 : 0 : free(object_name);
709 : 0 : return NULL;
710 : : }
711 : :
712 [ # # ]: 0 : if (obj)
713 : 0 : *obj = object;
714 : :
715 : 0 : free(object_name);
716 : 0 : return func;
717 : : }
718 : :
719 : : static struct field *
720 : 0 : extern_obj_mailbox_field_parse(struct rte_swx_pipeline *p,
721 : : const char *name,
722 : : struct extern_obj **object)
723 : : {
724 : : struct extern_obj *obj;
725 : : struct field *f;
726 : : char *obj_name, *field_name;
727 : :
728 [ # # # # ]: 0 : if ((name[0] != 'e') || (name[1] != '.'))
729 : : return NULL;
730 : :
731 : 0 : obj_name = strdup(&name[2]);
732 [ # # ]: 0 : if (!obj_name)
733 : : return NULL;
734 : :
735 : 0 : field_name = strchr(obj_name, '.');
736 [ # # ]: 0 : if (!field_name) {
737 : 0 : free(obj_name);
738 : 0 : return NULL;
739 : : }
740 : :
741 : 0 : *field_name = 0;
742 : 0 : field_name++;
743 : :
744 : : obj = extern_obj_find(p, obj_name);
745 [ # # ]: 0 : if (!obj) {
746 : 0 : free(obj_name);
747 : 0 : return NULL;
748 : : }
749 : :
750 : 0 : f = struct_type_field_find(obj->type->mailbox_struct_type, field_name);
751 [ # # ]: 0 : if (!f) {
752 : 0 : free(obj_name);
753 : 0 : return NULL;
754 : : }
755 : :
756 [ # # ]: 0 : if (object)
757 : 0 : *object = obj;
758 : :
759 : 0 : free(obj_name);
760 : 0 : return f;
761 : : }
762 : :
763 : : int
764 : 0 : rte_swx_pipeline_extern_type_register(struct rte_swx_pipeline *p,
765 : : const char *name,
766 : : const char *mailbox_struct_type_name,
767 : : rte_swx_extern_type_constructor_t constructor,
768 : : rte_swx_extern_type_destructor_t destructor)
769 : : {
770 : : struct extern_type *elem;
771 : : struct struct_type *mailbox_struct_type;
772 : :
773 [ # # ]: 0 : CHECK(p, EINVAL);
774 : :
775 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
776 [ # # ]: 0 : CHECK(!extern_type_find(p, name), EEXIST);
777 : :
778 [ # # # # : 0 : CHECK_NAME(mailbox_struct_type_name, EINVAL);
# # ]
779 : : mailbox_struct_type = struct_type_find(p, mailbox_struct_type_name);
780 [ # # ]: 0 : CHECK(mailbox_struct_type, EINVAL);
781 [ # # ]: 0 : CHECK(!mailbox_struct_type->var_size, EINVAL);
782 : :
783 [ # # ]: 0 : CHECK(constructor, EINVAL);
784 [ # # ]: 0 : CHECK(destructor, EINVAL);
785 : :
786 : : /* Node allocation. */
787 : 0 : elem = calloc(1, sizeof(struct extern_type));
788 [ # # ]: 0 : CHECK(elem, ENOMEM);
789 : :
790 : : /* Node initialization. */
791 : 0 : strcpy(elem->name, name);
792 : 0 : elem->mailbox_struct_type = mailbox_struct_type;
793 : 0 : elem->constructor = constructor;
794 : 0 : elem->destructor = destructor;
795 : 0 : TAILQ_INIT(&elem->funcs);
796 : :
797 : : /* Node add to tailq. */
798 : 0 : TAILQ_INSERT_TAIL(&p->extern_types, elem, node);
799 : :
800 : 0 : return 0;
801 : : }
802 : :
803 : : int
804 : 0 : rte_swx_pipeline_extern_type_member_func_register(struct rte_swx_pipeline *p,
805 : : const char *extern_type_name,
806 : : const char *name,
807 : : rte_swx_extern_type_member_func_t member_func)
808 : : {
809 : : struct extern_type *type;
810 : : struct extern_type_member_func *type_member;
811 : :
812 [ # # ]: 0 : CHECK(p, EINVAL);
813 : :
814 [ # # # # : 0 : CHECK_NAME(extern_type_name, EINVAL);
# # ]
815 : : type = extern_type_find(p, extern_type_name);
816 [ # # ]: 0 : CHECK(type, EINVAL);
817 [ # # ]: 0 : CHECK(type->n_funcs < RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX, ENOSPC);
818 : :
819 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
820 [ # # ]: 0 : CHECK(!extern_type_member_func_find(type, name), EEXIST);
821 : :
822 [ # # ]: 0 : CHECK(member_func, EINVAL);
823 : :
824 : : /* Node allocation. */
825 : 0 : type_member = calloc(1, sizeof(struct extern_type_member_func));
826 [ # # ]: 0 : CHECK(type_member, ENOMEM);
827 : :
828 : : /* Node initialization. */
829 : 0 : strcpy(type_member->name, name);
830 : 0 : type_member->func = member_func;
831 : 0 : type_member->id = type->n_funcs;
832 : :
833 : : /* Node add to tailq. */
834 : 0 : TAILQ_INSERT_TAIL(&type->funcs, type_member, node);
835 : 0 : type->n_funcs++;
836 : :
837 : 0 : return 0;
838 : : }
839 : :
840 : : int
841 : 0 : rte_swx_pipeline_extern_object_config(struct rte_swx_pipeline *p,
842 : : const char *extern_type_name,
843 : : const char *name,
844 : : const char *args)
845 : : {
846 : : struct extern_type *type;
847 : : struct extern_obj *obj;
848 : : void *obj_handle;
849 : :
850 [ # # ]: 0 : CHECK(p, EINVAL);
851 : :
852 [ # # # # : 0 : CHECK_NAME(extern_type_name, EINVAL);
# # ]
853 : : type = extern_type_find(p, extern_type_name);
854 [ # # ]: 0 : CHECK(type, EINVAL);
855 : :
856 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
857 [ # # ]: 0 : CHECK(!extern_obj_find(p, name), EEXIST);
858 : :
859 : : /* Node allocation. */
860 : 0 : obj = calloc(1, sizeof(struct extern_obj));
861 [ # # ]: 0 : CHECK(obj, ENOMEM);
862 : :
863 : : /* Object construction. */
864 : 0 : obj_handle = type->constructor(args);
865 [ # # ]: 0 : if (!obj_handle) {
866 : 0 : free(obj);
867 : 0 : CHECK(0, ENODEV);
868 : : }
869 : :
870 : : /* Node initialization. */
871 : 0 : strcpy(obj->name, name);
872 : 0 : obj->type = type;
873 : 0 : obj->obj = obj_handle;
874 : 0 : obj->struct_id = p->n_structs;
875 : 0 : obj->id = p->n_extern_objs;
876 : :
877 : : /* Node add to tailq. */
878 : 0 : TAILQ_INSERT_TAIL(&p->extern_objs, obj, node);
879 : 0 : p->n_extern_objs++;
880 : 0 : p->n_structs++;
881 : :
882 : 0 : return 0;
883 : : }
884 : :
885 : : static int
886 : 0 : extern_obj_build(struct rte_swx_pipeline *p)
887 : : {
888 : : uint32_t i;
889 : :
890 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
891 : : struct thread *t = &p->threads[i];
892 : : struct extern_obj *obj;
893 : :
894 : 0 : t->extern_objs = calloc(p->n_extern_objs,
895 : : sizeof(struct extern_obj_runtime));
896 [ # # ]: 0 : CHECK(t->extern_objs, ENOMEM);
897 : :
898 [ # # ]: 0 : TAILQ_FOREACH(obj, &p->extern_objs, node) {
899 : 0 : struct extern_obj_runtime *r =
900 : 0 : &t->extern_objs[obj->id];
901 : : struct extern_type_member_func *func;
902 : 0 : uint32_t mailbox_size =
903 : 0 : obj->type->mailbox_struct_type->n_bits / 8;
904 : :
905 : 0 : r->obj = obj->obj;
906 : :
907 : 0 : r->mailbox = calloc(1, mailbox_size);
908 [ # # ]: 0 : CHECK(r->mailbox, ENOMEM);
909 : :
910 [ # # ]: 0 : TAILQ_FOREACH(func, &obj->type->funcs, node)
911 : 0 : r->funcs[func->id] = func->func;
912 : :
913 : 0 : t->structs[obj->struct_id] = r->mailbox;
914 : : }
915 : : }
916 : :
917 : : return 0;
918 : : }
919 : :
920 : : static void
921 : 0 : extern_obj_build_free(struct rte_swx_pipeline *p)
922 : : {
923 : : uint32_t i;
924 : :
925 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
926 : : struct thread *t = &p->threads[i];
927 : : uint32_t j;
928 : :
929 [ # # ]: 0 : if (!t->extern_objs)
930 : 0 : continue;
931 : :
932 [ # # ]: 0 : for (j = 0; j < p->n_extern_objs; j++) {
933 : 0 : struct extern_obj_runtime *r = &t->extern_objs[j];
934 : :
935 : 0 : free(r->mailbox);
936 : : }
937 : :
938 : 0 : free(t->extern_objs);
939 : 0 : t->extern_objs = NULL;
940 : : }
941 : 0 : }
942 : :
943 : : static void
944 : 0 : extern_obj_free(struct rte_swx_pipeline *p)
945 : : {
946 : 0 : extern_obj_build_free(p);
947 : :
948 : : /* Extern objects. */
949 : 0 : for ( ; ; ) {
950 : : struct extern_obj *elem;
951 : :
952 : 0 : elem = TAILQ_FIRST(&p->extern_objs);
953 [ # # ]: 0 : if (!elem)
954 : : break;
955 : :
956 [ # # ]: 0 : TAILQ_REMOVE(&p->extern_objs, elem, node);
957 [ # # ]: 0 : if (elem->obj)
958 : 0 : elem->type->destructor(elem->obj);
959 : 0 : free(elem);
960 : : }
961 : :
962 : : /* Extern types. */
963 : 0 : for ( ; ; ) {
964 : : struct extern_type *elem;
965 : :
966 : 0 : elem = TAILQ_FIRST(&p->extern_types);
967 [ # # ]: 0 : if (!elem)
968 : : break;
969 : :
970 [ # # ]: 0 : TAILQ_REMOVE(&p->extern_types, elem, node);
971 : :
972 : 0 : for ( ; ; ) {
973 : : struct extern_type_member_func *func;
974 : :
975 : 0 : func = TAILQ_FIRST(&elem->funcs);
976 [ # # ]: 0 : if (!func)
977 : : break;
978 : :
979 [ # # ]: 0 : TAILQ_REMOVE(&elem->funcs, func, node);
980 : 0 : free(func);
981 : : }
982 : :
983 : 0 : free(elem);
984 : : }
985 : 0 : }
986 : :
987 : : /*
988 : : * Extern function.
989 : : */
990 : : static struct extern_func *
991 : : extern_func_find(struct rte_swx_pipeline *p, const char *name)
992 : : {
993 : : struct extern_func *elem;
994 : :
995 [ # # # # : 0 : TAILQ_FOREACH(elem, &p->extern_funcs, node)
# # ]
996 [ # # # # : 0 : if (strcmp(elem->name, name) == 0)
# # ]
997 : : return elem;
998 : :
999 : : return NULL;
1000 : : }
1001 : :
1002 : : static struct extern_func *
1003 : 0 : extern_func_parse(struct rte_swx_pipeline *p,
1004 : : const char *name)
1005 : : {
1006 [ # # # # ]: 0 : if (name[0] != 'f' || name[1] != '.')
1007 : : return NULL;
1008 : :
1009 : 0 : return extern_func_find(p, &name[2]);
1010 : : }
1011 : :
1012 : : static struct field *
1013 : 0 : extern_func_mailbox_field_parse(struct rte_swx_pipeline *p,
1014 : : const char *name,
1015 : : struct extern_func **function)
1016 : : {
1017 : : struct extern_func *func;
1018 : : struct field *f;
1019 : : char *func_name, *field_name;
1020 : :
1021 [ # # # # ]: 0 : if ((name[0] != 'f') || (name[1] != '.'))
1022 : : return NULL;
1023 : :
1024 : 0 : func_name = strdup(&name[2]);
1025 [ # # ]: 0 : if (!func_name)
1026 : : return NULL;
1027 : :
1028 : 0 : field_name = strchr(func_name, '.');
1029 [ # # ]: 0 : if (!field_name) {
1030 : 0 : free(func_name);
1031 : 0 : return NULL;
1032 : : }
1033 : :
1034 : 0 : *field_name = 0;
1035 : 0 : field_name++;
1036 : :
1037 : : func = extern_func_find(p, func_name);
1038 [ # # ]: 0 : if (!func) {
1039 : 0 : free(func_name);
1040 : 0 : return NULL;
1041 : : }
1042 : :
1043 : 0 : f = struct_type_field_find(func->mailbox_struct_type, field_name);
1044 [ # # ]: 0 : if (!f) {
1045 : 0 : free(func_name);
1046 : 0 : return NULL;
1047 : : }
1048 : :
1049 [ # # ]: 0 : if (function)
1050 : 0 : *function = func;
1051 : :
1052 : 0 : free(func_name);
1053 : 0 : return f;
1054 : : }
1055 : :
1056 : : int
1057 : 0 : rte_swx_pipeline_extern_func_register(struct rte_swx_pipeline *p,
1058 : : const char *name,
1059 : : const char *mailbox_struct_type_name,
1060 : : rte_swx_extern_func_t func)
1061 : : {
1062 : : struct extern_func *f;
1063 : : struct struct_type *mailbox_struct_type;
1064 : :
1065 [ # # ]: 0 : CHECK(p, EINVAL);
1066 : :
1067 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
1068 [ # # ]: 0 : CHECK(!extern_func_find(p, name), EEXIST);
1069 : :
1070 [ # # # # : 0 : CHECK_NAME(mailbox_struct_type_name, EINVAL);
# # ]
1071 : : mailbox_struct_type = struct_type_find(p, mailbox_struct_type_name);
1072 [ # # ]: 0 : CHECK(mailbox_struct_type, EINVAL);
1073 [ # # ]: 0 : CHECK(!mailbox_struct_type->var_size, EINVAL);
1074 : :
1075 [ # # ]: 0 : CHECK(func, EINVAL);
1076 : :
1077 : : /* Node allocation. */
1078 : 0 : f = calloc(1, sizeof(struct extern_func));
1079 : : CHECK(func, ENOMEM);
1080 : :
1081 : : /* Node initialization. */
1082 : 0 : strcpy(f->name, name);
1083 : 0 : f->mailbox_struct_type = mailbox_struct_type;
1084 : 0 : f->func = func;
1085 : 0 : f->struct_id = p->n_structs;
1086 : 0 : f->id = p->n_extern_funcs;
1087 : :
1088 : : /* Node add to tailq. */
1089 : 0 : TAILQ_INSERT_TAIL(&p->extern_funcs, f, node);
1090 : 0 : p->n_extern_funcs++;
1091 : 0 : p->n_structs++;
1092 : :
1093 : 0 : return 0;
1094 : : }
1095 : :
1096 : : static int
1097 : 0 : extern_func_build(struct rte_swx_pipeline *p)
1098 : : {
1099 : : uint32_t i;
1100 : :
1101 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1102 : : struct thread *t = &p->threads[i];
1103 : : struct extern_func *func;
1104 : :
1105 : : /* Memory allocation. */
1106 : 0 : t->extern_funcs = calloc(p->n_extern_funcs,
1107 : : sizeof(struct extern_func_runtime));
1108 [ # # ]: 0 : CHECK(t->extern_funcs, ENOMEM);
1109 : :
1110 : : /* Extern function. */
1111 [ # # ]: 0 : TAILQ_FOREACH(func, &p->extern_funcs, node) {
1112 : 0 : struct extern_func_runtime *r =
1113 : 0 : &t->extern_funcs[func->id];
1114 : 0 : uint32_t mailbox_size =
1115 : 0 : func->mailbox_struct_type->n_bits / 8;
1116 : :
1117 : 0 : r->func = func->func;
1118 : :
1119 : 0 : r->mailbox = calloc(1, mailbox_size);
1120 [ # # ]: 0 : CHECK(r->mailbox, ENOMEM);
1121 : :
1122 : 0 : t->structs[func->struct_id] = r->mailbox;
1123 : : }
1124 : : }
1125 : :
1126 : : return 0;
1127 : : }
1128 : :
1129 : : static void
1130 : 0 : extern_func_build_free(struct rte_swx_pipeline *p)
1131 : : {
1132 : : uint32_t i;
1133 : :
1134 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1135 : : struct thread *t = &p->threads[i];
1136 : : uint32_t j;
1137 : :
1138 [ # # ]: 0 : if (!t->extern_funcs)
1139 : 0 : continue;
1140 : :
1141 [ # # ]: 0 : for (j = 0; j < p->n_extern_funcs; j++) {
1142 : 0 : struct extern_func_runtime *r = &t->extern_funcs[j];
1143 : :
1144 : 0 : free(r->mailbox);
1145 : : }
1146 : :
1147 : 0 : free(t->extern_funcs);
1148 : 0 : t->extern_funcs = NULL;
1149 : : }
1150 : 0 : }
1151 : :
1152 : : static void
1153 : 0 : extern_func_free(struct rte_swx_pipeline *p)
1154 : : {
1155 : 0 : extern_func_build_free(p);
1156 : :
1157 : 0 : for ( ; ; ) {
1158 : : struct extern_func *elem;
1159 : :
1160 : 0 : elem = TAILQ_FIRST(&p->extern_funcs);
1161 [ # # ]: 0 : if (!elem)
1162 : : break;
1163 : :
1164 [ # # ]: 0 : TAILQ_REMOVE(&p->extern_funcs, elem, node);
1165 : 0 : free(elem);
1166 : : }
1167 : 0 : }
1168 : :
1169 : : /*
1170 : : * Hash function.
1171 : : */
1172 : : static struct hash_func *
1173 : : hash_func_find(struct rte_swx_pipeline *p, const char *name)
1174 : : {
1175 : : struct hash_func *elem;
1176 : :
1177 [ # # # # : 0 : TAILQ_FOREACH(elem, &p->hash_funcs, node)
# # # # ]
1178 [ # # # # : 0 : if (strcmp(elem->name, name) == 0)
# # # # ]
1179 : : return elem;
1180 : :
1181 : : return NULL;
1182 : : }
1183 : :
1184 : : int
1185 : 0 : rte_swx_pipeline_hash_func_register(struct rte_swx_pipeline *p,
1186 : : const char *name,
1187 : : rte_swx_hash_func_t func)
1188 : : {
1189 : : struct hash_func *f;
1190 : :
1191 [ # # ]: 0 : CHECK(p, EINVAL);
1192 : :
1193 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
1194 [ # # ]: 0 : CHECK(!hash_func_find(p, name), EEXIST);
1195 : :
1196 [ # # ]: 0 : CHECK(func, EINVAL);
1197 : :
1198 : : /* Node allocation. */
1199 : 0 : f = calloc(1, sizeof(struct hash_func));
1200 : : CHECK(func, ENOMEM);
1201 : :
1202 : : /* Node initialization. */
1203 : 0 : strcpy(f->name, name);
1204 : 0 : f->func = func;
1205 : 0 : f->id = p->n_hash_funcs;
1206 : :
1207 : : /* Node add to tailq. */
1208 : 0 : TAILQ_INSERT_TAIL(&p->hash_funcs, f, node);
1209 : 0 : p->n_hash_funcs++;
1210 : :
1211 : 0 : return 0;
1212 : : }
1213 : :
1214 : : static int
1215 : 0 : hash_func_build(struct rte_swx_pipeline *p)
1216 : : {
1217 : : struct hash_func *func;
1218 : :
1219 : : /* Memory allocation. */
1220 : 0 : p->hash_func_runtime = calloc(p->n_hash_funcs, sizeof(struct hash_func_runtime));
1221 [ # # ]: 0 : CHECK(p->hash_func_runtime, ENOMEM);
1222 : :
1223 : : /* Hash function. */
1224 [ # # ]: 0 : TAILQ_FOREACH(func, &p->hash_funcs, node) {
1225 : 0 : struct hash_func_runtime *r = &p->hash_func_runtime[func->id];
1226 : :
1227 : 0 : r->func = func->func;
1228 : : }
1229 : :
1230 : : return 0;
1231 : : }
1232 : :
1233 : : static void
1234 : : hash_func_build_free(struct rte_swx_pipeline *p)
1235 : : {
1236 : 0 : free(p->hash_func_runtime);
1237 : 0 : p->hash_func_runtime = NULL;
1238 : 0 : }
1239 : :
1240 : : static void
1241 : 0 : hash_func_free(struct rte_swx_pipeline *p)
1242 : : {
1243 : : hash_func_build_free(p);
1244 : :
1245 : 0 : for ( ; ; ) {
1246 : : struct hash_func *elem;
1247 : :
1248 : 0 : elem = TAILQ_FIRST(&p->hash_funcs);
1249 [ # # ]: 0 : if (!elem)
1250 : : break;
1251 : :
1252 [ # # ]: 0 : TAILQ_REMOVE(&p->hash_funcs, elem, node);
1253 : 0 : free(elem);
1254 : : }
1255 : 0 : }
1256 : :
1257 : : /*
1258 : : * RSS.
1259 : : */
1260 : : static struct rss *
1261 : : rss_find(struct rte_swx_pipeline *p, const char *name)
1262 : : {
1263 : : struct rss *elem;
1264 : :
1265 [ # # # # : 0 : TAILQ_FOREACH(elem, &p->rss, node)
# # # # #
# ]
1266 [ # # # # : 0 : if (strcmp(elem->name, name) == 0)
# # # # #
# ]
1267 : : return elem;
1268 : :
1269 : : return NULL;
1270 : : }
1271 : :
1272 : : static struct rss *
1273 : : rss_find_by_id(struct rte_swx_pipeline *p, uint32_t rss_obj_id)
1274 : : {
1275 : : struct rss *elem;
1276 : :
1277 [ # # ]: 0 : TAILQ_FOREACH(elem, &p->rss, node)
1278 [ # # ]: 0 : if (elem->id == rss_obj_id)
1279 : : return elem;
1280 : :
1281 : : return NULL;
1282 : : }
1283 : :
1284 : : int
1285 : 0 : rte_swx_pipeline_rss_config(struct rte_swx_pipeline *p, const char *name)
1286 : : {
1287 : : struct rss *r;
1288 : :
1289 [ # # ]: 0 : CHECK(p, EINVAL);
1290 : :
1291 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
1292 [ # # ]: 0 : CHECK(!rss_find(p, name), EEXIST);
1293 : :
1294 : : /* Memory allocation. */
1295 : 0 : r = calloc(1, sizeof(struct rss));
1296 [ # # ]: 0 : CHECK(r, ENOMEM);
1297 : :
1298 : : /* Node initialization. */
1299 : 0 : strcpy(r->name, name);
1300 : 0 : r->id = p->n_rss;
1301 : :
1302 : : /* Node add to tailq. */
1303 : 0 : TAILQ_INSERT_TAIL(&p->rss, r, node);
1304 : 0 : p->n_rss++;
1305 : :
1306 : 0 : return 0;
1307 : : }
1308 : :
1309 : : static void
1310 : 0 : rss_build_free(struct rte_swx_pipeline *p)
1311 : : {
1312 : : uint32_t i;
1313 : :
1314 [ # # ]: 0 : if (!p->rss_runtime)
1315 : : return;
1316 : :
1317 [ # # ]: 0 : for (i = 0; i < p->n_rss; i++)
1318 : 0 : free(p->rss_runtime[i]);
1319 : :
1320 : 0 : free(p->rss_runtime);
1321 : 0 : p->rss_runtime = NULL;
1322 : : }
1323 : :
1324 : : static const struct {
1325 : : uint32_t key_size;
1326 : : uint8_t key[4];
1327 : : } rss_runtime_default = {
1328 : : .key_size = 4,
1329 : : .key = {0, 0, 0, 0},
1330 : : };
1331 : :
1332 : : static int
1333 : 0 : rss_build(struct rte_swx_pipeline *p)
1334 : : {
1335 : : uint32_t i;
1336 : : int status = 0;
1337 : :
1338 : : /* Memory allocation. */
1339 : 0 : p->rss_runtime = calloc(p->n_rss, sizeof(struct rss_runtime *));
1340 [ # # ]: 0 : if (!p->rss_runtime) {
1341 : : status = -ENOMEM;
1342 : 0 : goto error;
1343 : : }
1344 : :
1345 : : /* RSS. */
1346 [ # # ]: 0 : for (i = 0; i < p->n_rss; i++) {
1347 : 0 : p->rss_runtime[i] = malloc(sizeof(rss_runtime_default));
1348 [ # # ]: 0 : if (!p->rss_runtime[i]) {
1349 : : status = -ENOMEM;
1350 : 0 : goto error;
1351 : : }
1352 : :
1353 : : memcpy(p->rss_runtime[i], &rss_runtime_default, sizeof(rss_runtime_default));
1354 : : }
1355 : :
1356 : : return 0;
1357 : :
1358 : 0 : error:
1359 : 0 : rss_build_free(p);
1360 : 0 : return status;
1361 : : }
1362 : :
1363 : : static void
1364 : 0 : rss_free(struct rte_swx_pipeline *p)
1365 : : {
1366 : 0 : rss_build_free(p);
1367 : :
1368 : 0 : for ( ; ; ) {
1369 : : struct rss *elem;
1370 : :
1371 : 0 : elem = TAILQ_FIRST(&p->rss);
1372 [ # # ]: 0 : if (!elem)
1373 : : break;
1374 : :
1375 [ # # ]: 0 : TAILQ_REMOVE(&p->rss, elem, node);
1376 : 0 : free(elem);
1377 : : }
1378 : 0 : }
1379 : :
1380 : : /*
1381 : : * Header.
1382 : : */
1383 : : static struct header *
1384 : : header_find(struct rte_swx_pipeline *p, const char *name)
1385 : : {
1386 : : struct header *elem;
1387 : :
1388 [ # # # # : 0 : TAILQ_FOREACH(elem, &p->headers, node)
# # ]
1389 [ # # # # : 0 : if (strcmp(elem->name, name) == 0)
# # ]
1390 : : return elem;
1391 : :
1392 : : return NULL;
1393 : : }
1394 : :
1395 : : static struct header *
1396 : : header_find_by_struct_id(struct rte_swx_pipeline *p, uint32_t struct_id)
1397 : : {
1398 : : struct header *elem;
1399 : :
1400 [ # # # # ]: 0 : TAILQ_FOREACH(elem, &p->headers, node)
1401 [ # # # # ]: 0 : if (elem->struct_id == struct_id)
1402 : : return elem;
1403 : :
1404 : : return NULL;
1405 : : }
1406 : :
1407 : : static struct header *
1408 : 0 : header_parse(struct rte_swx_pipeline *p,
1409 : : const char *name)
1410 : : {
1411 [ # # # # ]: 0 : if (name[0] != 'h' || name[1] != '.')
1412 : : return NULL;
1413 : :
1414 : 0 : return header_find(p, &name[2]);
1415 : : }
1416 : :
1417 : : static struct field *
1418 : 0 : header_field_parse(struct rte_swx_pipeline *p,
1419 : : const char *name,
1420 : : struct header **header)
1421 : : {
1422 : : struct header *h;
1423 : : struct field *f;
1424 : : char *header_name, *field_name;
1425 : :
1426 [ # # # # ]: 0 : if ((name[0] != 'h') || (name[1] != '.'))
1427 : : return NULL;
1428 : :
1429 : 0 : header_name = strdup(&name[2]);
1430 [ # # ]: 0 : if (!header_name)
1431 : : return NULL;
1432 : :
1433 : 0 : field_name = strchr(header_name, '.');
1434 [ # # ]: 0 : if (!field_name) {
1435 : 0 : free(header_name);
1436 : 0 : return NULL;
1437 : : }
1438 : :
1439 : 0 : *field_name = 0;
1440 : 0 : field_name++;
1441 : :
1442 : : h = header_find(p, header_name);
1443 [ # # ]: 0 : if (!h) {
1444 : 0 : free(header_name);
1445 : 0 : return NULL;
1446 : : }
1447 : :
1448 : 0 : f = struct_type_field_find(h->st, field_name);
1449 [ # # ]: 0 : if (!f) {
1450 : 0 : free(header_name);
1451 : 0 : return NULL;
1452 : : }
1453 : :
1454 [ # # ]: 0 : if (header)
1455 : 0 : *header = h;
1456 : :
1457 : 0 : free(header_name);
1458 : 0 : return f;
1459 : : }
1460 : :
1461 : : int
1462 : 0 : rte_swx_pipeline_packet_header_register(struct rte_swx_pipeline *p,
1463 : : const char *name,
1464 : : const char *struct_type_name)
1465 : : {
1466 : : struct struct_type *st;
1467 : : struct header *h;
1468 : : size_t n_headers_max;
1469 : :
1470 [ # # ]: 0 : CHECK(p, EINVAL);
1471 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
1472 [ # # # # : 0 : CHECK_NAME(struct_type_name, EINVAL);
# # ]
1473 : :
1474 [ # # ]: 0 : CHECK(!header_find(p, name), EEXIST);
1475 : :
1476 : : st = struct_type_find(p, struct_type_name);
1477 [ # # ]: 0 : CHECK(st, EINVAL);
1478 : :
1479 : : n_headers_max = RTE_SIZEOF_FIELD(struct thread, valid_headers) * 8;
1480 [ # # ]: 0 : CHECK(p->n_headers < n_headers_max, ENOSPC);
1481 : :
1482 : : /* Node allocation. */
1483 : 0 : h = calloc(1, sizeof(struct header));
1484 [ # # ]: 0 : CHECK(h, ENOMEM);
1485 : :
1486 : : /* Node initialization. */
1487 : 0 : strcpy(h->name, name);
1488 : 0 : h->st = st;
1489 : 0 : h->struct_id = p->n_structs;
1490 : 0 : h->id = p->n_headers;
1491 : :
1492 : : /* Node add to tailq. */
1493 : 0 : TAILQ_INSERT_TAIL(&p->headers, h, node);
1494 : 0 : p->n_headers++;
1495 : 0 : p->n_structs++;
1496 : :
1497 : 0 : return 0;
1498 : : }
1499 : :
1500 : : static int
1501 : 0 : header_build(struct rte_swx_pipeline *p)
1502 : : {
1503 : : struct header *h;
1504 : : uint32_t n_bytes = 0, i;
1505 : :
1506 [ # # ]: 0 : TAILQ_FOREACH(h, &p->headers, node) {
1507 : 0 : n_bytes += h->st->n_bits / 8;
1508 : : }
1509 : :
1510 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1511 : : struct thread *t = &p->threads[i];
1512 : : uint32_t offset = 0;
1513 : :
1514 : 0 : t->headers = calloc(p->n_headers,
1515 : : sizeof(struct header_runtime));
1516 [ # # ]: 0 : CHECK(t->headers, ENOMEM);
1517 : :
1518 : 0 : t->headers_out = calloc(p->n_headers,
1519 : : sizeof(struct header_out_runtime));
1520 [ # # ]: 0 : CHECK(t->headers_out, ENOMEM);
1521 : :
1522 : 0 : t->header_storage = calloc(1, n_bytes);
1523 [ # # ]: 0 : CHECK(t->header_storage, ENOMEM);
1524 : :
1525 : 0 : t->header_out_storage = calloc(1, n_bytes);
1526 [ # # ]: 0 : CHECK(t->header_out_storage, ENOMEM);
1527 : :
1528 [ # # ]: 0 : TAILQ_FOREACH(h, &p->headers, node) {
1529 : : uint8_t *header_storage;
1530 : 0 : uint32_t n_bytes = h->st->n_bits / 8;
1531 : :
1532 : 0 : header_storage = &t->header_storage[offset];
1533 : 0 : offset += n_bytes;
1534 : :
1535 : 0 : t->headers[h->id].ptr0 = header_storage;
1536 : 0 : t->headers[h->id].n_bytes = n_bytes;
1537 : :
1538 : 0 : t->structs[h->struct_id] = header_storage;
1539 : : }
1540 : : }
1541 : :
1542 : : return 0;
1543 : : }
1544 : :
1545 : : static void
1546 : 0 : header_build_free(struct rte_swx_pipeline *p)
1547 : : {
1548 : : uint32_t i;
1549 : :
1550 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1551 : : struct thread *t = &p->threads[i];
1552 : :
1553 : 0 : free(t->headers_out);
1554 : 0 : t->headers_out = NULL;
1555 : :
1556 : 0 : free(t->headers);
1557 : 0 : t->headers = NULL;
1558 : :
1559 : 0 : free(t->header_out_storage);
1560 : 0 : t->header_out_storage = NULL;
1561 : :
1562 : 0 : free(t->header_storage);
1563 : 0 : t->header_storage = NULL;
1564 : : }
1565 : 0 : }
1566 : :
1567 : : static void
1568 : 0 : header_free(struct rte_swx_pipeline *p)
1569 : : {
1570 : 0 : header_build_free(p);
1571 : :
1572 : 0 : for ( ; ; ) {
1573 : : struct header *elem;
1574 : :
1575 : 0 : elem = TAILQ_FIRST(&p->headers);
1576 [ # # ]: 0 : if (!elem)
1577 : : break;
1578 : :
1579 [ # # ]: 0 : TAILQ_REMOVE(&p->headers, elem, node);
1580 : 0 : free(elem);
1581 : : }
1582 : 0 : }
1583 : :
1584 : : /*
1585 : : * Meta-data.
1586 : : */
1587 : : static struct field *
1588 : 0 : metadata_field_parse(struct rte_swx_pipeline *p, const char *name)
1589 : : {
1590 [ # # ]: 0 : if (!p->metadata_st)
1591 : : return NULL;
1592 : :
1593 [ # # # # ]: 0 : if (name[0] != 'm' || name[1] != '.')
1594 : : return NULL;
1595 : :
1596 : 0 : return struct_type_field_find(p->metadata_st, &name[2]);
1597 : : }
1598 : :
1599 : : int
1600 : 0 : rte_swx_pipeline_packet_metadata_register(struct rte_swx_pipeline *p,
1601 : : const char *struct_type_name)
1602 : : {
1603 : : struct struct_type *st = NULL;
1604 : :
1605 [ # # ]: 0 : CHECK(p, EINVAL);
1606 : :
1607 [ # # # # : 0 : CHECK_NAME(struct_type_name, EINVAL);
# # ]
1608 : : st = struct_type_find(p, struct_type_name);
1609 [ # # ]: 0 : CHECK(st, EINVAL);
1610 [ # # ]: 0 : CHECK(!st->var_size, EINVAL);
1611 [ # # ]: 0 : CHECK(!p->metadata_st, EINVAL);
1612 : :
1613 : 0 : p->metadata_st = st;
1614 : 0 : p->metadata_struct_id = p->n_structs;
1615 : :
1616 : 0 : p->n_structs++;
1617 : :
1618 : 0 : return 0;
1619 : : }
1620 : :
1621 : : static int
1622 : 0 : metadata_build(struct rte_swx_pipeline *p)
1623 : : {
1624 : 0 : uint32_t n_bytes = p->metadata_st->n_bits / 8;
1625 : : uint32_t i;
1626 : :
1627 : : /* Thread-level initialization. */
1628 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1629 : : struct thread *t = &p->threads[i];
1630 : : uint8_t *metadata;
1631 : :
1632 : 0 : metadata = calloc(1, n_bytes);
1633 [ # # ]: 0 : CHECK(metadata, ENOMEM);
1634 : :
1635 : 0 : t->metadata = metadata;
1636 : 0 : t->structs[p->metadata_struct_id] = metadata;
1637 : : }
1638 : :
1639 : : return 0;
1640 : : }
1641 : :
1642 : : static void
1643 : : metadata_build_free(struct rte_swx_pipeline *p)
1644 : : {
1645 : : uint32_t i;
1646 : :
1647 [ # # # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1648 : : struct thread *t = &p->threads[i];
1649 : :
1650 : 0 : free(t->metadata);
1651 : 0 : t->metadata = NULL;
1652 : : }
1653 : : }
1654 : :
1655 : : static void
1656 : : metadata_free(struct rte_swx_pipeline *p)
1657 : : {
1658 : : metadata_build_free(p);
1659 : : }
1660 : :
1661 : : /*
1662 : : * Instruction.
1663 : : */
1664 : : static int
1665 : : instruction_is_tx(enum instruction_type type)
1666 : : {
1667 [ # # ]: 0 : switch (type) {
1668 : : case INSTR_TX:
1669 : : case INSTR_TX_I:
1670 : : case INSTR_DROP:
1671 : : return 1;
1672 : :
1673 : : default:
1674 : : return 0;
1675 : : }
1676 : : }
1677 : :
1678 : : static int
1679 : : instruction_does_tx(struct instruction *instr)
1680 : : {
1681 [ # # # # ]: 0 : switch (instr->type) {
1682 : : case INSTR_TX:
1683 : : case INSTR_TX_I:
1684 : : case INSTR_DROP:
1685 : : case INSTR_HDR_EMIT_TX:
1686 : : case INSTR_HDR_EMIT2_TX:
1687 : : case INSTR_HDR_EMIT3_TX:
1688 : : case INSTR_HDR_EMIT4_TX:
1689 : : case INSTR_HDR_EMIT5_TX:
1690 : : case INSTR_HDR_EMIT6_TX:
1691 : : case INSTR_HDR_EMIT7_TX:
1692 : : case INSTR_HDR_EMIT8_TX:
1693 : : return 1;
1694 : : default:
1695 : : return 0;
1696 : : }
1697 : : }
1698 : :
1699 : : static int
1700 : : instruction_is_jmp(struct instruction *instr)
1701 : : {
1702 [ # # # # ]: 0 : switch (instr->type) {
1703 : : case INSTR_JMP:
1704 : : case INSTR_JMP_VALID:
1705 : : case INSTR_JMP_INVALID:
1706 : : case INSTR_JMP_HIT:
1707 : : case INSTR_JMP_MISS:
1708 : : case INSTR_JMP_ACTION_HIT:
1709 : : case INSTR_JMP_ACTION_MISS:
1710 : : case INSTR_JMP_EQ:
1711 : : case INSTR_JMP_EQ_MH:
1712 : : case INSTR_JMP_EQ_HM:
1713 : : case INSTR_JMP_EQ_HH:
1714 : : case INSTR_JMP_EQ_I:
1715 : : case INSTR_JMP_NEQ:
1716 : : case INSTR_JMP_NEQ_MH:
1717 : : case INSTR_JMP_NEQ_HM:
1718 : : case INSTR_JMP_NEQ_HH:
1719 : : case INSTR_JMP_NEQ_I:
1720 : : case INSTR_JMP_LT:
1721 : : case INSTR_JMP_LT_MH:
1722 : : case INSTR_JMP_LT_HM:
1723 : : case INSTR_JMP_LT_HH:
1724 : : case INSTR_JMP_LT_MI:
1725 : : case INSTR_JMP_LT_HI:
1726 : : case INSTR_JMP_GT:
1727 : : case INSTR_JMP_GT_MH:
1728 : : case INSTR_JMP_GT_HM:
1729 : : case INSTR_JMP_GT_HH:
1730 : : case INSTR_JMP_GT_MI:
1731 : : case INSTR_JMP_GT_HI:
1732 : : return 1;
1733 : :
1734 : : default:
1735 : : return 0;
1736 : : }
1737 : : }
1738 : :
1739 : : static int
1740 : : instruction_does_thread_yield(struct instruction *instr)
1741 : : {
1742 : 0 : switch (instr->type) {
1743 : : case INSTR_RX:
1744 : : case INSTR_TABLE:
1745 : : case INSTR_TABLE_AF:
1746 : : case INSTR_SELECTOR:
1747 : : case INSTR_LEARNER:
1748 : : case INSTR_LEARNER_AF:
1749 : : case INSTR_EXTERN_OBJ:
1750 : : case INSTR_EXTERN_FUNC:
1751 : : return 1;
1752 : : default:
1753 : : return 0;
1754 : : }
1755 : : }
1756 : :
1757 : : static struct field *
1758 : : action_field_parse(struct action *action, const char *name);
1759 : :
1760 : : static struct field *
1761 : 0 : struct_field_parse(struct rte_swx_pipeline *p,
1762 : : struct action *action,
1763 : : const char *name,
1764 : : uint32_t *struct_id)
1765 : : {
1766 : : struct field *f;
1767 : :
1768 [ # # # # : 0 : switch (name[0]) {
# # ]
1769 : 0 : case 'h':
1770 : : {
1771 : : struct header *header;
1772 : :
1773 : 0 : f = header_field_parse(p, name, &header);
1774 [ # # ]: 0 : if (!f)
1775 : : return NULL;
1776 : :
1777 : 0 : *struct_id = header->struct_id;
1778 : 0 : return f;
1779 : : }
1780 : :
1781 : 0 : case 'm':
1782 : : {
1783 : 0 : f = metadata_field_parse(p, name);
1784 [ # # ]: 0 : if (!f)
1785 : : return NULL;
1786 : :
1787 : 0 : *struct_id = p->metadata_struct_id;
1788 : 0 : return f;
1789 : : }
1790 : :
1791 : 0 : case 't':
1792 : : {
1793 [ # # ]: 0 : if (!action)
1794 : : return NULL;
1795 : :
1796 : 0 : f = action_field_parse(action, name);
1797 [ # # ]: 0 : if (!f)
1798 : : return NULL;
1799 : :
1800 : 0 : *struct_id = 0;
1801 : 0 : return f;
1802 : : }
1803 : :
1804 : 0 : case 'e':
1805 : : {
1806 : : struct extern_obj *obj;
1807 : :
1808 : 0 : f = extern_obj_mailbox_field_parse(p, name, &obj);
1809 [ # # ]: 0 : if (!f)
1810 : : return NULL;
1811 : :
1812 : 0 : *struct_id = obj->struct_id;
1813 : 0 : return f;
1814 : : }
1815 : :
1816 : 0 : case 'f':
1817 : : {
1818 : : struct extern_func *func;
1819 : :
1820 : 0 : f = extern_func_mailbox_field_parse(p, name, &func);
1821 [ # # ]: 0 : if (!f)
1822 : : return NULL;
1823 : :
1824 : 0 : *struct_id = func->struct_id;
1825 : 0 : return f;
1826 : : }
1827 : :
1828 : : default:
1829 : : return NULL;
1830 : : }
1831 : : }
1832 : :
1833 : : /*
1834 : : * rx.
1835 : : */
1836 : : static int
1837 : 0 : instr_rx_translate(struct rte_swx_pipeline *p,
1838 : : struct action *action,
1839 : : char **tokens,
1840 : : int n_tokens,
1841 : : struct instruction *instr,
1842 : : struct instruction_data *data __rte_unused)
1843 : : {
1844 : : struct field *f;
1845 : :
1846 [ # # ]: 0 : CHECK(!action, EINVAL);
1847 [ # # ]: 0 : CHECK(n_tokens == 2, EINVAL);
1848 : :
1849 : 0 : f = metadata_field_parse(p, tokens[1]);
1850 [ # # ]: 0 : CHECK(f, EINVAL);
1851 [ # # ]: 0 : CHECK(f->n_bits <= 64, EINVAL);
1852 : :
1853 : 0 : instr->type = INSTR_RX;
1854 : 0 : instr->io.io.offset = f->offset / 8;
1855 : 0 : instr->io.io.n_bits = f->n_bits;
1856 : 0 : return 0;
1857 : : }
1858 : :
1859 : : /*
1860 : : * tx.
1861 : : */
1862 : : static int
1863 : 0 : instr_tx_translate(struct rte_swx_pipeline *p,
1864 : : struct action *action __rte_unused,
1865 : : char **tokens,
1866 : : int n_tokens,
1867 : : struct instruction *instr,
1868 : : struct instruction_data *data __rte_unused)
1869 : : {
1870 : 0 : char *port = tokens[1];
1871 : : struct field *f;
1872 : : uint32_t port_val;
1873 : :
1874 [ # # ]: 0 : CHECK(n_tokens == 2, EINVAL);
1875 : :
1876 : 0 : f = metadata_field_parse(p, port);
1877 [ # # ]: 0 : if (f) {
1878 [ # # ]: 0 : CHECK(f->n_bits <= 64, EINVAL);
1879 : 0 : instr->type = INSTR_TX;
1880 : 0 : instr->io.io.offset = f->offset / 8;
1881 : 0 : instr->io.io.n_bits = f->n_bits;
1882 : 0 : return 0;
1883 : : }
1884 : :
1885 : : /* TX_I. */
1886 : 0 : port_val = strtoul(port, &port, 0);
1887 [ # # ]: 0 : CHECK(!port[0], EINVAL);
1888 : :
1889 : 0 : instr->type = INSTR_TX_I;
1890 : 0 : instr->io.io.val = port_val;
1891 : 0 : return 0;
1892 : : }
1893 : :
1894 : : static int
1895 : : instr_drop_translate(struct rte_swx_pipeline *p __rte_unused,
1896 : : struct action *action __rte_unused,
1897 : : char **tokens __rte_unused,
1898 : : int n_tokens,
1899 : : struct instruction *instr,
1900 : : struct instruction_data *data __rte_unused)
1901 : : {
1902 : 0 : CHECK(n_tokens == 1, EINVAL);
1903 : :
1904 : : /* DROP. */
1905 : 0 : instr->type = INSTR_DROP;
1906 : 0 : return 0;
1907 : : }
1908 : :
1909 : : static inline void
1910 : 0 : instr_tx_exec(struct rte_swx_pipeline *p)
1911 : : {
1912 : 0 : struct thread *t = &p->threads[p->thread_id];
1913 : 0 : struct instruction *ip = t->ip;
1914 : :
1915 : 0 : __instr_tx_exec(p, t, ip);
1916 : :
1917 : : /* Thread. */
1918 : : thread_ip_reset(p, t);
1919 : 0 : instr_rx_exec(p);
1920 : 0 : }
1921 : :
1922 : : static inline void
1923 : 0 : instr_tx_i_exec(struct rte_swx_pipeline *p)
1924 : : {
1925 : 0 : struct thread *t = &p->threads[p->thread_id];
1926 : 0 : struct instruction *ip = t->ip;
1927 : :
1928 : 0 : __instr_tx_i_exec(p, t, ip);
1929 : :
1930 : : /* Thread. */
1931 : : thread_ip_reset(p, t);
1932 : 0 : instr_rx_exec(p);
1933 : 0 : }
1934 : :
1935 : : static inline void
1936 : 0 : instr_drop_exec(struct rte_swx_pipeline *p)
1937 : : {
1938 : 0 : struct thread *t = &p->threads[p->thread_id];
1939 : 0 : struct instruction *ip = t->ip;
1940 : :
1941 : 0 : __instr_drop_exec(p, t, ip);
1942 : :
1943 : : /* Thread. */
1944 : : thread_ip_reset(p, t);
1945 : 0 : instr_rx_exec(p);
1946 : 0 : }
1947 : :
1948 : : /*
1949 : : * mirror.
1950 : : */
1951 : : static int
1952 : 0 : instr_mirror_translate(struct rte_swx_pipeline *p,
1953 : : struct action *action,
1954 : : char **tokens,
1955 : : int n_tokens,
1956 : : struct instruction *instr,
1957 : : struct instruction_data *data __rte_unused)
1958 : : {
1959 : 0 : char *dst = tokens[1], *src = tokens[2];
1960 : : struct field *fdst, *fsrc;
1961 : 0 : uint32_t dst_struct_id = 0, src_struct_id = 0;
1962 : :
1963 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
1964 : :
1965 : 0 : fdst = struct_field_parse(p, action, dst, &dst_struct_id);
1966 [ # # ]: 0 : CHECK(fdst, EINVAL);
1967 [ # # ]: 0 : CHECK(dst[0] != 'h', EINVAL);
1968 [ # # # # ]: 0 : CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
1969 : :
1970 : 0 : fsrc = struct_field_parse(p, action, src, &src_struct_id);
1971 [ # # ]: 0 : CHECK(fsrc, EINVAL);
1972 [ # # ]: 0 : CHECK(src[0] != 'h', EINVAL);
1973 [ # # # # ]: 0 : CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
1974 : :
1975 : 0 : instr->type = INSTR_MIRROR;
1976 : 0 : instr->mirror.dst.struct_id = (uint8_t)dst_struct_id;
1977 : 0 : instr->mirror.dst.n_bits = fdst->n_bits;
1978 : 0 : instr->mirror.dst.offset = fdst->offset / 8;
1979 : 0 : instr->mirror.src.struct_id = (uint8_t)src_struct_id;
1980 : 0 : instr->mirror.src.n_bits = fsrc->n_bits;
1981 : 0 : instr->mirror.src.offset = fsrc->offset / 8;
1982 : :
1983 : 0 : return 0;
1984 : : }
1985 : :
1986 : : static inline void
1987 : 0 : instr_mirror_exec(struct rte_swx_pipeline *p)
1988 : : {
1989 : 0 : struct thread *t = &p->threads[p->thread_id];
1990 : 0 : struct instruction *ip = t->ip;
1991 : :
1992 : 0 : __instr_mirror_exec(p, t, ip);
1993 : :
1994 : : /* Thread. */
1995 : : thread_ip_inc(p);
1996 : 0 : }
1997 : :
1998 : : /*
1999 : : * recirculate.
2000 : : */
2001 : : static int
2002 : : instr_recirculate_translate(struct rte_swx_pipeline *p __rte_unused,
2003 : : struct action *action __rte_unused,
2004 : : char **tokens __rte_unused,
2005 : : int n_tokens,
2006 : : struct instruction *instr,
2007 : : struct instruction_data *data __rte_unused)
2008 : : {
2009 : 0 : CHECK(n_tokens == 1, EINVAL);
2010 : :
2011 : 0 : instr->type = INSTR_RECIRCULATE;
2012 : 0 : return 0;
2013 : : }
2014 : :
2015 : : static int
2016 : : instr_recircid_translate(struct rte_swx_pipeline *p,
2017 : : struct action *action __rte_unused,
2018 : : char **tokens,
2019 : : int n_tokens,
2020 : : struct instruction *instr,
2021 : : struct instruction_data *data __rte_unused)
2022 : : {
2023 : : struct field *f;
2024 : :
2025 : 0 : CHECK(n_tokens == 2, EINVAL);
2026 : :
2027 : 0 : f = metadata_field_parse(p, tokens[1]);
2028 [ # # ]: 0 : CHECK(f, EINVAL);
2029 [ # # ]: 0 : CHECK(f->n_bits <= 64, EINVAL);
2030 : :
2031 : 0 : instr->type = INSTR_RECIRCID;
2032 : 0 : instr->io.io.offset = f->offset / 8;
2033 : 0 : instr->io.io.n_bits = f->n_bits;
2034 : 0 : return 0;
2035 : : }
2036 : :
2037 : : static inline void
2038 : 0 : instr_recirculate_exec(struct rte_swx_pipeline *p)
2039 : : {
2040 : 0 : struct thread *t = &p->threads[p->thread_id];
2041 : 0 : struct instruction *ip = t->ip;
2042 : :
2043 : : __instr_recirculate_exec(p, t, ip);
2044 : :
2045 : : /* Thread. */
2046 : : thread_ip_inc(p);
2047 : 0 : }
2048 : :
2049 : : static inline void
2050 : 0 : instr_recircid_exec(struct rte_swx_pipeline *p)
2051 : : {
2052 : 0 : struct thread *t = &p->threads[p->thread_id];
2053 : 0 : struct instruction *ip = t->ip;
2054 : :
2055 : : __instr_recircid_exec(p, t, ip);
2056 : :
2057 : : /* Thread. */
2058 : : thread_ip_inc(p);
2059 : 0 : }
2060 : :
2061 : : /*
2062 : : * extract.
2063 : : */
2064 : : static int
2065 : 0 : instr_hdr_extract_translate(struct rte_swx_pipeline *p,
2066 : : struct action *action,
2067 : : char **tokens,
2068 : : int n_tokens,
2069 : : struct instruction *instr,
2070 : : struct instruction_data *data __rte_unused)
2071 : : {
2072 : : struct header *h;
2073 : :
2074 [ # # ]: 0 : CHECK(!action, EINVAL);
2075 [ # # ]: 0 : CHECK((n_tokens == 2) || (n_tokens == 3), EINVAL);
2076 : :
2077 : 0 : h = header_parse(p, tokens[1]);
2078 [ # # ]: 0 : CHECK(h, EINVAL);
2079 : :
2080 [ # # ]: 0 : if (n_tokens == 2) {
2081 [ # # ]: 0 : CHECK(!h->st->var_size, EINVAL);
2082 : :
2083 : 0 : instr->type = INSTR_HDR_EXTRACT;
2084 : 0 : instr->io.hdr.header_id[0] = h->id;
2085 : 0 : instr->io.hdr.struct_id[0] = h->struct_id;
2086 : 0 : instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
2087 : : } else {
2088 : : struct field *mf;
2089 : :
2090 [ # # ]: 0 : CHECK(h->st->var_size, EINVAL);
2091 : :
2092 : 0 : mf = metadata_field_parse(p, tokens[2]);
2093 [ # # ]: 0 : CHECK(mf, EINVAL);
2094 [ # # ]: 0 : CHECK(mf->n_bits <= 64, EINVAL);
2095 : :
2096 : 0 : instr->type = INSTR_HDR_EXTRACT_M;
2097 : 0 : instr->io.io.offset = mf->offset / 8;
2098 : 0 : instr->io.io.n_bits = mf->n_bits;
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_min / 8;
2102 : : }
2103 : :
2104 : : return 0;
2105 : : }
2106 : :
2107 : : static int
2108 : 0 : instr_hdr_lookahead_translate(struct rte_swx_pipeline *p,
2109 : : struct action *action,
2110 : : char **tokens,
2111 : : int n_tokens,
2112 : : struct instruction *instr,
2113 : : struct instruction_data *data __rte_unused)
2114 : : {
2115 : : struct header *h;
2116 : :
2117 [ # # ]: 0 : CHECK(!action, EINVAL);
2118 [ # # ]: 0 : CHECK(n_tokens == 2, EINVAL);
2119 : :
2120 : 0 : h = header_parse(p, tokens[1]);
2121 [ # # ]: 0 : CHECK(h, EINVAL);
2122 [ # # ]: 0 : CHECK(!h->st->var_size, EINVAL);
2123 : :
2124 : 0 : instr->type = INSTR_HDR_LOOKAHEAD;
2125 : 0 : instr->io.hdr.header_id[0] = h->id;
2126 : 0 : instr->io.hdr.struct_id[0] = h->struct_id;
2127 : 0 : instr->io.hdr.n_bytes[0] = 0; /* Unused. */
2128 : :
2129 : 0 : return 0;
2130 : : }
2131 : :
2132 : : static inline void
2133 : 0 : instr_hdr_extract_exec(struct rte_swx_pipeline *p)
2134 : : {
2135 : 0 : struct thread *t = &p->threads[p->thread_id];
2136 : 0 : struct instruction *ip = t->ip;
2137 : :
2138 : : __instr_hdr_extract_exec(p, t, ip);
2139 : :
2140 : : /* Thread. */
2141 : : thread_ip_inc(p);
2142 : 0 : }
2143 : :
2144 : : static inline void
2145 : 0 : instr_hdr_extract2_exec(struct rte_swx_pipeline *p)
2146 : : {
2147 : 0 : struct thread *t = &p->threads[p->thread_id];
2148 : 0 : struct instruction *ip = t->ip;
2149 : :
2150 : : __instr_hdr_extract2_exec(p, t, ip);
2151 : :
2152 : : /* Thread. */
2153 : : thread_ip_inc(p);
2154 : 0 : }
2155 : :
2156 : : static inline void
2157 : 0 : instr_hdr_extract3_exec(struct rte_swx_pipeline *p)
2158 : : {
2159 : 0 : struct thread *t = &p->threads[p->thread_id];
2160 : 0 : struct instruction *ip = t->ip;
2161 : :
2162 : : __instr_hdr_extract3_exec(p, t, ip);
2163 : :
2164 : : /* Thread. */
2165 : : thread_ip_inc(p);
2166 : 0 : }
2167 : :
2168 : : static inline void
2169 : 0 : instr_hdr_extract4_exec(struct rte_swx_pipeline *p)
2170 : : {
2171 : 0 : struct thread *t = &p->threads[p->thread_id];
2172 : 0 : struct instruction *ip = t->ip;
2173 : :
2174 : : __instr_hdr_extract4_exec(p, t, ip);
2175 : :
2176 : : /* Thread. */
2177 : : thread_ip_inc(p);
2178 : 0 : }
2179 : :
2180 : : static inline void
2181 : 0 : instr_hdr_extract5_exec(struct rte_swx_pipeline *p)
2182 : : {
2183 : 0 : struct thread *t = &p->threads[p->thread_id];
2184 : 0 : struct instruction *ip = t->ip;
2185 : :
2186 : : __instr_hdr_extract5_exec(p, t, ip);
2187 : :
2188 : : /* Thread. */
2189 : : thread_ip_inc(p);
2190 : 0 : }
2191 : :
2192 : : static inline void
2193 : 0 : instr_hdr_extract6_exec(struct rte_swx_pipeline *p)
2194 : : {
2195 : 0 : struct thread *t = &p->threads[p->thread_id];
2196 : 0 : struct instruction *ip = t->ip;
2197 : :
2198 : : __instr_hdr_extract6_exec(p, t, ip);
2199 : :
2200 : : /* Thread. */
2201 : : thread_ip_inc(p);
2202 : 0 : }
2203 : :
2204 : : static inline void
2205 : 0 : instr_hdr_extract7_exec(struct rte_swx_pipeline *p)
2206 : : {
2207 : 0 : struct thread *t = &p->threads[p->thread_id];
2208 : 0 : struct instruction *ip = t->ip;
2209 : :
2210 : : __instr_hdr_extract7_exec(p, t, ip);
2211 : :
2212 : : /* Thread. */
2213 : : thread_ip_inc(p);
2214 : 0 : }
2215 : :
2216 : : static inline void
2217 : 0 : instr_hdr_extract8_exec(struct rte_swx_pipeline *p)
2218 : : {
2219 : 0 : struct thread *t = &p->threads[p->thread_id];
2220 : 0 : struct instruction *ip = t->ip;
2221 : :
2222 : : __instr_hdr_extract8_exec(p, t, ip);
2223 : :
2224 : : /* Thread. */
2225 : : thread_ip_inc(p);
2226 : 0 : }
2227 : :
2228 : : static inline void
2229 : 0 : instr_hdr_extract_m_exec(struct rte_swx_pipeline *p)
2230 : : {
2231 : 0 : struct thread *t = &p->threads[p->thread_id];
2232 : 0 : struct instruction *ip = t->ip;
2233 : :
2234 : 0 : __instr_hdr_extract_m_exec(p, t, ip);
2235 : :
2236 : : /* Thread. */
2237 : : thread_ip_inc(p);
2238 : 0 : }
2239 : :
2240 : : static inline void
2241 : 0 : instr_hdr_lookahead_exec(struct rte_swx_pipeline *p)
2242 : : {
2243 : 0 : struct thread *t = &p->threads[p->thread_id];
2244 : 0 : struct instruction *ip = t->ip;
2245 : :
2246 : : __instr_hdr_lookahead_exec(p, t, ip);
2247 : :
2248 : : /* Thread. */
2249 : : thread_ip_inc(p);
2250 : 0 : }
2251 : :
2252 : : /*
2253 : : * emit.
2254 : : */
2255 : : static int
2256 : 0 : instr_hdr_emit_translate(struct rte_swx_pipeline *p,
2257 : : struct action *action __rte_unused,
2258 : : char **tokens,
2259 : : int n_tokens,
2260 : : struct instruction *instr,
2261 : : struct instruction_data *data __rte_unused)
2262 : : {
2263 : : struct header *h;
2264 : :
2265 [ # # ]: 0 : CHECK(n_tokens == 2, EINVAL);
2266 : :
2267 : 0 : h = header_parse(p, tokens[1]);
2268 [ # # ]: 0 : CHECK(h, EINVAL);
2269 : :
2270 : 0 : instr->type = INSTR_HDR_EMIT;
2271 : 0 : instr->io.hdr.header_id[0] = h->id;
2272 : 0 : instr->io.hdr.struct_id[0] = h->struct_id;
2273 : 0 : instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
2274 : 0 : return 0;
2275 : : }
2276 : :
2277 : : static inline void
2278 : 0 : instr_hdr_emit_exec(struct rte_swx_pipeline *p)
2279 : : {
2280 : 0 : struct thread *t = &p->threads[p->thread_id];
2281 : 0 : struct instruction *ip = t->ip;
2282 : :
2283 : : __instr_hdr_emit_exec(p, t, ip);
2284 : :
2285 : : /* Thread. */
2286 : : thread_ip_inc(p);
2287 : 0 : }
2288 : :
2289 : : static inline void
2290 : 0 : instr_hdr_emit_tx_exec(struct rte_swx_pipeline *p)
2291 : : {
2292 : 0 : struct thread *t = &p->threads[p->thread_id];
2293 : 0 : struct instruction *ip = t->ip;
2294 : :
2295 : 0 : __instr_hdr_emit_tx_exec(p, t, ip);
2296 : :
2297 : : /* Thread. */
2298 : : thread_ip_reset(p, t);
2299 : 0 : instr_rx_exec(p);
2300 : 0 : }
2301 : :
2302 : : static inline void
2303 : 0 : instr_hdr_emit2_tx_exec(struct rte_swx_pipeline *p)
2304 : : {
2305 : 0 : struct thread *t = &p->threads[p->thread_id];
2306 : 0 : struct instruction *ip = t->ip;
2307 : :
2308 : 0 : __instr_hdr_emit2_tx_exec(p, t, ip);
2309 : :
2310 : : /* Thread. */
2311 : : thread_ip_reset(p, t);
2312 : 0 : instr_rx_exec(p);
2313 : 0 : }
2314 : :
2315 : : static inline void
2316 : 0 : instr_hdr_emit3_tx_exec(struct rte_swx_pipeline *p)
2317 : : {
2318 : 0 : struct thread *t = &p->threads[p->thread_id];
2319 : 0 : struct instruction *ip = t->ip;
2320 : :
2321 : 0 : __instr_hdr_emit3_tx_exec(p, t, ip);
2322 : :
2323 : : /* Thread. */
2324 : : thread_ip_reset(p, t);
2325 : 0 : instr_rx_exec(p);
2326 : 0 : }
2327 : :
2328 : : static inline void
2329 : 0 : instr_hdr_emit4_tx_exec(struct rte_swx_pipeline *p)
2330 : : {
2331 : 0 : struct thread *t = &p->threads[p->thread_id];
2332 : 0 : struct instruction *ip = t->ip;
2333 : :
2334 : 0 : __instr_hdr_emit4_tx_exec(p, t, ip);
2335 : :
2336 : : /* Thread. */
2337 : : thread_ip_reset(p, t);
2338 : 0 : instr_rx_exec(p);
2339 : 0 : }
2340 : :
2341 : : static inline void
2342 : 0 : instr_hdr_emit5_tx_exec(struct rte_swx_pipeline *p)
2343 : : {
2344 : 0 : struct thread *t = &p->threads[p->thread_id];
2345 : 0 : struct instruction *ip = t->ip;
2346 : :
2347 : 0 : __instr_hdr_emit5_tx_exec(p, t, ip);
2348 : :
2349 : : /* Thread. */
2350 : : thread_ip_reset(p, t);
2351 : 0 : instr_rx_exec(p);
2352 : 0 : }
2353 : :
2354 : : static inline void
2355 : 0 : instr_hdr_emit6_tx_exec(struct rte_swx_pipeline *p)
2356 : : {
2357 : 0 : struct thread *t = &p->threads[p->thread_id];
2358 : 0 : struct instruction *ip = t->ip;
2359 : :
2360 : 0 : __instr_hdr_emit6_tx_exec(p, t, ip);
2361 : :
2362 : : /* Thread. */
2363 : : thread_ip_reset(p, t);
2364 : 0 : instr_rx_exec(p);
2365 : 0 : }
2366 : :
2367 : : static inline void
2368 : 0 : instr_hdr_emit7_tx_exec(struct rte_swx_pipeline *p)
2369 : : {
2370 : 0 : struct thread *t = &p->threads[p->thread_id];
2371 : 0 : struct instruction *ip = t->ip;
2372 : :
2373 : 0 : __instr_hdr_emit7_tx_exec(p, t, ip);
2374 : :
2375 : : /* Thread. */
2376 : : thread_ip_reset(p, t);
2377 : 0 : instr_rx_exec(p);
2378 : 0 : }
2379 : :
2380 : : static inline void
2381 : 0 : instr_hdr_emit8_tx_exec(struct rte_swx_pipeline *p)
2382 : : {
2383 : 0 : struct thread *t = &p->threads[p->thread_id];
2384 : 0 : struct instruction *ip = t->ip;
2385 : :
2386 : 0 : __instr_hdr_emit8_tx_exec(p, t, ip);
2387 : :
2388 : : /* Thread. */
2389 : : thread_ip_reset(p, t);
2390 : 0 : instr_rx_exec(p);
2391 : 0 : }
2392 : :
2393 : : /*
2394 : : * validate.
2395 : : */
2396 : : static int
2397 : : instr_hdr_validate_translate(struct rte_swx_pipeline *p,
2398 : : struct action *action __rte_unused,
2399 : : char **tokens,
2400 : : int n_tokens,
2401 : : struct instruction *instr,
2402 : : struct instruction_data *data __rte_unused)
2403 : : {
2404 : : struct header *h;
2405 : :
2406 : 0 : CHECK(n_tokens == 2, EINVAL);
2407 : :
2408 : 0 : h = header_parse(p, tokens[1]);
2409 [ # # ]: 0 : CHECK(h, EINVAL);
2410 : :
2411 : 0 : instr->type = INSTR_HDR_VALIDATE;
2412 : 0 : instr->valid.header_id = h->id;
2413 : 0 : instr->valid.struct_id = h->struct_id;
2414 : 0 : return 0;
2415 : : }
2416 : :
2417 : : static inline void
2418 : 0 : instr_hdr_validate_exec(struct rte_swx_pipeline *p)
2419 : : {
2420 : 0 : struct thread *t = &p->threads[p->thread_id];
2421 [ # # ]: 0 : struct instruction *ip = t->ip;
2422 : :
2423 : : __instr_hdr_validate_exec(p, t, ip);
2424 : :
2425 : : /* Thread. */
2426 : : thread_ip_inc(p);
2427 : 0 : }
2428 : :
2429 : : /*
2430 : : * invalidate.
2431 : : */
2432 : : static int
2433 : : instr_hdr_invalidate_translate(struct rte_swx_pipeline *p,
2434 : : struct action *action __rte_unused,
2435 : : char **tokens,
2436 : : int n_tokens,
2437 : : struct instruction *instr,
2438 : : struct instruction_data *data __rte_unused)
2439 : : {
2440 : : struct header *h;
2441 : :
2442 : 0 : CHECK(n_tokens == 2, EINVAL);
2443 : :
2444 : 0 : h = header_parse(p, tokens[1]);
2445 [ # # ]: 0 : CHECK(h, EINVAL);
2446 : :
2447 : 0 : instr->type = INSTR_HDR_INVALIDATE;
2448 : 0 : instr->valid.header_id = h->id;
2449 : 0 : return 0;
2450 : : }
2451 : :
2452 : : static inline void
2453 : 0 : instr_hdr_invalidate_exec(struct rte_swx_pipeline *p)
2454 : : {
2455 : 0 : struct thread *t = &p->threads[p->thread_id];
2456 : 0 : struct instruction *ip = t->ip;
2457 : :
2458 : : __instr_hdr_invalidate_exec(p, t, ip);
2459 : :
2460 : : /* Thread. */
2461 : : thread_ip_inc(p);
2462 : 0 : }
2463 : :
2464 : : /*
2465 : : * table.
2466 : : */
2467 : : static struct table *
2468 : : table_find(struct rte_swx_pipeline *p, const char *name);
2469 : :
2470 : : static struct selector *
2471 : : selector_find(struct rte_swx_pipeline *p, const char *name);
2472 : :
2473 : : static struct learner *
2474 : : learner_find(struct rte_swx_pipeline *p, const char *name);
2475 : :
2476 : : static int
2477 : 0 : instr_table_translate(struct rte_swx_pipeline *p,
2478 : : struct action *action,
2479 : : char **tokens,
2480 : : int n_tokens,
2481 : : struct instruction *instr,
2482 : : struct instruction_data *data __rte_unused)
2483 : : {
2484 : : struct table *t;
2485 : : struct selector *s;
2486 : : struct learner *l;
2487 : :
2488 [ # # ]: 0 : CHECK(!action, EINVAL);
2489 [ # # ]: 0 : CHECK(n_tokens == 2, EINVAL);
2490 : :
2491 : 0 : t = table_find(p, tokens[1]);
2492 [ # # ]: 0 : if (t) {
2493 : 0 : instr->type = INSTR_TABLE;
2494 : 0 : instr->table.table_id = t->id;
2495 : 0 : return 0;
2496 : : }
2497 : :
2498 : : s = selector_find(p, tokens[1]);
2499 [ # # ]: 0 : if (s) {
2500 : 0 : instr->type = INSTR_SELECTOR;
2501 : 0 : instr->table.table_id = s->id;
2502 : 0 : return 0;
2503 : : }
2504 : :
2505 : : l = learner_find(p, tokens[1]);
2506 [ # # ]: 0 : if (l) {
2507 : 0 : instr->type = INSTR_LEARNER;
2508 : 0 : instr->table.table_id = l->id;
2509 : 0 : return 0;
2510 : : }
2511 : :
2512 : : CHECK(0, EINVAL);
2513 : : }
2514 : :
2515 : : static inline void
2516 : 0 : instr_table_exec(struct rte_swx_pipeline *p)
2517 : : {
2518 : 0 : struct thread *t = &p->threads[p->thread_id];
2519 : 0 : struct instruction *ip = t->ip;
2520 : 0 : uint32_t table_id = ip->table.table_id;
2521 : 0 : struct rte_swx_table_state *ts = &t->table_state[table_id];
2522 : 0 : struct table_runtime *table = &t->tables[table_id];
2523 : 0 : struct table_statistics *stats = &p->table_stats[table_id];
2524 : : uint64_t action_id, n_pkts_hit, n_pkts_action;
2525 : : uint8_t *action_data;
2526 : : size_t entry_id;
2527 : : int done, hit;
2528 : :
2529 : : /* Table. */
2530 : 0 : done = table->func(ts->obj,
2531 : : table->mailbox,
2532 : : table->key,
2533 : : &action_id,
2534 : : &action_data,
2535 : : &entry_id,
2536 : : &hit);
2537 [ # # ]: 0 : if (!done) {
2538 : : /* Thread. */
2539 : : TRACE("[Thread %2u] table %u (not finalized)\n",
2540 : : p->thread_id,
2541 : : table_id);
2542 : :
2543 : : thread_yield(p);
2544 : 0 : return;
2545 : : }
2546 : :
2547 [ # # ]: 0 : action_id = hit ? action_id : ts->default_action_id;
2548 [ # # ]: 0 : action_data = hit ? action_data : ts->default_action_data;
2549 [ # # ]: 0 : entry_id = hit ? (1 + entry_id) : 0;
2550 : 0 : n_pkts_hit = stats->n_pkts_hit[hit];
2551 : 0 : n_pkts_action = stats->n_pkts_action[action_id];
2552 : :
2553 : : TRACE("[Thread %2u] table %u (%s, action %u)\n",
2554 : : p->thread_id,
2555 : : table_id,
2556 : : hit ? "hit" : "miss",
2557 : : (uint32_t)action_id);
2558 : :
2559 : 0 : t->action_id = action_id;
2560 : 0 : t->structs[0] = action_data;
2561 : 0 : t->entry_id = entry_id;
2562 : 0 : t->hit = hit;
2563 : 0 : stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2564 : 0 : stats->n_pkts_action[action_id] = n_pkts_action + 1;
2565 : :
2566 : : /* Thread. */
2567 : 0 : thread_ip_action_call(p, t, action_id);
2568 : : }
2569 : :
2570 : : static inline void
2571 : 0 : instr_table_af_exec(struct rte_swx_pipeline *p)
2572 : : {
2573 : 0 : struct thread *t = &p->threads[p->thread_id];
2574 : 0 : struct instruction *ip = t->ip;
2575 : 0 : uint32_t table_id = ip->table.table_id;
2576 : 0 : struct rte_swx_table_state *ts = &t->table_state[table_id];
2577 : 0 : struct table_runtime *table = &t->tables[table_id];
2578 : 0 : struct table_statistics *stats = &p->table_stats[table_id];
2579 : : uint64_t action_id, n_pkts_hit, n_pkts_action;
2580 : : uint8_t *action_data;
2581 : : size_t entry_id;
2582 : : action_func_t action_func;
2583 : : int done, hit;
2584 : :
2585 : : /* Table. */
2586 : 0 : done = table->func(ts->obj,
2587 : : table->mailbox,
2588 : : table->key,
2589 : : &action_id,
2590 : : &action_data,
2591 : : &entry_id,
2592 : : &hit);
2593 [ # # ]: 0 : if (!done) {
2594 : : /* Thread. */
2595 : : TRACE("[Thread %2u] table %u (not finalized)\n",
2596 : : p->thread_id,
2597 : : table_id);
2598 : :
2599 : : thread_yield(p);
2600 : 0 : return;
2601 : : }
2602 : :
2603 [ # # ]: 0 : action_id = hit ? action_id : ts->default_action_id;
2604 [ # # ]: 0 : action_data = hit ? action_data : ts->default_action_data;
2605 [ # # ]: 0 : entry_id = hit ? (1 + entry_id) : 0;
2606 : 0 : action_func = p->action_funcs[action_id];
2607 : 0 : n_pkts_hit = stats->n_pkts_hit[hit];
2608 : 0 : n_pkts_action = stats->n_pkts_action[action_id];
2609 : :
2610 : : TRACE("[Thread %2u] table %u (%s, action %u)\n",
2611 : : p->thread_id,
2612 : : table_id,
2613 : : hit ? "hit" : "miss",
2614 : : (uint32_t)action_id);
2615 : :
2616 : 0 : t->action_id = action_id;
2617 : 0 : t->structs[0] = action_data;
2618 : 0 : t->entry_id = entry_id;
2619 : 0 : t->hit = hit;
2620 : 0 : stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2621 : 0 : stats->n_pkts_action[action_id] = n_pkts_action + 1;
2622 : :
2623 : : /* Thread. */
2624 : : thread_ip_inc(p);
2625 : :
2626 : : /* Action. */
2627 : 0 : action_func(p);
2628 : : }
2629 : :
2630 : : static inline void
2631 : 0 : instr_selector_exec(struct rte_swx_pipeline *p)
2632 : : {
2633 : 0 : struct thread *t = &p->threads[p->thread_id];
2634 : 0 : struct instruction *ip = t->ip;
2635 : 0 : uint32_t selector_id = ip->table.table_id;
2636 : 0 : struct rte_swx_table_state *ts = &t->table_state[p->n_tables + selector_id];
2637 : 0 : struct selector_runtime *selector = &t->selectors[selector_id];
2638 : 0 : struct selector_statistics *stats = &p->selector_stats[selector_id];
2639 : 0 : uint64_t n_pkts = stats->n_pkts;
2640 : : int done;
2641 : :
2642 : : /* Table. */
2643 : 0 : done = rte_swx_table_selector_select(ts->obj,
2644 : : selector->mailbox,
2645 : : selector->group_id_buffer,
2646 : : selector->selector_buffer,
2647 : : selector->member_id_buffer);
2648 [ # # ]: 0 : if (!done) {
2649 : : /* Thread. */
2650 : : TRACE("[Thread %2u] selector %u (not finalized)\n",
2651 : : p->thread_id,
2652 : : selector_id);
2653 : :
2654 : : thread_yield(p);
2655 : 0 : return;
2656 : : }
2657 : :
2658 : :
2659 : : TRACE("[Thread %2u] selector %u\n",
2660 : : p->thread_id,
2661 : : selector_id);
2662 : :
2663 : 0 : stats->n_pkts = n_pkts + 1;
2664 : :
2665 : : /* Thread. */
2666 : : thread_ip_inc(p);
2667 : : }
2668 : :
2669 : : static inline void
2670 : 0 : instr_learner_exec(struct rte_swx_pipeline *p)
2671 : : {
2672 : 0 : struct thread *t = &p->threads[p->thread_id];
2673 : 0 : struct instruction *ip = t->ip;
2674 : 0 : uint32_t learner_id = ip->table.table_id;
2675 : 0 : struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2676 : 0 : p->n_selectors + learner_id];
2677 : 0 : struct learner_runtime *l = &t->learners[learner_id];
2678 : 0 : struct learner_statistics *stats = &p->learner_stats[learner_id];
2679 : : uint64_t action_id, n_pkts_hit, n_pkts_action, time;
2680 : : uint8_t *action_data;
2681 : : size_t entry_id;
2682 : : int done, hit;
2683 : :
2684 : : /* Table. */
2685 : : time = rte_get_tsc_cycles();
2686 : :
2687 : 0 : done = rte_swx_table_learner_lookup(ts->obj,
2688 : : l->mailbox,
2689 : : time,
2690 : : l->key,
2691 : : &action_id,
2692 : : &action_data,
2693 : : &entry_id,
2694 : : &hit);
2695 [ # # ]: 0 : if (!done) {
2696 : : /* Thread. */
2697 : : TRACE("[Thread %2u] learner %u (not finalized)\n",
2698 : : p->thread_id,
2699 : : learner_id);
2700 : :
2701 : : thread_yield(p);
2702 : 0 : return;
2703 : : }
2704 : :
2705 [ # # ]: 0 : action_id = hit ? action_id : ts->default_action_id;
2706 [ # # ]: 0 : action_data = hit ? action_data : ts->default_action_data;
2707 [ # # ]: 0 : entry_id = hit ? (1 + entry_id) : 0;
2708 : 0 : n_pkts_hit = stats->n_pkts_hit[hit];
2709 : 0 : n_pkts_action = stats->n_pkts_action[action_id];
2710 : :
2711 : : TRACE("[Thread %2u] learner %u (%s, action %u)\n",
2712 : : p->thread_id,
2713 : : learner_id,
2714 : : hit ? "hit" : "miss",
2715 : : (uint32_t)action_id);
2716 : :
2717 : 0 : t->action_id = action_id;
2718 : 0 : t->structs[0] = action_data;
2719 : 0 : t->entry_id = entry_id;
2720 : 0 : t->hit = hit;
2721 : 0 : t->learner_id = learner_id;
2722 : 0 : t->time = time;
2723 : 0 : stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2724 : 0 : stats->n_pkts_action[action_id] = n_pkts_action + 1;
2725 : :
2726 : : /* Thread. */
2727 : 0 : thread_ip_action_call(p, t, action_id);
2728 : : }
2729 : :
2730 : : static inline void
2731 : 0 : instr_learner_af_exec(struct rte_swx_pipeline *p)
2732 : : {
2733 : 0 : struct thread *t = &p->threads[p->thread_id];
2734 : 0 : struct instruction *ip = t->ip;
2735 : 0 : uint32_t learner_id = ip->table.table_id;
2736 : 0 : struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2737 : 0 : p->n_selectors + learner_id];
2738 : 0 : struct learner_runtime *l = &t->learners[learner_id];
2739 : 0 : struct learner_statistics *stats = &p->learner_stats[learner_id];
2740 : : uint64_t action_id, n_pkts_hit, n_pkts_action, time;
2741 : : uint8_t *action_data;
2742 : : size_t entry_id;
2743 : : action_func_t action_func;
2744 : : int done, hit;
2745 : :
2746 : : /* Table. */
2747 : : time = rte_get_tsc_cycles();
2748 : :
2749 : 0 : done = rte_swx_table_learner_lookup(ts->obj,
2750 : : l->mailbox,
2751 : : time,
2752 : : l->key,
2753 : : &action_id,
2754 : : &action_data,
2755 : : &entry_id,
2756 : : &hit);
2757 [ # # ]: 0 : if (!done) {
2758 : : /* Thread. */
2759 : : TRACE("[Thread %2u] learner %u (not finalized)\n",
2760 : : p->thread_id,
2761 : : learner_id);
2762 : :
2763 : : thread_yield(p);
2764 : 0 : return;
2765 : : }
2766 : :
2767 [ # # ]: 0 : action_id = hit ? action_id : ts->default_action_id;
2768 [ # # ]: 0 : action_data = hit ? action_data : ts->default_action_data;
2769 [ # # ]: 0 : entry_id = hit ? (1 + entry_id) : 0;
2770 : 0 : action_func = p->action_funcs[action_id];
2771 : 0 : n_pkts_hit = stats->n_pkts_hit[hit];
2772 : 0 : n_pkts_action = stats->n_pkts_action[action_id];
2773 : :
2774 : : TRACE("[Thread %2u] learner %u (%s, action %u)\n",
2775 : : p->thread_id,
2776 : : learner_id,
2777 : : hit ? "hit" : "miss",
2778 : : (uint32_t)action_id);
2779 : :
2780 : 0 : t->action_id = action_id;
2781 : 0 : t->structs[0] = action_data;
2782 : 0 : t->entry_id = entry_id;
2783 : 0 : t->hit = hit;
2784 : 0 : t->learner_id = learner_id;
2785 : 0 : t->time = time;
2786 : 0 : stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2787 : 0 : stats->n_pkts_action[action_id] = n_pkts_action + 1;
2788 : :
2789 : : /* Thread. */
2790 : : thread_ip_inc(p);
2791 : :
2792 : : /* Action */
2793 : 0 : action_func(p);
2794 : : }
2795 : :
2796 : : /*
2797 : : * learn.
2798 : : */
2799 : : static struct action *
2800 : : action_find(struct rte_swx_pipeline *p, const char *name);
2801 : :
2802 : : static int
2803 : : action_has_nbo_args(struct action *a);
2804 : :
2805 : : static int
2806 : : learner_action_args_check(struct rte_swx_pipeline *p, struct action *a, const char *mf_name);
2807 : :
2808 : : static int
2809 : 0 : instr_learn_translate(struct rte_swx_pipeline *p,
2810 : : struct action *action,
2811 : : char **tokens,
2812 : : int n_tokens,
2813 : : struct instruction *instr,
2814 : : struct instruction_data *data __rte_unused)
2815 : : {
2816 : : struct action *a;
2817 : : struct field *mf_first_arg = NULL, *mf_timeout_id = NULL;
2818 : : const char *mf_first_arg_name, *mf_timeout_id_name;
2819 : :
2820 [ # # ]: 0 : CHECK(action, EINVAL);
2821 [ # # ]: 0 : CHECK((n_tokens == 3) || (n_tokens == 4), EINVAL);
2822 : :
2823 : : /* Action. */
2824 : 0 : a = action_find(p, tokens[1]);
2825 [ # # ]: 0 : CHECK(a, EINVAL);
2826 [ # # ]: 0 : CHECK(!action_has_nbo_args(a), EINVAL);
2827 : :
2828 : : /* Action first argument. */
2829 [ # # ]: 0 : mf_first_arg_name = (n_tokens == 4) ? tokens[2] : NULL;
2830 [ # # ]: 0 : CHECK(!learner_action_args_check(p, a, mf_first_arg_name), EINVAL);
2831 : :
2832 [ # # ]: 0 : if (mf_first_arg_name) {
2833 : 0 : mf_first_arg = metadata_field_parse(p, mf_first_arg_name);
2834 [ # # ]: 0 : CHECK(mf_first_arg, EINVAL);
2835 [ # # ]: 0 : CHECK(mf_first_arg->n_bits <= 64, EINVAL);
2836 : : }
2837 : :
2838 : : /* Timeout ID. */
2839 [ # # ]: 0 : mf_timeout_id_name = (n_tokens == 4) ? tokens[3] : tokens[2];
2840 [ # # # # : 0 : CHECK_NAME(mf_timeout_id_name, EINVAL);
# # ]
2841 : 0 : mf_timeout_id = metadata_field_parse(p, mf_timeout_id_name);
2842 [ # # ]: 0 : CHECK(mf_timeout_id, EINVAL);
2843 [ # # ]: 0 : CHECK(mf_timeout_id->n_bits <= 64, EINVAL);
2844 : :
2845 : : /* Instruction. */
2846 : 0 : instr->type = INSTR_LEARNER_LEARN;
2847 : 0 : instr->learn.action_id = a->id;
2848 [ # # ]: 0 : instr->learn.mf_first_arg_offset = mf_first_arg ? (mf_first_arg->offset / 8) : 0;
2849 : 0 : instr->learn.mf_timeout_id_offset = mf_timeout_id->offset / 8;
2850 : 0 : instr->learn.mf_timeout_id_n_bits = mf_timeout_id->n_bits;
2851 : :
2852 : 0 : return 0;
2853 : : }
2854 : :
2855 : : static inline void
2856 : 0 : instr_learn_exec(struct rte_swx_pipeline *p)
2857 : : {
2858 : 0 : struct thread *t = &p->threads[p->thread_id];
2859 : 0 : struct instruction *ip = t->ip;
2860 : :
2861 : 0 : __instr_learn_exec(p, t, ip);
2862 : :
2863 : : /* Thread. */
2864 : : thread_ip_inc(p);
2865 : 0 : }
2866 : :
2867 : : /*
2868 : : * rearm.
2869 : : */
2870 : : static int
2871 : 0 : instr_rearm_translate(struct rte_swx_pipeline *p,
2872 : : struct action *action,
2873 : : char **tokens,
2874 : : int n_tokens,
2875 : : struct instruction *instr,
2876 : : struct instruction_data *data __rte_unused)
2877 : : {
2878 : : struct field *mf_timeout_id;
2879 : : const char *mf_timeout_id_name;
2880 : :
2881 [ # # ]: 0 : CHECK(action, EINVAL);
2882 [ # # ]: 0 : CHECK((n_tokens == 1) || (n_tokens == 2), EINVAL);
2883 : :
2884 : : /* INSTR_LEARNER_REARM. */
2885 [ # # ]: 0 : if (n_tokens == 1) {
2886 : 0 : instr->type = INSTR_LEARNER_REARM;
2887 : 0 : return 0;
2888 : : }
2889 : :
2890 : : /* INSTR_LEARNER_REARM_NEW. */
2891 : 0 : mf_timeout_id_name = tokens[1];
2892 [ # # # # : 0 : CHECK_NAME(mf_timeout_id_name, EINVAL);
# # ]
2893 : 0 : mf_timeout_id = metadata_field_parse(p, mf_timeout_id_name);
2894 [ # # ]: 0 : CHECK(mf_timeout_id, EINVAL);
2895 [ # # ]: 0 : CHECK(mf_timeout_id->n_bits <= 64, EINVAL);
2896 : :
2897 : 0 : instr->type = INSTR_LEARNER_REARM_NEW;
2898 : 0 : instr->learn.mf_timeout_id_offset = mf_timeout_id->offset / 8;
2899 : 0 : instr->learn.mf_timeout_id_n_bits = mf_timeout_id->n_bits;
2900 : :
2901 : 0 : return 0;
2902 : : }
2903 : :
2904 : : static inline void
2905 : 0 : instr_rearm_exec(struct rte_swx_pipeline *p)
2906 : : {
2907 : 0 : struct thread *t = &p->threads[p->thread_id];
2908 : 0 : struct instruction *ip = t->ip;
2909 : :
2910 : 0 : __instr_rearm_exec(p, t, ip);
2911 : :
2912 : : /* Thread. */
2913 : : thread_ip_inc(p);
2914 : 0 : }
2915 : :
2916 : : static inline void
2917 : 0 : instr_rearm_new_exec(struct rte_swx_pipeline *p)
2918 : : {
2919 : 0 : struct thread *t = &p->threads[p->thread_id];
2920 : 0 : struct instruction *ip = t->ip;
2921 : :
2922 : 0 : __instr_rearm_new_exec(p, t, ip);
2923 : :
2924 : : /* Thread. */
2925 : : thread_ip_inc(p);
2926 : 0 : }
2927 : :
2928 : : /*
2929 : : * forget.
2930 : : */
2931 : : static int
2932 : : instr_forget_translate(struct rte_swx_pipeline *p __rte_unused,
2933 : : struct action *action,
2934 : : char **tokens __rte_unused,
2935 : : int n_tokens,
2936 : : struct instruction *instr,
2937 : : struct instruction_data *data __rte_unused)
2938 : : {
2939 : 0 : CHECK(action, EINVAL);
2940 [ # # ]: 0 : CHECK(n_tokens == 1, EINVAL);
2941 : :
2942 : 0 : instr->type = INSTR_LEARNER_FORGET;
2943 : :
2944 : 0 : return 0;
2945 : : }
2946 : :
2947 : : static inline void
2948 : 0 : instr_forget_exec(struct rte_swx_pipeline *p)
2949 : : {
2950 : 0 : struct thread *t = &p->threads[p->thread_id];
2951 : 0 : struct instruction *ip = t->ip;
2952 : :
2953 : 0 : __instr_forget_exec(p, t, ip);
2954 : :
2955 : : /* Thread. */
2956 : : thread_ip_inc(p);
2957 : 0 : }
2958 : :
2959 : : /*
2960 : : * entryid.
2961 : : */
2962 : : static int
2963 : : instr_entryid_translate(struct rte_swx_pipeline *p,
2964 : : struct action *action __rte_unused,
2965 : : char **tokens,
2966 : : int n_tokens,
2967 : : struct instruction *instr,
2968 : : struct instruction_data *data __rte_unused)
2969 : : {
2970 : : struct field *f;
2971 : :
2972 : 0 : CHECK(n_tokens == 2, EINVAL);
2973 : :
2974 : 0 : f = metadata_field_parse(p, tokens[1]);
2975 [ # # ]: 0 : CHECK(f, EINVAL);
2976 [ # # ]: 0 : CHECK(f->n_bits <= 64, EINVAL);
2977 : :
2978 : 0 : instr->type = INSTR_ENTRYID;
2979 : 0 : instr->mov.dst.n_bits = f->n_bits;
2980 : 0 : instr->mov.dst.offset = f->offset / 8;
2981 : 0 : return 0;
2982 : : }
2983 : :
2984 : : static inline void
2985 : 0 : instr_entryid_exec(struct rte_swx_pipeline *p)
2986 : : {
2987 : 0 : struct thread *t = &p->threads[p->thread_id];
2988 : 0 : struct instruction *ip = t->ip;
2989 : :
2990 : : __instr_entryid_exec(p, t, ip);
2991 : :
2992 : : /* Thread. */
2993 : : thread_ip_inc(p);
2994 : 0 : }
2995 : :
2996 : : /*
2997 : : * extern.
2998 : : */
2999 : : static int
3000 : 0 : instr_extern_translate(struct rte_swx_pipeline *p,
3001 : : struct action *action __rte_unused,
3002 : : char **tokens,
3003 : : int n_tokens,
3004 : : struct instruction *instr,
3005 : : struct instruction_data *data __rte_unused)
3006 : : {
3007 : 0 : char *token = tokens[1];
3008 : :
3009 [ # # ]: 0 : CHECK(n_tokens == 2, EINVAL);
3010 : :
3011 [ # # ]: 0 : if (token[0] == 'e') {
3012 : : struct extern_obj *obj;
3013 : : struct extern_type_member_func *func;
3014 : :
3015 : 0 : func = extern_obj_member_func_parse(p, token, &obj);
3016 [ # # ]: 0 : CHECK(func, EINVAL);
3017 : :
3018 : 0 : instr->type = INSTR_EXTERN_OBJ;
3019 : 0 : instr->ext_obj.ext_obj_id = obj->id;
3020 : 0 : instr->ext_obj.func_id = func->id;
3021 : :
3022 : 0 : return 0;
3023 : : }
3024 : :
3025 [ # # ]: 0 : if (token[0] == 'f') {
3026 : : struct extern_func *func;
3027 : :
3028 : 0 : func = extern_func_parse(p, token);
3029 [ # # ]: 0 : CHECK(func, EINVAL);
3030 : :
3031 : 0 : instr->type = INSTR_EXTERN_FUNC;
3032 : 0 : instr->ext_func.ext_func_id = func->id;
3033 : :
3034 : 0 : return 0;
3035 : : }
3036 : :
3037 : : CHECK(0, EINVAL);
3038 : : }
3039 : :
3040 : : static inline void
3041 : 0 : instr_extern_obj_exec(struct rte_swx_pipeline *p)
3042 : : {
3043 : 0 : struct thread *t = &p->threads[p->thread_id];
3044 : 0 : struct instruction *ip = t->ip;
3045 : : uint32_t done;
3046 : :
3047 : : /* Extern object member function execute. */
3048 : : done = __instr_extern_obj_exec(p, t, ip);
3049 : :
3050 : : /* Thread. */
3051 : : thread_ip_inc_cond(t, done);
3052 : 0 : thread_yield_cond(p, done ^ 1);
3053 : 0 : }
3054 : :
3055 : : static inline void
3056 : 0 : instr_extern_func_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 function execute. */
3063 : : done = __instr_extern_func_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 : : /*
3071 : : * hash.
3072 : : */
3073 : : static int
3074 : 0 : instr_hash_translate(struct rte_swx_pipeline *p,
3075 : : struct action *action,
3076 : : char **tokens,
3077 : : int n_tokens,
3078 : : struct instruction *instr,
3079 : : struct instruction_data *data __rte_unused)
3080 : : {
3081 : : struct hash_func *func;
3082 : : struct field *dst, *src_first, *src_last;
3083 : 0 : uint32_t src_struct_id_first = 0, src_struct_id_last = 0;
3084 : :
3085 [ # # ]: 0 : CHECK(n_tokens == 5, EINVAL);
3086 : :
3087 : 0 : func = hash_func_find(p, tokens[1]);
3088 [ # # ]: 0 : CHECK(func, EINVAL);
3089 : :
3090 : 0 : dst = metadata_field_parse(p, tokens[2]);
3091 [ # # ]: 0 : CHECK(dst, EINVAL);
3092 [ # # ]: 0 : CHECK(dst->n_bits <= 64, EINVAL);
3093 : :
3094 : 0 : src_first = struct_field_parse(p, action, tokens[3], &src_struct_id_first);
3095 [ # # ]: 0 : CHECK(src_first, EINVAL);
3096 : :
3097 : 0 : src_last = struct_field_parse(p, action, tokens[4], &src_struct_id_last);
3098 [ # # ]: 0 : CHECK(src_last, EINVAL);
3099 [ # # ]: 0 : CHECK(!src_last->var_size, EINVAL);
3100 [ # # ]: 0 : CHECK(src_struct_id_first == src_struct_id_last, EINVAL);
3101 : :
3102 : 0 : instr->type = INSTR_HASH_FUNC;
3103 : 0 : instr->hash_func.hash_func_id = (uint8_t)func->id;
3104 : 0 : instr->hash_func.dst.offset = (uint8_t)dst->offset / 8;
3105 : 0 : instr->hash_func.dst.n_bits = (uint8_t)dst->n_bits;
3106 : 0 : instr->hash_func.src.struct_id = (uint8_t)src_struct_id_first;
3107 : 0 : instr->hash_func.src.offset = (uint16_t)src_first->offset / 8;
3108 : 0 : instr->hash_func.src.n_bytes = (uint16_t)((src_last->offset + src_last->n_bits -
3109 : 0 : src_first->offset) / 8);
3110 : :
3111 : 0 : return 0;
3112 : : }
3113 : :
3114 : : static inline void
3115 : 0 : instr_hash_func_exec(struct rte_swx_pipeline *p)
3116 : : {
3117 : 0 : struct thread *t = &p->threads[p->thread_id];
3118 : 0 : struct instruction *ip = t->ip;
3119 : :
3120 : : /* Extern function execute. */
3121 : 0 : __instr_hash_func_exec(p, t, ip);
3122 : :
3123 : : /* Thread. */
3124 : : thread_ip_inc(p);
3125 : 0 : }
3126 : :
3127 : : /*
3128 : : * rss.
3129 : : */
3130 : : static int
3131 : 0 : instr_rss_translate(struct rte_swx_pipeline *p,
3132 : : struct action *action,
3133 : : char **tokens,
3134 : : int n_tokens,
3135 : : struct instruction *instr,
3136 : : struct instruction_data *data __rte_unused)
3137 : : {
3138 : : struct rss *rss;
3139 : : struct field *dst, *src_first, *src_last;
3140 : 0 : uint32_t src_struct_id_first = 0, src_struct_id_last = 0;
3141 : :
3142 [ # # ]: 0 : CHECK(n_tokens == 5, EINVAL);
3143 : :
3144 : 0 : rss = rss_find(p, tokens[1]);
3145 [ # # ]: 0 : CHECK(rss, EINVAL);
3146 : :
3147 : 0 : dst = metadata_field_parse(p, tokens[2]);
3148 [ # # ]: 0 : CHECK(dst, EINVAL);
3149 [ # # ]: 0 : CHECK(dst->n_bits <= 64, EINVAL);
3150 : :
3151 : 0 : src_first = struct_field_parse(p, action, tokens[3], &src_struct_id_first);
3152 [ # # ]: 0 : CHECK(src_first, EINVAL);
3153 : :
3154 : 0 : src_last = struct_field_parse(p, action, tokens[4], &src_struct_id_last);
3155 [ # # ]: 0 : CHECK(src_last, EINVAL);
3156 [ # # ]: 0 : CHECK(!src_last->var_size, EINVAL);
3157 [ # # ]: 0 : CHECK(src_struct_id_first == src_struct_id_last, EINVAL);
3158 : :
3159 : 0 : instr->type = INSTR_RSS;
3160 : 0 : instr->rss.rss_obj_id = (uint8_t)rss->id;
3161 : 0 : instr->rss.dst.offset = (uint8_t)dst->offset / 8;
3162 : 0 : instr->rss.dst.n_bits = (uint8_t)dst->n_bits;
3163 : 0 : instr->rss.src.struct_id = (uint8_t)src_struct_id_first;
3164 : 0 : instr->rss.src.offset = (uint16_t)src_first->offset / 8;
3165 : 0 : instr->rss.src.n_bytes = (uint16_t)((src_last->offset + src_last->n_bits -
3166 : 0 : src_first->offset) / 8);
3167 : :
3168 : 0 : return 0;
3169 : : }
3170 : :
3171 : : static inline void
3172 : 0 : instr_rss_exec(struct rte_swx_pipeline *p)
3173 : : {
3174 : 0 : struct thread *t = &p->threads[p->thread_id];
3175 : 0 : struct instruction *ip = t->ip;
3176 : :
3177 : : /* Extern function execute. */
3178 : 0 : __instr_rss_exec(p, t, ip);
3179 : :
3180 : : /* Thread. */
3181 : : thread_ip_inc(p);
3182 : 0 : }
3183 : :
3184 : : /*
3185 : : * mov.
3186 : : */
3187 : : static int
3188 : 0 : instr_mov_translate(struct rte_swx_pipeline *p,
3189 : : struct action *action,
3190 : : char **tokens,
3191 : : int n_tokens,
3192 : : struct instruction *instr,
3193 : : struct instruction_data *data __rte_unused)
3194 : : {
3195 : 0 : char *dst = tokens[1], *src = tokens[2];
3196 : : struct field *fdst, *fsrc;
3197 : : uint64_t src_val;
3198 : 0 : uint32_t dst_struct_id = 0, src_struct_id = 0;
3199 : :
3200 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
3201 : :
3202 : 0 : fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3203 [ # # ]: 0 : CHECK(fdst, EINVAL);
3204 [ # # ]: 0 : CHECK(!fdst->var_size, EINVAL);
3205 : :
3206 : : /* MOV, MOV_MH, MOV_HM, MOV_HH, MOV16, MOVDMA. */
3207 : 0 : fsrc = struct_field_parse(p, action, src, &src_struct_id);
3208 [ # # ]: 0 : if (fsrc) {
3209 [ # # ]: 0 : CHECK(!fsrc->var_size, EINVAL);
3210 : :
3211 [ # # # # ]: 0 : if (fdst->n_bits <= 64 && fsrc->n_bits <= 64) {
3212 : 0 : instr->type = INSTR_MOV;
3213 [ # # # # ]: 0 : if (dst[0] != 'h' && src[0] == 'h')
3214 : 0 : instr->type = INSTR_MOV_MH;
3215 [ # # # # ]: 0 : if (dst[0] == 'h' && src[0] != 'h')
3216 : 0 : instr->type = INSTR_MOV_HM;
3217 [ # # # # ]: 0 : if (dst[0] == 'h' && src[0] == 'h')
3218 : 0 : instr->type = INSTR_MOV_HH;
3219 : : } else {
3220 : : /* The big fields (field with size > 64 bits) are always expected in NBO,
3221 : : * regardless of their type (H or MEFT). In case a big field is involved as
3222 : : * either dst or src, the other field must also be NBO.
3223 : : *
3224 : : * In case the dst field is big, the src field must be either a big field
3225 : : * (of the same or different size as dst) or a small H field. Similarly,
3226 : : * in case the src field is big, the dst field must be either a big field
3227 : : * (of the same or different size as src) or a small H field. Any other case
3228 : : * involving a big field as either dst or src is rejected.
3229 : : */
3230 [ # # # # ]: 0 : CHECK(fdst->n_bits > 64 || dst[0] == 'h', EINVAL);
3231 [ # # # # ]: 0 : CHECK(fsrc->n_bits > 64 || src[0] == 'h', EINVAL);
3232 : :
3233 : 0 : instr->type = INSTR_MOV_DMA;
3234 [ # # # # ]: 0 : if (fdst->n_bits == 128 && fsrc->n_bits == 128)
3235 : 0 : instr->type = INSTR_MOV_128;
3236 : :
3237 [ # # # # ]: 0 : if (fdst->n_bits == 128 && fsrc->n_bits == 64)
3238 : 0 : instr->type = INSTR_MOV_128_64;
3239 [ # # # # ]: 0 : if (fdst->n_bits == 64 && fsrc->n_bits == 128)
3240 : 0 : instr->type = INSTR_MOV_64_128;
3241 : :
3242 [ # # # # ]: 0 : if (fdst->n_bits == 128 && fsrc->n_bits == 32)
3243 : 0 : instr->type = INSTR_MOV_128_32;
3244 [ # # # # ]: 0 : if (fdst->n_bits == 32 && fsrc->n_bits == 128)
3245 : 0 : instr->type = INSTR_MOV_32_128;
3246 : : }
3247 : :
3248 : 0 : instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
3249 : 0 : instr->mov.dst.n_bits = fdst->n_bits;
3250 : 0 : instr->mov.dst.offset = fdst->offset / 8;
3251 : 0 : instr->mov.src.struct_id = (uint8_t)src_struct_id;
3252 : 0 : instr->mov.src.n_bits = fsrc->n_bits;
3253 : 0 : instr->mov.src.offset = fsrc->offset / 8;
3254 : 0 : return 0;
3255 : : }
3256 : :
3257 : : /* MOV_I. */
3258 [ # # ]: 0 : CHECK(fdst->n_bits <= 64, EINVAL);
3259 : 0 : src_val = strtoull(src, &src, 0);
3260 [ # # ]: 0 : CHECK(!src[0], EINVAL);
3261 : :
3262 [ # # ]: 0 : if (dst[0] == 'h')
3263 [ # # ]: 0 : src_val = hton64(src_val) >> (64 - fdst->n_bits);
3264 : :
3265 : 0 : instr->type = INSTR_MOV_I;
3266 : 0 : instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
3267 : 0 : instr->mov.dst.n_bits = fdst->n_bits;
3268 : 0 : instr->mov.dst.offset = fdst->offset / 8;
3269 : 0 : instr->mov.src_val = src_val;
3270 : 0 : return 0;
3271 : : }
3272 : :
3273 : : static inline void
3274 : 0 : instr_mov_exec(struct rte_swx_pipeline *p)
3275 : : {
3276 : 0 : struct thread *t = &p->threads[p->thread_id];
3277 : 0 : struct instruction *ip = t->ip;
3278 : :
3279 : 0 : __instr_mov_exec(p, t, ip);
3280 : :
3281 : : /* Thread. */
3282 : : thread_ip_inc(p);
3283 : 0 : }
3284 : :
3285 : : static inline void
3286 : 0 : instr_mov_mh_exec(struct rte_swx_pipeline *p)
3287 : : {
3288 : 0 : struct thread *t = &p->threads[p->thread_id];
3289 : 0 : struct instruction *ip = t->ip;
3290 : :
3291 : 0 : __instr_mov_mh_exec(p, t, ip);
3292 : :
3293 : : /* Thread. */
3294 : : thread_ip_inc(p);
3295 : 0 : }
3296 : :
3297 : : static inline void
3298 : 0 : instr_mov_hm_exec(struct rte_swx_pipeline *p)
3299 : : {
3300 : 0 : struct thread *t = &p->threads[p->thread_id];
3301 : 0 : struct instruction *ip = t->ip;
3302 : :
3303 : 0 : __instr_mov_hm_exec(p, t, ip);
3304 : :
3305 : : /* Thread. */
3306 : : thread_ip_inc(p);
3307 : 0 : }
3308 : :
3309 : : static inline void
3310 : 0 : instr_mov_hh_exec(struct rte_swx_pipeline *p)
3311 : : {
3312 : 0 : struct thread *t = &p->threads[p->thread_id];
3313 : 0 : struct instruction *ip = t->ip;
3314 : :
3315 : 0 : __instr_mov_hh_exec(p, t, ip);
3316 : :
3317 : : /* Thread. */
3318 : : thread_ip_inc(p);
3319 : 0 : }
3320 : :
3321 : : static inline void
3322 : 0 : instr_mov_dma_exec(struct rte_swx_pipeline *p)
3323 : : {
3324 : 0 : struct thread *t = &p->threads[p->thread_id];
3325 : 0 : struct instruction *ip = t->ip;
3326 : :
3327 : 0 : __instr_mov_dma_exec(p, t, ip);
3328 : :
3329 : : /* Thread. */
3330 : : thread_ip_inc(p);
3331 : 0 : }
3332 : :
3333 : : static inline void
3334 : 0 : instr_mov_128_exec(struct rte_swx_pipeline *p)
3335 : : {
3336 : 0 : struct thread *t = &p->threads[p->thread_id];
3337 : 0 : struct instruction *ip = t->ip;
3338 : :
3339 : : __instr_mov_128_exec(p, t, ip);
3340 : :
3341 : : /* Thread. */
3342 : : thread_ip_inc(p);
3343 : 0 : }
3344 : :
3345 : : static inline void
3346 : 0 : instr_mov_128_64_exec(struct rte_swx_pipeline *p)
3347 : : {
3348 : 0 : struct thread *t = &p->threads[p->thread_id];
3349 : 0 : struct instruction *ip = t->ip;
3350 : :
3351 : : __instr_mov_128_64_exec(p, t, ip);
3352 : :
3353 : : /* Thread. */
3354 : : thread_ip_inc(p);
3355 : 0 : }
3356 : :
3357 : : static inline void
3358 : 0 : instr_mov_64_128_exec(struct rte_swx_pipeline *p)
3359 : : {
3360 : 0 : struct thread *t = &p->threads[p->thread_id];
3361 : 0 : struct instruction *ip = t->ip;
3362 : :
3363 : : __instr_mov_64_128_exec(p, t, ip);
3364 : :
3365 : : /* Thread. */
3366 : : thread_ip_inc(p);
3367 : 0 : }
3368 : :
3369 : : static inline void
3370 : 0 : instr_mov_128_32_exec(struct rte_swx_pipeline *p)
3371 : : {
3372 : 0 : struct thread *t = &p->threads[p->thread_id];
3373 : 0 : struct instruction *ip = t->ip;
3374 : :
3375 : : __instr_mov_128_32_exec(p, t, ip);
3376 : :
3377 : : /* Thread. */
3378 : : thread_ip_inc(p);
3379 : 0 : }
3380 : :
3381 : : static inline void
3382 : 0 : instr_mov_32_128_exec(struct rte_swx_pipeline *p)
3383 : : {
3384 : 0 : struct thread *t = &p->threads[p->thread_id];
3385 : 0 : struct instruction *ip = t->ip;
3386 : :
3387 : : __instr_mov_32_128_exec(p, t, ip);
3388 : :
3389 : : /* Thread. */
3390 : : thread_ip_inc(p);
3391 : 0 : }
3392 : :
3393 : : static inline void
3394 : 0 : instr_mov_i_exec(struct rte_swx_pipeline *p)
3395 : : {
3396 : 0 : struct thread *t = &p->threads[p->thread_id];
3397 : 0 : struct instruction *ip = t->ip;
3398 : :
3399 : : __instr_mov_i_exec(p, t, ip);
3400 : :
3401 : : /* Thread. */
3402 : : thread_ip_inc(p);
3403 : 0 : }
3404 : :
3405 : : /*
3406 : : * movh.
3407 : : */
3408 : : static int
3409 : 0 : instr_movh_translate(struct rte_swx_pipeline *p,
3410 : : struct action *action,
3411 : : char **tokens,
3412 : : int n_tokens,
3413 : : struct instruction *instr,
3414 : : struct instruction_data *data __rte_unused)
3415 : : {
3416 : 0 : char *dst = tokens[1], *src = tokens[2];
3417 : : struct field *fdst, *fsrc;
3418 : 0 : uint32_t dst_struct_id = 0, src_struct_id = 0;
3419 : :
3420 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
3421 : :
3422 : 0 : fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3423 [ # # ]: 0 : CHECK(fdst, EINVAL);
3424 [ # # ]: 0 : CHECK(!fdst->var_size, EINVAL);
3425 : :
3426 : 0 : fsrc = struct_field_parse(p, action, src, &src_struct_id);
3427 [ # # ]: 0 : CHECK(fsrc, EINVAL);
3428 [ # # ]: 0 : CHECK(!fsrc->var_size, EINVAL);
3429 : :
3430 : : /* MOVH_64_128, MOVH_128_64. */
3431 [ # # # # : 0 : if ((dst[0] == 'h' && fdst->n_bits == 64 && fsrc->n_bits == 128) ||
# # ]
3432 [ # # # # : 0 : (fdst->n_bits == 128 && src[0] == 'h' && fsrc->n_bits == 64)) {
# # ]
3433 : 0 : instr->type = INSTR_MOVH;
3434 : :
3435 : 0 : instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
3436 : 0 : instr->mov.dst.n_bits = fdst->n_bits;
3437 : 0 : instr->mov.dst.offset = fdst->offset / 8;
3438 : :
3439 : 0 : instr->mov.src.struct_id = (uint8_t)src_struct_id;
3440 : 0 : instr->mov.src.n_bits = fsrc->n_bits;
3441 : 0 : instr->mov.src.offset = fsrc->offset / 8;
3442 : 0 : return 0;
3443 : : }
3444 : :
3445 : : CHECK(0, EINVAL);
3446 : : }
3447 : :
3448 : : static inline void
3449 : 0 : instr_movh_exec(struct rte_swx_pipeline *p)
3450 : : {
3451 : 0 : struct thread *t = &p->threads[p->thread_id];
3452 : 0 : struct instruction *ip = t->ip;
3453 : :
3454 : : __instr_movh_exec(p, t, ip);
3455 : :
3456 : : /* Thread. */
3457 : : thread_ip_inc(p);
3458 : 0 : }
3459 : :
3460 : : /*
3461 : : * dma.
3462 : : */
3463 : : static inline void
3464 : 0 : instr_dma_ht_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_dma_ht_exec(p, t, ip);
3470 : :
3471 : : /* Thread. */
3472 : : thread_ip_inc(p);
3473 : 0 : }
3474 : :
3475 : : static inline void
3476 : 0 : instr_dma_ht2_exec(struct rte_swx_pipeline *p)
3477 : : {
3478 : 0 : struct thread *t = &p->threads[p->thread_id];
3479 : 0 : struct instruction *ip = t->ip;
3480 : :
3481 : : __instr_dma_ht2_exec(p, t, ip);
3482 : :
3483 : : /* Thread. */
3484 : : thread_ip_inc(p);
3485 : 0 : }
3486 : :
3487 : : static inline void
3488 : 0 : instr_dma_ht3_exec(struct rte_swx_pipeline *p)
3489 : : {
3490 : 0 : struct thread *t = &p->threads[p->thread_id];
3491 : 0 : struct instruction *ip = t->ip;
3492 : :
3493 : : __instr_dma_ht3_exec(p, t, ip);
3494 : :
3495 : : /* Thread. */
3496 : : thread_ip_inc(p);
3497 : 0 : }
3498 : :
3499 : : static inline void
3500 : 0 : instr_dma_ht4_exec(struct rte_swx_pipeline *p)
3501 : : {
3502 : 0 : struct thread *t = &p->threads[p->thread_id];
3503 : 0 : struct instruction *ip = t->ip;
3504 : :
3505 : : __instr_dma_ht4_exec(p, t, ip);
3506 : :
3507 : : /* Thread. */
3508 : : thread_ip_inc(p);
3509 : 0 : }
3510 : :
3511 : : static inline void
3512 : 0 : instr_dma_ht5_exec(struct rte_swx_pipeline *p)
3513 : : {
3514 : 0 : struct thread *t = &p->threads[p->thread_id];
3515 : 0 : struct instruction *ip = t->ip;
3516 : :
3517 : : __instr_dma_ht5_exec(p, t, ip);
3518 : :
3519 : : /* Thread. */
3520 : : thread_ip_inc(p);
3521 : 0 : }
3522 : :
3523 : : static inline void
3524 : 0 : instr_dma_ht6_exec(struct rte_swx_pipeline *p)
3525 : : {
3526 : 0 : struct thread *t = &p->threads[p->thread_id];
3527 : 0 : struct instruction *ip = t->ip;
3528 : :
3529 : : __instr_dma_ht6_exec(p, t, ip);
3530 : :
3531 : : /* Thread. */
3532 : : thread_ip_inc(p);
3533 : 0 : }
3534 : :
3535 : : static inline void
3536 : 0 : instr_dma_ht7_exec(struct rte_swx_pipeline *p)
3537 : : {
3538 : 0 : struct thread *t = &p->threads[p->thread_id];
3539 : 0 : struct instruction *ip = t->ip;
3540 : :
3541 : : __instr_dma_ht7_exec(p, t, ip);
3542 : :
3543 : : /* Thread. */
3544 : : thread_ip_inc(p);
3545 : 0 : }
3546 : :
3547 : : static inline void
3548 : 0 : instr_dma_ht8_exec(struct rte_swx_pipeline *p)
3549 : : {
3550 : 0 : struct thread *t = &p->threads[p->thread_id];
3551 : 0 : struct instruction *ip = t->ip;
3552 : :
3553 : : __instr_dma_ht8_exec(p, t, ip);
3554 : :
3555 : : /* Thread. */
3556 : : thread_ip_inc(p);
3557 : 0 : }
3558 : :
3559 : : /*
3560 : : * alu.
3561 : : */
3562 : : static int
3563 : 0 : instr_alu_add_translate(struct rte_swx_pipeline *p,
3564 : : struct action *action,
3565 : : char **tokens,
3566 : : int n_tokens,
3567 : : struct instruction *instr,
3568 : : struct instruction_data *data __rte_unused)
3569 : : {
3570 : 0 : char *dst = tokens[1], *src = tokens[2];
3571 : : struct field *fdst, *fsrc;
3572 : : uint64_t src_val;
3573 : 0 : uint32_t dst_struct_id = 0, src_struct_id = 0;
3574 : :
3575 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
3576 : :
3577 : 0 : fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3578 [ # # ]: 0 : CHECK(fdst, EINVAL);
3579 [ # # # # ]: 0 : CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
3580 : :
3581 : : /* ADD, ADD_HM, ADD_MH, ADD_HH. */
3582 : 0 : fsrc = struct_field_parse(p, action, src, &src_struct_id);
3583 [ # # ]: 0 : if (fsrc) {
3584 [ # # # # ]: 0 : CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
3585 : :
3586 : 0 : instr->type = INSTR_ALU_ADD;
3587 [ # # # # ]: 0 : if (dst[0] == 'h' && src[0] != 'h')
3588 : 0 : instr->type = INSTR_ALU_ADD_HM;
3589 [ # # # # ]: 0 : if (dst[0] != 'h' && src[0] == 'h')
3590 : 0 : instr->type = INSTR_ALU_ADD_MH;
3591 [ # # # # ]: 0 : if (dst[0] == 'h' && src[0] == 'h')
3592 : 0 : instr->type = INSTR_ALU_ADD_HH;
3593 : :
3594 : 0 : instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3595 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
3596 : 0 : instr->alu.dst.offset = fdst->offset / 8;
3597 : 0 : instr->alu.src.struct_id = (uint8_t)src_struct_id;
3598 : 0 : instr->alu.src.n_bits = fsrc->n_bits;
3599 : 0 : instr->alu.src.offset = fsrc->offset / 8;
3600 : 0 : return 0;
3601 : : }
3602 : :
3603 : : /* ADD_MI, ADD_HI. */
3604 : 0 : src_val = strtoull(src, &src, 0);
3605 [ # # ]: 0 : CHECK(!src[0], EINVAL);
3606 : :
3607 : 0 : instr->type = INSTR_ALU_ADD_MI;
3608 [ # # ]: 0 : if (dst[0] == 'h')
3609 : 0 : instr->type = INSTR_ALU_ADD_HI;
3610 : :
3611 : 0 : instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3612 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
3613 : 0 : instr->alu.dst.offset = fdst->offset / 8;
3614 : 0 : instr->alu.src_val = src_val;
3615 : 0 : return 0;
3616 : : }
3617 : :
3618 : : static int
3619 : 0 : instr_alu_sub_translate(struct rte_swx_pipeline *p,
3620 : : struct action *action,
3621 : : char **tokens,
3622 : : int n_tokens,
3623 : : struct instruction *instr,
3624 : : struct instruction_data *data __rte_unused)
3625 : : {
3626 : 0 : char *dst = tokens[1], *src = tokens[2];
3627 : : struct field *fdst, *fsrc;
3628 : : uint64_t src_val;
3629 : 0 : uint32_t dst_struct_id = 0, src_struct_id = 0;
3630 : :
3631 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
3632 : :
3633 : 0 : fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3634 [ # # ]: 0 : CHECK(fdst, EINVAL);
3635 [ # # # # ]: 0 : CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
3636 : :
3637 : : /* SUB, SUB_HM, SUB_MH, SUB_HH. */
3638 : 0 : fsrc = struct_field_parse(p, action, src, &src_struct_id);
3639 [ # # ]: 0 : if (fsrc) {
3640 [ # # # # ]: 0 : CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
3641 : :
3642 : 0 : instr->type = INSTR_ALU_SUB;
3643 [ # # # # ]: 0 : if (dst[0] == 'h' && src[0] != 'h')
3644 : 0 : instr->type = INSTR_ALU_SUB_HM;
3645 [ # # # # ]: 0 : if (dst[0] != 'h' && src[0] == 'h')
3646 : 0 : instr->type = INSTR_ALU_SUB_MH;
3647 [ # # # # ]: 0 : if (dst[0] == 'h' && src[0] == 'h')
3648 : 0 : instr->type = INSTR_ALU_SUB_HH;
3649 : :
3650 : 0 : instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3651 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
3652 : 0 : instr->alu.dst.offset = fdst->offset / 8;
3653 : 0 : instr->alu.src.struct_id = (uint8_t)src_struct_id;
3654 : 0 : instr->alu.src.n_bits = fsrc->n_bits;
3655 : 0 : instr->alu.src.offset = fsrc->offset / 8;
3656 : 0 : return 0;
3657 : : }
3658 : :
3659 : : /* SUB_MI, SUB_HI. */
3660 : 0 : src_val = strtoull(src, &src, 0);
3661 [ # # ]: 0 : CHECK(!src[0], EINVAL);
3662 : :
3663 : 0 : instr->type = INSTR_ALU_SUB_MI;
3664 [ # # ]: 0 : if (dst[0] == 'h')
3665 : 0 : instr->type = INSTR_ALU_SUB_HI;
3666 : :
3667 : 0 : instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3668 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
3669 : 0 : instr->alu.dst.offset = fdst->offset / 8;
3670 : 0 : instr->alu.src_val = src_val;
3671 : 0 : return 0;
3672 : : }
3673 : :
3674 : : static int
3675 : 0 : instr_alu_ckadd_translate(struct rte_swx_pipeline *p,
3676 : : struct action *action __rte_unused,
3677 : : char **tokens,
3678 : : int n_tokens,
3679 : : struct instruction *instr,
3680 : : struct instruction_data *data __rte_unused)
3681 : : {
3682 : 0 : char *dst = tokens[1], *src = tokens[2];
3683 : : struct header *hdst, *hsrc;
3684 : : struct field *fdst, *fsrc;
3685 : :
3686 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
3687 : :
3688 : 0 : fdst = header_field_parse(p, dst, &hdst);
3689 [ # # ]: 0 : CHECK(fdst, EINVAL);
3690 [ # # # # ]: 0 : CHECK(!fdst->var_size && (fdst->n_bits == 16), EINVAL);
3691 : :
3692 : : /* CKADD_FIELD. */
3693 : 0 : fsrc = header_field_parse(p, src, &hsrc);
3694 [ # # ]: 0 : if (fsrc) {
3695 [ # # # # ]: 0 : CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
3696 : :
3697 : 0 : instr->type = INSTR_ALU_CKADD_FIELD;
3698 : 0 : instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
3699 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
3700 : 0 : instr->alu.dst.offset = fdst->offset / 8;
3701 : 0 : instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
3702 : 0 : instr->alu.src.n_bits = fsrc->n_bits;
3703 : 0 : instr->alu.src.offset = fsrc->offset / 8;
3704 : 0 : return 0;
3705 : : }
3706 : :
3707 : : /* CKADD_STRUCT, CKADD_STRUCT20. */
3708 : 0 : hsrc = header_parse(p, src);
3709 [ # # ]: 0 : CHECK(hsrc, EINVAL);
3710 : :
3711 : 0 : instr->type = INSTR_ALU_CKADD_STRUCT;
3712 [ # # # # ]: 0 : if (!hsrc->st->var_size && ((hsrc->st->n_bits / 8) == 20))
3713 : 0 : instr->type = INSTR_ALU_CKADD_STRUCT20;
3714 : :
3715 : 0 : instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
3716 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
3717 : 0 : instr->alu.dst.offset = fdst->offset / 8;
3718 : 0 : instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
3719 : 0 : instr->alu.src.n_bits = (uint8_t)hsrc->id; /* The src header ID is stored here. */
3720 : 0 : instr->alu.src.offset = 0; /* Unused. */
3721 : 0 : return 0;
3722 : : }
3723 : :
3724 : : static int
3725 : 0 : instr_alu_cksub_translate(struct rte_swx_pipeline *p,
3726 : : struct action *action __rte_unused,
3727 : : char **tokens,
3728 : : int n_tokens,
3729 : : struct instruction *instr,
3730 : : struct instruction_data *data __rte_unused)
3731 : : {
3732 : 0 : char *dst = tokens[1], *src = tokens[2];
3733 : : struct header *hdst, *hsrc;
3734 : : struct field *fdst, *fsrc;
3735 : :
3736 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
3737 : :
3738 : 0 : fdst = header_field_parse(p, dst, &hdst);
3739 [ # # ]: 0 : CHECK(fdst, EINVAL);
3740 [ # # # # ]: 0 : CHECK(!fdst->var_size && (fdst->n_bits == 16), EINVAL);
3741 : :
3742 : 0 : fsrc = header_field_parse(p, src, &hsrc);
3743 [ # # ]: 0 : CHECK(fsrc, EINVAL);
3744 [ # # # # ]: 0 : CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
3745 : :
3746 : 0 : instr->type = INSTR_ALU_CKSUB_FIELD;
3747 : 0 : instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
3748 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
3749 : 0 : instr->alu.dst.offset = fdst->offset / 8;
3750 : 0 : instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
3751 : 0 : instr->alu.src.n_bits = fsrc->n_bits;
3752 : 0 : instr->alu.src.offset = fsrc->offset / 8;
3753 : 0 : return 0;
3754 : : }
3755 : :
3756 : : static int
3757 : 0 : instr_alu_shl_translate(struct rte_swx_pipeline *p,
3758 : : struct action *action,
3759 : : char **tokens,
3760 : : int n_tokens,
3761 : : struct instruction *instr,
3762 : : struct instruction_data *data __rte_unused)
3763 : : {
3764 : 0 : char *dst = tokens[1], *src = tokens[2];
3765 : : struct field *fdst, *fsrc;
3766 : : uint64_t src_val;
3767 : 0 : uint32_t dst_struct_id = 0, src_struct_id = 0;
3768 : :
3769 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
3770 : :
3771 : 0 : fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3772 [ # # ]: 0 : CHECK(fdst, EINVAL);
3773 [ # # # # ]: 0 : CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
3774 : :
3775 : : /* SHL, SHL_HM, SHL_MH, SHL_HH. */
3776 : 0 : fsrc = struct_field_parse(p, action, src, &src_struct_id);
3777 [ # # ]: 0 : if (fsrc) {
3778 [ # # # # ]: 0 : CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
3779 : :
3780 : 0 : instr->type = INSTR_ALU_SHL;
3781 [ # # # # ]: 0 : if (dst[0] == 'h' && src[0] != 'h')
3782 : 0 : instr->type = INSTR_ALU_SHL_HM;
3783 [ # # # # ]: 0 : if (dst[0] != 'h' && src[0] == 'h')
3784 : 0 : instr->type = INSTR_ALU_SHL_MH;
3785 [ # # # # ]: 0 : if (dst[0] == 'h' && src[0] == 'h')
3786 : 0 : instr->type = INSTR_ALU_SHL_HH;
3787 : :
3788 : 0 : instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3789 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
3790 : 0 : instr->alu.dst.offset = fdst->offset / 8;
3791 : 0 : instr->alu.src.struct_id = (uint8_t)src_struct_id;
3792 : 0 : instr->alu.src.n_bits = fsrc->n_bits;
3793 : 0 : instr->alu.src.offset = fsrc->offset / 8;
3794 : 0 : return 0;
3795 : : }
3796 : :
3797 : : /* SHL_MI, SHL_HI. */
3798 : 0 : src_val = strtoull(src, &src, 0);
3799 [ # # ]: 0 : CHECK(!src[0], EINVAL);
3800 : :
3801 : 0 : instr->type = INSTR_ALU_SHL_MI;
3802 [ # # ]: 0 : if (dst[0] == 'h')
3803 : 0 : instr->type = INSTR_ALU_SHL_HI;
3804 : :
3805 : 0 : instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3806 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
3807 : 0 : instr->alu.dst.offset = fdst->offset / 8;
3808 : 0 : instr->alu.src_val = src_val;
3809 : 0 : return 0;
3810 : : }
3811 : :
3812 : : static int
3813 : 0 : instr_alu_shr_translate(struct rte_swx_pipeline *p,
3814 : : struct action *action,
3815 : : char **tokens,
3816 : : int n_tokens,
3817 : : struct instruction *instr,
3818 : : struct instruction_data *data __rte_unused)
3819 : : {
3820 : 0 : char *dst = tokens[1], *src = tokens[2];
3821 : : struct field *fdst, *fsrc;
3822 : : uint64_t src_val;
3823 : 0 : uint32_t dst_struct_id = 0, src_struct_id = 0;
3824 : :
3825 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
3826 : :
3827 : 0 : fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3828 [ # # ]: 0 : CHECK(fdst, EINVAL);
3829 [ # # # # ]: 0 : CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
3830 : :
3831 : : /* SHR, SHR_HM, SHR_MH, SHR_HH. */
3832 : 0 : fsrc = struct_field_parse(p, action, src, &src_struct_id);
3833 [ # # ]: 0 : if (fsrc) {
3834 [ # # # # ]: 0 : CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
3835 : :
3836 : 0 : instr->type = INSTR_ALU_SHR;
3837 [ # # # # ]: 0 : if (dst[0] == 'h' && src[0] != 'h')
3838 : 0 : instr->type = INSTR_ALU_SHR_HM;
3839 [ # # # # ]: 0 : if (dst[0] != 'h' && src[0] == 'h')
3840 : 0 : instr->type = INSTR_ALU_SHR_MH;
3841 [ # # # # ]: 0 : if (dst[0] == 'h' && src[0] == 'h')
3842 : 0 : instr->type = INSTR_ALU_SHR_HH;
3843 : :
3844 : 0 : instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3845 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
3846 : 0 : instr->alu.dst.offset = fdst->offset / 8;
3847 : 0 : instr->alu.src.struct_id = (uint8_t)src_struct_id;
3848 : 0 : instr->alu.src.n_bits = fsrc->n_bits;
3849 : 0 : instr->alu.src.offset = fsrc->offset / 8;
3850 : 0 : return 0;
3851 : : }
3852 : :
3853 : : /* SHR_MI, SHR_HI. */
3854 : 0 : src_val = strtoull(src, &src, 0);
3855 [ # # ]: 0 : CHECK(!src[0], EINVAL);
3856 : :
3857 : 0 : instr->type = INSTR_ALU_SHR_MI;
3858 [ # # ]: 0 : if (dst[0] == 'h')
3859 : 0 : instr->type = INSTR_ALU_SHR_HI;
3860 : :
3861 : 0 : instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3862 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
3863 : 0 : instr->alu.dst.offset = fdst->offset / 8;
3864 : 0 : instr->alu.src_val = src_val;
3865 : 0 : return 0;
3866 : : }
3867 : :
3868 : : static int
3869 : 0 : instr_alu_and_translate(struct rte_swx_pipeline *p,
3870 : : struct action *action,
3871 : : char **tokens,
3872 : : int n_tokens,
3873 : : struct instruction *instr,
3874 : : struct instruction_data *data __rte_unused)
3875 : : {
3876 : 0 : char *dst = tokens[1], *src = tokens[2];
3877 : : struct field *fdst, *fsrc;
3878 : : uint64_t src_val;
3879 : 0 : uint32_t dst_struct_id = 0, src_struct_id = 0;
3880 : :
3881 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
3882 : :
3883 : 0 : fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3884 [ # # ]: 0 : CHECK(fdst, EINVAL);
3885 [ # # # # ]: 0 : CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
3886 : :
3887 : : /* AND, AND_MH, AND_HM, AND_HH. */
3888 : 0 : fsrc = struct_field_parse(p, action, src, &src_struct_id);
3889 [ # # ]: 0 : if (fsrc) {
3890 [ # # # # ]: 0 : CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
3891 : :
3892 : 0 : instr->type = INSTR_ALU_AND;
3893 [ # # # # ]: 0 : if (dst[0] != 'h' && src[0] == 'h')
3894 : 0 : instr->type = INSTR_ALU_AND_MH;
3895 [ # # # # ]: 0 : if (dst[0] == 'h' && src[0] != 'h')
3896 : 0 : instr->type = INSTR_ALU_AND_HM;
3897 [ # # # # ]: 0 : if (dst[0] == 'h' && src[0] == 'h')
3898 : 0 : instr->type = INSTR_ALU_AND_HH;
3899 : :
3900 : 0 : instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3901 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
3902 : 0 : instr->alu.dst.offset = fdst->offset / 8;
3903 : 0 : instr->alu.src.struct_id = (uint8_t)src_struct_id;
3904 : 0 : instr->alu.src.n_bits = fsrc->n_bits;
3905 : 0 : instr->alu.src.offset = fsrc->offset / 8;
3906 : 0 : return 0;
3907 : : }
3908 : :
3909 : : /* AND_I. */
3910 : 0 : src_val = strtoull(src, &src, 0);
3911 [ # # ]: 0 : CHECK(!src[0], EINVAL);
3912 : :
3913 [ # # ]: 0 : if (dst[0] == 'h')
3914 [ # # ]: 0 : src_val = hton64(src_val) >> (64 - fdst->n_bits);
3915 : :
3916 : 0 : instr->type = INSTR_ALU_AND_I;
3917 : 0 : instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3918 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
3919 : 0 : instr->alu.dst.offset = fdst->offset / 8;
3920 : 0 : instr->alu.src_val = src_val;
3921 : 0 : return 0;
3922 : : }
3923 : :
3924 : : static int
3925 : 0 : instr_alu_or_translate(struct rte_swx_pipeline *p,
3926 : : struct action *action,
3927 : : char **tokens,
3928 : : int n_tokens,
3929 : : struct instruction *instr,
3930 : : struct instruction_data *data __rte_unused)
3931 : : {
3932 : 0 : char *dst = tokens[1], *src = tokens[2];
3933 : : struct field *fdst, *fsrc;
3934 : : uint64_t src_val;
3935 : 0 : uint32_t dst_struct_id = 0, src_struct_id = 0;
3936 : :
3937 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
3938 : :
3939 : 0 : fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3940 [ # # ]: 0 : CHECK(fdst, EINVAL);
3941 [ # # # # ]: 0 : CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
3942 : :
3943 : : /* OR, OR_MH, OR_HM, OR_HH. */
3944 : 0 : fsrc = struct_field_parse(p, action, src, &src_struct_id);
3945 [ # # ]: 0 : if (fsrc) {
3946 [ # # # # ]: 0 : CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
3947 : :
3948 : 0 : instr->type = INSTR_ALU_OR;
3949 [ # # # # ]: 0 : if (dst[0] != 'h' && src[0] == 'h')
3950 : 0 : instr->type = INSTR_ALU_OR_MH;
3951 [ # # # # ]: 0 : if (dst[0] == 'h' && src[0] != 'h')
3952 : 0 : instr->type = INSTR_ALU_OR_HM;
3953 [ # # # # ]: 0 : if (dst[0] == 'h' && src[0] == 'h')
3954 : 0 : instr->type = INSTR_ALU_OR_HH;
3955 : :
3956 : 0 : instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3957 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
3958 : 0 : instr->alu.dst.offset = fdst->offset / 8;
3959 : 0 : instr->alu.src.struct_id = (uint8_t)src_struct_id;
3960 : 0 : instr->alu.src.n_bits = fsrc->n_bits;
3961 : 0 : instr->alu.src.offset = fsrc->offset / 8;
3962 : 0 : return 0;
3963 : : }
3964 : :
3965 : : /* OR_I. */
3966 : 0 : src_val = strtoull(src, &src, 0);
3967 [ # # ]: 0 : CHECK(!src[0], EINVAL);
3968 : :
3969 [ # # ]: 0 : if (dst[0] == 'h')
3970 [ # # ]: 0 : src_val = hton64(src_val) >> (64 - fdst->n_bits);
3971 : :
3972 : 0 : instr->type = INSTR_ALU_OR_I;
3973 : 0 : instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3974 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
3975 : 0 : instr->alu.dst.offset = fdst->offset / 8;
3976 : 0 : instr->alu.src_val = src_val;
3977 : 0 : return 0;
3978 : : }
3979 : :
3980 : : static int
3981 : 0 : instr_alu_xor_translate(struct rte_swx_pipeline *p,
3982 : : struct action *action,
3983 : : char **tokens,
3984 : : int n_tokens,
3985 : : struct instruction *instr,
3986 : : struct instruction_data *data __rte_unused)
3987 : : {
3988 : 0 : char *dst = tokens[1], *src = tokens[2];
3989 : : struct field *fdst, *fsrc;
3990 : : uint64_t src_val;
3991 : 0 : uint32_t dst_struct_id = 0, src_struct_id = 0;
3992 : :
3993 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
3994 : :
3995 : 0 : fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3996 [ # # ]: 0 : CHECK(fdst, EINVAL);
3997 [ # # # # ]: 0 : CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
3998 : :
3999 : : /* XOR, XOR_MH, XOR_HM, XOR_HH. */
4000 : 0 : fsrc = struct_field_parse(p, action, src, &src_struct_id);
4001 [ # # ]: 0 : if (fsrc) {
4002 [ # # # # ]: 0 : CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
4003 : :
4004 : 0 : instr->type = INSTR_ALU_XOR;
4005 [ # # # # ]: 0 : if (dst[0] != 'h' && src[0] == 'h')
4006 : 0 : instr->type = INSTR_ALU_XOR_MH;
4007 [ # # # # ]: 0 : if (dst[0] == 'h' && src[0] != 'h')
4008 : 0 : instr->type = INSTR_ALU_XOR_HM;
4009 [ # # # # ]: 0 : if (dst[0] == 'h' && src[0] == 'h')
4010 : 0 : instr->type = INSTR_ALU_XOR_HH;
4011 : :
4012 : 0 : instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4013 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
4014 : 0 : instr->alu.dst.offset = fdst->offset / 8;
4015 : 0 : instr->alu.src.struct_id = (uint8_t)src_struct_id;
4016 : 0 : instr->alu.src.n_bits = fsrc->n_bits;
4017 : 0 : instr->alu.src.offset = fsrc->offset / 8;
4018 : 0 : return 0;
4019 : : }
4020 : :
4021 : : /* XOR_I. */
4022 : 0 : src_val = strtoull(src, &src, 0);
4023 [ # # ]: 0 : CHECK(!src[0], EINVAL);
4024 : :
4025 [ # # ]: 0 : if (dst[0] == 'h')
4026 [ # # ]: 0 : src_val = hton64(src_val) >> (64 - fdst->n_bits);
4027 : :
4028 : 0 : instr->type = INSTR_ALU_XOR_I;
4029 : 0 : instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4030 : 0 : instr->alu.dst.n_bits = fdst->n_bits;
4031 : 0 : instr->alu.dst.offset = fdst->offset / 8;
4032 : 0 : instr->alu.src_val = src_val;
4033 : 0 : return 0;
4034 : : }
4035 : :
4036 : : static inline void
4037 : 0 : instr_alu_add_exec(struct rte_swx_pipeline *p)
4038 : : {
4039 : 0 : struct thread *t = &p->threads[p->thread_id];
4040 : 0 : struct instruction *ip = t->ip;
4041 : :
4042 : : /* Structs */
4043 : 0 : __instr_alu_add_exec(p, t, ip);
4044 : :
4045 : : /* Thread. */
4046 : : thread_ip_inc(p);
4047 : 0 : }
4048 : :
4049 : : static inline void
4050 : 0 : instr_alu_add_mh_exec(struct rte_swx_pipeline *p)
4051 : : {
4052 : 0 : struct thread *t = &p->threads[p->thread_id];
4053 : 0 : struct instruction *ip = t->ip;
4054 : :
4055 : : /* Structs. */
4056 : 0 : __instr_alu_add_mh_exec(p, t, ip);
4057 : :
4058 : : /* Thread. */
4059 : : thread_ip_inc(p);
4060 : 0 : }
4061 : :
4062 : : static inline void
4063 : 0 : instr_alu_add_hm_exec(struct rte_swx_pipeline *p)
4064 : : {
4065 : 0 : struct thread *t = &p->threads[p->thread_id];
4066 : 0 : struct instruction *ip = t->ip;
4067 : :
4068 : : /* Structs. */
4069 : 0 : __instr_alu_add_hm_exec(p, t, ip);
4070 : :
4071 : : /* Thread. */
4072 : : thread_ip_inc(p);
4073 : 0 : }
4074 : :
4075 : : static inline void
4076 : 0 : instr_alu_add_hh_exec(struct rte_swx_pipeline *p)
4077 : : {
4078 : 0 : struct thread *t = &p->threads[p->thread_id];
4079 : 0 : struct instruction *ip = t->ip;
4080 : :
4081 : : /* Structs. */
4082 : 0 : __instr_alu_add_hh_exec(p, t, ip);
4083 : :
4084 : : /* Thread. */
4085 : : thread_ip_inc(p);
4086 : 0 : }
4087 : :
4088 : : static inline void
4089 : 0 : instr_alu_add_mi_exec(struct rte_swx_pipeline *p)
4090 : : {
4091 : 0 : struct thread *t = &p->threads[p->thread_id];
4092 : 0 : struct instruction *ip = t->ip;
4093 : :
4094 : : /* Structs. */
4095 : : __instr_alu_add_mi_exec(p, t, ip);
4096 : :
4097 : : /* Thread. */
4098 : : thread_ip_inc(p);
4099 : 0 : }
4100 : :
4101 : : static inline void
4102 : 0 : instr_alu_add_hi_exec(struct rte_swx_pipeline *p)
4103 : : {
4104 : 0 : struct thread *t = &p->threads[p->thread_id];
4105 : 0 : struct instruction *ip = t->ip;
4106 : :
4107 : : /* Structs. */
4108 : 0 : __instr_alu_add_hi_exec(p, t, ip);
4109 : :
4110 : : /* Thread. */
4111 : : thread_ip_inc(p);
4112 : 0 : }
4113 : :
4114 : : static inline void
4115 : 0 : instr_alu_sub_exec(struct rte_swx_pipeline *p)
4116 : : {
4117 : 0 : struct thread *t = &p->threads[p->thread_id];
4118 : 0 : struct instruction *ip = t->ip;
4119 : :
4120 : : /* Structs. */
4121 : 0 : __instr_alu_sub_exec(p, t, ip);
4122 : :
4123 : : /* Thread. */
4124 : : thread_ip_inc(p);
4125 : 0 : }
4126 : :
4127 : : static inline void
4128 : 0 : instr_alu_sub_mh_exec(struct rte_swx_pipeline *p)
4129 : : {
4130 : 0 : struct thread *t = &p->threads[p->thread_id];
4131 : 0 : struct instruction *ip = t->ip;
4132 : :
4133 : : /* Structs. */
4134 : 0 : __instr_alu_sub_mh_exec(p, t, ip);
4135 : :
4136 : : /* Thread. */
4137 : : thread_ip_inc(p);
4138 : 0 : }
4139 : :
4140 : : static inline void
4141 : 0 : instr_alu_sub_hm_exec(struct rte_swx_pipeline *p)
4142 : : {
4143 : 0 : struct thread *t = &p->threads[p->thread_id];
4144 : 0 : struct instruction *ip = t->ip;
4145 : :
4146 : : /* Structs. */
4147 : 0 : __instr_alu_sub_hm_exec(p, t, ip);
4148 : :
4149 : : /* Thread. */
4150 : : thread_ip_inc(p);
4151 : 0 : }
4152 : :
4153 : : static inline void
4154 : 0 : instr_alu_sub_hh_exec(struct rte_swx_pipeline *p)
4155 : : {
4156 : 0 : struct thread *t = &p->threads[p->thread_id];
4157 : 0 : struct instruction *ip = t->ip;
4158 : :
4159 : : /* Structs. */
4160 : 0 : __instr_alu_sub_hh_exec(p, t, ip);
4161 : :
4162 : : /* Thread. */
4163 : : thread_ip_inc(p);
4164 : 0 : }
4165 : :
4166 : : static inline void
4167 : 0 : instr_alu_sub_mi_exec(struct rte_swx_pipeline *p)
4168 : : {
4169 : 0 : struct thread *t = &p->threads[p->thread_id];
4170 : 0 : struct instruction *ip = t->ip;
4171 : :
4172 : : /* Structs. */
4173 : : __instr_alu_sub_mi_exec(p, t, ip);
4174 : :
4175 : : /* Thread. */
4176 : : thread_ip_inc(p);
4177 : 0 : }
4178 : :
4179 : : static inline void
4180 : 0 : instr_alu_sub_hi_exec(struct rte_swx_pipeline *p)
4181 : : {
4182 : 0 : struct thread *t = &p->threads[p->thread_id];
4183 : 0 : struct instruction *ip = t->ip;
4184 : :
4185 : : /* Structs. */
4186 : 0 : __instr_alu_sub_hi_exec(p, t, ip);
4187 : :
4188 : : /* Thread. */
4189 : : thread_ip_inc(p);
4190 : 0 : }
4191 : :
4192 : : static inline void
4193 : 0 : instr_alu_shl_exec(struct rte_swx_pipeline *p)
4194 : : {
4195 : 0 : struct thread *t = &p->threads[p->thread_id];
4196 : 0 : struct instruction *ip = t->ip;
4197 : :
4198 : : /* Structs. */
4199 : 0 : __instr_alu_shl_exec(p, t, ip);
4200 : :
4201 : : /* Thread. */
4202 : : thread_ip_inc(p);
4203 : 0 : }
4204 : :
4205 : : static inline void
4206 : 0 : instr_alu_shl_mh_exec(struct rte_swx_pipeline *p)
4207 : : {
4208 : 0 : struct thread *t = &p->threads[p->thread_id];
4209 : 0 : struct instruction *ip = t->ip;
4210 : :
4211 : : /* Structs. */
4212 : 0 : __instr_alu_shl_mh_exec(p, t, ip);
4213 : :
4214 : : /* Thread. */
4215 : : thread_ip_inc(p);
4216 : 0 : }
4217 : :
4218 : : static inline void
4219 : 0 : instr_alu_shl_hm_exec(struct rte_swx_pipeline *p)
4220 : : {
4221 : 0 : struct thread *t = &p->threads[p->thread_id];
4222 : 0 : struct instruction *ip = t->ip;
4223 : :
4224 : : /* Structs. */
4225 : 0 : __instr_alu_shl_hm_exec(p, t, ip);
4226 : :
4227 : : /* Thread. */
4228 : : thread_ip_inc(p);
4229 : 0 : }
4230 : :
4231 : : static inline void
4232 : 0 : instr_alu_shl_hh_exec(struct rte_swx_pipeline *p)
4233 : : {
4234 : 0 : struct thread *t = &p->threads[p->thread_id];
4235 : 0 : struct instruction *ip = t->ip;
4236 : :
4237 : : /* Structs. */
4238 : 0 : __instr_alu_shl_hh_exec(p, t, ip);
4239 : :
4240 : : /* Thread. */
4241 : : thread_ip_inc(p);
4242 : 0 : }
4243 : :
4244 : : static inline void
4245 : 0 : instr_alu_shl_mi_exec(struct rte_swx_pipeline *p)
4246 : : {
4247 : 0 : struct thread *t = &p->threads[p->thread_id];
4248 : 0 : struct instruction *ip = t->ip;
4249 : :
4250 : : /* Structs. */
4251 : : __instr_alu_shl_mi_exec(p, t, ip);
4252 : :
4253 : : /* Thread. */
4254 : : thread_ip_inc(p);
4255 : 0 : }
4256 : :
4257 : : static inline void
4258 : 0 : instr_alu_shl_hi_exec(struct rte_swx_pipeline *p)
4259 : : {
4260 : 0 : struct thread *t = &p->threads[p->thread_id];
4261 : 0 : struct instruction *ip = t->ip;
4262 : :
4263 : : /* Structs. */
4264 : 0 : __instr_alu_shl_hi_exec(p, t, ip);
4265 : :
4266 : : /* Thread. */
4267 : : thread_ip_inc(p);
4268 : 0 : }
4269 : :
4270 : : static inline void
4271 : 0 : instr_alu_shr_exec(struct rte_swx_pipeline *p)
4272 : : {
4273 : 0 : struct thread *t = &p->threads[p->thread_id];
4274 : 0 : struct instruction *ip = t->ip;
4275 : :
4276 : : /* Structs. */
4277 : 0 : __instr_alu_shr_exec(p, t, ip);
4278 : :
4279 : : /* Thread. */
4280 : : thread_ip_inc(p);
4281 : 0 : }
4282 : :
4283 : : static inline void
4284 : 0 : instr_alu_shr_mh_exec(struct rte_swx_pipeline *p)
4285 : : {
4286 : 0 : struct thread *t = &p->threads[p->thread_id];
4287 : 0 : struct instruction *ip = t->ip;
4288 : :
4289 : : /* Structs. */
4290 : 0 : __instr_alu_shr_mh_exec(p, t, ip);
4291 : :
4292 : : /* Thread. */
4293 : : thread_ip_inc(p);
4294 : 0 : }
4295 : :
4296 : : static inline void
4297 : 0 : instr_alu_shr_hm_exec(struct rte_swx_pipeline *p)
4298 : : {
4299 : 0 : struct thread *t = &p->threads[p->thread_id];
4300 : 0 : struct instruction *ip = t->ip;
4301 : :
4302 : : /* Structs. */
4303 : 0 : __instr_alu_shr_hm_exec(p, t, ip);
4304 : :
4305 : : /* Thread. */
4306 : : thread_ip_inc(p);
4307 : 0 : }
4308 : :
4309 : : static inline void
4310 : 0 : instr_alu_shr_hh_exec(struct rte_swx_pipeline *p)
4311 : : {
4312 : 0 : struct thread *t = &p->threads[p->thread_id];
4313 : 0 : struct instruction *ip = t->ip;
4314 : :
4315 : : /* Structs. */
4316 : 0 : __instr_alu_shr_hh_exec(p, t, ip);
4317 : :
4318 : : /* Thread. */
4319 : : thread_ip_inc(p);
4320 : 0 : }
4321 : :
4322 : : static inline void
4323 : 0 : instr_alu_shr_mi_exec(struct rte_swx_pipeline *p)
4324 : : {
4325 : 0 : struct thread *t = &p->threads[p->thread_id];
4326 : 0 : struct instruction *ip = t->ip;
4327 : :
4328 : : /* Structs. */
4329 : : __instr_alu_shr_mi_exec(p, t, ip);
4330 : :
4331 : : /* Thread. */
4332 : : thread_ip_inc(p);
4333 : 0 : }
4334 : :
4335 : : static inline void
4336 : 0 : instr_alu_shr_hi_exec(struct rte_swx_pipeline *p)
4337 : : {
4338 : 0 : struct thread *t = &p->threads[p->thread_id];
4339 : 0 : struct instruction *ip = t->ip;
4340 : :
4341 : : /* Structs. */
4342 : 0 : __instr_alu_shr_hi_exec(p, t, ip);
4343 : :
4344 : : /* Thread. */
4345 : : thread_ip_inc(p);
4346 : 0 : }
4347 : :
4348 : : static inline void
4349 : 0 : instr_alu_and_exec(struct rte_swx_pipeline *p)
4350 : : {
4351 : 0 : struct thread *t = &p->threads[p->thread_id];
4352 : 0 : struct instruction *ip = t->ip;
4353 : :
4354 : : /* Structs. */
4355 : 0 : __instr_alu_and_exec(p, t, ip);
4356 : :
4357 : : /* Thread. */
4358 : : thread_ip_inc(p);
4359 : 0 : }
4360 : :
4361 : : static inline void
4362 : 0 : instr_alu_and_mh_exec(struct rte_swx_pipeline *p)
4363 : : {
4364 : 0 : struct thread *t = &p->threads[p->thread_id];
4365 : 0 : struct instruction *ip = t->ip;
4366 : :
4367 : : /* Structs. */
4368 : 0 : __instr_alu_and_mh_exec(p, t, ip);
4369 : :
4370 : : /* Thread. */
4371 : : thread_ip_inc(p);
4372 : 0 : }
4373 : :
4374 : : static inline void
4375 : 0 : instr_alu_and_hm_exec(struct rte_swx_pipeline *p)
4376 : : {
4377 : 0 : struct thread *t = &p->threads[p->thread_id];
4378 : 0 : struct instruction *ip = t->ip;
4379 : :
4380 : : /* Structs. */
4381 : 0 : __instr_alu_and_hm_exec(p, t, ip);
4382 : :
4383 : : /* Thread. */
4384 : : thread_ip_inc(p);
4385 : 0 : }
4386 : :
4387 : : static inline void
4388 : 0 : instr_alu_and_hh_exec(struct rte_swx_pipeline *p)
4389 : : {
4390 : 0 : struct thread *t = &p->threads[p->thread_id];
4391 : 0 : struct instruction *ip = t->ip;
4392 : :
4393 : : /* Structs. */
4394 : 0 : __instr_alu_and_hh_exec(p, t, ip);
4395 : :
4396 : : /* Thread. */
4397 : : thread_ip_inc(p);
4398 : 0 : }
4399 : :
4400 : : static inline void
4401 : 0 : instr_alu_and_i_exec(struct rte_swx_pipeline *p)
4402 : : {
4403 : 0 : struct thread *t = &p->threads[p->thread_id];
4404 : 0 : struct instruction *ip = t->ip;
4405 : :
4406 : : /* Structs. */
4407 : : __instr_alu_and_i_exec(p, t, ip);
4408 : :
4409 : : /* Thread. */
4410 : : thread_ip_inc(p);
4411 : 0 : }
4412 : :
4413 : : static inline void
4414 : 0 : instr_alu_or_exec(struct rte_swx_pipeline *p)
4415 : : {
4416 : 0 : struct thread *t = &p->threads[p->thread_id];
4417 : 0 : struct instruction *ip = t->ip;
4418 : :
4419 : : /* Structs. */
4420 : 0 : __instr_alu_or_exec(p, t, ip);
4421 : :
4422 : : /* Thread. */
4423 : : thread_ip_inc(p);
4424 : 0 : }
4425 : :
4426 : : static inline void
4427 : 0 : instr_alu_or_mh_exec(struct rte_swx_pipeline *p)
4428 : : {
4429 : 0 : struct thread *t = &p->threads[p->thread_id];
4430 : 0 : struct instruction *ip = t->ip;
4431 : :
4432 : : /* Structs. */
4433 : 0 : __instr_alu_or_mh_exec(p, t, ip);
4434 : :
4435 : : /* Thread. */
4436 : : thread_ip_inc(p);
4437 : 0 : }
4438 : :
4439 : : static inline void
4440 : 0 : instr_alu_or_hm_exec(struct rte_swx_pipeline *p)
4441 : : {
4442 : 0 : struct thread *t = &p->threads[p->thread_id];
4443 : 0 : struct instruction *ip = t->ip;
4444 : :
4445 : : /* Structs. */
4446 : 0 : __instr_alu_or_hm_exec(p, t, ip);
4447 : :
4448 : : /* Thread. */
4449 : : thread_ip_inc(p);
4450 : 0 : }
4451 : :
4452 : : static inline void
4453 : 0 : instr_alu_or_hh_exec(struct rte_swx_pipeline *p)
4454 : : {
4455 : 0 : struct thread *t = &p->threads[p->thread_id];
4456 : 0 : struct instruction *ip = t->ip;
4457 : :
4458 : : /* Structs. */
4459 : 0 : __instr_alu_or_hh_exec(p, t, ip);
4460 : :
4461 : : /* Thread. */
4462 : : thread_ip_inc(p);
4463 : 0 : }
4464 : :
4465 : : static inline void
4466 : 0 : instr_alu_or_i_exec(struct rte_swx_pipeline *p)
4467 : : {
4468 : 0 : struct thread *t = &p->threads[p->thread_id];
4469 : 0 : struct instruction *ip = t->ip;
4470 : :
4471 : : /* Structs. */
4472 : : __instr_alu_or_i_exec(p, t, ip);
4473 : :
4474 : : /* Thread. */
4475 : : thread_ip_inc(p);
4476 : 0 : }
4477 : :
4478 : : static inline void
4479 : 0 : instr_alu_xor_exec(struct rte_swx_pipeline *p)
4480 : : {
4481 : 0 : struct thread *t = &p->threads[p->thread_id];
4482 : 0 : struct instruction *ip = t->ip;
4483 : :
4484 : : /* Structs. */
4485 : 0 : __instr_alu_xor_exec(p, t, ip);
4486 : :
4487 : : /* Thread. */
4488 : : thread_ip_inc(p);
4489 : 0 : }
4490 : :
4491 : : static inline void
4492 : 0 : instr_alu_xor_mh_exec(struct rte_swx_pipeline *p)
4493 : : {
4494 : 0 : struct thread *t = &p->threads[p->thread_id];
4495 : 0 : struct instruction *ip = t->ip;
4496 : :
4497 : : /* Structs. */
4498 : 0 : __instr_alu_xor_mh_exec(p, t, ip);
4499 : :
4500 : : /* Thread. */
4501 : : thread_ip_inc(p);
4502 : 0 : }
4503 : :
4504 : : static inline void
4505 : 0 : instr_alu_xor_hm_exec(struct rte_swx_pipeline *p)
4506 : : {
4507 : 0 : struct thread *t = &p->threads[p->thread_id];
4508 : 0 : struct instruction *ip = t->ip;
4509 : :
4510 : : /* Structs. */
4511 : 0 : __instr_alu_xor_hm_exec(p, t, ip);
4512 : :
4513 : : /* Thread. */
4514 : : thread_ip_inc(p);
4515 : 0 : }
4516 : :
4517 : : static inline void
4518 : 0 : instr_alu_xor_hh_exec(struct rte_swx_pipeline *p)
4519 : : {
4520 : 0 : struct thread *t = &p->threads[p->thread_id];
4521 : 0 : struct instruction *ip = t->ip;
4522 : :
4523 : : /* Structs. */
4524 : 0 : __instr_alu_xor_hh_exec(p, t, ip);
4525 : :
4526 : : /* Thread. */
4527 : : thread_ip_inc(p);
4528 : 0 : }
4529 : :
4530 : : static inline void
4531 : 0 : instr_alu_xor_i_exec(struct rte_swx_pipeline *p)
4532 : : {
4533 : 0 : struct thread *t = &p->threads[p->thread_id];
4534 : 0 : struct instruction *ip = t->ip;
4535 : :
4536 : : /* Structs. */
4537 : : __instr_alu_xor_i_exec(p, t, ip);
4538 : :
4539 : : /* Thread. */
4540 : : thread_ip_inc(p);
4541 : 0 : }
4542 : :
4543 : : static inline void
4544 : 0 : instr_alu_ckadd_field_exec(struct rte_swx_pipeline *p)
4545 : : {
4546 : 0 : struct thread *t = &p->threads[p->thread_id];
4547 : 0 : struct instruction *ip = t->ip;
4548 : :
4549 : : /* Structs. */
4550 : 0 : __instr_alu_ckadd_field_exec(p, t, ip);
4551 : :
4552 : : /* Thread. */
4553 : : thread_ip_inc(p);
4554 : 0 : }
4555 : :
4556 : : static inline void
4557 : 0 : instr_alu_cksub_field_exec(struct rte_swx_pipeline *p)
4558 : : {
4559 : 0 : struct thread *t = &p->threads[p->thread_id];
4560 : 0 : struct instruction *ip = t->ip;
4561 : :
4562 : : /* Structs. */
4563 : 0 : __instr_alu_cksub_field_exec(p, t, ip);
4564 : :
4565 : : /* Thread. */
4566 : : thread_ip_inc(p);
4567 : 0 : }
4568 : :
4569 : : static inline void
4570 : 0 : instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline *p)
4571 : : {
4572 : 0 : struct thread *t = &p->threads[p->thread_id];
4573 : 0 : struct instruction *ip = t->ip;
4574 : :
4575 : : /* Structs. */
4576 : 0 : __instr_alu_ckadd_struct20_exec(p, t, ip);
4577 : :
4578 : : /* Thread. */
4579 : : thread_ip_inc(p);
4580 : 0 : }
4581 : :
4582 : : static inline void
4583 : 0 : instr_alu_ckadd_struct_exec(struct rte_swx_pipeline *p)
4584 : : {
4585 : 0 : struct thread *t = &p->threads[p->thread_id];
4586 : 0 : struct instruction *ip = t->ip;
4587 : :
4588 : : /* Structs. */
4589 : 0 : __instr_alu_ckadd_struct_exec(p, t, ip);
4590 : :
4591 : : /* Thread. */
4592 : : thread_ip_inc(p);
4593 : 0 : }
4594 : :
4595 : : /*
4596 : : * Register array.
4597 : : */
4598 : : static struct regarray *
4599 : : regarray_find(struct rte_swx_pipeline *p, const char *name);
4600 : :
4601 : : static int
4602 : 0 : instr_regprefetch_translate(struct rte_swx_pipeline *p,
4603 : : struct action *action,
4604 : : char **tokens,
4605 : : int n_tokens,
4606 : : struct instruction *instr,
4607 : : struct instruction_data *data __rte_unused)
4608 : : {
4609 : 0 : char *regarray = tokens[1], *idx = tokens[2];
4610 : : struct regarray *r;
4611 : : struct field *fidx;
4612 : : uint32_t idx_struct_id, idx_val;
4613 : :
4614 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
4615 : :
4616 : : r = regarray_find(p, regarray);
4617 [ # # ]: 0 : CHECK(r, EINVAL);
4618 : :
4619 : : /* REGPREFETCH_RH, REGPREFETCH_RM. */
4620 : 0 : fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4621 [ # # ]: 0 : if (fidx) {
4622 [ # # # # ]: 0 : CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
4623 : :
4624 : 0 : instr->type = INSTR_REGPREFETCH_RM;
4625 [ # # ]: 0 : if (idx[0] == 'h')
4626 : 0 : instr->type = INSTR_REGPREFETCH_RH;
4627 : :
4628 : 0 : instr->regarray.regarray_id = r->id;
4629 : 0 : instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4630 : 0 : instr->regarray.idx.n_bits = fidx->n_bits;
4631 : 0 : instr->regarray.idx.offset = fidx->offset / 8;
4632 : 0 : instr->regarray.dstsrc_val = 0; /* Unused. */
4633 : 0 : return 0;
4634 : : }
4635 : :
4636 : : /* REGPREFETCH_RI. */
4637 : 0 : idx_val = strtoul(idx, &idx, 0);
4638 [ # # ]: 0 : CHECK(!idx[0], EINVAL);
4639 : :
4640 : 0 : instr->type = INSTR_REGPREFETCH_RI;
4641 : 0 : instr->regarray.regarray_id = r->id;
4642 : 0 : instr->regarray.idx_val = idx_val;
4643 : 0 : instr->regarray.dstsrc_val = 0; /* Unused. */
4644 : 0 : return 0;
4645 : : }
4646 : :
4647 : : static int
4648 : 0 : instr_regrd_translate(struct rte_swx_pipeline *p,
4649 : : struct action *action,
4650 : : char **tokens,
4651 : : int n_tokens,
4652 : : struct instruction *instr,
4653 : : struct instruction_data *data __rte_unused)
4654 : : {
4655 : 0 : char *dst = tokens[1], *regarray = tokens[2], *idx = tokens[3];
4656 : : struct regarray *r;
4657 : : struct field *fdst, *fidx;
4658 : : uint32_t dst_struct_id, idx_struct_id, idx_val;
4659 : :
4660 [ # # ]: 0 : CHECK(n_tokens == 4, EINVAL);
4661 : :
4662 : : r = regarray_find(p, regarray);
4663 [ # # ]: 0 : CHECK(r, EINVAL);
4664 : :
4665 : 0 : fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4666 [ # # ]: 0 : CHECK(fdst, EINVAL);
4667 [ # # # # ]: 0 : CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
4668 : :
4669 : : /* REGRD_HRH, REGRD_HRM, REGRD_MRH, REGRD_MRM. */
4670 : 0 : fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4671 [ # # ]: 0 : if (fidx) {
4672 [ # # # # ]: 0 : CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
4673 : :
4674 : 0 : instr->type = INSTR_REGRD_MRM;
4675 [ # # # # ]: 0 : if (dst[0] == 'h' && idx[0] != 'h')
4676 : 0 : instr->type = INSTR_REGRD_HRM;
4677 [ # # # # ]: 0 : if (dst[0] != 'h' && idx[0] == 'h')
4678 : 0 : instr->type = INSTR_REGRD_MRH;
4679 [ # # # # ]: 0 : if (dst[0] == 'h' && idx[0] == 'h')
4680 : 0 : instr->type = INSTR_REGRD_HRH;
4681 : :
4682 : 0 : instr->regarray.regarray_id = r->id;
4683 : 0 : instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4684 : 0 : instr->regarray.idx.n_bits = fidx->n_bits;
4685 : 0 : instr->regarray.idx.offset = fidx->offset / 8;
4686 : 0 : instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
4687 : 0 : instr->regarray.dstsrc.n_bits = fdst->n_bits;
4688 : 0 : instr->regarray.dstsrc.offset = fdst->offset / 8;
4689 : 0 : return 0;
4690 : : }
4691 : :
4692 : : /* REGRD_MRI, REGRD_HRI. */
4693 : 0 : idx_val = strtoul(idx, &idx, 0);
4694 [ # # ]: 0 : CHECK(!idx[0], EINVAL);
4695 : :
4696 : 0 : instr->type = INSTR_REGRD_MRI;
4697 [ # # ]: 0 : if (dst[0] == 'h')
4698 : 0 : instr->type = INSTR_REGRD_HRI;
4699 : :
4700 : 0 : instr->regarray.regarray_id = r->id;
4701 : 0 : instr->regarray.idx_val = idx_val;
4702 : 0 : instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
4703 : 0 : instr->regarray.dstsrc.n_bits = fdst->n_bits;
4704 : 0 : instr->regarray.dstsrc.offset = fdst->offset / 8;
4705 : 0 : return 0;
4706 : : }
4707 : :
4708 : : static int
4709 : 0 : instr_regwr_translate(struct rte_swx_pipeline *p,
4710 : : struct action *action,
4711 : : char **tokens,
4712 : : int n_tokens,
4713 : : struct instruction *instr,
4714 : : struct instruction_data *data __rte_unused)
4715 : : {
4716 : 0 : char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
4717 : : struct regarray *r;
4718 : : struct field *fidx, *fsrc;
4719 : : uint64_t src_val;
4720 : : uint32_t idx_struct_id, idx_val, src_struct_id;
4721 : :
4722 [ # # ]: 0 : CHECK(n_tokens == 4, EINVAL);
4723 : :
4724 : : r = regarray_find(p, regarray);
4725 [ # # ]: 0 : CHECK(r, EINVAL);
4726 : :
4727 : : /* REGWR_RHH, REGWR_RHM, REGWR_RMH, REGWR_RMM. */
4728 : 0 : fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4729 : 0 : fsrc = struct_field_parse(p, action, src, &src_struct_id);
4730 [ # # ]: 0 : if (fidx && fsrc) {
4731 [ # # # # ]: 0 : CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
4732 [ # # # # ]: 0 : CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
4733 : :
4734 : 0 : instr->type = INSTR_REGWR_RMM;
4735 [ # # # # ]: 0 : if (idx[0] == 'h' && src[0] != 'h')
4736 : 0 : instr->type = INSTR_REGWR_RHM;
4737 [ # # # # ]: 0 : if (idx[0] != 'h' && src[0] == 'h')
4738 : 0 : instr->type = INSTR_REGWR_RMH;
4739 [ # # # # ]: 0 : if (idx[0] == 'h' && src[0] == 'h')
4740 : 0 : instr->type = INSTR_REGWR_RHH;
4741 : :
4742 : 0 : instr->regarray.regarray_id = r->id;
4743 : 0 : instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4744 : 0 : instr->regarray.idx.n_bits = fidx->n_bits;
4745 : 0 : instr->regarray.idx.offset = fidx->offset / 8;
4746 : 0 : instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4747 : 0 : instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4748 : 0 : instr->regarray.dstsrc.offset = fsrc->offset / 8;
4749 : 0 : return 0;
4750 : : }
4751 : :
4752 : : /* REGWR_RHI, REGWR_RMI. */
4753 [ # # ]: 0 : if (fidx && !fsrc) {
4754 [ # # # # ]: 0 : CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
4755 : :
4756 : 0 : src_val = strtoull(src, &src, 0);
4757 [ # # ]: 0 : CHECK(!src[0], EINVAL);
4758 : :
4759 : 0 : instr->type = INSTR_REGWR_RMI;
4760 [ # # ]: 0 : if (idx[0] == 'h')
4761 : 0 : instr->type = INSTR_REGWR_RHI;
4762 : :
4763 : 0 : instr->regarray.regarray_id = r->id;
4764 : 0 : instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4765 : 0 : instr->regarray.idx.n_bits = fidx->n_bits;
4766 : 0 : instr->regarray.idx.offset = fidx->offset / 8;
4767 : 0 : instr->regarray.dstsrc_val = src_val;
4768 : 0 : return 0;
4769 : : }
4770 : :
4771 : : /* REGWR_RIH, REGWR_RIM. */
4772 [ # # ]: 0 : if (!fidx && fsrc) {
4773 : 0 : idx_val = strtoul(idx, &idx, 0);
4774 [ # # ]: 0 : CHECK(!idx[0], EINVAL);
4775 : :
4776 [ # # # # ]: 0 : CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
4777 : :
4778 : 0 : instr->type = INSTR_REGWR_RIM;
4779 [ # # ]: 0 : if (src[0] == 'h')
4780 : 0 : instr->type = INSTR_REGWR_RIH;
4781 : :
4782 : 0 : instr->regarray.regarray_id = r->id;
4783 : 0 : instr->regarray.idx_val = idx_val;
4784 : 0 : instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4785 : 0 : instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4786 : 0 : instr->regarray.dstsrc.offset = fsrc->offset / 8;
4787 : 0 : return 0;
4788 : : }
4789 : :
4790 : : /* REGWR_RII. */
4791 : 0 : src_val = strtoull(src, &src, 0);
4792 [ # # ]: 0 : CHECK(!src[0], EINVAL);
4793 : :
4794 : 0 : idx_val = strtoul(idx, &idx, 0);
4795 [ # # ]: 0 : CHECK(!idx[0], EINVAL);
4796 : :
4797 : 0 : instr->type = INSTR_REGWR_RII;
4798 : 0 : instr->regarray.idx_val = idx_val;
4799 : 0 : instr->regarray.dstsrc_val = src_val;
4800 : :
4801 : 0 : return 0;
4802 : : }
4803 : :
4804 : : static int
4805 : 0 : instr_regadd_translate(struct rte_swx_pipeline *p,
4806 : : struct action *action,
4807 : : char **tokens,
4808 : : int n_tokens,
4809 : : struct instruction *instr,
4810 : : struct instruction_data *data __rte_unused)
4811 : : {
4812 : 0 : char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
4813 : : struct regarray *r;
4814 : : struct field *fidx, *fsrc;
4815 : : uint64_t src_val;
4816 : : uint32_t idx_struct_id, idx_val, src_struct_id;
4817 : :
4818 [ # # ]: 0 : CHECK(n_tokens == 4, EINVAL);
4819 : :
4820 : : r = regarray_find(p, regarray);
4821 [ # # ]: 0 : CHECK(r, EINVAL);
4822 : :
4823 : : /* REGADD_RHH, REGADD_RHM, REGADD_RMH, REGADD_RMM. */
4824 : 0 : fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4825 : 0 : fsrc = struct_field_parse(p, action, src, &src_struct_id);
4826 [ # # ]: 0 : if (fidx && fsrc) {
4827 [ # # # # ]: 0 : CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
4828 [ # # # # ]: 0 : CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
4829 : :
4830 : 0 : instr->type = INSTR_REGADD_RMM;
4831 [ # # # # ]: 0 : if (idx[0] == 'h' && src[0] != 'h')
4832 : 0 : instr->type = INSTR_REGADD_RHM;
4833 [ # # # # ]: 0 : if (idx[0] != 'h' && src[0] == 'h')
4834 : 0 : instr->type = INSTR_REGADD_RMH;
4835 [ # # # # ]: 0 : if (idx[0] == 'h' && src[0] == 'h')
4836 : 0 : instr->type = INSTR_REGADD_RHH;
4837 : :
4838 : 0 : instr->regarray.regarray_id = r->id;
4839 : 0 : instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4840 : 0 : instr->regarray.idx.n_bits = fidx->n_bits;
4841 : 0 : instr->regarray.idx.offset = fidx->offset / 8;
4842 : 0 : instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4843 : 0 : instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4844 : 0 : instr->regarray.dstsrc.offset = fsrc->offset / 8;
4845 : 0 : return 0;
4846 : : }
4847 : :
4848 : : /* REGADD_RHI, REGADD_RMI. */
4849 [ # # ]: 0 : if (fidx && !fsrc) {
4850 [ # # # # ]: 0 : CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
4851 : :
4852 : 0 : src_val = strtoull(src, &src, 0);
4853 [ # # ]: 0 : CHECK(!src[0], EINVAL);
4854 : :
4855 : 0 : instr->type = INSTR_REGADD_RMI;
4856 [ # # ]: 0 : if (idx[0] == 'h')
4857 : 0 : instr->type = INSTR_REGADD_RHI;
4858 : :
4859 : 0 : instr->regarray.regarray_id = r->id;
4860 : 0 : instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4861 : 0 : instr->regarray.idx.n_bits = fidx->n_bits;
4862 : 0 : instr->regarray.idx.offset = fidx->offset / 8;
4863 : 0 : instr->regarray.dstsrc_val = src_val;
4864 : 0 : return 0;
4865 : : }
4866 : :
4867 : : /* REGADD_RIH, REGADD_RIM. */
4868 [ # # ]: 0 : if (!fidx && fsrc) {
4869 : 0 : idx_val = strtoul(idx, &idx, 0);
4870 [ # # ]: 0 : CHECK(!idx[0], EINVAL);
4871 : :
4872 [ # # # # ]: 0 : CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
4873 : :
4874 : 0 : instr->type = INSTR_REGADD_RIM;
4875 [ # # ]: 0 : if (src[0] == 'h')
4876 : 0 : instr->type = INSTR_REGADD_RIH;
4877 : :
4878 : 0 : instr->regarray.regarray_id = r->id;
4879 : 0 : instr->regarray.idx_val = idx_val;
4880 : 0 : instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4881 : 0 : instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4882 : 0 : instr->regarray.dstsrc.offset = fsrc->offset / 8;
4883 : 0 : return 0;
4884 : : }
4885 : :
4886 : : /* REGADD_RII. */
4887 : 0 : src_val = strtoull(src, &src, 0);
4888 [ # # ]: 0 : CHECK(!src[0], EINVAL);
4889 : :
4890 : 0 : idx_val = strtoul(idx, &idx, 0);
4891 [ # # ]: 0 : CHECK(!idx[0], EINVAL);
4892 : :
4893 : 0 : instr->type = INSTR_REGADD_RII;
4894 : 0 : instr->regarray.idx_val = idx_val;
4895 : 0 : instr->regarray.dstsrc_val = src_val;
4896 : 0 : return 0;
4897 : : }
4898 : :
4899 : : static inline void
4900 : 0 : instr_regprefetch_rh_exec(struct rte_swx_pipeline *p)
4901 : : {
4902 : 0 : struct thread *t = &p->threads[p->thread_id];
4903 : 0 : struct instruction *ip = t->ip;
4904 : :
4905 : : /* Structs. */
4906 : 0 : __instr_regprefetch_rh_exec(p, t, ip);
4907 : :
4908 : : /* Thread. */
4909 : : thread_ip_inc(p);
4910 : 0 : }
4911 : :
4912 : : static inline void
4913 : 0 : instr_regprefetch_rm_exec(struct rte_swx_pipeline *p)
4914 : : {
4915 : 0 : struct thread *t = &p->threads[p->thread_id];
4916 : 0 : struct instruction *ip = t->ip;
4917 : :
4918 : : /* Structs. */
4919 : 0 : __instr_regprefetch_rm_exec(p, t, ip);
4920 : :
4921 : : /* Thread. */
4922 : : thread_ip_inc(p);
4923 : 0 : }
4924 : :
4925 : : static inline void
4926 : 0 : instr_regprefetch_ri_exec(struct rte_swx_pipeline *p)
4927 : : {
4928 : 0 : struct thread *t = &p->threads[p->thread_id];
4929 : 0 : struct instruction *ip = t->ip;
4930 : :
4931 : : /* Structs. */
4932 : : __instr_regprefetch_ri_exec(p, t, ip);
4933 : :
4934 : : /* Thread. */
4935 : : thread_ip_inc(p);
4936 : 0 : }
4937 : :
4938 : : static inline void
4939 : 0 : instr_regrd_hrh_exec(struct rte_swx_pipeline *p)
4940 : : {
4941 : 0 : struct thread *t = &p->threads[p->thread_id];
4942 : 0 : struct instruction *ip = t->ip;
4943 : :
4944 : : /* Structs. */
4945 : 0 : __instr_regrd_hrh_exec(p, t, ip);
4946 : :
4947 : : /* Thread. */
4948 : : thread_ip_inc(p);
4949 : 0 : }
4950 : :
4951 : : static inline void
4952 : 0 : instr_regrd_hrm_exec(struct rte_swx_pipeline *p)
4953 : : {
4954 : 0 : struct thread *t = &p->threads[p->thread_id];
4955 : 0 : struct instruction *ip = t->ip;
4956 : :
4957 : : /* Structs. */
4958 : 0 : __instr_regrd_hrm_exec(p, t, ip);
4959 : :
4960 : : /* Thread. */
4961 : : thread_ip_inc(p);
4962 : 0 : }
4963 : :
4964 : : static inline void
4965 : 0 : instr_regrd_mrh_exec(struct rte_swx_pipeline *p)
4966 : : {
4967 : 0 : struct thread *t = &p->threads[p->thread_id];
4968 : 0 : struct instruction *ip = t->ip;
4969 : :
4970 : : /* Structs. */
4971 : 0 : __instr_regrd_mrh_exec(p, t, ip);
4972 : :
4973 : : /* Thread. */
4974 : : thread_ip_inc(p);
4975 : 0 : }
4976 : :
4977 : : static inline void
4978 : 0 : instr_regrd_mrm_exec(struct rte_swx_pipeline *p)
4979 : : {
4980 : 0 : struct thread *t = &p->threads[p->thread_id];
4981 : 0 : struct instruction *ip = t->ip;
4982 : :
4983 : : /* Structs. */
4984 : 0 : __instr_regrd_mrm_exec(p, t, ip);
4985 : :
4986 : : /* Thread. */
4987 : : thread_ip_inc(p);
4988 : 0 : }
4989 : :
4990 : : static inline void
4991 : 0 : instr_regrd_hri_exec(struct rte_swx_pipeline *p)
4992 : : {
4993 : 0 : struct thread *t = &p->threads[p->thread_id];
4994 : 0 : struct instruction *ip = t->ip;
4995 : :
4996 : : /* Structs. */
4997 : 0 : __instr_regrd_hri_exec(p, t, ip);
4998 : :
4999 : : /* Thread. */
5000 : : thread_ip_inc(p);
5001 : 0 : }
5002 : :
5003 : : static inline void
5004 : 0 : instr_regrd_mri_exec(struct rte_swx_pipeline *p)
5005 : : {
5006 : 0 : struct thread *t = &p->threads[p->thread_id];
5007 : 0 : struct instruction *ip = t->ip;
5008 : :
5009 : : /* Structs. */
5010 : 0 : __instr_regrd_mri_exec(p, t, ip);
5011 : :
5012 : : /* Thread. */
5013 : : thread_ip_inc(p);
5014 : 0 : }
5015 : :
5016 : : static inline void
5017 : 0 : instr_regwr_rhh_exec(struct rte_swx_pipeline *p)
5018 : : {
5019 : 0 : struct thread *t = &p->threads[p->thread_id];
5020 : 0 : struct instruction *ip = t->ip;
5021 : :
5022 : : /* Structs. */
5023 : 0 : __instr_regwr_rhh_exec(p, t, ip);
5024 : :
5025 : : /* Thread. */
5026 : : thread_ip_inc(p);
5027 : 0 : }
5028 : :
5029 : : static inline void
5030 : 0 : instr_regwr_rhm_exec(struct rte_swx_pipeline *p)
5031 : : {
5032 : 0 : struct thread *t = &p->threads[p->thread_id];
5033 : 0 : struct instruction *ip = t->ip;
5034 : :
5035 : : /* Structs. */
5036 : 0 : __instr_regwr_rhm_exec(p, t, ip);
5037 : :
5038 : : /* Thread. */
5039 : : thread_ip_inc(p);
5040 : 0 : }
5041 : :
5042 : : static inline void
5043 : 0 : instr_regwr_rmh_exec(struct rte_swx_pipeline *p)
5044 : : {
5045 : 0 : struct thread *t = &p->threads[p->thread_id];
5046 : 0 : struct instruction *ip = t->ip;
5047 : :
5048 : : /* Structs. */
5049 : 0 : __instr_regwr_rmh_exec(p, t, ip);
5050 : :
5051 : : /* Thread. */
5052 : : thread_ip_inc(p);
5053 : 0 : }
5054 : :
5055 : : static inline void
5056 : 0 : instr_regwr_rmm_exec(struct rte_swx_pipeline *p)
5057 : : {
5058 : 0 : struct thread *t = &p->threads[p->thread_id];
5059 : 0 : struct instruction *ip = t->ip;
5060 : :
5061 : : /* Structs. */
5062 : 0 : __instr_regwr_rmm_exec(p, t, ip);
5063 : :
5064 : : /* Thread. */
5065 : : thread_ip_inc(p);
5066 : 0 : }
5067 : :
5068 : : static inline void
5069 : 0 : instr_regwr_rhi_exec(struct rte_swx_pipeline *p)
5070 : : {
5071 : 0 : struct thread *t = &p->threads[p->thread_id];
5072 : 0 : struct instruction *ip = t->ip;
5073 : :
5074 : : /* Structs. */
5075 : 0 : __instr_regwr_rhi_exec(p, t, ip);
5076 : :
5077 : : /* Thread. */
5078 : : thread_ip_inc(p);
5079 : 0 : }
5080 : :
5081 : : static inline void
5082 : 0 : instr_regwr_rmi_exec(struct rte_swx_pipeline *p)
5083 : : {
5084 : 0 : struct thread *t = &p->threads[p->thread_id];
5085 : 0 : struct instruction *ip = t->ip;
5086 : :
5087 : : /* Structs. */
5088 : 0 : __instr_regwr_rmi_exec(p, t, ip);
5089 : :
5090 : : /* Thread. */
5091 : : thread_ip_inc(p);
5092 : 0 : }
5093 : :
5094 : : static inline void
5095 : 0 : instr_regwr_rih_exec(struct rte_swx_pipeline *p)
5096 : : {
5097 : 0 : struct thread *t = &p->threads[p->thread_id];
5098 : 0 : struct instruction *ip = t->ip;
5099 : :
5100 : : /* Structs. */
5101 : 0 : __instr_regwr_rih_exec(p, t, ip);
5102 : :
5103 : : /* Thread. */
5104 : : thread_ip_inc(p);
5105 : 0 : }
5106 : :
5107 : : static inline void
5108 : 0 : instr_regwr_rim_exec(struct rte_swx_pipeline *p)
5109 : : {
5110 : 0 : struct thread *t = &p->threads[p->thread_id];
5111 : 0 : struct instruction *ip = t->ip;
5112 : :
5113 : : /* Structs. */
5114 : 0 : __instr_regwr_rim_exec(p, t, ip);
5115 : :
5116 : : /* Thread. */
5117 : : thread_ip_inc(p);
5118 : 0 : }
5119 : :
5120 : : static inline void
5121 : 0 : instr_regwr_rii_exec(struct rte_swx_pipeline *p)
5122 : : {
5123 : 0 : struct thread *t = &p->threads[p->thread_id];
5124 : 0 : struct instruction *ip = t->ip;
5125 : :
5126 : : /* Structs. */
5127 : : __instr_regwr_rii_exec(p, t, ip);
5128 : :
5129 : : /* Thread. */
5130 : : thread_ip_inc(p);
5131 : 0 : }
5132 : :
5133 : : static inline void
5134 : 0 : instr_regadd_rhh_exec(struct rte_swx_pipeline *p)
5135 : : {
5136 : 0 : struct thread *t = &p->threads[p->thread_id];
5137 : 0 : struct instruction *ip = t->ip;
5138 : :
5139 : : /* Structs. */
5140 : 0 : __instr_regadd_rhh_exec(p, t, ip);
5141 : :
5142 : : /* Thread. */
5143 : : thread_ip_inc(p);
5144 : 0 : }
5145 : :
5146 : : static inline void
5147 : 0 : instr_regadd_rhm_exec(struct rte_swx_pipeline *p)
5148 : : {
5149 : 0 : struct thread *t = &p->threads[p->thread_id];
5150 : 0 : struct instruction *ip = t->ip;
5151 : :
5152 : : /* Structs. */
5153 : 0 : __instr_regadd_rhm_exec(p, t, ip);
5154 : :
5155 : : /* Thread. */
5156 : : thread_ip_inc(p);
5157 : 0 : }
5158 : :
5159 : : static inline void
5160 : 0 : instr_regadd_rmh_exec(struct rte_swx_pipeline *p)
5161 : : {
5162 : 0 : struct thread *t = &p->threads[p->thread_id];
5163 : 0 : struct instruction *ip = t->ip;
5164 : :
5165 : : /* Structs. */
5166 : 0 : __instr_regadd_rmh_exec(p, t, ip);
5167 : :
5168 : : /* Thread. */
5169 : : thread_ip_inc(p);
5170 : 0 : }
5171 : :
5172 : : static inline void
5173 : 0 : instr_regadd_rmm_exec(struct rte_swx_pipeline *p)
5174 : : {
5175 : 0 : struct thread *t = &p->threads[p->thread_id];
5176 : 0 : struct instruction *ip = t->ip;
5177 : :
5178 : : /* Structs. */
5179 : 0 : __instr_regadd_rmm_exec(p, t, ip);
5180 : :
5181 : : /* Thread. */
5182 : : thread_ip_inc(p);
5183 : 0 : }
5184 : :
5185 : : static inline void
5186 : 0 : instr_regadd_rhi_exec(struct rte_swx_pipeline *p)
5187 : : {
5188 : 0 : struct thread *t = &p->threads[p->thread_id];
5189 : 0 : struct instruction *ip = t->ip;
5190 : :
5191 : : /* Structs. */
5192 : 0 : __instr_regadd_rhi_exec(p, t, ip);
5193 : :
5194 : : /* Thread. */
5195 : : thread_ip_inc(p);
5196 : 0 : }
5197 : :
5198 : : static inline void
5199 : 0 : instr_regadd_rmi_exec(struct rte_swx_pipeline *p)
5200 : : {
5201 : 0 : struct thread *t = &p->threads[p->thread_id];
5202 : 0 : struct instruction *ip = t->ip;
5203 : :
5204 : : /* Structs. */
5205 : 0 : __instr_regadd_rmi_exec(p, t, ip);
5206 : :
5207 : : /* Thread. */
5208 : : thread_ip_inc(p);
5209 : 0 : }
5210 : :
5211 : : static inline void
5212 : 0 : instr_regadd_rih_exec(struct rte_swx_pipeline *p)
5213 : : {
5214 : 0 : struct thread *t = &p->threads[p->thread_id];
5215 : 0 : struct instruction *ip = t->ip;
5216 : :
5217 : : /* Structs. */
5218 : 0 : __instr_regadd_rih_exec(p, t, ip);
5219 : :
5220 : : /* Thread. */
5221 : : thread_ip_inc(p);
5222 : 0 : }
5223 : :
5224 : : static inline void
5225 : 0 : instr_regadd_rim_exec(struct rte_swx_pipeline *p)
5226 : : {
5227 : 0 : struct thread *t = &p->threads[p->thread_id];
5228 : 0 : struct instruction *ip = t->ip;
5229 : :
5230 : : /* Structs. */
5231 : 0 : __instr_regadd_rim_exec(p, t, ip);
5232 : :
5233 : : /* Thread. */
5234 : : thread_ip_inc(p);
5235 : 0 : }
5236 : :
5237 : : static inline void
5238 : 0 : instr_regadd_rii_exec(struct rte_swx_pipeline *p)
5239 : : {
5240 : 0 : struct thread *t = &p->threads[p->thread_id];
5241 : 0 : struct instruction *ip = t->ip;
5242 : :
5243 : : /* Structs. */
5244 : : __instr_regadd_rii_exec(p, t, ip);
5245 : :
5246 : : /* Thread. */
5247 : : thread_ip_inc(p);
5248 : 0 : }
5249 : :
5250 : : /*
5251 : : * metarray.
5252 : : */
5253 : : static struct metarray *
5254 : : metarray_find(struct rte_swx_pipeline *p, const char *name);
5255 : :
5256 : : static int
5257 : 0 : instr_metprefetch_translate(struct rte_swx_pipeline *p,
5258 : : struct action *action,
5259 : : char **tokens,
5260 : : int n_tokens,
5261 : : struct instruction *instr,
5262 : : struct instruction_data *data __rte_unused)
5263 : : {
5264 : 0 : char *metarray = tokens[1], *idx = tokens[2];
5265 : : struct metarray *m;
5266 : : struct field *fidx;
5267 : : uint32_t idx_struct_id, idx_val;
5268 : :
5269 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
5270 : :
5271 : : m = metarray_find(p, metarray);
5272 [ # # ]: 0 : CHECK(m, EINVAL);
5273 : :
5274 : : /* METPREFETCH_H, METPREFETCH_M. */
5275 : 0 : fidx = struct_field_parse(p, action, idx, &idx_struct_id);
5276 [ # # ]: 0 : if (fidx) {
5277 [ # # # # ]: 0 : CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
5278 : :
5279 : 0 : instr->type = INSTR_METPREFETCH_M;
5280 [ # # ]: 0 : if (idx[0] == 'h')
5281 : 0 : instr->type = INSTR_METPREFETCH_H;
5282 : :
5283 : 0 : instr->meter.metarray_id = m->id;
5284 : 0 : instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
5285 : 0 : instr->meter.idx.n_bits = fidx->n_bits;
5286 : 0 : instr->meter.idx.offset = fidx->offset / 8;
5287 : 0 : return 0;
5288 : : }
5289 : :
5290 : : /* METPREFETCH_I. */
5291 : 0 : idx_val = strtoul(idx, &idx, 0);
5292 [ # # ]: 0 : CHECK(!idx[0], EINVAL);
5293 : :
5294 : 0 : instr->type = INSTR_METPREFETCH_I;
5295 : 0 : instr->meter.metarray_id = m->id;
5296 : 0 : instr->meter.idx_val = idx_val;
5297 : 0 : return 0;
5298 : : }
5299 : :
5300 : : static int
5301 : 0 : instr_meter_translate(struct rte_swx_pipeline *p,
5302 : : struct action *action,
5303 : : char **tokens,
5304 : : int n_tokens,
5305 : : struct instruction *instr,
5306 : : struct instruction_data *data __rte_unused)
5307 : : {
5308 : 0 : char *metarray = tokens[1], *idx = tokens[2], *length = tokens[3];
5309 : 0 : char *color_in = tokens[4], *color_out = tokens[5];
5310 : : struct metarray *m;
5311 : : struct field *fidx, *flength, *fcin, *fcout;
5312 : : uint32_t idx_struct_id, length_struct_id;
5313 : : uint32_t color_in_struct_id, color_out_struct_id;
5314 : :
5315 [ # # ]: 0 : CHECK(n_tokens == 6, EINVAL);
5316 : :
5317 : : m = metarray_find(p, metarray);
5318 [ # # ]: 0 : CHECK(m, EINVAL);
5319 : :
5320 : 0 : fidx = struct_field_parse(p, action, idx, &idx_struct_id);
5321 : :
5322 : 0 : flength = struct_field_parse(p, action, length, &length_struct_id);
5323 [ # # ]: 0 : CHECK(flength, EINVAL);
5324 [ # # # # ]: 0 : CHECK(!flength->var_size && (flength->n_bits <= 64), EINVAL);
5325 : :
5326 : 0 : fcin = struct_field_parse(p, action, color_in, &color_in_struct_id);
5327 : :
5328 : 0 : fcout = struct_field_parse(p, NULL, color_out, &color_out_struct_id);
5329 [ # # ]: 0 : CHECK(fcout, EINVAL);
5330 [ # # # # ]: 0 : CHECK(!fcout->var_size && (fcout->n_bits <= 64), EINVAL);
5331 : :
5332 : : /* index = HMEFT, length = HMEFT, color_in = MEFT, color_out = MEF. */
5333 [ # # ]: 0 : if (fidx && fcin) {
5334 [ # # # # ]: 0 : CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
5335 [ # # # # ]: 0 : CHECK(!fcin->var_size && (fcin->n_bits <= 64), EINVAL);
5336 : :
5337 : 0 : instr->type = INSTR_METER_MMM;
5338 [ # # # # ]: 0 : if (idx[0] == 'h' && length[0] == 'h')
5339 : 0 : instr->type = INSTR_METER_HHM;
5340 [ # # # # ]: 0 : if (idx[0] == 'h' && length[0] != 'h')
5341 : 0 : instr->type = INSTR_METER_HMM;
5342 [ # # # # ]: 0 : if (idx[0] != 'h' && length[0] == 'h')
5343 : 0 : instr->type = INSTR_METER_MHM;
5344 : :
5345 : 0 : instr->meter.metarray_id = m->id;
5346 : :
5347 : 0 : instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
5348 : 0 : instr->meter.idx.n_bits = fidx->n_bits;
5349 : 0 : instr->meter.idx.offset = fidx->offset / 8;
5350 : :
5351 : 0 : instr->meter.length.struct_id = (uint8_t)length_struct_id;
5352 : 0 : instr->meter.length.n_bits = flength->n_bits;
5353 : 0 : instr->meter.length.offset = flength->offset / 8;
5354 : :
5355 : 0 : instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
5356 : 0 : instr->meter.color_in.n_bits = fcin->n_bits;
5357 : 0 : instr->meter.color_in.offset = fcin->offset / 8;
5358 : :
5359 : 0 : instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5360 : 0 : instr->meter.color_out.n_bits = fcout->n_bits;
5361 : 0 : instr->meter.color_out.offset = fcout->offset / 8;
5362 : : }
5363 : :
5364 : : /* index = HMEFT, length = HMEFT, color_in = I, color_out = MEF. */
5365 [ # # ]: 0 : if (fidx && !fcin) {
5366 : : uint32_t color_in_val;
5367 : :
5368 [ # # # # ]: 0 : CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
5369 : :
5370 : 0 : color_in_val = strtoul(color_in, &color_in, 0);
5371 [ # # ]: 0 : CHECK(!color_in[0], EINVAL);
5372 : :
5373 : 0 : instr->type = INSTR_METER_MMI;
5374 [ # # # # ]: 0 : if (idx[0] == 'h' && length[0] == 'h')
5375 : 0 : instr->type = INSTR_METER_HHI;
5376 [ # # # # ]: 0 : if (idx[0] == 'h' && length[0] != 'h')
5377 : 0 : instr->type = INSTR_METER_HMI;
5378 [ # # # # ]: 0 : if (idx[0] != 'h' && length[0] == 'h')
5379 : 0 : instr->type = INSTR_METER_MHI;
5380 : :
5381 : 0 : instr->meter.metarray_id = m->id;
5382 : :
5383 : 0 : instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
5384 : 0 : instr->meter.idx.n_bits = fidx->n_bits;
5385 : 0 : instr->meter.idx.offset = fidx->offset / 8;
5386 : :
5387 : 0 : instr->meter.length.struct_id = (uint8_t)length_struct_id;
5388 : 0 : instr->meter.length.n_bits = flength->n_bits;
5389 : 0 : instr->meter.length.offset = flength->offset / 8;
5390 : :
5391 : 0 : instr->meter.color_in_val = color_in_val;
5392 : :
5393 : 0 : instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5394 : 0 : instr->meter.color_out.n_bits = fcout->n_bits;
5395 : 0 : instr->meter.color_out.offset = fcout->offset / 8;
5396 : : }
5397 : :
5398 : : /* index = I, length = HMEFT, color_in = MEFT, color_out = MEF. */
5399 [ # # ]: 0 : if (!fidx && fcin) {
5400 : : uint32_t idx_val;
5401 : :
5402 : 0 : idx_val = strtoul(idx, &idx, 0);
5403 [ # # ]: 0 : CHECK(!idx[0], EINVAL);
5404 : :
5405 [ # # # # ]: 0 : CHECK(!fcin->var_size && (fcin->n_bits <= 64), EINVAL);
5406 : :
5407 : 0 : instr->type = INSTR_METER_IMM;
5408 [ # # ]: 0 : if (length[0] == 'h')
5409 : 0 : instr->type = INSTR_METER_IHM;
5410 : :
5411 : 0 : instr->meter.metarray_id = m->id;
5412 : :
5413 : 0 : instr->meter.idx_val = idx_val;
5414 : :
5415 : 0 : instr->meter.length.struct_id = (uint8_t)length_struct_id;
5416 : 0 : instr->meter.length.n_bits = flength->n_bits;
5417 : 0 : instr->meter.length.offset = flength->offset / 8;
5418 : :
5419 : 0 : instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
5420 : 0 : instr->meter.color_in.n_bits = fcin->n_bits;
5421 : 0 : instr->meter.color_in.offset = fcin->offset / 8;
5422 : :
5423 : 0 : instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5424 : 0 : instr->meter.color_out.n_bits = fcout->n_bits;
5425 : 0 : instr->meter.color_out.offset = fcout->offset / 8;
5426 : : }
5427 : :
5428 : : /* index = I, length = HMEFT, color_in = I, color_out = MEF. */
5429 [ # # ]: 0 : if (!fidx && !fcin) {
5430 : : uint32_t idx_val, color_in_val;
5431 : :
5432 : 0 : idx_val = strtoul(idx, &idx, 0);
5433 [ # # ]: 0 : CHECK(!idx[0], EINVAL);
5434 : :
5435 : 0 : color_in_val = strtoul(color_in, &color_in, 0);
5436 [ # # ]: 0 : CHECK(!color_in[0], EINVAL);
5437 : :
5438 : 0 : instr->type = INSTR_METER_IMI;
5439 [ # # ]: 0 : if (length[0] == 'h')
5440 : 0 : instr->type = INSTR_METER_IHI;
5441 : :
5442 : 0 : instr->meter.metarray_id = m->id;
5443 : :
5444 : 0 : instr->meter.idx_val = idx_val;
5445 : :
5446 : 0 : instr->meter.length.struct_id = (uint8_t)length_struct_id;
5447 : 0 : instr->meter.length.n_bits = flength->n_bits;
5448 : 0 : instr->meter.length.offset = flength->offset / 8;
5449 : :
5450 : 0 : instr->meter.color_in_val = color_in_val;
5451 : :
5452 : 0 : instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5453 : 0 : instr->meter.color_out.n_bits = fcout->n_bits;
5454 : 0 : instr->meter.color_out.offset = fcout->offset / 8;
5455 : : }
5456 : :
5457 : : return 0;
5458 : : }
5459 : :
5460 : : static inline void
5461 : 0 : instr_metprefetch_h_exec(struct rte_swx_pipeline *p)
5462 : : {
5463 : 0 : struct thread *t = &p->threads[p->thread_id];
5464 : 0 : struct instruction *ip = t->ip;
5465 : :
5466 : : /* Structs. */
5467 : : __instr_metprefetch_h_exec(p, t, ip);
5468 : :
5469 : : /* Thread. */
5470 : : thread_ip_inc(p);
5471 : 0 : }
5472 : :
5473 : : static inline void
5474 : 0 : instr_metprefetch_m_exec(struct rte_swx_pipeline *p)
5475 : : {
5476 : 0 : struct thread *t = &p->threads[p->thread_id];
5477 : 0 : struct instruction *ip = t->ip;
5478 : :
5479 : : /* Structs. */
5480 : 0 : __instr_metprefetch_m_exec(p, t, ip);
5481 : :
5482 : : /* Thread. */
5483 : : thread_ip_inc(p);
5484 : 0 : }
5485 : :
5486 : : static inline void
5487 : 0 : instr_metprefetch_i_exec(struct rte_swx_pipeline *p)
5488 : : {
5489 : 0 : struct thread *t = &p->threads[p->thread_id];
5490 : 0 : struct instruction *ip = t->ip;
5491 : :
5492 : : /* Structs. */
5493 : : __instr_metprefetch_i_exec(p, t, ip);
5494 : :
5495 : : /* Thread. */
5496 : : thread_ip_inc(p);
5497 : 0 : }
5498 : :
5499 : : static inline void
5500 : 0 : instr_meter_hhm_exec(struct rte_swx_pipeline *p)
5501 : : {
5502 : 0 : struct thread *t = &p->threads[p->thread_id];
5503 : 0 : struct instruction *ip = t->ip;
5504 : :
5505 : : /* Structs. */
5506 : 0 : __instr_meter_hhm_exec(p, t, ip);
5507 : :
5508 : : /* Thread. */
5509 : : thread_ip_inc(p);
5510 : 0 : }
5511 : :
5512 : : static inline void
5513 : 0 : instr_meter_hhi_exec(struct rte_swx_pipeline *p)
5514 : : {
5515 : 0 : struct thread *t = &p->threads[p->thread_id];
5516 : 0 : struct instruction *ip = t->ip;
5517 : :
5518 : : /* Structs. */
5519 : 0 : __instr_meter_hhi_exec(p, t, ip);
5520 : :
5521 : : /* Thread. */
5522 : : thread_ip_inc(p);
5523 : 0 : }
5524 : :
5525 : : static inline void
5526 : 0 : instr_meter_hmm_exec(struct rte_swx_pipeline *p)
5527 : : {
5528 : 0 : struct thread *t = &p->threads[p->thread_id];
5529 : 0 : struct instruction *ip = t->ip;
5530 : :
5531 : : /* Structs. */
5532 : 0 : __instr_meter_hmm_exec(p, t, ip);
5533 : :
5534 : : /* Thread. */
5535 : : thread_ip_inc(p);
5536 : 0 : }
5537 : :
5538 : : static inline void
5539 : 0 : instr_meter_hmi_exec(struct rte_swx_pipeline *p)
5540 : : {
5541 : 0 : struct thread *t = &p->threads[p->thread_id];
5542 : 0 : struct instruction *ip = t->ip;
5543 : :
5544 : : /* Structs. */
5545 : 0 : __instr_meter_hmi_exec(p, t, ip);
5546 : :
5547 : : /* Thread. */
5548 : : thread_ip_inc(p);
5549 : 0 : }
5550 : :
5551 : : static inline void
5552 : 0 : instr_meter_mhm_exec(struct rte_swx_pipeline *p)
5553 : : {
5554 : 0 : struct thread *t = &p->threads[p->thread_id];
5555 : 0 : struct instruction *ip = t->ip;
5556 : :
5557 : : /* Structs. */
5558 : 0 : __instr_meter_mhm_exec(p, t, ip);
5559 : :
5560 : : /* Thread. */
5561 : : thread_ip_inc(p);
5562 : 0 : }
5563 : :
5564 : : static inline void
5565 : 0 : instr_meter_mhi_exec(struct rte_swx_pipeline *p)
5566 : : {
5567 : 0 : struct thread *t = &p->threads[p->thread_id];
5568 : 0 : struct instruction *ip = t->ip;
5569 : :
5570 : : /* Structs. */
5571 : 0 : __instr_meter_mhi_exec(p, t, ip);
5572 : :
5573 : : /* Thread. */
5574 : : thread_ip_inc(p);
5575 : 0 : }
5576 : :
5577 : : static inline void
5578 : 0 : instr_meter_mmm_exec(struct rte_swx_pipeline *p)
5579 : : {
5580 : 0 : struct thread *t = &p->threads[p->thread_id];
5581 : 0 : struct instruction *ip = t->ip;
5582 : :
5583 : : /* Structs. */
5584 : 0 : __instr_meter_mmm_exec(p, t, ip);
5585 : :
5586 : : /* Thread. */
5587 : : thread_ip_inc(p);
5588 : 0 : }
5589 : :
5590 : : static inline void
5591 : 0 : instr_meter_mmi_exec(struct rte_swx_pipeline *p)
5592 : : {
5593 : 0 : struct thread *t = &p->threads[p->thread_id];
5594 : 0 : struct instruction *ip = t->ip;
5595 : :
5596 : : /* Structs. */
5597 : 0 : __instr_meter_mmi_exec(p, t, ip);
5598 : :
5599 : : /* Thread. */
5600 : : thread_ip_inc(p);
5601 : 0 : }
5602 : :
5603 : : static inline void
5604 : 0 : instr_meter_ihm_exec(struct rte_swx_pipeline *p)
5605 : : {
5606 : 0 : struct thread *t = &p->threads[p->thread_id];
5607 : 0 : struct instruction *ip = t->ip;
5608 : :
5609 : : /* Structs. */
5610 : 0 : __instr_meter_ihm_exec(p, t, ip);
5611 : :
5612 : : /* Thread. */
5613 : : thread_ip_inc(p);
5614 : 0 : }
5615 : :
5616 : : static inline void
5617 : 0 : instr_meter_ihi_exec(struct rte_swx_pipeline *p)
5618 : : {
5619 : 0 : struct thread *t = &p->threads[p->thread_id];
5620 : 0 : struct instruction *ip = t->ip;
5621 : :
5622 : : /* Structs. */
5623 : 0 : __instr_meter_ihi_exec(p, t, ip);
5624 : :
5625 : : /* Thread. */
5626 : : thread_ip_inc(p);
5627 : 0 : }
5628 : :
5629 : : static inline void
5630 : 0 : instr_meter_imm_exec(struct rte_swx_pipeline *p)
5631 : : {
5632 : 0 : struct thread *t = &p->threads[p->thread_id];
5633 : 0 : struct instruction *ip = t->ip;
5634 : :
5635 : : /* Structs. */
5636 : 0 : __instr_meter_imm_exec(p, t, ip);
5637 : :
5638 : : /* Thread. */
5639 : : thread_ip_inc(p);
5640 : 0 : }
5641 : :
5642 : : static inline void
5643 : 0 : instr_meter_imi_exec(struct rte_swx_pipeline *p)
5644 : : {
5645 : 0 : struct thread *t = &p->threads[p->thread_id];
5646 : 0 : struct instruction *ip = t->ip;
5647 : :
5648 : : /* Structs. */
5649 : 0 : __instr_meter_imi_exec(p, t, ip);
5650 : :
5651 : : /* Thread. */
5652 : : thread_ip_inc(p);
5653 : 0 : }
5654 : :
5655 : : /*
5656 : : * jmp.
5657 : : */
5658 : : static int
5659 : : instr_jmp_translate(struct rte_swx_pipeline *p __rte_unused,
5660 : : struct action *action __rte_unused,
5661 : : char **tokens,
5662 : : int n_tokens,
5663 : : struct instruction *instr,
5664 : : struct instruction_data *data)
5665 : : {
5666 : 0 : CHECK(n_tokens == 2, EINVAL);
5667 : :
5668 : 0 : strcpy(data->jmp_label, tokens[1]);
5669 : :
5670 : 0 : instr->type = INSTR_JMP;
5671 : 0 : instr->jmp.ip = NULL; /* Resolved later. */
5672 : 0 : return 0;
5673 : : }
5674 : :
5675 : : static int
5676 : 0 : instr_jmp_valid_translate(struct rte_swx_pipeline *p,
5677 : : struct action *action __rte_unused,
5678 : : char **tokens,
5679 : : int n_tokens,
5680 : : struct instruction *instr,
5681 : : struct instruction_data *data)
5682 : : {
5683 : : struct header *h;
5684 : :
5685 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
5686 : :
5687 : 0 : strcpy(data->jmp_label, tokens[1]);
5688 : :
5689 : 0 : h = header_parse(p, tokens[2]);
5690 [ # # ]: 0 : CHECK(h, EINVAL);
5691 : :
5692 : 0 : instr->type = INSTR_JMP_VALID;
5693 : 0 : instr->jmp.ip = NULL; /* Resolved later. */
5694 : 0 : instr->jmp.header_id = h->id;
5695 : 0 : return 0;
5696 : : }
5697 : :
5698 : : static int
5699 : 0 : instr_jmp_invalid_translate(struct rte_swx_pipeline *p,
5700 : : struct action *action __rte_unused,
5701 : : char **tokens,
5702 : : int n_tokens,
5703 : : struct instruction *instr,
5704 : : struct instruction_data *data)
5705 : : {
5706 : : struct header *h;
5707 : :
5708 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
5709 : :
5710 : 0 : strcpy(data->jmp_label, tokens[1]);
5711 : :
5712 : 0 : h = header_parse(p, tokens[2]);
5713 [ # # ]: 0 : CHECK(h, EINVAL);
5714 : :
5715 : 0 : instr->type = INSTR_JMP_INVALID;
5716 : 0 : instr->jmp.ip = NULL; /* Resolved later. */
5717 : 0 : instr->jmp.header_id = h->id;
5718 : 0 : return 0;
5719 : : }
5720 : :
5721 : : static int
5722 : : instr_jmp_hit_translate(struct rte_swx_pipeline *p __rte_unused,
5723 : : struct action *action,
5724 : : char **tokens,
5725 : : int n_tokens,
5726 : : struct instruction *instr,
5727 : : struct instruction_data *data)
5728 : : {
5729 : 0 : CHECK(!action, EINVAL);
5730 [ # # ]: 0 : CHECK(n_tokens == 2, EINVAL);
5731 : :
5732 : 0 : strcpy(data->jmp_label, tokens[1]);
5733 : :
5734 : 0 : instr->type = INSTR_JMP_HIT;
5735 : 0 : instr->jmp.ip = NULL; /* Resolved later. */
5736 : 0 : return 0;
5737 : : }
5738 : :
5739 : : static int
5740 : : instr_jmp_miss_translate(struct rte_swx_pipeline *p __rte_unused,
5741 : : struct action *action,
5742 : : char **tokens,
5743 : : int n_tokens,
5744 : : struct instruction *instr,
5745 : : struct instruction_data *data)
5746 : : {
5747 : 0 : CHECK(!action, EINVAL);
5748 [ # # ]: 0 : CHECK(n_tokens == 2, EINVAL);
5749 : :
5750 : 0 : strcpy(data->jmp_label, tokens[1]);
5751 : :
5752 : 0 : instr->type = INSTR_JMP_MISS;
5753 : 0 : instr->jmp.ip = NULL; /* Resolved later. */
5754 : 0 : return 0;
5755 : : }
5756 : :
5757 : : static int
5758 : 0 : instr_jmp_action_hit_translate(struct rte_swx_pipeline *p,
5759 : : struct action *action,
5760 : : char **tokens,
5761 : : int n_tokens,
5762 : : struct instruction *instr,
5763 : : struct instruction_data *data)
5764 : : {
5765 : : struct action *a;
5766 : :
5767 [ # # ]: 0 : CHECK(!action, EINVAL);
5768 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
5769 : :
5770 : 0 : strcpy(data->jmp_label, tokens[1]);
5771 : :
5772 : 0 : a = action_find(p, tokens[2]);
5773 [ # # ]: 0 : CHECK(a, EINVAL);
5774 : :
5775 : 0 : instr->type = INSTR_JMP_ACTION_HIT;
5776 : 0 : instr->jmp.ip = NULL; /* Resolved later. */
5777 : 0 : instr->jmp.action_id = a->id;
5778 : 0 : return 0;
5779 : : }
5780 : :
5781 : : static int
5782 : 0 : instr_jmp_action_miss_translate(struct rte_swx_pipeline *p,
5783 : : struct action *action,
5784 : : char **tokens,
5785 : : int n_tokens,
5786 : : struct instruction *instr,
5787 : : struct instruction_data *data)
5788 : : {
5789 : : struct action *a;
5790 : :
5791 [ # # ]: 0 : CHECK(!action, EINVAL);
5792 [ # # ]: 0 : CHECK(n_tokens == 3, EINVAL);
5793 : :
5794 : 0 : strcpy(data->jmp_label, tokens[1]);
5795 : :
5796 : 0 : a = action_find(p, tokens[2]);
5797 [ # # ]: 0 : CHECK(a, EINVAL);
5798 : :
5799 : 0 : instr->type = INSTR_JMP_ACTION_MISS;
5800 : 0 : instr->jmp.ip = NULL; /* Resolved later. */
5801 : 0 : instr->jmp.action_id = a->id;
5802 : 0 : return 0;
5803 : : }
5804 : :
5805 : : static int
5806 : 0 : instr_jmp_eq_translate(struct rte_swx_pipeline *p,
5807 : : struct action *action,
5808 : : char **tokens,
5809 : : int n_tokens,
5810 : : struct instruction *instr,
5811 : : struct instruction_data *data)
5812 : : {
5813 : 0 : char *a = tokens[2], *b = tokens[3];
5814 : : struct field *fa, *fb;
5815 : : uint64_t b_val;
5816 : : uint32_t a_struct_id, b_struct_id;
5817 : :
5818 [ # # ]: 0 : CHECK(n_tokens == 4, EINVAL);
5819 : :
5820 : 0 : strcpy(data->jmp_label, tokens[1]);
5821 : :
5822 : 0 : fa = struct_field_parse(p, action, a, &a_struct_id);
5823 [ # # ]: 0 : CHECK(fa, EINVAL);
5824 [ # # # # ]: 0 : CHECK(!fa->var_size && (fa->n_bits <= 64), EINVAL);
5825 : :
5826 : : /* JMP_EQ, JMP_EQ_MH, JMP_EQ_HM, JMP_EQ_HH. */
5827 : 0 : fb = struct_field_parse(p, action, b, &b_struct_id);
5828 [ # # ]: 0 : if (fb) {
5829 [ # # # # ]: 0 : CHECK(!fb->var_size && (fb->n_bits <= 64), EINVAL);
5830 : :
5831 : 0 : instr->type = INSTR_JMP_EQ;
5832 [ # # # # ]: 0 : if (a[0] != 'h' && b[0] == 'h')
5833 : 0 : instr->type = INSTR_JMP_EQ_MH;
5834 [ # # # # ]: 0 : if (a[0] == 'h' && b[0] != 'h')
5835 : 0 : instr->type = INSTR_JMP_EQ_HM;
5836 [ # # # # ]: 0 : if (a[0] == 'h' && b[0] == 'h')
5837 : 0 : instr->type = INSTR_JMP_EQ_HH;
5838 : 0 : instr->jmp.ip = NULL; /* Resolved later. */
5839 : :
5840 : 0 : instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5841 : 0 : instr->jmp.a.n_bits = fa->n_bits;
5842 : 0 : instr->jmp.a.offset = fa->offset / 8;
5843 : 0 : instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5844 : 0 : instr->jmp.b.n_bits = fb->n_bits;
5845 : 0 : instr->jmp.b.offset = fb->offset / 8;
5846 : 0 : return 0;
5847 : : }
5848 : :
5849 : : /* JMP_EQ_I. */
5850 : 0 : b_val = strtoull(b, &b, 0);
5851 [ # # ]: 0 : CHECK(!b[0], EINVAL);
5852 : :
5853 [ # # ]: 0 : if (a[0] == 'h')
5854 [ # # ]: 0 : b_val = hton64(b_val) >> (64 - fa->n_bits);
5855 : :
5856 : 0 : instr->type = INSTR_JMP_EQ_I;
5857 : 0 : instr->jmp.ip = NULL; /* Resolved later. */
5858 : 0 : instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5859 : 0 : instr->jmp.a.n_bits = fa->n_bits;
5860 : 0 : instr->jmp.a.offset = fa->offset / 8;
5861 : 0 : instr->jmp.b_val = b_val;
5862 : 0 : return 0;
5863 : : }
5864 : :
5865 : : static int
5866 : 0 : instr_jmp_neq_translate(struct rte_swx_pipeline *p,
5867 : : struct action *action,
5868 : : char **tokens,
5869 : : int n_tokens,
5870 : : struct instruction *instr,
5871 : : struct instruction_data *data)
5872 : : {
5873 : 0 : char *a = tokens[2], *b = tokens[3];
5874 : : struct field *fa, *fb;
5875 : : uint64_t b_val;
5876 : : uint32_t a_struct_id, b_struct_id;
5877 : :
5878 [ # # ]: 0 : CHECK(n_tokens == 4, EINVAL);
5879 : :
5880 : 0 : strcpy(data->jmp_label, tokens[1]);
5881 : :
5882 : 0 : fa = struct_field_parse(p, action, a, &a_struct_id);
5883 [ # # ]: 0 : CHECK(fa, EINVAL);
5884 [ # # # # ]: 0 : CHECK(!fa->var_size && (fa->n_bits <= 64), EINVAL);
5885 : :
5886 : : /* JMP_NEQ, JMP_NEQ_MH, JMP_NEQ_HM, JMP_NEQ_HH. */
5887 : 0 : fb = struct_field_parse(p, action, b, &b_struct_id);
5888 [ # # ]: 0 : if (fb) {
5889 [ # # # # ]: 0 : CHECK(!fb->var_size && (fb->n_bits <= 64), EINVAL);
5890 : :
5891 : 0 : instr->type = INSTR_JMP_NEQ;
5892 [ # # # # ]: 0 : if (a[0] != 'h' && b[0] == 'h')
5893 : 0 : instr->type = INSTR_JMP_NEQ_MH;
5894 [ # # # # ]: 0 : if (a[0] == 'h' && b[0] != 'h')
5895 : 0 : instr->type = INSTR_JMP_NEQ_HM;
5896 [ # # # # ]: 0 : if (a[0] == 'h' && b[0] == 'h')
5897 : 0 : instr->type = INSTR_JMP_NEQ_HH;
5898 : 0 : instr->jmp.ip = NULL; /* Resolved later. */
5899 : :
5900 : 0 : instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5901 : 0 : instr->jmp.a.n_bits = fa->n_bits;
5902 : 0 : instr->jmp.a.offset = fa->offset / 8;
5903 : 0 : instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5904 : 0 : instr->jmp.b.n_bits = fb->n_bits;
5905 : 0 : instr->jmp.b.offset = fb->offset / 8;
5906 : 0 : return 0;
5907 : : }
5908 : :
5909 : : /* JMP_NEQ_I. */
5910 : 0 : b_val = strtoull(b, &b, 0);
5911 [ # # ]: 0 : CHECK(!b[0], EINVAL);
5912 : :
5913 [ # # ]: 0 : if (a[0] == 'h')
5914 [ # # ]: 0 : b_val = hton64(b_val) >> (64 - fa->n_bits);
5915 : :
5916 : 0 : instr->type = INSTR_JMP_NEQ_I;
5917 : 0 : instr->jmp.ip = NULL; /* Resolved later. */
5918 : 0 : instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5919 : 0 : instr->jmp.a.n_bits = fa->n_bits;
5920 : 0 : instr->jmp.a.offset = fa->offset / 8;
5921 : 0 : instr->jmp.b_val = b_val;
5922 : 0 : return 0;
5923 : : }
5924 : :
5925 : : static int
5926 : 0 : instr_jmp_lt_translate(struct rte_swx_pipeline *p,
5927 : : struct action *action,
5928 : : char **tokens,
5929 : : int n_tokens,
5930 : : struct instruction *instr,
5931 : : struct instruction_data *data)
5932 : : {
5933 : 0 : char *a = tokens[2], *b = tokens[3];
5934 : : struct field *fa, *fb;
5935 : : uint64_t b_val;
5936 : : uint32_t a_struct_id, b_struct_id;
5937 : :
5938 [ # # ]: 0 : CHECK(n_tokens == 4, EINVAL);
5939 : :
5940 : 0 : strcpy(data->jmp_label, tokens[1]);
5941 : :
5942 : 0 : fa = struct_field_parse(p, action, a, &a_struct_id);
5943 [ # # ]: 0 : CHECK(fa, EINVAL);
5944 [ # # # # ]: 0 : CHECK(!fa->var_size && (fa->n_bits <= 64), EINVAL);
5945 : :
5946 : : /* JMP_LT, JMP_LT_MH, JMP_LT_HM, JMP_LT_HH. */
5947 : 0 : fb = struct_field_parse(p, action, b, &b_struct_id);
5948 [ # # ]: 0 : if (fb) {
5949 [ # # # # ]: 0 : CHECK(!fb->var_size && (fb->n_bits <= 64), EINVAL);
5950 : :
5951 : 0 : instr->type = INSTR_JMP_LT;
5952 [ # # # # ]: 0 : if (a[0] == 'h' && b[0] != 'h')
5953 : 0 : instr->type = INSTR_JMP_LT_HM;
5954 [ # # # # ]: 0 : if (a[0] != 'h' && b[0] == 'h')
5955 : 0 : instr->type = INSTR_JMP_LT_MH;
5956 [ # # # # ]: 0 : if (a[0] == 'h' && b[0] == 'h')
5957 : 0 : instr->type = INSTR_JMP_LT_HH;
5958 : 0 : instr->jmp.ip = NULL; /* Resolved later. */
5959 : :
5960 : 0 : instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5961 : 0 : instr->jmp.a.n_bits = fa->n_bits;
5962 : 0 : instr->jmp.a.offset = fa->offset / 8;
5963 : 0 : instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5964 : 0 : instr->jmp.b.n_bits = fb->n_bits;
5965 : 0 : instr->jmp.b.offset = fb->offset / 8;
5966 : 0 : return 0;
5967 : : }
5968 : :
5969 : : /* JMP_LT_MI, JMP_LT_HI. */
5970 : 0 : b_val = strtoull(b, &b, 0);
5971 [ # # ]: 0 : CHECK(!b[0], EINVAL);
5972 : :
5973 : 0 : instr->type = INSTR_JMP_LT_MI;
5974 [ # # ]: 0 : if (a[0] == 'h')
5975 : 0 : instr->type = INSTR_JMP_LT_HI;
5976 : 0 : instr->jmp.ip = NULL; /* Resolved later. */
5977 : :
5978 : 0 : instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5979 : 0 : instr->jmp.a.n_bits = fa->n_bits;
5980 : 0 : instr->jmp.a.offset = fa->offset / 8;
5981 : 0 : instr->jmp.b_val = b_val;
5982 : 0 : return 0;
5983 : : }
5984 : :
5985 : : static int
5986 : 0 : instr_jmp_gt_translate(struct rte_swx_pipeline *p,
5987 : : struct action *action,
5988 : : char **tokens,
5989 : : int n_tokens,
5990 : : struct instruction *instr,
5991 : : struct instruction_data *data)
5992 : : {
5993 : 0 : char *a = tokens[2], *b = tokens[3];
5994 : : struct field *fa, *fb;
5995 : : uint64_t b_val;
5996 : : uint32_t a_struct_id, b_struct_id;
5997 : :
5998 [ # # ]: 0 : CHECK(n_tokens == 4, EINVAL);
5999 : :
6000 : 0 : strcpy(data->jmp_label, tokens[1]);
6001 : :
6002 : 0 : fa = struct_field_parse(p, action, a, &a_struct_id);
6003 [ # # ]: 0 : CHECK(fa, EINVAL);
6004 [ # # # # ]: 0 : CHECK(!fa->var_size && (fa->n_bits <= 64), EINVAL);
6005 : :
6006 : : /* JMP_GT, JMP_GT_MH, JMP_GT_HM, JMP_GT_HH. */
6007 : 0 : fb = struct_field_parse(p, action, b, &b_struct_id);
6008 [ # # ]: 0 : if (fb) {
6009 [ # # # # ]: 0 : CHECK(!fb->var_size && (fb->n_bits <= 64), EINVAL);
6010 : :
6011 : 0 : instr->type = INSTR_JMP_GT;
6012 [ # # # # ]: 0 : if (a[0] == 'h' && b[0] != 'h')
6013 : 0 : instr->type = INSTR_JMP_GT_HM;
6014 [ # # # # ]: 0 : if (a[0] != 'h' && b[0] == 'h')
6015 : 0 : instr->type = INSTR_JMP_GT_MH;
6016 [ # # # # ]: 0 : if (a[0] == 'h' && b[0] == 'h')
6017 : 0 : instr->type = INSTR_JMP_GT_HH;
6018 : 0 : instr->jmp.ip = NULL; /* Resolved later. */
6019 : :
6020 : 0 : instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6021 : 0 : instr->jmp.a.n_bits = fa->n_bits;
6022 : 0 : instr->jmp.a.offset = fa->offset / 8;
6023 : 0 : instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6024 : 0 : instr->jmp.b.n_bits = fb->n_bits;
6025 : 0 : instr->jmp.b.offset = fb->offset / 8;
6026 : 0 : return 0;
6027 : : }
6028 : :
6029 : : /* JMP_GT_MI, JMP_GT_HI. */
6030 : 0 : b_val = strtoull(b, &b, 0);
6031 [ # # ]: 0 : CHECK(!b[0], EINVAL);
6032 : :
6033 : 0 : instr->type = INSTR_JMP_GT_MI;
6034 [ # # ]: 0 : if (a[0] == 'h')
6035 : 0 : instr->type = INSTR_JMP_GT_HI;
6036 : 0 : instr->jmp.ip = NULL; /* Resolved later. */
6037 : :
6038 : 0 : instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6039 : 0 : instr->jmp.a.n_bits = fa->n_bits;
6040 : 0 : instr->jmp.a.offset = fa->offset / 8;
6041 : 0 : instr->jmp.b_val = b_val;
6042 : 0 : return 0;
6043 : : }
6044 : :
6045 : : static inline void
6046 : 0 : instr_jmp_exec(struct rte_swx_pipeline *p)
6047 : : {
6048 : 0 : struct thread *t = &p->threads[p->thread_id];
6049 : 0 : struct instruction *ip = t->ip;
6050 : :
6051 : : TRACE("[Thread %2u] jmp\n", p->thread_id);
6052 : :
6053 : 0 : thread_ip_set(t, ip->jmp.ip);
6054 : 0 : }
6055 : :
6056 : : static inline void
6057 : 0 : instr_jmp_valid_exec(struct rte_swx_pipeline *p)
6058 : : {
6059 : 0 : struct thread *t = &p->threads[p->thread_id];
6060 : 0 : struct instruction *ip = t->ip;
6061 : 0 : uint32_t header_id = ip->jmp.header_id;
6062 : :
6063 : : TRACE("[Thread %2u] jmpv\n", p->thread_id);
6064 : :
6065 [ # # ]: 0 : t->ip = HEADER_VALID(t, header_id) ? ip->jmp.ip : (t->ip + 1);
6066 : 0 : }
6067 : :
6068 : : static inline void
6069 : 0 : instr_jmp_invalid_exec(struct rte_swx_pipeline *p)
6070 : : {
6071 : 0 : struct thread *t = &p->threads[p->thread_id];
6072 : 0 : struct instruction *ip = t->ip;
6073 : 0 : uint32_t header_id = ip->jmp.header_id;
6074 : :
6075 : : TRACE("[Thread %2u] jmpnv\n", p->thread_id);
6076 : :
6077 [ # # ]: 0 : t->ip = HEADER_VALID(t, header_id) ? (t->ip + 1) : ip->jmp.ip;
6078 : 0 : }
6079 : :
6080 : : static inline void
6081 : 0 : instr_jmp_hit_exec(struct rte_swx_pipeline *p)
6082 : : {
6083 : 0 : struct thread *t = &p->threads[p->thread_id];
6084 : 0 : struct instruction *ip = t->ip;
6085 : 0 : struct instruction *ip_next[] = {t->ip + 1, ip->jmp.ip};
6086 : :
6087 : : TRACE("[Thread %2u] jmph\n", p->thread_id);
6088 : :
6089 : 0 : t->ip = ip_next[t->hit];
6090 : 0 : }
6091 : :
6092 : : static inline void
6093 : 0 : instr_jmp_miss_exec(struct rte_swx_pipeline *p)
6094 : : {
6095 : 0 : struct thread *t = &p->threads[p->thread_id];
6096 : 0 : struct instruction *ip = t->ip;
6097 : 0 : struct instruction *ip_next[] = {ip->jmp.ip, t->ip + 1};
6098 : :
6099 : : TRACE("[Thread %2u] jmpnh\n", p->thread_id);
6100 : :
6101 : 0 : t->ip = ip_next[t->hit];
6102 : 0 : }
6103 : :
6104 : : static inline void
6105 : 0 : instr_jmp_action_hit_exec(struct rte_swx_pipeline *p)
6106 : : {
6107 : 0 : struct thread *t = &p->threads[p->thread_id];
6108 : 0 : struct instruction *ip = t->ip;
6109 : :
6110 : : TRACE("[Thread %2u] jmpa\n", p->thread_id);
6111 : :
6112 [ # # ]: 0 : t->ip = (ip->jmp.action_id == t->action_id) ? ip->jmp.ip : (t->ip + 1);
6113 : 0 : }
6114 : :
6115 : : static inline void
6116 : 0 : instr_jmp_action_miss_exec(struct rte_swx_pipeline *p)
6117 : : {
6118 : 0 : struct thread *t = &p->threads[p->thread_id];
6119 : 0 : struct instruction *ip = t->ip;
6120 : :
6121 : : TRACE("[Thread %2u] jmpna\n", p->thread_id);
6122 : :
6123 [ # # ]: 0 : t->ip = (ip->jmp.action_id == t->action_id) ? (t->ip + 1) : ip->jmp.ip;
6124 : 0 : }
6125 : :
6126 : : static inline void
6127 : 0 : instr_jmp_eq_exec(struct rte_swx_pipeline *p)
6128 : : {
6129 : 0 : struct thread *t = &p->threads[p->thread_id];
6130 : 0 : struct instruction *ip = t->ip;
6131 : :
6132 : : TRACE("[Thread %2u] jmpeq\n", p->thread_id);
6133 : :
6134 [ # # ]: 0 : JMP_CMP(t, ip, ==);
6135 : 0 : }
6136 : :
6137 : : static inline void
6138 : 0 : instr_jmp_eq_mh_exec(struct rte_swx_pipeline *p)
6139 : : {
6140 : 0 : struct thread *t = &p->threads[p->thread_id];
6141 : 0 : struct instruction *ip = t->ip;
6142 : :
6143 : : TRACE("[Thread %2u] jmpeq (mh)\n", p->thread_id);
6144 : :
6145 [ # # # # ]: 0 : JMP_CMP_MH(t, ip, ==);
6146 : 0 : }
6147 : :
6148 : : static inline void
6149 : 0 : instr_jmp_eq_hm_exec(struct rte_swx_pipeline *p)
6150 : : {
6151 : 0 : struct thread *t = &p->threads[p->thread_id];
6152 : 0 : struct instruction *ip = t->ip;
6153 : :
6154 : : TRACE("[Thread %2u] jmpeq (hm)\n", p->thread_id);
6155 : :
6156 [ # # # # ]: 0 : JMP_CMP_HM(t, ip, ==);
6157 : 0 : }
6158 : :
6159 : : static inline void
6160 : 0 : instr_jmp_eq_hh_exec(struct rte_swx_pipeline *p)
6161 : : {
6162 : 0 : struct thread *t = &p->threads[p->thread_id];
6163 : 0 : struct instruction *ip = t->ip;
6164 : :
6165 : : TRACE("[Thread %2u] jmpeq (hh)\n", p->thread_id);
6166 : :
6167 [ # # ]: 0 : JMP_CMP_HH_FAST(t, ip, ==);
6168 : 0 : }
6169 : :
6170 : : static inline void
6171 : 0 : instr_jmp_eq_i_exec(struct rte_swx_pipeline *p)
6172 : : {
6173 : 0 : struct thread *t = &p->threads[p->thread_id];
6174 : 0 : struct instruction *ip = t->ip;
6175 : :
6176 : : TRACE("[Thread %2u] jmpeq (i)\n", p->thread_id);
6177 : :
6178 [ # # ]: 0 : JMP_CMP_I(t, ip, ==);
6179 : 0 : }
6180 : :
6181 : : static inline void
6182 : 0 : instr_jmp_neq_exec(struct rte_swx_pipeline *p)
6183 : : {
6184 : 0 : struct thread *t = &p->threads[p->thread_id];
6185 : 0 : struct instruction *ip = t->ip;
6186 : :
6187 : : TRACE("[Thread %2u] jmpneq\n", p->thread_id);
6188 : :
6189 [ # # ]: 0 : JMP_CMP(t, ip, !=);
6190 : 0 : }
6191 : :
6192 : : static inline void
6193 : 0 : instr_jmp_neq_mh_exec(struct rte_swx_pipeline *p)
6194 : : {
6195 : 0 : struct thread *t = &p->threads[p->thread_id];
6196 : 0 : struct instruction *ip = t->ip;
6197 : :
6198 : : TRACE("[Thread %2u] jmpneq (mh)\n", p->thread_id);
6199 : :
6200 [ # # # # ]: 0 : JMP_CMP_MH(t, ip, !=);
6201 : 0 : }
6202 : :
6203 : : static inline void
6204 : 0 : instr_jmp_neq_hm_exec(struct rte_swx_pipeline *p)
6205 : : {
6206 : 0 : struct thread *t = &p->threads[p->thread_id];
6207 : 0 : struct instruction *ip = t->ip;
6208 : :
6209 : : TRACE("[Thread %2u] jmpneq (hm)\n", p->thread_id);
6210 : :
6211 [ # # # # ]: 0 : JMP_CMP_HM(t, ip, !=);
6212 : 0 : }
6213 : :
6214 : : static inline void
6215 : 0 : instr_jmp_neq_hh_exec(struct rte_swx_pipeline *p)
6216 : : {
6217 : 0 : struct thread *t = &p->threads[p->thread_id];
6218 : 0 : struct instruction *ip = t->ip;
6219 : :
6220 : : TRACE("[Thread %2u] jmpneq (hh)\n", p->thread_id);
6221 : :
6222 [ # # ]: 0 : JMP_CMP_HH_FAST(t, ip, !=);
6223 : 0 : }
6224 : :
6225 : : static inline void
6226 : 0 : instr_jmp_neq_i_exec(struct rte_swx_pipeline *p)
6227 : : {
6228 : 0 : struct thread *t = &p->threads[p->thread_id];
6229 : 0 : struct instruction *ip = t->ip;
6230 : :
6231 : : TRACE("[Thread %2u] jmpneq (i)\n", p->thread_id);
6232 : :
6233 [ # # ]: 0 : JMP_CMP_I(t, ip, !=);
6234 : 0 : }
6235 : :
6236 : : static inline void
6237 : 0 : instr_jmp_lt_exec(struct rte_swx_pipeline *p)
6238 : : {
6239 : 0 : struct thread *t = &p->threads[p->thread_id];
6240 : 0 : struct instruction *ip = t->ip;
6241 : :
6242 : : TRACE("[Thread %2u] jmplt\n", p->thread_id);
6243 : :
6244 [ # # ]: 0 : JMP_CMP(t, ip, <);
6245 : 0 : }
6246 : :
6247 : : static inline void
6248 : 0 : instr_jmp_lt_mh_exec(struct rte_swx_pipeline *p)
6249 : : {
6250 : 0 : struct thread *t = &p->threads[p->thread_id];
6251 : 0 : struct instruction *ip = t->ip;
6252 : :
6253 : : TRACE("[Thread %2u] jmplt (mh)\n", p->thread_id);
6254 : :
6255 [ # # # # ]: 0 : JMP_CMP_MH(t, ip, <);
6256 : 0 : }
6257 : :
6258 : : static inline void
6259 : 0 : instr_jmp_lt_hm_exec(struct rte_swx_pipeline *p)
6260 : : {
6261 : 0 : struct thread *t = &p->threads[p->thread_id];
6262 : 0 : struct instruction *ip = t->ip;
6263 : :
6264 : : TRACE("[Thread %2u] jmplt (hm)\n", p->thread_id);
6265 : :
6266 [ # # # # ]: 0 : JMP_CMP_HM(t, ip, <);
6267 : 0 : }
6268 : :
6269 : : static inline void
6270 : 0 : instr_jmp_lt_hh_exec(struct rte_swx_pipeline *p)
6271 : : {
6272 : 0 : struct thread *t = &p->threads[p->thread_id];
6273 : 0 : struct instruction *ip = t->ip;
6274 : :
6275 : : TRACE("[Thread %2u] jmplt (hh)\n", p->thread_id);
6276 : :
6277 [ # # # # : 0 : JMP_CMP_HH(t, ip, <);
# # ]
6278 : 0 : }
6279 : :
6280 : : static inline void
6281 : 0 : instr_jmp_lt_mi_exec(struct rte_swx_pipeline *p)
6282 : : {
6283 : 0 : struct thread *t = &p->threads[p->thread_id];
6284 : 0 : struct instruction *ip = t->ip;
6285 : :
6286 : : TRACE("[Thread %2u] jmplt (mi)\n", p->thread_id);
6287 : :
6288 [ # # ]: 0 : JMP_CMP_MI(t, ip, <);
6289 : 0 : }
6290 : :
6291 : : static inline void
6292 : 0 : instr_jmp_lt_hi_exec(struct rte_swx_pipeline *p)
6293 : : {
6294 : 0 : struct thread *t = &p->threads[p->thread_id];
6295 : 0 : struct instruction *ip = t->ip;
6296 : :
6297 : : TRACE("[Thread %2u] jmplt (hi)\n", p->thread_id);
6298 : :
6299 [ # # # # ]: 0 : JMP_CMP_HI(t, ip, <);
6300 : 0 : }
6301 : :
6302 : : static inline void
6303 : 0 : instr_jmp_gt_exec(struct rte_swx_pipeline *p)
6304 : : {
6305 : 0 : struct thread *t = &p->threads[p->thread_id];
6306 : 0 : struct instruction *ip = t->ip;
6307 : :
6308 : : TRACE("[Thread %2u] jmpgt\n", p->thread_id);
6309 : :
6310 [ # # ]: 0 : JMP_CMP(t, ip, >);
6311 : 0 : }
6312 : :
6313 : : static inline void
6314 : 0 : instr_jmp_gt_mh_exec(struct rte_swx_pipeline *p)
6315 : : {
6316 : 0 : struct thread *t = &p->threads[p->thread_id];
6317 : 0 : struct instruction *ip = t->ip;
6318 : :
6319 : : TRACE("[Thread %2u] jmpgt (mh)\n", p->thread_id);
6320 : :
6321 [ # # # # ]: 0 : JMP_CMP_MH(t, ip, >);
6322 : 0 : }
6323 : :
6324 : : static inline void
6325 : 0 : instr_jmp_gt_hm_exec(struct rte_swx_pipeline *p)
6326 : : {
6327 : 0 : struct thread *t = &p->threads[p->thread_id];
6328 : 0 : struct instruction *ip = t->ip;
6329 : :
6330 : : TRACE("[Thread %2u] jmpgt (hm)\n", p->thread_id);
6331 : :
6332 [ # # # # ]: 0 : JMP_CMP_HM(t, ip, >);
6333 : 0 : }
6334 : :
6335 : : static inline void
6336 : 0 : instr_jmp_gt_hh_exec(struct rte_swx_pipeline *p)
6337 : : {
6338 : 0 : struct thread *t = &p->threads[p->thread_id];
6339 : 0 : struct instruction *ip = t->ip;
6340 : :
6341 : : TRACE("[Thread %2u] jmpgt (hh)\n", p->thread_id);
6342 : :
6343 [ # # # # : 0 : JMP_CMP_HH(t, ip, >);
# # ]
6344 : 0 : }
6345 : :
6346 : : static inline void
6347 : 0 : instr_jmp_gt_mi_exec(struct rte_swx_pipeline *p)
6348 : : {
6349 : 0 : struct thread *t = &p->threads[p->thread_id];
6350 : 0 : struct instruction *ip = t->ip;
6351 : :
6352 : : TRACE("[Thread %2u] jmpgt (mi)\n", p->thread_id);
6353 : :
6354 [ # # ]: 0 : JMP_CMP_MI(t, ip, >);
6355 : 0 : }
6356 : :
6357 : : static inline void
6358 : 0 : instr_jmp_gt_hi_exec(struct rte_swx_pipeline *p)
6359 : : {
6360 : 0 : struct thread *t = &p->threads[p->thread_id];
6361 : 0 : struct instruction *ip = t->ip;
6362 : :
6363 : : TRACE("[Thread %2u] jmpgt (hi)\n", p->thread_id);
6364 : :
6365 [ # # # # ]: 0 : JMP_CMP_HI(t, ip, >);
6366 : 0 : }
6367 : :
6368 : : /*
6369 : : * return.
6370 : : */
6371 : : static int
6372 : : instr_return_translate(struct rte_swx_pipeline *p __rte_unused,
6373 : : struct action *action,
6374 : : char **tokens __rte_unused,
6375 : : int n_tokens,
6376 : : struct instruction *instr,
6377 : : struct instruction_data *data __rte_unused)
6378 : : {
6379 : 0 : CHECK(action, EINVAL);
6380 [ # # ]: 0 : CHECK(n_tokens == 1, EINVAL);
6381 : :
6382 : 0 : instr->type = INSTR_RETURN;
6383 : 0 : return 0;
6384 : : }
6385 : :
6386 : : static inline void
6387 : 0 : instr_return_exec(struct rte_swx_pipeline *p)
6388 : : {
6389 : 0 : struct thread *t = &p->threads[p->thread_id];
6390 : :
6391 : : TRACE("[Thread %2u] return\n", p->thread_id);
6392 : :
6393 : 0 : t->ip = t->ret;
6394 : 0 : }
6395 : :
6396 : : static int
6397 : 0 : instr_translate(struct rte_swx_pipeline *p,
6398 : : struct action *action,
6399 : : char *string,
6400 : : struct instruction *instr,
6401 : : struct instruction_data *data)
6402 : : {
6403 : : char *tokens[RTE_SWX_INSTRUCTION_TOKENS_MAX];
6404 : : int n_tokens = 0, tpos = 0;
6405 : :
6406 : : /* Parse the instruction string into tokens. */
6407 : 0 : for ( ; ; ) {
6408 : : char *token;
6409 : :
6410 : 0 : token = strtok_r(string, " \t\v", &string);
6411 [ # # ]: 0 : if (!token)
6412 : : break;
6413 : :
6414 [ # # ]: 0 : CHECK(n_tokens < RTE_SWX_INSTRUCTION_TOKENS_MAX, EINVAL);
6415 [ # # # # ]: 0 : CHECK_NAME(token, EINVAL);
6416 : :
6417 : 0 : tokens[n_tokens] = token;
6418 : 0 : n_tokens++;
6419 : : }
6420 : :
6421 [ # # ]: 0 : CHECK(n_tokens, EINVAL);
6422 : :
6423 : : /* Handle the optional instruction label. */
6424 [ # # # # ]: 0 : if ((n_tokens >= 2) && !strcmp(tokens[1], ":")) {
6425 [ # # ]: 0 : strcpy(data->label, tokens[0]);
6426 : :
6427 : : tpos += 2;
6428 [ # # ]: 0 : CHECK(n_tokens - tpos, EINVAL);
6429 : : }
6430 : :
6431 : : /* Identify the instruction type. */
6432 [ # # ]: 0 : if (!strcmp(tokens[tpos], "rx"))
6433 : 0 : return instr_rx_translate(p,
6434 : : action,
6435 : : &tokens[tpos],
6436 : : n_tokens - tpos,
6437 : : instr,
6438 : : data);
6439 : :
6440 [ # # ]: 0 : if (!strcmp(tokens[tpos], "tx"))
6441 : 0 : return instr_tx_translate(p,
6442 : : action,
6443 : : &tokens[tpos],
6444 : : n_tokens - tpos,
6445 : : instr,
6446 : : data);
6447 : :
6448 [ # # ]: 0 : if (!strcmp(tokens[tpos], "drop"))
6449 [ # # ]: 0 : return instr_drop_translate(p,
6450 : : action,
6451 : : &tokens[tpos],
6452 : : n_tokens - tpos,
6453 : : instr,
6454 : : data);
6455 : :
6456 [ # # ]: 0 : if (!strcmp(tokens[tpos], "mirror"))
6457 : 0 : return instr_mirror_translate(p,
6458 : : action,
6459 : : &tokens[tpos],
6460 : : n_tokens - tpos,
6461 : : instr,
6462 : : data);
6463 : :
6464 [ # # ]: 0 : if (!strcmp(tokens[tpos], "recirculate"))
6465 [ # # ]: 0 : return instr_recirculate_translate(p,
6466 : : action,
6467 : : &tokens[tpos],
6468 : : n_tokens - tpos,
6469 : : instr,
6470 : : data);
6471 : :
6472 [ # # ]: 0 : if (!strcmp(tokens[tpos], "recircid"))
6473 [ # # ]: 0 : return instr_recircid_translate(p,
6474 : : action,
6475 : : &tokens[tpos],
6476 : : n_tokens - tpos,
6477 : : instr,
6478 : : data);
6479 : :
6480 [ # # ]: 0 : if (!strcmp(tokens[tpos], "extract"))
6481 : 0 : return instr_hdr_extract_translate(p,
6482 : : action,
6483 : : &tokens[tpos],
6484 : : n_tokens - tpos,
6485 : : instr,
6486 : : data);
6487 : :
6488 [ # # ]: 0 : if (!strcmp(tokens[tpos], "lookahead"))
6489 : 0 : return instr_hdr_lookahead_translate(p,
6490 : : action,
6491 : : &tokens[tpos],
6492 : : n_tokens - tpos,
6493 : : instr,
6494 : : data);
6495 : :
6496 [ # # ]: 0 : if (!strcmp(tokens[tpos], "emit"))
6497 : 0 : return instr_hdr_emit_translate(p,
6498 : : action,
6499 : : &tokens[tpos],
6500 : : n_tokens - tpos,
6501 : : instr,
6502 : : data);
6503 : :
6504 [ # # ]: 0 : if (!strcmp(tokens[tpos], "validate"))
6505 [ # # ]: 0 : return instr_hdr_validate_translate(p,
6506 : : action,
6507 : : &tokens[tpos],
6508 : : n_tokens - tpos,
6509 : : instr,
6510 : : data);
6511 : :
6512 [ # # ]: 0 : if (!strcmp(tokens[tpos], "invalidate"))
6513 [ # # ]: 0 : return instr_hdr_invalidate_translate(p,
6514 : : action,
6515 : : &tokens[tpos],
6516 : : n_tokens - tpos,
6517 : : instr,
6518 : : data);
6519 : :
6520 [ # # ]: 0 : if (!strcmp(tokens[tpos], "mov"))
6521 : 0 : return instr_mov_translate(p,
6522 : : action,
6523 : : &tokens[tpos],
6524 : : n_tokens - tpos,
6525 : : instr,
6526 : : data);
6527 : :
6528 [ # # ]: 0 : if (!strcmp(tokens[tpos], "movh"))
6529 : 0 : return instr_movh_translate(p,
6530 : : action,
6531 : : &tokens[tpos],
6532 : : n_tokens - tpos,
6533 : : instr,
6534 : : data);
6535 : :
6536 [ # # ]: 0 : if (!strcmp(tokens[tpos], "add"))
6537 : 0 : return instr_alu_add_translate(p,
6538 : : action,
6539 : : &tokens[tpos],
6540 : : n_tokens - tpos,
6541 : : instr,
6542 : : data);
6543 : :
6544 [ # # ]: 0 : if (!strcmp(tokens[tpos], "sub"))
6545 : 0 : return instr_alu_sub_translate(p,
6546 : : action,
6547 : : &tokens[tpos],
6548 : : n_tokens - tpos,
6549 : : instr,
6550 : : data);
6551 : :
6552 [ # # ]: 0 : if (!strcmp(tokens[tpos], "ckadd"))
6553 : 0 : return instr_alu_ckadd_translate(p,
6554 : : action,
6555 : : &tokens[tpos],
6556 : : n_tokens - tpos,
6557 : : instr,
6558 : : data);
6559 : :
6560 [ # # ]: 0 : if (!strcmp(tokens[tpos], "cksub"))
6561 : 0 : return instr_alu_cksub_translate(p,
6562 : : action,
6563 : : &tokens[tpos],
6564 : : n_tokens - tpos,
6565 : : instr,
6566 : : data);
6567 : :
6568 [ # # ]: 0 : if (!strcmp(tokens[tpos], "and"))
6569 : 0 : return instr_alu_and_translate(p,
6570 : : action,
6571 : : &tokens[tpos],
6572 : : n_tokens - tpos,
6573 : : instr,
6574 : : data);
6575 : :
6576 [ # # ]: 0 : if (!strcmp(tokens[tpos], "or"))
6577 : 0 : return instr_alu_or_translate(p,
6578 : : action,
6579 : : &tokens[tpos],
6580 : : n_tokens - tpos,
6581 : : instr,
6582 : : data);
6583 : :
6584 [ # # ]: 0 : if (!strcmp(tokens[tpos], "xor"))
6585 : 0 : return instr_alu_xor_translate(p,
6586 : : action,
6587 : : &tokens[tpos],
6588 : : n_tokens - tpos,
6589 : : instr,
6590 : : data);
6591 : :
6592 [ # # ]: 0 : if (!strcmp(tokens[tpos], "shl"))
6593 : 0 : return instr_alu_shl_translate(p,
6594 : : action,
6595 : : &tokens[tpos],
6596 : : n_tokens - tpos,
6597 : : instr,
6598 : : data);
6599 : :
6600 [ # # ]: 0 : if (!strcmp(tokens[tpos], "shr"))
6601 : 0 : return instr_alu_shr_translate(p,
6602 : : action,
6603 : : &tokens[tpos],
6604 : : n_tokens - tpos,
6605 : : instr,
6606 : : data);
6607 : :
6608 [ # # ]: 0 : if (!strcmp(tokens[tpos], "regprefetch"))
6609 : 0 : return instr_regprefetch_translate(p,
6610 : : action,
6611 : : &tokens[tpos],
6612 : : n_tokens - tpos,
6613 : : instr,
6614 : : data);
6615 : :
6616 [ # # ]: 0 : if (!strcmp(tokens[tpos], "regrd"))
6617 : 0 : return instr_regrd_translate(p,
6618 : : action,
6619 : : &tokens[tpos],
6620 : : n_tokens - tpos,
6621 : : instr,
6622 : : data);
6623 : :
6624 [ # # ]: 0 : if (!strcmp(tokens[tpos], "regwr"))
6625 : 0 : return instr_regwr_translate(p,
6626 : : action,
6627 : : &tokens[tpos],
6628 : : n_tokens - tpos,
6629 : : instr,
6630 : : data);
6631 : :
6632 [ # # ]: 0 : if (!strcmp(tokens[tpos], "regadd"))
6633 : 0 : return instr_regadd_translate(p,
6634 : : action,
6635 : : &tokens[tpos],
6636 : : n_tokens - tpos,
6637 : : instr,
6638 : : data);
6639 : :
6640 [ # # ]: 0 : if (!strcmp(tokens[tpos], "metprefetch"))
6641 : 0 : return instr_metprefetch_translate(p,
6642 : : action,
6643 : : &tokens[tpos],
6644 : : n_tokens - tpos,
6645 : : instr,
6646 : : data);
6647 : :
6648 [ # # ]: 0 : if (!strcmp(tokens[tpos], "meter"))
6649 : 0 : return instr_meter_translate(p,
6650 : : action,
6651 : : &tokens[tpos],
6652 : : n_tokens - tpos,
6653 : : instr,
6654 : : data);
6655 : :
6656 [ # # ]: 0 : if (!strcmp(tokens[tpos], "table"))
6657 : 0 : return instr_table_translate(p,
6658 : : action,
6659 : : &tokens[tpos],
6660 : : n_tokens - tpos,
6661 : : instr,
6662 : : data);
6663 : :
6664 [ # # ]: 0 : if (!strcmp(tokens[tpos], "learn"))
6665 : 0 : return instr_learn_translate(p,
6666 : : action,
6667 : : &tokens[tpos],
6668 : : n_tokens - tpos,
6669 : : instr,
6670 : : data);
6671 [ # # ]: 0 : if (!strcmp(tokens[tpos], "rearm"))
6672 : 0 : return instr_rearm_translate(p,
6673 : : action,
6674 : : &tokens[tpos],
6675 : : n_tokens - tpos,
6676 : : instr,
6677 : : data);
6678 : :
6679 [ # # ]: 0 : if (!strcmp(tokens[tpos], "forget"))
6680 [ # # ]: 0 : return instr_forget_translate(p,
6681 : : action,
6682 : : &tokens[tpos],
6683 : : n_tokens - tpos,
6684 : : instr,
6685 : : data);
6686 : :
6687 [ # # ]: 0 : if (!strcmp(tokens[tpos], "entryid"))
6688 [ # # ]: 0 : return instr_entryid_translate(p,
6689 : : action,
6690 : : &tokens[tpos],
6691 : : n_tokens - tpos,
6692 : : instr,
6693 : : data);
6694 : :
6695 [ # # ]: 0 : if (!strcmp(tokens[tpos], "extern"))
6696 : 0 : return instr_extern_translate(p,
6697 : : action,
6698 : : &tokens[tpos],
6699 : : n_tokens - tpos,
6700 : : instr,
6701 : : data);
6702 : :
6703 [ # # ]: 0 : if (!strcmp(tokens[tpos], "hash"))
6704 : 0 : return instr_hash_translate(p,
6705 : : action,
6706 : : &tokens[tpos],
6707 : : n_tokens - tpos,
6708 : : instr,
6709 : : data);
6710 : :
6711 [ # # ]: 0 : if (!strcmp(tokens[tpos], "rss"))
6712 : 0 : return instr_rss_translate(p,
6713 : : action,
6714 : : &tokens[tpos],
6715 : : n_tokens - tpos,
6716 : : instr,
6717 : : data);
6718 : :
6719 [ # # ]: 0 : if (!strcmp(tokens[tpos], "jmp"))
6720 [ # # ]: 0 : return instr_jmp_translate(p,
6721 : : action,
6722 : : &tokens[tpos],
6723 : : n_tokens - tpos,
6724 : : instr,
6725 : : data);
6726 : :
6727 [ # # ]: 0 : if (!strcmp(tokens[tpos], "jmpv"))
6728 : 0 : return instr_jmp_valid_translate(p,
6729 : : action,
6730 : : &tokens[tpos],
6731 : : n_tokens - tpos,
6732 : : instr,
6733 : : data);
6734 : :
6735 [ # # ]: 0 : if (!strcmp(tokens[tpos], "jmpnv"))
6736 : 0 : return instr_jmp_invalid_translate(p,
6737 : : action,
6738 : : &tokens[tpos],
6739 : : n_tokens - tpos,
6740 : : instr,
6741 : : data);
6742 : :
6743 [ # # ]: 0 : if (!strcmp(tokens[tpos], "jmph"))
6744 [ # # ]: 0 : return instr_jmp_hit_translate(p,
6745 : : action,
6746 : : &tokens[tpos],
6747 : : n_tokens - tpos,
6748 : : instr,
6749 : : data);
6750 : :
6751 [ # # ]: 0 : if (!strcmp(tokens[tpos], "jmpnh"))
6752 [ # # ]: 0 : return instr_jmp_miss_translate(p,
6753 : : action,
6754 : : &tokens[tpos],
6755 : : n_tokens - tpos,
6756 : : instr,
6757 : : data);
6758 : :
6759 [ # # ]: 0 : if (!strcmp(tokens[tpos], "jmpa"))
6760 : 0 : return instr_jmp_action_hit_translate(p,
6761 : : action,
6762 : : &tokens[tpos],
6763 : : n_tokens - tpos,
6764 : : instr,
6765 : : data);
6766 : :
6767 [ # # ]: 0 : if (!strcmp(tokens[tpos], "jmpna"))
6768 : 0 : return instr_jmp_action_miss_translate(p,
6769 : : action,
6770 : : &tokens[tpos],
6771 : : n_tokens - tpos,
6772 : : instr,
6773 : : data);
6774 : :
6775 [ # # ]: 0 : if (!strcmp(tokens[tpos], "jmpeq"))
6776 : 0 : return instr_jmp_eq_translate(p,
6777 : : action,
6778 : : &tokens[tpos],
6779 : : n_tokens - tpos,
6780 : : instr,
6781 : : data);
6782 : :
6783 [ # # ]: 0 : if (!strcmp(tokens[tpos], "jmpneq"))
6784 : 0 : return instr_jmp_neq_translate(p,
6785 : : action,
6786 : : &tokens[tpos],
6787 : : n_tokens - tpos,
6788 : : instr,
6789 : : data);
6790 : :
6791 [ # # ]: 0 : if (!strcmp(tokens[tpos], "jmplt"))
6792 : 0 : return instr_jmp_lt_translate(p,
6793 : : action,
6794 : : &tokens[tpos],
6795 : : n_tokens - tpos,
6796 : : instr,
6797 : : data);
6798 : :
6799 [ # # ]: 0 : if (!strcmp(tokens[tpos], "jmpgt"))
6800 : 0 : return instr_jmp_gt_translate(p,
6801 : : action,
6802 : : &tokens[tpos],
6803 : : n_tokens - tpos,
6804 : : instr,
6805 : : data);
6806 : :
6807 [ # # ]: 0 : if (!strcmp(tokens[tpos], "return"))
6808 [ # # ]: 0 : return instr_return_translate(p,
6809 : : action,
6810 : : &tokens[tpos],
6811 : : n_tokens - tpos,
6812 : : instr,
6813 : : data);
6814 : :
6815 : : return -EINVAL;
6816 : : }
6817 : :
6818 : : static struct instruction_data *
6819 : : label_find(struct instruction_data *data, uint32_t n, const char *label)
6820 : : {
6821 : : uint32_t i;
6822 : :
6823 [ # # # # ]: 0 : for (i = 0; i < n; i++)
6824 [ # # # # ]: 0 : if (!strcmp(label, data[i].label))
6825 : : return &data[i];
6826 : :
6827 : : return NULL;
6828 : : }
6829 : :
6830 : : static uint32_t
6831 : 0 : label_is_used(struct instruction_data *data, uint32_t n, const char *label)
6832 : : {
6833 : : uint32_t count = 0, i;
6834 : :
6835 [ # # ]: 0 : if (!label[0])
6836 : : return 0;
6837 : :
6838 [ # # ]: 0 : for (i = 0; i < n; i++)
6839 [ # # ]: 0 : if (!strcmp(label, data[i].jmp_label))
6840 : 0 : count++;
6841 : :
6842 : : return count;
6843 : : }
6844 : :
6845 : : static int
6846 : 0 : instr_label_check(struct instruction_data *instruction_data,
6847 : : uint32_t n_instructions)
6848 : : {
6849 : : uint32_t i;
6850 : :
6851 : : /* Check that all instruction labels are unique. */
6852 [ # # ]: 0 : for (i = 0; i < n_instructions; i++) {
6853 : 0 : struct instruction_data *data = &instruction_data[i];
6854 : 0 : char *label = data->label;
6855 : : uint32_t j;
6856 : :
6857 [ # # ]: 0 : if (!label[0])
6858 : 0 : continue;
6859 : :
6860 [ # # ]: 0 : for (j = i + 1; j < n_instructions; j++)
6861 [ # # ]: 0 : CHECK(strcmp(label, instruction_data[j].label), EINVAL);
6862 : : }
6863 : :
6864 : : /* Check that no jump instruction (either conditional or not) can jump to itself (loop). */
6865 [ # # ]: 0 : for (i = 0; i < n_instructions; i++) {
6866 : 0 : struct instruction_data *data = &instruction_data[i];
6867 : 0 : char *label = data->label;
6868 : 0 : char *jmp_label = data->jmp_label;
6869 : :
6870 : : /* Continue if this instruction does not have a label or it is not a jump. */
6871 [ # # # # ]: 0 : if (!label[0] || !jmp_label[0])
6872 : 0 : continue;
6873 : :
6874 [ # # ]: 0 : CHECK(strcmp(label, jmp_label), EINVAL);
6875 : : }
6876 : :
6877 : : /* Get users for each instruction label. */
6878 [ # # ]: 0 : for (i = 0; i < n_instructions; i++) {
6879 : 0 : struct instruction_data *data = &instruction_data[i];
6880 : 0 : char *label = data->label;
6881 : :
6882 : 0 : data->n_users = label_is_used(instruction_data,
6883 : : n_instructions,
6884 : : label);
6885 : : }
6886 : :
6887 : : return 0;
6888 : : }
6889 : :
6890 : : static int
6891 : 0 : instr_jmp_resolve(struct instruction *instructions,
6892 : : struct instruction_data *instruction_data,
6893 : : uint32_t n_instructions)
6894 : : {
6895 : : uint32_t i;
6896 : :
6897 [ # # ]: 0 : for (i = 0; i < n_instructions; i++) {
6898 : 0 : struct instruction *instr = &instructions[i];
6899 [ # # ]: 0 : struct instruction_data *data = &instruction_data[i];
6900 : : struct instruction_data *found;
6901 : :
6902 : 0 : if (!instruction_is_jmp(instr))
6903 : 0 : continue;
6904 : :
6905 : : found = label_find(instruction_data,
6906 : : n_instructions,
6907 : 0 : data->jmp_label);
6908 [ # # ]: 0 : CHECK(found, EINVAL);
6909 : :
6910 : 0 : instr->jmp.ip = &instructions[found - instruction_data];
6911 : : }
6912 : :
6913 : : return 0;
6914 : : }
6915 : :
6916 : : static int
6917 : 0 : instr_verify(struct rte_swx_pipeline *p __rte_unused,
6918 : : struct action *a,
6919 : : struct instruction *instr,
6920 : : struct instruction_data *data __rte_unused,
6921 : : uint32_t n_instructions)
6922 : : {
6923 [ # # ]: 0 : if (!a) {
6924 : : enum instruction_type type;
6925 : : uint32_t i;
6926 : :
6927 : : /* Check that the first instruction is rx. */
6928 [ # # ]: 0 : CHECK(instr[0].type == INSTR_RX, EINVAL);
6929 : :
6930 : : /* Check that there is at least one tx instruction. */
6931 [ # # ]: 0 : for (i = 0; i < n_instructions; i++) {
6932 [ # # ]: 0 : type = instr[i].type;
6933 : :
6934 : : if (instruction_is_tx(type))
6935 : : break;
6936 : : }
6937 [ # # ]: 0 : CHECK(i < n_instructions, EINVAL);
6938 : :
6939 : : /* Check that the last instruction is either tx or unconditional
6940 : : * jump.
6941 : : */
6942 [ # # ]: 0 : type = instr[n_instructions - 1].type;
6943 [ # # ]: 0 : CHECK(instruction_is_tx(type) || (type == INSTR_JMP), EINVAL);
6944 : : }
6945 : :
6946 [ # # ]: 0 : if (a) {
6947 : : enum instruction_type type;
6948 : : uint32_t i;
6949 : :
6950 : : /* Check that there is at least one return or tx instruction. */
6951 [ # # ]: 0 : for (i = 0; i < n_instructions; i++) {
6952 : 0 : type = instr[i].type;
6953 : :
6954 [ # # ]: 0 : if ((type == INSTR_RETURN) || instruction_is_tx(type))
6955 : : break;
6956 : : }
6957 [ # # ]: 0 : CHECK(i < n_instructions, EINVAL);
6958 : : }
6959 : :
6960 : : return 0;
6961 : : }
6962 : :
6963 : : static uint32_t
6964 : 0 : instr_compact(struct instruction *instructions,
6965 : : struct instruction_data *instruction_data,
6966 : : uint32_t n_instructions)
6967 : : {
6968 : : uint32_t i, pos = 0;
6969 : :
6970 : : /* Eliminate the invalid instructions that have been optimized out. */
6971 [ # # ]: 0 : for (i = 0; i < n_instructions; i++) {
6972 : 0 : struct instruction *instr = &instructions[i];
6973 : 0 : struct instruction_data *data = &instruction_data[i];
6974 : :
6975 [ # # ]: 0 : if (data->invalid)
6976 : 0 : continue;
6977 : :
6978 [ # # ]: 0 : if (i != pos) {
6979 : 0 : memcpy(&instructions[pos], instr, sizeof(*instr));
6980 : 0 : memcpy(&instruction_data[pos], data, sizeof(*data));
6981 : : }
6982 : :
6983 : 0 : pos++;
6984 : : }
6985 : :
6986 : 0 : return pos;
6987 : : }
6988 : :
6989 : : static int
6990 : 0 : instr_pattern_extract_many_search(struct instruction *instr,
6991 : : struct instruction_data *data,
6992 : : uint32_t n_instr,
6993 : : uint32_t *n_pattern_instr)
6994 : : {
6995 : : uint32_t i;
6996 : :
6997 [ # # ]: 0 : for (i = 0; i < n_instr; i++) {
6998 [ # # ]: 0 : if (data[i].invalid)
6999 : : break;
7000 : :
7001 [ # # ]: 0 : if (instr[i].type != INSTR_HDR_EXTRACT)
7002 : : break;
7003 : :
7004 [ # # ]: 0 : if (i == RTE_DIM(instr->io.hdr.header_id))
7005 : : break;
7006 : :
7007 [ # # # # ]: 0 : if (i && data[i].n_users)
7008 : : break;
7009 : : }
7010 : :
7011 [ # # ]: 0 : if (i < 2)
7012 : : return 0;
7013 : :
7014 : 0 : *n_pattern_instr = i;
7015 : 0 : return 1;
7016 : : }
7017 : :
7018 : : static void
7019 : : instr_pattern_extract_many_replace(struct instruction *instr,
7020 : : struct instruction_data *data,
7021 : : uint32_t n_instr)
7022 : : {
7023 : : uint32_t i;
7024 : :
7025 [ # # ]: 0 : for (i = 1; i < n_instr; i++) {
7026 : 0 : instr[0].type++;
7027 : 0 : instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
7028 : 0 : instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
7029 : 0 : instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
7030 : :
7031 : 0 : data[i].invalid = 1;
7032 : : }
7033 : : }
7034 : :
7035 : : static uint32_t
7036 : 0 : instr_pattern_extract_many_optimize(struct instruction *instructions,
7037 : : struct instruction_data *instruction_data,
7038 : : uint32_t n_instructions)
7039 : : {
7040 : : uint32_t i;
7041 : :
7042 [ # # ]: 0 : for (i = 0; i < n_instructions; ) {
7043 : 0 : struct instruction *instr = &instructions[i];
7044 : 0 : struct instruction_data *data = &instruction_data[i];
7045 : 0 : uint32_t n_instr = 0;
7046 : : int detected;
7047 : :
7048 : : /* Extract many. */
7049 : 0 : detected = instr_pattern_extract_many_search(instr,
7050 : : data,
7051 : : n_instructions - i,
7052 : : &n_instr);
7053 [ # # ]: 0 : if (detected) {
7054 : 0 : instr_pattern_extract_many_replace(instr,
7055 : : data,
7056 : : n_instr);
7057 : 0 : i += n_instr;
7058 : 0 : continue;
7059 : : }
7060 : :
7061 : : /* No pattern starting at the current instruction. */
7062 : 0 : i++;
7063 : : }
7064 : :
7065 : : /* Eliminate the invalid instructions that have been optimized out. */
7066 : 0 : n_instructions = instr_compact(instructions,
7067 : : instruction_data,
7068 : : n_instructions);
7069 : :
7070 : 0 : return n_instructions;
7071 : : }
7072 : :
7073 : : static int
7074 : 0 : instr_pattern_emit_many_tx_search(struct instruction *instr,
7075 : : struct instruction_data *data,
7076 : : uint32_t n_instr,
7077 : : uint32_t *n_pattern_instr)
7078 : : {
7079 : : uint32_t i;
7080 : :
7081 [ # # ]: 0 : for (i = 0; i < n_instr; i++) {
7082 [ # # ]: 0 : if (data[i].invalid)
7083 : : break;
7084 : :
7085 [ # # ]: 0 : if (instr[i].type != INSTR_HDR_EMIT)
7086 : : break;
7087 : :
7088 [ # # ]: 0 : if (i == RTE_DIM(instr->io.hdr.header_id))
7089 : : break;
7090 : :
7091 [ # # # # ]: 0 : if (i && data[i].n_users)
7092 : : break;
7093 : : }
7094 : :
7095 [ # # ]: 0 : if (!i)
7096 : : return 0;
7097 : :
7098 [ # # ]: 0 : if (instr[i].type != INSTR_TX)
7099 : : return 0;
7100 : :
7101 [ # # ]: 0 : if (data[i].n_users)
7102 : : return 0;
7103 : :
7104 : 0 : i++;
7105 : :
7106 : 0 : *n_pattern_instr = i;
7107 : 0 : return 1;
7108 : : }
7109 : :
7110 : : static void
7111 : 0 : instr_pattern_emit_many_tx_replace(struct instruction *instr,
7112 : : struct instruction_data *data,
7113 : : uint32_t n_instr)
7114 : : {
7115 : : uint32_t i;
7116 : :
7117 : : /* Any emit instruction in addition to the first one. */
7118 [ # # ]: 0 : for (i = 1; i < n_instr - 1; i++) {
7119 : 0 : instr[0].type++;
7120 : 0 : instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
7121 : 0 : instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
7122 : 0 : instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
7123 : :
7124 : 0 : data[i].invalid = 1;
7125 : : }
7126 : :
7127 : : /* The TX instruction is the last one in the pattern. */
7128 : 0 : instr[0].type++;
7129 : 0 : instr[0].io.io.offset = instr[i].io.io.offset;
7130 : 0 : instr[0].io.io.n_bits = instr[i].io.io.n_bits;
7131 : 0 : data[i].invalid = 1;
7132 : 0 : }
7133 : :
7134 : : static uint32_t
7135 : 0 : instr_pattern_emit_many_tx_optimize(struct instruction *instructions,
7136 : : struct instruction_data *instruction_data,
7137 : : uint32_t n_instructions)
7138 : : {
7139 : : uint32_t i;
7140 : :
7141 [ # # ]: 0 : for (i = 0; i < n_instructions; ) {
7142 : 0 : struct instruction *instr = &instructions[i];
7143 : 0 : struct instruction_data *data = &instruction_data[i];
7144 : 0 : uint32_t n_instr = 0;
7145 : : int detected;
7146 : :
7147 : : /* Emit many + TX. */
7148 : 0 : detected = instr_pattern_emit_many_tx_search(instr,
7149 : : data,
7150 : : n_instructions - i,
7151 : : &n_instr);
7152 [ # # ]: 0 : if (detected) {
7153 : 0 : instr_pattern_emit_many_tx_replace(instr,
7154 : : data,
7155 : : n_instr);
7156 : 0 : i += n_instr;
7157 : 0 : continue;
7158 : : }
7159 : :
7160 : : /* No pattern starting at the current instruction. */
7161 : 0 : i++;
7162 : : }
7163 : :
7164 : : /* Eliminate the invalid instructions that have been optimized out. */
7165 : 0 : n_instructions = instr_compact(instructions,
7166 : : instruction_data,
7167 : : n_instructions);
7168 : :
7169 : 0 : return n_instructions;
7170 : : }
7171 : :
7172 : : static uint32_t
7173 : : action_arg_src_mov_count(struct action *a,
7174 : : uint32_t arg_id,
7175 : : struct instruction *instructions,
7176 : : struct instruction_data *instruction_data,
7177 : : uint32_t n_instructions);
7178 : :
7179 : : static int
7180 : 0 : instr_pattern_validate_mov_all_search(struct rte_swx_pipeline *p,
7181 : : struct action *a,
7182 : : struct instruction *instr,
7183 : : struct instruction_data *data,
7184 : : uint32_t n_instr,
7185 : : struct instruction *instructions,
7186 : : struct instruction_data *instruction_data,
7187 : : uint32_t n_instructions,
7188 : : uint32_t *n_pattern_instr)
7189 : : {
7190 : : struct header *h;
7191 : : uint32_t src_field_id, i, j;
7192 : :
7193 : : /* Prerequisites. */
7194 [ # # # # ]: 0 : if (!a || !a->st)
7195 : : return 0;
7196 : :
7197 : : /* First instruction: HDR_VALIDATE. Second instruction: MOV_HM, MOV_DMA or MOV_128. */
7198 [ # # ]: 0 : if (data[0].invalid ||
7199 [ # # # # ]: 0 : (instr[0].type != INSTR_HDR_VALIDATE) ||
7200 : 0 : (n_instr < 2) ||
7201 [ # # ]: 0 : data[1].invalid ||
7202 [ # # ]: 0 : (instr[1].type != INSTR_MOV_HM &&
7203 [ # # ]: 0 : instr[1].type != INSTR_MOV_DMA &&
7204 : 0 : instr[1].type != INSTR_MOV_128) ||
7205 [ # # ]: 0 : instr[1].mov.src.struct_id)
7206 : : return 0;
7207 : :
7208 : 0 : h = header_find_by_struct_id(p, instr[0].valid.struct_id);
7209 [ # # ]: 0 : if (!h ||
7210 [ # # ]: 0 : h->st->var_size ||
7211 [ # # ]: 0 : (n_instr < 1 + h->st->n_fields))
7212 : : return 0;
7213 : :
7214 [ # # ]: 0 : for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
7215 [ # # ]: 0 : if (instr[1].mov.src.offset == a->st->fields[src_field_id].offset / 8)
7216 : : break;
7217 : :
7218 [ # # ]: 0 : if (src_field_id + h->st->n_fields > a->st->n_fields)
7219 : : return 0;
7220 : :
7221 : : /* Second and subsequent instructions: MOV_HM. */
7222 [ # # ]: 0 : for (i = 0; i < h->st->n_fields; i++)
7223 [ # # ]: 0 : if (data[1 + i].invalid ||
7224 [ # # ]: 0 : data[1 + i].n_users ||
7225 [ # # ]: 0 : (instr[1 + i].type != INSTR_MOV_HM &&
7226 [ # # ]: 0 : instr[1 + i].type != INSTR_MOV_DMA &&
7227 : 0 : instr[1 + i].type != INSTR_MOV_128) ||
7228 [ # # ]: 0 : (instr[1 + i].mov.dst.struct_id != h->struct_id) ||
7229 [ # # ]: 0 : (instr[1 + i].mov.dst.offset != h->st->fields[i].offset / 8) ||
7230 [ # # ]: 0 : (instr[1 + i].mov.dst.n_bits != h->st->fields[i].n_bits) ||
7231 [ # # ]: 0 : instr[1 + i].mov.src.struct_id ||
7232 [ # # ]: 0 : (instr[1 + i].mov.src.offset != a->st->fields[src_field_id + i].offset / 8) ||
7233 [ # # # # ]: 0 : (instr[1 + i].mov.src.n_bits != a->st->fields[src_field_id + i].n_bits) ||
7234 : : (instr[1 + i].mov.dst.n_bits != instr[1 + i].mov.src.n_bits))
7235 : : return 0;
7236 : :
7237 : : /* Check that none of the action args that are used as source for this
7238 : : * DMA transfer are not used as source in any other mov instruction.
7239 : : */
7240 [ # # ]: 0 : for (j = src_field_id; j < src_field_id + h->st->n_fields; j++) {
7241 : : uint32_t n_users;
7242 : :
7243 : 0 : n_users = action_arg_src_mov_count(a,
7244 : : j,
7245 : : instructions,
7246 : : instruction_data,
7247 : : n_instructions);
7248 [ # # ]: 0 : if (n_users > 1)
7249 : : return 0;
7250 : : }
7251 : :
7252 : 0 : *n_pattern_instr = 1 + h->st->n_fields;
7253 : 0 : return 1;
7254 : : }
7255 : :
7256 : : static void
7257 : 0 : instr_pattern_validate_mov_all_replace(struct rte_swx_pipeline *p,
7258 : : struct action *a,
7259 : : struct instruction *instr,
7260 : : struct instruction_data *data,
7261 : : uint32_t n_instr)
7262 : : {
7263 : : struct header *h;
7264 : : uint32_t src_field_id, src_offset, i;
7265 : :
7266 : : /* Read from the instructions before they are modified. */
7267 : 0 : h = header_find_by_struct_id(p, instr[1].mov.dst.struct_id);
7268 [ # # ]: 0 : if (!h)
7269 : : return;
7270 : :
7271 : 0 : src_offset = instr[1].mov.src.offset;
7272 : :
7273 [ # # ]: 0 : for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
7274 [ # # ]: 0 : if (src_offset == a->st->fields[src_field_id].offset / 8)
7275 : : break;
7276 : :
7277 : : /* Modify the instructions. */
7278 : 0 : instr[0].type = INSTR_DMA_HT;
7279 : 0 : instr[0].dma.dst.header_id[0] = h->id;
7280 : 0 : instr[0].dma.dst.struct_id[0] = h->struct_id;
7281 : 0 : instr[0].dma.src.offset[0] = (uint8_t)src_offset;
7282 : 0 : instr[0].dma.n_bytes[0] = h->st->n_bits / 8;
7283 : :
7284 [ # # ]: 0 : for (i = 1; i < n_instr; i++)
7285 : 0 : data[i].invalid = 1;
7286 : :
7287 : : /* Update the endianness of the action arguments to header endianness. */
7288 [ # # ]: 0 : for (i = 0; i < h->st->n_fields; i++)
7289 : 0 : a->args_endianness[src_field_id + i] = 1;
7290 : : }
7291 : :
7292 : : static uint32_t
7293 : 0 : instr_pattern_validate_mov_all_optimize(struct rte_swx_pipeline *p,
7294 : : struct action *a,
7295 : : struct instruction *instructions,
7296 : : struct instruction_data *instruction_data,
7297 : : uint32_t n_instructions)
7298 : : {
7299 : : uint32_t i;
7300 : :
7301 [ # # # # ]: 0 : if (!a || !a->st)
7302 : : return n_instructions;
7303 : :
7304 [ # # ]: 0 : for (i = 0; i < n_instructions; ) {
7305 : 0 : struct instruction *instr = &instructions[i];
7306 : 0 : struct instruction_data *data = &instruction_data[i];
7307 : 0 : uint32_t n_instr = 0;
7308 : : int detected;
7309 : :
7310 : : /* Validate + mov all. */
7311 : 0 : detected = instr_pattern_validate_mov_all_search(p,
7312 : : a,
7313 : : instr,
7314 : : data,
7315 : : n_instructions - i,
7316 : : instructions,
7317 : : instruction_data,
7318 : : n_instructions,
7319 : : &n_instr);
7320 [ # # ]: 0 : if (detected) {
7321 : 0 : instr_pattern_validate_mov_all_replace(p, a, instr, data, n_instr);
7322 : 0 : i += n_instr;
7323 : 0 : continue;
7324 : : }
7325 : :
7326 : : /* No pattern starting at the current instruction. */
7327 : 0 : i++;
7328 : : }
7329 : :
7330 : : /* Eliminate the invalid instructions that have been optimized out. */
7331 : 0 : n_instructions = instr_compact(instructions,
7332 : : instruction_data,
7333 : : n_instructions);
7334 : :
7335 : 0 : return n_instructions;
7336 : : }
7337 : :
7338 : : static int
7339 : 0 : instr_pattern_dma_many_search(struct instruction *instr,
7340 : : struct instruction_data *data,
7341 : : uint32_t n_instr,
7342 : : uint32_t *n_pattern_instr)
7343 : : {
7344 : : uint32_t i;
7345 : :
7346 [ # # ]: 0 : for (i = 0; i < n_instr; i++) {
7347 [ # # ]: 0 : if (data[i].invalid)
7348 : : break;
7349 : :
7350 [ # # ]: 0 : if (instr[i].type != INSTR_DMA_HT)
7351 : : break;
7352 : :
7353 [ # # ]: 0 : if (i == RTE_DIM(instr->dma.dst.header_id))
7354 : : break;
7355 : :
7356 [ # # # # ]: 0 : if (i && data[i].n_users)
7357 : : break;
7358 : : }
7359 : :
7360 [ # # ]: 0 : if (i < 2)
7361 : : return 0;
7362 : :
7363 : 0 : *n_pattern_instr = i;
7364 : 0 : return 1;
7365 : : }
7366 : :
7367 : : static void
7368 : 0 : instr_pattern_dma_many_replace(struct instruction *instr,
7369 : : struct instruction_data *data,
7370 : : uint32_t n_instr)
7371 : : {
7372 : : uint32_t i;
7373 : :
7374 [ # # ]: 0 : for (i = 1; i < n_instr; i++) {
7375 : 0 : instr[0].type++;
7376 : 0 : instr[0].dma.dst.header_id[i] = instr[i].dma.dst.header_id[0];
7377 : 0 : instr[0].dma.dst.struct_id[i] = instr[i].dma.dst.struct_id[0];
7378 : 0 : instr[0].dma.src.offset[i] = instr[i].dma.src.offset[0];
7379 : 0 : instr[0].dma.n_bytes[i] = instr[i].dma.n_bytes[0];
7380 : :
7381 : 0 : data[i].invalid = 1;
7382 : : }
7383 : 0 : }
7384 : :
7385 : : static uint32_t
7386 : 0 : instr_pattern_dma_many_optimize(struct instruction *instructions,
7387 : : struct instruction_data *instruction_data,
7388 : : uint32_t n_instructions)
7389 : : {
7390 : : uint32_t i;
7391 : :
7392 [ # # ]: 0 : for (i = 0; i < n_instructions; ) {
7393 : 0 : struct instruction *instr = &instructions[i];
7394 : 0 : struct instruction_data *data = &instruction_data[i];
7395 : 0 : uint32_t n_instr = 0;
7396 : : int detected;
7397 : :
7398 : : /* DMA many. */
7399 : 0 : detected = instr_pattern_dma_many_search(instr,
7400 : : data,
7401 : : n_instructions - i,
7402 : : &n_instr);
7403 [ # # ]: 0 : if (detected) {
7404 : 0 : instr_pattern_dma_many_replace(instr, data, n_instr);
7405 : 0 : i += n_instr;
7406 : 0 : continue;
7407 : : }
7408 : :
7409 : : /* No pattern starting at the current instruction. */
7410 : 0 : i++;
7411 : : }
7412 : :
7413 : : /* Eliminate the invalid instructions that have been optimized out. */
7414 : 0 : n_instructions = instr_compact(instructions,
7415 : : instruction_data,
7416 : : n_instructions);
7417 : :
7418 : 0 : return n_instructions;
7419 : : }
7420 : :
7421 : : static uint32_t
7422 : 0 : instr_optimize(struct rte_swx_pipeline *p,
7423 : : struct action *a,
7424 : : struct instruction *instructions,
7425 : : struct instruction_data *instruction_data,
7426 : : uint32_t n_instructions)
7427 : : {
7428 : : /* Extract many. */
7429 : 0 : n_instructions = instr_pattern_extract_many_optimize(instructions,
7430 : : instruction_data,
7431 : : n_instructions);
7432 : :
7433 : : /* Emit many + TX. */
7434 : 0 : n_instructions = instr_pattern_emit_many_tx_optimize(instructions,
7435 : : instruction_data,
7436 : : n_instructions);
7437 : :
7438 : : /* Validate + mov all. */
7439 : 0 : n_instructions = instr_pattern_validate_mov_all_optimize(p,
7440 : : a,
7441 : : instructions,
7442 : : instruction_data,
7443 : : n_instructions);
7444 : :
7445 : : /* DMA many. */
7446 : 0 : n_instructions = instr_pattern_dma_many_optimize(instructions,
7447 : : instruction_data,
7448 : : n_instructions);
7449 : :
7450 : 0 : return n_instructions;
7451 : : }
7452 : :
7453 : : static int
7454 : 0 : instruction_config(struct rte_swx_pipeline *p,
7455 : : struct action *a,
7456 : : const char **instructions,
7457 : : uint32_t n_instructions)
7458 : : {
7459 : : struct instruction *instr = NULL;
7460 : : struct instruction_data *data = NULL;
7461 : : int err = 0;
7462 : : uint32_t i;
7463 : :
7464 [ # # ]: 0 : CHECK(n_instructions, EINVAL);
7465 [ # # ]: 0 : CHECK(instructions, EINVAL);
7466 [ # # ]: 0 : for (i = 0; i < n_instructions; i++)
7467 [ # # # # : 0 : CHECK_INSTRUCTION(instructions[i], EINVAL);
# # ]
7468 : :
7469 : : /* Memory allocation. */
7470 : 0 : instr = calloc(n_instructions, sizeof(struct instruction));
7471 [ # # ]: 0 : if (!instr) {
7472 : : err = -ENOMEM;
7473 : 0 : goto error;
7474 : : }
7475 : :
7476 : 0 : data = calloc(n_instructions, sizeof(struct instruction_data));
7477 [ # # ]: 0 : if (!data) {
7478 : : err = -ENOMEM;
7479 : 0 : goto error;
7480 : : }
7481 : :
7482 [ # # ]: 0 : for (i = 0; i < n_instructions; i++) {
7483 : 0 : char *string = strdup(instructions[i]);
7484 [ # # ]: 0 : if (!string) {
7485 : : err = -ENOMEM;
7486 : 0 : goto error;
7487 : : }
7488 : :
7489 : 0 : err = instr_translate(p, a, string, &instr[i], &data[i]);
7490 [ # # ]: 0 : if (err) {
7491 : 0 : free(string);
7492 : 0 : goto error;
7493 : : }
7494 : :
7495 : 0 : free(string);
7496 : : }
7497 : :
7498 : 0 : err = instr_label_check(data, n_instructions);
7499 [ # # ]: 0 : if (err)
7500 : 0 : goto error;
7501 : :
7502 : 0 : err = instr_verify(p, a, instr, data, n_instructions);
7503 [ # # ]: 0 : if (err)
7504 : 0 : goto error;
7505 : :
7506 : 0 : n_instructions = instr_optimize(p, a, instr, data, n_instructions);
7507 : :
7508 : 0 : err = instr_jmp_resolve(instr, data, n_instructions);
7509 [ # # ]: 0 : if (err)
7510 : 0 : goto error;
7511 : :
7512 [ # # ]: 0 : if (a) {
7513 : 0 : a->instructions = instr;
7514 : 0 : a->instruction_data = data;
7515 : 0 : a->n_instructions = n_instructions;
7516 : : } else {
7517 : 0 : p->instructions = instr;
7518 : 0 : p->instruction_data = data;
7519 : 0 : p->n_instructions = n_instructions;
7520 : : }
7521 : :
7522 : : return 0;
7523 : :
7524 : 0 : error:
7525 : 0 : free(data);
7526 : 0 : free(instr);
7527 : 0 : return err;
7528 : : }
7529 : :
7530 : : static instr_exec_t instruction_table[] = {
7531 : : [INSTR_RX] = instr_rx_exec,
7532 : : [INSTR_TX] = instr_tx_exec,
7533 : : [INSTR_TX_I] = instr_tx_i_exec,
7534 : : [INSTR_DROP] = instr_drop_exec,
7535 : : [INSTR_MIRROR] = instr_mirror_exec,
7536 : : [INSTR_RECIRCULATE] = instr_recirculate_exec,
7537 : : [INSTR_RECIRCID] = instr_recircid_exec,
7538 : :
7539 : : [INSTR_HDR_EXTRACT] = instr_hdr_extract_exec,
7540 : : [INSTR_HDR_EXTRACT2] = instr_hdr_extract2_exec,
7541 : : [INSTR_HDR_EXTRACT3] = instr_hdr_extract3_exec,
7542 : : [INSTR_HDR_EXTRACT4] = instr_hdr_extract4_exec,
7543 : : [INSTR_HDR_EXTRACT5] = instr_hdr_extract5_exec,
7544 : : [INSTR_HDR_EXTRACT6] = instr_hdr_extract6_exec,
7545 : : [INSTR_HDR_EXTRACT7] = instr_hdr_extract7_exec,
7546 : : [INSTR_HDR_EXTRACT8] = instr_hdr_extract8_exec,
7547 : : [INSTR_HDR_EXTRACT_M] = instr_hdr_extract_m_exec,
7548 : : [INSTR_HDR_LOOKAHEAD] = instr_hdr_lookahead_exec,
7549 : :
7550 : : [INSTR_HDR_EMIT] = instr_hdr_emit_exec,
7551 : : [INSTR_HDR_EMIT_TX] = instr_hdr_emit_tx_exec,
7552 : : [INSTR_HDR_EMIT2_TX] = instr_hdr_emit2_tx_exec,
7553 : : [INSTR_HDR_EMIT3_TX] = instr_hdr_emit3_tx_exec,
7554 : : [INSTR_HDR_EMIT4_TX] = instr_hdr_emit4_tx_exec,
7555 : : [INSTR_HDR_EMIT5_TX] = instr_hdr_emit5_tx_exec,
7556 : : [INSTR_HDR_EMIT6_TX] = instr_hdr_emit6_tx_exec,
7557 : : [INSTR_HDR_EMIT7_TX] = instr_hdr_emit7_tx_exec,
7558 : : [INSTR_HDR_EMIT8_TX] = instr_hdr_emit8_tx_exec,
7559 : :
7560 : : [INSTR_HDR_VALIDATE] = instr_hdr_validate_exec,
7561 : : [INSTR_HDR_INVALIDATE] = instr_hdr_invalidate_exec,
7562 : :
7563 : : [INSTR_MOV] = instr_mov_exec,
7564 : : [INSTR_MOV_MH] = instr_mov_mh_exec,
7565 : : [INSTR_MOV_HM] = instr_mov_hm_exec,
7566 : : [INSTR_MOV_HH] = instr_mov_hh_exec,
7567 : : [INSTR_MOV_DMA] = instr_mov_dma_exec,
7568 : : [INSTR_MOV_128] = instr_mov_128_exec,
7569 : : [INSTR_MOV_128_64] = instr_mov_128_64_exec,
7570 : : [INSTR_MOV_64_128] = instr_mov_64_128_exec,
7571 : : [INSTR_MOV_128_32] = instr_mov_128_32_exec,
7572 : : [INSTR_MOV_32_128] = instr_mov_32_128_exec,
7573 : : [INSTR_MOV_I] = instr_mov_i_exec,
7574 : :
7575 : : [INSTR_MOVH] = instr_movh_exec,
7576 : :
7577 : : [INSTR_DMA_HT] = instr_dma_ht_exec,
7578 : : [INSTR_DMA_HT2] = instr_dma_ht2_exec,
7579 : : [INSTR_DMA_HT3] = instr_dma_ht3_exec,
7580 : : [INSTR_DMA_HT4] = instr_dma_ht4_exec,
7581 : : [INSTR_DMA_HT5] = instr_dma_ht5_exec,
7582 : : [INSTR_DMA_HT6] = instr_dma_ht6_exec,
7583 : : [INSTR_DMA_HT7] = instr_dma_ht7_exec,
7584 : : [INSTR_DMA_HT8] = instr_dma_ht8_exec,
7585 : :
7586 : : [INSTR_ALU_ADD] = instr_alu_add_exec,
7587 : : [INSTR_ALU_ADD_MH] = instr_alu_add_mh_exec,
7588 : : [INSTR_ALU_ADD_HM] = instr_alu_add_hm_exec,
7589 : : [INSTR_ALU_ADD_HH] = instr_alu_add_hh_exec,
7590 : : [INSTR_ALU_ADD_MI] = instr_alu_add_mi_exec,
7591 : : [INSTR_ALU_ADD_HI] = instr_alu_add_hi_exec,
7592 : :
7593 : : [INSTR_ALU_SUB] = instr_alu_sub_exec,
7594 : : [INSTR_ALU_SUB_MH] = instr_alu_sub_mh_exec,
7595 : : [INSTR_ALU_SUB_HM] = instr_alu_sub_hm_exec,
7596 : : [INSTR_ALU_SUB_HH] = instr_alu_sub_hh_exec,
7597 : : [INSTR_ALU_SUB_MI] = instr_alu_sub_mi_exec,
7598 : : [INSTR_ALU_SUB_HI] = instr_alu_sub_hi_exec,
7599 : :
7600 : : [INSTR_ALU_CKADD_FIELD] = instr_alu_ckadd_field_exec,
7601 : : [INSTR_ALU_CKADD_STRUCT] = instr_alu_ckadd_struct_exec,
7602 : : [INSTR_ALU_CKADD_STRUCT20] = instr_alu_ckadd_struct20_exec,
7603 : : [INSTR_ALU_CKSUB_FIELD] = instr_alu_cksub_field_exec,
7604 : :
7605 : : [INSTR_ALU_AND] = instr_alu_and_exec,
7606 : : [INSTR_ALU_AND_MH] = instr_alu_and_mh_exec,
7607 : : [INSTR_ALU_AND_HM] = instr_alu_and_hm_exec,
7608 : : [INSTR_ALU_AND_HH] = instr_alu_and_hh_exec,
7609 : : [INSTR_ALU_AND_I] = instr_alu_and_i_exec,
7610 : :
7611 : : [INSTR_ALU_OR] = instr_alu_or_exec,
7612 : : [INSTR_ALU_OR_MH] = instr_alu_or_mh_exec,
7613 : : [INSTR_ALU_OR_HM] = instr_alu_or_hm_exec,
7614 : : [INSTR_ALU_OR_HH] = instr_alu_or_hh_exec,
7615 : : [INSTR_ALU_OR_I] = instr_alu_or_i_exec,
7616 : :
7617 : : [INSTR_ALU_XOR] = instr_alu_xor_exec,
7618 : : [INSTR_ALU_XOR_MH] = instr_alu_xor_mh_exec,
7619 : : [INSTR_ALU_XOR_HM] = instr_alu_xor_hm_exec,
7620 : : [INSTR_ALU_XOR_HH] = instr_alu_xor_hh_exec,
7621 : : [INSTR_ALU_XOR_I] = instr_alu_xor_i_exec,
7622 : :
7623 : : [INSTR_ALU_SHL] = instr_alu_shl_exec,
7624 : : [INSTR_ALU_SHL_MH] = instr_alu_shl_mh_exec,
7625 : : [INSTR_ALU_SHL_HM] = instr_alu_shl_hm_exec,
7626 : : [INSTR_ALU_SHL_HH] = instr_alu_shl_hh_exec,
7627 : : [INSTR_ALU_SHL_MI] = instr_alu_shl_mi_exec,
7628 : : [INSTR_ALU_SHL_HI] = instr_alu_shl_hi_exec,
7629 : :
7630 : : [INSTR_ALU_SHR] = instr_alu_shr_exec,
7631 : : [INSTR_ALU_SHR_MH] = instr_alu_shr_mh_exec,
7632 : : [INSTR_ALU_SHR_HM] = instr_alu_shr_hm_exec,
7633 : : [INSTR_ALU_SHR_HH] = instr_alu_shr_hh_exec,
7634 : : [INSTR_ALU_SHR_MI] = instr_alu_shr_mi_exec,
7635 : : [INSTR_ALU_SHR_HI] = instr_alu_shr_hi_exec,
7636 : :
7637 : : [INSTR_REGPREFETCH_RH] = instr_regprefetch_rh_exec,
7638 : : [INSTR_REGPREFETCH_RM] = instr_regprefetch_rm_exec,
7639 : : [INSTR_REGPREFETCH_RI] = instr_regprefetch_ri_exec,
7640 : :
7641 : : [INSTR_REGRD_HRH] = instr_regrd_hrh_exec,
7642 : : [INSTR_REGRD_HRM] = instr_regrd_hrm_exec,
7643 : : [INSTR_REGRD_MRH] = instr_regrd_mrh_exec,
7644 : : [INSTR_REGRD_MRM] = instr_regrd_mrm_exec,
7645 : : [INSTR_REGRD_HRI] = instr_regrd_hri_exec,
7646 : : [INSTR_REGRD_MRI] = instr_regrd_mri_exec,
7647 : :
7648 : : [INSTR_REGWR_RHH] = instr_regwr_rhh_exec,
7649 : : [INSTR_REGWR_RHM] = instr_regwr_rhm_exec,
7650 : : [INSTR_REGWR_RMH] = instr_regwr_rmh_exec,
7651 : : [INSTR_REGWR_RMM] = instr_regwr_rmm_exec,
7652 : : [INSTR_REGWR_RHI] = instr_regwr_rhi_exec,
7653 : : [INSTR_REGWR_RMI] = instr_regwr_rmi_exec,
7654 : : [INSTR_REGWR_RIH] = instr_regwr_rih_exec,
7655 : : [INSTR_REGWR_RIM] = instr_regwr_rim_exec,
7656 : : [INSTR_REGWR_RII] = instr_regwr_rii_exec,
7657 : :
7658 : : [INSTR_REGADD_RHH] = instr_regadd_rhh_exec,
7659 : : [INSTR_REGADD_RHM] = instr_regadd_rhm_exec,
7660 : : [INSTR_REGADD_RMH] = instr_regadd_rmh_exec,
7661 : : [INSTR_REGADD_RMM] = instr_regadd_rmm_exec,
7662 : : [INSTR_REGADD_RHI] = instr_regadd_rhi_exec,
7663 : : [INSTR_REGADD_RMI] = instr_regadd_rmi_exec,
7664 : : [INSTR_REGADD_RIH] = instr_regadd_rih_exec,
7665 : : [INSTR_REGADD_RIM] = instr_regadd_rim_exec,
7666 : : [INSTR_REGADD_RII] = instr_regadd_rii_exec,
7667 : :
7668 : : [INSTR_METPREFETCH_H] = instr_metprefetch_h_exec,
7669 : : [INSTR_METPREFETCH_M] = instr_metprefetch_m_exec,
7670 : : [INSTR_METPREFETCH_I] = instr_metprefetch_i_exec,
7671 : :
7672 : : [INSTR_METER_HHM] = instr_meter_hhm_exec,
7673 : : [INSTR_METER_HHI] = instr_meter_hhi_exec,
7674 : : [INSTR_METER_HMM] = instr_meter_hmm_exec,
7675 : : [INSTR_METER_HMI] = instr_meter_hmi_exec,
7676 : : [INSTR_METER_MHM] = instr_meter_mhm_exec,
7677 : : [INSTR_METER_MHI] = instr_meter_mhi_exec,
7678 : : [INSTR_METER_MMM] = instr_meter_mmm_exec,
7679 : : [INSTR_METER_MMI] = instr_meter_mmi_exec,
7680 : : [INSTR_METER_IHM] = instr_meter_ihm_exec,
7681 : : [INSTR_METER_IHI] = instr_meter_ihi_exec,
7682 : : [INSTR_METER_IMM] = instr_meter_imm_exec,
7683 : : [INSTR_METER_IMI] = instr_meter_imi_exec,
7684 : :
7685 : : [INSTR_TABLE] = instr_table_exec,
7686 : : [INSTR_TABLE_AF] = instr_table_af_exec,
7687 : : [INSTR_SELECTOR] = instr_selector_exec,
7688 : : [INSTR_LEARNER] = instr_learner_exec,
7689 : : [INSTR_LEARNER_AF] = instr_learner_af_exec,
7690 : : [INSTR_LEARNER_LEARN] = instr_learn_exec,
7691 : : [INSTR_LEARNER_REARM] = instr_rearm_exec,
7692 : : [INSTR_LEARNER_REARM_NEW] = instr_rearm_new_exec,
7693 : : [INSTR_LEARNER_FORGET] = instr_forget_exec,
7694 : : [INSTR_ENTRYID] = instr_entryid_exec,
7695 : :
7696 : : [INSTR_EXTERN_OBJ] = instr_extern_obj_exec,
7697 : : [INSTR_EXTERN_FUNC] = instr_extern_func_exec,
7698 : : [INSTR_HASH_FUNC] = instr_hash_func_exec,
7699 : : [INSTR_RSS] = instr_rss_exec,
7700 : :
7701 : : [INSTR_JMP] = instr_jmp_exec,
7702 : : [INSTR_JMP_VALID] = instr_jmp_valid_exec,
7703 : : [INSTR_JMP_INVALID] = instr_jmp_invalid_exec,
7704 : : [INSTR_JMP_HIT] = instr_jmp_hit_exec,
7705 : : [INSTR_JMP_MISS] = instr_jmp_miss_exec,
7706 : : [INSTR_JMP_ACTION_HIT] = instr_jmp_action_hit_exec,
7707 : : [INSTR_JMP_ACTION_MISS] = instr_jmp_action_miss_exec,
7708 : :
7709 : : [INSTR_JMP_EQ] = instr_jmp_eq_exec,
7710 : : [INSTR_JMP_EQ_MH] = instr_jmp_eq_mh_exec,
7711 : : [INSTR_JMP_EQ_HM] = instr_jmp_eq_hm_exec,
7712 : : [INSTR_JMP_EQ_HH] = instr_jmp_eq_hh_exec,
7713 : : [INSTR_JMP_EQ_I] = instr_jmp_eq_i_exec,
7714 : :
7715 : : [INSTR_JMP_NEQ] = instr_jmp_neq_exec,
7716 : : [INSTR_JMP_NEQ_MH] = instr_jmp_neq_mh_exec,
7717 : : [INSTR_JMP_NEQ_HM] = instr_jmp_neq_hm_exec,
7718 : : [INSTR_JMP_NEQ_HH] = instr_jmp_neq_hh_exec,
7719 : : [INSTR_JMP_NEQ_I] = instr_jmp_neq_i_exec,
7720 : :
7721 : : [INSTR_JMP_LT] = instr_jmp_lt_exec,
7722 : : [INSTR_JMP_LT_MH] = instr_jmp_lt_mh_exec,
7723 : : [INSTR_JMP_LT_HM] = instr_jmp_lt_hm_exec,
7724 : : [INSTR_JMP_LT_HH] = instr_jmp_lt_hh_exec,
7725 : : [INSTR_JMP_LT_MI] = instr_jmp_lt_mi_exec,
7726 : : [INSTR_JMP_LT_HI] = instr_jmp_lt_hi_exec,
7727 : :
7728 : : [INSTR_JMP_GT] = instr_jmp_gt_exec,
7729 : : [INSTR_JMP_GT_MH] = instr_jmp_gt_mh_exec,
7730 : : [INSTR_JMP_GT_HM] = instr_jmp_gt_hm_exec,
7731 : : [INSTR_JMP_GT_HH] = instr_jmp_gt_hh_exec,
7732 : : [INSTR_JMP_GT_MI] = instr_jmp_gt_mi_exec,
7733 : : [INSTR_JMP_GT_HI] = instr_jmp_gt_hi_exec,
7734 : :
7735 : : [INSTR_RETURN] = instr_return_exec,
7736 : : };
7737 : :
7738 : : static int
7739 : 0 : instruction_table_build(struct rte_swx_pipeline *p)
7740 : : {
7741 : 0 : p->instruction_table = calloc(RTE_SWX_PIPELINE_INSTRUCTION_TABLE_SIZE_MAX,
7742 : : sizeof(struct instr_exec_t *));
7743 [ # # ]: 0 : if (!p->instruction_table)
7744 : : return -EINVAL;
7745 : :
7746 : : memcpy(p->instruction_table, instruction_table, sizeof(instruction_table));
7747 : :
7748 : 0 : return 0;
7749 : : }
7750 : :
7751 : : static void
7752 : : instruction_table_build_free(struct rte_swx_pipeline *p)
7753 : : {
7754 [ # # ]: 0 : if (!p->instruction_table)
7755 : : return;
7756 : :
7757 : 0 : free(p->instruction_table);
7758 : 0 : p->instruction_table = NULL;
7759 : : }
7760 : :
7761 : : static void
7762 : : instruction_table_free(struct rte_swx_pipeline *p)
7763 : : {
7764 : : instruction_table_build_free(p);
7765 : : }
7766 : :
7767 : : static inline void
7768 : : instr_exec(struct rte_swx_pipeline *p)
7769 : : {
7770 : 0 : struct thread *t = &p->threads[p->thread_id];
7771 : 0 : struct instruction *ip = t->ip;
7772 : 0 : instr_exec_t instr = p->instruction_table[ip->type];
7773 : :
7774 : 0 : instr(p);
7775 : : }
7776 : :
7777 : : /*
7778 : : * Action.
7779 : : */
7780 : : static struct action *
7781 : 0 : action_find(struct rte_swx_pipeline *p, const char *name)
7782 : : {
7783 : : struct action *elem;
7784 : :
7785 [ # # ]: 0 : if (!name)
7786 : : return NULL;
7787 : :
7788 [ # # ]: 0 : TAILQ_FOREACH(elem, &p->actions, node)
7789 [ # # ]: 0 : if (strcmp(elem->name, name) == 0)
7790 : 0 : return elem;
7791 : :
7792 : : return NULL;
7793 : : }
7794 : :
7795 : : static struct action *
7796 : : action_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7797 : : {
7798 : : struct action *action = NULL;
7799 : :
7800 [ # # # # ]: 0 : TAILQ_FOREACH(action, &p->actions, node)
7801 [ # # # # ]: 0 : if (action->id == id)
7802 : : return action;
7803 : :
7804 : : return NULL;
7805 : : }
7806 : :
7807 : : static struct field *
7808 : : action_field_find(struct action *a, const char *name)
7809 : : {
7810 : 0 : return a->st ? struct_type_field_find(a->st, name) : NULL;
7811 : : }
7812 : :
7813 : : static struct field *
7814 : 0 : action_field_parse(struct action *action, const char *name)
7815 : : {
7816 [ # # # # ]: 0 : if (name[0] != 't' || name[1] != '.')
7817 : : return NULL;
7818 : :
7819 [ # # ]: 0 : return action_field_find(action, &name[2]);
7820 : : }
7821 : :
7822 : : static int
7823 : : action_has_nbo_args(struct action *a)
7824 : : {
7825 : : uint32_t i;
7826 : :
7827 : : /* Return if the action does not have any args. */
7828 [ # # ]: 0 : if (!a->st)
7829 : : return 0; /* FALSE */
7830 : :
7831 [ # # ]: 0 : for (i = 0; i < a->st->n_fields; i++)
7832 [ # # ]: 0 : if (a->args_endianness[i])
7833 : : return 1; /* TRUE */
7834 : :
7835 : : return 0; /* FALSE */
7836 : : }
7837 : :
7838 : : static int
7839 : : action_does_learning(struct action *a)
7840 : : {
7841 : : uint32_t i;
7842 : :
7843 [ # # ]: 0 : for (i = 0; i < a->n_instructions; i++)
7844 [ # # ]: 0 : switch (a->instructions[i].type) {
7845 : : case INSTR_LEARNER_LEARN:
7846 : : return 1; /* TRUE */
7847 : :
7848 : : case INSTR_LEARNER_FORGET:
7849 : : return 1; /* TRUE */
7850 : :
7851 : 0 : default:
7852 : : continue;
7853 : : }
7854 : :
7855 : : return 0; /* FALSE */
7856 : : }
7857 : :
7858 : : int
7859 : 0 : rte_swx_pipeline_action_config(struct rte_swx_pipeline *p,
7860 : : const char *name,
7861 : : const char *args_struct_type_name,
7862 : : const char **instructions,
7863 : : uint32_t n_instructions)
7864 : : {
7865 : : struct struct_type *args_struct_type = NULL;
7866 : : struct action *a = NULL;
7867 : : int status = 0;
7868 : :
7869 [ # # ]: 0 : CHECK(p, EINVAL);
7870 : :
7871 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
7872 [ # # ]: 0 : CHECK(!action_find(p, name), EEXIST);
7873 : :
7874 [ # # ]: 0 : if (args_struct_type_name) {
7875 [ # # # # ]: 0 : CHECK_NAME(args_struct_type_name, EINVAL);
7876 : : args_struct_type = struct_type_find(p, args_struct_type_name);
7877 [ # # ]: 0 : CHECK(args_struct_type, EINVAL);
7878 [ # # ]: 0 : CHECK(!args_struct_type->var_size, EINVAL);
7879 : : }
7880 : :
7881 : : /* Node allocation. */
7882 : 0 : a = calloc(1, sizeof(struct action));
7883 [ # # ]: 0 : if (!a) {
7884 : : status = -ENOMEM;
7885 : 0 : goto error;
7886 : : }
7887 : :
7888 [ # # ]: 0 : if (args_struct_type) {
7889 : 0 : a->args_endianness = calloc(args_struct_type->n_fields, sizeof(int));
7890 [ # # ]: 0 : if (!a->args_endianness) {
7891 : : status = -ENOMEM;
7892 : 0 : goto error;
7893 : : }
7894 : : }
7895 : :
7896 : : /* Node initialization. */
7897 : 0 : strcpy(a->name, name);
7898 : 0 : a->st = args_struct_type;
7899 : 0 : a->id = p->n_actions;
7900 : :
7901 : : /* Instruction translation. */
7902 : 0 : status = instruction_config(p, a, instructions, n_instructions);
7903 [ # # ]: 0 : if (status)
7904 : 0 : goto error;
7905 : :
7906 : : /* Node add to tailq. */
7907 : 0 : TAILQ_INSERT_TAIL(&p->actions, a, node);
7908 : 0 : p->n_actions++;
7909 : :
7910 : 0 : return 0;
7911 : :
7912 : 0 : error:
7913 [ # # ]: 0 : if (!a)
7914 : : return status;
7915 : :
7916 : 0 : free(a->args_endianness);
7917 : 0 : free(a->instructions);
7918 : 0 : free(a->instruction_data);
7919 : 0 : free(a);
7920 : :
7921 : 0 : return status;
7922 : : }
7923 : :
7924 : : static int
7925 : 0 : action_build(struct rte_swx_pipeline *p)
7926 : : {
7927 : : struct action *action;
7928 : :
7929 : : /* p->action_instructions. */
7930 : 0 : p->action_instructions = calloc(p->n_actions, sizeof(struct instruction *));
7931 [ # # ]: 0 : CHECK(p->action_instructions, ENOMEM);
7932 : :
7933 [ # # ]: 0 : TAILQ_FOREACH(action, &p->actions, node)
7934 : 0 : p->action_instructions[action->id] = action->instructions;
7935 : :
7936 : : /* p->action_funcs. */
7937 : 0 : p->action_funcs = calloc(p->n_actions, sizeof(action_func_t));
7938 [ # # ]: 0 : CHECK(p->action_funcs, ENOMEM);
7939 : :
7940 : : return 0;
7941 : : }
7942 : :
7943 : : static void
7944 : : action_build_free(struct rte_swx_pipeline *p)
7945 : : {
7946 : 0 : free(p->action_funcs);
7947 : 0 : p->action_funcs = NULL;
7948 : :
7949 : 0 : free(p->action_instructions);
7950 [ # # ]: 0 : p->action_instructions = NULL;
7951 : 0 : }
7952 : :
7953 : : static void
7954 : 0 : action_free(struct rte_swx_pipeline *p)
7955 : : {
7956 : : action_build_free(p);
7957 : :
7958 : 0 : for ( ; ; ) {
7959 : : struct action *action;
7960 : :
7961 : 0 : action = TAILQ_FIRST(&p->actions);
7962 [ # # ]: 0 : if (!action)
7963 : : break;
7964 : :
7965 [ # # ]: 0 : TAILQ_REMOVE(&p->actions, action, node);
7966 : 0 : free(action->args_endianness);
7967 : 0 : free(action->instructions);
7968 : 0 : free(action->instruction_data);
7969 : 0 : free(action);
7970 : : }
7971 : 0 : }
7972 : :
7973 : : static uint32_t
7974 : 0 : action_arg_src_mov_count(struct action *a,
7975 : : uint32_t arg_id,
7976 : : struct instruction *instructions,
7977 : : struct instruction_data *instruction_data,
7978 : : uint32_t n_instructions)
7979 : : {
7980 : : uint32_t offset, n_users = 0, i;
7981 : :
7982 [ # # ]: 0 : if (!a->st ||
7983 [ # # ]: 0 : (arg_id >= a->st->n_fields) ||
7984 : 0 : !instructions ||
7985 [ # # # # ]: 0 : !instruction_data ||
7986 : : !n_instructions)
7987 : : return 0;
7988 : :
7989 : 0 : offset = a->st->fields[arg_id].offset / 8;
7990 : :
7991 [ # # ]: 0 : for (i = 0; i < n_instructions; i++) {
7992 : 0 : struct instruction *instr = &instructions[i];
7993 : 0 : struct instruction_data *data = &instruction_data[i];
7994 : :
7995 [ # # ]: 0 : if (data->invalid ||
7996 [ # # ]: 0 : ((instr->type != INSTR_MOV) && (instr->type != INSTR_MOV_HM)) ||
7997 [ # # ]: 0 : instr->mov.src.struct_id ||
7998 [ # # ]: 0 : (instr->mov.src.offset != offset))
7999 : 0 : continue;
8000 : :
8001 : 0 : n_users++;
8002 : : }
8003 : :
8004 : : return n_users;
8005 : : }
8006 : :
8007 : : static int
8008 : : char_to_hex(char c, uint8_t *val)
8009 : : {
8010 : 0 : if (c >= '0' && c <= '9') {
8011 : : *val = c - '0';
8012 : : return 0;
8013 : : }
8014 : :
8015 [ # # # # ]: 0 : if (c >= 'A' && c <= 'F') {
8016 : 0 : *val = c - 'A' + 10;
8017 : : return 0;
8018 : : }
8019 : :
8020 [ # # # # ]: 0 : if (c >= 'a' && c <= 'f') {
8021 : 0 : *val = c - 'a' + 10;
8022 : : return 0;
8023 : : }
8024 : :
8025 : : return -EINVAL;
8026 : : }
8027 : :
8028 : : static int
8029 : 0 : hex_string_parse(char *src, uint8_t *dst, uint32_t n_dst_bytes)
8030 : : {
8031 : : uint32_t i;
8032 : :
8033 : : /* Check input arguments. */
8034 [ # # # # : 0 : if (!src || !src[0] || !dst || !n_dst_bytes)
# # ]
8035 : : return -EINVAL;
8036 : :
8037 : : /* Skip any leading "0x" or "0X" in the src string. */
8038 [ # # # # ]: 0 : if ((src[0] == '0') && (src[1] == 'x' || src[1] == 'X'))
8039 : 0 : src += 2;
8040 : :
8041 : : /* Convert each group of two hex characters in the src string to one byte in dst array. */
8042 [ # # ]: 0 : for (i = 0; i < n_dst_bytes; i++) {
8043 : : uint8_t a, b;
8044 : : int status;
8045 : :
8046 [ # # ]: 0 : status = char_to_hex(*src, &a);
8047 : : if (status)
8048 : : return status;
8049 : : src++;
8050 : :
8051 [ # # ]: 0 : status = char_to_hex(*src, &b);
8052 : : if (status)
8053 : : return status;
8054 : 0 : src++;
8055 : :
8056 : 0 : dst[i] = a * 16 + b;
8057 : : }
8058 : :
8059 : : /* Check for the end of the src string. */
8060 [ # # ]: 0 : if (*src)
8061 : 0 : return -EINVAL;
8062 : :
8063 : : return 0;
8064 : : }
8065 : :
8066 : : #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
8067 : : #define field_ntoh(val, n_bits) (ntoh64((val) << (64 - n_bits)))
8068 : : #define field_hton(val, n_bits) (hton64((val) << (64 - n_bits)))
8069 : : #else
8070 : : #define field_ntoh(val, n_bits) (val)
8071 : : #define field_hton(val, n_bits) (val)
8072 : : #endif
8073 : :
8074 : : #define ACTION_ARGS_TOKENS_MAX 256
8075 : :
8076 : : static int
8077 : 0 : action_args_parse(struct action *a, const char *args, uint8_t *data)
8078 : : {
8079 : : char *tokens[ACTION_ARGS_TOKENS_MAX], *s0 = NULL, *s;
8080 : : uint32_t n_tokens = 0, offset = 0, i;
8081 : : int status = 0;
8082 : :
8083 : : /* Checks. */
8084 [ # # # # : 0 : if (!a->st || !args || !args[0]) {
# # ]
8085 : : status = -EINVAL;
8086 : 0 : goto error;
8087 : : }
8088 : :
8089 : : /* Memory allocation. */
8090 : 0 : s0 = strdup(args);
8091 [ # # ]: 0 : if (!s0) {
8092 : : status = -ENOMEM;
8093 : 0 : goto error;
8094 : : }
8095 : :
8096 : : /* Parse the string into tokens. */
8097 : 0 : for (s = s0; ; ) {
8098 : : char *token;
8099 : :
8100 : 0 : token = strtok_r(s, " \f\n\r\t\v", &s);
8101 [ # # ]: 0 : if (!token)
8102 : : break;
8103 : :
8104 [ # # ]: 0 : if (n_tokens >= RTE_DIM(tokens)) {
8105 : : status = -EINVAL;
8106 : 0 : goto error;
8107 : : }
8108 : :
8109 : 0 : tokens[n_tokens] = token;
8110 : 0 : n_tokens++;
8111 : : }
8112 : :
8113 : : /* More checks. */
8114 [ # # ]: 0 : if (n_tokens != a->st->n_fields * 2) {
8115 : : status = -EINVAL;
8116 : 0 : goto error;
8117 : : }
8118 : :
8119 : : /* Process the action arguments. */
8120 [ # # ]: 0 : for (i = 0; i < a->st->n_fields; i++) {
8121 : 0 : struct field *f = &a->st->fields[i];
8122 : 0 : char *arg_name = tokens[i * 2];
8123 : 0 : char *arg_val = tokens[i * 2 + 1];
8124 : :
8125 [ # # ]: 0 : if (strcmp(arg_name, f->name)) {
8126 : : status = -EINVAL;
8127 : 0 : goto error;
8128 : : }
8129 : :
8130 [ # # ]: 0 : if (f->n_bits <= 64) {
8131 : : uint64_t val;
8132 : :
8133 : 0 : val = strtoull(arg_val, &arg_val, 0);
8134 [ # # ]: 0 : if (arg_val[0]) {
8135 : : status = -EINVAL;
8136 : 0 : goto error;
8137 : : }
8138 : :
8139 : : /* Endianness conversion. */
8140 [ # # ]: 0 : if (a->args_endianness[i])
8141 [ # # ]: 0 : val = field_hton(val, f->n_bits);
8142 : :
8143 : : /* Copy to entry. */
8144 : 0 : memcpy(&data[offset], (uint8_t *)&val, f->n_bits / 8);
8145 : : } else {
8146 : 0 : status = hex_string_parse(arg_val, &data[offset], f->n_bits / 8);
8147 [ # # ]: 0 : if (status)
8148 : 0 : goto error;
8149 : : }
8150 : :
8151 : 0 : offset += f->n_bits / 8;
8152 : : }
8153 : :
8154 : 0 : error:
8155 : 0 : free(s0);
8156 : 0 : return status;
8157 : : }
8158 : :
8159 : : /*
8160 : : * Table.
8161 : : */
8162 : : static struct table_type *
8163 : : table_type_find(struct rte_swx_pipeline *p, const char *name)
8164 : : {
8165 : : struct table_type *elem;
8166 : :
8167 [ # # ]: 0 : TAILQ_FOREACH(elem, &p->table_types, node)
8168 [ # # ]: 0 : if (strcmp(elem->name, name) == 0)
8169 : : return elem;
8170 : :
8171 : : return NULL;
8172 : : }
8173 : :
8174 : : static struct table_type *
8175 : 0 : table_type_resolve(struct rte_swx_pipeline *p,
8176 : : const char *recommended_type_name,
8177 : : enum rte_swx_table_match_type match_type)
8178 : : {
8179 : : struct table_type *elem;
8180 : :
8181 : : /* Only consider the recommended type if the match type is correct. */
8182 [ # # ]: 0 : if (recommended_type_name)
8183 [ # # ]: 0 : TAILQ_FOREACH(elem, &p->table_types, node)
8184 [ # # ]: 0 : if (!strcmp(elem->name, recommended_type_name) &&
8185 [ # # ]: 0 : (elem->match_type == match_type))
8186 : 0 : return elem;
8187 : :
8188 : : /* Ignore the recommended type and get the first element with this match
8189 : : * type.
8190 : : */
8191 [ # # ]: 0 : TAILQ_FOREACH(elem, &p->table_types, node)
8192 [ # # ]: 0 : if (elem->match_type == match_type)
8193 : 0 : return elem;
8194 : :
8195 : : return NULL;
8196 : : }
8197 : :
8198 : : static struct table *
8199 : : table_find(struct rte_swx_pipeline *p, const char *name)
8200 : : {
8201 : : struct table *elem;
8202 : :
8203 [ # # # # : 0 : TAILQ_FOREACH(elem, &p->tables, node)
# # # # #
# # # #
# ]
8204 [ # # # # : 0 : if (strcmp(elem->name, name) == 0)
# # # # #
# # # #
# ]
8205 : : return elem;
8206 : :
8207 : : return NULL;
8208 : : }
8209 : :
8210 : : static struct table *
8211 : : table_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8212 : : {
8213 : : struct table *table = NULL;
8214 : :
8215 [ # # # # : 0 : TAILQ_FOREACH(table, &p->tables, node)
# # # # #
# ]
8216 [ # # # # : 0 : if (table->id == id)
# # # # #
# ]
8217 : : return table;
8218 : :
8219 : : return NULL;
8220 : : }
8221 : :
8222 : : int
8223 : 0 : rte_swx_pipeline_table_type_register(struct rte_swx_pipeline *p,
8224 : : const char *name,
8225 : : enum rte_swx_table_match_type match_type,
8226 : : struct rte_swx_table_ops *ops)
8227 : : {
8228 : : struct table_type *elem;
8229 : :
8230 [ # # ]: 0 : CHECK(p, EINVAL);
8231 : :
8232 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
8233 [ # # ]: 0 : CHECK(!table_type_find(p, name), EEXIST);
8234 : :
8235 [ # # ]: 0 : CHECK(ops, EINVAL);
8236 [ # # ]: 0 : CHECK(ops->create, EINVAL);
8237 [ # # ]: 0 : CHECK(ops->lkp, EINVAL);
8238 [ # # ]: 0 : CHECK(ops->free, EINVAL);
8239 : :
8240 : : /* Node allocation. */
8241 : 0 : elem = calloc(1, sizeof(struct table_type));
8242 [ # # ]: 0 : CHECK(elem, ENOMEM);
8243 : :
8244 : : /* Node initialization. */
8245 : 0 : strcpy(elem->name, name);
8246 : 0 : elem->match_type = match_type;
8247 : 0 : memcpy(&elem->ops, ops, sizeof(*ops));
8248 : :
8249 : : /* Node add to tailq. */
8250 : 0 : TAILQ_INSERT_TAIL(&p->table_types, elem, node);
8251 : :
8252 : 0 : return 0;
8253 : : }
8254 : :
8255 : : static int
8256 : 0 : table_match_type_resolve(struct rte_swx_match_field_params *fields,
8257 : : uint32_t n_fields,
8258 : : int contiguous_fields,
8259 : : enum rte_swx_table_match_type *match_type)
8260 : : {
8261 : : uint32_t n_fields_em = 0, n_fields_lpm = 0, i;
8262 : :
8263 [ # # ]: 0 : for (i = 0; i < n_fields; i++) {
8264 : 0 : struct rte_swx_match_field_params *f = &fields[i];
8265 : :
8266 [ # # ]: 0 : if (f->match_type == RTE_SWX_TABLE_MATCH_EXACT)
8267 : 0 : n_fields_em++;
8268 : :
8269 [ # # ]: 0 : if (f->match_type == RTE_SWX_TABLE_MATCH_LPM)
8270 : 0 : n_fields_lpm++;
8271 : : }
8272 : :
8273 [ # # # # ]: 0 : if ((n_fields_lpm > 1) ||
8274 [ # # ]: 0 : (n_fields_lpm && (n_fields_em != n_fields - 1)))
8275 : : return -EINVAL;
8276 : :
8277 : 0 : *match_type = ((n_fields_em == n_fields) && contiguous_fields) ?
8278 [ # # ]: 0 : RTE_SWX_TABLE_MATCH_EXACT :
8279 : : RTE_SWX_TABLE_MATCH_WILDCARD;
8280 : :
8281 : 0 : return 0;
8282 : : }
8283 : :
8284 : : static int
8285 : 0 : table_match_fields_check(struct rte_swx_pipeline *p,
8286 : : struct rte_swx_pipeline_table_params *params,
8287 : : struct header **header,
8288 : : int *contiguous_fields)
8289 : : {
8290 : 0 : struct header *h0 = NULL;
8291 : : struct field *hf, *mf;
8292 : : uint32_t *offset = NULL, *n_bits = NULL, n_fields_with_valid_next = 0, i;
8293 : : int status = 0;
8294 : :
8295 : : /* Return if no match fields. */
8296 [ # # ]: 0 : if (!params->n_fields) {
8297 [ # # ]: 0 : if (params->fields) {
8298 : : status = -EINVAL;
8299 : 0 : goto end;
8300 : : }
8301 : :
8302 [ # # ]: 0 : if (header)
8303 : 0 : *header = NULL;
8304 : :
8305 [ # # ]: 0 : if (contiguous_fields)
8306 : 0 : *contiguous_fields = 0;
8307 : :
8308 : 0 : return 0;
8309 : : }
8310 : :
8311 : : /* Memory allocation. */
8312 : 0 : offset = calloc(params->n_fields, sizeof(uint32_t));
8313 : 0 : n_bits = calloc(params->n_fields, sizeof(uint32_t));
8314 [ # # ]: 0 : if (!offset || !n_bits) {
8315 : : status = -ENOMEM;
8316 : 0 : goto end;
8317 : : }
8318 : :
8319 : : /* Check that all the match fields belong to either the same header or
8320 : : * to the meta-data.
8321 : : */
8322 : 0 : hf = header_field_parse(p, params->fields[0].name, &h0);
8323 : 0 : mf = metadata_field_parse(p, params->fields[0].name);
8324 [ # # # # : 0 : if ((!hf && !mf) || (hf && hf->var_size)) {
# # ]
8325 : : status = -EINVAL;
8326 : 0 : goto end;
8327 : : }
8328 : :
8329 [ # # ]: 0 : offset[0] = h0 ? hf->offset : mf->offset;
8330 [ # # ]: 0 : n_bits[0] = h0 ? hf->n_bits : mf->n_bits;
8331 : :
8332 [ # # ]: 0 : for (i = 1; i < params->n_fields; i++)
8333 [ # # ]: 0 : if (h0) {
8334 : : struct header *h;
8335 : :
8336 : 0 : hf = header_field_parse(p, params->fields[i].name, &h);
8337 [ # # # # : 0 : if (!hf || (h->id != h0->id) || hf->var_size) {
# # ]
8338 : : status = -EINVAL;
8339 : 0 : goto end;
8340 : : }
8341 : :
8342 : 0 : offset[i] = hf->offset;
8343 : 0 : n_bits[i] = hf->n_bits;
8344 : : } else {
8345 : 0 : mf = metadata_field_parse(p, params->fields[i].name);
8346 [ # # ]: 0 : if (!mf) {
8347 : : status = -EINVAL;
8348 : 0 : goto end;
8349 : : }
8350 : :
8351 : 0 : offset[i] = mf->offset;
8352 : 0 : n_bits[i] = mf->n_bits;
8353 : : }
8354 : :
8355 : : /* Check that there are no duplicated match fields. */
8356 [ # # ]: 0 : for (i = 0; i < params->n_fields; i++) {
8357 : : uint32_t j;
8358 : :
8359 [ # # ]: 0 : for (j = 0; j < i; j++)
8360 [ # # ]: 0 : if (offset[j] == offset[i]) {
8361 : : status = -EINVAL;
8362 : 0 : goto end;
8363 : : }
8364 : : }
8365 : :
8366 : : /* Detect if the match fields are contiguous or not. */
8367 [ # # ]: 0 : for (i = 0; i < params->n_fields; i++) {
8368 : 0 : uint32_t offset_next = offset[i] + n_bits[i];
8369 : : uint32_t j;
8370 : :
8371 [ # # ]: 0 : for (j = 0; j < params->n_fields; j++)
8372 [ # # ]: 0 : if (offset[j] == offset_next) {
8373 : 0 : n_fields_with_valid_next++;
8374 : 0 : break;
8375 : : }
8376 : : }
8377 : :
8378 : : /* Return. */
8379 [ # # ]: 0 : if (header)
8380 : 0 : *header = h0;
8381 : :
8382 [ # # ]: 0 : if (contiguous_fields)
8383 : 0 : *contiguous_fields = (n_fields_with_valid_next == params->n_fields - 1) ? 1 : 0;
8384 : :
8385 : 0 : end:
8386 : 0 : free(offset);
8387 : 0 : free(n_bits);
8388 : 0 : return status;
8389 : : }
8390 : :
8391 : : int
8392 : 0 : rte_swx_pipeline_table_config(struct rte_swx_pipeline *p,
8393 : : const char *name,
8394 : : struct rte_swx_pipeline_table_params *params,
8395 : : const char *recommended_table_type_name,
8396 : : const char *args,
8397 : : uint32_t size)
8398 : : {
8399 : : struct table_type *type = NULL;
8400 : : struct table *t = NULL;
8401 : : struct action *default_action;
8402 : 0 : struct header *header = NULL;
8403 : : struct hash_func *hf = NULL;
8404 : : uint32_t action_data_size_max = 0, i;
8405 : 0 : int contiguous_fields = 0, status = 0;
8406 : :
8407 [ # # ]: 0 : CHECK(p, EINVAL);
8408 : :
8409 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
8410 [ # # ]: 0 : CHECK(!table_find(p, name), EEXIST);
8411 [ # # ]: 0 : CHECK(!selector_find(p, name), EEXIST);
8412 [ # # ]: 0 : CHECK(!learner_find(p, name), EEXIST);
8413 : :
8414 [ # # ]: 0 : CHECK(params, EINVAL);
8415 : :
8416 : : /* Match checks. */
8417 : 0 : status = table_match_fields_check(p, params, &header, &contiguous_fields);
8418 [ # # ]: 0 : if (status)
8419 : : return status;
8420 : :
8421 : : /* Action checks. */
8422 [ # # ]: 0 : CHECK(params->n_actions, EINVAL);
8423 [ # # ]: 0 : CHECK(params->action_names, EINVAL);
8424 [ # # ]: 0 : for (i = 0; i < params->n_actions; i++) {
8425 : 0 : const char *action_name = params->action_names[i];
8426 : : struct action *a;
8427 : : uint32_t action_data_size;
8428 : : int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
8429 : :
8430 [ # # # # : 0 : CHECK_NAME(action_name, EINVAL);
# # ]
8431 : :
8432 : 0 : a = action_find(p, action_name);
8433 [ # # ]: 0 : CHECK(a, EINVAL);
8434 [ # # ]: 0 : CHECK(!action_does_learning(a), EINVAL);
8435 : :
8436 [ # # ]: 0 : action_data_size = a->st ? a->st->n_bits / 8 : 0;
8437 : : if (action_data_size > action_data_size_max)
8438 : : action_data_size_max = action_data_size;
8439 : :
8440 [ # # ]: 0 : if (params->action_is_for_table_entries)
8441 : 0 : action_is_for_table_entries = params->action_is_for_table_entries[i];
8442 [ # # ]: 0 : if (params->action_is_for_default_entry)
8443 : 0 : action_is_for_default_entry = params->action_is_for_default_entry[i];
8444 [ # # ]: 0 : CHECK(action_is_for_table_entries || action_is_for_default_entry, EINVAL);
8445 : : }
8446 : :
8447 [ # # # # : 0 : CHECK_NAME(params->default_action_name, EINVAL);
# # ]
8448 [ # # ]: 0 : for (i = 0; i < p->n_actions; i++)
8449 [ # # ]: 0 : if (!strcmp(params->action_names[i],
8450 : : params->default_action_name))
8451 : : break;
8452 [ # # ]: 0 : CHECK(i < params->n_actions, EINVAL);
8453 [ # # # # ]: 0 : CHECK(!params->action_is_for_default_entry || params->action_is_for_default_entry[i],
8454 : : EINVAL);
8455 : :
8456 : 0 : default_action = action_find(p, params->default_action_name);
8457 [ # # # # ]: 0 : CHECK((default_action->st && params->default_action_args) || !params->default_action_args,
8458 : : EINVAL);
8459 : :
8460 : : /* Hash function checks. */
8461 [ # # ]: 0 : if (params->hash_func_name) {
8462 : : hf = hash_func_find(p, params->hash_func_name);
8463 [ # # ]: 0 : CHECK(hf, EINVAL);
8464 : : }
8465 : :
8466 : : /* Table type checks. */
8467 [ # # ]: 0 : if (recommended_table_type_name)
8468 [ # # # # ]: 0 : CHECK_NAME(recommended_table_type_name, EINVAL);
8469 : :
8470 [ # # ]: 0 : if (params->n_fields) {
8471 : : enum rte_swx_table_match_type match_type;
8472 : :
8473 : 0 : status = table_match_type_resolve(params->fields,
8474 : : params->n_fields,
8475 : : contiguous_fields,
8476 : : &match_type);
8477 [ # # ]: 0 : if (status)
8478 : 0 : return status;
8479 : :
8480 : 0 : type = table_type_resolve(p, recommended_table_type_name, match_type);
8481 [ # # ]: 0 : CHECK(type, EINVAL);
8482 : : }
8483 : :
8484 : : /* Memory allocation. */
8485 : 0 : t = calloc(1, sizeof(struct table));
8486 [ # # ]: 0 : if (!t) {
8487 : : status = -ENOMEM;
8488 : 0 : goto error;
8489 : : }
8490 : :
8491 : 0 : t->fields = calloc(params->n_fields, sizeof(struct match_field));
8492 [ # # ]: 0 : if (!t->fields) {
8493 : : status = -ENOMEM;
8494 : 0 : goto error;
8495 : : }
8496 : :
8497 : 0 : t->actions = calloc(params->n_actions, sizeof(struct action *));
8498 [ # # ]: 0 : if (!t->actions) {
8499 : : status = -ENOMEM;
8500 : 0 : goto error;
8501 : : }
8502 : :
8503 [ # # ]: 0 : if (action_data_size_max) {
8504 : 0 : t->default_action_data = calloc(1, action_data_size_max);
8505 [ # # ]: 0 : if (!t->default_action_data) {
8506 : : status = -ENOMEM;
8507 : 0 : goto error;
8508 : : }
8509 : : }
8510 : :
8511 : 0 : t->action_is_for_table_entries = calloc(params->n_actions, sizeof(int));
8512 [ # # ]: 0 : if (!t->action_is_for_table_entries) {
8513 : : status = -ENOMEM;
8514 : 0 : goto error;
8515 : : }
8516 : :
8517 : 0 : t->action_is_for_default_entry = calloc(params->n_actions, sizeof(int));
8518 [ # # ]: 0 : if (!t->action_is_for_default_entry) {
8519 : : status = -ENOMEM;
8520 : 0 : goto error;
8521 : : }
8522 : :
8523 : : /* Node initialization. */
8524 [ # # ]: 0 : strcpy(t->name, name);
8525 [ # # # # ]: 0 : if (args && args[0])
8526 : 0 : strcpy(t->args, args);
8527 : 0 : t->type = type;
8528 : :
8529 [ # # ]: 0 : for (i = 0; i < params->n_fields; i++) {
8530 : 0 : struct rte_swx_match_field_params *field = ¶ms->fields[i];
8531 : 0 : struct match_field *f = &t->fields[i];
8532 : :
8533 : 0 : f->match_type = field->match_type;
8534 : 0 : f->field = header ?
8535 [ # # ]: 0 : header_field_parse(p, field->name, NULL) :
8536 : 0 : metadata_field_parse(p, field->name);
8537 : : }
8538 : 0 : t->n_fields = params->n_fields;
8539 : 0 : t->header = header;
8540 : :
8541 [ # # ]: 0 : for (i = 0; i < params->n_actions; i++) {
8542 : : int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
8543 : :
8544 [ # # ]: 0 : if (params->action_is_for_table_entries)
8545 : 0 : action_is_for_table_entries = params->action_is_for_table_entries[i];
8546 [ # # ]: 0 : if (params->action_is_for_default_entry)
8547 : 0 : action_is_for_default_entry = params->action_is_for_default_entry[i];
8548 : :
8549 : 0 : t->actions[i] = action_find(p, params->action_names[i]);
8550 : 0 : t->action_is_for_table_entries[i] = action_is_for_table_entries;
8551 : 0 : t->action_is_for_default_entry[i] = action_is_for_default_entry;
8552 : : }
8553 : 0 : t->default_action = default_action;
8554 [ # # ]: 0 : if (default_action->st) {
8555 : 0 : status = action_args_parse(default_action,
8556 : : params->default_action_args,
8557 : : t->default_action_data);
8558 [ # # ]: 0 : if (status)
8559 : 0 : goto error;
8560 : : }
8561 : :
8562 : 0 : t->n_actions = params->n_actions;
8563 : 0 : t->default_action_is_const = params->default_action_is_const;
8564 : 0 : t->action_data_size_max = action_data_size_max;
8565 : :
8566 : 0 : t->hf = hf;
8567 : 0 : t->size = size;
8568 : 0 : t->id = p->n_tables;
8569 : :
8570 : : /* Node add to tailq. */
8571 : 0 : TAILQ_INSERT_TAIL(&p->tables, t, node);
8572 : 0 : p->n_tables++;
8573 : :
8574 : 0 : return 0;
8575 : :
8576 : 0 : error:
8577 [ # # ]: 0 : if (!t)
8578 : : return status;
8579 : :
8580 : 0 : free(t->action_is_for_default_entry);
8581 : 0 : free(t->action_is_for_table_entries);
8582 : 0 : free(t->default_action_data);
8583 : 0 : free(t->actions);
8584 : 0 : free(t->fields);
8585 : 0 : free(t);
8586 : :
8587 : 0 : return status;
8588 : : }
8589 : :
8590 : : static uint32_t
8591 : : table_params_offset_get(struct table *table)
8592 : : {
8593 : : struct field *first;
8594 : : uint32_t i;
8595 : :
8596 : 0 : first = table->fields[0].field;
8597 : :
8598 [ # # ]: 0 : for (i = 1; i < table->n_fields; i++) {
8599 : 0 : struct field *f = table->fields[i].field;
8600 : :
8601 [ # # ]: 0 : if (f->offset < first->offset)
8602 : : first = f;
8603 : : }
8604 : :
8605 : 0 : return first->offset / 8;
8606 : : }
8607 : :
8608 : : static struct rte_swx_table_params *
8609 : 0 : table_params_get(struct table *table)
8610 : : {
8611 : : struct rte_swx_table_params *params;
8612 : : struct field *first, *last;
8613 : : uint8_t *key_mask;
8614 : : uint32_t key_size, key_offset, action_data_size, i;
8615 : :
8616 : : /* Memory allocation. */
8617 : 0 : params = calloc(1, sizeof(struct rte_swx_table_params));
8618 [ # # ]: 0 : if (!params)
8619 : : return NULL;
8620 : :
8621 : : /* Find first (smallest offset) and last (biggest offset) match fields. */
8622 : 0 : first = table->fields[0].field;
8623 : : last = table->fields[0].field;
8624 : :
8625 [ # # ]: 0 : for (i = 0; i < table->n_fields; i++) {
8626 : 0 : struct field *f = table->fields[i].field;
8627 : :
8628 [ # # ]: 0 : if (f->offset < first->offset)
8629 : : first = f;
8630 : :
8631 [ # # ]: 0 : if (f->offset > last->offset)
8632 : : last = f;
8633 : : }
8634 : :
8635 : : /* Key offset and size. */
8636 : 0 : key_offset = first->offset / 8;
8637 : 0 : key_size = (last->offset + last->n_bits - first->offset) / 8;
8638 : :
8639 : : /* Memory allocation. */
8640 : 0 : key_mask = calloc(1, key_size);
8641 [ # # ]: 0 : if (!key_mask) {
8642 : 0 : free(params);
8643 : 0 : return NULL;
8644 : : }
8645 : :
8646 : : /* Key mask. */
8647 [ # # ]: 0 : for (i = 0; i < table->n_fields; i++) {
8648 : 0 : struct field *f = table->fields[i].field;
8649 : 0 : uint32_t start = (f->offset - first->offset) / 8;
8650 : 0 : size_t size = f->n_bits / 8;
8651 : :
8652 : 0 : memset(&key_mask[start], 0xFF, size);
8653 : : }
8654 : :
8655 : : /* Action data size. */
8656 : : action_data_size = 0;
8657 [ # # ]: 0 : for (i = 0; i < table->n_actions; i++) {
8658 : 0 : struct action *action = table->actions[i];
8659 [ # # ]: 0 : uint32_t ads = action->st ? action->st->n_bits / 8 : 0;
8660 : :
8661 : : if (ads > action_data_size)
8662 : : action_data_size = ads;
8663 : : }
8664 : :
8665 : : /* Fill in. */
8666 : 0 : params->match_type = table->type->match_type;
8667 : 0 : params->key_size = key_size;
8668 : 0 : params->key_offset = key_offset;
8669 : 0 : params->key_mask0 = key_mask;
8670 : 0 : params->action_data_size = action_data_size;
8671 [ # # ]: 0 : params->hash_func = table->hf ? table->hf->func : NULL;
8672 : 0 : params->n_keys_max = table->size;
8673 : :
8674 : 0 : return params;
8675 : : }
8676 : :
8677 : : static void
8678 : 0 : table_params_free(struct rte_swx_table_params *params)
8679 : : {
8680 [ # # ]: 0 : if (!params)
8681 : : return;
8682 : :
8683 : 0 : free(params->key_mask0);
8684 : 0 : free(params);
8685 : : }
8686 : :
8687 : : static int
8688 : 0 : table_stub_lkp(void *table __rte_unused,
8689 : : void *mailbox __rte_unused,
8690 : : uint8_t **key __rte_unused,
8691 : : uint64_t *action_id __rte_unused,
8692 : : uint8_t **action_data __rte_unused,
8693 : : size_t *entry_id __rte_unused,
8694 : : int *hit)
8695 : : {
8696 : 0 : *hit = 0;
8697 : 0 : return 1; /* DONE. */
8698 : : }
8699 : :
8700 : : static int
8701 : 0 : table_build(struct rte_swx_pipeline *p)
8702 : : {
8703 : : uint32_t i;
8704 : :
8705 : : /* Per pipeline: table statistics. */
8706 : 0 : p->table_stats = calloc(p->n_tables, sizeof(struct table_statistics));
8707 [ # # ]: 0 : CHECK(p->table_stats, ENOMEM);
8708 : :
8709 [ # # ]: 0 : for (i = 0; i < p->n_tables; i++) {
8710 : 0 : p->table_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
8711 [ # # ]: 0 : CHECK(p->table_stats[i].n_pkts_action, ENOMEM);
8712 : : }
8713 : :
8714 : : /* Per thread: table runt-time. */
8715 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8716 : : struct thread *t = &p->threads[i];
8717 : : struct table *table;
8718 : :
8719 : 0 : t->tables = calloc(p->n_tables, sizeof(struct table_runtime));
8720 [ # # ]: 0 : CHECK(t->tables, ENOMEM);
8721 : :
8722 [ # # ]: 0 : TAILQ_FOREACH(table, &p->tables, node) {
8723 : 0 : struct table_runtime *r = &t->tables[table->id];
8724 : :
8725 [ # # ]: 0 : if (table->type) {
8726 : : uint64_t size;
8727 : :
8728 : 0 : size = table->type->ops.mailbox_size_get();
8729 : :
8730 : : /* r->func. */
8731 : 0 : r->func = table->type->ops.lkp;
8732 : :
8733 : : /* r->mailbox. */
8734 [ # # ]: 0 : if (size) {
8735 : 0 : r->mailbox = calloc(1, size);
8736 [ # # ]: 0 : CHECK(r->mailbox, ENOMEM);
8737 : : }
8738 : :
8739 : : /* r->key. */
8740 : 0 : r->key = table->header ?
8741 [ # # ]: 0 : &t->structs[table->header->struct_id] :
8742 : 0 : &t->structs[p->metadata_struct_id];
8743 : : } else {
8744 : 0 : r->func = table_stub_lkp;
8745 : : }
8746 : : }
8747 : : }
8748 : :
8749 : : return 0;
8750 : : }
8751 : :
8752 : : static void
8753 : 0 : table_build_free(struct rte_swx_pipeline *p)
8754 : : {
8755 : : uint32_t i;
8756 : :
8757 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8758 : : struct thread *t = &p->threads[i];
8759 : : uint32_t j;
8760 : :
8761 [ # # ]: 0 : if (!t->tables)
8762 : 0 : continue;
8763 : :
8764 [ # # ]: 0 : for (j = 0; j < p->n_tables; j++) {
8765 : 0 : struct table_runtime *r = &t->tables[j];
8766 : :
8767 : 0 : free(r->mailbox);
8768 : : }
8769 : :
8770 : 0 : free(t->tables);
8771 : 0 : t->tables = NULL;
8772 : : }
8773 : :
8774 [ # # ]: 0 : if (p->table_stats) {
8775 [ # # ]: 0 : for (i = 0; i < p->n_tables; i++)
8776 : 0 : free(p->table_stats[i].n_pkts_action);
8777 : :
8778 : 0 : free(p->table_stats);
8779 : 0 : p->table_stats = NULL;
8780 : : }
8781 : 0 : }
8782 : :
8783 : : static void
8784 : 0 : table_free(struct rte_swx_pipeline *p)
8785 : : {
8786 : 0 : table_build_free(p);
8787 : :
8788 : : /* Tables. */
8789 : 0 : for ( ; ; ) {
8790 : : struct table *elem;
8791 : :
8792 : 0 : elem = TAILQ_FIRST(&p->tables);
8793 [ # # ]: 0 : if (!elem)
8794 : : break;
8795 : :
8796 [ # # ]: 0 : TAILQ_REMOVE(&p->tables, elem, node);
8797 : 0 : free(elem->fields);
8798 : 0 : free(elem->actions);
8799 : 0 : free(elem->default_action_data);
8800 : 0 : free(elem);
8801 : : }
8802 : :
8803 : : /* Table types. */
8804 : 0 : for ( ; ; ) {
8805 : : struct table_type *elem;
8806 : :
8807 : 0 : elem = TAILQ_FIRST(&p->table_types);
8808 [ # # ]: 0 : if (!elem)
8809 : : break;
8810 : :
8811 [ # # ]: 0 : TAILQ_REMOVE(&p->table_types, elem, node);
8812 : 0 : free(elem);
8813 : : }
8814 : 0 : }
8815 : :
8816 : : /*
8817 : : * Selector.
8818 : : */
8819 : : static struct selector *
8820 : : selector_find(struct rte_swx_pipeline *p, const char *name)
8821 : : {
8822 : : struct selector *s;
8823 : :
8824 [ # # # # : 0 : TAILQ_FOREACH(s, &p->selectors, node)
# # # # #
# ]
8825 [ # # # # : 0 : if (strcmp(s->name, name) == 0)
# # # # #
# ]
8826 : : return s;
8827 : :
8828 : : return NULL;
8829 : : }
8830 : :
8831 : : static struct selector *
8832 : : selector_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8833 : : {
8834 : : struct selector *s = NULL;
8835 : :
8836 [ # # # # : 0 : TAILQ_FOREACH(s, &p->selectors, node)
# # # # ]
8837 [ # # # # : 0 : if (s->id == id)
# # # # ]
8838 : : return s;
8839 : :
8840 : : return NULL;
8841 : : }
8842 : :
8843 : : static int
8844 : 0 : selector_fields_check(struct rte_swx_pipeline *p,
8845 : : struct rte_swx_pipeline_selector_params *params,
8846 : : struct header **header)
8847 : : {
8848 : 0 : struct header *h0 = NULL;
8849 : : struct field *hf, *mf;
8850 : : uint32_t i;
8851 : :
8852 : : /* Return if no selector fields. */
8853 [ # # # # ]: 0 : if (!params->n_selector_fields || !params->selector_field_names)
8854 : : return -EINVAL;
8855 : :
8856 : : /* Check that all the selector fields either belong to the same header
8857 : : * or are all meta-data fields.
8858 : : */
8859 : 0 : hf = header_field_parse(p, params->selector_field_names[0], &h0);
8860 : 0 : mf = metadata_field_parse(p, params->selector_field_names[0]);
8861 [ # # ]: 0 : if (!hf && !mf)
8862 : : return -EINVAL;
8863 : :
8864 [ # # ]: 0 : for (i = 1; i < params->n_selector_fields; i++)
8865 [ # # ]: 0 : if (h0) {
8866 : : struct header *h;
8867 : :
8868 : 0 : hf = header_field_parse(p, params->selector_field_names[i], &h);
8869 [ # # # # ]: 0 : if (!hf || (h->id != h0->id))
8870 : 0 : return -EINVAL;
8871 : : } else {
8872 : 0 : mf = metadata_field_parse(p, params->selector_field_names[i]);
8873 [ # # ]: 0 : if (!mf)
8874 : : return -EINVAL;
8875 : : }
8876 : :
8877 : : /* Check that there are no duplicated match fields. */
8878 [ # # ]: 0 : for (i = 0; i < params->n_selector_fields; i++) {
8879 : 0 : const char *field_name = params->selector_field_names[i];
8880 : : uint32_t j;
8881 : :
8882 [ # # ]: 0 : for (j = i + 1; j < params->n_selector_fields; j++)
8883 [ # # ]: 0 : if (!strcmp(params->selector_field_names[j], field_name))
8884 : : return -EINVAL;
8885 : : }
8886 : :
8887 : : /* Return. */
8888 [ # # ]: 0 : if (header)
8889 : 0 : *header = h0;
8890 : :
8891 : : return 0;
8892 : : }
8893 : :
8894 : : int
8895 : 0 : rte_swx_pipeline_selector_config(struct rte_swx_pipeline *p,
8896 : : const char *name,
8897 : : struct rte_swx_pipeline_selector_params *params)
8898 : : {
8899 : : struct selector *s;
8900 : 0 : struct header *selector_header = NULL;
8901 : : struct field *group_id_field, *member_id_field;
8902 : : uint32_t i;
8903 : : int status = 0;
8904 : :
8905 [ # # ]: 0 : CHECK(p, EINVAL);
8906 : :
8907 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
8908 [ # # ]: 0 : CHECK(!table_find(p, name), EEXIST);
8909 [ # # ]: 0 : CHECK(!selector_find(p, name), EEXIST);
8910 [ # # ]: 0 : CHECK(!learner_find(p, name), EEXIST);
8911 : :
8912 [ # # ]: 0 : CHECK(params, EINVAL);
8913 : :
8914 [ # # # # : 0 : CHECK_NAME(params->group_id_field_name, EINVAL);
# # ]
8915 : 0 : group_id_field = metadata_field_parse(p, params->group_id_field_name);
8916 [ # # ]: 0 : CHECK(group_id_field, EINVAL);
8917 : :
8918 [ # # ]: 0 : for (i = 0; i < params->n_selector_fields; i++) {
8919 : 0 : const char *field_name = params->selector_field_names[i];
8920 : :
8921 [ # # # # : 0 : CHECK_NAME(field_name, EINVAL);
# # ]
8922 : : }
8923 : 0 : status = selector_fields_check(p, params, &selector_header);
8924 [ # # ]: 0 : if (status)
8925 : : return status;
8926 : :
8927 [ # # # # : 0 : CHECK_NAME(params->member_id_field_name, EINVAL);
# # ]
8928 : 0 : member_id_field = metadata_field_parse(p, params->member_id_field_name);
8929 [ # # ]: 0 : CHECK(member_id_field, EINVAL);
8930 : :
8931 [ # # ]: 0 : CHECK(params->n_groups_max, EINVAL);
8932 : :
8933 [ # # ]: 0 : CHECK(params->n_members_per_group_max, EINVAL);
8934 : :
8935 : : /* Memory allocation. */
8936 : 0 : s = calloc(1, sizeof(struct selector));
8937 [ # # ]: 0 : if (!s) {
8938 : : status = -ENOMEM;
8939 : 0 : goto error;
8940 : : }
8941 : :
8942 : 0 : s->selector_fields = calloc(params->n_selector_fields, sizeof(struct field *));
8943 [ # # ]: 0 : if (!s->selector_fields) {
8944 : : status = -ENOMEM;
8945 : 0 : goto error;
8946 : : }
8947 : :
8948 : : /* Node initialization. */
8949 : 0 : strcpy(s->name, name);
8950 : :
8951 : 0 : s->group_id_field = group_id_field;
8952 : :
8953 [ # # ]: 0 : for (i = 0; i < params->n_selector_fields; i++) {
8954 : 0 : const char *field_name = params->selector_field_names[i];
8955 : :
8956 : 0 : s->selector_fields[i] = selector_header ?
8957 [ # # ]: 0 : header_field_parse(p, field_name, NULL) :
8958 : 0 : metadata_field_parse(p, field_name);
8959 : : }
8960 : :
8961 : 0 : s->n_selector_fields = params->n_selector_fields;
8962 : :
8963 : 0 : s->selector_header = selector_header;
8964 : :
8965 : 0 : s->member_id_field = member_id_field;
8966 : :
8967 : 0 : s->n_groups_max = params->n_groups_max;
8968 : :
8969 : 0 : s->n_members_per_group_max = params->n_members_per_group_max;
8970 : :
8971 : 0 : s->id = p->n_selectors;
8972 : :
8973 : : /* Node add to tailq. */
8974 : 0 : TAILQ_INSERT_TAIL(&p->selectors, s, node);
8975 : 0 : p->n_selectors++;
8976 : :
8977 : 0 : return 0;
8978 : :
8979 : 0 : error:
8980 [ # # ]: 0 : if (!s)
8981 : : return status;
8982 : :
8983 : 0 : free(s->selector_fields);
8984 : :
8985 : 0 : free(s);
8986 : :
8987 : 0 : return status;
8988 : : }
8989 : :
8990 : : static void
8991 : 0 : selector_params_free(struct rte_swx_table_selector_params *params)
8992 : : {
8993 [ # # ]: 0 : if (!params)
8994 : : return;
8995 : :
8996 : 0 : free(params->selector_mask);
8997 : :
8998 : 0 : free(params);
8999 : : }
9000 : :
9001 : : static struct rte_swx_table_selector_params *
9002 : 0 : selector_table_params_get(struct selector *s)
9003 : : {
9004 : : struct rte_swx_table_selector_params *params = NULL;
9005 : : struct field *first, *last;
9006 : : uint32_t i;
9007 : :
9008 : : /* Memory allocation. */
9009 : 0 : params = calloc(1, sizeof(struct rte_swx_table_selector_params));
9010 [ # # ]: 0 : if (!params)
9011 : 0 : goto error;
9012 : :
9013 : : /* Group ID. */
9014 : 0 : params->group_id_offset = s->group_id_field->offset / 8;
9015 : :
9016 : : /* Find first (smallest offset) and last (biggest offset) selector fields. */
9017 : 0 : first = s->selector_fields[0];
9018 : : last = s->selector_fields[0];
9019 : :
9020 [ # # ]: 0 : for (i = 0; i < s->n_selector_fields; i++) {
9021 : 0 : struct field *f = s->selector_fields[i];
9022 : :
9023 [ # # ]: 0 : if (f->offset < first->offset)
9024 : : first = f;
9025 : :
9026 [ # # ]: 0 : if (f->offset > last->offset)
9027 : : last = f;
9028 : : }
9029 : :
9030 : : /* Selector offset and size. */
9031 : 0 : params->selector_offset = first->offset / 8;
9032 : 0 : params->selector_size = (last->offset + last->n_bits - first->offset) / 8;
9033 : :
9034 : : /* Memory allocation. */
9035 : 0 : params->selector_mask = calloc(1, params->selector_size);
9036 [ # # ]: 0 : if (!params->selector_mask)
9037 : 0 : goto error;
9038 : :
9039 : : /* Selector mask. */
9040 [ # # ]: 0 : for (i = 0; i < s->n_selector_fields; i++) {
9041 : 0 : struct field *f = s->selector_fields[i];
9042 : 0 : uint32_t start = (f->offset - first->offset) / 8;
9043 : 0 : size_t size = f->n_bits / 8;
9044 : :
9045 : 0 : memset(¶ms->selector_mask[start], 0xFF, size);
9046 : : }
9047 : :
9048 : : /* Member ID. */
9049 : 0 : params->member_id_offset = s->member_id_field->offset / 8;
9050 : :
9051 : : /* Maximum number of groups. */
9052 : 0 : params->n_groups_max = s->n_groups_max;
9053 : :
9054 : : /* Maximum number of members per group. */
9055 : 0 : params->n_members_per_group_max = s->n_members_per_group_max;
9056 : :
9057 : 0 : return params;
9058 : :
9059 : 0 : error:
9060 : 0 : selector_params_free(params);
9061 : 0 : return NULL;
9062 : : }
9063 : :
9064 : : static void
9065 : 0 : selector_build_free(struct rte_swx_pipeline *p)
9066 : : {
9067 : : uint32_t i;
9068 : :
9069 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9070 : : struct thread *t = &p->threads[i];
9071 : : uint32_t j;
9072 : :
9073 [ # # ]: 0 : if (!t->selectors)
9074 : 0 : continue;
9075 : :
9076 [ # # ]: 0 : for (j = 0; j < p->n_selectors; j++) {
9077 : 0 : struct selector_runtime *r = &t->selectors[j];
9078 : :
9079 : 0 : free(r->mailbox);
9080 : : }
9081 : :
9082 : 0 : free(t->selectors);
9083 : 0 : t->selectors = NULL;
9084 : : }
9085 : :
9086 : 0 : free(p->selector_stats);
9087 : 0 : p->selector_stats = NULL;
9088 : 0 : }
9089 : :
9090 : : static int
9091 : 0 : selector_build(struct rte_swx_pipeline *p)
9092 : : {
9093 : : uint32_t i;
9094 : : int status = 0;
9095 : :
9096 : : /* Per pipeline: selector statistics. */
9097 : 0 : p->selector_stats = calloc(p->n_selectors, sizeof(struct selector_statistics));
9098 [ # # ]: 0 : if (!p->selector_stats) {
9099 : : status = -ENOMEM;
9100 : 0 : goto error;
9101 : : }
9102 : :
9103 : : /* Per thread: selector run-time. */
9104 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9105 : : struct thread *t = &p->threads[i];
9106 : : struct selector *s;
9107 : :
9108 : 0 : t->selectors = calloc(p->n_selectors, sizeof(struct selector_runtime));
9109 [ # # ]: 0 : if (!t->selectors) {
9110 : : status = -ENOMEM;
9111 : 0 : goto error;
9112 : : }
9113 : :
9114 [ # # ]: 0 : TAILQ_FOREACH(s, &p->selectors, node) {
9115 : 0 : struct selector_runtime *r = &t->selectors[s->id];
9116 : : uint64_t size;
9117 : :
9118 : : /* r->mailbox. */
9119 : 0 : size = rte_swx_table_selector_mailbox_size_get();
9120 [ # # ]: 0 : if (size) {
9121 : 0 : r->mailbox = calloc(1, size);
9122 [ # # ]: 0 : if (!r->mailbox) {
9123 : : status = -ENOMEM;
9124 : 0 : goto error;
9125 : : }
9126 : : }
9127 : :
9128 : : /* r->group_id_buffer. */
9129 : 0 : r->group_id_buffer = &t->structs[p->metadata_struct_id];
9130 : :
9131 : : /* r->selector_buffer. */
9132 : 0 : r->selector_buffer = s->selector_header ?
9133 [ # # ]: 0 : &t->structs[s->selector_header->struct_id] :
9134 : : &t->structs[p->metadata_struct_id];
9135 : :
9136 : : /* r->member_id_buffer. */
9137 : 0 : r->member_id_buffer = &t->structs[p->metadata_struct_id];
9138 : : }
9139 : : }
9140 : :
9141 : : return 0;
9142 : :
9143 : 0 : error:
9144 : 0 : selector_build_free(p);
9145 : 0 : return status;
9146 : : }
9147 : :
9148 : : static void
9149 : 0 : selector_free(struct rte_swx_pipeline *p)
9150 : : {
9151 : 0 : selector_build_free(p);
9152 : :
9153 : : /* Selector tables. */
9154 : 0 : for ( ; ; ) {
9155 : : struct selector *elem;
9156 : :
9157 : 0 : elem = TAILQ_FIRST(&p->selectors);
9158 [ # # ]: 0 : if (!elem)
9159 : : break;
9160 : :
9161 [ # # ]: 0 : TAILQ_REMOVE(&p->selectors, elem, node);
9162 : 0 : free(elem->selector_fields);
9163 : 0 : free(elem);
9164 : : }
9165 : 0 : }
9166 : :
9167 : : /*
9168 : : * Learner table.
9169 : : */
9170 : : static struct learner *
9171 : : learner_find(struct rte_swx_pipeline *p, const char *name)
9172 : : {
9173 : : struct learner *l;
9174 : :
9175 [ # # # # : 0 : TAILQ_FOREACH(l, &p->learners, node)
# # # # #
# # # #
# ]
9176 [ # # # # : 0 : if (!strcmp(l->name, name))
# # # # #
# # # #
# ]
9177 : : return l;
9178 : :
9179 : : return NULL;
9180 : : }
9181 : :
9182 : : static struct learner *
9183 : : learner_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9184 : : {
9185 : : struct learner *l = NULL;
9186 : :
9187 [ # # # # : 0 : TAILQ_FOREACH(l, &p->learners, node)
# # # # #
# ]
9188 [ # # # # : 0 : if (l->id == id)
# # # # #
# ]
9189 : : return l;
9190 : :
9191 : : return NULL;
9192 : : }
9193 : :
9194 : : static int
9195 : 0 : learner_match_fields_check(struct rte_swx_pipeline *p,
9196 : : struct rte_swx_pipeline_learner_params *params,
9197 : : struct header **header)
9198 : : {
9199 : 0 : struct header *h0 = NULL;
9200 : : struct field *hf, *mf;
9201 : : uint32_t *offset = NULL, *n_bits = NULL, n_fields_with_valid_next = 0, i;
9202 : : int status = 0;
9203 : :
9204 : : /* Return if no match fields. */
9205 [ # # # # ]: 0 : if (!params->n_fields || !params->field_names)
9206 : : return -EINVAL;
9207 : :
9208 : : /* Memory allocation. */
9209 : 0 : offset = calloc(params->n_fields, sizeof(uint32_t));
9210 : 0 : n_bits = calloc(params->n_fields, sizeof(uint32_t));
9211 [ # # ]: 0 : if (!offset || !n_bits) {
9212 : : status = -ENOMEM;
9213 : 0 : goto end;
9214 : : }
9215 : :
9216 : : /* Check that all the match fields either belong to the same header
9217 : : * or are all meta-data fields.
9218 : : */
9219 : 0 : hf = header_field_parse(p, params->field_names[0], &h0);
9220 : 0 : mf = metadata_field_parse(p, params->field_names[0]);
9221 [ # # # # : 0 : if ((!hf && !mf) || (hf && hf->var_size)) {
# # ]
9222 : : status = -EINVAL;
9223 : 0 : goto end;
9224 : : }
9225 : :
9226 [ # # ]: 0 : offset[0] = h0 ? hf->offset : mf->offset;
9227 [ # # ]: 0 : n_bits[0] = h0 ? hf->n_bits : mf->n_bits;
9228 : :
9229 [ # # ]: 0 : for (i = 1; i < params->n_fields; i++)
9230 [ # # ]: 0 : if (h0) {
9231 : : struct header *h;
9232 : :
9233 : 0 : hf = header_field_parse(p, params->field_names[i], &h);
9234 [ # # # # : 0 : if (!hf || (h->id != h0->id) || hf->var_size) {
# # ]
9235 : : status = -EINVAL;
9236 : 0 : goto end;
9237 : : }
9238 : :
9239 : 0 : offset[i] = hf->offset;
9240 : 0 : n_bits[i] = hf->n_bits;
9241 : : } else {
9242 : 0 : mf = metadata_field_parse(p, params->field_names[i]);
9243 [ # # ]: 0 : if (!mf) {
9244 : : status = -EINVAL;
9245 : 0 : goto end;
9246 : : }
9247 : :
9248 : 0 : offset[i] = mf->offset;
9249 : 0 : n_bits[i] = mf->n_bits;
9250 : : }
9251 : :
9252 : : /* Check that there are no duplicated match fields. */
9253 [ # # ]: 0 : for (i = 0; i < params->n_fields; i++) {
9254 : 0 : const char *field_name = params->field_names[i];
9255 : : uint32_t j;
9256 : :
9257 [ # # ]: 0 : for (j = i + 1; j < params->n_fields; j++)
9258 [ # # ]: 0 : if (!strcmp(params->field_names[j], field_name)) {
9259 : : status = -EINVAL;
9260 : 0 : goto end;
9261 : : }
9262 : : }
9263 : :
9264 : : /* Check that the match fields are contiguous. */
9265 [ # # ]: 0 : for (i = 0; i < params->n_fields; i++) {
9266 : 0 : uint32_t offset_next = offset[i] + n_bits[i];
9267 : : uint32_t j;
9268 : :
9269 [ # # ]: 0 : for (j = 0; j < params->n_fields; j++)
9270 [ # # ]: 0 : if (offset[j] == offset_next) {
9271 : 0 : n_fields_with_valid_next++;
9272 : 0 : break;
9273 : : }
9274 : : }
9275 : :
9276 [ # # ]: 0 : if (n_fields_with_valid_next != params->n_fields - 1) {
9277 : : status = -EINVAL;
9278 : 0 : goto end;
9279 : : }
9280 : :
9281 : : /* Return. */
9282 [ # # ]: 0 : if (header)
9283 : 0 : *header = h0;
9284 : :
9285 : 0 : end:
9286 : 0 : free(offset);
9287 : 0 : free(n_bits);
9288 : 0 : return status;
9289 : : }
9290 : :
9291 : : static int
9292 : 0 : learner_action_args_check(struct rte_swx_pipeline *p, struct action *a, const char *mf_name)
9293 : : {
9294 : 0 : struct struct_type *mst = p->metadata_st, *ast = a->st;
9295 : : struct field *mf, *af;
9296 : : uint32_t mf_pos, i;
9297 : :
9298 [ # # ]: 0 : if (!ast) {
9299 [ # # ]: 0 : if (mf_name)
9300 : : return -EINVAL;
9301 : :
9302 : 0 : return 0;
9303 : : }
9304 : :
9305 : : /* Check that mf_name is the name of a valid meta-data field. */
9306 [ # # # # : 0 : CHECK_NAME(mf_name, EINVAL);
# # ]
9307 : 0 : mf = metadata_field_parse(p, mf_name);
9308 [ # # ]: 0 : CHECK(mf, EINVAL);
9309 : :
9310 : : /* Check that there are enough meta-data fields, starting with the mf_name field, to cover
9311 : : * all the action arguments.
9312 : : */
9313 : 0 : mf_pos = mf - mst->fields;
9314 [ # # ]: 0 : CHECK(mst->n_fields - mf_pos >= ast->n_fields, EINVAL);
9315 : :
9316 : : /* Check that the size of each of the identified meta-data fields matches exactly the size
9317 : : * of the corresponding action argument.
9318 : : */
9319 [ # # ]: 0 : for (i = 0; i < ast->n_fields; i++) {
9320 : 0 : mf = &mst->fields[mf_pos + i];
9321 : 0 : af = &ast->fields[i];
9322 : :
9323 [ # # ]: 0 : CHECK(mf->n_bits == af->n_bits, EINVAL);
9324 : : }
9325 : :
9326 : : return 0;
9327 : : }
9328 : :
9329 : : static int
9330 : 0 : learner_action_learning_check(struct rte_swx_pipeline *p,
9331 : : struct action *action,
9332 : : const char **action_names,
9333 : : uint32_t n_actions)
9334 : : {
9335 : : uint32_t i;
9336 : :
9337 : : /* For each "learn" instruction of the current action, check that the learned action (i.e.
9338 : : * the action passed as argument to the "learn" instruction) is also enabled for the
9339 : : * current learner table.
9340 : : */
9341 [ # # ]: 0 : for (i = 0; i < action->n_instructions; i++) {
9342 : 0 : struct instruction *instr = &action->instructions[i];
9343 : : uint32_t found = 0, j;
9344 : :
9345 [ # # ]: 0 : if (instr->type != INSTR_LEARNER_LEARN)
9346 : 0 : continue;
9347 : :
9348 [ # # ]: 0 : for (j = 0; j < n_actions; j++) {
9349 : : struct action *a;
9350 : :
9351 : 0 : a = action_find(p, action_names[j]);
9352 [ # # ]: 0 : if (!a)
9353 : : return -EINVAL;
9354 : :
9355 [ # # ]: 0 : if (a->id == instr->learn.action_id)
9356 : : found = 1;
9357 : : }
9358 : :
9359 [ # # ]: 0 : if (!found)
9360 : : return -EINVAL;
9361 : : }
9362 : :
9363 : : return 0;
9364 : : }
9365 : :
9366 : : int
9367 : 0 : rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p,
9368 : : const char *name,
9369 : : struct rte_swx_pipeline_learner_params *params,
9370 : : uint32_t size,
9371 : : uint32_t *timeout,
9372 : : uint32_t n_timeouts)
9373 : : {
9374 : : struct learner *l = NULL;
9375 : : struct action *default_action;
9376 : 0 : struct header *header = NULL;
9377 : : struct hash_func *hf = NULL;
9378 : : uint32_t action_data_size_max = 0, i;
9379 : : int status = 0;
9380 : :
9381 [ # # ]: 0 : CHECK(p, EINVAL);
9382 : :
9383 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
9384 [ # # ]: 0 : CHECK(!table_find(p, name), EEXIST);
9385 [ # # ]: 0 : CHECK(!selector_find(p, name), EEXIST);
9386 [ # # ]: 0 : CHECK(!learner_find(p, name), EEXIST);
9387 : :
9388 [ # # ]: 0 : CHECK(params, EINVAL);
9389 : :
9390 : : /* Match checks. */
9391 : 0 : status = learner_match_fields_check(p, params, &header);
9392 [ # # ]: 0 : if (status)
9393 : : return status;
9394 : :
9395 : : /* Action checks. */
9396 [ # # ]: 0 : CHECK(params->n_actions, EINVAL);
9397 [ # # ]: 0 : CHECK(params->action_names, EINVAL);
9398 [ # # ]: 0 : for (i = 0; i < params->n_actions; i++) {
9399 : 0 : const char *action_name = params->action_names[i];
9400 : : struct action *a;
9401 : : uint32_t action_data_size;
9402 : : int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
9403 : :
9404 [ # # # # : 0 : CHECK_NAME(action_name, EINVAL);
# # ]
9405 : :
9406 : 0 : a = action_find(p, action_name);
9407 [ # # ]: 0 : CHECK(a, EINVAL);
9408 : :
9409 : 0 : status = learner_action_learning_check(p,
9410 : : a,
9411 : : params->action_names,
9412 : : params->n_actions);
9413 [ # # ]: 0 : if (status)
9414 : 0 : return status;
9415 : :
9416 [ # # ]: 0 : action_data_size = a->st ? a->st->n_bits / 8 : 0;
9417 : : if (action_data_size > action_data_size_max)
9418 : : action_data_size_max = action_data_size;
9419 : :
9420 [ # # ]: 0 : if (params->action_is_for_table_entries)
9421 : 0 : action_is_for_table_entries = params->action_is_for_table_entries[i];
9422 [ # # ]: 0 : if (params->action_is_for_default_entry)
9423 : 0 : action_is_for_default_entry = params->action_is_for_default_entry[i];
9424 [ # # ]: 0 : CHECK(action_is_for_table_entries || action_is_for_default_entry, EINVAL);
9425 : : }
9426 : :
9427 [ # # # # : 0 : CHECK_NAME(params->default_action_name, EINVAL);
# # ]
9428 [ # # ]: 0 : for (i = 0; i < p->n_actions; i++)
9429 [ # # ]: 0 : if (!strcmp(params->action_names[i],
9430 : : params->default_action_name))
9431 : : break;
9432 [ # # ]: 0 : CHECK(i < params->n_actions, EINVAL);
9433 [ # # # # ]: 0 : CHECK(!params->action_is_for_default_entry || params->action_is_for_default_entry[i],
9434 : : EINVAL);
9435 : :
9436 : 0 : default_action = action_find(p, params->default_action_name);
9437 [ # # # # ]: 0 : CHECK((default_action->st && params->default_action_args) || !params->default_action_args,
9438 : : EINVAL);
9439 : :
9440 : : /* Hash function checks. */
9441 [ # # ]: 0 : if (params->hash_func_name) {
9442 : : hf = hash_func_find(p, params->hash_func_name);
9443 [ # # ]: 0 : CHECK(hf, EINVAL);
9444 : : }
9445 : :
9446 : : /* Any other checks. */
9447 [ # # ]: 0 : CHECK(size, EINVAL);
9448 [ # # ]: 0 : CHECK(timeout, EINVAL);
9449 [ # # ]: 0 : CHECK(n_timeouts && (n_timeouts <= RTE_SWX_TABLE_LEARNER_N_KEY_TIMEOUTS_MAX), EINVAL);
9450 : :
9451 : : /* Memory allocation. */
9452 : 0 : l = calloc(1, sizeof(struct learner));
9453 [ # # ]: 0 : if (!l) {
9454 : : status = -ENOMEM;
9455 : 0 : goto error;
9456 : : }
9457 : :
9458 : 0 : l->fields = calloc(params->n_fields, sizeof(struct field *));
9459 [ # # ]: 0 : if (!l->fields) {
9460 : : status = -ENOMEM;
9461 : 0 : goto error;
9462 : : }
9463 : :
9464 : 0 : l->actions = calloc(params->n_actions, sizeof(struct action *));
9465 [ # # ]: 0 : if (!l->actions) {
9466 : : status = -ENOMEM;
9467 : 0 : goto error;
9468 : : }
9469 : :
9470 [ # # ]: 0 : if (action_data_size_max) {
9471 : 0 : l->default_action_data = calloc(1, action_data_size_max);
9472 [ # # ]: 0 : if (!l->default_action_data) {
9473 : : status = -ENOMEM;
9474 : 0 : goto error;
9475 : : }
9476 : : }
9477 : :
9478 : 0 : l->action_is_for_table_entries = calloc(params->n_actions, sizeof(int));
9479 [ # # ]: 0 : if (!l->action_is_for_table_entries) {
9480 : : status = -ENOMEM;
9481 : 0 : goto error;
9482 : : }
9483 : :
9484 : 0 : l->action_is_for_default_entry = calloc(params->n_actions, sizeof(int));
9485 [ # # ]: 0 : if (!l->action_is_for_default_entry) {
9486 : : status = -ENOMEM;
9487 : 0 : goto error;
9488 : : }
9489 : :
9490 : : /* Node initialization. */
9491 : 0 : strcpy(l->name, name);
9492 : :
9493 [ # # ]: 0 : for (i = 0; i < params->n_fields; i++) {
9494 : 0 : const char *field_name = params->field_names[i];
9495 : :
9496 : 0 : l->fields[i] = header ?
9497 [ # # ]: 0 : header_field_parse(p, field_name, NULL) :
9498 : 0 : metadata_field_parse(p, field_name);
9499 : : }
9500 : :
9501 : 0 : l->n_fields = params->n_fields;
9502 : :
9503 : 0 : l->header = header;
9504 : :
9505 [ # # ]: 0 : for (i = 0; i < params->n_actions; i++) {
9506 : : int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
9507 : :
9508 [ # # ]: 0 : if (params->action_is_for_table_entries)
9509 : 0 : action_is_for_table_entries = params->action_is_for_table_entries[i];
9510 [ # # ]: 0 : if (params->action_is_for_default_entry)
9511 : 0 : action_is_for_default_entry = params->action_is_for_default_entry[i];
9512 : :
9513 : 0 : l->actions[i] = action_find(p, params->action_names[i]);
9514 : 0 : l->action_is_for_table_entries[i] = action_is_for_table_entries;
9515 : 0 : l->action_is_for_default_entry[i] = action_is_for_default_entry;
9516 : : }
9517 : :
9518 : 0 : l->default_action = default_action;
9519 : :
9520 [ # # ]: 0 : if (default_action->st) {
9521 : 0 : status = action_args_parse(default_action,
9522 : : params->default_action_args,
9523 : : l->default_action_data);
9524 [ # # ]: 0 : if (status)
9525 : 0 : goto error;
9526 : : }
9527 : :
9528 : 0 : l->n_actions = params->n_actions;
9529 : :
9530 : 0 : l->default_action_is_const = params->default_action_is_const;
9531 : :
9532 : 0 : l->action_data_size_max = action_data_size_max;
9533 : :
9534 : 0 : l->hf = hf;
9535 : :
9536 : 0 : l->size = size;
9537 : :
9538 [ # # ]: 0 : for (i = 0; i < n_timeouts; i++)
9539 : 0 : l->timeout[i] = timeout[i];
9540 : :
9541 : 0 : l->n_timeouts = n_timeouts;
9542 : :
9543 : 0 : l->id = p->n_learners;
9544 : :
9545 : : /* Node add to tailq. */
9546 : 0 : TAILQ_INSERT_TAIL(&p->learners, l, node);
9547 : 0 : p->n_learners++;
9548 : :
9549 : 0 : return 0;
9550 : :
9551 : 0 : error:
9552 [ # # ]: 0 : if (!l)
9553 : : return status;
9554 : :
9555 : 0 : free(l->action_is_for_default_entry);
9556 : 0 : free(l->action_is_for_table_entries);
9557 : 0 : free(l->default_action_data);
9558 : 0 : free(l->actions);
9559 : 0 : free(l->fields);
9560 : 0 : free(l);
9561 : :
9562 : 0 : return status;
9563 : : }
9564 : :
9565 : : static uint32_t
9566 : : learner_params_offset_get(struct learner *l)
9567 : : {
9568 : : struct field *first;
9569 : : uint32_t i;
9570 : :
9571 : 0 : first = l->fields[0];
9572 : :
9573 [ # # ]: 0 : for (i = 1; i < l->n_fields; i++) {
9574 : 0 : struct field *f = l->fields[i];
9575 : :
9576 [ # # ]: 0 : if (f->offset < first->offset)
9577 : : first = f;
9578 : : }
9579 : :
9580 : 0 : return first->offset / 8;
9581 : : }
9582 : :
9583 : : static void
9584 : 0 : learner_params_free(struct rte_swx_table_learner_params *params)
9585 : : {
9586 [ # # ]: 0 : if (!params)
9587 : : return;
9588 : :
9589 : 0 : free(params->key_mask0);
9590 : :
9591 : 0 : free(params->key_timeout);
9592 : :
9593 : 0 : free(params);
9594 : : }
9595 : :
9596 : : static struct rte_swx_table_learner_params *
9597 : 0 : learner_params_get(struct learner *l)
9598 : : {
9599 : : struct rte_swx_table_learner_params *params = NULL;
9600 : : struct field *first, *last;
9601 : : uint32_t i;
9602 : :
9603 : : /* Memory allocation. */
9604 : 0 : params = calloc(1, sizeof(struct rte_swx_table_learner_params));
9605 [ # # ]: 0 : if (!params)
9606 : 0 : goto error;
9607 : :
9608 : : /* Find first (smallest offset) and last (biggest offset) match fields. */
9609 : 0 : first = l->fields[0];
9610 : : last = l->fields[0];
9611 : :
9612 [ # # ]: 0 : for (i = 0; i < l->n_fields; i++) {
9613 : 0 : struct field *f = l->fields[i];
9614 : :
9615 [ # # ]: 0 : if (f->offset < first->offset)
9616 : : first = f;
9617 : :
9618 [ # # ]: 0 : if (f->offset > last->offset)
9619 : : last = f;
9620 : : }
9621 : :
9622 : : /* Key offset and size. */
9623 : 0 : params->key_offset = first->offset / 8;
9624 : 0 : params->key_size = (last->offset + last->n_bits - first->offset) / 8;
9625 : :
9626 : : /* Memory allocation. */
9627 : 0 : params->key_mask0 = calloc(1, params->key_size);
9628 [ # # ]: 0 : if (!params->key_mask0)
9629 : 0 : goto error;
9630 : :
9631 : : /* Key mask. */
9632 [ # # ]: 0 : for (i = 0; i < l->n_fields; i++) {
9633 : 0 : struct field *f = l->fields[i];
9634 : 0 : uint32_t start = (f->offset - first->offset) / 8;
9635 : 0 : size_t size = f->n_bits / 8;
9636 : :
9637 : 0 : memset(¶ms->key_mask0[start], 0xFF, size);
9638 : : }
9639 : :
9640 : : /* Action data size. */
9641 : 0 : params->action_data_size = l->action_data_size_max;
9642 : :
9643 : : /* Hash function. */
9644 [ # # ]: 0 : params->hash_func = l->hf ? l->hf->func : NULL;
9645 : :
9646 : : /* Maximum number of keys. */
9647 : 0 : params->n_keys_max = l->size;
9648 : :
9649 : : /* Memory allocation. */
9650 : 0 : params->key_timeout = calloc(l->n_timeouts, sizeof(uint32_t));
9651 [ # # ]: 0 : if (!params->key_timeout)
9652 : 0 : goto error;
9653 : :
9654 : : /* Timeout. */
9655 [ # # ]: 0 : for (i = 0; i < l->n_timeouts; i++)
9656 : 0 : params->key_timeout[i] = l->timeout[i];
9657 : :
9658 : 0 : params->n_key_timeouts = l->n_timeouts;
9659 : :
9660 : 0 : return params;
9661 : :
9662 : 0 : error:
9663 : 0 : learner_params_free(params);
9664 : 0 : return NULL;
9665 : : }
9666 : :
9667 : : static void
9668 : 0 : learner_build_free(struct rte_swx_pipeline *p)
9669 : : {
9670 : : uint32_t i;
9671 : :
9672 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9673 : : struct thread *t = &p->threads[i];
9674 : : uint32_t j;
9675 : :
9676 [ # # ]: 0 : if (!t->learners)
9677 : 0 : continue;
9678 : :
9679 [ # # ]: 0 : for (j = 0; j < p->n_learners; j++) {
9680 : 0 : struct learner_runtime *r = &t->learners[j];
9681 : :
9682 : 0 : free(r->mailbox);
9683 : : }
9684 : :
9685 : 0 : free(t->learners);
9686 : 0 : t->learners = NULL;
9687 : : }
9688 : :
9689 [ # # ]: 0 : if (p->learner_stats) {
9690 [ # # ]: 0 : for (i = 0; i < p->n_learners; i++)
9691 : 0 : free(p->learner_stats[i].n_pkts_action);
9692 : :
9693 : 0 : free(p->learner_stats);
9694 : 0 : p->learner_stats = NULL;
9695 : : }
9696 : 0 : }
9697 : :
9698 : : static int
9699 : 0 : learner_build(struct rte_swx_pipeline *p)
9700 : : {
9701 : : uint32_t i;
9702 : : int status = 0;
9703 : :
9704 : : /* Per pipeline: learner statistics. */
9705 : 0 : p->learner_stats = calloc(p->n_learners, sizeof(struct learner_statistics));
9706 [ # # ]: 0 : CHECK(p->learner_stats, ENOMEM);
9707 : :
9708 [ # # ]: 0 : for (i = 0; i < p->n_learners; i++) {
9709 : 0 : p->learner_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
9710 [ # # ]: 0 : CHECK(p->learner_stats[i].n_pkts_action, ENOMEM);
9711 : : }
9712 : :
9713 : : /* Per thread: learner run-time. */
9714 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9715 : : struct thread *t = &p->threads[i];
9716 : : struct learner *l;
9717 : :
9718 : 0 : t->learners = calloc(p->n_learners, sizeof(struct learner_runtime));
9719 [ # # ]: 0 : if (!t->learners) {
9720 : : status = -ENOMEM;
9721 : 0 : goto error;
9722 : : }
9723 : :
9724 [ # # ]: 0 : TAILQ_FOREACH(l, &p->learners, node) {
9725 : 0 : struct learner_runtime *r = &t->learners[l->id];
9726 : : uint64_t size;
9727 : :
9728 : : /* r->mailbox. */
9729 : 0 : size = rte_swx_table_learner_mailbox_size_get();
9730 [ # # ]: 0 : if (size) {
9731 : 0 : r->mailbox = calloc(1, size);
9732 [ # # ]: 0 : if (!r->mailbox) {
9733 : : status = -ENOMEM;
9734 : 0 : goto error;
9735 : : }
9736 : : }
9737 : :
9738 : : /* r->key. */
9739 : 0 : r->key = l->header ?
9740 [ # # ]: 0 : &t->structs[l->header->struct_id] :
9741 : 0 : &t->structs[p->metadata_struct_id];
9742 : : }
9743 : : }
9744 : :
9745 : : return 0;
9746 : :
9747 : 0 : error:
9748 : 0 : learner_build_free(p);
9749 : 0 : return status;
9750 : : }
9751 : :
9752 : : static void
9753 : 0 : learner_free(struct rte_swx_pipeline *p)
9754 : : {
9755 : 0 : learner_build_free(p);
9756 : :
9757 : : /* Learner tables. */
9758 : 0 : for ( ; ; ) {
9759 : : struct learner *l;
9760 : :
9761 : 0 : l = TAILQ_FIRST(&p->learners);
9762 [ # # ]: 0 : if (!l)
9763 : : break;
9764 : :
9765 [ # # ]: 0 : TAILQ_REMOVE(&p->learners, l, node);
9766 : 0 : free(l->fields);
9767 : 0 : free(l->actions);
9768 : 0 : free(l->default_action_data);
9769 : 0 : free(l);
9770 : : }
9771 : 0 : }
9772 : :
9773 : : /*
9774 : : * Table state.
9775 : : */
9776 : : static int
9777 : 0 : table_state_build(struct rte_swx_pipeline *p)
9778 : : {
9779 : : struct table *table;
9780 : : struct selector *s;
9781 : : struct learner *l;
9782 : :
9783 : 0 : p->table_state = calloc(p->n_tables + p->n_selectors + p->n_learners,
9784 : : sizeof(struct rte_swx_table_state));
9785 [ # # ]: 0 : CHECK(p->table_state, ENOMEM);
9786 : :
9787 [ # # ]: 0 : TAILQ_FOREACH(table, &p->tables, node) {
9788 : 0 : struct rte_swx_table_state *ts = &p->table_state[table->id];
9789 : :
9790 [ # # ]: 0 : if (table->type) {
9791 : : struct rte_swx_table_params *params;
9792 : :
9793 : : /* ts->obj. */
9794 : 0 : params = table_params_get(table);
9795 [ # # ]: 0 : CHECK(params, ENOMEM);
9796 : :
9797 : 0 : ts->obj = table->type->ops.create(params,
9798 : : NULL,
9799 : 0 : table->args,
9800 : : p->numa_node);
9801 : :
9802 : 0 : table_params_free(params);
9803 [ # # ]: 0 : CHECK(ts->obj, ENODEV);
9804 : : }
9805 : :
9806 : : /* ts->default_action_data. */
9807 [ # # ]: 0 : if (table->action_data_size_max) {
9808 : 0 : ts->default_action_data =
9809 : 0 : malloc(table->action_data_size_max);
9810 [ # # ]: 0 : CHECK(ts->default_action_data, ENOMEM);
9811 : :
9812 : : memcpy(ts->default_action_data,
9813 : 0 : table->default_action_data,
9814 : : table->action_data_size_max);
9815 : : }
9816 : :
9817 : : /* ts->default_action_id. */
9818 : 0 : ts->default_action_id = table->default_action->id;
9819 : : }
9820 : :
9821 [ # # ]: 0 : TAILQ_FOREACH(s, &p->selectors, node) {
9822 : 0 : struct rte_swx_table_state *ts = &p->table_state[p->n_tables + s->id];
9823 : : struct rte_swx_table_selector_params *params;
9824 : :
9825 : : /* ts->obj. */
9826 : 0 : params = selector_table_params_get(s);
9827 [ # # ]: 0 : CHECK(params, ENOMEM);
9828 : :
9829 : 0 : ts->obj = rte_swx_table_selector_create(params, NULL, p->numa_node);
9830 : :
9831 : 0 : selector_params_free(params);
9832 [ # # ]: 0 : CHECK(ts->obj, ENODEV);
9833 : : }
9834 : :
9835 [ # # ]: 0 : TAILQ_FOREACH(l, &p->learners, node) {
9836 : 0 : struct rte_swx_table_state *ts = &p->table_state[p->n_tables +
9837 : 0 : p->n_selectors + l->id];
9838 : : struct rte_swx_table_learner_params *params;
9839 : :
9840 : : /* ts->obj. */
9841 : 0 : params = learner_params_get(l);
9842 [ # # ]: 0 : CHECK(params, ENOMEM);
9843 : :
9844 : 0 : ts->obj = rte_swx_table_learner_create(params, p->numa_node);
9845 : 0 : learner_params_free(params);
9846 [ # # ]: 0 : CHECK(ts->obj, ENODEV);
9847 : :
9848 : : /* ts->default_action_data. */
9849 [ # # ]: 0 : if (l->action_data_size_max) {
9850 : 0 : ts->default_action_data = malloc(l->action_data_size_max);
9851 [ # # ]: 0 : CHECK(ts->default_action_data, ENOMEM);
9852 : :
9853 : : memcpy(ts->default_action_data,
9854 : 0 : l->default_action_data,
9855 : : l->action_data_size_max);
9856 : : }
9857 : :
9858 : : /* ts->default_action_id. */
9859 : 0 : ts->default_action_id = l->default_action->id;
9860 : : }
9861 : :
9862 : : return 0;
9863 : : }
9864 : :
9865 : : static void
9866 : 0 : table_state_build_free(struct rte_swx_pipeline *p)
9867 : : {
9868 : : uint32_t i;
9869 : :
9870 [ # # ]: 0 : if (!p->table_state)
9871 : : return;
9872 : :
9873 [ # # ]: 0 : for (i = 0; i < p->n_tables; i++) {
9874 : 0 : struct rte_swx_table_state *ts = &p->table_state[i];
9875 : : struct table *table = table_find_by_id(p, i);
9876 : :
9877 : : /* ts->obj. */
9878 [ # # # # ]: 0 : if (table->type && ts->obj)
9879 : 0 : table->type->ops.free(ts->obj);
9880 : :
9881 : : /* ts->default_action_data. */
9882 : 0 : free(ts->default_action_data);
9883 : : }
9884 : :
9885 [ # # ]: 0 : for (i = 0; i < p->n_selectors; i++) {
9886 : 0 : struct rte_swx_table_state *ts = &p->table_state[p->n_tables + i];
9887 : :
9888 : : /* ts->obj. */
9889 : 0 : rte_swx_table_selector_free(ts->obj);
9890 : : }
9891 : :
9892 [ # # ]: 0 : for (i = 0; i < p->n_learners; i++) {
9893 : 0 : struct rte_swx_table_state *ts = &p->table_state[p->n_tables + p->n_selectors + i];
9894 : :
9895 : : /* ts->obj. */
9896 : 0 : rte_swx_table_learner_free(ts->obj);
9897 : :
9898 : : /* ts->default_action_data. */
9899 : 0 : free(ts->default_action_data);
9900 : : }
9901 : :
9902 : 0 : free(p->table_state);
9903 : 0 : p->table_state = NULL;
9904 : : }
9905 : :
9906 : : static void
9907 : : table_state_free(struct rte_swx_pipeline *p)
9908 : : {
9909 : 0 : table_state_build_free(p);
9910 : : }
9911 : :
9912 : : /*
9913 : : * Register array.
9914 : : */
9915 : : static struct regarray *
9916 : : regarray_find(struct rte_swx_pipeline *p, const char *name)
9917 : : {
9918 : : struct regarray *elem;
9919 : :
9920 [ # # # # : 0 : TAILQ_FOREACH(elem, &p->regarrays, node)
# # # # #
# # # #
# ]
9921 [ # # # # : 0 : if (!strcmp(elem->name, name))
# # # # #
# # # #
# ]
9922 : : return elem;
9923 : :
9924 : : return NULL;
9925 : : }
9926 : :
9927 : : static struct regarray *
9928 : : regarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9929 : : {
9930 : : struct regarray *elem = NULL;
9931 : :
9932 [ # # # # ]: 0 : TAILQ_FOREACH(elem, &p->regarrays, node)
9933 [ # # # # ]: 0 : if (elem->id == id)
9934 : : return elem;
9935 : :
9936 : : return NULL;
9937 : : }
9938 : :
9939 : : int
9940 : 0 : rte_swx_pipeline_regarray_config(struct rte_swx_pipeline *p,
9941 : : const char *name,
9942 : : uint32_t size,
9943 : : uint64_t init_val)
9944 : : {
9945 : : struct regarray *r;
9946 : :
9947 [ # # ]: 0 : CHECK(p, EINVAL);
9948 : :
9949 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
9950 [ # # ]: 0 : CHECK(!regarray_find(p, name), EEXIST);
9951 : :
9952 [ # # ]: 0 : CHECK(size, EINVAL);
9953 : : size = rte_align32pow2(size);
9954 : :
9955 : : /* Memory allocation. */
9956 : 0 : r = calloc(1, sizeof(struct regarray));
9957 [ # # ]: 0 : CHECK(r, ENOMEM);
9958 : :
9959 : : /* Node initialization. */
9960 : 0 : strcpy(r->name, name);
9961 : 0 : r->init_val = init_val;
9962 : 0 : r->size = size;
9963 : 0 : r->id = p->n_regarrays;
9964 : :
9965 : : /* Node add to tailq. */
9966 : 0 : TAILQ_INSERT_TAIL(&p->regarrays, r, node);
9967 : 0 : p->n_regarrays++;
9968 : :
9969 : 0 : return 0;
9970 : : }
9971 : :
9972 : : static int
9973 : 0 : regarray_build(struct rte_swx_pipeline *p)
9974 : : {
9975 : : struct regarray *regarray;
9976 : :
9977 [ # # ]: 0 : if (!p->n_regarrays)
9978 : : return 0;
9979 : :
9980 : 0 : p->regarray_runtime = calloc(p->n_regarrays, sizeof(struct regarray_runtime));
9981 [ # # ]: 0 : CHECK(p->regarray_runtime, ENOMEM);
9982 : :
9983 [ # # ]: 0 : TAILQ_FOREACH(regarray, &p->regarrays, node) {
9984 : 0 : struct regarray_runtime *r = &p->regarray_runtime[regarray->id];
9985 : : uint32_t i;
9986 : :
9987 : 0 : r->regarray = env_malloc(regarray->size * sizeof(uint64_t),
9988 : : RTE_CACHE_LINE_SIZE,
9989 : : p->numa_node);
9990 [ # # ]: 0 : CHECK(r->regarray, ENOMEM);
9991 : :
9992 [ # # ]: 0 : if (regarray->init_val)
9993 [ # # ]: 0 : for (i = 0; i < regarray->size; i++)
9994 : 0 : r->regarray[i] = regarray->init_val;
9995 : :
9996 : 0 : r->size_mask = regarray->size - 1;
9997 : : }
9998 : :
9999 : : return 0;
10000 : : }
10001 : :
10002 : : static void
10003 : 0 : regarray_build_free(struct rte_swx_pipeline *p)
10004 : : {
10005 : : uint32_t i;
10006 : :
10007 [ # # ]: 0 : if (!p->regarray_runtime)
10008 : : return;
10009 : :
10010 [ # # ]: 0 : for (i = 0; i < p->n_regarrays; i++) {
10011 : : struct regarray *regarray = regarray_find_by_id(p, i);
10012 : 0 : struct regarray_runtime *r = &p->regarray_runtime[i];
10013 : :
10014 : 0 : env_free(r->regarray, regarray->size * sizeof(uint64_t));
10015 : : }
10016 : :
10017 : 0 : free(p->regarray_runtime);
10018 : 0 : p->regarray_runtime = NULL;
10019 : : }
10020 : :
10021 : : static void
10022 : 0 : regarray_free(struct rte_swx_pipeline *p)
10023 : : {
10024 : 0 : regarray_build_free(p);
10025 : :
10026 : 0 : for ( ; ; ) {
10027 : : struct regarray *elem;
10028 : :
10029 : 0 : elem = TAILQ_FIRST(&p->regarrays);
10030 [ # # ]: 0 : if (!elem)
10031 : : break;
10032 : :
10033 [ # # ]: 0 : TAILQ_REMOVE(&p->regarrays, elem, node);
10034 : 0 : free(elem);
10035 : : }
10036 : 0 : }
10037 : :
10038 : : /*
10039 : : * Meter array.
10040 : : */
10041 : : static struct meter_profile *
10042 : : meter_profile_find(struct rte_swx_pipeline *p, const char *name)
10043 : : {
10044 : : struct meter_profile *elem;
10045 : :
10046 [ # # # # : 0 : TAILQ_FOREACH(elem, &p->meter_profiles, node)
# # ]
10047 [ # # # # : 0 : if (!strcmp(elem->name, name))
# # ]
10048 : : return elem;
10049 : :
10050 : : return NULL;
10051 : : }
10052 : :
10053 : : static struct metarray *
10054 : : metarray_find(struct rte_swx_pipeline *p, const char *name)
10055 : : {
10056 : : struct metarray *elem;
10057 : :
10058 [ # # # # : 0 : TAILQ_FOREACH(elem, &p->metarrays, node)
# # # # #
# # # ]
10059 [ # # # # : 0 : if (!strcmp(elem->name, name))
# # # # #
# # # ]
10060 : : return elem;
10061 : :
10062 : : return NULL;
10063 : : }
10064 : :
10065 : : static struct metarray *
10066 : : metarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
10067 : : {
10068 : : struct metarray *elem = NULL;
10069 : :
10070 [ # # # # ]: 0 : TAILQ_FOREACH(elem, &p->metarrays, node)
10071 [ # # # # ]: 0 : if (elem->id == id)
10072 : : return elem;
10073 : :
10074 : : return NULL;
10075 : : }
10076 : :
10077 : : int
10078 : 0 : rte_swx_pipeline_metarray_config(struct rte_swx_pipeline *p,
10079 : : const char *name,
10080 : : uint32_t size)
10081 : : {
10082 : : struct metarray *m;
10083 : :
10084 [ # # ]: 0 : CHECK(p, EINVAL);
10085 : :
10086 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
10087 [ # # ]: 0 : CHECK(!metarray_find(p, name), EEXIST);
10088 : :
10089 [ # # ]: 0 : CHECK(size, EINVAL);
10090 : : size = rte_align32pow2(size);
10091 : :
10092 : : /* Memory allocation. */
10093 : 0 : m = calloc(1, sizeof(struct metarray));
10094 [ # # ]: 0 : CHECK(m, ENOMEM);
10095 : :
10096 : : /* Node initialization. */
10097 : 0 : strcpy(m->name, name);
10098 : 0 : m->size = size;
10099 : 0 : m->id = p->n_metarrays;
10100 : :
10101 : : /* Node add to tailq. */
10102 : 0 : TAILQ_INSERT_TAIL(&p->metarrays, m, node);
10103 : 0 : p->n_metarrays++;
10104 : :
10105 : 0 : return 0;
10106 : : }
10107 : :
10108 : : struct meter_profile meter_profile_default = {
10109 : : .node = {0},
10110 : : .name = "",
10111 : : .params = {0},
10112 : :
10113 : : .profile = {
10114 : : .cbs = 10000,
10115 : : .pbs = 10000,
10116 : : .cir_period = 1,
10117 : : .cir_bytes_per_period = 1,
10118 : : .pir_period = 1,
10119 : : .pir_bytes_per_period = 1,
10120 : : },
10121 : :
10122 : : .n_users = 0,
10123 : : };
10124 : :
10125 : : static void
10126 : 0 : meter_init(struct meter *m)
10127 : : {
10128 : : memset(m, 0, sizeof(struct meter));
10129 : 0 : rte_meter_trtcm_config(&m->m, &meter_profile_default.profile);
10130 : 0 : m->profile = &meter_profile_default;
10131 : 0 : m->color_mask = RTE_COLOR_GREEN;
10132 : :
10133 : 0 : meter_profile_default.n_users++;
10134 : 0 : }
10135 : :
10136 : : static int
10137 : 0 : metarray_build(struct rte_swx_pipeline *p)
10138 : : {
10139 : : struct metarray *m;
10140 : :
10141 [ # # ]: 0 : if (!p->n_metarrays)
10142 : : return 0;
10143 : :
10144 : 0 : p->metarray_runtime = calloc(p->n_metarrays, sizeof(struct metarray_runtime));
10145 [ # # ]: 0 : CHECK(p->metarray_runtime, ENOMEM);
10146 : :
10147 [ # # ]: 0 : TAILQ_FOREACH(m, &p->metarrays, node) {
10148 : 0 : struct metarray_runtime *r = &p->metarray_runtime[m->id];
10149 : : uint32_t i;
10150 : :
10151 : 0 : r->metarray = env_malloc(m->size * sizeof(struct meter),
10152 : : RTE_CACHE_LINE_SIZE,
10153 : : p->numa_node);
10154 [ # # ]: 0 : CHECK(r->metarray, ENOMEM);
10155 : :
10156 [ # # ]: 0 : for (i = 0; i < m->size; i++)
10157 : 0 : meter_init(&r->metarray[i]);
10158 : :
10159 : 0 : r->size_mask = m->size - 1;
10160 : : }
10161 : :
10162 : : return 0;
10163 : : }
10164 : :
10165 : : static void
10166 : 0 : metarray_build_free(struct rte_swx_pipeline *p)
10167 : : {
10168 : : uint32_t i;
10169 : :
10170 [ # # ]: 0 : if (!p->metarray_runtime)
10171 : : return;
10172 : :
10173 [ # # ]: 0 : for (i = 0; i < p->n_metarrays; i++) {
10174 : : struct metarray *m = metarray_find_by_id(p, i);
10175 : 0 : struct metarray_runtime *r = &p->metarray_runtime[i];
10176 : :
10177 : 0 : env_free(r->metarray, m->size * sizeof(struct meter));
10178 : : }
10179 : :
10180 : 0 : free(p->metarray_runtime);
10181 : 0 : p->metarray_runtime = NULL;
10182 : : }
10183 : :
10184 : : static void
10185 : 0 : metarray_free(struct rte_swx_pipeline *p)
10186 : : {
10187 : 0 : metarray_build_free(p);
10188 : :
10189 : : /* Meter arrays. */
10190 : 0 : for ( ; ; ) {
10191 : : struct metarray *elem;
10192 : :
10193 : 0 : elem = TAILQ_FIRST(&p->metarrays);
10194 [ # # ]: 0 : if (!elem)
10195 : : break;
10196 : :
10197 [ # # ]: 0 : TAILQ_REMOVE(&p->metarrays, elem, node);
10198 : 0 : free(elem);
10199 : : }
10200 : :
10201 : : /* Meter profiles. */
10202 : 0 : for ( ; ; ) {
10203 : : struct meter_profile *elem;
10204 : :
10205 : 0 : elem = TAILQ_FIRST(&p->meter_profiles);
10206 [ # # ]: 0 : if (!elem)
10207 : : break;
10208 : :
10209 [ # # ]: 0 : TAILQ_REMOVE(&p->meter_profiles, elem, node);
10210 : 0 : free(elem);
10211 : : }
10212 : 0 : }
10213 : :
10214 : : /*
10215 : : * Pipeline.
10216 : : */
10217 : :
10218 : : /* Global list of pipeline instances. */
10219 : : TAILQ_HEAD(rte_swx_pipeline_list, rte_tailq_entry);
10220 : :
10221 : : static struct rte_tailq_elem rte_swx_pipeline_tailq = {
10222 : : .name = "RTE_SWX_PIPELINE",
10223 : : };
10224 : :
10225 [ - + ]: 252 : EAL_REGISTER_TAILQ(rte_swx_pipeline_tailq)
10226 : :
10227 : : struct rte_swx_pipeline *
10228 : 0 : rte_swx_pipeline_find(const char *name)
10229 : : {
10230 : : struct rte_swx_pipeline_list *pipeline_list;
10231 : : struct rte_tailq_entry *te = NULL;
10232 : :
10233 [ # # # # : 0 : if (!name || !name[0] || (strnlen(name, RTE_SWX_NAME_SIZE) >= RTE_SWX_NAME_SIZE))
# # ]
10234 : : return NULL;
10235 : :
10236 : 0 : pipeline_list = RTE_TAILQ_CAST(rte_swx_pipeline_tailq.head, rte_swx_pipeline_list);
10237 : :
10238 : 0 : rte_mcfg_tailq_read_lock();
10239 : :
10240 [ # # ]: 0 : TAILQ_FOREACH(te, pipeline_list, next) {
10241 : 0 : struct rte_swx_pipeline *p = (struct rte_swx_pipeline *)te->data;
10242 : :
10243 [ # # ]: 0 : if (!strncmp(name, p->name, sizeof(p->name))) {
10244 : 0 : rte_mcfg_tailq_read_unlock();
10245 : 0 : return p;
10246 : : }
10247 : : }
10248 : :
10249 : 0 : rte_mcfg_tailq_read_unlock();
10250 : 0 : return NULL;
10251 : : }
10252 : :
10253 : : static int
10254 : 0 : pipeline_register(struct rte_swx_pipeline *p)
10255 : : {
10256 : : struct rte_swx_pipeline_list *pipeline_list;
10257 : : struct rte_tailq_entry *te = NULL;
10258 : :
10259 : 0 : pipeline_list = RTE_TAILQ_CAST(rte_swx_pipeline_tailq.head, rte_swx_pipeline_list);
10260 : :
10261 : 0 : rte_mcfg_tailq_write_lock();
10262 : :
10263 [ # # ]: 0 : TAILQ_FOREACH(te, pipeline_list, next) {
10264 : 0 : struct rte_swx_pipeline *pipeline = (struct rte_swx_pipeline *)te->data;
10265 : :
10266 [ # # ]: 0 : if (!strncmp(p->name, pipeline->name, sizeof(p->name))) {
10267 : 0 : rte_mcfg_tailq_write_unlock();
10268 : 0 : return -EEXIST;
10269 : : }
10270 : : }
10271 : :
10272 : 0 : te = calloc(1, sizeof(struct rte_tailq_entry));
10273 [ # # ]: 0 : if (!te) {
10274 : 0 : rte_mcfg_tailq_write_unlock();
10275 : 0 : return -ENOMEM;
10276 : : }
10277 : :
10278 : 0 : te->data = (void *)p;
10279 : 0 : TAILQ_INSERT_TAIL(pipeline_list, te, next);
10280 : 0 : rte_mcfg_tailq_write_unlock();
10281 : 0 : return 0;
10282 : : }
10283 : :
10284 : : static void
10285 : 0 : pipeline_unregister(struct rte_swx_pipeline *p)
10286 : : {
10287 : : struct rte_swx_pipeline_list *pipeline_list;
10288 : : struct rte_tailq_entry *te = NULL;
10289 : :
10290 : 0 : pipeline_list = RTE_TAILQ_CAST(rte_swx_pipeline_tailq.head, rte_swx_pipeline_list);
10291 : :
10292 : 0 : rte_mcfg_tailq_write_lock();
10293 : :
10294 [ # # ]: 0 : TAILQ_FOREACH(te, pipeline_list, next) {
10295 [ # # ]: 0 : if (te->data == (void *)p) {
10296 [ # # ]: 0 : TAILQ_REMOVE(pipeline_list, te, next);
10297 : 0 : rte_mcfg_tailq_write_unlock();
10298 : 0 : free(te);
10299 : 0 : return;
10300 : : }
10301 : : }
10302 : :
10303 : 0 : rte_mcfg_tailq_write_unlock();
10304 : : }
10305 : :
10306 : : void
10307 : 0 : rte_swx_pipeline_free(struct rte_swx_pipeline *p)
10308 : : {
10309 : : void *lib;
10310 : :
10311 [ # # ]: 0 : if (!p)
10312 : : return;
10313 : :
10314 [ # # ]: 0 : if (p->name[0])
10315 : 0 : pipeline_unregister(p);
10316 : :
10317 : 0 : lib = p->lib;
10318 : :
10319 : 0 : free(p->instruction_data);
10320 : 0 : free(p->instructions);
10321 : :
10322 : 0 : metarray_free(p);
10323 : 0 : regarray_free(p);
10324 : : table_state_free(p);
10325 : 0 : learner_free(p);
10326 : 0 : selector_free(p);
10327 : 0 : table_free(p);
10328 : 0 : action_free(p);
10329 : : instruction_table_free(p);
10330 : : metadata_free(p);
10331 : 0 : header_free(p);
10332 : 0 : rss_free(p);
10333 : 0 : hash_func_free(p);
10334 : 0 : extern_func_free(p);
10335 : 0 : extern_obj_free(p);
10336 : : mirroring_free(p);
10337 : 0 : port_out_free(p);
10338 : 0 : port_in_free(p);
10339 : 0 : struct_free(p);
10340 : :
10341 : 0 : free(p);
10342 : :
10343 [ # # ]: 0 : if (lib)
10344 : 0 : dlclose(lib);
10345 : : }
10346 : :
10347 : : static int
10348 : 0 : port_in_types_register(struct rte_swx_pipeline *p)
10349 : : {
10350 : : int status;
10351 : :
10352 : 0 : status = rte_swx_pipeline_port_in_type_register(p,
10353 : : "ethdev",
10354 : : &rte_swx_port_ethdev_reader_ops);
10355 [ # # ]: 0 : if (status)
10356 : : return status;
10357 : :
10358 : 0 : status = rte_swx_pipeline_port_in_type_register(p,
10359 : : "ring",
10360 : : &rte_swx_port_ring_reader_ops);
10361 [ # # ]: 0 : if (status)
10362 : : return status;
10363 : :
10364 : : #ifdef RTE_PORT_PCAP
10365 : 0 : status = rte_swx_pipeline_port_in_type_register(p,
10366 : : "source",
10367 : : &rte_swx_port_source_ops);
10368 [ # # ]: 0 : if (status)
10369 : : return status;
10370 : : #endif
10371 : :
10372 : 0 : status = rte_swx_pipeline_port_in_type_register(p,
10373 : : "fd",
10374 : : &rte_swx_port_fd_reader_ops);
10375 [ # # ]: 0 : if (status)
10376 : 0 : return status;
10377 : :
10378 : : return 0;
10379 : : }
10380 : :
10381 : : static int
10382 : 0 : port_out_types_register(struct rte_swx_pipeline *p)
10383 : : {
10384 : : int status;
10385 : :
10386 : 0 : status = rte_swx_pipeline_port_out_type_register(p,
10387 : : "ethdev",
10388 : : &rte_swx_port_ethdev_writer_ops);
10389 [ # # ]: 0 : if (status)
10390 : : return status;
10391 : :
10392 : 0 : status = rte_swx_pipeline_port_out_type_register(p,
10393 : : "ring",
10394 : : &rte_swx_port_ring_writer_ops);
10395 [ # # ]: 0 : if (status)
10396 : : return status;
10397 : :
10398 : 0 : status = rte_swx_pipeline_port_out_type_register(p,
10399 : : "sink",
10400 : : &rte_swx_port_sink_ops);
10401 [ # # ]: 0 : if (status)
10402 : : return status;
10403 : :
10404 : 0 : status = rte_swx_pipeline_port_out_type_register(p,
10405 : : "fd",
10406 : : &rte_swx_port_fd_writer_ops);
10407 [ # # ]: 0 : if (status)
10408 : 0 : return status;
10409 : :
10410 : : return 0;
10411 : : }
10412 : :
10413 : : static int
10414 : 0 : table_types_register(struct rte_swx_pipeline *p)
10415 : : {
10416 : : int status;
10417 : :
10418 : 0 : status = rte_swx_pipeline_table_type_register(p,
10419 : : "exact",
10420 : : RTE_SWX_TABLE_MATCH_EXACT,
10421 : : &rte_swx_table_exact_match_ops);
10422 [ # # ]: 0 : if (status)
10423 : : return status;
10424 : :
10425 : 0 : status = rte_swx_pipeline_table_type_register(p,
10426 : : "wildcard",
10427 : : RTE_SWX_TABLE_MATCH_WILDCARD,
10428 : : &rte_swx_table_wildcard_match_ops);
10429 [ # # ]: 0 : if (status)
10430 : 0 : return status;
10431 : :
10432 : : return 0;
10433 : : }
10434 : :
10435 : : static int
10436 : 0 : hash_funcs_register(struct rte_swx_pipeline *p)
10437 : : {
10438 : : int status;
10439 : :
10440 : 0 : status = rte_swx_pipeline_hash_func_register(p, "jhash", rte_jhash);
10441 [ # # ]: 0 : if (status)
10442 : : return status;
10443 : :
10444 : 0 : status = rte_swx_pipeline_hash_func_register(p, "crc32", rte_hash_crc);
10445 [ # # ]: 0 : if (status)
10446 : 0 : return status;
10447 : :
10448 : : return 0;
10449 : : }
10450 : :
10451 : : int
10452 : 0 : rte_swx_pipeline_config(struct rte_swx_pipeline **p, const char *name, int numa_node)
10453 : : {
10454 : : struct rte_swx_pipeline *pipeline = NULL;
10455 : : int status = 0;
10456 : :
10457 : : /* Check input parameters. */
10458 [ # # ]: 0 : CHECK(p, EINVAL);
10459 [ # # # # ]: 0 : CHECK(!name || (strnlen(name, RTE_SWX_NAME_SIZE) < RTE_SWX_NAME_SIZE), EINVAL);
10460 : :
10461 : : /* Memory allocation. */
10462 : 0 : pipeline = calloc(1, sizeof(struct rte_swx_pipeline));
10463 [ # # ]: 0 : if (!pipeline) {
10464 : : status = -ENOMEM;
10465 : 0 : goto error;
10466 : : }
10467 : :
10468 : : /* Initialization. */
10469 [ # # ]: 0 : if (name)
10470 : 0 : strcpy(pipeline->name, name);
10471 : :
10472 : 0 : TAILQ_INIT(&pipeline->struct_types);
10473 : 0 : TAILQ_INIT(&pipeline->port_in_types);
10474 : 0 : TAILQ_INIT(&pipeline->ports_in);
10475 : 0 : TAILQ_INIT(&pipeline->port_out_types);
10476 : 0 : TAILQ_INIT(&pipeline->ports_out);
10477 : 0 : TAILQ_INIT(&pipeline->extern_types);
10478 : 0 : TAILQ_INIT(&pipeline->extern_objs);
10479 : 0 : TAILQ_INIT(&pipeline->extern_funcs);
10480 : 0 : TAILQ_INIT(&pipeline->hash_funcs);
10481 : 0 : TAILQ_INIT(&pipeline->rss);
10482 : 0 : TAILQ_INIT(&pipeline->headers);
10483 : 0 : TAILQ_INIT(&pipeline->actions);
10484 : 0 : TAILQ_INIT(&pipeline->table_types);
10485 : 0 : TAILQ_INIT(&pipeline->tables);
10486 : 0 : TAILQ_INIT(&pipeline->selectors);
10487 : 0 : TAILQ_INIT(&pipeline->learners);
10488 : 0 : TAILQ_INIT(&pipeline->regarrays);
10489 : 0 : TAILQ_INIT(&pipeline->meter_profiles);
10490 : 0 : TAILQ_INIT(&pipeline->metarrays);
10491 : :
10492 : 0 : pipeline->n_structs = 1; /* Struct 0 is reserved for action_data. */
10493 : 0 : pipeline->n_mirroring_slots = RTE_SWX_PACKET_MIRRORING_SLOTS_DEFAULT;
10494 : 0 : pipeline->n_mirroring_sessions = RTE_SWX_PACKET_MIRRORING_SESSIONS_DEFAULT;
10495 : 0 : pipeline->numa_node = numa_node;
10496 : :
10497 : 0 : status = port_in_types_register(pipeline);
10498 [ # # ]: 0 : if (status)
10499 : 0 : goto error;
10500 : :
10501 : 0 : status = port_out_types_register(pipeline);
10502 [ # # ]: 0 : if (status)
10503 : 0 : goto error;
10504 : :
10505 : 0 : status = table_types_register(pipeline);
10506 [ # # ]: 0 : if (status)
10507 : 0 : goto error;
10508 : :
10509 : 0 : status = hash_funcs_register(pipeline);
10510 [ # # ]: 0 : if (status)
10511 : 0 : goto error;
10512 : :
10513 [ # # ]: 0 : if (pipeline->name[0]) {
10514 : 0 : status = pipeline_register(pipeline);
10515 [ # # ]: 0 : if (status)
10516 : 0 : goto error;
10517 : : }
10518 : :
10519 : 0 : *p = pipeline;
10520 : 0 : return 0;
10521 : :
10522 : 0 : error:
10523 : 0 : rte_swx_pipeline_free(pipeline);
10524 : 0 : return status;
10525 : : }
10526 : :
10527 : : int
10528 : 0 : rte_swx_pipeline_instructions_config(struct rte_swx_pipeline *p,
10529 : : const char **instructions,
10530 : : uint32_t n_instructions)
10531 : : {
10532 : : int err;
10533 : : uint32_t i;
10534 : :
10535 : 0 : err = instruction_config(p, NULL, instructions, n_instructions);
10536 [ # # ]: 0 : if (err)
10537 : : return err;
10538 : :
10539 : : /* Thread instruction pointer reset. */
10540 [ # # ]: 0 : for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
10541 : : struct thread *t = &p->threads[i];
10542 : :
10543 : : thread_ip_reset(p, t);
10544 : : }
10545 : :
10546 : : return 0;
10547 : : }
10548 : :
10549 : : int
10550 : 0 : rte_swx_pipeline_build(struct rte_swx_pipeline *p)
10551 : : {
10552 : 0 : struct rte_swx_port_sink_params drop_port_params = {
10553 : : .file_name = NULL,
10554 : : };
10555 : : int status;
10556 : :
10557 [ # # ]: 0 : CHECK(p, EINVAL);
10558 [ # # ]: 0 : CHECK(p->build_done == 0, EEXIST);
10559 : :
10560 : 0 : status = port_in_build(p);
10561 [ # # ]: 0 : if (status)
10562 : 0 : goto error;
10563 : :
10564 : : /* Drop port. */
10565 : 0 : status = rte_swx_pipeline_port_out_config(p,
10566 : : p->n_ports_out,
10567 : : "sink",
10568 : : &drop_port_params);
10569 [ # # ]: 0 : if (status)
10570 : 0 : goto error;
10571 : :
10572 : 0 : status = port_out_build(p);
10573 [ # # ]: 0 : if (status)
10574 : 0 : goto error;
10575 : :
10576 : 0 : status = mirroring_build(p);
10577 [ # # ]: 0 : if (status)
10578 : 0 : goto error;
10579 : :
10580 : 0 : status = struct_build(p);
10581 [ # # ]: 0 : if (status)
10582 : 0 : goto error;
10583 : :
10584 : 0 : status = extern_obj_build(p);
10585 [ # # ]: 0 : if (status)
10586 : 0 : goto error;
10587 : :
10588 : 0 : status = extern_func_build(p);
10589 [ # # ]: 0 : if (status)
10590 : 0 : goto error;
10591 : :
10592 : 0 : status = hash_func_build(p);
10593 [ # # ]: 0 : if (status)
10594 : 0 : goto error;
10595 : :
10596 : 0 : status = rss_build(p);
10597 [ # # ]: 0 : if (status)
10598 : 0 : goto error;
10599 : :
10600 : 0 : status = header_build(p);
10601 [ # # ]: 0 : if (status)
10602 : 0 : goto error;
10603 : :
10604 : 0 : status = metadata_build(p);
10605 [ # # ]: 0 : if (status)
10606 : 0 : goto error;
10607 : :
10608 : 0 : status = instruction_table_build(p);
10609 [ # # ]: 0 : if (status)
10610 : 0 : goto error;
10611 : :
10612 : 0 : status = action_build(p);
10613 [ # # ]: 0 : if (status)
10614 : 0 : goto error;
10615 : :
10616 : 0 : status = table_build(p);
10617 [ # # ]: 0 : if (status)
10618 : 0 : goto error;
10619 : :
10620 : 0 : status = selector_build(p);
10621 [ # # ]: 0 : if (status)
10622 : 0 : goto error;
10623 : :
10624 : 0 : status = learner_build(p);
10625 [ # # ]: 0 : if (status)
10626 : 0 : goto error;
10627 : :
10628 : 0 : status = table_state_build(p);
10629 [ # # ]: 0 : if (status)
10630 : 0 : goto error;
10631 : :
10632 : 0 : status = regarray_build(p);
10633 [ # # ]: 0 : if (status)
10634 : 0 : goto error;
10635 : :
10636 : 0 : status = metarray_build(p);
10637 [ # # ]: 0 : if (status)
10638 : 0 : goto error;
10639 : :
10640 : 0 : p->build_done = 1;
10641 : :
10642 : 0 : return 0;
10643 : :
10644 : 0 : error:
10645 : 0 : metarray_build_free(p);
10646 : 0 : regarray_build_free(p);
10647 : 0 : table_state_build_free(p);
10648 : 0 : learner_build_free(p);
10649 : 0 : selector_build_free(p);
10650 : 0 : table_build_free(p);
10651 : : action_build_free(p);
10652 : : instruction_table_build_free(p);
10653 : : metadata_build_free(p);
10654 : 0 : header_build_free(p);
10655 : 0 : rss_build_free(p);
10656 : : hash_func_build_free(p);
10657 : 0 : extern_func_build_free(p);
10658 : 0 : extern_obj_build_free(p);
10659 : 0 : mirroring_build_free(p);
10660 : : port_out_build_free(p);
10661 : : port_in_build_free(p);
10662 : : struct_build_free(p);
10663 : :
10664 : : return status;
10665 : : }
10666 : :
10667 : : void
10668 : 0 : rte_swx_pipeline_run(struct rte_swx_pipeline *p, uint32_t n_instructions)
10669 : : {
10670 : : uint32_t i;
10671 : :
10672 [ # # ]: 0 : for (i = 0; i < n_instructions; i++)
10673 : : instr_exec(p);
10674 : 0 : }
10675 : :
10676 : : void
10677 : 0 : rte_swx_pipeline_flush(struct rte_swx_pipeline *p)
10678 : : {
10679 : : uint32_t i;
10680 : :
10681 [ # # ]: 0 : for (i = 0; i < p->n_ports_out; i++) {
10682 : 0 : struct port_out_runtime *port = &p->out[i];
10683 : :
10684 [ # # ]: 0 : if (port->flush)
10685 : 0 : port->flush(port->obj);
10686 : : }
10687 : 0 : }
10688 : :
10689 : : /*
10690 : : * Control.
10691 : : */
10692 : : int
10693 : 0 : rte_swx_ctl_pipeline_info_get(struct rte_swx_pipeline *p,
10694 : : struct rte_swx_ctl_pipeline_info *pipeline)
10695 : : {
10696 : : struct action *action;
10697 : : struct table *table;
10698 : : uint32_t n_actions = 0, n_tables = 0;
10699 : :
10700 [ # # ]: 0 : if (!p || !pipeline)
10701 : : return -EINVAL;
10702 : :
10703 [ # # ]: 0 : TAILQ_FOREACH(action, &p->actions, node)
10704 : 0 : n_actions++;
10705 : :
10706 [ # # ]: 0 : TAILQ_FOREACH(table, &p->tables, node)
10707 : 0 : n_tables++;
10708 : :
10709 : 0 : strcpy(pipeline->name, p->name);
10710 : 0 : pipeline->n_ports_in = p->n_ports_in;
10711 : 0 : pipeline->n_ports_out = p->n_ports_out;
10712 : 0 : pipeline->n_mirroring_slots = p->n_mirroring_slots;
10713 : 0 : pipeline->n_mirroring_sessions = p->n_mirroring_sessions;
10714 : 0 : pipeline->n_actions = n_actions;
10715 : 0 : pipeline->n_tables = n_tables;
10716 : 0 : pipeline->n_selectors = p->n_selectors;
10717 : 0 : pipeline->n_learners = p->n_learners;
10718 : 0 : pipeline->n_regarrays = p->n_regarrays;
10719 : 0 : pipeline->n_metarrays = p->n_metarrays;
10720 : 0 : pipeline->n_rss = p->n_rss;
10721 : :
10722 : 0 : return 0;
10723 : : }
10724 : :
10725 : : int
10726 : 0 : rte_swx_ctl_pipeline_numa_node_get(struct rte_swx_pipeline *p, int *numa_node)
10727 : : {
10728 [ # # ]: 0 : if (!p || !numa_node)
10729 : : return -EINVAL;
10730 : :
10731 : 0 : *numa_node = p->numa_node;
10732 : 0 : return 0;
10733 : : }
10734 : :
10735 : : int
10736 : 0 : rte_swx_ctl_action_info_get(struct rte_swx_pipeline *p,
10737 : : uint32_t action_id,
10738 : : struct rte_swx_ctl_action_info *action)
10739 : : {
10740 : : struct action *a = NULL;
10741 : :
10742 [ # # # # : 0 : if (!p || (action_id >= p->n_actions) || !action)
# # ]
10743 : : return -EINVAL;
10744 : :
10745 : : a = action_find_by_id(p, action_id);
10746 [ # # ]: 0 : if (!a)
10747 : : return -EINVAL;
10748 : :
10749 [ # # ]: 0 : strcpy(action->name, a->name);
10750 [ # # ]: 0 : action->n_args = a->st ? a->st->n_fields : 0;
10751 : 0 : return 0;
10752 : : }
10753 : :
10754 : : int
10755 : 0 : rte_swx_ctl_action_arg_info_get(struct rte_swx_pipeline *p,
10756 : : uint32_t action_id,
10757 : : uint32_t action_arg_id,
10758 : : struct rte_swx_ctl_action_arg_info *action_arg)
10759 : : {
10760 : : struct action *a = NULL;
10761 : : struct field *arg = NULL;
10762 : :
10763 [ # # # # : 0 : if (!p || (action_id >= p->n_actions) || !action_arg)
# # ]
10764 : : return -EINVAL;
10765 : :
10766 : : a = action_find_by_id(p, action_id);
10767 [ # # # # : 0 : if (!a || !a->st || (action_arg_id >= a->st->n_fields))
# # ]
10768 : : return -EINVAL;
10769 : :
10770 : 0 : arg = &a->st->fields[action_arg_id];
10771 : 0 : strcpy(action_arg->name, arg->name);
10772 : 0 : action_arg->n_bits = arg->n_bits;
10773 : 0 : action_arg->is_network_byte_order = a->args_endianness[action_arg_id];
10774 : :
10775 : 0 : return 0;
10776 : : }
10777 : :
10778 : : int
10779 : 0 : rte_swx_ctl_table_info_get(struct rte_swx_pipeline *p,
10780 : : uint32_t table_id,
10781 : : struct rte_swx_ctl_table_info *table)
10782 : : {
10783 : : struct table *t = NULL;
10784 : :
10785 [ # # ]: 0 : if (!p || !table)
10786 : : return -EINVAL;
10787 : :
10788 : : t = table_find_by_id(p, table_id);
10789 [ # # ]: 0 : if (!t)
10790 : : return -EINVAL;
10791 : :
10792 [ # # ]: 0 : strcpy(table->name, t->name);
10793 : 0 : strcpy(table->args, t->args);
10794 : 0 : table->n_match_fields = t->n_fields;
10795 : 0 : table->n_actions = t->n_actions;
10796 : 0 : table->default_action_is_const = t->default_action_is_const;
10797 [ # # ]: 0 : table->hash_func = t->hf ? t->hf->func : NULL;
10798 : 0 : table->size = t->size;
10799 : 0 : return 0;
10800 : : }
10801 : :
10802 : : int
10803 : 0 : rte_swx_ctl_table_match_field_info_get(struct rte_swx_pipeline *p,
10804 : : uint32_t table_id,
10805 : : uint32_t match_field_id,
10806 : : struct rte_swx_ctl_table_match_field_info *match_field)
10807 : : {
10808 : : struct table *t;
10809 : : struct match_field *f;
10810 : :
10811 [ # # # # : 0 : if (!p || (table_id >= p->n_tables) || !match_field)
# # ]
10812 : : return -EINVAL;
10813 : :
10814 : : t = table_find_by_id(p, table_id);
10815 [ # # # # ]: 0 : if (!t || (match_field_id >= t->n_fields))
10816 : : return -EINVAL;
10817 : :
10818 : 0 : f = &t->fields[match_field_id];
10819 : 0 : match_field->match_type = f->match_type;
10820 : 0 : match_field->is_header = t->header ? 1 : 0;
10821 : 0 : match_field->n_bits = f->field->n_bits;
10822 : 0 : match_field->offset = f->field->offset;
10823 : :
10824 : 0 : return 0;
10825 : : }
10826 : :
10827 : : int
10828 : 0 : rte_swx_ctl_table_action_info_get(struct rte_swx_pipeline *p,
10829 : : uint32_t table_id,
10830 : : uint32_t table_action_id,
10831 : : struct rte_swx_ctl_table_action_info *table_action)
10832 : : {
10833 : : struct table *t;
10834 : :
10835 [ # # # # : 0 : if (!p || (table_id >= p->n_tables) || !table_action)
# # ]
10836 : : return -EINVAL;
10837 : :
10838 : : t = table_find_by_id(p, table_id);
10839 [ # # # # ]: 0 : if (!t || (table_action_id >= t->n_actions))
10840 : : return -EINVAL;
10841 : :
10842 : 0 : table_action->action_id = t->actions[table_action_id]->id;
10843 : :
10844 : 0 : table_action->action_is_for_table_entries = t->action_is_for_table_entries[table_action_id];
10845 : 0 : table_action->action_is_for_default_entry = t->action_is_for_default_entry[table_action_id];
10846 : :
10847 : 0 : return 0;
10848 : : }
10849 : :
10850 : : int
10851 : 0 : rte_swx_ctl_table_ops_get(struct rte_swx_pipeline *p,
10852 : : uint32_t table_id,
10853 : : struct rte_swx_table_ops *table_ops,
10854 : : int *is_stub)
10855 : : {
10856 : : struct table *t;
10857 : :
10858 [ # # # # ]: 0 : if (!p || (table_id >= p->n_tables))
10859 : : return -EINVAL;
10860 : :
10861 : : t = table_find_by_id(p, table_id);
10862 [ # # ]: 0 : if (!t)
10863 : : return -EINVAL;
10864 : :
10865 [ # # ]: 0 : if (t->type) {
10866 [ # # ]: 0 : if (table_ops)
10867 : 0 : memcpy(table_ops, &t->type->ops, sizeof(*table_ops));
10868 : 0 : *is_stub = 0;
10869 : : } else {
10870 : 0 : *is_stub = 1;
10871 : : }
10872 : :
10873 : : return 0;
10874 : : }
10875 : :
10876 : : int
10877 : 0 : rte_swx_ctl_selector_info_get(struct rte_swx_pipeline *p,
10878 : : uint32_t selector_id,
10879 : : struct rte_swx_ctl_selector_info *selector)
10880 : : {
10881 : : struct selector *s = NULL;
10882 : :
10883 [ # # ]: 0 : if (!p || !selector)
10884 : : return -EINVAL;
10885 : :
10886 : : s = selector_find_by_id(p, selector_id);
10887 [ # # ]: 0 : if (!s)
10888 : : return -EINVAL;
10889 : :
10890 : 0 : strcpy(selector->name, s->name);
10891 : :
10892 : 0 : selector->n_selector_fields = s->n_selector_fields;
10893 : 0 : selector->n_groups_max = s->n_groups_max;
10894 : 0 : selector->n_members_per_group_max = s->n_members_per_group_max;
10895 : :
10896 : 0 : return 0;
10897 : : }
10898 : :
10899 : : int
10900 : 0 : rte_swx_ctl_selector_group_id_field_info_get(struct rte_swx_pipeline *p,
10901 : : uint32_t selector_id,
10902 : : struct rte_swx_ctl_table_match_field_info *field)
10903 : : {
10904 : : struct selector *s;
10905 : :
10906 [ # # # # : 0 : if (!p || (selector_id >= p->n_selectors) || !field)
# # ]
10907 : : return -EINVAL;
10908 : :
10909 : : s = selector_find_by_id(p, selector_id);
10910 [ # # ]: 0 : if (!s)
10911 : : return -EINVAL;
10912 : :
10913 : 0 : field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10914 : 0 : field->is_header = 0;
10915 : 0 : field->n_bits = s->group_id_field->n_bits;
10916 : 0 : field->offset = s->group_id_field->offset;
10917 : :
10918 : 0 : return 0;
10919 : : }
10920 : :
10921 : : int
10922 : 0 : rte_swx_ctl_selector_field_info_get(struct rte_swx_pipeline *p,
10923 : : uint32_t selector_id,
10924 : : uint32_t selector_field_id,
10925 : : struct rte_swx_ctl_table_match_field_info *field)
10926 : : {
10927 : : struct selector *s;
10928 : : struct field *f;
10929 : :
10930 [ # # # # : 0 : if (!p || (selector_id >= p->n_selectors) || !field)
# # ]
10931 : : return -EINVAL;
10932 : :
10933 : : s = selector_find_by_id(p, selector_id);
10934 [ # # # # ]: 0 : if (!s || (selector_field_id >= s->n_selector_fields))
10935 : : return -EINVAL;
10936 : :
10937 : 0 : f = s->selector_fields[selector_field_id];
10938 : 0 : field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10939 : 0 : field->is_header = s->selector_header ? 1 : 0;
10940 : 0 : field->n_bits = f->n_bits;
10941 : 0 : field->offset = f->offset;
10942 : :
10943 : 0 : return 0;
10944 : : }
10945 : :
10946 : : int
10947 : 0 : rte_swx_ctl_selector_member_id_field_info_get(struct rte_swx_pipeline *p,
10948 : : uint32_t selector_id,
10949 : : struct rte_swx_ctl_table_match_field_info *field)
10950 : : {
10951 : : struct selector *s;
10952 : :
10953 [ # # # # : 0 : if (!p || (selector_id >= p->n_selectors) || !field)
# # ]
10954 : : return -EINVAL;
10955 : :
10956 : : s = selector_find_by_id(p, selector_id);
10957 [ # # ]: 0 : if (!s)
10958 : : return -EINVAL;
10959 : :
10960 : 0 : field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10961 : 0 : field->is_header = 0;
10962 : 0 : field->n_bits = s->member_id_field->n_bits;
10963 : 0 : field->offset = s->member_id_field->offset;
10964 : :
10965 : 0 : return 0;
10966 : : }
10967 : :
10968 : : int
10969 : 0 : rte_swx_ctl_learner_info_get(struct rte_swx_pipeline *p,
10970 : : uint32_t learner_id,
10971 : : struct rte_swx_ctl_learner_info *learner)
10972 : : {
10973 : : struct learner *l = NULL;
10974 : :
10975 [ # # ]: 0 : if (!p || !learner)
10976 : : return -EINVAL;
10977 : :
10978 : : l = learner_find_by_id(p, learner_id);
10979 [ # # ]: 0 : if (!l)
10980 : : return -EINVAL;
10981 : :
10982 : 0 : strcpy(learner->name, l->name);
10983 : :
10984 : 0 : learner->n_match_fields = l->n_fields;
10985 : 0 : learner->n_actions = l->n_actions;
10986 : 0 : learner->default_action_is_const = l->default_action_is_const;
10987 : 0 : learner->size = l->size;
10988 : 0 : learner->n_key_timeouts = l->n_timeouts;
10989 : :
10990 : 0 : return 0;
10991 : : }
10992 : :
10993 : : int
10994 : 0 : rte_swx_ctl_learner_match_field_info_get(struct rte_swx_pipeline *p,
10995 : : uint32_t learner_id,
10996 : : uint32_t match_field_id,
10997 : : struct rte_swx_ctl_table_match_field_info *match_field)
10998 : : {
10999 : : struct learner *l;
11000 : : struct field *f;
11001 : :
11002 [ # # # # : 0 : if (!p || (learner_id >= p->n_learners) || !match_field)
# # ]
11003 : : return -EINVAL;
11004 : :
11005 : : l = learner_find_by_id(p, learner_id);
11006 [ # # # # ]: 0 : if (!l || (match_field_id >= l->n_fields))
11007 : : return -EINVAL;
11008 : :
11009 : 0 : f = l->fields[match_field_id];
11010 : 0 : match_field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
11011 : 0 : match_field->is_header = l->header ? 1 : 0;
11012 : 0 : match_field->n_bits = f->n_bits;
11013 : 0 : match_field->offset = f->offset;
11014 : :
11015 : 0 : return 0;
11016 : : }
11017 : :
11018 : : int
11019 : 0 : rte_swx_ctl_learner_action_info_get(struct rte_swx_pipeline *p,
11020 : : uint32_t learner_id,
11021 : : uint32_t learner_action_id,
11022 : : struct rte_swx_ctl_table_action_info *learner_action)
11023 : : {
11024 : : struct learner *l;
11025 : :
11026 [ # # # # : 0 : if (!p || (learner_id >= p->n_learners) || !learner_action)
# # ]
11027 : : return -EINVAL;
11028 : :
11029 : : l = learner_find_by_id(p, learner_id);
11030 [ # # # # ]: 0 : if (!l || (learner_action_id >= l->n_actions))
11031 : : return -EINVAL;
11032 : :
11033 : 0 : learner_action->action_id = l->actions[learner_action_id]->id;
11034 : :
11035 : 0 : learner_action->action_is_for_table_entries =
11036 : 0 : l->action_is_for_table_entries[learner_action_id];
11037 : :
11038 : 0 : learner_action->action_is_for_default_entry =
11039 : 0 : l->action_is_for_default_entry[learner_action_id];
11040 : :
11041 : 0 : return 0;
11042 : : }
11043 : :
11044 : : int
11045 : 0 : rte_swx_ctl_pipeline_learner_timeout_get(struct rte_swx_pipeline *p,
11046 : : uint32_t learner_id,
11047 : : uint32_t timeout_id,
11048 : : uint32_t *timeout)
11049 : : {
11050 : : struct learner *l;
11051 : :
11052 [ # # # # : 0 : if (!p || (learner_id >= p->n_learners) || !timeout)
# # ]
11053 : : return -EINVAL;
11054 : :
11055 : : l = learner_find_by_id(p, learner_id);
11056 [ # # # # ]: 0 : if (!l || (timeout_id >= l->n_timeouts))
11057 : : return -EINVAL;
11058 : :
11059 : 0 : *timeout = l->timeout[timeout_id];
11060 : 0 : return 0;
11061 : : }
11062 : :
11063 : : int
11064 : 0 : rte_swx_ctl_pipeline_learner_timeout_set(struct rte_swx_pipeline *p,
11065 : : uint32_t learner_id,
11066 : : uint32_t timeout_id,
11067 : : uint32_t timeout)
11068 : : {
11069 : : struct learner *l;
11070 : : struct rte_swx_table_state *ts;
11071 : : int status;
11072 : :
11073 [ # # # # : 0 : if (!p || (learner_id >= p->n_learners) || !timeout)
# # ]
11074 : : return -EINVAL;
11075 : :
11076 : : l = learner_find_by_id(p, learner_id);
11077 [ # # # # ]: 0 : if (!l || (timeout_id >= l->n_timeouts))
11078 : : return -EINVAL;
11079 : :
11080 [ # # ]: 0 : if (!p->build_done)
11081 : : return -EINVAL;
11082 : :
11083 : 0 : ts = &p->table_state[p->n_tables + p->n_selectors + l->id];
11084 : :
11085 : 0 : status = rte_swx_table_learner_timeout_update(ts->obj, timeout_id, timeout);
11086 [ # # ]: 0 : if (status)
11087 : : return -EINVAL;
11088 : :
11089 : 0 : l->timeout[timeout_id] = timeout;
11090 : :
11091 : 0 : return 0;
11092 : : }
11093 : :
11094 : : int
11095 : 0 : rte_swx_pipeline_table_state_get(struct rte_swx_pipeline *p,
11096 : : struct rte_swx_table_state **table_state)
11097 : : {
11098 [ # # # # ]: 0 : if (!p || !table_state || !p->build_done)
11099 : : return -EINVAL;
11100 : :
11101 : 0 : *table_state = p->table_state;
11102 : 0 : return 0;
11103 : : }
11104 : :
11105 : : int
11106 : 0 : rte_swx_pipeline_table_state_set(struct rte_swx_pipeline *p,
11107 : : struct rte_swx_table_state *table_state)
11108 : : {
11109 [ # # # # ]: 0 : if (!p || !table_state || !p->build_done)
11110 : : return -EINVAL;
11111 : :
11112 : 0 : p->table_state = table_state;
11113 : 0 : return 0;
11114 : : }
11115 : :
11116 : : int
11117 : 0 : rte_swx_ctl_pipeline_port_in_stats_read(struct rte_swx_pipeline *p,
11118 : : uint32_t port_id,
11119 : : struct rte_swx_port_in_stats *stats)
11120 : : {
11121 : : struct port_in *port;
11122 : :
11123 [ # # ]: 0 : if (!p || !stats)
11124 : : return -EINVAL;
11125 : :
11126 : : port = port_in_find(p, port_id);
11127 [ # # ]: 0 : if (!port)
11128 : : return -EINVAL;
11129 : :
11130 : 0 : port->type->ops.stats_read(port->obj, stats);
11131 : 0 : return 0;
11132 : : }
11133 : :
11134 : : int
11135 : 0 : rte_swx_ctl_pipeline_port_out_stats_read(struct rte_swx_pipeline *p,
11136 : : uint32_t port_id,
11137 : : struct rte_swx_port_out_stats *stats)
11138 : : {
11139 : : struct port_out *port;
11140 : :
11141 [ # # ]: 0 : if (!p || !stats)
11142 : : return -EINVAL;
11143 : :
11144 : : port = port_out_find(p, port_id);
11145 [ # # ]: 0 : if (!port)
11146 : : return -EINVAL;
11147 : :
11148 : 0 : port->type->ops.stats_read(port->obj, stats);
11149 : 0 : return 0;
11150 : : }
11151 : :
11152 : : int
11153 : 0 : rte_swx_ctl_pipeline_table_stats_read(struct rte_swx_pipeline *p,
11154 : : const char *table_name,
11155 : : struct rte_swx_table_stats *stats)
11156 : : {
11157 : : struct table *table;
11158 : : struct table_statistics *table_stats;
11159 : :
11160 [ # # # # : 0 : if (!p || !table_name || !table_name[0] || !stats || !stats->n_pkts_action)
# # # # ]
11161 : : return -EINVAL;
11162 : :
11163 : : table = table_find(p, table_name);
11164 [ # # ]: 0 : if (!table)
11165 : : return -EINVAL;
11166 : :
11167 : 0 : table_stats = &p->table_stats[table->id];
11168 : :
11169 : 0 : memcpy(stats->n_pkts_action,
11170 : 0 : table_stats->n_pkts_action,
11171 : 0 : p->n_actions * sizeof(uint64_t));
11172 : :
11173 : 0 : stats->n_pkts_hit = table_stats->n_pkts_hit[1];
11174 : 0 : stats->n_pkts_miss = table_stats->n_pkts_hit[0];
11175 : :
11176 : 0 : return 0;
11177 : : }
11178 : :
11179 : : int
11180 : 0 : rte_swx_ctl_pipeline_selector_stats_read(struct rte_swx_pipeline *p,
11181 : : const char *selector_name,
11182 : : struct rte_swx_pipeline_selector_stats *stats)
11183 : : {
11184 : : struct selector *s;
11185 : :
11186 [ # # # # : 0 : if (!p || !selector_name || !selector_name[0] || !stats)
# # ]
11187 : : return -EINVAL;
11188 : :
11189 : : s = selector_find(p, selector_name);
11190 [ # # ]: 0 : if (!s)
11191 : : return -EINVAL;
11192 : :
11193 : 0 : stats->n_pkts = p->selector_stats[s->id].n_pkts;
11194 : :
11195 : 0 : return 0;
11196 : : }
11197 : :
11198 : : int
11199 : 0 : rte_swx_ctl_pipeline_learner_stats_read(struct rte_swx_pipeline *p,
11200 : : const char *learner_name,
11201 : : struct rte_swx_learner_stats *stats)
11202 : : {
11203 : : struct learner *l;
11204 : : struct learner_statistics *learner_stats;
11205 : :
11206 [ # # # # : 0 : if (!p || !learner_name || !learner_name[0] || !stats || !stats->n_pkts_action)
# # # # ]
11207 : : return -EINVAL;
11208 : :
11209 : : l = learner_find(p, learner_name);
11210 [ # # ]: 0 : if (!l)
11211 : : return -EINVAL;
11212 : :
11213 : 0 : learner_stats = &p->learner_stats[l->id];
11214 : :
11215 : 0 : memcpy(stats->n_pkts_action,
11216 : 0 : learner_stats->n_pkts_action,
11217 : 0 : p->n_actions * sizeof(uint64_t));
11218 : :
11219 : 0 : stats->n_pkts_hit = learner_stats->n_pkts_hit[1];
11220 : 0 : stats->n_pkts_miss = learner_stats->n_pkts_hit[0];
11221 : :
11222 : 0 : stats->n_pkts_learn_ok = learner_stats->n_pkts_learn[0];
11223 : 0 : stats->n_pkts_learn_err = learner_stats->n_pkts_learn[1];
11224 : :
11225 : 0 : stats->n_pkts_rearm = learner_stats->n_pkts_rearm;
11226 : 0 : stats->n_pkts_forget = learner_stats->n_pkts_forget;
11227 : :
11228 : 0 : return 0;
11229 : : }
11230 : :
11231 : : int
11232 : 0 : rte_swx_ctl_regarray_info_get(struct rte_swx_pipeline *p,
11233 : : uint32_t regarray_id,
11234 : : struct rte_swx_ctl_regarray_info *regarray)
11235 : : {
11236 : : struct regarray *r;
11237 : :
11238 [ # # ]: 0 : if (!p || !regarray)
11239 : : return -EINVAL;
11240 : :
11241 : : r = regarray_find_by_id(p, regarray_id);
11242 [ # # ]: 0 : if (!r)
11243 : : return -EINVAL;
11244 : :
11245 : 0 : strcpy(regarray->name, r->name);
11246 : 0 : regarray->size = r->size;
11247 : 0 : return 0;
11248 : : }
11249 : :
11250 : : int
11251 : 0 : rte_swx_ctl_pipeline_regarray_read(struct rte_swx_pipeline *p,
11252 : : const char *regarray_name,
11253 : : uint32_t regarray_index,
11254 : : uint64_t *value)
11255 : : {
11256 : : struct regarray *regarray;
11257 : : struct regarray_runtime *r;
11258 : :
11259 [ # # # # ]: 0 : if (!p || !regarray_name || !value)
11260 : : return -EINVAL;
11261 : :
11262 : : regarray = regarray_find(p, regarray_name);
11263 [ # # # # ]: 0 : if (!regarray || (regarray_index >= regarray->size))
11264 : : return -EINVAL;
11265 : :
11266 : 0 : r = &p->regarray_runtime[regarray->id];
11267 : 0 : *value = r->regarray[regarray_index];
11268 : 0 : return 0;
11269 : : }
11270 : :
11271 : : int
11272 : 0 : rte_swx_ctl_pipeline_regarray_write(struct rte_swx_pipeline *p,
11273 : : const char *regarray_name,
11274 : : uint32_t regarray_index,
11275 : : uint64_t value)
11276 : : {
11277 : : struct regarray *regarray;
11278 : : struct regarray_runtime *r;
11279 : :
11280 [ # # ]: 0 : if (!p || !regarray_name)
11281 : : return -EINVAL;
11282 : :
11283 : : regarray = regarray_find(p, regarray_name);
11284 [ # # # # ]: 0 : if (!regarray || (regarray_index >= regarray->size))
11285 : : return -EINVAL;
11286 : :
11287 : 0 : r = &p->regarray_runtime[regarray->id];
11288 : 0 : r->regarray[regarray_index] = value;
11289 : 0 : return 0;
11290 : : }
11291 : :
11292 : : int
11293 : 0 : rte_swx_ctl_metarray_info_get(struct rte_swx_pipeline *p,
11294 : : uint32_t metarray_id,
11295 : : struct rte_swx_ctl_metarray_info *metarray)
11296 : : {
11297 : : struct metarray *m;
11298 : :
11299 [ # # ]: 0 : if (!p || !metarray)
11300 : : return -EINVAL;
11301 : :
11302 : : m = metarray_find_by_id(p, metarray_id);
11303 [ # # ]: 0 : if (!m)
11304 : : return -EINVAL;
11305 : :
11306 : 0 : strcpy(metarray->name, m->name);
11307 : 0 : metarray->size = m->size;
11308 : 0 : return 0;
11309 : : }
11310 : :
11311 : : int
11312 : 0 : rte_swx_ctl_meter_profile_add(struct rte_swx_pipeline *p,
11313 : : const char *name,
11314 : : struct rte_meter_trtcm_params *params)
11315 : : {
11316 : : struct meter_profile *mp;
11317 : : int status;
11318 : :
11319 [ # # ]: 0 : CHECK(p, EINVAL);
11320 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
11321 [ # # ]: 0 : CHECK(params, EINVAL);
11322 [ # # ]: 0 : CHECK(!meter_profile_find(p, name), EEXIST);
11323 : :
11324 : : /* Node allocation. */
11325 : 0 : mp = calloc(1, sizeof(struct meter_profile));
11326 [ # # ]: 0 : CHECK(mp, ENOMEM);
11327 : :
11328 : : /* Node initialization. */
11329 : 0 : strcpy(mp->name, name);
11330 : 0 : memcpy(&mp->params, params, sizeof(struct rte_meter_trtcm_params));
11331 : 0 : status = rte_meter_trtcm_profile_config(&mp->profile, params);
11332 [ # # ]: 0 : if (status) {
11333 : 0 : free(mp);
11334 : 0 : CHECK(0, EINVAL);
11335 : : }
11336 : :
11337 : : /* Node add to tailq. */
11338 : 0 : TAILQ_INSERT_TAIL(&p->meter_profiles, mp, node);
11339 : :
11340 : 0 : return 0;
11341 : : }
11342 : :
11343 : : int
11344 : 0 : rte_swx_ctl_meter_profile_delete(struct rte_swx_pipeline *p,
11345 : : const char *name)
11346 : : {
11347 : : struct meter_profile *mp;
11348 : :
11349 [ # # ]: 0 : CHECK(p, EINVAL);
11350 [ # # # # : 0 : CHECK_NAME(name, EINVAL);
# # ]
11351 : :
11352 : : mp = meter_profile_find(p, name);
11353 [ # # ]: 0 : CHECK(mp, EINVAL);
11354 [ # # ]: 0 : CHECK(!mp->n_users, EBUSY);
11355 : :
11356 : : /* Remove node from tailq. */
11357 [ # # ]: 0 : TAILQ_REMOVE(&p->meter_profiles, mp, node);
11358 : 0 : free(mp);
11359 : :
11360 : 0 : return 0;
11361 : : }
11362 : :
11363 : : int
11364 : 0 : rte_swx_ctl_meter_reset(struct rte_swx_pipeline *p,
11365 : : const char *metarray_name,
11366 : : uint32_t metarray_index)
11367 : : {
11368 : : struct meter_profile *mp_old;
11369 : : struct metarray *metarray;
11370 : : struct metarray_runtime *metarray_runtime;
11371 : : struct meter *m;
11372 : :
11373 [ # # ]: 0 : CHECK(p, EINVAL);
11374 [ # # # # : 0 : CHECK_NAME(metarray_name, EINVAL);
# # ]
11375 : :
11376 : : metarray = metarray_find(p, metarray_name);
11377 [ # # ]: 0 : CHECK(metarray, EINVAL);
11378 [ # # ]: 0 : CHECK(metarray_index < metarray->size, EINVAL);
11379 : :
11380 : 0 : metarray_runtime = &p->metarray_runtime[metarray->id];
11381 : 0 : m = &metarray_runtime->metarray[metarray_index];
11382 : 0 : mp_old = m->profile;
11383 : :
11384 : 0 : meter_init(m);
11385 : :
11386 : 0 : mp_old->n_users--;
11387 : :
11388 : 0 : return 0;
11389 : : }
11390 : :
11391 : : int
11392 : 0 : rte_swx_ctl_meter_set(struct rte_swx_pipeline *p,
11393 : : const char *metarray_name,
11394 : : uint32_t metarray_index,
11395 : : const char *profile_name)
11396 : : {
11397 : : struct meter_profile *mp, *mp_old;
11398 : : struct metarray *metarray;
11399 : : struct metarray_runtime *metarray_runtime;
11400 : : struct meter *m;
11401 : :
11402 [ # # ]: 0 : CHECK(p, EINVAL);
11403 [ # # # # : 0 : CHECK_NAME(metarray_name, EINVAL);
# # ]
11404 : :
11405 : : metarray = metarray_find(p, metarray_name);
11406 [ # # ]: 0 : CHECK(metarray, EINVAL);
11407 [ # # ]: 0 : CHECK(metarray_index < metarray->size, EINVAL);
11408 : :
11409 : : mp = meter_profile_find(p, profile_name);
11410 [ # # ]: 0 : CHECK(mp, EINVAL);
11411 : :
11412 : 0 : metarray_runtime = &p->metarray_runtime[metarray->id];
11413 : 0 : m = &metarray_runtime->metarray[metarray_index];
11414 : 0 : mp_old = m->profile;
11415 : :
11416 : : memset(m, 0, sizeof(struct meter));
11417 : 0 : rte_meter_trtcm_config(&m->m, &mp->profile);
11418 : 0 : m->profile = mp;
11419 : 0 : m->color_mask = RTE_COLORS;
11420 : :
11421 : 0 : mp->n_users++;
11422 : 0 : mp_old->n_users--;
11423 : :
11424 : 0 : return 0;
11425 : : }
11426 : :
11427 : : int
11428 : 0 : rte_swx_ctl_meter_stats_read(struct rte_swx_pipeline *p,
11429 : : const char *metarray_name,
11430 : : uint32_t metarray_index,
11431 : : struct rte_swx_ctl_meter_stats *stats)
11432 : : {
11433 : : struct metarray *metarray;
11434 : : struct metarray_runtime *metarray_runtime;
11435 : : struct meter *m;
11436 : :
11437 [ # # ]: 0 : CHECK(p, EINVAL);
11438 [ # # # # : 0 : CHECK_NAME(metarray_name, EINVAL);
# # ]
11439 : :
11440 : : metarray = metarray_find(p, metarray_name);
11441 [ # # ]: 0 : CHECK(metarray, EINVAL);
11442 [ # # ]: 0 : CHECK(metarray_index < metarray->size, EINVAL);
11443 : :
11444 [ # # ]: 0 : CHECK(stats, EINVAL);
11445 : :
11446 : 0 : metarray_runtime = &p->metarray_runtime[metarray->id];
11447 : 0 : m = &metarray_runtime->metarray[metarray_index];
11448 : :
11449 : 0 : memcpy(stats->n_pkts, m->n_pkts, sizeof(m->n_pkts));
11450 : 0 : memcpy(stats->n_bytes, m->n_bytes, sizeof(m->n_bytes));
11451 : :
11452 : 0 : return 0;
11453 : : }
11454 : :
11455 : : int
11456 : 0 : rte_swx_ctl_pipeline_mirroring_session_set(struct rte_swx_pipeline *p,
11457 : : uint32_t session_id,
11458 : : struct rte_swx_pipeline_mirroring_session_params *params)
11459 : : {
11460 : : struct mirroring_session *s;
11461 : :
11462 [ # # ]: 0 : CHECK(p, EINVAL);
11463 [ # # ]: 0 : CHECK(p->build_done, EEXIST);
11464 [ # # ]: 0 : CHECK(session_id < p->n_mirroring_sessions, EINVAL);
11465 [ # # ]: 0 : CHECK(params, EINVAL);
11466 [ # # ]: 0 : CHECK(params->port_id < p->n_ports_out, EINVAL);
11467 : :
11468 : 0 : s = &p->mirroring_sessions[session_id];
11469 : 0 : s->port_id = params->port_id;
11470 : 0 : s->fast_clone = params->fast_clone;
11471 [ # # ]: 0 : s->truncation_length = params->truncation_length ? params->truncation_length : UINT32_MAX;
11472 : :
11473 : 0 : return 0;
11474 : : }
11475 : :
11476 : : static int
11477 : 0 : rte_swx_ctl_pipeline_table_lookup(struct rte_swx_pipeline *p,
11478 : : const char *table_name,
11479 : : uint8_t *key,
11480 : : uint64_t *action_id,
11481 : : uint8_t **action_data,
11482 : : size_t *entry_id,
11483 : : int *hit)
11484 : : {
11485 : : struct table *t;
11486 : : void *mailbox = NULL;
11487 : :
11488 : : /* Check input arguments. */
11489 [ # # ]: 0 : if (!p ||
11490 [ # # # # ]: 0 : !p->build_done ||
11491 : 0 : !table_name ||
11492 [ # # ]: 0 : !table_name[0] ||
11493 : 0 : !key ||
11494 [ # # # # ]: 0 : !entry_id ||
11495 : : !hit)
11496 : : return -EINVAL;
11497 : :
11498 : : /* Find the table. */
11499 : : t = table_find(p, table_name);
11500 [ # # ]: 0 : if (!t)
11501 : : return -EINVAL;
11502 : :
11503 [ # # ]: 0 : if (!t->type) {
11504 : 0 : *hit = 0;
11505 : 0 : return 0;
11506 : : }
11507 : :
11508 : : /* Setup mailbox. */
11509 [ # # ]: 0 : if (t->type->ops.mailbox_size_get) {
11510 : : uint64_t mailbox_size;
11511 : :
11512 : 0 : mailbox_size = t->type->ops.mailbox_size_get();
11513 [ # # ]: 0 : if (mailbox_size) {
11514 : 0 : mailbox = calloc(1, mailbox_size);
11515 [ # # ]: 0 : if (!mailbox)
11516 : : return -ENOMEM;
11517 : : }
11518 : : }
11519 : :
11520 : : /* Table lookup operation. */
11521 : 0 : key -= table_params_offset_get(t);
11522 : :
11523 : : for ( ; ; ) {
11524 : 0 : struct rte_swx_table_state *ts = &p->table_state[t->id];
11525 : : int done;
11526 : :
11527 : 0 : done = t->type->ops.lkp(ts->obj,
11528 : : mailbox,
11529 : : &key,
11530 : : action_id,
11531 : : action_data,
11532 : : entry_id,
11533 : : hit);
11534 [ # # ]: 0 : if (done)
11535 : : break;
11536 : : }
11537 : :
11538 : : /* Free mailbox. */
11539 : 0 : free(mailbox);
11540 : :
11541 : 0 : return 0;
11542 : : }
11543 : :
11544 : : static int
11545 : 0 : rte_swx_ctl_pipeline_learner_lookup(struct rte_swx_pipeline *p,
11546 : : const char *learner_name,
11547 : : uint8_t *key,
11548 : : uint64_t *action_id,
11549 : : uint8_t **action_data,
11550 : : size_t *entry_id,
11551 : : int *hit)
11552 : : {
11553 : : struct learner *l;
11554 : : void *mailbox = NULL;
11555 : : uint64_t mailbox_size, time;
11556 : :
11557 : : /* Check input arguments. */
11558 [ # # ]: 0 : if (!p ||
11559 [ # # # # ]: 0 : !p->build_done ||
11560 : 0 : !learner_name ||
11561 [ # # ]: 0 : !learner_name[0] ||
11562 : 0 : !key ||
11563 [ # # # # ]: 0 : !entry_id ||
11564 : : !hit)
11565 : : return -EINVAL;
11566 : :
11567 : : /* Find the learner table. */
11568 : : l = learner_find(p, learner_name);
11569 [ # # ]: 0 : if (!l)
11570 : : return -EINVAL;
11571 : :
11572 : : /* Setup mailbox. */
11573 : 0 : mailbox_size = rte_swx_table_learner_mailbox_size_get();
11574 [ # # ]: 0 : if (mailbox_size) {
11575 : 0 : mailbox = calloc(1, mailbox_size);
11576 [ # # ]: 0 : if (!mailbox)
11577 : : return -ENOMEM;
11578 : : }
11579 : :
11580 : : /* Learner table lookup operation. */
11581 : 0 : key -= learner_params_offset_get(l);
11582 : :
11583 : : time = rte_get_tsc_cycles();
11584 : :
11585 : : for ( ; ; ) {
11586 : 0 : uint32_t pos = p->n_tables + p->n_selectors + l->id;
11587 : 0 : struct rte_swx_table_state *ts = &p->table_state[pos];
11588 : : int done;
11589 : :
11590 : 0 : done = rte_swx_table_learner_lookup(ts->obj,
11591 : : mailbox,
11592 : : time,
11593 : : &key,
11594 : : action_id,
11595 : : action_data,
11596 : : entry_id,
11597 : : hit);
11598 [ # # ]: 0 : if (done)
11599 : : break;
11600 : : }
11601 : :
11602 : : /* Free mailbox. */
11603 : 0 : free(mailbox);
11604 : :
11605 : 0 : return 0;
11606 : : }
11607 : :
11608 : : static int
11609 : 0 : rte_swx_ctl_pipeline_table_entry_id_get(struct rte_swx_pipeline *p,
11610 : : const char *table_name,
11611 : : uint8_t *table_key,
11612 : : size_t *table_entry_id)
11613 : : {
11614 : : struct table *t;
11615 : : struct learner *l;
11616 : : uint64_t action_id;
11617 : : uint8_t *action_data;
11618 : 0 : size_t entry_id = 0;
11619 : 0 : int hit = 0, status;
11620 : :
11621 : : /* Check input arguments. */
11622 [ # # ]: 0 : if (!p ||
11623 [ # # # # ]: 0 : !p->build_done ||
11624 : 0 : !table_name ||
11625 [ # # ]: 0 : !table_name[0] ||
11626 : 0 : !table_key ||
11627 [ # # ]: 0 : !table_entry_id)
11628 : : return -EINVAL;
11629 : :
11630 : : t = table_find(p, table_name);
11631 : : l = learner_find(p, table_name);
11632 [ # # ]: 0 : if (!t && !l)
11633 : : return -EINVAL;
11634 : :
11635 : : /* Table lookup operation. */
11636 [ # # ]: 0 : if (t)
11637 : 0 : status = rte_swx_ctl_pipeline_table_lookup(p,
11638 : : table_name,
11639 : : table_key,
11640 : : &action_id,
11641 : : &action_data,
11642 : : &entry_id,
11643 : : &hit);
11644 : : else
11645 : 0 : status = rte_swx_ctl_pipeline_learner_lookup(p,
11646 : : table_name,
11647 : : table_key,
11648 : : &action_id,
11649 : : &action_data,
11650 : : &entry_id,
11651 : : &hit);
11652 [ # # ]: 0 : if (status)
11653 : : return status;
11654 : :
11655 : : /* Reserve entry ID 0 for the table default entry. */
11656 [ # # ]: 0 : *table_entry_id = hit ? (1 + entry_id) : 0;
11657 : :
11658 : 0 : return 0;
11659 : : }
11660 : :
11661 : : int
11662 : 0 : rte_swx_ctl_pipeline_regarray_read_with_key(struct rte_swx_pipeline *p,
11663 : : const char *regarray_name,
11664 : : const char *table_name,
11665 : : uint8_t *table_key,
11666 : : uint64_t *value)
11667 : : {
11668 : 0 : size_t entry_id = 0;
11669 : : int status;
11670 : :
11671 : 0 : status = rte_swx_ctl_pipeline_table_entry_id_get(p, table_name, table_key, &entry_id);
11672 [ # # ]: 0 : if (status)
11673 : : return status;
11674 : :
11675 : 0 : return rte_swx_ctl_pipeline_regarray_read(p, regarray_name, entry_id, value);
11676 : : }
11677 : :
11678 : : int
11679 : 0 : rte_swx_ctl_pipeline_regarray_write_with_key(struct rte_swx_pipeline *p,
11680 : : const char *regarray_name,
11681 : : const char *table_name,
11682 : : uint8_t *table_key,
11683 : : uint64_t value)
11684 : : {
11685 : 0 : size_t entry_id = 0;
11686 : : int status;
11687 : :
11688 : 0 : status = rte_swx_ctl_pipeline_table_entry_id_get(p, table_name, table_key, &entry_id);
11689 [ # # ]: 0 : if (status)
11690 : : return status;
11691 : :
11692 : 0 : return rte_swx_ctl_pipeline_regarray_write(p, regarray_name, entry_id, value);
11693 : : }
11694 : :
11695 : : int
11696 : 0 : rte_swx_ctl_meter_reset_with_key(struct rte_swx_pipeline *p,
11697 : : const char *metarray_name,
11698 : : const char *table_name,
11699 : : uint8_t *table_key)
11700 : : {
11701 : 0 : size_t entry_id = 0;
11702 : : int status;
11703 : :
11704 : 0 : status = rte_swx_ctl_pipeline_table_entry_id_get(p, table_name, table_key, &entry_id);
11705 [ # # ]: 0 : if (status)
11706 : : return status;
11707 : :
11708 : 0 : return rte_swx_ctl_meter_reset(p, metarray_name, entry_id);
11709 : : }
11710 : :
11711 : : int
11712 : 0 : rte_swx_ctl_meter_set_with_key(struct rte_swx_pipeline *p,
11713 : : const char *metarray_name,
11714 : : const char *table_name,
11715 : : uint8_t *table_key,
11716 : : const char *profile_name)
11717 : : {
11718 : 0 : size_t entry_id = 0;
11719 : : int status;
11720 : :
11721 : 0 : status = rte_swx_ctl_pipeline_table_entry_id_get(p, table_name, table_key, &entry_id);
11722 [ # # ]: 0 : if (status)
11723 : : return status;
11724 : :
11725 : 0 : return rte_swx_ctl_meter_set(p, metarray_name, entry_id, profile_name);
11726 : : }
11727 : :
11728 : : int
11729 : 0 : rte_swx_ctl_meter_stats_read_with_key(struct rte_swx_pipeline *p,
11730 : : const char *metarray_name,
11731 : : const char *table_name,
11732 : : uint8_t *table_key,
11733 : : struct rte_swx_ctl_meter_stats *stats)
11734 : : {
11735 : 0 : size_t entry_id = 0;
11736 : : int status;
11737 : :
11738 : 0 : status = rte_swx_ctl_pipeline_table_entry_id_get(p, table_name, table_key, &entry_id);
11739 [ # # ]: 0 : if (status)
11740 : : return status;
11741 : :
11742 : 0 : return rte_swx_ctl_meter_stats_read(p, metarray_name, entry_id, stats);
11743 : : }
11744 : :
11745 : : int
11746 : 0 : rte_swx_ctl_rss_info_get(struct rte_swx_pipeline *p,
11747 : : uint32_t rss_obj_id,
11748 : : struct rte_swx_ctl_rss_info *info)
11749 : : {
11750 : : struct rss *rss;
11751 : :
11752 : : /* Check the input arguments. */
11753 [ # # ]: 0 : if (!p || !info)
11754 : : return -EINVAL;
11755 : :
11756 : : rss = rss_find_by_id(p, rss_obj_id);
11757 [ # # ]: 0 : if (!rss)
11758 : : return -EINVAL;
11759 : :
11760 : : /* Read from the internal data structures. */
11761 : 0 : strcpy(info->name, rss->name);
11762 : 0 : return 0;
11763 : : }
11764 : :
11765 : : int
11766 : 0 : rte_swx_ctl_pipeline_rss_key_size_read(struct rte_swx_pipeline *p,
11767 : : const char *rss_name,
11768 : : uint32_t *key_size)
11769 : : {
11770 : : struct rss *rss;
11771 : : struct rss_runtime *r;
11772 : :
11773 : : /* Check the input arguments. */
11774 [ # # ]: 0 : CHECK(p, EINVAL);
11775 : :
11776 [ # # # # : 0 : CHECK_NAME(rss_name, EINVAL);
# # ]
11777 : : rss = rss_find(p, rss_name);
11778 [ # # ]: 0 : CHECK(rss, EINVAL);
11779 : 0 : r = p->rss_runtime[rss->id];
11780 : :
11781 [ # # ]: 0 : CHECK(key_size, EINVAL);
11782 : :
11783 : : /* Read from the internal data structures. */
11784 : 0 : *key_size = r->key_size;
11785 : :
11786 : 0 : return 0;
11787 : : }
11788 : :
11789 : : int
11790 : 0 : rte_swx_ctl_pipeline_rss_key_read(struct rte_swx_pipeline *p,
11791 : : const char *rss_name,
11792 : : uint8_t *key)
11793 : : {
11794 : : struct rss *rss;
11795 : : struct rss_runtime *r;
11796 : :
11797 : : /* Check the input arguments. */
11798 [ # # ]: 0 : CHECK(p, EINVAL);
11799 : :
11800 [ # # # # : 0 : CHECK_NAME(rss_name, EINVAL);
# # ]
11801 : : rss = rss_find(p, rss_name);
11802 [ # # ]: 0 : CHECK(rss, EINVAL);
11803 : 0 : r = p->rss_runtime[rss->id];
11804 : :
11805 [ # # ]: 0 : CHECK(key, EINVAL);
11806 : :
11807 : : /* Read from the internal data structures. */
11808 : 0 : memcpy(key, r->key, r->key_size);
11809 : :
11810 : 0 : return 0;
11811 : : }
11812 : :
11813 : : int
11814 : 0 : rte_swx_ctl_pipeline_rss_key_write(struct rte_swx_pipeline *p,
11815 : : const char *rss_name,
11816 : : uint32_t key_size,
11817 : : uint8_t *key)
11818 : : {
11819 : : struct rss *rss;
11820 : : struct rss_runtime *r, *r_new;
11821 : :
11822 : : /* Check the input arguments. */
11823 [ # # ]: 0 : CHECK(p, EINVAL);
11824 : :
11825 [ # # # # : 0 : CHECK_NAME(rss_name, EINVAL);
# # ]
11826 : : rss = rss_find(p, rss_name);
11827 [ # # ]: 0 : CHECK(rss, EINVAL);
11828 : 0 : r = p->rss_runtime[rss->id];
11829 : :
11830 [ # # ]: 0 : CHECK(key_size >= 4, EINVAL);
11831 [ # # ]: 0 : CHECK(key, EINVAL);
11832 : :
11833 : : /* Allocate new RSS run-time entry. */
11834 : 0 : r_new = malloc(sizeof(struct rss_runtime) + key_size * sizeof(uint32_t));
11835 [ # # ]: 0 : if (!r_new)
11836 : : return -ENOMEM;
11837 : :
11838 : : /* Fill in the new RSS run-time entry. */
11839 : 0 : r_new->key_size = key_size;
11840 : 0 : memcpy(r_new->key, key, key_size);
11841 : :
11842 : : /* Commit the RSS run-time change atomically. */
11843 : 0 : p->rss_runtime[rss->id] = r_new;
11844 : :
11845 : : /* Free the old RSS run-time entry. */
11846 : 0 : free(r);
11847 : :
11848 : 0 : return 0;
11849 : : }
11850 : :
11851 : : /*
11852 : : * Pipeline compilation.
11853 : : */
11854 : : static const char *
11855 : 0 : instr_type_to_name(struct instruction *instr)
11856 : : {
11857 [ # # # # : 0 : switch (instr->type) {
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
11858 : : case INSTR_RX: return "INSTR_RX";
11859 : :
11860 : 0 : case INSTR_TX: return "INSTR_TX";
11861 : 0 : case INSTR_TX_I: return "INSTR_TX_I";
11862 : 0 : case INSTR_DROP: return "INSTR_DROP";
11863 : 0 : case INSTR_MIRROR: return "INSTR_MIRROR";
11864 : 0 : case INSTR_RECIRCULATE: return "INSTR_RECIRCULATE";
11865 : 0 : case INSTR_RECIRCID: return "INSTR_RECIRCID";
11866 : :
11867 : 0 : case INSTR_HDR_EXTRACT: return "INSTR_HDR_EXTRACT";
11868 : 0 : case INSTR_HDR_EXTRACT2: return "INSTR_HDR_EXTRACT2";
11869 : 0 : case INSTR_HDR_EXTRACT3: return "INSTR_HDR_EXTRACT3";
11870 : 0 : case INSTR_HDR_EXTRACT4: return "INSTR_HDR_EXTRACT4";
11871 : 0 : case INSTR_HDR_EXTRACT5: return "INSTR_HDR_EXTRACT5";
11872 : 0 : case INSTR_HDR_EXTRACT6: return "INSTR_HDR_EXTRACT6";
11873 : 0 : case INSTR_HDR_EXTRACT7: return "INSTR_HDR_EXTRACT7";
11874 : 0 : case INSTR_HDR_EXTRACT8: return "INSTR_HDR_EXTRACT8";
11875 : :
11876 : 0 : case INSTR_HDR_EXTRACT_M: return "INSTR_HDR_EXTRACT_M";
11877 : :
11878 : 0 : case INSTR_HDR_LOOKAHEAD: return "INSTR_HDR_LOOKAHEAD";
11879 : :
11880 : 0 : case INSTR_HDR_EMIT: return "INSTR_HDR_EMIT";
11881 : 0 : case INSTR_HDR_EMIT_TX: return "INSTR_HDR_EMIT_TX";
11882 : 0 : case INSTR_HDR_EMIT2_TX: return "INSTR_HDR_EMIT2_TX";
11883 : 0 : case INSTR_HDR_EMIT3_TX: return "INSTR_HDR_EMIT3_TX";
11884 : 0 : case INSTR_HDR_EMIT4_TX: return "INSTR_HDR_EMIT4_TX";
11885 : 0 : case INSTR_HDR_EMIT5_TX: return "INSTR_HDR_EMIT5_TX";
11886 : 0 : case INSTR_HDR_EMIT6_TX: return "INSTR_HDR_EMIT6_TX";
11887 : 0 : case INSTR_HDR_EMIT7_TX: return "INSTR_HDR_EMIT7_TX";
11888 : 0 : case INSTR_HDR_EMIT8_TX: return "INSTR_HDR_EMIT8_TX";
11889 : :
11890 : 0 : case INSTR_HDR_VALIDATE: return "INSTR_HDR_VALIDATE";
11891 : 0 : case INSTR_HDR_INVALIDATE: return "INSTR_HDR_INVALIDATE";
11892 : :
11893 : 0 : case INSTR_MOV: return "INSTR_MOV";
11894 : 0 : case INSTR_MOV_MH: return "INSTR_MOV_MH";
11895 : 0 : case INSTR_MOV_HM: return "INSTR_MOV_HM";
11896 : 0 : case INSTR_MOV_HH: return "INSTR_MOV_HH";
11897 : 0 : case INSTR_MOV_DMA: return "INSTR_MOV_DMA";
11898 : 0 : case INSTR_MOV_128: return "INSTR_MOV_128";
11899 : 0 : case INSTR_MOV_128_64: return "INSTR_MOV_128_64";
11900 : 0 : case INSTR_MOV_64_128: return "INSTR_MOV_64_128";
11901 : 0 : case INSTR_MOV_128_32: return "INSTR_MOV_128_32";
11902 : 0 : case INSTR_MOV_32_128: return "INSTR_MOV_32_128";
11903 : 0 : case INSTR_MOV_I: return "INSTR_MOV_I";
11904 : :
11905 : 0 : case INSTR_MOVH: return "INSTR_MOVH";
11906 : :
11907 : 0 : case INSTR_DMA_HT: return "INSTR_DMA_HT";
11908 : 0 : case INSTR_DMA_HT2: return "INSTR_DMA_HT2";
11909 : 0 : case INSTR_DMA_HT3: return "INSTR_DMA_HT3";
11910 : 0 : case INSTR_DMA_HT4: return "INSTR_DMA_HT4";
11911 : 0 : case INSTR_DMA_HT5: return "INSTR_DMA_HT5";
11912 : 0 : case INSTR_DMA_HT6: return "INSTR_DMA_HT6";
11913 : 0 : case INSTR_DMA_HT7: return "INSTR_DMA_HT7";
11914 : 0 : case INSTR_DMA_HT8: return "INSTR_DMA_HT8";
11915 : :
11916 : 0 : case INSTR_ALU_ADD: return "INSTR_ALU_ADD";
11917 : 0 : case INSTR_ALU_ADD_MH: return "INSTR_ALU_ADD_MH";
11918 : 0 : case INSTR_ALU_ADD_HM: return "INSTR_ALU_ADD_HM";
11919 : 0 : case INSTR_ALU_ADD_HH: return "INSTR_ALU_ADD_HH";
11920 : 0 : case INSTR_ALU_ADD_MI: return "INSTR_ALU_ADD_MI";
11921 : 0 : case INSTR_ALU_ADD_HI: return "INSTR_ALU_ADD_HI";
11922 : :
11923 : 0 : case INSTR_ALU_SUB: return "INSTR_ALU_SUB";
11924 : 0 : case INSTR_ALU_SUB_MH: return "INSTR_ALU_SUB_MH";
11925 : 0 : case INSTR_ALU_SUB_HM: return "INSTR_ALU_SUB_HM";
11926 : 0 : case INSTR_ALU_SUB_HH: return "INSTR_ALU_SUB_HH";
11927 : 0 : case INSTR_ALU_SUB_MI: return "INSTR_ALU_SUB_MI";
11928 : 0 : case INSTR_ALU_SUB_HI: return "INSTR_ALU_SUB_HI";
11929 : :
11930 : 0 : case INSTR_ALU_CKADD_FIELD: return "INSTR_ALU_CKADD_FIELD";
11931 : 0 : case INSTR_ALU_CKADD_STRUCT20: return "INSTR_ALU_CKADD_STRUCT20";
11932 : 0 : case INSTR_ALU_CKADD_STRUCT: return "INSTR_ALU_CKADD_STRUCT";
11933 : 0 : case INSTR_ALU_CKSUB_FIELD: return "INSTR_ALU_CKSUB_FIELD";
11934 : :
11935 : 0 : case INSTR_ALU_AND: return "INSTR_ALU_AND";
11936 : 0 : case INSTR_ALU_AND_MH: return "INSTR_ALU_AND_MH";
11937 : 0 : case INSTR_ALU_AND_HM: return "INSTR_ALU_AND_HM";
11938 : 0 : case INSTR_ALU_AND_HH: return "INSTR_ALU_AND_HH";
11939 : 0 : case INSTR_ALU_AND_I: return "INSTR_ALU_AND_I";
11940 : :
11941 : 0 : case INSTR_ALU_OR: return "INSTR_ALU_OR";
11942 : 0 : case INSTR_ALU_OR_MH: return "INSTR_ALU_OR_MH";
11943 : 0 : case INSTR_ALU_OR_HM: return "INSTR_ALU_OR_HM";
11944 : 0 : case INSTR_ALU_OR_HH: return "INSTR_ALU_OR_HH";
11945 : 0 : case INSTR_ALU_OR_I: return "INSTR_ALU_OR_I";
11946 : :
11947 : 0 : case INSTR_ALU_XOR: return "INSTR_ALU_XOR";
11948 : 0 : case INSTR_ALU_XOR_MH: return "INSTR_ALU_XOR_MH";
11949 : 0 : case INSTR_ALU_XOR_HM: return "INSTR_ALU_XOR_HM";
11950 : 0 : case INSTR_ALU_XOR_HH: return "INSTR_ALU_XOR_HH";
11951 : 0 : case INSTR_ALU_XOR_I: return "INSTR_ALU_XOR_I";
11952 : :
11953 : 0 : case INSTR_ALU_SHL: return "INSTR_ALU_SHL";
11954 : 0 : case INSTR_ALU_SHL_MH: return "INSTR_ALU_SHL_MH";
11955 : 0 : case INSTR_ALU_SHL_HM: return "INSTR_ALU_SHL_HM";
11956 : 0 : case INSTR_ALU_SHL_HH: return "INSTR_ALU_SHL_HH";
11957 : 0 : case INSTR_ALU_SHL_MI: return "INSTR_ALU_SHL_MI";
11958 : 0 : case INSTR_ALU_SHL_HI: return "INSTR_ALU_SHL_HI";
11959 : :
11960 : 0 : case INSTR_ALU_SHR: return "INSTR_ALU_SHR";
11961 : 0 : case INSTR_ALU_SHR_MH: return "INSTR_ALU_SHR_MH";
11962 : 0 : case INSTR_ALU_SHR_HM: return "INSTR_ALU_SHR_HM";
11963 : 0 : case INSTR_ALU_SHR_HH: return "INSTR_ALU_SHR_HH";
11964 : 0 : case INSTR_ALU_SHR_MI: return "INSTR_ALU_SHR_MI";
11965 : 0 : case INSTR_ALU_SHR_HI: return "INSTR_ALU_SHR_HI";
11966 : :
11967 : 0 : case INSTR_REGPREFETCH_RH: return "INSTR_REGPREFETCH_RH";
11968 : 0 : case INSTR_REGPREFETCH_RM: return "INSTR_REGPREFETCH_RM";
11969 : 0 : case INSTR_REGPREFETCH_RI: return "INSTR_REGPREFETCH_RI";
11970 : :
11971 : 0 : case INSTR_REGRD_HRH: return "INSTR_REGRD_HRH";
11972 : 0 : case INSTR_REGRD_HRM: return "INSTR_REGRD_HRM";
11973 : 0 : case INSTR_REGRD_HRI: return "INSTR_REGRD_HRI";
11974 : 0 : case INSTR_REGRD_MRH: return "INSTR_REGRD_MRH";
11975 : 0 : case INSTR_REGRD_MRM: return "INSTR_REGRD_MRM";
11976 : 0 : case INSTR_REGRD_MRI: return "INSTR_REGRD_MRI";
11977 : :
11978 : 0 : case INSTR_REGWR_RHH: return "INSTR_REGWR_RHH";
11979 : 0 : case INSTR_REGWR_RHM: return "INSTR_REGWR_RHM";
11980 : 0 : case INSTR_REGWR_RHI: return "INSTR_REGWR_RHI";
11981 : 0 : case INSTR_REGWR_RMH: return "INSTR_REGWR_RMH";
11982 : 0 : case INSTR_REGWR_RMM: return "INSTR_REGWR_RMM";
11983 : 0 : case INSTR_REGWR_RMI: return "INSTR_REGWR_RMI";
11984 : 0 : case INSTR_REGWR_RIH: return "INSTR_REGWR_RIH";
11985 : 0 : case INSTR_REGWR_RIM: return "INSTR_REGWR_RIM";
11986 : 0 : case INSTR_REGWR_RII: return "INSTR_REGWR_RII";
11987 : :
11988 : 0 : case INSTR_REGADD_RHH: return "INSTR_REGADD_RHH";
11989 : 0 : case INSTR_REGADD_RHM: return "INSTR_REGADD_RHM";
11990 : 0 : case INSTR_REGADD_RHI: return "INSTR_REGADD_RHI";
11991 : 0 : case INSTR_REGADD_RMH: return "INSTR_REGADD_RMH";
11992 : 0 : case INSTR_REGADD_RMM: return "INSTR_REGADD_RMM";
11993 : 0 : case INSTR_REGADD_RMI: return "INSTR_REGADD_RMI";
11994 : 0 : case INSTR_REGADD_RIH: return "INSTR_REGADD_RIH";
11995 : 0 : case INSTR_REGADD_RIM: return "INSTR_REGADD_RIM";
11996 : 0 : case INSTR_REGADD_RII: return "INSTR_REGADD_RII";
11997 : :
11998 : 0 : case INSTR_METPREFETCH_H: return "INSTR_METPREFETCH_H";
11999 : 0 : case INSTR_METPREFETCH_M: return "INSTR_METPREFETCH_M";
12000 : 0 : case INSTR_METPREFETCH_I: return "INSTR_METPREFETCH_I";
12001 : :
12002 : 0 : case INSTR_METER_HHM: return "INSTR_METER_HHM";
12003 : 0 : case INSTR_METER_HHI: return "INSTR_METER_HHI";
12004 : 0 : case INSTR_METER_HMM: return "INSTR_METER_HMM";
12005 : 0 : case INSTR_METER_HMI: return "INSTR_METER_HMI";
12006 : 0 : case INSTR_METER_MHM: return "INSTR_METER_MHM";
12007 : 0 : case INSTR_METER_MHI: return "INSTR_METER_MHI";
12008 : 0 : case INSTR_METER_MMM: return "INSTR_METER_MMM";
12009 : 0 : case INSTR_METER_MMI: return "INSTR_METER_MMI";
12010 : 0 : case INSTR_METER_IHM: return "INSTR_METER_IHM";
12011 : 0 : case INSTR_METER_IHI: return "INSTR_METER_IHI";
12012 : 0 : case INSTR_METER_IMM: return "INSTR_METER_IMM";
12013 : 0 : case INSTR_METER_IMI: return "INSTR_METER_IMI";
12014 : :
12015 : 0 : case INSTR_TABLE: return "INSTR_TABLE";
12016 : 0 : case INSTR_TABLE_AF: return "INSTR_TABLE_AF";
12017 : 0 : case INSTR_SELECTOR: return "INSTR_SELECTOR";
12018 : 0 : case INSTR_LEARNER: return "INSTR_LEARNER";
12019 : 0 : case INSTR_LEARNER_AF: return "INSTR_LEARNER_AF";
12020 : :
12021 : 0 : case INSTR_LEARNER_LEARN: return "INSTR_LEARNER_LEARN";
12022 : 0 : case INSTR_LEARNER_REARM: return "INSTR_LEARNER_REARM";
12023 : 0 : case INSTR_LEARNER_REARM_NEW: return "INSTR_LEARNER_REARM_NEW";
12024 : 0 : case INSTR_LEARNER_FORGET: return "INSTR_LEARNER_FORGET";
12025 : 0 : case INSTR_ENTRYID: return "INSTR_ENTRYID";
12026 : :
12027 : 0 : case INSTR_EXTERN_OBJ: return "INSTR_EXTERN_OBJ";
12028 : 0 : case INSTR_EXTERN_FUNC: return "INSTR_EXTERN_FUNC";
12029 : 0 : case INSTR_HASH_FUNC: return "INSTR_HASH_FUNC";
12030 : 0 : case INSTR_RSS: return "INSTR_RSS";
12031 : :
12032 : 0 : case INSTR_JMP: return "INSTR_JMP";
12033 : 0 : case INSTR_JMP_VALID: return "INSTR_JMP_VALID";
12034 : 0 : case INSTR_JMP_INVALID: return "INSTR_JMP_INVALID";
12035 : 0 : case INSTR_JMP_HIT: return "INSTR_JMP_HIT";
12036 : 0 : case INSTR_JMP_MISS: return "INSTR_JMP_MISS";
12037 : 0 : case INSTR_JMP_ACTION_HIT: return "INSTR_JMP_ACTION_HIT";
12038 : 0 : case INSTR_JMP_ACTION_MISS: return "INSTR_JMP_ACTION_MISS";
12039 : 0 : case INSTR_JMP_EQ: return "INSTR_JMP_EQ";
12040 : 0 : case INSTR_JMP_EQ_MH: return "INSTR_JMP_EQ_MH";
12041 : 0 : case INSTR_JMP_EQ_HM: return "INSTR_JMP_EQ_HM";
12042 : 0 : case INSTR_JMP_EQ_HH: return "INSTR_JMP_EQ_HH";
12043 : 0 : case INSTR_JMP_EQ_I: return "INSTR_JMP_EQ_I";
12044 : 0 : case INSTR_JMP_NEQ: return "INSTR_JMP_NEQ";
12045 : 0 : case INSTR_JMP_NEQ_MH: return "INSTR_JMP_NEQ_MH";
12046 : 0 : case INSTR_JMP_NEQ_HM: return "INSTR_JMP_NEQ_HM";
12047 : 0 : case INSTR_JMP_NEQ_HH: return "INSTR_JMP_NEQ_HH";
12048 : 0 : case INSTR_JMP_NEQ_I: return "INSTR_JMP_NEQ_I";
12049 : 0 : case INSTR_JMP_LT: return "INSTR_JMP_LT";
12050 : 0 : case INSTR_JMP_LT_MH: return "INSTR_JMP_LT_MH";
12051 : 0 : case INSTR_JMP_LT_HM: return "INSTR_JMP_LT_HM";
12052 : 0 : case INSTR_JMP_LT_HH: return "INSTR_JMP_LT_HH";
12053 : 0 : case INSTR_JMP_LT_MI: return "INSTR_JMP_LT_MI";
12054 : 0 : case INSTR_JMP_LT_HI: return "INSTR_JMP_LT_HI";
12055 : 0 : case INSTR_JMP_GT: return "INSTR_JMP_GT";
12056 : 0 : case INSTR_JMP_GT_MH: return "INSTR_JMP_GT_MH";
12057 : 0 : case INSTR_JMP_GT_HM: return "INSTR_JMP_GT_HM";
12058 : 0 : case INSTR_JMP_GT_HH: return "INSTR_JMP_GT_HH";
12059 : 0 : case INSTR_JMP_GT_MI: return "INSTR_JMP_GT_MI";
12060 : 0 : case INSTR_JMP_GT_HI: return "INSTR_JMP_GT_HI";
12061 : :
12062 : 0 : case INSTR_RETURN: return "INSTR_RETURN";
12063 : :
12064 : 0 : default: return "INSTR_UNKNOWN";
12065 : : }
12066 : : }
12067 : :
12068 : : typedef void
12069 : : (*instruction_export_t)(struct instruction *, FILE *);
12070 : :
12071 : : static void
12072 : 0 : instr_io_export(struct instruction *instr, FILE *f)
12073 : : {
12074 : : uint32_t n_io = 0, n_io_imm = 0, n_hdrs = 0, i;
12075 : :
12076 : : /* n_io, n_io_imm, n_hdrs. */
12077 : 0 : if (instr->type == INSTR_RX ||
12078 [ # # ]: 0 : instr->type == INSTR_TX ||
12079 : 0 : instr->type == INSTR_HDR_EXTRACT_M ||
12080 [ # # ]: 0 : (instr->type >= INSTR_HDR_EMIT_TX && instr->type <= INSTR_HDR_EMIT8_TX))
12081 : : n_io = 1;
12082 : :
12083 [ # # ]: 0 : if (instr->type == INSTR_TX_I)
12084 : : n_io_imm = 1;
12085 : :
12086 [ # # ]: 0 : if (instr->type >= INSTR_HDR_EXTRACT && instr->type <= INSTR_HDR_EXTRACT8)
12087 : 0 : n_hdrs = 1 + (instr->type - INSTR_HDR_EXTRACT);
12088 : :
12089 : 0 : if (instr->type == INSTR_HDR_EXTRACT_M ||
12090 [ # # ]: 0 : instr->type == INSTR_HDR_LOOKAHEAD ||
12091 : : instr->type == INSTR_HDR_EMIT)
12092 : : n_hdrs = 1;
12093 : :
12094 [ # # ]: 0 : if (instr->type >= INSTR_HDR_EMIT_TX && instr->type <= INSTR_HDR_EMIT8_TX)
12095 : 0 : n_hdrs = 1 + (instr->type - INSTR_HDR_EMIT_TX);
12096 : :
12097 : : /* instr. */
12098 : 0 : fprintf(f,
12099 : : "\t{\n"
12100 : : "\t\t.type = %s,\n",
12101 : : instr_type_to_name(instr));
12102 : :
12103 : : /* instr.io. */
12104 [ # # ]: 0 : if (n_io || n_io_imm || n_hdrs)
12105 : : fprintf(f,
12106 : : "\t\t.io = {\n");
12107 : :
12108 : : /* instr.io.io. */
12109 [ # # ]: 0 : if (n_io)
12110 : 0 : fprintf(f,
12111 : : "\t\t\t.io = {\n"
12112 : : "\t\t\t\t.offset = %u,\n"
12113 : : "\t\t\t\t.n_bits = %u,\n"
12114 : : "\t\t\t},\n",
12115 : 0 : instr->io.io.offset,
12116 : 0 : instr->io.io.n_bits);
12117 : :
12118 [ # # ]: 0 : if (n_io_imm)
12119 : 0 : fprintf(f,
12120 : : "\t\t\t.io = {\n"
12121 : : "\t\t\t\t.val = %u,\n"
12122 : : "\t\t\t},\n",
12123 : : instr->io.io.val);
12124 : :
12125 : : /* instr.io.hdr. */
12126 [ # # ]: 0 : if (n_hdrs) {
12127 : : fprintf(f,
12128 : : "\t\t.hdr = {\n");
12129 : :
12130 : : /* instr.io.hdr.header_id. */
12131 : : fprintf(f,
12132 : : "\t\t\t.header_id = {");
12133 : :
12134 [ # # ]: 0 : for (i = 0; i < n_hdrs; i++)
12135 : 0 : fprintf(f,
12136 : : "%u, ",
12137 : 0 : instr->io.hdr.header_id[i]);
12138 : :
12139 : : fprintf(f,
12140 : : "},\n");
12141 : :
12142 : : /* instr.io.hdr.struct_id. */
12143 : : fprintf(f,
12144 : : "\t\t\t.struct_id = {");
12145 : :
12146 [ # # ]: 0 : for (i = 0; i < n_hdrs; i++)
12147 : 0 : fprintf(f,
12148 : : "%u, ",
12149 : 0 : instr->io.hdr.struct_id[i]);
12150 : :
12151 : : fprintf(f,
12152 : : "},\n");
12153 : :
12154 : : /* instr.io.hdr.n_bytes. */
12155 : : fprintf(f,
12156 : : "\t\t\t.n_bytes = {");
12157 : :
12158 [ # # ]: 0 : for (i = 0; i < n_hdrs; i++)
12159 : 0 : fprintf(f,
12160 : : "%u, ",
12161 : 0 : instr->io.hdr.n_bytes[i]);
12162 : :
12163 : : fprintf(f,
12164 : : "},\n");
12165 : :
12166 : : /* instr.io.hdr - closing curly brace. */
12167 : : fprintf(f,
12168 : : "\t\t\t}\n,");
12169 : : }
12170 : :
12171 : : /* instr.io - closing curly brace. */
12172 [ # # ]: 0 : if (n_io || n_io_imm || n_hdrs)
12173 : : fprintf(f,
12174 : : "\t\t},\n");
12175 : :
12176 : : /* instr - closing curly brace. */
12177 : : fprintf(f,
12178 : : "\t},\n");
12179 : 0 : }
12180 : :
12181 : : static void
12182 : 0 : instr_mirror_export(struct instruction *instr, FILE *f)
12183 : : {
12184 : 0 : fprintf(f,
12185 : : "\t{\n"
12186 : : "\t\t.type = %s,\n"
12187 : : "\t\t.mirror = {\n"
12188 : : "\t\t\t.dst = {\n"
12189 : : "\t\t\t\t.struct_id = %u,\n"
12190 : : "\t\t\t\t.n_bits = %u,\n"
12191 : : "\t\t\t\t.offset = %u,\n"
12192 : : "\t\t\t}\n,"
12193 : : "\t\t\t.src = {\n"
12194 : : "\t\t\t\t.struct_id = %u,\n"
12195 : : "\t\t\t\t.n_bits = %u,\n"
12196 : : "\t\t\t\t.offset = %u,\n"
12197 : : "\t\t\t}\n,"
12198 : : "\t\t},\n"
12199 : : "\t},\n",
12200 : : instr_type_to_name(instr),
12201 : 0 : instr->mirror.dst.struct_id,
12202 : 0 : instr->mirror.dst.n_bits,
12203 : 0 : instr->mirror.dst.offset,
12204 : 0 : instr->mirror.src.struct_id,
12205 : 0 : instr->mirror.src.n_bits,
12206 : 0 : instr->mirror.src.offset);
12207 : 0 : }
12208 : :
12209 : : static void
12210 : 0 : instr_recirculate_export(struct instruction *instr, FILE *f)
12211 : : {
12212 : 0 : fprintf(f,
12213 : : "\t{\n"
12214 : : "\t\t.type = %s,\n"
12215 : : "\t},\n",
12216 : : instr_type_to_name(instr));
12217 : 0 : }
12218 : :
12219 : : static void
12220 : 0 : instr_recircid_export(struct instruction *instr, FILE *f)
12221 : : {
12222 : 0 : fprintf(f,
12223 : : "\t{\n"
12224 : : "\t\t.type = %s,\n"
12225 : : "\t\t.io = {\n"
12226 : : "\t\t\t.io = {\n"
12227 : : "\t\t\t\t.offset = %u,\n"
12228 : : "\t\t\t\t.n_bits = %u,\n"
12229 : : "\t\t\t},\n"
12230 : : "\t\t},\n"
12231 : : "\t},\n",
12232 : : instr_type_to_name(instr),
12233 : 0 : instr->io.io.offset,
12234 : 0 : instr->io.io.n_bits);
12235 : 0 : }
12236 : :
12237 : : static void
12238 : 0 : instr_hdr_validate_export(struct instruction *instr, FILE *f)
12239 : : {
12240 : 0 : fprintf(f,
12241 : : "\t{\n"
12242 : : "\t\t.type = %s,\n"
12243 : : "\t\t.valid = {\n"
12244 : : "\t\t\t.header_id = %u,\n"
12245 : : "\t\t\t.struct_id = %u,\n"
12246 : : "\t\t},\n"
12247 : : "\t},\n",
12248 : : instr_type_to_name(instr),
12249 : 0 : instr->valid.header_id,
12250 : 0 : instr->valid.struct_id);
12251 : 0 : }
12252 : :
12253 : : static void
12254 : 0 : instr_mov_export(struct instruction *instr, FILE *f)
12255 : : {
12256 [ # # ]: 0 : if (instr->type != INSTR_MOV_I)
12257 : 0 : fprintf(f,
12258 : : "\t{\n"
12259 : : "\t\t.type = %s,\n"
12260 : : "\t\t.mov = {\n"
12261 : : "\t\t\t.dst = {\n"
12262 : : "\t\t\t\t.struct_id = %u,\n"
12263 : : "\t\t\t\t.n_bits = %u,\n"
12264 : : "\t\t\t\t.offset = %u,\n"
12265 : : "\t\t\t},\n"
12266 : : "\t\t\t.src = {\n"
12267 : : "\t\t\t\t.struct_id = %u,\n"
12268 : : "\t\t\t\t.n_bits = %u,\n"
12269 : : "\t\t\t\t.offset = %u,\n"
12270 : : "\t\t\t},\n"
12271 : : "\t\t},\n"
12272 : : "\t},\n",
12273 : : instr_type_to_name(instr),
12274 : 0 : instr->mov.dst.struct_id,
12275 : 0 : instr->mov.dst.n_bits,
12276 : 0 : instr->mov.dst.offset,
12277 : 0 : instr->mov.src.struct_id,
12278 : 0 : instr->mov.src.n_bits,
12279 : 0 : instr->mov.src.offset);
12280 : : else
12281 : 0 : fprintf(f,
12282 : : "\t{\n"
12283 : : "\t\t.type = %s,\n"
12284 : : "\t\t.mov = {\n"
12285 : : "\t\t\t.dst = {\n"
12286 : : "\t\t\t\t.struct_id = %u,\n"
12287 : : "\t\t\t\t.n_bits = %u,\n"
12288 : : "\t\t\t\t.offset = %u,\n"
12289 : : "\t\t\t}\n,"
12290 : : "\t\t\t.src_val = %" PRIu64 ",\n"
12291 : : "\t\t},\n"
12292 : : "\t},\n",
12293 : : instr_type_to_name(instr),
12294 : 0 : instr->mov.dst.struct_id,
12295 : 0 : instr->mov.dst.n_bits,
12296 : 0 : instr->mov.dst.offset,
12297 : : instr->mov.src_val);
12298 : 0 : }
12299 : :
12300 : : static void
12301 : 0 : instr_movh_export(struct instruction *instr, FILE *f)
12302 : : {
12303 : 0 : fprintf(f,
12304 : : "\t{\n"
12305 : : "\t\t.type = %s,\n"
12306 : : "\t\t.mov = {\n"
12307 : : "\t\t\t.dst = {\n"
12308 : : "\t\t\t\t.struct_id = %u,\n"
12309 : : "\t\t\t\t.n_bits = %u,\n"
12310 : : "\t\t\t\t.offset = %u,\n"
12311 : : "\t\t\t},\n"
12312 : : "\t\t\t.src = {\n"
12313 : : "\t\t\t\t.struct_id = %u,\n"
12314 : : "\t\t\t\t.n_bits = %u,\n"
12315 : : "\t\t\t\t.offset = %u,\n"
12316 : : "\t\t\t},\n"
12317 : : "\t\t},\n"
12318 : : "\t},\n",
12319 : : instr_type_to_name(instr),
12320 : 0 : instr->mov.dst.struct_id,
12321 : 0 : instr->mov.dst.n_bits,
12322 : 0 : instr->mov.dst.offset,
12323 : 0 : instr->mov.src.struct_id,
12324 : 0 : instr->mov.src.n_bits,
12325 : 0 : instr->mov.src.offset);
12326 : 0 : }
12327 : :
12328 : : static void
12329 : 0 : instr_dma_ht_export(struct instruction *instr, FILE *f)
12330 : : {
12331 : : uint32_t n_dma = 0, i;
12332 : :
12333 : : /* n_dma. */
12334 : 0 : n_dma = 1 + (instr->type - INSTR_DMA_HT);
12335 : :
12336 : : /* instr. */
12337 : 0 : fprintf(f,
12338 : : "\t{\n"
12339 : : "\t\t.type = %s,\n",
12340 : : instr_type_to_name(instr));
12341 : :
12342 : : /* instr.dma. */
12343 : : fprintf(f,
12344 : : "\t\t.dma = {\n");
12345 : :
12346 : : /* instr.dma.dst. */
12347 : : fprintf(f,
12348 : : "\t\t\t.dst = {\n");
12349 : :
12350 : : /* instr.dma.dst.header_id. */
12351 : : fprintf(f,
12352 : : "\t\t\t\t.header_id = {");
12353 : :
12354 [ # # ]: 0 : for (i = 0; i < n_dma; i++)
12355 : 0 : fprintf(f,
12356 : : "%u, ",
12357 : 0 : instr->dma.dst.header_id[i]);
12358 : :
12359 : : fprintf(f,
12360 : : "},\n");
12361 : :
12362 : : /* instr.dma.dst.struct_id. */
12363 : : fprintf(f,
12364 : : "\t\t\t\t.struct_id = {");
12365 : :
12366 [ # # ]: 0 : for (i = 0; i < n_dma; i++)
12367 : 0 : fprintf(f,
12368 : : "%u, ",
12369 : 0 : instr->dma.dst.struct_id[i]);
12370 : :
12371 : : fprintf(f,
12372 : : "},\n");
12373 : :
12374 : : /* instr.dma.dst - closing curly brace. */
12375 : : fprintf(f,
12376 : : "\t\t\t},\n");
12377 : :
12378 : : /* instr.dma.src. */
12379 : : fprintf(f,
12380 : : "\t\t\t.src = {\n");
12381 : :
12382 : : /* instr.dma.src.offset. */
12383 : : fprintf(f,
12384 : : "\t\t\t\t.offset = {");
12385 : :
12386 [ # # ]: 0 : for (i = 0; i < n_dma; i++)
12387 : 0 : fprintf(f,
12388 : : "%u, ",
12389 : 0 : instr->dma.src.offset[i]);
12390 : :
12391 : : fprintf(f,
12392 : : "},\n");
12393 : :
12394 : : /* instr.dma.src - closing curly brace. */
12395 : : fprintf(f,
12396 : : "\t\t\t},\n");
12397 : :
12398 : : /* instr.dma.n_bytes. */
12399 : : fprintf(f,
12400 : : "\t\t\t.n_bytes = {");
12401 : :
12402 [ # # ]: 0 : for (i = 0; i < n_dma; i++)
12403 : 0 : fprintf(f,
12404 : : "%u, ",
12405 : 0 : instr->dma.n_bytes[i]);
12406 : :
12407 : : fprintf(f,
12408 : : "},\n");
12409 : :
12410 : : /* instr.dma - closing curly brace. */
12411 : : fprintf(f,
12412 : : "\t\t},\n");
12413 : :
12414 : : /* instr - closing curly brace. */
12415 : : fprintf(f,
12416 : : "\t},\n");
12417 : 0 : }
12418 : :
12419 : : static void
12420 : 0 : instr_alu_export(struct instruction *instr, FILE *f)
12421 : : {
12422 : : int imm = 0;
12423 : :
12424 : 0 : if (instr->type == INSTR_ALU_ADD_MI ||
12425 [ # # ]: 0 : instr->type == INSTR_ALU_ADD_HI ||
12426 : : instr->type == INSTR_ALU_SUB_MI ||
12427 : : instr->type == INSTR_ALU_SUB_HI ||
12428 : : instr->type == INSTR_ALU_SHL_MI ||
12429 : : instr->type == INSTR_ALU_SHL_HI ||
12430 : : instr->type == INSTR_ALU_SHR_MI ||
12431 : : instr->type == INSTR_ALU_SHR_HI ||
12432 : : instr->type == INSTR_ALU_AND_I ||
12433 : : instr->type == INSTR_ALU_OR_I ||
12434 : : instr->type == INSTR_ALU_XOR_I)
12435 : : imm = 1;
12436 : :
12437 : : if (!imm)
12438 : 0 : fprintf(f,
12439 : : "\t{\n"
12440 : : "\t\t.type = %s,\n"
12441 : : "\t\t.alu = {\n"
12442 : : "\t\t\t.dst = {\n"
12443 : : "\t\t\t\t.struct_id = %u,\n"
12444 : : "\t\t\t\t.n_bits = %u,\n"
12445 : : "\t\t\t\t.offset = %u,\n"
12446 : : "\t\t\t},\n"
12447 : : "\t\t\t.src = {\n"
12448 : : "\t\t\t\t.struct_id = %u,\n"
12449 : : "\t\t\t\t.n_bits = %u,\n"
12450 : : "\t\t\t\t.offset = %u,\n"
12451 : : "\t\t\t},\n"
12452 : : "\t\t},\n"
12453 : : "\t},\n",
12454 : : instr_type_to_name(instr),
12455 : 0 : instr->alu.dst.struct_id,
12456 : 0 : instr->alu.dst.n_bits,
12457 : 0 : instr->alu.dst.offset,
12458 : 0 : instr->alu.src.struct_id,
12459 : 0 : instr->alu.src.n_bits,
12460 : 0 : instr->alu.src.offset);
12461 : : else
12462 : 0 : fprintf(f,
12463 : : "\t{\n"
12464 : : "\t\t.type = %s,\n"
12465 : : "\t\t.alu = {\n"
12466 : : "\t\t\t.dst = {\n"
12467 : : "\t\t\t\t.struct_id = %u,\n"
12468 : : "\t\t\t\t.n_bits = %u,\n"
12469 : : "\t\t\t\t.offset = %u,\n"
12470 : : "\t\t\t}\n,"
12471 : : "\t\t\t.src_val = %" PRIu64 ",\n"
12472 : : "\t\t},\n"
12473 : : "\t},\n",
12474 : : instr_type_to_name(instr),
12475 : 0 : instr->alu.dst.struct_id,
12476 : 0 : instr->alu.dst.n_bits,
12477 : 0 : instr->alu.dst.offset,
12478 : : instr->alu.src_val);
12479 : 0 : }
12480 : :
12481 : : static void
12482 : 0 : instr_hash_export(struct instruction *instr, FILE *f)
12483 : : {
12484 : 0 : fprintf(f,
12485 : : "\t{\n"
12486 : : "\t\t.type = %s,\n"
12487 : : "\t\t.hash_func = {\n"
12488 : : "\t\t\t.hash_func_id = %u,\n"
12489 : : "\t\t\t.dst = {\n"
12490 : : "\t\t\t\t.offset = %u,\n"
12491 : : "\t\t\t\t.n_bits = %u,\n"
12492 : : "\t\t\t},\n"
12493 : : "\t\t\t.src = {\n"
12494 : : "\t\t\t\t.struct_id = %u,\n"
12495 : : "\t\t\t\t.offset = %u,\n"
12496 : : "\t\t\t\t.n_bytes = %u,\n"
12497 : : "\t\t\t},\n"
12498 : : "\t\t},\n"
12499 : : "\t},\n",
12500 : : instr_type_to_name(instr),
12501 : 0 : instr->hash_func.hash_func_id,
12502 : 0 : instr->hash_func.dst.offset,
12503 : 0 : instr->hash_func.dst.n_bits,
12504 : 0 : instr->hash_func.src.struct_id,
12505 : 0 : instr->hash_func.src.offset,
12506 : 0 : instr->hash_func.src.n_bytes);
12507 : 0 : }
12508 : :
12509 : : static void
12510 : 0 : instr_rss_export(struct instruction *instr, FILE *f)
12511 : : {
12512 : 0 : fprintf(f,
12513 : : "\t{\n"
12514 : : "\t\t.type = %s,\n"
12515 : : "\t\t.rss = {\n"
12516 : : "\t\t\t.rss_obj_id = %u,\n"
12517 : : "\t\t\t.dst = {\n"
12518 : : "\t\t\t\t.offset = %u,\n"
12519 : : "\t\t\t\t.n_bits = %u,\n"
12520 : : "\t\t\t},\n"
12521 : : "\t\t\t.src = {\n"
12522 : : "\t\t\t\t.struct_id = %u,\n"
12523 : : "\t\t\t\t.offset = %u,\n"
12524 : : "\t\t\t\t.n_bytes = %u,\n"
12525 : : "\t\t\t},\n"
12526 : : "\t\t},\n"
12527 : : "\t},\n",
12528 : : instr_type_to_name(instr),
12529 : 0 : instr->rss.rss_obj_id,
12530 : 0 : instr->rss.dst.offset,
12531 : 0 : instr->rss.dst.n_bits,
12532 : 0 : instr->rss.src.struct_id,
12533 : 0 : instr->rss.src.offset,
12534 : 0 : instr->rss.src.n_bytes);
12535 : 0 : }
12536 : :
12537 : : static void
12538 : 0 : instr_reg_export(struct instruction *instr __rte_unused, FILE *f __rte_unused)
12539 : : {
12540 : : int prefetch = 0, idx_imm = 0, src_imm = 0;
12541 : :
12542 : 0 : if (instr->type == INSTR_REGPREFETCH_RH ||
12543 [ # # ]: 0 : instr->type == INSTR_REGPREFETCH_RM ||
12544 : : instr->type == INSTR_REGPREFETCH_RI)
12545 : : prefetch = 1;
12546 : :
12547 : : /* index is the 3rd operand for the regrd instruction and the 2nd
12548 : : * operand for the regwr and regadd instructions.
12549 : : */
12550 [ # # ]: 0 : if (instr->type == INSTR_REGPREFETCH_RI ||
12551 : : instr->type == INSTR_REGRD_HRI ||
12552 : : instr->type == INSTR_REGRD_MRI ||
12553 : : instr->type == INSTR_REGWR_RIH ||
12554 : : instr->type == INSTR_REGWR_RIM ||
12555 : : instr->type == INSTR_REGWR_RII ||
12556 : : instr->type == INSTR_REGADD_RIH ||
12557 : : instr->type == INSTR_REGADD_RIM ||
12558 : : instr->type == INSTR_REGADD_RII)
12559 : : idx_imm = 1;
12560 : :
12561 : : /* src is the 3rd operand for the regwr and regadd instructions. */
12562 [ # # ]: 0 : if (instr->type == INSTR_REGWR_RHI ||
12563 : : instr->type == INSTR_REGWR_RMI ||
12564 : : instr->type == INSTR_REGWR_RII ||
12565 : : instr->type == INSTR_REGADD_RHI ||
12566 : : instr->type == INSTR_REGADD_RMI ||
12567 : : instr->type == INSTR_REGADD_RII)
12568 : : src_imm = 1;
12569 : :
12570 : : /* instr.regarray.regarray_id. */
12571 : 0 : fprintf(f,
12572 : : "\t{\n"
12573 : : "\t\t.type = %s,\n"
12574 : : "\t\t.regarray = {\n"
12575 : : "\t\t\t.regarray_id = %u,\n",
12576 : : instr_type_to_name(instr),
12577 : 0 : instr->regarray.regarray_id);
12578 : :
12579 : : /* instr.regarray.idx / instr.regarray.idx_val. */
12580 [ # # ]: 0 : if (!idx_imm)
12581 : 0 : fprintf(f,
12582 : : "\t\t\t\t.idx = {\n"
12583 : : "\t\t\t\t\t.struct_id = %u,\n"
12584 : : "\t\t\t\t\t.n_bits = %u,\n"
12585 : : "\t\t\t\t\t.offset = %u,\n"
12586 : : "\t\t\t\t},\n",
12587 : 0 : instr->regarray.idx.struct_id,
12588 : 0 : instr->regarray.idx.n_bits,
12589 : 0 : instr->regarray.idx.offset);
12590 : : else
12591 : 0 : fprintf(f,
12592 : : "\t\t\t\t.idx_val = %u,\n",
12593 : : instr->regarray.idx_val);
12594 : :
12595 : : /* instr.regarray.dstsrc / instr.regarray.dstsrc_val. */
12596 [ # # ]: 0 : if (!prefetch) {
12597 [ # # ]: 0 : if (!src_imm)
12598 : 0 : fprintf(f,
12599 : : "\t\t\t\t.dstsrc = {\n"
12600 : : "\t\t\t\t\t.struct_id = %u,\n"
12601 : : "\t\t\t\t\t.n_bits = %u,\n"
12602 : : "\t\t\t\t\t.offset = %u,\n"
12603 : : "\t\t\t\t},\n",
12604 : 0 : instr->regarray.dstsrc.struct_id,
12605 : 0 : instr->regarray.dstsrc.n_bits,
12606 : 0 : instr->regarray.dstsrc.offset);
12607 : : else
12608 : 0 : fprintf(f,
12609 : : "\t\t\t\t.dstsrc_val = %" PRIu64 ",\n",
12610 : : instr->regarray.dstsrc_val);
12611 : : }
12612 : :
12613 : : /* instr.regarray and instr - closing curly braces. */
12614 : : fprintf(f,
12615 : : "\t\t},\n"
12616 : : "\t},\n");
12617 : 0 : }
12618 : :
12619 : : static void
12620 : 0 : instr_meter_export(struct instruction *instr __rte_unused, FILE *f __rte_unused)
12621 : : {
12622 : : int prefetch = 0, idx_imm = 0, color_in_imm = 0;
12623 : :
12624 : 0 : if (instr->type == INSTR_METPREFETCH_H ||
12625 [ # # ]: 0 : instr->type == INSTR_METPREFETCH_M ||
12626 : : instr->type == INSTR_METPREFETCH_I)
12627 : : prefetch = 1;
12628 : :
12629 : : /* idx_imm. */
12630 [ # # ]: 0 : if (instr->type == INSTR_METPREFETCH_I ||
12631 [ # # ]: 0 : instr->type == INSTR_METER_IHM ||
12632 [ # # ]: 0 : instr->type == INSTR_METER_IHI ||
12633 [ # # ]: 0 : instr->type == INSTR_METER_IMM ||
12634 : : instr->type == INSTR_METER_IMI)
12635 : : idx_imm = 1;
12636 : :
12637 : : /* color_in_imm. */
12638 [ # # ]: 0 : if (instr->type == INSTR_METER_HHI ||
12639 : : instr->type == INSTR_METER_HMI ||
12640 : : instr->type == INSTR_METER_MHI ||
12641 : : instr->type == INSTR_METER_MMI ||
12642 : : instr->type == INSTR_METER_IHI ||
12643 : : instr->type == INSTR_METER_IMI)
12644 : : color_in_imm = 1;
12645 : :
12646 : : /* instr.meter.metarray_id. */
12647 : 0 : fprintf(f,
12648 : : "\t{\n"
12649 : : "\t\t.type = %s,\n"
12650 : : "\t\t.meter = {\n"
12651 : : "\t\t\t.metarray_id = %u,\n",
12652 : : instr_type_to_name(instr),
12653 : 0 : instr->meter.metarray_id);
12654 : :
12655 : : /* instr.meter.idx / instr.meter.idx_val. */
12656 [ # # ]: 0 : if (!idx_imm)
12657 : 0 : fprintf(f,
12658 : : "\t\t\t.idx = {\n"
12659 : : "\t\t\t\t.struct_id = %u,\n"
12660 : : "\t\t\t\t.n_bits = %u,\n"
12661 : : "\t\t\t\t.offset = %u,\n"
12662 : : "\t\t\t},\n",
12663 : 0 : instr->meter.idx.struct_id,
12664 : 0 : instr->meter.idx.n_bits,
12665 : 0 : instr->meter.idx.offset);
12666 : : else
12667 : 0 : fprintf(f,
12668 : : "\t\t\t.idx_val = %u,\n",
12669 : : instr->meter.idx_val);
12670 : :
12671 [ # # ]: 0 : if (!prefetch) {
12672 : : /* instr.meter.length. */
12673 : 0 : fprintf(f,
12674 : : "\t\t\t.length = {\n"
12675 : : "\t\t\t\t.struct_id = %u,\n"
12676 : : "\t\t\t\t.n_bits = %u,\n"
12677 : : "\t\t\t\t.offset = %u,\n"
12678 : : "\t\t\t},\n",
12679 : 0 : instr->meter.length.struct_id,
12680 : 0 : instr->meter.length.n_bits,
12681 : 0 : instr->meter.length.offset);
12682 : :
12683 : : /* instr.meter.color_in / instr.meter.color_in_val. */
12684 [ # # ]: 0 : if (!color_in_imm)
12685 : 0 : fprintf(f,
12686 : : "\t\t\t.color_in = {\n"
12687 : : "\t\t\t\t.struct_id = %u,\n"
12688 : : "\t\t\t\t.n_bits = %u,\n"
12689 : : "\t\t\t\t.offset = %u,\n"
12690 : : "\t\t\t},\n",
12691 : 0 : instr->meter.color_in.struct_id,
12692 : 0 : instr->meter.color_in.n_bits,
12693 : 0 : instr->meter.color_in.offset);
12694 : : else
12695 : : fprintf(f,
12696 : : "\t\t\t.color_in_val = %u,\n",
12697 : 0 : (uint32_t)instr->meter.color_in_val);
12698 : :
12699 : : /* instr.meter.color_out. */
12700 : 0 : fprintf(f,
12701 : : "\t\t\t.color_out = {\n"
12702 : : "\t\t\t\t.struct_id = %u,\n"
12703 : : "\t\t\t\t.n_bits = %u,\n"
12704 : : "\t\t\t\t.offset = %u,\n"
12705 : : "\t\t\t},\n",
12706 : 0 : instr->meter.color_out.struct_id,
12707 : 0 : instr->meter.color_out.n_bits,
12708 : 0 : instr->meter.color_out.offset);
12709 : : }
12710 : :
12711 : : /* instr.meter and instr - closing curly braces. */
12712 : : fprintf(f,
12713 : : "\t\t},\n"
12714 : : "\t},\n");
12715 : 0 : }
12716 : :
12717 : : static void
12718 : 0 : instr_table_export(struct instruction *instr,
12719 : : FILE *f)
12720 : : {
12721 : 0 : fprintf(f,
12722 : : "\t{\n"
12723 : : "\t\t.type = %s,\n"
12724 : : "\t\t.table = {\n"
12725 : : "\t\t\t.table_id = %u,\n"
12726 : : "\t\t},\n"
12727 : : "\t},\n",
12728 : : instr_type_to_name(instr),
12729 : 0 : instr->table.table_id);
12730 : 0 : }
12731 : :
12732 : : static void
12733 : 0 : instr_learn_export(struct instruction *instr, FILE *f)
12734 : : {
12735 : 0 : fprintf(f,
12736 : : "\t{\n"
12737 : : "\t\t.type = %s,\n"
12738 : : "\t\t.learn = {\n"
12739 : : "\t\t\t.action_id = %u,\n"
12740 : : "\t\t\t.mf_first_arg_offset = %u,\n"
12741 : : "\t\t\t.mf_timeout_id_offset = %u,\n"
12742 : : "\t\t\t.mf_timeout_id_n_bits = %u,\n"
12743 : : "\t\t},\n"
12744 : : "\t},\n",
12745 : : instr_type_to_name(instr),
12746 : 0 : instr->learn.action_id,
12747 : 0 : instr->learn.mf_first_arg_offset,
12748 : 0 : instr->learn.mf_timeout_id_offset,
12749 : 0 : instr->learn.mf_timeout_id_n_bits);
12750 : 0 : }
12751 : :
12752 : : static void
12753 : 0 : instr_rearm_export(struct instruction *instr, FILE *f)
12754 : : {
12755 [ # # ]: 0 : if (instr->type == INSTR_LEARNER_REARM)
12756 : 0 : fprintf(f,
12757 : : "\t{\n"
12758 : : "\t\t.type = %s,\n"
12759 : : "\t},\n",
12760 : : instr_type_to_name(instr));
12761 : : else
12762 : 0 : fprintf(f,
12763 : : "\t{\n"
12764 : : "\t\t.type = %s,\n"
12765 : : "\t\t.learn = {\n"
12766 : : "\t\t\t.mf_timeout_id_offset = %u,\n"
12767 : : "\t\t\t.mf_timeout_id_n_bits = %u,\n"
12768 : : "\t\t},\n"
12769 : : "\t},\n",
12770 : : instr_type_to_name(instr),
12771 : 0 : instr->learn.mf_timeout_id_offset,
12772 : 0 : instr->learn.mf_timeout_id_n_bits);
12773 : 0 : }
12774 : :
12775 : : static void
12776 : 0 : instr_forget_export(struct instruction *instr, FILE *f)
12777 : : {
12778 : 0 : fprintf(f,
12779 : : "\t{\n"
12780 : : "\t\t.type = %s,\n"
12781 : : "\t},\n",
12782 : : instr_type_to_name(instr));
12783 : 0 : }
12784 : :
12785 : : static void
12786 : 0 : instr_entryid_export(struct instruction *instr, FILE *f)
12787 : : {
12788 : 0 : fprintf(f,
12789 : : "\t{\n"
12790 : : "\t\t.type = %s,\n"
12791 : : "\t\t.mov = {\n"
12792 : : "\t\t\t.dst = {\n"
12793 : : "\t\t\t\t.n_bits = %u,\n"
12794 : : "\t\t\t\t.offset = %u,\n"
12795 : : "\t\t\t},\n"
12796 : : "\t\t},\n"
12797 : : "\t},\n",
12798 : : instr_type_to_name(instr),
12799 : 0 : instr->mov.dst.n_bits,
12800 : 0 : instr->mov.dst.offset);
12801 : 0 : }
12802 : :
12803 : : static void
12804 : 0 : instr_extern_export(struct instruction *instr, FILE *f)
12805 : : {
12806 [ # # ]: 0 : if (instr->type == INSTR_EXTERN_OBJ)
12807 : 0 : fprintf(f,
12808 : : "\t{\n"
12809 : : "\t\t.type = %s,\n"
12810 : : "\t\t.ext_obj = {\n"
12811 : : "\t\t\t.ext_obj_id = %u,\n"
12812 : : "\t\t\t.func_id = %u,\n"
12813 : : "\t\t},\n"
12814 : : "\t},\n",
12815 : : instr_type_to_name(instr),
12816 : 0 : instr->ext_obj.ext_obj_id,
12817 : 0 : instr->ext_obj.func_id);
12818 : : else
12819 : 0 : fprintf(f,
12820 : : "\t{\n"
12821 : : "\t\t.type = %s,\n"
12822 : : "\t\t.ext_func = {\n"
12823 : : "\t\t\t.ext_func_id = %u,\n"
12824 : : "\t\t},\n"
12825 : : "\t},\n",
12826 : : instr_type_to_name(instr),
12827 : 0 : instr->ext_func.ext_func_id);
12828 : 0 : }
12829 : :
12830 : : static void
12831 : 0 : instr_jmp_export(struct instruction *instr, FILE *f __rte_unused)
12832 : : {
12833 : 0 : fprintf(f,
12834 : : "\t{\n"
12835 : : "\t\t.type = %s,\n"
12836 : : "\t\t.jmp = {\n"
12837 : : "\t\t\t.ip = NULL,\n",
12838 : : instr_type_to_name(instr));
12839 : :
12840 [ # # # # : 0 : switch (instr->type) {
# ]
12841 : 0 : case INSTR_JMP_VALID:
12842 : : case INSTR_JMP_INVALID:
12843 : 0 : fprintf(f,
12844 : : "\t\t\t.header_id = %u,\n",
12845 : 0 : instr->jmp.header_id);
12846 : : break;
12847 : :
12848 : 0 : case INSTR_JMP_ACTION_HIT:
12849 : : case INSTR_JMP_ACTION_MISS:
12850 : 0 : fprintf(f,
12851 : : "\t\t\t.action_id = %u,\n",
12852 : 0 : instr->jmp.action_id);
12853 : : break;
12854 : :
12855 : 0 : case INSTR_JMP_EQ:
12856 : : case INSTR_JMP_EQ_MH:
12857 : : case INSTR_JMP_EQ_HM:
12858 : : case INSTR_JMP_EQ_HH:
12859 : : case INSTR_JMP_NEQ:
12860 : : case INSTR_JMP_NEQ_MH:
12861 : : case INSTR_JMP_NEQ_HM:
12862 : : case INSTR_JMP_NEQ_HH:
12863 : : case INSTR_JMP_LT:
12864 : : case INSTR_JMP_LT_MH:
12865 : : case INSTR_JMP_LT_HM:
12866 : : case INSTR_JMP_LT_HH:
12867 : : case INSTR_JMP_GT:
12868 : : case INSTR_JMP_GT_MH:
12869 : : case INSTR_JMP_GT_HM:
12870 : : case INSTR_JMP_GT_HH:
12871 : 0 : fprintf(f,
12872 : : "\t\t\t.a = {\n"
12873 : : "\t\t\t\t.struct_id = %u,\n"
12874 : : "\t\t\t\t.n_bits = %u,\n"
12875 : : "\t\t\t\t.offset = %u,\n"
12876 : : "\t\t\t},\n"
12877 : : "\t\t\t.b = {\n"
12878 : : "\t\t\t\t.struct_id = %u,\n"
12879 : : "\t\t\t\t.n_bits = %u,\n"
12880 : : "\t\t\t\t.offset = %u,\n"
12881 : : "\t\t\t},\n",
12882 : 0 : instr->jmp.a.struct_id,
12883 : 0 : instr->jmp.a.n_bits,
12884 : 0 : instr->jmp.a.offset,
12885 : 0 : instr->jmp.b.struct_id,
12886 : 0 : instr->jmp.b.n_bits,
12887 : 0 : instr->jmp.b.offset);
12888 : : break;
12889 : :
12890 : 0 : case INSTR_JMP_EQ_I:
12891 : : case INSTR_JMP_NEQ_I:
12892 : : case INSTR_JMP_LT_MI:
12893 : : case INSTR_JMP_LT_HI:
12894 : : case INSTR_JMP_GT_MI:
12895 : : case INSTR_JMP_GT_HI:
12896 : 0 : fprintf(f,
12897 : : "\t\t\t.a = {\n"
12898 : : "\t\t\t\t.struct_id = %u,\n"
12899 : : "\t\t\t\t.n_bits = %u,\n"
12900 : : "\t\t\t\t.offset = %u,\n"
12901 : : "\t\t\t}\n,"
12902 : : "\t\t\t.b_val = %" PRIu64 ",\n",
12903 : 0 : instr->jmp.a.struct_id,
12904 : 0 : instr->jmp.a.n_bits,
12905 : 0 : instr->jmp.a.offset,
12906 : : instr->jmp.b_val);
12907 : : break;
12908 : :
12909 : : default:
12910 : : break;
12911 : : }
12912 : :
12913 : : fprintf(f,
12914 : : "\t\t},\n"
12915 : : "\t},\n");
12916 : 0 : }
12917 : :
12918 : : static void
12919 : 0 : instr_return_export(struct instruction *instr,
12920 : : FILE *f)
12921 : : {
12922 : 0 : fprintf(f,
12923 : : "\t{\n"
12924 : : "\t\t.type = %s,\n",
12925 : : instr_type_to_name(instr));
12926 : :
12927 : : fprintf(f,
12928 : : "\t},\n");
12929 : 0 : }
12930 : :
12931 : : static instruction_export_t export_table[] = {
12932 : : [INSTR_RX] = instr_io_export,
12933 : :
12934 : : [INSTR_TX] = instr_io_export,
12935 : : [INSTR_TX_I] = instr_io_export,
12936 : : [INSTR_DROP] = instr_io_export,
12937 : : [INSTR_MIRROR] = instr_mirror_export,
12938 : : [INSTR_RECIRCULATE] = instr_recirculate_export,
12939 : : [INSTR_RECIRCID] = instr_recircid_export,
12940 : :
12941 : : [INSTR_HDR_EXTRACT] = instr_io_export,
12942 : : [INSTR_HDR_EXTRACT2] = instr_io_export,
12943 : : [INSTR_HDR_EXTRACT3] = instr_io_export,
12944 : : [INSTR_HDR_EXTRACT4] = instr_io_export,
12945 : : [INSTR_HDR_EXTRACT5] = instr_io_export,
12946 : : [INSTR_HDR_EXTRACT6] = instr_io_export,
12947 : : [INSTR_HDR_EXTRACT7] = instr_io_export,
12948 : : [INSTR_HDR_EXTRACT8] = instr_io_export,
12949 : :
12950 : : [INSTR_HDR_EXTRACT_M] = instr_io_export,
12951 : :
12952 : : [INSTR_HDR_LOOKAHEAD] = instr_io_export,
12953 : :
12954 : : [INSTR_HDR_EMIT] = instr_io_export,
12955 : : [INSTR_HDR_EMIT_TX] = instr_io_export,
12956 : : [INSTR_HDR_EMIT2_TX] = instr_io_export,
12957 : : [INSTR_HDR_EMIT3_TX] = instr_io_export,
12958 : : [INSTR_HDR_EMIT4_TX] = instr_io_export,
12959 : : [INSTR_HDR_EMIT5_TX] = instr_io_export,
12960 : : [INSTR_HDR_EMIT6_TX] = instr_io_export,
12961 : : [INSTR_HDR_EMIT7_TX] = instr_io_export,
12962 : : [INSTR_HDR_EMIT8_TX] = instr_io_export,
12963 : :
12964 : : [INSTR_HDR_VALIDATE] = instr_hdr_validate_export,
12965 : : [INSTR_HDR_INVALIDATE] = instr_hdr_validate_export,
12966 : :
12967 : : [INSTR_MOV] = instr_mov_export,
12968 : : [INSTR_MOV_MH] = instr_mov_export,
12969 : : [INSTR_MOV_HM] = instr_mov_export,
12970 : : [INSTR_MOV_HH] = instr_mov_export,
12971 : : [INSTR_MOV_DMA] = instr_mov_export,
12972 : : [INSTR_MOV_128] = instr_mov_export,
12973 : : [INSTR_MOV_128_64] = instr_mov_export,
12974 : : [INSTR_MOV_64_128] = instr_mov_export,
12975 : : [INSTR_MOV_128_32] = instr_mov_export,
12976 : : [INSTR_MOV_32_128] = instr_mov_export,
12977 : : [INSTR_MOV_I] = instr_mov_export,
12978 : :
12979 : : [INSTR_MOVH] = instr_movh_export,
12980 : :
12981 : : [INSTR_DMA_HT] = instr_dma_ht_export,
12982 : : [INSTR_DMA_HT2] = instr_dma_ht_export,
12983 : : [INSTR_DMA_HT3] = instr_dma_ht_export,
12984 : : [INSTR_DMA_HT4] = instr_dma_ht_export,
12985 : : [INSTR_DMA_HT5] = instr_dma_ht_export,
12986 : : [INSTR_DMA_HT6] = instr_dma_ht_export,
12987 : : [INSTR_DMA_HT7] = instr_dma_ht_export,
12988 : : [INSTR_DMA_HT8] = instr_dma_ht_export,
12989 : :
12990 : : [INSTR_ALU_ADD] = instr_alu_export,
12991 : : [INSTR_ALU_ADD_MH] = instr_alu_export,
12992 : : [INSTR_ALU_ADD_HM] = instr_alu_export,
12993 : : [INSTR_ALU_ADD_HH] = instr_alu_export,
12994 : : [INSTR_ALU_ADD_MI] = instr_alu_export,
12995 : : [INSTR_ALU_ADD_HI] = instr_alu_export,
12996 : :
12997 : : [INSTR_ALU_SUB] = instr_alu_export,
12998 : : [INSTR_ALU_SUB_MH] = instr_alu_export,
12999 : : [INSTR_ALU_SUB_HM] = instr_alu_export,
13000 : : [INSTR_ALU_SUB_HH] = instr_alu_export,
13001 : : [INSTR_ALU_SUB_MI] = instr_alu_export,
13002 : : [INSTR_ALU_SUB_HI] = instr_alu_export,
13003 : :
13004 : : [INSTR_ALU_CKADD_FIELD] = instr_alu_export,
13005 : : [INSTR_ALU_CKADD_STRUCT] = instr_alu_export,
13006 : : [INSTR_ALU_CKADD_STRUCT20] = instr_alu_export,
13007 : : [INSTR_ALU_CKSUB_FIELD] = instr_alu_export,
13008 : :
13009 : : [INSTR_ALU_AND] = instr_alu_export,
13010 : : [INSTR_ALU_AND_MH] = instr_alu_export,
13011 : : [INSTR_ALU_AND_HM] = instr_alu_export,
13012 : : [INSTR_ALU_AND_HH] = instr_alu_export,
13013 : : [INSTR_ALU_AND_I] = instr_alu_export,
13014 : :
13015 : : [INSTR_ALU_OR] = instr_alu_export,
13016 : : [INSTR_ALU_OR_MH] = instr_alu_export,
13017 : : [INSTR_ALU_OR_HM] = instr_alu_export,
13018 : : [INSTR_ALU_OR_HH] = instr_alu_export,
13019 : : [INSTR_ALU_OR_I] = instr_alu_export,
13020 : :
13021 : : [INSTR_ALU_XOR] = instr_alu_export,
13022 : : [INSTR_ALU_XOR_MH] = instr_alu_export,
13023 : : [INSTR_ALU_XOR_HM] = instr_alu_export,
13024 : : [INSTR_ALU_XOR_HH] = instr_alu_export,
13025 : : [INSTR_ALU_XOR_I] = instr_alu_export,
13026 : :
13027 : : [INSTR_ALU_SHL] = instr_alu_export,
13028 : : [INSTR_ALU_SHL_MH] = instr_alu_export,
13029 : : [INSTR_ALU_SHL_HM] = instr_alu_export,
13030 : : [INSTR_ALU_SHL_HH] = instr_alu_export,
13031 : : [INSTR_ALU_SHL_MI] = instr_alu_export,
13032 : : [INSTR_ALU_SHL_HI] = instr_alu_export,
13033 : :
13034 : : [INSTR_ALU_SHR] = instr_alu_export,
13035 : : [INSTR_ALU_SHR_MH] = instr_alu_export,
13036 : : [INSTR_ALU_SHR_HM] = instr_alu_export,
13037 : : [INSTR_ALU_SHR_HH] = instr_alu_export,
13038 : : [INSTR_ALU_SHR_MI] = instr_alu_export,
13039 : : [INSTR_ALU_SHR_HI] = instr_alu_export,
13040 : :
13041 : : [INSTR_REGPREFETCH_RH] = instr_reg_export,
13042 : : [INSTR_REGPREFETCH_RM] = instr_reg_export,
13043 : : [INSTR_REGPREFETCH_RI] = instr_reg_export,
13044 : :
13045 : : [INSTR_REGRD_HRH] = instr_reg_export,
13046 : : [INSTR_REGRD_HRM] = instr_reg_export,
13047 : : [INSTR_REGRD_MRH] = instr_reg_export,
13048 : : [INSTR_REGRD_MRM] = instr_reg_export,
13049 : : [INSTR_REGRD_HRI] = instr_reg_export,
13050 : : [INSTR_REGRD_MRI] = instr_reg_export,
13051 : :
13052 : : [INSTR_REGWR_RHH] = instr_reg_export,
13053 : : [INSTR_REGWR_RHM] = instr_reg_export,
13054 : : [INSTR_REGWR_RMH] = instr_reg_export,
13055 : : [INSTR_REGWR_RMM] = instr_reg_export,
13056 : : [INSTR_REGWR_RHI] = instr_reg_export,
13057 : : [INSTR_REGWR_RMI] = instr_reg_export,
13058 : : [INSTR_REGWR_RIH] = instr_reg_export,
13059 : : [INSTR_REGWR_RIM] = instr_reg_export,
13060 : : [INSTR_REGWR_RII] = instr_reg_export,
13061 : :
13062 : : [INSTR_REGADD_RHH] = instr_reg_export,
13063 : : [INSTR_REGADD_RHM] = instr_reg_export,
13064 : : [INSTR_REGADD_RMH] = instr_reg_export,
13065 : : [INSTR_REGADD_RMM] = instr_reg_export,
13066 : : [INSTR_REGADD_RHI] = instr_reg_export,
13067 : : [INSTR_REGADD_RMI] = instr_reg_export,
13068 : : [INSTR_REGADD_RIH] = instr_reg_export,
13069 : : [INSTR_REGADD_RIM] = instr_reg_export,
13070 : : [INSTR_REGADD_RII] = instr_reg_export,
13071 : :
13072 : : [INSTR_METPREFETCH_H] = instr_meter_export,
13073 : : [INSTR_METPREFETCH_M] = instr_meter_export,
13074 : : [INSTR_METPREFETCH_I] = instr_meter_export,
13075 : :
13076 : : [INSTR_METER_HHM] = instr_meter_export,
13077 : : [INSTR_METER_HHI] = instr_meter_export,
13078 : : [INSTR_METER_HMM] = instr_meter_export,
13079 : : [INSTR_METER_HMI] = instr_meter_export,
13080 : : [INSTR_METER_MHM] = instr_meter_export,
13081 : : [INSTR_METER_MHI] = instr_meter_export,
13082 : : [INSTR_METER_MMM] = instr_meter_export,
13083 : : [INSTR_METER_MMI] = instr_meter_export,
13084 : : [INSTR_METER_IHM] = instr_meter_export,
13085 : : [INSTR_METER_IHI] = instr_meter_export,
13086 : : [INSTR_METER_IMM] = instr_meter_export,
13087 : : [INSTR_METER_IMI] = instr_meter_export,
13088 : :
13089 : : [INSTR_TABLE] = instr_table_export,
13090 : : [INSTR_TABLE_AF] = instr_table_export,
13091 : : [INSTR_SELECTOR] = instr_table_export,
13092 : : [INSTR_LEARNER] = instr_table_export,
13093 : : [INSTR_LEARNER_AF] = instr_table_export,
13094 : :
13095 : : [INSTR_LEARNER_LEARN] = instr_learn_export,
13096 : : [INSTR_LEARNER_REARM] = instr_rearm_export,
13097 : : [INSTR_LEARNER_REARM_NEW] = instr_rearm_export,
13098 : : [INSTR_LEARNER_FORGET] = instr_forget_export,
13099 : : [INSTR_ENTRYID] = instr_entryid_export,
13100 : :
13101 : : [INSTR_EXTERN_OBJ] = instr_extern_export,
13102 : : [INSTR_EXTERN_FUNC] = instr_extern_export,
13103 : : [INSTR_HASH_FUNC] = instr_hash_export,
13104 : : [INSTR_RSS] = instr_rss_export,
13105 : :
13106 : : [INSTR_JMP] = instr_jmp_export,
13107 : : [INSTR_JMP_VALID] = instr_jmp_export,
13108 : : [INSTR_JMP_INVALID] = instr_jmp_export,
13109 : : [INSTR_JMP_HIT] = instr_jmp_export,
13110 : : [INSTR_JMP_MISS] = instr_jmp_export,
13111 : : [INSTR_JMP_ACTION_HIT] = instr_jmp_export,
13112 : : [INSTR_JMP_ACTION_MISS] = instr_jmp_export,
13113 : :
13114 : : [INSTR_JMP_EQ] = instr_jmp_export,
13115 : : [INSTR_JMP_EQ_MH] = instr_jmp_export,
13116 : : [INSTR_JMP_EQ_HM] = instr_jmp_export,
13117 : : [INSTR_JMP_EQ_HH] = instr_jmp_export,
13118 : : [INSTR_JMP_EQ_I] = instr_jmp_export,
13119 : :
13120 : : [INSTR_JMP_NEQ] = instr_jmp_export,
13121 : : [INSTR_JMP_NEQ_MH] = instr_jmp_export,
13122 : : [INSTR_JMP_NEQ_HM] = instr_jmp_export,
13123 : : [INSTR_JMP_NEQ_HH] = instr_jmp_export,
13124 : : [INSTR_JMP_NEQ_I] = instr_jmp_export,
13125 : :
13126 : : [INSTR_JMP_LT] = instr_jmp_export,
13127 : : [INSTR_JMP_LT_MH] = instr_jmp_export,
13128 : : [INSTR_JMP_LT_HM] = instr_jmp_export,
13129 : : [INSTR_JMP_LT_HH] = instr_jmp_export,
13130 : : [INSTR_JMP_LT_MI] = instr_jmp_export,
13131 : : [INSTR_JMP_LT_HI] = instr_jmp_export,
13132 : :
13133 : : [INSTR_JMP_GT] = instr_jmp_export,
13134 : : [INSTR_JMP_GT_MH] = instr_jmp_export,
13135 : : [INSTR_JMP_GT_HM] = instr_jmp_export,
13136 : : [INSTR_JMP_GT_HH] = instr_jmp_export,
13137 : : [INSTR_JMP_GT_MI] = instr_jmp_export,
13138 : : [INSTR_JMP_GT_HI] = instr_jmp_export,
13139 : :
13140 : : [INSTR_RETURN] = instr_return_export,
13141 : : };
13142 : :
13143 : : static void
13144 : 0 : action_data_codegen(struct action *a, FILE *f)
13145 : : {
13146 : : uint32_t i;
13147 : :
13148 : : fprintf(f,
13149 : : "static const struct instruction action_%s_instructions[] = {\n",
13150 : 0 : a->name);
13151 : :
13152 [ # # ]: 0 : for (i = 0; i < a->n_instructions; i++) {
13153 : 0 : struct instruction *instr = &a->instructions[i];
13154 : 0 : instruction_export_t func = export_table[instr->type];
13155 : :
13156 : 0 : func(instr, f);
13157 : : }
13158 : :
13159 : : fprintf(f, "};\n");
13160 : 0 : }
13161 : :
13162 : : static const char *
13163 : 0 : instr_type_to_func(struct instruction *instr)
13164 : : {
13165 [ # # # # : 0 : switch (instr->type) {
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
13166 : : case INSTR_RX: return NULL;
13167 : :
13168 : 0 : case INSTR_TX: return "__instr_tx_exec";
13169 : 0 : case INSTR_TX_I: return "__instr_tx_i_exec";
13170 : 0 : case INSTR_DROP: return "__instr_drop_exec";
13171 : 0 : case INSTR_MIRROR: return "__instr_mirror_exec";
13172 : 0 : case INSTR_RECIRCULATE: return "__instr_recirculate_exec";
13173 : 0 : case INSTR_RECIRCID: return "__instr_recircid_exec";
13174 : :
13175 : 0 : case INSTR_HDR_EXTRACT: return "__instr_hdr_extract_exec";
13176 : 0 : case INSTR_HDR_EXTRACT2: return "__instr_hdr_extract2_exec";
13177 : 0 : case INSTR_HDR_EXTRACT3: return "__instr_hdr_extract3_exec";
13178 : 0 : case INSTR_HDR_EXTRACT4: return "__instr_hdr_extract4_exec";
13179 : 0 : case INSTR_HDR_EXTRACT5: return "__instr_hdr_extract5_exec";
13180 : 0 : case INSTR_HDR_EXTRACT6: return "__instr_hdr_extract6_exec";
13181 : 0 : case INSTR_HDR_EXTRACT7: return "__instr_hdr_extract7_exec";
13182 : 0 : case INSTR_HDR_EXTRACT8: return "__instr_hdr_extract8_exec";
13183 : :
13184 : 0 : case INSTR_HDR_EXTRACT_M: return "__instr_hdr_extract_m_exec";
13185 : :
13186 : 0 : case INSTR_HDR_LOOKAHEAD: return "__instr_hdr_lookahead_exec";
13187 : :
13188 : 0 : case INSTR_HDR_EMIT: return "__instr_hdr_emit_exec";
13189 : 0 : case INSTR_HDR_EMIT_TX: return "__instr_hdr_emit_tx_exec";
13190 : 0 : case INSTR_HDR_EMIT2_TX: return "__instr_hdr_emit2_tx_exec";
13191 : 0 : case INSTR_HDR_EMIT3_TX: return "__instr_hdr_emit3_tx_exec";
13192 : 0 : case INSTR_HDR_EMIT4_TX: return "__instr_hdr_emit4_tx_exec";
13193 : 0 : case INSTR_HDR_EMIT5_TX: return "__instr_hdr_emit5_tx_exec";
13194 : 0 : case INSTR_HDR_EMIT6_TX: return "__instr_hdr_emit6_tx_exec";
13195 : 0 : case INSTR_HDR_EMIT7_TX: return "__instr_hdr_emit7_tx_exec";
13196 : 0 : case INSTR_HDR_EMIT8_TX: return "__instr_hdr_emit8_tx_exec";
13197 : :
13198 : 0 : case INSTR_HDR_VALIDATE: return "__instr_hdr_validate_exec";
13199 : 0 : case INSTR_HDR_INVALIDATE: return "__instr_hdr_invalidate_exec";
13200 : :
13201 : 0 : case INSTR_MOV: return "__instr_mov_exec";
13202 : 0 : case INSTR_MOV_MH: return "__instr_mov_mh_exec";
13203 : 0 : case INSTR_MOV_HM: return "__instr_mov_hm_exec";
13204 : 0 : case INSTR_MOV_HH: return "__instr_mov_hh_exec";
13205 : 0 : case INSTR_MOV_DMA: return "__instr_mov_dma_exec";
13206 : 0 : case INSTR_MOV_128: return "__instr_mov_128_exec";
13207 : 0 : case INSTR_MOV_128_64: return "__instr_mov_128_64_exec";
13208 : 0 : case INSTR_MOV_64_128: return "__instr_mov_64_128_exec";
13209 : 0 : case INSTR_MOV_128_32: return "__instr_mov_128_32_exec";
13210 : 0 : case INSTR_MOV_32_128: return "__instr_mov_32_128_exec";
13211 : 0 : case INSTR_MOV_I: return "__instr_mov_i_exec";
13212 : :
13213 : 0 : case INSTR_MOVH: return "__instr_movh_exec";
13214 : :
13215 : 0 : case INSTR_DMA_HT: return "__instr_dma_ht_exec";
13216 : 0 : case INSTR_DMA_HT2: return "__instr_dma_ht2_exec";
13217 : 0 : case INSTR_DMA_HT3: return "__instr_dma_ht3_exec";
13218 : 0 : case INSTR_DMA_HT4: return "__instr_dma_ht4_exec";
13219 : 0 : case INSTR_DMA_HT5: return "__instr_dma_ht5_exec";
13220 : 0 : case INSTR_DMA_HT6: return "__instr_dma_ht6_exec";
13221 : 0 : case INSTR_DMA_HT7: return "__instr_dma_ht7_exec";
13222 : 0 : case INSTR_DMA_HT8: return "__instr_dma_ht8_exec";
13223 : :
13224 : 0 : case INSTR_ALU_ADD: return "__instr_alu_add_exec";
13225 : 0 : case INSTR_ALU_ADD_MH: return "__instr_alu_add_mh_exec";
13226 : 0 : case INSTR_ALU_ADD_HM: return "__instr_alu_add_hm_exec";
13227 : 0 : case INSTR_ALU_ADD_HH: return "__instr_alu_add_hh_exec";
13228 : 0 : case INSTR_ALU_ADD_MI: return "__instr_alu_add_mi_exec";
13229 : 0 : case INSTR_ALU_ADD_HI: return "__instr_alu_add_hi_exec";
13230 : :
13231 : 0 : case INSTR_ALU_SUB: return "__instr_alu_sub_exec";
13232 : 0 : case INSTR_ALU_SUB_MH: return "__instr_alu_sub_mh_exec";
13233 : 0 : case INSTR_ALU_SUB_HM: return "__instr_alu_sub_hm_exec";
13234 : 0 : case INSTR_ALU_SUB_HH: return "__instr_alu_sub_hh_exec";
13235 : 0 : case INSTR_ALU_SUB_MI: return "__instr_alu_sub_mi_exec";
13236 : 0 : case INSTR_ALU_SUB_HI: return "__instr_alu_sub_hi_exec";
13237 : :
13238 : 0 : case INSTR_ALU_CKADD_FIELD: return "__instr_alu_ckadd_field_exec";
13239 : 0 : case INSTR_ALU_CKADD_STRUCT20: return "__instr_alu_ckadd_struct20_exec";
13240 : 0 : case INSTR_ALU_CKADD_STRUCT: return "__instr_alu_ckadd_struct_exec";
13241 : 0 : case INSTR_ALU_CKSUB_FIELD: return "__instr_alu_cksub_field_exec";
13242 : :
13243 : 0 : case INSTR_ALU_AND: return "__instr_alu_and_exec";
13244 : 0 : case INSTR_ALU_AND_MH: return "__instr_alu_and_mh_exec";
13245 : 0 : case INSTR_ALU_AND_HM: return "__instr_alu_and_hm_exec";
13246 : 0 : case INSTR_ALU_AND_HH: return "__instr_alu_and_hh_exec";
13247 : 0 : case INSTR_ALU_AND_I: return "__instr_alu_and_i_exec";
13248 : :
13249 : 0 : case INSTR_ALU_OR: return "__instr_alu_or_exec";
13250 : 0 : case INSTR_ALU_OR_MH: return "__instr_alu_or_mh_exec";
13251 : 0 : case INSTR_ALU_OR_HM: return "__instr_alu_or_hm_exec";
13252 : 0 : case INSTR_ALU_OR_HH: return "__instr_alu_or_hh_exec";
13253 : 0 : case INSTR_ALU_OR_I: return "__instr_alu_or_i_exec";
13254 : :
13255 : 0 : case INSTR_ALU_XOR: return "__instr_alu_xor_exec";
13256 : 0 : case INSTR_ALU_XOR_MH: return "__instr_alu_xor_mh_exec";
13257 : 0 : case INSTR_ALU_XOR_HM: return "__instr_alu_xor_hm_exec";
13258 : 0 : case INSTR_ALU_XOR_HH: return "__instr_alu_xor_hh_exec";
13259 : 0 : case INSTR_ALU_XOR_I: return "__instr_alu_xor_i_exec";
13260 : :
13261 : 0 : case INSTR_ALU_SHL: return "__instr_alu_shl_exec";
13262 : 0 : case INSTR_ALU_SHL_MH: return "__instr_alu_shl_mh_exec";
13263 : 0 : case INSTR_ALU_SHL_HM: return "__instr_alu_shl_hm_exec";
13264 : 0 : case INSTR_ALU_SHL_HH: return "__instr_alu_shl_hh_exec";
13265 : 0 : case INSTR_ALU_SHL_MI: return "__instr_alu_shl_mi_exec";
13266 : 0 : case INSTR_ALU_SHL_HI: return "__instr_alu_shl_hi_exec";
13267 : :
13268 : 0 : case INSTR_ALU_SHR: return "__instr_alu_shr_exec";
13269 : 0 : case INSTR_ALU_SHR_MH: return "__instr_alu_shr_mh_exec";
13270 : 0 : case INSTR_ALU_SHR_HM: return "__instr_alu_shr_hm_exec";
13271 : 0 : case INSTR_ALU_SHR_HH: return "__instr_alu_shr_hh_exec";
13272 : 0 : case INSTR_ALU_SHR_MI: return "__instr_alu_shr_mi_exec";
13273 : 0 : case INSTR_ALU_SHR_HI: return "__instr_alu_shr_hi_exec";
13274 : :
13275 : 0 : case INSTR_REGPREFETCH_RH: return "__instr_regprefetch_rh_exec";
13276 : 0 : case INSTR_REGPREFETCH_RM: return "__instr_regprefetch_rm_exec";
13277 : 0 : case INSTR_REGPREFETCH_RI: return "__instr_regprefetch_ri_exec";
13278 : :
13279 : 0 : case INSTR_REGRD_HRH: return "__instr_regrd_hrh_exec";
13280 : 0 : case INSTR_REGRD_HRM: return "__instr_regrd_hrm_exec";
13281 : 0 : case INSTR_REGRD_HRI: return "__instr_regrd_hri_exec";
13282 : 0 : case INSTR_REGRD_MRH: return "__instr_regrd_mrh_exec";
13283 : 0 : case INSTR_REGRD_MRM: return "__instr_regrd_mrm_exec";
13284 : 0 : case INSTR_REGRD_MRI: return "__instr_regrd_mri_exec";
13285 : :
13286 : 0 : case INSTR_REGWR_RHH: return "__instr_regwr_rhh_exec";
13287 : 0 : case INSTR_REGWR_RHM: return "__instr_regwr_rhm_exec";
13288 : 0 : case INSTR_REGWR_RHI: return "__instr_regwr_rhi_exec";
13289 : 0 : case INSTR_REGWR_RMH: return "__instr_regwr_rmh_exec";
13290 : 0 : case INSTR_REGWR_RMM: return "__instr_regwr_rmm_exec";
13291 : 0 : case INSTR_REGWR_RMI: return "__instr_regwr_rmi_exec";
13292 : 0 : case INSTR_REGWR_RIH: return "__instr_regwr_rih_exec";
13293 : 0 : case INSTR_REGWR_RIM: return "__instr_regwr_rim_exec";
13294 : 0 : case INSTR_REGWR_RII: return "__instr_regwr_rii_exec";
13295 : :
13296 : 0 : case INSTR_REGADD_RHH: return "__instr_regadd_rhh_exec";
13297 : 0 : case INSTR_REGADD_RHM: return "__instr_regadd_rhm_exec";
13298 : 0 : case INSTR_REGADD_RHI: return "__instr_regadd_rhi_exec";
13299 : 0 : case INSTR_REGADD_RMH: return "__instr_regadd_rmh_exec";
13300 : 0 : case INSTR_REGADD_RMM: return "__instr_regadd_rmm_exec";
13301 : 0 : case INSTR_REGADD_RMI: return "__instr_regadd_rmi_exec";
13302 : 0 : case INSTR_REGADD_RIH: return "__instr_regadd_rih_exec";
13303 : 0 : case INSTR_REGADD_RIM: return "__instr_regadd_rim_exec";
13304 : 0 : case INSTR_REGADD_RII: return "__instr_regadd_rii_exec";
13305 : :
13306 : 0 : case INSTR_METPREFETCH_H: return "__instr_metprefetch_h_exec";
13307 : 0 : case INSTR_METPREFETCH_M: return "__instr_metprefetch_m_exec";
13308 : 0 : case INSTR_METPREFETCH_I: return "__instr_metprefetch_i_exec";
13309 : :
13310 : 0 : case INSTR_METER_HHM: return "__instr_meter_hhm_exec";
13311 : 0 : case INSTR_METER_HHI: return "__instr_meter_hhi_exec";
13312 : 0 : case INSTR_METER_HMM: return "__instr_meter_hmm_exec";
13313 : 0 : case INSTR_METER_HMI: return "__instr_meter_hmi_exec";
13314 : 0 : case INSTR_METER_MHM: return "__instr_meter_mhm_exec";
13315 : 0 : case INSTR_METER_MHI: return "__instr_meter_mhi_exec";
13316 : 0 : case INSTR_METER_MMM: return "__instr_meter_mmm_exec";
13317 : 0 : case INSTR_METER_MMI: return "__instr_meter_mmi_exec";
13318 : 0 : case INSTR_METER_IHM: return "__instr_meter_ihm_exec";
13319 : 0 : case INSTR_METER_IHI: return "__instr_meter_ihi_exec";
13320 : 0 : case INSTR_METER_IMM: return "__instr_meter_imm_exec";
13321 : 0 : case INSTR_METER_IMI: return "__instr_meter_imi_exec";
13322 : :
13323 : : case INSTR_TABLE: return NULL;
13324 : : case INSTR_TABLE_AF: return NULL;
13325 : : case INSTR_SELECTOR: return NULL;
13326 : : case INSTR_LEARNER: return NULL;
13327 : : case INSTR_LEARNER_AF: return NULL;
13328 : :
13329 : 0 : case INSTR_LEARNER_LEARN: return "__instr_learn_exec";
13330 : 0 : case INSTR_LEARNER_REARM: return "__instr_rearm_exec";
13331 : 0 : case INSTR_LEARNER_REARM_NEW: return "__instr_rearm_new_exec";
13332 : 0 : case INSTR_LEARNER_FORGET: return "__instr_forget_exec";
13333 : 0 : case INSTR_ENTRYID: return "__instr_entryid_exec";
13334 : :
13335 : : case INSTR_EXTERN_OBJ: return NULL;
13336 : : case INSTR_EXTERN_FUNC: return NULL;
13337 : 0 : case INSTR_HASH_FUNC: return "__instr_hash_func_exec";
13338 : 0 : case INSTR_RSS: return "__instr_rss_exec";
13339 : :
13340 : : case INSTR_JMP: return NULL;
13341 : : case INSTR_JMP_VALID: return NULL;
13342 : : case INSTR_JMP_INVALID: return NULL;
13343 : : case INSTR_JMP_HIT: return NULL;
13344 : : case INSTR_JMP_MISS: return NULL;
13345 : : case INSTR_JMP_ACTION_HIT: return NULL;
13346 : : case INSTR_JMP_ACTION_MISS: return NULL;
13347 : : case INSTR_JMP_EQ: return NULL;
13348 : : case INSTR_JMP_EQ_MH: return NULL;
13349 : : case INSTR_JMP_EQ_HM: return NULL;
13350 : : case INSTR_JMP_EQ_HH: return NULL;
13351 : : case INSTR_JMP_EQ_I: return NULL;
13352 : : case INSTR_JMP_NEQ: return NULL;
13353 : : case INSTR_JMP_NEQ_MH: return NULL;
13354 : : case INSTR_JMP_NEQ_HM: return NULL;
13355 : : case INSTR_JMP_NEQ_HH: return NULL;
13356 : : case INSTR_JMP_NEQ_I: return NULL;
13357 : : case INSTR_JMP_LT: return NULL;
13358 : : case INSTR_JMP_LT_MH: return NULL;
13359 : : case INSTR_JMP_LT_HM: return NULL;
13360 : : case INSTR_JMP_LT_HH: return NULL;
13361 : : case INSTR_JMP_LT_MI: return NULL;
13362 : : case INSTR_JMP_LT_HI: return NULL;
13363 : : case INSTR_JMP_GT: return NULL;
13364 : : case INSTR_JMP_GT_MH: return NULL;
13365 : : case INSTR_JMP_GT_HM: return NULL;
13366 : : case INSTR_JMP_GT_HH: return NULL;
13367 : : case INSTR_JMP_GT_MI: return NULL;
13368 : : case INSTR_JMP_GT_HI: return NULL;
13369 : :
13370 : : case INSTR_RETURN: return NULL;
13371 : :
13372 : : default: return NULL;
13373 : : }
13374 : : }
13375 : :
13376 : : static void
13377 : 0 : action_instr_does_tx_codegen(struct action *a,
13378 : : uint32_t instr_pos,
13379 : : struct instruction *instr,
13380 : : FILE *f)
13381 : : {
13382 : 0 : fprintf(f,
13383 : : "%s(p, t, &action_%s_instructions[%u]);\n"
13384 : : "\tthread_ip_reset(p, t);\n"
13385 : : "\tinstr_rx_exec(p);\n"
13386 : : "\treturn;\n",
13387 : : instr_type_to_func(instr),
13388 : 0 : a->name,
13389 : : instr_pos);
13390 : 0 : }
13391 : :
13392 : : static void
13393 : : action_instr_extern_obj_codegen(struct action *a,
13394 : : uint32_t instr_pos,
13395 : : FILE *f)
13396 : : {
13397 : : fprintf(f,
13398 : : "while (!__instr_extern_obj_exec(p, t, &action_%s_instructions[%u]));\n",
13399 : : a->name,
13400 : : instr_pos);
13401 : : }
13402 : :
13403 : : static void
13404 : : action_instr_extern_func_codegen(struct action *a,
13405 : : uint32_t instr_pos,
13406 : : FILE *f)
13407 : : {
13408 : : fprintf(f,
13409 : : "while (!__instr_extern_func_exec(p, t, &action_%s_instructions[%u]));\n",
13410 : : a->name,
13411 : : instr_pos);
13412 : : }
13413 : :
13414 : : static void
13415 : 0 : action_instr_jmp_codegen(struct action *a,
13416 : : uint32_t instr_pos,
13417 : : struct instruction *instr,
13418 : : struct instruction_data *data,
13419 : : FILE *f)
13420 : : {
13421 [ # # # # : 0 : switch (instr->type) {
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
13422 : 0 : case INSTR_JMP:
13423 : : fprintf(f,
13424 : : "goto %s;\n",
13425 : 0 : data->jmp_label);
13426 : : return;
13427 : :
13428 : 0 : case INSTR_JMP_VALID:
13429 : : fprintf(f,
13430 : : "if (HEADER_VALID(t, action_%s_instructions[%u].jmp.header_id))\n"
13431 : : "\t\tgoto %s;\n",
13432 : 0 : a->name,
13433 : : instr_pos,
13434 : 0 : data->jmp_label);
13435 : : return;
13436 : :
13437 : 0 : case INSTR_JMP_INVALID:
13438 : : fprintf(f,
13439 : : "if (!HEADER_VALID(t, action_%s_instructions[%u].jmp.header_id))\n"
13440 : : "\t\tgoto %s;\n",
13441 : 0 : a->name,
13442 : : instr_pos,
13443 : 0 : data->jmp_label);
13444 : : return;
13445 : :
13446 : 0 : case INSTR_JMP_HIT:
13447 : : fprintf(f,
13448 : : "if (t->hit)\n"
13449 : : "\t\tgoto %s;\n",
13450 : 0 : data->jmp_label);
13451 : : return;
13452 : :
13453 : 0 : case INSTR_JMP_MISS:
13454 : : fprintf(f,
13455 : : "if (!t->hit)\n"
13456 : : "\t\tgoto %s;\n",
13457 : 0 : data->jmp_label);
13458 : : return;
13459 : :
13460 : 0 : case INSTR_JMP_ACTION_HIT:
13461 : : fprintf(f,
13462 : : "if (t->action_id == action_%s_instructions[%u].jmp.action_id)\n"
13463 : : "\t\tgoto %s;\n",
13464 : 0 : a->name,
13465 : : instr_pos,
13466 : 0 : data->jmp_label);
13467 : : return;
13468 : :
13469 : 0 : case INSTR_JMP_ACTION_MISS:
13470 : : fprintf(f,
13471 : : "if (t->action_id != action_%s_instructions[%u].jmp.action_id)\n"
13472 : : "\t\tgoto %s;\n",
13473 : 0 : a->name,
13474 : : instr_pos,
13475 : 0 : data->jmp_label);
13476 : : return;
13477 : :
13478 : 0 : case INSTR_JMP_EQ:
13479 : : fprintf(f,
13480 : : "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) == "
13481 : : "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
13482 : : "\t\tgoto %s;\n",
13483 : : a->name,
13484 : : instr_pos,
13485 : 0 : a->name,
13486 : : instr_pos,
13487 : 0 : data->jmp_label);
13488 : : return;
13489 : :
13490 : 0 : case INSTR_JMP_EQ_MH:
13491 : : fprintf(f,
13492 : : "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) == "
13493 : : "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
13494 : : "\t\tgoto %s;\n",
13495 : : a->name,
13496 : : instr_pos,
13497 : 0 : a->name,
13498 : : instr_pos,
13499 : 0 : data->jmp_label);
13500 : : return;
13501 : :
13502 : 0 : case INSTR_JMP_EQ_HM:
13503 : : fprintf(f,
13504 : : "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) == "
13505 : : "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
13506 : : "\t\tgoto %s;\n",
13507 : : a->name,
13508 : : instr_pos,
13509 : 0 : a->name,
13510 : : instr_pos,
13511 : 0 : data->jmp_label);
13512 : : return;
13513 : :
13514 : 0 : case INSTR_JMP_EQ_HH:
13515 : : fprintf(f,
13516 : : "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) == "
13517 : : "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
13518 : : "\t\tgoto %s;\n",
13519 : : a->name,
13520 : : instr_pos,
13521 : 0 : a->name,
13522 : : instr_pos,
13523 : 0 : data->jmp_label);
13524 : : return;
13525 : :
13526 : 0 : case INSTR_JMP_EQ_I:
13527 : : fprintf(f,
13528 : : "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) == "
13529 : : "action_%s_instructions[%u].jmp.b_val)\n"
13530 : : "\t\tgoto %s;\n",
13531 : : a->name,
13532 : : instr_pos,
13533 : 0 : a->name,
13534 : : instr_pos,
13535 : 0 : data->jmp_label);
13536 : : return;
13537 : :
13538 : 0 : case INSTR_JMP_NEQ:
13539 : : fprintf(f,
13540 : : "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) != "
13541 : : "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
13542 : : "\t\tgoto %s;\n",
13543 : : a->name,
13544 : : instr_pos,
13545 : 0 : a->name,
13546 : : instr_pos,
13547 : 0 : data->jmp_label);
13548 : : return;
13549 : :
13550 : 0 : case INSTR_JMP_NEQ_MH:
13551 : : fprintf(f,
13552 : : "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) != "
13553 : : "instr_operand_nbo(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_NEQ_HM:
13563 : : fprintf(f,
13564 : : "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) != "
13565 : : "instr_operand_hbo(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_NEQ_HH:
13575 : : fprintf(f,
13576 : : "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) != "
13577 : : "instr_operand_nbo(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_NEQ_I:
13587 : : fprintf(f,
13588 : : "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) != "
13589 : : "action_%s_instructions[%u].jmp.b_val)\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_LT:
13599 : : fprintf(f,
13600 : : "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) < "
13601 : : "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\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_LT_MH:
13611 : : fprintf(f,
13612 : : "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) < "
13613 : : "instr_operand_nbo(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_LT_HM:
13623 : : fprintf(f,
13624 : : "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) < "
13625 : : "instr_operand_hbo(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_LT_HH:
13635 : : fprintf(f,
13636 : : "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) < "
13637 : : "instr_operand_nbo(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_LT_MI:
13647 : : fprintf(f,
13648 : : "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) < "
13649 : : "action_%s_instructions[%u].jmp.b_val)\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_LT_HI:
13659 : : fprintf(f,
13660 : : "if (instr_operand_nbo(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_GT:
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_GT_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_GT_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_GT_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_GT_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_GT_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 : : default:
13743 : : return;
13744 : : }
13745 : : }
13746 : :
13747 : : static void
13748 : : action_instr_return_codegen(FILE *f)
13749 : : {
13750 : : fprintf(f,
13751 : : "return;\n");
13752 : : }
13753 : :
13754 : : static void
13755 : 0 : action_instr_codegen(struct action *a, FILE *f)
13756 : : {
13757 : : uint32_t i;
13758 : :
13759 : : fprintf(f,
13760 : : "void\n"
13761 : : "action_%s_run(struct rte_swx_pipeline *p)\n"
13762 : : "{\n"
13763 : : "\tstruct thread *t = &p->threads[p->thread_id];\n"
13764 : : "\n",
13765 : 0 : a->name);
13766 : :
13767 [ # # ]: 0 : for (i = 0; i < a->n_instructions; i++) {
13768 : 0 : struct instruction *instr = &a->instructions[i];
13769 : 0 : struct instruction_data *data = &a->instruction_data[i];
13770 : :
13771 : : /* Label, if present. */
13772 [ # # ]: 0 : if (data->label[0])
13773 : 0 : fprintf(f, "\n%s : ", data->label);
13774 : : else
13775 : : fprintf(f, "\n\t");
13776 : :
13777 : : /* TX instruction type. */
13778 : 0 : if (instruction_does_tx(instr)) {
13779 : 0 : action_instr_does_tx_codegen(a, i, instr, f);
13780 : 0 : continue;
13781 : : }
13782 : :
13783 : : /* Extern object/function instruction type. */
13784 [ # # ]: 0 : if (instr->type == INSTR_EXTERN_OBJ) {
13785 : : action_instr_extern_obj_codegen(a, i, f);
13786 : 0 : continue;
13787 : : }
13788 : :
13789 [ # # ]: 0 : if (instr->type == INSTR_EXTERN_FUNC) {
13790 : : action_instr_extern_func_codegen(a, i, f);
13791 : 0 : continue;
13792 : : }
13793 : :
13794 : : /* Jump instruction type. */
13795 : 0 : if (instruction_is_jmp(instr)) {
13796 : 0 : action_instr_jmp_codegen(a, i, instr, data, f);
13797 : 0 : continue;
13798 : : }
13799 : :
13800 : : /* Return instruction type. */
13801 [ # # ]: 0 : if (instr->type == INSTR_RETURN) {
13802 : : action_instr_return_codegen(f);
13803 : 0 : continue;
13804 : : }
13805 : :
13806 : : /* Any other instruction type. */
13807 : 0 : fprintf(f,
13808 : : "%s(p, t, &action_%s_instructions[%u]);\n",
13809 : : instr_type_to_func(instr),
13810 : : a->name,
13811 : : i);
13812 : : }
13813 : :
13814 : : fprintf(f, "}\n\n");
13815 : 0 : }
13816 : :
13817 : : struct instruction_group {
13818 : : TAILQ_ENTRY(instruction_group) node;
13819 : :
13820 : : uint32_t group_id;
13821 : :
13822 : : uint32_t first_instr_id;
13823 : :
13824 : : uint32_t last_instr_id;
13825 : :
13826 : : instr_exec_t func;
13827 : : };
13828 : :
13829 : : TAILQ_HEAD(instruction_group_list, instruction_group);
13830 : :
13831 : : static struct instruction_group *
13832 : : instruction_group_list_group_find(struct instruction_group_list *igl, uint32_t instruction_id)
13833 : : {
13834 : : struct instruction_group *g;
13835 : :
13836 [ # # # # : 0 : TAILQ_FOREACH(g, igl, node)
# # # # ]
13837 [ # # # # : 0 : if ((g->first_instr_id <= instruction_id) && (instruction_id <= g->last_instr_id))
# # # # #
# # # # #
# # ]
13838 : : return g;
13839 : :
13840 : : return NULL;
13841 : : }
13842 : :
13843 : : static void
13844 : 0 : instruction_group_list_free(struct instruction_group_list *igl)
13845 : : {
13846 [ # # ]: 0 : if (!igl)
13847 : : return;
13848 : :
13849 : 0 : for ( ; ; ) {
13850 : : struct instruction_group *g;
13851 : :
13852 : 0 : g = TAILQ_FIRST(igl);
13853 [ # # ]: 0 : if (!g)
13854 : : break;
13855 : :
13856 [ # # ]: 0 : TAILQ_REMOVE(igl, g, node);
13857 : 0 : free(g);
13858 : : }
13859 : :
13860 : 0 : free(igl);
13861 : : }
13862 : :
13863 : : static struct instruction_group_list *
13864 : 0 : instruction_group_list_create(struct rte_swx_pipeline *p)
13865 : : {
13866 : : struct instruction_group_list *igl = NULL;
13867 : : struct instruction_group *g = NULL;
13868 : : uint32_t n_groups = 0, i;
13869 : :
13870 [ # # # # : 0 : if (!p || !p->instructions || !p->instruction_data || !p->n_instructions)
# # # # ]
13871 : 0 : goto error;
13872 : :
13873 : : /* List init. */
13874 : 0 : igl = calloc(1, sizeof(struct instruction_group_list));
13875 [ # # ]: 0 : if (!igl)
13876 : 0 : goto error;
13877 : :
13878 : 0 : TAILQ_INIT(igl);
13879 : :
13880 : : /* Allocate the first group. */
13881 : 0 : g = calloc(1, sizeof(struct instruction_group));
13882 [ # # ]: 0 : if (!g)
13883 : 0 : goto error;
13884 : :
13885 : : /* Iteration 1: Separate the instructions into groups based on the thread yield
13886 : : * instructions. Do not worry about the jump instructions at this point.
13887 : : */
13888 [ # # ]: 0 : for (i = 0; i < p->n_instructions; i++) {
13889 [ # # ]: 0 : struct instruction *instr = &p->instructions[i];
13890 : :
13891 : : /* Check for thread yield instructions. */
13892 : 0 : if (!instruction_does_thread_yield(instr))
13893 : 0 : continue;
13894 : :
13895 : : /* If the current group contains at least one instruction, then finalize it (with
13896 : : * the previous instruction), add it to the list and allocate a new group (that
13897 : : * starts with the current instruction).
13898 : : */
13899 [ # # ]: 0 : if (i - g->first_instr_id) {
13900 : : /* Finalize the group. */
13901 : 0 : g->last_instr_id = i - 1;
13902 : :
13903 : : /* Add the group to the list. Advance the number of groups. */
13904 : 0 : TAILQ_INSERT_TAIL(igl, g, node);
13905 : 0 : n_groups++;
13906 : :
13907 : : /* Allocate a new group. */
13908 : 0 : g = calloc(1, sizeof(struct instruction_group));
13909 [ # # ]: 0 : if (!g)
13910 : 0 : goto error;
13911 : :
13912 : : /* Initialize the new group. */
13913 : 0 : g->group_id = n_groups;
13914 : 0 : g->first_instr_id = i;
13915 : : }
13916 : :
13917 : : /* Finalize the current group (with the current instruction, therefore this group
13918 : : * contains just the current thread yield instruction), add it to the list and
13919 : : * allocate a new group (that starts with the next instruction).
13920 : : */
13921 : :
13922 : : /* Finalize the group. */
13923 : 0 : g->last_instr_id = i;
13924 : :
13925 : : /* Add the group to the list. Advance the number of groups. */
13926 : 0 : TAILQ_INSERT_TAIL(igl, g, node);
13927 : 0 : n_groups++;
13928 : :
13929 : : /* Allocate a new group. */
13930 : 0 : g = calloc(1, sizeof(struct instruction_group));
13931 [ # # ]: 0 : if (!g)
13932 : 0 : goto error;
13933 : :
13934 : : /* Initialize the new group. */
13935 : 0 : g->group_id = n_groups;
13936 : 0 : g->first_instr_id = i + 1;
13937 : : }
13938 : :
13939 : : /* Handle the last group. */
13940 [ # # ]: 0 : if (i - g->first_instr_id) {
13941 : : /* Finalize the group. */
13942 : 0 : g->last_instr_id = i - 1;
13943 : :
13944 : : /* Add the group to the list. Advance the number of groups. */
13945 : 0 : TAILQ_INSERT_TAIL(igl, g, node);
13946 : 0 : n_groups++;
13947 : : } else
13948 : 0 : free(g);
13949 : :
13950 : : g = NULL;
13951 : :
13952 : : /* Iteration 2: Handle jumps. If the current group contains an instruction which represents
13953 : : * the destination of a jump instruction located in a different group ("far jump"), then the
13954 : : * current group has to be split, so that the instruction representing the far jump
13955 : : * destination is at the start of its group.
13956 : : */
13957 : : for ( ; ; ) {
13958 : : int is_modified = 0;
13959 : :
13960 [ # # ]: 0 : for (i = 0; i < p->n_instructions; i++) {
13961 : 0 : struct instruction_data *data = &p->instruction_data[i];
13962 : : struct instruction_group *g;
13963 : : uint32_t j;
13964 : :
13965 : : /* Continue when the current instruction is not a jump destination. */
13966 [ # # ]: 0 : if (!data->n_users)
13967 : 0 : continue;
13968 : :
13969 : : g = instruction_group_list_group_find(igl, i);
13970 [ # # ]: 0 : if (!g)
13971 : 0 : goto error;
13972 : :
13973 : : /* Find out all the jump instructions with this destination. */
13974 [ # # ]: 0 : for (j = 0; j < p->n_instructions; j++) {
13975 : 0 : struct instruction *jmp_instr = &p->instructions[j];
13976 [ # # ]: 0 : struct instruction_data *jmp_data = &p->instruction_data[j];
13977 : : struct instruction_group *jmp_g, *new_g;
13978 : :
13979 : : /* Continue when not a jump instruction. Even when jump instruction,
13980 : : * continue when the jump destination is not this instruction.
13981 : : */
13982 : 0 : if (!instruction_is_jmp(jmp_instr) ||
13983 [ # # ]: 0 : strcmp(jmp_data->jmp_label, data->label))
13984 : 0 : continue;
13985 : :
13986 : : jmp_g = instruction_group_list_group_find(igl, j);
13987 [ # # ]: 0 : if (!jmp_g)
13988 : 0 : goto error;
13989 : :
13990 : : /* Continue when both the jump instruction and the jump destination
13991 : : * instruction are in the same group. Even when in different groups,
13992 : : * still continue if the jump destination instruction is already the
13993 : : * first instruction of its group.
13994 : : */
13995 [ # # # # ]: 0 : if ((jmp_g->group_id == g->group_id) || (g->first_instr_id == i))
13996 : 0 : continue;
13997 : :
13998 : : /* Split the group of the current jump destination instruction to
13999 : : * make this instruction the first instruction of a new group.
14000 : : */
14001 : 0 : new_g = calloc(1, sizeof(struct instruction_group));
14002 [ # # ]: 0 : if (!new_g)
14003 : 0 : goto error;
14004 : :
14005 : 0 : new_g->group_id = n_groups;
14006 : 0 : new_g->first_instr_id = i;
14007 : 0 : new_g->last_instr_id = g->last_instr_id;
14008 : :
14009 : 0 : g->last_instr_id = i - 1;
14010 : :
14011 [ # # ]: 0 : TAILQ_INSERT_AFTER(igl, g, new_g, node);
14012 : 0 : n_groups++;
14013 : : is_modified = 1;
14014 : :
14015 : : /* The decision to split this group (to make the current instruction
14016 : : * the first instruction of a new group) is already taken and fully
14017 : : * implemented, so no need to search for more reasons to do it.
14018 : : */
14019 : 0 : break;
14020 : : }
14021 : : }
14022 : :
14023 : : /* Re-evaluate everything, as at least one group got split, so some jumps that were
14024 : : * previously considered local (i.e. the jump destination is in the same group as
14025 : : * the jump instruction) can now be "far jumps" (i.e. the jump destination is in a
14026 : : * different group than the jump instruction). Wost case scenario: each instruction
14027 : : * that is a jump destination ends up as the first instruction of its group.
14028 : : */
14029 [ # # ]: 0 : if (!is_modified)
14030 : : break;
14031 : : }
14032 : :
14033 : : /* Re-assign the group IDs to be in incremental order. */
14034 : : i = 0;
14035 [ # # ]: 0 : TAILQ_FOREACH(g, igl, node) {
14036 : 0 : g->group_id = i;
14037 : :
14038 : 0 : i++;
14039 : : }
14040 : :
14041 : : return igl;
14042 : :
14043 : 0 : error:
14044 : 0 : instruction_group_list_free(igl);
14045 : :
14046 : : free(g);
14047 : :
14048 : 0 : return NULL;
14049 : : }
14050 : :
14051 : : static void
14052 : : pipeline_instr_does_tx_codegen(struct rte_swx_pipeline *p __rte_unused,
14053 : : uint32_t instr_pos,
14054 : : struct instruction *instr,
14055 : : FILE *f)
14056 : : {
14057 : 0 : fprintf(f,
14058 : : "%s(p, t, &pipeline_instructions[%u]);\n"
14059 : : "\tthread_ip_reset(p, t);\n"
14060 : : "\tinstr_rx_exec(p);\n"
14061 : : "\treturn;\n",
14062 : : instr_type_to_func(instr),
14063 : : instr_pos);
14064 : : }
14065 : :
14066 : : static int
14067 : 0 : pipeline_instr_jmp_codegen(struct rte_swx_pipeline *p,
14068 : : struct instruction_group_list *igl,
14069 : : uint32_t jmp_instr_id,
14070 : : struct instruction *jmp_instr,
14071 : : struct instruction_data *jmp_data,
14072 : : FILE *f)
14073 : : {
14074 : : struct instruction_group *jmp_g, *g;
14075 : : struct instruction_data *data;
14076 : : uint32_t instr_id;
14077 : :
14078 [ # # # # : 0 : switch (jmp_instr->type) {
# # # # #
# # # # #
# # # # #
# # # # #
# # # #
# ]
14079 : : case INSTR_JMP:
14080 : : break;
14081 : :
14082 : : case INSTR_JMP_VALID:
14083 : : fprintf(f,
14084 : : "if (HEADER_VALID(t, pipeline_instructions[%u].jmp.header_id))",
14085 : : jmp_instr_id);
14086 : : break;
14087 : :
14088 : : case INSTR_JMP_INVALID:
14089 : : fprintf(f,
14090 : : "if (!HEADER_VALID(t, pipeline_instructions[%u].jmp.header_id))",
14091 : : jmp_instr_id);
14092 : : break;
14093 : :
14094 : : case INSTR_JMP_HIT:
14095 : : fprintf(f,
14096 : : "if (t->hit)\n");
14097 : : break;
14098 : :
14099 : : case INSTR_JMP_MISS:
14100 : : fprintf(f,
14101 : : "if (!t->hit)\n");
14102 : : break;
14103 : :
14104 : : case INSTR_JMP_ACTION_HIT:
14105 : : fprintf(f,
14106 : : "if (t->action_id == pipeline_instructions[%u].jmp.action_id)",
14107 : : jmp_instr_id);
14108 : : break;
14109 : :
14110 : : case INSTR_JMP_ACTION_MISS:
14111 : : fprintf(f,
14112 : : "if (t->action_id != pipeline_instructions[%u].jmp.action_id)",
14113 : : jmp_instr_id);
14114 : : break;
14115 : :
14116 : : case INSTR_JMP_EQ:
14117 : : fprintf(f,
14118 : : "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) == "
14119 : : "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
14120 : : jmp_instr_id,
14121 : : jmp_instr_id);
14122 : : break;
14123 : :
14124 : : case INSTR_JMP_EQ_MH:
14125 : : fprintf(f,
14126 : : "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) == "
14127 : : "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
14128 : : jmp_instr_id,
14129 : : jmp_instr_id);
14130 : : break;
14131 : :
14132 : : case INSTR_JMP_EQ_HM:
14133 : : fprintf(f,
14134 : : "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) == "
14135 : : "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
14136 : : jmp_instr_id,
14137 : : jmp_instr_id);
14138 : : break;
14139 : :
14140 : : case INSTR_JMP_EQ_HH:
14141 : : fprintf(f,
14142 : : "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) == "
14143 : : "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
14144 : : jmp_instr_id,
14145 : : jmp_instr_id);
14146 : : break;
14147 : :
14148 : : case INSTR_JMP_EQ_I:
14149 : : fprintf(f,
14150 : : "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) == "
14151 : : "pipeline_instructions[%u].jmp.b_val)",
14152 : : jmp_instr_id,
14153 : : jmp_instr_id);
14154 : : break;
14155 : :
14156 : : case INSTR_JMP_NEQ:
14157 : : fprintf(f,
14158 : : "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) != "
14159 : : "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
14160 : : jmp_instr_id,
14161 : : jmp_instr_id);
14162 : : break;
14163 : :
14164 : : case INSTR_JMP_NEQ_MH:
14165 : : fprintf(f,
14166 : : "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) != "
14167 : : "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
14168 : : jmp_instr_id,
14169 : : jmp_instr_id);
14170 : : break;
14171 : :
14172 : : case INSTR_JMP_NEQ_HM:
14173 : : fprintf(f,
14174 : : "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) != "
14175 : : "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
14176 : : jmp_instr_id,
14177 : : jmp_instr_id);
14178 : : break;
14179 : :
14180 : : case INSTR_JMP_NEQ_HH:
14181 : : fprintf(f,
14182 : : "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) != "
14183 : : "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
14184 : : jmp_instr_id,
14185 : : jmp_instr_id);
14186 : : break;
14187 : :
14188 : : case INSTR_JMP_NEQ_I:
14189 : : fprintf(f,
14190 : : "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) != "
14191 : : "pipeline_instructions[%u].jmp.b_val)",
14192 : : jmp_instr_id,
14193 : : jmp_instr_id);
14194 : : break;
14195 : :
14196 : : case INSTR_JMP_LT:
14197 : : fprintf(f,
14198 : : "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) < "
14199 : : "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
14200 : : jmp_instr_id,
14201 : : jmp_instr_id);
14202 : : break;
14203 : :
14204 : : case INSTR_JMP_LT_MH:
14205 : : fprintf(f,
14206 : : "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) < "
14207 : : "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
14208 : : jmp_instr_id,
14209 : : jmp_instr_id);
14210 : : break;
14211 : :
14212 : : case INSTR_JMP_LT_HM:
14213 : : fprintf(f,
14214 : : "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) < "
14215 : : "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
14216 : : jmp_instr_id,
14217 : : jmp_instr_id);
14218 : : break;
14219 : :
14220 : : case INSTR_JMP_LT_HH:
14221 : : fprintf(f,
14222 : : "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) < "
14223 : : "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
14224 : : jmp_instr_id,
14225 : : jmp_instr_id);
14226 : : break;
14227 : :
14228 : : case INSTR_JMP_LT_MI:
14229 : : fprintf(f,
14230 : : "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) < "
14231 : : "pipeline_instructions[%u].jmp.b_val)",
14232 : : jmp_instr_id,
14233 : : jmp_instr_id);
14234 : : break;
14235 : :
14236 : : case INSTR_JMP_LT_HI:
14237 : : fprintf(f,
14238 : : "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) < "
14239 : : "pipeline_instructions[%u].jmp.b_val)",
14240 : : jmp_instr_id,
14241 : : jmp_instr_id);
14242 : : break;
14243 : :
14244 : : case INSTR_JMP_GT:
14245 : : fprintf(f,
14246 : : "if (instr_operand_hbo(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_GT_MH:
14253 : : fprintf(f,
14254 : : "if (instr_operand_hbo(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_GT_HM:
14261 : : fprintf(f,
14262 : : "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) > "
14263 : : "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
14264 : : jmp_instr_id,
14265 : : jmp_instr_id);
14266 : : break;
14267 : :
14268 : : case INSTR_JMP_GT_HH:
14269 : : fprintf(f,
14270 : : "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) > "
14271 : : "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
14272 : : jmp_instr_id,
14273 : : jmp_instr_id);
14274 : : break;
14275 : :
14276 : : case INSTR_JMP_GT_MI:
14277 : : fprintf(f,
14278 : : "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) > "
14279 : : "pipeline_instructions[%u].jmp.b_val)",
14280 : : jmp_instr_id,
14281 : : jmp_instr_id);
14282 : : break;
14283 : :
14284 : : case INSTR_JMP_GT_HI:
14285 : : fprintf(f,
14286 : : "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) > "
14287 : : "pipeline_instructions[%u].jmp.b_val)",
14288 : : jmp_instr_id,
14289 : : jmp_instr_id);
14290 : : break;
14291 : :
14292 : : default:
14293 : : break;
14294 : : }
14295 : :
14296 : : /* Find the instruction group of the jump instruction. */
14297 : : jmp_g = instruction_group_list_group_find(igl, jmp_instr_id);
14298 [ # # ]: 0 : if (!jmp_g)
14299 : : return -EINVAL;
14300 : :
14301 : : /* Find the instruction group of the jump destination instruction. */
14302 : 0 : data = label_find(p->instruction_data, p->n_instructions, jmp_data->jmp_label);
14303 [ # # ]: 0 : if (!data)
14304 : : return -EINVAL;
14305 : :
14306 : 0 : instr_id = data - p->instruction_data;
14307 : :
14308 : : g = instruction_group_list_group_find(igl, instr_id);
14309 [ # # ]: 0 : if (!g)
14310 : : return -EINVAL;
14311 : :
14312 : : /* Code generation for "near" jump (same instruction group) or "far" jump (different
14313 : : * instruction group).
14314 : : */
14315 [ # # ]: 0 : if (g->group_id == jmp_g->group_id)
14316 : : fprintf(f,
14317 : : "\n\t\tgoto %s;\n",
14318 : : jmp_data->jmp_label);
14319 : : else
14320 : : fprintf(f,
14321 : : " {\n"
14322 : : "\t\tthread_ip_set(t, &p->instructions[%u]);\n"
14323 : : "\t\treturn;\n"
14324 : : "\t}\n\n",
14325 : : g->group_id);
14326 : :
14327 : : return 0;
14328 : : }
14329 : :
14330 : : static void
14331 : 0 : instruction_group_list_codegen(struct instruction_group_list *igl,
14332 : : struct rte_swx_pipeline *p,
14333 : : FILE *f)
14334 : : {
14335 : : struct instruction_group *g;
14336 : : uint32_t i;
14337 : : int is_required = 0;
14338 : :
14339 : : /* Check if code generation is required. */
14340 [ # # ]: 0 : TAILQ_FOREACH(g, igl, node)
14341 [ # # ]: 0 : if (g->first_instr_id < g->last_instr_id)
14342 : : is_required = 1;
14343 : :
14344 [ # # ]: 0 : if (!is_required)
14345 : : return;
14346 : :
14347 : : /* Generate the code for the pipeline instruction array. */
14348 : : fprintf(f,
14349 : : "static const struct instruction pipeline_instructions[] = {\n");
14350 : :
14351 [ # # ]: 0 : for (i = 0; i < p->n_instructions; i++) {
14352 : 0 : struct instruction *instr = &p->instructions[i];
14353 : 0 : instruction_export_t func = export_table[instr->type];
14354 : :
14355 : 0 : func(instr, f);
14356 : : }
14357 : :
14358 : : fprintf(f, "};\n\n");
14359 : :
14360 : : /* Generate the code for the pipeline functions: one function for each instruction group
14361 : : * that contains more than one instruction.
14362 : : */
14363 [ # # ]: 0 : TAILQ_FOREACH(g, igl, node) {
14364 : : struct instruction *last_instr;
14365 : : uint32_t j;
14366 : :
14367 : : /* Skip if group contains a single instruction. */
14368 [ # # ]: 0 : if (g->last_instr_id == g->first_instr_id)
14369 : 0 : continue;
14370 : :
14371 : : /* Generate new pipeline function. */
14372 : 0 : fprintf(f,
14373 : : "void\n"
14374 : : "pipeline_func_%u(struct rte_swx_pipeline *p)\n"
14375 : : "{\n"
14376 : : "\tstruct thread *t = &p->threads[p->thread_id];\n"
14377 : : "\n",
14378 : : g->group_id);
14379 : :
14380 : : /* Generate the code for each pipeline instruction. */
14381 [ # # ]: 0 : for (j = g->first_instr_id; j <= g->last_instr_id; j++) {
14382 : 0 : struct instruction *instr = &p->instructions[j];
14383 : 0 : struct instruction_data *data = &p->instruction_data[j];
14384 : :
14385 : : /* Label, if present. */
14386 [ # # ]: 0 : if (data->label[0])
14387 : 0 : fprintf(f, "\n%s : ", data->label);
14388 : : else
14389 : : fprintf(f, "\n\t");
14390 : :
14391 : : /* TX instruction type. */
14392 : 0 : if (instruction_does_tx(instr)) {
14393 : : pipeline_instr_does_tx_codegen(p, j, instr, f);
14394 : 0 : continue;
14395 : : }
14396 : :
14397 : : /* Jump instruction type. */
14398 : 0 : if (instruction_is_jmp(instr)) {
14399 : 0 : pipeline_instr_jmp_codegen(p, igl, j, instr, data, f);
14400 : 0 : continue;
14401 : : }
14402 : :
14403 : : /* Any other instruction type. */
14404 : 0 : fprintf(f,
14405 : : "%s(p, t, &pipeline_instructions[%u]);\n",
14406 : : instr_type_to_func(instr),
14407 : : j);
14408 : : }
14409 : :
14410 : : /* Finalize the generated pipeline function. For some instructions such as TX,
14411 : : * emit-many-and-TX and unconditional jump, the next instruction has been already
14412 : : * decided unconditionally and the instruction pointer of the current thread set
14413 : : * accordingly; for all the other instructions, the instruction pointer must be
14414 : : * incremented now.
14415 : : */
14416 [ # # ]: 0 : last_instr = &p->instructions[g->last_instr_id];
14417 : :
14418 [ # # ]: 0 : if (!instruction_does_tx(last_instr) && (last_instr->type != INSTR_JMP))
14419 : : fprintf(f,
14420 : : "thread_ip_inc(p);\n");
14421 : :
14422 : : fprintf(f,
14423 : : "}\n"
14424 : : "\n");
14425 : : }
14426 : : }
14427 : :
14428 : : static uint32_t
14429 : : instruction_group_list_custom_instructions_count(struct instruction_group_list *igl)
14430 : : {
14431 : : struct instruction_group *g;
14432 : : uint32_t n_custom_instr = 0;
14433 : :
14434 : : /* Groups with a single instruction: no function is generated for this group, the group
14435 : : * keeps its current instruction. Groups with more than two instructions: one function and
14436 : : * the associated custom instruction get generated for each such group.
14437 : : */
14438 [ # # ]: 0 : TAILQ_FOREACH(g, igl, node) {
14439 [ # # ]: 0 : if (g->first_instr_id == g->last_instr_id)
14440 : 0 : continue;
14441 : :
14442 : 0 : n_custom_instr++;
14443 : : }
14444 : :
14445 : : return n_custom_instr;
14446 : : }
14447 : :
14448 : : static int
14449 : : pipeline_adjust_check(struct rte_swx_pipeline *p __rte_unused,
14450 : : struct instruction_group_list *igl)
14451 : : {
14452 : : uint32_t n_custom_instr = instruction_group_list_custom_instructions_count(igl);
14453 : :
14454 : : /* Check that enough space is available within the pipeline instruction table to store all
14455 : : * the custom instructions.
14456 : : */
14457 [ # # ]: 0 : if (INSTR_CUSTOM_0 + n_custom_instr > RTE_SWX_PIPELINE_INSTRUCTION_TABLE_SIZE_MAX)
14458 : : return -ENOSPC;
14459 : :
14460 : : return 0;
14461 : : }
14462 : :
14463 : : static void
14464 : 0 : pipeline_adjust(struct rte_swx_pipeline *p, struct instruction_group_list *igl)
14465 : : {
14466 : : struct instruction_group *g;
14467 : : uint32_t i;
14468 : :
14469 : : /* Pipeline table instructions. */
14470 [ # # ]: 0 : for (i = 0; i < p->n_instructions; i++) {
14471 : 0 : struct instruction *instr = &p->instructions[i];
14472 : :
14473 [ # # ]: 0 : if (instr->type == INSTR_TABLE)
14474 : 0 : instr->type = INSTR_TABLE_AF;
14475 : :
14476 [ # # ]: 0 : if (instr->type == INSTR_LEARNER)
14477 : 0 : instr->type = INSTR_LEARNER_AF;
14478 : : }
14479 : :
14480 : : /* Pipeline custom instructions. */
14481 : : i = 0;
14482 [ # # ]: 0 : TAILQ_FOREACH(g, igl, node) {
14483 : 0 : struct instruction *instr = &p->instructions[g->first_instr_id];
14484 : : uint32_t j;
14485 : :
14486 [ # # ]: 0 : if (g->first_instr_id == g->last_instr_id)
14487 : 0 : continue;
14488 : :
14489 : : /* Install a new custom instruction. */
14490 : 0 : p->instruction_table[INSTR_CUSTOM_0 + i] = g->func;
14491 : :
14492 : : /* First instruction of the group: change its type to the new custom instruction. */
14493 : 0 : instr->type = INSTR_CUSTOM_0 + i;
14494 : :
14495 : : /* All the subsequent instructions of the group: invalidate. */
14496 [ # # ]: 0 : for (j = g->first_instr_id + 1; j <= g->last_instr_id; j++) {
14497 : 0 : struct instruction_data *data = &p->instruction_data[j];
14498 : :
14499 : 0 : data->invalid = 1;
14500 : : }
14501 : :
14502 : 0 : i++;
14503 : : }
14504 : :
14505 : : /* Remove the invalidated instructions. */
14506 : 0 : p->n_instructions = instr_compact(p->instructions, p->instruction_data, p->n_instructions);
14507 : :
14508 : : /* Resolve the jump destination for any "standalone" jump instructions (i.e. those jump
14509 : : * instructions that are the only instruction within their group, so they were left
14510 : : * unmodified).
14511 : : */
14512 : 0 : instr_jmp_resolve(p->instructions, p->instruction_data, p->n_instructions);
14513 : 0 : }
14514 : :
14515 : : int
14516 : 0 : rte_swx_pipeline_codegen(FILE *spec_file,
14517 : : FILE *code_file,
14518 : : uint32_t *err_line,
14519 : : const char **err_msg)
14520 : :
14521 : : {
14522 : 0 : struct rte_swx_pipeline *p = NULL;
14523 : : struct pipeline_spec *s = NULL;
14524 : : struct instruction_group_list *igl = NULL;
14525 : : struct action *a;
14526 : : int status = 0;
14527 : :
14528 : : /* Check input arguments. */
14529 [ # # ]: 0 : if (!spec_file || !code_file) {
14530 [ # # ]: 0 : if (err_line)
14531 : 0 : *err_line = 0;
14532 [ # # ]: 0 : if (err_msg)
14533 : 0 : *err_msg = "Invalid input argument.";
14534 : : status = -EINVAL;
14535 : 0 : goto free;
14536 : : }
14537 : :
14538 : : /* Pipeline configuration. */
14539 : 0 : s = pipeline_spec_parse(spec_file, err_line, err_msg);
14540 [ # # ]: 0 : if (!s) {
14541 : : status = -EINVAL;
14542 : 0 : goto free;
14543 : : }
14544 : :
14545 : 0 : status = rte_swx_pipeline_config(&p, NULL, 0);
14546 [ # # ]: 0 : if (status) {
14547 [ # # ]: 0 : if (err_line)
14548 : 0 : *err_line = 0;
14549 [ # # ]: 0 : if (err_msg)
14550 : 0 : *err_msg = "Pipeline configuration error.";
14551 : 0 : goto free;
14552 : : }
14553 : :
14554 : 0 : status = pipeline_spec_configure(p, s, err_msg);
14555 [ # # ]: 0 : if (status) {
14556 [ # # ]: 0 : if (err_line)
14557 : 0 : *err_line = 0;
14558 : 0 : goto free;
14559 : : }
14560 : :
14561 : : /*
14562 : : * Pipeline code generation.
14563 : : */
14564 : :
14565 : : /* Instruction Group List (IGL) computation: the pipeline configuration must be done first,
14566 : : * but there is no need for the pipeline build to be done as well.
14567 : : */
14568 : 0 : igl = instruction_group_list_create(p);
14569 [ # # ]: 0 : if (!igl) {
14570 [ # # ]: 0 : if (err_line)
14571 : 0 : *err_line = 0;
14572 [ # # ]: 0 : if (err_msg)
14573 : 0 : *err_msg = "Memory allocation failed.";
14574 : : status = -ENOMEM;
14575 : 0 : goto free;
14576 : : }
14577 : :
14578 : : /* Header file inclusion. */
14579 : : fprintf(code_file, "#include \"rte_swx_pipeline_internal.h\"\n");
14580 : : fprintf(code_file, "#include \"rte_swx_pipeline_spec.h\"\n\n");
14581 : :
14582 : : /* Code generation for the pipeline specification. */
14583 : 0 : pipeline_spec_codegen(code_file, s);
14584 : : fprintf(code_file, "\n");
14585 : :
14586 : : /* Code generation for the action instructions. */
14587 [ # # ]: 0 : TAILQ_FOREACH(a, &p->actions, node) {
14588 : 0 : fprintf(code_file, "/**\n * Action %s\n */\n\n", a->name);
14589 : :
14590 : 0 : action_data_codegen(a, code_file);
14591 : : fprintf(code_file, "\n");
14592 : :
14593 : 0 : action_instr_codegen(a, code_file);
14594 : : fprintf(code_file, "\n");
14595 : : }
14596 : :
14597 : : /* Code generation for the pipeline instructions. */
14598 : 0 : instruction_group_list_codegen(igl, p, code_file);
14599 : :
14600 : 0 : free:
14601 : 0 : instruction_group_list_free(igl);
14602 : 0 : rte_swx_pipeline_free(p);
14603 : 0 : pipeline_spec_free(s);
14604 : :
14605 : 0 : return status;
14606 : : }
14607 : :
14608 : : int
14609 : 0 : rte_swx_pipeline_build_from_lib(struct rte_swx_pipeline **pipeline,
14610 : : const char *name,
14611 : : const char *lib_file_name,
14612 : : FILE *iospec_file,
14613 : : int numa_node)
14614 : : {
14615 : 0 : struct rte_swx_pipeline *p = NULL;
14616 : : void *lib = NULL;
14617 : : struct pipeline_iospec *sio = NULL;
14618 : : struct pipeline_spec *s = NULL;
14619 : : struct instruction_group_list *igl = NULL;
14620 : : struct action *a;
14621 : : struct instruction_group *g;
14622 : : int status = 0;
14623 : :
14624 : : /* Check input arguments. */
14625 : 0 : if (!pipeline ||
14626 [ # # ]: 0 : !name ||
14627 [ # # # # ]: 0 : !name[0] ||
14628 : 0 : !lib_file_name ||
14629 [ # # # # ]: 0 : !lib_file_name[0] ||
14630 : : !iospec_file) {
14631 : : status = -EINVAL;
14632 : 0 : goto free;
14633 : : }
14634 : :
14635 : : /* Open the library. */
14636 : 0 : lib = dlopen(lib_file_name, RTLD_LAZY);
14637 [ # # ]: 0 : if (!lib) {
14638 : : status = -EIO;
14639 : 0 : goto free;
14640 : : }
14641 : :
14642 : : /* Get the pipeline specification structures. */
14643 : 0 : s = dlsym(lib, "pipeline_spec");
14644 [ # # ]: 0 : if (!s) {
14645 : : status = -EINVAL;
14646 : 0 : goto free;
14647 : : }
14648 : :
14649 : 0 : sio = pipeline_iospec_parse(iospec_file, NULL, NULL);
14650 [ # # ]: 0 : if (!sio) {
14651 : : status = -EINVAL;
14652 : 0 : goto free;
14653 : : }
14654 : :
14655 : : /* Pipeline configuration based on the specification structures. */
14656 : 0 : status = rte_swx_pipeline_config(&p, name, numa_node);
14657 [ # # ]: 0 : if (status)
14658 : 0 : goto free;
14659 : :
14660 : 0 : status = pipeline_iospec_configure(p, sio, NULL);
14661 [ # # ]: 0 : if (status)
14662 : 0 : goto free;
14663 : :
14664 : 0 : status = pipeline_spec_configure(p, s, NULL);
14665 [ # # ]: 0 : if (status)
14666 : 0 : goto free;
14667 : :
14668 : : /* Pipeline build. */
14669 : 0 : status = rte_swx_pipeline_build(p);
14670 [ # # ]: 0 : if (status)
14671 : 0 : goto free;
14672 : :
14673 : : /* Action instructions. */
14674 [ # # ]: 0 : TAILQ_FOREACH(a, &p->actions, node) {
14675 : : char name[RTE_SWX_NAME_SIZE * 2];
14676 : :
14677 : 0 : snprintf(name, sizeof(name), "action_%s_run", a->name);
14678 : :
14679 : 0 : p->action_funcs[a->id] = dlsym(lib, name);
14680 [ # # ]: 0 : if (!p->action_funcs[a->id]) {
14681 : : status = -EINVAL;
14682 : 0 : goto free;
14683 : : }
14684 : : }
14685 : :
14686 : : /* Pipeline instructions. */
14687 : 0 : igl = instruction_group_list_create(p);
14688 [ # # ]: 0 : if (!igl) {
14689 : : status = -ENOMEM;
14690 : 0 : goto free;
14691 : : }
14692 : :
14693 [ # # ]: 0 : TAILQ_FOREACH(g, igl, node) {
14694 : : char name[RTE_SWX_NAME_SIZE * 2];
14695 : :
14696 [ # # ]: 0 : if (g->first_instr_id == g->last_instr_id)
14697 : 0 : continue;
14698 : :
14699 : 0 : snprintf(name, sizeof(name), "pipeline_func_%u", g->group_id);
14700 : :
14701 : 0 : g->func = dlsym(lib, name);
14702 [ # # ]: 0 : if (!g->func) {
14703 : : status = -EINVAL;
14704 : 0 : goto free;
14705 : : }
14706 : : }
14707 : :
14708 : 0 : status = pipeline_adjust_check(p, igl);
14709 : : if (status)
14710 : 0 : goto free;
14711 : :
14712 : 0 : pipeline_adjust(p, igl);
14713 : :
14714 : 0 : p->lib = lib;
14715 : :
14716 : 0 : *pipeline = p;
14717 : :
14718 : 0 : free:
14719 : 0 : instruction_group_list_free(igl);
14720 : :
14721 : 0 : pipeline_iospec_free(sio);
14722 : :
14723 [ # # ]: 0 : if (status) {
14724 : 0 : rte_swx_pipeline_free(p);
14725 : :
14726 [ # # ]: 0 : if (lib)
14727 : 0 : dlclose(lib);
14728 : : }
14729 : :
14730 : 0 : return status;
14731 : : }
|