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 *
env_malloc(size_t size,size_t alignment,int numa_node)52 env_malloc(size_t size, size_t alignment, int numa_node)
53 {
54 return rte_zmalloc_socket(NULL, size, alignment, numa_node);
55 }
56
57 static void
env_free(void * start,size_t size __rte_unused)58 env_free(void *start, size_t size __rte_unused)
59 {
60 rte_free(start);
61 }
62
63 #else
64
65 #include <numa.h>
66
67 static void *
env_malloc(size_t size,size_t alignment __rte_unused,int numa_node)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
env_free(void * start,size_t size)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 *
struct_type_find(struct rte_swx_pipeline * p,const char * name)98 struct_type_find(struct rte_swx_pipeline *p, const char *name)
99 {
100 struct struct_type *elem;
101
102 TAILQ_FOREACH(elem, &p->struct_types, node)
103 if (strcmp(elem->name, name) == 0)
104 return elem;
105
106 return NULL;
107 }
108
109 static struct field *
struct_type_field_find(struct struct_type * st,const char * name)110 struct_type_field_find(struct struct_type *st, const char *name)
111 {
112 uint32_t i;
113
114 for (i = 0; i < st->n_fields; i++) {
115 struct field *f = &st->fields[i];
116
117 if (strcmp(f->name, name) == 0)
118 return f;
119 }
120
121 return NULL;
122 }
123
124 int
rte_swx_pipeline_struct_type_register(struct rte_swx_pipeline * p,const char * name,struct rte_swx_field_params * fields,uint32_t n_fields,int last_field_has_variable_size)125 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 CHECK(p, EINVAL);
135 CHECK_NAME(name, EINVAL);
136 CHECK(fields, EINVAL);
137 CHECK(n_fields, EINVAL);
138
139 for (i = 0; i < n_fields; i++) {
140 struct rte_swx_field_params *f = &fields[i];
141 uint32_t j;
142
143 CHECK_NAME(f->name, EINVAL);
144 CHECK(f->n_bits, EINVAL);
145 CHECK((f->n_bits & 7) == 0, EINVAL);
146
147 for (j = 0; j < i; j++) {
148 struct rte_swx_field_params *f_prev = &fields[j];
149
150 CHECK(strcmp(f->name, f_prev->name), EINVAL);
151 }
152 }
153
154 CHECK(!struct_type_find(p, name), EEXIST);
155
156 /* Node allocation. */
157 st = calloc(1, sizeof(struct struct_type));
158 CHECK(st, ENOMEM);
159
160 st->fields = calloc(n_fields, sizeof(struct field));
161 if (!st->fields) {
162 free(st);
163 CHECK(0, ENOMEM);
164 }
165
166 /* Node initialization. */
167 strcpy(st->name, name);
168 for (i = 0; i < n_fields; i++) {
169 struct field *dst = &st->fields[i];
170 struct rte_swx_field_params *src = &fields[i];
171 int var_size = ((i == n_fields - 1) && last_field_has_variable_size) ? 1 : 0;
172
173 strcpy(dst->name, src->name);
174 dst->n_bits = src->n_bits;
175 dst->offset = st->n_bits;
176 dst->var_size = var_size;
177
178 st->n_bits += src->n_bits;
179 st->n_bits_min += var_size ? 0 : src->n_bits;
180 }
181 st->n_fields = n_fields;
182 st->var_size = last_field_has_variable_size;
183
184 /* Node add to tailq. */
185 TAILQ_INSERT_TAIL(&p->struct_types, st, node);
186
187 return 0;
188 }
189
190 static int
struct_build(struct rte_swx_pipeline * p)191 struct_build(struct rte_swx_pipeline *p)
192 {
193 uint32_t i;
194
195 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
196 struct thread *t = &p->threads[i];
197
198 t->structs = calloc(p->n_structs, sizeof(uint8_t *));
199 CHECK(t->structs, ENOMEM);
200 }
201
202 return 0;
203 }
204
205 static void
struct_build_free(struct rte_swx_pipeline * p)206 struct_build_free(struct rte_swx_pipeline *p)
207 {
208 uint32_t i;
209
210 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
211 struct thread *t = &p->threads[i];
212
213 free(t->structs);
214 t->structs = NULL;
215 }
216 }
217
218 static void
struct_free(struct rte_swx_pipeline * p)219 struct_free(struct rte_swx_pipeline *p)
220 {
221 struct_build_free(p);
222
223 /* Struct types. */
224 for ( ; ; ) {
225 struct struct_type *elem;
226
227 elem = TAILQ_FIRST(&p->struct_types);
228 if (!elem)
229 break;
230
231 TAILQ_REMOVE(&p->struct_types, elem, node);
232 free(elem->fields);
233 free(elem);
234 }
235 }
236
237 /*
238 * Input port.
239 */
240 static struct port_in_type *
port_in_type_find(struct rte_swx_pipeline * p,const char * name)241 port_in_type_find(struct rte_swx_pipeline *p, const char *name)
242 {
243 struct port_in_type *elem;
244
245 if (!name)
246 return NULL;
247
248 TAILQ_FOREACH(elem, &p->port_in_types, node)
249 if (strcmp(elem->name, name) == 0)
250 return elem;
251
252 return NULL;
253 }
254
255 int
rte_swx_pipeline_port_in_type_register(struct rte_swx_pipeline * p,const char * name,struct rte_swx_port_in_ops * ops)256 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 CHECK(p, EINVAL);
263 CHECK_NAME(name, EINVAL);
264 CHECK(ops, EINVAL);
265 CHECK(ops->create, EINVAL);
266 CHECK(ops->free, EINVAL);
267 CHECK(ops->pkt_rx, EINVAL);
268 CHECK(ops->stats_read, EINVAL);
269
270 CHECK(!port_in_type_find(p, name), EEXIST);
271
272 /* Node allocation. */
273 elem = calloc(1, sizeof(struct port_in_type));
274 CHECK(elem, ENOMEM);
275
276 /* Node initialization. */
277 strcpy(elem->name, name);
278 memcpy(&elem->ops, ops, sizeof(*ops));
279
280 /* Node add to tailq. */
281 TAILQ_INSERT_TAIL(&p->port_in_types, elem, node);
282
283 return 0;
284 }
285
286 static struct port_in *
port_in_find(struct rte_swx_pipeline * p,uint32_t port_id)287 port_in_find(struct rte_swx_pipeline *p, uint32_t port_id)
288 {
289 struct port_in *port;
290
291 TAILQ_FOREACH(port, &p->ports_in, node)
292 if (port->id == port_id)
293 return port;
294
295 return NULL;
296 }
297
298 int
rte_swx_pipeline_port_in_config(struct rte_swx_pipeline * p,uint32_t port_id,const char * port_type_name,void * args)299 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 CHECK(p, EINVAL);
309
310 CHECK(!port_in_find(p, port_id), EINVAL);
311
312 CHECK_NAME(port_type_name, EINVAL);
313 type = port_in_type_find(p, port_type_name);
314 CHECK(type, EINVAL);
315
316 obj = type->ops.create(args);
317 CHECK(obj, ENODEV);
318
319 /* Node allocation. */
320 port = calloc(1, sizeof(struct port_in));
321 CHECK(port, ENOMEM);
322
323 /* Node initialization. */
324 port->type = type;
325 port->obj = obj;
326 port->id = port_id;
327
328 /* Node add to tailq. */
329 TAILQ_INSERT_TAIL(&p->ports_in, port, node);
330 if (p->n_ports_in < port_id + 1)
331 p->n_ports_in = port_id + 1;
332
333 return 0;
334 }
335
336 static int
port_in_build(struct rte_swx_pipeline * p)337 port_in_build(struct rte_swx_pipeline *p)
338 {
339 struct port_in *port;
340 uint32_t i;
341
342 CHECK(p->n_ports_in, EINVAL);
343
344 for (i = 0; i < p->n_ports_in; i++)
345 CHECK(port_in_find(p, i), EINVAL);
346
347 p->in = calloc(p->n_ports_in, sizeof(struct port_in_runtime));
348 CHECK(p->in, ENOMEM);
349
350 TAILQ_FOREACH(port, &p->ports_in, node) {
351 struct port_in_runtime *in = &p->in[port->id];
352
353 in->pkt_rx = port->type->ops.pkt_rx;
354 in->obj = port->obj;
355 }
356
357 return 0;
358 }
359
360 static void
port_in_build_free(struct rte_swx_pipeline * p)361 port_in_build_free(struct rte_swx_pipeline *p)
362 {
363 free(p->in);
364 p->in = NULL;
365 }
366
367 static void
port_in_free(struct rte_swx_pipeline * p)368 port_in_free(struct rte_swx_pipeline *p)
369 {
370 port_in_build_free(p);
371
372 /* Input ports. */
373 for ( ; ; ) {
374 struct port_in *port;
375
376 port = TAILQ_FIRST(&p->ports_in);
377 if (!port)
378 break;
379
380 TAILQ_REMOVE(&p->ports_in, port, node);
381 port->type->ops.free(port->obj);
382 free(port);
383 }
384
385 /* Input port types. */
386 for ( ; ; ) {
387 struct port_in_type *elem;
388
389 elem = TAILQ_FIRST(&p->port_in_types);
390 if (!elem)
391 break;
392
393 TAILQ_REMOVE(&p->port_in_types, elem, node);
394 free(elem);
395 }
396 }
397
398 /*
399 * Output port.
400 */
401 static struct port_out_type *
port_out_type_find(struct rte_swx_pipeline * p,const char * name)402 port_out_type_find(struct rte_swx_pipeline *p, const char *name)
403 {
404 struct port_out_type *elem;
405
406 if (!name)
407 return NULL;
408
409 TAILQ_FOREACH(elem, &p->port_out_types, node)
410 if (!strcmp(elem->name, name))
411 return elem;
412
413 return NULL;
414 }
415
416 int
rte_swx_pipeline_port_out_type_register(struct rte_swx_pipeline * p,const char * name,struct rte_swx_port_out_ops * ops)417 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 CHECK(p, EINVAL);
424 CHECK_NAME(name, EINVAL);
425 CHECK(ops, EINVAL);
426 CHECK(ops->create, EINVAL);
427 CHECK(ops->free, EINVAL);
428 CHECK(ops->pkt_tx, EINVAL);
429 CHECK(ops->pkt_fast_clone_tx, EINVAL);
430 CHECK(ops->pkt_clone_tx, EINVAL);
431 CHECK(ops->stats_read, EINVAL);
432
433 CHECK(!port_out_type_find(p, name), EEXIST);
434
435 /* Node allocation. */
436 elem = calloc(1, sizeof(struct port_out_type));
437 CHECK(elem, ENOMEM);
438
439 /* Node initialization. */
440 strcpy(elem->name, name);
441 memcpy(&elem->ops, ops, sizeof(*ops));
442
443 /* Node add to tailq. */
444 TAILQ_INSERT_TAIL(&p->port_out_types, elem, node);
445
446 return 0;
447 }
448
449 static struct port_out *
port_out_find(struct rte_swx_pipeline * p,uint32_t port_id)450 port_out_find(struct rte_swx_pipeline *p, uint32_t port_id)
451 {
452 struct port_out *port;
453
454 TAILQ_FOREACH(port, &p->ports_out, node)
455 if (port->id == port_id)
456 return port;
457
458 return NULL;
459 }
460
461 int
rte_swx_pipeline_port_out_config(struct rte_swx_pipeline * p,uint32_t port_id,const char * port_type_name,void * args)462 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 CHECK(p, EINVAL);
472
473 CHECK(!port_out_find(p, port_id), EINVAL);
474
475 CHECK_NAME(port_type_name, EINVAL);
476 type = port_out_type_find(p, port_type_name);
477 CHECK(type, EINVAL);
478
479 obj = type->ops.create(args);
480 CHECK(obj, ENODEV);
481
482 /* Node allocation. */
483 port = calloc(1, sizeof(struct port_out));
484 CHECK(port, ENOMEM);
485
486 /* Node initialization. */
487 port->type = type;
488 port->obj = obj;
489 port->id = port_id;
490
491 /* Node add to tailq. */
492 TAILQ_INSERT_TAIL(&p->ports_out, port, node);
493 if (p->n_ports_out < port_id + 1)
494 p->n_ports_out = port_id + 1;
495
496 return 0;
497 }
498
499 static int
port_out_build(struct rte_swx_pipeline * p)500 port_out_build(struct rte_swx_pipeline *p)
501 {
502 struct port_out *port;
503 uint32_t i;
504
505 CHECK(p->n_ports_out, EINVAL);
506
507 for (i = 0; i < p->n_ports_out; i++)
508 CHECK(port_out_find(p, i), EINVAL);
509
510 p->out = calloc(p->n_ports_out, sizeof(struct port_out_runtime));
511 CHECK(p->out, ENOMEM);
512
513 TAILQ_FOREACH(port, &p->ports_out, node) {
514 struct port_out_runtime *out = &p->out[port->id];
515
516 out->pkt_tx = port->type->ops.pkt_tx;
517 out->pkt_fast_clone_tx = port->type->ops.pkt_fast_clone_tx;
518 out->pkt_clone_tx = port->type->ops.pkt_clone_tx;
519 out->flush = port->type->ops.flush;
520 out->obj = port->obj;
521 }
522
523 return 0;
524 }
525
526 static void
port_out_build_free(struct rte_swx_pipeline * p)527 port_out_build_free(struct rte_swx_pipeline *p)
528 {
529 free(p->out);
530 p->out = NULL;
531 }
532
533 static void
port_out_free(struct rte_swx_pipeline * p)534 port_out_free(struct rte_swx_pipeline *p)
535 {
536 port_out_build_free(p);
537
538 /* Output ports. */
539 for ( ; ; ) {
540 struct port_out *port;
541
542 port = TAILQ_FIRST(&p->ports_out);
543 if (!port)
544 break;
545
546 TAILQ_REMOVE(&p->ports_out, port, node);
547 port->type->ops.free(port->obj);
548 free(port);
549 }
550
551 /* Output port types. */
552 for ( ; ; ) {
553 struct port_out_type *elem;
554
555 elem = TAILQ_FIRST(&p->port_out_types);
556 if (!elem)
557 break;
558
559 TAILQ_REMOVE(&p->port_out_types, elem, node);
560 free(elem);
561 }
562 }
563
564 /*
565 * Packet mirroring.
566 */
567 int
rte_swx_pipeline_mirroring_config(struct rte_swx_pipeline * p,struct rte_swx_pipeline_mirroring_params * params)568 rte_swx_pipeline_mirroring_config(struct rte_swx_pipeline *p,
569 struct rte_swx_pipeline_mirroring_params *params)
570 {
571 CHECK(p, EINVAL);
572 CHECK(params, EINVAL);
573 CHECK(params->n_slots, EINVAL);
574 CHECK(params->n_sessions, EINVAL);
575 CHECK(!p->build_done, EEXIST);
576
577 p->n_mirroring_slots = rte_align32pow2(params->n_slots);
578 if (p->n_mirroring_slots > 64)
579 p->n_mirroring_slots = 64;
580
581 p->n_mirroring_sessions = rte_align32pow2(params->n_sessions);
582
583 return 0;
584 }
585
586 static void
mirroring_build_free(struct rte_swx_pipeline * p)587 mirroring_build_free(struct rte_swx_pipeline *p)
588 {
589 uint32_t i;
590
591 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
592 struct thread *t = &p->threads[i];
593
594 /* mirroring_slots. */
595 free(t->mirroring_slots);
596 t->mirroring_slots = NULL;
597 }
598
599 /* mirroring_sessions. */
600 free(p->mirroring_sessions);
601 p->mirroring_sessions = NULL;
602 }
603
604 static void
mirroring_free(struct rte_swx_pipeline * p)605 mirroring_free(struct rte_swx_pipeline *p)
606 {
607 mirroring_build_free(p);
608 }
609
610 static int
mirroring_build(struct rte_swx_pipeline * p)611 mirroring_build(struct rte_swx_pipeline *p)
612 {
613 uint32_t i;
614
615 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
616 struct thread *t = &p->threads[i];
617
618 /* mirroring_slots. */
619 t->mirroring_slots = calloc(p->n_mirroring_slots, sizeof(uint32_t));
620 if (!t->mirroring_slots)
621 goto error;
622 }
623
624 /* mirroring_sessions. */
625 p->mirroring_sessions = calloc(p->n_mirroring_sessions, sizeof(struct mirroring_session));
626 if (!p->mirroring_sessions)
627 goto error;
628
629 return 0;
630
631 error:
632 mirroring_build_free(p);
633 return -ENOMEM;
634 }
635
636 /*
637 * Extern object.
638 */
639 static struct extern_type *
extern_type_find(struct rte_swx_pipeline * p,const char * name)640 extern_type_find(struct rte_swx_pipeline *p, const char *name)
641 {
642 struct extern_type *elem;
643
644 TAILQ_FOREACH(elem, &p->extern_types, node)
645 if (strcmp(elem->name, name) == 0)
646 return elem;
647
648 return NULL;
649 }
650
651 static struct extern_type_member_func *
extern_type_member_func_find(struct extern_type * type,const char * name)652 extern_type_member_func_find(struct extern_type *type, const char *name)
653 {
654 struct extern_type_member_func *elem;
655
656 TAILQ_FOREACH(elem, &type->funcs, node)
657 if (strcmp(elem->name, name) == 0)
658 return elem;
659
660 return NULL;
661 }
662
663 static struct extern_obj *
extern_obj_find(struct rte_swx_pipeline * p,const char * name)664 extern_obj_find(struct rte_swx_pipeline *p, const char *name)
665 {
666 struct extern_obj *elem;
667
668 TAILQ_FOREACH(elem, &p->extern_objs, node)
669 if (strcmp(elem->name, name) == 0)
670 return elem;
671
672 return NULL;
673 }
674
675 static struct extern_type_member_func *
extern_obj_member_func_parse(struct rte_swx_pipeline * p,const char * name,struct extern_obj ** obj)676 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 if (name[0] != 'e' || name[1] != '.')
685 return NULL;
686
687 object_name = strdup(&name[2]);
688 if (!object_name)
689 return NULL;
690
691 func_name = strchr(object_name, '.');
692 if (!func_name) {
693 free(object_name);
694 return NULL;
695 }
696
697 *func_name = 0;
698 func_name++;
699
700 object = extern_obj_find(p, object_name);
701 if (!object) {
702 free(object_name);
703 return NULL;
704 }
705
706 func = extern_type_member_func_find(object->type, func_name);
707 if (!func) {
708 free(object_name);
709 return NULL;
710 }
711
712 if (obj)
713 *obj = object;
714
715 free(object_name);
716 return func;
717 }
718
719 static struct field *
extern_obj_mailbox_field_parse(struct rte_swx_pipeline * p,const char * name,struct extern_obj ** object)720 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 if ((name[0] != 'e') || (name[1] != '.'))
729 return NULL;
730
731 obj_name = strdup(&name[2]);
732 if (!obj_name)
733 return NULL;
734
735 field_name = strchr(obj_name, '.');
736 if (!field_name) {
737 free(obj_name);
738 return NULL;
739 }
740
741 *field_name = 0;
742 field_name++;
743
744 obj = extern_obj_find(p, obj_name);
745 if (!obj) {
746 free(obj_name);
747 return NULL;
748 }
749
750 f = struct_type_field_find(obj->type->mailbox_struct_type, field_name);
751 if (!f) {
752 free(obj_name);
753 return NULL;
754 }
755
756 if (object)
757 *object = obj;
758
759 free(obj_name);
760 return f;
761 }
762
763 int
rte_swx_pipeline_extern_type_register(struct rte_swx_pipeline * p,const char * name,const char * mailbox_struct_type_name,rte_swx_extern_type_constructor_t constructor,rte_swx_extern_type_destructor_t destructor)764 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 CHECK(p, EINVAL);
774
775 CHECK_NAME(name, EINVAL);
776 CHECK(!extern_type_find(p, name), EEXIST);
777
778 CHECK_NAME(mailbox_struct_type_name, EINVAL);
779 mailbox_struct_type = struct_type_find(p, mailbox_struct_type_name);
780 CHECK(mailbox_struct_type, EINVAL);
781 CHECK(!mailbox_struct_type->var_size, EINVAL);
782
783 CHECK(constructor, EINVAL);
784 CHECK(destructor, EINVAL);
785
786 /* Node allocation. */
787 elem = calloc(1, sizeof(struct extern_type));
788 CHECK(elem, ENOMEM);
789
790 /* Node initialization. */
791 strcpy(elem->name, name);
792 elem->mailbox_struct_type = mailbox_struct_type;
793 elem->constructor = constructor;
794 elem->destructor = destructor;
795 TAILQ_INIT(&elem->funcs);
796
797 /* Node add to tailq. */
798 TAILQ_INSERT_TAIL(&p->extern_types, elem, node);
799
800 return 0;
801 }
802
803 int
rte_swx_pipeline_extern_type_member_func_register(struct rte_swx_pipeline * p,const char * extern_type_name,const char * name,rte_swx_extern_type_member_func_t member_func)804 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 CHECK(p, EINVAL);
813
814 CHECK_NAME(extern_type_name, EINVAL);
815 type = extern_type_find(p, extern_type_name);
816 CHECK(type, EINVAL);
817 CHECK(type->n_funcs < RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX, ENOSPC);
818
819 CHECK_NAME(name, EINVAL);
820 CHECK(!extern_type_member_func_find(type, name), EEXIST);
821
822 CHECK(member_func, EINVAL);
823
824 /* Node allocation. */
825 type_member = calloc(1, sizeof(struct extern_type_member_func));
826 CHECK(type_member, ENOMEM);
827
828 /* Node initialization. */
829 strcpy(type_member->name, name);
830 type_member->func = member_func;
831 type_member->id = type->n_funcs;
832
833 /* Node add to tailq. */
834 TAILQ_INSERT_TAIL(&type->funcs, type_member, node);
835 type->n_funcs++;
836
837 return 0;
838 }
839
840 int
rte_swx_pipeline_extern_object_config(struct rte_swx_pipeline * p,const char * extern_type_name,const char * name,const char * args)841 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 CHECK(p, EINVAL);
851
852 CHECK_NAME(extern_type_name, EINVAL);
853 type = extern_type_find(p, extern_type_name);
854 CHECK(type, EINVAL);
855
856 CHECK_NAME(name, EINVAL);
857 CHECK(!extern_obj_find(p, name), EEXIST);
858
859 /* Node allocation. */
860 obj = calloc(1, sizeof(struct extern_obj));
861 CHECK(obj, ENOMEM);
862
863 /* Object construction. */
864 obj_handle = type->constructor(args);
865 if (!obj_handle) {
866 free(obj);
867 CHECK(0, ENODEV);
868 }
869
870 /* Node initialization. */
871 strcpy(obj->name, name);
872 obj->type = type;
873 obj->obj = obj_handle;
874 obj->struct_id = p->n_structs;
875 obj->id = p->n_extern_objs;
876
877 /* Node add to tailq. */
878 TAILQ_INSERT_TAIL(&p->extern_objs, obj, node);
879 p->n_extern_objs++;
880 p->n_structs++;
881
882 return 0;
883 }
884
885 static int
extern_obj_build(struct rte_swx_pipeline * p)886 extern_obj_build(struct rte_swx_pipeline *p)
887 {
888 uint32_t i;
889
890 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
891 struct thread *t = &p->threads[i];
892 struct extern_obj *obj;
893
894 t->extern_objs = calloc(p->n_extern_objs,
895 sizeof(struct extern_obj_runtime));
896 CHECK(t->extern_objs, ENOMEM);
897
898 TAILQ_FOREACH(obj, &p->extern_objs, node) {
899 struct extern_obj_runtime *r =
900 &t->extern_objs[obj->id];
901 struct extern_type_member_func *func;
902 uint32_t mailbox_size =
903 obj->type->mailbox_struct_type->n_bits / 8;
904
905 r->obj = obj->obj;
906
907 r->mailbox = calloc(1, mailbox_size);
908 CHECK(r->mailbox, ENOMEM);
909
910 TAILQ_FOREACH(func, &obj->type->funcs, node)
911 r->funcs[func->id] = func->func;
912
913 t->structs[obj->struct_id] = r->mailbox;
914 }
915 }
916
917 return 0;
918 }
919
920 static void
extern_obj_build_free(struct rte_swx_pipeline * p)921 extern_obj_build_free(struct rte_swx_pipeline *p)
922 {
923 uint32_t i;
924
925 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
926 struct thread *t = &p->threads[i];
927 uint32_t j;
928
929 if (!t->extern_objs)
930 continue;
931
932 for (j = 0; j < p->n_extern_objs; j++) {
933 struct extern_obj_runtime *r = &t->extern_objs[j];
934
935 free(r->mailbox);
936 }
937
938 free(t->extern_objs);
939 t->extern_objs = NULL;
940 }
941 }
942
943 static void
extern_obj_free(struct rte_swx_pipeline * p)944 extern_obj_free(struct rte_swx_pipeline *p)
945 {
946 extern_obj_build_free(p);
947
948 /* Extern objects. */
949 for ( ; ; ) {
950 struct extern_obj *elem;
951
952 elem = TAILQ_FIRST(&p->extern_objs);
953 if (!elem)
954 break;
955
956 TAILQ_REMOVE(&p->extern_objs, elem, node);
957 if (elem->obj)
958 elem->type->destructor(elem->obj);
959 free(elem);
960 }
961
962 /* Extern types. */
963 for ( ; ; ) {
964 struct extern_type *elem;
965
966 elem = TAILQ_FIRST(&p->extern_types);
967 if (!elem)
968 break;
969
970 TAILQ_REMOVE(&p->extern_types, elem, node);
971
972 for ( ; ; ) {
973 struct extern_type_member_func *func;
974
975 func = TAILQ_FIRST(&elem->funcs);
976 if (!func)
977 break;
978
979 TAILQ_REMOVE(&elem->funcs, func, node);
980 free(func);
981 }
982
983 free(elem);
984 }
985 }
986
987 /*
988 * Extern function.
989 */
990 static struct extern_func *
extern_func_find(struct rte_swx_pipeline * p,const char * name)991 extern_func_find(struct rte_swx_pipeline *p, const char *name)
992 {
993 struct extern_func *elem;
994
995 TAILQ_FOREACH(elem, &p->extern_funcs, node)
996 if (strcmp(elem->name, name) == 0)
997 return elem;
998
999 return NULL;
1000 }
1001
1002 static struct extern_func *
extern_func_parse(struct rte_swx_pipeline * p,const char * name)1003 extern_func_parse(struct rte_swx_pipeline *p,
1004 const char *name)
1005 {
1006 if (name[0] != 'f' || name[1] != '.')
1007 return NULL;
1008
1009 return extern_func_find(p, &name[2]);
1010 }
1011
1012 static struct field *
extern_func_mailbox_field_parse(struct rte_swx_pipeline * p,const char * name,struct extern_func ** function)1013 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 if ((name[0] != 'f') || (name[1] != '.'))
1022 return NULL;
1023
1024 func_name = strdup(&name[2]);
1025 if (!func_name)
1026 return NULL;
1027
1028 field_name = strchr(func_name, '.');
1029 if (!field_name) {
1030 free(func_name);
1031 return NULL;
1032 }
1033
1034 *field_name = 0;
1035 field_name++;
1036
1037 func = extern_func_find(p, func_name);
1038 if (!func) {
1039 free(func_name);
1040 return NULL;
1041 }
1042
1043 f = struct_type_field_find(func->mailbox_struct_type, field_name);
1044 if (!f) {
1045 free(func_name);
1046 return NULL;
1047 }
1048
1049 if (function)
1050 *function = func;
1051
1052 free(func_name);
1053 return f;
1054 }
1055
1056 int
rte_swx_pipeline_extern_func_register(struct rte_swx_pipeline * p,const char * name,const char * mailbox_struct_type_name,rte_swx_extern_func_t func)1057 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 CHECK(p, EINVAL);
1066
1067 CHECK_NAME(name, EINVAL);
1068 CHECK(!extern_func_find(p, name), EEXIST);
1069
1070 CHECK_NAME(mailbox_struct_type_name, EINVAL);
1071 mailbox_struct_type = struct_type_find(p, mailbox_struct_type_name);
1072 CHECK(mailbox_struct_type, EINVAL);
1073 CHECK(!mailbox_struct_type->var_size, EINVAL);
1074
1075 CHECK(func, EINVAL);
1076
1077 /* Node allocation. */
1078 f = calloc(1, sizeof(struct extern_func));
1079 CHECK(func, ENOMEM);
1080
1081 /* Node initialization. */
1082 strcpy(f->name, name);
1083 f->mailbox_struct_type = mailbox_struct_type;
1084 f->func = func;
1085 f->struct_id = p->n_structs;
1086 f->id = p->n_extern_funcs;
1087
1088 /* Node add to tailq. */
1089 TAILQ_INSERT_TAIL(&p->extern_funcs, f, node);
1090 p->n_extern_funcs++;
1091 p->n_structs++;
1092
1093 return 0;
1094 }
1095
1096 static int
extern_func_build(struct rte_swx_pipeline * p)1097 extern_func_build(struct rte_swx_pipeline *p)
1098 {
1099 uint32_t i;
1100
1101 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 t->extern_funcs = calloc(p->n_extern_funcs,
1107 sizeof(struct extern_func_runtime));
1108 CHECK(t->extern_funcs, ENOMEM);
1109
1110 /* Extern function. */
1111 TAILQ_FOREACH(func, &p->extern_funcs, node) {
1112 struct extern_func_runtime *r =
1113 &t->extern_funcs[func->id];
1114 uint32_t mailbox_size =
1115 func->mailbox_struct_type->n_bits / 8;
1116
1117 r->func = func->func;
1118
1119 r->mailbox = calloc(1, mailbox_size);
1120 CHECK(r->mailbox, ENOMEM);
1121
1122 t->structs[func->struct_id] = r->mailbox;
1123 }
1124 }
1125
1126 return 0;
1127 }
1128
1129 static void
extern_func_build_free(struct rte_swx_pipeline * p)1130 extern_func_build_free(struct rte_swx_pipeline *p)
1131 {
1132 uint32_t i;
1133
1134 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1135 struct thread *t = &p->threads[i];
1136 uint32_t j;
1137
1138 if (!t->extern_funcs)
1139 continue;
1140
1141 for (j = 0; j < p->n_extern_funcs; j++) {
1142 struct extern_func_runtime *r = &t->extern_funcs[j];
1143
1144 free(r->mailbox);
1145 }
1146
1147 free(t->extern_funcs);
1148 t->extern_funcs = NULL;
1149 }
1150 }
1151
1152 static void
extern_func_free(struct rte_swx_pipeline * p)1153 extern_func_free(struct rte_swx_pipeline *p)
1154 {
1155 extern_func_build_free(p);
1156
1157 for ( ; ; ) {
1158 struct extern_func *elem;
1159
1160 elem = TAILQ_FIRST(&p->extern_funcs);
1161 if (!elem)
1162 break;
1163
1164 TAILQ_REMOVE(&p->extern_funcs, elem, node);
1165 free(elem);
1166 }
1167 }
1168
1169 /*
1170 * Hash function.
1171 */
1172 static struct hash_func *
hash_func_find(struct rte_swx_pipeline * p,const char * name)1173 hash_func_find(struct rte_swx_pipeline *p, const char *name)
1174 {
1175 struct hash_func *elem;
1176
1177 TAILQ_FOREACH(elem, &p->hash_funcs, node)
1178 if (strcmp(elem->name, name) == 0)
1179 return elem;
1180
1181 return NULL;
1182 }
1183
1184 int
rte_swx_pipeline_hash_func_register(struct rte_swx_pipeline * p,const char * name,rte_swx_hash_func_t func)1185 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 CHECK(p, EINVAL);
1192
1193 CHECK_NAME(name, EINVAL);
1194 CHECK(!hash_func_find(p, name), EEXIST);
1195
1196 CHECK(func, EINVAL);
1197
1198 /* Node allocation. */
1199 f = calloc(1, sizeof(struct hash_func));
1200 CHECK(func, ENOMEM);
1201
1202 /* Node initialization. */
1203 strcpy(f->name, name);
1204 f->func = func;
1205 f->id = p->n_hash_funcs;
1206
1207 /* Node add to tailq. */
1208 TAILQ_INSERT_TAIL(&p->hash_funcs, f, node);
1209 p->n_hash_funcs++;
1210
1211 return 0;
1212 }
1213
1214 static int
hash_func_build(struct rte_swx_pipeline * p)1215 hash_func_build(struct rte_swx_pipeline *p)
1216 {
1217 struct hash_func *func;
1218
1219 /* Memory allocation. */
1220 p->hash_func_runtime = calloc(p->n_hash_funcs, sizeof(struct hash_func_runtime));
1221 CHECK(p->hash_func_runtime, ENOMEM);
1222
1223 /* Hash function. */
1224 TAILQ_FOREACH(func, &p->hash_funcs, node) {
1225 struct hash_func_runtime *r = &p->hash_func_runtime[func->id];
1226
1227 r->func = func->func;
1228 }
1229
1230 return 0;
1231 }
1232
1233 static void
hash_func_build_free(struct rte_swx_pipeline * p)1234 hash_func_build_free(struct rte_swx_pipeline *p)
1235 {
1236 free(p->hash_func_runtime);
1237 p->hash_func_runtime = NULL;
1238 }
1239
1240 static void
hash_func_free(struct rte_swx_pipeline * p)1241 hash_func_free(struct rte_swx_pipeline *p)
1242 {
1243 hash_func_build_free(p);
1244
1245 for ( ; ; ) {
1246 struct hash_func *elem;
1247
1248 elem = TAILQ_FIRST(&p->hash_funcs);
1249 if (!elem)
1250 break;
1251
1252 TAILQ_REMOVE(&p->hash_funcs, elem, node);
1253 free(elem);
1254 }
1255 }
1256
1257 /*
1258 * RSS.
1259 */
1260 static struct rss *
rss_find(struct rte_swx_pipeline * p,const char * name)1261 rss_find(struct rte_swx_pipeline *p, const char *name)
1262 {
1263 struct rss *elem;
1264
1265 TAILQ_FOREACH(elem, &p->rss, node)
1266 if (strcmp(elem->name, name) == 0)
1267 return elem;
1268
1269 return NULL;
1270 }
1271
1272 static struct rss *
rss_find_by_id(struct rte_swx_pipeline * p,uint32_t rss_obj_id)1273 rss_find_by_id(struct rte_swx_pipeline *p, uint32_t rss_obj_id)
1274 {
1275 struct rss *elem;
1276
1277 TAILQ_FOREACH(elem, &p->rss, node)
1278 if (elem->id == rss_obj_id)
1279 return elem;
1280
1281 return NULL;
1282 }
1283
1284 int
rte_swx_pipeline_rss_config(struct rte_swx_pipeline * p,const char * name)1285 rte_swx_pipeline_rss_config(struct rte_swx_pipeline *p, const char *name)
1286 {
1287 struct rss *r;
1288
1289 CHECK(p, EINVAL);
1290
1291 CHECK_NAME(name, EINVAL);
1292 CHECK(!rss_find(p, name), EEXIST);
1293
1294 /* Memory allocation. */
1295 r = calloc(1, sizeof(struct rss));
1296 CHECK(r, ENOMEM);
1297
1298 /* Node initialization. */
1299 strcpy(r->name, name);
1300 r->id = p->n_rss;
1301
1302 /* Node add to tailq. */
1303 TAILQ_INSERT_TAIL(&p->rss, r, node);
1304 p->n_rss++;
1305
1306 return 0;
1307 }
1308
1309 static void
rss_build_free(struct rte_swx_pipeline * p)1310 rss_build_free(struct rte_swx_pipeline *p)
1311 {
1312 uint32_t i;
1313
1314 if (!p->rss_runtime)
1315 return;
1316
1317 for (i = 0; i < p->n_rss; i++)
1318 free(p->rss_runtime[i]);
1319
1320 free(p->rss_runtime);
1321 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
rss_build(struct rte_swx_pipeline * p)1333 rss_build(struct rte_swx_pipeline *p)
1334 {
1335 uint32_t i;
1336 int status = 0;
1337
1338 /* Memory allocation. */
1339 p->rss_runtime = calloc(p->n_rss, sizeof(struct rss_runtime *));
1340 if (!p->rss_runtime) {
1341 status = -ENOMEM;
1342 goto error;
1343 }
1344
1345 /* RSS. */
1346 for (i = 0; i < p->n_rss; i++) {
1347 p->rss_runtime[i] = malloc(sizeof(rss_runtime_default));
1348 if (!p->rss_runtime[i]) {
1349 status = -ENOMEM;
1350 goto error;
1351 }
1352
1353 memcpy(p->rss_runtime[i], &rss_runtime_default, sizeof(rss_runtime_default));
1354 }
1355
1356 return 0;
1357
1358 error:
1359 rss_build_free(p);
1360 return status;
1361 }
1362
1363 static void
rss_free(struct rte_swx_pipeline * p)1364 rss_free(struct rte_swx_pipeline *p)
1365 {
1366 rss_build_free(p);
1367
1368 for ( ; ; ) {
1369 struct rss *elem;
1370
1371 elem = TAILQ_FIRST(&p->rss);
1372 if (!elem)
1373 break;
1374
1375 TAILQ_REMOVE(&p->rss, elem, node);
1376 free(elem);
1377 }
1378 }
1379
1380 /*
1381 * Header.
1382 */
1383 static struct header *
header_find(struct rte_swx_pipeline * p,const char * name)1384 header_find(struct rte_swx_pipeline *p, const char *name)
1385 {
1386 struct header *elem;
1387
1388 TAILQ_FOREACH(elem, &p->headers, node)
1389 if (strcmp(elem->name, name) == 0)
1390 return elem;
1391
1392 return NULL;
1393 }
1394
1395 static struct header *
header_find_by_struct_id(struct rte_swx_pipeline * p,uint32_t struct_id)1396 header_find_by_struct_id(struct rte_swx_pipeline *p, uint32_t struct_id)
1397 {
1398 struct header *elem;
1399
1400 TAILQ_FOREACH(elem, &p->headers, node)
1401 if (elem->struct_id == struct_id)
1402 return elem;
1403
1404 return NULL;
1405 }
1406
1407 static struct header *
header_parse(struct rte_swx_pipeline * p,const char * name)1408 header_parse(struct rte_swx_pipeline *p,
1409 const char *name)
1410 {
1411 if (name[0] != 'h' || name[1] != '.')
1412 return NULL;
1413
1414 return header_find(p, &name[2]);
1415 }
1416
1417 static struct field *
header_field_parse(struct rte_swx_pipeline * p,const char * name,struct header ** header)1418 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 if ((name[0] != 'h') || (name[1] != '.'))
1427 return NULL;
1428
1429 header_name = strdup(&name[2]);
1430 if (!header_name)
1431 return NULL;
1432
1433 field_name = strchr(header_name, '.');
1434 if (!field_name) {
1435 free(header_name);
1436 return NULL;
1437 }
1438
1439 *field_name = 0;
1440 field_name++;
1441
1442 h = header_find(p, header_name);
1443 if (!h) {
1444 free(header_name);
1445 return NULL;
1446 }
1447
1448 f = struct_type_field_find(h->st, field_name);
1449 if (!f) {
1450 free(header_name);
1451 return NULL;
1452 }
1453
1454 if (header)
1455 *header = h;
1456
1457 free(header_name);
1458 return f;
1459 }
1460
1461 int
rte_swx_pipeline_packet_header_register(struct rte_swx_pipeline * p,const char * name,const char * struct_type_name)1462 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 CHECK(p, EINVAL);
1471 CHECK_NAME(name, EINVAL);
1472 CHECK_NAME(struct_type_name, EINVAL);
1473
1474 CHECK(!header_find(p, name), EEXIST);
1475
1476 st = struct_type_find(p, struct_type_name);
1477 CHECK(st, EINVAL);
1478
1479 n_headers_max = RTE_SIZEOF_FIELD(struct thread, valid_headers) * 8;
1480 CHECK(p->n_headers < n_headers_max, ENOSPC);
1481
1482 /* Node allocation. */
1483 h = calloc(1, sizeof(struct header));
1484 CHECK(h, ENOMEM);
1485
1486 /* Node initialization. */
1487 strcpy(h->name, name);
1488 h->st = st;
1489 h->struct_id = p->n_structs;
1490 h->id = p->n_headers;
1491
1492 /* Node add to tailq. */
1493 TAILQ_INSERT_TAIL(&p->headers, h, node);
1494 p->n_headers++;
1495 p->n_structs++;
1496
1497 return 0;
1498 }
1499
1500 static int
header_build(struct rte_swx_pipeline * p)1501 header_build(struct rte_swx_pipeline *p)
1502 {
1503 struct header *h;
1504 uint32_t n_bytes = 0, i;
1505
1506 TAILQ_FOREACH(h, &p->headers, node) {
1507 n_bytes += h->st->n_bits / 8;
1508 }
1509
1510 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1511 struct thread *t = &p->threads[i];
1512 uint32_t offset = 0;
1513
1514 t->headers = calloc(p->n_headers,
1515 sizeof(struct header_runtime));
1516 CHECK(t->headers, ENOMEM);
1517
1518 t->headers_out = calloc(p->n_headers,
1519 sizeof(struct header_out_runtime));
1520 CHECK(t->headers_out, ENOMEM);
1521
1522 t->header_storage = calloc(1, n_bytes);
1523 CHECK(t->header_storage, ENOMEM);
1524
1525 t->header_out_storage = calloc(1, n_bytes);
1526 CHECK(t->header_out_storage, ENOMEM);
1527
1528 TAILQ_FOREACH(h, &p->headers, node) {
1529 uint8_t *header_storage;
1530 uint32_t n_bytes = h->st->n_bits / 8;
1531
1532 header_storage = &t->header_storage[offset];
1533 offset += n_bytes;
1534
1535 t->headers[h->id].ptr0 = header_storage;
1536 t->headers[h->id].n_bytes = n_bytes;
1537
1538 t->structs[h->struct_id] = header_storage;
1539 }
1540 }
1541
1542 return 0;
1543 }
1544
1545 static void
header_build_free(struct rte_swx_pipeline * p)1546 header_build_free(struct rte_swx_pipeline *p)
1547 {
1548 uint32_t i;
1549
1550 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1551 struct thread *t = &p->threads[i];
1552
1553 free(t->headers_out);
1554 t->headers_out = NULL;
1555
1556 free(t->headers);
1557 t->headers = NULL;
1558
1559 free(t->header_out_storage);
1560 t->header_out_storage = NULL;
1561
1562 free(t->header_storage);
1563 t->header_storage = NULL;
1564 }
1565 }
1566
1567 static void
header_free(struct rte_swx_pipeline * p)1568 header_free(struct rte_swx_pipeline *p)
1569 {
1570 header_build_free(p);
1571
1572 for ( ; ; ) {
1573 struct header *elem;
1574
1575 elem = TAILQ_FIRST(&p->headers);
1576 if (!elem)
1577 break;
1578
1579 TAILQ_REMOVE(&p->headers, elem, node);
1580 free(elem);
1581 }
1582 }
1583
1584 /*
1585 * Meta-data.
1586 */
1587 static struct field *
metadata_field_parse(struct rte_swx_pipeline * p,const char * name)1588 metadata_field_parse(struct rte_swx_pipeline *p, const char *name)
1589 {
1590 if (!p->metadata_st)
1591 return NULL;
1592
1593 if (name[0] != 'm' || name[1] != '.')
1594 return NULL;
1595
1596 return struct_type_field_find(p->metadata_st, &name[2]);
1597 }
1598
1599 int
rte_swx_pipeline_packet_metadata_register(struct rte_swx_pipeline * p,const char * struct_type_name)1600 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 CHECK(p, EINVAL);
1606
1607 CHECK_NAME(struct_type_name, EINVAL);
1608 st = struct_type_find(p, struct_type_name);
1609 CHECK(st, EINVAL);
1610 CHECK(!st->var_size, EINVAL);
1611 CHECK(!p->metadata_st, EINVAL);
1612
1613 p->metadata_st = st;
1614 p->metadata_struct_id = p->n_structs;
1615
1616 p->n_structs++;
1617
1618 return 0;
1619 }
1620
1621 static int
metadata_build(struct rte_swx_pipeline * p)1622 metadata_build(struct rte_swx_pipeline *p)
1623 {
1624 uint32_t n_bytes = p->metadata_st->n_bits / 8;
1625 uint32_t i;
1626
1627 /* Thread-level initialization. */
1628 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1629 struct thread *t = &p->threads[i];
1630 uint8_t *metadata;
1631
1632 metadata = calloc(1, n_bytes);
1633 CHECK(metadata, ENOMEM);
1634
1635 t->metadata = metadata;
1636 t->structs[p->metadata_struct_id] = metadata;
1637 }
1638
1639 return 0;
1640 }
1641
1642 static void
metadata_build_free(struct rte_swx_pipeline * p)1643 metadata_build_free(struct rte_swx_pipeline *p)
1644 {
1645 uint32_t i;
1646
1647 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1648 struct thread *t = &p->threads[i];
1649
1650 free(t->metadata);
1651 t->metadata = NULL;
1652 }
1653 }
1654
1655 static void
metadata_free(struct rte_swx_pipeline * p)1656 metadata_free(struct rte_swx_pipeline *p)
1657 {
1658 metadata_build_free(p);
1659 }
1660
1661 /*
1662 * Instruction.
1663 */
1664 static int
instruction_is_tx(enum instruction_type type)1665 instruction_is_tx(enum instruction_type type)
1666 {
1667 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
instruction_does_tx(struct instruction * instr)1679 instruction_does_tx(struct instruction *instr)
1680 {
1681 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
instruction_is_jmp(struct instruction * instr)1700 instruction_is_jmp(struct instruction *instr)
1701 {
1702 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
instruction_does_thread_yield(struct instruction * instr)1740 instruction_does_thread_yield(struct instruction *instr)
1741 {
1742 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 *
struct_field_parse(struct rte_swx_pipeline * p,struct action * action,const char * name,uint32_t * struct_id)1761 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 switch (name[0]) {
1769 case 'h':
1770 {
1771 struct header *header;
1772
1773 f = header_field_parse(p, name, &header);
1774 if (!f)
1775 return NULL;
1776
1777 *struct_id = header->struct_id;
1778 return f;
1779 }
1780
1781 case 'm':
1782 {
1783 f = metadata_field_parse(p, name);
1784 if (!f)
1785 return NULL;
1786
1787 *struct_id = p->metadata_struct_id;
1788 return f;
1789 }
1790
1791 case 't':
1792 {
1793 if (!action)
1794 return NULL;
1795
1796 f = action_field_parse(action, name);
1797 if (!f)
1798 return NULL;
1799
1800 *struct_id = 0;
1801 return f;
1802 }
1803
1804 case 'e':
1805 {
1806 struct extern_obj *obj;
1807
1808 f = extern_obj_mailbox_field_parse(p, name, &obj);
1809 if (!f)
1810 return NULL;
1811
1812 *struct_id = obj->struct_id;
1813 return f;
1814 }
1815
1816 case 'f':
1817 {
1818 struct extern_func *func;
1819
1820 f = extern_func_mailbox_field_parse(p, name, &func);
1821 if (!f)
1822 return NULL;
1823
1824 *struct_id = func->struct_id;
1825 return f;
1826 }
1827
1828 default:
1829 return NULL;
1830 }
1831 }
1832
1833 /*
1834 * rx.
1835 */
1836 static int
instr_rx_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)1837 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 CHECK(!action, EINVAL);
1847 CHECK(n_tokens == 2, EINVAL);
1848
1849 f = metadata_field_parse(p, tokens[1]);
1850 CHECK(f, EINVAL);
1851 CHECK(f->n_bits <= 64, EINVAL);
1852
1853 instr->type = INSTR_RX;
1854 instr->io.io.offset = f->offset / 8;
1855 instr->io.io.n_bits = f->n_bits;
1856 return 0;
1857 }
1858
1859 /*
1860 * tx.
1861 */
1862 static int
instr_tx_translate(struct rte_swx_pipeline * p,struct action * action __rte_unused,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)1863 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 char *port = tokens[1];
1871 struct field *f;
1872 uint32_t port_val;
1873
1874 CHECK(n_tokens == 2, EINVAL);
1875
1876 f = metadata_field_parse(p, port);
1877 if (f) {
1878 CHECK(f->n_bits <= 64, EINVAL);
1879 instr->type = INSTR_TX;
1880 instr->io.io.offset = f->offset / 8;
1881 instr->io.io.n_bits = f->n_bits;
1882 return 0;
1883 }
1884
1885 /* TX_I. */
1886 port_val = strtoul(port, &port, 0);
1887 CHECK(!port[0], EINVAL);
1888
1889 instr->type = INSTR_TX_I;
1890 instr->io.io.val = port_val;
1891 return 0;
1892 }
1893
1894 static int
instr_drop_translate(struct rte_swx_pipeline * p __rte_unused,struct action * action __rte_unused,char ** tokens __rte_unused,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)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 CHECK(n_tokens == 1, EINVAL);
1903
1904 /* DROP. */
1905 instr->type = INSTR_DROP;
1906 return 0;
1907 }
1908
1909 static inline void
instr_tx_exec(struct rte_swx_pipeline * p)1910 instr_tx_exec(struct rte_swx_pipeline *p)
1911 {
1912 struct thread *t = &p->threads[p->thread_id];
1913 struct instruction *ip = t->ip;
1914
1915 __instr_tx_exec(p, t, ip);
1916
1917 /* Thread. */
1918 thread_ip_reset(p, t);
1919 instr_rx_exec(p);
1920 }
1921
1922 static inline void
instr_tx_i_exec(struct rte_swx_pipeline * p)1923 instr_tx_i_exec(struct rte_swx_pipeline *p)
1924 {
1925 struct thread *t = &p->threads[p->thread_id];
1926 struct instruction *ip = t->ip;
1927
1928 __instr_tx_i_exec(p, t, ip);
1929
1930 /* Thread. */
1931 thread_ip_reset(p, t);
1932 instr_rx_exec(p);
1933 }
1934
1935 static inline void
instr_drop_exec(struct rte_swx_pipeline * p)1936 instr_drop_exec(struct rte_swx_pipeline *p)
1937 {
1938 struct thread *t = &p->threads[p->thread_id];
1939 struct instruction *ip = t->ip;
1940
1941 __instr_drop_exec(p, t, ip);
1942
1943 /* Thread. */
1944 thread_ip_reset(p, t);
1945 instr_rx_exec(p);
1946 }
1947
1948 /*
1949 * mirror.
1950 */
1951 static int
instr_mirror_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)1952 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 char *dst = tokens[1], *src = tokens[2];
1960 struct field *fdst, *fsrc;
1961 uint32_t dst_struct_id = 0, src_struct_id = 0;
1962
1963 CHECK(n_tokens == 3, EINVAL);
1964
1965 fdst = struct_field_parse(p, action, dst, &dst_struct_id);
1966 CHECK(fdst, EINVAL);
1967 CHECK(dst[0] != 'h', EINVAL);
1968 CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
1969
1970 fsrc = struct_field_parse(p, action, src, &src_struct_id);
1971 CHECK(fsrc, EINVAL);
1972 CHECK(src[0] != 'h', EINVAL);
1973 CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
1974
1975 instr->type = INSTR_MIRROR;
1976 instr->mirror.dst.struct_id = (uint8_t)dst_struct_id;
1977 instr->mirror.dst.n_bits = fdst->n_bits;
1978 instr->mirror.dst.offset = fdst->offset / 8;
1979 instr->mirror.src.struct_id = (uint8_t)src_struct_id;
1980 instr->mirror.src.n_bits = fsrc->n_bits;
1981 instr->mirror.src.offset = fsrc->offset / 8;
1982
1983 return 0;
1984 }
1985
1986 static inline void
instr_mirror_exec(struct rte_swx_pipeline * p)1987 instr_mirror_exec(struct rte_swx_pipeline *p)
1988 {
1989 struct thread *t = &p->threads[p->thread_id];
1990 struct instruction *ip = t->ip;
1991
1992 __instr_mirror_exec(p, t, ip);
1993
1994 /* Thread. */
1995 thread_ip_inc(p);
1996 }
1997
1998 /*
1999 * recirculate.
2000 */
2001 static int
instr_recirculate_translate(struct rte_swx_pipeline * p __rte_unused,struct action * action __rte_unused,char ** tokens __rte_unused,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)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 CHECK(n_tokens == 1, EINVAL);
2010
2011 instr->type = INSTR_RECIRCULATE;
2012 return 0;
2013 }
2014
2015 static int
instr_recircid_translate(struct rte_swx_pipeline * p,struct action * action __rte_unused,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)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 CHECK(n_tokens == 2, EINVAL);
2026
2027 f = metadata_field_parse(p, tokens[1]);
2028 CHECK(f, EINVAL);
2029 CHECK(f->n_bits <= 64, EINVAL);
2030
2031 instr->type = INSTR_RECIRCID;
2032 instr->io.io.offset = f->offset / 8;
2033 instr->io.io.n_bits = f->n_bits;
2034 return 0;
2035 }
2036
2037 static inline void
instr_recirculate_exec(struct rte_swx_pipeline * p)2038 instr_recirculate_exec(struct rte_swx_pipeline *p)
2039 {
2040 struct thread *t = &p->threads[p->thread_id];
2041 struct instruction *ip = t->ip;
2042
2043 __instr_recirculate_exec(p, t, ip);
2044
2045 /* Thread. */
2046 thread_ip_inc(p);
2047 }
2048
2049 static inline void
instr_recircid_exec(struct rte_swx_pipeline * p)2050 instr_recircid_exec(struct rte_swx_pipeline *p)
2051 {
2052 struct thread *t = &p->threads[p->thread_id];
2053 struct instruction *ip = t->ip;
2054
2055 __instr_recircid_exec(p, t, ip);
2056
2057 /* Thread. */
2058 thread_ip_inc(p);
2059 }
2060
2061 /*
2062 * extract.
2063 */
2064 static int
instr_hdr_extract_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)2065 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 CHECK(!action, EINVAL);
2075 CHECK((n_tokens == 2) || (n_tokens == 3), EINVAL);
2076
2077 h = header_parse(p, tokens[1]);
2078 CHECK(h, EINVAL);
2079
2080 if (n_tokens == 2) {
2081 CHECK(!h->st->var_size, EINVAL);
2082
2083 instr->type = INSTR_HDR_EXTRACT;
2084 instr->io.hdr.header_id[0] = h->id;
2085 instr->io.hdr.struct_id[0] = h->struct_id;
2086 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
2087 } else {
2088 struct field *mf;
2089
2090 CHECK(h->st->var_size, EINVAL);
2091
2092 mf = metadata_field_parse(p, tokens[2]);
2093 CHECK(mf, EINVAL);
2094 CHECK(mf->n_bits <= 64, EINVAL);
2095
2096 instr->type = INSTR_HDR_EXTRACT_M;
2097 instr->io.io.offset = mf->offset / 8;
2098 instr->io.io.n_bits = mf->n_bits;
2099 instr->io.hdr.header_id[0] = h->id;
2100 instr->io.hdr.struct_id[0] = h->struct_id;
2101 instr->io.hdr.n_bytes[0] = h->st->n_bits_min / 8;
2102 }
2103
2104 return 0;
2105 }
2106
2107 static int
instr_hdr_lookahead_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)2108 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 CHECK(!action, EINVAL);
2118 CHECK(n_tokens == 2, EINVAL);
2119
2120 h = header_parse(p, tokens[1]);
2121 CHECK(h, EINVAL);
2122 CHECK(!h->st->var_size, EINVAL);
2123
2124 instr->type = INSTR_HDR_LOOKAHEAD;
2125 instr->io.hdr.header_id[0] = h->id;
2126 instr->io.hdr.struct_id[0] = h->struct_id;
2127 instr->io.hdr.n_bytes[0] = 0; /* Unused. */
2128
2129 return 0;
2130 }
2131
2132 static inline void
instr_hdr_extract_exec(struct rte_swx_pipeline * p)2133 instr_hdr_extract_exec(struct rte_swx_pipeline *p)
2134 {
2135 struct thread *t = &p->threads[p->thread_id];
2136 struct instruction *ip = t->ip;
2137
2138 __instr_hdr_extract_exec(p, t, ip);
2139
2140 /* Thread. */
2141 thread_ip_inc(p);
2142 }
2143
2144 static inline void
instr_hdr_extract2_exec(struct rte_swx_pipeline * p)2145 instr_hdr_extract2_exec(struct rte_swx_pipeline *p)
2146 {
2147 struct thread *t = &p->threads[p->thread_id];
2148 struct instruction *ip = t->ip;
2149
2150 __instr_hdr_extract2_exec(p, t, ip);
2151
2152 /* Thread. */
2153 thread_ip_inc(p);
2154 }
2155
2156 static inline void
instr_hdr_extract3_exec(struct rte_swx_pipeline * p)2157 instr_hdr_extract3_exec(struct rte_swx_pipeline *p)
2158 {
2159 struct thread *t = &p->threads[p->thread_id];
2160 struct instruction *ip = t->ip;
2161
2162 __instr_hdr_extract3_exec(p, t, ip);
2163
2164 /* Thread. */
2165 thread_ip_inc(p);
2166 }
2167
2168 static inline void
instr_hdr_extract4_exec(struct rte_swx_pipeline * p)2169 instr_hdr_extract4_exec(struct rte_swx_pipeline *p)
2170 {
2171 struct thread *t = &p->threads[p->thread_id];
2172 struct instruction *ip = t->ip;
2173
2174 __instr_hdr_extract4_exec(p, t, ip);
2175
2176 /* Thread. */
2177 thread_ip_inc(p);
2178 }
2179
2180 static inline void
instr_hdr_extract5_exec(struct rte_swx_pipeline * p)2181 instr_hdr_extract5_exec(struct rte_swx_pipeline *p)
2182 {
2183 struct thread *t = &p->threads[p->thread_id];
2184 struct instruction *ip = t->ip;
2185
2186 __instr_hdr_extract5_exec(p, t, ip);
2187
2188 /* Thread. */
2189 thread_ip_inc(p);
2190 }
2191
2192 static inline void
instr_hdr_extract6_exec(struct rte_swx_pipeline * p)2193 instr_hdr_extract6_exec(struct rte_swx_pipeline *p)
2194 {
2195 struct thread *t = &p->threads[p->thread_id];
2196 struct instruction *ip = t->ip;
2197
2198 __instr_hdr_extract6_exec(p, t, ip);
2199
2200 /* Thread. */
2201 thread_ip_inc(p);
2202 }
2203
2204 static inline void
instr_hdr_extract7_exec(struct rte_swx_pipeline * p)2205 instr_hdr_extract7_exec(struct rte_swx_pipeline *p)
2206 {
2207 struct thread *t = &p->threads[p->thread_id];
2208 struct instruction *ip = t->ip;
2209
2210 __instr_hdr_extract7_exec(p, t, ip);
2211
2212 /* Thread. */
2213 thread_ip_inc(p);
2214 }
2215
2216 static inline void
instr_hdr_extract8_exec(struct rte_swx_pipeline * p)2217 instr_hdr_extract8_exec(struct rte_swx_pipeline *p)
2218 {
2219 struct thread *t = &p->threads[p->thread_id];
2220 struct instruction *ip = t->ip;
2221
2222 __instr_hdr_extract8_exec(p, t, ip);
2223
2224 /* Thread. */
2225 thread_ip_inc(p);
2226 }
2227
2228 static inline void
instr_hdr_extract_m_exec(struct rte_swx_pipeline * p)2229 instr_hdr_extract_m_exec(struct rte_swx_pipeline *p)
2230 {
2231 struct thread *t = &p->threads[p->thread_id];
2232 struct instruction *ip = t->ip;
2233
2234 __instr_hdr_extract_m_exec(p, t, ip);
2235
2236 /* Thread. */
2237 thread_ip_inc(p);
2238 }
2239
2240 static inline void
instr_hdr_lookahead_exec(struct rte_swx_pipeline * p)2241 instr_hdr_lookahead_exec(struct rte_swx_pipeline *p)
2242 {
2243 struct thread *t = &p->threads[p->thread_id];
2244 struct instruction *ip = t->ip;
2245
2246 __instr_hdr_lookahead_exec(p, t, ip);
2247
2248 /* Thread. */
2249 thread_ip_inc(p);
2250 }
2251
2252 /*
2253 * emit.
2254 */
2255 static int
instr_hdr_emit_translate(struct rte_swx_pipeline * p,struct action * action __rte_unused,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)2256 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 CHECK(n_tokens == 2, EINVAL);
2266
2267 h = header_parse(p, tokens[1]);
2268 CHECK(h, EINVAL);
2269
2270 instr->type = INSTR_HDR_EMIT;
2271 instr->io.hdr.header_id[0] = h->id;
2272 instr->io.hdr.struct_id[0] = h->struct_id;
2273 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
2274 return 0;
2275 }
2276
2277 static inline void
instr_hdr_emit_exec(struct rte_swx_pipeline * p)2278 instr_hdr_emit_exec(struct rte_swx_pipeline *p)
2279 {
2280 struct thread *t = &p->threads[p->thread_id];
2281 struct instruction *ip = t->ip;
2282
2283 __instr_hdr_emit_exec(p, t, ip);
2284
2285 /* Thread. */
2286 thread_ip_inc(p);
2287 }
2288
2289 static inline void
instr_hdr_emit_tx_exec(struct rte_swx_pipeline * p)2290 instr_hdr_emit_tx_exec(struct rte_swx_pipeline *p)
2291 {
2292 struct thread *t = &p->threads[p->thread_id];
2293 struct instruction *ip = t->ip;
2294
2295 __instr_hdr_emit_tx_exec(p, t, ip);
2296
2297 /* Thread. */
2298 thread_ip_reset(p, t);
2299 instr_rx_exec(p);
2300 }
2301
2302 static inline void
instr_hdr_emit2_tx_exec(struct rte_swx_pipeline * p)2303 instr_hdr_emit2_tx_exec(struct rte_swx_pipeline *p)
2304 {
2305 struct thread *t = &p->threads[p->thread_id];
2306 struct instruction *ip = t->ip;
2307
2308 __instr_hdr_emit2_tx_exec(p, t, ip);
2309
2310 /* Thread. */
2311 thread_ip_reset(p, t);
2312 instr_rx_exec(p);
2313 }
2314
2315 static inline void
instr_hdr_emit3_tx_exec(struct rte_swx_pipeline * p)2316 instr_hdr_emit3_tx_exec(struct rte_swx_pipeline *p)
2317 {
2318 struct thread *t = &p->threads[p->thread_id];
2319 struct instruction *ip = t->ip;
2320
2321 __instr_hdr_emit3_tx_exec(p, t, ip);
2322
2323 /* Thread. */
2324 thread_ip_reset(p, t);
2325 instr_rx_exec(p);
2326 }
2327
2328 static inline void
instr_hdr_emit4_tx_exec(struct rte_swx_pipeline * p)2329 instr_hdr_emit4_tx_exec(struct rte_swx_pipeline *p)
2330 {
2331 struct thread *t = &p->threads[p->thread_id];
2332 struct instruction *ip = t->ip;
2333
2334 __instr_hdr_emit4_tx_exec(p, t, ip);
2335
2336 /* Thread. */
2337 thread_ip_reset(p, t);
2338 instr_rx_exec(p);
2339 }
2340
2341 static inline void
instr_hdr_emit5_tx_exec(struct rte_swx_pipeline * p)2342 instr_hdr_emit5_tx_exec(struct rte_swx_pipeline *p)
2343 {
2344 struct thread *t = &p->threads[p->thread_id];
2345 struct instruction *ip = t->ip;
2346
2347 __instr_hdr_emit5_tx_exec(p, t, ip);
2348
2349 /* Thread. */
2350 thread_ip_reset(p, t);
2351 instr_rx_exec(p);
2352 }
2353
2354 static inline void
instr_hdr_emit6_tx_exec(struct rte_swx_pipeline * p)2355 instr_hdr_emit6_tx_exec(struct rte_swx_pipeline *p)
2356 {
2357 struct thread *t = &p->threads[p->thread_id];
2358 struct instruction *ip = t->ip;
2359
2360 __instr_hdr_emit6_tx_exec(p, t, ip);
2361
2362 /* Thread. */
2363 thread_ip_reset(p, t);
2364 instr_rx_exec(p);
2365 }
2366
2367 static inline void
instr_hdr_emit7_tx_exec(struct rte_swx_pipeline * p)2368 instr_hdr_emit7_tx_exec(struct rte_swx_pipeline *p)
2369 {
2370 struct thread *t = &p->threads[p->thread_id];
2371 struct instruction *ip = t->ip;
2372
2373 __instr_hdr_emit7_tx_exec(p, t, ip);
2374
2375 /* Thread. */
2376 thread_ip_reset(p, t);
2377 instr_rx_exec(p);
2378 }
2379
2380 static inline void
instr_hdr_emit8_tx_exec(struct rte_swx_pipeline * p)2381 instr_hdr_emit8_tx_exec(struct rte_swx_pipeline *p)
2382 {
2383 struct thread *t = &p->threads[p->thread_id];
2384 struct instruction *ip = t->ip;
2385
2386 __instr_hdr_emit8_tx_exec(p, t, ip);
2387
2388 /* Thread. */
2389 thread_ip_reset(p, t);
2390 instr_rx_exec(p);
2391 }
2392
2393 /*
2394 * validate.
2395 */
2396 static int
instr_hdr_validate_translate(struct rte_swx_pipeline * p,struct action * action __rte_unused,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)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 CHECK(n_tokens == 2, EINVAL);
2407
2408 h = header_parse(p, tokens[1]);
2409 CHECK(h, EINVAL);
2410
2411 instr->type = INSTR_HDR_VALIDATE;
2412 instr->valid.header_id = h->id;
2413 instr->valid.struct_id = h->struct_id;
2414 return 0;
2415 }
2416
2417 static inline void
instr_hdr_validate_exec(struct rte_swx_pipeline * p)2418 instr_hdr_validate_exec(struct rte_swx_pipeline *p)
2419 {
2420 struct thread *t = &p->threads[p->thread_id];
2421 struct instruction *ip = t->ip;
2422
2423 __instr_hdr_validate_exec(p, t, ip);
2424
2425 /* Thread. */
2426 thread_ip_inc(p);
2427 }
2428
2429 /*
2430 * invalidate.
2431 */
2432 static int
instr_hdr_invalidate_translate(struct rte_swx_pipeline * p,struct action * action __rte_unused,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)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 CHECK(n_tokens == 2, EINVAL);
2443
2444 h = header_parse(p, tokens[1]);
2445 CHECK(h, EINVAL);
2446
2447 instr->type = INSTR_HDR_INVALIDATE;
2448 instr->valid.header_id = h->id;
2449 return 0;
2450 }
2451
2452 static inline void
instr_hdr_invalidate_exec(struct rte_swx_pipeline * p)2453 instr_hdr_invalidate_exec(struct rte_swx_pipeline *p)
2454 {
2455 struct thread *t = &p->threads[p->thread_id];
2456 struct instruction *ip = t->ip;
2457
2458 __instr_hdr_invalidate_exec(p, t, ip);
2459
2460 /* Thread. */
2461 thread_ip_inc(p);
2462 }
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
instr_table_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)2477 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 CHECK(!action, EINVAL);
2489 CHECK(n_tokens == 2, EINVAL);
2490
2491 t = table_find(p, tokens[1]);
2492 if (t) {
2493 instr->type = INSTR_TABLE;
2494 instr->table.table_id = t->id;
2495 return 0;
2496 }
2497
2498 s = selector_find(p, tokens[1]);
2499 if (s) {
2500 instr->type = INSTR_SELECTOR;
2501 instr->table.table_id = s->id;
2502 return 0;
2503 }
2504
2505 l = learner_find(p, tokens[1]);
2506 if (l) {
2507 instr->type = INSTR_LEARNER;
2508 instr->table.table_id = l->id;
2509 return 0;
2510 }
2511
2512 CHECK(0, EINVAL);
2513 }
2514
2515 static inline void
instr_table_exec(struct rte_swx_pipeline * p)2516 instr_table_exec(struct rte_swx_pipeline *p)
2517 {
2518 struct thread *t = &p->threads[p->thread_id];
2519 struct instruction *ip = t->ip;
2520 uint32_t table_id = ip->table.table_id;
2521 struct rte_swx_table_state *ts = &t->table_state[table_id];
2522 struct table_runtime *table = &t->tables[table_id];
2523 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 done = table->func(ts->obj,
2531 table->mailbox,
2532 table->key,
2533 &action_id,
2534 &action_data,
2535 &entry_id,
2536 &hit);
2537 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 return;
2545 }
2546
2547 action_id = hit ? action_id : ts->default_action_id;
2548 action_data = hit ? action_data : ts->default_action_data;
2549 entry_id = hit ? (1 + entry_id) : 0;
2550 n_pkts_hit = stats->n_pkts_hit[hit];
2551 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 t->action_id = action_id;
2560 t->structs[0] = action_data;
2561 t->entry_id = entry_id;
2562 t->hit = hit;
2563 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2564 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2565
2566 /* Thread. */
2567 thread_ip_action_call(p, t, action_id);
2568 }
2569
2570 static inline void
instr_table_af_exec(struct rte_swx_pipeline * p)2571 instr_table_af_exec(struct rte_swx_pipeline *p)
2572 {
2573 struct thread *t = &p->threads[p->thread_id];
2574 struct instruction *ip = t->ip;
2575 uint32_t table_id = ip->table.table_id;
2576 struct rte_swx_table_state *ts = &t->table_state[table_id];
2577 struct table_runtime *table = &t->tables[table_id];
2578 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 done = table->func(ts->obj,
2587 table->mailbox,
2588 table->key,
2589 &action_id,
2590 &action_data,
2591 &entry_id,
2592 &hit);
2593 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 return;
2601 }
2602
2603 action_id = hit ? action_id : ts->default_action_id;
2604 action_data = hit ? action_data : ts->default_action_data;
2605 entry_id = hit ? (1 + entry_id) : 0;
2606 action_func = p->action_funcs[action_id];
2607 n_pkts_hit = stats->n_pkts_hit[hit];
2608 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 t->action_id = action_id;
2617 t->structs[0] = action_data;
2618 t->entry_id = entry_id;
2619 t->hit = hit;
2620 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2621 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2622
2623 /* Thread. */
2624 thread_ip_inc(p);
2625
2626 /* Action. */
2627 action_func(p);
2628 }
2629
2630 static inline void
instr_selector_exec(struct rte_swx_pipeline * p)2631 instr_selector_exec(struct rte_swx_pipeline *p)
2632 {
2633 struct thread *t = &p->threads[p->thread_id];
2634 struct instruction *ip = t->ip;
2635 uint32_t selector_id = ip->table.table_id;
2636 struct rte_swx_table_state *ts = &t->table_state[p->n_tables + selector_id];
2637 struct selector_runtime *selector = &t->selectors[selector_id];
2638 struct selector_statistics *stats = &p->selector_stats[selector_id];
2639 uint64_t n_pkts = stats->n_pkts;
2640 int done;
2641
2642 /* Table. */
2643 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 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 return;
2656 }
2657
2658
2659 TRACE("[Thread %2u] selector %u\n",
2660 p->thread_id,
2661 selector_id);
2662
2663 stats->n_pkts = n_pkts + 1;
2664
2665 /* Thread. */
2666 thread_ip_inc(p);
2667 }
2668
2669 static inline void
instr_learner_exec(struct rte_swx_pipeline * p)2670 instr_learner_exec(struct rte_swx_pipeline *p)
2671 {
2672 struct thread *t = &p->threads[p->thread_id];
2673 struct instruction *ip = t->ip;
2674 uint32_t learner_id = ip->table.table_id;
2675 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2676 p->n_selectors + learner_id];
2677 struct learner_runtime *l = &t->learners[learner_id];
2678 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 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 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 return;
2703 }
2704
2705 action_id = hit ? action_id : ts->default_action_id;
2706 action_data = hit ? action_data : ts->default_action_data;
2707 entry_id = hit ? (1 + entry_id) : 0;
2708 n_pkts_hit = stats->n_pkts_hit[hit];
2709 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 t->action_id = action_id;
2718 t->structs[0] = action_data;
2719 t->entry_id = entry_id;
2720 t->hit = hit;
2721 t->learner_id = learner_id;
2722 t->time = time;
2723 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2724 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2725
2726 /* Thread. */
2727 thread_ip_action_call(p, t, action_id);
2728 }
2729
2730 static inline void
instr_learner_af_exec(struct rte_swx_pipeline * p)2731 instr_learner_af_exec(struct rte_swx_pipeline *p)
2732 {
2733 struct thread *t = &p->threads[p->thread_id];
2734 struct instruction *ip = t->ip;
2735 uint32_t learner_id = ip->table.table_id;
2736 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2737 p->n_selectors + learner_id];
2738 struct learner_runtime *l = &t->learners[learner_id];
2739 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 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 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 return;
2765 }
2766
2767 action_id = hit ? action_id : ts->default_action_id;
2768 action_data = hit ? action_data : ts->default_action_data;
2769 entry_id = hit ? (1 + entry_id) : 0;
2770 action_func = p->action_funcs[action_id];
2771 n_pkts_hit = stats->n_pkts_hit[hit];
2772 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 t->action_id = action_id;
2781 t->structs[0] = action_data;
2782 t->entry_id = entry_id;
2783 t->hit = hit;
2784 t->learner_id = learner_id;
2785 t->time = time;
2786 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2787 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2788
2789 /* Thread. */
2790 thread_ip_inc(p);
2791
2792 /* Action */
2793 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
instr_learn_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)2809 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 CHECK(action, EINVAL);
2821 CHECK((n_tokens == 3) || (n_tokens == 4), EINVAL);
2822
2823 /* Action. */
2824 a = action_find(p, tokens[1]);
2825 CHECK(a, EINVAL);
2826 CHECK(!action_has_nbo_args(a), EINVAL);
2827
2828 /* Action first argument. */
2829 mf_first_arg_name = (n_tokens == 4) ? tokens[2] : NULL;
2830 CHECK(!learner_action_args_check(p, a, mf_first_arg_name), EINVAL);
2831
2832 if (mf_first_arg_name) {
2833 mf_first_arg = metadata_field_parse(p, mf_first_arg_name);
2834 CHECK(mf_first_arg, EINVAL);
2835 CHECK(mf_first_arg->n_bits <= 64, EINVAL);
2836 }
2837
2838 /* Timeout ID. */
2839 mf_timeout_id_name = (n_tokens == 4) ? tokens[3] : tokens[2];
2840 CHECK_NAME(mf_timeout_id_name, EINVAL);
2841 mf_timeout_id = metadata_field_parse(p, mf_timeout_id_name);
2842 CHECK(mf_timeout_id, EINVAL);
2843 CHECK(mf_timeout_id->n_bits <= 64, EINVAL);
2844
2845 /* Instruction. */
2846 instr->type = INSTR_LEARNER_LEARN;
2847 instr->learn.action_id = a->id;
2848 instr->learn.mf_first_arg_offset = mf_first_arg ? (mf_first_arg->offset / 8) : 0;
2849 instr->learn.mf_timeout_id_offset = mf_timeout_id->offset / 8;
2850 instr->learn.mf_timeout_id_n_bits = mf_timeout_id->n_bits;
2851
2852 return 0;
2853 }
2854
2855 static inline void
instr_learn_exec(struct rte_swx_pipeline * p)2856 instr_learn_exec(struct rte_swx_pipeline *p)
2857 {
2858 struct thread *t = &p->threads[p->thread_id];
2859 struct instruction *ip = t->ip;
2860
2861 __instr_learn_exec(p, t, ip);
2862
2863 /* Thread. */
2864 thread_ip_inc(p);
2865 }
2866
2867 /*
2868 * rearm.
2869 */
2870 static int
instr_rearm_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)2871 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 CHECK(action, EINVAL);
2882 CHECK((n_tokens == 1) || (n_tokens == 2), EINVAL);
2883
2884 /* INSTR_LEARNER_REARM. */
2885 if (n_tokens == 1) {
2886 instr->type = INSTR_LEARNER_REARM;
2887 return 0;
2888 }
2889
2890 /* INSTR_LEARNER_REARM_NEW. */
2891 mf_timeout_id_name = tokens[1];
2892 CHECK_NAME(mf_timeout_id_name, EINVAL);
2893 mf_timeout_id = metadata_field_parse(p, mf_timeout_id_name);
2894 CHECK(mf_timeout_id, EINVAL);
2895 CHECK(mf_timeout_id->n_bits <= 64, EINVAL);
2896
2897 instr->type = INSTR_LEARNER_REARM_NEW;
2898 instr->learn.mf_timeout_id_offset = mf_timeout_id->offset / 8;
2899 instr->learn.mf_timeout_id_n_bits = mf_timeout_id->n_bits;
2900
2901 return 0;
2902 }
2903
2904 static inline void
instr_rearm_exec(struct rte_swx_pipeline * p)2905 instr_rearm_exec(struct rte_swx_pipeline *p)
2906 {
2907 struct thread *t = &p->threads[p->thread_id];
2908 struct instruction *ip = t->ip;
2909
2910 __instr_rearm_exec(p, t, ip);
2911
2912 /* Thread. */
2913 thread_ip_inc(p);
2914 }
2915
2916 static inline void
instr_rearm_new_exec(struct rte_swx_pipeline * p)2917 instr_rearm_new_exec(struct rte_swx_pipeline *p)
2918 {
2919 struct thread *t = &p->threads[p->thread_id];
2920 struct instruction *ip = t->ip;
2921
2922 __instr_rearm_new_exec(p, t, ip);
2923
2924 /* Thread. */
2925 thread_ip_inc(p);
2926 }
2927
2928 /*
2929 * forget.
2930 */
2931 static int
instr_forget_translate(struct rte_swx_pipeline * p __rte_unused,struct action * action,char ** tokens __rte_unused,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)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 CHECK(action, EINVAL);
2940 CHECK(n_tokens == 1, EINVAL);
2941
2942 instr->type = INSTR_LEARNER_FORGET;
2943
2944 return 0;
2945 }
2946
2947 static inline void
instr_forget_exec(struct rte_swx_pipeline * p)2948 instr_forget_exec(struct rte_swx_pipeline *p)
2949 {
2950 struct thread *t = &p->threads[p->thread_id];
2951 struct instruction *ip = t->ip;
2952
2953 __instr_forget_exec(p, t, ip);
2954
2955 /* Thread. */
2956 thread_ip_inc(p);
2957 }
2958
2959 /*
2960 * entryid.
2961 */
2962 static int
instr_entryid_translate(struct rte_swx_pipeline * p,struct action * action __rte_unused,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)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 CHECK(n_tokens == 2, EINVAL);
2973
2974 f = metadata_field_parse(p, tokens[1]);
2975 CHECK(f, EINVAL);
2976 CHECK(f->n_bits <= 64, EINVAL);
2977
2978 instr->type = INSTR_ENTRYID;
2979 instr->mov.dst.n_bits = f->n_bits;
2980 instr->mov.dst.offset = f->offset / 8;
2981 return 0;
2982 }
2983
2984 static inline void
instr_entryid_exec(struct rte_swx_pipeline * p)2985 instr_entryid_exec(struct rte_swx_pipeline *p)
2986 {
2987 struct thread *t = &p->threads[p->thread_id];
2988 struct instruction *ip = t->ip;
2989
2990 __instr_entryid_exec(p, t, ip);
2991
2992 /* Thread. */
2993 thread_ip_inc(p);
2994 }
2995
2996 /*
2997 * extern.
2998 */
2999 static int
instr_extern_translate(struct rte_swx_pipeline * p,struct action * action __rte_unused,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)3000 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 char *token = tokens[1];
3008
3009 CHECK(n_tokens == 2, EINVAL);
3010
3011 if (token[0] == 'e') {
3012 struct extern_obj *obj;
3013 struct extern_type_member_func *func;
3014
3015 func = extern_obj_member_func_parse(p, token, &obj);
3016 CHECK(func, EINVAL);
3017
3018 instr->type = INSTR_EXTERN_OBJ;
3019 instr->ext_obj.ext_obj_id = obj->id;
3020 instr->ext_obj.func_id = func->id;
3021
3022 return 0;
3023 }
3024
3025 if (token[0] == 'f') {
3026 struct extern_func *func;
3027
3028 func = extern_func_parse(p, token);
3029 CHECK(func, EINVAL);
3030
3031 instr->type = INSTR_EXTERN_FUNC;
3032 instr->ext_func.ext_func_id = func->id;
3033
3034 return 0;
3035 }
3036
3037 CHECK(0, EINVAL);
3038 }
3039
3040 static inline void
instr_extern_obj_exec(struct rte_swx_pipeline * p)3041 instr_extern_obj_exec(struct rte_swx_pipeline *p)
3042 {
3043 struct thread *t = &p->threads[p->thread_id];
3044 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 thread_yield_cond(p, done ^ 1);
3053 }
3054
3055 static inline void
instr_extern_func_exec(struct rte_swx_pipeline * p)3056 instr_extern_func_exec(struct rte_swx_pipeline *p)
3057 {
3058 struct thread *t = &p->threads[p->thread_id];
3059 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 thread_yield_cond(p, done ^ 1);
3068 }
3069
3070 /*
3071 * hash.
3072 */
3073 static int
instr_hash_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)3074 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 uint32_t src_struct_id_first = 0, src_struct_id_last = 0;
3084
3085 CHECK(n_tokens == 5, EINVAL);
3086
3087 func = hash_func_find(p, tokens[1]);
3088 CHECK(func, EINVAL);
3089
3090 dst = metadata_field_parse(p, tokens[2]);
3091 CHECK(dst, EINVAL);
3092 CHECK(dst->n_bits <= 64, EINVAL);
3093
3094 src_first = struct_field_parse(p, action, tokens[3], &src_struct_id_first);
3095 CHECK(src_first, EINVAL);
3096
3097 src_last = struct_field_parse(p, action, tokens[4], &src_struct_id_last);
3098 CHECK(src_last, EINVAL);
3099 CHECK(!src_last->var_size, EINVAL);
3100 CHECK(src_struct_id_first == src_struct_id_last, EINVAL);
3101
3102 instr->type = INSTR_HASH_FUNC;
3103 instr->hash_func.hash_func_id = (uint8_t)func->id;
3104 instr->hash_func.dst.offset = (uint8_t)dst->offset / 8;
3105 instr->hash_func.dst.n_bits = (uint8_t)dst->n_bits;
3106 instr->hash_func.src.struct_id = (uint8_t)src_struct_id_first;
3107 instr->hash_func.src.offset = (uint16_t)src_first->offset / 8;
3108 instr->hash_func.src.n_bytes = (uint16_t)((src_last->offset + src_last->n_bits -
3109 src_first->offset) / 8);
3110
3111 return 0;
3112 }
3113
3114 static inline void
instr_hash_func_exec(struct rte_swx_pipeline * p)3115 instr_hash_func_exec(struct rte_swx_pipeline *p)
3116 {
3117 struct thread *t = &p->threads[p->thread_id];
3118 struct instruction *ip = t->ip;
3119
3120 /* Extern function execute. */
3121 __instr_hash_func_exec(p, t, ip);
3122
3123 /* Thread. */
3124 thread_ip_inc(p);
3125 }
3126
3127 /*
3128 * rss.
3129 */
3130 static int
instr_rss_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)3131 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 uint32_t src_struct_id_first = 0, src_struct_id_last = 0;
3141
3142 CHECK(n_tokens == 5, EINVAL);
3143
3144 rss = rss_find(p, tokens[1]);
3145 CHECK(rss, EINVAL);
3146
3147 dst = metadata_field_parse(p, tokens[2]);
3148 CHECK(dst, EINVAL);
3149 CHECK(dst->n_bits <= 64, EINVAL);
3150
3151 src_first = struct_field_parse(p, action, tokens[3], &src_struct_id_first);
3152 CHECK(src_first, EINVAL);
3153
3154 src_last = struct_field_parse(p, action, tokens[4], &src_struct_id_last);
3155 CHECK(src_last, EINVAL);
3156 CHECK(!src_last->var_size, EINVAL);
3157 CHECK(src_struct_id_first == src_struct_id_last, EINVAL);
3158
3159 instr->type = INSTR_RSS;
3160 instr->rss.rss_obj_id = (uint8_t)rss->id;
3161 instr->rss.dst.offset = (uint8_t)dst->offset / 8;
3162 instr->rss.dst.n_bits = (uint8_t)dst->n_bits;
3163 instr->rss.src.struct_id = (uint8_t)src_struct_id_first;
3164 instr->rss.src.offset = (uint16_t)src_first->offset / 8;
3165 instr->rss.src.n_bytes = (uint16_t)((src_last->offset + src_last->n_bits -
3166 src_first->offset) / 8);
3167
3168 return 0;
3169 }
3170
3171 static inline void
instr_rss_exec(struct rte_swx_pipeline * p)3172 instr_rss_exec(struct rte_swx_pipeline *p)
3173 {
3174 struct thread *t = &p->threads[p->thread_id];
3175 struct instruction *ip = t->ip;
3176
3177 /* Extern function execute. */
3178 __instr_rss_exec(p, t, ip);
3179
3180 /* Thread. */
3181 thread_ip_inc(p);
3182 }
3183
3184 /*
3185 * mov.
3186 */
3187 static int
instr_mov_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)3188 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 char *dst = tokens[1], *src = tokens[2];
3196 struct field *fdst, *fsrc;
3197 uint64_t src_val;
3198 uint32_t dst_struct_id = 0, src_struct_id = 0;
3199
3200 CHECK(n_tokens == 3, EINVAL);
3201
3202 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3203 CHECK(fdst, EINVAL);
3204 CHECK(!fdst->var_size, EINVAL);
3205
3206 /* MOV, MOV_MH, MOV_HM, MOV_HH, MOV16, MOVDMA. */
3207 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3208 if (fsrc) {
3209 CHECK(!fsrc->var_size, EINVAL);
3210
3211 if (fdst->n_bits <= 64 && fsrc->n_bits <= 64) {
3212 instr->type = INSTR_MOV;
3213 if (dst[0] != 'h' && src[0] == 'h')
3214 instr->type = INSTR_MOV_MH;
3215 if (dst[0] == 'h' && src[0] != 'h')
3216 instr->type = INSTR_MOV_HM;
3217 if (dst[0] == 'h' && src[0] == 'h')
3218 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 CHECK(fdst->n_bits > 64 || dst[0] == 'h', EINVAL);
3231 CHECK(fsrc->n_bits > 64 || src[0] == 'h', EINVAL);
3232
3233 instr->type = INSTR_MOV_DMA;
3234 if (fdst->n_bits == 128 && fsrc->n_bits == 128)
3235 instr->type = INSTR_MOV_128;
3236
3237 if (fdst->n_bits == 128 && fsrc->n_bits == 64)
3238 instr->type = INSTR_MOV_128_64;
3239 if (fdst->n_bits == 64 && fsrc->n_bits == 128)
3240 instr->type = INSTR_MOV_64_128;
3241
3242 if (fdst->n_bits == 128 && fsrc->n_bits == 32)
3243 instr->type = INSTR_MOV_128_32;
3244 if (fdst->n_bits == 32 && fsrc->n_bits == 128)
3245 instr->type = INSTR_MOV_32_128;
3246 }
3247
3248 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
3249 instr->mov.dst.n_bits = fdst->n_bits;
3250 instr->mov.dst.offset = fdst->offset / 8;
3251 instr->mov.src.struct_id = (uint8_t)src_struct_id;
3252 instr->mov.src.n_bits = fsrc->n_bits;
3253 instr->mov.src.offset = fsrc->offset / 8;
3254 return 0;
3255 }
3256
3257 /* MOV_I. */
3258 CHECK(fdst->n_bits <= 64, EINVAL);
3259 src_val = strtoull(src, &src, 0);
3260 CHECK(!src[0], EINVAL);
3261
3262 if (dst[0] == 'h')
3263 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3264
3265 instr->type = INSTR_MOV_I;
3266 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
3267 instr->mov.dst.n_bits = fdst->n_bits;
3268 instr->mov.dst.offset = fdst->offset / 8;
3269 instr->mov.src_val = src_val;
3270 return 0;
3271 }
3272
3273 static inline void
instr_mov_exec(struct rte_swx_pipeline * p)3274 instr_mov_exec(struct rte_swx_pipeline *p)
3275 {
3276 struct thread *t = &p->threads[p->thread_id];
3277 struct instruction *ip = t->ip;
3278
3279 __instr_mov_exec(p, t, ip);
3280
3281 /* Thread. */
3282 thread_ip_inc(p);
3283 }
3284
3285 static inline void
instr_mov_mh_exec(struct rte_swx_pipeline * p)3286 instr_mov_mh_exec(struct rte_swx_pipeline *p)
3287 {
3288 struct thread *t = &p->threads[p->thread_id];
3289 struct instruction *ip = t->ip;
3290
3291 __instr_mov_mh_exec(p, t, ip);
3292
3293 /* Thread. */
3294 thread_ip_inc(p);
3295 }
3296
3297 static inline void
instr_mov_hm_exec(struct rte_swx_pipeline * p)3298 instr_mov_hm_exec(struct rte_swx_pipeline *p)
3299 {
3300 struct thread *t = &p->threads[p->thread_id];
3301 struct instruction *ip = t->ip;
3302
3303 __instr_mov_hm_exec(p, t, ip);
3304
3305 /* Thread. */
3306 thread_ip_inc(p);
3307 }
3308
3309 static inline void
instr_mov_hh_exec(struct rte_swx_pipeline * p)3310 instr_mov_hh_exec(struct rte_swx_pipeline *p)
3311 {
3312 struct thread *t = &p->threads[p->thread_id];
3313 struct instruction *ip = t->ip;
3314
3315 __instr_mov_hh_exec(p, t, ip);
3316
3317 /* Thread. */
3318 thread_ip_inc(p);
3319 }
3320
3321 static inline void
instr_mov_dma_exec(struct rte_swx_pipeline * p)3322 instr_mov_dma_exec(struct rte_swx_pipeline *p)
3323 {
3324 struct thread *t = &p->threads[p->thread_id];
3325 struct instruction *ip = t->ip;
3326
3327 __instr_mov_dma_exec(p, t, ip);
3328
3329 /* Thread. */
3330 thread_ip_inc(p);
3331 }
3332
3333 static inline void
instr_mov_128_exec(struct rte_swx_pipeline * p)3334 instr_mov_128_exec(struct rte_swx_pipeline *p)
3335 {
3336 struct thread *t = &p->threads[p->thread_id];
3337 struct instruction *ip = t->ip;
3338
3339 __instr_mov_128_exec(p, t, ip);
3340
3341 /* Thread. */
3342 thread_ip_inc(p);
3343 }
3344
3345 static inline void
instr_mov_128_64_exec(struct rte_swx_pipeline * p)3346 instr_mov_128_64_exec(struct rte_swx_pipeline *p)
3347 {
3348 struct thread *t = &p->threads[p->thread_id];
3349 struct instruction *ip = t->ip;
3350
3351 __instr_mov_128_64_exec(p, t, ip);
3352
3353 /* Thread. */
3354 thread_ip_inc(p);
3355 }
3356
3357 static inline void
instr_mov_64_128_exec(struct rte_swx_pipeline * p)3358 instr_mov_64_128_exec(struct rte_swx_pipeline *p)
3359 {
3360 struct thread *t = &p->threads[p->thread_id];
3361 struct instruction *ip = t->ip;
3362
3363 __instr_mov_64_128_exec(p, t, ip);
3364
3365 /* Thread. */
3366 thread_ip_inc(p);
3367 }
3368
3369 static inline void
instr_mov_128_32_exec(struct rte_swx_pipeline * p)3370 instr_mov_128_32_exec(struct rte_swx_pipeline *p)
3371 {
3372 struct thread *t = &p->threads[p->thread_id];
3373 struct instruction *ip = t->ip;
3374
3375 __instr_mov_128_32_exec(p, t, ip);
3376
3377 /* Thread. */
3378 thread_ip_inc(p);
3379 }
3380
3381 static inline void
instr_mov_32_128_exec(struct rte_swx_pipeline * p)3382 instr_mov_32_128_exec(struct rte_swx_pipeline *p)
3383 {
3384 struct thread *t = &p->threads[p->thread_id];
3385 struct instruction *ip = t->ip;
3386
3387 __instr_mov_32_128_exec(p, t, ip);
3388
3389 /* Thread. */
3390 thread_ip_inc(p);
3391 }
3392
3393 static inline void
instr_mov_i_exec(struct rte_swx_pipeline * p)3394 instr_mov_i_exec(struct rte_swx_pipeline *p)
3395 {
3396 struct thread *t = &p->threads[p->thread_id];
3397 struct instruction *ip = t->ip;
3398
3399 __instr_mov_i_exec(p, t, ip);
3400
3401 /* Thread. */
3402 thread_ip_inc(p);
3403 }
3404
3405 /*
3406 * movh.
3407 */
3408 static int
instr_movh_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)3409 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 char *dst = tokens[1], *src = tokens[2];
3417 struct field *fdst, *fsrc;
3418 uint32_t dst_struct_id = 0, src_struct_id = 0;
3419
3420 CHECK(n_tokens == 3, EINVAL);
3421
3422 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3423 CHECK(fdst, EINVAL);
3424 CHECK(!fdst->var_size, EINVAL);
3425
3426 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3427 CHECK(fsrc, EINVAL);
3428 CHECK(!fsrc->var_size, EINVAL);
3429
3430 /* MOVH_64_128, MOVH_128_64. */
3431 if ((dst[0] == 'h' && fdst->n_bits == 64 && fsrc->n_bits == 128) ||
3432 (fdst->n_bits == 128 && src[0] == 'h' && fsrc->n_bits == 64)) {
3433 instr->type = INSTR_MOVH;
3434
3435 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
3436 instr->mov.dst.n_bits = fdst->n_bits;
3437 instr->mov.dst.offset = fdst->offset / 8;
3438
3439 instr->mov.src.struct_id = (uint8_t)src_struct_id;
3440 instr->mov.src.n_bits = fsrc->n_bits;
3441 instr->mov.src.offset = fsrc->offset / 8;
3442 return 0;
3443 }
3444
3445 CHECK(0, EINVAL);
3446 }
3447
3448 static inline void
instr_movh_exec(struct rte_swx_pipeline * p)3449 instr_movh_exec(struct rte_swx_pipeline *p)
3450 {
3451 struct thread *t = &p->threads[p->thread_id];
3452 struct instruction *ip = t->ip;
3453
3454 __instr_movh_exec(p, t, ip);
3455
3456 /* Thread. */
3457 thread_ip_inc(p);
3458 }
3459
3460 /*
3461 * dma.
3462 */
3463 static inline void
instr_dma_ht_exec(struct rte_swx_pipeline * p)3464 instr_dma_ht_exec(struct rte_swx_pipeline *p)
3465 {
3466 struct thread *t = &p->threads[p->thread_id];
3467 struct instruction *ip = t->ip;
3468
3469 __instr_dma_ht_exec(p, t, ip);
3470
3471 /* Thread. */
3472 thread_ip_inc(p);
3473 }
3474
3475 static inline void
instr_dma_ht2_exec(struct rte_swx_pipeline * p)3476 instr_dma_ht2_exec(struct rte_swx_pipeline *p)
3477 {
3478 struct thread *t = &p->threads[p->thread_id];
3479 struct instruction *ip = t->ip;
3480
3481 __instr_dma_ht2_exec(p, t, ip);
3482
3483 /* Thread. */
3484 thread_ip_inc(p);
3485 }
3486
3487 static inline void
instr_dma_ht3_exec(struct rte_swx_pipeline * p)3488 instr_dma_ht3_exec(struct rte_swx_pipeline *p)
3489 {
3490 struct thread *t = &p->threads[p->thread_id];
3491 struct instruction *ip = t->ip;
3492
3493 __instr_dma_ht3_exec(p, t, ip);
3494
3495 /* Thread. */
3496 thread_ip_inc(p);
3497 }
3498
3499 static inline void
instr_dma_ht4_exec(struct rte_swx_pipeline * p)3500 instr_dma_ht4_exec(struct rte_swx_pipeline *p)
3501 {
3502 struct thread *t = &p->threads[p->thread_id];
3503 struct instruction *ip = t->ip;
3504
3505 __instr_dma_ht4_exec(p, t, ip);
3506
3507 /* Thread. */
3508 thread_ip_inc(p);
3509 }
3510
3511 static inline void
instr_dma_ht5_exec(struct rte_swx_pipeline * p)3512 instr_dma_ht5_exec(struct rte_swx_pipeline *p)
3513 {
3514 struct thread *t = &p->threads[p->thread_id];
3515 struct instruction *ip = t->ip;
3516
3517 __instr_dma_ht5_exec(p, t, ip);
3518
3519 /* Thread. */
3520 thread_ip_inc(p);
3521 }
3522
3523 static inline void
instr_dma_ht6_exec(struct rte_swx_pipeline * p)3524 instr_dma_ht6_exec(struct rte_swx_pipeline *p)
3525 {
3526 struct thread *t = &p->threads[p->thread_id];
3527 struct instruction *ip = t->ip;
3528
3529 __instr_dma_ht6_exec(p, t, ip);
3530
3531 /* Thread. */
3532 thread_ip_inc(p);
3533 }
3534
3535 static inline void
instr_dma_ht7_exec(struct rte_swx_pipeline * p)3536 instr_dma_ht7_exec(struct rte_swx_pipeline *p)
3537 {
3538 struct thread *t = &p->threads[p->thread_id];
3539 struct instruction *ip = t->ip;
3540
3541 __instr_dma_ht7_exec(p, t, ip);
3542
3543 /* Thread. */
3544 thread_ip_inc(p);
3545 }
3546
3547 static inline void
instr_dma_ht8_exec(struct rte_swx_pipeline * p)3548 instr_dma_ht8_exec(struct rte_swx_pipeline *p)
3549 {
3550 struct thread *t = &p->threads[p->thread_id];
3551 struct instruction *ip = t->ip;
3552
3553 __instr_dma_ht8_exec(p, t, ip);
3554
3555 /* Thread. */
3556 thread_ip_inc(p);
3557 }
3558
3559 /*
3560 * alu.
3561 */
3562 static int
instr_alu_add_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)3563 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 char *dst = tokens[1], *src = tokens[2];
3571 struct field *fdst, *fsrc;
3572 uint64_t src_val;
3573 uint32_t dst_struct_id = 0, src_struct_id = 0;
3574
3575 CHECK(n_tokens == 3, EINVAL);
3576
3577 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3578 CHECK(fdst, EINVAL);
3579 CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
3580
3581 /* ADD, ADD_HM, ADD_MH, ADD_HH. */
3582 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3583 if (fsrc) {
3584 CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
3585
3586 instr->type = INSTR_ALU_ADD;
3587 if (dst[0] == 'h' && src[0] != 'h')
3588 instr->type = INSTR_ALU_ADD_HM;
3589 if (dst[0] != 'h' && src[0] == 'h')
3590 instr->type = INSTR_ALU_ADD_MH;
3591 if (dst[0] == 'h' && src[0] == 'h')
3592 instr->type = INSTR_ALU_ADD_HH;
3593
3594 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3595 instr->alu.dst.n_bits = fdst->n_bits;
3596 instr->alu.dst.offset = fdst->offset / 8;
3597 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3598 instr->alu.src.n_bits = fsrc->n_bits;
3599 instr->alu.src.offset = fsrc->offset / 8;
3600 return 0;
3601 }
3602
3603 /* ADD_MI, ADD_HI. */
3604 src_val = strtoull(src, &src, 0);
3605 CHECK(!src[0], EINVAL);
3606
3607 instr->type = INSTR_ALU_ADD_MI;
3608 if (dst[0] == 'h')
3609 instr->type = INSTR_ALU_ADD_HI;
3610
3611 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3612 instr->alu.dst.n_bits = fdst->n_bits;
3613 instr->alu.dst.offset = fdst->offset / 8;
3614 instr->alu.src_val = src_val;
3615 return 0;
3616 }
3617
3618 static int
instr_alu_sub_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)3619 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 char *dst = tokens[1], *src = tokens[2];
3627 struct field *fdst, *fsrc;
3628 uint64_t src_val;
3629 uint32_t dst_struct_id = 0, src_struct_id = 0;
3630
3631 CHECK(n_tokens == 3, EINVAL);
3632
3633 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3634 CHECK(fdst, EINVAL);
3635 CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
3636
3637 /* SUB, SUB_HM, SUB_MH, SUB_HH. */
3638 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3639 if (fsrc) {
3640 CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
3641
3642 instr->type = INSTR_ALU_SUB;
3643 if (dst[0] == 'h' && src[0] != 'h')
3644 instr->type = INSTR_ALU_SUB_HM;
3645 if (dst[0] != 'h' && src[0] == 'h')
3646 instr->type = INSTR_ALU_SUB_MH;
3647 if (dst[0] == 'h' && src[0] == 'h')
3648 instr->type = INSTR_ALU_SUB_HH;
3649
3650 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3651 instr->alu.dst.n_bits = fdst->n_bits;
3652 instr->alu.dst.offset = fdst->offset / 8;
3653 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3654 instr->alu.src.n_bits = fsrc->n_bits;
3655 instr->alu.src.offset = fsrc->offset / 8;
3656 return 0;
3657 }
3658
3659 /* SUB_MI, SUB_HI. */
3660 src_val = strtoull(src, &src, 0);
3661 CHECK(!src[0], EINVAL);
3662
3663 instr->type = INSTR_ALU_SUB_MI;
3664 if (dst[0] == 'h')
3665 instr->type = INSTR_ALU_SUB_HI;
3666
3667 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3668 instr->alu.dst.n_bits = fdst->n_bits;
3669 instr->alu.dst.offset = fdst->offset / 8;
3670 instr->alu.src_val = src_val;
3671 return 0;
3672 }
3673
3674 static int
instr_alu_ckadd_translate(struct rte_swx_pipeline * p,struct action * action __rte_unused,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)3675 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 char *dst = tokens[1], *src = tokens[2];
3683 struct header *hdst, *hsrc;
3684 struct field *fdst, *fsrc;
3685
3686 CHECK(n_tokens == 3, EINVAL);
3687
3688 fdst = header_field_parse(p, dst, &hdst);
3689 CHECK(fdst, EINVAL);
3690 CHECK(!fdst->var_size && (fdst->n_bits == 16), EINVAL);
3691
3692 /* CKADD_FIELD. */
3693 fsrc = header_field_parse(p, src, &hsrc);
3694 if (fsrc) {
3695 CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
3696
3697 instr->type = INSTR_ALU_CKADD_FIELD;
3698 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
3699 instr->alu.dst.n_bits = fdst->n_bits;
3700 instr->alu.dst.offset = fdst->offset / 8;
3701 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
3702 instr->alu.src.n_bits = fsrc->n_bits;
3703 instr->alu.src.offset = fsrc->offset / 8;
3704 return 0;
3705 }
3706
3707 /* CKADD_STRUCT, CKADD_STRUCT20. */
3708 hsrc = header_parse(p, src);
3709 CHECK(hsrc, EINVAL);
3710
3711 instr->type = INSTR_ALU_CKADD_STRUCT;
3712 if (!hsrc->st->var_size && ((hsrc->st->n_bits / 8) == 20))
3713 instr->type = INSTR_ALU_CKADD_STRUCT20;
3714
3715 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
3716 instr->alu.dst.n_bits = fdst->n_bits;
3717 instr->alu.dst.offset = fdst->offset / 8;
3718 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
3719 instr->alu.src.n_bits = (uint8_t)hsrc->id; /* The src header ID is stored here. */
3720 instr->alu.src.offset = 0; /* Unused. */
3721 return 0;
3722 }
3723
3724 static int
instr_alu_cksub_translate(struct rte_swx_pipeline * p,struct action * action __rte_unused,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)3725 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 char *dst = tokens[1], *src = tokens[2];
3733 struct header *hdst, *hsrc;
3734 struct field *fdst, *fsrc;
3735
3736 CHECK(n_tokens == 3, EINVAL);
3737
3738 fdst = header_field_parse(p, dst, &hdst);
3739 CHECK(fdst, EINVAL);
3740 CHECK(!fdst->var_size && (fdst->n_bits == 16), EINVAL);
3741
3742 fsrc = header_field_parse(p, src, &hsrc);
3743 CHECK(fsrc, EINVAL);
3744 CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
3745
3746 instr->type = INSTR_ALU_CKSUB_FIELD;
3747 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
3748 instr->alu.dst.n_bits = fdst->n_bits;
3749 instr->alu.dst.offset = fdst->offset / 8;
3750 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
3751 instr->alu.src.n_bits = fsrc->n_bits;
3752 instr->alu.src.offset = fsrc->offset / 8;
3753 return 0;
3754 }
3755
3756 static int
instr_alu_shl_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)3757 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 char *dst = tokens[1], *src = tokens[2];
3765 struct field *fdst, *fsrc;
3766 uint64_t src_val;
3767 uint32_t dst_struct_id = 0, src_struct_id = 0;
3768
3769 CHECK(n_tokens == 3, EINVAL);
3770
3771 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3772 CHECK(fdst, EINVAL);
3773 CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
3774
3775 /* SHL, SHL_HM, SHL_MH, SHL_HH. */
3776 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3777 if (fsrc) {
3778 CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
3779
3780 instr->type = INSTR_ALU_SHL;
3781 if (dst[0] == 'h' && src[0] != 'h')
3782 instr->type = INSTR_ALU_SHL_HM;
3783 if (dst[0] != 'h' && src[0] == 'h')
3784 instr->type = INSTR_ALU_SHL_MH;
3785 if (dst[0] == 'h' && src[0] == 'h')
3786 instr->type = INSTR_ALU_SHL_HH;
3787
3788 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3789 instr->alu.dst.n_bits = fdst->n_bits;
3790 instr->alu.dst.offset = fdst->offset / 8;
3791 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3792 instr->alu.src.n_bits = fsrc->n_bits;
3793 instr->alu.src.offset = fsrc->offset / 8;
3794 return 0;
3795 }
3796
3797 /* SHL_MI, SHL_HI. */
3798 src_val = strtoull(src, &src, 0);
3799 CHECK(!src[0], EINVAL);
3800
3801 instr->type = INSTR_ALU_SHL_MI;
3802 if (dst[0] == 'h')
3803 instr->type = INSTR_ALU_SHL_HI;
3804
3805 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3806 instr->alu.dst.n_bits = fdst->n_bits;
3807 instr->alu.dst.offset = fdst->offset / 8;
3808 instr->alu.src_val = src_val;
3809 return 0;
3810 }
3811
3812 static int
instr_alu_shr_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)3813 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 char *dst = tokens[1], *src = tokens[2];
3821 struct field *fdst, *fsrc;
3822 uint64_t src_val;
3823 uint32_t dst_struct_id = 0, src_struct_id = 0;
3824
3825 CHECK(n_tokens == 3, EINVAL);
3826
3827 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3828 CHECK(fdst, EINVAL);
3829 CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
3830
3831 /* SHR, SHR_HM, SHR_MH, SHR_HH. */
3832 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3833 if (fsrc) {
3834 CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
3835
3836 instr->type = INSTR_ALU_SHR;
3837 if (dst[0] == 'h' && src[0] != 'h')
3838 instr->type = INSTR_ALU_SHR_HM;
3839 if (dst[0] != 'h' && src[0] == 'h')
3840 instr->type = INSTR_ALU_SHR_MH;
3841 if (dst[0] == 'h' && src[0] == 'h')
3842 instr->type = INSTR_ALU_SHR_HH;
3843
3844 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3845 instr->alu.dst.n_bits = fdst->n_bits;
3846 instr->alu.dst.offset = fdst->offset / 8;
3847 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3848 instr->alu.src.n_bits = fsrc->n_bits;
3849 instr->alu.src.offset = fsrc->offset / 8;
3850 return 0;
3851 }
3852
3853 /* SHR_MI, SHR_HI. */
3854 src_val = strtoull(src, &src, 0);
3855 CHECK(!src[0], EINVAL);
3856
3857 instr->type = INSTR_ALU_SHR_MI;
3858 if (dst[0] == 'h')
3859 instr->type = INSTR_ALU_SHR_HI;
3860
3861 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3862 instr->alu.dst.n_bits = fdst->n_bits;
3863 instr->alu.dst.offset = fdst->offset / 8;
3864 instr->alu.src_val = src_val;
3865 return 0;
3866 }
3867
3868 static int
instr_alu_and_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)3869 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 char *dst = tokens[1], *src = tokens[2];
3877 struct field *fdst, *fsrc;
3878 uint64_t src_val;
3879 uint32_t dst_struct_id = 0, src_struct_id = 0;
3880
3881 CHECK(n_tokens == 3, EINVAL);
3882
3883 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3884 CHECK(fdst, EINVAL);
3885 CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
3886
3887 /* AND, AND_MH, AND_HM, AND_HH. */
3888 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3889 if (fsrc) {
3890 CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
3891
3892 instr->type = INSTR_ALU_AND;
3893 if (dst[0] != 'h' && src[0] == 'h')
3894 instr->type = INSTR_ALU_AND_MH;
3895 if (dst[0] == 'h' && src[0] != 'h')
3896 instr->type = INSTR_ALU_AND_HM;
3897 if (dst[0] == 'h' && src[0] == 'h')
3898 instr->type = INSTR_ALU_AND_HH;
3899
3900 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3901 instr->alu.dst.n_bits = fdst->n_bits;
3902 instr->alu.dst.offset = fdst->offset / 8;
3903 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3904 instr->alu.src.n_bits = fsrc->n_bits;
3905 instr->alu.src.offset = fsrc->offset / 8;
3906 return 0;
3907 }
3908
3909 /* AND_I. */
3910 src_val = strtoull(src, &src, 0);
3911 CHECK(!src[0], EINVAL);
3912
3913 if (dst[0] == 'h')
3914 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3915
3916 instr->type = INSTR_ALU_AND_I;
3917 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3918 instr->alu.dst.n_bits = fdst->n_bits;
3919 instr->alu.dst.offset = fdst->offset / 8;
3920 instr->alu.src_val = src_val;
3921 return 0;
3922 }
3923
3924 static int
instr_alu_or_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)3925 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 char *dst = tokens[1], *src = tokens[2];
3933 struct field *fdst, *fsrc;
3934 uint64_t src_val;
3935 uint32_t dst_struct_id = 0, src_struct_id = 0;
3936
3937 CHECK(n_tokens == 3, EINVAL);
3938
3939 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3940 CHECK(fdst, EINVAL);
3941 CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
3942
3943 /* OR, OR_MH, OR_HM, OR_HH. */
3944 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3945 if (fsrc) {
3946 CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
3947
3948 instr->type = INSTR_ALU_OR;
3949 if (dst[0] != 'h' && src[0] == 'h')
3950 instr->type = INSTR_ALU_OR_MH;
3951 if (dst[0] == 'h' && src[0] != 'h')
3952 instr->type = INSTR_ALU_OR_HM;
3953 if (dst[0] == 'h' && src[0] == 'h')
3954 instr->type = INSTR_ALU_OR_HH;
3955
3956 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3957 instr->alu.dst.n_bits = fdst->n_bits;
3958 instr->alu.dst.offset = fdst->offset / 8;
3959 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3960 instr->alu.src.n_bits = fsrc->n_bits;
3961 instr->alu.src.offset = fsrc->offset / 8;
3962 return 0;
3963 }
3964
3965 /* OR_I. */
3966 src_val = strtoull(src, &src, 0);
3967 CHECK(!src[0], EINVAL);
3968
3969 if (dst[0] == 'h')
3970 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3971
3972 instr->type = INSTR_ALU_OR_I;
3973 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3974 instr->alu.dst.n_bits = fdst->n_bits;
3975 instr->alu.dst.offset = fdst->offset / 8;
3976 instr->alu.src_val = src_val;
3977 return 0;
3978 }
3979
3980 static int
instr_alu_xor_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)3981 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 char *dst = tokens[1], *src = tokens[2];
3989 struct field *fdst, *fsrc;
3990 uint64_t src_val;
3991 uint32_t dst_struct_id = 0, src_struct_id = 0;
3992
3993 CHECK(n_tokens == 3, EINVAL);
3994
3995 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3996 CHECK(fdst, EINVAL);
3997 CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
3998
3999 /* XOR, XOR_MH, XOR_HM, XOR_HH. */
4000 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4001 if (fsrc) {
4002 CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
4003
4004 instr->type = INSTR_ALU_XOR;
4005 if (dst[0] != 'h' && src[0] == 'h')
4006 instr->type = INSTR_ALU_XOR_MH;
4007 if (dst[0] == 'h' && src[0] != 'h')
4008 instr->type = INSTR_ALU_XOR_HM;
4009 if (dst[0] == 'h' && src[0] == 'h')
4010 instr->type = INSTR_ALU_XOR_HH;
4011
4012 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4013 instr->alu.dst.n_bits = fdst->n_bits;
4014 instr->alu.dst.offset = fdst->offset / 8;
4015 instr->alu.src.struct_id = (uint8_t)src_struct_id;
4016 instr->alu.src.n_bits = fsrc->n_bits;
4017 instr->alu.src.offset = fsrc->offset / 8;
4018 return 0;
4019 }
4020
4021 /* XOR_I. */
4022 src_val = strtoull(src, &src, 0);
4023 CHECK(!src[0], EINVAL);
4024
4025 if (dst[0] == 'h')
4026 src_val = hton64(src_val) >> (64 - fdst->n_bits);
4027
4028 instr->type = INSTR_ALU_XOR_I;
4029 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4030 instr->alu.dst.n_bits = fdst->n_bits;
4031 instr->alu.dst.offset = fdst->offset / 8;
4032 instr->alu.src_val = src_val;
4033 return 0;
4034 }
4035
4036 static inline void
instr_alu_add_exec(struct rte_swx_pipeline * p)4037 instr_alu_add_exec(struct rte_swx_pipeline *p)
4038 {
4039 struct thread *t = &p->threads[p->thread_id];
4040 struct instruction *ip = t->ip;
4041
4042 /* Structs */
4043 __instr_alu_add_exec(p, t, ip);
4044
4045 /* Thread. */
4046 thread_ip_inc(p);
4047 }
4048
4049 static inline void
instr_alu_add_mh_exec(struct rte_swx_pipeline * p)4050 instr_alu_add_mh_exec(struct rte_swx_pipeline *p)
4051 {
4052 struct thread *t = &p->threads[p->thread_id];
4053 struct instruction *ip = t->ip;
4054
4055 /* Structs. */
4056 __instr_alu_add_mh_exec(p, t, ip);
4057
4058 /* Thread. */
4059 thread_ip_inc(p);
4060 }
4061
4062 static inline void
instr_alu_add_hm_exec(struct rte_swx_pipeline * p)4063 instr_alu_add_hm_exec(struct rte_swx_pipeline *p)
4064 {
4065 struct thread *t = &p->threads[p->thread_id];
4066 struct instruction *ip = t->ip;
4067
4068 /* Structs. */
4069 __instr_alu_add_hm_exec(p, t, ip);
4070
4071 /* Thread. */
4072 thread_ip_inc(p);
4073 }
4074
4075 static inline void
instr_alu_add_hh_exec(struct rte_swx_pipeline * p)4076 instr_alu_add_hh_exec(struct rte_swx_pipeline *p)
4077 {
4078 struct thread *t = &p->threads[p->thread_id];
4079 struct instruction *ip = t->ip;
4080
4081 /* Structs. */
4082 __instr_alu_add_hh_exec(p, t, ip);
4083
4084 /* Thread. */
4085 thread_ip_inc(p);
4086 }
4087
4088 static inline void
instr_alu_add_mi_exec(struct rte_swx_pipeline * p)4089 instr_alu_add_mi_exec(struct rte_swx_pipeline *p)
4090 {
4091 struct thread *t = &p->threads[p->thread_id];
4092 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 }
4100
4101 static inline void
instr_alu_add_hi_exec(struct rte_swx_pipeline * p)4102 instr_alu_add_hi_exec(struct rte_swx_pipeline *p)
4103 {
4104 struct thread *t = &p->threads[p->thread_id];
4105 struct instruction *ip = t->ip;
4106
4107 /* Structs. */
4108 __instr_alu_add_hi_exec(p, t, ip);
4109
4110 /* Thread. */
4111 thread_ip_inc(p);
4112 }
4113
4114 static inline void
instr_alu_sub_exec(struct rte_swx_pipeline * p)4115 instr_alu_sub_exec(struct rte_swx_pipeline *p)
4116 {
4117 struct thread *t = &p->threads[p->thread_id];
4118 struct instruction *ip = t->ip;
4119
4120 /* Structs. */
4121 __instr_alu_sub_exec(p, t, ip);
4122
4123 /* Thread. */
4124 thread_ip_inc(p);
4125 }
4126
4127 static inline void
instr_alu_sub_mh_exec(struct rte_swx_pipeline * p)4128 instr_alu_sub_mh_exec(struct rte_swx_pipeline *p)
4129 {
4130 struct thread *t = &p->threads[p->thread_id];
4131 struct instruction *ip = t->ip;
4132
4133 /* Structs. */
4134 __instr_alu_sub_mh_exec(p, t, ip);
4135
4136 /* Thread. */
4137 thread_ip_inc(p);
4138 }
4139
4140 static inline void
instr_alu_sub_hm_exec(struct rte_swx_pipeline * p)4141 instr_alu_sub_hm_exec(struct rte_swx_pipeline *p)
4142 {
4143 struct thread *t = &p->threads[p->thread_id];
4144 struct instruction *ip = t->ip;
4145
4146 /* Structs. */
4147 __instr_alu_sub_hm_exec(p, t, ip);
4148
4149 /* Thread. */
4150 thread_ip_inc(p);
4151 }
4152
4153 static inline void
instr_alu_sub_hh_exec(struct rte_swx_pipeline * p)4154 instr_alu_sub_hh_exec(struct rte_swx_pipeline *p)
4155 {
4156 struct thread *t = &p->threads[p->thread_id];
4157 struct instruction *ip = t->ip;
4158
4159 /* Structs. */
4160 __instr_alu_sub_hh_exec(p, t, ip);
4161
4162 /* Thread. */
4163 thread_ip_inc(p);
4164 }
4165
4166 static inline void
instr_alu_sub_mi_exec(struct rte_swx_pipeline * p)4167 instr_alu_sub_mi_exec(struct rte_swx_pipeline *p)
4168 {
4169 struct thread *t = &p->threads[p->thread_id];
4170 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 }
4178
4179 static inline void
instr_alu_sub_hi_exec(struct rte_swx_pipeline * p)4180 instr_alu_sub_hi_exec(struct rte_swx_pipeline *p)
4181 {
4182 struct thread *t = &p->threads[p->thread_id];
4183 struct instruction *ip = t->ip;
4184
4185 /* Structs. */
4186 __instr_alu_sub_hi_exec(p, t, ip);
4187
4188 /* Thread. */
4189 thread_ip_inc(p);
4190 }
4191
4192 static inline void
instr_alu_shl_exec(struct rte_swx_pipeline * p)4193 instr_alu_shl_exec(struct rte_swx_pipeline *p)
4194 {
4195 struct thread *t = &p->threads[p->thread_id];
4196 struct instruction *ip = t->ip;
4197
4198 /* Structs. */
4199 __instr_alu_shl_exec(p, t, ip);
4200
4201 /* Thread. */
4202 thread_ip_inc(p);
4203 }
4204
4205 static inline void
instr_alu_shl_mh_exec(struct rte_swx_pipeline * p)4206 instr_alu_shl_mh_exec(struct rte_swx_pipeline *p)
4207 {
4208 struct thread *t = &p->threads[p->thread_id];
4209 struct instruction *ip = t->ip;
4210
4211 /* Structs. */
4212 __instr_alu_shl_mh_exec(p, t, ip);
4213
4214 /* Thread. */
4215 thread_ip_inc(p);
4216 }
4217
4218 static inline void
instr_alu_shl_hm_exec(struct rte_swx_pipeline * p)4219 instr_alu_shl_hm_exec(struct rte_swx_pipeline *p)
4220 {
4221 struct thread *t = &p->threads[p->thread_id];
4222 struct instruction *ip = t->ip;
4223
4224 /* Structs. */
4225 __instr_alu_shl_hm_exec(p, t, ip);
4226
4227 /* Thread. */
4228 thread_ip_inc(p);
4229 }
4230
4231 static inline void
instr_alu_shl_hh_exec(struct rte_swx_pipeline * p)4232 instr_alu_shl_hh_exec(struct rte_swx_pipeline *p)
4233 {
4234 struct thread *t = &p->threads[p->thread_id];
4235 struct instruction *ip = t->ip;
4236
4237 /* Structs. */
4238 __instr_alu_shl_hh_exec(p, t, ip);
4239
4240 /* Thread. */
4241 thread_ip_inc(p);
4242 }
4243
4244 static inline void
instr_alu_shl_mi_exec(struct rte_swx_pipeline * p)4245 instr_alu_shl_mi_exec(struct rte_swx_pipeline *p)
4246 {
4247 struct thread *t = &p->threads[p->thread_id];
4248 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 }
4256
4257 static inline void
instr_alu_shl_hi_exec(struct rte_swx_pipeline * p)4258 instr_alu_shl_hi_exec(struct rte_swx_pipeline *p)
4259 {
4260 struct thread *t = &p->threads[p->thread_id];
4261 struct instruction *ip = t->ip;
4262
4263 /* Structs. */
4264 __instr_alu_shl_hi_exec(p, t, ip);
4265
4266 /* Thread. */
4267 thread_ip_inc(p);
4268 }
4269
4270 static inline void
instr_alu_shr_exec(struct rte_swx_pipeline * p)4271 instr_alu_shr_exec(struct rte_swx_pipeline *p)
4272 {
4273 struct thread *t = &p->threads[p->thread_id];
4274 struct instruction *ip = t->ip;
4275
4276 /* Structs. */
4277 __instr_alu_shr_exec(p, t, ip);
4278
4279 /* Thread. */
4280 thread_ip_inc(p);
4281 }
4282
4283 static inline void
instr_alu_shr_mh_exec(struct rte_swx_pipeline * p)4284 instr_alu_shr_mh_exec(struct rte_swx_pipeline *p)
4285 {
4286 struct thread *t = &p->threads[p->thread_id];
4287 struct instruction *ip = t->ip;
4288
4289 /* Structs. */
4290 __instr_alu_shr_mh_exec(p, t, ip);
4291
4292 /* Thread. */
4293 thread_ip_inc(p);
4294 }
4295
4296 static inline void
instr_alu_shr_hm_exec(struct rte_swx_pipeline * p)4297 instr_alu_shr_hm_exec(struct rte_swx_pipeline *p)
4298 {
4299 struct thread *t = &p->threads[p->thread_id];
4300 struct instruction *ip = t->ip;
4301
4302 /* Structs. */
4303 __instr_alu_shr_hm_exec(p, t, ip);
4304
4305 /* Thread. */
4306 thread_ip_inc(p);
4307 }
4308
4309 static inline void
instr_alu_shr_hh_exec(struct rte_swx_pipeline * p)4310 instr_alu_shr_hh_exec(struct rte_swx_pipeline *p)
4311 {
4312 struct thread *t = &p->threads[p->thread_id];
4313 struct instruction *ip = t->ip;
4314
4315 /* Structs. */
4316 __instr_alu_shr_hh_exec(p, t, ip);
4317
4318 /* Thread. */
4319 thread_ip_inc(p);
4320 }
4321
4322 static inline void
instr_alu_shr_mi_exec(struct rte_swx_pipeline * p)4323 instr_alu_shr_mi_exec(struct rte_swx_pipeline *p)
4324 {
4325 struct thread *t = &p->threads[p->thread_id];
4326 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 }
4334
4335 static inline void
instr_alu_shr_hi_exec(struct rte_swx_pipeline * p)4336 instr_alu_shr_hi_exec(struct rte_swx_pipeline *p)
4337 {
4338 struct thread *t = &p->threads[p->thread_id];
4339 struct instruction *ip = t->ip;
4340
4341 /* Structs. */
4342 __instr_alu_shr_hi_exec(p, t, ip);
4343
4344 /* Thread. */
4345 thread_ip_inc(p);
4346 }
4347
4348 static inline void
instr_alu_and_exec(struct rte_swx_pipeline * p)4349 instr_alu_and_exec(struct rte_swx_pipeline *p)
4350 {
4351 struct thread *t = &p->threads[p->thread_id];
4352 struct instruction *ip = t->ip;
4353
4354 /* Structs. */
4355 __instr_alu_and_exec(p, t, ip);
4356
4357 /* Thread. */
4358 thread_ip_inc(p);
4359 }
4360
4361 static inline void
instr_alu_and_mh_exec(struct rte_swx_pipeline * p)4362 instr_alu_and_mh_exec(struct rte_swx_pipeline *p)
4363 {
4364 struct thread *t = &p->threads[p->thread_id];
4365 struct instruction *ip = t->ip;
4366
4367 /* Structs. */
4368 __instr_alu_and_mh_exec(p, t, ip);
4369
4370 /* Thread. */
4371 thread_ip_inc(p);
4372 }
4373
4374 static inline void
instr_alu_and_hm_exec(struct rte_swx_pipeline * p)4375 instr_alu_and_hm_exec(struct rte_swx_pipeline *p)
4376 {
4377 struct thread *t = &p->threads[p->thread_id];
4378 struct instruction *ip = t->ip;
4379
4380 /* Structs. */
4381 __instr_alu_and_hm_exec(p, t, ip);
4382
4383 /* Thread. */
4384 thread_ip_inc(p);
4385 }
4386
4387 static inline void
instr_alu_and_hh_exec(struct rte_swx_pipeline * p)4388 instr_alu_and_hh_exec(struct rte_swx_pipeline *p)
4389 {
4390 struct thread *t = &p->threads[p->thread_id];
4391 struct instruction *ip = t->ip;
4392
4393 /* Structs. */
4394 __instr_alu_and_hh_exec(p, t, ip);
4395
4396 /* Thread. */
4397 thread_ip_inc(p);
4398 }
4399
4400 static inline void
instr_alu_and_i_exec(struct rte_swx_pipeline * p)4401 instr_alu_and_i_exec(struct rte_swx_pipeline *p)
4402 {
4403 struct thread *t = &p->threads[p->thread_id];
4404 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 }
4412
4413 static inline void
instr_alu_or_exec(struct rte_swx_pipeline * p)4414 instr_alu_or_exec(struct rte_swx_pipeline *p)
4415 {
4416 struct thread *t = &p->threads[p->thread_id];
4417 struct instruction *ip = t->ip;
4418
4419 /* Structs. */
4420 __instr_alu_or_exec(p, t, ip);
4421
4422 /* Thread. */
4423 thread_ip_inc(p);
4424 }
4425
4426 static inline void
instr_alu_or_mh_exec(struct rte_swx_pipeline * p)4427 instr_alu_or_mh_exec(struct rte_swx_pipeline *p)
4428 {
4429 struct thread *t = &p->threads[p->thread_id];
4430 struct instruction *ip = t->ip;
4431
4432 /* Structs. */
4433 __instr_alu_or_mh_exec(p, t, ip);
4434
4435 /* Thread. */
4436 thread_ip_inc(p);
4437 }
4438
4439 static inline void
instr_alu_or_hm_exec(struct rte_swx_pipeline * p)4440 instr_alu_or_hm_exec(struct rte_swx_pipeline *p)
4441 {
4442 struct thread *t = &p->threads[p->thread_id];
4443 struct instruction *ip = t->ip;
4444
4445 /* Structs. */
4446 __instr_alu_or_hm_exec(p, t, ip);
4447
4448 /* Thread. */
4449 thread_ip_inc(p);
4450 }
4451
4452 static inline void
instr_alu_or_hh_exec(struct rte_swx_pipeline * p)4453 instr_alu_or_hh_exec(struct rte_swx_pipeline *p)
4454 {
4455 struct thread *t = &p->threads[p->thread_id];
4456 struct instruction *ip = t->ip;
4457
4458 /* Structs. */
4459 __instr_alu_or_hh_exec(p, t, ip);
4460
4461 /* Thread. */
4462 thread_ip_inc(p);
4463 }
4464
4465 static inline void
instr_alu_or_i_exec(struct rte_swx_pipeline * p)4466 instr_alu_or_i_exec(struct rte_swx_pipeline *p)
4467 {
4468 struct thread *t = &p->threads[p->thread_id];
4469 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 }
4477
4478 static inline void
instr_alu_xor_exec(struct rte_swx_pipeline * p)4479 instr_alu_xor_exec(struct rte_swx_pipeline *p)
4480 {
4481 struct thread *t = &p->threads[p->thread_id];
4482 struct instruction *ip = t->ip;
4483
4484 /* Structs. */
4485 __instr_alu_xor_exec(p, t, ip);
4486
4487 /* Thread. */
4488 thread_ip_inc(p);
4489 }
4490
4491 static inline void
instr_alu_xor_mh_exec(struct rte_swx_pipeline * p)4492 instr_alu_xor_mh_exec(struct rte_swx_pipeline *p)
4493 {
4494 struct thread *t = &p->threads[p->thread_id];
4495 struct instruction *ip = t->ip;
4496
4497 /* Structs. */
4498 __instr_alu_xor_mh_exec(p, t, ip);
4499
4500 /* Thread. */
4501 thread_ip_inc(p);
4502 }
4503
4504 static inline void
instr_alu_xor_hm_exec(struct rte_swx_pipeline * p)4505 instr_alu_xor_hm_exec(struct rte_swx_pipeline *p)
4506 {
4507 struct thread *t = &p->threads[p->thread_id];
4508 struct instruction *ip = t->ip;
4509
4510 /* Structs. */
4511 __instr_alu_xor_hm_exec(p, t, ip);
4512
4513 /* Thread. */
4514 thread_ip_inc(p);
4515 }
4516
4517 static inline void
instr_alu_xor_hh_exec(struct rte_swx_pipeline * p)4518 instr_alu_xor_hh_exec(struct rte_swx_pipeline *p)
4519 {
4520 struct thread *t = &p->threads[p->thread_id];
4521 struct instruction *ip = t->ip;
4522
4523 /* Structs. */
4524 __instr_alu_xor_hh_exec(p, t, ip);
4525
4526 /* Thread. */
4527 thread_ip_inc(p);
4528 }
4529
4530 static inline void
instr_alu_xor_i_exec(struct rte_swx_pipeline * p)4531 instr_alu_xor_i_exec(struct rte_swx_pipeline *p)
4532 {
4533 struct thread *t = &p->threads[p->thread_id];
4534 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 }
4542
4543 static inline void
instr_alu_ckadd_field_exec(struct rte_swx_pipeline * p)4544 instr_alu_ckadd_field_exec(struct rte_swx_pipeline *p)
4545 {
4546 struct thread *t = &p->threads[p->thread_id];
4547 struct instruction *ip = t->ip;
4548
4549 /* Structs. */
4550 __instr_alu_ckadd_field_exec(p, t, ip);
4551
4552 /* Thread. */
4553 thread_ip_inc(p);
4554 }
4555
4556 static inline void
instr_alu_cksub_field_exec(struct rte_swx_pipeline * p)4557 instr_alu_cksub_field_exec(struct rte_swx_pipeline *p)
4558 {
4559 struct thread *t = &p->threads[p->thread_id];
4560 struct instruction *ip = t->ip;
4561
4562 /* Structs. */
4563 __instr_alu_cksub_field_exec(p, t, ip);
4564
4565 /* Thread. */
4566 thread_ip_inc(p);
4567 }
4568
4569 static inline void
instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline * p)4570 instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline *p)
4571 {
4572 struct thread *t = &p->threads[p->thread_id];
4573 struct instruction *ip = t->ip;
4574
4575 /* Structs. */
4576 __instr_alu_ckadd_struct20_exec(p, t, ip);
4577
4578 /* Thread. */
4579 thread_ip_inc(p);
4580 }
4581
4582 static inline void
instr_alu_ckadd_struct_exec(struct rte_swx_pipeline * p)4583 instr_alu_ckadd_struct_exec(struct rte_swx_pipeline *p)
4584 {
4585 struct thread *t = &p->threads[p->thread_id];
4586 struct instruction *ip = t->ip;
4587
4588 /* Structs. */
4589 __instr_alu_ckadd_struct_exec(p, t, ip);
4590
4591 /* Thread. */
4592 thread_ip_inc(p);
4593 }
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
instr_regprefetch_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)4602 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 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 CHECK(n_tokens == 3, EINVAL);
4615
4616 r = regarray_find(p, regarray);
4617 CHECK(r, EINVAL);
4618
4619 /* REGPREFETCH_RH, REGPREFETCH_RM. */
4620 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4621 if (fidx) {
4622 CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
4623
4624 instr->type = INSTR_REGPREFETCH_RM;
4625 if (idx[0] == 'h')
4626 instr->type = INSTR_REGPREFETCH_RH;
4627
4628 instr->regarray.regarray_id = r->id;
4629 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4630 instr->regarray.idx.n_bits = fidx->n_bits;
4631 instr->regarray.idx.offset = fidx->offset / 8;
4632 instr->regarray.dstsrc_val = 0; /* Unused. */
4633 return 0;
4634 }
4635
4636 /* REGPREFETCH_RI. */
4637 idx_val = strtoul(idx, &idx, 0);
4638 CHECK(!idx[0], EINVAL);
4639
4640 instr->type = INSTR_REGPREFETCH_RI;
4641 instr->regarray.regarray_id = r->id;
4642 instr->regarray.idx_val = idx_val;
4643 instr->regarray.dstsrc_val = 0; /* Unused. */
4644 return 0;
4645 }
4646
4647 static int
instr_regrd_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)4648 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 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 CHECK(n_tokens == 4, EINVAL);
4661
4662 r = regarray_find(p, regarray);
4663 CHECK(r, EINVAL);
4664
4665 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4666 CHECK(fdst, EINVAL);
4667 CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
4668
4669 /* REGRD_HRH, REGRD_HRM, REGRD_MRH, REGRD_MRM. */
4670 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4671 if (fidx) {
4672 CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
4673
4674 instr->type = INSTR_REGRD_MRM;
4675 if (dst[0] == 'h' && idx[0] != 'h')
4676 instr->type = INSTR_REGRD_HRM;
4677 if (dst[0] != 'h' && idx[0] == 'h')
4678 instr->type = INSTR_REGRD_MRH;
4679 if (dst[0] == 'h' && idx[0] == 'h')
4680 instr->type = INSTR_REGRD_HRH;
4681
4682 instr->regarray.regarray_id = r->id;
4683 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4684 instr->regarray.idx.n_bits = fidx->n_bits;
4685 instr->regarray.idx.offset = fidx->offset / 8;
4686 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
4687 instr->regarray.dstsrc.n_bits = fdst->n_bits;
4688 instr->regarray.dstsrc.offset = fdst->offset / 8;
4689 return 0;
4690 }
4691
4692 /* REGRD_MRI, REGRD_HRI. */
4693 idx_val = strtoul(idx, &idx, 0);
4694 CHECK(!idx[0], EINVAL);
4695
4696 instr->type = INSTR_REGRD_MRI;
4697 if (dst[0] == 'h')
4698 instr->type = INSTR_REGRD_HRI;
4699
4700 instr->regarray.regarray_id = r->id;
4701 instr->regarray.idx_val = idx_val;
4702 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
4703 instr->regarray.dstsrc.n_bits = fdst->n_bits;
4704 instr->regarray.dstsrc.offset = fdst->offset / 8;
4705 return 0;
4706 }
4707
4708 static int
instr_regwr_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)4709 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 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 CHECK(n_tokens == 4, EINVAL);
4723
4724 r = regarray_find(p, regarray);
4725 CHECK(r, EINVAL);
4726
4727 /* REGWR_RHH, REGWR_RHM, REGWR_RMH, REGWR_RMM. */
4728 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4729 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4730 if (fidx && fsrc) {
4731 CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
4732 CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
4733
4734 instr->type = INSTR_REGWR_RMM;
4735 if (idx[0] == 'h' && src[0] != 'h')
4736 instr->type = INSTR_REGWR_RHM;
4737 if (idx[0] != 'h' && src[0] == 'h')
4738 instr->type = INSTR_REGWR_RMH;
4739 if (idx[0] == 'h' && src[0] == 'h')
4740 instr->type = INSTR_REGWR_RHH;
4741
4742 instr->regarray.regarray_id = r->id;
4743 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4744 instr->regarray.idx.n_bits = fidx->n_bits;
4745 instr->regarray.idx.offset = fidx->offset / 8;
4746 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4747 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4748 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4749 return 0;
4750 }
4751
4752 /* REGWR_RHI, REGWR_RMI. */
4753 if (fidx && !fsrc) {
4754 CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
4755
4756 src_val = strtoull(src, &src, 0);
4757 CHECK(!src[0], EINVAL);
4758
4759 instr->type = INSTR_REGWR_RMI;
4760 if (idx[0] == 'h')
4761 instr->type = INSTR_REGWR_RHI;
4762
4763 instr->regarray.regarray_id = r->id;
4764 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4765 instr->regarray.idx.n_bits = fidx->n_bits;
4766 instr->regarray.idx.offset = fidx->offset / 8;
4767 instr->regarray.dstsrc_val = src_val;
4768 return 0;
4769 }
4770
4771 /* REGWR_RIH, REGWR_RIM. */
4772 if (!fidx && fsrc) {
4773 idx_val = strtoul(idx, &idx, 0);
4774 CHECK(!idx[0], EINVAL);
4775
4776 CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
4777
4778 instr->type = INSTR_REGWR_RIM;
4779 if (src[0] == 'h')
4780 instr->type = INSTR_REGWR_RIH;
4781
4782 instr->regarray.regarray_id = r->id;
4783 instr->regarray.idx_val = idx_val;
4784 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4785 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4786 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4787 return 0;
4788 }
4789
4790 /* REGWR_RII. */
4791 src_val = strtoull(src, &src, 0);
4792 CHECK(!src[0], EINVAL);
4793
4794 idx_val = strtoul(idx, &idx, 0);
4795 CHECK(!idx[0], EINVAL);
4796
4797 instr->type = INSTR_REGWR_RII;
4798 instr->regarray.idx_val = idx_val;
4799 instr->regarray.dstsrc_val = src_val;
4800
4801 return 0;
4802 }
4803
4804 static int
instr_regadd_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)4805 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 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 CHECK(n_tokens == 4, EINVAL);
4819
4820 r = regarray_find(p, regarray);
4821 CHECK(r, EINVAL);
4822
4823 /* REGADD_RHH, REGADD_RHM, REGADD_RMH, REGADD_RMM. */
4824 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4825 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4826 if (fidx && fsrc) {
4827 CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
4828 CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
4829
4830 instr->type = INSTR_REGADD_RMM;
4831 if (idx[0] == 'h' && src[0] != 'h')
4832 instr->type = INSTR_REGADD_RHM;
4833 if (idx[0] != 'h' && src[0] == 'h')
4834 instr->type = INSTR_REGADD_RMH;
4835 if (idx[0] == 'h' && src[0] == 'h')
4836 instr->type = INSTR_REGADD_RHH;
4837
4838 instr->regarray.regarray_id = r->id;
4839 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4840 instr->regarray.idx.n_bits = fidx->n_bits;
4841 instr->regarray.idx.offset = fidx->offset / 8;
4842 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4843 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4844 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4845 return 0;
4846 }
4847
4848 /* REGADD_RHI, REGADD_RMI. */
4849 if (fidx && !fsrc) {
4850 CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
4851
4852 src_val = strtoull(src, &src, 0);
4853 CHECK(!src[0], EINVAL);
4854
4855 instr->type = INSTR_REGADD_RMI;
4856 if (idx[0] == 'h')
4857 instr->type = INSTR_REGADD_RHI;
4858
4859 instr->regarray.regarray_id = r->id;
4860 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4861 instr->regarray.idx.n_bits = fidx->n_bits;
4862 instr->regarray.idx.offset = fidx->offset / 8;
4863 instr->regarray.dstsrc_val = src_val;
4864 return 0;
4865 }
4866
4867 /* REGADD_RIH, REGADD_RIM. */
4868 if (!fidx && fsrc) {
4869 idx_val = strtoul(idx, &idx, 0);
4870 CHECK(!idx[0], EINVAL);
4871
4872 CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
4873
4874 instr->type = INSTR_REGADD_RIM;
4875 if (src[0] == 'h')
4876 instr->type = INSTR_REGADD_RIH;
4877
4878 instr->regarray.regarray_id = r->id;
4879 instr->regarray.idx_val = idx_val;
4880 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4881 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4882 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4883 return 0;
4884 }
4885
4886 /* REGADD_RII. */
4887 src_val = strtoull(src, &src, 0);
4888 CHECK(!src[0], EINVAL);
4889
4890 idx_val = strtoul(idx, &idx, 0);
4891 CHECK(!idx[0], EINVAL);
4892
4893 instr->type = INSTR_REGADD_RII;
4894 instr->regarray.idx_val = idx_val;
4895 instr->regarray.dstsrc_val = src_val;
4896 return 0;
4897 }
4898
4899 static inline void
instr_regprefetch_rh_exec(struct rte_swx_pipeline * p)4900 instr_regprefetch_rh_exec(struct rte_swx_pipeline *p)
4901 {
4902 struct thread *t = &p->threads[p->thread_id];
4903 struct instruction *ip = t->ip;
4904
4905 /* Structs. */
4906 __instr_regprefetch_rh_exec(p, t, ip);
4907
4908 /* Thread. */
4909 thread_ip_inc(p);
4910 }
4911
4912 static inline void
instr_regprefetch_rm_exec(struct rte_swx_pipeline * p)4913 instr_regprefetch_rm_exec(struct rte_swx_pipeline *p)
4914 {
4915 struct thread *t = &p->threads[p->thread_id];
4916 struct instruction *ip = t->ip;
4917
4918 /* Structs. */
4919 __instr_regprefetch_rm_exec(p, t, ip);
4920
4921 /* Thread. */
4922 thread_ip_inc(p);
4923 }
4924
4925 static inline void
instr_regprefetch_ri_exec(struct rte_swx_pipeline * p)4926 instr_regprefetch_ri_exec(struct rte_swx_pipeline *p)
4927 {
4928 struct thread *t = &p->threads[p->thread_id];
4929 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 }
4937
4938 static inline void
instr_regrd_hrh_exec(struct rte_swx_pipeline * p)4939 instr_regrd_hrh_exec(struct rte_swx_pipeline *p)
4940 {
4941 struct thread *t = &p->threads[p->thread_id];
4942 struct instruction *ip = t->ip;
4943
4944 /* Structs. */
4945 __instr_regrd_hrh_exec(p, t, ip);
4946
4947 /* Thread. */
4948 thread_ip_inc(p);
4949 }
4950
4951 static inline void
instr_regrd_hrm_exec(struct rte_swx_pipeline * p)4952 instr_regrd_hrm_exec(struct rte_swx_pipeline *p)
4953 {
4954 struct thread *t = &p->threads[p->thread_id];
4955 struct instruction *ip = t->ip;
4956
4957 /* Structs. */
4958 __instr_regrd_hrm_exec(p, t, ip);
4959
4960 /* Thread. */
4961 thread_ip_inc(p);
4962 }
4963
4964 static inline void
instr_regrd_mrh_exec(struct rte_swx_pipeline * p)4965 instr_regrd_mrh_exec(struct rte_swx_pipeline *p)
4966 {
4967 struct thread *t = &p->threads[p->thread_id];
4968 struct instruction *ip = t->ip;
4969
4970 /* Structs. */
4971 __instr_regrd_mrh_exec(p, t, ip);
4972
4973 /* Thread. */
4974 thread_ip_inc(p);
4975 }
4976
4977 static inline void
instr_regrd_mrm_exec(struct rte_swx_pipeline * p)4978 instr_regrd_mrm_exec(struct rte_swx_pipeline *p)
4979 {
4980 struct thread *t = &p->threads[p->thread_id];
4981 struct instruction *ip = t->ip;
4982
4983 /* Structs. */
4984 __instr_regrd_mrm_exec(p, t, ip);
4985
4986 /* Thread. */
4987 thread_ip_inc(p);
4988 }
4989
4990 static inline void
instr_regrd_hri_exec(struct rte_swx_pipeline * p)4991 instr_regrd_hri_exec(struct rte_swx_pipeline *p)
4992 {
4993 struct thread *t = &p->threads[p->thread_id];
4994 struct instruction *ip = t->ip;
4995
4996 /* Structs. */
4997 __instr_regrd_hri_exec(p, t, ip);
4998
4999 /* Thread. */
5000 thread_ip_inc(p);
5001 }
5002
5003 static inline void
instr_regrd_mri_exec(struct rte_swx_pipeline * p)5004 instr_regrd_mri_exec(struct rte_swx_pipeline *p)
5005 {
5006 struct thread *t = &p->threads[p->thread_id];
5007 struct instruction *ip = t->ip;
5008
5009 /* Structs. */
5010 __instr_regrd_mri_exec(p, t, ip);
5011
5012 /* Thread. */
5013 thread_ip_inc(p);
5014 }
5015
5016 static inline void
instr_regwr_rhh_exec(struct rte_swx_pipeline * p)5017 instr_regwr_rhh_exec(struct rte_swx_pipeline *p)
5018 {
5019 struct thread *t = &p->threads[p->thread_id];
5020 struct instruction *ip = t->ip;
5021
5022 /* Structs. */
5023 __instr_regwr_rhh_exec(p, t, ip);
5024
5025 /* Thread. */
5026 thread_ip_inc(p);
5027 }
5028
5029 static inline void
instr_regwr_rhm_exec(struct rte_swx_pipeline * p)5030 instr_regwr_rhm_exec(struct rte_swx_pipeline *p)
5031 {
5032 struct thread *t = &p->threads[p->thread_id];
5033 struct instruction *ip = t->ip;
5034
5035 /* Structs. */
5036 __instr_regwr_rhm_exec(p, t, ip);
5037
5038 /* Thread. */
5039 thread_ip_inc(p);
5040 }
5041
5042 static inline void
instr_regwr_rmh_exec(struct rte_swx_pipeline * p)5043 instr_regwr_rmh_exec(struct rte_swx_pipeline *p)
5044 {
5045 struct thread *t = &p->threads[p->thread_id];
5046 struct instruction *ip = t->ip;
5047
5048 /* Structs. */
5049 __instr_regwr_rmh_exec(p, t, ip);
5050
5051 /* Thread. */
5052 thread_ip_inc(p);
5053 }
5054
5055 static inline void
instr_regwr_rmm_exec(struct rte_swx_pipeline * p)5056 instr_regwr_rmm_exec(struct rte_swx_pipeline *p)
5057 {
5058 struct thread *t = &p->threads[p->thread_id];
5059 struct instruction *ip = t->ip;
5060
5061 /* Structs. */
5062 __instr_regwr_rmm_exec(p, t, ip);
5063
5064 /* Thread. */
5065 thread_ip_inc(p);
5066 }
5067
5068 static inline void
instr_regwr_rhi_exec(struct rte_swx_pipeline * p)5069 instr_regwr_rhi_exec(struct rte_swx_pipeline *p)
5070 {
5071 struct thread *t = &p->threads[p->thread_id];
5072 struct instruction *ip = t->ip;
5073
5074 /* Structs. */
5075 __instr_regwr_rhi_exec(p, t, ip);
5076
5077 /* Thread. */
5078 thread_ip_inc(p);
5079 }
5080
5081 static inline void
instr_regwr_rmi_exec(struct rte_swx_pipeline * p)5082 instr_regwr_rmi_exec(struct rte_swx_pipeline *p)
5083 {
5084 struct thread *t = &p->threads[p->thread_id];
5085 struct instruction *ip = t->ip;
5086
5087 /* Structs. */
5088 __instr_regwr_rmi_exec(p, t, ip);
5089
5090 /* Thread. */
5091 thread_ip_inc(p);
5092 }
5093
5094 static inline void
instr_regwr_rih_exec(struct rte_swx_pipeline * p)5095 instr_regwr_rih_exec(struct rte_swx_pipeline *p)
5096 {
5097 struct thread *t = &p->threads[p->thread_id];
5098 struct instruction *ip = t->ip;
5099
5100 /* Structs. */
5101 __instr_regwr_rih_exec(p, t, ip);
5102
5103 /* Thread. */
5104 thread_ip_inc(p);
5105 }
5106
5107 static inline void
instr_regwr_rim_exec(struct rte_swx_pipeline * p)5108 instr_regwr_rim_exec(struct rte_swx_pipeline *p)
5109 {
5110 struct thread *t = &p->threads[p->thread_id];
5111 struct instruction *ip = t->ip;
5112
5113 /* Structs. */
5114 __instr_regwr_rim_exec(p, t, ip);
5115
5116 /* Thread. */
5117 thread_ip_inc(p);
5118 }
5119
5120 static inline void
instr_regwr_rii_exec(struct rte_swx_pipeline * p)5121 instr_regwr_rii_exec(struct rte_swx_pipeline *p)
5122 {
5123 struct thread *t = &p->threads[p->thread_id];
5124 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 }
5132
5133 static inline void
instr_regadd_rhh_exec(struct rte_swx_pipeline * p)5134 instr_regadd_rhh_exec(struct rte_swx_pipeline *p)
5135 {
5136 struct thread *t = &p->threads[p->thread_id];
5137 struct instruction *ip = t->ip;
5138
5139 /* Structs. */
5140 __instr_regadd_rhh_exec(p, t, ip);
5141
5142 /* Thread. */
5143 thread_ip_inc(p);
5144 }
5145
5146 static inline void
instr_regadd_rhm_exec(struct rte_swx_pipeline * p)5147 instr_regadd_rhm_exec(struct rte_swx_pipeline *p)
5148 {
5149 struct thread *t = &p->threads[p->thread_id];
5150 struct instruction *ip = t->ip;
5151
5152 /* Structs. */
5153 __instr_regadd_rhm_exec(p, t, ip);
5154
5155 /* Thread. */
5156 thread_ip_inc(p);
5157 }
5158
5159 static inline void
instr_regadd_rmh_exec(struct rte_swx_pipeline * p)5160 instr_regadd_rmh_exec(struct rte_swx_pipeline *p)
5161 {
5162 struct thread *t = &p->threads[p->thread_id];
5163 struct instruction *ip = t->ip;
5164
5165 /* Structs. */
5166 __instr_regadd_rmh_exec(p, t, ip);
5167
5168 /* Thread. */
5169 thread_ip_inc(p);
5170 }
5171
5172 static inline void
instr_regadd_rmm_exec(struct rte_swx_pipeline * p)5173 instr_regadd_rmm_exec(struct rte_swx_pipeline *p)
5174 {
5175 struct thread *t = &p->threads[p->thread_id];
5176 struct instruction *ip = t->ip;
5177
5178 /* Structs. */
5179 __instr_regadd_rmm_exec(p, t, ip);
5180
5181 /* Thread. */
5182 thread_ip_inc(p);
5183 }
5184
5185 static inline void
instr_regadd_rhi_exec(struct rte_swx_pipeline * p)5186 instr_regadd_rhi_exec(struct rte_swx_pipeline *p)
5187 {
5188 struct thread *t = &p->threads[p->thread_id];
5189 struct instruction *ip = t->ip;
5190
5191 /* Structs. */
5192 __instr_regadd_rhi_exec(p, t, ip);
5193
5194 /* Thread. */
5195 thread_ip_inc(p);
5196 }
5197
5198 static inline void
instr_regadd_rmi_exec(struct rte_swx_pipeline * p)5199 instr_regadd_rmi_exec(struct rte_swx_pipeline *p)
5200 {
5201 struct thread *t = &p->threads[p->thread_id];
5202 struct instruction *ip = t->ip;
5203
5204 /* Structs. */
5205 __instr_regadd_rmi_exec(p, t, ip);
5206
5207 /* Thread. */
5208 thread_ip_inc(p);
5209 }
5210
5211 static inline void
instr_regadd_rih_exec(struct rte_swx_pipeline * p)5212 instr_regadd_rih_exec(struct rte_swx_pipeline *p)
5213 {
5214 struct thread *t = &p->threads[p->thread_id];
5215 struct instruction *ip = t->ip;
5216
5217 /* Structs. */
5218 __instr_regadd_rih_exec(p, t, ip);
5219
5220 /* Thread. */
5221 thread_ip_inc(p);
5222 }
5223
5224 static inline void
instr_regadd_rim_exec(struct rte_swx_pipeline * p)5225 instr_regadd_rim_exec(struct rte_swx_pipeline *p)
5226 {
5227 struct thread *t = &p->threads[p->thread_id];
5228 struct instruction *ip = t->ip;
5229
5230 /* Structs. */
5231 __instr_regadd_rim_exec(p, t, ip);
5232
5233 /* Thread. */
5234 thread_ip_inc(p);
5235 }
5236
5237 static inline void
instr_regadd_rii_exec(struct rte_swx_pipeline * p)5238 instr_regadd_rii_exec(struct rte_swx_pipeline *p)
5239 {
5240 struct thread *t = &p->threads[p->thread_id];
5241 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 }
5249
5250 /*
5251 * metarray.
5252 */
5253 static struct metarray *
5254 metarray_find(struct rte_swx_pipeline *p, const char *name);
5255
5256 static int
instr_metprefetch_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)5257 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 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 CHECK(n_tokens == 3, EINVAL);
5270
5271 m = metarray_find(p, metarray);
5272 CHECK(m, EINVAL);
5273
5274 /* METPREFETCH_H, METPREFETCH_M. */
5275 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
5276 if (fidx) {
5277 CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
5278
5279 instr->type = INSTR_METPREFETCH_M;
5280 if (idx[0] == 'h')
5281 instr->type = INSTR_METPREFETCH_H;
5282
5283 instr->meter.metarray_id = m->id;
5284 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
5285 instr->meter.idx.n_bits = fidx->n_bits;
5286 instr->meter.idx.offset = fidx->offset / 8;
5287 return 0;
5288 }
5289
5290 /* METPREFETCH_I. */
5291 idx_val = strtoul(idx, &idx, 0);
5292 CHECK(!idx[0], EINVAL);
5293
5294 instr->type = INSTR_METPREFETCH_I;
5295 instr->meter.metarray_id = m->id;
5296 instr->meter.idx_val = idx_val;
5297 return 0;
5298 }
5299
5300 static int
instr_meter_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)5301 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 char *metarray = tokens[1], *idx = tokens[2], *length = tokens[3];
5309 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 CHECK(n_tokens == 6, EINVAL);
5316
5317 m = metarray_find(p, metarray);
5318 CHECK(m, EINVAL);
5319
5320 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
5321
5322 flength = struct_field_parse(p, action, length, &length_struct_id);
5323 CHECK(flength, EINVAL);
5324 CHECK(!flength->var_size && (flength->n_bits <= 64), EINVAL);
5325
5326 fcin = struct_field_parse(p, action, color_in, &color_in_struct_id);
5327
5328 fcout = struct_field_parse(p, NULL, color_out, &color_out_struct_id);
5329 CHECK(fcout, EINVAL);
5330 CHECK(!fcout->var_size && (fcout->n_bits <= 64), EINVAL);
5331
5332 /* index = HMEFT, length = HMEFT, color_in = MEFT, color_out = MEF. */
5333 if (fidx && fcin) {
5334 CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
5335 CHECK(!fcin->var_size && (fcin->n_bits <= 64), EINVAL);
5336
5337 instr->type = INSTR_METER_MMM;
5338 if (idx[0] == 'h' && length[0] == 'h')
5339 instr->type = INSTR_METER_HHM;
5340 if (idx[0] == 'h' && length[0] != 'h')
5341 instr->type = INSTR_METER_HMM;
5342 if (idx[0] != 'h' && length[0] == 'h')
5343 instr->type = INSTR_METER_MHM;
5344
5345 instr->meter.metarray_id = m->id;
5346
5347 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
5348 instr->meter.idx.n_bits = fidx->n_bits;
5349 instr->meter.idx.offset = fidx->offset / 8;
5350
5351 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5352 instr->meter.length.n_bits = flength->n_bits;
5353 instr->meter.length.offset = flength->offset / 8;
5354
5355 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
5356 instr->meter.color_in.n_bits = fcin->n_bits;
5357 instr->meter.color_in.offset = fcin->offset / 8;
5358
5359 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5360 instr->meter.color_out.n_bits = fcout->n_bits;
5361 instr->meter.color_out.offset = fcout->offset / 8;
5362 }
5363
5364 /* index = HMEFT, length = HMEFT, color_in = I, color_out = MEF. */
5365 if (fidx && !fcin) {
5366 uint32_t color_in_val;
5367
5368 CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
5369
5370 color_in_val = strtoul(color_in, &color_in, 0);
5371 CHECK(!color_in[0], EINVAL);
5372
5373 instr->type = INSTR_METER_MMI;
5374 if (idx[0] == 'h' && length[0] == 'h')
5375 instr->type = INSTR_METER_HHI;
5376 if (idx[0] == 'h' && length[0] != 'h')
5377 instr->type = INSTR_METER_HMI;
5378 if (idx[0] != 'h' && length[0] == 'h')
5379 instr->type = INSTR_METER_MHI;
5380
5381 instr->meter.metarray_id = m->id;
5382
5383 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
5384 instr->meter.idx.n_bits = fidx->n_bits;
5385 instr->meter.idx.offset = fidx->offset / 8;
5386
5387 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5388 instr->meter.length.n_bits = flength->n_bits;
5389 instr->meter.length.offset = flength->offset / 8;
5390
5391 instr->meter.color_in_val = color_in_val;
5392
5393 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5394 instr->meter.color_out.n_bits = fcout->n_bits;
5395 instr->meter.color_out.offset = fcout->offset / 8;
5396 }
5397
5398 /* index = I, length = HMEFT, color_in = MEFT, color_out = MEF. */
5399 if (!fidx && fcin) {
5400 uint32_t idx_val;
5401
5402 idx_val = strtoul(idx, &idx, 0);
5403 CHECK(!idx[0], EINVAL);
5404
5405 CHECK(!fcin->var_size && (fcin->n_bits <= 64), EINVAL);
5406
5407 instr->type = INSTR_METER_IMM;
5408 if (length[0] == 'h')
5409 instr->type = INSTR_METER_IHM;
5410
5411 instr->meter.metarray_id = m->id;
5412
5413 instr->meter.idx_val = idx_val;
5414
5415 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5416 instr->meter.length.n_bits = flength->n_bits;
5417 instr->meter.length.offset = flength->offset / 8;
5418
5419 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
5420 instr->meter.color_in.n_bits = fcin->n_bits;
5421 instr->meter.color_in.offset = fcin->offset / 8;
5422
5423 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5424 instr->meter.color_out.n_bits = fcout->n_bits;
5425 instr->meter.color_out.offset = fcout->offset / 8;
5426 }
5427
5428 /* index = I, length = HMEFT, color_in = I, color_out = MEF. */
5429 if (!fidx && !fcin) {
5430 uint32_t idx_val, color_in_val;
5431
5432 idx_val = strtoul(idx, &idx, 0);
5433 CHECK(!idx[0], EINVAL);
5434
5435 color_in_val = strtoul(color_in, &color_in, 0);
5436 CHECK(!color_in[0], EINVAL);
5437
5438 instr->type = INSTR_METER_IMI;
5439 if (length[0] == 'h')
5440 instr->type = INSTR_METER_IHI;
5441
5442 instr->meter.metarray_id = m->id;
5443
5444 instr->meter.idx_val = idx_val;
5445
5446 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5447 instr->meter.length.n_bits = flength->n_bits;
5448 instr->meter.length.offset = flength->offset / 8;
5449
5450 instr->meter.color_in_val = color_in_val;
5451
5452 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5453 instr->meter.color_out.n_bits = fcout->n_bits;
5454 instr->meter.color_out.offset = fcout->offset / 8;
5455 }
5456
5457 return 0;
5458 }
5459
5460 static inline void
instr_metprefetch_h_exec(struct rte_swx_pipeline * p)5461 instr_metprefetch_h_exec(struct rte_swx_pipeline *p)
5462 {
5463 struct thread *t = &p->threads[p->thread_id];
5464 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 }
5472
5473 static inline void
instr_metprefetch_m_exec(struct rte_swx_pipeline * p)5474 instr_metprefetch_m_exec(struct rte_swx_pipeline *p)
5475 {
5476 struct thread *t = &p->threads[p->thread_id];
5477 struct instruction *ip = t->ip;
5478
5479 /* Structs. */
5480 __instr_metprefetch_m_exec(p, t, ip);
5481
5482 /* Thread. */
5483 thread_ip_inc(p);
5484 }
5485
5486 static inline void
instr_metprefetch_i_exec(struct rte_swx_pipeline * p)5487 instr_metprefetch_i_exec(struct rte_swx_pipeline *p)
5488 {
5489 struct thread *t = &p->threads[p->thread_id];
5490 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 }
5498
5499 static inline void
instr_meter_hhm_exec(struct rte_swx_pipeline * p)5500 instr_meter_hhm_exec(struct rte_swx_pipeline *p)
5501 {
5502 struct thread *t = &p->threads[p->thread_id];
5503 struct instruction *ip = t->ip;
5504
5505 /* Structs. */
5506 __instr_meter_hhm_exec(p, t, ip);
5507
5508 /* Thread. */
5509 thread_ip_inc(p);
5510 }
5511
5512 static inline void
instr_meter_hhi_exec(struct rte_swx_pipeline * p)5513 instr_meter_hhi_exec(struct rte_swx_pipeline *p)
5514 {
5515 struct thread *t = &p->threads[p->thread_id];
5516 struct instruction *ip = t->ip;
5517
5518 /* Structs. */
5519 __instr_meter_hhi_exec(p, t, ip);
5520
5521 /* Thread. */
5522 thread_ip_inc(p);
5523 }
5524
5525 static inline void
instr_meter_hmm_exec(struct rte_swx_pipeline * p)5526 instr_meter_hmm_exec(struct rte_swx_pipeline *p)
5527 {
5528 struct thread *t = &p->threads[p->thread_id];
5529 struct instruction *ip = t->ip;
5530
5531 /* Structs. */
5532 __instr_meter_hmm_exec(p, t, ip);
5533
5534 /* Thread. */
5535 thread_ip_inc(p);
5536 }
5537
5538 static inline void
instr_meter_hmi_exec(struct rte_swx_pipeline * p)5539 instr_meter_hmi_exec(struct rte_swx_pipeline *p)
5540 {
5541 struct thread *t = &p->threads[p->thread_id];
5542 struct instruction *ip = t->ip;
5543
5544 /* Structs. */
5545 __instr_meter_hmi_exec(p, t, ip);
5546
5547 /* Thread. */
5548 thread_ip_inc(p);
5549 }
5550
5551 static inline void
instr_meter_mhm_exec(struct rte_swx_pipeline * p)5552 instr_meter_mhm_exec(struct rte_swx_pipeline *p)
5553 {
5554 struct thread *t = &p->threads[p->thread_id];
5555 struct instruction *ip = t->ip;
5556
5557 /* Structs. */
5558 __instr_meter_mhm_exec(p, t, ip);
5559
5560 /* Thread. */
5561 thread_ip_inc(p);
5562 }
5563
5564 static inline void
instr_meter_mhi_exec(struct rte_swx_pipeline * p)5565 instr_meter_mhi_exec(struct rte_swx_pipeline *p)
5566 {
5567 struct thread *t = &p->threads[p->thread_id];
5568 struct instruction *ip = t->ip;
5569
5570 /* Structs. */
5571 __instr_meter_mhi_exec(p, t, ip);
5572
5573 /* Thread. */
5574 thread_ip_inc(p);
5575 }
5576
5577 static inline void
instr_meter_mmm_exec(struct rte_swx_pipeline * p)5578 instr_meter_mmm_exec(struct rte_swx_pipeline *p)
5579 {
5580 struct thread *t = &p->threads[p->thread_id];
5581 struct instruction *ip = t->ip;
5582
5583 /* Structs. */
5584 __instr_meter_mmm_exec(p, t, ip);
5585
5586 /* Thread. */
5587 thread_ip_inc(p);
5588 }
5589
5590 static inline void
instr_meter_mmi_exec(struct rte_swx_pipeline * p)5591 instr_meter_mmi_exec(struct rte_swx_pipeline *p)
5592 {
5593 struct thread *t = &p->threads[p->thread_id];
5594 struct instruction *ip = t->ip;
5595
5596 /* Structs. */
5597 __instr_meter_mmi_exec(p, t, ip);
5598
5599 /* Thread. */
5600 thread_ip_inc(p);
5601 }
5602
5603 static inline void
instr_meter_ihm_exec(struct rte_swx_pipeline * p)5604 instr_meter_ihm_exec(struct rte_swx_pipeline *p)
5605 {
5606 struct thread *t = &p->threads[p->thread_id];
5607 struct instruction *ip = t->ip;
5608
5609 /* Structs. */
5610 __instr_meter_ihm_exec(p, t, ip);
5611
5612 /* Thread. */
5613 thread_ip_inc(p);
5614 }
5615
5616 static inline void
instr_meter_ihi_exec(struct rte_swx_pipeline * p)5617 instr_meter_ihi_exec(struct rte_swx_pipeline *p)
5618 {
5619 struct thread *t = &p->threads[p->thread_id];
5620 struct instruction *ip = t->ip;
5621
5622 /* Structs. */
5623 __instr_meter_ihi_exec(p, t, ip);
5624
5625 /* Thread. */
5626 thread_ip_inc(p);
5627 }
5628
5629 static inline void
instr_meter_imm_exec(struct rte_swx_pipeline * p)5630 instr_meter_imm_exec(struct rte_swx_pipeline *p)
5631 {
5632 struct thread *t = &p->threads[p->thread_id];
5633 struct instruction *ip = t->ip;
5634
5635 /* Structs. */
5636 __instr_meter_imm_exec(p, t, ip);
5637
5638 /* Thread. */
5639 thread_ip_inc(p);
5640 }
5641
5642 static inline void
instr_meter_imi_exec(struct rte_swx_pipeline * p)5643 instr_meter_imi_exec(struct rte_swx_pipeline *p)
5644 {
5645 struct thread *t = &p->threads[p->thread_id];
5646 struct instruction *ip = t->ip;
5647
5648 /* Structs. */
5649 __instr_meter_imi_exec(p, t, ip);
5650
5651 /* Thread. */
5652 thread_ip_inc(p);
5653 }
5654
5655 /*
5656 * jmp.
5657 */
5658 static int
instr_jmp_translate(struct rte_swx_pipeline * p __rte_unused,struct action * action __rte_unused,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data)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 CHECK(n_tokens == 2, EINVAL);
5667
5668 strcpy(data->jmp_label, tokens[1]);
5669
5670 instr->type = INSTR_JMP;
5671 instr->jmp.ip = NULL; /* Resolved later. */
5672 return 0;
5673 }
5674
5675 static int
instr_jmp_valid_translate(struct rte_swx_pipeline * p,struct action * action __rte_unused,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data)5676 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 CHECK(n_tokens == 3, EINVAL);
5686
5687 strcpy(data->jmp_label, tokens[1]);
5688
5689 h = header_parse(p, tokens[2]);
5690 CHECK(h, EINVAL);
5691
5692 instr->type = INSTR_JMP_VALID;
5693 instr->jmp.ip = NULL; /* Resolved later. */
5694 instr->jmp.header_id = h->id;
5695 return 0;
5696 }
5697
5698 static int
instr_jmp_invalid_translate(struct rte_swx_pipeline * p,struct action * action __rte_unused,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data)5699 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 CHECK(n_tokens == 3, EINVAL);
5709
5710 strcpy(data->jmp_label, tokens[1]);
5711
5712 h = header_parse(p, tokens[2]);
5713 CHECK(h, EINVAL);
5714
5715 instr->type = INSTR_JMP_INVALID;
5716 instr->jmp.ip = NULL; /* Resolved later. */
5717 instr->jmp.header_id = h->id;
5718 return 0;
5719 }
5720
5721 static int
instr_jmp_hit_translate(struct rte_swx_pipeline * p __rte_unused,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data)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 CHECK(!action, EINVAL);
5730 CHECK(n_tokens == 2, EINVAL);
5731
5732 strcpy(data->jmp_label, tokens[1]);
5733
5734 instr->type = INSTR_JMP_HIT;
5735 instr->jmp.ip = NULL; /* Resolved later. */
5736 return 0;
5737 }
5738
5739 static int
instr_jmp_miss_translate(struct rte_swx_pipeline * p __rte_unused,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data)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 CHECK(!action, EINVAL);
5748 CHECK(n_tokens == 2, EINVAL);
5749
5750 strcpy(data->jmp_label, tokens[1]);
5751
5752 instr->type = INSTR_JMP_MISS;
5753 instr->jmp.ip = NULL; /* Resolved later. */
5754 return 0;
5755 }
5756
5757 static int
instr_jmp_action_hit_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data)5758 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 CHECK(!action, EINVAL);
5768 CHECK(n_tokens == 3, EINVAL);
5769
5770 strcpy(data->jmp_label, tokens[1]);
5771
5772 a = action_find(p, tokens[2]);
5773 CHECK(a, EINVAL);
5774
5775 instr->type = INSTR_JMP_ACTION_HIT;
5776 instr->jmp.ip = NULL; /* Resolved later. */
5777 instr->jmp.action_id = a->id;
5778 return 0;
5779 }
5780
5781 static int
instr_jmp_action_miss_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data)5782 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 CHECK(!action, EINVAL);
5792 CHECK(n_tokens == 3, EINVAL);
5793
5794 strcpy(data->jmp_label, tokens[1]);
5795
5796 a = action_find(p, tokens[2]);
5797 CHECK(a, EINVAL);
5798
5799 instr->type = INSTR_JMP_ACTION_MISS;
5800 instr->jmp.ip = NULL; /* Resolved later. */
5801 instr->jmp.action_id = a->id;
5802 return 0;
5803 }
5804
5805 static int
instr_jmp_eq_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data)5806 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 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 CHECK(n_tokens == 4, EINVAL);
5819
5820 strcpy(data->jmp_label, tokens[1]);
5821
5822 fa = struct_field_parse(p, action, a, &a_struct_id);
5823 CHECK(fa, EINVAL);
5824 CHECK(!fa->var_size && (fa->n_bits <= 64), EINVAL);
5825
5826 /* JMP_EQ, JMP_EQ_MH, JMP_EQ_HM, JMP_EQ_HH. */
5827 fb = struct_field_parse(p, action, b, &b_struct_id);
5828 if (fb) {
5829 CHECK(!fb->var_size && (fb->n_bits <= 64), EINVAL);
5830
5831 instr->type = INSTR_JMP_EQ;
5832 if (a[0] != 'h' && b[0] == 'h')
5833 instr->type = INSTR_JMP_EQ_MH;
5834 if (a[0] == 'h' && b[0] != 'h')
5835 instr->type = INSTR_JMP_EQ_HM;
5836 if (a[0] == 'h' && b[0] == 'h')
5837 instr->type = INSTR_JMP_EQ_HH;
5838 instr->jmp.ip = NULL; /* Resolved later. */
5839
5840 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5841 instr->jmp.a.n_bits = fa->n_bits;
5842 instr->jmp.a.offset = fa->offset / 8;
5843 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5844 instr->jmp.b.n_bits = fb->n_bits;
5845 instr->jmp.b.offset = fb->offset / 8;
5846 return 0;
5847 }
5848
5849 /* JMP_EQ_I. */
5850 b_val = strtoull(b, &b, 0);
5851 CHECK(!b[0], EINVAL);
5852
5853 if (a[0] == 'h')
5854 b_val = hton64(b_val) >> (64 - fa->n_bits);
5855
5856 instr->type = INSTR_JMP_EQ_I;
5857 instr->jmp.ip = NULL; /* Resolved later. */
5858 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5859 instr->jmp.a.n_bits = fa->n_bits;
5860 instr->jmp.a.offset = fa->offset / 8;
5861 instr->jmp.b_val = b_val;
5862 return 0;
5863 }
5864
5865 static int
instr_jmp_neq_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data)5866 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 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 CHECK(n_tokens == 4, EINVAL);
5879
5880 strcpy(data->jmp_label, tokens[1]);
5881
5882 fa = struct_field_parse(p, action, a, &a_struct_id);
5883 CHECK(fa, EINVAL);
5884 CHECK(!fa->var_size && (fa->n_bits <= 64), EINVAL);
5885
5886 /* JMP_NEQ, JMP_NEQ_MH, JMP_NEQ_HM, JMP_NEQ_HH. */
5887 fb = struct_field_parse(p, action, b, &b_struct_id);
5888 if (fb) {
5889 CHECK(!fb->var_size && (fb->n_bits <= 64), EINVAL);
5890
5891 instr->type = INSTR_JMP_NEQ;
5892 if (a[0] != 'h' && b[0] == 'h')
5893 instr->type = INSTR_JMP_NEQ_MH;
5894 if (a[0] == 'h' && b[0] != 'h')
5895 instr->type = INSTR_JMP_NEQ_HM;
5896 if (a[0] == 'h' && b[0] == 'h')
5897 instr->type = INSTR_JMP_NEQ_HH;
5898 instr->jmp.ip = NULL; /* Resolved later. */
5899
5900 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5901 instr->jmp.a.n_bits = fa->n_bits;
5902 instr->jmp.a.offset = fa->offset / 8;
5903 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5904 instr->jmp.b.n_bits = fb->n_bits;
5905 instr->jmp.b.offset = fb->offset / 8;
5906 return 0;
5907 }
5908
5909 /* JMP_NEQ_I. */
5910 b_val = strtoull(b, &b, 0);
5911 CHECK(!b[0], EINVAL);
5912
5913 if (a[0] == 'h')
5914 b_val = hton64(b_val) >> (64 - fa->n_bits);
5915
5916 instr->type = INSTR_JMP_NEQ_I;
5917 instr->jmp.ip = NULL; /* Resolved later. */
5918 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5919 instr->jmp.a.n_bits = fa->n_bits;
5920 instr->jmp.a.offset = fa->offset / 8;
5921 instr->jmp.b_val = b_val;
5922 return 0;
5923 }
5924
5925 static int
instr_jmp_lt_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data)5926 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 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 CHECK(n_tokens == 4, EINVAL);
5939
5940 strcpy(data->jmp_label, tokens[1]);
5941
5942 fa = struct_field_parse(p, action, a, &a_struct_id);
5943 CHECK(fa, EINVAL);
5944 CHECK(!fa->var_size && (fa->n_bits <= 64), EINVAL);
5945
5946 /* JMP_LT, JMP_LT_MH, JMP_LT_HM, JMP_LT_HH. */
5947 fb = struct_field_parse(p, action, b, &b_struct_id);
5948 if (fb) {
5949 CHECK(!fb->var_size && (fb->n_bits <= 64), EINVAL);
5950
5951 instr->type = INSTR_JMP_LT;
5952 if (a[0] == 'h' && b[0] != 'h')
5953 instr->type = INSTR_JMP_LT_HM;
5954 if (a[0] != 'h' && b[0] == 'h')
5955 instr->type = INSTR_JMP_LT_MH;
5956 if (a[0] == 'h' && b[0] == 'h')
5957 instr->type = INSTR_JMP_LT_HH;
5958 instr->jmp.ip = NULL; /* Resolved later. */
5959
5960 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5961 instr->jmp.a.n_bits = fa->n_bits;
5962 instr->jmp.a.offset = fa->offset / 8;
5963 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5964 instr->jmp.b.n_bits = fb->n_bits;
5965 instr->jmp.b.offset = fb->offset / 8;
5966 return 0;
5967 }
5968
5969 /* JMP_LT_MI, JMP_LT_HI. */
5970 b_val = strtoull(b, &b, 0);
5971 CHECK(!b[0], EINVAL);
5972
5973 instr->type = INSTR_JMP_LT_MI;
5974 if (a[0] == 'h')
5975 instr->type = INSTR_JMP_LT_HI;
5976 instr->jmp.ip = NULL; /* Resolved later. */
5977
5978 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5979 instr->jmp.a.n_bits = fa->n_bits;
5980 instr->jmp.a.offset = fa->offset / 8;
5981 instr->jmp.b_val = b_val;
5982 return 0;
5983 }
5984
5985 static int
instr_jmp_gt_translate(struct rte_swx_pipeline * p,struct action * action,char ** tokens,int n_tokens,struct instruction * instr,struct instruction_data * data)5986 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 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 CHECK(n_tokens == 4, EINVAL);
5999
6000 strcpy(data->jmp_label, tokens[1]);
6001
6002 fa = struct_field_parse(p, action, a, &a_struct_id);
6003 CHECK(fa, EINVAL);
6004 CHECK(!fa->var_size && (fa->n_bits <= 64), EINVAL);
6005
6006 /* JMP_GT, JMP_GT_MH, JMP_GT_HM, JMP_GT_HH. */
6007 fb = struct_field_parse(p, action, b, &b_struct_id);
6008 if (fb) {
6009 CHECK(!fb->var_size && (fb->n_bits <= 64), EINVAL);
6010
6011 instr->type = INSTR_JMP_GT;
6012 if (a[0] == 'h' && b[0] != 'h')
6013 instr->type = INSTR_JMP_GT_HM;
6014 if (a[0] != 'h' && b[0] == 'h')
6015 instr->type = INSTR_JMP_GT_MH;
6016 if (a[0] == 'h' && b[0] == 'h')
6017 instr->type = INSTR_JMP_GT_HH;
6018 instr->jmp.ip = NULL; /* Resolved later. */
6019
6020 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6021 instr->jmp.a.n_bits = fa->n_bits;
6022 instr->jmp.a.offset = fa->offset / 8;
6023 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6024 instr->jmp.b.n_bits = fb->n_bits;
6025 instr->jmp.b.offset = fb->offset / 8;
6026 return 0;
6027 }
6028
6029 /* JMP_GT_MI, JMP_GT_HI. */
6030 b_val = strtoull(b, &b, 0);
6031 CHECK(!b[0], EINVAL);
6032
6033 instr->type = INSTR_JMP_GT_MI;
6034 if (a[0] == 'h')
6035 instr->type = INSTR_JMP_GT_HI;
6036 instr->jmp.ip = NULL; /* Resolved later. */
6037
6038 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6039 instr->jmp.a.n_bits = fa->n_bits;
6040 instr->jmp.a.offset = fa->offset / 8;
6041 instr->jmp.b_val = b_val;
6042 return 0;
6043 }
6044
6045 static inline void
instr_jmp_exec(struct rte_swx_pipeline * p)6046 instr_jmp_exec(struct rte_swx_pipeline *p)
6047 {
6048 struct thread *t = &p->threads[p->thread_id];
6049 struct instruction *ip = t->ip;
6050
6051 TRACE("[Thread %2u] jmp\n", p->thread_id);
6052
6053 thread_ip_set(t, ip->jmp.ip);
6054 }
6055
6056 static inline void
instr_jmp_valid_exec(struct rte_swx_pipeline * p)6057 instr_jmp_valid_exec(struct rte_swx_pipeline *p)
6058 {
6059 struct thread *t = &p->threads[p->thread_id];
6060 struct instruction *ip = t->ip;
6061 uint32_t header_id = ip->jmp.header_id;
6062
6063 TRACE("[Thread %2u] jmpv\n", p->thread_id);
6064
6065 t->ip = HEADER_VALID(t, header_id) ? ip->jmp.ip : (t->ip + 1);
6066 }
6067
6068 static inline void
instr_jmp_invalid_exec(struct rte_swx_pipeline * p)6069 instr_jmp_invalid_exec(struct rte_swx_pipeline *p)
6070 {
6071 struct thread *t = &p->threads[p->thread_id];
6072 struct instruction *ip = t->ip;
6073 uint32_t header_id = ip->jmp.header_id;
6074
6075 TRACE("[Thread %2u] jmpnv\n", p->thread_id);
6076
6077 t->ip = HEADER_VALID(t, header_id) ? (t->ip + 1) : ip->jmp.ip;
6078 }
6079
6080 static inline void
instr_jmp_hit_exec(struct rte_swx_pipeline * p)6081 instr_jmp_hit_exec(struct rte_swx_pipeline *p)
6082 {
6083 struct thread *t = &p->threads[p->thread_id];
6084 struct instruction *ip = t->ip;
6085 struct instruction *ip_next[] = {t->ip + 1, ip->jmp.ip};
6086
6087 TRACE("[Thread %2u] jmph\n", p->thread_id);
6088
6089 t->ip = ip_next[t->hit];
6090 }
6091
6092 static inline void
instr_jmp_miss_exec(struct rte_swx_pipeline * p)6093 instr_jmp_miss_exec(struct rte_swx_pipeline *p)
6094 {
6095 struct thread *t = &p->threads[p->thread_id];
6096 struct instruction *ip = t->ip;
6097 struct instruction *ip_next[] = {ip->jmp.ip, t->ip + 1};
6098
6099 TRACE("[Thread %2u] jmpnh\n", p->thread_id);
6100
6101 t->ip = ip_next[t->hit];
6102 }
6103
6104 static inline void
instr_jmp_action_hit_exec(struct rte_swx_pipeline * p)6105 instr_jmp_action_hit_exec(struct rte_swx_pipeline *p)
6106 {
6107 struct thread *t = &p->threads[p->thread_id];
6108 struct instruction *ip = t->ip;
6109
6110 TRACE("[Thread %2u] jmpa\n", p->thread_id);
6111
6112 t->ip = (ip->jmp.action_id == t->action_id) ? ip->jmp.ip : (t->ip + 1);
6113 }
6114
6115 static inline void
instr_jmp_action_miss_exec(struct rte_swx_pipeline * p)6116 instr_jmp_action_miss_exec(struct rte_swx_pipeline *p)
6117 {
6118 struct thread *t = &p->threads[p->thread_id];
6119 struct instruction *ip = t->ip;
6120
6121 TRACE("[Thread %2u] jmpna\n", p->thread_id);
6122
6123 t->ip = (ip->jmp.action_id == t->action_id) ? (t->ip + 1) : ip->jmp.ip;
6124 }
6125
6126 static inline void
instr_jmp_eq_exec(struct rte_swx_pipeline * p)6127 instr_jmp_eq_exec(struct rte_swx_pipeline *p)
6128 {
6129 struct thread *t = &p->threads[p->thread_id];
6130 struct instruction *ip = t->ip;
6131
6132 TRACE("[Thread %2u] jmpeq\n", p->thread_id);
6133
6134 JMP_CMP(t, ip, ==);
6135 }
6136
6137 static inline void
instr_jmp_eq_mh_exec(struct rte_swx_pipeline * p)6138 instr_jmp_eq_mh_exec(struct rte_swx_pipeline *p)
6139 {
6140 struct thread *t = &p->threads[p->thread_id];
6141 struct instruction *ip = t->ip;
6142
6143 TRACE("[Thread %2u] jmpeq (mh)\n", p->thread_id);
6144
6145 JMP_CMP_MH(t, ip, ==);
6146 }
6147
6148 static inline void
instr_jmp_eq_hm_exec(struct rte_swx_pipeline * p)6149 instr_jmp_eq_hm_exec(struct rte_swx_pipeline *p)
6150 {
6151 struct thread *t = &p->threads[p->thread_id];
6152 struct instruction *ip = t->ip;
6153
6154 TRACE("[Thread %2u] jmpeq (hm)\n", p->thread_id);
6155
6156 JMP_CMP_HM(t, ip, ==);
6157 }
6158
6159 static inline void
instr_jmp_eq_hh_exec(struct rte_swx_pipeline * p)6160 instr_jmp_eq_hh_exec(struct rte_swx_pipeline *p)
6161 {
6162 struct thread *t = &p->threads[p->thread_id];
6163 struct instruction *ip = t->ip;
6164
6165 TRACE("[Thread %2u] jmpeq (hh)\n", p->thread_id);
6166
6167 JMP_CMP_HH_FAST(t, ip, ==);
6168 }
6169
6170 static inline void
instr_jmp_eq_i_exec(struct rte_swx_pipeline * p)6171 instr_jmp_eq_i_exec(struct rte_swx_pipeline *p)
6172 {
6173 struct thread *t = &p->threads[p->thread_id];
6174 struct instruction *ip = t->ip;
6175
6176 TRACE("[Thread %2u] jmpeq (i)\n", p->thread_id);
6177
6178 JMP_CMP_I(t, ip, ==);
6179 }
6180
6181 static inline void
instr_jmp_neq_exec(struct rte_swx_pipeline * p)6182 instr_jmp_neq_exec(struct rte_swx_pipeline *p)
6183 {
6184 struct thread *t = &p->threads[p->thread_id];
6185 struct instruction *ip = t->ip;
6186
6187 TRACE("[Thread %2u] jmpneq\n", p->thread_id);
6188
6189 JMP_CMP(t, ip, !=);
6190 }
6191
6192 static inline void
instr_jmp_neq_mh_exec(struct rte_swx_pipeline * p)6193 instr_jmp_neq_mh_exec(struct rte_swx_pipeline *p)
6194 {
6195 struct thread *t = &p->threads[p->thread_id];
6196 struct instruction *ip = t->ip;
6197
6198 TRACE("[Thread %2u] jmpneq (mh)\n", p->thread_id);
6199
6200 JMP_CMP_MH(t, ip, !=);
6201 }
6202
6203 static inline void
instr_jmp_neq_hm_exec(struct rte_swx_pipeline * p)6204 instr_jmp_neq_hm_exec(struct rte_swx_pipeline *p)
6205 {
6206 struct thread *t = &p->threads[p->thread_id];
6207 struct instruction *ip = t->ip;
6208
6209 TRACE("[Thread %2u] jmpneq (hm)\n", p->thread_id);
6210
6211 JMP_CMP_HM(t, ip, !=);
6212 }
6213
6214 static inline void
instr_jmp_neq_hh_exec(struct rte_swx_pipeline * p)6215 instr_jmp_neq_hh_exec(struct rte_swx_pipeline *p)
6216 {
6217 struct thread *t = &p->threads[p->thread_id];
6218 struct instruction *ip = t->ip;
6219
6220 TRACE("[Thread %2u] jmpneq (hh)\n", p->thread_id);
6221
6222 JMP_CMP_HH_FAST(t, ip, !=);
6223 }
6224
6225 static inline void
instr_jmp_neq_i_exec(struct rte_swx_pipeline * p)6226 instr_jmp_neq_i_exec(struct rte_swx_pipeline *p)
6227 {
6228 struct thread *t = &p->threads[p->thread_id];
6229 struct instruction *ip = t->ip;
6230
6231 TRACE("[Thread %2u] jmpneq (i)\n", p->thread_id);
6232
6233 JMP_CMP_I(t, ip, !=);
6234 }
6235
6236 static inline void
instr_jmp_lt_exec(struct rte_swx_pipeline * p)6237 instr_jmp_lt_exec(struct rte_swx_pipeline *p)
6238 {
6239 struct thread *t = &p->threads[p->thread_id];
6240 struct instruction *ip = t->ip;
6241
6242 TRACE("[Thread %2u] jmplt\n", p->thread_id);
6243
6244 JMP_CMP(t, ip, <);
6245 }
6246
6247 static inline void
instr_jmp_lt_mh_exec(struct rte_swx_pipeline * p)6248 instr_jmp_lt_mh_exec(struct rte_swx_pipeline *p)
6249 {
6250 struct thread *t = &p->threads[p->thread_id];
6251 struct instruction *ip = t->ip;
6252
6253 TRACE("[Thread %2u] jmplt (mh)\n", p->thread_id);
6254
6255 JMP_CMP_MH(t, ip, <);
6256 }
6257
6258 static inline void
instr_jmp_lt_hm_exec(struct rte_swx_pipeline * p)6259 instr_jmp_lt_hm_exec(struct rte_swx_pipeline *p)
6260 {
6261 struct thread *t = &p->threads[p->thread_id];
6262 struct instruction *ip = t->ip;
6263
6264 TRACE("[Thread %2u] jmplt (hm)\n", p->thread_id);
6265
6266 JMP_CMP_HM(t, ip, <);
6267 }
6268
6269 static inline void
instr_jmp_lt_hh_exec(struct rte_swx_pipeline * p)6270 instr_jmp_lt_hh_exec(struct rte_swx_pipeline *p)
6271 {
6272 struct thread *t = &p->threads[p->thread_id];
6273 struct instruction *ip = t->ip;
6274
6275 TRACE("[Thread %2u] jmplt (hh)\n", p->thread_id);
6276
6277 JMP_CMP_HH(t, ip, <);
6278 }
6279
6280 static inline void
instr_jmp_lt_mi_exec(struct rte_swx_pipeline * p)6281 instr_jmp_lt_mi_exec(struct rte_swx_pipeline *p)
6282 {
6283 struct thread *t = &p->threads[p->thread_id];
6284 struct instruction *ip = t->ip;
6285
6286 TRACE("[Thread %2u] jmplt (mi)\n", p->thread_id);
6287
6288 JMP_CMP_MI(t, ip, <);
6289 }
6290
6291 static inline void
instr_jmp_lt_hi_exec(struct rte_swx_pipeline * p)6292 instr_jmp_lt_hi_exec(struct rte_swx_pipeline *p)
6293 {
6294 struct thread *t = &p->threads[p->thread_id];
6295 struct instruction *ip = t->ip;
6296
6297 TRACE("[Thread %2u] jmplt (hi)\n", p->thread_id);
6298
6299 JMP_CMP_HI(t, ip, <);
6300 }
6301
6302 static inline void
instr_jmp_gt_exec(struct rte_swx_pipeline * p)6303 instr_jmp_gt_exec(struct rte_swx_pipeline *p)
6304 {
6305 struct thread *t = &p->threads[p->thread_id];
6306 struct instruction *ip = t->ip;
6307
6308 TRACE("[Thread %2u] jmpgt\n", p->thread_id);
6309
6310 JMP_CMP(t, ip, >);
6311 }
6312
6313 static inline void
instr_jmp_gt_mh_exec(struct rte_swx_pipeline * p)6314 instr_jmp_gt_mh_exec(struct rte_swx_pipeline *p)
6315 {
6316 struct thread *t = &p->threads[p->thread_id];
6317 struct instruction *ip = t->ip;
6318
6319 TRACE("[Thread %2u] jmpgt (mh)\n", p->thread_id);
6320
6321 JMP_CMP_MH(t, ip, >);
6322 }
6323
6324 static inline void
instr_jmp_gt_hm_exec(struct rte_swx_pipeline * p)6325 instr_jmp_gt_hm_exec(struct rte_swx_pipeline *p)
6326 {
6327 struct thread *t = &p->threads[p->thread_id];
6328 struct instruction *ip = t->ip;
6329
6330 TRACE("[Thread %2u] jmpgt (hm)\n", p->thread_id);
6331
6332 JMP_CMP_HM(t, ip, >);
6333 }
6334
6335 static inline void
instr_jmp_gt_hh_exec(struct rte_swx_pipeline * p)6336 instr_jmp_gt_hh_exec(struct rte_swx_pipeline *p)
6337 {
6338 struct thread *t = &p->threads[p->thread_id];
6339 struct instruction *ip = t->ip;
6340
6341 TRACE("[Thread %2u] jmpgt (hh)\n", p->thread_id);
6342
6343 JMP_CMP_HH(t, ip, >);
6344 }
6345
6346 static inline void
instr_jmp_gt_mi_exec(struct rte_swx_pipeline * p)6347 instr_jmp_gt_mi_exec(struct rte_swx_pipeline *p)
6348 {
6349 struct thread *t = &p->threads[p->thread_id];
6350 struct instruction *ip = t->ip;
6351
6352 TRACE("[Thread %2u] jmpgt (mi)\n", p->thread_id);
6353
6354 JMP_CMP_MI(t, ip, >);
6355 }
6356
6357 static inline void
instr_jmp_gt_hi_exec(struct rte_swx_pipeline * p)6358 instr_jmp_gt_hi_exec(struct rte_swx_pipeline *p)
6359 {
6360 struct thread *t = &p->threads[p->thread_id];
6361 struct instruction *ip = t->ip;
6362
6363 TRACE("[Thread %2u] jmpgt (hi)\n", p->thread_id);
6364
6365 JMP_CMP_HI(t, ip, >);
6366 }
6367
6368 /*
6369 * return.
6370 */
6371 static int
instr_return_translate(struct rte_swx_pipeline * p __rte_unused,struct action * action,char ** tokens __rte_unused,int n_tokens,struct instruction * instr,struct instruction_data * data __rte_unused)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 CHECK(action, EINVAL);
6380 CHECK(n_tokens == 1, EINVAL);
6381
6382 instr->type = INSTR_RETURN;
6383 return 0;
6384 }
6385
6386 static inline void
instr_return_exec(struct rte_swx_pipeline * p)6387 instr_return_exec(struct rte_swx_pipeline *p)
6388 {
6389 struct thread *t = &p->threads[p->thread_id];
6390
6391 TRACE("[Thread %2u] return\n", p->thread_id);
6392
6393 t->ip = t->ret;
6394 }
6395
6396 static int
instr_translate(struct rte_swx_pipeline * p,struct action * action,char * string,struct instruction * instr,struct instruction_data * data)6397 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 for ( ; ; ) {
6408 char *token;
6409
6410 token = strtok_r(string, " \t\v", &string);
6411 if (!token)
6412 break;
6413
6414 CHECK(n_tokens < RTE_SWX_INSTRUCTION_TOKENS_MAX, EINVAL);
6415 CHECK_NAME(token, EINVAL);
6416
6417 tokens[n_tokens] = token;
6418 n_tokens++;
6419 }
6420
6421 CHECK(n_tokens, EINVAL);
6422
6423 /* Handle the optional instruction label. */
6424 if ((n_tokens >= 2) && !strcmp(tokens[1], ":")) {
6425 strcpy(data->label, tokens[0]);
6426
6427 tpos += 2;
6428 CHECK(n_tokens - tpos, EINVAL);
6429 }
6430
6431 /* Identify the instruction type. */
6432 if (!strcmp(tokens[tpos], "rx"))
6433 return instr_rx_translate(p,
6434 action,
6435 &tokens[tpos],
6436 n_tokens - tpos,
6437 instr,
6438 data);
6439
6440 if (!strcmp(tokens[tpos], "tx"))
6441 return instr_tx_translate(p,
6442 action,
6443 &tokens[tpos],
6444 n_tokens - tpos,
6445 instr,
6446 data);
6447
6448 if (!strcmp(tokens[tpos], "drop"))
6449 return instr_drop_translate(p,
6450 action,
6451 &tokens[tpos],
6452 n_tokens - tpos,
6453 instr,
6454 data);
6455
6456 if (!strcmp(tokens[tpos], "mirror"))
6457 return instr_mirror_translate(p,
6458 action,
6459 &tokens[tpos],
6460 n_tokens - tpos,
6461 instr,
6462 data);
6463
6464 if (!strcmp(tokens[tpos], "recirculate"))
6465 return instr_recirculate_translate(p,
6466 action,
6467 &tokens[tpos],
6468 n_tokens - tpos,
6469 instr,
6470 data);
6471
6472 if (!strcmp(tokens[tpos], "recircid"))
6473 return instr_recircid_translate(p,
6474 action,
6475 &tokens[tpos],
6476 n_tokens - tpos,
6477 instr,
6478 data);
6479
6480 if (!strcmp(tokens[tpos], "extract"))
6481 return instr_hdr_extract_translate(p,
6482 action,
6483 &tokens[tpos],
6484 n_tokens - tpos,
6485 instr,
6486 data);
6487
6488 if (!strcmp(tokens[tpos], "lookahead"))
6489 return instr_hdr_lookahead_translate(p,
6490 action,
6491 &tokens[tpos],
6492 n_tokens - tpos,
6493 instr,
6494 data);
6495
6496 if (!strcmp(tokens[tpos], "emit"))
6497 return instr_hdr_emit_translate(p,
6498 action,
6499 &tokens[tpos],
6500 n_tokens - tpos,
6501 instr,
6502 data);
6503
6504 if (!strcmp(tokens[tpos], "validate"))
6505 return instr_hdr_validate_translate(p,
6506 action,
6507 &tokens[tpos],
6508 n_tokens - tpos,
6509 instr,
6510 data);
6511
6512 if (!strcmp(tokens[tpos], "invalidate"))
6513 return instr_hdr_invalidate_translate(p,
6514 action,
6515 &tokens[tpos],
6516 n_tokens - tpos,
6517 instr,
6518 data);
6519
6520 if (!strcmp(tokens[tpos], "mov"))
6521 return instr_mov_translate(p,
6522 action,
6523 &tokens[tpos],
6524 n_tokens - tpos,
6525 instr,
6526 data);
6527
6528 if (!strcmp(tokens[tpos], "movh"))
6529 return instr_movh_translate(p,
6530 action,
6531 &tokens[tpos],
6532 n_tokens - tpos,
6533 instr,
6534 data);
6535
6536 if (!strcmp(tokens[tpos], "add"))
6537 return instr_alu_add_translate(p,
6538 action,
6539 &tokens[tpos],
6540 n_tokens - tpos,
6541 instr,
6542 data);
6543
6544 if (!strcmp(tokens[tpos], "sub"))
6545 return instr_alu_sub_translate(p,
6546 action,
6547 &tokens[tpos],
6548 n_tokens - tpos,
6549 instr,
6550 data);
6551
6552 if (!strcmp(tokens[tpos], "ckadd"))
6553 return instr_alu_ckadd_translate(p,
6554 action,
6555 &tokens[tpos],
6556 n_tokens - tpos,
6557 instr,
6558 data);
6559
6560 if (!strcmp(tokens[tpos], "cksub"))
6561 return instr_alu_cksub_translate(p,
6562 action,
6563 &tokens[tpos],
6564 n_tokens - tpos,
6565 instr,
6566 data);
6567
6568 if (!strcmp(tokens[tpos], "and"))
6569 return instr_alu_and_translate(p,
6570 action,
6571 &tokens[tpos],
6572 n_tokens - tpos,
6573 instr,
6574 data);
6575
6576 if (!strcmp(tokens[tpos], "or"))
6577 return instr_alu_or_translate(p,
6578 action,
6579 &tokens[tpos],
6580 n_tokens - tpos,
6581 instr,
6582 data);
6583
6584 if (!strcmp(tokens[tpos], "xor"))
6585 return instr_alu_xor_translate(p,
6586 action,
6587 &tokens[tpos],
6588 n_tokens - tpos,
6589 instr,
6590 data);
6591
6592 if (!strcmp(tokens[tpos], "shl"))
6593 return instr_alu_shl_translate(p,
6594 action,
6595 &tokens[tpos],
6596 n_tokens - tpos,
6597 instr,
6598 data);
6599
6600 if (!strcmp(tokens[tpos], "shr"))
6601 return instr_alu_shr_translate(p,
6602 action,
6603 &tokens[tpos],
6604 n_tokens - tpos,
6605 instr,
6606 data);
6607
6608 if (!strcmp(tokens[tpos], "regprefetch"))
6609 return instr_regprefetch_translate(p,
6610 action,
6611 &tokens[tpos],
6612 n_tokens - tpos,
6613 instr,
6614 data);
6615
6616 if (!strcmp(tokens[tpos], "regrd"))
6617 return instr_regrd_translate(p,
6618 action,
6619 &tokens[tpos],
6620 n_tokens - tpos,
6621 instr,
6622 data);
6623
6624 if (!strcmp(tokens[tpos], "regwr"))
6625 return instr_regwr_translate(p,
6626 action,
6627 &tokens[tpos],
6628 n_tokens - tpos,
6629 instr,
6630 data);
6631
6632 if (!strcmp(tokens[tpos], "regadd"))
6633 return instr_regadd_translate(p,
6634 action,
6635 &tokens[tpos],
6636 n_tokens - tpos,
6637 instr,
6638 data);
6639
6640 if (!strcmp(tokens[tpos], "metprefetch"))
6641 return instr_metprefetch_translate(p,
6642 action,
6643 &tokens[tpos],
6644 n_tokens - tpos,
6645 instr,
6646 data);
6647
6648 if (!strcmp(tokens[tpos], "meter"))
6649 return instr_meter_translate(p,
6650 action,
6651 &tokens[tpos],
6652 n_tokens - tpos,
6653 instr,
6654 data);
6655
6656 if (!strcmp(tokens[tpos], "table"))
6657 return instr_table_translate(p,
6658 action,
6659 &tokens[tpos],
6660 n_tokens - tpos,
6661 instr,
6662 data);
6663
6664 if (!strcmp(tokens[tpos], "learn"))
6665 return instr_learn_translate(p,
6666 action,
6667 &tokens[tpos],
6668 n_tokens - tpos,
6669 instr,
6670 data);
6671 if (!strcmp(tokens[tpos], "rearm"))
6672 return instr_rearm_translate(p,
6673 action,
6674 &tokens[tpos],
6675 n_tokens - tpos,
6676 instr,
6677 data);
6678
6679 if (!strcmp(tokens[tpos], "forget"))
6680 return instr_forget_translate(p,
6681 action,
6682 &tokens[tpos],
6683 n_tokens - tpos,
6684 instr,
6685 data);
6686
6687 if (!strcmp(tokens[tpos], "entryid"))
6688 return instr_entryid_translate(p,
6689 action,
6690 &tokens[tpos],
6691 n_tokens - tpos,
6692 instr,
6693 data);
6694
6695 if (!strcmp(tokens[tpos], "extern"))
6696 return instr_extern_translate(p,
6697 action,
6698 &tokens[tpos],
6699 n_tokens - tpos,
6700 instr,
6701 data);
6702
6703 if (!strcmp(tokens[tpos], "hash"))
6704 return instr_hash_translate(p,
6705 action,
6706 &tokens[tpos],
6707 n_tokens - tpos,
6708 instr,
6709 data);
6710
6711 if (!strcmp(tokens[tpos], "rss"))
6712 return instr_rss_translate(p,
6713 action,
6714 &tokens[tpos],
6715 n_tokens - tpos,
6716 instr,
6717 data);
6718
6719 if (!strcmp(tokens[tpos], "jmp"))
6720 return instr_jmp_translate(p,
6721 action,
6722 &tokens[tpos],
6723 n_tokens - tpos,
6724 instr,
6725 data);
6726
6727 if (!strcmp(tokens[tpos], "jmpv"))
6728 return instr_jmp_valid_translate(p,
6729 action,
6730 &tokens[tpos],
6731 n_tokens - tpos,
6732 instr,
6733 data);
6734
6735 if (!strcmp(tokens[tpos], "jmpnv"))
6736 return instr_jmp_invalid_translate(p,
6737 action,
6738 &tokens[tpos],
6739 n_tokens - tpos,
6740 instr,
6741 data);
6742
6743 if (!strcmp(tokens[tpos], "jmph"))
6744 return instr_jmp_hit_translate(p,
6745 action,
6746 &tokens[tpos],
6747 n_tokens - tpos,
6748 instr,
6749 data);
6750
6751 if (!strcmp(tokens[tpos], "jmpnh"))
6752 return instr_jmp_miss_translate(p,
6753 action,
6754 &tokens[tpos],
6755 n_tokens - tpos,
6756 instr,
6757 data);
6758
6759 if (!strcmp(tokens[tpos], "jmpa"))
6760 return instr_jmp_action_hit_translate(p,
6761 action,
6762 &tokens[tpos],
6763 n_tokens - tpos,
6764 instr,
6765 data);
6766
6767 if (!strcmp(tokens[tpos], "jmpna"))
6768 return instr_jmp_action_miss_translate(p,
6769 action,
6770 &tokens[tpos],
6771 n_tokens - tpos,
6772 instr,
6773 data);
6774
6775 if (!strcmp(tokens[tpos], "jmpeq"))
6776 return instr_jmp_eq_translate(p,
6777 action,
6778 &tokens[tpos],
6779 n_tokens - tpos,
6780 instr,
6781 data);
6782
6783 if (!strcmp(tokens[tpos], "jmpneq"))
6784 return instr_jmp_neq_translate(p,
6785 action,
6786 &tokens[tpos],
6787 n_tokens - tpos,
6788 instr,
6789 data);
6790
6791 if (!strcmp(tokens[tpos], "jmplt"))
6792 return instr_jmp_lt_translate(p,
6793 action,
6794 &tokens[tpos],
6795 n_tokens - tpos,
6796 instr,
6797 data);
6798
6799 if (!strcmp(tokens[tpos], "jmpgt"))
6800 return instr_jmp_gt_translate(p,
6801 action,
6802 &tokens[tpos],
6803 n_tokens - tpos,
6804 instr,
6805 data);
6806
6807 if (!strcmp(tokens[tpos], "return"))
6808 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 *
label_find(struct instruction_data * data,uint32_t n,const char * label)6819 label_find(struct instruction_data *data, uint32_t n, const char *label)
6820 {
6821 uint32_t i;
6822
6823 for (i = 0; i < n; i++)
6824 if (!strcmp(label, data[i].label))
6825 return &data[i];
6826
6827 return NULL;
6828 }
6829
6830 static uint32_t
label_is_used(struct instruction_data * data,uint32_t n,const char * label)6831 label_is_used(struct instruction_data *data, uint32_t n, const char *label)
6832 {
6833 uint32_t count = 0, i;
6834
6835 if (!label[0])
6836 return 0;
6837
6838 for (i = 0; i < n; i++)
6839 if (!strcmp(label, data[i].jmp_label))
6840 count++;
6841
6842 return count;
6843 }
6844
6845 static int
instr_label_check(struct instruction_data * instruction_data,uint32_t n_instructions)6846 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 for (i = 0; i < n_instructions; i++) {
6853 struct instruction_data *data = &instruction_data[i];
6854 char *label = data->label;
6855 uint32_t j;
6856
6857 if (!label[0])
6858 continue;
6859
6860 for (j = i + 1; j < n_instructions; j++)
6861 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 for (i = 0; i < n_instructions; i++) {
6866 struct instruction_data *data = &instruction_data[i];
6867 char *label = data->label;
6868 char *jmp_label = data->jmp_label;
6869
6870 /* Continue if this instruction does not have a label or it is not a jump. */
6871 if (!label[0] || !jmp_label[0])
6872 continue;
6873
6874 CHECK(strcmp(label, jmp_label), EINVAL);
6875 }
6876
6877 /* Get users for each instruction label. */
6878 for (i = 0; i < n_instructions; i++) {
6879 struct instruction_data *data = &instruction_data[i];
6880 char *label = data->label;
6881
6882 data->n_users = label_is_used(instruction_data,
6883 n_instructions,
6884 label);
6885 }
6886
6887 return 0;
6888 }
6889
6890 static int
instr_jmp_resolve(struct instruction * instructions,struct instruction_data * instruction_data,uint32_t n_instructions)6891 instr_jmp_resolve(struct instruction *instructions,
6892 struct instruction_data *instruction_data,
6893 uint32_t n_instructions)
6894 {
6895 uint32_t i;
6896
6897 for (i = 0; i < n_instructions; i++) {
6898 struct instruction *instr = &instructions[i];
6899 struct instruction_data *data = &instruction_data[i];
6900 struct instruction_data *found;
6901
6902 if (!instruction_is_jmp(instr))
6903 continue;
6904
6905 found = label_find(instruction_data,
6906 n_instructions,
6907 data->jmp_label);
6908 CHECK(found, EINVAL);
6909
6910 instr->jmp.ip = &instructions[found - instruction_data];
6911 }
6912
6913 return 0;
6914 }
6915
6916 static int
instr_verify(struct rte_swx_pipeline * p __rte_unused,struct action * a,struct instruction * instr,struct instruction_data * data __rte_unused,uint32_t n_instructions)6917 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 if (!a) {
6924 enum instruction_type type;
6925 uint32_t i;
6926
6927 /* Check that the first instruction is rx. */
6928 CHECK(instr[0].type == INSTR_RX, EINVAL);
6929
6930 /* Check that there is at least one tx instruction. */
6931 for (i = 0; i < n_instructions; i++) {
6932 type = instr[i].type;
6933
6934 if (instruction_is_tx(type))
6935 break;
6936 }
6937 CHECK(i < n_instructions, EINVAL);
6938
6939 /* Check that the last instruction is either tx or unconditional
6940 * jump.
6941 */
6942 type = instr[n_instructions - 1].type;
6943 CHECK(instruction_is_tx(type) || (type == INSTR_JMP), EINVAL);
6944 }
6945
6946 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 for (i = 0; i < n_instructions; i++) {
6952 type = instr[i].type;
6953
6954 if ((type == INSTR_RETURN) || instruction_is_tx(type))
6955 break;
6956 }
6957 CHECK(i < n_instructions, EINVAL);
6958 }
6959
6960 return 0;
6961 }
6962
6963 static uint32_t
instr_compact(struct instruction * instructions,struct instruction_data * instruction_data,uint32_t n_instructions)6964 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 for (i = 0; i < n_instructions; i++) {
6972 struct instruction *instr = &instructions[i];
6973 struct instruction_data *data = &instruction_data[i];
6974
6975 if (data->invalid)
6976 continue;
6977
6978 if (i != pos) {
6979 memcpy(&instructions[pos], instr, sizeof(*instr));
6980 memcpy(&instruction_data[pos], data, sizeof(*data));
6981 }
6982
6983 pos++;
6984 }
6985
6986 return pos;
6987 }
6988
6989 static int
instr_pattern_extract_many_search(struct instruction * instr,struct instruction_data * data,uint32_t n_instr,uint32_t * n_pattern_instr)6990 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 for (i = 0; i < n_instr; i++) {
6998 if (data[i].invalid)
6999 break;
7000
7001 if (instr[i].type != INSTR_HDR_EXTRACT)
7002 break;
7003
7004 if (i == RTE_DIM(instr->io.hdr.header_id))
7005 break;
7006
7007 if (i && data[i].n_users)
7008 break;
7009 }
7010
7011 if (i < 2)
7012 return 0;
7013
7014 *n_pattern_instr = i;
7015 return 1;
7016 }
7017
7018 static void
instr_pattern_extract_many_replace(struct instruction * instr,struct instruction_data * data,uint32_t n_instr)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 for (i = 1; i < n_instr; i++) {
7026 instr[0].type++;
7027 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
7028 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
7029 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
7030
7031 data[i].invalid = 1;
7032 }
7033 }
7034
7035 static uint32_t
instr_pattern_extract_many_optimize(struct instruction * instructions,struct instruction_data * instruction_data,uint32_t n_instructions)7036 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 for (i = 0; i < n_instructions; ) {
7043 struct instruction *instr = &instructions[i];
7044 struct instruction_data *data = &instruction_data[i];
7045 uint32_t n_instr = 0;
7046 int detected;
7047
7048 /* Extract many. */
7049 detected = instr_pattern_extract_many_search(instr,
7050 data,
7051 n_instructions - i,
7052 &n_instr);
7053 if (detected) {
7054 instr_pattern_extract_many_replace(instr,
7055 data,
7056 n_instr);
7057 i += n_instr;
7058 continue;
7059 }
7060
7061 /* No pattern starting at the current instruction. */
7062 i++;
7063 }
7064
7065 /* Eliminate the invalid instructions that have been optimized out. */
7066 n_instructions = instr_compact(instructions,
7067 instruction_data,
7068 n_instructions);
7069
7070 return n_instructions;
7071 }
7072
7073 static int
instr_pattern_emit_many_tx_search(struct instruction * instr,struct instruction_data * data,uint32_t n_instr,uint32_t * n_pattern_instr)7074 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 for (i = 0; i < n_instr; i++) {
7082 if (data[i].invalid)
7083 break;
7084
7085 if (instr[i].type != INSTR_HDR_EMIT)
7086 break;
7087
7088 if (i == RTE_DIM(instr->io.hdr.header_id))
7089 break;
7090
7091 if (i && data[i].n_users)
7092 break;
7093 }
7094
7095 if (!i)
7096 return 0;
7097
7098 if (instr[i].type != INSTR_TX)
7099 return 0;
7100
7101 if (data[i].n_users)
7102 return 0;
7103
7104 i++;
7105
7106 *n_pattern_instr = i;
7107 return 1;
7108 }
7109
7110 static void
instr_pattern_emit_many_tx_replace(struct instruction * instr,struct instruction_data * data,uint32_t n_instr)7111 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 for (i = 1; i < n_instr - 1; i++) {
7119 instr[0].type++;
7120 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
7121 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
7122 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
7123
7124 data[i].invalid = 1;
7125 }
7126
7127 /* The TX instruction is the last one in the pattern. */
7128 instr[0].type++;
7129 instr[0].io.io.offset = instr[i].io.io.offset;
7130 instr[0].io.io.n_bits = instr[i].io.io.n_bits;
7131 data[i].invalid = 1;
7132 }
7133
7134 static uint32_t
instr_pattern_emit_many_tx_optimize(struct instruction * instructions,struct instruction_data * instruction_data,uint32_t n_instructions)7135 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 for (i = 0; i < n_instructions; ) {
7142 struct instruction *instr = &instructions[i];
7143 struct instruction_data *data = &instruction_data[i];
7144 uint32_t n_instr = 0;
7145 int detected;
7146
7147 /* Emit many + TX. */
7148 detected = instr_pattern_emit_many_tx_search(instr,
7149 data,
7150 n_instructions - i,
7151 &n_instr);
7152 if (detected) {
7153 instr_pattern_emit_many_tx_replace(instr,
7154 data,
7155 n_instr);
7156 i += n_instr;
7157 continue;
7158 }
7159
7160 /* No pattern starting at the current instruction. */
7161 i++;
7162 }
7163
7164 /* Eliminate the invalid instructions that have been optimized out. */
7165 n_instructions = instr_compact(instructions,
7166 instruction_data,
7167 n_instructions);
7168
7169 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
instr_pattern_validate_mov_all_search(struct rte_swx_pipeline * p,struct action * a,struct instruction * instr,struct instruction_data * data,uint32_t n_instr,struct instruction * instructions,struct instruction_data * instruction_data,uint32_t n_instructions,uint32_t * n_pattern_instr)7180 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 if (!a || !a->st)
7195 return 0;
7196
7197 /* First instruction: HDR_VALIDATE. Second instruction: MOV_HM, MOV_DMA or MOV_128. */
7198 if (data[0].invalid ||
7199 (instr[0].type != INSTR_HDR_VALIDATE) ||
7200 (n_instr < 2) ||
7201 data[1].invalid ||
7202 (instr[1].type != INSTR_MOV_HM &&
7203 instr[1].type != INSTR_MOV_DMA &&
7204 instr[1].type != INSTR_MOV_128) ||
7205 instr[1].mov.src.struct_id)
7206 return 0;
7207
7208 h = header_find_by_struct_id(p, instr[0].valid.struct_id);
7209 if (!h ||
7210 h->st->var_size ||
7211 (n_instr < 1 + h->st->n_fields))
7212 return 0;
7213
7214 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
7215 if (instr[1].mov.src.offset == a->st->fields[src_field_id].offset / 8)
7216 break;
7217
7218 if (src_field_id + h->st->n_fields > a->st->n_fields)
7219 return 0;
7220
7221 /* Second and subsequent instructions: MOV_HM. */
7222 for (i = 0; i < h->st->n_fields; i++)
7223 if (data[1 + i].invalid ||
7224 data[1 + i].n_users ||
7225 (instr[1 + i].type != INSTR_MOV_HM &&
7226 instr[1 + i].type != INSTR_MOV_DMA &&
7227 instr[1 + i].type != INSTR_MOV_128) ||
7228 (instr[1 + i].mov.dst.struct_id != h->struct_id) ||
7229 (instr[1 + i].mov.dst.offset != h->st->fields[i].offset / 8) ||
7230 (instr[1 + i].mov.dst.n_bits != h->st->fields[i].n_bits) ||
7231 instr[1 + i].mov.src.struct_id ||
7232 (instr[1 + i].mov.src.offset != a->st->fields[src_field_id + i].offset / 8) ||
7233 (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 for (j = src_field_id; j < src_field_id + h->st->n_fields; j++) {
7241 uint32_t n_users;
7242
7243 n_users = action_arg_src_mov_count(a,
7244 j,
7245 instructions,
7246 instruction_data,
7247 n_instructions);
7248 if (n_users > 1)
7249 return 0;
7250 }
7251
7252 *n_pattern_instr = 1 + h->st->n_fields;
7253 return 1;
7254 }
7255
7256 static void
instr_pattern_validate_mov_all_replace(struct rte_swx_pipeline * p,struct action * a,struct instruction * instr,struct instruction_data * data,uint32_t n_instr)7257 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 h = header_find_by_struct_id(p, instr[1].mov.dst.struct_id);
7268 if (!h)
7269 return;
7270
7271 src_offset = instr[1].mov.src.offset;
7272
7273 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
7274 if (src_offset == a->st->fields[src_field_id].offset / 8)
7275 break;
7276
7277 /* Modify the instructions. */
7278 instr[0].type = INSTR_DMA_HT;
7279 instr[0].dma.dst.header_id[0] = h->id;
7280 instr[0].dma.dst.struct_id[0] = h->struct_id;
7281 instr[0].dma.src.offset[0] = (uint8_t)src_offset;
7282 instr[0].dma.n_bytes[0] = h->st->n_bits / 8;
7283
7284 for (i = 1; i < n_instr; i++)
7285 data[i].invalid = 1;
7286
7287 /* Update the endianness of the action arguments to header endianness. */
7288 for (i = 0; i < h->st->n_fields; i++)
7289 a->args_endianness[src_field_id + i] = 1;
7290 }
7291
7292 static uint32_t
instr_pattern_validate_mov_all_optimize(struct rte_swx_pipeline * p,struct action * a,struct instruction * instructions,struct instruction_data * instruction_data,uint32_t n_instructions)7293 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 if (!a || !a->st)
7302 return n_instructions;
7303
7304 for (i = 0; i < n_instructions; ) {
7305 struct instruction *instr = &instructions[i];
7306 struct instruction_data *data = &instruction_data[i];
7307 uint32_t n_instr = 0;
7308 int detected;
7309
7310 /* Validate + mov all. */
7311 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 if (detected) {
7321 instr_pattern_validate_mov_all_replace(p, a, instr, data, n_instr);
7322 i += n_instr;
7323 continue;
7324 }
7325
7326 /* No pattern starting at the current instruction. */
7327 i++;
7328 }
7329
7330 /* Eliminate the invalid instructions that have been optimized out. */
7331 n_instructions = instr_compact(instructions,
7332 instruction_data,
7333 n_instructions);
7334
7335 return n_instructions;
7336 }
7337
7338 static int
instr_pattern_dma_many_search(struct instruction * instr,struct instruction_data * data,uint32_t n_instr,uint32_t * n_pattern_instr)7339 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 for (i = 0; i < n_instr; i++) {
7347 if (data[i].invalid)
7348 break;
7349
7350 if (instr[i].type != INSTR_DMA_HT)
7351 break;
7352
7353 if (i == RTE_DIM(instr->dma.dst.header_id))
7354 break;
7355
7356 if (i && data[i].n_users)
7357 break;
7358 }
7359
7360 if (i < 2)
7361 return 0;
7362
7363 *n_pattern_instr = i;
7364 return 1;
7365 }
7366
7367 static void
instr_pattern_dma_many_replace(struct instruction * instr,struct instruction_data * data,uint32_t n_instr)7368 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 for (i = 1; i < n_instr; i++) {
7375 instr[0].type++;
7376 instr[0].dma.dst.header_id[i] = instr[i].dma.dst.header_id[0];
7377 instr[0].dma.dst.struct_id[i] = instr[i].dma.dst.struct_id[0];
7378 instr[0].dma.src.offset[i] = instr[i].dma.src.offset[0];
7379 instr[0].dma.n_bytes[i] = instr[i].dma.n_bytes[0];
7380
7381 data[i].invalid = 1;
7382 }
7383 }
7384
7385 static uint32_t
instr_pattern_dma_many_optimize(struct instruction * instructions,struct instruction_data * instruction_data,uint32_t n_instructions)7386 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 for (i = 0; i < n_instructions; ) {
7393 struct instruction *instr = &instructions[i];
7394 struct instruction_data *data = &instruction_data[i];
7395 uint32_t n_instr = 0;
7396 int detected;
7397
7398 /* DMA many. */
7399 detected = instr_pattern_dma_many_search(instr,
7400 data,
7401 n_instructions - i,
7402 &n_instr);
7403 if (detected) {
7404 instr_pattern_dma_many_replace(instr, data, n_instr);
7405 i += n_instr;
7406 continue;
7407 }
7408
7409 /* No pattern starting at the current instruction. */
7410 i++;
7411 }
7412
7413 /* Eliminate the invalid instructions that have been optimized out. */
7414 n_instructions = instr_compact(instructions,
7415 instruction_data,
7416 n_instructions);
7417
7418 return n_instructions;
7419 }
7420
7421 static uint32_t
instr_optimize(struct rte_swx_pipeline * p,struct action * a,struct instruction * instructions,struct instruction_data * instruction_data,uint32_t n_instructions)7422 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 n_instructions = instr_pattern_extract_many_optimize(instructions,
7430 instruction_data,
7431 n_instructions);
7432
7433 /* Emit many + TX. */
7434 n_instructions = instr_pattern_emit_many_tx_optimize(instructions,
7435 instruction_data,
7436 n_instructions);
7437
7438 /* Validate + mov all. */
7439 n_instructions = instr_pattern_validate_mov_all_optimize(p,
7440 a,
7441 instructions,
7442 instruction_data,
7443 n_instructions);
7444
7445 /* DMA many. */
7446 n_instructions = instr_pattern_dma_many_optimize(instructions,
7447 instruction_data,
7448 n_instructions);
7449
7450 return n_instructions;
7451 }
7452
7453 static int
instruction_config(struct rte_swx_pipeline * p,struct action * a,const char ** instructions,uint32_t n_instructions)7454 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 CHECK(n_instructions, EINVAL);
7465 CHECK(instructions, EINVAL);
7466 for (i = 0; i < n_instructions; i++)
7467 CHECK_INSTRUCTION(instructions[i], EINVAL);
7468
7469 /* Memory allocation. */
7470 instr = calloc(n_instructions, sizeof(struct instruction));
7471 if (!instr) {
7472 err = -ENOMEM;
7473 goto error;
7474 }
7475
7476 data = calloc(n_instructions, sizeof(struct instruction_data));
7477 if (!data) {
7478 err = -ENOMEM;
7479 goto error;
7480 }
7481
7482 for (i = 0; i < n_instructions; i++) {
7483 char *string = strdup(instructions[i]);
7484 if (!string) {
7485 err = -ENOMEM;
7486 goto error;
7487 }
7488
7489 err = instr_translate(p, a, string, &instr[i], &data[i]);
7490 if (err) {
7491 free(string);
7492 goto error;
7493 }
7494
7495 free(string);
7496 }
7497
7498 err = instr_label_check(data, n_instructions);
7499 if (err)
7500 goto error;
7501
7502 err = instr_verify(p, a, instr, data, n_instructions);
7503 if (err)
7504 goto error;
7505
7506 n_instructions = instr_optimize(p, a, instr, data, n_instructions);
7507
7508 err = instr_jmp_resolve(instr, data, n_instructions);
7509 if (err)
7510 goto error;
7511
7512 if (a) {
7513 a->instructions = instr;
7514 a->instruction_data = data;
7515 a->n_instructions = n_instructions;
7516 } else {
7517 p->instructions = instr;
7518 p->instruction_data = data;
7519 p->n_instructions = n_instructions;
7520 }
7521
7522 return 0;
7523
7524 error:
7525 free(data);
7526 free(instr);
7527 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
instruction_table_build(struct rte_swx_pipeline * p)7739 instruction_table_build(struct rte_swx_pipeline *p)
7740 {
7741 p->instruction_table = calloc(RTE_SWX_PIPELINE_INSTRUCTION_TABLE_SIZE_MAX,
7742 sizeof(struct instr_exec_t *));
7743 if (!p->instruction_table)
7744 return -EINVAL;
7745
7746 memcpy(p->instruction_table, instruction_table, sizeof(instruction_table));
7747
7748 return 0;
7749 }
7750
7751 static void
instruction_table_build_free(struct rte_swx_pipeline * p)7752 instruction_table_build_free(struct rte_swx_pipeline *p)
7753 {
7754 if (!p->instruction_table)
7755 return;
7756
7757 free(p->instruction_table);
7758 p->instruction_table = NULL;
7759 }
7760
7761 static void
instruction_table_free(struct rte_swx_pipeline * p)7762 instruction_table_free(struct rte_swx_pipeline *p)
7763 {
7764 instruction_table_build_free(p);
7765 }
7766
7767 static inline void
instr_exec(struct rte_swx_pipeline * p)7768 instr_exec(struct rte_swx_pipeline *p)
7769 {
7770 struct thread *t = &p->threads[p->thread_id];
7771 struct instruction *ip = t->ip;
7772 instr_exec_t instr = p->instruction_table[ip->type];
7773
7774 instr(p);
7775 }
7776
7777 /*
7778 * Action.
7779 */
7780 static struct action *
action_find(struct rte_swx_pipeline * p,const char * name)7781 action_find(struct rte_swx_pipeline *p, const char *name)
7782 {
7783 struct action *elem;
7784
7785 if (!name)
7786 return NULL;
7787
7788 TAILQ_FOREACH(elem, &p->actions, node)
7789 if (strcmp(elem->name, name) == 0)
7790 return elem;
7791
7792 return NULL;
7793 }
7794
7795 static struct action *
action_find_by_id(struct rte_swx_pipeline * p,uint32_t id)7796 action_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7797 {
7798 struct action *action = NULL;
7799
7800 TAILQ_FOREACH(action, &p->actions, node)
7801 if (action->id == id)
7802 return action;
7803
7804 return NULL;
7805 }
7806
7807 static struct field *
action_field_find(struct action * a,const char * name)7808 action_field_find(struct action *a, const char *name)
7809 {
7810 return a->st ? struct_type_field_find(a->st, name) : NULL;
7811 }
7812
7813 static struct field *
action_field_parse(struct action * action,const char * name)7814 action_field_parse(struct action *action, const char *name)
7815 {
7816 if (name[0] != 't' || name[1] != '.')
7817 return NULL;
7818
7819 return action_field_find(action, &name[2]);
7820 }
7821
7822 static int
action_has_nbo_args(struct action * a)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 if (!a->st)
7829 return 0; /* FALSE */
7830
7831 for (i = 0; i < a->st->n_fields; i++)
7832 if (a->args_endianness[i])
7833 return 1; /* TRUE */
7834
7835 return 0; /* FALSE */
7836 }
7837
7838 static int
action_does_learning(struct action * a)7839 action_does_learning(struct action *a)
7840 {
7841 uint32_t i;
7842
7843 for (i = 0; i < a->n_instructions; i++)
7844 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 default:
7852 continue;
7853 }
7854
7855 return 0; /* FALSE */
7856 }
7857
7858 int
rte_swx_pipeline_action_config(struct rte_swx_pipeline * p,const char * name,const char * args_struct_type_name,const char ** instructions,uint32_t n_instructions)7859 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 CHECK(p, EINVAL);
7870
7871 CHECK_NAME(name, EINVAL);
7872 CHECK(!action_find(p, name), EEXIST);
7873
7874 if (args_struct_type_name) {
7875 CHECK_NAME(args_struct_type_name, EINVAL);
7876 args_struct_type = struct_type_find(p, args_struct_type_name);
7877 CHECK(args_struct_type, EINVAL);
7878 CHECK(!args_struct_type->var_size, EINVAL);
7879 }
7880
7881 /* Node allocation. */
7882 a = calloc(1, sizeof(struct action));
7883 if (!a) {
7884 status = -ENOMEM;
7885 goto error;
7886 }
7887
7888 if (args_struct_type) {
7889 a->args_endianness = calloc(args_struct_type->n_fields, sizeof(int));
7890 if (!a->args_endianness) {
7891 status = -ENOMEM;
7892 goto error;
7893 }
7894 }
7895
7896 /* Node initialization. */
7897 strcpy(a->name, name);
7898 a->st = args_struct_type;
7899 a->id = p->n_actions;
7900
7901 /* Instruction translation. */
7902 status = instruction_config(p, a, instructions, n_instructions);
7903 if (status)
7904 goto error;
7905
7906 /* Node add to tailq. */
7907 TAILQ_INSERT_TAIL(&p->actions, a, node);
7908 p->n_actions++;
7909
7910 return 0;
7911
7912 error:
7913 if (!a)
7914 return status;
7915
7916 free(a->args_endianness);
7917 free(a->instructions);
7918 free(a->instruction_data);
7919 free(a);
7920
7921 return status;
7922 }
7923
7924 static int
action_build(struct rte_swx_pipeline * p)7925 action_build(struct rte_swx_pipeline *p)
7926 {
7927 struct action *action;
7928
7929 /* p->action_instructions. */
7930 p->action_instructions = calloc(p->n_actions, sizeof(struct instruction *));
7931 CHECK(p->action_instructions, ENOMEM);
7932
7933 TAILQ_FOREACH(action, &p->actions, node)
7934 p->action_instructions[action->id] = action->instructions;
7935
7936 /* p->action_funcs. */
7937 p->action_funcs = calloc(p->n_actions, sizeof(action_func_t));
7938 CHECK(p->action_funcs, ENOMEM);
7939
7940 return 0;
7941 }
7942
7943 static void
action_build_free(struct rte_swx_pipeline * p)7944 action_build_free(struct rte_swx_pipeline *p)
7945 {
7946 free(p->action_funcs);
7947 p->action_funcs = NULL;
7948
7949 free(p->action_instructions);
7950 p->action_instructions = NULL;
7951 }
7952
7953 static void
action_free(struct rte_swx_pipeline * p)7954 action_free(struct rte_swx_pipeline *p)
7955 {
7956 action_build_free(p);
7957
7958 for ( ; ; ) {
7959 struct action *action;
7960
7961 action = TAILQ_FIRST(&p->actions);
7962 if (!action)
7963 break;
7964
7965 TAILQ_REMOVE(&p->actions, action, node);
7966 free(action->args_endianness);
7967 free(action->instructions);
7968 free(action->instruction_data);
7969 free(action);
7970 }
7971 }
7972
7973 static uint32_t
action_arg_src_mov_count(struct action * a,uint32_t arg_id,struct instruction * instructions,struct instruction_data * instruction_data,uint32_t n_instructions)7974 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 if (!a->st ||
7983 (arg_id >= a->st->n_fields) ||
7984 !instructions ||
7985 !instruction_data ||
7986 !n_instructions)
7987 return 0;
7988
7989 offset = a->st->fields[arg_id].offset / 8;
7990
7991 for (i = 0; i < n_instructions; i++) {
7992 struct instruction *instr = &instructions[i];
7993 struct instruction_data *data = &instruction_data[i];
7994
7995 if (data->invalid ||
7996 ((instr->type != INSTR_MOV) && (instr->type != INSTR_MOV_HM)) ||
7997 instr->mov.src.struct_id ||
7998 (instr->mov.src.offset != offset))
7999 continue;
8000
8001 n_users++;
8002 }
8003
8004 return n_users;
8005 }
8006
8007 static int
char_to_hex(char c,uint8_t * val)8008 char_to_hex(char c, uint8_t *val)
8009 {
8010 if (c >= '0' && c <= '9') {
8011 *val = c - '0';
8012 return 0;
8013 }
8014
8015 if (c >= 'A' && c <= 'F') {
8016 *val = c - 'A' + 10;
8017 return 0;
8018 }
8019
8020 if (c >= 'a' && c <= 'f') {
8021 *val = c - 'a' + 10;
8022 return 0;
8023 }
8024
8025 return -EINVAL;
8026 }
8027
8028 static int
hex_string_parse(char * src,uint8_t * dst,uint32_t n_dst_bytes)8029 hex_string_parse(char *src, uint8_t *dst, uint32_t n_dst_bytes)
8030 {
8031 uint32_t i;
8032
8033 /* Check input arguments. */
8034 if (!src || !src[0] || !dst || !n_dst_bytes)
8035 return -EINVAL;
8036
8037 /* Skip any leading "0x" or "0X" in the src string. */
8038 if ((src[0] == '0') && (src[1] == 'x' || src[1] == 'X'))
8039 src += 2;
8040
8041 /* Convert each group of two hex characters in the src string to one byte in dst array. */
8042 for (i = 0; i < n_dst_bytes; i++) {
8043 uint8_t a, b;
8044 int status;
8045
8046 status = char_to_hex(*src, &a);
8047 if (status)
8048 return status;
8049 src++;
8050
8051 status = char_to_hex(*src, &b);
8052 if (status)
8053 return status;
8054 src++;
8055
8056 dst[i] = a * 16 + b;
8057 }
8058
8059 /* Check for the end of the src string. */
8060 if (*src)
8061 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
action_args_parse(struct action * a,const char * args,uint8_t * data)8077 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 if (!a->st || !args || !args[0]) {
8085 status = -EINVAL;
8086 goto error;
8087 }
8088
8089 /* Memory allocation. */
8090 s0 = strdup(args);
8091 if (!s0) {
8092 status = -ENOMEM;
8093 goto error;
8094 }
8095
8096 /* Parse the string into tokens. */
8097 for (s = s0; ; ) {
8098 char *token;
8099
8100 token = strtok_r(s, " \f\n\r\t\v", &s);
8101 if (!token)
8102 break;
8103
8104 if (n_tokens >= RTE_DIM(tokens)) {
8105 status = -EINVAL;
8106 goto error;
8107 }
8108
8109 tokens[n_tokens] = token;
8110 n_tokens++;
8111 }
8112
8113 /* More checks. */
8114 if (n_tokens != a->st->n_fields * 2) {
8115 status = -EINVAL;
8116 goto error;
8117 }
8118
8119 /* Process the action arguments. */
8120 for (i = 0; i < a->st->n_fields; i++) {
8121 struct field *f = &a->st->fields[i];
8122 char *arg_name = tokens[i * 2];
8123 char *arg_val = tokens[i * 2 + 1];
8124
8125 if (strcmp(arg_name, f->name)) {
8126 status = -EINVAL;
8127 goto error;
8128 }
8129
8130 if (f->n_bits <= 64) {
8131 uint64_t val;
8132
8133 val = strtoull(arg_val, &arg_val, 0);
8134 if (arg_val[0]) {
8135 status = -EINVAL;
8136 goto error;
8137 }
8138
8139 /* Endianness conversion. */
8140 if (a->args_endianness[i])
8141 val = field_hton(val, f->n_bits);
8142
8143 /* Copy to entry. */
8144 memcpy(&data[offset], (uint8_t *)&val, f->n_bits / 8);
8145 } else {
8146 status = hex_string_parse(arg_val, &data[offset], f->n_bits / 8);
8147 if (status)
8148 goto error;
8149 }
8150
8151 offset += f->n_bits / 8;
8152 }
8153
8154 error:
8155 free(s0);
8156 return status;
8157 }
8158
8159 /*
8160 * Table.
8161 */
8162 static struct table_type *
table_type_find(struct rte_swx_pipeline * p,const char * name)8163 table_type_find(struct rte_swx_pipeline *p, const char *name)
8164 {
8165 struct table_type *elem;
8166
8167 TAILQ_FOREACH(elem, &p->table_types, node)
8168 if (strcmp(elem->name, name) == 0)
8169 return elem;
8170
8171 return NULL;
8172 }
8173
8174 static struct table_type *
table_type_resolve(struct rte_swx_pipeline * p,const char * recommended_type_name,enum rte_swx_table_match_type match_type)8175 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 if (recommended_type_name)
8183 TAILQ_FOREACH(elem, &p->table_types, node)
8184 if (!strcmp(elem->name, recommended_type_name) &&
8185 (elem->match_type == match_type))
8186 return elem;
8187
8188 /* Ignore the recommended type and get the first element with this match
8189 * type.
8190 */
8191 TAILQ_FOREACH(elem, &p->table_types, node)
8192 if (elem->match_type == match_type)
8193 return elem;
8194
8195 return NULL;
8196 }
8197
8198 static struct table *
table_find(struct rte_swx_pipeline * p,const char * name)8199 table_find(struct rte_swx_pipeline *p, const char *name)
8200 {
8201 struct table *elem;
8202
8203 TAILQ_FOREACH(elem, &p->tables, node)
8204 if (strcmp(elem->name, name) == 0)
8205 return elem;
8206
8207 return NULL;
8208 }
8209
8210 static struct table *
table_find_by_id(struct rte_swx_pipeline * p,uint32_t id)8211 table_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8212 {
8213 struct table *table = NULL;
8214
8215 TAILQ_FOREACH(table, &p->tables, node)
8216 if (table->id == id)
8217 return table;
8218
8219 return NULL;
8220 }
8221
8222 int
rte_swx_pipeline_table_type_register(struct rte_swx_pipeline * p,const char * name,enum rte_swx_table_match_type match_type,struct rte_swx_table_ops * ops)8223 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 CHECK(p, EINVAL);
8231
8232 CHECK_NAME(name, EINVAL);
8233 CHECK(!table_type_find(p, name), EEXIST);
8234
8235 CHECK(ops, EINVAL);
8236 CHECK(ops->create, EINVAL);
8237 CHECK(ops->lkp, EINVAL);
8238 CHECK(ops->free, EINVAL);
8239
8240 /* Node allocation. */
8241 elem = calloc(1, sizeof(struct table_type));
8242 CHECK(elem, ENOMEM);
8243
8244 /* Node initialization. */
8245 strcpy(elem->name, name);
8246 elem->match_type = match_type;
8247 memcpy(&elem->ops, ops, sizeof(*ops));
8248
8249 /* Node add to tailq. */
8250 TAILQ_INSERT_TAIL(&p->table_types, elem, node);
8251
8252 return 0;
8253 }
8254
8255 static int
table_match_type_resolve(struct rte_swx_match_field_params * fields,uint32_t n_fields,int contiguous_fields,enum rte_swx_table_match_type * match_type)8256 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 for (i = 0; i < n_fields; i++) {
8264 struct rte_swx_match_field_params *f = &fields[i];
8265
8266 if (f->match_type == RTE_SWX_TABLE_MATCH_EXACT)
8267 n_fields_em++;
8268
8269 if (f->match_type == RTE_SWX_TABLE_MATCH_LPM)
8270 n_fields_lpm++;
8271 }
8272
8273 if ((n_fields_lpm > 1) ||
8274 (n_fields_lpm && (n_fields_em != n_fields - 1)))
8275 return -EINVAL;
8276
8277 *match_type = ((n_fields_em == n_fields) && contiguous_fields) ?
8278 RTE_SWX_TABLE_MATCH_EXACT :
8279 RTE_SWX_TABLE_MATCH_WILDCARD;
8280
8281 return 0;
8282 }
8283
8284 static int
table_match_fields_check(struct rte_swx_pipeline * p,struct rte_swx_pipeline_table_params * params,struct header ** header,int * contiguous_fields)8285 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 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 if (!params->n_fields) {
8297 if (params->fields) {
8298 status = -EINVAL;
8299 goto end;
8300 }
8301
8302 if (header)
8303 *header = NULL;
8304
8305 if (contiguous_fields)
8306 *contiguous_fields = 0;
8307
8308 return 0;
8309 }
8310
8311 /* Memory allocation. */
8312 offset = calloc(params->n_fields, sizeof(uint32_t));
8313 n_bits = calloc(params->n_fields, sizeof(uint32_t));
8314 if (!offset || !n_bits) {
8315 status = -ENOMEM;
8316 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 hf = header_field_parse(p, params->fields[0].name, &h0);
8323 mf = metadata_field_parse(p, params->fields[0].name);
8324 if ((!hf && !mf) || (hf && hf->var_size)) {
8325 status = -EINVAL;
8326 goto end;
8327 }
8328
8329 offset[0] = h0 ? hf->offset : mf->offset;
8330 n_bits[0] = h0 ? hf->n_bits : mf->n_bits;
8331
8332 for (i = 1; i < params->n_fields; i++)
8333 if (h0) {
8334 struct header *h;
8335
8336 hf = header_field_parse(p, params->fields[i].name, &h);
8337 if (!hf || (h->id != h0->id) || hf->var_size) {
8338 status = -EINVAL;
8339 goto end;
8340 }
8341
8342 offset[i] = hf->offset;
8343 n_bits[i] = hf->n_bits;
8344 } else {
8345 mf = metadata_field_parse(p, params->fields[i].name);
8346 if (!mf) {
8347 status = -EINVAL;
8348 goto end;
8349 }
8350
8351 offset[i] = mf->offset;
8352 n_bits[i] = mf->n_bits;
8353 }
8354
8355 /* Check that there are no duplicated match fields. */
8356 for (i = 0; i < params->n_fields; i++) {
8357 uint32_t j;
8358
8359 for (j = 0; j < i; j++)
8360 if (offset[j] == offset[i]) {
8361 status = -EINVAL;
8362 goto end;
8363 }
8364 }
8365
8366 /* Detect if the match fields are contiguous or not. */
8367 for (i = 0; i < params->n_fields; i++) {
8368 uint32_t offset_next = offset[i] + n_bits[i];
8369 uint32_t j;
8370
8371 for (j = 0; j < params->n_fields; j++)
8372 if (offset[j] == offset_next) {
8373 n_fields_with_valid_next++;
8374 break;
8375 }
8376 }
8377
8378 /* Return. */
8379 if (header)
8380 *header = h0;
8381
8382 if (contiguous_fields)
8383 *contiguous_fields = (n_fields_with_valid_next == params->n_fields - 1) ? 1 : 0;
8384
8385 end:
8386 free(offset);
8387 free(n_bits);
8388 return status;
8389 }
8390
8391 int
rte_swx_pipeline_table_config(struct rte_swx_pipeline * p,const char * name,struct rte_swx_pipeline_table_params * params,const char * recommended_table_type_name,const char * args,uint32_t size)8392 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 struct header *header = NULL;
8403 struct hash_func *hf = NULL;
8404 uint32_t action_data_size_max = 0, i;
8405 int contiguous_fields = 0, status = 0;
8406
8407 CHECK(p, EINVAL);
8408
8409 CHECK_NAME(name, EINVAL);
8410 CHECK(!table_find(p, name), EEXIST);
8411 CHECK(!selector_find(p, name), EEXIST);
8412 CHECK(!learner_find(p, name), EEXIST);
8413
8414 CHECK(params, EINVAL);
8415
8416 /* Match checks. */
8417 status = table_match_fields_check(p, params, &header, &contiguous_fields);
8418 if (status)
8419 return status;
8420
8421 /* Action checks. */
8422 CHECK(params->n_actions, EINVAL);
8423 CHECK(params->action_names, EINVAL);
8424 for (i = 0; i < params->n_actions; i++) {
8425 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 CHECK_NAME(action_name, EINVAL);
8431
8432 a = action_find(p, action_name);
8433 CHECK(a, EINVAL);
8434 CHECK(!action_does_learning(a), EINVAL);
8435
8436 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 if (params->action_is_for_table_entries)
8441 action_is_for_table_entries = params->action_is_for_table_entries[i];
8442 if (params->action_is_for_default_entry)
8443 action_is_for_default_entry = params->action_is_for_default_entry[i];
8444 CHECK(action_is_for_table_entries || action_is_for_default_entry, EINVAL);
8445 }
8446
8447 CHECK_NAME(params->default_action_name, EINVAL);
8448 for (i = 0; i < p->n_actions; i++)
8449 if (!strcmp(params->action_names[i],
8450 params->default_action_name))
8451 break;
8452 CHECK(i < params->n_actions, EINVAL);
8453 CHECK(!params->action_is_for_default_entry || params->action_is_for_default_entry[i],
8454 EINVAL);
8455
8456 default_action = action_find(p, params->default_action_name);
8457 CHECK((default_action->st && params->default_action_args) || !params->default_action_args,
8458 EINVAL);
8459
8460 /* Hash function checks. */
8461 if (params->hash_func_name) {
8462 hf = hash_func_find(p, params->hash_func_name);
8463 CHECK(hf, EINVAL);
8464 }
8465
8466 /* Table type checks. */
8467 if (recommended_table_type_name)
8468 CHECK_NAME(recommended_table_type_name, EINVAL);
8469
8470 if (params->n_fields) {
8471 enum rte_swx_table_match_type match_type;
8472
8473 status = table_match_type_resolve(params->fields,
8474 params->n_fields,
8475 contiguous_fields,
8476 &match_type);
8477 if (status)
8478 return status;
8479
8480 type = table_type_resolve(p, recommended_table_type_name, match_type);
8481 CHECK(type, EINVAL);
8482 }
8483
8484 /* Memory allocation. */
8485 t = calloc(1, sizeof(struct table));
8486 if (!t) {
8487 status = -ENOMEM;
8488 goto error;
8489 }
8490
8491 t->fields = calloc(params->n_fields, sizeof(struct match_field));
8492 if (!t->fields) {
8493 status = -ENOMEM;
8494 goto error;
8495 }
8496
8497 t->actions = calloc(params->n_actions, sizeof(struct action *));
8498 if (!t->actions) {
8499 status = -ENOMEM;
8500 goto error;
8501 }
8502
8503 if (action_data_size_max) {
8504 t->default_action_data = calloc(1, action_data_size_max);
8505 if (!t->default_action_data) {
8506 status = -ENOMEM;
8507 goto error;
8508 }
8509 }
8510
8511 t->action_is_for_table_entries = calloc(params->n_actions, sizeof(int));
8512 if (!t->action_is_for_table_entries) {
8513 status = -ENOMEM;
8514 goto error;
8515 }
8516
8517 t->action_is_for_default_entry = calloc(params->n_actions, sizeof(int));
8518 if (!t->action_is_for_default_entry) {
8519 status = -ENOMEM;
8520 goto error;
8521 }
8522
8523 /* Node initialization. */
8524 strcpy(t->name, name);
8525 if (args && args[0])
8526 strcpy(t->args, args);
8527 t->type = type;
8528
8529 for (i = 0; i < params->n_fields; i++) {
8530 struct rte_swx_match_field_params *field = ¶ms->fields[i];
8531 struct match_field *f = &t->fields[i];
8532
8533 f->match_type = field->match_type;
8534 f->field = header ?
8535 header_field_parse(p, field->name, NULL) :
8536 metadata_field_parse(p, field->name);
8537 }
8538 t->n_fields = params->n_fields;
8539 t->header = header;
8540
8541 for (i = 0; i < params->n_actions; i++) {
8542 int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
8543
8544 if (params->action_is_for_table_entries)
8545 action_is_for_table_entries = params->action_is_for_table_entries[i];
8546 if (params->action_is_for_default_entry)
8547 action_is_for_default_entry = params->action_is_for_default_entry[i];
8548
8549 t->actions[i] = action_find(p, params->action_names[i]);
8550 t->action_is_for_table_entries[i] = action_is_for_table_entries;
8551 t->action_is_for_default_entry[i] = action_is_for_default_entry;
8552 }
8553 t->default_action = default_action;
8554 if (default_action->st) {
8555 status = action_args_parse(default_action,
8556 params->default_action_args,
8557 t->default_action_data);
8558 if (status)
8559 goto error;
8560 }
8561
8562 t->n_actions = params->n_actions;
8563 t->default_action_is_const = params->default_action_is_const;
8564 t->action_data_size_max = action_data_size_max;
8565
8566 t->hf = hf;
8567 t->size = size;
8568 t->id = p->n_tables;
8569
8570 /* Node add to tailq. */
8571 TAILQ_INSERT_TAIL(&p->tables, t, node);
8572 p->n_tables++;
8573
8574 return 0;
8575
8576 error:
8577 if (!t)
8578 return status;
8579
8580 free(t->action_is_for_default_entry);
8581 free(t->action_is_for_table_entries);
8582 free(t->default_action_data);
8583 free(t->actions);
8584 free(t->fields);
8585 free(t);
8586
8587 return status;
8588 }
8589
8590 static uint32_t
table_params_offset_get(struct table * table)8591 table_params_offset_get(struct table *table)
8592 {
8593 struct field *first;
8594 uint32_t i;
8595
8596 first = table->fields[0].field;
8597
8598 for (i = 1; i < table->n_fields; i++) {
8599 struct field *f = table->fields[i].field;
8600
8601 if (f->offset < first->offset)
8602 first = f;
8603 }
8604
8605 return first->offset / 8;
8606 }
8607
8608 static struct rte_swx_table_params *
table_params_get(struct table * table)8609 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 params = calloc(1, sizeof(struct rte_swx_table_params));
8618 if (!params)
8619 return NULL;
8620
8621 /* Find first (smallest offset) and last (biggest offset) match fields. */
8622 first = table->fields[0].field;
8623 last = table->fields[0].field;
8624
8625 for (i = 0; i < table->n_fields; i++) {
8626 struct field *f = table->fields[i].field;
8627
8628 if (f->offset < first->offset)
8629 first = f;
8630
8631 if (f->offset > last->offset)
8632 last = f;
8633 }
8634
8635 /* Key offset and size. */
8636 key_offset = first->offset / 8;
8637 key_size = (last->offset + last->n_bits - first->offset) / 8;
8638
8639 /* Memory allocation. */
8640 key_mask = calloc(1, key_size);
8641 if (!key_mask) {
8642 free(params);
8643 return NULL;
8644 }
8645
8646 /* Key mask. */
8647 for (i = 0; i < table->n_fields; i++) {
8648 struct field *f = table->fields[i].field;
8649 uint32_t start = (f->offset - first->offset) / 8;
8650 size_t size = f->n_bits / 8;
8651
8652 memset(&key_mask[start], 0xFF, size);
8653 }
8654
8655 /* Action data size. */
8656 action_data_size = 0;
8657 for (i = 0; i < table->n_actions; i++) {
8658 struct action *action = table->actions[i];
8659 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 params->match_type = table->type->match_type;
8667 params->key_size = key_size;
8668 params->key_offset = key_offset;
8669 params->key_mask0 = key_mask;
8670 params->action_data_size = action_data_size;
8671 params->hash_func = table->hf ? table->hf->func : NULL;
8672 params->n_keys_max = table->size;
8673
8674 return params;
8675 }
8676
8677 static void
table_params_free(struct rte_swx_table_params * params)8678 table_params_free(struct rte_swx_table_params *params)
8679 {
8680 if (!params)
8681 return;
8682
8683 free(params->key_mask0);
8684 free(params);
8685 }
8686
8687 static int
table_stub_lkp(void * table __rte_unused,void * mailbox __rte_unused,uint8_t ** key __rte_unused,uint64_t * action_id __rte_unused,uint8_t ** action_data __rte_unused,size_t * entry_id __rte_unused,int * hit)8688 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 *hit = 0;
8697 return 1; /* DONE. */
8698 }
8699
8700 static int
table_build(struct rte_swx_pipeline * p)8701 table_build(struct rte_swx_pipeline *p)
8702 {
8703 uint32_t i;
8704
8705 /* Per pipeline: table statistics. */
8706 p->table_stats = calloc(p->n_tables, sizeof(struct table_statistics));
8707 CHECK(p->table_stats, ENOMEM);
8708
8709 for (i = 0; i < p->n_tables; i++) {
8710 p->table_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
8711 CHECK(p->table_stats[i].n_pkts_action, ENOMEM);
8712 }
8713
8714 /* Per thread: table runt-time. */
8715 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8716 struct thread *t = &p->threads[i];
8717 struct table *table;
8718
8719 t->tables = calloc(p->n_tables, sizeof(struct table_runtime));
8720 CHECK(t->tables, ENOMEM);
8721
8722 TAILQ_FOREACH(table, &p->tables, node) {
8723 struct table_runtime *r = &t->tables[table->id];
8724
8725 if (table->type) {
8726 uint64_t size;
8727
8728 size = table->type->ops.mailbox_size_get();
8729
8730 /* r->func. */
8731 r->func = table->type->ops.lkp;
8732
8733 /* r->mailbox. */
8734 if (size) {
8735 r->mailbox = calloc(1, size);
8736 CHECK(r->mailbox, ENOMEM);
8737 }
8738
8739 /* r->key. */
8740 r->key = table->header ?
8741 &t->structs[table->header->struct_id] :
8742 &t->structs[p->metadata_struct_id];
8743 } else {
8744 r->func = table_stub_lkp;
8745 }
8746 }
8747 }
8748
8749 return 0;
8750 }
8751
8752 static void
table_build_free(struct rte_swx_pipeline * p)8753 table_build_free(struct rte_swx_pipeline *p)
8754 {
8755 uint32_t i;
8756
8757 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8758 struct thread *t = &p->threads[i];
8759 uint32_t j;
8760
8761 if (!t->tables)
8762 continue;
8763
8764 for (j = 0; j < p->n_tables; j++) {
8765 struct table_runtime *r = &t->tables[j];
8766
8767 free(r->mailbox);
8768 }
8769
8770 free(t->tables);
8771 t->tables = NULL;
8772 }
8773
8774 if (p->table_stats) {
8775 for (i = 0; i < p->n_tables; i++)
8776 free(p->table_stats[i].n_pkts_action);
8777
8778 free(p->table_stats);
8779 p->table_stats = NULL;
8780 }
8781 }
8782
8783 static void
table_free(struct rte_swx_pipeline * p)8784 table_free(struct rte_swx_pipeline *p)
8785 {
8786 table_build_free(p);
8787
8788 /* Tables. */
8789 for ( ; ; ) {
8790 struct table *elem;
8791
8792 elem = TAILQ_FIRST(&p->tables);
8793 if (!elem)
8794 break;
8795
8796 TAILQ_REMOVE(&p->tables, elem, node);
8797 free(elem->fields);
8798 free(elem->actions);
8799 free(elem->default_action_data);
8800 free(elem);
8801 }
8802
8803 /* Table types. */
8804 for ( ; ; ) {
8805 struct table_type *elem;
8806
8807 elem = TAILQ_FIRST(&p->table_types);
8808 if (!elem)
8809 break;
8810
8811 TAILQ_REMOVE(&p->table_types, elem, node);
8812 free(elem);
8813 }
8814 }
8815
8816 /*
8817 * Selector.
8818 */
8819 static struct selector *
selector_find(struct rte_swx_pipeline * p,const char * name)8820 selector_find(struct rte_swx_pipeline *p, const char *name)
8821 {
8822 struct selector *s;
8823
8824 TAILQ_FOREACH(s, &p->selectors, node)
8825 if (strcmp(s->name, name) == 0)
8826 return s;
8827
8828 return NULL;
8829 }
8830
8831 static struct selector *
selector_find_by_id(struct rte_swx_pipeline * p,uint32_t id)8832 selector_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8833 {
8834 struct selector *s = NULL;
8835
8836 TAILQ_FOREACH(s, &p->selectors, node)
8837 if (s->id == id)
8838 return s;
8839
8840 return NULL;
8841 }
8842
8843 static int
selector_fields_check(struct rte_swx_pipeline * p,struct rte_swx_pipeline_selector_params * params,struct header ** header)8844 selector_fields_check(struct rte_swx_pipeline *p,
8845 struct rte_swx_pipeline_selector_params *params,
8846 struct header **header)
8847 {
8848 struct header *h0 = NULL;
8849 struct field *hf, *mf;
8850 uint32_t i;
8851
8852 /* Return if no selector fields. */
8853 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 hf = header_field_parse(p, params->selector_field_names[0], &h0);
8860 mf = metadata_field_parse(p, params->selector_field_names[0]);
8861 if (!hf && !mf)
8862 return -EINVAL;
8863
8864 for (i = 1; i < params->n_selector_fields; i++)
8865 if (h0) {
8866 struct header *h;
8867
8868 hf = header_field_parse(p, params->selector_field_names[i], &h);
8869 if (!hf || (h->id != h0->id))
8870 return -EINVAL;
8871 } else {
8872 mf = metadata_field_parse(p, params->selector_field_names[i]);
8873 if (!mf)
8874 return -EINVAL;
8875 }
8876
8877 /* Check that there are no duplicated match fields. */
8878 for (i = 0; i < params->n_selector_fields; i++) {
8879 const char *field_name = params->selector_field_names[i];
8880 uint32_t j;
8881
8882 for (j = i + 1; j < params->n_selector_fields; j++)
8883 if (!strcmp(params->selector_field_names[j], field_name))
8884 return -EINVAL;
8885 }
8886
8887 /* Return. */
8888 if (header)
8889 *header = h0;
8890
8891 return 0;
8892 }
8893
8894 int
rte_swx_pipeline_selector_config(struct rte_swx_pipeline * p,const char * name,struct rte_swx_pipeline_selector_params * params)8895 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 struct header *selector_header = NULL;
8901 struct field *group_id_field, *member_id_field;
8902 uint32_t i;
8903 int status = 0;
8904
8905 CHECK(p, EINVAL);
8906
8907 CHECK_NAME(name, EINVAL);
8908 CHECK(!table_find(p, name), EEXIST);
8909 CHECK(!selector_find(p, name), EEXIST);
8910 CHECK(!learner_find(p, name), EEXIST);
8911
8912 CHECK(params, EINVAL);
8913
8914 CHECK_NAME(params->group_id_field_name, EINVAL);
8915 group_id_field = metadata_field_parse(p, params->group_id_field_name);
8916 CHECK(group_id_field, EINVAL);
8917
8918 for (i = 0; i < params->n_selector_fields; i++) {
8919 const char *field_name = params->selector_field_names[i];
8920
8921 CHECK_NAME(field_name, EINVAL);
8922 }
8923 status = selector_fields_check(p, params, &selector_header);
8924 if (status)
8925 return status;
8926
8927 CHECK_NAME(params->member_id_field_name, EINVAL);
8928 member_id_field = metadata_field_parse(p, params->member_id_field_name);
8929 CHECK(member_id_field, EINVAL);
8930
8931 CHECK(params->n_groups_max, EINVAL);
8932
8933 CHECK(params->n_members_per_group_max, EINVAL);
8934
8935 /* Memory allocation. */
8936 s = calloc(1, sizeof(struct selector));
8937 if (!s) {
8938 status = -ENOMEM;
8939 goto error;
8940 }
8941
8942 s->selector_fields = calloc(params->n_selector_fields, sizeof(struct field *));
8943 if (!s->selector_fields) {
8944 status = -ENOMEM;
8945 goto error;
8946 }
8947
8948 /* Node initialization. */
8949 strcpy(s->name, name);
8950
8951 s->group_id_field = group_id_field;
8952
8953 for (i = 0; i < params->n_selector_fields; i++) {
8954 const char *field_name = params->selector_field_names[i];
8955
8956 s->selector_fields[i] = selector_header ?
8957 header_field_parse(p, field_name, NULL) :
8958 metadata_field_parse(p, field_name);
8959 }
8960
8961 s->n_selector_fields = params->n_selector_fields;
8962
8963 s->selector_header = selector_header;
8964
8965 s->member_id_field = member_id_field;
8966
8967 s->n_groups_max = params->n_groups_max;
8968
8969 s->n_members_per_group_max = params->n_members_per_group_max;
8970
8971 s->id = p->n_selectors;
8972
8973 /* Node add to tailq. */
8974 TAILQ_INSERT_TAIL(&p->selectors, s, node);
8975 p->n_selectors++;
8976
8977 return 0;
8978
8979 error:
8980 if (!s)
8981 return status;
8982
8983 free(s->selector_fields);
8984
8985 free(s);
8986
8987 return status;
8988 }
8989
8990 static void
selector_params_free(struct rte_swx_table_selector_params * params)8991 selector_params_free(struct rte_swx_table_selector_params *params)
8992 {
8993 if (!params)
8994 return;
8995
8996 free(params->selector_mask);
8997
8998 free(params);
8999 }
9000
9001 static struct rte_swx_table_selector_params *
selector_table_params_get(struct selector * s)9002 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 params = calloc(1, sizeof(struct rte_swx_table_selector_params));
9010 if (!params)
9011 goto error;
9012
9013 /* Group ID. */
9014 params->group_id_offset = s->group_id_field->offset / 8;
9015
9016 /* Find first (smallest offset) and last (biggest offset) selector fields. */
9017 first = s->selector_fields[0];
9018 last = s->selector_fields[0];
9019
9020 for (i = 0; i < s->n_selector_fields; i++) {
9021 struct field *f = s->selector_fields[i];
9022
9023 if (f->offset < first->offset)
9024 first = f;
9025
9026 if (f->offset > last->offset)
9027 last = f;
9028 }
9029
9030 /* Selector offset and size. */
9031 params->selector_offset = first->offset / 8;
9032 params->selector_size = (last->offset + last->n_bits - first->offset) / 8;
9033
9034 /* Memory allocation. */
9035 params->selector_mask = calloc(1, params->selector_size);
9036 if (!params->selector_mask)
9037 goto error;
9038
9039 /* Selector mask. */
9040 for (i = 0; i < s->n_selector_fields; i++) {
9041 struct field *f = s->selector_fields[i];
9042 uint32_t start = (f->offset - first->offset) / 8;
9043 size_t size = f->n_bits / 8;
9044
9045 memset(¶ms->selector_mask[start], 0xFF, size);
9046 }
9047
9048 /* Member ID. */
9049 params->member_id_offset = s->member_id_field->offset / 8;
9050
9051 /* Maximum number of groups. */
9052 params->n_groups_max = s->n_groups_max;
9053
9054 /* Maximum number of members per group. */
9055 params->n_members_per_group_max = s->n_members_per_group_max;
9056
9057 return params;
9058
9059 error:
9060 selector_params_free(params);
9061 return NULL;
9062 }
9063
9064 static void
selector_build_free(struct rte_swx_pipeline * p)9065 selector_build_free(struct rte_swx_pipeline *p)
9066 {
9067 uint32_t i;
9068
9069 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9070 struct thread *t = &p->threads[i];
9071 uint32_t j;
9072
9073 if (!t->selectors)
9074 continue;
9075
9076 for (j = 0; j < p->n_selectors; j++) {
9077 struct selector_runtime *r = &t->selectors[j];
9078
9079 free(r->mailbox);
9080 }
9081
9082 free(t->selectors);
9083 t->selectors = NULL;
9084 }
9085
9086 free(p->selector_stats);
9087 p->selector_stats = NULL;
9088 }
9089
9090 static int
selector_build(struct rte_swx_pipeline * p)9091 selector_build(struct rte_swx_pipeline *p)
9092 {
9093 uint32_t i;
9094 int status = 0;
9095
9096 /* Per pipeline: selector statistics. */
9097 p->selector_stats = calloc(p->n_selectors, sizeof(struct selector_statistics));
9098 if (!p->selector_stats) {
9099 status = -ENOMEM;
9100 goto error;
9101 }
9102
9103 /* Per thread: selector run-time. */
9104 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9105 struct thread *t = &p->threads[i];
9106 struct selector *s;
9107
9108 t->selectors = calloc(p->n_selectors, sizeof(struct selector_runtime));
9109 if (!t->selectors) {
9110 status = -ENOMEM;
9111 goto error;
9112 }
9113
9114 TAILQ_FOREACH(s, &p->selectors, node) {
9115 struct selector_runtime *r = &t->selectors[s->id];
9116 uint64_t size;
9117
9118 /* r->mailbox. */
9119 size = rte_swx_table_selector_mailbox_size_get();
9120 if (size) {
9121 r->mailbox = calloc(1, size);
9122 if (!r->mailbox) {
9123 status = -ENOMEM;
9124 goto error;
9125 }
9126 }
9127
9128 /* r->group_id_buffer. */
9129 r->group_id_buffer = &t->structs[p->metadata_struct_id];
9130
9131 /* r->selector_buffer. */
9132 r->selector_buffer = s->selector_header ?
9133 &t->structs[s->selector_header->struct_id] :
9134 &t->structs[p->metadata_struct_id];
9135
9136 /* r->member_id_buffer. */
9137 r->member_id_buffer = &t->structs[p->metadata_struct_id];
9138 }
9139 }
9140
9141 return 0;
9142
9143 error:
9144 selector_build_free(p);
9145 return status;
9146 }
9147
9148 static void
selector_free(struct rte_swx_pipeline * p)9149 selector_free(struct rte_swx_pipeline *p)
9150 {
9151 selector_build_free(p);
9152
9153 /* Selector tables. */
9154 for ( ; ; ) {
9155 struct selector *elem;
9156
9157 elem = TAILQ_FIRST(&p->selectors);
9158 if (!elem)
9159 break;
9160
9161 TAILQ_REMOVE(&p->selectors, elem, node);
9162 free(elem->selector_fields);
9163 free(elem);
9164 }
9165 }
9166
9167 /*
9168 * Learner table.
9169 */
9170 static struct learner *
learner_find(struct rte_swx_pipeline * p,const char * name)9171 learner_find(struct rte_swx_pipeline *p, const char *name)
9172 {
9173 struct learner *l;
9174
9175 TAILQ_FOREACH(l, &p->learners, node)
9176 if (!strcmp(l->name, name))
9177 return l;
9178
9179 return NULL;
9180 }
9181
9182 static struct learner *
learner_find_by_id(struct rte_swx_pipeline * p,uint32_t id)9183 learner_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9184 {
9185 struct learner *l = NULL;
9186
9187 TAILQ_FOREACH(l, &p->learners, node)
9188 if (l->id == id)
9189 return l;
9190
9191 return NULL;
9192 }
9193
9194 static int
learner_match_fields_check(struct rte_swx_pipeline * p,struct rte_swx_pipeline_learner_params * params,struct header ** header)9195 learner_match_fields_check(struct rte_swx_pipeline *p,
9196 struct rte_swx_pipeline_learner_params *params,
9197 struct header **header)
9198 {
9199 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 if (!params->n_fields || !params->field_names)
9206 return -EINVAL;
9207
9208 /* Memory allocation. */
9209 offset = calloc(params->n_fields, sizeof(uint32_t));
9210 n_bits = calloc(params->n_fields, sizeof(uint32_t));
9211 if (!offset || !n_bits) {
9212 status = -ENOMEM;
9213 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 hf = header_field_parse(p, params->field_names[0], &h0);
9220 mf = metadata_field_parse(p, params->field_names[0]);
9221 if ((!hf && !mf) || (hf && hf->var_size)) {
9222 status = -EINVAL;
9223 goto end;
9224 }
9225
9226 offset[0] = h0 ? hf->offset : mf->offset;
9227 n_bits[0] = h0 ? hf->n_bits : mf->n_bits;
9228
9229 for (i = 1; i < params->n_fields; i++)
9230 if (h0) {
9231 struct header *h;
9232
9233 hf = header_field_parse(p, params->field_names[i], &h);
9234 if (!hf || (h->id != h0->id) || hf->var_size) {
9235 status = -EINVAL;
9236 goto end;
9237 }
9238
9239 offset[i] = hf->offset;
9240 n_bits[i] = hf->n_bits;
9241 } else {
9242 mf = metadata_field_parse(p, params->field_names[i]);
9243 if (!mf) {
9244 status = -EINVAL;
9245 goto end;
9246 }
9247
9248 offset[i] = mf->offset;
9249 n_bits[i] = mf->n_bits;
9250 }
9251
9252 /* Check that there are no duplicated match fields. */
9253 for (i = 0; i < params->n_fields; i++) {
9254 const char *field_name = params->field_names[i];
9255 uint32_t j;
9256
9257 for (j = i + 1; j < params->n_fields; j++)
9258 if (!strcmp(params->field_names[j], field_name)) {
9259 status = -EINVAL;
9260 goto end;
9261 }
9262 }
9263
9264 /* Check that the match fields are contiguous. */
9265 for (i = 0; i < params->n_fields; i++) {
9266 uint32_t offset_next = offset[i] + n_bits[i];
9267 uint32_t j;
9268
9269 for (j = 0; j < params->n_fields; j++)
9270 if (offset[j] == offset_next) {
9271 n_fields_with_valid_next++;
9272 break;
9273 }
9274 }
9275
9276 if (n_fields_with_valid_next != params->n_fields - 1) {
9277 status = -EINVAL;
9278 goto end;
9279 }
9280
9281 /* Return. */
9282 if (header)
9283 *header = h0;
9284
9285 end:
9286 free(offset);
9287 free(n_bits);
9288 return status;
9289 }
9290
9291 static int
learner_action_args_check(struct rte_swx_pipeline * p,struct action * a,const char * mf_name)9292 learner_action_args_check(struct rte_swx_pipeline *p, struct action *a, const char *mf_name)
9293 {
9294 struct struct_type *mst = p->metadata_st, *ast = a->st;
9295 struct field *mf, *af;
9296 uint32_t mf_pos, i;
9297
9298 if (!ast) {
9299 if (mf_name)
9300 return -EINVAL;
9301
9302 return 0;
9303 }
9304
9305 /* Check that mf_name is the name of a valid meta-data field. */
9306 CHECK_NAME(mf_name, EINVAL);
9307 mf = metadata_field_parse(p, mf_name);
9308 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 mf_pos = mf - mst->fields;
9314 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 for (i = 0; i < ast->n_fields; i++) {
9320 mf = &mst->fields[mf_pos + i];
9321 af = &ast->fields[i];
9322
9323 CHECK(mf->n_bits == af->n_bits, EINVAL);
9324 }
9325
9326 return 0;
9327 }
9328
9329 static int
learner_action_learning_check(struct rte_swx_pipeline * p,struct action * action,const char ** action_names,uint32_t n_actions)9330 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 for (i = 0; i < action->n_instructions; i++) {
9342 struct instruction *instr = &action->instructions[i];
9343 uint32_t found = 0, j;
9344
9345 if (instr->type != INSTR_LEARNER_LEARN)
9346 continue;
9347
9348 for (j = 0; j < n_actions; j++) {
9349 struct action *a;
9350
9351 a = action_find(p, action_names[j]);
9352 if (!a)
9353 return -EINVAL;
9354
9355 if (a->id == instr->learn.action_id)
9356 found = 1;
9357 }
9358
9359 if (!found)
9360 return -EINVAL;
9361 }
9362
9363 return 0;
9364 }
9365
9366 int
rte_swx_pipeline_learner_config(struct rte_swx_pipeline * p,const char * name,struct rte_swx_pipeline_learner_params * params,uint32_t size,uint32_t * timeout,uint32_t n_timeouts)9367 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 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 CHECK(p, EINVAL);
9382
9383 CHECK_NAME(name, EINVAL);
9384 CHECK(!table_find(p, name), EEXIST);
9385 CHECK(!selector_find(p, name), EEXIST);
9386 CHECK(!learner_find(p, name), EEXIST);
9387
9388 CHECK(params, EINVAL);
9389
9390 /* Match checks. */
9391 status = learner_match_fields_check(p, params, &header);
9392 if (status)
9393 return status;
9394
9395 /* Action checks. */
9396 CHECK(params->n_actions, EINVAL);
9397 CHECK(params->action_names, EINVAL);
9398 for (i = 0; i < params->n_actions; i++) {
9399 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 CHECK_NAME(action_name, EINVAL);
9405
9406 a = action_find(p, action_name);
9407 CHECK(a, EINVAL);
9408
9409 status = learner_action_learning_check(p,
9410 a,
9411 params->action_names,
9412 params->n_actions);
9413 if (status)
9414 return status;
9415
9416 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 if (params->action_is_for_table_entries)
9421 action_is_for_table_entries = params->action_is_for_table_entries[i];
9422 if (params->action_is_for_default_entry)
9423 action_is_for_default_entry = params->action_is_for_default_entry[i];
9424 CHECK(action_is_for_table_entries || action_is_for_default_entry, EINVAL);
9425 }
9426
9427 CHECK_NAME(params->default_action_name, EINVAL);
9428 for (i = 0; i < p->n_actions; i++)
9429 if (!strcmp(params->action_names[i],
9430 params->default_action_name))
9431 break;
9432 CHECK(i < params->n_actions, EINVAL);
9433 CHECK(!params->action_is_for_default_entry || params->action_is_for_default_entry[i],
9434 EINVAL);
9435
9436 default_action = action_find(p, params->default_action_name);
9437 CHECK((default_action->st && params->default_action_args) || !params->default_action_args,
9438 EINVAL);
9439
9440 /* Hash function checks. */
9441 if (params->hash_func_name) {
9442 hf = hash_func_find(p, params->hash_func_name);
9443 CHECK(hf, EINVAL);
9444 }
9445
9446 /* Any other checks. */
9447 CHECK(size, EINVAL);
9448 CHECK(timeout, EINVAL);
9449 CHECK(n_timeouts && (n_timeouts <= RTE_SWX_TABLE_LEARNER_N_KEY_TIMEOUTS_MAX), EINVAL);
9450
9451 /* Memory allocation. */
9452 l = calloc(1, sizeof(struct learner));
9453 if (!l) {
9454 status = -ENOMEM;
9455 goto error;
9456 }
9457
9458 l->fields = calloc(params->n_fields, sizeof(struct field *));
9459 if (!l->fields) {
9460 status = -ENOMEM;
9461 goto error;
9462 }
9463
9464 l->actions = calloc(params->n_actions, sizeof(struct action *));
9465 if (!l->actions) {
9466 status = -ENOMEM;
9467 goto error;
9468 }
9469
9470 if (action_data_size_max) {
9471 l->default_action_data = calloc(1, action_data_size_max);
9472 if (!l->default_action_data) {
9473 status = -ENOMEM;
9474 goto error;
9475 }
9476 }
9477
9478 l->action_is_for_table_entries = calloc(params->n_actions, sizeof(int));
9479 if (!l->action_is_for_table_entries) {
9480 status = -ENOMEM;
9481 goto error;
9482 }
9483
9484 l->action_is_for_default_entry = calloc(params->n_actions, sizeof(int));
9485 if (!l->action_is_for_default_entry) {
9486 status = -ENOMEM;
9487 goto error;
9488 }
9489
9490 /* Node initialization. */
9491 strcpy(l->name, name);
9492
9493 for (i = 0; i < params->n_fields; i++) {
9494 const char *field_name = params->field_names[i];
9495
9496 l->fields[i] = header ?
9497 header_field_parse(p, field_name, NULL) :
9498 metadata_field_parse(p, field_name);
9499 }
9500
9501 l->n_fields = params->n_fields;
9502
9503 l->header = header;
9504
9505 for (i = 0; i < params->n_actions; i++) {
9506 int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
9507
9508 if (params->action_is_for_table_entries)
9509 action_is_for_table_entries = params->action_is_for_table_entries[i];
9510 if (params->action_is_for_default_entry)
9511 action_is_for_default_entry = params->action_is_for_default_entry[i];
9512
9513 l->actions[i] = action_find(p, params->action_names[i]);
9514 l->action_is_for_table_entries[i] = action_is_for_table_entries;
9515 l->action_is_for_default_entry[i] = action_is_for_default_entry;
9516 }
9517
9518 l->default_action = default_action;
9519
9520 if (default_action->st) {
9521 status = action_args_parse(default_action,
9522 params->default_action_args,
9523 l->default_action_data);
9524 if (status)
9525 goto error;
9526 }
9527
9528 l->n_actions = params->n_actions;
9529
9530 l->default_action_is_const = params->default_action_is_const;
9531
9532 l->action_data_size_max = action_data_size_max;
9533
9534 l->hf = hf;
9535
9536 l->size = size;
9537
9538 for (i = 0; i < n_timeouts; i++)
9539 l->timeout[i] = timeout[i];
9540
9541 l->n_timeouts = n_timeouts;
9542
9543 l->id = p->n_learners;
9544
9545 /* Node add to tailq. */
9546 TAILQ_INSERT_TAIL(&p->learners, l, node);
9547 p->n_learners++;
9548
9549 return 0;
9550
9551 error:
9552 if (!l)
9553 return status;
9554
9555 free(l->action_is_for_default_entry);
9556 free(l->action_is_for_table_entries);
9557 free(l->default_action_data);
9558 free(l->actions);
9559 free(l->fields);
9560 free(l);
9561
9562 return status;
9563 }
9564
9565 static uint32_t
learner_params_offset_get(struct learner * l)9566 learner_params_offset_get(struct learner *l)
9567 {
9568 struct field *first;
9569 uint32_t i;
9570
9571 first = l->fields[0];
9572
9573 for (i = 1; i < l->n_fields; i++) {
9574 struct field *f = l->fields[i];
9575
9576 if (f->offset < first->offset)
9577 first = f;
9578 }
9579
9580 return first->offset / 8;
9581 }
9582
9583 static void
learner_params_free(struct rte_swx_table_learner_params * params)9584 learner_params_free(struct rte_swx_table_learner_params *params)
9585 {
9586 if (!params)
9587 return;
9588
9589 free(params->key_mask0);
9590
9591 free(params->key_timeout);
9592
9593 free(params);
9594 }
9595
9596 static struct rte_swx_table_learner_params *
learner_params_get(struct learner * l)9597 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 params = calloc(1, sizeof(struct rte_swx_table_learner_params));
9605 if (!params)
9606 goto error;
9607
9608 /* Find first (smallest offset) and last (biggest offset) match fields. */
9609 first = l->fields[0];
9610 last = l->fields[0];
9611
9612 for (i = 0; i < l->n_fields; i++) {
9613 struct field *f = l->fields[i];
9614
9615 if (f->offset < first->offset)
9616 first = f;
9617
9618 if (f->offset > last->offset)
9619 last = f;
9620 }
9621
9622 /* Key offset and size. */
9623 params->key_offset = first->offset / 8;
9624 params->key_size = (last->offset + last->n_bits - first->offset) / 8;
9625
9626 /* Memory allocation. */
9627 params->key_mask0 = calloc(1, params->key_size);
9628 if (!params->key_mask0)
9629 goto error;
9630
9631 /* Key mask. */
9632 for (i = 0; i < l->n_fields; i++) {
9633 struct field *f = l->fields[i];
9634 uint32_t start = (f->offset - first->offset) / 8;
9635 size_t size = f->n_bits / 8;
9636
9637 memset(¶ms->key_mask0[start], 0xFF, size);
9638 }
9639
9640 /* Action data size. */
9641 params->action_data_size = l->action_data_size_max;
9642
9643 /* Hash function. */
9644 params->hash_func = l->hf ? l->hf->func : NULL;
9645
9646 /* Maximum number of keys. */
9647 params->n_keys_max = l->size;
9648
9649 /* Memory allocation. */
9650 params->key_timeout = calloc(l->n_timeouts, sizeof(uint32_t));
9651 if (!params->key_timeout)
9652 goto error;
9653
9654 /* Timeout. */
9655 for (i = 0; i < l->n_timeouts; i++)
9656 params->key_timeout[i] = l->timeout[i];
9657
9658 params->n_key_timeouts = l->n_timeouts;
9659
9660 return params;
9661
9662 error:
9663 learner_params_free(params);
9664 return NULL;
9665 }
9666
9667 static void
learner_build_free(struct rte_swx_pipeline * p)9668 learner_build_free(struct rte_swx_pipeline *p)
9669 {
9670 uint32_t i;
9671
9672 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9673 struct thread *t = &p->threads[i];
9674 uint32_t j;
9675
9676 if (!t->learners)
9677 continue;
9678
9679 for (j = 0; j < p->n_learners; j++) {
9680 struct learner_runtime *r = &t->learners[j];
9681
9682 free(r->mailbox);
9683 }
9684
9685 free(t->learners);
9686 t->learners = NULL;
9687 }
9688
9689 if (p->learner_stats) {
9690 for (i = 0; i < p->n_learners; i++)
9691 free(p->learner_stats[i].n_pkts_action);
9692
9693 free(p->learner_stats);
9694 p->learner_stats = NULL;
9695 }
9696 }
9697
9698 static int
learner_build(struct rte_swx_pipeline * p)9699 learner_build(struct rte_swx_pipeline *p)
9700 {
9701 uint32_t i;
9702 int status = 0;
9703
9704 /* Per pipeline: learner statistics. */
9705 p->learner_stats = calloc(p->n_learners, sizeof(struct learner_statistics));
9706 CHECK(p->learner_stats, ENOMEM);
9707
9708 for (i = 0; i < p->n_learners; i++) {
9709 p->learner_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
9710 CHECK(p->learner_stats[i].n_pkts_action, ENOMEM);
9711 }
9712
9713 /* Per thread: learner run-time. */
9714 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9715 struct thread *t = &p->threads[i];
9716 struct learner *l;
9717
9718 t->learners = calloc(p->n_learners, sizeof(struct learner_runtime));
9719 if (!t->learners) {
9720 status = -ENOMEM;
9721 goto error;
9722 }
9723
9724 TAILQ_FOREACH(l, &p->learners, node) {
9725 struct learner_runtime *r = &t->learners[l->id];
9726 uint64_t size;
9727
9728 /* r->mailbox. */
9729 size = rte_swx_table_learner_mailbox_size_get();
9730 if (size) {
9731 r->mailbox = calloc(1, size);
9732 if (!r->mailbox) {
9733 status = -ENOMEM;
9734 goto error;
9735 }
9736 }
9737
9738 /* r->key. */
9739 r->key = l->header ?
9740 &t->structs[l->header->struct_id] :
9741 &t->structs[p->metadata_struct_id];
9742 }
9743 }
9744
9745 return 0;
9746
9747 error:
9748 learner_build_free(p);
9749 return status;
9750 }
9751
9752 static void
learner_free(struct rte_swx_pipeline * p)9753 learner_free(struct rte_swx_pipeline *p)
9754 {
9755 learner_build_free(p);
9756
9757 /* Learner tables. */
9758 for ( ; ; ) {
9759 struct learner *l;
9760
9761 l = TAILQ_FIRST(&p->learners);
9762 if (!l)
9763 break;
9764
9765 TAILQ_REMOVE(&p->learners, l, node);
9766 free(l->fields);
9767 free(l->actions);
9768 free(l->default_action_data);
9769 free(l);
9770 }
9771 }
9772
9773 /*
9774 * Table state.
9775 */
9776 static int
table_state_build(struct rte_swx_pipeline * p)9777 table_state_build(struct rte_swx_pipeline *p)
9778 {
9779 struct table *table;
9780 struct selector *s;
9781 struct learner *l;
9782
9783 p->table_state = calloc(p->n_tables + p->n_selectors + p->n_learners,
9784 sizeof(struct rte_swx_table_state));
9785 CHECK(p->table_state, ENOMEM);
9786
9787 TAILQ_FOREACH(table, &p->tables, node) {
9788 struct rte_swx_table_state *ts = &p->table_state[table->id];
9789
9790 if (table->type) {
9791 struct rte_swx_table_params *params;
9792
9793 /* ts->obj. */
9794 params = table_params_get(table);
9795 CHECK(params, ENOMEM);
9796
9797 ts->obj = table->type->ops.create(params,
9798 NULL,
9799 table->args,
9800 p->numa_node);
9801
9802 table_params_free(params);
9803 CHECK(ts->obj, ENODEV);
9804 }
9805
9806 /* ts->default_action_data. */
9807 if (table->action_data_size_max) {
9808 ts->default_action_data =
9809 malloc(table->action_data_size_max);
9810 CHECK(ts->default_action_data, ENOMEM);
9811
9812 memcpy(ts->default_action_data,
9813 table->default_action_data,
9814 table->action_data_size_max);
9815 }
9816
9817 /* ts->default_action_id. */
9818 ts->default_action_id = table->default_action->id;
9819 }
9820
9821 TAILQ_FOREACH(s, &p->selectors, node) {
9822 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 params = selector_table_params_get(s);
9827 CHECK(params, ENOMEM);
9828
9829 ts->obj = rte_swx_table_selector_create(params, NULL, p->numa_node);
9830
9831 selector_params_free(params);
9832 CHECK(ts->obj, ENODEV);
9833 }
9834
9835 TAILQ_FOREACH(l, &p->learners, node) {
9836 struct rte_swx_table_state *ts = &p->table_state[p->n_tables +
9837 p->n_selectors + l->id];
9838 struct rte_swx_table_learner_params *params;
9839
9840 /* ts->obj. */
9841 params = learner_params_get(l);
9842 CHECK(params, ENOMEM);
9843
9844 ts->obj = rte_swx_table_learner_create(params, p->numa_node);
9845 learner_params_free(params);
9846 CHECK(ts->obj, ENODEV);
9847
9848 /* ts->default_action_data. */
9849 if (l->action_data_size_max) {
9850 ts->default_action_data = malloc(l->action_data_size_max);
9851 CHECK(ts->default_action_data, ENOMEM);
9852
9853 memcpy(ts->default_action_data,
9854 l->default_action_data,
9855 l->action_data_size_max);
9856 }
9857
9858 /* ts->default_action_id. */
9859 ts->default_action_id = l->default_action->id;
9860 }
9861
9862 return 0;
9863 }
9864
9865 static void
table_state_build_free(struct rte_swx_pipeline * p)9866 table_state_build_free(struct rte_swx_pipeline *p)
9867 {
9868 uint32_t i;
9869
9870 if (!p->table_state)
9871 return;
9872
9873 for (i = 0; i < p->n_tables; i++) {
9874 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 if (table->type && ts->obj)
9879 table->type->ops.free(ts->obj);
9880
9881 /* ts->default_action_data. */
9882 free(ts->default_action_data);
9883 }
9884
9885 for (i = 0; i < p->n_selectors; i++) {
9886 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + i];
9887
9888 /* ts->obj. */
9889 rte_swx_table_selector_free(ts->obj);
9890 }
9891
9892 for (i = 0; i < p->n_learners; i++) {
9893 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + p->n_selectors + i];
9894
9895 /* ts->obj. */
9896 rte_swx_table_learner_free(ts->obj);
9897
9898 /* ts->default_action_data. */
9899 free(ts->default_action_data);
9900 }
9901
9902 free(p->table_state);
9903 p->table_state = NULL;
9904 }
9905
9906 static void
table_state_free(struct rte_swx_pipeline * p)9907 table_state_free(struct rte_swx_pipeline *p)
9908 {
9909 table_state_build_free(p);
9910 }
9911
9912 /*
9913 * Register array.
9914 */
9915 static struct regarray *
regarray_find(struct rte_swx_pipeline * p,const char * name)9916 regarray_find(struct rte_swx_pipeline *p, const char *name)
9917 {
9918 struct regarray *elem;
9919
9920 TAILQ_FOREACH(elem, &p->regarrays, node)
9921 if (!strcmp(elem->name, name))
9922 return elem;
9923
9924 return NULL;
9925 }
9926
9927 static struct regarray *
regarray_find_by_id(struct rte_swx_pipeline * p,uint32_t id)9928 regarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9929 {
9930 struct regarray *elem = NULL;
9931
9932 TAILQ_FOREACH(elem, &p->regarrays, node)
9933 if (elem->id == id)
9934 return elem;
9935
9936 return NULL;
9937 }
9938
9939 int
rte_swx_pipeline_regarray_config(struct rte_swx_pipeline * p,const char * name,uint32_t size,uint64_t init_val)9940 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 CHECK(p, EINVAL);
9948
9949 CHECK_NAME(name, EINVAL);
9950 CHECK(!regarray_find(p, name), EEXIST);
9951
9952 CHECK(size, EINVAL);
9953 size = rte_align32pow2(size);
9954
9955 /* Memory allocation. */
9956 r = calloc(1, sizeof(struct regarray));
9957 CHECK(r, ENOMEM);
9958
9959 /* Node initialization. */
9960 strcpy(r->name, name);
9961 r->init_val = init_val;
9962 r->size = size;
9963 r->id = p->n_regarrays;
9964
9965 /* Node add to tailq. */
9966 TAILQ_INSERT_TAIL(&p->regarrays, r, node);
9967 p->n_regarrays++;
9968
9969 return 0;
9970 }
9971
9972 static int
regarray_build(struct rte_swx_pipeline * p)9973 regarray_build(struct rte_swx_pipeline *p)
9974 {
9975 struct regarray *regarray;
9976
9977 if (!p->n_regarrays)
9978 return 0;
9979
9980 p->regarray_runtime = calloc(p->n_regarrays, sizeof(struct regarray_runtime));
9981 CHECK(p->regarray_runtime, ENOMEM);
9982
9983 TAILQ_FOREACH(regarray, &p->regarrays, node) {
9984 struct regarray_runtime *r = &p->regarray_runtime[regarray->id];
9985 uint32_t i;
9986
9987 r->regarray = env_malloc(regarray->size * sizeof(uint64_t),
9988 RTE_CACHE_LINE_SIZE,
9989 p->numa_node);
9990 CHECK(r->regarray, ENOMEM);
9991
9992 if (regarray->init_val)
9993 for (i = 0; i < regarray->size; i++)
9994 r->regarray[i] = regarray->init_val;
9995
9996 r->size_mask = regarray->size - 1;
9997 }
9998
9999 return 0;
10000 }
10001
10002 static void
regarray_build_free(struct rte_swx_pipeline * p)10003 regarray_build_free(struct rte_swx_pipeline *p)
10004 {
10005 uint32_t i;
10006
10007 if (!p->regarray_runtime)
10008 return;
10009
10010 for (i = 0; i < p->n_regarrays; i++) {
10011 struct regarray *regarray = regarray_find_by_id(p, i);
10012 struct regarray_runtime *r = &p->regarray_runtime[i];
10013
10014 env_free(r->regarray, regarray->size * sizeof(uint64_t));
10015 }
10016
10017 free(p->regarray_runtime);
10018 p->regarray_runtime = NULL;
10019 }
10020
10021 static void
regarray_free(struct rte_swx_pipeline * p)10022 regarray_free(struct rte_swx_pipeline *p)
10023 {
10024 regarray_build_free(p);
10025
10026 for ( ; ; ) {
10027 struct regarray *elem;
10028
10029 elem = TAILQ_FIRST(&p->regarrays);
10030 if (!elem)
10031 break;
10032
10033 TAILQ_REMOVE(&p->regarrays, elem, node);
10034 free(elem);
10035 }
10036 }
10037
10038 /*
10039 * Meter array.
10040 */
10041 static struct meter_profile *
meter_profile_find(struct rte_swx_pipeline * p,const char * name)10042 meter_profile_find(struct rte_swx_pipeline *p, const char *name)
10043 {
10044 struct meter_profile *elem;
10045
10046 TAILQ_FOREACH(elem, &p->meter_profiles, node)
10047 if (!strcmp(elem->name, name))
10048 return elem;
10049
10050 return NULL;
10051 }
10052
10053 static struct metarray *
metarray_find(struct rte_swx_pipeline * p,const char * name)10054 metarray_find(struct rte_swx_pipeline *p, const char *name)
10055 {
10056 struct metarray *elem;
10057
10058 TAILQ_FOREACH(elem, &p->metarrays, node)
10059 if (!strcmp(elem->name, name))
10060 return elem;
10061
10062 return NULL;
10063 }
10064
10065 static struct metarray *
metarray_find_by_id(struct rte_swx_pipeline * p,uint32_t id)10066 metarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
10067 {
10068 struct metarray *elem = NULL;
10069
10070 TAILQ_FOREACH(elem, &p->metarrays, node)
10071 if (elem->id == id)
10072 return elem;
10073
10074 return NULL;
10075 }
10076
10077 int
rte_swx_pipeline_metarray_config(struct rte_swx_pipeline * p,const char * name,uint32_t size)10078 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 CHECK(p, EINVAL);
10085
10086 CHECK_NAME(name, EINVAL);
10087 CHECK(!metarray_find(p, name), EEXIST);
10088
10089 CHECK(size, EINVAL);
10090 size = rte_align32pow2(size);
10091
10092 /* Memory allocation. */
10093 m = calloc(1, sizeof(struct metarray));
10094 CHECK(m, ENOMEM);
10095
10096 /* Node initialization. */
10097 strcpy(m->name, name);
10098 m->size = size;
10099 m->id = p->n_metarrays;
10100
10101 /* Node add to tailq. */
10102 TAILQ_INSERT_TAIL(&p->metarrays, m, node);
10103 p->n_metarrays++;
10104
10105 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
meter_init(struct meter * m)10126 meter_init(struct meter *m)
10127 {
10128 memset(m, 0, sizeof(struct meter));
10129 rte_meter_trtcm_config(&m->m, &meter_profile_default.profile);
10130 m->profile = &meter_profile_default;
10131 m->color_mask = RTE_COLOR_GREEN;
10132
10133 meter_profile_default.n_users++;
10134 }
10135
10136 static int
metarray_build(struct rte_swx_pipeline * p)10137 metarray_build(struct rte_swx_pipeline *p)
10138 {
10139 struct metarray *m;
10140
10141 if (!p->n_metarrays)
10142 return 0;
10143
10144 p->metarray_runtime = calloc(p->n_metarrays, sizeof(struct metarray_runtime));
10145 CHECK(p->metarray_runtime, ENOMEM);
10146
10147 TAILQ_FOREACH(m, &p->metarrays, node) {
10148 struct metarray_runtime *r = &p->metarray_runtime[m->id];
10149 uint32_t i;
10150
10151 r->metarray = env_malloc(m->size * sizeof(struct meter),
10152 RTE_CACHE_LINE_SIZE,
10153 p->numa_node);
10154 CHECK(r->metarray, ENOMEM);
10155
10156 for (i = 0; i < m->size; i++)
10157 meter_init(&r->metarray[i]);
10158
10159 r->size_mask = m->size - 1;
10160 }
10161
10162 return 0;
10163 }
10164
10165 static void
metarray_build_free(struct rte_swx_pipeline * p)10166 metarray_build_free(struct rte_swx_pipeline *p)
10167 {
10168 uint32_t i;
10169
10170 if (!p->metarray_runtime)
10171 return;
10172
10173 for (i = 0; i < p->n_metarrays; i++) {
10174 struct metarray *m = metarray_find_by_id(p, i);
10175 struct metarray_runtime *r = &p->metarray_runtime[i];
10176
10177 env_free(r->metarray, m->size * sizeof(struct meter));
10178 }
10179
10180 free(p->metarray_runtime);
10181 p->metarray_runtime = NULL;
10182 }
10183
10184 static void
metarray_free(struct rte_swx_pipeline * p)10185 metarray_free(struct rte_swx_pipeline *p)
10186 {
10187 metarray_build_free(p);
10188
10189 /* Meter arrays. */
10190 for ( ; ; ) {
10191 struct metarray *elem;
10192
10193 elem = TAILQ_FIRST(&p->metarrays);
10194 if (!elem)
10195 break;
10196
10197 TAILQ_REMOVE(&p->metarrays, elem, node);
10198 free(elem);
10199 }
10200
10201 /* Meter profiles. */
10202 for ( ; ; ) {
10203 struct meter_profile *elem;
10204
10205 elem = TAILQ_FIRST(&p->meter_profiles);
10206 if (!elem)
10207 break;
10208
10209 TAILQ_REMOVE(&p->meter_profiles, elem, node);
10210 free(elem);
10211 }
10212 }
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
EAL_REGISTER_TAILQ(rte_swx_pipeline_tailq)10225 EAL_REGISTER_TAILQ(rte_swx_pipeline_tailq)
10226
10227 struct rte_swx_pipeline *
10228 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 if (!name || !name[0] || (strnlen(name, RTE_SWX_NAME_SIZE) >= RTE_SWX_NAME_SIZE))
10234 return NULL;
10235
10236 pipeline_list = RTE_TAILQ_CAST(rte_swx_pipeline_tailq.head, rte_swx_pipeline_list);
10237
10238 rte_mcfg_tailq_read_lock();
10239
10240 TAILQ_FOREACH(te, pipeline_list, next) {
10241 struct rte_swx_pipeline *p = (struct rte_swx_pipeline *)te->data;
10242
10243 if (!strncmp(name, p->name, sizeof(p->name))) {
10244 rte_mcfg_tailq_read_unlock();
10245 return p;
10246 }
10247 }
10248
10249 rte_mcfg_tailq_read_unlock();
10250 return NULL;
10251 }
10252
10253 static int
pipeline_register(struct rte_swx_pipeline * p)10254 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 pipeline_list = RTE_TAILQ_CAST(rte_swx_pipeline_tailq.head, rte_swx_pipeline_list);
10260
10261 rte_mcfg_tailq_write_lock();
10262
10263 TAILQ_FOREACH(te, pipeline_list, next) {
10264 struct rte_swx_pipeline *pipeline = (struct rte_swx_pipeline *)te->data;
10265
10266 if (!strncmp(p->name, pipeline->name, sizeof(p->name))) {
10267 rte_mcfg_tailq_write_unlock();
10268 return -EEXIST;
10269 }
10270 }
10271
10272 te = calloc(1, sizeof(struct rte_tailq_entry));
10273 if (!te) {
10274 rte_mcfg_tailq_write_unlock();
10275 return -ENOMEM;
10276 }
10277
10278 te->data = (void *)p;
10279 TAILQ_INSERT_TAIL(pipeline_list, te, next);
10280 rte_mcfg_tailq_write_unlock();
10281 return 0;
10282 }
10283
10284 static void
pipeline_unregister(struct rte_swx_pipeline * p)10285 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 pipeline_list = RTE_TAILQ_CAST(rte_swx_pipeline_tailq.head, rte_swx_pipeline_list);
10291
10292 rte_mcfg_tailq_write_lock();
10293
10294 TAILQ_FOREACH(te, pipeline_list, next) {
10295 if (te->data == (void *)p) {
10296 TAILQ_REMOVE(pipeline_list, te, next);
10297 rte_mcfg_tailq_write_unlock();
10298 free(te);
10299 return;
10300 }
10301 }
10302
10303 rte_mcfg_tailq_write_unlock();
10304 }
10305
10306 void
rte_swx_pipeline_free(struct rte_swx_pipeline * p)10307 rte_swx_pipeline_free(struct rte_swx_pipeline *p)
10308 {
10309 void *lib;
10310
10311 if (!p)
10312 return;
10313
10314 if (p->name[0])
10315 pipeline_unregister(p);
10316
10317 lib = p->lib;
10318
10319 free(p->instruction_data);
10320 free(p->instructions);
10321
10322 metarray_free(p);
10323 regarray_free(p);
10324 table_state_free(p);
10325 learner_free(p);
10326 selector_free(p);
10327 table_free(p);
10328 action_free(p);
10329 instruction_table_free(p);
10330 metadata_free(p);
10331 header_free(p);
10332 rss_free(p);
10333 hash_func_free(p);
10334 extern_func_free(p);
10335 extern_obj_free(p);
10336 mirroring_free(p);
10337 port_out_free(p);
10338 port_in_free(p);
10339 struct_free(p);
10340
10341 free(p);
10342
10343 if (lib)
10344 dlclose(lib);
10345 }
10346
10347 static int
port_in_types_register(struct rte_swx_pipeline * p)10348 port_in_types_register(struct rte_swx_pipeline *p)
10349 {
10350 int status;
10351
10352 status = rte_swx_pipeline_port_in_type_register(p,
10353 "ethdev",
10354 &rte_swx_port_ethdev_reader_ops);
10355 if (status)
10356 return status;
10357
10358 status = rte_swx_pipeline_port_in_type_register(p,
10359 "ring",
10360 &rte_swx_port_ring_reader_ops);
10361 if (status)
10362 return status;
10363
10364 #ifdef RTE_PORT_PCAP
10365 status = rte_swx_pipeline_port_in_type_register(p,
10366 "source",
10367 &rte_swx_port_source_ops);
10368 if (status)
10369 return status;
10370 #endif
10371
10372 status = rte_swx_pipeline_port_in_type_register(p,
10373 "fd",
10374 &rte_swx_port_fd_reader_ops);
10375 if (status)
10376 return status;
10377
10378 return 0;
10379 }
10380
10381 static int
port_out_types_register(struct rte_swx_pipeline * p)10382 port_out_types_register(struct rte_swx_pipeline *p)
10383 {
10384 int status;
10385
10386 status = rte_swx_pipeline_port_out_type_register(p,
10387 "ethdev",
10388 &rte_swx_port_ethdev_writer_ops);
10389 if (status)
10390 return status;
10391
10392 status = rte_swx_pipeline_port_out_type_register(p,
10393 "ring",
10394 &rte_swx_port_ring_writer_ops);
10395 if (status)
10396 return status;
10397
10398 status = rte_swx_pipeline_port_out_type_register(p,
10399 "sink",
10400 &rte_swx_port_sink_ops);
10401 if (status)
10402 return status;
10403
10404 status = rte_swx_pipeline_port_out_type_register(p,
10405 "fd",
10406 &rte_swx_port_fd_writer_ops);
10407 if (status)
10408 return status;
10409
10410 return 0;
10411 }
10412
10413 static int
table_types_register(struct rte_swx_pipeline * p)10414 table_types_register(struct rte_swx_pipeline *p)
10415 {
10416 int status;
10417
10418 status = rte_swx_pipeline_table_type_register(p,
10419 "exact",
10420 RTE_SWX_TABLE_MATCH_EXACT,
10421 &rte_swx_table_exact_match_ops);
10422 if (status)
10423 return status;
10424
10425 status = rte_swx_pipeline_table_type_register(p,
10426 "wildcard",
10427 RTE_SWX_TABLE_MATCH_WILDCARD,
10428 &rte_swx_table_wildcard_match_ops);
10429 if (status)
10430 return status;
10431
10432 return 0;
10433 }
10434
10435 static int
hash_funcs_register(struct rte_swx_pipeline * p)10436 hash_funcs_register(struct rte_swx_pipeline *p)
10437 {
10438 int status;
10439
10440 status = rte_swx_pipeline_hash_func_register(p, "jhash", rte_jhash);
10441 if (status)
10442 return status;
10443
10444 status = rte_swx_pipeline_hash_func_register(p, "crc32", rte_hash_crc);
10445 if (status)
10446 return status;
10447
10448 return 0;
10449 }
10450
10451 int
rte_swx_pipeline_config(struct rte_swx_pipeline ** p,const char * name,int numa_node)10452 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 CHECK(p, EINVAL);
10459 CHECK(!name || (strnlen(name, RTE_SWX_NAME_SIZE) < RTE_SWX_NAME_SIZE), EINVAL);
10460
10461 /* Memory allocation. */
10462 pipeline = calloc(1, sizeof(struct rte_swx_pipeline));
10463 if (!pipeline) {
10464 status = -ENOMEM;
10465 goto error;
10466 }
10467
10468 /* Initialization. */
10469 if (name)
10470 strcpy(pipeline->name, name);
10471
10472 TAILQ_INIT(&pipeline->struct_types);
10473 TAILQ_INIT(&pipeline->port_in_types);
10474 TAILQ_INIT(&pipeline->ports_in);
10475 TAILQ_INIT(&pipeline->port_out_types);
10476 TAILQ_INIT(&pipeline->ports_out);
10477 TAILQ_INIT(&pipeline->extern_types);
10478 TAILQ_INIT(&pipeline->extern_objs);
10479 TAILQ_INIT(&pipeline->extern_funcs);
10480 TAILQ_INIT(&pipeline->hash_funcs);
10481 TAILQ_INIT(&pipeline->rss);
10482 TAILQ_INIT(&pipeline->headers);
10483 TAILQ_INIT(&pipeline->actions);
10484 TAILQ_INIT(&pipeline->table_types);
10485 TAILQ_INIT(&pipeline->tables);
10486 TAILQ_INIT(&pipeline->selectors);
10487 TAILQ_INIT(&pipeline->learners);
10488 TAILQ_INIT(&pipeline->regarrays);
10489 TAILQ_INIT(&pipeline->meter_profiles);
10490 TAILQ_INIT(&pipeline->metarrays);
10491
10492 pipeline->n_structs = 1; /* Struct 0 is reserved for action_data. */
10493 pipeline->n_mirroring_slots = RTE_SWX_PACKET_MIRRORING_SLOTS_DEFAULT;
10494 pipeline->n_mirroring_sessions = RTE_SWX_PACKET_MIRRORING_SESSIONS_DEFAULT;
10495 pipeline->numa_node = numa_node;
10496
10497 status = port_in_types_register(pipeline);
10498 if (status)
10499 goto error;
10500
10501 status = port_out_types_register(pipeline);
10502 if (status)
10503 goto error;
10504
10505 status = table_types_register(pipeline);
10506 if (status)
10507 goto error;
10508
10509 status = hash_funcs_register(pipeline);
10510 if (status)
10511 goto error;
10512
10513 if (pipeline->name[0]) {
10514 status = pipeline_register(pipeline);
10515 if (status)
10516 goto error;
10517 }
10518
10519 *p = pipeline;
10520 return 0;
10521
10522 error:
10523 rte_swx_pipeline_free(pipeline);
10524 return status;
10525 }
10526
10527 int
rte_swx_pipeline_instructions_config(struct rte_swx_pipeline * p,const char ** instructions,uint32_t n_instructions)10528 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 err = instruction_config(p, NULL, instructions, n_instructions);
10536 if (err)
10537 return err;
10538
10539 /* Thread instruction pointer reset. */
10540 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
rte_swx_pipeline_build(struct rte_swx_pipeline * p)10550 rte_swx_pipeline_build(struct rte_swx_pipeline *p)
10551 {
10552 struct rte_swx_port_sink_params drop_port_params = {
10553 .file_name = NULL,
10554 };
10555 int status;
10556
10557 CHECK(p, EINVAL);
10558 CHECK(p->build_done == 0, EEXIST);
10559
10560 status = port_in_build(p);
10561 if (status)
10562 goto error;
10563
10564 /* Drop port. */
10565 status = rte_swx_pipeline_port_out_config(p,
10566 p->n_ports_out,
10567 "sink",
10568 &drop_port_params);
10569 if (status)
10570 goto error;
10571
10572 status = port_out_build(p);
10573 if (status)
10574 goto error;
10575
10576 status = mirroring_build(p);
10577 if (status)
10578 goto error;
10579
10580 status = struct_build(p);
10581 if (status)
10582 goto error;
10583
10584 status = extern_obj_build(p);
10585 if (status)
10586 goto error;
10587
10588 status = extern_func_build(p);
10589 if (status)
10590 goto error;
10591
10592 status = hash_func_build(p);
10593 if (status)
10594 goto error;
10595
10596 status = rss_build(p);
10597 if (status)
10598 goto error;
10599
10600 status = header_build(p);
10601 if (status)
10602 goto error;
10603
10604 status = metadata_build(p);
10605 if (status)
10606 goto error;
10607
10608 status = instruction_table_build(p);
10609 if (status)
10610 goto error;
10611
10612 status = action_build(p);
10613 if (status)
10614 goto error;
10615
10616 status = table_build(p);
10617 if (status)
10618 goto error;
10619
10620 status = selector_build(p);
10621 if (status)
10622 goto error;
10623
10624 status = learner_build(p);
10625 if (status)
10626 goto error;
10627
10628 status = table_state_build(p);
10629 if (status)
10630 goto error;
10631
10632 status = regarray_build(p);
10633 if (status)
10634 goto error;
10635
10636 status = metarray_build(p);
10637 if (status)
10638 goto error;
10639
10640 p->build_done = 1;
10641
10642 return 0;
10643
10644 error:
10645 metarray_build_free(p);
10646 regarray_build_free(p);
10647 table_state_build_free(p);
10648 learner_build_free(p);
10649 selector_build_free(p);
10650 table_build_free(p);
10651 action_build_free(p);
10652 instruction_table_build_free(p);
10653 metadata_build_free(p);
10654 header_build_free(p);
10655 rss_build_free(p);
10656 hash_func_build_free(p);
10657 extern_func_build_free(p);
10658 extern_obj_build_free(p);
10659 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
rte_swx_pipeline_run(struct rte_swx_pipeline * p,uint32_t n_instructions)10668 rte_swx_pipeline_run(struct rte_swx_pipeline *p, uint32_t n_instructions)
10669 {
10670 uint32_t i;
10671
10672 for (i = 0; i < n_instructions; i++)
10673 instr_exec(p);
10674 }
10675
10676 void
rte_swx_pipeline_flush(struct rte_swx_pipeline * p)10677 rte_swx_pipeline_flush(struct rte_swx_pipeline *p)
10678 {
10679 uint32_t i;
10680
10681 for (i = 0; i < p->n_ports_out; i++) {
10682 struct port_out_runtime *port = &p->out[i];
10683
10684 if (port->flush)
10685 port->flush(port->obj);
10686 }
10687 }
10688
10689 /*
10690 * Control.
10691 */
10692 int
rte_swx_ctl_pipeline_info_get(struct rte_swx_pipeline * p,struct rte_swx_ctl_pipeline_info * pipeline)10693 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 if (!p || !pipeline)
10701 return -EINVAL;
10702
10703 TAILQ_FOREACH(action, &p->actions, node)
10704 n_actions++;
10705
10706 TAILQ_FOREACH(table, &p->tables, node)
10707 n_tables++;
10708
10709 strcpy(pipeline->name, p->name);
10710 pipeline->n_ports_in = p->n_ports_in;
10711 pipeline->n_ports_out = p->n_ports_out;
10712 pipeline->n_mirroring_slots = p->n_mirroring_slots;
10713 pipeline->n_mirroring_sessions = p->n_mirroring_sessions;
10714 pipeline->n_actions = n_actions;
10715 pipeline->n_tables = n_tables;
10716 pipeline->n_selectors = p->n_selectors;
10717 pipeline->n_learners = p->n_learners;
10718 pipeline->n_regarrays = p->n_regarrays;
10719 pipeline->n_metarrays = p->n_metarrays;
10720 pipeline->n_rss = p->n_rss;
10721
10722 return 0;
10723 }
10724
10725 int
rte_swx_ctl_pipeline_numa_node_get(struct rte_swx_pipeline * p,int * numa_node)10726 rte_swx_ctl_pipeline_numa_node_get(struct rte_swx_pipeline *p, int *numa_node)
10727 {
10728 if (!p || !numa_node)
10729 return -EINVAL;
10730
10731 *numa_node = p->numa_node;
10732 return 0;
10733 }
10734
10735 int
rte_swx_ctl_action_info_get(struct rte_swx_pipeline * p,uint32_t action_id,struct rte_swx_ctl_action_info * action)10736 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 if (!p || (action_id >= p->n_actions) || !action)
10743 return -EINVAL;
10744
10745 a = action_find_by_id(p, action_id);
10746 if (!a)
10747 return -EINVAL;
10748
10749 strcpy(action->name, a->name);
10750 action->n_args = a->st ? a->st->n_fields : 0;
10751 return 0;
10752 }
10753
10754 int
rte_swx_ctl_action_arg_info_get(struct rte_swx_pipeline * p,uint32_t action_id,uint32_t action_arg_id,struct rte_swx_ctl_action_arg_info * action_arg)10755 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 if (!p || (action_id >= p->n_actions) || !action_arg)
10764 return -EINVAL;
10765
10766 a = action_find_by_id(p, action_id);
10767 if (!a || !a->st || (action_arg_id >= a->st->n_fields))
10768 return -EINVAL;
10769
10770 arg = &a->st->fields[action_arg_id];
10771 strcpy(action_arg->name, arg->name);
10772 action_arg->n_bits = arg->n_bits;
10773 action_arg->is_network_byte_order = a->args_endianness[action_arg_id];
10774
10775 return 0;
10776 }
10777
10778 int
rte_swx_ctl_table_info_get(struct rte_swx_pipeline * p,uint32_t table_id,struct rte_swx_ctl_table_info * table)10779 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 if (!p || !table)
10786 return -EINVAL;
10787
10788 t = table_find_by_id(p, table_id);
10789 if (!t)
10790 return -EINVAL;
10791
10792 strcpy(table->name, t->name);
10793 strcpy(table->args, t->args);
10794 table->n_match_fields = t->n_fields;
10795 table->n_actions = t->n_actions;
10796 table->default_action_is_const = t->default_action_is_const;
10797 table->hash_func = t->hf ? t->hf->func : NULL;
10798 table->size = t->size;
10799 return 0;
10800 }
10801
10802 int
rte_swx_ctl_table_match_field_info_get(struct rte_swx_pipeline * p,uint32_t table_id,uint32_t match_field_id,struct rte_swx_ctl_table_match_field_info * match_field)10803 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 if (!p || (table_id >= p->n_tables) || !match_field)
10812 return -EINVAL;
10813
10814 t = table_find_by_id(p, table_id);
10815 if (!t || (match_field_id >= t->n_fields))
10816 return -EINVAL;
10817
10818 f = &t->fields[match_field_id];
10819 match_field->match_type = f->match_type;
10820 match_field->is_header = t->header ? 1 : 0;
10821 match_field->n_bits = f->field->n_bits;
10822 match_field->offset = f->field->offset;
10823
10824 return 0;
10825 }
10826
10827 int
rte_swx_ctl_table_action_info_get(struct rte_swx_pipeline * p,uint32_t table_id,uint32_t table_action_id,struct rte_swx_ctl_table_action_info * table_action)10828 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 if (!p || (table_id >= p->n_tables) || !table_action)
10836 return -EINVAL;
10837
10838 t = table_find_by_id(p, table_id);
10839 if (!t || (table_action_id >= t->n_actions))
10840 return -EINVAL;
10841
10842 table_action->action_id = t->actions[table_action_id]->id;
10843
10844 table_action->action_is_for_table_entries = t->action_is_for_table_entries[table_action_id];
10845 table_action->action_is_for_default_entry = t->action_is_for_default_entry[table_action_id];
10846
10847 return 0;
10848 }
10849
10850 int
rte_swx_ctl_table_ops_get(struct rte_swx_pipeline * p,uint32_t table_id,struct rte_swx_table_ops * table_ops,int * is_stub)10851 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 if (!p || (table_id >= p->n_tables))
10859 return -EINVAL;
10860
10861 t = table_find_by_id(p, table_id);
10862 if (!t)
10863 return -EINVAL;
10864
10865 if (t->type) {
10866 if (table_ops)
10867 memcpy(table_ops, &t->type->ops, sizeof(*table_ops));
10868 *is_stub = 0;
10869 } else {
10870 *is_stub = 1;
10871 }
10872
10873 return 0;
10874 }
10875
10876 int
rte_swx_ctl_selector_info_get(struct rte_swx_pipeline * p,uint32_t selector_id,struct rte_swx_ctl_selector_info * selector)10877 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 if (!p || !selector)
10884 return -EINVAL;
10885
10886 s = selector_find_by_id(p, selector_id);
10887 if (!s)
10888 return -EINVAL;
10889
10890 strcpy(selector->name, s->name);
10891
10892 selector->n_selector_fields = s->n_selector_fields;
10893 selector->n_groups_max = s->n_groups_max;
10894 selector->n_members_per_group_max = s->n_members_per_group_max;
10895
10896 return 0;
10897 }
10898
10899 int
rte_swx_ctl_selector_group_id_field_info_get(struct rte_swx_pipeline * p,uint32_t selector_id,struct rte_swx_ctl_table_match_field_info * field)10900 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 if (!p || (selector_id >= p->n_selectors) || !field)
10907 return -EINVAL;
10908
10909 s = selector_find_by_id(p, selector_id);
10910 if (!s)
10911 return -EINVAL;
10912
10913 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10914 field->is_header = 0;
10915 field->n_bits = s->group_id_field->n_bits;
10916 field->offset = s->group_id_field->offset;
10917
10918 return 0;
10919 }
10920
10921 int
rte_swx_ctl_selector_field_info_get(struct rte_swx_pipeline * p,uint32_t selector_id,uint32_t selector_field_id,struct rte_swx_ctl_table_match_field_info * field)10922 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 if (!p || (selector_id >= p->n_selectors) || !field)
10931 return -EINVAL;
10932
10933 s = selector_find_by_id(p, selector_id);
10934 if (!s || (selector_field_id >= s->n_selector_fields))
10935 return -EINVAL;
10936
10937 f = s->selector_fields[selector_field_id];
10938 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10939 field->is_header = s->selector_header ? 1 : 0;
10940 field->n_bits = f->n_bits;
10941 field->offset = f->offset;
10942
10943 return 0;
10944 }
10945
10946 int
rte_swx_ctl_selector_member_id_field_info_get(struct rte_swx_pipeline * p,uint32_t selector_id,struct rte_swx_ctl_table_match_field_info * field)10947 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 if (!p || (selector_id >= p->n_selectors) || !field)
10954 return -EINVAL;
10955
10956 s = selector_find_by_id(p, selector_id);
10957 if (!s)
10958 return -EINVAL;
10959
10960 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10961 field->is_header = 0;
10962 field->n_bits = s->member_id_field->n_bits;
10963 field->offset = s->member_id_field->offset;
10964
10965 return 0;
10966 }
10967
10968 int
rte_swx_ctl_learner_info_get(struct rte_swx_pipeline * p,uint32_t learner_id,struct rte_swx_ctl_learner_info * learner)10969 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 if (!p || !learner)
10976 return -EINVAL;
10977
10978 l = learner_find_by_id(p, learner_id);
10979 if (!l)
10980 return -EINVAL;
10981
10982 strcpy(learner->name, l->name);
10983
10984 learner->n_match_fields = l->n_fields;
10985 learner->n_actions = l->n_actions;
10986 learner->default_action_is_const = l->default_action_is_const;
10987 learner->size = l->size;
10988 learner->n_key_timeouts = l->n_timeouts;
10989
10990 return 0;
10991 }
10992
10993 int
rte_swx_ctl_learner_match_field_info_get(struct rte_swx_pipeline * p,uint32_t learner_id,uint32_t match_field_id,struct rte_swx_ctl_table_match_field_info * match_field)10994 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 if (!p || (learner_id >= p->n_learners) || !match_field)
11003 return -EINVAL;
11004
11005 l = learner_find_by_id(p, learner_id);
11006 if (!l || (match_field_id >= l->n_fields))
11007 return -EINVAL;
11008
11009 f = l->fields[match_field_id];
11010 match_field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
11011 match_field->is_header = l->header ? 1 : 0;
11012 match_field->n_bits = f->n_bits;
11013 match_field->offset = f->offset;
11014
11015 return 0;
11016 }
11017
11018 int
rte_swx_ctl_learner_action_info_get(struct rte_swx_pipeline * p,uint32_t learner_id,uint32_t learner_action_id,struct rte_swx_ctl_table_action_info * learner_action)11019 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 if (!p || (learner_id >= p->n_learners) || !learner_action)
11027 return -EINVAL;
11028
11029 l = learner_find_by_id(p, learner_id);
11030 if (!l || (learner_action_id >= l->n_actions))
11031 return -EINVAL;
11032
11033 learner_action->action_id = l->actions[learner_action_id]->id;
11034
11035 learner_action->action_is_for_table_entries =
11036 l->action_is_for_table_entries[learner_action_id];
11037
11038 learner_action->action_is_for_default_entry =
11039 l->action_is_for_default_entry[learner_action_id];
11040
11041 return 0;
11042 }
11043
11044 int
rte_swx_ctl_pipeline_learner_timeout_get(struct rte_swx_pipeline * p,uint32_t learner_id,uint32_t timeout_id,uint32_t * timeout)11045 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 if (!p || (learner_id >= p->n_learners) || !timeout)
11053 return -EINVAL;
11054
11055 l = learner_find_by_id(p, learner_id);
11056 if (!l || (timeout_id >= l->n_timeouts))
11057 return -EINVAL;
11058
11059 *timeout = l->timeout[timeout_id];
11060 return 0;
11061 }
11062
11063 int
rte_swx_ctl_pipeline_learner_timeout_set(struct rte_swx_pipeline * p,uint32_t learner_id,uint32_t timeout_id,uint32_t timeout)11064 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 if (!p || (learner_id >= p->n_learners) || !timeout)
11074 return -EINVAL;
11075
11076 l = learner_find_by_id(p, learner_id);
11077 if (!l || (timeout_id >= l->n_timeouts))
11078 return -EINVAL;
11079
11080 if (!p->build_done)
11081 return -EINVAL;
11082
11083 ts = &p->table_state[p->n_tables + p->n_selectors + l->id];
11084
11085 status = rte_swx_table_learner_timeout_update(ts->obj, timeout_id, timeout);
11086 if (status)
11087 return -EINVAL;
11088
11089 l->timeout[timeout_id] = timeout;
11090
11091 return 0;
11092 }
11093
11094 int
rte_swx_pipeline_table_state_get(struct rte_swx_pipeline * p,struct rte_swx_table_state ** table_state)11095 rte_swx_pipeline_table_state_get(struct rte_swx_pipeline *p,
11096 struct rte_swx_table_state **table_state)
11097 {
11098 if (!p || !table_state || !p->build_done)
11099 return -EINVAL;
11100
11101 *table_state = p->table_state;
11102 return 0;
11103 }
11104
11105 int
rte_swx_pipeline_table_state_set(struct rte_swx_pipeline * p,struct rte_swx_table_state * table_state)11106 rte_swx_pipeline_table_state_set(struct rte_swx_pipeline *p,
11107 struct rte_swx_table_state *table_state)
11108 {
11109 if (!p || !table_state || !p->build_done)
11110 return -EINVAL;
11111
11112 p->table_state = table_state;
11113 return 0;
11114 }
11115
11116 int
rte_swx_ctl_pipeline_port_in_stats_read(struct rte_swx_pipeline * p,uint32_t port_id,struct rte_swx_port_in_stats * stats)11117 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 if (!p || !stats)
11124 return -EINVAL;
11125
11126 port = port_in_find(p, port_id);
11127 if (!port)
11128 return -EINVAL;
11129
11130 port->type->ops.stats_read(port->obj, stats);
11131 return 0;
11132 }
11133
11134 int
rte_swx_ctl_pipeline_port_out_stats_read(struct rte_swx_pipeline * p,uint32_t port_id,struct rte_swx_port_out_stats * stats)11135 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 if (!p || !stats)
11142 return -EINVAL;
11143
11144 port = port_out_find(p, port_id);
11145 if (!port)
11146 return -EINVAL;
11147
11148 port->type->ops.stats_read(port->obj, stats);
11149 return 0;
11150 }
11151
11152 int
rte_swx_ctl_pipeline_table_stats_read(struct rte_swx_pipeline * p,const char * table_name,struct rte_swx_table_stats * stats)11153 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 if (!p || !table_name || !table_name[0] || !stats || !stats->n_pkts_action)
11161 return -EINVAL;
11162
11163 table = table_find(p, table_name);
11164 if (!table)
11165 return -EINVAL;
11166
11167 table_stats = &p->table_stats[table->id];
11168
11169 memcpy(stats->n_pkts_action,
11170 table_stats->n_pkts_action,
11171 p->n_actions * sizeof(uint64_t));
11172
11173 stats->n_pkts_hit = table_stats->n_pkts_hit[1];
11174 stats->n_pkts_miss = table_stats->n_pkts_hit[0];
11175
11176 return 0;
11177 }
11178
11179 int
rte_swx_ctl_pipeline_selector_stats_read(struct rte_swx_pipeline * p,const char * selector_name,struct rte_swx_pipeline_selector_stats * stats)11180 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 if (!p || !selector_name || !selector_name[0] || !stats)
11187 return -EINVAL;
11188
11189 s = selector_find(p, selector_name);
11190 if (!s)
11191 return -EINVAL;
11192
11193 stats->n_pkts = p->selector_stats[s->id].n_pkts;
11194
11195 return 0;
11196 }
11197
11198 int
rte_swx_ctl_pipeline_learner_stats_read(struct rte_swx_pipeline * p,const char * learner_name,struct rte_swx_learner_stats * stats)11199 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 if (!p || !learner_name || !learner_name[0] || !stats || !stats->n_pkts_action)
11207 return -EINVAL;
11208
11209 l = learner_find(p, learner_name);
11210 if (!l)
11211 return -EINVAL;
11212
11213 learner_stats = &p->learner_stats[l->id];
11214
11215 memcpy(stats->n_pkts_action,
11216 learner_stats->n_pkts_action,
11217 p->n_actions * sizeof(uint64_t));
11218
11219 stats->n_pkts_hit = learner_stats->n_pkts_hit[1];
11220 stats->n_pkts_miss = learner_stats->n_pkts_hit[0];
11221
11222 stats->n_pkts_learn_ok = learner_stats->n_pkts_learn[0];
11223 stats->n_pkts_learn_err = learner_stats->n_pkts_learn[1];
11224
11225 stats->n_pkts_rearm = learner_stats->n_pkts_rearm;
11226 stats->n_pkts_forget = learner_stats->n_pkts_forget;
11227
11228 return 0;
11229 }
11230
11231 int
rte_swx_ctl_regarray_info_get(struct rte_swx_pipeline * p,uint32_t regarray_id,struct rte_swx_ctl_regarray_info * regarray)11232 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 if (!p || !regarray)
11239 return -EINVAL;
11240
11241 r = regarray_find_by_id(p, regarray_id);
11242 if (!r)
11243 return -EINVAL;
11244
11245 strcpy(regarray->name, r->name);
11246 regarray->size = r->size;
11247 return 0;
11248 }
11249
11250 int
rte_swx_ctl_pipeline_regarray_read(struct rte_swx_pipeline * p,const char * regarray_name,uint32_t regarray_index,uint64_t * value)11251 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 if (!p || !regarray_name || !value)
11260 return -EINVAL;
11261
11262 regarray = regarray_find(p, regarray_name);
11263 if (!regarray || (regarray_index >= regarray->size))
11264 return -EINVAL;
11265
11266 r = &p->regarray_runtime[regarray->id];
11267 *value = r->regarray[regarray_index];
11268 return 0;
11269 }
11270
11271 int
rte_swx_ctl_pipeline_regarray_write(struct rte_swx_pipeline * p,const char * regarray_name,uint32_t regarray_index,uint64_t value)11272 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 if (!p || !regarray_name)
11281 return -EINVAL;
11282
11283 regarray = regarray_find(p, regarray_name);
11284 if (!regarray || (regarray_index >= regarray->size))
11285 return -EINVAL;
11286
11287 r = &p->regarray_runtime[regarray->id];
11288 r->regarray[regarray_index] = value;
11289 return 0;
11290 }
11291
11292 int
rte_swx_ctl_metarray_info_get(struct rte_swx_pipeline * p,uint32_t metarray_id,struct rte_swx_ctl_metarray_info * metarray)11293 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 if (!p || !metarray)
11300 return -EINVAL;
11301
11302 m = metarray_find_by_id(p, metarray_id);
11303 if (!m)
11304 return -EINVAL;
11305
11306 strcpy(metarray->name, m->name);
11307 metarray->size = m->size;
11308 return 0;
11309 }
11310
11311 int
rte_swx_ctl_meter_profile_add(struct rte_swx_pipeline * p,const char * name,struct rte_meter_trtcm_params * params)11312 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 CHECK(p, EINVAL);
11320 CHECK_NAME(name, EINVAL);
11321 CHECK(params, EINVAL);
11322 CHECK(!meter_profile_find(p, name), EEXIST);
11323
11324 /* Node allocation. */
11325 mp = calloc(1, sizeof(struct meter_profile));
11326 CHECK(mp, ENOMEM);
11327
11328 /* Node initialization. */
11329 strcpy(mp->name, name);
11330 memcpy(&mp->params, params, sizeof(struct rte_meter_trtcm_params));
11331 status = rte_meter_trtcm_profile_config(&mp->profile, params);
11332 if (status) {
11333 free(mp);
11334 CHECK(0, EINVAL);
11335 }
11336
11337 /* Node add to tailq. */
11338 TAILQ_INSERT_TAIL(&p->meter_profiles, mp, node);
11339
11340 return 0;
11341 }
11342
11343 int
rte_swx_ctl_meter_profile_delete(struct rte_swx_pipeline * p,const char * name)11344 rte_swx_ctl_meter_profile_delete(struct rte_swx_pipeline *p,
11345 const char *name)
11346 {
11347 struct meter_profile *mp;
11348
11349 CHECK(p, EINVAL);
11350 CHECK_NAME(name, EINVAL);
11351
11352 mp = meter_profile_find(p, name);
11353 CHECK(mp, EINVAL);
11354 CHECK(!mp->n_users, EBUSY);
11355
11356 /* Remove node from tailq. */
11357 TAILQ_REMOVE(&p->meter_profiles, mp, node);
11358 free(mp);
11359
11360 return 0;
11361 }
11362
11363 int
rte_swx_ctl_meter_reset(struct rte_swx_pipeline * p,const char * metarray_name,uint32_t metarray_index)11364 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 CHECK(p, EINVAL);
11374 CHECK_NAME(metarray_name, EINVAL);
11375
11376 metarray = metarray_find(p, metarray_name);
11377 CHECK(metarray, EINVAL);
11378 CHECK(metarray_index < metarray->size, EINVAL);
11379
11380 metarray_runtime = &p->metarray_runtime[metarray->id];
11381 m = &metarray_runtime->metarray[metarray_index];
11382 mp_old = m->profile;
11383
11384 meter_init(m);
11385
11386 mp_old->n_users--;
11387
11388 return 0;
11389 }
11390
11391 int
rte_swx_ctl_meter_set(struct rte_swx_pipeline * p,const char * metarray_name,uint32_t metarray_index,const char * profile_name)11392 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 CHECK(p, EINVAL);
11403 CHECK_NAME(metarray_name, EINVAL);
11404
11405 metarray = metarray_find(p, metarray_name);
11406 CHECK(metarray, EINVAL);
11407 CHECK(metarray_index < metarray->size, EINVAL);
11408
11409 mp = meter_profile_find(p, profile_name);
11410 CHECK(mp, EINVAL);
11411
11412 metarray_runtime = &p->metarray_runtime[metarray->id];
11413 m = &metarray_runtime->metarray[metarray_index];
11414 mp_old = m->profile;
11415
11416 memset(m, 0, sizeof(struct meter));
11417 rte_meter_trtcm_config(&m->m, &mp->profile);
11418 m->profile = mp;
11419 m->color_mask = RTE_COLORS;
11420
11421 mp->n_users++;
11422 mp_old->n_users--;
11423
11424 return 0;
11425 }
11426
11427 int
rte_swx_ctl_meter_stats_read(struct rte_swx_pipeline * p,const char * metarray_name,uint32_t metarray_index,struct rte_swx_ctl_meter_stats * stats)11428 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 CHECK(p, EINVAL);
11438 CHECK_NAME(metarray_name, EINVAL);
11439
11440 metarray = metarray_find(p, metarray_name);
11441 CHECK(metarray, EINVAL);
11442 CHECK(metarray_index < metarray->size, EINVAL);
11443
11444 CHECK(stats, EINVAL);
11445
11446 metarray_runtime = &p->metarray_runtime[metarray->id];
11447 m = &metarray_runtime->metarray[metarray_index];
11448
11449 memcpy(stats->n_pkts, m->n_pkts, sizeof(m->n_pkts));
11450 memcpy(stats->n_bytes, m->n_bytes, sizeof(m->n_bytes));
11451
11452 return 0;
11453 }
11454
11455 int
rte_swx_ctl_pipeline_mirroring_session_set(struct rte_swx_pipeline * p,uint32_t session_id,struct rte_swx_pipeline_mirroring_session_params * params)11456 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 CHECK(p, EINVAL);
11463 CHECK(p->build_done, EEXIST);
11464 CHECK(session_id < p->n_mirroring_sessions, EINVAL);
11465 CHECK(params, EINVAL);
11466 CHECK(params->port_id < p->n_ports_out, EINVAL);
11467
11468 s = &p->mirroring_sessions[session_id];
11469 s->port_id = params->port_id;
11470 s->fast_clone = params->fast_clone;
11471 s->truncation_length = params->truncation_length ? params->truncation_length : UINT32_MAX;
11472
11473 return 0;
11474 }
11475
11476 static int
rte_swx_ctl_pipeline_table_lookup(struct rte_swx_pipeline * p,const char * table_name,uint8_t * key,uint64_t * action_id,uint8_t ** action_data,size_t * entry_id,int * hit)11477 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 if (!p ||
11490 !p->build_done ||
11491 !table_name ||
11492 !table_name[0] ||
11493 !key ||
11494 !entry_id ||
11495 !hit)
11496 return -EINVAL;
11497
11498 /* Find the table. */
11499 t = table_find(p, table_name);
11500 if (!t)
11501 return -EINVAL;
11502
11503 if (!t->type) {
11504 *hit = 0;
11505 return 0;
11506 }
11507
11508 /* Setup mailbox. */
11509 if (t->type->ops.mailbox_size_get) {
11510 uint64_t mailbox_size;
11511
11512 mailbox_size = t->type->ops.mailbox_size_get();
11513 if (mailbox_size) {
11514 mailbox = calloc(1, mailbox_size);
11515 if (!mailbox)
11516 return -ENOMEM;
11517 }
11518 }
11519
11520 /* Table lookup operation. */
11521 key -= table_params_offset_get(t);
11522
11523 for ( ; ; ) {
11524 struct rte_swx_table_state *ts = &p->table_state[t->id];
11525 int done;
11526
11527 done = t->type->ops.lkp(ts->obj,
11528 mailbox,
11529 &key,
11530 action_id,
11531 action_data,
11532 entry_id,
11533 hit);
11534 if (done)
11535 break;
11536 }
11537
11538 /* Free mailbox. */
11539 free(mailbox);
11540
11541 return 0;
11542 }
11543
11544 static int
rte_swx_ctl_pipeline_learner_lookup(struct rte_swx_pipeline * p,const char * learner_name,uint8_t * key,uint64_t * action_id,uint8_t ** action_data,size_t * entry_id,int * hit)11545 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 if (!p ||
11559 !p->build_done ||
11560 !learner_name ||
11561 !learner_name[0] ||
11562 !key ||
11563 !entry_id ||
11564 !hit)
11565 return -EINVAL;
11566
11567 /* Find the learner table. */
11568 l = learner_find(p, learner_name);
11569 if (!l)
11570 return -EINVAL;
11571
11572 /* Setup mailbox. */
11573 mailbox_size = rte_swx_table_learner_mailbox_size_get();
11574 if (mailbox_size) {
11575 mailbox = calloc(1, mailbox_size);
11576 if (!mailbox)
11577 return -ENOMEM;
11578 }
11579
11580 /* Learner table lookup operation. */
11581 key -= learner_params_offset_get(l);
11582
11583 time = rte_get_tsc_cycles();
11584
11585 for ( ; ; ) {
11586 uint32_t pos = p->n_tables + p->n_selectors + l->id;
11587 struct rte_swx_table_state *ts = &p->table_state[pos];
11588 int done;
11589
11590 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 if (done)
11599 break;
11600 }
11601
11602 /* Free mailbox. */
11603 free(mailbox);
11604
11605 return 0;
11606 }
11607
11608 static int
rte_swx_ctl_pipeline_table_entry_id_get(struct rte_swx_pipeline * p,const char * table_name,uint8_t * table_key,size_t * table_entry_id)11609 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 size_t entry_id = 0;
11619 int hit = 0, status;
11620
11621 /* Check input arguments. */
11622 if (!p ||
11623 !p->build_done ||
11624 !table_name ||
11625 !table_name[0] ||
11626 !table_key ||
11627 !table_entry_id)
11628 return -EINVAL;
11629
11630 t = table_find(p, table_name);
11631 l = learner_find(p, table_name);
11632 if (!t && !l)
11633 return -EINVAL;
11634
11635 /* Table lookup operation. */
11636 if (t)
11637 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 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 if (status)
11653 return status;
11654
11655 /* Reserve entry ID 0 for the table default entry. */
11656 *table_entry_id = hit ? (1 + entry_id) : 0;
11657
11658 return 0;
11659 }
11660
11661 int
rte_swx_ctl_pipeline_regarray_read_with_key(struct rte_swx_pipeline * p,const char * regarray_name,const char * table_name,uint8_t * table_key,uint64_t * value)11662 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 size_t entry_id = 0;
11669 int status;
11670
11671 status = rte_swx_ctl_pipeline_table_entry_id_get(p, table_name, table_key, &entry_id);
11672 if (status)
11673 return status;
11674
11675 return rte_swx_ctl_pipeline_regarray_read(p, regarray_name, entry_id, value);
11676 }
11677
11678 int
rte_swx_ctl_pipeline_regarray_write_with_key(struct rte_swx_pipeline * p,const char * regarray_name,const char * table_name,uint8_t * table_key,uint64_t value)11679 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 size_t entry_id = 0;
11686 int status;
11687
11688 status = rte_swx_ctl_pipeline_table_entry_id_get(p, table_name, table_key, &entry_id);
11689 if (status)
11690 return status;
11691
11692 return rte_swx_ctl_pipeline_regarray_write(p, regarray_name, entry_id, value);
11693 }
11694
11695 int
rte_swx_ctl_meter_reset_with_key(struct rte_swx_pipeline * p,const char * metarray_name,const char * table_name,uint8_t * table_key)11696 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 size_t entry_id = 0;
11702 int status;
11703
11704 status = rte_swx_ctl_pipeline_table_entry_id_get(p, table_name, table_key, &entry_id);
11705 if (status)
11706 return status;
11707
11708 return rte_swx_ctl_meter_reset(p, metarray_name, entry_id);
11709 }
11710
11711 int
rte_swx_ctl_meter_set_with_key(struct rte_swx_pipeline * p,const char * metarray_name,const char * table_name,uint8_t * table_key,const char * profile_name)11712 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 size_t entry_id = 0;
11719 int status;
11720
11721 status = rte_swx_ctl_pipeline_table_entry_id_get(p, table_name, table_key, &entry_id);
11722 if (status)
11723 return status;
11724
11725 return rte_swx_ctl_meter_set(p, metarray_name, entry_id, profile_name);
11726 }
11727
11728 int
rte_swx_ctl_meter_stats_read_with_key(struct rte_swx_pipeline * p,const char * metarray_name,const char * table_name,uint8_t * table_key,struct rte_swx_ctl_meter_stats * stats)11729 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 size_t entry_id = 0;
11736 int status;
11737
11738 status = rte_swx_ctl_pipeline_table_entry_id_get(p, table_name, table_key, &entry_id);
11739 if (status)
11740 return status;
11741
11742 return rte_swx_ctl_meter_stats_read(p, metarray_name, entry_id, stats);
11743 }
11744
11745 int
rte_swx_ctl_rss_info_get(struct rte_swx_pipeline * p,uint32_t rss_obj_id,struct rte_swx_ctl_rss_info * info)11746 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 if (!p || !info)
11754 return -EINVAL;
11755
11756 rss = rss_find_by_id(p, rss_obj_id);
11757 if (!rss)
11758 return -EINVAL;
11759
11760 /* Read from the internal data structures. */
11761 strcpy(info->name, rss->name);
11762 return 0;
11763 }
11764
11765 int
rte_swx_ctl_pipeline_rss_key_size_read(struct rte_swx_pipeline * p,const char * rss_name,uint32_t * key_size)11766 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 CHECK(p, EINVAL);
11775
11776 CHECK_NAME(rss_name, EINVAL);
11777 rss = rss_find(p, rss_name);
11778 CHECK(rss, EINVAL);
11779 r = p->rss_runtime[rss->id];
11780
11781 CHECK(key_size, EINVAL);
11782
11783 /* Read from the internal data structures. */
11784 *key_size = r->key_size;
11785
11786 return 0;
11787 }
11788
11789 int
rte_swx_ctl_pipeline_rss_key_read(struct rte_swx_pipeline * p,const char * rss_name,uint8_t * key)11790 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 CHECK(p, EINVAL);
11799
11800 CHECK_NAME(rss_name, EINVAL);
11801 rss = rss_find(p, rss_name);
11802 CHECK(rss, EINVAL);
11803 r = p->rss_runtime[rss->id];
11804
11805 CHECK(key, EINVAL);
11806
11807 /* Read from the internal data structures. */
11808 memcpy(key, r->key, r->key_size);
11809
11810 return 0;
11811 }
11812
11813 int
rte_swx_ctl_pipeline_rss_key_write(struct rte_swx_pipeline * p,const char * rss_name,uint32_t key_size,uint8_t * key)11814 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 CHECK(p, EINVAL);
11824
11825 CHECK_NAME(rss_name, EINVAL);
11826 rss = rss_find(p, rss_name);
11827 CHECK(rss, EINVAL);
11828 r = p->rss_runtime[rss->id];
11829
11830 CHECK(key_size >= 4, EINVAL);
11831 CHECK(key, EINVAL);
11832
11833 /* Allocate new RSS run-time entry. */
11834 r_new = malloc(sizeof(struct rss_runtime) + key_size * sizeof(uint32_t));
11835 if (!r_new)
11836 return -ENOMEM;
11837
11838 /* Fill in the new RSS run-time entry. */
11839 r_new->key_size = key_size;
11840 memcpy(r_new->key, key, key_size);
11841
11842 /* Commit the RSS run-time change atomically. */
11843 p->rss_runtime[rss->id] = r_new;
11844
11845 /* Free the old RSS run-time entry. */
11846 free(r);
11847
11848 return 0;
11849 }
11850
11851 /*
11852 * Pipeline compilation.
11853 */
11854 static const char *
instr_type_to_name(struct instruction * instr)11855 instr_type_to_name(struct instruction *instr)
11856 {
11857 switch (instr->type) {
11858 case INSTR_RX: return "INSTR_RX";
11859
11860 case INSTR_TX: return "INSTR_TX";
11861 case INSTR_TX_I: return "INSTR_TX_I";
11862 case INSTR_DROP: return "INSTR_DROP";
11863 case INSTR_MIRROR: return "INSTR_MIRROR";
11864 case INSTR_RECIRCULATE: return "INSTR_RECIRCULATE";
11865 case INSTR_RECIRCID: return "INSTR_RECIRCID";
11866
11867 case INSTR_HDR_EXTRACT: return "INSTR_HDR_EXTRACT";
11868 case INSTR_HDR_EXTRACT2: return "INSTR_HDR_EXTRACT2";
11869 case INSTR_HDR_EXTRACT3: return "INSTR_HDR_EXTRACT3";
11870 case INSTR_HDR_EXTRACT4: return "INSTR_HDR_EXTRACT4";
11871 case INSTR_HDR_EXTRACT5: return "INSTR_HDR_EXTRACT5";
11872 case INSTR_HDR_EXTRACT6: return "INSTR_HDR_EXTRACT6";
11873 case INSTR_HDR_EXTRACT7: return "INSTR_HDR_EXTRACT7";
11874 case INSTR_HDR_EXTRACT8: return "INSTR_HDR_EXTRACT8";
11875
11876 case INSTR_HDR_EXTRACT_M: return "INSTR_HDR_EXTRACT_M";
11877
11878 case INSTR_HDR_LOOKAHEAD: return "INSTR_HDR_LOOKAHEAD";
11879
11880 case INSTR_HDR_EMIT: return "INSTR_HDR_EMIT";
11881 case INSTR_HDR_EMIT_TX: return "INSTR_HDR_EMIT_TX";
11882 case INSTR_HDR_EMIT2_TX: return "INSTR_HDR_EMIT2_TX";
11883 case INSTR_HDR_EMIT3_TX: return "INSTR_HDR_EMIT3_TX";
11884 case INSTR_HDR_EMIT4_TX: return "INSTR_HDR_EMIT4_TX";
11885 case INSTR_HDR_EMIT5_TX: return "INSTR_HDR_EMIT5_TX";
11886 case INSTR_HDR_EMIT6_TX: return "INSTR_HDR_EMIT6_TX";
11887 case INSTR_HDR_EMIT7_TX: return "INSTR_HDR_EMIT7_TX";
11888 case INSTR_HDR_EMIT8_TX: return "INSTR_HDR_EMIT8_TX";
11889
11890 case INSTR_HDR_VALIDATE: return "INSTR_HDR_VALIDATE";
11891 case INSTR_HDR_INVALIDATE: return "INSTR_HDR_INVALIDATE";
11892
11893 case INSTR_MOV: return "INSTR_MOV";
11894 case INSTR_MOV_MH: return "INSTR_MOV_MH";
11895 case INSTR_MOV_HM: return "INSTR_MOV_HM";
11896 case INSTR_MOV_HH: return "INSTR_MOV_HH";
11897 case INSTR_MOV_DMA: return "INSTR_MOV_DMA";
11898 case INSTR_MOV_128: return "INSTR_MOV_128";
11899 case INSTR_MOV_128_64: return "INSTR_MOV_128_64";
11900 case INSTR_MOV_64_128: return "INSTR_MOV_64_128";
11901 case INSTR_MOV_128_32: return "INSTR_MOV_128_32";
11902 case INSTR_MOV_32_128: return "INSTR_MOV_32_128";
11903 case INSTR_MOV_I: return "INSTR_MOV_I";
11904
11905 case INSTR_MOVH: return "INSTR_MOVH";
11906
11907 case INSTR_DMA_HT: return "INSTR_DMA_HT";
11908 case INSTR_DMA_HT2: return "INSTR_DMA_HT2";
11909 case INSTR_DMA_HT3: return "INSTR_DMA_HT3";
11910 case INSTR_DMA_HT4: return "INSTR_DMA_HT4";
11911 case INSTR_DMA_HT5: return "INSTR_DMA_HT5";
11912 case INSTR_DMA_HT6: return "INSTR_DMA_HT6";
11913 case INSTR_DMA_HT7: return "INSTR_DMA_HT7";
11914 case INSTR_DMA_HT8: return "INSTR_DMA_HT8";
11915
11916 case INSTR_ALU_ADD: return "INSTR_ALU_ADD";
11917 case INSTR_ALU_ADD_MH: return "INSTR_ALU_ADD_MH";
11918 case INSTR_ALU_ADD_HM: return "INSTR_ALU_ADD_HM";
11919 case INSTR_ALU_ADD_HH: return "INSTR_ALU_ADD_HH";
11920 case INSTR_ALU_ADD_MI: return "INSTR_ALU_ADD_MI";
11921 case INSTR_ALU_ADD_HI: return "INSTR_ALU_ADD_HI";
11922
11923 case INSTR_ALU_SUB: return "INSTR_ALU_SUB";
11924 case INSTR_ALU_SUB_MH: return "INSTR_ALU_SUB_MH";
11925 case INSTR_ALU_SUB_HM: return "INSTR_ALU_SUB_HM";
11926 case INSTR_ALU_SUB_HH: return "INSTR_ALU_SUB_HH";
11927 case INSTR_ALU_SUB_MI: return "INSTR_ALU_SUB_MI";
11928 case INSTR_ALU_SUB_HI: return "INSTR_ALU_SUB_HI";
11929
11930 case INSTR_ALU_CKADD_FIELD: return "INSTR_ALU_CKADD_FIELD";
11931 case INSTR_ALU_CKADD_STRUCT20: return "INSTR_ALU_CKADD_STRUCT20";
11932 case INSTR_ALU_CKADD_STRUCT: return "INSTR_ALU_CKADD_STRUCT";
11933 case INSTR_ALU_CKSUB_FIELD: return "INSTR_ALU_CKSUB_FIELD";
11934
11935 case INSTR_ALU_AND: return "INSTR_ALU_AND";
11936 case INSTR_ALU_AND_MH: return "INSTR_ALU_AND_MH";
11937 case INSTR_ALU_AND_HM: return "INSTR_ALU_AND_HM";
11938 case INSTR_ALU_AND_HH: return "INSTR_ALU_AND_HH";
11939 case INSTR_ALU_AND_I: return "INSTR_ALU_AND_I";
11940
11941 case INSTR_ALU_OR: return "INSTR_ALU_OR";
11942 case INSTR_ALU_OR_MH: return "INSTR_ALU_OR_MH";
11943 case INSTR_ALU_OR_HM: return "INSTR_ALU_OR_HM";
11944 case INSTR_ALU_OR_HH: return "INSTR_ALU_OR_HH";
11945 case INSTR_ALU_OR_I: return "INSTR_ALU_OR_I";
11946
11947 case INSTR_ALU_XOR: return "INSTR_ALU_XOR";
11948 case INSTR_ALU_XOR_MH: return "INSTR_ALU_XOR_MH";
11949 case INSTR_ALU_XOR_HM: return "INSTR_ALU_XOR_HM";
11950 case INSTR_ALU_XOR_HH: return "INSTR_ALU_XOR_HH";
11951 case INSTR_ALU_XOR_I: return "INSTR_ALU_XOR_I";
11952
11953 case INSTR_ALU_SHL: return "INSTR_ALU_SHL";
11954 case INSTR_ALU_SHL_MH: return "INSTR_ALU_SHL_MH";
11955 case INSTR_ALU_SHL_HM: return "INSTR_ALU_SHL_HM";
11956 case INSTR_ALU_SHL_HH: return "INSTR_ALU_SHL_HH";
11957 case INSTR_ALU_SHL_MI: return "INSTR_ALU_SHL_MI";
11958 case INSTR_ALU_SHL_HI: return "INSTR_ALU_SHL_HI";
11959
11960 case INSTR_ALU_SHR: return "INSTR_ALU_SHR";
11961 case INSTR_ALU_SHR_MH: return "INSTR_ALU_SHR_MH";
11962 case INSTR_ALU_SHR_HM: return "INSTR_ALU_SHR_HM";
11963 case INSTR_ALU_SHR_HH: return "INSTR_ALU_SHR_HH";
11964 case INSTR_ALU_SHR_MI: return "INSTR_ALU_SHR_MI";
11965 case INSTR_ALU_SHR_HI: return "INSTR_ALU_SHR_HI";
11966
11967 case INSTR_REGPREFETCH_RH: return "INSTR_REGPREFETCH_RH";
11968 case INSTR_REGPREFETCH_RM: return "INSTR_REGPREFETCH_RM";
11969 case INSTR_REGPREFETCH_RI: return "INSTR_REGPREFETCH_RI";
11970
11971 case INSTR_REGRD_HRH: return "INSTR_REGRD_HRH";
11972 case INSTR_REGRD_HRM: return "INSTR_REGRD_HRM";
11973 case INSTR_REGRD_HRI: return "INSTR_REGRD_HRI";
11974 case INSTR_REGRD_MRH: return "INSTR_REGRD_MRH";
11975 case INSTR_REGRD_MRM: return "INSTR_REGRD_MRM";
11976 case INSTR_REGRD_MRI: return "INSTR_REGRD_MRI";
11977
11978 case INSTR_REGWR_RHH: return "INSTR_REGWR_RHH";
11979 case INSTR_REGWR_RHM: return "INSTR_REGWR_RHM";
11980 case INSTR_REGWR_RHI: return "INSTR_REGWR_RHI";
11981 case INSTR_REGWR_RMH: return "INSTR_REGWR_RMH";
11982 case INSTR_REGWR_RMM: return "INSTR_REGWR_RMM";
11983 case INSTR_REGWR_RMI: return "INSTR_REGWR_RMI";
11984 case INSTR_REGWR_RIH: return "INSTR_REGWR_RIH";
11985 case INSTR_REGWR_RIM: return "INSTR_REGWR_RIM";
11986 case INSTR_REGWR_RII: return "INSTR_REGWR_RII";
11987
11988 case INSTR_REGADD_RHH: return "INSTR_REGADD_RHH";
11989 case INSTR_REGADD_RHM: return "INSTR_REGADD_RHM";
11990 case INSTR_REGADD_RHI: return "INSTR_REGADD_RHI";
11991 case INSTR_REGADD_RMH: return "INSTR_REGADD_RMH";
11992 case INSTR_REGADD_RMM: return "INSTR_REGADD_RMM";
11993 case INSTR_REGADD_RMI: return "INSTR_REGADD_RMI";
11994 case INSTR_REGADD_RIH: return "INSTR_REGADD_RIH";
11995 case INSTR_REGADD_RIM: return "INSTR_REGADD_RIM";
11996 case INSTR_REGADD_RII: return "INSTR_REGADD_RII";
11997
11998 case INSTR_METPREFETCH_H: return "INSTR_METPREFETCH_H";
11999 case INSTR_METPREFETCH_M: return "INSTR_METPREFETCH_M";
12000 case INSTR_METPREFETCH_I: return "INSTR_METPREFETCH_I";
12001
12002 case INSTR_METER_HHM: return "INSTR_METER_HHM";
12003 case INSTR_METER_HHI: return "INSTR_METER_HHI";
12004 case INSTR_METER_HMM: return "INSTR_METER_HMM";
12005 case INSTR_METER_HMI: return "INSTR_METER_HMI";
12006 case INSTR_METER_MHM: return "INSTR_METER_MHM";
12007 case INSTR_METER_MHI: return "INSTR_METER_MHI";
12008 case INSTR_METER_MMM: return "INSTR_METER_MMM";
12009 case INSTR_METER_MMI: return "INSTR_METER_MMI";
12010 case INSTR_METER_IHM: return "INSTR_METER_IHM";
12011 case INSTR_METER_IHI: return "INSTR_METER_IHI";
12012 case INSTR_METER_IMM: return "INSTR_METER_IMM";
12013 case INSTR_METER_IMI: return "INSTR_METER_IMI";
12014
12015 case INSTR_TABLE: return "INSTR_TABLE";
12016 case INSTR_TABLE_AF: return "INSTR_TABLE_AF";
12017 case INSTR_SELECTOR: return "INSTR_SELECTOR";
12018 case INSTR_LEARNER: return "INSTR_LEARNER";
12019 case INSTR_LEARNER_AF: return "INSTR_LEARNER_AF";
12020
12021 case INSTR_LEARNER_LEARN: return "INSTR_LEARNER_LEARN";
12022 case INSTR_LEARNER_REARM: return "INSTR_LEARNER_REARM";
12023 case INSTR_LEARNER_REARM_NEW: return "INSTR_LEARNER_REARM_NEW";
12024 case INSTR_LEARNER_FORGET: return "INSTR_LEARNER_FORGET";
12025 case INSTR_ENTRYID: return "INSTR_ENTRYID";
12026
12027 case INSTR_EXTERN_OBJ: return "INSTR_EXTERN_OBJ";
12028 case INSTR_EXTERN_FUNC: return "INSTR_EXTERN_FUNC";
12029 case INSTR_HASH_FUNC: return "INSTR_HASH_FUNC";
12030 case INSTR_RSS: return "INSTR_RSS";
12031
12032 case INSTR_JMP: return "INSTR_JMP";
12033 case INSTR_JMP_VALID: return "INSTR_JMP_VALID";
12034 case INSTR_JMP_INVALID: return "INSTR_JMP_INVALID";
12035 case INSTR_JMP_HIT: return "INSTR_JMP_HIT";
12036 case INSTR_JMP_MISS: return "INSTR_JMP_MISS";
12037 case INSTR_JMP_ACTION_HIT: return "INSTR_JMP_ACTION_HIT";
12038 case INSTR_JMP_ACTION_MISS: return "INSTR_JMP_ACTION_MISS";
12039 case INSTR_JMP_EQ: return "INSTR_JMP_EQ";
12040 case INSTR_JMP_EQ_MH: return "INSTR_JMP_EQ_MH";
12041 case INSTR_JMP_EQ_HM: return "INSTR_JMP_EQ_HM";
12042 case INSTR_JMP_EQ_HH: return "INSTR_JMP_EQ_HH";
12043 case INSTR_JMP_EQ_I: return "INSTR_JMP_EQ_I";
12044 case INSTR_JMP_NEQ: return "INSTR_JMP_NEQ";
12045 case INSTR_JMP_NEQ_MH: return "INSTR_JMP_NEQ_MH";
12046 case INSTR_JMP_NEQ_HM: return "INSTR_JMP_NEQ_HM";
12047 case INSTR_JMP_NEQ_HH: return "INSTR_JMP_NEQ_HH";
12048 case INSTR_JMP_NEQ_I: return "INSTR_JMP_NEQ_I";
12049 case INSTR_JMP_LT: return "INSTR_JMP_LT";
12050 case INSTR_JMP_LT_MH: return "INSTR_JMP_LT_MH";
12051 case INSTR_JMP_LT_HM: return "INSTR_JMP_LT_HM";
12052 case INSTR_JMP_LT_HH: return "INSTR_JMP_LT_HH";
12053 case INSTR_JMP_LT_MI: return "INSTR_JMP_LT_MI";
12054 case INSTR_JMP_LT_HI: return "INSTR_JMP_LT_HI";
12055 case INSTR_JMP_GT: return "INSTR_JMP_GT";
12056 case INSTR_JMP_GT_MH: return "INSTR_JMP_GT_MH";
12057 case INSTR_JMP_GT_HM: return "INSTR_JMP_GT_HM";
12058 case INSTR_JMP_GT_HH: return "INSTR_JMP_GT_HH";
12059 case INSTR_JMP_GT_MI: return "INSTR_JMP_GT_MI";
12060 case INSTR_JMP_GT_HI: return "INSTR_JMP_GT_HI";
12061
12062 case INSTR_RETURN: return "INSTR_RETURN";
12063
12064 default: return "INSTR_UNKNOWN";
12065 }
12066 }
12067
12068 typedef void
12069 (*instruction_export_t)(struct instruction *, FILE *);
12070
12071 static void
instr_io_export(struct instruction * instr,FILE * f)12072 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 if (instr->type == INSTR_RX ||
12078 instr->type == INSTR_TX ||
12079 instr->type == INSTR_HDR_EXTRACT_M ||
12080 (instr->type >= INSTR_HDR_EMIT_TX && instr->type <= INSTR_HDR_EMIT8_TX))
12081 n_io = 1;
12082
12083 if (instr->type == INSTR_TX_I)
12084 n_io_imm = 1;
12085
12086 if (instr->type >= INSTR_HDR_EXTRACT && instr->type <= INSTR_HDR_EXTRACT8)
12087 n_hdrs = 1 + (instr->type - INSTR_HDR_EXTRACT);
12088
12089 if (instr->type == INSTR_HDR_EXTRACT_M ||
12090 instr->type == INSTR_HDR_LOOKAHEAD ||
12091 instr->type == INSTR_HDR_EMIT)
12092 n_hdrs = 1;
12093
12094 if (instr->type >= INSTR_HDR_EMIT_TX && instr->type <= INSTR_HDR_EMIT8_TX)
12095 n_hdrs = 1 + (instr->type - INSTR_HDR_EMIT_TX);
12096
12097 /* instr. */
12098 fprintf(f,
12099 "\t{\n"
12100 "\t\t.type = %s,\n",
12101 instr_type_to_name(instr));
12102
12103 /* instr.io. */
12104 if (n_io || n_io_imm || n_hdrs)
12105 fprintf(f,
12106 "\t\t.io = {\n");
12107
12108 /* instr.io.io. */
12109 if (n_io)
12110 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 instr->io.io.offset,
12116 instr->io.io.n_bits);
12117
12118 if (n_io_imm)
12119 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 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 for (i = 0; i < n_hdrs; i++)
12135 fprintf(f,
12136 "%u, ",
12137 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 for (i = 0; i < n_hdrs; i++)
12147 fprintf(f,
12148 "%u, ",
12149 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 for (i = 0; i < n_hdrs; i++)
12159 fprintf(f,
12160 "%u, ",
12161 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 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 }
12180
12181 static void
instr_mirror_export(struct instruction * instr,FILE * f)12182 instr_mirror_export(struct instruction *instr, FILE *f)
12183 {
12184 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 instr->mirror.dst.struct_id,
12202 instr->mirror.dst.n_bits,
12203 instr->mirror.dst.offset,
12204 instr->mirror.src.struct_id,
12205 instr->mirror.src.n_bits,
12206 instr->mirror.src.offset);
12207 }
12208
12209 static void
instr_recirculate_export(struct instruction * instr,FILE * f)12210 instr_recirculate_export(struct instruction *instr, FILE *f)
12211 {
12212 fprintf(f,
12213 "\t{\n"
12214 "\t\t.type = %s,\n"
12215 "\t},\n",
12216 instr_type_to_name(instr));
12217 }
12218
12219 static void
instr_recircid_export(struct instruction * instr,FILE * f)12220 instr_recircid_export(struct instruction *instr, FILE *f)
12221 {
12222 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 instr->io.io.offset,
12234 instr->io.io.n_bits);
12235 }
12236
12237 static void
instr_hdr_validate_export(struct instruction * instr,FILE * f)12238 instr_hdr_validate_export(struct instruction *instr, FILE *f)
12239 {
12240 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 instr->valid.header_id,
12250 instr->valid.struct_id);
12251 }
12252
12253 static void
instr_mov_export(struct instruction * instr,FILE * f)12254 instr_mov_export(struct instruction *instr, FILE *f)
12255 {
12256 if (instr->type != INSTR_MOV_I)
12257 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 instr->mov.dst.struct_id,
12275 instr->mov.dst.n_bits,
12276 instr->mov.dst.offset,
12277 instr->mov.src.struct_id,
12278 instr->mov.src.n_bits,
12279 instr->mov.src.offset);
12280 else
12281 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 instr->mov.dst.struct_id,
12295 instr->mov.dst.n_bits,
12296 instr->mov.dst.offset,
12297 instr->mov.src_val);
12298 }
12299
12300 static void
instr_movh_export(struct instruction * instr,FILE * f)12301 instr_movh_export(struct instruction *instr, FILE *f)
12302 {
12303 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 instr->mov.dst.struct_id,
12321 instr->mov.dst.n_bits,
12322 instr->mov.dst.offset,
12323 instr->mov.src.struct_id,
12324 instr->mov.src.n_bits,
12325 instr->mov.src.offset);
12326 }
12327
12328 static void
instr_dma_ht_export(struct instruction * instr,FILE * f)12329 instr_dma_ht_export(struct instruction *instr, FILE *f)
12330 {
12331 uint32_t n_dma = 0, i;
12332
12333 /* n_dma. */
12334 n_dma = 1 + (instr->type - INSTR_DMA_HT);
12335
12336 /* instr. */
12337 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 for (i = 0; i < n_dma; i++)
12355 fprintf(f,
12356 "%u, ",
12357 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 for (i = 0; i < n_dma; i++)
12367 fprintf(f,
12368 "%u, ",
12369 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 for (i = 0; i < n_dma; i++)
12387 fprintf(f,
12388 "%u, ",
12389 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 for (i = 0; i < n_dma; i++)
12403 fprintf(f,
12404 "%u, ",
12405 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 }
12418
12419 static void
instr_alu_export(struct instruction * instr,FILE * f)12420 instr_alu_export(struct instruction *instr, FILE *f)
12421 {
12422 int imm = 0;
12423
12424 if (instr->type == INSTR_ALU_ADD_MI ||
12425 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 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 instr->alu.dst.struct_id,
12456 instr->alu.dst.n_bits,
12457 instr->alu.dst.offset,
12458 instr->alu.src.struct_id,
12459 instr->alu.src.n_bits,
12460 instr->alu.src.offset);
12461 else
12462 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 instr->alu.dst.struct_id,
12476 instr->alu.dst.n_bits,
12477 instr->alu.dst.offset,
12478 instr->alu.src_val);
12479 }
12480
12481 static void
instr_hash_export(struct instruction * instr,FILE * f)12482 instr_hash_export(struct instruction *instr, FILE *f)
12483 {
12484 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 instr->hash_func.hash_func_id,
12502 instr->hash_func.dst.offset,
12503 instr->hash_func.dst.n_bits,
12504 instr->hash_func.src.struct_id,
12505 instr->hash_func.src.offset,
12506 instr->hash_func.src.n_bytes);
12507 }
12508
12509 static void
instr_rss_export(struct instruction * instr,FILE * f)12510 instr_rss_export(struct instruction *instr, FILE *f)
12511 {
12512 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 instr->rss.rss_obj_id,
12530 instr->rss.dst.offset,
12531 instr->rss.dst.n_bits,
12532 instr->rss.src.struct_id,
12533 instr->rss.src.offset,
12534 instr->rss.src.n_bytes);
12535 }
12536
12537 static void
instr_reg_export(struct instruction * instr __rte_unused,FILE * f __rte_unused)12538 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 if (instr->type == INSTR_REGPREFETCH_RH ||
12543 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 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 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 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 instr->regarray.regarray_id);
12578
12579 /* instr.regarray.idx / instr.regarray.idx_val. */
12580 if (!idx_imm)
12581 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 instr->regarray.idx.struct_id,
12588 instr->regarray.idx.n_bits,
12589 instr->regarray.idx.offset);
12590 else
12591 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 if (!prefetch) {
12597 if (!src_imm)
12598 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 instr->regarray.dstsrc.struct_id,
12605 instr->regarray.dstsrc.n_bits,
12606 instr->regarray.dstsrc.offset);
12607 else
12608 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 }
12618
12619 static void
instr_meter_export(struct instruction * instr __rte_unused,FILE * f __rte_unused)12620 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 if (instr->type == INSTR_METPREFETCH_H ||
12625 instr->type == INSTR_METPREFETCH_M ||
12626 instr->type == INSTR_METPREFETCH_I)
12627 prefetch = 1;
12628
12629 /* idx_imm. */
12630 if (instr->type == INSTR_METPREFETCH_I ||
12631 instr->type == INSTR_METER_IHM ||
12632 instr->type == INSTR_METER_IHI ||
12633 instr->type == INSTR_METER_IMM ||
12634 instr->type == INSTR_METER_IMI)
12635 idx_imm = 1;
12636
12637 /* color_in_imm. */
12638 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 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 instr->meter.metarray_id);
12654
12655 /* instr.meter.idx / instr.meter.idx_val. */
12656 if (!idx_imm)
12657 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 instr->meter.idx.struct_id,
12664 instr->meter.idx.n_bits,
12665 instr->meter.idx.offset);
12666 else
12667 fprintf(f,
12668 "\t\t\t.idx_val = %u,\n",
12669 instr->meter.idx_val);
12670
12671 if (!prefetch) {
12672 /* instr.meter.length. */
12673 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 instr->meter.length.struct_id,
12680 instr->meter.length.n_bits,
12681 instr->meter.length.offset);
12682
12683 /* instr.meter.color_in / instr.meter.color_in_val. */
12684 if (!color_in_imm)
12685 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 instr->meter.color_in.struct_id,
12692 instr->meter.color_in.n_bits,
12693 instr->meter.color_in.offset);
12694 else
12695 fprintf(f,
12696 "\t\t\t.color_in_val = %u,\n",
12697 (uint32_t)instr->meter.color_in_val);
12698
12699 /* instr.meter.color_out. */
12700 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 instr->meter.color_out.struct_id,
12707 instr->meter.color_out.n_bits,
12708 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 }
12716
12717 static void
instr_table_export(struct instruction * instr,FILE * f)12718 instr_table_export(struct instruction *instr,
12719 FILE *f)
12720 {
12721 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 instr->table.table_id);
12730 }
12731
12732 static void
instr_learn_export(struct instruction * instr,FILE * f)12733 instr_learn_export(struct instruction *instr, FILE *f)
12734 {
12735 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 instr->learn.action_id,
12747 instr->learn.mf_first_arg_offset,
12748 instr->learn.mf_timeout_id_offset,
12749 instr->learn.mf_timeout_id_n_bits);
12750 }
12751
12752 static void
instr_rearm_export(struct instruction * instr,FILE * f)12753 instr_rearm_export(struct instruction *instr, FILE *f)
12754 {
12755 if (instr->type == INSTR_LEARNER_REARM)
12756 fprintf(f,
12757 "\t{\n"
12758 "\t\t.type = %s,\n"
12759 "\t},\n",
12760 instr_type_to_name(instr));
12761 else
12762 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 instr->learn.mf_timeout_id_offset,
12772 instr->learn.mf_timeout_id_n_bits);
12773 }
12774
12775 static void
instr_forget_export(struct instruction * instr,FILE * f)12776 instr_forget_export(struct instruction *instr, FILE *f)
12777 {
12778 fprintf(f,
12779 "\t{\n"
12780 "\t\t.type = %s,\n"
12781 "\t},\n",
12782 instr_type_to_name(instr));
12783 }
12784
12785 static void
instr_entryid_export(struct instruction * instr,FILE * f)12786 instr_entryid_export(struct instruction *instr, FILE *f)
12787 {
12788 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 instr->mov.dst.n_bits,
12800 instr->mov.dst.offset);
12801 }
12802
12803 static void
instr_extern_export(struct instruction * instr,FILE * f)12804 instr_extern_export(struct instruction *instr, FILE *f)
12805 {
12806 if (instr->type == INSTR_EXTERN_OBJ)
12807 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 instr->ext_obj.ext_obj_id,
12817 instr->ext_obj.func_id);
12818 else
12819 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 instr->ext_func.ext_func_id);
12828 }
12829
12830 static void
instr_jmp_export(struct instruction * instr,FILE * f __rte_unused)12831 instr_jmp_export(struct instruction *instr, FILE *f __rte_unused)
12832 {
12833 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 switch (instr->type) {
12841 case INSTR_JMP_VALID:
12842 case INSTR_JMP_INVALID:
12843 fprintf(f,
12844 "\t\t\t.header_id = %u,\n",
12845 instr->jmp.header_id);
12846 break;
12847
12848 case INSTR_JMP_ACTION_HIT:
12849 case INSTR_JMP_ACTION_MISS:
12850 fprintf(f,
12851 "\t\t\t.action_id = %u,\n",
12852 instr->jmp.action_id);
12853 break;
12854
12855 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 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 instr->jmp.a.struct_id,
12883 instr->jmp.a.n_bits,
12884 instr->jmp.a.offset,
12885 instr->jmp.b.struct_id,
12886 instr->jmp.b.n_bits,
12887 instr->jmp.b.offset);
12888 break;
12889
12890 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 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 instr->jmp.a.struct_id,
12904 instr->jmp.a.n_bits,
12905 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 }
12917
12918 static void
instr_return_export(struct instruction * instr,FILE * f)12919 instr_return_export(struct instruction *instr,
12920 FILE *f)
12921 {
12922 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 }
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
action_data_codegen(struct action * a,FILE * f)13144 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 a->name);
13151
13152 for (i = 0; i < a->n_instructions; i++) {
13153 struct instruction *instr = &a->instructions[i];
13154 instruction_export_t func = export_table[instr->type];
13155
13156 func(instr, f);
13157 }
13158
13159 fprintf(f, "};\n");
13160 }
13161
13162 static const char *
instr_type_to_func(struct instruction * instr)13163 instr_type_to_func(struct instruction *instr)
13164 {
13165 switch (instr->type) {
13166 case INSTR_RX: return NULL;
13167
13168 case INSTR_TX: return "__instr_tx_exec";
13169 case INSTR_TX_I: return "__instr_tx_i_exec";
13170 case INSTR_DROP: return "__instr_drop_exec";
13171 case INSTR_MIRROR: return "__instr_mirror_exec";
13172 case INSTR_RECIRCULATE: return "__instr_recirculate_exec";
13173 case INSTR_RECIRCID: return "__instr_recircid_exec";
13174
13175 case INSTR_HDR_EXTRACT: return "__instr_hdr_extract_exec";
13176 case INSTR_HDR_EXTRACT2: return "__instr_hdr_extract2_exec";
13177 case INSTR_HDR_EXTRACT3: return "__instr_hdr_extract3_exec";
13178 case INSTR_HDR_EXTRACT4: return "__instr_hdr_extract4_exec";
13179 case INSTR_HDR_EXTRACT5: return "__instr_hdr_extract5_exec";
13180 case INSTR_HDR_EXTRACT6: return "__instr_hdr_extract6_exec";
13181 case INSTR_HDR_EXTRACT7: return "__instr_hdr_extract7_exec";
13182 case INSTR_HDR_EXTRACT8: return "__instr_hdr_extract8_exec";
13183
13184 case INSTR_HDR_EXTRACT_M: return "__instr_hdr_extract_m_exec";
13185
13186 case INSTR_HDR_LOOKAHEAD: return "__instr_hdr_lookahead_exec";
13187
13188 case INSTR_HDR_EMIT: return "__instr_hdr_emit_exec";
13189 case INSTR_HDR_EMIT_TX: return "__instr_hdr_emit_tx_exec";
13190 case INSTR_HDR_EMIT2_TX: return "__instr_hdr_emit2_tx_exec";
13191 case INSTR_HDR_EMIT3_TX: return "__instr_hdr_emit3_tx_exec";
13192 case INSTR_HDR_EMIT4_TX: return "__instr_hdr_emit4_tx_exec";
13193 case INSTR_HDR_EMIT5_TX: return "__instr_hdr_emit5_tx_exec";
13194 case INSTR_HDR_EMIT6_TX: return "__instr_hdr_emit6_tx_exec";
13195 case INSTR_HDR_EMIT7_TX: return "__instr_hdr_emit7_tx_exec";
13196 case INSTR_HDR_EMIT8_TX: return "__instr_hdr_emit8_tx_exec";
13197
13198 case INSTR_HDR_VALIDATE: return "__instr_hdr_validate_exec";
13199 case INSTR_HDR_INVALIDATE: return "__instr_hdr_invalidate_exec";
13200
13201 case INSTR_MOV: return "__instr_mov_exec";
13202 case INSTR_MOV_MH: return "__instr_mov_mh_exec";
13203 case INSTR_MOV_HM: return "__instr_mov_hm_exec";
13204 case INSTR_MOV_HH: return "__instr_mov_hh_exec";
13205 case INSTR_MOV_DMA: return "__instr_mov_dma_exec";
13206 case INSTR_MOV_128: return "__instr_mov_128_exec";
13207 case INSTR_MOV_128_64: return "__instr_mov_128_64_exec";
13208 case INSTR_MOV_64_128: return "__instr_mov_64_128_exec";
13209 case INSTR_MOV_128_32: return "__instr_mov_128_32_exec";
13210 case INSTR_MOV_32_128: return "__instr_mov_32_128_exec";
13211 case INSTR_MOV_I: return "__instr_mov_i_exec";
13212
13213 case INSTR_MOVH: return "__instr_movh_exec";
13214
13215 case INSTR_DMA_HT: return "__instr_dma_ht_exec";
13216 case INSTR_DMA_HT2: return "__instr_dma_ht2_exec";
13217 case INSTR_DMA_HT3: return "__instr_dma_ht3_exec";
13218 case INSTR_DMA_HT4: return "__instr_dma_ht4_exec";
13219 case INSTR_DMA_HT5: return "__instr_dma_ht5_exec";
13220 case INSTR_DMA_HT6: return "__instr_dma_ht6_exec";
13221 case INSTR_DMA_HT7: return "__instr_dma_ht7_exec";
13222 case INSTR_DMA_HT8: return "__instr_dma_ht8_exec";
13223
13224 case INSTR_ALU_ADD: return "__instr_alu_add_exec";
13225 case INSTR_ALU_ADD_MH: return "__instr_alu_add_mh_exec";
13226 case INSTR_ALU_ADD_HM: return "__instr_alu_add_hm_exec";
13227 case INSTR_ALU_ADD_HH: return "__instr_alu_add_hh_exec";
13228 case INSTR_ALU_ADD_MI: return "__instr_alu_add_mi_exec";
13229 case INSTR_ALU_ADD_HI: return "__instr_alu_add_hi_exec";
13230
13231 case INSTR_ALU_SUB: return "__instr_alu_sub_exec";
13232 case INSTR_ALU_SUB_MH: return "__instr_alu_sub_mh_exec";
13233 case INSTR_ALU_SUB_HM: return "__instr_alu_sub_hm_exec";
13234 case INSTR_ALU_SUB_HH: return "__instr_alu_sub_hh_exec";
13235 case INSTR_ALU_SUB_MI: return "__instr_alu_sub_mi_exec";
13236 case INSTR_ALU_SUB_HI: return "__instr_alu_sub_hi_exec";
13237
13238 case INSTR_ALU_CKADD_FIELD: return "__instr_alu_ckadd_field_exec";
13239 case INSTR_ALU_CKADD_STRUCT20: return "__instr_alu_ckadd_struct20_exec";
13240 case INSTR_ALU_CKADD_STRUCT: return "__instr_alu_ckadd_struct_exec";
13241 case INSTR_ALU_CKSUB_FIELD: return "__instr_alu_cksub_field_exec";
13242
13243 case INSTR_ALU_AND: return "__instr_alu_and_exec";
13244 case INSTR_ALU_AND_MH: return "__instr_alu_and_mh_exec";
13245 case INSTR_ALU_AND_HM: return "__instr_alu_and_hm_exec";
13246 case INSTR_ALU_AND_HH: return "__instr_alu_and_hh_exec";
13247 case INSTR_ALU_AND_I: return "__instr_alu_and_i_exec";
13248
13249 case INSTR_ALU_OR: return "__instr_alu_or_exec";
13250 case INSTR_ALU_OR_MH: return "__instr_alu_or_mh_exec";
13251 case INSTR_ALU_OR_HM: return "__instr_alu_or_hm_exec";
13252 case INSTR_ALU_OR_HH: return "__instr_alu_or_hh_exec";
13253 case INSTR_ALU_OR_I: return "__instr_alu_or_i_exec";
13254
13255 case INSTR_ALU_XOR: return "__instr_alu_xor_exec";
13256 case INSTR_ALU_XOR_MH: return "__instr_alu_xor_mh_exec";
13257 case INSTR_ALU_XOR_HM: return "__instr_alu_xor_hm_exec";
13258 case INSTR_ALU_XOR_HH: return "__instr_alu_xor_hh_exec";
13259 case INSTR_ALU_XOR_I: return "__instr_alu_xor_i_exec";
13260
13261 case INSTR_ALU_SHL: return "__instr_alu_shl_exec";
13262 case INSTR_ALU_SHL_MH: return "__instr_alu_shl_mh_exec";
13263 case INSTR_ALU_SHL_HM: return "__instr_alu_shl_hm_exec";
13264 case INSTR_ALU_SHL_HH: return "__instr_alu_shl_hh_exec";
13265 case INSTR_ALU_SHL_MI: return "__instr_alu_shl_mi_exec";
13266 case INSTR_ALU_SHL_HI: return "__instr_alu_shl_hi_exec";
13267
13268 case INSTR_ALU_SHR: return "__instr_alu_shr_exec";
13269 case INSTR_ALU_SHR_MH: return "__instr_alu_shr_mh_exec";
13270 case INSTR_ALU_SHR_HM: return "__instr_alu_shr_hm_exec";
13271 case INSTR_ALU_SHR_HH: return "__instr_alu_shr_hh_exec";
13272 case INSTR_ALU_SHR_MI: return "__instr_alu_shr_mi_exec";
13273 case INSTR_ALU_SHR_HI: return "__instr_alu_shr_hi_exec";
13274
13275 case INSTR_REGPREFETCH_RH: return "__instr_regprefetch_rh_exec";
13276 case INSTR_REGPREFETCH_RM: return "__instr_regprefetch_rm_exec";
13277 case INSTR_REGPREFETCH_RI: return "__instr_regprefetch_ri_exec";
13278
13279 case INSTR_REGRD_HRH: return "__instr_regrd_hrh_exec";
13280 case INSTR_REGRD_HRM: return "__instr_regrd_hrm_exec";
13281 case INSTR_REGRD_HRI: return "__instr_regrd_hri_exec";
13282 case INSTR_REGRD_MRH: return "__instr_regrd_mrh_exec";
13283 case INSTR_REGRD_MRM: return "__instr_regrd_mrm_exec";
13284 case INSTR_REGRD_MRI: return "__instr_regrd_mri_exec";
13285
13286 case INSTR_REGWR_RHH: return "__instr_regwr_rhh_exec";
13287 case INSTR_REGWR_RHM: return "__instr_regwr_rhm_exec";
13288 case INSTR_REGWR_RHI: return "__instr_regwr_rhi_exec";
13289 case INSTR_REGWR_RMH: return "__instr_regwr_rmh_exec";
13290 case INSTR_REGWR_RMM: return "__instr_regwr_rmm_exec";
13291 case INSTR_REGWR_RMI: return "__instr_regwr_rmi_exec";
13292 case INSTR_REGWR_RIH: return "__instr_regwr_rih_exec";
13293 case INSTR_REGWR_RIM: return "__instr_regwr_rim_exec";
13294 case INSTR_REGWR_RII: return "__instr_regwr_rii_exec";
13295
13296 case INSTR_REGADD_RHH: return "__instr_regadd_rhh_exec";
13297 case INSTR_REGADD_RHM: return "__instr_regadd_rhm_exec";
13298 case INSTR_REGADD_RHI: return "__instr_regadd_rhi_exec";
13299 case INSTR_REGADD_RMH: return "__instr_regadd_rmh_exec";
13300 case INSTR_REGADD_RMM: return "__instr_regadd_rmm_exec";
13301 case INSTR_REGADD_RMI: return "__instr_regadd_rmi_exec";
13302 case INSTR_REGADD_RIH: return "__instr_regadd_rih_exec";
13303 case INSTR_REGADD_RIM: return "__instr_regadd_rim_exec";
13304 case INSTR_REGADD_RII: return "__instr_regadd_rii_exec";
13305
13306 case INSTR_METPREFETCH_H: return "__instr_metprefetch_h_exec";
13307 case INSTR_METPREFETCH_M: return "__instr_metprefetch_m_exec";
13308 case INSTR_METPREFETCH_I: return "__instr_metprefetch_i_exec";
13309
13310 case INSTR_METER_HHM: return "__instr_meter_hhm_exec";
13311 case INSTR_METER_HHI: return "__instr_meter_hhi_exec";
13312 case INSTR_METER_HMM: return "__instr_meter_hmm_exec";
13313 case INSTR_METER_HMI: return "__instr_meter_hmi_exec";
13314 case INSTR_METER_MHM: return "__instr_meter_mhm_exec";
13315 case INSTR_METER_MHI: return "__instr_meter_mhi_exec";
13316 case INSTR_METER_MMM: return "__instr_meter_mmm_exec";
13317 case INSTR_METER_MMI: return "__instr_meter_mmi_exec";
13318 case INSTR_METER_IHM: return "__instr_meter_ihm_exec";
13319 case INSTR_METER_IHI: return "__instr_meter_ihi_exec";
13320 case INSTR_METER_IMM: return "__instr_meter_imm_exec";
13321 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 case INSTR_LEARNER_LEARN: return "__instr_learn_exec";
13330 case INSTR_LEARNER_REARM: return "__instr_rearm_exec";
13331 case INSTR_LEARNER_REARM_NEW: return "__instr_rearm_new_exec";
13332 case INSTR_LEARNER_FORGET: return "__instr_forget_exec";
13333 case INSTR_ENTRYID: return "__instr_entryid_exec";
13334
13335 case INSTR_EXTERN_OBJ: return NULL;
13336 case INSTR_EXTERN_FUNC: return NULL;
13337 case INSTR_HASH_FUNC: return "__instr_hash_func_exec";
13338 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
action_instr_does_tx_codegen(struct action * a,uint32_t instr_pos,struct instruction * instr,FILE * f)13377 action_instr_does_tx_codegen(struct action *a,
13378 uint32_t instr_pos,
13379 struct instruction *instr,
13380 FILE *f)
13381 {
13382 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 a->name,
13389 instr_pos);
13390 }
13391
13392 static void
action_instr_extern_obj_codegen(struct action * a,uint32_t instr_pos,FILE * f)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
action_instr_extern_func_codegen(struct action * a,uint32_t instr_pos,FILE * f)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
action_instr_jmp_codegen(struct action * a,uint32_t instr_pos,struct instruction * instr,struct instruction_data * data,FILE * f)13415 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 switch (instr->type) {
13422 case INSTR_JMP:
13423 fprintf(f,
13424 "goto %s;\n",
13425 data->jmp_label);
13426 return;
13427
13428 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 a->name,
13433 instr_pos,
13434 data->jmp_label);
13435 return;
13436
13437 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 a->name,
13442 instr_pos,
13443 data->jmp_label);
13444 return;
13445
13446 case INSTR_JMP_HIT:
13447 fprintf(f,
13448 "if (t->hit)\n"
13449 "\t\tgoto %s;\n",
13450 data->jmp_label);
13451 return;
13452
13453 case INSTR_JMP_MISS:
13454 fprintf(f,
13455 "if (!t->hit)\n"
13456 "\t\tgoto %s;\n",
13457 data->jmp_label);
13458 return;
13459
13460 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 a->name,
13465 instr_pos,
13466 data->jmp_label);
13467 return;
13468
13469 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 a->name,
13474 instr_pos,
13475 data->jmp_label);
13476 return;
13477
13478 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 a->name,
13486 instr_pos,
13487 data->jmp_label);
13488 return;
13489
13490 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 a->name,
13498 instr_pos,
13499 data->jmp_label);
13500 return;
13501
13502 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 a->name,
13510 instr_pos,
13511 data->jmp_label);
13512 return;
13513
13514 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 a->name,
13522 instr_pos,
13523 data->jmp_label);
13524 return;
13525
13526 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 a->name,
13534 instr_pos,
13535 data->jmp_label);
13536 return;
13537
13538 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 a->name,
13546 instr_pos,
13547 data->jmp_label);
13548 return;
13549
13550 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 a->name,
13558 instr_pos,
13559 data->jmp_label);
13560 return;
13561
13562 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 a->name,
13570 instr_pos,
13571 data->jmp_label);
13572 return;
13573
13574 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 a->name,
13582 instr_pos,
13583 data->jmp_label);
13584 return;
13585
13586 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 a->name,
13594 instr_pos,
13595 data->jmp_label);
13596 return;
13597
13598 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 a->name,
13606 instr_pos,
13607 data->jmp_label);
13608 return;
13609
13610 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 a->name,
13618 instr_pos,
13619 data->jmp_label);
13620 return;
13621
13622 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 a->name,
13630 instr_pos,
13631 data->jmp_label);
13632 return;
13633
13634 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 a->name,
13642 instr_pos,
13643 data->jmp_label);
13644 return;
13645
13646 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 a->name,
13654 instr_pos,
13655 data->jmp_label);
13656 return;
13657
13658 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 a->name,
13666 instr_pos,
13667 data->jmp_label);
13668 return;
13669
13670 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 a->name,
13678 instr_pos,
13679 data->jmp_label);
13680 return;
13681
13682 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 a->name,
13690 instr_pos,
13691 data->jmp_label);
13692 return;
13693
13694 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 a->name,
13702 instr_pos,
13703 data->jmp_label);
13704 return;
13705
13706 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 a->name,
13714 instr_pos,
13715 data->jmp_label);
13716 return;
13717
13718 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 a->name,
13726 instr_pos,
13727 data->jmp_label);
13728 return;
13729
13730 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 a->name,
13738 instr_pos,
13739 data->jmp_label);
13740 return;
13741
13742 default:
13743 return;
13744 }
13745 }
13746
13747 static void
action_instr_return_codegen(FILE * f)13748 action_instr_return_codegen(FILE *f)
13749 {
13750 fprintf(f,
13751 "return;\n");
13752 }
13753
13754 static void
action_instr_codegen(struct action * a,FILE * f)13755 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 a->name);
13766
13767 for (i = 0; i < a->n_instructions; i++) {
13768 struct instruction *instr = &a->instructions[i];
13769 struct instruction_data *data = &a->instruction_data[i];
13770
13771 /* Label, if present. */
13772 if (data->label[0])
13773 fprintf(f, "\n%s : ", data->label);
13774 else
13775 fprintf(f, "\n\t");
13776
13777 /* TX instruction type. */
13778 if (instruction_does_tx(instr)) {
13779 action_instr_does_tx_codegen(a, i, instr, f);
13780 continue;
13781 }
13782
13783 /* Extern object/function instruction type. */
13784 if (instr->type == INSTR_EXTERN_OBJ) {
13785 action_instr_extern_obj_codegen(a, i, f);
13786 continue;
13787 }
13788
13789 if (instr->type == INSTR_EXTERN_FUNC) {
13790 action_instr_extern_func_codegen(a, i, f);
13791 continue;
13792 }
13793
13794 /* Jump instruction type. */
13795 if (instruction_is_jmp(instr)) {
13796 action_instr_jmp_codegen(a, i, instr, data, f);
13797 continue;
13798 }
13799
13800 /* Return instruction type. */
13801 if (instr->type == INSTR_RETURN) {
13802 action_instr_return_codegen(f);
13803 continue;
13804 }
13805
13806 /* Any other instruction type. */
13807 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 }
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 *
instruction_group_list_group_find(struct instruction_group_list * igl,uint32_t instruction_id)13832 instruction_group_list_group_find(struct instruction_group_list *igl, uint32_t instruction_id)
13833 {
13834 struct instruction_group *g;
13835
13836 TAILQ_FOREACH(g, igl, node)
13837 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
instruction_group_list_free(struct instruction_group_list * igl)13844 instruction_group_list_free(struct instruction_group_list *igl)
13845 {
13846 if (!igl)
13847 return;
13848
13849 for ( ; ; ) {
13850 struct instruction_group *g;
13851
13852 g = TAILQ_FIRST(igl);
13853 if (!g)
13854 break;
13855
13856 TAILQ_REMOVE(igl, g, node);
13857 free(g);
13858 }
13859
13860 free(igl);
13861 }
13862
13863 static struct instruction_group_list *
instruction_group_list_create(struct rte_swx_pipeline * p)13864 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 if (!p || !p->instructions || !p->instruction_data || !p->n_instructions)
13871 goto error;
13872
13873 /* List init. */
13874 igl = calloc(1, sizeof(struct instruction_group_list));
13875 if (!igl)
13876 goto error;
13877
13878 TAILQ_INIT(igl);
13879
13880 /* Allocate the first group. */
13881 g = calloc(1, sizeof(struct instruction_group));
13882 if (!g)
13883 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 for (i = 0; i < p->n_instructions; i++) {
13889 struct instruction *instr = &p->instructions[i];
13890
13891 /* Check for thread yield instructions. */
13892 if (!instruction_does_thread_yield(instr))
13893 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 if (i - g->first_instr_id) {
13900 /* Finalize the group. */
13901 g->last_instr_id = i - 1;
13902
13903 /* Add the group to the list. Advance the number of groups. */
13904 TAILQ_INSERT_TAIL(igl, g, node);
13905 n_groups++;
13906
13907 /* Allocate a new group. */
13908 g = calloc(1, sizeof(struct instruction_group));
13909 if (!g)
13910 goto error;
13911
13912 /* Initialize the new group. */
13913 g->group_id = n_groups;
13914 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 g->last_instr_id = i;
13924
13925 /* Add the group to the list. Advance the number of groups. */
13926 TAILQ_INSERT_TAIL(igl, g, node);
13927 n_groups++;
13928
13929 /* Allocate a new group. */
13930 g = calloc(1, sizeof(struct instruction_group));
13931 if (!g)
13932 goto error;
13933
13934 /* Initialize the new group. */
13935 g->group_id = n_groups;
13936 g->first_instr_id = i + 1;
13937 }
13938
13939 /* Handle the last group. */
13940 if (i - g->first_instr_id) {
13941 /* Finalize the group. */
13942 g->last_instr_id = i - 1;
13943
13944 /* Add the group to the list. Advance the number of groups. */
13945 TAILQ_INSERT_TAIL(igl, g, node);
13946 n_groups++;
13947 } else
13948 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 for (i = 0; i < p->n_instructions; i++) {
13961 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 if (!data->n_users)
13967 continue;
13968
13969 g = instruction_group_list_group_find(igl, i);
13970 if (!g)
13971 goto error;
13972
13973 /* Find out all the jump instructions with this destination. */
13974 for (j = 0; j < p->n_instructions; j++) {
13975 struct instruction *jmp_instr = &p->instructions[j];
13976 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 if (!instruction_is_jmp(jmp_instr) ||
13983 strcmp(jmp_data->jmp_label, data->label))
13984 continue;
13985
13986 jmp_g = instruction_group_list_group_find(igl, j);
13987 if (!jmp_g)
13988 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 if ((jmp_g->group_id == g->group_id) || (g->first_instr_id == i))
13996 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 new_g = calloc(1, sizeof(struct instruction_group));
14002 if (!new_g)
14003 goto error;
14004
14005 new_g->group_id = n_groups;
14006 new_g->first_instr_id = i;
14007 new_g->last_instr_id = g->last_instr_id;
14008
14009 g->last_instr_id = i - 1;
14010
14011 TAILQ_INSERT_AFTER(igl, g, new_g, node);
14012 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 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 if (!is_modified)
14030 break;
14031 }
14032
14033 /* Re-assign the group IDs to be in incremental order. */
14034 i = 0;
14035 TAILQ_FOREACH(g, igl, node) {
14036 g->group_id = i;
14037
14038 i++;
14039 }
14040
14041 return igl;
14042
14043 error:
14044 instruction_group_list_free(igl);
14045
14046 free(g);
14047
14048 return NULL;
14049 }
14050
14051 static void
pipeline_instr_does_tx_codegen(struct rte_swx_pipeline * p __rte_unused,uint32_t instr_pos,struct instruction * instr,FILE * f)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 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
pipeline_instr_jmp_codegen(struct rte_swx_pipeline * p,struct instruction_group_list * igl,uint32_t jmp_instr_id,struct instruction * jmp_instr,struct instruction_data * jmp_data,FILE * f)14067 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 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 if (!jmp_g)
14299 return -EINVAL;
14300
14301 /* Find the instruction group of the jump destination instruction. */
14302 data = label_find(p->instruction_data, p->n_instructions, jmp_data->jmp_label);
14303 if (!data)
14304 return -EINVAL;
14305
14306 instr_id = data - p->instruction_data;
14307
14308 g = instruction_group_list_group_find(igl, instr_id);
14309 if (!g)
14310 return -EINVAL;
14311
14312 /* Code generation for "near" jump (same instruction group) or "far" jump (different
14313 * instruction group).
14314 */
14315 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
instruction_group_list_codegen(struct instruction_group_list * igl,struct rte_swx_pipeline * p,FILE * f)14331 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 TAILQ_FOREACH(g, igl, node)
14341 if (g->first_instr_id < g->last_instr_id)
14342 is_required = 1;
14343
14344 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 for (i = 0; i < p->n_instructions; i++) {
14352 struct instruction *instr = &p->instructions[i];
14353 instruction_export_t func = export_table[instr->type];
14354
14355 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 TAILQ_FOREACH(g, igl, node) {
14364 struct instruction *last_instr;
14365 uint32_t j;
14366
14367 /* Skip if group contains a single instruction. */
14368 if (g->last_instr_id == g->first_instr_id)
14369 continue;
14370
14371 /* Generate new pipeline function. */
14372 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 for (j = g->first_instr_id; j <= g->last_instr_id; j++) {
14382 struct instruction *instr = &p->instructions[j];
14383 struct instruction_data *data = &p->instruction_data[j];
14384
14385 /* Label, if present. */
14386 if (data->label[0])
14387 fprintf(f, "\n%s : ", data->label);
14388 else
14389 fprintf(f, "\n\t");
14390
14391 /* TX instruction type. */
14392 if (instruction_does_tx(instr)) {
14393 pipeline_instr_does_tx_codegen(p, j, instr, f);
14394 continue;
14395 }
14396
14397 /* Jump instruction type. */
14398 if (instruction_is_jmp(instr)) {
14399 pipeline_instr_jmp_codegen(p, igl, j, instr, data, f);
14400 continue;
14401 }
14402
14403 /* Any other instruction type. */
14404 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 last_instr = &p->instructions[g->last_instr_id];
14417
14418 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
instruction_group_list_custom_instructions_count(struct instruction_group_list * igl)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 TAILQ_FOREACH(g, igl, node) {
14439 if (g->first_instr_id == g->last_instr_id)
14440 continue;
14441
14442 n_custom_instr++;
14443 }
14444
14445 return n_custom_instr;
14446 }
14447
14448 static int
pipeline_adjust_check(struct rte_swx_pipeline * p __rte_unused,struct instruction_group_list * igl)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 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
pipeline_adjust(struct rte_swx_pipeline * p,struct instruction_group_list * igl)14464 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 for (i = 0; i < p->n_instructions; i++) {
14471 struct instruction *instr = &p->instructions[i];
14472
14473 if (instr->type == INSTR_TABLE)
14474 instr->type = INSTR_TABLE_AF;
14475
14476 if (instr->type == INSTR_LEARNER)
14477 instr->type = INSTR_LEARNER_AF;
14478 }
14479
14480 /* Pipeline custom instructions. */
14481 i = 0;
14482 TAILQ_FOREACH(g, igl, node) {
14483 struct instruction *instr = &p->instructions[g->first_instr_id];
14484 uint32_t j;
14485
14486 if (g->first_instr_id == g->last_instr_id)
14487 continue;
14488
14489 /* Install a new custom instruction. */
14490 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 instr->type = INSTR_CUSTOM_0 + i;
14494
14495 /* All the subsequent instructions of the group: invalidate. */
14496 for (j = g->first_instr_id + 1; j <= g->last_instr_id; j++) {
14497 struct instruction_data *data = &p->instruction_data[j];
14498
14499 data->invalid = 1;
14500 }
14501
14502 i++;
14503 }
14504
14505 /* Remove the invalidated instructions. */
14506 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 instr_jmp_resolve(p->instructions, p->instruction_data, p->n_instructions);
14513 }
14514
14515 int
rte_swx_pipeline_codegen(FILE * spec_file,FILE * code_file,uint32_t * err_line,const char ** err_msg)14516 rte_swx_pipeline_codegen(FILE *spec_file,
14517 FILE *code_file,
14518 uint32_t *err_line,
14519 const char **err_msg)
14520
14521 {
14522 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 if (!spec_file || !code_file) {
14530 if (err_line)
14531 *err_line = 0;
14532 if (err_msg)
14533 *err_msg = "Invalid input argument.";
14534 status = -EINVAL;
14535 goto free;
14536 }
14537
14538 /* Pipeline configuration. */
14539 s = pipeline_spec_parse(spec_file, err_line, err_msg);
14540 if (!s) {
14541 status = -EINVAL;
14542 goto free;
14543 }
14544
14545 status = rte_swx_pipeline_config(&p, NULL, 0);
14546 if (status) {
14547 if (err_line)
14548 *err_line = 0;
14549 if (err_msg)
14550 *err_msg = "Pipeline configuration error.";
14551 goto free;
14552 }
14553
14554 status = pipeline_spec_configure(p, s, err_msg);
14555 if (status) {
14556 if (err_line)
14557 *err_line = 0;
14558 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 igl = instruction_group_list_create(p);
14569 if (!igl) {
14570 if (err_line)
14571 *err_line = 0;
14572 if (err_msg)
14573 *err_msg = "Memory allocation failed.";
14574 status = -ENOMEM;
14575 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 pipeline_spec_codegen(code_file, s);
14584 fprintf(code_file, "\n");
14585
14586 /* Code generation for the action instructions. */
14587 TAILQ_FOREACH(a, &p->actions, node) {
14588 fprintf(code_file, "/**\n * Action %s\n */\n\n", a->name);
14589
14590 action_data_codegen(a, code_file);
14591 fprintf(code_file, "\n");
14592
14593 action_instr_codegen(a, code_file);
14594 fprintf(code_file, "\n");
14595 }
14596
14597 /* Code generation for the pipeline instructions. */
14598 instruction_group_list_codegen(igl, p, code_file);
14599
14600 free:
14601 instruction_group_list_free(igl);
14602 rte_swx_pipeline_free(p);
14603 pipeline_spec_free(s);
14604
14605 return status;
14606 }
14607
14608 int
rte_swx_pipeline_build_from_lib(struct rte_swx_pipeline ** pipeline,const char * name,const char * lib_file_name,FILE * iospec_file,int numa_node)14609 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 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 if (!pipeline ||
14626 !name ||
14627 !name[0] ||
14628 !lib_file_name ||
14629 !lib_file_name[0] ||
14630 !iospec_file) {
14631 status = -EINVAL;
14632 goto free;
14633 }
14634
14635 /* Open the library. */
14636 lib = dlopen(lib_file_name, RTLD_LAZY);
14637 if (!lib) {
14638 status = -EIO;
14639 goto free;
14640 }
14641
14642 /* Get the pipeline specification structures. */
14643 s = dlsym(lib, "pipeline_spec");
14644 if (!s) {
14645 status = -EINVAL;
14646 goto free;
14647 }
14648
14649 sio = pipeline_iospec_parse(iospec_file, NULL, NULL);
14650 if (!sio) {
14651 status = -EINVAL;
14652 goto free;
14653 }
14654
14655 /* Pipeline configuration based on the specification structures. */
14656 status = rte_swx_pipeline_config(&p, name, numa_node);
14657 if (status)
14658 goto free;
14659
14660 status = pipeline_iospec_configure(p, sio, NULL);
14661 if (status)
14662 goto free;
14663
14664 status = pipeline_spec_configure(p, s, NULL);
14665 if (status)
14666 goto free;
14667
14668 /* Pipeline build. */
14669 status = rte_swx_pipeline_build(p);
14670 if (status)
14671 goto free;
14672
14673 /* Action instructions. */
14674 TAILQ_FOREACH(a, &p->actions, node) {
14675 char name[RTE_SWX_NAME_SIZE * 2];
14676
14677 snprintf(name, sizeof(name), "action_%s_run", a->name);
14678
14679 p->action_funcs[a->id] = dlsym(lib, name);
14680 if (!p->action_funcs[a->id]) {
14681 status = -EINVAL;
14682 goto free;
14683 }
14684 }
14685
14686 /* Pipeline instructions. */
14687 igl = instruction_group_list_create(p);
14688 if (!igl) {
14689 status = -ENOMEM;
14690 goto free;
14691 }
14692
14693 TAILQ_FOREACH(g, igl, node) {
14694 char name[RTE_SWX_NAME_SIZE * 2];
14695
14696 if (g->first_instr_id == g->last_instr_id)
14697 continue;
14698
14699 snprintf(name, sizeof(name), "pipeline_func_%u", g->group_id);
14700
14701 g->func = dlsym(lib, name);
14702 if (!g->func) {
14703 status = -EINVAL;
14704 goto free;
14705 }
14706 }
14707
14708 status = pipeline_adjust_check(p, igl);
14709 if (status)
14710 goto free;
14711
14712 pipeline_adjust(p, igl);
14713
14714 p->lib = lib;
14715
14716 *pipeline = p;
14717
14718 free:
14719 instruction_group_list_free(igl);
14720
14721 pipeline_iospec_free(sio);
14722
14723 if (status) {
14724 rte_swx_pipeline_free(p);
14725
14726 if (lib)
14727 dlclose(lib);
14728 }
14729
14730 return status;
14731 }
14732