1
2
3
4#include <stdlib.h>
5#include <stdio.h>
6#include <errno.h>
7#include <dlfcn.h>
8
9#include <rte_jhash.h>
10#include <rte_hash_crc.h>
11
12#include <rte_swx_port_ethdev.h>
13#include <rte_swx_port_fd.h>
14#include <rte_swx_port_ring.h>
15#include "rte_swx_port_source_sink.h"
16
17#include <rte_swx_table_em.h>
18#include <rte_swx_table_wm.h>
19
20#include "rte_swx_pipeline_internal.h"
21
22#define CHECK(condition, err_code) \
23do { \
24 if (!(condition)) \
25 return -(err_code); \
26} while (0)
27
28#define CHECK_NAME(name, err_code) \
29 CHECK((name) && \
30 (name)[0] && \
31 (strnlen((name), RTE_SWX_NAME_SIZE) < RTE_SWX_NAME_SIZE), \
32 err_code)
33
34#define CHECK_INSTRUCTION(instr, err_code) \
35 CHECK((instr) && \
36 (instr)[0] && \
37 (strnlen((instr), RTE_SWX_INSTRUCTION_SIZE) < \
38 RTE_SWX_INSTRUCTION_SIZE), \
39 err_code)
40
41
42
43
44#ifndef RTE_SWX_PIPELINE_HUGE_PAGES_DISABLE
45
46#include <rte_malloc.h>
47
48static void *
49env_malloc(size_t size, size_t alignment, int numa_node)
50{
51 return rte_zmalloc_socket(NULL, size, alignment, numa_node);
52}
53
54static void
55env_free(void *start, size_t size __rte_unused)
56{
57 rte_free(start);
58}
59
60#else
61
62#include <numa.h>
63
64static void *
65env_malloc(size_t size, size_t alignment __rte_unused, int numa_node)
66{
67 void *start;
68
69 if (numa_available() == -1)
70 return NULL;
71
72 start = numa_alloc_onnode(size, numa_node);
73 if (!start)
74 return NULL;
75
76 memset(start, 0, size);
77 return start;
78}
79
80static void
81env_free(void *start, size_t size)
82{
83 if (numa_available() == -1)
84 return;
85
86 numa_free(start, size);
87}
88
89#endif
90
91
92
93
94static struct struct_type *
95struct_type_find(struct rte_swx_pipeline *p, const char *name)
96{
97 struct struct_type *elem;
98
99 TAILQ_FOREACH(elem, &p->struct_types, node)
100 if (strcmp(elem->name, name) == 0)
101 return elem;
102
103 return NULL;
104}
105
106static struct field *
107struct_type_field_find(struct struct_type *st, const char *name)
108{
109 uint32_t i;
110
111 for (i = 0; i < st->n_fields; i++) {
112 struct field *f = &st->fields[i];
113
114 if (strcmp(f->name, name) == 0)
115 return f;
116 }
117
118 return NULL;
119}
120
121int
122rte_swx_pipeline_struct_type_register(struct rte_swx_pipeline *p,
123 const char *name,
124 struct rte_swx_field_params *fields,
125 uint32_t n_fields,
126 int last_field_has_variable_size)
127{
128 struct struct_type *st;
129 uint32_t i;
130
131 CHECK(p, EINVAL);
132 CHECK_NAME(name, EINVAL);
133 CHECK(fields, EINVAL);
134 CHECK(n_fields, EINVAL);
135
136 for (i = 0; i < n_fields; i++) {
137 struct rte_swx_field_params *f = &fields[i];
138 int var_size = ((i == n_fields - 1) && last_field_has_variable_size) ? 1 : 0;
139 uint32_t j;
140
141 CHECK_NAME(f->name, EINVAL);
142 CHECK(f->n_bits, EINVAL);
143 CHECK((f->n_bits <= 64) || var_size, EINVAL);
144 CHECK((f->n_bits & 7) == 0, EINVAL);
145
146 for (j = 0; j < i; j++) {
147 struct rte_swx_field_params *f_prev = &fields[j];
148
149 CHECK(strcmp(f->name, f_prev->name), EINVAL);
150 }
151 }
152
153 CHECK(!struct_type_find(p, name), EEXIST);
154
155
156 st = calloc(1, sizeof(struct struct_type));
157 CHECK(st, ENOMEM);
158
159 st->fields = calloc(n_fields, sizeof(struct field));
160 if (!st->fields) {
161 free(st);
162 CHECK(0, ENOMEM);
163 }
164
165
166 strcpy(st->name, name);
167 for (i = 0; i < n_fields; i++) {
168 struct field *dst = &st->fields[i];
169 struct rte_swx_field_params *src = &fields[i];
170 int var_size = ((i == n_fields - 1) && last_field_has_variable_size) ? 1 : 0;
171
172 strcpy(dst->name, src->name);
173 dst->n_bits = src->n_bits;
174 dst->offset = st->n_bits;
175 dst->var_size = var_size;
176
177 st->n_bits += src->n_bits;
178 st->n_bits_min += var_size ? 0 : src->n_bits;
179 }
180 st->n_fields = n_fields;
181 st->var_size = last_field_has_variable_size;
182
183
184 TAILQ_INSERT_TAIL(&p->struct_types, st, node);
185
186 return 0;
187}
188
189static int
190struct_build(struct rte_swx_pipeline *p)
191{
192 uint32_t i;
193
194 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
195 struct thread *t = &p->threads[i];
196
197 t->structs = calloc(p->n_structs, sizeof(uint8_t *));
198 CHECK(t->structs, ENOMEM);
199 }
200
201 return 0;
202}
203
204static void
205struct_build_free(struct rte_swx_pipeline *p)
206{
207 uint32_t i;
208
209 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
210 struct thread *t = &p->threads[i];
211
212 free(t->structs);
213 t->structs = NULL;
214 }
215}
216
217static void
218struct_free(struct rte_swx_pipeline *p)
219{
220 struct_build_free(p);
221
222
223 for ( ; ; ) {
224 struct struct_type *elem;
225
226 elem = TAILQ_FIRST(&p->struct_types);
227 if (!elem)
228 break;
229
230 TAILQ_REMOVE(&p->struct_types, elem, node);
231 free(elem->fields);
232 free(elem);
233 }
234}
235
236
237
238
239static struct port_in_type *
240port_in_type_find(struct rte_swx_pipeline *p, const char *name)
241{
242 struct port_in_type *elem;
243
244 if (!name)
245 return NULL;
246
247 TAILQ_FOREACH(elem, &p->port_in_types, node)
248 if (strcmp(elem->name, name) == 0)
249 return elem;
250
251 return NULL;
252}
253
254int
255rte_swx_pipeline_port_in_type_register(struct rte_swx_pipeline *p,
256 const char *name,
257 struct rte_swx_port_in_ops *ops)
258{
259 struct port_in_type *elem;
260
261 CHECK(p, EINVAL);
262 CHECK_NAME(name, EINVAL);
263 CHECK(ops, EINVAL);
264 CHECK(ops->create, EINVAL);
265 CHECK(ops->free, EINVAL);
266 CHECK(ops->pkt_rx, EINVAL);
267 CHECK(ops->stats_read, EINVAL);
268
269 CHECK(!port_in_type_find(p, name), EEXIST);
270
271
272 elem = calloc(1, sizeof(struct port_in_type));
273 CHECK(elem, ENOMEM);
274
275
276 strcpy(elem->name, name);
277 memcpy(&elem->ops, ops, sizeof(*ops));
278
279
280 TAILQ_INSERT_TAIL(&p->port_in_types, elem, node);
281
282 return 0;
283}
284
285static struct port_in *
286port_in_find(struct rte_swx_pipeline *p, uint32_t port_id)
287{
288 struct port_in *port;
289
290 TAILQ_FOREACH(port, &p->ports_in, node)
291 if (port->id == port_id)
292 return port;
293
294 return NULL;
295}
296
297int
298rte_swx_pipeline_port_in_config(struct rte_swx_pipeline *p,
299 uint32_t port_id,
300 const char *port_type_name,
301 void *args)
302{
303 struct port_in_type *type = NULL;
304 struct port_in *port = NULL;
305 void *obj = NULL;
306
307 CHECK(p, EINVAL);
308
309 CHECK(!port_in_find(p, port_id), EINVAL);
310
311 CHECK_NAME(port_type_name, EINVAL);
312 type = port_in_type_find(p, port_type_name);
313 CHECK(type, EINVAL);
314
315 obj = type->ops.create(args);
316 CHECK(obj, ENODEV);
317
318
319 port = calloc(1, sizeof(struct port_in));
320 CHECK(port, ENOMEM);
321
322
323 port->type = type;
324 port->obj = obj;
325 port->id = port_id;
326
327
328 TAILQ_INSERT_TAIL(&p->ports_in, port, node);
329 if (p->n_ports_in < port_id + 1)
330 p->n_ports_in = port_id + 1;
331
332 return 0;
333}
334
335static int
336port_in_build(struct rte_swx_pipeline *p)
337{
338 struct port_in *port;
339 uint32_t i;
340
341 CHECK(p->n_ports_in, EINVAL);
342 CHECK(rte_is_power_of_2(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
360static void
361port_in_build_free(struct rte_swx_pipeline *p)
362{
363 free(p->in);
364 p->in = NULL;
365}
366
367static void
368port_in_free(struct rte_swx_pipeline *p)
369{
370 port_in_build_free(p);
371
372
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
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
400
401static struct port_out_type *
402port_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
416int
417rte_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
436 elem = calloc(1, sizeof(struct port_out_type));
437 CHECK(elem, ENOMEM);
438
439
440 strcpy(elem->name, name);
441 memcpy(&elem->ops, ops, sizeof(*ops));
442
443
444 TAILQ_INSERT_TAIL(&p->port_out_types, elem, node);
445
446 return 0;
447}
448
449static struct port_out *
450port_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
461int
462rte_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
483 port = calloc(1, sizeof(struct port_out));
484 CHECK(port, ENOMEM);
485
486
487 port->type = type;
488 port->obj = obj;
489 port->id = port_id;
490
491
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
499static int
500port_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
526static void
527port_out_build_free(struct rte_swx_pipeline *p)
528{
529 free(p->out);
530 p->out = NULL;
531}
532
533static void
534port_out_free(struct rte_swx_pipeline *p)
535{
536 port_out_build_free(p);
537
538
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
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
566
567int
568rte_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
586static void
587mirroring_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
595 free(t->mirroring_slots);
596 t->mirroring_slots = NULL;
597 }
598
599
600 free(p->mirroring_sessions);
601 p->mirroring_sessions = NULL;
602}
603
604static void
605mirroring_free(struct rte_swx_pipeline *p)
606{
607 mirroring_build_free(p);
608}
609
610static int
611mirroring_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
619 t->mirroring_slots = calloc(p->n_mirroring_slots, sizeof(uint32_t));
620 if (!t->mirroring_slots)
621 goto error;
622 }
623
624
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
631error:
632 mirroring_build_free(p);
633 return -ENOMEM;
634}
635
636
637
638
639static struct extern_type *
640extern_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
651static struct extern_type_member_func *
652extern_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
663static struct extern_obj *
664extern_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
675static struct extern_type_member_func *
676extern_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
719static struct field *
720extern_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
763int
764rte_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
787 elem = calloc(1, sizeof(struct extern_type));
788 CHECK(elem, ENOMEM);
789
790
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
798 TAILQ_INSERT_TAIL(&p->extern_types, elem, node);
799
800 return 0;
801}
802
803int
804rte_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
825 type_member = calloc(1, sizeof(struct extern_type_member_func));
826 CHECK(type_member, ENOMEM);
827
828
829 strcpy(type_member->name, name);
830 type_member->func = member_func;
831 type_member->id = type->n_funcs;
832
833
834 TAILQ_INSERT_TAIL(&type->funcs, type_member, node);
835 type->n_funcs++;
836
837 return 0;
838}
839
840int
841rte_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
860 obj = calloc(1, sizeof(struct extern_obj));
861 CHECK(obj, ENOMEM);
862
863
864 obj_handle = type->constructor(args);
865 if (!obj_handle) {
866 free(obj);
867 CHECK(0, ENODEV);
868 }
869
870
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
878 TAILQ_INSERT_TAIL(&p->extern_objs, obj, node);
879 p->n_extern_objs++;
880 p->n_structs++;
881
882 return 0;
883}
884
885static int
886extern_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
920static void
921extern_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
943static void
944extern_obj_free(struct rte_swx_pipeline *p)
945{
946 extern_obj_build_free(p);
947
948
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
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
989
990static struct extern_func *
991extern_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
1002static struct extern_func *
1003extern_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
1012static struct field *
1013extern_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
1056int
1057rte_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
1078 f = calloc(1, sizeof(struct extern_func));
1079 CHECK(func, ENOMEM);
1080
1081
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
1089 TAILQ_INSERT_TAIL(&p->extern_funcs, f, node);
1090 p->n_extern_funcs++;
1091 p->n_structs++;
1092
1093 return 0;
1094}
1095
1096static int
1097extern_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
1106 t->extern_funcs = calloc(p->n_extern_funcs,
1107 sizeof(struct extern_func_runtime));
1108 CHECK(t->extern_funcs, ENOMEM);
1109
1110
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
1129static void
1130extern_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
1152static void
1153extern_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
1171
1172static struct hash_func *
1173hash_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
1184int
1185rte_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
1199 f = calloc(1, sizeof(struct hash_func));
1200 CHECK(func, ENOMEM);
1201
1202
1203 strcpy(f->name, name);
1204 f->func = func;
1205 f->id = p->n_hash_funcs;
1206
1207
1208 TAILQ_INSERT_TAIL(&p->hash_funcs, f, node);
1209 p->n_hash_funcs++;
1210
1211 return 0;
1212}
1213
1214static int
1215hash_func_build(struct rte_swx_pipeline *p)
1216{
1217 struct hash_func *func;
1218
1219
1220 p->hash_func_runtime = calloc(p->n_hash_funcs, sizeof(struct hash_func_runtime));
1221 CHECK(p->hash_func_runtime, ENOMEM);
1222
1223
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
1233static void
1234hash_func_build_free(struct rte_swx_pipeline *p)
1235{
1236 free(p->hash_func_runtime);
1237 p->hash_func_runtime = NULL;
1238}
1239
1240static void
1241hash_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
1259
1260static struct header *
1261header_find(struct rte_swx_pipeline *p, const char *name)
1262{
1263 struct header *elem;
1264
1265 TAILQ_FOREACH(elem, &p->headers, node)
1266 if (strcmp(elem->name, name) == 0)
1267 return elem;
1268
1269 return NULL;
1270}
1271
1272static struct header *
1273header_find_by_struct_id(struct rte_swx_pipeline *p, uint32_t struct_id)
1274{
1275 struct header *elem;
1276
1277 TAILQ_FOREACH(elem, &p->headers, node)
1278 if (elem->struct_id == struct_id)
1279 return elem;
1280
1281 return NULL;
1282}
1283
1284static struct header *
1285header_parse(struct rte_swx_pipeline *p,
1286 const char *name)
1287{
1288 if (name[0] != 'h' || name[1] != '.')
1289 return NULL;
1290
1291 return header_find(p, &name[2]);
1292}
1293
1294static struct field *
1295header_field_parse(struct rte_swx_pipeline *p,
1296 const char *name,
1297 struct header **header)
1298{
1299 struct header *h;
1300 struct field *f;
1301 char *header_name, *field_name;
1302
1303 if ((name[0] != 'h') || (name[1] != '.'))
1304 return NULL;
1305
1306 header_name = strdup(&name[2]);
1307 if (!header_name)
1308 return NULL;
1309
1310 field_name = strchr(header_name, '.');
1311 if (!field_name) {
1312 free(header_name);
1313 return NULL;
1314 }
1315
1316 *field_name = 0;
1317 field_name++;
1318
1319 h = header_find(p, header_name);
1320 if (!h) {
1321 free(header_name);
1322 return NULL;
1323 }
1324
1325 f = struct_type_field_find(h->st, field_name);
1326 if (!f) {
1327 free(header_name);
1328 return NULL;
1329 }
1330
1331 if (header)
1332 *header = h;
1333
1334 free(header_name);
1335 return f;
1336}
1337
1338int
1339rte_swx_pipeline_packet_header_register(struct rte_swx_pipeline *p,
1340 const char *name,
1341 const char *struct_type_name)
1342{
1343 struct struct_type *st;
1344 struct header *h;
1345 size_t n_headers_max;
1346
1347 CHECK(p, EINVAL);
1348 CHECK_NAME(name, EINVAL);
1349 CHECK_NAME(struct_type_name, EINVAL);
1350
1351 CHECK(!header_find(p, name), EEXIST);
1352
1353 st = struct_type_find(p, struct_type_name);
1354 CHECK(st, EINVAL);
1355
1356 n_headers_max = RTE_SIZEOF_FIELD(struct thread, valid_headers) * 8;
1357 CHECK(p->n_headers < n_headers_max, ENOSPC);
1358
1359
1360 h = calloc(1, sizeof(struct header));
1361 CHECK(h, ENOMEM);
1362
1363
1364 strcpy(h->name, name);
1365 h->st = st;
1366 h->struct_id = p->n_structs;
1367 h->id = p->n_headers;
1368
1369
1370 TAILQ_INSERT_TAIL(&p->headers, h, node);
1371 p->n_headers++;
1372 p->n_structs++;
1373
1374 return 0;
1375}
1376
1377static int
1378header_build(struct rte_swx_pipeline *p)
1379{
1380 struct header *h;
1381 uint32_t n_bytes = 0, i;
1382
1383 TAILQ_FOREACH(h, &p->headers, node) {
1384 n_bytes += h->st->n_bits / 8;
1385 }
1386
1387 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1388 struct thread *t = &p->threads[i];
1389 uint32_t offset = 0;
1390
1391 t->headers = calloc(p->n_headers,
1392 sizeof(struct header_runtime));
1393 CHECK(t->headers, ENOMEM);
1394
1395 t->headers_out = calloc(p->n_headers,
1396 sizeof(struct header_out_runtime));
1397 CHECK(t->headers_out, ENOMEM);
1398
1399 t->header_storage = calloc(1, n_bytes);
1400 CHECK(t->header_storage, ENOMEM);
1401
1402 t->header_out_storage = calloc(1, n_bytes);
1403 CHECK(t->header_out_storage, ENOMEM);
1404
1405 TAILQ_FOREACH(h, &p->headers, node) {
1406 uint8_t *header_storage;
1407 uint32_t n_bytes = h->st->n_bits / 8;
1408
1409 header_storage = &t->header_storage[offset];
1410 offset += n_bytes;
1411
1412 t->headers[h->id].ptr0 = header_storage;
1413 t->headers[h->id].n_bytes = n_bytes;
1414
1415 t->structs[h->struct_id] = header_storage;
1416 }
1417 }
1418
1419 return 0;
1420}
1421
1422static void
1423header_build_free(struct rte_swx_pipeline *p)
1424{
1425 uint32_t i;
1426
1427 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1428 struct thread *t = &p->threads[i];
1429
1430 free(t->headers_out);
1431 t->headers_out = NULL;
1432
1433 free(t->headers);
1434 t->headers = NULL;
1435
1436 free(t->header_out_storage);
1437 t->header_out_storage = NULL;
1438
1439 free(t->header_storage);
1440 t->header_storage = NULL;
1441 }
1442}
1443
1444static void
1445header_free(struct rte_swx_pipeline *p)
1446{
1447 header_build_free(p);
1448
1449 for ( ; ; ) {
1450 struct header *elem;
1451
1452 elem = TAILQ_FIRST(&p->headers);
1453 if (!elem)
1454 break;
1455
1456 TAILQ_REMOVE(&p->headers, elem, node);
1457 free(elem);
1458 }
1459}
1460
1461
1462
1463
1464static struct field *
1465metadata_field_parse(struct rte_swx_pipeline *p, const char *name)
1466{
1467 if (!p->metadata_st)
1468 return NULL;
1469
1470 if (name[0] != 'm' || name[1] != '.')
1471 return NULL;
1472
1473 return struct_type_field_find(p->metadata_st, &name[2]);
1474}
1475
1476int
1477rte_swx_pipeline_packet_metadata_register(struct rte_swx_pipeline *p,
1478 const char *struct_type_name)
1479{
1480 struct struct_type *st = NULL;
1481
1482 CHECK(p, EINVAL);
1483
1484 CHECK_NAME(struct_type_name, EINVAL);
1485 st = struct_type_find(p, struct_type_name);
1486 CHECK(st, EINVAL);
1487 CHECK(!st->var_size, EINVAL);
1488 CHECK(!p->metadata_st, EINVAL);
1489
1490 p->metadata_st = st;
1491 p->metadata_struct_id = p->n_structs;
1492
1493 p->n_structs++;
1494
1495 return 0;
1496}
1497
1498static int
1499metadata_build(struct rte_swx_pipeline *p)
1500{
1501 uint32_t n_bytes = p->metadata_st->n_bits / 8;
1502 uint32_t i;
1503
1504
1505 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1506 struct thread *t = &p->threads[i];
1507 uint8_t *metadata;
1508
1509 metadata = calloc(1, n_bytes);
1510 CHECK(metadata, ENOMEM);
1511
1512 t->metadata = metadata;
1513 t->structs[p->metadata_struct_id] = metadata;
1514 }
1515
1516 return 0;
1517}
1518
1519static void
1520metadata_build_free(struct rte_swx_pipeline *p)
1521{
1522 uint32_t i;
1523
1524 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1525 struct thread *t = &p->threads[i];
1526
1527 free(t->metadata);
1528 t->metadata = NULL;
1529 }
1530}
1531
1532static void
1533metadata_free(struct rte_swx_pipeline *p)
1534{
1535 metadata_build_free(p);
1536}
1537
1538
1539
1540
1541static int
1542instruction_is_tx(enum instruction_type type)
1543{
1544 switch (type) {
1545 case INSTR_TX:
1546 case INSTR_TX_I:
1547 case INSTR_DROP:
1548 return 1;
1549
1550 default:
1551 return 0;
1552 }
1553}
1554
1555static int
1556instruction_does_tx(struct instruction *instr)
1557{
1558 switch (instr->type) {
1559 case INSTR_TX:
1560 case INSTR_TX_I:
1561 case INSTR_DROP:
1562 case INSTR_HDR_EMIT_TX:
1563 case INSTR_HDR_EMIT2_TX:
1564 case INSTR_HDR_EMIT3_TX:
1565 case INSTR_HDR_EMIT4_TX:
1566 case INSTR_HDR_EMIT5_TX:
1567 case INSTR_HDR_EMIT6_TX:
1568 case INSTR_HDR_EMIT7_TX:
1569 case INSTR_HDR_EMIT8_TX:
1570 return 1;
1571 default:
1572 return 0;
1573 }
1574}
1575
1576static int
1577instruction_is_jmp(struct instruction *instr)
1578{
1579 switch (instr->type) {
1580 case INSTR_JMP:
1581 case INSTR_JMP_VALID:
1582 case INSTR_JMP_INVALID:
1583 case INSTR_JMP_HIT:
1584 case INSTR_JMP_MISS:
1585 case INSTR_JMP_ACTION_HIT:
1586 case INSTR_JMP_ACTION_MISS:
1587 case INSTR_JMP_EQ:
1588 case INSTR_JMP_EQ_MH:
1589 case INSTR_JMP_EQ_HM:
1590 case INSTR_JMP_EQ_HH:
1591 case INSTR_JMP_EQ_I:
1592 case INSTR_JMP_NEQ:
1593 case INSTR_JMP_NEQ_MH:
1594 case INSTR_JMP_NEQ_HM:
1595 case INSTR_JMP_NEQ_HH:
1596 case INSTR_JMP_NEQ_I:
1597 case INSTR_JMP_LT:
1598 case INSTR_JMP_LT_MH:
1599 case INSTR_JMP_LT_HM:
1600 case INSTR_JMP_LT_HH:
1601 case INSTR_JMP_LT_MI:
1602 case INSTR_JMP_LT_HI:
1603 case INSTR_JMP_GT:
1604 case INSTR_JMP_GT_MH:
1605 case INSTR_JMP_GT_HM:
1606 case INSTR_JMP_GT_HH:
1607 case INSTR_JMP_GT_MI:
1608 case INSTR_JMP_GT_HI:
1609 return 1;
1610
1611 default:
1612 return 0;
1613 }
1614}
1615
1616static int
1617instruction_does_thread_yield(struct instruction *instr)
1618{
1619 switch (instr->type) {
1620 case INSTR_RX:
1621 case INSTR_TABLE:
1622 case INSTR_TABLE_AF:
1623 case INSTR_SELECTOR:
1624 case INSTR_LEARNER:
1625 case INSTR_LEARNER_AF:
1626 case INSTR_EXTERN_OBJ:
1627 case INSTR_EXTERN_FUNC:
1628 return 1;
1629 default:
1630 return 0;
1631 }
1632}
1633
1634static struct field *
1635action_field_parse(struct action *action, const char *name);
1636
1637static struct field *
1638struct_field_parse(struct rte_swx_pipeline *p,
1639 struct action *action,
1640 const char *name,
1641 uint32_t *struct_id)
1642{
1643 struct field *f;
1644
1645 switch (name[0]) {
1646 case 'h':
1647 {
1648 struct header *header;
1649
1650 f = header_field_parse(p, name, &header);
1651 if (!f)
1652 return NULL;
1653
1654 *struct_id = header->struct_id;
1655 return f;
1656 }
1657
1658 case 'm':
1659 {
1660 f = metadata_field_parse(p, name);
1661 if (!f)
1662 return NULL;
1663
1664 *struct_id = p->metadata_struct_id;
1665 return f;
1666 }
1667
1668 case 't':
1669 {
1670 if (!action)
1671 return NULL;
1672
1673 f = action_field_parse(action, name);
1674 if (!f)
1675 return NULL;
1676
1677 *struct_id = 0;
1678 return f;
1679 }
1680
1681 case 'e':
1682 {
1683 struct extern_obj *obj;
1684
1685 f = extern_obj_mailbox_field_parse(p, name, &obj);
1686 if (!f)
1687 return NULL;
1688
1689 *struct_id = obj->struct_id;
1690 return f;
1691 }
1692
1693 case 'f':
1694 {
1695 struct extern_func *func;
1696
1697 f = extern_func_mailbox_field_parse(p, name, &func);
1698 if (!f)
1699 return NULL;
1700
1701 *struct_id = func->struct_id;
1702 return f;
1703 }
1704
1705 default:
1706 return NULL;
1707 }
1708}
1709
1710
1711
1712
1713static int
1714instr_rx_translate(struct rte_swx_pipeline *p,
1715 struct action *action,
1716 char **tokens,
1717 int n_tokens,
1718 struct instruction *instr,
1719 struct instruction_data *data __rte_unused)
1720{
1721 struct field *f;
1722
1723 CHECK(!action, EINVAL);
1724 CHECK(n_tokens == 2, EINVAL);
1725
1726 f = metadata_field_parse(p, tokens[1]);
1727 CHECK(f, EINVAL);
1728
1729 instr->type = INSTR_RX;
1730 instr->io.io.offset = f->offset / 8;
1731 instr->io.io.n_bits = f->n_bits;
1732 return 0;
1733}
1734
1735
1736
1737
1738static int
1739instr_tx_translate(struct rte_swx_pipeline *p,
1740 struct action *action __rte_unused,
1741 char **tokens,
1742 int n_tokens,
1743 struct instruction *instr,
1744 struct instruction_data *data __rte_unused)
1745{
1746 char *port = tokens[1];
1747 struct field *f;
1748 uint32_t port_val;
1749
1750 CHECK(n_tokens == 2, EINVAL);
1751
1752 f = metadata_field_parse(p, port);
1753 if (f) {
1754 instr->type = INSTR_TX;
1755 instr->io.io.offset = f->offset / 8;
1756 instr->io.io.n_bits = f->n_bits;
1757 return 0;
1758 }
1759
1760
1761 port_val = strtoul(port, &port, 0);
1762 CHECK(!port[0], EINVAL);
1763
1764 instr->type = INSTR_TX_I;
1765 instr->io.io.val = port_val;
1766 return 0;
1767}
1768
1769static int
1770instr_drop_translate(struct rte_swx_pipeline *p __rte_unused,
1771 struct action *action __rte_unused,
1772 char **tokens __rte_unused,
1773 int n_tokens,
1774 struct instruction *instr,
1775 struct instruction_data *data __rte_unused)
1776{
1777 CHECK(n_tokens == 1, EINVAL);
1778
1779
1780 instr->type = INSTR_DROP;
1781 return 0;
1782}
1783
1784static inline void
1785instr_tx_exec(struct rte_swx_pipeline *p)
1786{
1787 struct thread *t = &p->threads[p->thread_id];
1788 struct instruction *ip = t->ip;
1789
1790 __instr_tx_exec(p, t, ip);
1791
1792
1793 thread_ip_reset(p, t);
1794 instr_rx_exec(p);
1795}
1796
1797static inline void
1798instr_tx_i_exec(struct rte_swx_pipeline *p)
1799{
1800 struct thread *t = &p->threads[p->thread_id];
1801 struct instruction *ip = t->ip;
1802
1803 __instr_tx_i_exec(p, t, ip);
1804
1805
1806 thread_ip_reset(p, t);
1807 instr_rx_exec(p);
1808}
1809
1810static inline void
1811instr_drop_exec(struct rte_swx_pipeline *p)
1812{
1813 struct thread *t = &p->threads[p->thread_id];
1814 struct instruction *ip = t->ip;
1815
1816 __instr_drop_exec(p, t, ip);
1817
1818
1819 thread_ip_reset(p, t);
1820 instr_rx_exec(p);
1821}
1822
1823
1824
1825
1826static int
1827instr_mirror_translate(struct rte_swx_pipeline *p,
1828 struct action *action,
1829 char **tokens,
1830 int n_tokens,
1831 struct instruction *instr,
1832 struct instruction_data *data __rte_unused)
1833{
1834 char *dst = tokens[1], *src = tokens[2];
1835 struct field *fdst, *fsrc;
1836 uint32_t dst_struct_id = 0, src_struct_id = 0;
1837
1838 CHECK(n_tokens == 3, EINVAL);
1839
1840 fdst = struct_field_parse(p, action, dst, &dst_struct_id);
1841 CHECK(fdst, EINVAL);
1842 CHECK(dst[0] != 'h', EINVAL);
1843 CHECK(!fdst->var_size, EINVAL);
1844
1845 fsrc = struct_field_parse(p, action, src, &src_struct_id);
1846 CHECK(fsrc, EINVAL);
1847 CHECK(src[0] != 'h', EINVAL);
1848 CHECK(!fsrc->var_size, EINVAL);
1849
1850 instr->type = INSTR_MIRROR;
1851 instr->mirror.dst.struct_id = (uint8_t)dst_struct_id;
1852 instr->mirror.dst.n_bits = fdst->n_bits;
1853 instr->mirror.dst.offset = fdst->offset / 8;
1854 instr->mirror.src.struct_id = (uint8_t)src_struct_id;
1855 instr->mirror.src.n_bits = fsrc->n_bits;
1856 instr->mirror.src.offset = fsrc->offset / 8;
1857
1858 return 0;
1859}
1860
1861static inline void
1862instr_mirror_exec(struct rte_swx_pipeline *p)
1863{
1864 struct thread *t = &p->threads[p->thread_id];
1865 struct instruction *ip = t->ip;
1866
1867 __instr_mirror_exec(p, t, ip);
1868
1869
1870 thread_ip_inc(p);
1871}
1872
1873
1874
1875
1876static int
1877instr_recirculate_translate(struct rte_swx_pipeline *p __rte_unused,
1878 struct action *action __rte_unused,
1879 char **tokens __rte_unused,
1880 int n_tokens,
1881 struct instruction *instr,
1882 struct instruction_data *data __rte_unused)
1883{
1884 CHECK(n_tokens == 1, EINVAL);
1885
1886 instr->type = INSTR_RECIRCULATE;
1887 return 0;
1888}
1889
1890static int
1891instr_recircid_translate(struct rte_swx_pipeline *p,
1892 struct action *action __rte_unused,
1893 char **tokens,
1894 int n_tokens,
1895 struct instruction *instr,
1896 struct instruction_data *data __rte_unused)
1897{
1898 struct field *f;
1899
1900 CHECK(n_tokens == 2, EINVAL);
1901
1902 f = metadata_field_parse(p, tokens[1]);
1903 CHECK(f, EINVAL);
1904
1905 instr->type = INSTR_RECIRCID;
1906 instr->io.io.offset = f->offset / 8;
1907 instr->io.io.n_bits = f->n_bits;
1908 return 0;
1909}
1910
1911static inline void
1912instr_recirculate_exec(struct rte_swx_pipeline *p)
1913{
1914 struct thread *t = &p->threads[p->thread_id];
1915 struct instruction *ip = t->ip;
1916
1917 __instr_recirculate_exec(p, t, ip);
1918
1919
1920 thread_ip_inc(p);
1921}
1922
1923static inline void
1924instr_recircid_exec(struct rte_swx_pipeline *p)
1925{
1926 struct thread *t = &p->threads[p->thread_id];
1927 struct instruction *ip = t->ip;
1928
1929 __instr_recircid_exec(p, t, ip);
1930
1931
1932 thread_ip_inc(p);
1933}
1934
1935
1936
1937
1938static int
1939instr_hdr_extract_translate(struct rte_swx_pipeline *p,
1940 struct action *action,
1941 char **tokens,
1942 int n_tokens,
1943 struct instruction *instr,
1944 struct instruction_data *data __rte_unused)
1945{
1946 struct header *h;
1947
1948 CHECK(!action, EINVAL);
1949 CHECK((n_tokens == 2) || (n_tokens == 3), EINVAL);
1950
1951 h = header_parse(p, tokens[1]);
1952 CHECK(h, EINVAL);
1953
1954 if (n_tokens == 2) {
1955 CHECK(!h->st->var_size, EINVAL);
1956
1957 instr->type = INSTR_HDR_EXTRACT;
1958 instr->io.hdr.header_id[0] = h->id;
1959 instr->io.hdr.struct_id[0] = h->struct_id;
1960 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
1961 } else {
1962 struct field *mf;
1963
1964 CHECK(h->st->var_size, EINVAL);
1965
1966 mf = metadata_field_parse(p, tokens[2]);
1967 CHECK(mf, EINVAL);
1968 CHECK(!mf->var_size, EINVAL);
1969
1970 instr->type = INSTR_HDR_EXTRACT_M;
1971 instr->io.io.offset = mf->offset / 8;
1972 instr->io.io.n_bits = mf->n_bits;
1973 instr->io.hdr.header_id[0] = h->id;
1974 instr->io.hdr.struct_id[0] = h->struct_id;
1975 instr->io.hdr.n_bytes[0] = h->st->n_bits_min / 8;
1976 }
1977
1978 return 0;
1979}
1980
1981static int
1982instr_hdr_lookahead_translate(struct rte_swx_pipeline *p,
1983 struct action *action,
1984 char **tokens,
1985 int n_tokens,
1986 struct instruction *instr,
1987 struct instruction_data *data __rte_unused)
1988{
1989 struct header *h;
1990
1991 CHECK(!action, EINVAL);
1992 CHECK(n_tokens == 2, EINVAL);
1993
1994 h = header_parse(p, tokens[1]);
1995 CHECK(h, EINVAL);
1996 CHECK(!h->st->var_size, EINVAL);
1997
1998 instr->type = INSTR_HDR_LOOKAHEAD;
1999 instr->io.hdr.header_id[0] = h->id;
2000 instr->io.hdr.struct_id[0] = h->struct_id;
2001 instr->io.hdr.n_bytes[0] = 0;
2002
2003 return 0;
2004}
2005
2006static inline void
2007instr_hdr_extract_exec(struct rte_swx_pipeline *p)
2008{
2009 struct thread *t = &p->threads[p->thread_id];
2010 struct instruction *ip = t->ip;
2011
2012 __instr_hdr_extract_exec(p, t, ip);
2013
2014
2015 thread_ip_inc(p);
2016}
2017
2018static inline void
2019instr_hdr_extract2_exec(struct rte_swx_pipeline *p)
2020{
2021 struct thread *t = &p->threads[p->thread_id];
2022 struct instruction *ip = t->ip;
2023
2024 __instr_hdr_extract2_exec(p, t, ip);
2025
2026
2027 thread_ip_inc(p);
2028}
2029
2030static inline void
2031instr_hdr_extract3_exec(struct rte_swx_pipeline *p)
2032{
2033 struct thread *t = &p->threads[p->thread_id];
2034 struct instruction *ip = t->ip;
2035
2036 __instr_hdr_extract3_exec(p, t, ip);
2037
2038
2039 thread_ip_inc(p);
2040}
2041
2042static inline void
2043instr_hdr_extract4_exec(struct rte_swx_pipeline *p)
2044{
2045 struct thread *t = &p->threads[p->thread_id];
2046 struct instruction *ip = t->ip;
2047
2048 __instr_hdr_extract4_exec(p, t, ip);
2049
2050
2051 thread_ip_inc(p);
2052}
2053
2054static inline void
2055instr_hdr_extract5_exec(struct rte_swx_pipeline *p)
2056{
2057 struct thread *t = &p->threads[p->thread_id];
2058 struct instruction *ip = t->ip;
2059
2060 __instr_hdr_extract5_exec(p, t, ip);
2061
2062
2063 thread_ip_inc(p);
2064}
2065
2066static inline void
2067instr_hdr_extract6_exec(struct rte_swx_pipeline *p)
2068{
2069 struct thread *t = &p->threads[p->thread_id];
2070 struct instruction *ip = t->ip;
2071
2072 __instr_hdr_extract6_exec(p, t, ip);
2073
2074
2075 thread_ip_inc(p);
2076}
2077
2078static inline void
2079instr_hdr_extract7_exec(struct rte_swx_pipeline *p)
2080{
2081 struct thread *t = &p->threads[p->thread_id];
2082 struct instruction *ip = t->ip;
2083
2084 __instr_hdr_extract7_exec(p, t, ip);
2085
2086
2087 thread_ip_inc(p);
2088}
2089
2090static inline void
2091instr_hdr_extract8_exec(struct rte_swx_pipeline *p)
2092{
2093 struct thread *t = &p->threads[p->thread_id];
2094 struct instruction *ip = t->ip;
2095
2096 __instr_hdr_extract8_exec(p, t, ip);
2097
2098
2099 thread_ip_inc(p);
2100}
2101
2102static inline void
2103instr_hdr_extract_m_exec(struct rte_swx_pipeline *p)
2104{
2105 struct thread *t = &p->threads[p->thread_id];
2106 struct instruction *ip = t->ip;
2107
2108 __instr_hdr_extract_m_exec(p, t, ip);
2109
2110
2111 thread_ip_inc(p);
2112}
2113
2114static inline void
2115instr_hdr_lookahead_exec(struct rte_swx_pipeline *p)
2116{
2117 struct thread *t = &p->threads[p->thread_id];
2118 struct instruction *ip = t->ip;
2119
2120 __instr_hdr_lookahead_exec(p, t, ip);
2121
2122
2123 thread_ip_inc(p);
2124}
2125
2126
2127
2128
2129static int
2130instr_hdr_emit_translate(struct rte_swx_pipeline *p,
2131 struct action *action __rte_unused,
2132 char **tokens,
2133 int n_tokens,
2134 struct instruction *instr,
2135 struct instruction_data *data __rte_unused)
2136{
2137 struct header *h;
2138
2139 CHECK(n_tokens == 2, EINVAL);
2140
2141 h = header_parse(p, tokens[1]);
2142 CHECK(h, EINVAL);
2143
2144 instr->type = INSTR_HDR_EMIT;
2145 instr->io.hdr.header_id[0] = h->id;
2146 instr->io.hdr.struct_id[0] = h->struct_id;
2147 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
2148 return 0;
2149}
2150
2151static inline void
2152instr_hdr_emit_exec(struct rte_swx_pipeline *p)
2153{
2154 struct thread *t = &p->threads[p->thread_id];
2155 struct instruction *ip = t->ip;
2156
2157 __instr_hdr_emit_exec(p, t, ip);
2158
2159
2160 thread_ip_inc(p);
2161}
2162
2163static inline void
2164instr_hdr_emit_tx_exec(struct rte_swx_pipeline *p)
2165{
2166 struct thread *t = &p->threads[p->thread_id];
2167 struct instruction *ip = t->ip;
2168
2169 __instr_hdr_emit_tx_exec(p, t, ip);
2170
2171
2172 thread_ip_reset(p, t);
2173 instr_rx_exec(p);
2174}
2175
2176static inline void
2177instr_hdr_emit2_tx_exec(struct rte_swx_pipeline *p)
2178{
2179 struct thread *t = &p->threads[p->thread_id];
2180 struct instruction *ip = t->ip;
2181
2182 __instr_hdr_emit2_tx_exec(p, t, ip);
2183
2184
2185 thread_ip_reset(p, t);
2186 instr_rx_exec(p);
2187}
2188
2189static inline void
2190instr_hdr_emit3_tx_exec(struct rte_swx_pipeline *p)
2191{
2192 struct thread *t = &p->threads[p->thread_id];
2193 struct instruction *ip = t->ip;
2194
2195 __instr_hdr_emit3_tx_exec(p, t, ip);
2196
2197
2198 thread_ip_reset(p, t);
2199 instr_rx_exec(p);
2200}
2201
2202static inline void
2203instr_hdr_emit4_tx_exec(struct rte_swx_pipeline *p)
2204{
2205 struct thread *t = &p->threads[p->thread_id];
2206 struct instruction *ip = t->ip;
2207
2208 __instr_hdr_emit4_tx_exec(p, t, ip);
2209
2210
2211 thread_ip_reset(p, t);
2212 instr_rx_exec(p);
2213}
2214
2215static inline void
2216instr_hdr_emit5_tx_exec(struct rte_swx_pipeline *p)
2217{
2218 struct thread *t = &p->threads[p->thread_id];
2219 struct instruction *ip = t->ip;
2220
2221 __instr_hdr_emit5_tx_exec(p, t, ip);
2222
2223
2224 thread_ip_reset(p, t);
2225 instr_rx_exec(p);
2226}
2227
2228static inline void
2229instr_hdr_emit6_tx_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_emit6_tx_exec(p, t, ip);
2235
2236
2237 thread_ip_reset(p, t);
2238 instr_rx_exec(p);
2239}
2240
2241static inline void
2242instr_hdr_emit7_tx_exec(struct rte_swx_pipeline *p)
2243{
2244 struct thread *t = &p->threads[p->thread_id];
2245 struct instruction *ip = t->ip;
2246
2247 __instr_hdr_emit7_tx_exec(p, t, ip);
2248
2249
2250 thread_ip_reset(p, t);
2251 instr_rx_exec(p);
2252}
2253
2254static inline void
2255instr_hdr_emit8_tx_exec(struct rte_swx_pipeline *p)
2256{
2257 struct thread *t = &p->threads[p->thread_id];
2258 struct instruction *ip = t->ip;
2259
2260 __instr_hdr_emit8_tx_exec(p, t, ip);
2261
2262
2263 thread_ip_reset(p, t);
2264 instr_rx_exec(p);
2265}
2266
2267
2268
2269
2270static int
2271instr_hdr_validate_translate(struct rte_swx_pipeline *p,
2272 struct action *action __rte_unused,
2273 char **tokens,
2274 int n_tokens,
2275 struct instruction *instr,
2276 struct instruction_data *data __rte_unused)
2277{
2278 struct header *h;
2279
2280 CHECK(n_tokens == 2, EINVAL);
2281
2282 h = header_parse(p, tokens[1]);
2283 CHECK(h, EINVAL);
2284
2285 instr->type = INSTR_HDR_VALIDATE;
2286 instr->valid.header_id = h->id;
2287 instr->valid.struct_id = h->struct_id;
2288 return 0;
2289}
2290
2291static inline void
2292instr_hdr_validate_exec(struct rte_swx_pipeline *p)
2293{
2294 struct thread *t = &p->threads[p->thread_id];
2295 struct instruction *ip = t->ip;
2296
2297 __instr_hdr_validate_exec(p, t, ip);
2298
2299
2300 thread_ip_inc(p);
2301}
2302
2303
2304
2305
2306static int
2307instr_hdr_invalidate_translate(struct rte_swx_pipeline *p,
2308 struct action *action __rte_unused,
2309 char **tokens,
2310 int n_tokens,
2311 struct instruction *instr,
2312 struct instruction_data *data __rte_unused)
2313{
2314 struct header *h;
2315
2316 CHECK(n_tokens == 2, EINVAL);
2317
2318 h = header_parse(p, tokens[1]);
2319 CHECK(h, EINVAL);
2320
2321 instr->type = INSTR_HDR_INVALIDATE;
2322 instr->valid.header_id = h->id;
2323 return 0;
2324}
2325
2326static inline void
2327instr_hdr_invalidate_exec(struct rte_swx_pipeline *p)
2328{
2329 struct thread *t = &p->threads[p->thread_id];
2330 struct instruction *ip = t->ip;
2331
2332 __instr_hdr_invalidate_exec(p, t, ip);
2333
2334
2335 thread_ip_inc(p);
2336}
2337
2338
2339
2340
2341static struct table *
2342table_find(struct rte_swx_pipeline *p, const char *name);
2343
2344static struct selector *
2345selector_find(struct rte_swx_pipeline *p, const char *name);
2346
2347static struct learner *
2348learner_find(struct rte_swx_pipeline *p, const char *name);
2349
2350static int
2351instr_table_translate(struct rte_swx_pipeline *p,
2352 struct action *action,
2353 char **tokens,
2354 int n_tokens,
2355 struct instruction *instr,
2356 struct instruction_data *data __rte_unused)
2357{
2358 struct table *t;
2359 struct selector *s;
2360 struct learner *l;
2361
2362 CHECK(!action, EINVAL);
2363 CHECK(n_tokens == 2, EINVAL);
2364
2365 t = table_find(p, tokens[1]);
2366 if (t) {
2367 instr->type = INSTR_TABLE;
2368 instr->table.table_id = t->id;
2369 return 0;
2370 }
2371
2372 s = selector_find(p, tokens[1]);
2373 if (s) {
2374 instr->type = INSTR_SELECTOR;
2375 instr->table.table_id = s->id;
2376 return 0;
2377 }
2378
2379 l = learner_find(p, tokens[1]);
2380 if (l) {
2381 instr->type = INSTR_LEARNER;
2382 instr->table.table_id = l->id;
2383 return 0;
2384 }
2385
2386 CHECK(0, EINVAL);
2387}
2388
2389static inline void
2390instr_table_exec(struct rte_swx_pipeline *p)
2391{
2392 struct thread *t = &p->threads[p->thread_id];
2393 struct instruction *ip = t->ip;
2394 uint32_t table_id = ip->table.table_id;
2395 struct rte_swx_table_state *ts = &t->table_state[table_id];
2396 struct table_runtime *table = &t->tables[table_id];
2397 struct table_statistics *stats = &p->table_stats[table_id];
2398 uint64_t action_id, n_pkts_hit, n_pkts_action;
2399 uint8_t *action_data;
2400 int done, hit;
2401
2402
2403 done = table->func(ts->obj,
2404 table->mailbox,
2405 table->key,
2406 &action_id,
2407 &action_data,
2408 &hit);
2409 if (!done) {
2410
2411 TRACE("[Thread %2u] table %u (not finalized)\n",
2412 p->thread_id,
2413 table_id);
2414
2415 thread_yield(p);
2416 return;
2417 }
2418
2419 action_id = hit ? action_id : ts->default_action_id;
2420 action_data = hit ? action_data : ts->default_action_data;
2421 n_pkts_hit = stats->n_pkts_hit[hit];
2422 n_pkts_action = stats->n_pkts_action[action_id];
2423
2424 TRACE("[Thread %2u] table %u (%s, action %u)\n",
2425 p->thread_id,
2426 table_id,
2427 hit ? "hit" : "miss",
2428 (uint32_t)action_id);
2429
2430 t->action_id = action_id;
2431 t->structs[0] = action_data;
2432 t->hit = hit;
2433 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2434 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2435
2436
2437 thread_ip_action_call(p, t, action_id);
2438}
2439
2440static inline void
2441instr_table_af_exec(struct rte_swx_pipeline *p)
2442{
2443 struct thread *t = &p->threads[p->thread_id];
2444 struct instruction *ip = t->ip;
2445 uint32_t table_id = ip->table.table_id;
2446 struct rte_swx_table_state *ts = &t->table_state[table_id];
2447 struct table_runtime *table = &t->tables[table_id];
2448 struct table_statistics *stats = &p->table_stats[table_id];
2449 uint64_t action_id, n_pkts_hit, n_pkts_action;
2450 uint8_t *action_data;
2451 action_func_t action_func;
2452 int done, hit;
2453
2454
2455 done = table->func(ts->obj,
2456 table->mailbox,
2457 table->key,
2458 &action_id,
2459 &action_data,
2460 &hit);
2461 if (!done) {
2462
2463 TRACE("[Thread %2u] table %u (not finalized)\n",
2464 p->thread_id,
2465 table_id);
2466
2467 thread_yield(p);
2468 return;
2469 }
2470
2471 action_id = hit ? action_id : ts->default_action_id;
2472 action_data = hit ? action_data : ts->default_action_data;
2473 action_func = p->action_funcs[action_id];
2474 n_pkts_hit = stats->n_pkts_hit[hit];
2475 n_pkts_action = stats->n_pkts_action[action_id];
2476
2477 TRACE("[Thread %2u] table %u (%s, action %u)\n",
2478 p->thread_id,
2479 table_id,
2480 hit ? "hit" : "miss",
2481 (uint32_t)action_id);
2482
2483 t->action_id = action_id;
2484 t->structs[0] = action_data;
2485 t->hit = hit;
2486 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2487 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2488
2489
2490 thread_ip_inc(p);
2491
2492
2493 action_func(p);
2494}
2495
2496static inline void
2497instr_selector_exec(struct rte_swx_pipeline *p)
2498{
2499 struct thread *t = &p->threads[p->thread_id];
2500 struct instruction *ip = t->ip;
2501 uint32_t selector_id = ip->table.table_id;
2502 struct rte_swx_table_state *ts = &t->table_state[p->n_tables + selector_id];
2503 struct selector_runtime *selector = &t->selectors[selector_id];
2504 struct selector_statistics *stats = &p->selector_stats[selector_id];
2505 uint64_t n_pkts = stats->n_pkts;
2506 int done;
2507
2508
2509 done = rte_swx_table_selector_select(ts->obj,
2510 selector->mailbox,
2511 selector->group_id_buffer,
2512 selector->selector_buffer,
2513 selector->member_id_buffer);
2514 if (!done) {
2515
2516 TRACE("[Thread %2u] selector %u (not finalized)\n",
2517 p->thread_id,
2518 selector_id);
2519
2520 thread_yield(p);
2521 return;
2522 }
2523
2524
2525 TRACE("[Thread %2u] selector %u\n",
2526 p->thread_id,
2527 selector_id);
2528
2529 stats->n_pkts = n_pkts + 1;
2530
2531
2532 thread_ip_inc(p);
2533}
2534
2535static inline void
2536instr_learner_exec(struct rte_swx_pipeline *p)
2537{
2538 struct thread *t = &p->threads[p->thread_id];
2539 struct instruction *ip = t->ip;
2540 uint32_t learner_id = ip->table.table_id;
2541 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2542 p->n_selectors + learner_id];
2543 struct learner_runtime *l = &t->learners[learner_id];
2544 struct learner_statistics *stats = &p->learner_stats[learner_id];
2545 uint64_t action_id, n_pkts_hit, n_pkts_action, time;
2546 uint8_t *action_data;
2547 int done, hit;
2548
2549
2550 time = rte_get_tsc_cycles();
2551
2552 done = rte_swx_table_learner_lookup(ts->obj,
2553 l->mailbox,
2554 time,
2555 l->key,
2556 &action_id,
2557 &action_data,
2558 &hit);
2559 if (!done) {
2560
2561 TRACE("[Thread %2u] learner %u (not finalized)\n",
2562 p->thread_id,
2563 learner_id);
2564
2565 thread_yield(p);
2566 return;
2567 }
2568
2569 action_id = hit ? action_id : ts->default_action_id;
2570 action_data = hit ? action_data : ts->default_action_data;
2571 n_pkts_hit = stats->n_pkts_hit[hit];
2572 n_pkts_action = stats->n_pkts_action[action_id];
2573
2574 TRACE("[Thread %2u] learner %u (%s, action %u)\n",
2575 p->thread_id,
2576 learner_id,
2577 hit ? "hit" : "miss",
2578 (uint32_t)action_id);
2579
2580 t->action_id = action_id;
2581 t->structs[0] = action_data;
2582 t->hit = hit;
2583 t->learner_id = learner_id;
2584 t->time = time;
2585 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2586 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2587
2588
2589 thread_ip_action_call(p, t, action_id);
2590}
2591
2592static inline void
2593instr_learner_af_exec(struct rte_swx_pipeline *p)
2594{
2595 struct thread *t = &p->threads[p->thread_id];
2596 struct instruction *ip = t->ip;
2597 uint32_t learner_id = ip->table.table_id;
2598 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2599 p->n_selectors + learner_id];
2600 struct learner_runtime *l = &t->learners[learner_id];
2601 struct learner_statistics *stats = &p->learner_stats[learner_id];
2602 uint64_t action_id, n_pkts_hit, n_pkts_action, time;
2603 uint8_t *action_data;
2604 action_func_t action_func;
2605 int done, hit;
2606
2607
2608 time = rte_get_tsc_cycles();
2609
2610 done = rte_swx_table_learner_lookup(ts->obj,
2611 l->mailbox,
2612 time,
2613 l->key,
2614 &action_id,
2615 &action_data,
2616 &hit);
2617 if (!done) {
2618
2619 TRACE("[Thread %2u] learner %u (not finalized)\n",
2620 p->thread_id,
2621 learner_id);
2622
2623 thread_yield(p);
2624 return;
2625 }
2626
2627 action_id = hit ? action_id : ts->default_action_id;
2628 action_data = hit ? action_data : ts->default_action_data;
2629 action_func = p->action_funcs[action_id];
2630 n_pkts_hit = stats->n_pkts_hit[hit];
2631 n_pkts_action = stats->n_pkts_action[action_id];
2632
2633 TRACE("[Thread %2u] learner %u (%s, action %u)\n",
2634 p->thread_id,
2635 learner_id,
2636 hit ? "hit" : "miss",
2637 (uint32_t)action_id);
2638
2639 t->action_id = action_id;
2640 t->structs[0] = action_data;
2641 t->hit = hit;
2642 t->learner_id = learner_id;
2643 t->time = time;
2644 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2645 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2646
2647
2648 thread_ip_inc(p);
2649
2650
2651 action_func(p);
2652}
2653
2654
2655
2656
2657static struct action *
2658action_find(struct rte_swx_pipeline *p, const char *name);
2659
2660static int
2661action_has_nbo_args(struct action *a);
2662
2663static int
2664learner_action_args_check(struct rte_swx_pipeline *p, struct action *a, const char *mf_name);
2665
2666static int
2667instr_learn_translate(struct rte_swx_pipeline *p,
2668 struct action *action,
2669 char **tokens,
2670 int n_tokens,
2671 struct instruction *instr,
2672 struct instruction_data *data __rte_unused)
2673{
2674 struct action *a;
2675 struct field *mf_first_arg = NULL, *mf_timeout_id = NULL;
2676 const char *mf_first_arg_name, *mf_timeout_id_name;
2677
2678 CHECK(action, EINVAL);
2679 CHECK((n_tokens == 3) || (n_tokens == 4), EINVAL);
2680
2681
2682 a = action_find(p, tokens[1]);
2683 CHECK(a, EINVAL);
2684 CHECK(!action_has_nbo_args(a), EINVAL);
2685
2686
2687 mf_first_arg_name = (n_tokens == 4) ? tokens[2] : NULL;
2688 CHECK(!learner_action_args_check(p, a, mf_first_arg_name), EINVAL);
2689
2690 if (mf_first_arg_name) {
2691 mf_first_arg = metadata_field_parse(p, mf_first_arg_name);
2692 CHECK(mf_first_arg, EINVAL);
2693 }
2694
2695
2696 mf_timeout_id_name = (n_tokens == 4) ? tokens[3] : tokens[2];
2697 CHECK_NAME(mf_timeout_id_name, EINVAL);
2698 mf_timeout_id = metadata_field_parse(p, mf_timeout_id_name);
2699 CHECK(mf_timeout_id, EINVAL);
2700
2701
2702 instr->type = INSTR_LEARNER_LEARN;
2703 instr->learn.action_id = a->id;
2704 instr->learn.mf_first_arg_offset = mf_first_arg ? (mf_first_arg->offset / 8) : 0;
2705 instr->learn.mf_timeout_id_offset = mf_timeout_id->offset / 8;
2706 instr->learn.mf_timeout_id_n_bits = mf_timeout_id->n_bits;
2707
2708 return 0;
2709}
2710
2711static inline void
2712instr_learn_exec(struct rte_swx_pipeline *p)
2713{
2714 struct thread *t = &p->threads[p->thread_id];
2715 struct instruction *ip = t->ip;
2716
2717 __instr_learn_exec(p, t, ip);
2718
2719
2720 thread_ip_inc(p);
2721}
2722
2723
2724
2725
2726static int
2727instr_rearm_translate(struct rte_swx_pipeline *p,
2728 struct action *action,
2729 char **tokens,
2730 int n_tokens,
2731 struct instruction *instr,
2732 struct instruction_data *data __rte_unused)
2733{
2734 struct field *mf_timeout_id;
2735 const char *mf_timeout_id_name;
2736
2737 CHECK(action, EINVAL);
2738 CHECK((n_tokens == 1) || (n_tokens == 2), EINVAL);
2739
2740
2741 if (n_tokens == 1) {
2742 instr->type = INSTR_LEARNER_REARM;
2743 return 0;
2744 }
2745
2746
2747 mf_timeout_id_name = tokens[1];
2748 CHECK_NAME(mf_timeout_id_name, EINVAL);
2749 mf_timeout_id = metadata_field_parse(p, mf_timeout_id_name);
2750 CHECK(mf_timeout_id, EINVAL);
2751
2752 instr->type = INSTR_LEARNER_REARM_NEW;
2753 instr->learn.mf_timeout_id_offset = mf_timeout_id->offset / 8;
2754 instr->learn.mf_timeout_id_n_bits = mf_timeout_id->n_bits;
2755
2756 return 0;
2757}
2758
2759static inline void
2760instr_rearm_exec(struct rte_swx_pipeline *p)
2761{
2762 struct thread *t = &p->threads[p->thread_id];
2763 struct instruction *ip = t->ip;
2764
2765 __instr_rearm_exec(p, t, ip);
2766
2767
2768 thread_ip_inc(p);
2769}
2770
2771static inline void
2772instr_rearm_new_exec(struct rte_swx_pipeline *p)
2773{
2774 struct thread *t = &p->threads[p->thread_id];
2775 struct instruction *ip = t->ip;
2776
2777 __instr_rearm_new_exec(p, t, ip);
2778
2779
2780 thread_ip_inc(p);
2781}
2782
2783
2784
2785
2786static int
2787instr_forget_translate(struct rte_swx_pipeline *p __rte_unused,
2788 struct action *action,
2789 char **tokens __rte_unused,
2790 int n_tokens,
2791 struct instruction *instr,
2792 struct instruction_data *data __rte_unused)
2793{
2794 CHECK(action, EINVAL);
2795 CHECK(n_tokens == 1, EINVAL);
2796
2797 instr->type = INSTR_LEARNER_FORGET;
2798
2799 return 0;
2800}
2801
2802static inline void
2803instr_forget_exec(struct rte_swx_pipeline *p)
2804{
2805 struct thread *t = &p->threads[p->thread_id];
2806 struct instruction *ip = t->ip;
2807
2808 __instr_forget_exec(p, t, ip);
2809
2810
2811 thread_ip_inc(p);
2812}
2813
2814
2815
2816
2817static int
2818instr_extern_translate(struct rte_swx_pipeline *p,
2819 struct action *action __rte_unused,
2820 char **tokens,
2821 int n_tokens,
2822 struct instruction *instr,
2823 struct instruction_data *data __rte_unused)
2824{
2825 char *token = tokens[1];
2826
2827 CHECK(n_tokens == 2, EINVAL);
2828
2829 if (token[0] == 'e') {
2830 struct extern_obj *obj;
2831 struct extern_type_member_func *func;
2832
2833 func = extern_obj_member_func_parse(p, token, &obj);
2834 CHECK(func, EINVAL);
2835
2836 instr->type = INSTR_EXTERN_OBJ;
2837 instr->ext_obj.ext_obj_id = obj->id;
2838 instr->ext_obj.func_id = func->id;
2839
2840 return 0;
2841 }
2842
2843 if (token[0] == 'f') {
2844 struct extern_func *func;
2845
2846 func = extern_func_parse(p, token);
2847 CHECK(func, EINVAL);
2848
2849 instr->type = INSTR_EXTERN_FUNC;
2850 instr->ext_func.ext_func_id = func->id;
2851
2852 return 0;
2853 }
2854
2855 CHECK(0, EINVAL);
2856}
2857
2858static inline void
2859instr_extern_obj_exec(struct rte_swx_pipeline *p)
2860{
2861 struct thread *t = &p->threads[p->thread_id];
2862 struct instruction *ip = t->ip;
2863 uint32_t done;
2864
2865
2866 done = __instr_extern_obj_exec(p, t, ip);
2867
2868
2869 thread_ip_inc_cond(t, done);
2870 thread_yield_cond(p, done ^ 1);
2871}
2872
2873static inline void
2874instr_extern_func_exec(struct rte_swx_pipeline *p)
2875{
2876 struct thread *t = &p->threads[p->thread_id];
2877 struct instruction *ip = t->ip;
2878 uint32_t done;
2879
2880
2881 done = __instr_extern_func_exec(p, t, ip);
2882
2883
2884 thread_ip_inc_cond(t, done);
2885 thread_yield_cond(p, done ^ 1);
2886}
2887
2888
2889
2890
2891static int
2892instr_hash_translate(struct rte_swx_pipeline *p,
2893 struct action *action,
2894 char **tokens,
2895 int n_tokens,
2896 struct instruction *instr,
2897 struct instruction_data *data __rte_unused)
2898{
2899 struct hash_func *func;
2900 struct field *dst, *src_first, *src_last;
2901 uint32_t src_struct_id_first = 0, src_struct_id_last = 0;
2902
2903 CHECK(n_tokens == 5, EINVAL);
2904
2905 func = hash_func_find(p, tokens[1]);
2906 CHECK(func, EINVAL);
2907
2908 dst = metadata_field_parse(p, tokens[2]);
2909 CHECK(dst, EINVAL);
2910
2911 src_first = struct_field_parse(p, action, tokens[3], &src_struct_id_first);
2912 CHECK(src_first, EINVAL);
2913
2914 src_last = struct_field_parse(p, action, tokens[4], &src_struct_id_last);
2915 CHECK(src_last, EINVAL);
2916 CHECK(src_struct_id_first == src_struct_id_last, EINVAL);
2917
2918 instr->type = INSTR_HASH_FUNC;
2919 instr->hash_func.hash_func_id = (uint8_t)func->id;
2920 instr->hash_func.dst.offset = (uint8_t)dst->offset / 8;
2921 instr->hash_func.dst.n_bits = (uint8_t)dst->n_bits;
2922 instr->hash_func.src.struct_id = (uint8_t)src_struct_id_first;
2923 instr->hash_func.src.offset = (uint16_t)src_first->offset / 8;
2924 instr->hash_func.src.n_bytes = (uint16_t)((src_last->offset + src_last->n_bits -
2925 src_first->offset) / 8);
2926
2927 return 0;
2928}
2929
2930static inline void
2931instr_hash_func_exec(struct rte_swx_pipeline *p)
2932{
2933 struct thread *t = &p->threads[p->thread_id];
2934 struct instruction *ip = t->ip;
2935
2936
2937 __instr_hash_func_exec(p, t, ip);
2938
2939
2940 thread_ip_inc(p);
2941}
2942
2943
2944
2945
2946static int
2947instr_mov_translate(struct rte_swx_pipeline *p,
2948 struct action *action,
2949 char **tokens,
2950 int n_tokens,
2951 struct instruction *instr,
2952 struct instruction_data *data __rte_unused)
2953{
2954 char *dst = tokens[1], *src = tokens[2];
2955 struct field *fdst, *fsrc;
2956 uint64_t src_val;
2957 uint32_t dst_struct_id = 0, src_struct_id = 0;
2958
2959 CHECK(n_tokens == 3, EINVAL);
2960
2961 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2962 CHECK(fdst, EINVAL);
2963 CHECK(!fdst->var_size, EINVAL);
2964
2965
2966 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2967 if (fsrc) {
2968 CHECK(!fsrc->var_size, EINVAL);
2969
2970 instr->type = INSTR_MOV;
2971 if (dst[0] != 'h' && src[0] == 'h')
2972 instr->type = INSTR_MOV_MH;
2973 if (dst[0] == 'h' && src[0] != 'h')
2974 instr->type = INSTR_MOV_HM;
2975 if (dst[0] == 'h' && src[0] == 'h')
2976 instr->type = INSTR_MOV_HH;
2977
2978 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
2979 instr->mov.dst.n_bits = fdst->n_bits;
2980 instr->mov.dst.offset = fdst->offset / 8;
2981 instr->mov.src.struct_id = (uint8_t)src_struct_id;
2982 instr->mov.src.n_bits = fsrc->n_bits;
2983 instr->mov.src.offset = fsrc->offset / 8;
2984 return 0;
2985 }
2986
2987
2988 src_val = strtoull(src, &src, 0);
2989 CHECK(!src[0], EINVAL);
2990
2991 if (dst[0] == 'h')
2992 src_val = hton64(src_val) >> (64 - fdst->n_bits);
2993
2994 instr->type = INSTR_MOV_I;
2995 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
2996 instr->mov.dst.n_bits = fdst->n_bits;
2997 instr->mov.dst.offset = fdst->offset / 8;
2998 instr->mov.src_val = src_val;
2999 return 0;
3000}
3001
3002static inline void
3003instr_mov_exec(struct rte_swx_pipeline *p)
3004{
3005 struct thread *t = &p->threads[p->thread_id];
3006 struct instruction *ip = t->ip;
3007
3008 __instr_mov_exec(p, t, ip);
3009
3010
3011 thread_ip_inc(p);
3012}
3013
3014static inline void
3015instr_mov_mh_exec(struct rte_swx_pipeline *p)
3016{
3017 struct thread *t = &p->threads[p->thread_id];
3018 struct instruction *ip = t->ip;
3019
3020 __instr_mov_mh_exec(p, t, ip);
3021
3022
3023 thread_ip_inc(p);
3024}
3025
3026static inline void
3027instr_mov_hm_exec(struct rte_swx_pipeline *p)
3028{
3029 struct thread *t = &p->threads[p->thread_id];
3030 struct instruction *ip = t->ip;
3031
3032 __instr_mov_hm_exec(p, t, ip);
3033
3034
3035 thread_ip_inc(p);
3036}
3037
3038static inline void
3039instr_mov_hh_exec(struct rte_swx_pipeline *p)
3040{
3041 struct thread *t = &p->threads[p->thread_id];
3042 struct instruction *ip = t->ip;
3043
3044 __instr_mov_hh_exec(p, t, ip);
3045
3046
3047 thread_ip_inc(p);
3048}
3049
3050static inline void
3051instr_mov_i_exec(struct rte_swx_pipeline *p)
3052{
3053 struct thread *t = &p->threads[p->thread_id];
3054 struct instruction *ip = t->ip;
3055
3056 __instr_mov_i_exec(p, t, ip);
3057
3058
3059 thread_ip_inc(p);
3060}
3061
3062
3063
3064
3065static inline void
3066instr_dma_ht_exec(struct rte_swx_pipeline *p)
3067{
3068 struct thread *t = &p->threads[p->thread_id];
3069 struct instruction *ip = t->ip;
3070
3071 __instr_dma_ht_exec(p, t, ip);
3072
3073
3074 thread_ip_inc(p);
3075}
3076
3077static inline void
3078instr_dma_ht2_exec(struct rte_swx_pipeline *p)
3079{
3080 struct thread *t = &p->threads[p->thread_id];
3081 struct instruction *ip = t->ip;
3082
3083 __instr_dma_ht2_exec(p, t, ip);
3084
3085
3086 thread_ip_inc(p);
3087}
3088
3089static inline void
3090instr_dma_ht3_exec(struct rte_swx_pipeline *p)
3091{
3092 struct thread *t = &p->threads[p->thread_id];
3093 struct instruction *ip = t->ip;
3094
3095 __instr_dma_ht3_exec(p, t, ip);
3096
3097
3098 thread_ip_inc(p);
3099}
3100
3101static inline void
3102instr_dma_ht4_exec(struct rte_swx_pipeline *p)
3103{
3104 struct thread *t = &p->threads[p->thread_id];
3105 struct instruction *ip = t->ip;
3106
3107 __instr_dma_ht4_exec(p, t, ip);
3108
3109
3110 thread_ip_inc(p);
3111}
3112
3113static inline void
3114instr_dma_ht5_exec(struct rte_swx_pipeline *p)
3115{
3116 struct thread *t = &p->threads[p->thread_id];
3117 struct instruction *ip = t->ip;
3118
3119 __instr_dma_ht5_exec(p, t, ip);
3120
3121
3122 thread_ip_inc(p);
3123}
3124
3125static inline void
3126instr_dma_ht6_exec(struct rte_swx_pipeline *p)
3127{
3128 struct thread *t = &p->threads[p->thread_id];
3129 struct instruction *ip = t->ip;
3130
3131 __instr_dma_ht6_exec(p, t, ip);
3132
3133
3134 thread_ip_inc(p);
3135}
3136
3137static inline void
3138instr_dma_ht7_exec(struct rte_swx_pipeline *p)
3139{
3140 struct thread *t = &p->threads[p->thread_id];
3141 struct instruction *ip = t->ip;
3142
3143 __instr_dma_ht7_exec(p, t, ip);
3144
3145
3146 thread_ip_inc(p);
3147}
3148
3149static inline void
3150instr_dma_ht8_exec(struct rte_swx_pipeline *p)
3151{
3152 struct thread *t = &p->threads[p->thread_id];
3153 struct instruction *ip = t->ip;
3154
3155 __instr_dma_ht8_exec(p, t, ip);
3156
3157
3158 thread_ip_inc(p);
3159}
3160
3161
3162
3163
3164static int
3165instr_alu_add_translate(struct rte_swx_pipeline *p,
3166 struct action *action,
3167 char **tokens,
3168 int n_tokens,
3169 struct instruction *instr,
3170 struct instruction_data *data __rte_unused)
3171{
3172 char *dst = tokens[1], *src = tokens[2];
3173 struct field *fdst, *fsrc;
3174 uint64_t src_val;
3175 uint32_t dst_struct_id = 0, src_struct_id = 0;
3176
3177 CHECK(n_tokens == 3, EINVAL);
3178
3179 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3180 CHECK(fdst, EINVAL);
3181 CHECK(!fdst->var_size, EINVAL);
3182
3183
3184 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3185 if (fsrc) {
3186 CHECK(!fsrc->var_size, EINVAL);
3187
3188 instr->type = INSTR_ALU_ADD;
3189 if (dst[0] == 'h' && src[0] != 'h')
3190 instr->type = INSTR_ALU_ADD_HM;
3191 if (dst[0] != 'h' && src[0] == 'h')
3192 instr->type = INSTR_ALU_ADD_MH;
3193 if (dst[0] == 'h' && src[0] == 'h')
3194 instr->type = INSTR_ALU_ADD_HH;
3195
3196 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3197 instr->alu.dst.n_bits = fdst->n_bits;
3198 instr->alu.dst.offset = fdst->offset / 8;
3199 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3200 instr->alu.src.n_bits = fsrc->n_bits;
3201 instr->alu.src.offset = fsrc->offset / 8;
3202 return 0;
3203 }
3204
3205
3206 src_val = strtoull(src, &src, 0);
3207 CHECK(!src[0], EINVAL);
3208
3209 instr->type = INSTR_ALU_ADD_MI;
3210 if (dst[0] == 'h')
3211 instr->type = INSTR_ALU_ADD_HI;
3212
3213 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3214 instr->alu.dst.n_bits = fdst->n_bits;
3215 instr->alu.dst.offset = fdst->offset / 8;
3216 instr->alu.src_val = src_val;
3217 return 0;
3218}
3219
3220static int
3221instr_alu_sub_translate(struct rte_swx_pipeline *p,
3222 struct action *action,
3223 char **tokens,
3224 int n_tokens,
3225 struct instruction *instr,
3226 struct instruction_data *data __rte_unused)
3227{
3228 char *dst = tokens[1], *src = tokens[2];
3229 struct field *fdst, *fsrc;
3230 uint64_t src_val;
3231 uint32_t dst_struct_id = 0, src_struct_id = 0;
3232
3233 CHECK(n_tokens == 3, EINVAL);
3234
3235 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3236 CHECK(fdst, EINVAL);
3237 CHECK(!fdst->var_size, EINVAL);
3238
3239
3240 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3241 if (fsrc) {
3242 CHECK(!fsrc->var_size, EINVAL);
3243
3244 instr->type = INSTR_ALU_SUB;
3245 if (dst[0] == 'h' && src[0] != 'h')
3246 instr->type = INSTR_ALU_SUB_HM;
3247 if (dst[0] != 'h' && src[0] == 'h')
3248 instr->type = INSTR_ALU_SUB_MH;
3249 if (dst[0] == 'h' && src[0] == 'h')
3250 instr->type = INSTR_ALU_SUB_HH;
3251
3252 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3253 instr->alu.dst.n_bits = fdst->n_bits;
3254 instr->alu.dst.offset = fdst->offset / 8;
3255 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3256 instr->alu.src.n_bits = fsrc->n_bits;
3257 instr->alu.src.offset = fsrc->offset / 8;
3258 return 0;
3259 }
3260
3261
3262 src_val = strtoull(src, &src, 0);
3263 CHECK(!src[0], EINVAL);
3264
3265 instr->type = INSTR_ALU_SUB_MI;
3266 if (dst[0] == 'h')
3267 instr->type = INSTR_ALU_SUB_HI;
3268
3269 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3270 instr->alu.dst.n_bits = fdst->n_bits;
3271 instr->alu.dst.offset = fdst->offset / 8;
3272 instr->alu.src_val = src_val;
3273 return 0;
3274}
3275
3276static int
3277instr_alu_ckadd_translate(struct rte_swx_pipeline *p,
3278 struct action *action __rte_unused,
3279 char **tokens,
3280 int n_tokens,
3281 struct instruction *instr,
3282 struct instruction_data *data __rte_unused)
3283{
3284 char *dst = tokens[1], *src = tokens[2];
3285 struct header *hdst, *hsrc;
3286 struct field *fdst, *fsrc;
3287
3288 CHECK(n_tokens == 3, EINVAL);
3289
3290 fdst = header_field_parse(p, dst, &hdst);
3291 CHECK(fdst, EINVAL);
3292 CHECK(!fdst->var_size && (fdst->n_bits == 16), EINVAL);
3293
3294
3295 fsrc = header_field_parse(p, src, &hsrc);
3296 if (fsrc) {
3297 CHECK(!fsrc->var_size, EINVAL);
3298
3299 instr->type = INSTR_ALU_CKADD_FIELD;
3300 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
3301 instr->alu.dst.n_bits = fdst->n_bits;
3302 instr->alu.dst.offset = fdst->offset / 8;
3303 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
3304 instr->alu.src.n_bits = fsrc->n_bits;
3305 instr->alu.src.offset = fsrc->offset / 8;
3306 return 0;
3307 }
3308
3309
3310 hsrc = header_parse(p, src);
3311 CHECK(hsrc, EINVAL);
3312
3313 instr->type = INSTR_ALU_CKADD_STRUCT;
3314 if (!hsrc->st->var_size && ((hsrc->st->n_bits / 8) == 20))
3315 instr->type = INSTR_ALU_CKADD_STRUCT20;
3316
3317 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
3318 instr->alu.dst.n_bits = fdst->n_bits;
3319 instr->alu.dst.offset = fdst->offset / 8;
3320 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
3321 instr->alu.src.n_bits = (uint8_t)hsrc->id;
3322 instr->alu.src.offset = 0;
3323 return 0;
3324}
3325
3326static int
3327instr_alu_cksub_translate(struct rte_swx_pipeline *p,
3328 struct action *action __rte_unused,
3329 char **tokens,
3330 int n_tokens,
3331 struct instruction *instr,
3332 struct instruction_data *data __rte_unused)
3333{
3334 char *dst = tokens[1], *src = tokens[2];
3335 struct header *hdst, *hsrc;
3336 struct field *fdst, *fsrc;
3337
3338 CHECK(n_tokens == 3, EINVAL);
3339
3340 fdst = header_field_parse(p, dst, &hdst);
3341 CHECK(fdst, EINVAL);
3342 CHECK(!fdst->var_size && (fdst->n_bits == 16), EINVAL);
3343
3344 fsrc = header_field_parse(p, src, &hsrc);
3345 CHECK(fsrc, EINVAL);
3346 CHECK(!fsrc->var_size, EINVAL);
3347
3348 instr->type = INSTR_ALU_CKSUB_FIELD;
3349 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
3350 instr->alu.dst.n_bits = fdst->n_bits;
3351 instr->alu.dst.offset = fdst->offset / 8;
3352 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
3353 instr->alu.src.n_bits = fsrc->n_bits;
3354 instr->alu.src.offset = fsrc->offset / 8;
3355 return 0;
3356}
3357
3358static int
3359instr_alu_shl_translate(struct rte_swx_pipeline *p,
3360 struct action *action,
3361 char **tokens,
3362 int n_tokens,
3363 struct instruction *instr,
3364 struct instruction_data *data __rte_unused)
3365{
3366 char *dst = tokens[1], *src = tokens[2];
3367 struct field *fdst, *fsrc;
3368 uint64_t src_val;
3369 uint32_t dst_struct_id = 0, src_struct_id = 0;
3370
3371 CHECK(n_tokens == 3, EINVAL);
3372
3373 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3374 CHECK(fdst, EINVAL);
3375 CHECK(!fdst->var_size, EINVAL);
3376
3377
3378 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3379 if (fsrc) {
3380 CHECK(!fsrc->var_size, EINVAL);
3381
3382 instr->type = INSTR_ALU_SHL;
3383 if (dst[0] == 'h' && src[0] != 'h')
3384 instr->type = INSTR_ALU_SHL_HM;
3385 if (dst[0] != 'h' && src[0] == 'h')
3386 instr->type = INSTR_ALU_SHL_MH;
3387 if (dst[0] == 'h' && src[0] == 'h')
3388 instr->type = INSTR_ALU_SHL_HH;
3389
3390 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3391 instr->alu.dst.n_bits = fdst->n_bits;
3392 instr->alu.dst.offset = fdst->offset / 8;
3393 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3394 instr->alu.src.n_bits = fsrc->n_bits;
3395 instr->alu.src.offset = fsrc->offset / 8;
3396 return 0;
3397 }
3398
3399
3400 src_val = strtoull(src, &src, 0);
3401 CHECK(!src[0], EINVAL);
3402
3403 instr->type = INSTR_ALU_SHL_MI;
3404 if (dst[0] == 'h')
3405 instr->type = INSTR_ALU_SHL_HI;
3406
3407 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3408 instr->alu.dst.n_bits = fdst->n_bits;
3409 instr->alu.dst.offset = fdst->offset / 8;
3410 instr->alu.src_val = src_val;
3411 return 0;
3412}
3413
3414static int
3415instr_alu_shr_translate(struct rte_swx_pipeline *p,
3416 struct action *action,
3417 char **tokens,
3418 int n_tokens,
3419 struct instruction *instr,
3420 struct instruction_data *data __rte_unused)
3421{
3422 char *dst = tokens[1], *src = tokens[2];
3423 struct field *fdst, *fsrc;
3424 uint64_t src_val;
3425 uint32_t dst_struct_id = 0, src_struct_id = 0;
3426
3427 CHECK(n_tokens == 3, EINVAL);
3428
3429 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3430 CHECK(fdst, EINVAL);
3431 CHECK(!fdst->var_size, EINVAL);
3432
3433
3434 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3435 if (fsrc) {
3436 CHECK(!fsrc->var_size, EINVAL);
3437
3438 instr->type = INSTR_ALU_SHR;
3439 if (dst[0] == 'h' && src[0] != 'h')
3440 instr->type = INSTR_ALU_SHR_HM;
3441 if (dst[0] != 'h' && src[0] == 'h')
3442 instr->type = INSTR_ALU_SHR_MH;
3443 if (dst[0] == 'h' && src[0] == 'h')
3444 instr->type = INSTR_ALU_SHR_HH;
3445
3446 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3447 instr->alu.dst.n_bits = fdst->n_bits;
3448 instr->alu.dst.offset = fdst->offset / 8;
3449 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3450 instr->alu.src.n_bits = fsrc->n_bits;
3451 instr->alu.src.offset = fsrc->offset / 8;
3452 return 0;
3453 }
3454
3455
3456 src_val = strtoull(src, &src, 0);
3457 CHECK(!src[0], EINVAL);
3458
3459 instr->type = INSTR_ALU_SHR_MI;
3460 if (dst[0] == 'h')
3461 instr->type = INSTR_ALU_SHR_HI;
3462
3463 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3464 instr->alu.dst.n_bits = fdst->n_bits;
3465 instr->alu.dst.offset = fdst->offset / 8;
3466 instr->alu.src_val = src_val;
3467 return 0;
3468}
3469
3470static int
3471instr_alu_and_translate(struct rte_swx_pipeline *p,
3472 struct action *action,
3473 char **tokens,
3474 int n_tokens,
3475 struct instruction *instr,
3476 struct instruction_data *data __rte_unused)
3477{
3478 char *dst = tokens[1], *src = tokens[2];
3479 struct field *fdst, *fsrc;
3480 uint64_t src_val;
3481 uint32_t dst_struct_id = 0, src_struct_id = 0;
3482
3483 CHECK(n_tokens == 3, EINVAL);
3484
3485 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3486 CHECK(fdst, EINVAL);
3487 CHECK(!fdst->var_size, EINVAL);
3488
3489
3490 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3491 if (fsrc) {
3492 CHECK(!fsrc->var_size, EINVAL);
3493
3494 instr->type = INSTR_ALU_AND;
3495 if (dst[0] != 'h' && src[0] == 'h')
3496 instr->type = INSTR_ALU_AND_MH;
3497 if (dst[0] == 'h' && src[0] != 'h')
3498 instr->type = INSTR_ALU_AND_HM;
3499 if (dst[0] == 'h' && src[0] == 'h')
3500 instr->type = INSTR_ALU_AND_HH;
3501
3502 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3503 instr->alu.dst.n_bits = fdst->n_bits;
3504 instr->alu.dst.offset = fdst->offset / 8;
3505 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3506 instr->alu.src.n_bits = fsrc->n_bits;
3507 instr->alu.src.offset = fsrc->offset / 8;
3508 return 0;
3509 }
3510
3511
3512 src_val = strtoull(src, &src, 0);
3513 CHECK(!src[0], EINVAL);
3514
3515 if (dst[0] == 'h')
3516 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3517
3518 instr->type = INSTR_ALU_AND_I;
3519 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3520 instr->alu.dst.n_bits = fdst->n_bits;
3521 instr->alu.dst.offset = fdst->offset / 8;
3522 instr->alu.src_val = src_val;
3523 return 0;
3524}
3525
3526static int
3527instr_alu_or_translate(struct rte_swx_pipeline *p,
3528 struct action *action,
3529 char **tokens,
3530 int n_tokens,
3531 struct instruction *instr,
3532 struct instruction_data *data __rte_unused)
3533{
3534 char *dst = tokens[1], *src = tokens[2];
3535 struct field *fdst, *fsrc;
3536 uint64_t src_val;
3537 uint32_t dst_struct_id = 0, src_struct_id = 0;
3538
3539 CHECK(n_tokens == 3, EINVAL);
3540
3541 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3542 CHECK(fdst, EINVAL);
3543 CHECK(!fdst->var_size, EINVAL);
3544
3545
3546 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3547 if (fsrc) {
3548 CHECK(!fsrc->var_size, EINVAL);
3549
3550 instr->type = INSTR_ALU_OR;
3551 if (dst[0] != 'h' && src[0] == 'h')
3552 instr->type = INSTR_ALU_OR_MH;
3553 if (dst[0] == 'h' && src[0] != 'h')
3554 instr->type = INSTR_ALU_OR_HM;
3555 if (dst[0] == 'h' && src[0] == 'h')
3556 instr->type = INSTR_ALU_OR_HH;
3557
3558 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3559 instr->alu.dst.n_bits = fdst->n_bits;
3560 instr->alu.dst.offset = fdst->offset / 8;
3561 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3562 instr->alu.src.n_bits = fsrc->n_bits;
3563 instr->alu.src.offset = fsrc->offset / 8;
3564 return 0;
3565 }
3566
3567
3568 src_val = strtoull(src, &src, 0);
3569 CHECK(!src[0], EINVAL);
3570
3571 if (dst[0] == 'h')
3572 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3573
3574 instr->type = INSTR_ALU_OR_I;
3575 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3576 instr->alu.dst.n_bits = fdst->n_bits;
3577 instr->alu.dst.offset = fdst->offset / 8;
3578 instr->alu.src_val = src_val;
3579 return 0;
3580}
3581
3582static int
3583instr_alu_xor_translate(struct rte_swx_pipeline *p,
3584 struct action *action,
3585 char **tokens,
3586 int n_tokens,
3587 struct instruction *instr,
3588 struct instruction_data *data __rte_unused)
3589{
3590 char *dst = tokens[1], *src = tokens[2];
3591 struct field *fdst, *fsrc;
3592 uint64_t src_val;
3593 uint32_t dst_struct_id = 0, src_struct_id = 0;
3594
3595 CHECK(n_tokens == 3, EINVAL);
3596
3597 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3598 CHECK(fdst, EINVAL);
3599 CHECK(!fdst->var_size, EINVAL);
3600
3601
3602 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3603 if (fsrc) {
3604 CHECK(!fsrc->var_size, EINVAL);
3605
3606 instr->type = INSTR_ALU_XOR;
3607 if (dst[0] != 'h' && src[0] == 'h')
3608 instr->type = INSTR_ALU_XOR_MH;
3609 if (dst[0] == 'h' && src[0] != 'h')
3610 instr->type = INSTR_ALU_XOR_HM;
3611 if (dst[0] == 'h' && src[0] == 'h')
3612 instr->type = INSTR_ALU_XOR_HH;
3613
3614 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3615 instr->alu.dst.n_bits = fdst->n_bits;
3616 instr->alu.dst.offset = fdst->offset / 8;
3617 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3618 instr->alu.src.n_bits = fsrc->n_bits;
3619 instr->alu.src.offset = fsrc->offset / 8;
3620 return 0;
3621 }
3622
3623
3624 src_val = strtoull(src, &src, 0);
3625 CHECK(!src[0], EINVAL);
3626
3627 if (dst[0] == 'h')
3628 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3629
3630 instr->type = INSTR_ALU_XOR_I;
3631 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3632 instr->alu.dst.n_bits = fdst->n_bits;
3633 instr->alu.dst.offset = fdst->offset / 8;
3634 instr->alu.src_val = src_val;
3635 return 0;
3636}
3637
3638static inline void
3639instr_alu_add_exec(struct rte_swx_pipeline *p)
3640{
3641 struct thread *t = &p->threads[p->thread_id];
3642 struct instruction *ip = t->ip;
3643
3644
3645 __instr_alu_add_exec(p, t, ip);
3646
3647
3648 thread_ip_inc(p);
3649}
3650
3651static inline void
3652instr_alu_add_mh_exec(struct rte_swx_pipeline *p)
3653{
3654 struct thread *t = &p->threads[p->thread_id];
3655 struct instruction *ip = t->ip;
3656
3657
3658 __instr_alu_add_mh_exec(p, t, ip);
3659
3660
3661 thread_ip_inc(p);
3662}
3663
3664static inline void
3665instr_alu_add_hm_exec(struct rte_swx_pipeline *p)
3666{
3667 struct thread *t = &p->threads[p->thread_id];
3668 struct instruction *ip = t->ip;
3669
3670
3671 __instr_alu_add_hm_exec(p, t, ip);
3672
3673
3674 thread_ip_inc(p);
3675}
3676
3677static inline void
3678instr_alu_add_hh_exec(struct rte_swx_pipeline *p)
3679{
3680 struct thread *t = &p->threads[p->thread_id];
3681 struct instruction *ip = t->ip;
3682
3683
3684 __instr_alu_add_hh_exec(p, t, ip);
3685
3686
3687 thread_ip_inc(p);
3688}
3689
3690static inline void
3691instr_alu_add_mi_exec(struct rte_swx_pipeline *p)
3692{
3693 struct thread *t = &p->threads[p->thread_id];
3694 struct instruction *ip = t->ip;
3695
3696
3697 __instr_alu_add_mi_exec(p, t, ip);
3698
3699
3700 thread_ip_inc(p);
3701}
3702
3703static inline void
3704instr_alu_add_hi_exec(struct rte_swx_pipeline *p)
3705{
3706 struct thread *t = &p->threads[p->thread_id];
3707 struct instruction *ip = t->ip;
3708
3709
3710 __instr_alu_add_hi_exec(p, t, ip);
3711
3712
3713 thread_ip_inc(p);
3714}
3715
3716static inline void
3717instr_alu_sub_exec(struct rte_swx_pipeline *p)
3718{
3719 struct thread *t = &p->threads[p->thread_id];
3720 struct instruction *ip = t->ip;
3721
3722
3723 __instr_alu_sub_exec(p, t, ip);
3724
3725
3726 thread_ip_inc(p);
3727}
3728
3729static inline void
3730instr_alu_sub_mh_exec(struct rte_swx_pipeline *p)
3731{
3732 struct thread *t = &p->threads[p->thread_id];
3733 struct instruction *ip = t->ip;
3734
3735
3736 __instr_alu_sub_mh_exec(p, t, ip);
3737
3738
3739 thread_ip_inc(p);
3740}
3741
3742static inline void
3743instr_alu_sub_hm_exec(struct rte_swx_pipeline *p)
3744{
3745 struct thread *t = &p->threads[p->thread_id];
3746 struct instruction *ip = t->ip;
3747
3748
3749 __instr_alu_sub_hm_exec(p, t, ip);
3750
3751
3752 thread_ip_inc(p);
3753}
3754
3755static inline void
3756instr_alu_sub_hh_exec(struct rte_swx_pipeline *p)
3757{
3758 struct thread *t = &p->threads[p->thread_id];
3759 struct instruction *ip = t->ip;
3760
3761
3762 __instr_alu_sub_hh_exec(p, t, ip);
3763
3764
3765 thread_ip_inc(p);
3766}
3767
3768static inline void
3769instr_alu_sub_mi_exec(struct rte_swx_pipeline *p)
3770{
3771 struct thread *t = &p->threads[p->thread_id];
3772 struct instruction *ip = t->ip;
3773
3774
3775 __instr_alu_sub_mi_exec(p, t, ip);
3776
3777
3778 thread_ip_inc(p);
3779}
3780
3781static inline void
3782instr_alu_sub_hi_exec(struct rte_swx_pipeline *p)
3783{
3784 struct thread *t = &p->threads[p->thread_id];
3785 struct instruction *ip = t->ip;
3786
3787
3788 __instr_alu_sub_hi_exec(p, t, ip);
3789
3790
3791 thread_ip_inc(p);
3792}
3793
3794static inline void
3795instr_alu_shl_exec(struct rte_swx_pipeline *p)
3796{
3797 struct thread *t = &p->threads[p->thread_id];
3798 struct instruction *ip = t->ip;
3799
3800
3801 __instr_alu_shl_exec(p, t, ip);
3802
3803
3804 thread_ip_inc(p);
3805}
3806
3807static inline void
3808instr_alu_shl_mh_exec(struct rte_swx_pipeline *p)
3809{
3810 struct thread *t = &p->threads[p->thread_id];
3811 struct instruction *ip = t->ip;
3812
3813
3814 __instr_alu_shl_mh_exec(p, t, ip);
3815
3816
3817 thread_ip_inc(p);
3818}
3819
3820static inline void
3821instr_alu_shl_hm_exec(struct rte_swx_pipeline *p)
3822{
3823 struct thread *t = &p->threads[p->thread_id];
3824 struct instruction *ip = t->ip;
3825
3826
3827 __instr_alu_shl_hm_exec(p, t, ip);
3828
3829
3830 thread_ip_inc(p);
3831}
3832
3833static inline void
3834instr_alu_shl_hh_exec(struct rte_swx_pipeline *p)
3835{
3836 struct thread *t = &p->threads[p->thread_id];
3837 struct instruction *ip = t->ip;
3838
3839
3840 __instr_alu_shl_hh_exec(p, t, ip);
3841
3842
3843 thread_ip_inc(p);
3844}
3845
3846static inline void
3847instr_alu_shl_mi_exec(struct rte_swx_pipeline *p)
3848{
3849 struct thread *t = &p->threads[p->thread_id];
3850 struct instruction *ip = t->ip;
3851
3852
3853 __instr_alu_shl_mi_exec(p, t, ip);
3854
3855
3856 thread_ip_inc(p);
3857}
3858
3859static inline void
3860instr_alu_shl_hi_exec(struct rte_swx_pipeline *p)
3861{
3862 struct thread *t = &p->threads[p->thread_id];
3863 struct instruction *ip = t->ip;
3864
3865
3866 __instr_alu_shl_hi_exec(p, t, ip);
3867
3868
3869 thread_ip_inc(p);
3870}
3871
3872static inline void
3873instr_alu_shr_exec(struct rte_swx_pipeline *p)
3874{
3875 struct thread *t = &p->threads[p->thread_id];
3876 struct instruction *ip = t->ip;
3877
3878
3879 __instr_alu_shr_exec(p, t, ip);
3880
3881
3882 thread_ip_inc(p);
3883}
3884
3885static inline void
3886instr_alu_shr_mh_exec(struct rte_swx_pipeline *p)
3887{
3888 struct thread *t = &p->threads[p->thread_id];
3889 struct instruction *ip = t->ip;
3890
3891
3892 __instr_alu_shr_mh_exec(p, t, ip);
3893
3894
3895 thread_ip_inc(p);
3896}
3897
3898static inline void
3899instr_alu_shr_hm_exec(struct rte_swx_pipeline *p)
3900{
3901 struct thread *t = &p->threads[p->thread_id];
3902 struct instruction *ip = t->ip;
3903
3904
3905 __instr_alu_shr_hm_exec(p, t, ip);
3906
3907
3908 thread_ip_inc(p);
3909}
3910
3911static inline void
3912instr_alu_shr_hh_exec(struct rte_swx_pipeline *p)
3913{
3914 struct thread *t = &p->threads[p->thread_id];
3915 struct instruction *ip = t->ip;
3916
3917
3918 __instr_alu_shr_hh_exec(p, t, ip);
3919
3920
3921 thread_ip_inc(p);
3922}
3923
3924static inline void
3925instr_alu_shr_mi_exec(struct rte_swx_pipeline *p)
3926{
3927 struct thread *t = &p->threads[p->thread_id];
3928 struct instruction *ip = t->ip;
3929
3930
3931 __instr_alu_shr_mi_exec(p, t, ip);
3932
3933
3934 thread_ip_inc(p);
3935}
3936
3937static inline void
3938instr_alu_shr_hi_exec(struct rte_swx_pipeline *p)
3939{
3940 struct thread *t = &p->threads[p->thread_id];
3941 struct instruction *ip = t->ip;
3942
3943
3944 __instr_alu_shr_hi_exec(p, t, ip);
3945
3946
3947 thread_ip_inc(p);
3948}
3949
3950static inline void
3951instr_alu_and_exec(struct rte_swx_pipeline *p)
3952{
3953 struct thread *t = &p->threads[p->thread_id];
3954 struct instruction *ip = t->ip;
3955
3956
3957 __instr_alu_and_exec(p, t, ip);
3958
3959
3960 thread_ip_inc(p);
3961}
3962
3963static inline void
3964instr_alu_and_mh_exec(struct rte_swx_pipeline *p)
3965{
3966 struct thread *t = &p->threads[p->thread_id];
3967 struct instruction *ip = t->ip;
3968
3969
3970 __instr_alu_and_mh_exec(p, t, ip);
3971
3972
3973 thread_ip_inc(p);
3974}
3975
3976static inline void
3977instr_alu_and_hm_exec(struct rte_swx_pipeline *p)
3978{
3979 struct thread *t = &p->threads[p->thread_id];
3980 struct instruction *ip = t->ip;
3981
3982
3983 __instr_alu_and_hm_exec(p, t, ip);
3984
3985
3986 thread_ip_inc(p);
3987}
3988
3989static inline void
3990instr_alu_and_hh_exec(struct rte_swx_pipeline *p)
3991{
3992 struct thread *t = &p->threads[p->thread_id];
3993 struct instruction *ip = t->ip;
3994
3995
3996 __instr_alu_and_hh_exec(p, t, ip);
3997
3998
3999 thread_ip_inc(p);
4000}
4001
4002static inline void
4003instr_alu_and_i_exec(struct rte_swx_pipeline *p)
4004{
4005 struct thread *t = &p->threads[p->thread_id];
4006 struct instruction *ip = t->ip;
4007
4008
4009 __instr_alu_and_i_exec(p, t, ip);
4010
4011
4012 thread_ip_inc(p);
4013}
4014
4015static inline void
4016instr_alu_or_exec(struct rte_swx_pipeline *p)
4017{
4018 struct thread *t = &p->threads[p->thread_id];
4019 struct instruction *ip = t->ip;
4020
4021
4022 __instr_alu_or_exec(p, t, ip);
4023
4024
4025 thread_ip_inc(p);
4026}
4027
4028static inline void
4029instr_alu_or_mh_exec(struct rte_swx_pipeline *p)
4030{
4031 struct thread *t = &p->threads[p->thread_id];
4032 struct instruction *ip = t->ip;
4033
4034
4035 __instr_alu_or_mh_exec(p, t, ip);
4036
4037
4038 thread_ip_inc(p);
4039}
4040
4041static inline void
4042instr_alu_or_hm_exec(struct rte_swx_pipeline *p)
4043{
4044 struct thread *t = &p->threads[p->thread_id];
4045 struct instruction *ip = t->ip;
4046
4047
4048 __instr_alu_or_hm_exec(p, t, ip);
4049
4050
4051 thread_ip_inc(p);
4052}
4053
4054static inline void
4055instr_alu_or_hh_exec(struct rte_swx_pipeline *p)
4056{
4057 struct thread *t = &p->threads[p->thread_id];
4058 struct instruction *ip = t->ip;
4059
4060
4061 __instr_alu_or_hh_exec(p, t, ip);
4062
4063
4064 thread_ip_inc(p);
4065}
4066
4067static inline void
4068instr_alu_or_i_exec(struct rte_swx_pipeline *p)
4069{
4070 struct thread *t = &p->threads[p->thread_id];
4071 struct instruction *ip = t->ip;
4072
4073
4074 __instr_alu_or_i_exec(p, t, ip);
4075
4076
4077 thread_ip_inc(p);
4078}
4079
4080static inline void
4081instr_alu_xor_exec(struct rte_swx_pipeline *p)
4082{
4083 struct thread *t = &p->threads[p->thread_id];
4084 struct instruction *ip = t->ip;
4085
4086
4087 __instr_alu_xor_exec(p, t, ip);
4088
4089
4090 thread_ip_inc(p);
4091}
4092
4093static inline void
4094instr_alu_xor_mh_exec(struct rte_swx_pipeline *p)
4095{
4096 struct thread *t = &p->threads[p->thread_id];
4097 struct instruction *ip = t->ip;
4098
4099
4100 __instr_alu_xor_mh_exec(p, t, ip);
4101
4102
4103 thread_ip_inc(p);
4104}
4105
4106static inline void
4107instr_alu_xor_hm_exec(struct rte_swx_pipeline *p)
4108{
4109 struct thread *t = &p->threads[p->thread_id];
4110 struct instruction *ip = t->ip;
4111
4112
4113 __instr_alu_xor_hm_exec(p, t, ip);
4114
4115
4116 thread_ip_inc(p);
4117}
4118
4119static inline void
4120instr_alu_xor_hh_exec(struct rte_swx_pipeline *p)
4121{
4122 struct thread *t = &p->threads[p->thread_id];
4123 struct instruction *ip = t->ip;
4124
4125
4126 __instr_alu_xor_hh_exec(p, t, ip);
4127
4128
4129 thread_ip_inc(p);
4130}
4131
4132static inline void
4133instr_alu_xor_i_exec(struct rte_swx_pipeline *p)
4134{
4135 struct thread *t = &p->threads[p->thread_id];
4136 struct instruction *ip = t->ip;
4137
4138
4139 __instr_alu_xor_i_exec(p, t, ip);
4140
4141
4142 thread_ip_inc(p);
4143}
4144
4145static inline void
4146instr_alu_ckadd_field_exec(struct rte_swx_pipeline *p)
4147{
4148 struct thread *t = &p->threads[p->thread_id];
4149 struct instruction *ip = t->ip;
4150
4151
4152 __instr_alu_ckadd_field_exec(p, t, ip);
4153
4154
4155 thread_ip_inc(p);
4156}
4157
4158static inline void
4159instr_alu_cksub_field_exec(struct rte_swx_pipeline *p)
4160{
4161 struct thread *t = &p->threads[p->thread_id];
4162 struct instruction *ip = t->ip;
4163
4164
4165 __instr_alu_cksub_field_exec(p, t, ip);
4166
4167
4168 thread_ip_inc(p);
4169}
4170
4171static inline void
4172instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline *p)
4173{
4174 struct thread *t = &p->threads[p->thread_id];
4175 struct instruction *ip = t->ip;
4176
4177
4178 __instr_alu_ckadd_struct20_exec(p, t, ip);
4179
4180
4181 thread_ip_inc(p);
4182}
4183
4184static inline void
4185instr_alu_ckadd_struct_exec(struct rte_swx_pipeline *p)
4186{
4187 struct thread *t = &p->threads[p->thread_id];
4188 struct instruction *ip = t->ip;
4189
4190
4191 __instr_alu_ckadd_struct_exec(p, t, ip);
4192
4193
4194 thread_ip_inc(p);
4195}
4196
4197
4198
4199
4200static struct regarray *
4201regarray_find(struct rte_swx_pipeline *p, const char *name);
4202
4203static int
4204instr_regprefetch_translate(struct rte_swx_pipeline *p,
4205 struct action *action,
4206 char **tokens,
4207 int n_tokens,
4208 struct instruction *instr,
4209 struct instruction_data *data __rte_unused)
4210{
4211 char *regarray = tokens[1], *idx = tokens[2];
4212 struct regarray *r;
4213 struct field *fidx;
4214 uint32_t idx_struct_id, idx_val;
4215
4216 CHECK(n_tokens == 3, EINVAL);
4217
4218 r = regarray_find(p, regarray);
4219 CHECK(r, EINVAL);
4220
4221
4222 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4223 if (fidx) {
4224 CHECK(!fidx->var_size, EINVAL);
4225
4226 instr->type = INSTR_REGPREFETCH_RM;
4227 if (idx[0] == 'h')
4228 instr->type = INSTR_REGPREFETCH_RH;
4229
4230 instr->regarray.regarray_id = r->id;
4231 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4232 instr->regarray.idx.n_bits = fidx->n_bits;
4233 instr->regarray.idx.offset = fidx->offset / 8;
4234 instr->regarray.dstsrc_val = 0;
4235 return 0;
4236 }
4237
4238
4239 idx_val = strtoul(idx, &idx, 0);
4240 CHECK(!idx[0], EINVAL);
4241
4242 instr->type = INSTR_REGPREFETCH_RI;
4243 instr->regarray.regarray_id = r->id;
4244 instr->regarray.idx_val = idx_val;
4245 instr->regarray.dstsrc_val = 0;
4246 return 0;
4247}
4248
4249static int
4250instr_regrd_translate(struct rte_swx_pipeline *p,
4251 struct action *action,
4252 char **tokens,
4253 int n_tokens,
4254 struct instruction *instr,
4255 struct instruction_data *data __rte_unused)
4256{
4257 char *dst = tokens[1], *regarray = tokens[2], *idx = tokens[3];
4258 struct regarray *r;
4259 struct field *fdst, *fidx;
4260 uint32_t dst_struct_id, idx_struct_id, idx_val;
4261
4262 CHECK(n_tokens == 4, EINVAL);
4263
4264 r = regarray_find(p, regarray);
4265 CHECK(r, EINVAL);
4266
4267 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4268 CHECK(fdst, EINVAL);
4269 CHECK(!fdst->var_size, EINVAL);
4270
4271
4272 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4273 if (fidx) {
4274 CHECK(!fidx->var_size, EINVAL);
4275
4276 instr->type = INSTR_REGRD_MRM;
4277 if (dst[0] == 'h' && idx[0] != 'h')
4278 instr->type = INSTR_REGRD_HRM;
4279 if (dst[0] != 'h' && idx[0] == 'h')
4280 instr->type = INSTR_REGRD_MRH;
4281 if (dst[0] == 'h' && idx[0] == 'h')
4282 instr->type = INSTR_REGRD_HRH;
4283
4284 instr->regarray.regarray_id = r->id;
4285 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4286 instr->regarray.idx.n_bits = fidx->n_bits;
4287 instr->regarray.idx.offset = fidx->offset / 8;
4288 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
4289 instr->regarray.dstsrc.n_bits = fdst->n_bits;
4290 instr->regarray.dstsrc.offset = fdst->offset / 8;
4291 return 0;
4292 }
4293
4294
4295 idx_val = strtoul(idx, &idx, 0);
4296 CHECK(!idx[0], EINVAL);
4297
4298 instr->type = INSTR_REGRD_MRI;
4299 if (dst[0] == 'h')
4300 instr->type = INSTR_REGRD_HRI;
4301
4302 instr->regarray.regarray_id = r->id;
4303 instr->regarray.idx_val = idx_val;
4304 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
4305 instr->regarray.dstsrc.n_bits = fdst->n_bits;
4306 instr->regarray.dstsrc.offset = fdst->offset / 8;
4307 return 0;
4308}
4309
4310static int
4311instr_regwr_translate(struct rte_swx_pipeline *p,
4312 struct action *action,
4313 char **tokens,
4314 int n_tokens,
4315 struct instruction *instr,
4316 struct instruction_data *data __rte_unused)
4317{
4318 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
4319 struct regarray *r;
4320 struct field *fidx, *fsrc;
4321 uint64_t src_val;
4322 uint32_t idx_struct_id, idx_val, src_struct_id;
4323
4324 CHECK(n_tokens == 4, EINVAL);
4325
4326 r = regarray_find(p, regarray);
4327 CHECK(r, EINVAL);
4328
4329
4330 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4331 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4332 if (fidx && fsrc) {
4333 CHECK(!fidx->var_size, EINVAL);
4334 CHECK(!fsrc->var_size, EINVAL);
4335
4336 instr->type = INSTR_REGWR_RMM;
4337 if (idx[0] == 'h' && src[0] != 'h')
4338 instr->type = INSTR_REGWR_RHM;
4339 if (idx[0] != 'h' && src[0] == 'h')
4340 instr->type = INSTR_REGWR_RMH;
4341 if (idx[0] == 'h' && src[0] == 'h')
4342 instr->type = INSTR_REGWR_RHH;
4343
4344 instr->regarray.regarray_id = r->id;
4345 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4346 instr->regarray.idx.n_bits = fidx->n_bits;
4347 instr->regarray.idx.offset = fidx->offset / 8;
4348 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4349 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4350 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4351 return 0;
4352 }
4353
4354
4355 if (fidx && !fsrc) {
4356 CHECK(!fidx->var_size, EINVAL);
4357
4358 src_val = strtoull(src, &src, 0);
4359 CHECK(!src[0], EINVAL);
4360
4361 instr->type = INSTR_REGWR_RMI;
4362 if (idx[0] == 'h')
4363 instr->type = INSTR_REGWR_RHI;
4364
4365 instr->regarray.regarray_id = r->id;
4366 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4367 instr->regarray.idx.n_bits = fidx->n_bits;
4368 instr->regarray.idx.offset = fidx->offset / 8;
4369 instr->regarray.dstsrc_val = src_val;
4370 return 0;
4371 }
4372
4373
4374 if (!fidx && fsrc) {
4375 idx_val = strtoul(idx, &idx, 0);
4376 CHECK(!idx[0], EINVAL);
4377
4378 CHECK(!fsrc->var_size, EINVAL);
4379
4380 instr->type = INSTR_REGWR_RIM;
4381 if (src[0] == 'h')
4382 instr->type = INSTR_REGWR_RIH;
4383
4384 instr->regarray.regarray_id = r->id;
4385 instr->regarray.idx_val = idx_val;
4386 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4387 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4388 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4389 return 0;
4390 }
4391
4392
4393 src_val = strtoull(src, &src, 0);
4394 CHECK(!src[0], EINVAL);
4395
4396 idx_val = strtoul(idx, &idx, 0);
4397 CHECK(!idx[0], EINVAL);
4398
4399 instr->type = INSTR_REGWR_RII;
4400 instr->regarray.idx_val = idx_val;
4401 instr->regarray.dstsrc_val = src_val;
4402
4403 return 0;
4404}
4405
4406static int
4407instr_regadd_translate(struct rte_swx_pipeline *p,
4408 struct action *action,
4409 char **tokens,
4410 int n_tokens,
4411 struct instruction *instr,
4412 struct instruction_data *data __rte_unused)
4413{
4414 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
4415 struct regarray *r;
4416 struct field *fidx, *fsrc;
4417 uint64_t src_val;
4418 uint32_t idx_struct_id, idx_val, src_struct_id;
4419
4420 CHECK(n_tokens == 4, EINVAL);
4421
4422 r = regarray_find(p, regarray);
4423 CHECK(r, EINVAL);
4424
4425
4426 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4427 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4428 if (fidx && fsrc) {
4429 CHECK(!fidx->var_size, EINVAL);
4430 CHECK(!fsrc->var_size, EINVAL);
4431
4432 instr->type = INSTR_REGADD_RMM;
4433 if (idx[0] == 'h' && src[0] != 'h')
4434 instr->type = INSTR_REGADD_RHM;
4435 if (idx[0] != 'h' && src[0] == 'h')
4436 instr->type = INSTR_REGADD_RMH;
4437 if (idx[0] == 'h' && src[0] == 'h')
4438 instr->type = INSTR_REGADD_RHH;
4439
4440 instr->regarray.regarray_id = r->id;
4441 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4442 instr->regarray.idx.n_bits = fidx->n_bits;
4443 instr->regarray.idx.offset = fidx->offset / 8;
4444 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4445 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4446 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4447 return 0;
4448 }
4449
4450
4451 if (fidx && !fsrc) {
4452 CHECK(!fidx->var_size, EINVAL);
4453
4454 src_val = strtoull(src, &src, 0);
4455 CHECK(!src[0], EINVAL);
4456
4457 instr->type = INSTR_REGADD_RMI;
4458 if (idx[0] == 'h')
4459 instr->type = INSTR_REGADD_RHI;
4460
4461 instr->regarray.regarray_id = r->id;
4462 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4463 instr->regarray.idx.n_bits = fidx->n_bits;
4464 instr->regarray.idx.offset = fidx->offset / 8;
4465 instr->regarray.dstsrc_val = src_val;
4466 return 0;
4467 }
4468
4469
4470 if (!fidx && fsrc) {
4471 idx_val = strtoul(idx, &idx, 0);
4472 CHECK(!idx[0], EINVAL);
4473
4474 CHECK(!fsrc->var_size, EINVAL);
4475
4476 instr->type = INSTR_REGADD_RIM;
4477 if (src[0] == 'h')
4478 instr->type = INSTR_REGADD_RIH;
4479
4480 instr->regarray.regarray_id = r->id;
4481 instr->regarray.idx_val = idx_val;
4482 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4483 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4484 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4485 return 0;
4486 }
4487
4488
4489 src_val = strtoull(src, &src, 0);
4490 CHECK(!src[0], EINVAL);
4491
4492 idx_val = strtoul(idx, &idx, 0);
4493 CHECK(!idx[0], EINVAL);
4494
4495 instr->type = INSTR_REGADD_RII;
4496 instr->regarray.idx_val = idx_val;
4497 instr->regarray.dstsrc_val = src_val;
4498 return 0;
4499}
4500
4501static inline void
4502instr_regprefetch_rh_exec(struct rte_swx_pipeline *p)
4503{
4504 struct thread *t = &p->threads[p->thread_id];
4505 struct instruction *ip = t->ip;
4506
4507
4508 __instr_regprefetch_rh_exec(p, t, ip);
4509
4510
4511 thread_ip_inc(p);
4512}
4513
4514static inline void
4515instr_regprefetch_rm_exec(struct rte_swx_pipeline *p)
4516{
4517 struct thread *t = &p->threads[p->thread_id];
4518 struct instruction *ip = t->ip;
4519
4520
4521 __instr_regprefetch_rm_exec(p, t, ip);
4522
4523
4524 thread_ip_inc(p);
4525}
4526
4527static inline void
4528instr_regprefetch_ri_exec(struct rte_swx_pipeline *p)
4529{
4530 struct thread *t = &p->threads[p->thread_id];
4531 struct instruction *ip = t->ip;
4532
4533
4534 __instr_regprefetch_ri_exec(p, t, ip);
4535
4536
4537 thread_ip_inc(p);
4538}
4539
4540static inline void
4541instr_regrd_hrh_exec(struct rte_swx_pipeline *p)
4542{
4543 struct thread *t = &p->threads[p->thread_id];
4544 struct instruction *ip = t->ip;
4545
4546
4547 __instr_regrd_hrh_exec(p, t, ip);
4548
4549
4550 thread_ip_inc(p);
4551}
4552
4553static inline void
4554instr_regrd_hrm_exec(struct rte_swx_pipeline *p)
4555{
4556 struct thread *t = &p->threads[p->thread_id];
4557 struct instruction *ip = t->ip;
4558
4559
4560 __instr_regrd_hrm_exec(p, t, ip);
4561
4562
4563 thread_ip_inc(p);
4564}
4565
4566static inline void
4567instr_regrd_mrh_exec(struct rte_swx_pipeline *p)
4568{
4569 struct thread *t = &p->threads[p->thread_id];
4570 struct instruction *ip = t->ip;
4571
4572
4573 __instr_regrd_mrh_exec(p, t, ip);
4574
4575
4576 thread_ip_inc(p);
4577}
4578
4579static inline void
4580instr_regrd_mrm_exec(struct rte_swx_pipeline *p)
4581{
4582 struct thread *t = &p->threads[p->thread_id];
4583 struct instruction *ip = t->ip;
4584
4585
4586 __instr_regrd_mrm_exec(p, t, ip);
4587
4588
4589 thread_ip_inc(p);
4590}
4591
4592static inline void
4593instr_regrd_hri_exec(struct rte_swx_pipeline *p)
4594{
4595 struct thread *t = &p->threads[p->thread_id];
4596 struct instruction *ip = t->ip;
4597
4598
4599 __instr_regrd_hri_exec(p, t, ip);
4600
4601
4602 thread_ip_inc(p);
4603}
4604
4605static inline void
4606instr_regrd_mri_exec(struct rte_swx_pipeline *p)
4607{
4608 struct thread *t = &p->threads[p->thread_id];
4609 struct instruction *ip = t->ip;
4610
4611
4612 __instr_regrd_mri_exec(p, t, ip);
4613
4614
4615 thread_ip_inc(p);
4616}
4617
4618static inline void
4619instr_regwr_rhh_exec(struct rte_swx_pipeline *p)
4620{
4621 struct thread *t = &p->threads[p->thread_id];
4622 struct instruction *ip = t->ip;
4623
4624
4625 __instr_regwr_rhh_exec(p, t, ip);
4626
4627
4628 thread_ip_inc(p);
4629}
4630
4631static inline void
4632instr_regwr_rhm_exec(struct rte_swx_pipeline *p)
4633{
4634 struct thread *t = &p->threads[p->thread_id];
4635 struct instruction *ip = t->ip;
4636
4637
4638 __instr_regwr_rhm_exec(p, t, ip);
4639
4640
4641 thread_ip_inc(p);
4642}
4643
4644static inline void
4645instr_regwr_rmh_exec(struct rte_swx_pipeline *p)
4646{
4647 struct thread *t = &p->threads[p->thread_id];
4648 struct instruction *ip = t->ip;
4649
4650
4651 __instr_regwr_rmh_exec(p, t, ip);
4652
4653
4654 thread_ip_inc(p);
4655}
4656
4657static inline void
4658instr_regwr_rmm_exec(struct rte_swx_pipeline *p)
4659{
4660 struct thread *t = &p->threads[p->thread_id];
4661 struct instruction *ip = t->ip;
4662
4663
4664 __instr_regwr_rmm_exec(p, t, ip);
4665
4666
4667 thread_ip_inc(p);
4668}
4669
4670static inline void
4671instr_regwr_rhi_exec(struct rte_swx_pipeline *p)
4672{
4673 struct thread *t = &p->threads[p->thread_id];
4674 struct instruction *ip = t->ip;
4675
4676
4677 __instr_regwr_rhi_exec(p, t, ip);
4678
4679
4680 thread_ip_inc(p);
4681}
4682
4683static inline void
4684instr_regwr_rmi_exec(struct rte_swx_pipeline *p)
4685{
4686 struct thread *t = &p->threads[p->thread_id];
4687 struct instruction *ip = t->ip;
4688
4689
4690 __instr_regwr_rmi_exec(p, t, ip);
4691
4692
4693 thread_ip_inc(p);
4694}
4695
4696static inline void
4697instr_regwr_rih_exec(struct rte_swx_pipeline *p)
4698{
4699 struct thread *t = &p->threads[p->thread_id];
4700 struct instruction *ip = t->ip;
4701
4702
4703 __instr_regwr_rih_exec(p, t, ip);
4704
4705
4706 thread_ip_inc(p);
4707}
4708
4709static inline void
4710instr_regwr_rim_exec(struct rte_swx_pipeline *p)
4711{
4712 struct thread *t = &p->threads[p->thread_id];
4713 struct instruction *ip = t->ip;
4714
4715
4716 __instr_regwr_rim_exec(p, t, ip);
4717
4718
4719 thread_ip_inc(p);
4720}
4721
4722static inline void
4723instr_regwr_rii_exec(struct rte_swx_pipeline *p)
4724{
4725 struct thread *t = &p->threads[p->thread_id];
4726 struct instruction *ip = t->ip;
4727
4728
4729 __instr_regwr_rii_exec(p, t, ip);
4730
4731
4732 thread_ip_inc(p);
4733}
4734
4735static inline void
4736instr_regadd_rhh_exec(struct rte_swx_pipeline *p)
4737{
4738 struct thread *t = &p->threads[p->thread_id];
4739 struct instruction *ip = t->ip;
4740
4741
4742 __instr_regadd_rhh_exec(p, t, ip);
4743
4744
4745 thread_ip_inc(p);
4746}
4747
4748static inline void
4749instr_regadd_rhm_exec(struct rte_swx_pipeline *p)
4750{
4751 struct thread *t = &p->threads[p->thread_id];
4752 struct instruction *ip = t->ip;
4753
4754
4755 __instr_regadd_rhm_exec(p, t, ip);
4756
4757
4758 thread_ip_inc(p);
4759}
4760
4761static inline void
4762instr_regadd_rmh_exec(struct rte_swx_pipeline *p)
4763{
4764 struct thread *t = &p->threads[p->thread_id];
4765 struct instruction *ip = t->ip;
4766
4767
4768 __instr_regadd_rmh_exec(p, t, ip);
4769
4770
4771 thread_ip_inc(p);
4772}
4773
4774static inline void
4775instr_regadd_rmm_exec(struct rte_swx_pipeline *p)
4776{
4777 struct thread *t = &p->threads[p->thread_id];
4778 struct instruction *ip = t->ip;
4779
4780
4781 __instr_regadd_rmm_exec(p, t, ip);
4782
4783
4784 thread_ip_inc(p);
4785}
4786
4787static inline void
4788instr_regadd_rhi_exec(struct rte_swx_pipeline *p)
4789{
4790 struct thread *t = &p->threads[p->thread_id];
4791 struct instruction *ip = t->ip;
4792
4793
4794 __instr_regadd_rhi_exec(p, t, ip);
4795
4796
4797 thread_ip_inc(p);
4798}
4799
4800static inline void
4801instr_regadd_rmi_exec(struct rte_swx_pipeline *p)
4802{
4803 struct thread *t = &p->threads[p->thread_id];
4804 struct instruction *ip = t->ip;
4805
4806
4807 __instr_regadd_rmi_exec(p, t, ip);
4808
4809
4810 thread_ip_inc(p);
4811}
4812
4813static inline void
4814instr_regadd_rih_exec(struct rte_swx_pipeline *p)
4815{
4816 struct thread *t = &p->threads[p->thread_id];
4817 struct instruction *ip = t->ip;
4818
4819
4820 __instr_regadd_rih_exec(p, t, ip);
4821
4822
4823 thread_ip_inc(p);
4824}
4825
4826static inline void
4827instr_regadd_rim_exec(struct rte_swx_pipeline *p)
4828{
4829 struct thread *t = &p->threads[p->thread_id];
4830 struct instruction *ip = t->ip;
4831
4832
4833 __instr_regadd_rim_exec(p, t, ip);
4834
4835
4836 thread_ip_inc(p);
4837}
4838
4839static inline void
4840instr_regadd_rii_exec(struct rte_swx_pipeline *p)
4841{
4842 struct thread *t = &p->threads[p->thread_id];
4843 struct instruction *ip = t->ip;
4844
4845
4846 __instr_regadd_rii_exec(p, t, ip);
4847
4848
4849 thread_ip_inc(p);
4850}
4851
4852
4853
4854
4855static struct metarray *
4856metarray_find(struct rte_swx_pipeline *p, const char *name);
4857
4858static int
4859instr_metprefetch_translate(struct rte_swx_pipeline *p,
4860 struct action *action,
4861 char **tokens,
4862 int n_tokens,
4863 struct instruction *instr,
4864 struct instruction_data *data __rte_unused)
4865{
4866 char *metarray = tokens[1], *idx = tokens[2];
4867 struct metarray *m;
4868 struct field *fidx;
4869 uint32_t idx_struct_id, idx_val;
4870
4871 CHECK(n_tokens == 3, EINVAL);
4872
4873 m = metarray_find(p, metarray);
4874 CHECK(m, EINVAL);
4875
4876
4877 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4878 if (fidx) {
4879 CHECK(!fidx->var_size, EINVAL);
4880
4881 instr->type = INSTR_METPREFETCH_M;
4882 if (idx[0] == 'h')
4883 instr->type = INSTR_METPREFETCH_H;
4884
4885 instr->meter.metarray_id = m->id;
4886 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4887 instr->meter.idx.n_bits = fidx->n_bits;
4888 instr->meter.idx.offset = fidx->offset / 8;
4889 return 0;
4890 }
4891
4892
4893 idx_val = strtoul(idx, &idx, 0);
4894 CHECK(!idx[0], EINVAL);
4895
4896 instr->type = INSTR_METPREFETCH_I;
4897 instr->meter.metarray_id = m->id;
4898 instr->meter.idx_val = idx_val;
4899 return 0;
4900}
4901
4902static int
4903instr_meter_translate(struct rte_swx_pipeline *p,
4904 struct action *action,
4905 char **tokens,
4906 int n_tokens,
4907 struct instruction *instr,
4908 struct instruction_data *data __rte_unused)
4909{
4910 char *metarray = tokens[1], *idx = tokens[2], *length = tokens[3];
4911 char *color_in = tokens[4], *color_out = tokens[5];
4912 struct metarray *m;
4913 struct field *fidx, *flength, *fcin, *fcout;
4914 uint32_t idx_struct_id, length_struct_id;
4915 uint32_t color_in_struct_id, color_out_struct_id;
4916
4917 CHECK(n_tokens == 6, EINVAL);
4918
4919 m = metarray_find(p, metarray);
4920 CHECK(m, EINVAL);
4921
4922 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4923
4924 flength = struct_field_parse(p, action, length, &length_struct_id);
4925 CHECK(flength, EINVAL);
4926 CHECK(!flength->var_size, EINVAL);
4927
4928 fcin = struct_field_parse(p, action, color_in, &color_in_struct_id);
4929
4930 fcout = struct_field_parse(p, NULL, color_out, &color_out_struct_id);
4931 CHECK(fcout, EINVAL);
4932 CHECK(!fcout->var_size, EINVAL);
4933
4934
4935 if (fidx && fcin) {
4936 CHECK(!fidx->var_size, EINVAL);
4937 CHECK(!fcin->var_size, EINVAL);
4938
4939 instr->type = INSTR_METER_MMM;
4940 if (idx[0] == 'h' && length[0] == 'h')
4941 instr->type = INSTR_METER_HHM;
4942 if (idx[0] == 'h' && length[0] != 'h')
4943 instr->type = INSTR_METER_HMM;
4944 if (idx[0] != 'h' && length[0] == 'h')
4945 instr->type = INSTR_METER_MHM;
4946
4947 instr->meter.metarray_id = m->id;
4948
4949 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4950 instr->meter.idx.n_bits = fidx->n_bits;
4951 instr->meter.idx.offset = fidx->offset / 8;
4952
4953 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4954 instr->meter.length.n_bits = flength->n_bits;
4955 instr->meter.length.offset = flength->offset / 8;
4956
4957 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
4958 instr->meter.color_in.n_bits = fcin->n_bits;
4959 instr->meter.color_in.offset = fcin->offset / 8;
4960
4961 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4962 instr->meter.color_out.n_bits = fcout->n_bits;
4963 instr->meter.color_out.offset = fcout->offset / 8;
4964 }
4965
4966
4967 if (fidx && !fcin) {
4968 uint32_t color_in_val;
4969
4970 CHECK(!fidx->var_size, EINVAL);
4971
4972 color_in_val = strtoul(color_in, &color_in, 0);
4973 CHECK(!color_in[0], EINVAL);
4974
4975 instr->type = INSTR_METER_MMI;
4976 if (idx[0] == 'h' && length[0] == 'h')
4977 instr->type = INSTR_METER_HHI;
4978 if (idx[0] == 'h' && length[0] != 'h')
4979 instr->type = INSTR_METER_HMI;
4980 if (idx[0] != 'h' && length[0] == 'h')
4981 instr->type = INSTR_METER_MHI;
4982
4983 instr->meter.metarray_id = m->id;
4984
4985 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4986 instr->meter.idx.n_bits = fidx->n_bits;
4987 instr->meter.idx.offset = fidx->offset / 8;
4988
4989 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4990 instr->meter.length.n_bits = flength->n_bits;
4991 instr->meter.length.offset = flength->offset / 8;
4992
4993 instr->meter.color_in_val = color_in_val;
4994
4995 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4996 instr->meter.color_out.n_bits = fcout->n_bits;
4997 instr->meter.color_out.offset = fcout->offset / 8;
4998 }
4999
5000
5001 if (!fidx && fcin) {
5002 uint32_t idx_val;
5003
5004 idx_val = strtoul(idx, &idx, 0);
5005 CHECK(!idx[0], EINVAL);
5006
5007 CHECK(!fcin->var_size, EINVAL);
5008
5009 instr->type = INSTR_METER_IMM;
5010 if (length[0] == 'h')
5011 instr->type = INSTR_METER_IHM;
5012
5013 instr->meter.metarray_id = m->id;
5014
5015 instr->meter.idx_val = idx_val;
5016
5017 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5018 instr->meter.length.n_bits = flength->n_bits;
5019 instr->meter.length.offset = flength->offset / 8;
5020
5021 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
5022 instr->meter.color_in.n_bits = fcin->n_bits;
5023 instr->meter.color_in.offset = fcin->offset / 8;
5024
5025 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5026 instr->meter.color_out.n_bits = fcout->n_bits;
5027 instr->meter.color_out.offset = fcout->offset / 8;
5028 }
5029
5030
5031 if (!fidx && !fcin) {
5032 uint32_t idx_val, color_in_val;
5033
5034 idx_val = strtoul(idx, &idx, 0);
5035 CHECK(!idx[0], EINVAL);
5036
5037 color_in_val = strtoul(color_in, &color_in, 0);
5038 CHECK(!color_in[0], EINVAL);
5039
5040 instr->type = INSTR_METER_IMI;
5041 if (length[0] == 'h')
5042 instr->type = INSTR_METER_IHI;
5043
5044 instr->meter.metarray_id = m->id;
5045
5046 instr->meter.idx_val = idx_val;
5047
5048 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5049 instr->meter.length.n_bits = flength->n_bits;
5050 instr->meter.length.offset = flength->offset / 8;
5051
5052 instr->meter.color_in_val = color_in_val;
5053
5054 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5055 instr->meter.color_out.n_bits = fcout->n_bits;
5056 instr->meter.color_out.offset = fcout->offset / 8;
5057 }
5058
5059 return 0;
5060}
5061
5062static inline void
5063instr_metprefetch_h_exec(struct rte_swx_pipeline *p)
5064{
5065 struct thread *t = &p->threads[p->thread_id];
5066 struct instruction *ip = t->ip;
5067
5068
5069 __instr_metprefetch_h_exec(p, t, ip);
5070
5071
5072 thread_ip_inc(p);
5073}
5074
5075static inline void
5076instr_metprefetch_m_exec(struct rte_swx_pipeline *p)
5077{
5078 struct thread *t = &p->threads[p->thread_id];
5079 struct instruction *ip = t->ip;
5080
5081
5082 __instr_metprefetch_m_exec(p, t, ip);
5083
5084
5085 thread_ip_inc(p);
5086}
5087
5088static inline void
5089instr_metprefetch_i_exec(struct rte_swx_pipeline *p)
5090{
5091 struct thread *t = &p->threads[p->thread_id];
5092 struct instruction *ip = t->ip;
5093
5094
5095 __instr_metprefetch_i_exec(p, t, ip);
5096
5097
5098 thread_ip_inc(p);
5099}
5100
5101static inline void
5102instr_meter_hhm_exec(struct rte_swx_pipeline *p)
5103{
5104 struct thread *t = &p->threads[p->thread_id];
5105 struct instruction *ip = t->ip;
5106
5107
5108 __instr_meter_hhm_exec(p, t, ip);
5109
5110
5111 thread_ip_inc(p);
5112}
5113
5114static inline void
5115instr_meter_hhi_exec(struct rte_swx_pipeline *p)
5116{
5117 struct thread *t = &p->threads[p->thread_id];
5118 struct instruction *ip = t->ip;
5119
5120
5121 __instr_meter_hhi_exec(p, t, ip);
5122
5123
5124 thread_ip_inc(p);
5125}
5126
5127static inline void
5128instr_meter_hmm_exec(struct rte_swx_pipeline *p)
5129{
5130 struct thread *t = &p->threads[p->thread_id];
5131 struct instruction *ip = t->ip;
5132
5133
5134 __instr_meter_hmm_exec(p, t, ip);
5135
5136
5137 thread_ip_inc(p);
5138}
5139
5140static inline void
5141instr_meter_hmi_exec(struct rte_swx_pipeline *p)
5142{
5143 struct thread *t = &p->threads[p->thread_id];
5144 struct instruction *ip = t->ip;
5145
5146
5147 __instr_meter_hmi_exec(p, t, ip);
5148
5149
5150 thread_ip_inc(p);
5151}
5152
5153static inline void
5154instr_meter_mhm_exec(struct rte_swx_pipeline *p)
5155{
5156 struct thread *t = &p->threads[p->thread_id];
5157 struct instruction *ip = t->ip;
5158
5159
5160 __instr_meter_mhm_exec(p, t, ip);
5161
5162
5163 thread_ip_inc(p);
5164}
5165
5166static inline void
5167instr_meter_mhi_exec(struct rte_swx_pipeline *p)
5168{
5169 struct thread *t = &p->threads[p->thread_id];
5170 struct instruction *ip = t->ip;
5171
5172
5173 __instr_meter_mhi_exec(p, t, ip);
5174
5175
5176 thread_ip_inc(p);
5177}
5178
5179static inline void
5180instr_meter_mmm_exec(struct rte_swx_pipeline *p)
5181{
5182 struct thread *t = &p->threads[p->thread_id];
5183 struct instruction *ip = t->ip;
5184
5185
5186 __instr_meter_mmm_exec(p, t, ip);
5187
5188
5189 thread_ip_inc(p);
5190}
5191
5192static inline void
5193instr_meter_mmi_exec(struct rte_swx_pipeline *p)
5194{
5195 struct thread *t = &p->threads[p->thread_id];
5196 struct instruction *ip = t->ip;
5197
5198
5199 __instr_meter_mmi_exec(p, t, ip);
5200
5201
5202 thread_ip_inc(p);
5203}
5204
5205static inline void
5206instr_meter_ihm_exec(struct rte_swx_pipeline *p)
5207{
5208 struct thread *t = &p->threads[p->thread_id];
5209 struct instruction *ip = t->ip;
5210
5211
5212 __instr_meter_ihm_exec(p, t, ip);
5213
5214
5215 thread_ip_inc(p);
5216}
5217
5218static inline void
5219instr_meter_ihi_exec(struct rte_swx_pipeline *p)
5220{
5221 struct thread *t = &p->threads[p->thread_id];
5222 struct instruction *ip = t->ip;
5223
5224
5225 __instr_meter_ihi_exec(p, t, ip);
5226
5227
5228 thread_ip_inc(p);
5229}
5230
5231static inline void
5232instr_meter_imm_exec(struct rte_swx_pipeline *p)
5233{
5234 struct thread *t = &p->threads[p->thread_id];
5235 struct instruction *ip = t->ip;
5236
5237
5238 __instr_meter_imm_exec(p, t, ip);
5239
5240
5241 thread_ip_inc(p);
5242}
5243
5244static inline void
5245instr_meter_imi_exec(struct rte_swx_pipeline *p)
5246{
5247 struct thread *t = &p->threads[p->thread_id];
5248 struct instruction *ip = t->ip;
5249
5250
5251 __instr_meter_imi_exec(p, t, ip);
5252
5253
5254 thread_ip_inc(p);
5255}
5256
5257
5258
5259
5260static int
5261instr_jmp_translate(struct rte_swx_pipeline *p __rte_unused,
5262 struct action *action __rte_unused,
5263 char **tokens,
5264 int n_tokens,
5265 struct instruction *instr,
5266 struct instruction_data *data)
5267{
5268 CHECK(n_tokens == 2, EINVAL);
5269
5270 strcpy(data->jmp_label, tokens[1]);
5271
5272 instr->type = INSTR_JMP;
5273 instr->jmp.ip = NULL;
5274 return 0;
5275}
5276
5277static int
5278instr_jmp_valid_translate(struct rte_swx_pipeline *p,
5279 struct action *action __rte_unused,
5280 char **tokens,
5281 int n_tokens,
5282 struct instruction *instr,
5283 struct instruction_data *data)
5284{
5285 struct header *h;
5286
5287 CHECK(n_tokens == 3, EINVAL);
5288
5289 strcpy(data->jmp_label, tokens[1]);
5290
5291 h = header_parse(p, tokens[2]);
5292 CHECK(h, EINVAL);
5293
5294 instr->type = INSTR_JMP_VALID;
5295 instr->jmp.ip = NULL;
5296 instr->jmp.header_id = h->id;
5297 return 0;
5298}
5299
5300static int
5301instr_jmp_invalid_translate(struct rte_swx_pipeline *p,
5302 struct action *action __rte_unused,
5303 char **tokens,
5304 int n_tokens,
5305 struct instruction *instr,
5306 struct instruction_data *data)
5307{
5308 struct header *h;
5309
5310 CHECK(n_tokens == 3, EINVAL);
5311
5312 strcpy(data->jmp_label, tokens[1]);
5313
5314 h = header_parse(p, tokens[2]);
5315 CHECK(h, EINVAL);
5316
5317 instr->type = INSTR_JMP_INVALID;
5318 instr->jmp.ip = NULL;
5319 instr->jmp.header_id = h->id;
5320 return 0;
5321}
5322
5323static int
5324instr_jmp_hit_translate(struct rte_swx_pipeline *p __rte_unused,
5325 struct action *action,
5326 char **tokens,
5327 int n_tokens,
5328 struct instruction *instr,
5329 struct instruction_data *data)
5330{
5331 CHECK(!action, EINVAL);
5332 CHECK(n_tokens == 2, EINVAL);
5333
5334 strcpy(data->jmp_label, tokens[1]);
5335
5336 instr->type = INSTR_JMP_HIT;
5337 instr->jmp.ip = NULL;
5338 return 0;
5339}
5340
5341static int
5342instr_jmp_miss_translate(struct rte_swx_pipeline *p __rte_unused,
5343 struct action *action,
5344 char **tokens,
5345 int n_tokens,
5346 struct instruction *instr,
5347 struct instruction_data *data)
5348{
5349 CHECK(!action, EINVAL);
5350 CHECK(n_tokens == 2, EINVAL);
5351
5352 strcpy(data->jmp_label, tokens[1]);
5353
5354 instr->type = INSTR_JMP_MISS;
5355 instr->jmp.ip = NULL;
5356 return 0;
5357}
5358
5359static int
5360instr_jmp_action_hit_translate(struct rte_swx_pipeline *p,
5361 struct action *action,
5362 char **tokens,
5363 int n_tokens,
5364 struct instruction *instr,
5365 struct instruction_data *data)
5366{
5367 struct action *a;
5368
5369 CHECK(!action, EINVAL);
5370 CHECK(n_tokens == 3, EINVAL);
5371
5372 strcpy(data->jmp_label, tokens[1]);
5373
5374 a = action_find(p, tokens[2]);
5375 CHECK(a, EINVAL);
5376
5377 instr->type = INSTR_JMP_ACTION_HIT;
5378 instr->jmp.ip = NULL;
5379 instr->jmp.action_id = a->id;
5380 return 0;
5381}
5382
5383static int
5384instr_jmp_action_miss_translate(struct rte_swx_pipeline *p,
5385 struct action *action,
5386 char **tokens,
5387 int n_tokens,
5388 struct instruction *instr,
5389 struct instruction_data *data)
5390{
5391 struct action *a;
5392
5393 CHECK(!action, EINVAL);
5394 CHECK(n_tokens == 3, EINVAL);
5395
5396 strcpy(data->jmp_label, tokens[1]);
5397
5398 a = action_find(p, tokens[2]);
5399 CHECK(a, EINVAL);
5400
5401 instr->type = INSTR_JMP_ACTION_MISS;
5402 instr->jmp.ip = NULL;
5403 instr->jmp.action_id = a->id;
5404 return 0;
5405}
5406
5407static int
5408instr_jmp_eq_translate(struct rte_swx_pipeline *p,
5409 struct action *action,
5410 char **tokens,
5411 int n_tokens,
5412 struct instruction *instr,
5413 struct instruction_data *data)
5414{
5415 char *a = tokens[2], *b = tokens[3];
5416 struct field *fa, *fb;
5417 uint64_t b_val;
5418 uint32_t a_struct_id, b_struct_id;
5419
5420 CHECK(n_tokens == 4, EINVAL);
5421
5422 strcpy(data->jmp_label, tokens[1]);
5423
5424 fa = struct_field_parse(p, action, a, &a_struct_id);
5425 CHECK(fa, EINVAL);
5426 CHECK(!fa->var_size, EINVAL);
5427
5428
5429 fb = struct_field_parse(p, action, b, &b_struct_id);
5430 if (fb) {
5431 CHECK(!fb->var_size, EINVAL);
5432
5433 instr->type = INSTR_JMP_EQ;
5434 if (a[0] != 'h' && b[0] == 'h')
5435 instr->type = INSTR_JMP_EQ_MH;
5436 if (a[0] == 'h' && b[0] != 'h')
5437 instr->type = INSTR_JMP_EQ_HM;
5438 if (a[0] == 'h' && b[0] == 'h')
5439 instr->type = INSTR_JMP_EQ_HH;
5440 instr->jmp.ip = NULL;
5441
5442 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5443 instr->jmp.a.n_bits = fa->n_bits;
5444 instr->jmp.a.offset = fa->offset / 8;
5445 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5446 instr->jmp.b.n_bits = fb->n_bits;
5447 instr->jmp.b.offset = fb->offset / 8;
5448 return 0;
5449 }
5450
5451
5452 b_val = strtoull(b, &b, 0);
5453 CHECK(!b[0], EINVAL);
5454
5455 if (a[0] == 'h')
5456 b_val = hton64(b_val) >> (64 - fa->n_bits);
5457
5458 instr->type = INSTR_JMP_EQ_I;
5459 instr->jmp.ip = NULL;
5460 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5461 instr->jmp.a.n_bits = fa->n_bits;
5462 instr->jmp.a.offset = fa->offset / 8;
5463 instr->jmp.b_val = b_val;
5464 return 0;
5465}
5466
5467static int
5468instr_jmp_neq_translate(struct rte_swx_pipeline *p,
5469 struct action *action,
5470 char **tokens,
5471 int n_tokens,
5472 struct instruction *instr,
5473 struct instruction_data *data)
5474{
5475 char *a = tokens[2], *b = tokens[3];
5476 struct field *fa, *fb;
5477 uint64_t b_val;
5478 uint32_t a_struct_id, b_struct_id;
5479
5480 CHECK(n_tokens == 4, EINVAL);
5481
5482 strcpy(data->jmp_label, tokens[1]);
5483
5484 fa = struct_field_parse(p, action, a, &a_struct_id);
5485 CHECK(fa, EINVAL);
5486 CHECK(!fa->var_size, EINVAL);
5487
5488
5489 fb = struct_field_parse(p, action, b, &b_struct_id);
5490 if (fb) {
5491 CHECK(!fb->var_size, EINVAL);
5492
5493 instr->type = INSTR_JMP_NEQ;
5494 if (a[0] != 'h' && b[0] == 'h')
5495 instr->type = INSTR_JMP_NEQ_MH;
5496 if (a[0] == 'h' && b[0] != 'h')
5497 instr->type = INSTR_JMP_NEQ_HM;
5498 if (a[0] == 'h' && b[0] == 'h')
5499 instr->type = INSTR_JMP_NEQ_HH;
5500 instr->jmp.ip = NULL;
5501
5502 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5503 instr->jmp.a.n_bits = fa->n_bits;
5504 instr->jmp.a.offset = fa->offset / 8;
5505 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5506 instr->jmp.b.n_bits = fb->n_bits;
5507 instr->jmp.b.offset = fb->offset / 8;
5508 return 0;
5509 }
5510
5511
5512 b_val = strtoull(b, &b, 0);
5513 CHECK(!b[0], EINVAL);
5514
5515 if (a[0] == 'h')
5516 b_val = hton64(b_val) >> (64 - fa->n_bits);
5517
5518 instr->type = INSTR_JMP_NEQ_I;
5519 instr->jmp.ip = NULL;
5520 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5521 instr->jmp.a.n_bits = fa->n_bits;
5522 instr->jmp.a.offset = fa->offset / 8;
5523 instr->jmp.b_val = b_val;
5524 return 0;
5525}
5526
5527static int
5528instr_jmp_lt_translate(struct rte_swx_pipeline *p,
5529 struct action *action,
5530 char **tokens,
5531 int n_tokens,
5532 struct instruction *instr,
5533 struct instruction_data *data)
5534{
5535 char *a = tokens[2], *b = tokens[3];
5536 struct field *fa, *fb;
5537 uint64_t b_val;
5538 uint32_t a_struct_id, b_struct_id;
5539
5540 CHECK(n_tokens == 4, EINVAL);
5541
5542 strcpy(data->jmp_label, tokens[1]);
5543
5544 fa = struct_field_parse(p, action, a, &a_struct_id);
5545 CHECK(fa, EINVAL);
5546 CHECK(!fa->var_size, EINVAL);
5547
5548
5549 fb = struct_field_parse(p, action, b, &b_struct_id);
5550 if (fb) {
5551 CHECK(!fb->var_size, EINVAL);
5552
5553 instr->type = INSTR_JMP_LT;
5554 if (a[0] == 'h' && b[0] != 'h')
5555 instr->type = INSTR_JMP_LT_HM;
5556 if (a[0] != 'h' && b[0] == 'h')
5557 instr->type = INSTR_JMP_LT_MH;
5558 if (a[0] == 'h' && b[0] == 'h')
5559 instr->type = INSTR_JMP_LT_HH;
5560 instr->jmp.ip = NULL;
5561
5562 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5563 instr->jmp.a.n_bits = fa->n_bits;
5564 instr->jmp.a.offset = fa->offset / 8;
5565 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5566 instr->jmp.b.n_bits = fb->n_bits;
5567 instr->jmp.b.offset = fb->offset / 8;
5568 return 0;
5569 }
5570
5571
5572 b_val = strtoull(b, &b, 0);
5573 CHECK(!b[0], EINVAL);
5574
5575 instr->type = INSTR_JMP_LT_MI;
5576 if (a[0] == 'h')
5577 instr->type = INSTR_JMP_LT_HI;
5578 instr->jmp.ip = NULL;
5579
5580 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5581 instr->jmp.a.n_bits = fa->n_bits;
5582 instr->jmp.a.offset = fa->offset / 8;
5583 instr->jmp.b_val = b_val;
5584 return 0;
5585}
5586
5587static int
5588instr_jmp_gt_translate(struct rte_swx_pipeline *p,
5589 struct action *action,
5590 char **tokens,
5591 int n_tokens,
5592 struct instruction *instr,
5593 struct instruction_data *data)
5594{
5595 char *a = tokens[2], *b = tokens[3];
5596 struct field *fa, *fb;
5597 uint64_t b_val;
5598 uint32_t a_struct_id, b_struct_id;
5599
5600 CHECK(n_tokens == 4, EINVAL);
5601
5602 strcpy(data->jmp_label, tokens[1]);
5603
5604 fa = struct_field_parse(p, action, a, &a_struct_id);
5605 CHECK(fa, EINVAL);
5606 CHECK(!fa->var_size, EINVAL);
5607
5608
5609 fb = struct_field_parse(p, action, b, &b_struct_id);
5610 if (fb) {
5611 CHECK(!fb->var_size, EINVAL);
5612
5613 instr->type = INSTR_JMP_GT;
5614 if (a[0] == 'h' && b[0] != 'h')
5615 instr->type = INSTR_JMP_GT_HM;
5616 if (a[0] != 'h' && b[0] == 'h')
5617 instr->type = INSTR_JMP_GT_MH;
5618 if (a[0] == 'h' && b[0] == 'h')
5619 instr->type = INSTR_JMP_GT_HH;
5620 instr->jmp.ip = NULL;
5621
5622 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5623 instr->jmp.a.n_bits = fa->n_bits;
5624 instr->jmp.a.offset = fa->offset / 8;
5625 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5626 instr->jmp.b.n_bits = fb->n_bits;
5627 instr->jmp.b.offset = fb->offset / 8;
5628 return 0;
5629 }
5630
5631
5632 b_val = strtoull(b, &b, 0);
5633 CHECK(!b[0], EINVAL);
5634
5635 instr->type = INSTR_JMP_GT_MI;
5636 if (a[0] == 'h')
5637 instr->type = INSTR_JMP_GT_HI;
5638 instr->jmp.ip = NULL;
5639
5640 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5641 instr->jmp.a.n_bits = fa->n_bits;
5642 instr->jmp.a.offset = fa->offset / 8;
5643 instr->jmp.b_val = b_val;
5644 return 0;
5645}
5646
5647static inline void
5648instr_jmp_exec(struct rte_swx_pipeline *p)
5649{
5650 struct thread *t = &p->threads[p->thread_id];
5651 struct instruction *ip = t->ip;
5652
5653 TRACE("[Thread %2u] jmp\n", p->thread_id);
5654
5655 thread_ip_set(t, ip->jmp.ip);
5656}
5657
5658static inline void
5659instr_jmp_valid_exec(struct rte_swx_pipeline *p)
5660{
5661 struct thread *t = &p->threads[p->thread_id];
5662 struct instruction *ip = t->ip;
5663 uint32_t header_id = ip->jmp.header_id;
5664
5665 TRACE("[Thread %2u] jmpv\n", p->thread_id);
5666
5667 t->ip = HEADER_VALID(t, header_id) ? ip->jmp.ip : (t->ip + 1);
5668}
5669
5670static inline void
5671instr_jmp_invalid_exec(struct rte_swx_pipeline *p)
5672{
5673 struct thread *t = &p->threads[p->thread_id];
5674 struct instruction *ip = t->ip;
5675 uint32_t header_id = ip->jmp.header_id;
5676
5677 TRACE("[Thread %2u] jmpnv\n", p->thread_id);
5678
5679 t->ip = HEADER_VALID(t, header_id) ? (t->ip + 1) : ip->jmp.ip;
5680}
5681
5682static inline void
5683instr_jmp_hit_exec(struct rte_swx_pipeline *p)
5684{
5685 struct thread *t = &p->threads[p->thread_id];
5686 struct instruction *ip = t->ip;
5687 struct instruction *ip_next[] = {t->ip + 1, ip->jmp.ip};
5688
5689 TRACE("[Thread %2u] jmph\n", p->thread_id);
5690
5691 t->ip = ip_next[t->hit];
5692}
5693
5694static inline void
5695instr_jmp_miss_exec(struct rte_swx_pipeline *p)
5696{
5697 struct thread *t = &p->threads[p->thread_id];
5698 struct instruction *ip = t->ip;
5699 struct instruction *ip_next[] = {ip->jmp.ip, t->ip + 1};
5700
5701 TRACE("[Thread %2u] jmpnh\n", p->thread_id);
5702
5703 t->ip = ip_next[t->hit];
5704}
5705
5706static inline void
5707instr_jmp_action_hit_exec(struct rte_swx_pipeline *p)
5708{
5709 struct thread *t = &p->threads[p->thread_id];
5710 struct instruction *ip = t->ip;
5711
5712 TRACE("[Thread %2u] jmpa\n", p->thread_id);
5713
5714 t->ip = (ip->jmp.action_id == t->action_id) ? ip->jmp.ip : (t->ip + 1);
5715}
5716
5717static inline void
5718instr_jmp_action_miss_exec(struct rte_swx_pipeline *p)
5719{
5720 struct thread *t = &p->threads[p->thread_id];
5721 struct instruction *ip = t->ip;
5722
5723 TRACE("[Thread %2u] jmpna\n", p->thread_id);
5724
5725 t->ip = (ip->jmp.action_id == t->action_id) ? (t->ip + 1) : ip->jmp.ip;
5726}
5727
5728static inline void
5729instr_jmp_eq_exec(struct rte_swx_pipeline *p)
5730{
5731 struct thread *t = &p->threads[p->thread_id];
5732 struct instruction *ip = t->ip;
5733
5734 TRACE("[Thread %2u] jmpeq\n", p->thread_id);
5735
5736 JMP_CMP(t, ip, ==);
5737}
5738
5739static inline void
5740instr_jmp_eq_mh_exec(struct rte_swx_pipeline *p)
5741{
5742 struct thread *t = &p->threads[p->thread_id];
5743 struct instruction *ip = t->ip;
5744
5745 TRACE("[Thread %2u] jmpeq (mh)\n", p->thread_id);
5746
5747 JMP_CMP_MH(t, ip, ==);
5748}
5749
5750static inline void
5751instr_jmp_eq_hm_exec(struct rte_swx_pipeline *p)
5752{
5753 struct thread *t = &p->threads[p->thread_id];
5754 struct instruction *ip = t->ip;
5755
5756 TRACE("[Thread %2u] jmpeq (hm)\n", p->thread_id);
5757
5758 JMP_CMP_HM(t, ip, ==);
5759}
5760
5761static inline void
5762instr_jmp_eq_hh_exec(struct rte_swx_pipeline *p)
5763{
5764 struct thread *t = &p->threads[p->thread_id];
5765 struct instruction *ip = t->ip;
5766
5767 TRACE("[Thread %2u] jmpeq (hh)\n", p->thread_id);
5768
5769 JMP_CMP_HH_FAST(t, ip, ==);
5770}
5771
5772static inline void
5773instr_jmp_eq_i_exec(struct rte_swx_pipeline *p)
5774{
5775 struct thread *t = &p->threads[p->thread_id];
5776 struct instruction *ip = t->ip;
5777
5778 TRACE("[Thread %2u] jmpeq (i)\n", p->thread_id);
5779
5780 JMP_CMP_I(t, ip, ==);
5781}
5782
5783static inline void
5784instr_jmp_neq_exec(struct rte_swx_pipeline *p)
5785{
5786 struct thread *t = &p->threads[p->thread_id];
5787 struct instruction *ip = t->ip;
5788
5789 TRACE("[Thread %2u] jmpneq\n", p->thread_id);
5790
5791 JMP_CMP(t, ip, !=);
5792}
5793
5794static inline void
5795instr_jmp_neq_mh_exec(struct rte_swx_pipeline *p)
5796{
5797 struct thread *t = &p->threads[p->thread_id];
5798 struct instruction *ip = t->ip;
5799
5800 TRACE("[Thread %2u] jmpneq (mh)\n", p->thread_id);
5801
5802 JMP_CMP_MH(t, ip, !=);
5803}
5804
5805static inline void
5806instr_jmp_neq_hm_exec(struct rte_swx_pipeline *p)
5807{
5808 struct thread *t = &p->threads[p->thread_id];
5809 struct instruction *ip = t->ip;
5810
5811 TRACE("[Thread %2u] jmpneq (hm)\n", p->thread_id);
5812
5813 JMP_CMP_HM(t, ip, !=);
5814}
5815
5816static inline void
5817instr_jmp_neq_hh_exec(struct rte_swx_pipeline *p)
5818{
5819 struct thread *t = &p->threads[p->thread_id];
5820 struct instruction *ip = t->ip;
5821
5822 TRACE("[Thread %2u] jmpneq (hh)\n", p->thread_id);
5823
5824 JMP_CMP_HH_FAST(t, ip, !=);
5825}
5826
5827static inline void
5828instr_jmp_neq_i_exec(struct rte_swx_pipeline *p)
5829{
5830 struct thread *t = &p->threads[p->thread_id];
5831 struct instruction *ip = t->ip;
5832
5833 TRACE("[Thread %2u] jmpneq (i)\n", p->thread_id);
5834
5835 JMP_CMP_I(t, ip, !=);
5836}
5837
5838static inline void
5839instr_jmp_lt_exec(struct rte_swx_pipeline *p)
5840{
5841 struct thread *t = &p->threads[p->thread_id];
5842 struct instruction *ip = t->ip;
5843
5844 TRACE("[Thread %2u] jmplt\n", p->thread_id);
5845
5846 JMP_CMP(t, ip, <);
5847}
5848
5849static inline void
5850instr_jmp_lt_mh_exec(struct rte_swx_pipeline *p)
5851{
5852 struct thread *t = &p->threads[p->thread_id];
5853 struct instruction *ip = t->ip;
5854
5855 TRACE("[Thread %2u] jmplt (mh)\n", p->thread_id);
5856
5857 JMP_CMP_MH(t, ip, <);
5858}
5859
5860static inline void
5861instr_jmp_lt_hm_exec(struct rte_swx_pipeline *p)
5862{
5863 struct thread *t = &p->threads[p->thread_id];
5864 struct instruction *ip = t->ip;
5865
5866 TRACE("[Thread %2u] jmplt (hm)\n", p->thread_id);
5867
5868 JMP_CMP_HM(t, ip, <);
5869}
5870
5871static inline void
5872instr_jmp_lt_hh_exec(struct rte_swx_pipeline *p)
5873{
5874 struct thread *t = &p->threads[p->thread_id];
5875 struct instruction *ip = t->ip;
5876
5877 TRACE("[Thread %2u] jmplt (hh)\n", p->thread_id);
5878
5879 JMP_CMP_HH(t, ip, <);
5880}
5881
5882static inline void
5883instr_jmp_lt_mi_exec(struct rte_swx_pipeline *p)
5884{
5885 struct thread *t = &p->threads[p->thread_id];
5886 struct instruction *ip = t->ip;
5887
5888 TRACE("[Thread %2u] jmplt (mi)\n", p->thread_id);
5889
5890 JMP_CMP_MI(t, ip, <);
5891}
5892
5893static inline void
5894instr_jmp_lt_hi_exec(struct rte_swx_pipeline *p)
5895{
5896 struct thread *t = &p->threads[p->thread_id];
5897 struct instruction *ip = t->ip;
5898
5899 TRACE("[Thread %2u] jmplt (hi)\n", p->thread_id);
5900
5901 JMP_CMP_HI(t, ip, <);
5902}
5903
5904static inline void
5905instr_jmp_gt_exec(struct rte_swx_pipeline *p)
5906{
5907 struct thread *t = &p->threads[p->thread_id];
5908 struct instruction *ip = t->ip;
5909
5910 TRACE("[Thread %2u] jmpgt\n", p->thread_id);
5911
5912 JMP_CMP(t, ip, >);
5913}
5914
5915static inline void
5916instr_jmp_gt_mh_exec(struct rte_swx_pipeline *p)
5917{
5918 struct thread *t = &p->threads[p->thread_id];
5919 struct instruction *ip = t->ip;
5920
5921 TRACE("[Thread %2u] jmpgt (mh)\n", p->thread_id);
5922
5923 JMP_CMP_MH(t, ip, >);
5924}
5925
5926static inline void
5927instr_jmp_gt_hm_exec(struct rte_swx_pipeline *p)
5928{
5929 struct thread *t = &p->threads[p->thread_id];
5930 struct instruction *ip = t->ip;
5931
5932 TRACE("[Thread %2u] jmpgt (hm)\n", p->thread_id);
5933
5934 JMP_CMP_HM(t, ip, >);
5935}
5936
5937static inline void
5938instr_jmp_gt_hh_exec(struct rte_swx_pipeline *p)
5939{
5940 struct thread *t = &p->threads[p->thread_id];
5941 struct instruction *ip = t->ip;
5942
5943 TRACE("[Thread %2u] jmpgt (hh)\n", p->thread_id);
5944
5945 JMP_CMP_HH(t, ip, >);
5946}
5947
5948static inline void
5949instr_jmp_gt_mi_exec(struct rte_swx_pipeline *p)
5950{
5951 struct thread *t = &p->threads[p->thread_id];
5952 struct instruction *ip = t->ip;
5953
5954 TRACE("[Thread %2u] jmpgt (mi)\n", p->thread_id);
5955
5956 JMP_CMP_MI(t, ip, >);
5957}
5958
5959static inline void
5960instr_jmp_gt_hi_exec(struct rte_swx_pipeline *p)
5961{
5962 struct thread *t = &p->threads[p->thread_id];
5963 struct instruction *ip = t->ip;
5964
5965 TRACE("[Thread %2u] jmpgt (hi)\n", p->thread_id);
5966
5967 JMP_CMP_HI(t, ip, >);
5968}
5969
5970
5971
5972
5973static int
5974instr_return_translate(struct rte_swx_pipeline *p __rte_unused,
5975 struct action *action,
5976 char **tokens __rte_unused,
5977 int n_tokens,
5978 struct instruction *instr,
5979 struct instruction_data *data __rte_unused)
5980{
5981 CHECK(action, EINVAL);
5982 CHECK(n_tokens == 1, EINVAL);
5983
5984 instr->type = INSTR_RETURN;
5985 return 0;
5986}
5987
5988static inline void
5989instr_return_exec(struct rte_swx_pipeline *p)
5990{
5991 struct thread *t = &p->threads[p->thread_id];
5992
5993 TRACE("[Thread %2u] return\n", p->thread_id);
5994
5995 t->ip = t->ret;
5996}
5997
5998static int
5999instr_translate(struct rte_swx_pipeline *p,
6000 struct action *action,
6001 char *string,
6002 struct instruction *instr,
6003 struct instruction_data *data)
6004{
6005 char *tokens[RTE_SWX_INSTRUCTION_TOKENS_MAX];
6006 int n_tokens = 0, tpos = 0;
6007
6008
6009 for ( ; ; ) {
6010 char *token;
6011
6012 token = strtok_r(string, " \t\v", &string);
6013 if (!token)
6014 break;
6015
6016 CHECK(n_tokens < RTE_SWX_INSTRUCTION_TOKENS_MAX, EINVAL);
6017 CHECK_NAME(token, EINVAL);
6018
6019 tokens[n_tokens] = token;
6020 n_tokens++;
6021 }
6022
6023 CHECK(n_tokens, EINVAL);
6024
6025
6026 if ((n_tokens >= 2) && !strcmp(tokens[1], ":")) {
6027 strcpy(data->label, tokens[0]);
6028
6029 tpos += 2;
6030 CHECK(n_tokens - tpos, EINVAL);
6031 }
6032
6033
6034 if (!strcmp(tokens[tpos], "rx"))
6035 return instr_rx_translate(p,
6036 action,
6037 &tokens[tpos],
6038 n_tokens - tpos,
6039 instr,
6040 data);
6041
6042 if (!strcmp(tokens[tpos], "tx"))
6043 return instr_tx_translate(p,
6044 action,
6045 &tokens[tpos],
6046 n_tokens - tpos,
6047 instr,
6048 data);
6049
6050 if (!strcmp(tokens[tpos], "drop"))
6051 return instr_drop_translate(p,
6052 action,
6053 &tokens[tpos],
6054 n_tokens - tpos,
6055 instr,
6056 data);
6057
6058 if (!strcmp(tokens[tpos], "mirror"))
6059 return instr_mirror_translate(p,
6060 action,
6061 &tokens[tpos],
6062 n_tokens - tpos,
6063 instr,
6064 data);
6065
6066 if (!strcmp(tokens[tpos], "recirculate"))
6067 return instr_recirculate_translate(p,
6068 action,
6069 &tokens[tpos],
6070 n_tokens - tpos,
6071 instr,
6072 data);
6073
6074 if (!strcmp(tokens[tpos], "recircid"))
6075 return instr_recircid_translate(p,
6076 action,
6077 &tokens[tpos],
6078 n_tokens - tpos,
6079 instr,
6080 data);
6081
6082 if (!strcmp(tokens[tpos], "extract"))
6083 return instr_hdr_extract_translate(p,
6084 action,
6085 &tokens[tpos],
6086 n_tokens - tpos,
6087 instr,
6088 data);
6089
6090 if (!strcmp(tokens[tpos], "lookahead"))
6091 return instr_hdr_lookahead_translate(p,
6092 action,
6093 &tokens[tpos],
6094 n_tokens - tpos,
6095 instr,
6096 data);
6097
6098 if (!strcmp(tokens[tpos], "emit"))
6099 return instr_hdr_emit_translate(p,
6100 action,
6101 &tokens[tpos],
6102 n_tokens - tpos,
6103 instr,
6104 data);
6105
6106 if (!strcmp(tokens[tpos], "validate"))
6107 return instr_hdr_validate_translate(p,
6108 action,
6109 &tokens[tpos],
6110 n_tokens - tpos,
6111 instr,
6112 data);
6113
6114 if (!strcmp(tokens[tpos], "invalidate"))
6115 return instr_hdr_invalidate_translate(p,
6116 action,
6117 &tokens[tpos],
6118 n_tokens - tpos,
6119 instr,
6120 data);
6121
6122 if (!strcmp(tokens[tpos], "mov"))
6123 return instr_mov_translate(p,
6124 action,
6125 &tokens[tpos],
6126 n_tokens - tpos,
6127 instr,
6128 data);
6129
6130 if (!strcmp(tokens[tpos], "add"))
6131 return instr_alu_add_translate(p,
6132 action,
6133 &tokens[tpos],
6134 n_tokens - tpos,
6135 instr,
6136 data);
6137
6138 if (!strcmp(tokens[tpos], "sub"))
6139 return instr_alu_sub_translate(p,
6140 action,
6141 &tokens[tpos],
6142 n_tokens - tpos,
6143 instr,
6144 data);
6145
6146 if (!strcmp(tokens[tpos], "ckadd"))
6147 return instr_alu_ckadd_translate(p,
6148 action,
6149 &tokens[tpos],
6150 n_tokens - tpos,
6151 instr,
6152 data);
6153
6154 if (!strcmp(tokens[tpos], "cksub"))
6155 return instr_alu_cksub_translate(p,
6156 action,
6157 &tokens[tpos],
6158 n_tokens - tpos,
6159 instr,
6160 data);
6161
6162 if (!strcmp(tokens[tpos], "and"))
6163 return instr_alu_and_translate(p,
6164 action,
6165 &tokens[tpos],
6166 n_tokens - tpos,
6167 instr,
6168 data);
6169
6170 if (!strcmp(tokens[tpos], "or"))
6171 return instr_alu_or_translate(p,
6172 action,
6173 &tokens[tpos],
6174 n_tokens - tpos,
6175 instr,
6176 data);
6177
6178 if (!strcmp(tokens[tpos], "xor"))
6179 return instr_alu_xor_translate(p,
6180 action,
6181 &tokens[tpos],
6182 n_tokens - tpos,
6183 instr,
6184 data);
6185
6186 if (!strcmp(tokens[tpos], "shl"))
6187 return instr_alu_shl_translate(p,
6188 action,
6189 &tokens[tpos],
6190 n_tokens - tpos,
6191 instr,
6192 data);
6193
6194 if (!strcmp(tokens[tpos], "shr"))
6195 return instr_alu_shr_translate(p,
6196 action,
6197 &tokens[tpos],
6198 n_tokens - tpos,
6199 instr,
6200 data);
6201
6202 if (!strcmp(tokens[tpos], "regprefetch"))
6203 return instr_regprefetch_translate(p,
6204 action,
6205 &tokens[tpos],
6206 n_tokens - tpos,
6207 instr,
6208 data);
6209
6210 if (!strcmp(tokens[tpos], "regrd"))
6211 return instr_regrd_translate(p,
6212 action,
6213 &tokens[tpos],
6214 n_tokens - tpos,
6215 instr,
6216 data);
6217
6218 if (!strcmp(tokens[tpos], "regwr"))
6219 return instr_regwr_translate(p,
6220 action,
6221 &tokens[tpos],
6222 n_tokens - tpos,
6223 instr,
6224 data);
6225
6226 if (!strcmp(tokens[tpos], "regadd"))
6227 return instr_regadd_translate(p,
6228 action,
6229 &tokens[tpos],
6230 n_tokens - tpos,
6231 instr,
6232 data);
6233
6234 if (!strcmp(tokens[tpos], "metprefetch"))
6235 return instr_metprefetch_translate(p,
6236 action,
6237 &tokens[tpos],
6238 n_tokens - tpos,
6239 instr,
6240 data);
6241
6242 if (!strcmp(tokens[tpos], "meter"))
6243 return instr_meter_translate(p,
6244 action,
6245 &tokens[tpos],
6246 n_tokens - tpos,
6247 instr,
6248 data);
6249
6250 if (!strcmp(tokens[tpos], "table"))
6251 return instr_table_translate(p,
6252 action,
6253 &tokens[tpos],
6254 n_tokens - tpos,
6255 instr,
6256 data);
6257
6258 if (!strcmp(tokens[tpos], "learn"))
6259 return instr_learn_translate(p,
6260 action,
6261 &tokens[tpos],
6262 n_tokens - tpos,
6263 instr,
6264 data);
6265 if (!strcmp(tokens[tpos], "rearm"))
6266 return instr_rearm_translate(p,
6267 action,
6268 &tokens[tpos],
6269 n_tokens - tpos,
6270 instr,
6271 data);
6272
6273 if (!strcmp(tokens[tpos], "forget"))
6274 return instr_forget_translate(p,
6275 action,
6276 &tokens[tpos],
6277 n_tokens - tpos,
6278 instr,
6279 data);
6280
6281 if (!strcmp(tokens[tpos], "extern"))
6282 return instr_extern_translate(p,
6283 action,
6284 &tokens[tpos],
6285 n_tokens - tpos,
6286 instr,
6287 data);
6288
6289 if (!strcmp(tokens[tpos], "hash"))
6290 return instr_hash_translate(p,
6291 action,
6292 &tokens[tpos],
6293 n_tokens - tpos,
6294 instr,
6295 data);
6296
6297 if (!strcmp(tokens[tpos], "jmp"))
6298 return instr_jmp_translate(p,
6299 action,
6300 &tokens[tpos],
6301 n_tokens - tpos,
6302 instr,
6303 data);
6304
6305 if (!strcmp(tokens[tpos], "jmpv"))
6306 return instr_jmp_valid_translate(p,
6307 action,
6308 &tokens[tpos],
6309 n_tokens - tpos,
6310 instr,
6311 data);
6312
6313 if (!strcmp(tokens[tpos], "jmpnv"))
6314 return instr_jmp_invalid_translate(p,
6315 action,
6316 &tokens[tpos],
6317 n_tokens - tpos,
6318 instr,
6319 data);
6320
6321 if (!strcmp(tokens[tpos], "jmph"))
6322 return instr_jmp_hit_translate(p,
6323 action,
6324 &tokens[tpos],
6325 n_tokens - tpos,
6326 instr,
6327 data);
6328
6329 if (!strcmp(tokens[tpos], "jmpnh"))
6330 return instr_jmp_miss_translate(p,
6331 action,
6332 &tokens[tpos],
6333 n_tokens - tpos,
6334 instr,
6335 data);
6336
6337 if (!strcmp(tokens[tpos], "jmpa"))
6338 return instr_jmp_action_hit_translate(p,
6339 action,
6340 &tokens[tpos],
6341 n_tokens - tpos,
6342 instr,
6343 data);
6344
6345 if (!strcmp(tokens[tpos], "jmpna"))
6346 return instr_jmp_action_miss_translate(p,
6347 action,
6348 &tokens[tpos],
6349 n_tokens - tpos,
6350 instr,
6351 data);
6352
6353 if (!strcmp(tokens[tpos], "jmpeq"))
6354 return instr_jmp_eq_translate(p,
6355 action,
6356 &tokens[tpos],
6357 n_tokens - tpos,
6358 instr,
6359 data);
6360
6361 if (!strcmp(tokens[tpos], "jmpneq"))
6362 return instr_jmp_neq_translate(p,
6363 action,
6364 &tokens[tpos],
6365 n_tokens - tpos,
6366 instr,
6367 data);
6368
6369 if (!strcmp(tokens[tpos], "jmplt"))
6370 return instr_jmp_lt_translate(p,
6371 action,
6372 &tokens[tpos],
6373 n_tokens - tpos,
6374 instr,
6375 data);
6376
6377 if (!strcmp(tokens[tpos], "jmpgt"))
6378 return instr_jmp_gt_translate(p,
6379 action,
6380 &tokens[tpos],
6381 n_tokens - tpos,
6382 instr,
6383 data);
6384
6385 if (!strcmp(tokens[tpos], "return"))
6386 return instr_return_translate(p,
6387 action,
6388 &tokens[tpos],
6389 n_tokens - tpos,
6390 instr,
6391 data);
6392
6393 return -EINVAL;
6394}
6395
6396static struct instruction_data *
6397label_find(struct instruction_data *data, uint32_t n, const char *label)
6398{
6399 uint32_t i;
6400
6401 for (i = 0; i < n; i++)
6402 if (!strcmp(label, data[i].label))
6403 return &data[i];
6404
6405 return NULL;
6406}
6407
6408static uint32_t
6409label_is_used(struct instruction_data *data, uint32_t n, const char *label)
6410{
6411 uint32_t count = 0, i;
6412
6413 if (!label[0])
6414 return 0;
6415
6416 for (i = 0; i < n; i++)
6417 if (!strcmp(label, data[i].jmp_label))
6418 count++;
6419
6420 return count;
6421}
6422
6423static int
6424instr_label_check(struct instruction_data *instruction_data,
6425 uint32_t n_instructions)
6426{
6427 uint32_t i;
6428
6429
6430 for (i = 0; i < n_instructions; i++) {
6431 struct instruction_data *data = &instruction_data[i];
6432 char *label = data->label;
6433 uint32_t j;
6434
6435 if (!label[0])
6436 continue;
6437
6438 for (j = i + 1; j < n_instructions; j++)
6439 CHECK(strcmp(label, instruction_data[j].label), EINVAL);
6440 }
6441
6442
6443 for (i = 0; i < n_instructions; i++) {
6444 struct instruction_data *data = &instruction_data[i];
6445 char *label = data->label;
6446 char *jmp_label = data->jmp_label;
6447
6448
6449 if (!label[0] || !jmp_label[0])
6450 continue;
6451
6452 CHECK(strcmp(label, jmp_label), EINVAL);
6453 }
6454
6455
6456 for (i = 0; i < n_instructions; i++) {
6457 struct instruction_data *data = &instruction_data[i];
6458 char *label = data->label;
6459
6460 data->n_users = label_is_used(instruction_data,
6461 n_instructions,
6462 label);
6463 }
6464
6465 return 0;
6466}
6467
6468static int
6469instr_jmp_resolve(struct instruction *instructions,
6470 struct instruction_data *instruction_data,
6471 uint32_t n_instructions)
6472{
6473 uint32_t i;
6474
6475 for (i = 0; i < n_instructions; i++) {
6476 struct instruction *instr = &instructions[i];
6477 struct instruction_data *data = &instruction_data[i];
6478 struct instruction_data *found;
6479
6480 if (!instruction_is_jmp(instr))
6481 continue;
6482
6483 found = label_find(instruction_data,
6484 n_instructions,
6485 data->jmp_label);
6486 CHECK(found, EINVAL);
6487
6488 instr->jmp.ip = &instructions[found - instruction_data];
6489 }
6490
6491 return 0;
6492}
6493
6494static int
6495instr_verify(struct rte_swx_pipeline *p __rte_unused,
6496 struct action *a,
6497 struct instruction *instr,
6498 struct instruction_data *data __rte_unused,
6499 uint32_t n_instructions)
6500{
6501 if (!a) {
6502 enum instruction_type type;
6503 uint32_t i;
6504
6505
6506 CHECK(instr[0].type == INSTR_RX, EINVAL);
6507
6508
6509 for (i = 0; i < n_instructions; i++) {
6510 type = instr[i].type;
6511
6512 if (instruction_is_tx(type))
6513 break;
6514 }
6515 CHECK(i < n_instructions, EINVAL);
6516
6517
6518
6519
6520 type = instr[n_instructions - 1].type;
6521 CHECK(instruction_is_tx(type) || (type == INSTR_JMP), EINVAL);
6522 }
6523
6524 if (a) {
6525 enum instruction_type type;
6526 uint32_t i;
6527
6528
6529 for (i = 0; i < n_instructions; i++) {
6530 type = instr[i].type;
6531
6532 if ((type == INSTR_RETURN) || instruction_is_tx(type))
6533 break;
6534 }
6535 CHECK(i < n_instructions, EINVAL);
6536 }
6537
6538 return 0;
6539}
6540
6541static uint32_t
6542instr_compact(struct instruction *instructions,
6543 struct instruction_data *instruction_data,
6544 uint32_t n_instructions)
6545{
6546 uint32_t i, pos = 0;
6547
6548
6549 for (i = 0; i < n_instructions; i++) {
6550 struct instruction *instr = &instructions[i];
6551 struct instruction_data *data = &instruction_data[i];
6552
6553 if (data->invalid)
6554 continue;
6555
6556 if (i != pos) {
6557 memcpy(&instructions[pos], instr, sizeof(*instr));
6558 memcpy(&instruction_data[pos], data, sizeof(*data));
6559 }
6560
6561 pos++;
6562 }
6563
6564 return pos;
6565}
6566
6567static int
6568instr_pattern_extract_many_search(struct instruction *instr,
6569 struct instruction_data *data,
6570 uint32_t n_instr,
6571 uint32_t *n_pattern_instr)
6572{
6573 uint32_t i;
6574
6575 for (i = 0; i < n_instr; i++) {
6576 if (data[i].invalid)
6577 break;
6578
6579 if (instr[i].type != INSTR_HDR_EXTRACT)
6580 break;
6581
6582 if (i == RTE_DIM(instr->io.hdr.header_id))
6583 break;
6584
6585 if (i && data[i].n_users)
6586 break;
6587 }
6588
6589 if (i < 2)
6590 return 0;
6591
6592 *n_pattern_instr = i;
6593 return 1;
6594}
6595
6596static void
6597instr_pattern_extract_many_replace(struct instruction *instr,
6598 struct instruction_data *data,
6599 uint32_t n_instr)
6600{
6601 uint32_t i;
6602
6603 for (i = 1; i < n_instr; i++) {
6604 instr[0].type++;
6605 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
6606 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
6607 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
6608
6609 data[i].invalid = 1;
6610 }
6611}
6612
6613static uint32_t
6614instr_pattern_extract_many_optimize(struct instruction *instructions,
6615 struct instruction_data *instruction_data,
6616 uint32_t n_instructions)
6617{
6618 uint32_t i;
6619
6620 for (i = 0; i < n_instructions; ) {
6621 struct instruction *instr = &instructions[i];
6622 struct instruction_data *data = &instruction_data[i];
6623 uint32_t n_instr = 0;
6624 int detected;
6625
6626
6627 detected = instr_pattern_extract_many_search(instr,
6628 data,
6629 n_instructions - i,
6630 &n_instr);
6631 if (detected) {
6632 instr_pattern_extract_many_replace(instr,
6633 data,
6634 n_instr);
6635 i += n_instr;
6636 continue;
6637 }
6638
6639
6640 i++;
6641 }
6642
6643
6644 n_instructions = instr_compact(instructions,
6645 instruction_data,
6646 n_instructions);
6647
6648 return n_instructions;
6649}
6650
6651static int
6652instr_pattern_emit_many_tx_search(struct instruction *instr,
6653 struct instruction_data *data,
6654 uint32_t n_instr,
6655 uint32_t *n_pattern_instr)
6656{
6657 uint32_t i;
6658
6659 for (i = 0; i < n_instr; i++) {
6660 if (data[i].invalid)
6661 break;
6662
6663 if (instr[i].type != INSTR_HDR_EMIT)
6664 break;
6665
6666 if (i == RTE_DIM(instr->io.hdr.header_id))
6667 break;
6668
6669 if (i && data[i].n_users)
6670 break;
6671 }
6672
6673 if (!i)
6674 return 0;
6675
6676 if (instr[i].type != INSTR_TX)
6677 return 0;
6678
6679 if (data[i].n_users)
6680 return 0;
6681
6682 i++;
6683
6684 *n_pattern_instr = i;
6685 return 1;
6686}
6687
6688static void
6689instr_pattern_emit_many_tx_replace(struct instruction *instr,
6690 struct instruction_data *data,
6691 uint32_t n_instr)
6692{
6693 uint32_t i;
6694
6695
6696 for (i = 1; i < n_instr - 1; i++) {
6697 instr[0].type++;
6698 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
6699 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
6700 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
6701
6702 data[i].invalid = 1;
6703 }
6704
6705
6706 instr[0].type++;
6707 instr[0].io.io.offset = instr[i].io.io.offset;
6708 instr[0].io.io.n_bits = instr[i].io.io.n_bits;
6709 data[i].invalid = 1;
6710}
6711
6712static uint32_t
6713instr_pattern_emit_many_tx_optimize(struct instruction *instructions,
6714 struct instruction_data *instruction_data,
6715 uint32_t n_instructions)
6716{
6717 uint32_t i;
6718
6719 for (i = 0; i < n_instructions; ) {
6720 struct instruction *instr = &instructions[i];
6721 struct instruction_data *data = &instruction_data[i];
6722 uint32_t n_instr = 0;
6723 int detected;
6724
6725
6726 detected = instr_pattern_emit_many_tx_search(instr,
6727 data,
6728 n_instructions - i,
6729 &n_instr);
6730 if (detected) {
6731 instr_pattern_emit_many_tx_replace(instr,
6732 data,
6733 n_instr);
6734 i += n_instr;
6735 continue;
6736 }
6737
6738
6739 i++;
6740 }
6741
6742
6743 n_instructions = instr_compact(instructions,
6744 instruction_data,
6745 n_instructions);
6746
6747 return n_instructions;
6748}
6749
6750static uint32_t
6751action_arg_src_mov_count(struct action *a,
6752 uint32_t arg_id,
6753 struct instruction *instructions,
6754 struct instruction_data *instruction_data,
6755 uint32_t n_instructions);
6756
6757static int
6758instr_pattern_validate_mov_all_search(struct rte_swx_pipeline *p,
6759 struct action *a,
6760 struct instruction *instr,
6761 struct instruction_data *data,
6762 uint32_t n_instr,
6763 struct instruction *instructions,
6764 struct instruction_data *instruction_data,
6765 uint32_t n_instructions,
6766 uint32_t *n_pattern_instr)
6767{
6768 struct header *h;
6769 uint32_t src_field_id, i, j;
6770
6771
6772 if (!a || !a->st)
6773 return 0;
6774
6775
6776 if (data[0].invalid ||
6777 (instr[0].type != INSTR_HDR_VALIDATE) ||
6778 (n_instr < 2) ||
6779 data[1].invalid ||
6780 (instr[1].type != INSTR_MOV_HM) ||
6781 instr[1].mov.src.struct_id)
6782 return 0;
6783
6784 h = header_find_by_struct_id(p, instr[0].valid.struct_id);
6785 if (!h ||
6786 h->st->var_size ||
6787 (n_instr < 1 + h->st->n_fields))
6788 return 0;
6789
6790 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
6791 if (instr[1].mov.src.offset == a->st->fields[src_field_id].offset / 8)
6792 break;
6793
6794 if (src_field_id + h->st->n_fields > a->st->n_fields)
6795 return 0;
6796
6797
6798 for (i = 0; i < h->st->n_fields; i++)
6799 if (data[1 + i].invalid ||
6800 data[1 + i].n_users ||
6801 (instr[1 + i].type != INSTR_MOV_HM) ||
6802 (instr[1 + i].mov.dst.struct_id != h->struct_id) ||
6803 (instr[1 + i].mov.dst.offset != h->st->fields[i].offset / 8) ||
6804 (instr[1 + i].mov.dst.n_bits != h->st->fields[i].n_bits) ||
6805 instr[1 + i].mov.src.struct_id ||
6806 (instr[1 + i].mov.src.offset != a->st->fields[src_field_id + i].offset / 8) ||
6807 (instr[1 + i].mov.src.n_bits != a->st->fields[src_field_id + i].n_bits) ||
6808 (instr[1 + i].mov.dst.n_bits != instr[1 + i].mov.src.n_bits))
6809 return 0;
6810
6811
6812
6813
6814 for (j = src_field_id; j < src_field_id + h->st->n_fields; j++) {
6815 uint32_t n_users;
6816
6817 n_users = action_arg_src_mov_count(a,
6818 j,
6819 instructions,
6820 instruction_data,
6821 n_instructions);
6822 if (n_users > 1)
6823 return 0;
6824 }
6825
6826 *n_pattern_instr = 1 + h->st->n_fields;
6827 return 1;
6828}
6829
6830static void
6831instr_pattern_validate_mov_all_replace(struct rte_swx_pipeline *p,
6832 struct action *a,
6833 struct instruction *instr,
6834 struct instruction_data *data,
6835 uint32_t n_instr)
6836{
6837 struct header *h;
6838 uint32_t src_field_id, src_offset, i;
6839
6840
6841 h = header_find_by_struct_id(p, instr[1].mov.dst.struct_id);
6842 if (!h)
6843 return;
6844
6845 src_offset = instr[1].mov.src.offset;
6846
6847 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
6848 if (src_offset == a->st->fields[src_field_id].offset / 8)
6849 break;
6850
6851
6852 instr[0].type = INSTR_DMA_HT;
6853 instr[0].dma.dst.header_id[0] = h->id;
6854 instr[0].dma.dst.struct_id[0] = h->struct_id;
6855 instr[0].dma.src.offset[0] = (uint8_t)src_offset;
6856 instr[0].dma.n_bytes[0] = h->st->n_bits / 8;
6857
6858 for (i = 1; i < n_instr; i++)
6859 data[i].invalid = 1;
6860
6861
6862 for (i = 0; i < h->st->n_fields; i++)
6863 a->args_endianness[src_field_id + i] = 1;
6864}
6865
6866static uint32_t
6867instr_pattern_validate_mov_all_optimize(struct rte_swx_pipeline *p,
6868 struct action *a,
6869 struct instruction *instructions,
6870 struct instruction_data *instruction_data,
6871 uint32_t n_instructions)
6872{
6873 uint32_t i;
6874
6875 if (!a || !a->st)
6876 return n_instructions;
6877
6878 for (i = 0; i < n_instructions; ) {
6879 struct instruction *instr = &instructions[i];
6880 struct instruction_data *data = &instruction_data[i];
6881 uint32_t n_instr = 0;
6882 int detected;
6883
6884
6885 detected = instr_pattern_validate_mov_all_search(p,
6886 a,
6887 instr,
6888 data,
6889 n_instructions - i,
6890 instructions,
6891 instruction_data,
6892 n_instructions,
6893 &n_instr);
6894 if (detected) {
6895 instr_pattern_validate_mov_all_replace(p, a, instr, data, n_instr);
6896 i += n_instr;
6897 continue;
6898 }
6899
6900
6901 i++;
6902 }
6903
6904
6905 n_instructions = instr_compact(instructions,
6906 instruction_data,
6907 n_instructions);
6908
6909 return n_instructions;
6910}
6911
6912static int
6913instr_pattern_dma_many_search(struct instruction *instr,
6914 struct instruction_data *data,
6915 uint32_t n_instr,
6916 uint32_t *n_pattern_instr)
6917{
6918 uint32_t i;
6919
6920 for (i = 0; i < n_instr; i++) {
6921 if (data[i].invalid)
6922 break;
6923
6924 if (instr[i].type != INSTR_DMA_HT)
6925 break;
6926
6927 if (i == RTE_DIM(instr->dma.dst.header_id))
6928 break;
6929
6930 if (i && data[i].n_users)
6931 break;
6932 }
6933
6934 if (i < 2)
6935 return 0;
6936
6937 *n_pattern_instr = i;
6938 return 1;
6939}
6940
6941static void
6942instr_pattern_dma_many_replace(struct instruction *instr,
6943 struct instruction_data *data,
6944 uint32_t n_instr)
6945{
6946 uint32_t i;
6947
6948 for (i = 1; i < n_instr; i++) {
6949 instr[0].type++;
6950 instr[0].dma.dst.header_id[i] = instr[i].dma.dst.header_id[0];
6951 instr[0].dma.dst.struct_id[i] = instr[i].dma.dst.struct_id[0];
6952 instr[0].dma.src.offset[i] = instr[i].dma.src.offset[0];
6953 instr[0].dma.n_bytes[i] = instr[i].dma.n_bytes[0];
6954
6955 data[i].invalid = 1;
6956 }
6957}
6958
6959static uint32_t
6960instr_pattern_dma_many_optimize(struct instruction *instructions,
6961 struct instruction_data *instruction_data,
6962 uint32_t n_instructions)
6963{
6964 uint32_t i;
6965
6966 for (i = 0; i < n_instructions; ) {
6967 struct instruction *instr = &instructions[i];
6968 struct instruction_data *data = &instruction_data[i];
6969 uint32_t n_instr = 0;
6970 int detected;
6971
6972
6973 detected = instr_pattern_dma_many_search(instr,
6974 data,
6975 n_instructions - i,
6976 &n_instr);
6977 if (detected) {
6978 instr_pattern_dma_many_replace(instr, data, n_instr);
6979 i += n_instr;
6980 continue;
6981 }
6982
6983
6984 i++;
6985 }
6986
6987
6988 n_instructions = instr_compact(instructions,
6989 instruction_data,
6990 n_instructions);
6991
6992 return n_instructions;
6993}
6994
6995static uint32_t
6996instr_optimize(struct rte_swx_pipeline *p,
6997 struct action *a,
6998 struct instruction *instructions,
6999 struct instruction_data *instruction_data,
7000 uint32_t n_instructions)
7001{
7002
7003 n_instructions = instr_pattern_extract_many_optimize(instructions,
7004 instruction_data,
7005 n_instructions);
7006
7007
7008 n_instructions = instr_pattern_emit_many_tx_optimize(instructions,
7009 instruction_data,
7010 n_instructions);
7011
7012
7013 n_instructions = instr_pattern_validate_mov_all_optimize(p,
7014 a,
7015 instructions,
7016 instruction_data,
7017 n_instructions);
7018
7019
7020 n_instructions = instr_pattern_dma_many_optimize(instructions,
7021 instruction_data,
7022 n_instructions);
7023
7024 return n_instructions;
7025}
7026
7027static int
7028instruction_config(struct rte_swx_pipeline *p,
7029 struct action *a,
7030 const char **instructions,
7031 uint32_t n_instructions)
7032{
7033 struct instruction *instr = NULL;
7034 struct instruction_data *data = NULL;
7035 int err = 0;
7036 uint32_t i;
7037
7038 CHECK(n_instructions, EINVAL);
7039 CHECK(instructions, EINVAL);
7040 for (i = 0; i < n_instructions; i++)
7041 CHECK_INSTRUCTION(instructions[i], EINVAL);
7042
7043
7044 instr = calloc(n_instructions, sizeof(struct instruction));
7045 if (!instr) {
7046 err = -ENOMEM;
7047 goto error;
7048 }
7049
7050 data = calloc(n_instructions, sizeof(struct instruction_data));
7051 if (!data) {
7052 err = -ENOMEM;
7053 goto error;
7054 }
7055
7056 for (i = 0; i < n_instructions; i++) {
7057 char *string = strdup(instructions[i]);
7058 if (!string) {
7059 err = -ENOMEM;
7060 goto error;
7061 }
7062
7063 err = instr_translate(p, a, string, &instr[i], &data[i]);
7064 if (err) {
7065 free(string);
7066 goto error;
7067 }
7068
7069 free(string);
7070 }
7071
7072 err = instr_label_check(data, n_instructions);
7073 if (err)
7074 goto error;
7075
7076 err = instr_verify(p, a, instr, data, n_instructions);
7077 if (err)
7078 goto error;
7079
7080 n_instructions = instr_optimize(p, a, instr, data, n_instructions);
7081
7082 err = instr_jmp_resolve(instr, data, n_instructions);
7083 if (err)
7084 goto error;
7085
7086 if (a) {
7087 a->instructions = instr;
7088 a->instruction_data = data;
7089 a->n_instructions = n_instructions;
7090 } else {
7091 p->instructions = instr;
7092 p->instruction_data = data;
7093 p->n_instructions = n_instructions;
7094 }
7095
7096 return 0;
7097
7098error:
7099 free(data);
7100 free(instr);
7101 return err;
7102}
7103
7104static instr_exec_t instruction_table[] = {
7105 [INSTR_RX] = instr_rx_exec,
7106 [INSTR_TX] = instr_tx_exec,
7107 [INSTR_TX_I] = instr_tx_i_exec,
7108 [INSTR_DROP] = instr_drop_exec,
7109 [INSTR_MIRROR] = instr_mirror_exec,
7110 [INSTR_RECIRCULATE] = instr_recirculate_exec,
7111 [INSTR_RECIRCID] = instr_recircid_exec,
7112
7113 [INSTR_HDR_EXTRACT] = instr_hdr_extract_exec,
7114 [INSTR_HDR_EXTRACT2] = instr_hdr_extract2_exec,
7115 [INSTR_HDR_EXTRACT3] = instr_hdr_extract3_exec,
7116 [INSTR_HDR_EXTRACT4] = instr_hdr_extract4_exec,
7117 [INSTR_HDR_EXTRACT5] = instr_hdr_extract5_exec,
7118 [INSTR_HDR_EXTRACT6] = instr_hdr_extract6_exec,
7119 [INSTR_HDR_EXTRACT7] = instr_hdr_extract7_exec,
7120 [INSTR_HDR_EXTRACT8] = instr_hdr_extract8_exec,
7121 [INSTR_HDR_EXTRACT_M] = instr_hdr_extract_m_exec,
7122 [INSTR_HDR_LOOKAHEAD] = instr_hdr_lookahead_exec,
7123
7124 [INSTR_HDR_EMIT] = instr_hdr_emit_exec,
7125 [INSTR_HDR_EMIT_TX] = instr_hdr_emit_tx_exec,
7126 [INSTR_HDR_EMIT2_TX] = instr_hdr_emit2_tx_exec,
7127 [INSTR_HDR_EMIT3_TX] = instr_hdr_emit3_tx_exec,
7128 [INSTR_HDR_EMIT4_TX] = instr_hdr_emit4_tx_exec,
7129 [INSTR_HDR_EMIT5_TX] = instr_hdr_emit5_tx_exec,
7130 [INSTR_HDR_EMIT6_TX] = instr_hdr_emit6_tx_exec,
7131 [INSTR_HDR_EMIT7_TX] = instr_hdr_emit7_tx_exec,
7132 [INSTR_HDR_EMIT8_TX] = instr_hdr_emit8_tx_exec,
7133
7134 [INSTR_HDR_VALIDATE] = instr_hdr_validate_exec,
7135 [INSTR_HDR_INVALIDATE] = instr_hdr_invalidate_exec,
7136
7137 [INSTR_MOV] = instr_mov_exec,
7138 [INSTR_MOV_MH] = instr_mov_mh_exec,
7139 [INSTR_MOV_HM] = instr_mov_hm_exec,
7140 [INSTR_MOV_HH] = instr_mov_hh_exec,
7141 [INSTR_MOV_I] = instr_mov_i_exec,
7142
7143 [INSTR_DMA_HT] = instr_dma_ht_exec,
7144 [INSTR_DMA_HT2] = instr_dma_ht2_exec,
7145 [INSTR_DMA_HT3] = instr_dma_ht3_exec,
7146 [INSTR_DMA_HT4] = instr_dma_ht4_exec,
7147 [INSTR_DMA_HT5] = instr_dma_ht5_exec,
7148 [INSTR_DMA_HT6] = instr_dma_ht6_exec,
7149 [INSTR_DMA_HT7] = instr_dma_ht7_exec,
7150 [INSTR_DMA_HT8] = instr_dma_ht8_exec,
7151
7152 [INSTR_ALU_ADD] = instr_alu_add_exec,
7153 [INSTR_ALU_ADD_MH] = instr_alu_add_mh_exec,
7154 [INSTR_ALU_ADD_HM] = instr_alu_add_hm_exec,
7155 [INSTR_ALU_ADD_HH] = instr_alu_add_hh_exec,
7156 [INSTR_ALU_ADD_MI] = instr_alu_add_mi_exec,
7157 [INSTR_ALU_ADD_HI] = instr_alu_add_hi_exec,
7158
7159 [INSTR_ALU_SUB] = instr_alu_sub_exec,
7160 [INSTR_ALU_SUB_MH] = instr_alu_sub_mh_exec,
7161 [INSTR_ALU_SUB_HM] = instr_alu_sub_hm_exec,
7162 [INSTR_ALU_SUB_HH] = instr_alu_sub_hh_exec,
7163 [INSTR_ALU_SUB_MI] = instr_alu_sub_mi_exec,
7164 [INSTR_ALU_SUB_HI] = instr_alu_sub_hi_exec,
7165
7166 [INSTR_ALU_CKADD_FIELD] = instr_alu_ckadd_field_exec,
7167 [INSTR_ALU_CKADD_STRUCT] = instr_alu_ckadd_struct_exec,
7168 [INSTR_ALU_CKADD_STRUCT20] = instr_alu_ckadd_struct20_exec,
7169 [INSTR_ALU_CKSUB_FIELD] = instr_alu_cksub_field_exec,
7170
7171 [INSTR_ALU_AND] = instr_alu_and_exec,
7172 [INSTR_ALU_AND_MH] = instr_alu_and_mh_exec,
7173 [INSTR_ALU_AND_HM] = instr_alu_and_hm_exec,
7174 [INSTR_ALU_AND_HH] = instr_alu_and_hh_exec,
7175 [INSTR_ALU_AND_I] = instr_alu_and_i_exec,
7176
7177 [INSTR_ALU_OR] = instr_alu_or_exec,
7178 [INSTR_ALU_OR_MH] = instr_alu_or_mh_exec,
7179 [INSTR_ALU_OR_HM] = instr_alu_or_hm_exec,
7180 [INSTR_ALU_OR_HH] = instr_alu_or_hh_exec,
7181 [INSTR_ALU_OR_I] = instr_alu_or_i_exec,
7182
7183 [INSTR_ALU_XOR] = instr_alu_xor_exec,
7184 [INSTR_ALU_XOR_MH] = instr_alu_xor_mh_exec,
7185 [INSTR_ALU_XOR_HM] = instr_alu_xor_hm_exec,
7186 [INSTR_ALU_XOR_HH] = instr_alu_xor_hh_exec,
7187 [INSTR_ALU_XOR_I] = instr_alu_xor_i_exec,
7188
7189 [INSTR_ALU_SHL] = instr_alu_shl_exec,
7190 [INSTR_ALU_SHL_MH] = instr_alu_shl_mh_exec,
7191 [INSTR_ALU_SHL_HM] = instr_alu_shl_hm_exec,
7192 [INSTR_ALU_SHL_HH] = instr_alu_shl_hh_exec,
7193 [INSTR_ALU_SHL_MI] = instr_alu_shl_mi_exec,
7194 [INSTR_ALU_SHL_HI] = instr_alu_shl_hi_exec,
7195
7196 [INSTR_ALU_SHR] = instr_alu_shr_exec,
7197 [INSTR_ALU_SHR_MH] = instr_alu_shr_mh_exec,
7198 [INSTR_ALU_SHR_HM] = instr_alu_shr_hm_exec,
7199 [INSTR_ALU_SHR_HH] = instr_alu_shr_hh_exec,
7200 [INSTR_ALU_SHR_MI] = instr_alu_shr_mi_exec,
7201 [INSTR_ALU_SHR_HI] = instr_alu_shr_hi_exec,
7202
7203 [INSTR_REGPREFETCH_RH] = instr_regprefetch_rh_exec,
7204 [INSTR_REGPREFETCH_RM] = instr_regprefetch_rm_exec,
7205 [INSTR_REGPREFETCH_RI] = instr_regprefetch_ri_exec,
7206
7207 [INSTR_REGRD_HRH] = instr_regrd_hrh_exec,
7208 [INSTR_REGRD_HRM] = instr_regrd_hrm_exec,
7209 [INSTR_REGRD_MRH] = instr_regrd_mrh_exec,
7210 [INSTR_REGRD_MRM] = instr_regrd_mrm_exec,
7211 [INSTR_REGRD_HRI] = instr_regrd_hri_exec,
7212 [INSTR_REGRD_MRI] = instr_regrd_mri_exec,
7213
7214 [INSTR_REGWR_RHH] = instr_regwr_rhh_exec,
7215 [INSTR_REGWR_RHM] = instr_regwr_rhm_exec,
7216 [INSTR_REGWR_RMH] = instr_regwr_rmh_exec,
7217 [INSTR_REGWR_RMM] = instr_regwr_rmm_exec,
7218 [INSTR_REGWR_RHI] = instr_regwr_rhi_exec,
7219 [INSTR_REGWR_RMI] = instr_regwr_rmi_exec,
7220 [INSTR_REGWR_RIH] = instr_regwr_rih_exec,
7221 [INSTR_REGWR_RIM] = instr_regwr_rim_exec,
7222 [INSTR_REGWR_RII] = instr_regwr_rii_exec,
7223
7224 [INSTR_REGADD_RHH] = instr_regadd_rhh_exec,
7225 [INSTR_REGADD_RHM] = instr_regadd_rhm_exec,
7226 [INSTR_REGADD_RMH] = instr_regadd_rmh_exec,
7227 [INSTR_REGADD_RMM] = instr_regadd_rmm_exec,
7228 [INSTR_REGADD_RHI] = instr_regadd_rhi_exec,
7229 [INSTR_REGADD_RMI] = instr_regadd_rmi_exec,
7230 [INSTR_REGADD_RIH] = instr_regadd_rih_exec,
7231 [INSTR_REGADD_RIM] = instr_regadd_rim_exec,
7232 [INSTR_REGADD_RII] = instr_regadd_rii_exec,
7233
7234 [INSTR_METPREFETCH_H] = instr_metprefetch_h_exec,
7235 [INSTR_METPREFETCH_M] = instr_metprefetch_m_exec,
7236 [INSTR_METPREFETCH_I] = instr_metprefetch_i_exec,
7237
7238 [INSTR_METER_HHM] = instr_meter_hhm_exec,
7239 [INSTR_METER_HHI] = instr_meter_hhi_exec,
7240 [INSTR_METER_HMM] = instr_meter_hmm_exec,
7241 [INSTR_METER_HMI] = instr_meter_hmi_exec,
7242 [INSTR_METER_MHM] = instr_meter_mhm_exec,
7243 [INSTR_METER_MHI] = instr_meter_mhi_exec,
7244 [INSTR_METER_MMM] = instr_meter_mmm_exec,
7245 [INSTR_METER_MMI] = instr_meter_mmi_exec,
7246 [INSTR_METER_IHM] = instr_meter_ihm_exec,
7247 [INSTR_METER_IHI] = instr_meter_ihi_exec,
7248 [INSTR_METER_IMM] = instr_meter_imm_exec,
7249 [INSTR_METER_IMI] = instr_meter_imi_exec,
7250
7251 [INSTR_TABLE] = instr_table_exec,
7252 [INSTR_TABLE_AF] = instr_table_af_exec,
7253 [INSTR_SELECTOR] = instr_selector_exec,
7254 [INSTR_LEARNER] = instr_learner_exec,
7255 [INSTR_LEARNER_AF] = instr_learner_af_exec,
7256 [INSTR_LEARNER_LEARN] = instr_learn_exec,
7257 [INSTR_LEARNER_REARM] = instr_rearm_exec,
7258 [INSTR_LEARNER_REARM_NEW] = instr_rearm_new_exec,
7259 [INSTR_LEARNER_FORGET] = instr_forget_exec,
7260 [INSTR_EXTERN_OBJ] = instr_extern_obj_exec,
7261 [INSTR_EXTERN_FUNC] = instr_extern_func_exec,
7262 [INSTR_HASH_FUNC] = instr_hash_func_exec,
7263
7264 [INSTR_JMP] = instr_jmp_exec,
7265 [INSTR_JMP_VALID] = instr_jmp_valid_exec,
7266 [INSTR_JMP_INVALID] = instr_jmp_invalid_exec,
7267 [INSTR_JMP_HIT] = instr_jmp_hit_exec,
7268 [INSTR_JMP_MISS] = instr_jmp_miss_exec,
7269 [INSTR_JMP_ACTION_HIT] = instr_jmp_action_hit_exec,
7270 [INSTR_JMP_ACTION_MISS] = instr_jmp_action_miss_exec,
7271
7272 [INSTR_JMP_EQ] = instr_jmp_eq_exec,
7273 [INSTR_JMP_EQ_MH] = instr_jmp_eq_mh_exec,
7274 [INSTR_JMP_EQ_HM] = instr_jmp_eq_hm_exec,
7275 [INSTR_JMP_EQ_HH] = instr_jmp_eq_hh_exec,
7276 [INSTR_JMP_EQ_I] = instr_jmp_eq_i_exec,
7277
7278 [INSTR_JMP_NEQ] = instr_jmp_neq_exec,
7279 [INSTR_JMP_NEQ_MH] = instr_jmp_neq_mh_exec,
7280 [INSTR_JMP_NEQ_HM] = instr_jmp_neq_hm_exec,
7281 [INSTR_JMP_NEQ_HH] = instr_jmp_neq_hh_exec,
7282 [INSTR_JMP_NEQ_I] = instr_jmp_neq_i_exec,
7283
7284 [INSTR_JMP_LT] = instr_jmp_lt_exec,
7285 [INSTR_JMP_LT_MH] = instr_jmp_lt_mh_exec,
7286 [INSTR_JMP_LT_HM] = instr_jmp_lt_hm_exec,
7287 [INSTR_JMP_LT_HH] = instr_jmp_lt_hh_exec,
7288 [INSTR_JMP_LT_MI] = instr_jmp_lt_mi_exec,
7289 [INSTR_JMP_LT_HI] = instr_jmp_lt_hi_exec,
7290
7291 [INSTR_JMP_GT] = instr_jmp_gt_exec,
7292 [INSTR_JMP_GT_MH] = instr_jmp_gt_mh_exec,
7293 [INSTR_JMP_GT_HM] = instr_jmp_gt_hm_exec,
7294 [INSTR_JMP_GT_HH] = instr_jmp_gt_hh_exec,
7295 [INSTR_JMP_GT_MI] = instr_jmp_gt_mi_exec,
7296 [INSTR_JMP_GT_HI] = instr_jmp_gt_hi_exec,
7297
7298 [INSTR_RETURN] = instr_return_exec,
7299};
7300
7301static int
7302instruction_table_build(struct rte_swx_pipeline *p)
7303{
7304 p->instruction_table = calloc(RTE_SWX_PIPELINE_INSTRUCTION_TABLE_SIZE_MAX,
7305 sizeof(struct instr_exec_t *));
7306 if (!p->instruction_table)
7307 return -EINVAL;
7308
7309 memcpy(p->instruction_table, instruction_table, sizeof(instruction_table));
7310
7311 return 0;
7312}
7313
7314static void
7315instruction_table_build_free(struct rte_swx_pipeline *p)
7316{
7317 if (!p->instruction_table)
7318 return;
7319
7320 free(p->instruction_table);
7321 p->instruction_table = NULL;
7322}
7323
7324static void
7325instruction_table_free(struct rte_swx_pipeline *p)
7326{
7327 instruction_table_build_free(p);
7328}
7329
7330static inline void
7331instr_exec(struct rte_swx_pipeline *p)
7332{
7333 struct thread *t = &p->threads[p->thread_id];
7334 struct instruction *ip = t->ip;
7335 instr_exec_t instr = p->instruction_table[ip->type];
7336
7337 instr(p);
7338}
7339
7340
7341
7342
7343static struct action *
7344action_find(struct rte_swx_pipeline *p, const char *name)
7345{
7346 struct action *elem;
7347
7348 if (!name)
7349 return NULL;
7350
7351 TAILQ_FOREACH(elem, &p->actions, node)
7352 if (strcmp(elem->name, name) == 0)
7353 return elem;
7354
7355 return NULL;
7356}
7357
7358static struct action *
7359action_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7360{
7361 struct action *action = NULL;
7362
7363 TAILQ_FOREACH(action, &p->actions, node)
7364 if (action->id == id)
7365 return action;
7366
7367 return NULL;
7368}
7369
7370static struct field *
7371action_field_find(struct action *a, const char *name)
7372{
7373 return a->st ? struct_type_field_find(a->st, name) : NULL;
7374}
7375
7376static struct field *
7377action_field_parse(struct action *action, const char *name)
7378{
7379 if (name[0] != 't' || name[1] != '.')
7380 return NULL;
7381
7382 return action_field_find(action, &name[2]);
7383}
7384
7385static int
7386action_has_nbo_args(struct action *a)
7387{
7388 uint32_t i;
7389
7390
7391 if (!a->st)
7392 return 0;
7393
7394 for (i = 0; i < a->st->n_fields; i++)
7395 if (a->args_endianness[i])
7396 return 1;
7397
7398 return 0;
7399}
7400
7401static int
7402action_does_learning(struct action *a)
7403{
7404 uint32_t i;
7405
7406 for (i = 0; i < a->n_instructions; i++)
7407 switch (a->instructions[i].type) {
7408 case INSTR_LEARNER_LEARN:
7409 return 1;
7410
7411 case INSTR_LEARNER_FORGET:
7412 return 1;
7413
7414 default:
7415 continue;
7416 }
7417
7418 return 0;
7419}
7420
7421int
7422rte_swx_pipeline_action_config(struct rte_swx_pipeline *p,
7423 const char *name,
7424 const char *args_struct_type_name,
7425 const char **instructions,
7426 uint32_t n_instructions)
7427{
7428 struct struct_type *args_struct_type = NULL;
7429 struct action *a = NULL;
7430 int status = 0;
7431
7432 CHECK(p, EINVAL);
7433
7434 CHECK_NAME(name, EINVAL);
7435 CHECK(!action_find(p, name), EEXIST);
7436
7437 if (args_struct_type_name) {
7438 CHECK_NAME(args_struct_type_name, EINVAL);
7439 args_struct_type = struct_type_find(p, args_struct_type_name);
7440 CHECK(args_struct_type, EINVAL);
7441 CHECK(!args_struct_type->var_size, EINVAL);
7442 }
7443
7444
7445 a = calloc(1, sizeof(struct action));
7446 if (!a) {
7447 status = -ENOMEM;
7448 goto error;
7449 }
7450
7451 if (args_struct_type) {
7452 a->args_endianness = calloc(args_struct_type->n_fields, sizeof(int));
7453 if (!a->args_endianness) {
7454 status = -ENOMEM;
7455 goto error;
7456 }
7457 }
7458
7459
7460 strcpy(a->name, name);
7461 a->st = args_struct_type;
7462 a->id = p->n_actions;
7463
7464
7465 status = instruction_config(p, a, instructions, n_instructions);
7466 if (status)
7467 goto error;
7468
7469
7470 TAILQ_INSERT_TAIL(&p->actions, a, node);
7471 p->n_actions++;
7472
7473 return 0;
7474
7475error:
7476 if (!a)
7477 return status;
7478
7479 free(a->args_endianness);
7480 free(a->instructions);
7481 free(a->instruction_data);
7482 free(a);
7483
7484 return status;
7485}
7486
7487static int
7488action_build(struct rte_swx_pipeline *p)
7489{
7490 struct action *action;
7491
7492
7493 p->action_instructions = calloc(p->n_actions, sizeof(struct instruction *));
7494 CHECK(p->action_instructions, ENOMEM);
7495
7496 TAILQ_FOREACH(action, &p->actions, node)
7497 p->action_instructions[action->id] = action->instructions;
7498
7499
7500 p->action_funcs = calloc(p->n_actions, sizeof(action_func_t));
7501 CHECK(p->action_funcs, ENOMEM);
7502
7503 return 0;
7504}
7505
7506static void
7507action_build_free(struct rte_swx_pipeline *p)
7508{
7509 free(p->action_funcs);
7510 p->action_funcs = NULL;
7511
7512 free(p->action_instructions);
7513 p->action_instructions = NULL;
7514}
7515
7516static void
7517action_free(struct rte_swx_pipeline *p)
7518{
7519 action_build_free(p);
7520
7521 for ( ; ; ) {
7522 struct action *action;
7523
7524 action = TAILQ_FIRST(&p->actions);
7525 if (!action)
7526 break;
7527
7528 TAILQ_REMOVE(&p->actions, action, node);
7529 free(action->args_endianness);
7530 free(action->instructions);
7531 free(action->instruction_data);
7532 free(action);
7533 }
7534}
7535
7536static uint32_t
7537action_arg_src_mov_count(struct action *a,
7538 uint32_t arg_id,
7539 struct instruction *instructions,
7540 struct instruction_data *instruction_data,
7541 uint32_t n_instructions)
7542{
7543 uint32_t offset, n_users = 0, i;
7544
7545 if (!a->st ||
7546 (arg_id >= a->st->n_fields) ||
7547 !instructions ||
7548 !instruction_data ||
7549 !n_instructions)
7550 return 0;
7551
7552 offset = a->st->fields[arg_id].offset / 8;
7553
7554 for (i = 0; i < n_instructions; i++) {
7555 struct instruction *instr = &instructions[i];
7556 struct instruction_data *data = &instruction_data[i];
7557
7558 if (data->invalid ||
7559 ((instr->type != INSTR_MOV) && (instr->type != INSTR_MOV_HM)) ||
7560 instr->mov.src.struct_id ||
7561 (instr->mov.src.offset != offset))
7562 continue;
7563
7564 n_users++;
7565 }
7566
7567 return n_users;
7568}
7569
7570#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
7571#define field_ntoh(val, n_bits) (ntoh64((val) << (64 - n_bits)))
7572#define field_hton(val, n_bits) (hton64((val) << (64 - n_bits)))
7573#else
7574#define field_ntoh(val, n_bits) (val)
7575#define field_hton(val, n_bits) (val)
7576#endif
7577
7578#define ACTION_ARGS_TOKENS_MAX 256
7579
7580static int
7581action_args_parse(struct action *a, const char *args, uint8_t *data)
7582{
7583 char *tokens[ACTION_ARGS_TOKENS_MAX], *s0 = NULL, *s;
7584 uint32_t n_tokens = 0, offset = 0, i;
7585 int status = 0;
7586
7587
7588 if (!a->st || !args || !args[0]) {
7589 status = -EINVAL;
7590 goto error;
7591 }
7592
7593
7594 s0 = strdup(args);
7595 if (!s0) {
7596 status = -ENOMEM;
7597 goto error;
7598 }
7599
7600
7601 for (s = s0; ; ) {
7602 char *token;
7603
7604 token = strtok_r(s, " \f\n\r\t\v", &s);
7605 if (!token)
7606 break;
7607
7608 if (n_tokens >= RTE_DIM(tokens)) {
7609 status = -EINVAL;
7610 goto error;
7611 }
7612
7613 tokens[n_tokens] = token;
7614 n_tokens++;
7615 }
7616
7617
7618 if (n_tokens != a->st->n_fields * 2) {
7619 status = -EINVAL;
7620 goto error;
7621 }
7622
7623
7624 for (i = 0; i < a->st->n_fields; i++) {
7625 struct field *f = &a->st->fields[i];
7626 char *arg_name = tokens[i * 2];
7627 char *arg_val = tokens[i * 2 + 1];
7628 uint64_t val;
7629
7630 if (strcmp(arg_name, f->name)) {
7631 status = -EINVAL;
7632 goto error;
7633 }
7634
7635 val = strtoull(arg_val, &arg_val, 0);
7636 if (arg_val[0]) {
7637 status = -EINVAL;
7638 goto error;
7639 }
7640
7641
7642 if (a->args_endianness[i])
7643 val = field_hton(val, f->n_bits);
7644
7645
7646 memcpy(&data[offset], (uint8_t *)&val, f->n_bits / 8);
7647 offset += f->n_bits / 8;
7648 }
7649
7650error:
7651 free(s0);
7652 return status;
7653}
7654
7655
7656
7657
7658static struct table_type *
7659table_type_find(struct rte_swx_pipeline *p, const char *name)
7660{
7661 struct table_type *elem;
7662
7663 TAILQ_FOREACH(elem, &p->table_types, node)
7664 if (strcmp(elem->name, name) == 0)
7665 return elem;
7666
7667 return NULL;
7668}
7669
7670static struct table_type *
7671table_type_resolve(struct rte_swx_pipeline *p,
7672 const char *recommended_type_name,
7673 enum rte_swx_table_match_type match_type)
7674{
7675 struct table_type *elem;
7676
7677
7678 if (recommended_type_name)
7679 TAILQ_FOREACH(elem, &p->table_types, node)
7680 if (!strcmp(elem->name, recommended_type_name) &&
7681 (elem->match_type == match_type))
7682 return elem;
7683
7684
7685
7686
7687 TAILQ_FOREACH(elem, &p->table_types, node)
7688 if (elem->match_type == match_type)
7689 return elem;
7690
7691 return NULL;
7692}
7693
7694static struct table *
7695table_find(struct rte_swx_pipeline *p, const char *name)
7696{
7697 struct table *elem;
7698
7699 TAILQ_FOREACH(elem, &p->tables, node)
7700 if (strcmp(elem->name, name) == 0)
7701 return elem;
7702
7703 return NULL;
7704}
7705
7706static struct table *
7707table_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7708{
7709 struct table *table = NULL;
7710
7711 TAILQ_FOREACH(table, &p->tables, node)
7712 if (table->id == id)
7713 return table;
7714
7715 return NULL;
7716}
7717
7718int
7719rte_swx_pipeline_table_type_register(struct rte_swx_pipeline *p,
7720 const char *name,
7721 enum rte_swx_table_match_type match_type,
7722 struct rte_swx_table_ops *ops)
7723{
7724 struct table_type *elem;
7725
7726 CHECK(p, EINVAL);
7727
7728 CHECK_NAME(name, EINVAL);
7729 CHECK(!table_type_find(p, name), EEXIST);
7730
7731 CHECK(ops, EINVAL);
7732 CHECK(ops->create, EINVAL);
7733 CHECK(ops->lkp, EINVAL);
7734 CHECK(ops->free, EINVAL);
7735
7736
7737 elem = calloc(1, sizeof(struct table_type));
7738 CHECK(elem, ENOMEM);
7739
7740
7741 strcpy(elem->name, name);
7742 elem->match_type = match_type;
7743 memcpy(&elem->ops, ops, sizeof(*ops));
7744
7745
7746 TAILQ_INSERT_TAIL(&p->table_types, elem, node);
7747
7748 return 0;
7749}
7750
7751static int
7752table_match_type_resolve(struct rte_swx_match_field_params *fields,
7753 uint32_t n_fields,
7754 enum rte_swx_table_match_type *match_type)
7755{
7756 uint32_t n_fields_em = 0, n_fields_lpm = 0, i;
7757
7758 for (i = 0; i < n_fields; i++) {
7759 struct rte_swx_match_field_params *f = &fields[i];
7760
7761 if (f->match_type == RTE_SWX_TABLE_MATCH_EXACT)
7762 n_fields_em++;
7763
7764 if (f->match_type == RTE_SWX_TABLE_MATCH_LPM)
7765 n_fields_lpm++;
7766 }
7767
7768 if ((n_fields_lpm > 1) ||
7769 (n_fields_lpm && (n_fields_em != n_fields - 1)))
7770 return -EINVAL;
7771
7772 *match_type = (n_fields_em == n_fields) ?
7773 RTE_SWX_TABLE_MATCH_EXACT :
7774 RTE_SWX_TABLE_MATCH_WILDCARD;
7775
7776 return 0;
7777}
7778
7779static int
7780table_match_fields_check(struct rte_swx_pipeline *p,
7781 struct rte_swx_pipeline_table_params *params,
7782 struct header **header)
7783{
7784 struct header *h0 = NULL;
7785 struct field *hf, *mf;
7786 uint32_t *offset = NULL, i;
7787 int status = 0;
7788
7789
7790 if (!params->n_fields) {
7791 if (params->fields) {
7792 status = -EINVAL;
7793 goto end;
7794 }
7795
7796 if (header)
7797 *header = NULL;
7798
7799 return 0;
7800 }
7801
7802
7803 offset = calloc(params->n_fields, sizeof(uint32_t));
7804 if (!offset) {
7805 status = -ENOMEM;
7806 goto end;
7807 }
7808
7809
7810
7811
7812 hf = header_field_parse(p, params->fields[0].name, &h0);
7813 mf = metadata_field_parse(p, params->fields[0].name);
7814 if ((!hf && !mf) || (hf && hf->var_size)) {
7815 status = -EINVAL;
7816 goto end;
7817 }
7818
7819 offset[0] = h0 ? hf->offset : mf->offset;
7820
7821 for (i = 1; i < params->n_fields; i++)
7822 if (h0) {
7823 struct header *h;
7824
7825 hf = header_field_parse(p, params->fields[i].name, &h);
7826 if (!hf || (h->id != h0->id) || hf->var_size) {
7827 status = -EINVAL;
7828 goto end;
7829 }
7830
7831 offset[i] = hf->offset;
7832 } else {
7833 mf = metadata_field_parse(p, params->fields[i].name);
7834 if (!mf) {
7835 status = -EINVAL;
7836 goto end;
7837 }
7838
7839 offset[i] = mf->offset;
7840 }
7841
7842
7843 for (i = 0; i < params->n_fields; i++) {
7844 uint32_t j;
7845
7846 for (j = 0; j < i; j++)
7847 if (offset[j] == offset[i]) {
7848 status = -EINVAL;
7849 goto end;
7850 }
7851 }
7852
7853
7854 if (header)
7855 *header = h0;
7856
7857end:
7858 free(offset);
7859 return status;
7860}
7861
7862int
7863rte_swx_pipeline_table_config(struct rte_swx_pipeline *p,
7864 const char *name,
7865 struct rte_swx_pipeline_table_params *params,
7866 const char *recommended_table_type_name,
7867 const char *args,
7868 uint32_t size)
7869{
7870 struct table_type *type;
7871 struct table *t = NULL;
7872 struct action *default_action;
7873 struct header *header = NULL;
7874 uint32_t action_data_size_max = 0, i;
7875 int status = 0;
7876
7877 CHECK(p, EINVAL);
7878
7879 CHECK_NAME(name, EINVAL);
7880 CHECK(!table_find(p, name), EEXIST);
7881 CHECK(!selector_find(p, name), EEXIST);
7882 CHECK(!learner_find(p, name), EEXIST);
7883
7884 CHECK(params, EINVAL);
7885
7886
7887 status = table_match_fields_check(p, params, &header);
7888 if (status)
7889 return status;
7890
7891
7892 CHECK(params->n_actions, EINVAL);
7893 CHECK(params->action_names, EINVAL);
7894 for (i = 0; i < params->n_actions; i++) {
7895 const char *action_name = params->action_names[i];
7896 struct action *a;
7897 uint32_t action_data_size;
7898 int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
7899
7900 CHECK_NAME(action_name, EINVAL);
7901
7902 a = action_find(p, action_name);
7903 CHECK(a, EINVAL);
7904 CHECK(!action_does_learning(a), EINVAL);
7905
7906 action_data_size = a->st ? a->st->n_bits / 8 : 0;
7907 if (action_data_size > action_data_size_max)
7908 action_data_size_max = action_data_size;
7909
7910 if (params->action_is_for_table_entries)
7911 action_is_for_table_entries = params->action_is_for_table_entries[i];
7912 if (params->action_is_for_default_entry)
7913 action_is_for_default_entry = params->action_is_for_default_entry[i];
7914 CHECK(action_is_for_table_entries || action_is_for_default_entry, EINVAL);
7915 }
7916
7917 CHECK_NAME(params->default_action_name, EINVAL);
7918 for (i = 0; i < p->n_actions; i++)
7919 if (!strcmp(params->action_names[i],
7920 params->default_action_name))
7921 break;
7922 CHECK(i < params->n_actions, EINVAL);
7923 CHECK(!params->action_is_for_default_entry || params->action_is_for_default_entry[i],
7924 EINVAL);
7925
7926 default_action = action_find(p, params->default_action_name);
7927 CHECK((default_action->st && params->default_action_args) || !params->default_action_args,
7928 EINVAL);
7929
7930
7931 if (recommended_table_type_name)
7932 CHECK_NAME(recommended_table_type_name, EINVAL);
7933
7934 if (params->n_fields) {
7935 enum rte_swx_table_match_type match_type;
7936
7937 status = table_match_type_resolve(params->fields, params->n_fields, &match_type);
7938 if (status)
7939 return status;
7940
7941 type = table_type_resolve(p, recommended_table_type_name, match_type);
7942 CHECK(type, EINVAL);
7943 } else {
7944 type = NULL;
7945 }
7946
7947
7948 t = calloc(1, sizeof(struct table));
7949 if (!t) {
7950 status = -ENOMEM;
7951 goto error;
7952 }
7953
7954 t->fields = calloc(params->n_fields, sizeof(struct match_field));
7955 if (!t->fields) {
7956 status = -ENOMEM;
7957 goto error;
7958 }
7959
7960 t->actions = calloc(params->n_actions, sizeof(struct action *));
7961 if (!t->actions) {
7962 status = -ENOMEM;
7963 goto error;
7964 }
7965
7966 if (action_data_size_max) {
7967 t->default_action_data = calloc(1, action_data_size_max);
7968 if (!t->default_action_data) {
7969 status = -ENOMEM;
7970 goto error;
7971 }
7972 }
7973
7974 t->action_is_for_table_entries = calloc(params->n_actions, sizeof(int));
7975 if (!t->action_is_for_table_entries) {
7976 status = -ENOMEM;
7977 goto error;
7978 }
7979
7980 t->action_is_for_default_entry = calloc(params->n_actions, sizeof(int));
7981 if (!t->action_is_for_default_entry) {
7982 status = -ENOMEM;
7983 goto error;
7984 }
7985
7986
7987 strcpy(t->name, name);
7988 if (args && args[0])
7989 strcpy(t->args, args);
7990 t->type = type;
7991
7992 for (i = 0; i < params->n_fields; i++) {
7993 struct rte_swx_match_field_params *field = ¶ms->fields[i];
7994 struct match_field *f = &t->fields[i];
7995
7996 f->match_type = field->match_type;
7997 f->field = header ?
7998 header_field_parse(p, field->name, NULL) :
7999 metadata_field_parse(p, field->name);
8000 }
8001 t->n_fields = params->n_fields;
8002 t->header = header;
8003
8004 for (i = 0; i < params->n_actions; i++) {
8005 int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
8006
8007 if (params->action_is_for_table_entries)
8008 action_is_for_table_entries = params->action_is_for_table_entries[i];
8009 if (params->action_is_for_default_entry)
8010 action_is_for_default_entry = params->action_is_for_default_entry[i];
8011
8012 t->actions[i] = action_find(p, params->action_names[i]);
8013 t->action_is_for_table_entries[i] = action_is_for_table_entries;
8014 t->action_is_for_default_entry[i] = action_is_for_default_entry;
8015 }
8016 t->default_action = default_action;
8017 if (default_action->st) {
8018 status = action_args_parse(default_action,
8019 params->default_action_args,
8020 t->default_action_data);
8021 if (status)
8022 goto error;
8023 }
8024
8025 t->n_actions = params->n_actions;
8026 t->default_action_is_const = params->default_action_is_const;
8027 t->action_data_size_max = action_data_size_max;
8028
8029 t->size = size;
8030 t->id = p->n_tables;
8031
8032
8033 TAILQ_INSERT_TAIL(&p->tables, t, node);
8034 p->n_tables++;
8035
8036 return 0;
8037
8038error:
8039 if (!t)
8040 return status;
8041
8042 free(t->action_is_for_default_entry);
8043 free(t->action_is_for_table_entries);
8044 free(t->default_action_data);
8045 free(t->actions);
8046 free(t->fields);
8047 free(t);
8048
8049 return status;
8050}
8051
8052static struct rte_swx_table_params *
8053table_params_get(struct table *table)
8054{
8055 struct rte_swx_table_params *params;
8056 struct field *first, *last;
8057 uint8_t *key_mask;
8058 uint32_t key_size, key_offset, action_data_size, i;
8059
8060
8061 params = calloc(1, sizeof(struct rte_swx_table_params));
8062 if (!params)
8063 return NULL;
8064
8065
8066 first = table->fields[0].field;
8067 last = table->fields[0].field;
8068
8069 for (i = 0; i < table->n_fields; i++) {
8070 struct field *f = table->fields[i].field;
8071
8072 if (f->offset < first->offset)
8073 first = f;
8074
8075 if (f->offset > last->offset)
8076 last = f;
8077 }
8078
8079
8080 key_offset = first->offset / 8;
8081 key_size = (last->offset + last->n_bits - first->offset) / 8;
8082
8083
8084 key_mask = calloc(1, key_size);
8085 if (!key_mask) {
8086 free(params);
8087 return NULL;
8088 }
8089
8090
8091 for (i = 0; i < table->n_fields; i++) {
8092 struct field *f = table->fields[i].field;
8093 uint32_t start = (f->offset - first->offset) / 8;
8094 size_t size = f->n_bits / 8;
8095
8096 memset(&key_mask[start], 0xFF, size);
8097 }
8098
8099
8100 action_data_size = 0;
8101 for (i = 0; i < table->n_actions; i++) {
8102 struct action *action = table->actions[i];
8103 uint32_t ads = action->st ? action->st->n_bits / 8 : 0;
8104
8105 if (ads > action_data_size)
8106 action_data_size = ads;
8107 }
8108
8109
8110 params->match_type = table->type->match_type;
8111 params->key_size = key_size;
8112 params->key_offset = key_offset;
8113 params->key_mask0 = key_mask;
8114 params->action_data_size = action_data_size;
8115 params->n_keys_max = table->size;
8116
8117 return params;
8118}
8119
8120static void
8121table_params_free(struct rte_swx_table_params *params)
8122{
8123 if (!params)
8124 return;
8125
8126 free(params->key_mask0);
8127 free(params);
8128}
8129
8130static int
8131table_stub_lkp(void *table __rte_unused,
8132 void *mailbox __rte_unused,
8133 uint8_t **key __rte_unused,
8134 uint64_t *action_id __rte_unused,
8135 uint8_t **action_data __rte_unused,
8136 int *hit)
8137{
8138 *hit = 0;
8139 return 1;
8140}
8141
8142static int
8143table_build(struct rte_swx_pipeline *p)
8144{
8145 uint32_t i;
8146
8147
8148 p->table_stats = calloc(p->n_tables, sizeof(struct table_statistics));
8149 CHECK(p->table_stats, ENOMEM);
8150
8151 for (i = 0; i < p->n_tables; i++) {
8152 p->table_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
8153 CHECK(p->table_stats[i].n_pkts_action, ENOMEM);
8154 }
8155
8156
8157 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8158 struct thread *t = &p->threads[i];
8159 struct table *table;
8160
8161 t->tables = calloc(p->n_tables, sizeof(struct table_runtime));
8162 CHECK(t->tables, ENOMEM);
8163
8164 TAILQ_FOREACH(table, &p->tables, node) {
8165 struct table_runtime *r = &t->tables[table->id];
8166
8167 if (table->type) {
8168 uint64_t size;
8169
8170 size = table->type->ops.mailbox_size_get();
8171
8172
8173 r->func = table->type->ops.lkp;
8174
8175
8176 if (size) {
8177 r->mailbox = calloc(1, size);
8178 CHECK(r->mailbox, ENOMEM);
8179 }
8180
8181
8182 r->key = table->header ?
8183 &t->structs[table->header->struct_id] :
8184 &t->structs[p->metadata_struct_id];
8185 } else {
8186 r->func = table_stub_lkp;
8187 }
8188 }
8189 }
8190
8191 return 0;
8192}
8193
8194static void
8195table_build_free(struct rte_swx_pipeline *p)
8196{
8197 uint32_t i;
8198
8199 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8200 struct thread *t = &p->threads[i];
8201 uint32_t j;
8202
8203 if (!t->tables)
8204 continue;
8205
8206 for (j = 0; j < p->n_tables; j++) {
8207 struct table_runtime *r = &t->tables[j];
8208
8209 free(r->mailbox);
8210 }
8211
8212 free(t->tables);
8213 t->tables = NULL;
8214 }
8215
8216 if (p->table_stats) {
8217 for (i = 0; i < p->n_tables; i++)
8218 free(p->table_stats[i].n_pkts_action);
8219
8220 free(p->table_stats);
8221 }
8222}
8223
8224static void
8225table_free(struct rte_swx_pipeline *p)
8226{
8227 table_build_free(p);
8228
8229
8230 for ( ; ; ) {
8231 struct table *elem;
8232
8233 elem = TAILQ_FIRST(&p->tables);
8234 if (!elem)
8235 break;
8236
8237 TAILQ_REMOVE(&p->tables, elem, node);
8238 free(elem->fields);
8239 free(elem->actions);
8240 free(elem->default_action_data);
8241 free(elem);
8242 }
8243
8244
8245 for ( ; ; ) {
8246 struct table_type *elem;
8247
8248 elem = TAILQ_FIRST(&p->table_types);
8249 if (!elem)
8250 break;
8251
8252 TAILQ_REMOVE(&p->table_types, elem, node);
8253 free(elem);
8254 }
8255}
8256
8257
8258
8259
8260static struct selector *
8261selector_find(struct rte_swx_pipeline *p, const char *name)
8262{
8263 struct selector *s;
8264
8265 TAILQ_FOREACH(s, &p->selectors, node)
8266 if (strcmp(s->name, name) == 0)
8267 return s;
8268
8269 return NULL;
8270}
8271
8272static struct selector *
8273selector_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8274{
8275 struct selector *s = NULL;
8276
8277 TAILQ_FOREACH(s, &p->selectors, node)
8278 if (s->id == id)
8279 return s;
8280
8281 return NULL;
8282}
8283
8284static int
8285selector_fields_check(struct rte_swx_pipeline *p,
8286 struct rte_swx_pipeline_selector_params *params,
8287 struct header **header)
8288{
8289 struct header *h0 = NULL;
8290 struct field *hf, *mf;
8291 uint32_t i;
8292
8293
8294 if (!params->n_selector_fields || !params->selector_field_names)
8295 return -EINVAL;
8296
8297
8298
8299
8300 hf = header_field_parse(p, params->selector_field_names[0], &h0);
8301 mf = metadata_field_parse(p, params->selector_field_names[0]);
8302 if (!hf && !mf)
8303 return -EINVAL;
8304
8305 for (i = 1; i < params->n_selector_fields; i++)
8306 if (h0) {
8307 struct header *h;
8308
8309 hf = header_field_parse(p, params->selector_field_names[i], &h);
8310 if (!hf || (h->id != h0->id))
8311 return -EINVAL;
8312 } else {
8313 mf = metadata_field_parse(p, params->selector_field_names[i]);
8314 if (!mf)
8315 return -EINVAL;
8316 }
8317
8318
8319 for (i = 0; i < params->n_selector_fields; i++) {
8320 const char *field_name = params->selector_field_names[i];
8321 uint32_t j;
8322
8323 for (j = i + 1; j < params->n_selector_fields; j++)
8324 if (!strcmp(params->selector_field_names[j], field_name))
8325 return -EINVAL;
8326 }
8327
8328
8329 if (header)
8330 *header = h0;
8331
8332 return 0;
8333}
8334
8335int
8336rte_swx_pipeline_selector_config(struct rte_swx_pipeline *p,
8337 const char *name,
8338 struct rte_swx_pipeline_selector_params *params)
8339{
8340 struct selector *s;
8341 struct header *selector_header = NULL;
8342 struct field *group_id_field, *member_id_field;
8343 uint32_t i;
8344 int status = 0;
8345
8346 CHECK(p, EINVAL);
8347
8348 CHECK_NAME(name, EINVAL);
8349 CHECK(!table_find(p, name), EEXIST);
8350 CHECK(!selector_find(p, name), EEXIST);
8351 CHECK(!learner_find(p, name), EEXIST);
8352
8353 CHECK(params, EINVAL);
8354
8355 CHECK_NAME(params->group_id_field_name, EINVAL);
8356 group_id_field = metadata_field_parse(p, params->group_id_field_name);
8357 CHECK(group_id_field, EINVAL);
8358
8359 for (i = 0; i < params->n_selector_fields; i++) {
8360 const char *field_name = params->selector_field_names[i];
8361
8362 CHECK_NAME(field_name, EINVAL);
8363 }
8364 status = selector_fields_check(p, params, &selector_header);
8365 if (status)
8366 return status;
8367
8368 CHECK_NAME(params->member_id_field_name, EINVAL);
8369 member_id_field = metadata_field_parse(p, params->member_id_field_name);
8370 CHECK(member_id_field, EINVAL);
8371
8372 CHECK(params->n_groups_max, EINVAL);
8373
8374 CHECK(params->n_members_per_group_max, EINVAL);
8375
8376
8377 s = calloc(1, sizeof(struct selector));
8378 if (!s) {
8379 status = -ENOMEM;
8380 goto error;
8381 }
8382
8383 s->selector_fields = calloc(params->n_selector_fields, sizeof(struct field *));
8384 if (!s->selector_fields) {
8385 status = -ENOMEM;
8386 goto error;
8387 }
8388
8389
8390 strcpy(s->name, name);
8391
8392 s->group_id_field = group_id_field;
8393
8394 for (i = 0; i < params->n_selector_fields; i++) {
8395 const char *field_name = params->selector_field_names[i];
8396
8397 s->selector_fields[i] = selector_header ?
8398 header_field_parse(p, field_name, NULL) :
8399 metadata_field_parse(p, field_name);
8400 }
8401
8402 s->n_selector_fields = params->n_selector_fields;
8403
8404 s->selector_header = selector_header;
8405
8406 s->member_id_field = member_id_field;
8407
8408 s->n_groups_max = params->n_groups_max;
8409
8410 s->n_members_per_group_max = params->n_members_per_group_max;
8411
8412 s->id = p->n_selectors;
8413
8414
8415 TAILQ_INSERT_TAIL(&p->selectors, s, node);
8416 p->n_selectors++;
8417
8418 return 0;
8419
8420error:
8421 if (!s)
8422 return status;
8423
8424 free(s->selector_fields);
8425
8426 free(s);
8427
8428 return status;
8429}
8430
8431static void
8432selector_params_free(struct rte_swx_table_selector_params *params)
8433{
8434 if (!params)
8435 return;
8436
8437 free(params->selector_mask);
8438
8439 free(params);
8440}
8441
8442static struct rte_swx_table_selector_params *
8443selector_table_params_get(struct selector *s)
8444{
8445 struct rte_swx_table_selector_params *params = NULL;
8446 struct field *first, *last;
8447 uint32_t i;
8448
8449
8450 params = calloc(1, sizeof(struct rte_swx_table_selector_params));
8451 if (!params)
8452 goto error;
8453
8454
8455 params->group_id_offset = s->group_id_field->offset / 8;
8456
8457
8458 first = s->selector_fields[0];
8459 last = s->selector_fields[0];
8460
8461 for (i = 0; i < s->n_selector_fields; i++) {
8462 struct field *f = s->selector_fields[i];
8463
8464 if (f->offset < first->offset)
8465 first = f;
8466
8467 if (f->offset > last->offset)
8468 last = f;
8469 }
8470
8471
8472 params->selector_offset = first->offset / 8;
8473 params->selector_size = (last->offset + last->n_bits - first->offset) / 8;
8474
8475
8476 params->selector_mask = calloc(1, params->selector_size);
8477 if (!params->selector_mask)
8478 goto error;
8479
8480
8481 for (i = 0; i < s->n_selector_fields; i++) {
8482 struct field *f = s->selector_fields[i];
8483 uint32_t start = (f->offset - first->offset) / 8;
8484 size_t size = f->n_bits / 8;
8485
8486 memset(¶ms->selector_mask[start], 0xFF, size);
8487 }
8488
8489
8490 params->member_id_offset = s->member_id_field->offset / 8;
8491
8492
8493 params->n_groups_max = s->n_groups_max;
8494
8495
8496 params->n_members_per_group_max = s->n_members_per_group_max;
8497
8498 return params;
8499
8500error:
8501 selector_params_free(params);
8502 return NULL;
8503}
8504
8505static void
8506selector_build_free(struct rte_swx_pipeline *p)
8507{
8508 uint32_t i;
8509
8510 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8511 struct thread *t = &p->threads[i];
8512 uint32_t j;
8513
8514 if (!t->selectors)
8515 continue;
8516
8517 for (j = 0; j < p->n_selectors; j++) {
8518 struct selector_runtime *r = &t->selectors[j];
8519
8520 free(r->mailbox);
8521 }
8522
8523 free(t->selectors);
8524 t->selectors = NULL;
8525 }
8526
8527 free(p->selector_stats);
8528 p->selector_stats = NULL;
8529}
8530
8531static int
8532selector_build(struct rte_swx_pipeline *p)
8533{
8534 uint32_t i;
8535 int status = 0;
8536
8537
8538 p->selector_stats = calloc(p->n_selectors, sizeof(struct selector_statistics));
8539 if (!p->selector_stats) {
8540 status = -ENOMEM;
8541 goto error;
8542 }
8543
8544
8545 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8546 struct thread *t = &p->threads[i];
8547 struct selector *s;
8548
8549 t->selectors = calloc(p->n_selectors, sizeof(struct selector_runtime));
8550 if (!t->selectors) {
8551 status = -ENOMEM;
8552 goto error;
8553 }
8554
8555 TAILQ_FOREACH(s, &p->selectors, node) {
8556 struct selector_runtime *r = &t->selectors[s->id];
8557 uint64_t size;
8558
8559
8560 size = rte_swx_table_selector_mailbox_size_get();
8561 if (size) {
8562 r->mailbox = calloc(1, size);
8563 if (!r->mailbox) {
8564 status = -ENOMEM;
8565 goto error;
8566 }
8567 }
8568
8569
8570 r->group_id_buffer = &t->structs[p->metadata_struct_id];
8571
8572
8573 r->selector_buffer = s->selector_header ?
8574 &t->structs[s->selector_header->struct_id] :
8575 &t->structs[p->metadata_struct_id];
8576
8577
8578 r->member_id_buffer = &t->structs[p->metadata_struct_id];
8579 }
8580 }
8581
8582 return 0;
8583
8584error:
8585 selector_build_free(p);
8586 return status;
8587}
8588
8589static void
8590selector_free(struct rte_swx_pipeline *p)
8591{
8592 selector_build_free(p);
8593
8594
8595 for ( ; ; ) {
8596 struct selector *elem;
8597
8598 elem = TAILQ_FIRST(&p->selectors);
8599 if (!elem)
8600 break;
8601
8602 TAILQ_REMOVE(&p->selectors, elem, node);
8603 free(elem->selector_fields);
8604 free(elem);
8605 }
8606}
8607
8608
8609
8610
8611static struct learner *
8612learner_find(struct rte_swx_pipeline *p, const char *name)
8613{
8614 struct learner *l;
8615
8616 TAILQ_FOREACH(l, &p->learners, node)
8617 if (!strcmp(l->name, name))
8618 return l;
8619
8620 return NULL;
8621}
8622
8623static struct learner *
8624learner_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8625{
8626 struct learner *l = NULL;
8627
8628 TAILQ_FOREACH(l, &p->learners, node)
8629 if (l->id == id)
8630 return l;
8631
8632 return NULL;
8633}
8634
8635static int
8636learner_match_fields_check(struct rte_swx_pipeline *p,
8637 struct rte_swx_pipeline_learner_params *params,
8638 struct header **header)
8639{
8640 struct header *h0 = NULL;
8641 struct field *hf, *mf;
8642 uint32_t i;
8643
8644
8645 if (!params->n_fields || !params->field_names)
8646 return -EINVAL;
8647
8648
8649
8650
8651 hf = header_field_parse(p, params->field_names[0], &h0);
8652 mf = metadata_field_parse(p, params->field_names[0]);
8653 if (!hf && !mf)
8654 return -EINVAL;
8655
8656 for (i = 1; i < params->n_fields; i++)
8657 if (h0) {
8658 struct header *h;
8659
8660 hf = header_field_parse(p, params->field_names[i], &h);
8661 if (!hf || (h->id != h0->id))
8662 return -EINVAL;
8663 } else {
8664 mf = metadata_field_parse(p, params->field_names[i]);
8665 if (!mf)
8666 return -EINVAL;
8667 }
8668
8669
8670 for (i = 0; i < params->n_fields; i++) {
8671 const char *field_name = params->field_names[i];
8672 uint32_t j;
8673
8674 for (j = i + 1; j < params->n_fields; j++)
8675 if (!strcmp(params->field_names[j], field_name))
8676 return -EINVAL;
8677 }
8678
8679
8680 if (header)
8681 *header = h0;
8682
8683 return 0;
8684}
8685
8686static int
8687learner_action_args_check(struct rte_swx_pipeline *p, struct action *a, const char *mf_name)
8688{
8689 struct struct_type *mst = p->metadata_st, *ast = a->st;
8690 struct field *mf, *af;
8691 uint32_t mf_pos, i;
8692
8693 if (!ast) {
8694 if (mf_name)
8695 return -EINVAL;
8696
8697 return 0;
8698 }
8699
8700
8701 CHECK_NAME(mf_name, EINVAL);
8702 mf = metadata_field_parse(p, mf_name);
8703 CHECK(mf, EINVAL);
8704
8705
8706
8707
8708 mf_pos = mf - mst->fields;
8709 CHECK(mst->n_fields - mf_pos >= ast->n_fields, EINVAL);
8710
8711
8712
8713
8714 for (i = 0; i < ast->n_fields; i++) {
8715 mf = &mst->fields[mf_pos + i];
8716 af = &ast->fields[i];
8717
8718 CHECK(mf->n_bits == af->n_bits, EINVAL);
8719 }
8720
8721 return 0;
8722}
8723
8724static int
8725learner_action_learning_check(struct rte_swx_pipeline *p,
8726 struct action *action,
8727 const char **action_names,
8728 uint32_t n_actions)
8729{
8730 uint32_t i;
8731
8732
8733
8734
8735
8736 for (i = 0; i < action->n_instructions; i++) {
8737 struct instruction *instr = &action->instructions[i];
8738 uint32_t found = 0, j;
8739
8740 if (instr->type != INSTR_LEARNER_LEARN)
8741 continue;
8742
8743 for (j = 0; j < n_actions; j++) {
8744 struct action *a;
8745
8746 a = action_find(p, action_names[j]);
8747 if (!a)
8748 return -EINVAL;
8749
8750 if (a->id == instr->learn.action_id)
8751 found = 1;
8752 }
8753
8754 if (!found)
8755 return -EINVAL;
8756 }
8757
8758 return 0;
8759}
8760
8761int
8762rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p,
8763 const char *name,
8764 struct rte_swx_pipeline_learner_params *params,
8765 uint32_t size,
8766 uint32_t *timeout,
8767 uint32_t n_timeouts)
8768{
8769 struct learner *l = NULL;
8770 struct action *default_action;
8771 struct header *header = NULL;
8772 uint32_t action_data_size_max = 0, i;
8773 int status = 0;
8774
8775 CHECK(p, EINVAL);
8776
8777 CHECK_NAME(name, EINVAL);
8778 CHECK(!table_find(p, name), EEXIST);
8779 CHECK(!selector_find(p, name), EEXIST);
8780 CHECK(!learner_find(p, name), EEXIST);
8781
8782 CHECK(params, EINVAL);
8783
8784
8785 status = learner_match_fields_check(p, params, &header);
8786 if (status)
8787 return status;
8788
8789
8790 CHECK(params->n_actions, EINVAL);
8791 CHECK(params->action_names, EINVAL);
8792 for (i = 0; i < params->n_actions; i++) {
8793 const char *action_name = params->action_names[i];
8794 struct action *a;
8795 uint32_t action_data_size;
8796 int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
8797
8798 CHECK_NAME(action_name, EINVAL);
8799
8800 a = action_find(p, action_name);
8801 CHECK(a, EINVAL);
8802
8803 status = learner_action_learning_check(p,
8804 a,
8805 params->action_names,
8806 params->n_actions);
8807 if (status)
8808 return status;
8809
8810 action_data_size = a->st ? a->st->n_bits / 8 : 0;
8811 if (action_data_size > action_data_size_max)
8812 action_data_size_max = action_data_size;
8813
8814 if (params->action_is_for_table_entries)
8815 action_is_for_table_entries = params->action_is_for_table_entries[i];
8816 if (params->action_is_for_default_entry)
8817 action_is_for_default_entry = params->action_is_for_default_entry[i];
8818 CHECK(action_is_for_table_entries || action_is_for_default_entry, EINVAL);
8819 }
8820
8821 CHECK_NAME(params->default_action_name, EINVAL);
8822 for (i = 0; i < p->n_actions; i++)
8823 if (!strcmp(params->action_names[i],
8824 params->default_action_name))
8825 break;
8826 CHECK(i < params->n_actions, EINVAL);
8827 CHECK(!params->action_is_for_default_entry || params->action_is_for_default_entry[i],
8828 EINVAL);
8829
8830 default_action = action_find(p, params->default_action_name);
8831 CHECK((default_action->st && params->default_action_args) || !params->default_action_args,
8832 EINVAL);
8833
8834
8835 CHECK(size, EINVAL);
8836 CHECK(timeout, EINVAL);
8837 CHECK(n_timeouts && (n_timeouts <= RTE_SWX_TABLE_LEARNER_N_KEY_TIMEOUTS_MAX), EINVAL);
8838
8839
8840 l = calloc(1, sizeof(struct learner));
8841 if (!l) {
8842 status = -ENOMEM;
8843 goto error;
8844 }
8845
8846 l->fields = calloc(params->n_fields, sizeof(struct field *));
8847 if (!l->fields) {
8848 status = -ENOMEM;
8849 goto error;
8850 }
8851
8852 l->actions = calloc(params->n_actions, sizeof(struct action *));
8853 if (!l->actions) {
8854 status = -ENOMEM;
8855 goto error;
8856 }
8857
8858 if (action_data_size_max) {
8859 l->default_action_data = calloc(1, action_data_size_max);
8860 if (!l->default_action_data) {
8861 status = -ENOMEM;
8862 goto error;
8863 }
8864 }
8865
8866 l->action_is_for_table_entries = calloc(params->n_actions, sizeof(int));
8867 if (!l->action_is_for_table_entries) {
8868 status = -ENOMEM;
8869 goto error;
8870 }
8871
8872 l->action_is_for_default_entry = calloc(params->n_actions, sizeof(int));
8873 if (!l->action_is_for_default_entry) {
8874 status = -ENOMEM;
8875 goto error;
8876 }
8877
8878
8879 strcpy(l->name, name);
8880
8881 for (i = 0; i < params->n_fields; i++) {
8882 const char *field_name = params->field_names[i];
8883
8884 l->fields[i] = header ?
8885 header_field_parse(p, field_name, NULL) :
8886 metadata_field_parse(p, field_name);
8887 }
8888
8889 l->n_fields = params->n_fields;
8890
8891 l->header = header;
8892
8893 for (i = 0; i < params->n_actions; i++) {
8894 int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
8895
8896 if (params->action_is_for_table_entries)
8897 action_is_for_table_entries = params->action_is_for_table_entries[i];
8898 if (params->action_is_for_default_entry)
8899 action_is_for_default_entry = params->action_is_for_default_entry[i];
8900
8901 l->actions[i] = action_find(p, params->action_names[i]);
8902 l->action_is_for_table_entries[i] = action_is_for_table_entries;
8903 l->action_is_for_default_entry[i] = action_is_for_default_entry;
8904 }
8905
8906 l->default_action = default_action;
8907
8908 if (default_action->st) {
8909 status = action_args_parse(default_action,
8910 params->default_action_args,
8911 l->default_action_data);
8912 if (status)
8913 goto error;
8914 }
8915
8916 l->n_actions = params->n_actions;
8917
8918 l->default_action_is_const = params->default_action_is_const;
8919
8920 l->action_data_size_max = action_data_size_max;
8921
8922 l->size = size;
8923
8924 for (i = 0; i < n_timeouts; i++)
8925 l->timeout[i] = timeout[i];
8926
8927 l->n_timeouts = n_timeouts;
8928
8929 l->id = p->n_learners;
8930
8931
8932 TAILQ_INSERT_TAIL(&p->learners, l, node);
8933 p->n_learners++;
8934
8935 return 0;
8936
8937error:
8938 if (!l)
8939 return status;
8940
8941 free(l->action_is_for_default_entry);
8942 free(l->action_is_for_table_entries);
8943 free(l->default_action_data);
8944 free(l->actions);
8945 free(l->fields);
8946 free(l);
8947
8948 return status;
8949}
8950
8951static void
8952learner_params_free(struct rte_swx_table_learner_params *params)
8953{
8954 if (!params)
8955 return;
8956
8957 free(params->key_mask0);
8958
8959 free(params->key_timeout);
8960
8961 free(params);
8962}
8963
8964static struct rte_swx_table_learner_params *
8965learner_params_get(struct learner *l)
8966{
8967 struct rte_swx_table_learner_params *params = NULL;
8968 struct field *first, *last;
8969 uint32_t i;
8970
8971
8972 params = calloc(1, sizeof(struct rte_swx_table_learner_params));
8973 if (!params)
8974 goto error;
8975
8976
8977 first = l->fields[0];
8978 last = l->fields[0];
8979
8980 for (i = 0; i < l->n_fields; i++) {
8981 struct field *f = l->fields[i];
8982
8983 if (f->offset < first->offset)
8984 first = f;
8985
8986 if (f->offset > last->offset)
8987 last = f;
8988 }
8989
8990
8991 params->key_offset = first->offset / 8;
8992 params->key_size = (last->offset + last->n_bits - first->offset) / 8;
8993
8994
8995 params->key_mask0 = calloc(1, params->key_size);
8996 if (!params->key_mask0)
8997 goto error;
8998
8999
9000 for (i = 0; i < l->n_fields; i++) {
9001 struct field *f = l->fields[i];
9002 uint32_t start = (f->offset - first->offset) / 8;
9003 size_t size = f->n_bits / 8;
9004
9005 memset(¶ms->key_mask0[start], 0xFF, size);
9006 }
9007
9008
9009 params->action_data_size = l->action_data_size_max;
9010
9011
9012 params->n_keys_max = l->size;
9013
9014
9015 params->key_timeout = calloc(l->n_timeouts, sizeof(uint32_t));
9016 if (!params->key_timeout)
9017 goto error;
9018
9019
9020 for (i = 0; i < l->n_timeouts; i++)
9021 params->key_timeout[i] = l->timeout[i];
9022
9023 params->n_key_timeouts = l->n_timeouts;
9024
9025 return params;
9026
9027error:
9028 learner_params_free(params);
9029 return NULL;
9030}
9031
9032static void
9033learner_build_free(struct rte_swx_pipeline *p)
9034{
9035 uint32_t i;
9036
9037 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9038 struct thread *t = &p->threads[i];
9039 uint32_t j;
9040
9041 if (!t->learners)
9042 continue;
9043
9044 for (j = 0; j < p->n_learners; j++) {
9045 struct learner_runtime *r = &t->learners[j];
9046
9047 free(r->mailbox);
9048 }
9049
9050 free(t->learners);
9051 t->learners = NULL;
9052 }
9053
9054 if (p->learner_stats) {
9055 for (i = 0; i < p->n_learners; i++)
9056 free(p->learner_stats[i].n_pkts_action);
9057
9058 free(p->learner_stats);
9059 }
9060}
9061
9062static int
9063learner_build(struct rte_swx_pipeline *p)
9064{
9065 uint32_t i;
9066 int status = 0;
9067
9068
9069 p->learner_stats = calloc(p->n_learners, sizeof(struct learner_statistics));
9070 CHECK(p->learner_stats, ENOMEM);
9071
9072 for (i = 0; i < p->n_learners; i++) {
9073 p->learner_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
9074 CHECK(p->learner_stats[i].n_pkts_action, ENOMEM);
9075 }
9076
9077
9078 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9079 struct thread *t = &p->threads[i];
9080 struct learner *l;
9081
9082 t->learners = calloc(p->n_learners, sizeof(struct learner_runtime));
9083 if (!t->learners) {
9084 status = -ENOMEM;
9085 goto error;
9086 }
9087
9088 TAILQ_FOREACH(l, &p->learners, node) {
9089 struct learner_runtime *r = &t->learners[l->id];
9090 uint64_t size;
9091
9092
9093 size = rte_swx_table_learner_mailbox_size_get();
9094 if (size) {
9095 r->mailbox = calloc(1, size);
9096 if (!r->mailbox) {
9097 status = -ENOMEM;
9098 goto error;
9099 }
9100 }
9101
9102
9103 r->key = l->header ?
9104 &t->structs[l->header->struct_id] :
9105 &t->structs[p->metadata_struct_id];
9106 }
9107 }
9108
9109 return 0;
9110
9111error:
9112 learner_build_free(p);
9113 return status;
9114}
9115
9116static void
9117learner_free(struct rte_swx_pipeline *p)
9118{
9119 learner_build_free(p);
9120
9121
9122 for ( ; ; ) {
9123 struct learner *l;
9124
9125 l = TAILQ_FIRST(&p->learners);
9126 if (!l)
9127 break;
9128
9129 TAILQ_REMOVE(&p->learners, l, node);
9130 free(l->fields);
9131 free(l->actions);
9132 free(l->default_action_data);
9133 free(l);
9134 }
9135}
9136
9137
9138
9139
9140static int
9141table_state_build(struct rte_swx_pipeline *p)
9142{
9143 struct table *table;
9144 struct selector *s;
9145 struct learner *l;
9146
9147 p->table_state = calloc(p->n_tables + p->n_selectors + p->n_learners,
9148 sizeof(struct rte_swx_table_state));
9149 CHECK(p->table_state, ENOMEM);
9150
9151 TAILQ_FOREACH(table, &p->tables, node) {
9152 struct rte_swx_table_state *ts = &p->table_state[table->id];
9153
9154 if (table->type) {
9155 struct rte_swx_table_params *params;
9156
9157
9158 params = table_params_get(table);
9159 CHECK(params, ENOMEM);
9160
9161 ts->obj = table->type->ops.create(params,
9162 NULL,
9163 table->args,
9164 p->numa_node);
9165
9166 table_params_free(params);
9167 CHECK(ts->obj, ENODEV);
9168 }
9169
9170
9171 if (table->action_data_size_max) {
9172 ts->default_action_data =
9173 malloc(table->action_data_size_max);
9174 CHECK(ts->default_action_data, ENOMEM);
9175
9176 memcpy(ts->default_action_data,
9177 table->default_action_data,
9178 table->action_data_size_max);
9179 }
9180
9181
9182 ts->default_action_id = table->default_action->id;
9183 }
9184
9185 TAILQ_FOREACH(s, &p->selectors, node) {
9186 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + s->id];
9187 struct rte_swx_table_selector_params *params;
9188
9189
9190 params = selector_table_params_get(s);
9191 CHECK(params, ENOMEM);
9192
9193 ts->obj = rte_swx_table_selector_create(params, NULL, p->numa_node);
9194
9195 selector_params_free(params);
9196 CHECK(ts->obj, ENODEV);
9197 }
9198
9199 TAILQ_FOREACH(l, &p->learners, node) {
9200 struct rte_swx_table_state *ts = &p->table_state[p->n_tables +
9201 p->n_selectors + l->id];
9202 struct rte_swx_table_learner_params *params;
9203
9204
9205 params = learner_params_get(l);
9206 CHECK(params, ENOMEM);
9207
9208 ts->obj = rte_swx_table_learner_create(params, p->numa_node);
9209 learner_params_free(params);
9210 CHECK(ts->obj, ENODEV);
9211
9212
9213 if (l->action_data_size_max) {
9214 ts->default_action_data = malloc(l->action_data_size_max);
9215 CHECK(ts->default_action_data, ENOMEM);
9216
9217 memcpy(ts->default_action_data,
9218 l->default_action_data,
9219 l->action_data_size_max);
9220 }
9221
9222
9223 ts->default_action_id = l->default_action->id;
9224 }
9225
9226 return 0;
9227}
9228
9229static void
9230table_state_build_free(struct rte_swx_pipeline *p)
9231{
9232 uint32_t i;
9233
9234 if (!p->table_state)
9235 return;
9236
9237 for (i = 0; i < p->n_tables; i++) {
9238 struct rte_swx_table_state *ts = &p->table_state[i];
9239 struct table *table = table_find_by_id(p, i);
9240
9241
9242 if (table->type && ts->obj)
9243 table->type->ops.free(ts->obj);
9244
9245
9246 free(ts->default_action_data);
9247 }
9248
9249 for (i = 0; i < p->n_selectors; i++) {
9250 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + i];
9251
9252
9253 rte_swx_table_selector_free(ts->obj);
9254 }
9255
9256 for (i = 0; i < p->n_learners; i++) {
9257 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + p->n_selectors + i];
9258
9259
9260 rte_swx_table_learner_free(ts->obj);
9261
9262
9263 free(ts->default_action_data);
9264 }
9265
9266 free(p->table_state);
9267 p->table_state = NULL;
9268}
9269
9270static void
9271table_state_free(struct rte_swx_pipeline *p)
9272{
9273 table_state_build_free(p);
9274}
9275
9276
9277
9278
9279static struct regarray *
9280regarray_find(struct rte_swx_pipeline *p, const char *name)
9281{
9282 struct regarray *elem;
9283
9284 TAILQ_FOREACH(elem, &p->regarrays, node)
9285 if (!strcmp(elem->name, name))
9286 return elem;
9287
9288 return NULL;
9289}
9290
9291static struct regarray *
9292regarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9293{
9294 struct regarray *elem = NULL;
9295
9296 TAILQ_FOREACH(elem, &p->regarrays, node)
9297 if (elem->id == id)
9298 return elem;
9299
9300 return NULL;
9301}
9302
9303int
9304rte_swx_pipeline_regarray_config(struct rte_swx_pipeline *p,
9305 const char *name,
9306 uint32_t size,
9307 uint64_t init_val)
9308{
9309 struct regarray *r;
9310
9311 CHECK(p, EINVAL);
9312
9313 CHECK_NAME(name, EINVAL);
9314 CHECK(!regarray_find(p, name), EEXIST);
9315
9316 CHECK(size, EINVAL);
9317 size = rte_align32pow2(size);
9318
9319
9320 r = calloc(1, sizeof(struct regarray));
9321 CHECK(r, ENOMEM);
9322
9323
9324 strcpy(r->name, name);
9325 r->init_val = init_val;
9326 r->size = size;
9327 r->id = p->n_regarrays;
9328
9329
9330 TAILQ_INSERT_TAIL(&p->regarrays, r, node);
9331 p->n_regarrays++;
9332
9333 return 0;
9334}
9335
9336static int
9337regarray_build(struct rte_swx_pipeline *p)
9338{
9339 struct regarray *regarray;
9340
9341 if (!p->n_regarrays)
9342 return 0;
9343
9344 p->regarray_runtime = calloc(p->n_regarrays, sizeof(struct regarray_runtime));
9345 CHECK(p->regarray_runtime, ENOMEM);
9346
9347 TAILQ_FOREACH(regarray, &p->regarrays, node) {
9348 struct regarray_runtime *r = &p->regarray_runtime[regarray->id];
9349 uint32_t i;
9350
9351 r->regarray = env_malloc(regarray->size * sizeof(uint64_t),
9352 RTE_CACHE_LINE_SIZE,
9353 p->numa_node);
9354 CHECK(r->regarray, ENOMEM);
9355
9356 if (regarray->init_val)
9357 for (i = 0; i < regarray->size; i++)
9358 r->regarray[i] = regarray->init_val;
9359
9360 r->size_mask = regarray->size - 1;
9361 }
9362
9363 return 0;
9364}
9365
9366static void
9367regarray_build_free(struct rte_swx_pipeline *p)
9368{
9369 uint32_t i;
9370
9371 if (!p->regarray_runtime)
9372 return;
9373
9374 for (i = 0; i < p->n_regarrays; i++) {
9375 struct regarray *regarray = regarray_find_by_id(p, i);
9376 struct regarray_runtime *r = &p->regarray_runtime[i];
9377
9378 env_free(r->regarray, regarray->size * sizeof(uint64_t));
9379 }
9380
9381 free(p->regarray_runtime);
9382 p->regarray_runtime = NULL;
9383}
9384
9385static void
9386regarray_free(struct rte_swx_pipeline *p)
9387{
9388 regarray_build_free(p);
9389
9390 for ( ; ; ) {
9391 struct regarray *elem;
9392
9393 elem = TAILQ_FIRST(&p->regarrays);
9394 if (!elem)
9395 break;
9396
9397 TAILQ_REMOVE(&p->regarrays, elem, node);
9398 free(elem);
9399 }
9400}
9401
9402
9403
9404
9405static struct meter_profile *
9406meter_profile_find(struct rte_swx_pipeline *p, const char *name)
9407{
9408 struct meter_profile *elem;
9409
9410 TAILQ_FOREACH(elem, &p->meter_profiles, node)
9411 if (!strcmp(elem->name, name))
9412 return elem;
9413
9414 return NULL;
9415}
9416
9417static struct metarray *
9418metarray_find(struct rte_swx_pipeline *p, const char *name)
9419{
9420 struct metarray *elem;
9421
9422 TAILQ_FOREACH(elem, &p->metarrays, node)
9423 if (!strcmp(elem->name, name))
9424 return elem;
9425
9426 return NULL;
9427}
9428
9429static struct metarray *
9430metarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9431{
9432 struct metarray *elem = NULL;
9433
9434 TAILQ_FOREACH(elem, &p->metarrays, node)
9435 if (elem->id == id)
9436 return elem;
9437
9438 return NULL;
9439}
9440
9441int
9442rte_swx_pipeline_metarray_config(struct rte_swx_pipeline *p,
9443 const char *name,
9444 uint32_t size)
9445{
9446 struct metarray *m;
9447
9448 CHECK(p, EINVAL);
9449
9450 CHECK_NAME(name, EINVAL);
9451 CHECK(!metarray_find(p, name), EEXIST);
9452
9453 CHECK(size, EINVAL);
9454 size = rte_align32pow2(size);
9455
9456
9457 m = calloc(1, sizeof(struct metarray));
9458 CHECK(m, ENOMEM);
9459
9460
9461 strcpy(m->name, name);
9462 m->size = size;
9463 m->id = p->n_metarrays;
9464
9465
9466 TAILQ_INSERT_TAIL(&p->metarrays, m, node);
9467 p->n_metarrays++;
9468
9469 return 0;
9470}
9471
9472struct meter_profile meter_profile_default = {
9473 .node = {0},
9474 .name = "",
9475 .params = {0},
9476
9477 .profile = {
9478 .cbs = 10000,
9479 .pbs = 10000,
9480 .cir_period = 1,
9481 .cir_bytes_per_period = 1,
9482 .pir_period = 1,
9483 .pir_bytes_per_period = 1,
9484 },
9485
9486 .n_users = 0,
9487};
9488
9489static void
9490meter_init(struct meter *m)
9491{
9492 memset(m, 0, sizeof(struct meter));
9493 rte_meter_trtcm_config(&m->m, &meter_profile_default.profile);
9494 m->profile = &meter_profile_default;
9495 m->color_mask = RTE_COLOR_GREEN;
9496
9497 meter_profile_default.n_users++;
9498}
9499
9500static int
9501metarray_build(struct rte_swx_pipeline *p)
9502{
9503 struct metarray *m;
9504
9505 if (!p->n_metarrays)
9506 return 0;
9507
9508 p->metarray_runtime = calloc(p->n_metarrays, sizeof(struct metarray_runtime));
9509 CHECK(p->metarray_runtime, ENOMEM);
9510
9511 TAILQ_FOREACH(m, &p->metarrays, node) {
9512 struct metarray_runtime *r = &p->metarray_runtime[m->id];
9513 uint32_t i;
9514
9515 r->metarray = env_malloc(m->size * sizeof(struct meter),
9516 RTE_CACHE_LINE_SIZE,
9517 p->numa_node);
9518 CHECK(r->metarray, ENOMEM);
9519
9520 for (i = 0; i < m->size; i++)
9521 meter_init(&r->metarray[i]);
9522
9523 r->size_mask = m->size - 1;
9524 }
9525
9526 return 0;
9527}
9528
9529static void
9530metarray_build_free(struct rte_swx_pipeline *p)
9531{
9532 uint32_t i;
9533
9534 if (!p->metarray_runtime)
9535 return;
9536
9537 for (i = 0; i < p->n_metarrays; i++) {
9538 struct metarray *m = metarray_find_by_id(p, i);
9539 struct metarray_runtime *r = &p->metarray_runtime[i];
9540
9541 env_free(r->metarray, m->size * sizeof(struct meter));
9542 }
9543
9544 free(p->metarray_runtime);
9545 p->metarray_runtime = NULL;
9546}
9547
9548static void
9549metarray_free(struct rte_swx_pipeline *p)
9550{
9551 metarray_build_free(p);
9552
9553
9554 for ( ; ; ) {
9555 struct metarray *elem;
9556
9557 elem = TAILQ_FIRST(&p->metarrays);
9558 if (!elem)
9559 break;
9560
9561 TAILQ_REMOVE(&p->metarrays, elem, node);
9562 free(elem);
9563 }
9564
9565
9566 for ( ; ; ) {
9567 struct meter_profile *elem;
9568
9569 elem = TAILQ_FIRST(&p->meter_profiles);
9570 if (!elem)
9571 break;
9572
9573 TAILQ_REMOVE(&p->meter_profiles, elem, node);
9574 free(elem);
9575 }
9576}
9577
9578
9579
9580
9581void
9582rte_swx_pipeline_free(struct rte_swx_pipeline *p)
9583{
9584 void *lib;
9585
9586 if (!p)
9587 return;
9588
9589 lib = p->lib;
9590
9591 free(p->instruction_data);
9592 free(p->instructions);
9593
9594 metarray_free(p);
9595 regarray_free(p);
9596 table_state_free(p);
9597 learner_free(p);
9598 selector_free(p);
9599 table_free(p);
9600 action_free(p);
9601 instruction_table_free(p);
9602 metadata_free(p);
9603 header_free(p);
9604 hash_func_free(p);
9605 extern_func_free(p);
9606 extern_obj_free(p);
9607 mirroring_free(p);
9608 port_out_free(p);
9609 port_in_free(p);
9610 struct_free(p);
9611
9612 free(p);
9613
9614 if (lib)
9615 dlclose(lib);
9616}
9617
9618static int
9619port_in_types_register(struct rte_swx_pipeline *p)
9620{
9621 int status;
9622
9623 status = rte_swx_pipeline_port_in_type_register(p,
9624 "ethdev",
9625 &rte_swx_port_ethdev_reader_ops);
9626 if (status)
9627 return status;
9628
9629 status = rte_swx_pipeline_port_in_type_register(p,
9630 "ring",
9631 &rte_swx_port_ring_reader_ops);
9632 if (status)
9633 return status;
9634
9635#ifdef RTE_PORT_PCAP
9636 status = rte_swx_pipeline_port_in_type_register(p,
9637 "source",
9638 &rte_swx_port_source_ops);
9639 if (status)
9640 return status;
9641#endif
9642
9643 status = rte_swx_pipeline_port_in_type_register(p,
9644 "fd",
9645 &rte_swx_port_fd_reader_ops);
9646 if (status)
9647 return status;
9648
9649 return 0;
9650}
9651
9652static int
9653port_out_types_register(struct rte_swx_pipeline *p)
9654{
9655 int status;
9656
9657 status = rte_swx_pipeline_port_out_type_register(p,
9658 "ethdev",
9659 &rte_swx_port_ethdev_writer_ops);
9660 if (status)
9661 return status;
9662
9663 status = rte_swx_pipeline_port_out_type_register(p,
9664 "ring",
9665 &rte_swx_port_ring_writer_ops);
9666 if (status)
9667 return status;
9668
9669 status = rte_swx_pipeline_port_out_type_register(p,
9670 "sink",
9671 &rte_swx_port_sink_ops);
9672 if (status)
9673 return status;
9674
9675 status = rte_swx_pipeline_port_out_type_register(p,
9676 "fd",
9677 &rte_swx_port_fd_writer_ops);
9678 if (status)
9679 return status;
9680
9681 return 0;
9682}
9683
9684static int
9685table_types_register(struct rte_swx_pipeline *p)
9686{
9687 int status;
9688
9689 status = rte_swx_pipeline_table_type_register(p,
9690 "exact",
9691 RTE_SWX_TABLE_MATCH_EXACT,
9692 &rte_swx_table_exact_match_ops);
9693 if (status)
9694 return status;
9695
9696 status = rte_swx_pipeline_table_type_register(p,
9697 "wildcard",
9698 RTE_SWX_TABLE_MATCH_WILDCARD,
9699 &rte_swx_table_wildcard_match_ops);
9700 if (status)
9701 return status;
9702
9703 return 0;
9704}
9705
9706static int
9707hash_funcs_register(struct rte_swx_pipeline *p)
9708{
9709 int status;
9710
9711 status = rte_swx_pipeline_hash_func_register(p, "jhash", rte_jhash);
9712 if (status)
9713 return status;
9714
9715 status = rte_swx_pipeline_hash_func_register(p, "crc32", rte_hash_crc);
9716 if (status)
9717 return status;
9718
9719 return 0;
9720}
9721
9722int
9723rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
9724{
9725 struct rte_swx_pipeline *pipeline = NULL;
9726 int status = 0;
9727
9728
9729 CHECK(p, EINVAL);
9730
9731
9732 pipeline = calloc(1, sizeof(struct rte_swx_pipeline));
9733 if (!pipeline) {
9734 status = -ENOMEM;
9735 goto error;
9736 }
9737
9738
9739 TAILQ_INIT(&pipeline->struct_types);
9740 TAILQ_INIT(&pipeline->port_in_types);
9741 TAILQ_INIT(&pipeline->ports_in);
9742 TAILQ_INIT(&pipeline->port_out_types);
9743 TAILQ_INIT(&pipeline->ports_out);
9744 TAILQ_INIT(&pipeline->extern_types);
9745 TAILQ_INIT(&pipeline->extern_objs);
9746 TAILQ_INIT(&pipeline->extern_funcs);
9747 TAILQ_INIT(&pipeline->hash_funcs);
9748 TAILQ_INIT(&pipeline->headers);
9749 TAILQ_INIT(&pipeline->actions);
9750 TAILQ_INIT(&pipeline->table_types);
9751 TAILQ_INIT(&pipeline->tables);
9752 TAILQ_INIT(&pipeline->selectors);
9753 TAILQ_INIT(&pipeline->learners);
9754 TAILQ_INIT(&pipeline->regarrays);
9755 TAILQ_INIT(&pipeline->meter_profiles);
9756 TAILQ_INIT(&pipeline->metarrays);
9757
9758 pipeline->n_structs = 1;
9759 pipeline->n_mirroring_slots = RTE_SWX_PACKET_MIRRORING_SLOTS_DEFAULT;
9760 pipeline->n_mirroring_sessions = RTE_SWX_PACKET_MIRRORING_SESSIONS_DEFAULT;
9761 pipeline->numa_node = numa_node;
9762
9763 status = port_in_types_register(pipeline);
9764 if (status)
9765 goto error;
9766
9767 status = port_out_types_register(pipeline);
9768 if (status)
9769 goto error;
9770
9771 status = table_types_register(pipeline);
9772 if (status)
9773 goto error;
9774
9775 status = hash_funcs_register(pipeline);
9776 if (status)
9777 goto error;
9778
9779 *p = pipeline;
9780 return 0;
9781
9782error:
9783 rte_swx_pipeline_free(pipeline);
9784 return status;
9785}
9786
9787int
9788rte_swx_pipeline_instructions_config(struct rte_swx_pipeline *p,
9789 const char **instructions,
9790 uint32_t n_instructions)
9791{
9792 int err;
9793 uint32_t i;
9794
9795 err = instruction_config(p, NULL, instructions, n_instructions);
9796 if (err)
9797 return err;
9798
9799
9800 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9801 struct thread *t = &p->threads[i];
9802
9803 thread_ip_reset(p, t);
9804 }
9805
9806 return 0;
9807}
9808
9809static int
9810pipeline_compile(struct rte_swx_pipeline *p);
9811
9812int
9813rte_swx_pipeline_build(struct rte_swx_pipeline *p)
9814{
9815 struct rte_swx_port_sink_params drop_port_params = {
9816 .file_name = NULL,
9817 };
9818 int status;
9819
9820 CHECK(p, EINVAL);
9821 CHECK(p->build_done == 0, EEXIST);
9822
9823 status = port_in_build(p);
9824 if (status)
9825 goto error;
9826
9827
9828 status = rte_swx_pipeline_port_out_config(p,
9829 p->n_ports_out,
9830 "sink",
9831 &drop_port_params);
9832 if (status)
9833 goto error;
9834
9835 status = port_out_build(p);
9836 if (status)
9837 goto error;
9838
9839 status = mirroring_build(p);
9840 if (status)
9841 goto error;
9842
9843 status = struct_build(p);
9844 if (status)
9845 goto error;
9846
9847 status = extern_obj_build(p);
9848 if (status)
9849 goto error;
9850
9851 status = extern_func_build(p);
9852 if (status)
9853 goto error;
9854
9855 status = hash_func_build(p);
9856 if (status)
9857 goto error;
9858
9859 status = header_build(p);
9860 if (status)
9861 goto error;
9862
9863 status = metadata_build(p);
9864 if (status)
9865 goto error;
9866
9867 status = instruction_table_build(p);
9868 if (status)
9869 goto error;
9870
9871 status = action_build(p);
9872 if (status)
9873 goto error;
9874
9875 status = table_build(p);
9876 if (status)
9877 goto error;
9878
9879 status = selector_build(p);
9880 if (status)
9881 goto error;
9882
9883 status = learner_build(p);
9884 if (status)
9885 goto error;
9886
9887 status = table_state_build(p);
9888 if (status)
9889 goto error;
9890
9891 status = regarray_build(p);
9892 if (status)
9893 goto error;
9894
9895 status = metarray_build(p);
9896 if (status)
9897 goto error;
9898
9899 p->build_done = 1;
9900
9901 pipeline_compile(p);
9902
9903 return 0;
9904
9905error:
9906 metarray_build_free(p);
9907 regarray_build_free(p);
9908 table_state_build_free(p);
9909 learner_build_free(p);
9910 selector_build_free(p);
9911 table_build_free(p);
9912 action_build_free(p);
9913 instruction_table_build_free(p);
9914 metadata_build_free(p);
9915 header_build_free(p);
9916 hash_func_build_free(p);
9917 extern_func_build_free(p);
9918 extern_obj_build_free(p);
9919 mirroring_build_free(p);
9920 port_out_build_free(p);
9921 port_in_build_free(p);
9922 struct_build_free(p);
9923
9924 return status;
9925}
9926
9927void
9928rte_swx_pipeline_run(struct rte_swx_pipeline *p, uint32_t n_instructions)
9929{
9930 uint32_t i;
9931
9932 for (i = 0; i < n_instructions; i++)
9933 instr_exec(p);
9934}
9935
9936void
9937rte_swx_pipeline_flush(struct rte_swx_pipeline *p)
9938{
9939 uint32_t i;
9940
9941 for (i = 0; i < p->n_ports_out; i++) {
9942 struct port_out_runtime *port = &p->out[i];
9943
9944 if (port->flush)
9945 port->flush(port->obj);
9946 }
9947}
9948
9949
9950
9951
9952int
9953rte_swx_ctl_pipeline_info_get(struct rte_swx_pipeline *p,
9954 struct rte_swx_ctl_pipeline_info *pipeline)
9955{
9956 struct action *action;
9957 struct table *table;
9958 uint32_t n_actions = 0, n_tables = 0;
9959
9960 if (!p || !pipeline)
9961 return -EINVAL;
9962
9963 TAILQ_FOREACH(action, &p->actions, node)
9964 n_actions++;
9965
9966 TAILQ_FOREACH(table, &p->tables, node)
9967 n_tables++;
9968
9969 pipeline->n_ports_in = p->n_ports_in;
9970 pipeline->n_ports_out = p->n_ports_out;
9971 pipeline->n_mirroring_slots = p->n_mirroring_slots;
9972 pipeline->n_mirroring_sessions = p->n_mirroring_sessions;
9973 pipeline->n_actions = n_actions;
9974 pipeline->n_tables = n_tables;
9975 pipeline->n_selectors = p->n_selectors;
9976 pipeline->n_learners = p->n_learners;
9977 pipeline->n_regarrays = p->n_regarrays;
9978 pipeline->n_metarrays = p->n_metarrays;
9979
9980 return 0;
9981}
9982
9983int
9984rte_swx_ctl_pipeline_numa_node_get(struct rte_swx_pipeline *p, int *numa_node)
9985{
9986 if (!p || !numa_node)
9987 return -EINVAL;
9988
9989 *numa_node = p->numa_node;
9990 return 0;
9991}
9992
9993int
9994rte_swx_ctl_action_info_get(struct rte_swx_pipeline *p,
9995 uint32_t action_id,
9996 struct rte_swx_ctl_action_info *action)
9997{
9998 struct action *a = NULL;
9999
10000 if (!p || (action_id >= p->n_actions) || !action)
10001 return -EINVAL;
10002
10003 a = action_find_by_id(p, action_id);
10004 if (!a)
10005 return -EINVAL;
10006
10007 strcpy(action->name, a->name);
10008 action->n_args = a->st ? a->st->n_fields : 0;
10009 return 0;
10010}
10011
10012int
10013rte_swx_ctl_action_arg_info_get(struct rte_swx_pipeline *p,
10014 uint32_t action_id,
10015 uint32_t action_arg_id,
10016 struct rte_swx_ctl_action_arg_info *action_arg)
10017{
10018 struct action *a = NULL;
10019 struct field *arg = NULL;
10020
10021 if (!p || (action_id >= p->n_actions) || !action_arg)
10022 return -EINVAL;
10023
10024 a = action_find_by_id(p, action_id);
10025 if (!a || !a->st || (action_arg_id >= a->st->n_fields))
10026 return -EINVAL;
10027
10028 arg = &a->st->fields[action_arg_id];
10029 strcpy(action_arg->name, arg->name);
10030 action_arg->n_bits = arg->n_bits;
10031 action_arg->is_network_byte_order = a->args_endianness[action_arg_id];
10032
10033 return 0;
10034}
10035
10036int
10037rte_swx_ctl_table_info_get(struct rte_swx_pipeline *p,
10038 uint32_t table_id,
10039 struct rte_swx_ctl_table_info *table)
10040{
10041 struct table *t = NULL;
10042
10043 if (!p || !table)
10044 return -EINVAL;
10045
10046 t = table_find_by_id(p, table_id);
10047 if (!t)
10048 return -EINVAL;
10049
10050 strcpy(table->name, t->name);
10051 strcpy(table->args, t->args);
10052 table->n_match_fields = t->n_fields;
10053 table->n_actions = t->n_actions;
10054 table->default_action_is_const = t->default_action_is_const;
10055 table->size = t->size;
10056 return 0;
10057}
10058
10059int
10060rte_swx_ctl_table_match_field_info_get(struct rte_swx_pipeline *p,
10061 uint32_t table_id,
10062 uint32_t match_field_id,
10063 struct rte_swx_ctl_table_match_field_info *match_field)
10064{
10065 struct table *t;
10066 struct match_field *f;
10067
10068 if (!p || (table_id >= p->n_tables) || !match_field)
10069 return -EINVAL;
10070
10071 t = table_find_by_id(p, table_id);
10072 if (!t || (match_field_id >= t->n_fields))
10073 return -EINVAL;
10074
10075 f = &t->fields[match_field_id];
10076 match_field->match_type = f->match_type;
10077 match_field->is_header = t->header ? 1 : 0;
10078 match_field->n_bits = f->field->n_bits;
10079 match_field->offset = f->field->offset;
10080
10081 return 0;
10082}
10083
10084int
10085rte_swx_ctl_table_action_info_get(struct rte_swx_pipeline *p,
10086 uint32_t table_id,
10087 uint32_t table_action_id,
10088 struct rte_swx_ctl_table_action_info *table_action)
10089{
10090 struct table *t;
10091
10092 if (!p || (table_id >= p->n_tables) || !table_action)
10093 return -EINVAL;
10094
10095 t = table_find_by_id(p, table_id);
10096 if (!t || (table_action_id >= t->n_actions))
10097 return -EINVAL;
10098
10099 table_action->action_id = t->actions[table_action_id]->id;
10100
10101 table_action->action_is_for_table_entries = t->action_is_for_table_entries[table_action_id];
10102 table_action->action_is_for_default_entry = t->action_is_for_default_entry[table_action_id];
10103
10104 return 0;
10105}
10106
10107int
10108rte_swx_ctl_table_ops_get(struct rte_swx_pipeline *p,
10109 uint32_t table_id,
10110 struct rte_swx_table_ops *table_ops,
10111 int *is_stub)
10112{
10113 struct table *t;
10114
10115 if (!p || (table_id >= p->n_tables))
10116 return -EINVAL;
10117
10118 t = table_find_by_id(p, table_id);
10119 if (!t)
10120 return -EINVAL;
10121
10122 if (t->type) {
10123 if (table_ops)
10124 memcpy(table_ops, &t->type->ops, sizeof(*table_ops));
10125 *is_stub = 0;
10126 } else {
10127 *is_stub = 1;
10128 }
10129
10130 return 0;
10131}
10132
10133int
10134rte_swx_ctl_selector_info_get(struct rte_swx_pipeline *p,
10135 uint32_t selector_id,
10136 struct rte_swx_ctl_selector_info *selector)
10137{
10138 struct selector *s = NULL;
10139
10140 if (!p || !selector)
10141 return -EINVAL;
10142
10143 s = selector_find_by_id(p, selector_id);
10144 if (!s)
10145 return -EINVAL;
10146
10147 strcpy(selector->name, s->name);
10148
10149 selector->n_selector_fields = s->n_selector_fields;
10150 selector->n_groups_max = s->n_groups_max;
10151 selector->n_members_per_group_max = s->n_members_per_group_max;
10152
10153 return 0;
10154}
10155
10156int
10157rte_swx_ctl_selector_group_id_field_info_get(struct rte_swx_pipeline *p,
10158 uint32_t selector_id,
10159 struct rte_swx_ctl_table_match_field_info *field)
10160{
10161 struct selector *s;
10162
10163 if (!p || (selector_id >= p->n_selectors) || !field)
10164 return -EINVAL;
10165
10166 s = selector_find_by_id(p, selector_id);
10167 if (!s)
10168 return -EINVAL;
10169
10170 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10171 field->is_header = 0;
10172 field->n_bits = s->group_id_field->n_bits;
10173 field->offset = s->group_id_field->offset;
10174
10175 return 0;
10176}
10177
10178int
10179rte_swx_ctl_selector_field_info_get(struct rte_swx_pipeline *p,
10180 uint32_t selector_id,
10181 uint32_t selector_field_id,
10182 struct rte_swx_ctl_table_match_field_info *field)
10183{
10184 struct selector *s;
10185 struct field *f;
10186
10187 if (!p || (selector_id >= p->n_selectors) || !field)
10188 return -EINVAL;
10189
10190 s = selector_find_by_id(p, selector_id);
10191 if (!s || (selector_field_id >= s->n_selector_fields))
10192 return -EINVAL;
10193
10194 f = s->selector_fields[selector_field_id];
10195 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10196 field->is_header = s->selector_header ? 1 : 0;
10197 field->n_bits = f->n_bits;
10198 field->offset = f->offset;
10199
10200 return 0;
10201}
10202
10203int
10204rte_swx_ctl_selector_member_id_field_info_get(struct rte_swx_pipeline *p,
10205 uint32_t selector_id,
10206 struct rte_swx_ctl_table_match_field_info *field)
10207{
10208 struct selector *s;
10209
10210 if (!p || (selector_id >= p->n_selectors) || !field)
10211 return -EINVAL;
10212
10213 s = selector_find_by_id(p, selector_id);
10214 if (!s)
10215 return -EINVAL;
10216
10217 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10218 field->is_header = 0;
10219 field->n_bits = s->member_id_field->n_bits;
10220 field->offset = s->member_id_field->offset;
10221
10222 return 0;
10223}
10224
10225int
10226rte_swx_ctl_learner_info_get(struct rte_swx_pipeline *p,
10227 uint32_t learner_id,
10228 struct rte_swx_ctl_learner_info *learner)
10229{
10230 struct learner *l = NULL;
10231
10232 if (!p || !learner)
10233 return -EINVAL;
10234
10235 l = learner_find_by_id(p, learner_id);
10236 if (!l)
10237 return -EINVAL;
10238
10239 strcpy(learner->name, l->name);
10240
10241 learner->n_match_fields = l->n_fields;
10242 learner->n_actions = l->n_actions;
10243 learner->default_action_is_const = l->default_action_is_const;
10244 learner->size = l->size;
10245 learner->n_key_timeouts = l->n_timeouts;
10246
10247 return 0;
10248}
10249
10250int
10251rte_swx_ctl_learner_match_field_info_get(struct rte_swx_pipeline *p,
10252 uint32_t learner_id,
10253 uint32_t match_field_id,
10254 struct rte_swx_ctl_table_match_field_info *match_field)
10255{
10256 struct learner *l;
10257 struct field *f;
10258
10259 if (!p || (learner_id >= p->n_learners) || !match_field)
10260 return -EINVAL;
10261
10262 l = learner_find_by_id(p, learner_id);
10263 if (!l || (match_field_id >= l->n_fields))
10264 return -EINVAL;
10265
10266 f = l->fields[match_field_id];
10267 match_field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10268 match_field->is_header = l->header ? 1 : 0;
10269 match_field->n_bits = f->n_bits;
10270 match_field->offset = f->offset;
10271
10272 return 0;
10273}
10274
10275int
10276rte_swx_ctl_learner_action_info_get(struct rte_swx_pipeline *p,
10277 uint32_t learner_id,
10278 uint32_t learner_action_id,
10279 struct rte_swx_ctl_table_action_info *learner_action)
10280{
10281 struct learner *l;
10282
10283 if (!p || (learner_id >= p->n_learners) || !learner_action)
10284 return -EINVAL;
10285
10286 l = learner_find_by_id(p, learner_id);
10287 if (!l || (learner_action_id >= l->n_actions))
10288 return -EINVAL;
10289
10290 learner_action->action_id = l->actions[learner_action_id]->id;
10291
10292 learner_action->action_is_for_table_entries =
10293 l->action_is_for_table_entries[learner_action_id];
10294
10295 learner_action->action_is_for_default_entry =
10296 l->action_is_for_default_entry[learner_action_id];
10297
10298 return 0;
10299}
10300
10301int
10302rte_swx_ctl_pipeline_learner_timeout_get(struct rte_swx_pipeline *p,
10303 uint32_t learner_id,
10304 uint32_t timeout_id,
10305 uint32_t *timeout)
10306{
10307 struct learner *l;
10308
10309 if (!p || (learner_id >= p->n_learners) || !timeout)
10310 return -EINVAL;
10311
10312 l = learner_find_by_id(p, learner_id);
10313 if (!l || (timeout_id >= l->n_timeouts))
10314 return -EINVAL;
10315
10316 *timeout = l->timeout[timeout_id];
10317 return 0;
10318}
10319
10320int
10321rte_swx_ctl_pipeline_learner_timeout_set(struct rte_swx_pipeline *p,
10322 uint32_t learner_id,
10323 uint32_t timeout_id,
10324 uint32_t timeout)
10325{
10326 struct learner *l;
10327 struct rte_swx_table_state *ts;
10328 int status;
10329
10330 if (!p || (learner_id >= p->n_learners) || !timeout)
10331 return -EINVAL;
10332
10333 l = learner_find_by_id(p, learner_id);
10334 if (!l || (timeout_id >= l->n_timeouts))
10335 return -EINVAL;
10336
10337 if (!p->build_done)
10338 return -EINVAL;
10339
10340 ts = &p->table_state[p->n_tables + p->n_selectors + l->id];
10341
10342 status = rte_swx_table_learner_timeout_update(ts->obj, timeout_id, timeout);
10343 if (status)
10344 return -EINVAL;
10345
10346 l->timeout[timeout_id] = timeout;
10347
10348 return 0;
10349}
10350
10351int
10352rte_swx_pipeline_table_state_get(struct rte_swx_pipeline *p,
10353 struct rte_swx_table_state **table_state)
10354{
10355 if (!p || !table_state || !p->build_done)
10356 return -EINVAL;
10357
10358 *table_state = p->table_state;
10359 return 0;
10360}
10361
10362int
10363rte_swx_pipeline_table_state_set(struct rte_swx_pipeline *p,
10364 struct rte_swx_table_state *table_state)
10365{
10366 if (!p || !table_state || !p->build_done)
10367 return -EINVAL;
10368
10369 p->table_state = table_state;
10370 return 0;
10371}
10372
10373int
10374rte_swx_ctl_pipeline_port_in_stats_read(struct rte_swx_pipeline *p,
10375 uint32_t port_id,
10376 struct rte_swx_port_in_stats *stats)
10377{
10378 struct port_in *port;
10379
10380 if (!p || !stats)
10381 return -EINVAL;
10382
10383 port = port_in_find(p, port_id);
10384 if (!port)
10385 return -EINVAL;
10386
10387 port->type->ops.stats_read(port->obj, stats);
10388 return 0;
10389}
10390
10391int
10392rte_swx_ctl_pipeline_port_out_stats_read(struct rte_swx_pipeline *p,
10393 uint32_t port_id,
10394 struct rte_swx_port_out_stats *stats)
10395{
10396 struct port_out *port;
10397
10398 if (!p || !stats)
10399 return -EINVAL;
10400
10401 port = port_out_find(p, port_id);
10402 if (!port)
10403 return -EINVAL;
10404
10405 port->type->ops.stats_read(port->obj, stats);
10406 return 0;
10407}
10408
10409int
10410rte_swx_ctl_pipeline_table_stats_read(struct rte_swx_pipeline *p,
10411 const char *table_name,
10412 struct rte_swx_table_stats *stats)
10413{
10414 struct table *table;
10415 struct table_statistics *table_stats;
10416
10417 if (!p || !table_name || !table_name[0] || !stats || !stats->n_pkts_action)
10418 return -EINVAL;
10419
10420 table = table_find(p, table_name);
10421 if (!table)
10422 return -EINVAL;
10423
10424 table_stats = &p->table_stats[table->id];
10425
10426 memcpy(stats->n_pkts_action,
10427 table_stats->n_pkts_action,
10428 p->n_actions * sizeof(uint64_t));
10429
10430 stats->n_pkts_hit = table_stats->n_pkts_hit[1];
10431 stats->n_pkts_miss = table_stats->n_pkts_hit[0];
10432
10433 return 0;
10434}
10435
10436int
10437rte_swx_ctl_pipeline_selector_stats_read(struct rte_swx_pipeline *p,
10438 const char *selector_name,
10439 struct rte_swx_pipeline_selector_stats *stats)
10440{
10441 struct selector *s;
10442
10443 if (!p || !selector_name || !selector_name[0] || !stats)
10444 return -EINVAL;
10445
10446 s = selector_find(p, selector_name);
10447 if (!s)
10448 return -EINVAL;
10449
10450 stats->n_pkts = p->selector_stats[s->id].n_pkts;
10451
10452 return 0;
10453}
10454
10455int
10456rte_swx_ctl_pipeline_learner_stats_read(struct rte_swx_pipeline *p,
10457 const char *learner_name,
10458 struct rte_swx_learner_stats *stats)
10459{
10460 struct learner *l;
10461 struct learner_statistics *learner_stats;
10462
10463 if (!p || !learner_name || !learner_name[0] || !stats || !stats->n_pkts_action)
10464 return -EINVAL;
10465
10466 l = learner_find(p, learner_name);
10467 if (!l)
10468 return -EINVAL;
10469
10470 learner_stats = &p->learner_stats[l->id];
10471
10472 memcpy(stats->n_pkts_action,
10473 learner_stats->n_pkts_action,
10474 p->n_actions * sizeof(uint64_t));
10475
10476 stats->n_pkts_hit = learner_stats->n_pkts_hit[1];
10477 stats->n_pkts_miss = learner_stats->n_pkts_hit[0];
10478
10479 stats->n_pkts_learn_ok = learner_stats->n_pkts_learn[0];
10480 stats->n_pkts_learn_err = learner_stats->n_pkts_learn[1];
10481
10482 stats->n_pkts_rearm = learner_stats->n_pkts_rearm;
10483 stats->n_pkts_forget = learner_stats->n_pkts_forget;
10484
10485 return 0;
10486}
10487
10488int
10489rte_swx_ctl_regarray_info_get(struct rte_swx_pipeline *p,
10490 uint32_t regarray_id,
10491 struct rte_swx_ctl_regarray_info *regarray)
10492{
10493 struct regarray *r;
10494
10495 if (!p || !regarray)
10496 return -EINVAL;
10497
10498 r = regarray_find_by_id(p, regarray_id);
10499 if (!r)
10500 return -EINVAL;
10501
10502 strcpy(regarray->name, r->name);
10503 regarray->size = r->size;
10504 return 0;
10505}
10506
10507int
10508rte_swx_ctl_pipeline_regarray_read(struct rte_swx_pipeline *p,
10509 const char *regarray_name,
10510 uint32_t regarray_index,
10511 uint64_t *value)
10512{
10513 struct regarray *regarray;
10514 struct regarray_runtime *r;
10515
10516 if (!p || !regarray_name || !value)
10517 return -EINVAL;
10518
10519 regarray = regarray_find(p, regarray_name);
10520 if (!regarray || (regarray_index >= regarray->size))
10521 return -EINVAL;
10522
10523 r = &p->regarray_runtime[regarray->id];
10524 *value = r->regarray[regarray_index];
10525 return 0;
10526}
10527
10528int
10529rte_swx_ctl_pipeline_regarray_write(struct rte_swx_pipeline *p,
10530 const char *regarray_name,
10531 uint32_t regarray_index,
10532 uint64_t value)
10533{
10534 struct regarray *regarray;
10535 struct regarray_runtime *r;
10536
10537 if (!p || !regarray_name)
10538 return -EINVAL;
10539
10540 regarray = regarray_find(p, regarray_name);
10541 if (!regarray || (regarray_index >= regarray->size))
10542 return -EINVAL;
10543
10544 r = &p->regarray_runtime[regarray->id];
10545 r->regarray[regarray_index] = value;
10546 return 0;
10547}
10548
10549int
10550rte_swx_ctl_metarray_info_get(struct rte_swx_pipeline *p,
10551 uint32_t metarray_id,
10552 struct rte_swx_ctl_metarray_info *metarray)
10553{
10554 struct metarray *m;
10555
10556 if (!p || !metarray)
10557 return -EINVAL;
10558
10559 m = metarray_find_by_id(p, metarray_id);
10560 if (!m)
10561 return -EINVAL;
10562
10563 strcpy(metarray->name, m->name);
10564 metarray->size = m->size;
10565 return 0;
10566}
10567
10568int
10569rte_swx_ctl_meter_profile_add(struct rte_swx_pipeline *p,
10570 const char *name,
10571 struct rte_meter_trtcm_params *params)
10572{
10573 struct meter_profile *mp;
10574 int status;
10575
10576 CHECK(p, EINVAL);
10577 CHECK_NAME(name, EINVAL);
10578 CHECK(params, EINVAL);
10579 CHECK(!meter_profile_find(p, name), EEXIST);
10580
10581
10582 mp = calloc(1, sizeof(struct meter_profile));
10583 CHECK(mp, ENOMEM);
10584
10585
10586 strcpy(mp->name, name);
10587 memcpy(&mp->params, params, sizeof(struct rte_meter_trtcm_params));
10588 status = rte_meter_trtcm_profile_config(&mp->profile, params);
10589 if (status) {
10590 free(mp);
10591 CHECK(0, EINVAL);
10592 }
10593
10594
10595 TAILQ_INSERT_TAIL(&p->meter_profiles, mp, node);
10596
10597 return 0;
10598}
10599
10600int
10601rte_swx_ctl_meter_profile_delete(struct rte_swx_pipeline *p,
10602 const char *name)
10603{
10604 struct meter_profile *mp;
10605
10606 CHECK(p, EINVAL);
10607 CHECK_NAME(name, EINVAL);
10608
10609 mp = meter_profile_find(p, name);
10610 CHECK(mp, EINVAL);
10611 CHECK(!mp->n_users, EBUSY);
10612
10613
10614 TAILQ_REMOVE(&p->meter_profiles, mp, node);
10615 free(mp);
10616
10617 return 0;
10618}
10619
10620int
10621rte_swx_ctl_meter_reset(struct rte_swx_pipeline *p,
10622 const char *metarray_name,
10623 uint32_t metarray_index)
10624{
10625 struct meter_profile *mp_old;
10626 struct metarray *metarray;
10627 struct metarray_runtime *metarray_runtime;
10628 struct meter *m;
10629
10630 CHECK(p, EINVAL);
10631 CHECK_NAME(metarray_name, EINVAL);
10632
10633 metarray = metarray_find(p, metarray_name);
10634 CHECK(metarray, EINVAL);
10635 CHECK(metarray_index < metarray->size, EINVAL);
10636
10637 metarray_runtime = &p->metarray_runtime[metarray->id];
10638 m = &metarray_runtime->metarray[metarray_index];
10639 mp_old = m->profile;
10640
10641 meter_init(m);
10642
10643 mp_old->n_users--;
10644
10645 return 0;
10646}
10647
10648int
10649rte_swx_ctl_meter_set(struct rte_swx_pipeline *p,
10650 const char *metarray_name,
10651 uint32_t metarray_index,
10652 const char *profile_name)
10653{
10654 struct meter_profile *mp, *mp_old;
10655 struct metarray *metarray;
10656 struct metarray_runtime *metarray_runtime;
10657 struct meter *m;
10658
10659 CHECK(p, EINVAL);
10660 CHECK_NAME(metarray_name, EINVAL);
10661
10662 metarray = metarray_find(p, metarray_name);
10663 CHECK(metarray, EINVAL);
10664 CHECK(metarray_index < metarray->size, EINVAL);
10665
10666 mp = meter_profile_find(p, profile_name);
10667 CHECK(mp, EINVAL);
10668
10669 metarray_runtime = &p->metarray_runtime[metarray->id];
10670 m = &metarray_runtime->metarray[metarray_index];
10671 mp_old = m->profile;
10672
10673 memset(m, 0, sizeof(struct meter));
10674 rte_meter_trtcm_config(&m->m, &mp->profile);
10675 m->profile = mp;
10676 m->color_mask = RTE_COLORS;
10677
10678 mp->n_users++;
10679 mp_old->n_users--;
10680
10681 return 0;
10682}
10683
10684int
10685rte_swx_ctl_meter_stats_read(struct rte_swx_pipeline *p,
10686 const char *metarray_name,
10687 uint32_t metarray_index,
10688 struct rte_swx_ctl_meter_stats *stats)
10689{
10690 struct metarray *metarray;
10691 struct metarray_runtime *metarray_runtime;
10692 struct meter *m;
10693
10694 CHECK(p, EINVAL);
10695 CHECK_NAME(metarray_name, EINVAL);
10696
10697 metarray = metarray_find(p, metarray_name);
10698 CHECK(metarray, EINVAL);
10699 CHECK(metarray_index < metarray->size, EINVAL);
10700
10701 CHECK(stats, EINVAL);
10702
10703 metarray_runtime = &p->metarray_runtime[metarray->id];
10704 m = &metarray_runtime->metarray[metarray_index];
10705
10706 memcpy(stats->n_pkts, m->n_pkts, sizeof(m->n_pkts));
10707 memcpy(stats->n_bytes, m->n_bytes, sizeof(m->n_bytes));
10708
10709 return 0;
10710}
10711
10712int
10713rte_swx_ctl_pipeline_mirroring_session_set(struct rte_swx_pipeline *p,
10714 uint32_t session_id,
10715 struct rte_swx_pipeline_mirroring_session_params *params)
10716{
10717 struct mirroring_session *s;
10718
10719 CHECK(p, EINVAL);
10720 CHECK(p->build_done, EEXIST);
10721 CHECK(session_id < p->n_mirroring_sessions, EINVAL);
10722 CHECK(params, EINVAL);
10723 CHECK(params->port_id < p->n_ports_out, EINVAL);
10724
10725 s = &p->mirroring_sessions[session_id];
10726 s->port_id = params->port_id;
10727 s->fast_clone = params->fast_clone;
10728 s->truncation_length = params->truncation_length ? params->truncation_length : UINT32_MAX;
10729
10730 return 0;
10731}
10732
10733
10734
10735
10736static const char *
10737instr_type_to_name(struct instruction *instr)
10738{
10739 switch (instr->type) {
10740 case INSTR_RX: return "INSTR_RX";
10741
10742 case INSTR_TX: return "INSTR_TX";
10743 case INSTR_TX_I: return "INSTR_TX_I";
10744 case INSTR_DROP: return "INSTR_DROP";
10745 case INSTR_MIRROR: return "INSTR_MIRROR";
10746 case INSTR_RECIRCULATE: return "INSTR_RECIRCULATE";
10747 case INSTR_RECIRCID: return "INSTR_RECIRCID";
10748
10749 case INSTR_HDR_EXTRACT: return "INSTR_HDR_EXTRACT";
10750 case INSTR_HDR_EXTRACT2: return "INSTR_HDR_EXTRACT2";
10751 case INSTR_HDR_EXTRACT3: return "INSTR_HDR_EXTRACT3";
10752 case INSTR_HDR_EXTRACT4: return "INSTR_HDR_EXTRACT4";
10753 case INSTR_HDR_EXTRACT5: return "INSTR_HDR_EXTRACT5";
10754 case INSTR_HDR_EXTRACT6: return "INSTR_HDR_EXTRACT6";
10755 case INSTR_HDR_EXTRACT7: return "INSTR_HDR_EXTRACT7";
10756 case INSTR_HDR_EXTRACT8: return "INSTR_HDR_EXTRACT8";
10757
10758 case INSTR_HDR_EXTRACT_M: return "INSTR_HDR_EXTRACT_M";
10759
10760 case INSTR_HDR_LOOKAHEAD: return "INSTR_HDR_LOOKAHEAD";
10761
10762 case INSTR_HDR_EMIT: return "INSTR_HDR_EMIT";
10763 case INSTR_HDR_EMIT_TX: return "INSTR_HDR_EMIT_TX";
10764 case INSTR_HDR_EMIT2_TX: return "INSTR_HDR_EMIT2_TX";
10765 case INSTR_HDR_EMIT3_TX: return "INSTR_HDR_EMIT3_TX";
10766 case INSTR_HDR_EMIT4_TX: return "INSTR_HDR_EMIT4_TX";
10767 case INSTR_HDR_EMIT5_TX: return "INSTR_HDR_EMIT5_TX";
10768 case INSTR_HDR_EMIT6_TX: return "INSTR_HDR_EMIT6_TX";
10769 case INSTR_HDR_EMIT7_TX: return "INSTR_HDR_EMIT7_TX";
10770 case INSTR_HDR_EMIT8_TX: return "INSTR_HDR_EMIT8_TX";
10771
10772 case INSTR_HDR_VALIDATE: return "INSTR_HDR_VALIDATE";
10773 case INSTR_HDR_INVALIDATE: return "INSTR_HDR_INVALIDATE";
10774
10775 case INSTR_MOV: return "INSTR_MOV";
10776 case INSTR_MOV_MH: return "INSTR_MOV_MH";
10777 case INSTR_MOV_HM: return "INSTR_MOV_HM";
10778 case INSTR_MOV_HH: return "INSTR_MOV_HH";
10779 case INSTR_MOV_I: return "INSTR_MOV_I";
10780
10781 case INSTR_DMA_HT: return "INSTR_DMA_HT";
10782 case INSTR_DMA_HT2: return "INSTR_DMA_HT2";
10783 case INSTR_DMA_HT3: return "INSTR_DMA_HT3";
10784 case INSTR_DMA_HT4: return "INSTR_DMA_HT4";
10785 case INSTR_DMA_HT5: return "INSTR_DMA_HT5";
10786 case INSTR_DMA_HT6: return "INSTR_DMA_HT6";
10787 case INSTR_DMA_HT7: return "INSTR_DMA_HT7";
10788 case INSTR_DMA_HT8: return "INSTR_DMA_HT8";
10789
10790 case INSTR_ALU_ADD: return "INSTR_ALU_ADD";
10791 case INSTR_ALU_ADD_MH: return "INSTR_ALU_ADD_MH";
10792 case INSTR_ALU_ADD_HM: return "INSTR_ALU_ADD_HM";
10793 case INSTR_ALU_ADD_HH: return "INSTR_ALU_ADD_HH";
10794 case INSTR_ALU_ADD_MI: return "INSTR_ALU_ADD_MI";
10795 case INSTR_ALU_ADD_HI: return "INSTR_ALU_ADD_HI";
10796
10797 case INSTR_ALU_SUB: return "INSTR_ALU_SUB";
10798 case INSTR_ALU_SUB_MH: return "INSTR_ALU_SUB_MH";
10799 case INSTR_ALU_SUB_HM: return "INSTR_ALU_SUB_HM";
10800 case INSTR_ALU_SUB_HH: return "INSTR_ALU_SUB_HH";
10801 case INSTR_ALU_SUB_MI: return "INSTR_ALU_SUB_MI";
10802 case INSTR_ALU_SUB_HI: return "INSTR_ALU_SUB_HI";
10803
10804 case INSTR_ALU_CKADD_FIELD: return "INSTR_ALU_CKADD_FIELD";
10805 case INSTR_ALU_CKADD_STRUCT20: return "INSTR_ALU_CKADD_STRUCT20";
10806 case INSTR_ALU_CKADD_STRUCT: return "INSTR_ALU_CKADD_STRUCT";
10807 case INSTR_ALU_CKSUB_FIELD: return "INSTR_ALU_CKSUB_FIELD";
10808
10809 case INSTR_ALU_AND: return "INSTR_ALU_AND";
10810 case INSTR_ALU_AND_MH: return "INSTR_ALU_AND_MH";
10811 case INSTR_ALU_AND_HM: return "INSTR_ALU_AND_HM";
10812 case INSTR_ALU_AND_HH: return "INSTR_ALU_AND_HH";
10813 case INSTR_ALU_AND_I: return "INSTR_ALU_AND_I";
10814
10815 case INSTR_ALU_OR: return "INSTR_ALU_OR";
10816 case INSTR_ALU_OR_MH: return "INSTR_ALU_OR_MH";
10817 case INSTR_ALU_OR_HM: return "INSTR_ALU_OR_HM";
10818 case INSTR_ALU_OR_HH: return "INSTR_ALU_OR_HH";
10819 case INSTR_ALU_OR_I: return "INSTR_ALU_OR_I";
10820
10821 case INSTR_ALU_XOR: return "INSTR_ALU_XOR";
10822 case INSTR_ALU_XOR_MH: return "INSTR_ALU_XOR_MH";
10823 case INSTR_ALU_XOR_HM: return "INSTR_ALU_XOR_HM";
10824 case INSTR_ALU_XOR_HH: return "INSTR_ALU_XOR_HH";
10825 case INSTR_ALU_XOR_I: return "INSTR_ALU_XOR_I";
10826
10827 case INSTR_ALU_SHL: return "INSTR_ALU_SHL";
10828 case INSTR_ALU_SHL_MH: return "INSTR_ALU_SHL_MH";
10829 case INSTR_ALU_SHL_HM: return "INSTR_ALU_SHL_HM";
10830 case INSTR_ALU_SHL_HH: return "INSTR_ALU_SHL_HH";
10831 case INSTR_ALU_SHL_MI: return "INSTR_ALU_SHL_MI";
10832 case INSTR_ALU_SHL_HI: return "INSTR_ALU_SHL_HI";
10833
10834 case INSTR_ALU_SHR: return "INSTR_ALU_SHR";
10835 case INSTR_ALU_SHR_MH: return "INSTR_ALU_SHR_MH";
10836 case INSTR_ALU_SHR_HM: return "INSTR_ALU_SHR_HM";
10837 case INSTR_ALU_SHR_HH: return "INSTR_ALU_SHR_HH";
10838 case INSTR_ALU_SHR_MI: return "INSTR_ALU_SHR_MI";
10839 case INSTR_ALU_SHR_HI: return "INSTR_ALU_SHR_HI";
10840
10841 case INSTR_REGPREFETCH_RH: return "INSTR_REGPREFETCH_RH";
10842 case INSTR_REGPREFETCH_RM: return "INSTR_REGPREFETCH_RM";
10843 case INSTR_REGPREFETCH_RI: return "INSTR_REGPREFETCH_RI";
10844
10845 case INSTR_REGRD_HRH: return "INSTR_REGRD_HRH";
10846 case INSTR_REGRD_HRM: return "INSTR_REGRD_HRM";
10847 case INSTR_REGRD_HRI: return "INSTR_REGRD_HRI";
10848 case INSTR_REGRD_MRH: return "INSTR_REGRD_MRH";
10849 case INSTR_REGRD_MRM: return "INSTR_REGRD_MRM";
10850 case INSTR_REGRD_MRI: return "INSTR_REGRD_MRI";
10851
10852 case INSTR_REGWR_RHH: return "INSTR_REGWR_RHH";
10853 case INSTR_REGWR_RHM: return "INSTR_REGWR_RHM";
10854 case INSTR_REGWR_RHI: return "INSTR_REGWR_RHI";
10855 case INSTR_REGWR_RMH: return "INSTR_REGWR_RMH";
10856 case INSTR_REGWR_RMM: return "INSTR_REGWR_RMM";
10857 case INSTR_REGWR_RMI: return "INSTR_REGWR_RMI";
10858 case INSTR_REGWR_RIH: return "INSTR_REGWR_RIH";
10859 case INSTR_REGWR_RIM: return "INSTR_REGWR_RIM";
10860 case INSTR_REGWR_RII: return "INSTR_REGWR_RII";
10861
10862 case INSTR_REGADD_RHH: return "INSTR_REGADD_RHH";
10863 case INSTR_REGADD_RHM: return "INSTR_REGADD_RHM";
10864 case INSTR_REGADD_RHI: return "INSTR_REGADD_RHI";
10865 case INSTR_REGADD_RMH: return "INSTR_REGADD_RMH";
10866 case INSTR_REGADD_RMM: return "INSTR_REGADD_RMM";
10867 case INSTR_REGADD_RMI: return "INSTR_REGADD_RMI";
10868 case INSTR_REGADD_RIH: return "INSTR_REGADD_RIH";
10869 case INSTR_REGADD_RIM: return "INSTR_REGADD_RIM";
10870 case INSTR_REGADD_RII: return "INSTR_REGADD_RII";
10871
10872 case INSTR_METPREFETCH_H: return "INSTR_METPREFETCH_H";
10873 case INSTR_METPREFETCH_M: return "INSTR_METPREFETCH_M";
10874 case INSTR_METPREFETCH_I: return "INSTR_METPREFETCH_I";
10875
10876 case INSTR_METER_HHM: return "INSTR_METER_HHM";
10877 case INSTR_METER_HHI: return "INSTR_METER_HHI";
10878 case INSTR_METER_HMM: return "INSTR_METER_HMM";
10879 case INSTR_METER_HMI: return "INSTR_METER_HMI";
10880 case INSTR_METER_MHM: return "INSTR_METER_MHM";
10881 case INSTR_METER_MHI: return "INSTR_METER_MHI";
10882 case INSTR_METER_MMM: return "INSTR_METER_MMM";
10883 case INSTR_METER_MMI: return "INSTR_METER_MMI";
10884 case INSTR_METER_IHM: return "INSTR_METER_IHM";
10885 case INSTR_METER_IHI: return "INSTR_METER_IHI";
10886 case INSTR_METER_IMM: return "INSTR_METER_IMM";
10887 case INSTR_METER_IMI: return "INSTR_METER_IMI";
10888
10889 case INSTR_TABLE: return "INSTR_TABLE";
10890 case INSTR_TABLE_AF: return "INSTR_TABLE_AF";
10891 case INSTR_SELECTOR: return "INSTR_SELECTOR";
10892 case INSTR_LEARNER: return "INSTR_LEARNER";
10893 case INSTR_LEARNER_AF: return "INSTR_LEARNER_AF";
10894
10895 case INSTR_LEARNER_LEARN: return "INSTR_LEARNER_LEARN";
10896 case INSTR_LEARNER_REARM: return "INSTR_LEARNER_REARM";
10897 case INSTR_LEARNER_REARM_NEW: return "INSTR_LEARNER_REARM_NEW";
10898 case INSTR_LEARNER_FORGET: return "INSTR_LEARNER_FORGET";
10899
10900 case INSTR_EXTERN_OBJ: return "INSTR_EXTERN_OBJ";
10901 case INSTR_EXTERN_FUNC: return "INSTR_EXTERN_FUNC";
10902 case INSTR_HASH_FUNC: return "INSTR_HASH_FUNC";
10903
10904 case INSTR_JMP: return "INSTR_JMP";
10905 case INSTR_JMP_VALID: return "INSTR_JMP_VALID";
10906 case INSTR_JMP_INVALID: return "INSTR_JMP_INVALID";
10907 case INSTR_JMP_HIT: return "INSTR_JMP_HIT";
10908 case INSTR_JMP_MISS: return "INSTR_JMP_MISS";
10909 case INSTR_JMP_ACTION_HIT: return "INSTR_JMP_ACTION_HIT";
10910 case INSTR_JMP_ACTION_MISS: return "INSTR_JMP_ACTION_MISS";
10911 case INSTR_JMP_EQ: return "INSTR_JMP_EQ";
10912 case INSTR_JMP_EQ_MH: return "INSTR_JMP_EQ_MH";
10913 case INSTR_JMP_EQ_HM: return "INSTR_JMP_EQ_HM";
10914 case INSTR_JMP_EQ_HH: return "INSTR_JMP_EQ_HH";
10915 case INSTR_JMP_EQ_I: return "INSTR_JMP_EQ_I";
10916 case INSTR_JMP_NEQ: return "INSTR_JMP_NEQ";
10917 case INSTR_JMP_NEQ_MH: return "INSTR_JMP_NEQ_MH";
10918 case INSTR_JMP_NEQ_HM: return "INSTR_JMP_NEQ_HM";
10919 case INSTR_JMP_NEQ_HH: return "INSTR_JMP_NEQ_HH";
10920 case INSTR_JMP_NEQ_I: return "INSTR_JMP_NEQ_I";
10921 case INSTR_JMP_LT: return "INSTR_JMP_LT";
10922 case INSTR_JMP_LT_MH: return "INSTR_JMP_LT_MH";
10923 case INSTR_JMP_LT_HM: return "INSTR_JMP_LT_HM";
10924 case INSTR_JMP_LT_HH: return "INSTR_JMP_LT_HH";
10925 case INSTR_JMP_LT_MI: return "INSTR_JMP_LT_MI";
10926 case INSTR_JMP_LT_HI: return "INSTR_JMP_LT_HI";
10927 case INSTR_JMP_GT: return "INSTR_JMP_GT";
10928 case INSTR_JMP_GT_MH: return "INSTR_JMP_GT_MH";
10929 case INSTR_JMP_GT_HM: return "INSTR_JMP_GT_HM";
10930 case INSTR_JMP_GT_HH: return "INSTR_JMP_GT_HH";
10931 case INSTR_JMP_GT_MI: return "INSTR_JMP_GT_MI";
10932 case INSTR_JMP_GT_HI: return "INSTR_JMP_GT_HI";
10933
10934 case INSTR_RETURN: return "INSTR_RETURN";
10935
10936 default: return "INSTR_UNKNOWN";
10937 }
10938}
10939
10940typedef void
10941(*instruction_export_t)(struct instruction *, FILE *);
10942
10943static void
10944instr_io_export(struct instruction *instr, FILE *f)
10945{
10946 uint32_t n_io = 0, n_io_imm = 0, n_hdrs = 0, i;
10947
10948
10949 if (instr->type == INSTR_RX ||
10950 instr->type == INSTR_TX ||
10951 instr->type == INSTR_HDR_EXTRACT_M ||
10952 (instr->type >= INSTR_HDR_EMIT_TX && instr->type <= INSTR_HDR_EMIT8_TX))
10953 n_io = 1;
10954
10955 if (instr->type == INSTR_TX_I)
10956 n_io_imm = 1;
10957
10958 if (instr->type >= INSTR_HDR_EXTRACT && instr->type <= INSTR_HDR_EXTRACT8)
10959 n_hdrs = 1 + (instr->type - INSTR_HDR_EXTRACT);
10960
10961 if (instr->type == INSTR_HDR_EXTRACT_M ||
10962 instr->type == INSTR_HDR_LOOKAHEAD ||
10963 instr->type == INSTR_HDR_EMIT)
10964 n_hdrs = 1;
10965
10966 if (instr->type >= INSTR_HDR_EMIT_TX && instr->type <= INSTR_HDR_EMIT8_TX)
10967 n_hdrs = 1 + (instr->type - INSTR_HDR_EMIT_TX);
10968
10969
10970 fprintf(f,
10971 "\t{\n"
10972 "\t\t.type = %s,\n",
10973 instr_type_to_name(instr));
10974
10975
10976 if (n_io || n_io_imm || n_hdrs)
10977 fprintf(f,
10978 "\t\t.io = {\n");
10979
10980
10981 if (n_io)
10982 fprintf(f,
10983 "\t\t\t.io = {\n"
10984 "\t\t\t\t.offset = %u,\n"
10985 "\t\t\t\t.n_bits = %u,\n"
10986 "\t\t\t},\n",
10987 instr->io.io.offset,
10988 instr->io.io.n_bits);
10989
10990 if (n_io_imm)
10991 fprintf(f,
10992 "\t\t\t.io = {\n"
10993 "\t\t\t\t.val = %u,\n"
10994 "\t\t\t},\n",
10995 instr->io.io.val);
10996
10997
10998 if (n_hdrs) {
10999 fprintf(f,
11000 "\t\t.hdr = {\n");
11001
11002
11003 fprintf(f,
11004 "\t\t\t.header_id = {");
11005
11006 for (i = 0; i < n_hdrs; i++)
11007 fprintf(f,
11008 "%u, ",
11009 instr->io.hdr.header_id[i]);
11010
11011 fprintf(f,
11012 "},\n");
11013
11014
11015 fprintf(f,
11016 "\t\t\t.struct_id = {");
11017
11018 for (i = 0; i < n_hdrs; i++)
11019 fprintf(f,
11020 "%u, ",
11021 instr->io.hdr.struct_id[i]);
11022
11023 fprintf(f,
11024 "},\n");
11025
11026
11027 fprintf(f,
11028 "\t\t\t.n_bytes = {");
11029
11030 for (i = 0; i < n_hdrs; i++)
11031 fprintf(f,
11032 "%u, ",
11033 instr->io.hdr.n_bytes[i]);
11034
11035 fprintf(f,
11036 "},\n");
11037
11038
11039 fprintf(f,
11040 "\t\t\t}\n,");
11041 }
11042
11043
11044 if (n_io || n_io_imm || n_hdrs)
11045 fprintf(f,
11046 "\t\t},\n");
11047
11048
11049 fprintf(f,
11050 "\t},\n");
11051}
11052
11053static void
11054instr_mirror_export(struct instruction *instr, FILE *f)
11055{
11056 fprintf(f,
11057 "\t{\n"
11058 "\t\t.type = %s,\n"
11059 "\t\t.mirror = {\n"
11060 "\t\t\t.dst = {\n"
11061 "\t\t\t\t.struct_id = %u,\n"
11062 "\t\t\t\t.n_bits = %u,\n"
11063 "\t\t\t\t.offset = %u,\n"
11064 "\t\t\t}\n,"
11065 "\t\t\t.src = {\n"
11066 "\t\t\t\t.struct_id = %u,\n"
11067 "\t\t\t\t.n_bits = %u,\n"
11068 "\t\t\t\t.offset = %u,\n"
11069 "\t\t\t}\n,"
11070 "\t\t},\n"
11071 "\t},\n",
11072 instr_type_to_name(instr),
11073 instr->mirror.dst.struct_id,
11074 instr->mirror.dst.n_bits,
11075 instr->mirror.dst.offset,
11076 instr->mirror.src.struct_id,
11077 instr->mirror.src.n_bits,
11078 instr->mirror.src.offset);
11079}
11080
11081static void
11082instr_recirculate_export(struct instruction *instr, FILE *f)
11083{
11084 fprintf(f,
11085 "\t{\n"
11086 "\t\t.type = %s,\n"
11087 "\t},\n",
11088 instr_type_to_name(instr));
11089}
11090
11091static void
11092instr_recircid_export(struct instruction *instr, FILE *f)
11093{
11094 fprintf(f,
11095 "\t{\n"
11096 "\t\t.type = %s,\n"
11097 "\t\t.io = {\n"
11098 "\t\t\t.offset = %u,\n"
11099 "\t\t\t.n_bits = %u,\n"
11100 "\t\t},\n"
11101 "\t},\n",
11102 instr_type_to_name(instr),
11103 instr->io.io.offset,
11104 instr->io.io.n_bits);
11105}
11106
11107static void
11108instr_hdr_validate_export(struct instruction *instr, FILE *f)
11109{
11110 fprintf(f,
11111 "\t{\n"
11112 "\t\t.type = %s,\n"
11113 "\t\t.valid = {\n"
11114 "\t\t\t.header_id = %u,\n"
11115 "\t\t},\n"
11116 "\t},\n",
11117 instr_type_to_name(instr),
11118 instr->valid.header_id);
11119}
11120
11121static void
11122instr_mov_export(struct instruction *instr, FILE *f)
11123{
11124 if (instr->type != INSTR_MOV_I)
11125 fprintf(f,
11126 "\t{\n"
11127 "\t\t.type = %s,\n"
11128 "\t\t.mov = {\n"
11129 "\t\t\t.dst = {\n"
11130 "\t\t\t\t.struct_id = %u,\n"
11131 "\t\t\t\t.n_bits = %u,\n"
11132 "\t\t\t\t.offset = %u,\n"
11133 "\t\t\t},\n"
11134 "\t\t\t.src = {\n"
11135 "\t\t\t\t.struct_id = %u,\n"
11136 "\t\t\t\t.n_bits = %u,\n"
11137 "\t\t\t\t.offset = %u,\n"
11138 "\t\t\t},\n"
11139 "\t\t},\n"
11140 "\t},\n",
11141 instr_type_to_name(instr),
11142 instr->mov.dst.struct_id,
11143 instr->mov.dst.n_bits,
11144 instr->mov.dst.offset,
11145 instr->mov.src.struct_id,
11146 instr->mov.src.n_bits,
11147 instr->mov.src.offset);
11148 else
11149 fprintf(f,
11150 "\t{\n"
11151 "\t\t.type = %s,\n"
11152 "\t\t.mov = {\n"
11153 "\t\t\t.dst = {\n"
11154 "\t\t\t\t.struct_id = %u,\n"
11155 "\t\t\t\t.n_bits = %u,\n"
11156 "\t\t\t\t.offset = %u,\n"
11157 "\t\t\t}\n,"
11158 "\t\t\t.src_val = %" PRIu64 ",\n"
11159 "\t\t},\n"
11160 "\t},\n",
11161 instr_type_to_name(instr),
11162 instr->mov.dst.struct_id,
11163 instr->mov.dst.n_bits,
11164 instr->mov.dst.offset,
11165 instr->mov.src_val);
11166}
11167
11168static void
11169instr_dma_ht_export(struct instruction *instr, FILE *f)
11170{
11171 uint32_t n_dma = 0, i;
11172
11173
11174 n_dma = 1 + (instr->type - INSTR_DMA_HT);
11175
11176
11177 fprintf(f,
11178 "\t{\n"
11179 "\t\t.type = %s,\n",
11180 instr_type_to_name(instr));
11181
11182
11183 fprintf(f,
11184 "\t\t.dma = {\n");
11185
11186
11187 fprintf(f,
11188 "\t\t\t.dst = {\n");
11189
11190
11191 fprintf(f,
11192 "\t\t\t\t.header_id = {");
11193
11194 for (i = 0; i < n_dma; i++)
11195 fprintf(f,
11196 "%u, ",
11197 instr->dma.dst.header_id[i]);
11198
11199 fprintf(f,
11200 "},\n");
11201
11202
11203 fprintf(f,
11204 "\t\t\t\t.struct_id = {");
11205
11206 for (i = 0; i < n_dma; i++)
11207 fprintf(f,
11208 "%u, ",
11209 instr->dma.dst.struct_id[i]);
11210
11211 fprintf(f,
11212 "},\n");
11213
11214
11215 fprintf(f,
11216 "\t\t\t},\n");
11217
11218
11219 fprintf(f,
11220 "\t\t\t.src = {\n");
11221
11222
11223 fprintf(f,
11224 "\t\t\t\t.offset = {");
11225
11226 for (i = 0; i < n_dma; i++)
11227 fprintf(f,
11228 "%u, ",
11229 instr->dma.src.offset[i]);
11230
11231 fprintf(f,
11232 "},\n");
11233
11234
11235 fprintf(f,
11236 "\t\t\t},\n");
11237
11238
11239 fprintf(f,
11240 "\t\t\t.n_bytes = {");
11241
11242 for (i = 0; i < n_dma; i++)
11243 fprintf(f,
11244 "%u, ",
11245 instr->dma.n_bytes[i]);
11246
11247 fprintf(f,
11248 "},\n");
11249
11250
11251 fprintf(f,
11252 "\t\t},\n");
11253
11254
11255 fprintf(f,
11256 "\t},\n");
11257}
11258
11259static void
11260instr_alu_export(struct instruction *instr, FILE *f)
11261{
11262 int imm = 0;
11263
11264 if (instr->type == INSTR_ALU_ADD_MI ||
11265 instr->type == INSTR_ALU_ADD_HI ||
11266 instr->type == INSTR_ALU_SUB_MI ||
11267 instr->type == INSTR_ALU_SUB_HI ||
11268 instr->type == INSTR_ALU_SHL_MI ||
11269 instr->type == INSTR_ALU_SHL_HI ||
11270 instr->type == INSTR_ALU_SHR_MI ||
11271 instr->type == INSTR_ALU_SHR_HI ||
11272 instr->type == INSTR_ALU_AND_I ||
11273 instr->type == INSTR_ALU_OR_I ||
11274 instr->type == INSTR_ALU_XOR_I)
11275 imm = 1;
11276
11277 if (!imm)
11278 fprintf(f,
11279 "\t{\n"
11280 "\t\t.type = %s,\n"
11281 "\t\t.alu = {\n"
11282 "\t\t\t.dst = {\n"
11283 "\t\t\t\t.struct_id = %u,\n"
11284 "\t\t\t\t.n_bits = %u,\n"
11285 "\t\t\t\t.offset = %u,\n"
11286 "\t\t\t},\n"
11287 "\t\t\t.src = {\n"
11288 "\t\t\t\t.struct_id = %u,\n"
11289 "\t\t\t\t.n_bits = %u,\n"
11290 "\t\t\t\t.offset = %u,\n"
11291 "\t\t\t},\n"
11292 "\t\t},\n"
11293 "\t},\n",
11294 instr_type_to_name(instr),
11295 instr->alu.dst.struct_id,
11296 instr->alu.dst.n_bits,
11297 instr->alu.dst.offset,
11298 instr->alu.src.struct_id,
11299 instr->alu.src.n_bits,
11300 instr->alu.src.offset);
11301 else
11302 fprintf(f,
11303 "\t{\n"
11304 "\t\t.type = %s,\n"
11305 "\t\t.alu = {\n"
11306 "\t\t\t.dst = {\n"
11307 "\t\t\t\t.struct_id = %u,\n"
11308 "\t\t\t\t.n_bits = %u,\n"
11309 "\t\t\t\t.offset = %u,\n"
11310 "\t\t\t}\n,"
11311 "\t\t\t.src_val = %" PRIu64 ",\n"
11312 "\t\t},\n"
11313 "\t},\n",
11314 instr_type_to_name(instr),
11315 instr->alu.dst.struct_id,
11316 instr->alu.dst.n_bits,
11317 instr->alu.dst.offset,
11318 instr->alu.src_val);
11319}
11320
11321static void
11322instr_hash_export(struct instruction *instr, FILE *f)
11323{
11324 fprintf(f,
11325 "\t{\n"
11326 "\t\t.type = %s,\n"
11327 "\t\t.hash_func = {\n"
11328 "\t\t\t.hash_func_id = %u,\n"
11329 "\t\t\t.dst = {\n"
11330 "\t\t\t\t.offset = %u,\n"
11331 "\t\t\t\t.n_bits = %u,\n"
11332 "\t\t\t},\n"
11333 "\t\t\t.src = {\n"
11334 "\t\t\t\t.struct_id = %u,\n"
11335 "\t\t\t\t.offset = %u,\n"
11336 "\t\t\t\t.n_bytes = %u,\n"
11337 "\t\t\t},\n"
11338 "\t\t},\n"
11339 "\t},\n",
11340 instr_type_to_name(instr),
11341 instr->hash_func.hash_func_id,
11342 instr->hash_func.dst.offset,
11343 instr->hash_func.dst.n_bits,
11344 instr->hash_func.src.struct_id,
11345 instr->hash_func.src.offset,
11346 instr->hash_func.src.n_bytes);
11347}
11348
11349static void
11350instr_reg_export(struct instruction *instr __rte_unused, FILE *f __rte_unused)
11351{
11352 int prefetch = 0, idx_imm = 0, src_imm = 0;
11353
11354 if (instr->type == INSTR_REGPREFETCH_RH ||
11355 instr->type == INSTR_REGPREFETCH_RM ||
11356 instr->type == INSTR_REGPREFETCH_RI)
11357 prefetch = 1;
11358
11359
11360
11361
11362 if (instr->type == INSTR_REGPREFETCH_RI ||
11363 instr->type == INSTR_REGRD_HRI ||
11364 instr->type == INSTR_REGRD_MRI ||
11365 instr->type == INSTR_REGWR_RIH ||
11366 instr->type == INSTR_REGWR_RIM ||
11367 instr->type == INSTR_REGWR_RII ||
11368 instr->type == INSTR_REGADD_RIH ||
11369 instr->type == INSTR_REGADD_RIM ||
11370 instr->type == INSTR_REGADD_RII)
11371 idx_imm = 1;
11372
11373
11374 if (instr->type == INSTR_REGWR_RHI ||
11375 instr->type == INSTR_REGWR_RMI ||
11376 instr->type == INSTR_REGWR_RII ||
11377 instr->type == INSTR_REGADD_RHI ||
11378 instr->type == INSTR_REGADD_RMI ||
11379 instr->type == INSTR_REGADD_RII)
11380 src_imm = 1;
11381
11382
11383 fprintf(f,
11384 "\t{\n"
11385 "\t\t.type = %s,\n"
11386 "\t\t.regarray = {\n"
11387 "\t\t\t.regarray_id = %u,\n",
11388 instr_type_to_name(instr),
11389 instr->regarray.regarray_id);
11390
11391
11392 if (!idx_imm)
11393 fprintf(f,
11394 "\t\t\t\t.idx = {\n"
11395 "\t\t\t\t\t.struct_id = %u,\n"
11396 "\t\t\t\t\t.n_bits = %u,\n"
11397 "\t\t\t\t\t.offset = %u,\n"
11398 "\t\t\t\t},\n",
11399 instr->regarray.idx.struct_id,
11400 instr->regarray.idx.n_bits,
11401 instr->regarray.idx.offset);
11402 else
11403 fprintf(f,
11404 "\t\t\t\t.idx_val = %u,\n",
11405 instr->regarray.idx_val);
11406
11407
11408 if (!prefetch) {
11409 if (!src_imm)
11410 fprintf(f,
11411 "\t\t\t\t.dstsrc = {\n"
11412 "\t\t\t\t\t.struct_id = %u,\n"
11413 "\t\t\t\t\t.n_bits = %u,\n"
11414 "\t\t\t\t\t.offset = %u,\n"
11415 "\t\t\t\t},\n",
11416 instr->regarray.dstsrc.struct_id,
11417 instr->regarray.dstsrc.n_bits,
11418 instr->regarray.dstsrc.offset);
11419 else
11420 fprintf(f,
11421 "\t\t\t\t.dstsrc_val = %" PRIu64 ",\n",
11422 instr->regarray.dstsrc_val);
11423 }
11424
11425
11426 fprintf(f,
11427 "\t\t},\n"
11428 "\t},\n");
11429}
11430
11431static void
11432instr_meter_export(struct instruction *instr __rte_unused, FILE *f __rte_unused)
11433{
11434 int prefetch = 0, idx_imm = 0, color_in_imm = 0;
11435
11436 if (instr->type == INSTR_METPREFETCH_H ||
11437 instr->type == INSTR_METPREFETCH_M ||
11438 instr->type == INSTR_METPREFETCH_I)
11439 prefetch = 1;
11440
11441
11442 if (instr->type == INSTR_METPREFETCH_I ||
11443 instr->type == INSTR_METER_IHM ||
11444 instr->type == INSTR_METER_IHI ||
11445 instr->type == INSTR_METER_IMM ||
11446 instr->type == INSTR_METER_IMI)
11447 idx_imm = 1;
11448
11449
11450 if (instr->type == INSTR_METER_HHI ||
11451 instr->type == INSTR_METER_HMI ||
11452 instr->type == INSTR_METER_MHI ||
11453 instr->type == INSTR_METER_MMI ||
11454 instr->type == INSTR_METER_IHI ||
11455 instr->type == INSTR_METER_IMI)
11456 color_in_imm = 1;
11457
11458
11459 fprintf(f,
11460 "\t{\n"
11461 "\t\t.type = %s,\n"
11462 "\t\t.meter = {\n"
11463 "\t\t\t.metarray_id = %u,\n",
11464 instr_type_to_name(instr),
11465 instr->meter.metarray_id);
11466
11467
11468 if (!idx_imm)
11469 fprintf(f,
11470 "\t\t\t.idx = {\n"
11471 "\t\t\t\t.struct_id = %u,\n"
11472 "\t\t\t\t.n_bits = %u,\n"
11473 "\t\t\t\t.offset = %u,\n"
11474 "\t\t\t},\n",
11475 instr->meter.idx.struct_id,
11476 instr->meter.idx.n_bits,
11477 instr->meter.idx.offset);
11478 else
11479 fprintf(f,
11480 "\t\t\t.idx_val = %u,\n",
11481 instr->meter.idx_val);
11482
11483 if (!prefetch) {
11484
11485 fprintf(f,
11486 "\t\t\t.length = {\n"
11487 "\t\t\t\t.struct_id = %u,\n"
11488 "\t\t\t\t.n_bits = %u,\n"
11489 "\t\t\t\t.offset = %u,\n"
11490 "\t\t\t},\n",
11491 instr->meter.length.struct_id,
11492 instr->meter.length.n_bits,
11493 instr->meter.length.offset);
11494
11495
11496 if (!color_in_imm)
11497 fprintf(f,
11498 "\t\t\t.color_in = {\n"
11499 "\t\t\t\t.struct_id = %u,\n"
11500 "\t\t\t\t.n_bits = %u,\n"
11501 "\t\t\t\t.offset = %u,\n"
11502 "\t\t\t},\n",
11503 instr->meter.color_in.struct_id,
11504 instr->meter.color_in.n_bits,
11505 instr->meter.color_in.offset);
11506 else
11507 fprintf(f,
11508 "\t\t\t.color_in_val = %u,\n",
11509 (uint32_t)instr->meter.color_in_val);
11510
11511
11512 fprintf(f,
11513 "\t\t\t.color_out = {\n"
11514 "\t\t\t\t.struct_id = %u,\n"
11515 "\t\t\t\t.n_bits = %u,\n"
11516 "\t\t\t\t.offset = %u,\n"
11517 "\t\t\t},\n",
11518 instr->meter.color_out.struct_id,
11519 instr->meter.color_out.n_bits,
11520 instr->meter.color_out.offset);
11521 }
11522
11523
11524 fprintf(f,
11525 "\t\t},\n"
11526 "\t},\n");
11527}
11528
11529static void
11530instr_table_export(struct instruction *instr,
11531 FILE *f)
11532{
11533 fprintf(f,
11534 "\t{\n"
11535 "\t\t.type = %s,\n"
11536 "\t\t.table = {\n"
11537 "\t\t\t.table_id = %u,\n"
11538 "\t\t},\n"
11539 "\t},\n",
11540 instr_type_to_name(instr),
11541 instr->table.table_id);
11542}
11543
11544static void
11545instr_learn_export(struct instruction *instr, FILE *f)
11546{
11547 fprintf(f,
11548 "\t{\n"
11549 "\t\t.type = %s,\n"
11550 "\t\t.learn = {\n"
11551 "\t\t\t.action_id = %u,\n"
11552 "\t\t\t.mf_first_arg_offset = %u,\n"
11553 "\t\t\t.mf_timeout_id_offset = %u,\n"
11554 "\t\t\t.mf_timeout_id_n_bits = %u,\n"
11555 "\t\t},\n"
11556 "\t},\n",
11557 instr_type_to_name(instr),
11558 instr->learn.action_id,
11559 instr->learn.mf_first_arg_offset,
11560 instr->learn.mf_timeout_id_offset,
11561 instr->learn.mf_timeout_id_n_bits);
11562}
11563
11564static void
11565instr_rearm_export(struct instruction *instr, FILE *f)
11566{
11567 if (instr->type == INSTR_LEARNER_REARM)
11568 fprintf(f,
11569 "\t{\n"
11570 "\t\t.type = %s,\n"
11571 "\t},\n",
11572 instr_type_to_name(instr));
11573 else
11574 fprintf(f,
11575 "\t{\n"
11576 "\t\t.type = %s,\n"
11577 "\t\t.learn = {\n"
11578 "\t\t\t.mf_timeout_id_offset = %u,\n"
11579 "\t\t\t.mf_timeout_id_n_bits = %u,\n"
11580 "\t\t},\n"
11581 "\t},\n",
11582 instr_type_to_name(instr),
11583 instr->learn.mf_timeout_id_offset,
11584 instr->learn.mf_timeout_id_n_bits);
11585}
11586
11587static void
11588instr_forget_export(struct instruction *instr, FILE *f)
11589{
11590 fprintf(f,
11591 "\t{\n"
11592 "\t\t.type = %s,\n"
11593 "\t},\n",
11594 instr_type_to_name(instr));
11595}
11596
11597static void
11598instr_extern_export(struct instruction *instr, FILE *f)
11599{
11600 if (instr->type == INSTR_EXTERN_OBJ)
11601 fprintf(f,
11602 "\t{\n"
11603 "\t\t.type = %s,\n"
11604 "\t\t.ext_obj = {\n"
11605 "\t\t\t.ext_obj_id = %u,\n"
11606 "\t\t\t.func_id = %u,\n"
11607 "\t\t},\n"
11608 "\t},\n",
11609 instr_type_to_name(instr),
11610 instr->ext_obj.ext_obj_id,
11611 instr->ext_obj.func_id);
11612 else
11613 fprintf(f,
11614 "\t{\n"
11615 "\t\t.type = %s,\n"
11616 "\t\t.ext_func = {\n"
11617 "\t\t\t.ext_func_id = %u,\n"
11618 "\t\t},\n"
11619 "\t},\n",
11620 instr_type_to_name(instr),
11621 instr->ext_func.ext_func_id);
11622}
11623
11624static void
11625instr_jmp_export(struct instruction *instr, FILE *f __rte_unused)
11626{
11627 fprintf(f,
11628 "\t{\n"
11629 "\t\t.type = %s,\n"
11630 "\t\t.jmp = {\n"
11631 "\t\t\t.ip = NULL,\n",
11632 instr_type_to_name(instr));
11633
11634 switch (instr->type) {
11635 case INSTR_JMP_VALID:
11636 case INSTR_JMP_INVALID:
11637 fprintf(f,
11638 "\t\t\t.header_id = %u,\n",
11639 instr->jmp.header_id);
11640 break;
11641
11642 case INSTR_JMP_ACTION_HIT:
11643 case INSTR_JMP_ACTION_MISS:
11644 fprintf(f,
11645 "\t\t\t.action_id = %u,\n",
11646 instr->jmp.action_id);
11647 break;
11648
11649 case INSTR_JMP_EQ:
11650 case INSTR_JMP_EQ_MH:
11651 case INSTR_JMP_EQ_HM:
11652 case INSTR_JMP_EQ_HH:
11653 case INSTR_JMP_NEQ:
11654 case INSTR_JMP_NEQ_MH:
11655 case INSTR_JMP_NEQ_HM:
11656 case INSTR_JMP_NEQ_HH:
11657 case INSTR_JMP_LT:
11658 case INSTR_JMP_LT_MH:
11659 case INSTR_JMP_LT_HM:
11660 case INSTR_JMP_LT_HH:
11661 case INSTR_JMP_GT:
11662 case INSTR_JMP_GT_MH:
11663 case INSTR_JMP_GT_HM:
11664 case INSTR_JMP_GT_HH:
11665 fprintf(f,
11666 "\t\t\t.a = {\n"
11667 "\t\t\t\t.struct_id = %u,\n"
11668 "\t\t\t\t.n_bits = %u,\n"
11669 "\t\t\t\t.offset = %u,\n"
11670 "\t\t\t},\n"
11671 "\t\t\t.b = {\n"
11672 "\t\t\t\t.struct_id = %u,\n"
11673 "\t\t\t\t.n_bits = %u,\n"
11674 "\t\t\t\t.offset = %u,\n"
11675 "\t\t\t},\n",
11676 instr->jmp.a.struct_id,
11677 instr->jmp.a.n_bits,
11678 instr->jmp.a.offset,
11679 instr->jmp.b.struct_id,
11680 instr->jmp.b.n_bits,
11681 instr->jmp.b.offset);
11682 break;
11683
11684 case INSTR_JMP_EQ_I:
11685 case INSTR_JMP_NEQ_I:
11686 case INSTR_JMP_LT_MI:
11687 case INSTR_JMP_LT_HI:
11688 case INSTR_JMP_GT_MI:
11689 case INSTR_JMP_GT_HI:
11690 fprintf(f,
11691 "\t\t\t.a = {\n"
11692 "\t\t\t\t.struct_id = %u,\n"
11693 "\t\t\t\t.n_bits = %u,\n"
11694 "\t\t\t\t.offset = %u,\n"
11695 "\t\t\t}\n,"
11696 "\t\t\t.b_val = %" PRIu64 ",\n",
11697 instr->jmp.a.struct_id,
11698 instr->jmp.a.n_bits,
11699 instr->jmp.a.offset,
11700 instr->jmp.b_val);
11701 break;
11702
11703 default:
11704 break;
11705 }
11706
11707 fprintf(f,
11708 "\t\t},\n"
11709 "\t},\n");
11710}
11711
11712static void
11713instr_return_export(struct instruction *instr,
11714 FILE *f)
11715{
11716 fprintf(f,
11717 "\t{\n"
11718 "\t\t.type = %s,\n",
11719 instr_type_to_name(instr));
11720
11721 fprintf(f,
11722 "\t},\n");
11723}
11724
11725static instruction_export_t export_table[] = {
11726 [INSTR_RX] = instr_io_export,
11727
11728 [INSTR_TX] = instr_io_export,
11729 [INSTR_TX_I] = instr_io_export,
11730 [INSTR_DROP] = instr_io_export,
11731 [INSTR_MIRROR] = instr_mirror_export,
11732 [INSTR_RECIRCULATE] = instr_recirculate_export,
11733 [INSTR_RECIRCID] = instr_recircid_export,
11734
11735 [INSTR_HDR_EXTRACT] = instr_io_export,
11736 [INSTR_HDR_EXTRACT2] = instr_io_export,
11737 [INSTR_HDR_EXTRACT3] = instr_io_export,
11738 [INSTR_HDR_EXTRACT4] = instr_io_export,
11739 [INSTR_HDR_EXTRACT5] = instr_io_export,
11740 [INSTR_HDR_EXTRACT6] = instr_io_export,
11741 [INSTR_HDR_EXTRACT7] = instr_io_export,
11742 [INSTR_HDR_EXTRACT8] = instr_io_export,
11743
11744 [INSTR_HDR_EXTRACT_M] = instr_io_export,
11745
11746 [INSTR_HDR_LOOKAHEAD] = instr_io_export,
11747
11748 [INSTR_HDR_EMIT] = instr_io_export,
11749 [INSTR_HDR_EMIT_TX] = instr_io_export,
11750 [INSTR_HDR_EMIT2_TX] = instr_io_export,
11751 [INSTR_HDR_EMIT3_TX] = instr_io_export,
11752 [INSTR_HDR_EMIT4_TX] = instr_io_export,
11753 [INSTR_HDR_EMIT5_TX] = instr_io_export,
11754 [INSTR_HDR_EMIT6_TX] = instr_io_export,
11755 [INSTR_HDR_EMIT7_TX] = instr_io_export,
11756 [INSTR_HDR_EMIT8_TX] = instr_io_export,
11757
11758 [INSTR_HDR_VALIDATE] = instr_hdr_validate_export,
11759 [INSTR_HDR_INVALIDATE] = instr_hdr_validate_export,
11760
11761 [INSTR_MOV] = instr_mov_export,
11762 [INSTR_MOV_MH] = instr_mov_export,
11763 [INSTR_MOV_HM] = instr_mov_export,
11764 [INSTR_MOV_HH] = instr_mov_export,
11765 [INSTR_MOV_I] = instr_mov_export,
11766
11767 [INSTR_DMA_HT] = instr_dma_ht_export,
11768 [INSTR_DMA_HT2] = instr_dma_ht_export,
11769 [INSTR_DMA_HT3] = instr_dma_ht_export,
11770 [INSTR_DMA_HT4] = instr_dma_ht_export,
11771 [INSTR_DMA_HT5] = instr_dma_ht_export,
11772 [INSTR_DMA_HT6] = instr_dma_ht_export,
11773 [INSTR_DMA_HT7] = instr_dma_ht_export,
11774 [INSTR_DMA_HT8] = instr_dma_ht_export,
11775
11776 [INSTR_ALU_ADD] = instr_alu_export,
11777 [INSTR_ALU_ADD_MH] = instr_alu_export,
11778 [INSTR_ALU_ADD_HM] = instr_alu_export,
11779 [INSTR_ALU_ADD_HH] = instr_alu_export,
11780 [INSTR_ALU_ADD_MI] = instr_alu_export,
11781 [INSTR_ALU_ADD_HI] = instr_alu_export,
11782
11783 [INSTR_ALU_SUB] = instr_alu_export,
11784 [INSTR_ALU_SUB_MH] = instr_alu_export,
11785 [INSTR_ALU_SUB_HM] = instr_alu_export,
11786 [INSTR_ALU_SUB_HH] = instr_alu_export,
11787 [INSTR_ALU_SUB_MI] = instr_alu_export,
11788 [INSTR_ALU_SUB_HI] = instr_alu_export,
11789
11790 [INSTR_ALU_CKADD_FIELD] = instr_alu_export,
11791 [INSTR_ALU_CKADD_STRUCT] = instr_alu_export,
11792 [INSTR_ALU_CKADD_STRUCT20] = instr_alu_export,
11793 [INSTR_ALU_CKSUB_FIELD] = instr_alu_export,
11794
11795 [INSTR_ALU_AND] = instr_alu_export,
11796 [INSTR_ALU_AND_MH] = instr_alu_export,
11797 [INSTR_ALU_AND_HM] = instr_alu_export,
11798 [INSTR_ALU_AND_HH] = instr_alu_export,
11799 [INSTR_ALU_AND_I] = instr_alu_export,
11800
11801 [INSTR_ALU_OR] = instr_alu_export,
11802 [INSTR_ALU_OR_MH] = instr_alu_export,
11803 [INSTR_ALU_OR_HM] = instr_alu_export,
11804 [INSTR_ALU_OR_HH] = instr_alu_export,
11805 [INSTR_ALU_OR_I] = instr_alu_export,
11806
11807 [INSTR_ALU_XOR] = instr_alu_export,
11808 [INSTR_ALU_XOR_MH] = instr_alu_export,
11809 [INSTR_ALU_XOR_HM] = instr_alu_export,
11810 [INSTR_ALU_XOR_HH] = instr_alu_export,
11811 [INSTR_ALU_XOR_I] = instr_alu_export,
11812
11813 [INSTR_ALU_SHL] = instr_alu_export,
11814 [INSTR_ALU_SHL_MH] = instr_alu_export,
11815 [INSTR_ALU_SHL_HM] = instr_alu_export,
11816 [INSTR_ALU_SHL_HH] = instr_alu_export,
11817 [INSTR_ALU_SHL_MI] = instr_alu_export,
11818 [INSTR_ALU_SHL_HI] = instr_alu_export,
11819
11820 [INSTR_ALU_SHR] = instr_alu_export,
11821 [INSTR_ALU_SHR_MH] = instr_alu_export,
11822 [INSTR_ALU_SHR_HM] = instr_alu_export,
11823 [INSTR_ALU_SHR_HH] = instr_alu_export,
11824 [INSTR_ALU_SHR_MI] = instr_alu_export,
11825 [INSTR_ALU_SHR_HI] = instr_alu_export,
11826
11827 [INSTR_REGPREFETCH_RH] = instr_reg_export,
11828 [INSTR_REGPREFETCH_RM] = instr_reg_export,
11829 [INSTR_REGPREFETCH_RI] = instr_reg_export,
11830
11831 [INSTR_REGRD_HRH] = instr_reg_export,
11832 [INSTR_REGRD_HRM] = instr_reg_export,
11833 [INSTR_REGRD_MRH] = instr_reg_export,
11834 [INSTR_REGRD_MRM] = instr_reg_export,
11835 [INSTR_REGRD_HRI] = instr_reg_export,
11836 [INSTR_REGRD_MRI] = instr_reg_export,
11837
11838 [INSTR_REGWR_RHH] = instr_reg_export,
11839 [INSTR_REGWR_RHM] = instr_reg_export,
11840 [INSTR_REGWR_RMH] = instr_reg_export,
11841 [INSTR_REGWR_RMM] = instr_reg_export,
11842 [INSTR_REGWR_RHI] = instr_reg_export,
11843 [INSTR_REGWR_RMI] = instr_reg_export,
11844 [INSTR_REGWR_RIH] = instr_reg_export,
11845 [INSTR_REGWR_RIM] = instr_reg_export,
11846 [INSTR_REGWR_RII] = instr_reg_export,
11847
11848 [INSTR_REGADD_RHH] = instr_reg_export,
11849 [INSTR_REGADD_RHM] = instr_reg_export,
11850 [INSTR_REGADD_RMH] = instr_reg_export,
11851 [INSTR_REGADD_RMM] = instr_reg_export,
11852 [INSTR_REGADD_RHI] = instr_reg_export,
11853 [INSTR_REGADD_RMI] = instr_reg_export,
11854 [INSTR_REGADD_RIH] = instr_reg_export,
11855 [INSTR_REGADD_RIM] = instr_reg_export,
11856 [INSTR_REGADD_RII] = instr_reg_export,
11857
11858 [INSTR_METPREFETCH_H] = instr_meter_export,
11859 [INSTR_METPREFETCH_M] = instr_meter_export,
11860 [INSTR_METPREFETCH_I] = instr_meter_export,
11861
11862 [INSTR_METER_HHM] = instr_meter_export,
11863 [INSTR_METER_HHI] = instr_meter_export,
11864 [INSTR_METER_HMM] = instr_meter_export,
11865 [INSTR_METER_HMI] = instr_meter_export,
11866 [INSTR_METER_MHM] = instr_meter_export,
11867 [INSTR_METER_MHI] = instr_meter_export,
11868 [INSTR_METER_MMM] = instr_meter_export,
11869 [INSTR_METER_MMI] = instr_meter_export,
11870 [INSTR_METER_IHM] = instr_meter_export,
11871 [INSTR_METER_IHI] = instr_meter_export,
11872 [INSTR_METER_IMM] = instr_meter_export,
11873 [INSTR_METER_IMI] = instr_meter_export,
11874
11875 [INSTR_TABLE] = instr_table_export,
11876 [INSTR_TABLE_AF] = instr_table_export,
11877 [INSTR_SELECTOR] = instr_table_export,
11878 [INSTR_LEARNER] = instr_table_export,
11879 [INSTR_LEARNER_AF] = instr_table_export,
11880
11881 [INSTR_LEARNER_LEARN] = instr_learn_export,
11882 [INSTR_LEARNER_REARM] = instr_rearm_export,
11883 [INSTR_LEARNER_REARM_NEW] = instr_rearm_export,
11884 [INSTR_LEARNER_FORGET] = instr_forget_export,
11885
11886 [INSTR_EXTERN_OBJ] = instr_extern_export,
11887 [INSTR_EXTERN_FUNC] = instr_extern_export,
11888 [INSTR_HASH_FUNC] = instr_hash_export,
11889
11890 [INSTR_JMP] = instr_jmp_export,
11891 [INSTR_JMP_VALID] = instr_jmp_export,
11892 [INSTR_JMP_INVALID] = instr_jmp_export,
11893 [INSTR_JMP_HIT] = instr_jmp_export,
11894 [INSTR_JMP_MISS] = instr_jmp_export,
11895 [INSTR_JMP_ACTION_HIT] = instr_jmp_export,
11896 [INSTR_JMP_ACTION_MISS] = instr_jmp_export,
11897
11898 [INSTR_JMP_EQ] = instr_jmp_export,
11899 [INSTR_JMP_EQ_MH] = instr_jmp_export,
11900 [INSTR_JMP_EQ_HM] = instr_jmp_export,
11901 [INSTR_JMP_EQ_HH] = instr_jmp_export,
11902 [INSTR_JMP_EQ_I] = instr_jmp_export,
11903
11904 [INSTR_JMP_NEQ] = instr_jmp_export,
11905 [INSTR_JMP_NEQ_MH] = instr_jmp_export,
11906 [INSTR_JMP_NEQ_HM] = instr_jmp_export,
11907 [INSTR_JMP_NEQ_HH] = instr_jmp_export,
11908 [INSTR_JMP_NEQ_I] = instr_jmp_export,
11909
11910 [INSTR_JMP_LT] = instr_jmp_export,
11911 [INSTR_JMP_LT_MH] = instr_jmp_export,
11912 [INSTR_JMP_LT_HM] = instr_jmp_export,
11913 [INSTR_JMP_LT_HH] = instr_jmp_export,
11914 [INSTR_JMP_LT_MI] = instr_jmp_export,
11915 [INSTR_JMP_LT_HI] = instr_jmp_export,
11916
11917 [INSTR_JMP_GT] = instr_jmp_export,
11918 [INSTR_JMP_GT_MH] = instr_jmp_export,
11919 [INSTR_JMP_GT_HM] = instr_jmp_export,
11920 [INSTR_JMP_GT_HH] = instr_jmp_export,
11921 [INSTR_JMP_GT_MI] = instr_jmp_export,
11922 [INSTR_JMP_GT_HI] = instr_jmp_export,
11923
11924 [INSTR_RETURN] = instr_return_export,
11925};
11926
11927static void
11928action_data_codegen(struct action *a, FILE *f)
11929{
11930 uint32_t i;
11931
11932 fprintf(f,
11933 "static const struct instruction action_%s_instructions[] = {\n",
11934 a->name);
11935
11936 for (i = 0; i < a->n_instructions; i++) {
11937 struct instruction *instr = &a->instructions[i];
11938 instruction_export_t func = export_table[instr->type];
11939
11940 func(instr, f);
11941 }
11942
11943 fprintf(f, "};\n");
11944}
11945
11946static const char *
11947instr_type_to_func(struct instruction *instr)
11948{
11949 switch (instr->type) {
11950 case INSTR_RX: return NULL;
11951
11952 case INSTR_TX: return "__instr_tx_exec";
11953 case INSTR_TX_I: return "__instr_tx_i_exec";
11954 case INSTR_DROP: return "__instr_drop_exec";
11955 case INSTR_MIRROR: return "__instr_mirror_exec";
11956 case INSTR_RECIRCULATE: return "__instr_recirculate_exec";
11957 case INSTR_RECIRCID: return "__instr_recircid_exec";
11958
11959 case INSTR_HDR_EXTRACT: return "__instr_hdr_extract_exec";
11960 case INSTR_HDR_EXTRACT2: return "__instr_hdr_extract2_exec";
11961 case INSTR_HDR_EXTRACT3: return "__instr_hdr_extract3_exec";
11962 case INSTR_HDR_EXTRACT4: return "__instr_hdr_extract4_exec";
11963 case INSTR_HDR_EXTRACT5: return "__instr_hdr_extract5_exec";
11964 case INSTR_HDR_EXTRACT6: return "__instr_hdr_extract6_exec";
11965 case INSTR_HDR_EXTRACT7: return "__instr_hdr_extract7_exec";
11966 case INSTR_HDR_EXTRACT8: return "__instr_hdr_extract8_exec";
11967
11968 case INSTR_HDR_EXTRACT_M: return "__instr_hdr_extract_m_exec";
11969
11970 case INSTR_HDR_LOOKAHEAD: return "__instr_hdr_lookahead_exec";
11971
11972 case INSTR_HDR_EMIT: return "__instr_hdr_emit_exec";
11973 case INSTR_HDR_EMIT_TX: return "__instr_hdr_emit_tx_exec";
11974 case INSTR_HDR_EMIT2_TX: return "__instr_hdr_emit2_tx_exec";
11975 case INSTR_HDR_EMIT3_TX: return "__instr_hdr_emit3_tx_exec";
11976 case INSTR_HDR_EMIT4_TX: return "__instr_hdr_emit4_tx_exec";
11977 case INSTR_HDR_EMIT5_TX: return "__instr_hdr_emit5_tx_exec";
11978 case INSTR_HDR_EMIT6_TX: return "__instr_hdr_emit6_tx_exec";
11979 case INSTR_HDR_EMIT7_TX: return "__instr_hdr_emit7_tx_exec";
11980 case INSTR_HDR_EMIT8_TX: return "__instr_hdr_emit8_tx_exec";
11981
11982 case INSTR_HDR_VALIDATE: return "__instr_hdr_validate_exec";
11983 case INSTR_HDR_INVALIDATE: return "__instr_hdr_invalidate_exec";
11984
11985 case INSTR_MOV: return "__instr_mov_exec";
11986 case INSTR_MOV_MH: return "__instr_mov_mh_exec";
11987 case INSTR_MOV_HM: return "__instr_mov_hm_exec";
11988 case INSTR_MOV_HH: return "__instr_mov_hh_exec";
11989 case INSTR_MOV_I: return "__instr_mov_i_exec";
11990
11991 case INSTR_DMA_HT: return "__instr_dma_ht_exec";
11992 case INSTR_DMA_HT2: return "__instr_dma_ht2_exec";
11993 case INSTR_DMA_HT3: return "__instr_dma_ht3_exec";
11994 case INSTR_DMA_HT4: return "__instr_dma_ht4_exec";
11995 case INSTR_DMA_HT5: return "__instr_dma_ht5_exec";
11996 case INSTR_DMA_HT6: return "__instr_dma_ht6_exec";
11997 case INSTR_DMA_HT7: return "__instr_dma_ht7_exec";
11998 case INSTR_DMA_HT8: return "__instr_dma_ht8_exec";
11999
12000 case INSTR_ALU_ADD: return "__instr_alu_add_exec";
12001 case INSTR_ALU_ADD_MH: return "__instr_alu_add_mh_exec";
12002 case INSTR_ALU_ADD_HM: return "__instr_alu_add_hm_exec";
12003 case INSTR_ALU_ADD_HH: return "__instr_alu_add_hh_exec";
12004 case INSTR_ALU_ADD_MI: return "__instr_alu_add_mi_exec";
12005 case INSTR_ALU_ADD_HI: return "__instr_alu_add_hi_exec";
12006
12007 case INSTR_ALU_SUB: return "__instr_alu_sub_exec";
12008 case INSTR_ALU_SUB_MH: return "__instr_alu_sub_mh_exec";
12009 case INSTR_ALU_SUB_HM: return "__instr_alu_sub_hm_exec";
12010 case INSTR_ALU_SUB_HH: return "__instr_alu_sub_hh_exec";
12011 case INSTR_ALU_SUB_MI: return "__instr_alu_sub_mi_exec";
12012 case INSTR_ALU_SUB_HI: return "__instr_alu_sub_hi_exec";
12013
12014 case INSTR_ALU_CKADD_FIELD: return "__instr_alu_ckadd_field_exec";
12015 case INSTR_ALU_CKADD_STRUCT20: return "__instr_alu_ckadd_struct20_exec";
12016 case INSTR_ALU_CKADD_STRUCT: return "__instr_alu_ckadd_struct_exec";
12017 case INSTR_ALU_CKSUB_FIELD: return "__instr_alu_cksub_field_exec";
12018
12019 case INSTR_ALU_AND: return "__instr_alu_and_exec";
12020 case INSTR_ALU_AND_MH: return "__instr_alu_and_mh_exec";
12021 case INSTR_ALU_AND_HM: return "__instr_alu_and_hm_exec";
12022 case INSTR_ALU_AND_HH: return "__instr_alu_and_hh_exec";
12023 case INSTR_ALU_AND_I: return "__instr_alu_and_i_exec";
12024
12025 case INSTR_ALU_OR: return "__instr_alu_or_exec";
12026 case INSTR_ALU_OR_MH: return "__instr_alu_or_mh_exec";
12027 case INSTR_ALU_OR_HM: return "__instr_alu_or_hm_exec";
12028 case INSTR_ALU_OR_HH: return "__instr_alu_or_hh_exec";
12029 case INSTR_ALU_OR_I: return "__instr_alu_or_i_exec";
12030
12031 case INSTR_ALU_XOR: return "__instr_alu_xor_exec";
12032 case INSTR_ALU_XOR_MH: return "__instr_alu_xor_mh_exec";
12033 case INSTR_ALU_XOR_HM: return "__instr_alu_xor_hm_exec";
12034 case INSTR_ALU_XOR_HH: return "__instr_alu_xor_hh_exec";
12035 case INSTR_ALU_XOR_I: return "__instr_alu_xor_i_exec";
12036
12037 case INSTR_ALU_SHL: return "__instr_alu_shl_exec";
12038 case INSTR_ALU_SHL_MH: return "__instr_alu_shl_mh_exec";
12039 case INSTR_ALU_SHL_HM: return "__instr_alu_shl_hm_exec";
12040 case INSTR_ALU_SHL_HH: return "__instr_alu_shl_hh_exec";
12041 case INSTR_ALU_SHL_MI: return "__instr_alu_shl_mi_exec";
12042 case INSTR_ALU_SHL_HI: return "__instr_alu_shl_hi_exec";
12043
12044 case INSTR_ALU_SHR: return "__instr_alu_shr_exec";
12045 case INSTR_ALU_SHR_MH: return "__instr_alu_shr_mh_exec";
12046 case INSTR_ALU_SHR_HM: return "__instr_alu_shr_hm_exec";
12047 case INSTR_ALU_SHR_HH: return "__instr_alu_shr_hh_exec";
12048 case INSTR_ALU_SHR_MI: return "__instr_alu_shr_mi_exec";
12049 case INSTR_ALU_SHR_HI: return "__instr_alu_shr_hi_exec";
12050
12051 case INSTR_REGPREFETCH_RH: return "__instr_regprefetch_rh_exec";
12052 case INSTR_REGPREFETCH_RM: return "__instr_regprefetch_rm_exec";
12053 case INSTR_REGPREFETCH_RI: return "__instr_regprefetch_ri_exec";
12054
12055 case INSTR_REGRD_HRH: return "__instr_regrd_hrh_exec";
12056 case INSTR_REGRD_HRM: return "__instr_regrd_hrm_exec";
12057 case INSTR_REGRD_HRI: return "__instr_regrd_hri_exec";
12058 case INSTR_REGRD_MRH: return "__instr_regrd_mrh_exec";
12059 case INSTR_REGRD_MRM: return "__instr_regrd_mrm_exec";
12060 case INSTR_REGRD_MRI: return "__instr_regrd_mri_exec";
12061
12062 case INSTR_REGWR_RHH: return "__instr_regwr_rhh_exec";
12063 case INSTR_REGWR_RHM: return "__instr_regwr_rhm_exec";
12064 case INSTR_REGWR_RHI: return "__instr_regwr_rhi_exec";
12065 case INSTR_REGWR_RMH: return "__instr_regwr_rmh_exec";
12066 case INSTR_REGWR_RMM: return "__instr_regwr_rmm_exec";
12067 case INSTR_REGWR_RMI: return "__instr_regwr_rmi_exec";
12068 case INSTR_REGWR_RIH: return "__instr_regwr_rih_exec";
12069 case INSTR_REGWR_RIM: return "__instr_regwr_rim_exec";
12070 case INSTR_REGWR_RII: return "__instr_regwr_rii_exec";
12071
12072 case INSTR_REGADD_RHH: return "__instr_regadd_rhh_exec";
12073 case INSTR_REGADD_RHM: return "__instr_regadd_rhm_exec";
12074 case INSTR_REGADD_RHI: return "__instr_regadd_rhi_exec";
12075 case INSTR_REGADD_RMH: return "__instr_regadd_rmh_exec";
12076 case INSTR_REGADD_RMM: return "__instr_regadd_rmm_exec";
12077 case INSTR_REGADD_RMI: return "__instr_regadd_rmi_exec";
12078 case INSTR_REGADD_RIH: return "__instr_regadd_rih_exec";
12079 case INSTR_REGADD_RIM: return "__instr_regadd_rim_exec";
12080 case INSTR_REGADD_RII: return "__instr_regadd_rii_exec";
12081
12082 case INSTR_METPREFETCH_H: return "__instr_metprefetch_h_exec";
12083 case INSTR_METPREFETCH_M: return "__instr_metprefetch_m_exec";
12084 case INSTR_METPREFETCH_I: return "__instr_metprefetch_i_exec";
12085
12086 case INSTR_METER_HHM: return "__instr_meter_hhm_exec";
12087 case INSTR_METER_HHI: return "__instr_meter_hhi_exec";
12088 case INSTR_METER_HMM: return "__instr_meter_hmm_exec";
12089 case INSTR_METER_HMI: return "__instr_meter_hmi_exec";
12090 case INSTR_METER_MHM: return "__instr_meter_mhm_exec";
12091 case INSTR_METER_MHI: return "__instr_meter_mhi_exec";
12092 case INSTR_METER_MMM: return "__instr_meter_mmm_exec";
12093 case INSTR_METER_MMI: return "__instr_meter_mmi_exec";
12094 case INSTR_METER_IHM: return "__instr_meter_ihm_exec";
12095 case INSTR_METER_IHI: return "__instr_meter_ihi_exec";
12096 case INSTR_METER_IMM: return "__instr_meter_imm_exec";
12097 case INSTR_METER_IMI: return "__instr_meter_imi_exec";
12098
12099 case INSTR_TABLE: return NULL;
12100 case INSTR_TABLE_AF: return NULL;
12101 case INSTR_SELECTOR: return NULL;
12102 case INSTR_LEARNER: return NULL;
12103 case INSTR_LEARNER_AF: return NULL;
12104
12105 case INSTR_LEARNER_LEARN: return "__instr_learn_exec";
12106 case INSTR_LEARNER_REARM: return "__instr_rearm_exec";
12107 case INSTR_LEARNER_REARM_NEW: return "__instr_rearm_new_exec";
12108 case INSTR_LEARNER_FORGET: return "__instr_forget_exec";
12109
12110 case INSTR_EXTERN_OBJ: return NULL;
12111 case INSTR_EXTERN_FUNC: return NULL;
12112 case INSTR_HASH_FUNC: return "__instr_hash_func_exec";
12113
12114 case INSTR_JMP: return NULL;
12115 case INSTR_JMP_VALID: return NULL;
12116 case INSTR_JMP_INVALID: return NULL;
12117 case INSTR_JMP_HIT: return NULL;
12118 case INSTR_JMP_MISS: return NULL;
12119 case INSTR_JMP_ACTION_HIT: return NULL;
12120 case INSTR_JMP_ACTION_MISS: return NULL;
12121 case INSTR_JMP_EQ: return NULL;
12122 case INSTR_JMP_EQ_MH: return NULL;
12123 case INSTR_JMP_EQ_HM: return NULL;
12124 case INSTR_JMP_EQ_HH: return NULL;
12125 case INSTR_JMP_EQ_I: return NULL;
12126 case INSTR_JMP_NEQ: return NULL;
12127 case INSTR_JMP_NEQ_MH: return NULL;
12128 case INSTR_JMP_NEQ_HM: return NULL;
12129 case INSTR_JMP_NEQ_HH: return NULL;
12130 case INSTR_JMP_NEQ_I: return NULL;
12131 case INSTR_JMP_LT: return NULL;
12132 case INSTR_JMP_LT_MH: return NULL;
12133 case INSTR_JMP_LT_HM: return NULL;
12134 case INSTR_JMP_LT_HH: return NULL;
12135 case INSTR_JMP_LT_MI: return NULL;
12136 case INSTR_JMP_LT_HI: return NULL;
12137 case INSTR_JMP_GT: return NULL;
12138 case INSTR_JMP_GT_MH: return NULL;
12139 case INSTR_JMP_GT_HM: return NULL;
12140 case INSTR_JMP_GT_HH: return NULL;
12141 case INSTR_JMP_GT_MI: return NULL;
12142 case INSTR_JMP_GT_HI: return NULL;
12143
12144 case INSTR_RETURN: return NULL;
12145
12146 default: return NULL;
12147 }
12148}
12149
12150static void
12151action_instr_does_tx_codegen(struct action *a,
12152 uint32_t instr_pos,
12153 struct instruction *instr,
12154 FILE *f)
12155{
12156 fprintf(f,
12157 "%s(p, t, &action_%s_instructions[%u]);\n"
12158 "\tthread_ip_reset(p, t);\n"
12159 "\tinstr_rx_exec(p);\n"
12160 "\treturn;\n",
12161 instr_type_to_func(instr),
12162 a->name,
12163 instr_pos);
12164}
12165
12166static void
12167action_instr_extern_obj_codegen(struct action *a,
12168 uint32_t instr_pos,
12169 FILE *f)
12170{
12171 fprintf(f,
12172 "while (!__instr_extern_obj_exec(p, t, &action_%s_instructions[%u]));\n",
12173 a->name,
12174 instr_pos);
12175}
12176
12177static void
12178action_instr_extern_func_codegen(struct action *a,
12179 uint32_t instr_pos,
12180 FILE *f)
12181{
12182 fprintf(f,
12183 "while (!__instr_extern_func_exec(p, t, &action_%s_instructions[%u]));\n",
12184 a->name,
12185 instr_pos);
12186}
12187
12188static void
12189action_instr_jmp_codegen(struct action *a,
12190 uint32_t instr_pos,
12191 struct instruction *instr,
12192 struct instruction_data *data,
12193 FILE *f)
12194{
12195 switch (instr->type) {
12196 case INSTR_JMP:
12197 fprintf(f,
12198 "goto %s;\n",
12199 data->jmp_label);
12200 return;
12201
12202 case INSTR_JMP_VALID:
12203 fprintf(f,
12204 "if (HEADER_VALID(t, action_%s_instructions[%u].jmp.header_id))\n"
12205 "\t\tgoto %s;\n",
12206 a->name,
12207 instr_pos,
12208 data->jmp_label);
12209 return;
12210
12211 case INSTR_JMP_INVALID:
12212 fprintf(f,
12213 "if (!HEADER_VALID(t, action_%s_instructions[%u].jmp.header_id))\n"
12214 "\t\tgoto %s;\n",
12215 a->name,
12216 instr_pos,
12217 data->jmp_label);
12218 return;
12219
12220 case INSTR_JMP_HIT:
12221 fprintf(f,
12222 "if (t->hit)\n"
12223 "\t\tgoto %s;\n",
12224 data->jmp_label);
12225 return;
12226
12227 case INSTR_JMP_MISS:
12228 fprintf(f,
12229 "if (!t->hit)\n"
12230 "\t\tgoto %s;\n",
12231 data->jmp_label);
12232 return;
12233
12234 case INSTR_JMP_ACTION_HIT:
12235 fprintf(f,
12236 "if (t->action_id == action_%s_instructions[%u].jmp.action_id)\n"
12237 "\t\tgoto %s;\n",
12238 a->name,
12239 instr_pos,
12240 data->jmp_label);
12241 return;
12242
12243 case INSTR_JMP_ACTION_MISS:
12244 fprintf(f,
12245 "if (t->action_id != action_%s_instructions[%u].jmp.action_id)\n"
12246 "\t\tgoto %s;\n",
12247 a->name,
12248 instr_pos,
12249 data->jmp_label);
12250 return;
12251
12252 case INSTR_JMP_EQ:
12253 fprintf(f,
12254 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) == "
12255 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
12256 "\t\tgoto %s;\n",
12257 a->name,
12258 instr_pos,
12259 a->name,
12260 instr_pos,
12261 data->jmp_label);
12262 return;
12263
12264 case INSTR_JMP_EQ_MH:
12265 fprintf(f,
12266 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) == "
12267 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
12268 "\t\tgoto %s;\n",
12269 a->name,
12270 instr_pos,
12271 a->name,
12272 instr_pos,
12273 data->jmp_label);
12274 return;
12275
12276 case INSTR_JMP_EQ_HM:
12277 fprintf(f,
12278 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) == "
12279 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
12280 "\t\tgoto %s;\n",
12281 a->name,
12282 instr_pos,
12283 a->name,
12284 instr_pos,
12285 data->jmp_label);
12286 return;
12287
12288 case INSTR_JMP_EQ_HH:
12289 fprintf(f,
12290 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) == "
12291 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
12292 "\t\tgoto %s;\n",
12293 a->name,
12294 instr_pos,
12295 a->name,
12296 instr_pos,
12297 data->jmp_label);
12298 return;
12299
12300 case INSTR_JMP_EQ_I:
12301 fprintf(f,
12302 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) == "
12303 "action_%s_instructions[%u].jmp.b_val)\n"
12304 "\t\tgoto %s;\n",
12305 a->name,
12306 instr_pos,
12307 a->name,
12308 instr_pos,
12309 data->jmp_label);
12310 return;
12311
12312 case INSTR_JMP_NEQ:
12313 fprintf(f,
12314 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) != "
12315 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
12316 "\t\tgoto %s;\n",
12317 a->name,
12318 instr_pos,
12319 a->name,
12320 instr_pos,
12321 data->jmp_label);
12322 return;
12323
12324 case INSTR_JMP_NEQ_MH:
12325 fprintf(f,
12326 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) != "
12327 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
12328 "\t\tgoto %s;\n",
12329 a->name,
12330 instr_pos,
12331 a->name,
12332 instr_pos,
12333 data->jmp_label);
12334 return;
12335
12336 case INSTR_JMP_NEQ_HM:
12337 fprintf(f,
12338 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) != "
12339 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
12340 "\t\tgoto %s;\n",
12341 a->name,
12342 instr_pos,
12343 a->name,
12344 instr_pos,
12345 data->jmp_label);
12346 return;
12347
12348 case INSTR_JMP_NEQ_HH:
12349 fprintf(f,
12350 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) != "
12351 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
12352 "\t\tgoto %s;\n",
12353 a->name,
12354 instr_pos,
12355 a->name,
12356 instr_pos,
12357 data->jmp_label);
12358 return;
12359
12360 case INSTR_JMP_NEQ_I:
12361 fprintf(f,
12362 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) != "
12363 "action_%s_instructions[%u].jmp.b_val)\n"
12364 "\t\tgoto %s;\n",
12365 a->name,
12366 instr_pos,
12367 a->name,
12368 instr_pos,
12369 data->jmp_label);
12370 return;
12371
12372 case INSTR_JMP_LT:
12373 fprintf(f,
12374 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) < "
12375 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
12376 "\t\tgoto %s;\n",
12377 a->name,
12378 instr_pos,
12379 a->name,
12380 instr_pos,
12381 data->jmp_label);
12382 return;
12383
12384 case INSTR_JMP_LT_MH:
12385 fprintf(f,
12386 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) < "
12387 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
12388 "\t\tgoto %s;\n",
12389 a->name,
12390 instr_pos,
12391 a->name,
12392 instr_pos,
12393 data->jmp_label);
12394 return;
12395
12396 case INSTR_JMP_LT_HM:
12397 fprintf(f,
12398 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) < "
12399 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
12400 "\t\tgoto %s;\n",
12401 a->name,
12402 instr_pos,
12403 a->name,
12404 instr_pos,
12405 data->jmp_label);
12406 return;
12407
12408 case INSTR_JMP_LT_HH:
12409 fprintf(f,
12410 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) < "
12411 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
12412 "\t\tgoto %s;\n",
12413 a->name,
12414 instr_pos,
12415 a->name,
12416 instr_pos,
12417 data->jmp_label);
12418 return;
12419
12420 case INSTR_JMP_LT_MI:
12421 fprintf(f,
12422 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) < "
12423 "action_%s_instructions[%u].jmp.b_val)\n"
12424 "\t\tgoto %s;\n",
12425 a->name,
12426 instr_pos,
12427 a->name,
12428 instr_pos,
12429 data->jmp_label);
12430 return;
12431
12432 case INSTR_JMP_LT_HI:
12433 fprintf(f,
12434 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) < "
12435 "action_%s_instructions[%u].jmp.b_val)\n"
12436 "\t\tgoto %s;\n",
12437 a->name,
12438 instr_pos,
12439 a->name,
12440 instr_pos,
12441 data->jmp_label);
12442 return;
12443
12444 case INSTR_JMP_GT:
12445 fprintf(f,
12446 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) > "
12447 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
12448 "\t\tgoto %s;\n",
12449 a->name,
12450 instr_pos,
12451 a->name,
12452 instr_pos,
12453 data->jmp_label);
12454 return;
12455
12456 case INSTR_JMP_GT_MH:
12457 fprintf(f,
12458 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) > "
12459 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
12460 "\t\tgoto %s;\n",
12461 a->name,
12462 instr_pos,
12463 a->name,
12464 instr_pos,
12465 data->jmp_label);
12466 return;
12467
12468 case INSTR_JMP_GT_HM:
12469 fprintf(f,
12470 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) > "
12471 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
12472 "\t\tgoto %s;\n",
12473 a->name,
12474 instr_pos,
12475 a->name,
12476 instr_pos,
12477 data->jmp_label);
12478 return;
12479
12480 case INSTR_JMP_GT_HH:
12481 fprintf(f,
12482 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) > "
12483 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
12484 "\t\tgoto %s;\n",
12485 a->name,
12486 instr_pos,
12487 a->name,
12488 instr_pos,
12489 data->jmp_label);
12490 return;
12491
12492 case INSTR_JMP_GT_MI:
12493 fprintf(f,
12494 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) > "
12495 "action_%s_instructions[%u].jmp.b_val)\n"
12496 "\t\tgoto %s;\n",
12497 a->name,
12498 instr_pos,
12499 a->name,
12500 instr_pos,
12501 data->jmp_label);
12502 return;
12503
12504 case INSTR_JMP_GT_HI:
12505 fprintf(f,
12506 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) > "
12507 "action_%s_instructions[%u].jmp.b_val)\n"
12508 "\t\tgoto %s;\n",
12509 a->name,
12510 instr_pos,
12511 a->name,
12512 instr_pos,
12513 data->jmp_label);
12514 return;
12515
12516 default:
12517 return;
12518 }
12519}
12520
12521static void
12522action_instr_return_codegen(FILE *f)
12523{
12524 fprintf(f,
12525 "return;\n");
12526}
12527
12528static void
12529action_instr_codegen(struct action *a, FILE *f)
12530{
12531 uint32_t i;
12532
12533 fprintf(f,
12534 "void\n"
12535 "action_%s_run(struct rte_swx_pipeline *p)\n"
12536 "{\n"
12537 "\tstruct thread *t = &p->threads[p->thread_id];\n"
12538 "\n",
12539 a->name);
12540
12541 for (i = 0; i < a->n_instructions; i++) {
12542 struct instruction *instr = &a->instructions[i];
12543 struct instruction_data *data = &a->instruction_data[i];
12544
12545
12546 if (data->label[0])
12547 fprintf(f, "\n%s : ", data->label);
12548 else
12549 fprintf(f, "\n\t");
12550
12551
12552 if (instruction_does_tx(instr)) {
12553 action_instr_does_tx_codegen(a, i, instr, f);
12554 continue;
12555 }
12556
12557
12558 if (instr->type == INSTR_EXTERN_OBJ) {
12559 action_instr_extern_obj_codegen(a, i, f);
12560 continue;
12561 }
12562
12563 if (instr->type == INSTR_EXTERN_FUNC) {
12564 action_instr_extern_func_codegen(a, i, f);
12565 continue;
12566 }
12567
12568
12569 if (instruction_is_jmp(instr)) {
12570 action_instr_jmp_codegen(a, i, instr, data, f);
12571 continue;
12572 }
12573
12574
12575 if (instr->type == INSTR_RETURN) {
12576 action_instr_return_codegen(f);
12577 continue;
12578 }
12579
12580
12581 fprintf(f,
12582 "%s(p, t, &action_%s_instructions[%u]);\n",
12583 instr_type_to_func(instr),
12584 a->name,
12585 i);
12586 }
12587
12588 fprintf(f, "}\n\n");
12589}
12590
12591struct instruction_group {
12592 TAILQ_ENTRY(instruction_group) node;
12593
12594 uint32_t group_id;
12595
12596 uint32_t first_instr_id;
12597
12598 uint32_t last_instr_id;
12599
12600 instr_exec_t func;
12601};
12602
12603TAILQ_HEAD(instruction_group_list, instruction_group);
12604
12605static struct instruction_group *
12606instruction_group_list_group_find(struct instruction_group_list *igl, uint32_t instruction_id)
12607{
12608 struct instruction_group *g;
12609
12610 TAILQ_FOREACH(g, igl, node)
12611 if ((g->first_instr_id <= instruction_id) && (instruction_id <= g->last_instr_id))
12612 return g;
12613
12614 return NULL;
12615}
12616
12617static void
12618instruction_group_list_free(struct instruction_group_list *igl)
12619{
12620 if (!igl)
12621 return;
12622
12623 for ( ; ; ) {
12624 struct instruction_group *g;
12625
12626 g = TAILQ_FIRST(igl);
12627 if (!g)
12628 break;
12629
12630 TAILQ_REMOVE(igl, g, node);
12631 free(g);
12632 }
12633
12634 free(igl);
12635}
12636
12637static struct instruction_group_list *
12638instruction_group_list_create(struct rte_swx_pipeline *p)
12639{
12640 struct instruction_group_list *igl = NULL;
12641 struct instruction_group *g = NULL;
12642 uint32_t n_groups = 0, i;
12643
12644 if (!p || !p->instructions || !p->instruction_data || !p->n_instructions)
12645 goto error;
12646
12647
12648 igl = calloc(1, sizeof(struct instruction_group_list));
12649 if (!igl)
12650 goto error;
12651
12652 TAILQ_INIT(igl);
12653
12654
12655 g = calloc(1, sizeof(struct instruction_group));
12656 if (!g)
12657 goto error;
12658
12659
12660
12661
12662 for (i = 0; i < p->n_instructions; i++) {
12663 struct instruction *instr = &p->instructions[i];
12664
12665
12666 if (!instruction_does_thread_yield(instr))
12667 continue;
12668
12669
12670
12671
12672
12673 if (i - g->first_instr_id) {
12674
12675 g->last_instr_id = i - 1;
12676
12677
12678 TAILQ_INSERT_TAIL(igl, g, node);
12679 n_groups++;
12680
12681
12682 g = calloc(1, sizeof(struct instruction_group));
12683 if (!g)
12684 goto error;
12685
12686
12687 g->group_id = n_groups;
12688 g->first_instr_id = i;
12689 }
12690
12691
12692
12693
12694
12695
12696
12697 g->last_instr_id = i;
12698
12699
12700 TAILQ_INSERT_TAIL(igl, g, node);
12701 n_groups++;
12702
12703
12704 g = calloc(1, sizeof(struct instruction_group));
12705 if (!g)
12706 goto error;
12707
12708
12709 g->group_id = n_groups;
12710 g->first_instr_id = i + 1;
12711 }
12712
12713
12714 if (i - g->first_instr_id) {
12715
12716 g->last_instr_id = i - 1;
12717
12718
12719 TAILQ_INSERT_TAIL(igl, g, node);
12720 n_groups++;
12721 } else
12722 free(g);
12723
12724 g = NULL;
12725
12726
12727
12728
12729
12730
12731 for ( ; ; ) {
12732 int is_modified = 0;
12733
12734 for (i = 0; i < p->n_instructions; i++) {
12735 struct instruction_data *data = &p->instruction_data[i];
12736 struct instruction_group *g;
12737 uint32_t j;
12738
12739
12740 if (!data->n_users)
12741 continue;
12742
12743 g = instruction_group_list_group_find(igl, i);
12744 if (!g)
12745 goto error;
12746
12747
12748 for (j = 0; j < p->n_instructions; j++) {
12749 struct instruction *jmp_instr = &p->instructions[j];
12750 struct instruction_data *jmp_data = &p->instruction_data[j];
12751 struct instruction_group *jmp_g, *new_g;
12752
12753
12754
12755
12756 if (!instruction_is_jmp(jmp_instr) ||
12757 strcmp(jmp_data->jmp_label, data->label))
12758 continue;
12759
12760 jmp_g = instruction_group_list_group_find(igl, j);
12761 if (!jmp_g)
12762 goto error;
12763
12764
12765
12766
12767
12768
12769 if ((jmp_g->group_id == g->group_id) || (g->first_instr_id == i))
12770 continue;
12771
12772
12773
12774
12775 new_g = calloc(1, sizeof(struct instruction_group));
12776 if (!new_g)
12777 goto error;
12778
12779 new_g->group_id = n_groups;
12780 new_g->first_instr_id = i;
12781 new_g->last_instr_id = g->last_instr_id;
12782
12783 g->last_instr_id = i - 1;
12784
12785 TAILQ_INSERT_AFTER(igl, g, new_g, node);
12786 n_groups++;
12787 is_modified = 1;
12788
12789
12790
12791
12792
12793 break;
12794 }
12795 }
12796
12797
12798
12799
12800
12801
12802
12803 if (!is_modified)
12804 break;
12805 }
12806
12807
12808 i = 0;
12809 TAILQ_FOREACH(g, igl, node) {
12810 g->group_id = i;
12811
12812 i++;
12813 }
12814
12815 return igl;
12816
12817error:
12818 instruction_group_list_free(igl);
12819
12820 free(g);
12821
12822 return NULL;
12823}
12824
12825static void
12826pipeline_instr_does_tx_codegen(struct rte_swx_pipeline *p __rte_unused,
12827 uint32_t instr_pos,
12828 struct instruction *instr,
12829 FILE *f)
12830{
12831 fprintf(f,
12832 "%s(p, t, &pipeline_instructions[%u]);\n"
12833 "\tthread_ip_reset(p, t);\n"
12834 "\tinstr_rx_exec(p);\n"
12835 "\treturn;\n",
12836 instr_type_to_func(instr),
12837 instr_pos);
12838}
12839
12840static int
12841pipeline_instr_jmp_codegen(struct rte_swx_pipeline *p,
12842 struct instruction_group_list *igl,
12843 uint32_t jmp_instr_id,
12844 struct instruction *jmp_instr,
12845 struct instruction_data *jmp_data,
12846 FILE *f)
12847{
12848 struct instruction_group *jmp_g, *g;
12849 struct instruction_data *data;
12850 uint32_t instr_id;
12851
12852 switch (jmp_instr->type) {
12853 case INSTR_JMP:
12854 break;
12855
12856 case INSTR_JMP_VALID:
12857 fprintf(f,
12858 "if (HEADER_VALID(t, pipeline_instructions[%u].jmp.header_id))",
12859 jmp_instr_id);
12860 break;
12861
12862 case INSTR_JMP_INVALID:
12863 fprintf(f,
12864 "if (!HEADER_VALID(t, pipeline_instructions[%u].jmp.header_id))",
12865 jmp_instr_id);
12866 break;
12867
12868 case INSTR_JMP_HIT:
12869 fprintf(f,
12870 "if (t->hit)\n");
12871 break;
12872
12873 case INSTR_JMP_MISS:
12874 fprintf(f,
12875 "if (!t->hit)\n");
12876 break;
12877
12878 case INSTR_JMP_ACTION_HIT:
12879 fprintf(f,
12880 "if (t->action_id == pipeline_instructions[%u].jmp.action_id)",
12881 jmp_instr_id);
12882 break;
12883
12884 case INSTR_JMP_ACTION_MISS:
12885 fprintf(f,
12886 "if (t->action_id != pipeline_instructions[%u].jmp.action_id)",
12887 jmp_instr_id);
12888 break;
12889
12890 case INSTR_JMP_EQ:
12891 fprintf(f,
12892 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) == "
12893 "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
12894 jmp_instr_id,
12895 jmp_instr_id);
12896 break;
12897
12898 case INSTR_JMP_EQ_MH:
12899 fprintf(f,
12900 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) == "
12901 "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
12902 jmp_instr_id,
12903 jmp_instr_id);
12904 break;
12905
12906 case INSTR_JMP_EQ_HM:
12907 fprintf(f,
12908 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) == "
12909 "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
12910 jmp_instr_id,
12911 jmp_instr_id);
12912 break;
12913
12914 case INSTR_JMP_EQ_HH:
12915 fprintf(f,
12916 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) == "
12917 "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
12918 jmp_instr_id,
12919 jmp_instr_id);
12920 break;
12921
12922 case INSTR_JMP_EQ_I:
12923 fprintf(f,
12924 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) == "
12925 "pipeline_instructions[%u].jmp.b_val)",
12926 jmp_instr_id,
12927 jmp_instr_id);
12928 break;
12929
12930 case INSTR_JMP_NEQ:
12931 fprintf(f,
12932 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) != "
12933 "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
12934 jmp_instr_id,
12935 jmp_instr_id);
12936 break;
12937
12938 case INSTR_JMP_NEQ_MH:
12939 fprintf(f,
12940 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) != "
12941 "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
12942 jmp_instr_id,
12943 jmp_instr_id);
12944 break;
12945
12946 case INSTR_JMP_NEQ_HM:
12947 fprintf(f,
12948 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) != "
12949 "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
12950 jmp_instr_id,
12951 jmp_instr_id);
12952 break;
12953
12954 case INSTR_JMP_NEQ_HH:
12955 fprintf(f,
12956 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) != "
12957 "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
12958 jmp_instr_id,
12959 jmp_instr_id);
12960 break;
12961
12962 case INSTR_JMP_NEQ_I:
12963 fprintf(f,
12964 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) != "
12965 "pipeline_instructions[%u].jmp.b_val)",
12966 jmp_instr_id,
12967 jmp_instr_id);
12968 break;
12969
12970 case INSTR_JMP_LT:
12971 fprintf(f,
12972 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) < "
12973 "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
12974 jmp_instr_id,
12975 jmp_instr_id);
12976 break;
12977
12978 case INSTR_JMP_LT_MH:
12979 fprintf(f,
12980 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) < "
12981 "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
12982 jmp_instr_id,
12983 jmp_instr_id);
12984 break;
12985
12986 case INSTR_JMP_LT_HM:
12987 fprintf(f,
12988 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) < "
12989 "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
12990 jmp_instr_id,
12991 jmp_instr_id);
12992 break;
12993
12994 case INSTR_JMP_LT_HH:
12995 fprintf(f,
12996 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) < "
12997 "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
12998 jmp_instr_id,
12999 jmp_instr_id);
13000 break;
13001
13002 case INSTR_JMP_LT_MI:
13003 fprintf(f,
13004 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) < "
13005 "pipeline_instructions[%u].jmp.b_val)",
13006 jmp_instr_id,
13007 jmp_instr_id);
13008 break;
13009
13010 case INSTR_JMP_LT_HI:
13011 fprintf(f,
13012 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) < "
13013 "pipeline_instructions[%u].jmp.b_val)",
13014 jmp_instr_id,
13015 jmp_instr_id);
13016 break;
13017
13018 case INSTR_JMP_GT:
13019 fprintf(f,
13020 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) > "
13021 "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
13022 jmp_instr_id,
13023 jmp_instr_id);
13024 break;
13025
13026 case INSTR_JMP_GT_MH:
13027 fprintf(f,
13028 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) > "
13029 "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
13030 jmp_instr_id,
13031 jmp_instr_id);
13032 break;
13033
13034 case INSTR_JMP_GT_HM:
13035 fprintf(f,
13036 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) > "
13037 "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
13038 jmp_instr_id,
13039 jmp_instr_id);
13040 break;
13041
13042 case INSTR_JMP_GT_HH:
13043 fprintf(f,
13044 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) > "
13045 "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
13046 jmp_instr_id,
13047 jmp_instr_id);
13048 break;
13049
13050 case INSTR_JMP_GT_MI:
13051 fprintf(f,
13052 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) > "
13053 "pipeline_instructions[%u].jmp.b_val)",
13054 jmp_instr_id,
13055 jmp_instr_id);
13056 break;
13057
13058 case INSTR_JMP_GT_HI:
13059 fprintf(f,
13060 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) > "
13061 "pipeline_instructions[%u].jmp.b_val)",
13062 jmp_instr_id,
13063 jmp_instr_id);
13064 break;
13065
13066 default:
13067 break;
13068 }
13069
13070
13071 jmp_g = instruction_group_list_group_find(igl, jmp_instr_id);
13072 if (!jmp_g)
13073 return -EINVAL;
13074
13075
13076 data = label_find(p->instruction_data, p->n_instructions, jmp_data->jmp_label);
13077 if (!data)
13078 return -EINVAL;
13079
13080 instr_id = data - p->instruction_data;
13081
13082 g = instruction_group_list_group_find(igl, instr_id);
13083 if (!g)
13084 return -EINVAL;
13085
13086
13087
13088
13089 if (g->group_id == jmp_g->group_id)
13090 fprintf(f,
13091 "\n\t\tgoto %s;\n",
13092 jmp_data->jmp_label);
13093 else
13094 fprintf(f,
13095 " {\n"
13096 "\t\tthread_ip_set(t, &p->instructions[%u]);\n"
13097 "\t\treturn;\n"
13098 "\t}\n\n",
13099 g->group_id);
13100
13101 return 0;
13102}
13103
13104static void
13105instruction_group_list_codegen(struct instruction_group_list *igl,
13106 struct rte_swx_pipeline *p,
13107 FILE *f)
13108{
13109 struct instruction_group *g;
13110 uint32_t i;
13111 int is_required = 0;
13112
13113
13114 TAILQ_FOREACH(g, igl, node)
13115 if (g->first_instr_id < g->last_instr_id)
13116 is_required = 1;
13117
13118 if (!is_required)
13119 return;
13120
13121
13122 fprintf(f,
13123 "static const struct instruction pipeline_instructions[] = {\n");
13124
13125 for (i = 0; i < p->n_instructions; i++) {
13126 struct instruction *instr = &p->instructions[i];
13127 instruction_export_t func = export_table[instr->type];
13128
13129 func(instr, f);
13130 }
13131
13132 fprintf(f, "};\n\n");
13133
13134
13135
13136
13137 TAILQ_FOREACH(g, igl, node) {
13138 struct instruction *last_instr;
13139 uint32_t j;
13140
13141
13142 if (g->last_instr_id == g->first_instr_id)
13143 continue;
13144
13145
13146 fprintf(f,
13147 "void\n"
13148 "pipeline_func_%u(struct rte_swx_pipeline *p)\n"
13149 "{\n"
13150 "\tstruct thread *t = &p->threads[p->thread_id];\n"
13151 "\n",
13152 g->group_id);
13153
13154
13155 for (j = g->first_instr_id; j <= g->last_instr_id; j++) {
13156 struct instruction *instr = &p->instructions[j];
13157 struct instruction_data *data = &p->instruction_data[j];
13158
13159
13160 if (data->label[0])
13161 fprintf(f, "\n%s : ", data->label);
13162 else
13163 fprintf(f, "\n\t");
13164
13165
13166 if (instruction_does_tx(instr)) {
13167 pipeline_instr_does_tx_codegen(p, j, instr, f);
13168 continue;
13169 }
13170
13171
13172 if (instruction_is_jmp(instr)) {
13173 pipeline_instr_jmp_codegen(p, igl, j, instr, data, f);
13174 continue;
13175 }
13176
13177
13178 fprintf(f,
13179 "%s(p, t, &pipeline_instructions[%u]);\n",
13180 instr_type_to_func(instr),
13181 j);
13182 }
13183
13184
13185
13186
13187
13188
13189
13190 last_instr = &p->instructions[g->last_instr_id];
13191
13192 if (!instruction_does_tx(last_instr) && (last_instr->type != INSTR_JMP))
13193 fprintf(f,
13194 "thread_ip_inc(p);\n");
13195
13196 fprintf(f,
13197 "}\n"
13198 "\n");
13199 }
13200}
13201
13202static uint32_t
13203instruction_group_list_custom_instructions_count(struct instruction_group_list *igl)
13204{
13205 struct instruction_group *g;
13206 uint32_t n_custom_instr = 0;
13207
13208
13209
13210
13211
13212 TAILQ_FOREACH(g, igl, node) {
13213 if (g->first_instr_id == g->last_instr_id)
13214 continue;
13215
13216 n_custom_instr++;
13217 }
13218
13219 return n_custom_instr;
13220}
13221
13222static int
13223pipeline_codegen(struct rte_swx_pipeline *p, struct instruction_group_list *igl)
13224{
13225 struct action *a;
13226 FILE *f = NULL;
13227
13228
13229 f = fopen("/tmp/pipeline.c", "w");
13230 if (!f)
13231 return -EIO;
13232
13233
13234 fprintf(f, "#include \"rte_swx_pipeline_internal.h\"\n");
13235
13236
13237 TAILQ_FOREACH(a, &p->actions, node) {
13238 fprintf(f, "/**\n * Action %s\n */\n\n", a->name);
13239
13240 action_data_codegen(a, f);
13241
13242 fprintf(f, "\n");
13243
13244 action_instr_codegen(a, f);
13245
13246 fprintf(f, "\n");
13247 }
13248
13249
13250 instruction_group_list_codegen(igl, p, f);
13251
13252
13253 fclose(f);
13254
13255 return 0;
13256}
13257
13258#ifndef RTE_SWX_PIPELINE_CMD_MAX_SIZE
13259#define RTE_SWX_PIPELINE_CMD_MAX_SIZE 4096
13260#endif
13261
13262static int
13263pipeline_libload(struct rte_swx_pipeline *p, struct instruction_group_list *igl)
13264{
13265 struct action *a;
13266 struct instruction_group *g;
13267 char *dir_in, *buffer = NULL;
13268 const char *dir_out;
13269 int status = 0;
13270
13271
13272 dir_in = getenv("RTE_INSTALL_DIR");
13273 if (!dir_in) {
13274 status = -EINVAL;
13275 goto free;
13276 }
13277
13278 dir_out = "/tmp";
13279
13280
13281 buffer = malloc(RTE_SWX_PIPELINE_CMD_MAX_SIZE);
13282 if (!buffer) {
13283 status = -ENOMEM;
13284 goto free;
13285 }
13286
13287 snprintf(buffer,
13288 RTE_SWX_PIPELINE_CMD_MAX_SIZE,
13289 "gcc -c -O3 -fpic -Wno-deprecated-declarations -o %s/pipeline.o %s/pipeline.c "
13290 "-I %s/lib/pipeline "
13291 "-I %s/lib/eal/include "
13292 "-I %s/lib/eal/x86/include "
13293 "-I %s/lib/eal/include/generic "
13294 "-I %s/lib/meter "
13295 "-I %s/lib/port "
13296 "-I %s/lib/table "
13297 "-I %s/lib/pipeline "
13298 "-I %s/config "
13299 "-I %s/build "
13300 "-I %s/lib/eal/linux/include "
13301 ">%s/pipeline.log 2>&1 "
13302 "&& "
13303 "gcc -shared %s/pipeline.o -o %s/libpipeline.so "
13304 ">>%s/pipeline.log 2>&1",
13305 dir_out,
13306 dir_out,
13307 dir_in,
13308 dir_in,
13309 dir_in,
13310 dir_in,
13311 dir_in,
13312 dir_in,
13313 dir_in,
13314 dir_in,
13315 dir_in,
13316 dir_in,
13317 dir_in,
13318 dir_out,
13319 dir_out,
13320 dir_out,
13321 dir_out);
13322
13323
13324 status = system(buffer);
13325 if (status)
13326 goto free;
13327
13328
13329 snprintf(buffer,
13330 RTE_SWX_PIPELINE_CMD_MAX_SIZE,
13331 "%s/libpipeline.so",
13332 dir_out);
13333
13334 p->lib = dlopen(buffer, RTLD_LAZY);
13335 if (!p->lib) {
13336 status = -EIO;
13337 goto free;
13338 }
13339
13340
13341 TAILQ_FOREACH(a, &p->actions, node) {
13342 snprintf(buffer, RTE_SWX_PIPELINE_CMD_MAX_SIZE, "action_%s_run", a->name);
13343
13344 p->action_funcs[a->id] = dlsym(p->lib, buffer);
13345 if (!p->action_funcs[a->id]) {
13346 status = -EINVAL;
13347 goto free;
13348 }
13349 }
13350
13351
13352 TAILQ_FOREACH(g, igl, node) {
13353 if (g->first_instr_id == g->last_instr_id)
13354 continue;
13355
13356 snprintf(buffer, RTE_SWX_PIPELINE_CMD_MAX_SIZE, "pipeline_func_%u", g->group_id);
13357
13358 g->func = dlsym(p->lib, buffer);
13359 if (!g->func) {
13360 status = -EINVAL;
13361 goto free;
13362 }
13363 }
13364
13365free:
13366 if (status && p->lib) {
13367 dlclose(p->lib);
13368 p->lib = NULL;
13369 }
13370
13371 free(buffer);
13372
13373 return status;
13374}
13375
13376static int
13377pipeline_adjust_check(struct rte_swx_pipeline *p __rte_unused,
13378 struct instruction_group_list *igl)
13379{
13380 uint32_t n_custom_instr = instruction_group_list_custom_instructions_count(igl);
13381
13382
13383
13384
13385 if (INSTR_CUSTOM_0 + n_custom_instr > RTE_SWX_PIPELINE_INSTRUCTION_TABLE_SIZE_MAX)
13386 return -ENOSPC;
13387
13388 return 0;
13389}
13390
13391static void
13392pipeline_adjust(struct rte_swx_pipeline *p, struct instruction_group_list *igl)
13393{
13394 struct instruction_group *g;
13395 uint32_t i;
13396
13397
13398 for (i = 0; i < p->n_instructions; i++) {
13399 struct instruction *instr = &p->instructions[i];
13400
13401 if (instr->type == INSTR_TABLE)
13402 instr->type = INSTR_TABLE_AF;
13403
13404 if (instr->type == INSTR_LEARNER)
13405 instr->type = INSTR_LEARNER_AF;
13406 }
13407
13408
13409 i = 0;
13410 TAILQ_FOREACH(g, igl, node) {
13411 struct instruction *instr = &p->instructions[g->first_instr_id];
13412 uint32_t j;
13413
13414 if (g->first_instr_id == g->last_instr_id)
13415 continue;
13416
13417
13418 p->instruction_table[INSTR_CUSTOM_0 + i] = g->func;
13419
13420
13421 instr->type = INSTR_CUSTOM_0 + i;
13422
13423
13424 for (j = g->first_instr_id + 1; j <= g->last_instr_id; j++) {
13425 struct instruction_data *data = &p->instruction_data[j];
13426
13427 data->invalid = 1;
13428 }
13429
13430 i++;
13431 }
13432
13433
13434 p->n_instructions = instr_compact(p->instructions, p->instruction_data, p->n_instructions);
13435
13436
13437
13438
13439
13440 instr_jmp_resolve(p->instructions, p->instruction_data, p->n_instructions);
13441}
13442
13443static int
13444pipeline_compile(struct rte_swx_pipeline *p)
13445{
13446 struct instruction_group_list *igl = NULL;
13447 int status = 0;
13448
13449 igl = instruction_group_list_create(p);
13450 if (!igl) {
13451 status = -ENOMEM;
13452 goto free;
13453 }
13454
13455
13456 status = pipeline_codegen(p, igl);
13457 if (status)
13458 goto free;
13459
13460
13461 status = pipeline_libload(p, igl);
13462 if (status)
13463 goto free;
13464
13465
13466 status = pipeline_adjust_check(p, igl);
13467 if (status)
13468 goto free;
13469
13470 pipeline_adjust(p, igl);
13471
13472free:
13473 instruction_group_list_free(igl);
13474
13475 return status;
13476}
13477