1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2020 Intel Corporation
9 #include <rte_swx_port_ethdev.h>
10 #include <rte_swx_port_fd.h>
11 #include <rte_swx_port_ring.h>
12 #include "rte_swx_port_source_sink.h"
14 #include <rte_swx_table_em.h>
15 #include <rte_swx_table_wm.h>
17 #include "rte_swx_pipeline_internal.h"
19 #define CHECK(condition, err_code) \
25 #define CHECK_NAME(name, err_code) \
28 (strnlen((name), RTE_SWX_NAME_SIZE) < RTE_SWX_NAME_SIZE), \
31 #define CHECK_INSTRUCTION(instr, err_code) \
34 (strnlen((instr), RTE_SWX_INSTRUCTION_SIZE) < \
35 RTE_SWX_INSTRUCTION_SIZE), \
41 #ifndef RTE_SWX_PIPELINE_HUGE_PAGES_DISABLE
43 #include <rte_malloc.h>
46 env_malloc(size_t size, size_t alignment, int numa_node)
48 return rte_zmalloc_socket(NULL, size, alignment, numa_node);
52 env_free(void *start, size_t size __rte_unused)
62 env_malloc(size_t size, size_t alignment __rte_unused, int numa_node)
66 if (numa_available() == -1)
69 start = numa_alloc_onnode(size, numa_node);
73 memset(start, 0, size);
78 env_free(void *start, size_t size)
80 if (numa_available() == -1)
83 numa_free(start, size);
91 static struct struct_type *
92 struct_type_find(struct rte_swx_pipeline *p, const char *name)
94 struct struct_type *elem;
96 TAILQ_FOREACH(elem, &p->struct_types, node)
97 if (strcmp(elem->name, name) == 0)
103 static struct field *
104 struct_type_field_find(struct struct_type *st, const char *name)
108 for (i = 0; i < st->n_fields; i++) {
109 struct field *f = &st->fields[i];
111 if (strcmp(f->name, name) == 0)
119 rte_swx_pipeline_struct_type_register(struct rte_swx_pipeline *p,
121 struct rte_swx_field_params *fields,
123 int last_field_has_variable_size)
125 struct struct_type *st;
129 CHECK_NAME(name, EINVAL);
130 CHECK(fields, EINVAL);
131 CHECK(n_fields, EINVAL);
133 for (i = 0; i < n_fields; i++) {
134 struct rte_swx_field_params *f = &fields[i];
135 int var_size = ((i == n_fields - 1) && last_field_has_variable_size) ? 1 : 0;
138 CHECK_NAME(f->name, EINVAL);
139 CHECK(f->n_bits, EINVAL);
140 CHECK((f->n_bits <= 64) || var_size, EINVAL);
141 CHECK((f->n_bits & 7) == 0, EINVAL);
143 for (j = 0; j < i; j++) {
144 struct rte_swx_field_params *f_prev = &fields[j];
146 CHECK(strcmp(f->name, f_prev->name), EINVAL);
150 CHECK(!struct_type_find(p, name), EEXIST);
152 /* Node allocation. */
153 st = calloc(1, sizeof(struct struct_type));
156 st->fields = calloc(n_fields, sizeof(struct field));
162 /* Node initialization. */
163 strcpy(st->name, name);
164 for (i = 0; i < n_fields; i++) {
165 struct field *dst = &st->fields[i];
166 struct rte_swx_field_params *src = &fields[i];
167 int var_size = ((i == n_fields - 1) && last_field_has_variable_size) ? 1 : 0;
169 strcpy(dst->name, src->name);
170 dst->n_bits = src->n_bits;
171 dst->offset = st->n_bits;
172 dst->var_size = var_size;
174 st->n_bits += src->n_bits;
175 st->n_bits_min += var_size ? 0 : src->n_bits;
177 st->n_fields = n_fields;
178 st->var_size = last_field_has_variable_size;
180 /* Node add to tailq. */
181 TAILQ_INSERT_TAIL(&p->struct_types, st, node);
187 struct_build(struct rte_swx_pipeline *p)
191 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
192 struct thread *t = &p->threads[i];
194 t->structs = calloc(p->n_structs, sizeof(uint8_t *));
195 CHECK(t->structs, ENOMEM);
202 struct_build_free(struct rte_swx_pipeline *p)
206 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
207 struct thread *t = &p->threads[i];
215 struct_free(struct rte_swx_pipeline *p)
217 struct_build_free(p);
221 struct struct_type *elem;
223 elem = TAILQ_FIRST(&p->struct_types);
227 TAILQ_REMOVE(&p->struct_types, elem, node);
236 static struct port_in_type *
237 port_in_type_find(struct rte_swx_pipeline *p, const char *name)
239 struct port_in_type *elem;
244 TAILQ_FOREACH(elem, &p->port_in_types, node)
245 if (strcmp(elem->name, name) == 0)
252 rte_swx_pipeline_port_in_type_register(struct rte_swx_pipeline *p,
254 struct rte_swx_port_in_ops *ops)
256 struct port_in_type *elem;
259 CHECK_NAME(name, EINVAL);
261 CHECK(ops->create, EINVAL);
262 CHECK(ops->free, EINVAL);
263 CHECK(ops->pkt_rx, EINVAL);
264 CHECK(ops->stats_read, EINVAL);
266 CHECK(!port_in_type_find(p, name), EEXIST);
268 /* Node allocation. */
269 elem = calloc(1, sizeof(struct port_in_type));
272 /* Node initialization. */
273 strcpy(elem->name, name);
274 memcpy(&elem->ops, ops, sizeof(*ops));
276 /* Node add to tailq. */
277 TAILQ_INSERT_TAIL(&p->port_in_types, elem, node);
282 static struct port_in *
283 port_in_find(struct rte_swx_pipeline *p, uint32_t port_id)
285 struct port_in *port;
287 TAILQ_FOREACH(port, &p->ports_in, node)
288 if (port->id == port_id)
295 rte_swx_pipeline_port_in_config(struct rte_swx_pipeline *p,
297 const char *port_type_name,
300 struct port_in_type *type = NULL;
301 struct port_in *port = NULL;
306 CHECK(!port_in_find(p, port_id), EINVAL);
308 CHECK_NAME(port_type_name, EINVAL);
309 type = port_in_type_find(p, port_type_name);
312 obj = type->ops.create(args);
315 /* Node allocation. */
316 port = calloc(1, sizeof(struct port_in));
319 /* Node initialization. */
324 /* Node add to tailq. */
325 TAILQ_INSERT_TAIL(&p->ports_in, port, node);
326 if (p->n_ports_in < port_id + 1)
327 p->n_ports_in = port_id + 1;
333 port_in_build(struct rte_swx_pipeline *p)
335 struct port_in *port;
338 CHECK(p->n_ports_in, EINVAL);
339 CHECK(rte_is_power_of_2(p->n_ports_in), EINVAL);
341 for (i = 0; i < p->n_ports_in; i++)
342 CHECK(port_in_find(p, i), EINVAL);
344 p->in = calloc(p->n_ports_in, sizeof(struct port_in_runtime));
345 CHECK(p->in, ENOMEM);
347 TAILQ_FOREACH(port, &p->ports_in, node) {
348 struct port_in_runtime *in = &p->in[port->id];
350 in->pkt_rx = port->type->ops.pkt_rx;
358 port_in_build_free(struct rte_swx_pipeline *p)
365 port_in_free(struct rte_swx_pipeline *p)
367 port_in_build_free(p);
371 struct port_in *port;
373 port = TAILQ_FIRST(&p->ports_in);
377 TAILQ_REMOVE(&p->ports_in, port, node);
378 port->type->ops.free(port->obj);
382 /* Input port types. */
384 struct port_in_type *elem;
386 elem = TAILQ_FIRST(&p->port_in_types);
390 TAILQ_REMOVE(&p->port_in_types, elem, node);
398 static struct port_out_type *
399 port_out_type_find(struct rte_swx_pipeline *p, const char *name)
401 struct port_out_type *elem;
406 TAILQ_FOREACH(elem, &p->port_out_types, node)
407 if (!strcmp(elem->name, name))
414 rte_swx_pipeline_port_out_type_register(struct rte_swx_pipeline *p,
416 struct rte_swx_port_out_ops *ops)
418 struct port_out_type *elem;
421 CHECK_NAME(name, EINVAL);
423 CHECK(ops->create, EINVAL);
424 CHECK(ops->free, EINVAL);
425 CHECK(ops->pkt_tx, EINVAL);
426 CHECK(ops->pkt_fast_clone_tx, EINVAL);
427 CHECK(ops->pkt_clone_tx, EINVAL);
428 CHECK(ops->stats_read, EINVAL);
430 CHECK(!port_out_type_find(p, name), EEXIST);
432 /* Node allocation. */
433 elem = calloc(1, sizeof(struct port_out_type));
436 /* Node initialization. */
437 strcpy(elem->name, name);
438 memcpy(&elem->ops, ops, sizeof(*ops));
440 /* Node add to tailq. */
441 TAILQ_INSERT_TAIL(&p->port_out_types, elem, node);
446 static struct port_out *
447 port_out_find(struct rte_swx_pipeline *p, uint32_t port_id)
449 struct port_out *port;
451 TAILQ_FOREACH(port, &p->ports_out, node)
452 if (port->id == port_id)
459 rte_swx_pipeline_port_out_config(struct rte_swx_pipeline *p,
461 const char *port_type_name,
464 struct port_out_type *type = NULL;
465 struct port_out *port = NULL;
470 CHECK(!port_out_find(p, port_id), EINVAL);
472 CHECK_NAME(port_type_name, EINVAL);
473 type = port_out_type_find(p, port_type_name);
476 obj = type->ops.create(args);
479 /* Node allocation. */
480 port = calloc(1, sizeof(struct port_out));
483 /* Node initialization. */
488 /* Node add to tailq. */
489 TAILQ_INSERT_TAIL(&p->ports_out, port, node);
490 if (p->n_ports_out < port_id + 1)
491 p->n_ports_out = port_id + 1;
497 port_out_build(struct rte_swx_pipeline *p)
499 struct port_out *port;
502 CHECK(p->n_ports_out, EINVAL);
504 for (i = 0; i < p->n_ports_out; i++)
505 CHECK(port_out_find(p, i), EINVAL);
507 p->out = calloc(p->n_ports_out, sizeof(struct port_out_runtime));
508 CHECK(p->out, ENOMEM);
510 TAILQ_FOREACH(port, &p->ports_out, node) {
511 struct port_out_runtime *out = &p->out[port->id];
513 out->pkt_tx = port->type->ops.pkt_tx;
514 out->pkt_fast_clone_tx = port->type->ops.pkt_fast_clone_tx;
515 out->pkt_clone_tx = port->type->ops.pkt_clone_tx;
516 out->flush = port->type->ops.flush;
517 out->obj = port->obj;
524 port_out_build_free(struct rte_swx_pipeline *p)
531 port_out_free(struct rte_swx_pipeline *p)
533 port_out_build_free(p);
537 struct port_out *port;
539 port = TAILQ_FIRST(&p->ports_out);
543 TAILQ_REMOVE(&p->ports_out, port, node);
544 port->type->ops.free(port->obj);
548 /* Output port types. */
550 struct port_out_type *elem;
552 elem = TAILQ_FIRST(&p->port_out_types);
556 TAILQ_REMOVE(&p->port_out_types, elem, node);
565 rte_swx_pipeline_mirroring_config(struct rte_swx_pipeline *p,
566 struct rte_swx_pipeline_mirroring_params *params)
569 CHECK(params, EINVAL);
570 CHECK(params->n_slots, EINVAL);
571 CHECK(params->n_sessions, EINVAL);
572 CHECK(!p->build_done, EEXIST);
574 p->n_mirroring_slots = rte_align32pow2(params->n_slots);
575 if (p->n_mirroring_slots > 64)
576 p->n_mirroring_slots = 64;
578 p->n_mirroring_sessions = rte_align32pow2(params->n_sessions);
584 mirroring_build_free(struct rte_swx_pipeline *p)
588 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
589 struct thread *t = &p->threads[i];
591 /* mirroring_slots. */
592 free(t->mirroring_slots);
593 t->mirroring_slots = NULL;
596 /* mirroring_sessions. */
597 free(p->mirroring_sessions);
598 p->mirroring_sessions = NULL;
602 mirroring_free(struct rte_swx_pipeline *p)
604 mirroring_build_free(p);
608 mirroring_build(struct rte_swx_pipeline *p)
612 if (!p->n_mirroring_slots || !p->n_mirroring_sessions)
615 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
616 struct thread *t = &p->threads[i];
618 /* mirroring_slots. */
619 t->mirroring_slots = calloc(p->n_mirroring_slots, sizeof(uint32_t));
620 if (!t->mirroring_slots)
624 /* mirroring_sessions. */
625 p->mirroring_sessions = calloc(p->n_mirroring_sessions, sizeof(struct mirroring_session));
626 if (!p->mirroring_sessions)
632 mirroring_build_free(p);
639 static struct extern_type *
640 extern_type_find(struct rte_swx_pipeline *p, const char *name)
642 struct extern_type *elem;
644 TAILQ_FOREACH(elem, &p->extern_types, node)
645 if (strcmp(elem->name, name) == 0)
651 static struct extern_type_member_func *
652 extern_type_member_func_find(struct extern_type *type, const char *name)
654 struct extern_type_member_func *elem;
656 TAILQ_FOREACH(elem, &type->funcs, node)
657 if (strcmp(elem->name, name) == 0)
663 static struct extern_obj *
664 extern_obj_find(struct rte_swx_pipeline *p, const char *name)
666 struct extern_obj *elem;
668 TAILQ_FOREACH(elem, &p->extern_objs, node)
669 if (strcmp(elem->name, name) == 0)
675 static struct extern_type_member_func *
676 extern_obj_member_func_parse(struct rte_swx_pipeline *p,
678 struct extern_obj **obj)
680 struct extern_obj *object;
681 struct extern_type_member_func *func;
682 char *object_name, *func_name;
684 if (name[0] != 'e' || name[1] != '.')
687 object_name = strdup(&name[2]);
691 func_name = strchr(object_name, '.');
700 object = extern_obj_find(p, object_name);
706 func = extern_type_member_func_find(object->type, func_name);
719 static struct field *
720 extern_obj_mailbox_field_parse(struct rte_swx_pipeline *p,
722 struct extern_obj **object)
724 struct extern_obj *obj;
726 char *obj_name, *field_name;
728 if ((name[0] != 'e') || (name[1] != '.'))
731 obj_name = strdup(&name[2]);
735 field_name = strchr(obj_name, '.');
744 obj = extern_obj_find(p, obj_name);
750 f = struct_type_field_find(obj->type->mailbox_struct_type, field_name);
764 rte_swx_pipeline_extern_type_register(struct rte_swx_pipeline *p,
766 const char *mailbox_struct_type_name,
767 rte_swx_extern_type_constructor_t constructor,
768 rte_swx_extern_type_destructor_t destructor)
770 struct extern_type *elem;
771 struct struct_type *mailbox_struct_type;
775 CHECK_NAME(name, EINVAL);
776 CHECK(!extern_type_find(p, name), EEXIST);
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);
783 CHECK(constructor, EINVAL);
784 CHECK(destructor, EINVAL);
786 /* Node allocation. */
787 elem = calloc(1, sizeof(struct extern_type));
790 /* Node initialization. */
791 strcpy(elem->name, name);
792 elem->mailbox_struct_type = mailbox_struct_type;
793 elem->constructor = constructor;
794 elem->destructor = destructor;
795 TAILQ_INIT(&elem->funcs);
797 /* Node add to tailq. */
798 TAILQ_INSERT_TAIL(&p->extern_types, elem, node);
804 rte_swx_pipeline_extern_type_member_func_register(struct rte_swx_pipeline *p,
805 const char *extern_type_name,
807 rte_swx_extern_type_member_func_t member_func)
809 struct extern_type *type;
810 struct extern_type_member_func *type_member;
814 CHECK_NAME(extern_type_name, EINVAL);
815 type = extern_type_find(p, extern_type_name);
817 CHECK(type->n_funcs < RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX, ENOSPC);
819 CHECK_NAME(name, EINVAL);
820 CHECK(!extern_type_member_func_find(type, name), EEXIST);
822 CHECK(member_func, EINVAL);
824 /* Node allocation. */
825 type_member = calloc(1, sizeof(struct extern_type_member_func));
826 CHECK(type_member, ENOMEM);
828 /* Node initialization. */
829 strcpy(type_member->name, name);
830 type_member->func = member_func;
831 type_member->id = type->n_funcs;
833 /* Node add to tailq. */
834 TAILQ_INSERT_TAIL(&type->funcs, type_member, node);
841 rte_swx_pipeline_extern_object_config(struct rte_swx_pipeline *p,
842 const char *extern_type_name,
846 struct extern_type *type;
847 struct extern_obj *obj;
852 CHECK_NAME(extern_type_name, EINVAL);
853 type = extern_type_find(p, extern_type_name);
856 CHECK_NAME(name, EINVAL);
857 CHECK(!extern_obj_find(p, name), EEXIST);
859 /* Node allocation. */
860 obj = calloc(1, sizeof(struct extern_obj));
863 /* Object construction. */
864 obj_handle = type->constructor(args);
870 /* Node initialization. */
871 strcpy(obj->name, name);
873 obj->obj = obj_handle;
874 obj->struct_id = p->n_structs;
875 obj->id = p->n_extern_objs;
877 /* Node add to tailq. */
878 TAILQ_INSERT_TAIL(&p->extern_objs, obj, node);
886 extern_obj_build(struct rte_swx_pipeline *p)
890 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
891 struct thread *t = &p->threads[i];
892 struct extern_obj *obj;
894 t->extern_objs = calloc(p->n_extern_objs,
895 sizeof(struct extern_obj_runtime));
896 CHECK(t->extern_objs, ENOMEM);
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;
907 r->mailbox = calloc(1, mailbox_size);
908 CHECK(r->mailbox, ENOMEM);
910 TAILQ_FOREACH(func, &obj->type->funcs, node)
911 r->funcs[func->id] = func->func;
913 t->structs[obj->struct_id] = r->mailbox;
921 extern_obj_build_free(struct rte_swx_pipeline *p)
925 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
926 struct thread *t = &p->threads[i];
932 for (j = 0; j < p->n_extern_objs; j++) {
933 struct extern_obj_runtime *r = &t->extern_objs[j];
938 free(t->extern_objs);
939 t->extern_objs = NULL;
944 extern_obj_free(struct rte_swx_pipeline *p)
946 extern_obj_build_free(p);
948 /* Extern objects. */
950 struct extern_obj *elem;
952 elem = TAILQ_FIRST(&p->extern_objs);
956 TAILQ_REMOVE(&p->extern_objs, elem, node);
958 elem->type->destructor(elem->obj);
964 struct extern_type *elem;
966 elem = TAILQ_FIRST(&p->extern_types);
970 TAILQ_REMOVE(&p->extern_types, elem, node);
973 struct extern_type_member_func *func;
975 func = TAILQ_FIRST(&elem->funcs);
979 TAILQ_REMOVE(&elem->funcs, func, node);
990 static struct extern_func *
991 extern_func_find(struct rte_swx_pipeline *p, const char *name)
993 struct extern_func *elem;
995 TAILQ_FOREACH(elem, &p->extern_funcs, node)
996 if (strcmp(elem->name, name) == 0)
1002 static struct extern_func *
1003 extern_func_parse(struct rte_swx_pipeline *p,
1006 if (name[0] != 'f' || name[1] != '.')
1009 return extern_func_find(p, &name[2]);
1012 static struct field *
1013 extern_func_mailbox_field_parse(struct rte_swx_pipeline *p,
1015 struct extern_func **function)
1017 struct extern_func *func;
1019 char *func_name, *field_name;
1021 if ((name[0] != 'f') || (name[1] != '.'))
1024 func_name = strdup(&name[2]);
1028 field_name = strchr(func_name, '.');
1037 func = extern_func_find(p, func_name);
1043 f = struct_type_field_find(func->mailbox_struct_type, field_name);
1057 rte_swx_pipeline_extern_func_register(struct rte_swx_pipeline *p,
1059 const char *mailbox_struct_type_name,
1060 rte_swx_extern_func_t func)
1062 struct extern_func *f;
1063 struct struct_type *mailbox_struct_type;
1067 CHECK_NAME(name, EINVAL);
1068 CHECK(!extern_func_find(p, name), EEXIST);
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);
1075 CHECK(func, EINVAL);
1077 /* Node allocation. */
1078 f = calloc(1, sizeof(struct extern_func));
1079 CHECK(func, ENOMEM);
1081 /* Node initialization. */
1082 strcpy(f->name, name);
1083 f->mailbox_struct_type = mailbox_struct_type;
1085 f->struct_id = p->n_structs;
1086 f->id = p->n_extern_funcs;
1088 /* Node add to tailq. */
1089 TAILQ_INSERT_TAIL(&p->extern_funcs, f, node);
1090 p->n_extern_funcs++;
1097 extern_func_build(struct rte_swx_pipeline *p)
1101 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1102 struct thread *t = &p->threads[i];
1103 struct extern_func *func;
1105 /* Memory allocation. */
1106 t->extern_funcs = calloc(p->n_extern_funcs,
1107 sizeof(struct extern_func_runtime));
1108 CHECK(t->extern_funcs, ENOMEM);
1110 /* Extern function. */
1111 TAILQ_FOREACH(func, &p->extern_funcs, node) {
1112 struct extern_func_runtime *r =
1113 &t->extern_funcs[func->id];
1114 uint32_t mailbox_size =
1115 func->mailbox_struct_type->n_bits / 8;
1117 r->func = func->func;
1119 r->mailbox = calloc(1, mailbox_size);
1120 CHECK(r->mailbox, ENOMEM);
1122 t->structs[func->struct_id] = r->mailbox;
1130 extern_func_build_free(struct rte_swx_pipeline *p)
1134 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1135 struct thread *t = &p->threads[i];
1138 if (!t->extern_funcs)
1141 for (j = 0; j < p->n_extern_funcs; j++) {
1142 struct extern_func_runtime *r = &t->extern_funcs[j];
1147 free(t->extern_funcs);
1148 t->extern_funcs = NULL;
1153 extern_func_free(struct rte_swx_pipeline *p)
1155 extern_func_build_free(p);
1158 struct extern_func *elem;
1160 elem = TAILQ_FIRST(&p->extern_funcs);
1164 TAILQ_REMOVE(&p->extern_funcs, elem, node);
1172 static struct header *
1173 header_find(struct rte_swx_pipeline *p, const char *name)
1175 struct header *elem;
1177 TAILQ_FOREACH(elem, &p->headers, node)
1178 if (strcmp(elem->name, name) == 0)
1184 static struct header *
1185 header_find_by_struct_id(struct rte_swx_pipeline *p, uint32_t struct_id)
1187 struct header *elem;
1189 TAILQ_FOREACH(elem, &p->headers, node)
1190 if (elem->struct_id == struct_id)
1196 static struct header *
1197 header_parse(struct rte_swx_pipeline *p,
1200 if (name[0] != 'h' || name[1] != '.')
1203 return header_find(p, &name[2]);
1206 static struct field *
1207 header_field_parse(struct rte_swx_pipeline *p,
1209 struct header **header)
1213 char *header_name, *field_name;
1215 if ((name[0] != 'h') || (name[1] != '.'))
1218 header_name = strdup(&name[2]);
1222 field_name = strchr(header_name, '.');
1231 h = header_find(p, header_name);
1237 f = struct_type_field_find(h->st, field_name);
1251 rte_swx_pipeline_packet_header_register(struct rte_swx_pipeline *p,
1253 const char *struct_type_name)
1255 struct struct_type *st;
1257 size_t n_headers_max;
1260 CHECK_NAME(name, EINVAL);
1261 CHECK_NAME(struct_type_name, EINVAL);
1263 CHECK(!header_find(p, name), EEXIST);
1265 st = struct_type_find(p, struct_type_name);
1268 n_headers_max = RTE_SIZEOF_FIELD(struct thread, valid_headers) * 8;
1269 CHECK(p->n_headers < n_headers_max, ENOSPC);
1271 /* Node allocation. */
1272 h = calloc(1, sizeof(struct header));
1275 /* Node initialization. */
1276 strcpy(h->name, name);
1278 h->struct_id = p->n_structs;
1279 h->id = p->n_headers;
1281 /* Node add to tailq. */
1282 TAILQ_INSERT_TAIL(&p->headers, h, node);
1290 header_build(struct rte_swx_pipeline *p)
1293 uint32_t n_bytes = 0, i;
1295 TAILQ_FOREACH(h, &p->headers, node) {
1296 n_bytes += h->st->n_bits / 8;
1299 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1300 struct thread *t = &p->threads[i];
1301 uint32_t offset = 0;
1303 t->headers = calloc(p->n_headers,
1304 sizeof(struct header_runtime));
1305 CHECK(t->headers, ENOMEM);
1307 t->headers_out = calloc(p->n_headers,
1308 sizeof(struct header_out_runtime));
1309 CHECK(t->headers_out, ENOMEM);
1311 t->header_storage = calloc(1, n_bytes);
1312 CHECK(t->header_storage, ENOMEM);
1314 t->header_out_storage = calloc(1, n_bytes);
1315 CHECK(t->header_out_storage, ENOMEM);
1317 TAILQ_FOREACH(h, &p->headers, node) {
1318 uint8_t *header_storage;
1319 uint32_t n_bytes = h->st->n_bits / 8;
1321 header_storage = &t->header_storage[offset];
1324 t->headers[h->id].ptr0 = header_storage;
1325 t->headers[h->id].n_bytes = n_bytes;
1327 t->structs[h->struct_id] = header_storage;
1335 header_build_free(struct rte_swx_pipeline *p)
1339 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1340 struct thread *t = &p->threads[i];
1342 free(t->headers_out);
1343 t->headers_out = NULL;
1348 free(t->header_out_storage);
1349 t->header_out_storage = NULL;
1351 free(t->header_storage);
1352 t->header_storage = NULL;
1357 header_free(struct rte_swx_pipeline *p)
1359 header_build_free(p);
1362 struct header *elem;
1364 elem = TAILQ_FIRST(&p->headers);
1368 TAILQ_REMOVE(&p->headers, elem, node);
1376 static struct field *
1377 metadata_field_parse(struct rte_swx_pipeline *p, const char *name)
1379 if (!p->metadata_st)
1382 if (name[0] != 'm' || name[1] != '.')
1385 return struct_type_field_find(p->metadata_st, &name[2]);
1389 rte_swx_pipeline_packet_metadata_register(struct rte_swx_pipeline *p,
1390 const char *struct_type_name)
1392 struct struct_type *st = NULL;
1396 CHECK_NAME(struct_type_name, EINVAL);
1397 st = struct_type_find(p, struct_type_name);
1399 CHECK(!st->var_size, EINVAL);
1400 CHECK(!p->metadata_st, EINVAL);
1402 p->metadata_st = st;
1403 p->metadata_struct_id = p->n_structs;
1411 metadata_build(struct rte_swx_pipeline *p)
1413 uint32_t n_bytes = p->metadata_st->n_bits / 8;
1416 /* Thread-level initialization. */
1417 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1418 struct thread *t = &p->threads[i];
1421 metadata = calloc(1, n_bytes);
1422 CHECK(metadata, ENOMEM);
1424 t->metadata = metadata;
1425 t->structs[p->metadata_struct_id] = metadata;
1432 metadata_build_free(struct rte_swx_pipeline *p)
1436 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1437 struct thread *t = &p->threads[i];
1445 metadata_free(struct rte_swx_pipeline *p)
1447 metadata_build_free(p);
1454 instruction_is_tx(enum instruction_type type)
1468 instruction_does_tx(struct instruction *instr)
1470 switch (instr->type) {
1474 case INSTR_HDR_EMIT_TX:
1475 case INSTR_HDR_EMIT2_TX:
1476 case INSTR_HDR_EMIT3_TX:
1477 case INSTR_HDR_EMIT4_TX:
1478 case INSTR_HDR_EMIT5_TX:
1479 case INSTR_HDR_EMIT6_TX:
1480 case INSTR_HDR_EMIT7_TX:
1481 case INSTR_HDR_EMIT8_TX:
1489 instruction_is_jmp(struct instruction *instr)
1491 switch (instr->type) {
1493 case INSTR_JMP_VALID:
1494 case INSTR_JMP_INVALID:
1496 case INSTR_JMP_MISS:
1497 case INSTR_JMP_ACTION_HIT:
1498 case INSTR_JMP_ACTION_MISS:
1500 case INSTR_JMP_EQ_MH:
1501 case INSTR_JMP_EQ_HM:
1502 case INSTR_JMP_EQ_HH:
1503 case INSTR_JMP_EQ_I:
1505 case INSTR_JMP_NEQ_MH:
1506 case INSTR_JMP_NEQ_HM:
1507 case INSTR_JMP_NEQ_HH:
1508 case INSTR_JMP_NEQ_I:
1510 case INSTR_JMP_LT_MH:
1511 case INSTR_JMP_LT_HM:
1512 case INSTR_JMP_LT_HH:
1513 case INSTR_JMP_LT_MI:
1514 case INSTR_JMP_LT_HI:
1516 case INSTR_JMP_GT_MH:
1517 case INSTR_JMP_GT_HM:
1518 case INSTR_JMP_GT_HH:
1519 case INSTR_JMP_GT_MI:
1520 case INSTR_JMP_GT_HI:
1529 instruction_does_thread_yield(struct instruction *instr)
1531 switch (instr->type) {
1534 case INSTR_TABLE_AF:
1535 case INSTR_SELECTOR:
1537 case INSTR_LEARNER_AF:
1538 case INSTR_EXTERN_OBJ:
1539 case INSTR_EXTERN_FUNC:
1546 static struct field *
1547 action_field_parse(struct action *action, const char *name);
1549 static struct field *
1550 struct_field_parse(struct rte_swx_pipeline *p,
1551 struct action *action,
1553 uint32_t *struct_id)
1560 struct header *header;
1562 f = header_field_parse(p, name, &header);
1566 *struct_id = header->struct_id;
1572 f = metadata_field_parse(p, name);
1576 *struct_id = p->metadata_struct_id;
1585 f = action_field_parse(action, name);
1595 struct extern_obj *obj;
1597 f = extern_obj_mailbox_field_parse(p, name, &obj);
1601 *struct_id = obj->struct_id;
1607 struct extern_func *func;
1609 f = extern_func_mailbox_field_parse(p, name, &func);
1613 *struct_id = func->struct_id;
1626 instr_rx_translate(struct rte_swx_pipeline *p,
1627 struct action *action,
1630 struct instruction *instr,
1631 struct instruction_data *data __rte_unused)
1635 CHECK(!action, EINVAL);
1636 CHECK(n_tokens == 2, EINVAL);
1638 f = metadata_field_parse(p, tokens[1]);
1641 instr->type = INSTR_RX;
1642 instr->io.io.offset = f->offset / 8;
1643 instr->io.io.n_bits = f->n_bits;
1651 instr_tx_translate(struct rte_swx_pipeline *p,
1652 struct action *action __rte_unused,
1655 struct instruction *instr,
1656 struct instruction_data *data __rte_unused)
1658 char *port = tokens[1];
1662 CHECK(n_tokens == 2, EINVAL);
1664 f = metadata_field_parse(p, port);
1666 instr->type = INSTR_TX;
1667 instr->io.io.offset = f->offset / 8;
1668 instr->io.io.n_bits = f->n_bits;
1673 port_val = strtoul(port, &port, 0);
1674 CHECK(!port[0], EINVAL);
1676 instr->type = INSTR_TX_I;
1677 instr->io.io.val = port_val;
1682 instr_drop_translate(struct rte_swx_pipeline *p __rte_unused,
1683 struct action *action __rte_unused,
1684 char **tokens __rte_unused,
1686 struct instruction *instr,
1687 struct instruction_data *data __rte_unused)
1689 CHECK(n_tokens == 1, EINVAL);
1692 instr->type = INSTR_DROP;
1697 instr_tx_exec(struct rte_swx_pipeline *p)
1699 struct thread *t = &p->threads[p->thread_id];
1700 struct instruction *ip = t->ip;
1702 __instr_tx_exec(p, t, ip);
1705 thread_ip_reset(p, t);
1710 instr_tx_i_exec(struct rte_swx_pipeline *p)
1712 struct thread *t = &p->threads[p->thread_id];
1713 struct instruction *ip = t->ip;
1715 __instr_tx_i_exec(p, t, ip);
1718 thread_ip_reset(p, t);
1723 instr_drop_exec(struct rte_swx_pipeline *p)
1725 struct thread *t = &p->threads[p->thread_id];
1726 struct instruction *ip = t->ip;
1728 __instr_drop_exec(p, t, ip);
1731 thread_ip_reset(p, t);
1739 instr_mirror_translate(struct rte_swx_pipeline *p,
1740 struct action *action,
1743 struct instruction *instr,
1744 struct instruction_data *data __rte_unused)
1746 char *dst = tokens[1], *src = tokens[2];
1747 struct field *fdst, *fsrc;
1748 uint32_t dst_struct_id = 0, src_struct_id = 0;
1750 CHECK(n_tokens == 3, EINVAL);
1752 fdst = struct_field_parse(p, action, dst, &dst_struct_id);
1753 CHECK(fdst, EINVAL);
1754 CHECK(dst[0] != 'h', EINVAL);
1755 CHECK(!fdst->var_size, EINVAL);
1757 fsrc = struct_field_parse(p, action, src, &src_struct_id);
1758 CHECK(fsrc, EINVAL);
1759 CHECK(src[0] != 'h', EINVAL);
1760 CHECK(!fsrc->var_size, EINVAL);
1762 instr->type = INSTR_MIRROR;
1763 instr->mirror.dst.struct_id = (uint8_t)dst_struct_id;
1764 instr->mirror.dst.n_bits = fdst->n_bits;
1765 instr->mirror.dst.offset = fdst->offset / 8;
1766 instr->mirror.src.struct_id = (uint8_t)src_struct_id;
1767 instr->mirror.src.n_bits = fsrc->n_bits;
1768 instr->mirror.src.offset = fsrc->offset / 8;
1774 instr_mirror_exec(struct rte_swx_pipeline *p)
1776 struct thread *t = &p->threads[p->thread_id];
1777 struct instruction *ip = t->ip;
1779 __instr_mirror_exec(p, t, ip);
1789 instr_recirculate_translate(struct rte_swx_pipeline *p __rte_unused,
1790 struct action *action __rte_unused,
1791 char **tokens __rte_unused,
1793 struct instruction *instr,
1794 struct instruction_data *data __rte_unused)
1796 CHECK(n_tokens == 1, EINVAL);
1798 instr->type = INSTR_RECIRCULATE;
1803 instr_recircid_translate(struct rte_swx_pipeline *p,
1804 struct action *action __rte_unused,
1807 struct instruction *instr,
1808 struct instruction_data *data __rte_unused)
1812 CHECK(n_tokens == 2, EINVAL);
1814 f = metadata_field_parse(p, tokens[1]);
1817 instr->type = INSTR_RECIRCID;
1818 instr->io.io.offset = f->offset / 8;
1819 instr->io.io.n_bits = f->n_bits;
1824 instr_recirculate_exec(struct rte_swx_pipeline *p)
1826 struct thread *t = &p->threads[p->thread_id];
1827 struct instruction *ip = t->ip;
1829 __instr_recirculate_exec(p, t, ip);
1836 instr_recircid_exec(struct rte_swx_pipeline *p)
1838 struct thread *t = &p->threads[p->thread_id];
1839 struct instruction *ip = t->ip;
1841 __instr_recircid_exec(p, t, ip);
1851 instr_hdr_extract_translate(struct rte_swx_pipeline *p,
1852 struct action *action,
1855 struct instruction *instr,
1856 struct instruction_data *data __rte_unused)
1860 CHECK(!action, EINVAL);
1861 CHECK((n_tokens == 2) || (n_tokens == 3), EINVAL);
1863 h = header_parse(p, tokens[1]);
1866 if (n_tokens == 2) {
1867 CHECK(!h->st->var_size, EINVAL);
1869 instr->type = INSTR_HDR_EXTRACT;
1870 instr->io.hdr.header_id[0] = h->id;
1871 instr->io.hdr.struct_id[0] = h->struct_id;
1872 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
1876 CHECK(h->st->var_size, EINVAL);
1878 mf = metadata_field_parse(p, tokens[2]);
1880 CHECK(!mf->var_size, EINVAL);
1882 instr->type = INSTR_HDR_EXTRACT_M;
1883 instr->io.io.offset = mf->offset / 8;
1884 instr->io.io.n_bits = mf->n_bits;
1885 instr->io.hdr.header_id[0] = h->id;
1886 instr->io.hdr.struct_id[0] = h->struct_id;
1887 instr->io.hdr.n_bytes[0] = h->st->n_bits_min / 8;
1894 instr_hdr_lookahead_translate(struct rte_swx_pipeline *p,
1895 struct action *action,
1898 struct instruction *instr,
1899 struct instruction_data *data __rte_unused)
1903 CHECK(!action, EINVAL);
1904 CHECK(n_tokens == 2, EINVAL);
1906 h = header_parse(p, tokens[1]);
1908 CHECK(!h->st->var_size, EINVAL);
1910 instr->type = INSTR_HDR_LOOKAHEAD;
1911 instr->io.hdr.header_id[0] = h->id;
1912 instr->io.hdr.struct_id[0] = h->struct_id;
1913 instr->io.hdr.n_bytes[0] = 0; /* Unused. */
1919 instr_hdr_extract_exec(struct rte_swx_pipeline *p)
1921 struct thread *t = &p->threads[p->thread_id];
1922 struct instruction *ip = t->ip;
1924 __instr_hdr_extract_exec(p, t, ip);
1931 instr_hdr_extract2_exec(struct rte_swx_pipeline *p)
1933 struct thread *t = &p->threads[p->thread_id];
1934 struct instruction *ip = t->ip;
1936 __instr_hdr_extract2_exec(p, t, ip);
1943 instr_hdr_extract3_exec(struct rte_swx_pipeline *p)
1945 struct thread *t = &p->threads[p->thread_id];
1946 struct instruction *ip = t->ip;
1948 __instr_hdr_extract3_exec(p, t, ip);
1955 instr_hdr_extract4_exec(struct rte_swx_pipeline *p)
1957 struct thread *t = &p->threads[p->thread_id];
1958 struct instruction *ip = t->ip;
1960 __instr_hdr_extract4_exec(p, t, ip);
1967 instr_hdr_extract5_exec(struct rte_swx_pipeline *p)
1969 struct thread *t = &p->threads[p->thread_id];
1970 struct instruction *ip = t->ip;
1972 __instr_hdr_extract5_exec(p, t, ip);
1979 instr_hdr_extract6_exec(struct rte_swx_pipeline *p)
1981 struct thread *t = &p->threads[p->thread_id];
1982 struct instruction *ip = t->ip;
1984 __instr_hdr_extract6_exec(p, t, ip);
1991 instr_hdr_extract7_exec(struct rte_swx_pipeline *p)
1993 struct thread *t = &p->threads[p->thread_id];
1994 struct instruction *ip = t->ip;
1996 __instr_hdr_extract7_exec(p, t, ip);
2003 instr_hdr_extract8_exec(struct rte_swx_pipeline *p)
2005 struct thread *t = &p->threads[p->thread_id];
2006 struct instruction *ip = t->ip;
2008 __instr_hdr_extract8_exec(p, t, ip);
2015 instr_hdr_extract_m_exec(struct rte_swx_pipeline *p)
2017 struct thread *t = &p->threads[p->thread_id];
2018 struct instruction *ip = t->ip;
2020 __instr_hdr_extract_m_exec(p, t, ip);
2027 instr_hdr_lookahead_exec(struct rte_swx_pipeline *p)
2029 struct thread *t = &p->threads[p->thread_id];
2030 struct instruction *ip = t->ip;
2032 __instr_hdr_lookahead_exec(p, t, ip);
2042 instr_hdr_emit_translate(struct rte_swx_pipeline *p,
2043 struct action *action __rte_unused,
2046 struct instruction *instr,
2047 struct instruction_data *data __rte_unused)
2051 CHECK(n_tokens == 2, EINVAL);
2053 h = header_parse(p, tokens[1]);
2056 instr->type = INSTR_HDR_EMIT;
2057 instr->io.hdr.header_id[0] = h->id;
2058 instr->io.hdr.struct_id[0] = h->struct_id;
2059 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
2064 instr_hdr_emit_exec(struct rte_swx_pipeline *p)
2066 struct thread *t = &p->threads[p->thread_id];
2067 struct instruction *ip = t->ip;
2069 __instr_hdr_emit_exec(p, t, ip);
2076 instr_hdr_emit_tx_exec(struct rte_swx_pipeline *p)
2078 struct thread *t = &p->threads[p->thread_id];
2079 struct instruction *ip = t->ip;
2081 __instr_hdr_emit_tx_exec(p, t, ip);
2084 thread_ip_reset(p, t);
2089 instr_hdr_emit2_tx_exec(struct rte_swx_pipeline *p)
2091 struct thread *t = &p->threads[p->thread_id];
2092 struct instruction *ip = t->ip;
2094 __instr_hdr_emit2_tx_exec(p, t, ip);
2097 thread_ip_reset(p, t);
2102 instr_hdr_emit3_tx_exec(struct rte_swx_pipeline *p)
2104 struct thread *t = &p->threads[p->thread_id];
2105 struct instruction *ip = t->ip;
2107 __instr_hdr_emit3_tx_exec(p, t, ip);
2110 thread_ip_reset(p, t);
2115 instr_hdr_emit4_tx_exec(struct rte_swx_pipeline *p)
2117 struct thread *t = &p->threads[p->thread_id];
2118 struct instruction *ip = t->ip;
2120 __instr_hdr_emit4_tx_exec(p, t, ip);
2123 thread_ip_reset(p, t);
2128 instr_hdr_emit5_tx_exec(struct rte_swx_pipeline *p)
2130 struct thread *t = &p->threads[p->thread_id];
2131 struct instruction *ip = t->ip;
2133 __instr_hdr_emit5_tx_exec(p, t, ip);
2136 thread_ip_reset(p, t);
2141 instr_hdr_emit6_tx_exec(struct rte_swx_pipeline *p)
2143 struct thread *t = &p->threads[p->thread_id];
2144 struct instruction *ip = t->ip;
2146 __instr_hdr_emit6_tx_exec(p, t, ip);
2149 thread_ip_reset(p, t);
2154 instr_hdr_emit7_tx_exec(struct rte_swx_pipeline *p)
2156 struct thread *t = &p->threads[p->thread_id];
2157 struct instruction *ip = t->ip;
2159 __instr_hdr_emit7_tx_exec(p, t, ip);
2162 thread_ip_reset(p, t);
2167 instr_hdr_emit8_tx_exec(struct rte_swx_pipeline *p)
2169 struct thread *t = &p->threads[p->thread_id];
2170 struct instruction *ip = t->ip;
2172 __instr_hdr_emit8_tx_exec(p, t, ip);
2175 thread_ip_reset(p, t);
2183 instr_hdr_validate_translate(struct rte_swx_pipeline *p,
2184 struct action *action __rte_unused,
2187 struct instruction *instr,
2188 struct instruction_data *data __rte_unused)
2192 CHECK(n_tokens == 2, EINVAL);
2194 h = header_parse(p, tokens[1]);
2197 instr->type = INSTR_HDR_VALIDATE;
2198 instr->valid.header_id = h->id;
2203 instr_hdr_validate_exec(struct rte_swx_pipeline *p)
2205 struct thread *t = &p->threads[p->thread_id];
2206 struct instruction *ip = t->ip;
2208 __instr_hdr_validate_exec(p, t, ip);
2218 instr_hdr_invalidate_translate(struct rte_swx_pipeline *p,
2219 struct action *action __rte_unused,
2222 struct instruction *instr,
2223 struct instruction_data *data __rte_unused)
2227 CHECK(n_tokens == 2, EINVAL);
2229 h = header_parse(p, tokens[1]);
2232 instr->type = INSTR_HDR_INVALIDATE;
2233 instr->valid.header_id = h->id;
2238 instr_hdr_invalidate_exec(struct rte_swx_pipeline *p)
2240 struct thread *t = &p->threads[p->thread_id];
2241 struct instruction *ip = t->ip;
2243 __instr_hdr_invalidate_exec(p, t, ip);
2252 static struct table *
2253 table_find(struct rte_swx_pipeline *p, const char *name);
2255 static struct selector *
2256 selector_find(struct rte_swx_pipeline *p, const char *name);
2258 static struct learner *
2259 learner_find(struct rte_swx_pipeline *p, const char *name);
2262 instr_table_translate(struct rte_swx_pipeline *p,
2263 struct action *action,
2266 struct instruction *instr,
2267 struct instruction_data *data __rte_unused)
2273 CHECK(!action, EINVAL);
2274 CHECK(n_tokens == 2, EINVAL);
2276 t = table_find(p, tokens[1]);
2278 instr->type = INSTR_TABLE;
2279 instr->table.table_id = t->id;
2283 s = selector_find(p, tokens[1]);
2285 instr->type = INSTR_SELECTOR;
2286 instr->table.table_id = s->id;
2290 l = learner_find(p, tokens[1]);
2292 instr->type = INSTR_LEARNER;
2293 instr->table.table_id = l->id;
2301 instr_table_exec(struct rte_swx_pipeline *p)
2303 struct thread *t = &p->threads[p->thread_id];
2304 struct instruction *ip = t->ip;
2305 uint32_t table_id = ip->table.table_id;
2306 struct rte_swx_table_state *ts = &t->table_state[table_id];
2307 struct table_runtime *table = &t->tables[table_id];
2308 struct table_statistics *stats = &p->table_stats[table_id];
2309 uint64_t action_id, n_pkts_hit, n_pkts_action;
2310 uint8_t *action_data;
2314 done = table->func(ts->obj,
2322 TRACE("[Thread %2u] table %u (not finalized)\n",
2330 action_id = hit ? action_id : ts->default_action_id;
2331 action_data = hit ? action_data : ts->default_action_data;
2332 n_pkts_hit = stats->n_pkts_hit[hit];
2333 n_pkts_action = stats->n_pkts_action[action_id];
2335 TRACE("[Thread %2u] table %u (%s, action %u)\n",
2338 hit ? "hit" : "miss",
2339 (uint32_t)action_id);
2341 t->action_id = action_id;
2342 t->structs[0] = action_data;
2344 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2345 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2348 thread_ip_action_call(p, t, action_id);
2352 instr_table_af_exec(struct rte_swx_pipeline *p)
2354 struct thread *t = &p->threads[p->thread_id];
2355 struct instruction *ip = t->ip;
2356 uint32_t table_id = ip->table.table_id;
2357 struct rte_swx_table_state *ts = &t->table_state[table_id];
2358 struct table_runtime *table = &t->tables[table_id];
2359 struct table_statistics *stats = &p->table_stats[table_id];
2360 uint64_t action_id, n_pkts_hit, n_pkts_action;
2361 uint8_t *action_data;
2362 action_func_t action_func;
2366 done = table->func(ts->obj,
2374 TRACE("[Thread %2u] table %u (not finalized)\n",
2382 action_id = hit ? action_id : ts->default_action_id;
2383 action_data = hit ? action_data : ts->default_action_data;
2384 action_func = p->action_funcs[action_id];
2385 n_pkts_hit = stats->n_pkts_hit[hit];
2386 n_pkts_action = stats->n_pkts_action[action_id];
2388 TRACE("[Thread %2u] table %u (%s, action %u)\n",
2391 hit ? "hit" : "miss",
2392 (uint32_t)action_id);
2394 t->action_id = action_id;
2395 t->structs[0] = action_data;
2397 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2398 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2408 instr_selector_exec(struct rte_swx_pipeline *p)
2410 struct thread *t = &p->threads[p->thread_id];
2411 struct instruction *ip = t->ip;
2412 uint32_t selector_id = ip->table.table_id;
2413 struct rte_swx_table_state *ts = &t->table_state[p->n_tables + selector_id];
2414 struct selector_runtime *selector = &t->selectors[selector_id];
2415 struct selector_statistics *stats = &p->selector_stats[selector_id];
2416 uint64_t n_pkts = stats->n_pkts;
2420 done = rte_swx_table_selector_select(ts->obj,
2422 selector->group_id_buffer,
2423 selector->selector_buffer,
2424 selector->member_id_buffer);
2427 TRACE("[Thread %2u] selector %u (not finalized)\n",
2436 TRACE("[Thread %2u] selector %u\n",
2440 stats->n_pkts = n_pkts + 1;
2447 instr_learner_exec(struct rte_swx_pipeline *p)
2449 struct thread *t = &p->threads[p->thread_id];
2450 struct instruction *ip = t->ip;
2451 uint32_t learner_id = ip->table.table_id;
2452 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2453 p->n_selectors + learner_id];
2454 struct learner_runtime *l = &t->learners[learner_id];
2455 struct learner_statistics *stats = &p->learner_stats[learner_id];
2456 uint64_t action_id, n_pkts_hit, n_pkts_action, time;
2457 uint8_t *action_data;
2461 time = rte_get_tsc_cycles();
2463 done = rte_swx_table_learner_lookup(ts->obj,
2472 TRACE("[Thread %2u] learner %u (not finalized)\n",
2480 action_id = hit ? action_id : ts->default_action_id;
2481 action_data = hit ? action_data : ts->default_action_data;
2482 n_pkts_hit = stats->n_pkts_hit[hit];
2483 n_pkts_action = stats->n_pkts_action[action_id];
2485 TRACE("[Thread %2u] learner %u (%s, action %u)\n",
2488 hit ? "hit" : "miss",
2489 (uint32_t)action_id);
2491 t->action_id = action_id;
2492 t->structs[0] = action_data;
2494 t->learner_id = learner_id;
2496 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2497 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2500 thread_ip_action_call(p, t, action_id);
2504 instr_learner_af_exec(struct rte_swx_pipeline *p)
2506 struct thread *t = &p->threads[p->thread_id];
2507 struct instruction *ip = t->ip;
2508 uint32_t learner_id = ip->table.table_id;
2509 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2510 p->n_selectors + learner_id];
2511 struct learner_runtime *l = &t->learners[learner_id];
2512 struct learner_statistics *stats = &p->learner_stats[learner_id];
2513 uint64_t action_id, n_pkts_hit, n_pkts_action, time;
2514 uint8_t *action_data;
2515 action_func_t action_func;
2519 time = rte_get_tsc_cycles();
2521 done = rte_swx_table_learner_lookup(ts->obj,
2530 TRACE("[Thread %2u] learner %u (not finalized)\n",
2538 action_id = hit ? action_id : ts->default_action_id;
2539 action_data = hit ? action_data : ts->default_action_data;
2540 action_func = p->action_funcs[action_id];
2541 n_pkts_hit = stats->n_pkts_hit[hit];
2542 n_pkts_action = stats->n_pkts_action[action_id];
2544 TRACE("[Thread %2u] learner %u (%s, action %u)\n",
2547 hit ? "hit" : "miss",
2548 (uint32_t)action_id);
2550 t->action_id = action_id;
2551 t->structs[0] = action_data;
2553 t->learner_id = learner_id;
2555 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2556 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2568 static struct action *
2569 action_find(struct rte_swx_pipeline *p, const char *name);
2572 action_has_nbo_args(struct action *a);
2575 learner_action_args_check(struct rte_swx_pipeline *p, struct action *a, const char *mf_name);
2578 instr_learn_translate(struct rte_swx_pipeline *p,
2579 struct action *action,
2582 struct instruction *instr,
2583 struct instruction_data *data __rte_unused)
2586 struct field *mf_first_arg = NULL, *mf_timeout_id = NULL;
2587 const char *mf_first_arg_name, *mf_timeout_id_name;
2589 CHECK(action, EINVAL);
2590 CHECK((n_tokens == 3) || (n_tokens == 4), EINVAL);
2593 a = action_find(p, tokens[1]);
2595 CHECK(!action_has_nbo_args(a), EINVAL);
2597 /* Action first argument. */
2598 mf_first_arg_name = (n_tokens == 4) ? tokens[2] : NULL;
2599 CHECK(!learner_action_args_check(p, a, mf_first_arg_name), EINVAL);
2601 if (mf_first_arg_name) {
2602 mf_first_arg = metadata_field_parse(p, mf_first_arg_name);
2603 CHECK(mf_first_arg, EINVAL);
2607 mf_timeout_id_name = (n_tokens == 4) ? tokens[3] : tokens[2];
2608 CHECK_NAME(mf_timeout_id_name, EINVAL);
2609 mf_timeout_id = metadata_field_parse(p, mf_timeout_id_name);
2610 CHECK(mf_timeout_id, EINVAL);
2613 instr->type = INSTR_LEARNER_LEARN;
2614 instr->learn.action_id = a->id;
2615 instr->learn.mf_first_arg_offset = mf_first_arg ? (mf_first_arg->offset / 8) : 0;
2616 instr->learn.mf_timeout_id_offset = mf_timeout_id->offset / 8;
2617 instr->learn.mf_timeout_id_n_bits = mf_timeout_id->n_bits;
2623 instr_learn_exec(struct rte_swx_pipeline *p)
2625 struct thread *t = &p->threads[p->thread_id];
2626 struct instruction *ip = t->ip;
2628 __instr_learn_exec(p, t, ip);
2638 instr_rearm_translate(struct rte_swx_pipeline *p,
2639 struct action *action,
2642 struct instruction *instr,
2643 struct instruction_data *data __rte_unused)
2645 struct field *mf_timeout_id;
2646 const char *mf_timeout_id_name;
2648 CHECK(action, EINVAL);
2649 CHECK((n_tokens == 1) || (n_tokens == 2), EINVAL);
2651 /* INSTR_LEARNER_REARM. */
2652 if (n_tokens == 1) {
2653 instr->type = INSTR_LEARNER_REARM;
2657 /* INSTR_LEARNER_REARM_NEW. */
2658 mf_timeout_id_name = tokens[1];
2659 CHECK_NAME(mf_timeout_id_name, EINVAL);
2660 mf_timeout_id = metadata_field_parse(p, mf_timeout_id_name);
2661 CHECK(mf_timeout_id, EINVAL);
2663 instr->type = INSTR_LEARNER_REARM_NEW;
2664 instr->learn.mf_timeout_id_offset = mf_timeout_id->offset / 8;
2665 instr->learn.mf_timeout_id_n_bits = mf_timeout_id->n_bits;
2671 instr_rearm_exec(struct rte_swx_pipeline *p)
2673 struct thread *t = &p->threads[p->thread_id];
2674 struct instruction *ip = t->ip;
2676 __instr_rearm_exec(p, t, ip);
2683 instr_rearm_new_exec(struct rte_swx_pipeline *p)
2685 struct thread *t = &p->threads[p->thread_id];
2686 struct instruction *ip = t->ip;
2688 __instr_rearm_new_exec(p, t, ip);
2698 instr_forget_translate(struct rte_swx_pipeline *p __rte_unused,
2699 struct action *action,
2700 char **tokens __rte_unused,
2702 struct instruction *instr,
2703 struct instruction_data *data __rte_unused)
2705 CHECK(action, EINVAL);
2706 CHECK(n_tokens == 1, EINVAL);
2708 instr->type = INSTR_LEARNER_FORGET;
2714 instr_forget_exec(struct rte_swx_pipeline *p)
2716 struct thread *t = &p->threads[p->thread_id];
2717 struct instruction *ip = t->ip;
2719 __instr_forget_exec(p, t, ip);
2729 instr_extern_translate(struct rte_swx_pipeline *p,
2730 struct action *action __rte_unused,
2733 struct instruction *instr,
2734 struct instruction_data *data __rte_unused)
2736 char *token = tokens[1];
2738 CHECK(n_tokens == 2, EINVAL);
2740 if (token[0] == 'e') {
2741 struct extern_obj *obj;
2742 struct extern_type_member_func *func;
2744 func = extern_obj_member_func_parse(p, token, &obj);
2745 CHECK(func, EINVAL);
2747 instr->type = INSTR_EXTERN_OBJ;
2748 instr->ext_obj.ext_obj_id = obj->id;
2749 instr->ext_obj.func_id = func->id;
2754 if (token[0] == 'f') {
2755 struct extern_func *func;
2757 func = extern_func_parse(p, token);
2758 CHECK(func, EINVAL);
2760 instr->type = INSTR_EXTERN_FUNC;
2761 instr->ext_func.ext_func_id = func->id;
2770 instr_extern_obj_exec(struct rte_swx_pipeline *p)
2772 struct thread *t = &p->threads[p->thread_id];
2773 struct instruction *ip = t->ip;
2776 /* Extern object member function execute. */
2777 done = __instr_extern_obj_exec(p, t, ip);
2780 thread_ip_inc_cond(t, done);
2781 thread_yield_cond(p, done ^ 1);
2785 instr_extern_func_exec(struct rte_swx_pipeline *p)
2787 struct thread *t = &p->threads[p->thread_id];
2788 struct instruction *ip = t->ip;
2791 /* Extern function execute. */
2792 done = __instr_extern_func_exec(p, t, ip);
2795 thread_ip_inc_cond(t, done);
2796 thread_yield_cond(p, done ^ 1);
2803 instr_mov_translate(struct rte_swx_pipeline *p,
2804 struct action *action,
2807 struct instruction *instr,
2808 struct instruction_data *data __rte_unused)
2810 char *dst = tokens[1], *src = tokens[2];
2811 struct field *fdst, *fsrc;
2813 uint32_t dst_struct_id = 0, src_struct_id = 0;
2815 CHECK(n_tokens == 3, EINVAL);
2817 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2818 CHECK(fdst, EINVAL);
2819 CHECK(!fdst->var_size, EINVAL);
2821 /* MOV, MOV_MH, MOV_HM or MOV_HH. */
2822 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2824 CHECK(!fsrc->var_size, EINVAL);
2826 instr->type = INSTR_MOV;
2827 if (dst[0] != 'h' && src[0] == 'h')
2828 instr->type = INSTR_MOV_MH;
2829 if (dst[0] == 'h' && src[0] != 'h')
2830 instr->type = INSTR_MOV_HM;
2831 if (dst[0] == 'h' && src[0] == 'h')
2832 instr->type = INSTR_MOV_HH;
2834 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
2835 instr->mov.dst.n_bits = fdst->n_bits;
2836 instr->mov.dst.offset = fdst->offset / 8;
2837 instr->mov.src.struct_id = (uint8_t)src_struct_id;
2838 instr->mov.src.n_bits = fsrc->n_bits;
2839 instr->mov.src.offset = fsrc->offset / 8;
2844 src_val = strtoull(src, &src, 0);
2845 CHECK(!src[0], EINVAL);
2848 src_val = hton64(src_val) >> (64 - fdst->n_bits);
2850 instr->type = INSTR_MOV_I;
2851 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
2852 instr->mov.dst.n_bits = fdst->n_bits;
2853 instr->mov.dst.offset = fdst->offset / 8;
2854 instr->mov.src_val = src_val;
2859 instr_mov_exec(struct rte_swx_pipeline *p)
2861 struct thread *t = &p->threads[p->thread_id];
2862 struct instruction *ip = t->ip;
2864 __instr_mov_exec(p, t, ip);
2871 instr_mov_mh_exec(struct rte_swx_pipeline *p)
2873 struct thread *t = &p->threads[p->thread_id];
2874 struct instruction *ip = t->ip;
2876 __instr_mov_mh_exec(p, t, ip);
2883 instr_mov_hm_exec(struct rte_swx_pipeline *p)
2885 struct thread *t = &p->threads[p->thread_id];
2886 struct instruction *ip = t->ip;
2888 __instr_mov_hm_exec(p, t, ip);
2895 instr_mov_hh_exec(struct rte_swx_pipeline *p)
2897 struct thread *t = &p->threads[p->thread_id];
2898 struct instruction *ip = t->ip;
2900 __instr_mov_hh_exec(p, t, ip);
2907 instr_mov_i_exec(struct rte_swx_pipeline *p)
2909 struct thread *t = &p->threads[p->thread_id];
2910 struct instruction *ip = t->ip;
2912 __instr_mov_i_exec(p, t, ip);
2922 instr_dma_ht_exec(struct rte_swx_pipeline *p)
2924 struct thread *t = &p->threads[p->thread_id];
2925 struct instruction *ip = t->ip;
2927 __instr_dma_ht_exec(p, t, ip);
2934 instr_dma_ht2_exec(struct rte_swx_pipeline *p)
2936 struct thread *t = &p->threads[p->thread_id];
2937 struct instruction *ip = t->ip;
2939 __instr_dma_ht2_exec(p, t, ip);
2946 instr_dma_ht3_exec(struct rte_swx_pipeline *p)
2948 struct thread *t = &p->threads[p->thread_id];
2949 struct instruction *ip = t->ip;
2951 __instr_dma_ht3_exec(p, t, ip);
2958 instr_dma_ht4_exec(struct rte_swx_pipeline *p)
2960 struct thread *t = &p->threads[p->thread_id];
2961 struct instruction *ip = t->ip;
2963 __instr_dma_ht4_exec(p, t, ip);
2970 instr_dma_ht5_exec(struct rte_swx_pipeline *p)
2972 struct thread *t = &p->threads[p->thread_id];
2973 struct instruction *ip = t->ip;
2975 __instr_dma_ht5_exec(p, t, ip);
2982 instr_dma_ht6_exec(struct rte_swx_pipeline *p)
2984 struct thread *t = &p->threads[p->thread_id];
2985 struct instruction *ip = t->ip;
2987 __instr_dma_ht6_exec(p, t, ip);
2994 instr_dma_ht7_exec(struct rte_swx_pipeline *p)
2996 struct thread *t = &p->threads[p->thread_id];
2997 struct instruction *ip = t->ip;
2999 __instr_dma_ht7_exec(p, t, ip);
3006 instr_dma_ht8_exec(struct rte_swx_pipeline *p)
3008 struct thread *t = &p->threads[p->thread_id];
3009 struct instruction *ip = t->ip;
3011 __instr_dma_ht8_exec(p, t, ip);
3021 instr_alu_add_translate(struct rte_swx_pipeline *p,
3022 struct action *action,
3025 struct instruction *instr,
3026 struct instruction_data *data __rte_unused)
3028 char *dst = tokens[1], *src = tokens[2];
3029 struct field *fdst, *fsrc;
3031 uint32_t dst_struct_id = 0, src_struct_id = 0;
3033 CHECK(n_tokens == 3, EINVAL);
3035 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3036 CHECK(fdst, EINVAL);
3037 CHECK(!fdst->var_size, EINVAL);
3039 /* ADD, ADD_HM, ADD_MH, ADD_HH. */
3040 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3042 CHECK(!fsrc->var_size, EINVAL);
3044 instr->type = INSTR_ALU_ADD;
3045 if (dst[0] == 'h' && src[0] != 'h')
3046 instr->type = INSTR_ALU_ADD_HM;
3047 if (dst[0] != 'h' && src[0] == 'h')
3048 instr->type = INSTR_ALU_ADD_MH;
3049 if (dst[0] == 'h' && src[0] == 'h')
3050 instr->type = INSTR_ALU_ADD_HH;
3052 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3053 instr->alu.dst.n_bits = fdst->n_bits;
3054 instr->alu.dst.offset = fdst->offset / 8;
3055 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3056 instr->alu.src.n_bits = fsrc->n_bits;
3057 instr->alu.src.offset = fsrc->offset / 8;
3061 /* ADD_MI, ADD_HI. */
3062 src_val = strtoull(src, &src, 0);
3063 CHECK(!src[0], EINVAL);
3065 instr->type = INSTR_ALU_ADD_MI;
3067 instr->type = INSTR_ALU_ADD_HI;
3069 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3070 instr->alu.dst.n_bits = fdst->n_bits;
3071 instr->alu.dst.offset = fdst->offset / 8;
3072 instr->alu.src_val = src_val;
3077 instr_alu_sub_translate(struct rte_swx_pipeline *p,
3078 struct action *action,
3081 struct instruction *instr,
3082 struct instruction_data *data __rte_unused)
3084 char *dst = tokens[1], *src = tokens[2];
3085 struct field *fdst, *fsrc;
3087 uint32_t dst_struct_id = 0, src_struct_id = 0;
3089 CHECK(n_tokens == 3, EINVAL);
3091 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3092 CHECK(fdst, EINVAL);
3093 CHECK(!fdst->var_size, EINVAL);
3095 /* SUB, SUB_HM, SUB_MH, SUB_HH. */
3096 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3098 CHECK(!fsrc->var_size, EINVAL);
3100 instr->type = INSTR_ALU_SUB;
3101 if (dst[0] == 'h' && src[0] != 'h')
3102 instr->type = INSTR_ALU_SUB_HM;
3103 if (dst[0] != 'h' && src[0] == 'h')
3104 instr->type = INSTR_ALU_SUB_MH;
3105 if (dst[0] == 'h' && src[0] == 'h')
3106 instr->type = INSTR_ALU_SUB_HH;
3108 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3109 instr->alu.dst.n_bits = fdst->n_bits;
3110 instr->alu.dst.offset = fdst->offset / 8;
3111 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3112 instr->alu.src.n_bits = fsrc->n_bits;
3113 instr->alu.src.offset = fsrc->offset / 8;
3117 /* SUB_MI, SUB_HI. */
3118 src_val = strtoull(src, &src, 0);
3119 CHECK(!src[0], EINVAL);
3121 instr->type = INSTR_ALU_SUB_MI;
3123 instr->type = INSTR_ALU_SUB_HI;
3125 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3126 instr->alu.dst.n_bits = fdst->n_bits;
3127 instr->alu.dst.offset = fdst->offset / 8;
3128 instr->alu.src_val = src_val;
3133 instr_alu_ckadd_translate(struct rte_swx_pipeline *p,
3134 struct action *action __rte_unused,
3137 struct instruction *instr,
3138 struct instruction_data *data __rte_unused)
3140 char *dst = tokens[1], *src = tokens[2];
3141 struct header *hdst, *hsrc;
3142 struct field *fdst, *fsrc;
3144 CHECK(n_tokens == 3, EINVAL);
3146 fdst = header_field_parse(p, dst, &hdst);
3147 CHECK(fdst, EINVAL);
3148 CHECK(!fdst->var_size && (fdst->n_bits == 16), EINVAL);
3151 fsrc = header_field_parse(p, src, &hsrc);
3153 CHECK(!fsrc->var_size, EINVAL);
3155 instr->type = INSTR_ALU_CKADD_FIELD;
3156 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
3157 instr->alu.dst.n_bits = fdst->n_bits;
3158 instr->alu.dst.offset = fdst->offset / 8;
3159 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
3160 instr->alu.src.n_bits = fsrc->n_bits;
3161 instr->alu.src.offset = fsrc->offset / 8;
3165 /* CKADD_STRUCT, CKADD_STRUCT20. */
3166 hsrc = header_parse(p, src);
3167 CHECK(hsrc, EINVAL);
3169 instr->type = INSTR_ALU_CKADD_STRUCT;
3170 if (!hsrc->st->var_size && ((hsrc->st->n_bits / 8) == 20))
3171 instr->type = INSTR_ALU_CKADD_STRUCT20;
3173 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
3174 instr->alu.dst.n_bits = fdst->n_bits;
3175 instr->alu.dst.offset = fdst->offset / 8;
3176 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
3177 instr->alu.src.n_bits = (uint8_t)hsrc->id; /* The src header ID is stored here. */
3178 instr->alu.src.offset = 0; /* Unused. */
3183 instr_alu_cksub_translate(struct rte_swx_pipeline *p,
3184 struct action *action __rte_unused,
3187 struct instruction *instr,
3188 struct instruction_data *data __rte_unused)
3190 char *dst = tokens[1], *src = tokens[2];
3191 struct header *hdst, *hsrc;
3192 struct field *fdst, *fsrc;
3194 CHECK(n_tokens == 3, EINVAL);
3196 fdst = header_field_parse(p, dst, &hdst);
3197 CHECK(fdst, EINVAL);
3198 CHECK(!fdst->var_size && (fdst->n_bits == 16), EINVAL);
3200 fsrc = header_field_parse(p, src, &hsrc);
3201 CHECK(fsrc, EINVAL);
3202 CHECK(!fsrc->var_size, EINVAL);
3204 instr->type = INSTR_ALU_CKSUB_FIELD;
3205 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
3206 instr->alu.dst.n_bits = fdst->n_bits;
3207 instr->alu.dst.offset = fdst->offset / 8;
3208 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
3209 instr->alu.src.n_bits = fsrc->n_bits;
3210 instr->alu.src.offset = fsrc->offset / 8;
3215 instr_alu_shl_translate(struct rte_swx_pipeline *p,
3216 struct action *action,
3219 struct instruction *instr,
3220 struct instruction_data *data __rte_unused)
3222 char *dst = tokens[1], *src = tokens[2];
3223 struct field *fdst, *fsrc;
3225 uint32_t dst_struct_id = 0, src_struct_id = 0;
3227 CHECK(n_tokens == 3, EINVAL);
3229 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3230 CHECK(fdst, EINVAL);
3231 CHECK(!fdst->var_size, EINVAL);
3233 /* SHL, SHL_HM, SHL_MH, SHL_HH. */
3234 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3236 CHECK(!fsrc->var_size, EINVAL);
3238 instr->type = INSTR_ALU_SHL;
3239 if (dst[0] == 'h' && src[0] != 'h')
3240 instr->type = INSTR_ALU_SHL_HM;
3241 if (dst[0] != 'h' && src[0] == 'h')
3242 instr->type = INSTR_ALU_SHL_MH;
3243 if (dst[0] == 'h' && src[0] == 'h')
3244 instr->type = INSTR_ALU_SHL_HH;
3246 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3247 instr->alu.dst.n_bits = fdst->n_bits;
3248 instr->alu.dst.offset = fdst->offset / 8;
3249 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3250 instr->alu.src.n_bits = fsrc->n_bits;
3251 instr->alu.src.offset = fsrc->offset / 8;
3255 /* SHL_MI, SHL_HI. */
3256 src_val = strtoull(src, &src, 0);
3257 CHECK(!src[0], EINVAL);
3259 instr->type = INSTR_ALU_SHL_MI;
3261 instr->type = INSTR_ALU_SHL_HI;
3263 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3264 instr->alu.dst.n_bits = fdst->n_bits;
3265 instr->alu.dst.offset = fdst->offset / 8;
3266 instr->alu.src_val = src_val;
3271 instr_alu_shr_translate(struct rte_swx_pipeline *p,
3272 struct action *action,
3275 struct instruction *instr,
3276 struct instruction_data *data __rte_unused)
3278 char *dst = tokens[1], *src = tokens[2];
3279 struct field *fdst, *fsrc;
3281 uint32_t dst_struct_id = 0, src_struct_id = 0;
3283 CHECK(n_tokens == 3, EINVAL);
3285 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3286 CHECK(fdst, EINVAL);
3287 CHECK(!fdst->var_size, EINVAL);
3289 /* SHR, SHR_HM, SHR_MH, SHR_HH. */
3290 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3292 CHECK(!fsrc->var_size, EINVAL);
3294 instr->type = INSTR_ALU_SHR;
3295 if (dst[0] == 'h' && src[0] != 'h')
3296 instr->type = INSTR_ALU_SHR_HM;
3297 if (dst[0] != 'h' && src[0] == 'h')
3298 instr->type = INSTR_ALU_SHR_MH;
3299 if (dst[0] == 'h' && src[0] == 'h')
3300 instr->type = INSTR_ALU_SHR_HH;
3302 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3303 instr->alu.dst.n_bits = fdst->n_bits;
3304 instr->alu.dst.offset = fdst->offset / 8;
3305 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3306 instr->alu.src.n_bits = fsrc->n_bits;
3307 instr->alu.src.offset = fsrc->offset / 8;
3311 /* SHR_MI, SHR_HI. */
3312 src_val = strtoull(src, &src, 0);
3313 CHECK(!src[0], EINVAL);
3315 instr->type = INSTR_ALU_SHR_MI;
3317 instr->type = INSTR_ALU_SHR_HI;
3319 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3320 instr->alu.dst.n_bits = fdst->n_bits;
3321 instr->alu.dst.offset = fdst->offset / 8;
3322 instr->alu.src_val = src_val;
3327 instr_alu_and_translate(struct rte_swx_pipeline *p,
3328 struct action *action,
3331 struct instruction *instr,
3332 struct instruction_data *data __rte_unused)
3334 char *dst = tokens[1], *src = tokens[2];
3335 struct field *fdst, *fsrc;
3337 uint32_t dst_struct_id = 0, src_struct_id = 0;
3339 CHECK(n_tokens == 3, EINVAL);
3341 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3342 CHECK(fdst, EINVAL);
3343 CHECK(!fdst->var_size, EINVAL);
3345 /* AND, AND_MH, AND_HM, AND_HH. */
3346 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3348 CHECK(!fsrc->var_size, EINVAL);
3350 instr->type = INSTR_ALU_AND;
3351 if (dst[0] != 'h' && src[0] == 'h')
3352 instr->type = INSTR_ALU_AND_MH;
3353 if (dst[0] == 'h' && src[0] != 'h')
3354 instr->type = INSTR_ALU_AND_HM;
3355 if (dst[0] == 'h' && src[0] == 'h')
3356 instr->type = INSTR_ALU_AND_HH;
3358 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3359 instr->alu.dst.n_bits = fdst->n_bits;
3360 instr->alu.dst.offset = fdst->offset / 8;
3361 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3362 instr->alu.src.n_bits = fsrc->n_bits;
3363 instr->alu.src.offset = fsrc->offset / 8;
3368 src_val = strtoull(src, &src, 0);
3369 CHECK(!src[0], EINVAL);
3372 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3374 instr->type = INSTR_ALU_AND_I;
3375 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3376 instr->alu.dst.n_bits = fdst->n_bits;
3377 instr->alu.dst.offset = fdst->offset / 8;
3378 instr->alu.src_val = src_val;
3383 instr_alu_or_translate(struct rte_swx_pipeline *p,
3384 struct action *action,
3387 struct instruction *instr,
3388 struct instruction_data *data __rte_unused)
3390 char *dst = tokens[1], *src = tokens[2];
3391 struct field *fdst, *fsrc;
3393 uint32_t dst_struct_id = 0, src_struct_id = 0;
3395 CHECK(n_tokens == 3, EINVAL);
3397 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3398 CHECK(fdst, EINVAL);
3399 CHECK(!fdst->var_size, EINVAL);
3401 /* OR, OR_MH, OR_HM, OR_HH. */
3402 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3404 CHECK(!fsrc->var_size, EINVAL);
3406 instr->type = INSTR_ALU_OR;
3407 if (dst[0] != 'h' && src[0] == 'h')
3408 instr->type = INSTR_ALU_OR_MH;
3409 if (dst[0] == 'h' && src[0] != 'h')
3410 instr->type = INSTR_ALU_OR_HM;
3411 if (dst[0] == 'h' && src[0] == 'h')
3412 instr->type = INSTR_ALU_OR_HH;
3414 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3415 instr->alu.dst.n_bits = fdst->n_bits;
3416 instr->alu.dst.offset = fdst->offset / 8;
3417 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3418 instr->alu.src.n_bits = fsrc->n_bits;
3419 instr->alu.src.offset = fsrc->offset / 8;
3424 src_val = strtoull(src, &src, 0);
3425 CHECK(!src[0], EINVAL);
3428 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3430 instr->type = INSTR_ALU_OR_I;
3431 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3432 instr->alu.dst.n_bits = fdst->n_bits;
3433 instr->alu.dst.offset = fdst->offset / 8;
3434 instr->alu.src_val = src_val;
3439 instr_alu_xor_translate(struct rte_swx_pipeline *p,
3440 struct action *action,
3443 struct instruction *instr,
3444 struct instruction_data *data __rte_unused)
3446 char *dst = tokens[1], *src = tokens[2];
3447 struct field *fdst, *fsrc;
3449 uint32_t dst_struct_id = 0, src_struct_id = 0;
3451 CHECK(n_tokens == 3, EINVAL);
3453 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3454 CHECK(fdst, EINVAL);
3455 CHECK(!fdst->var_size, EINVAL);
3457 /* XOR, XOR_MH, XOR_HM, XOR_HH. */
3458 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3460 CHECK(!fsrc->var_size, EINVAL);
3462 instr->type = INSTR_ALU_XOR;
3463 if (dst[0] != 'h' && src[0] == 'h')
3464 instr->type = INSTR_ALU_XOR_MH;
3465 if (dst[0] == 'h' && src[0] != 'h')
3466 instr->type = INSTR_ALU_XOR_HM;
3467 if (dst[0] == 'h' && src[0] == 'h')
3468 instr->type = INSTR_ALU_XOR_HH;
3470 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3471 instr->alu.dst.n_bits = fdst->n_bits;
3472 instr->alu.dst.offset = fdst->offset / 8;
3473 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3474 instr->alu.src.n_bits = fsrc->n_bits;
3475 instr->alu.src.offset = fsrc->offset / 8;
3480 src_val = strtoull(src, &src, 0);
3481 CHECK(!src[0], EINVAL);
3484 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3486 instr->type = INSTR_ALU_XOR_I;
3487 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3488 instr->alu.dst.n_bits = fdst->n_bits;
3489 instr->alu.dst.offset = fdst->offset / 8;
3490 instr->alu.src_val = src_val;
3495 instr_alu_add_exec(struct rte_swx_pipeline *p)
3497 struct thread *t = &p->threads[p->thread_id];
3498 struct instruction *ip = t->ip;
3501 __instr_alu_add_exec(p, t, ip);
3508 instr_alu_add_mh_exec(struct rte_swx_pipeline *p)
3510 struct thread *t = &p->threads[p->thread_id];
3511 struct instruction *ip = t->ip;
3514 __instr_alu_add_mh_exec(p, t, ip);
3521 instr_alu_add_hm_exec(struct rte_swx_pipeline *p)
3523 struct thread *t = &p->threads[p->thread_id];
3524 struct instruction *ip = t->ip;
3527 __instr_alu_add_hm_exec(p, t, ip);
3534 instr_alu_add_hh_exec(struct rte_swx_pipeline *p)
3536 struct thread *t = &p->threads[p->thread_id];
3537 struct instruction *ip = t->ip;
3540 __instr_alu_add_hh_exec(p, t, ip);
3547 instr_alu_add_mi_exec(struct rte_swx_pipeline *p)
3549 struct thread *t = &p->threads[p->thread_id];
3550 struct instruction *ip = t->ip;
3553 __instr_alu_add_mi_exec(p, t, ip);
3560 instr_alu_add_hi_exec(struct rte_swx_pipeline *p)
3562 struct thread *t = &p->threads[p->thread_id];
3563 struct instruction *ip = t->ip;
3566 __instr_alu_add_hi_exec(p, t, ip);
3573 instr_alu_sub_exec(struct rte_swx_pipeline *p)
3575 struct thread *t = &p->threads[p->thread_id];
3576 struct instruction *ip = t->ip;
3579 __instr_alu_sub_exec(p, t, ip);
3586 instr_alu_sub_mh_exec(struct rte_swx_pipeline *p)
3588 struct thread *t = &p->threads[p->thread_id];
3589 struct instruction *ip = t->ip;
3592 __instr_alu_sub_mh_exec(p, t, ip);
3599 instr_alu_sub_hm_exec(struct rte_swx_pipeline *p)
3601 struct thread *t = &p->threads[p->thread_id];
3602 struct instruction *ip = t->ip;
3605 __instr_alu_sub_hm_exec(p, t, ip);
3612 instr_alu_sub_hh_exec(struct rte_swx_pipeline *p)
3614 struct thread *t = &p->threads[p->thread_id];
3615 struct instruction *ip = t->ip;
3618 __instr_alu_sub_hh_exec(p, t, ip);
3625 instr_alu_sub_mi_exec(struct rte_swx_pipeline *p)
3627 struct thread *t = &p->threads[p->thread_id];
3628 struct instruction *ip = t->ip;
3631 __instr_alu_sub_mi_exec(p, t, ip);
3638 instr_alu_sub_hi_exec(struct rte_swx_pipeline *p)
3640 struct thread *t = &p->threads[p->thread_id];
3641 struct instruction *ip = t->ip;
3644 __instr_alu_sub_hi_exec(p, t, ip);
3651 instr_alu_shl_exec(struct rte_swx_pipeline *p)
3653 struct thread *t = &p->threads[p->thread_id];
3654 struct instruction *ip = t->ip;
3657 __instr_alu_shl_exec(p, t, ip);
3664 instr_alu_shl_mh_exec(struct rte_swx_pipeline *p)
3666 struct thread *t = &p->threads[p->thread_id];
3667 struct instruction *ip = t->ip;
3670 __instr_alu_shl_mh_exec(p, t, ip);
3677 instr_alu_shl_hm_exec(struct rte_swx_pipeline *p)
3679 struct thread *t = &p->threads[p->thread_id];
3680 struct instruction *ip = t->ip;
3683 __instr_alu_shl_hm_exec(p, t, ip);
3690 instr_alu_shl_hh_exec(struct rte_swx_pipeline *p)
3692 struct thread *t = &p->threads[p->thread_id];
3693 struct instruction *ip = t->ip;
3696 __instr_alu_shl_hh_exec(p, t, ip);
3703 instr_alu_shl_mi_exec(struct rte_swx_pipeline *p)
3705 struct thread *t = &p->threads[p->thread_id];
3706 struct instruction *ip = t->ip;
3709 __instr_alu_shl_mi_exec(p, t, ip);
3716 instr_alu_shl_hi_exec(struct rte_swx_pipeline *p)
3718 struct thread *t = &p->threads[p->thread_id];
3719 struct instruction *ip = t->ip;
3722 __instr_alu_shl_hi_exec(p, t, ip);
3729 instr_alu_shr_exec(struct rte_swx_pipeline *p)
3731 struct thread *t = &p->threads[p->thread_id];
3732 struct instruction *ip = t->ip;
3735 __instr_alu_shr_exec(p, t, ip);
3742 instr_alu_shr_mh_exec(struct rte_swx_pipeline *p)
3744 struct thread *t = &p->threads[p->thread_id];
3745 struct instruction *ip = t->ip;
3748 __instr_alu_shr_mh_exec(p, t, ip);
3755 instr_alu_shr_hm_exec(struct rte_swx_pipeline *p)
3757 struct thread *t = &p->threads[p->thread_id];
3758 struct instruction *ip = t->ip;
3761 __instr_alu_shr_hm_exec(p, t, ip);
3768 instr_alu_shr_hh_exec(struct rte_swx_pipeline *p)
3770 struct thread *t = &p->threads[p->thread_id];
3771 struct instruction *ip = t->ip;
3774 __instr_alu_shr_hh_exec(p, t, ip);
3781 instr_alu_shr_mi_exec(struct rte_swx_pipeline *p)
3783 struct thread *t = &p->threads[p->thread_id];
3784 struct instruction *ip = t->ip;
3787 __instr_alu_shr_mi_exec(p, t, ip);
3794 instr_alu_shr_hi_exec(struct rte_swx_pipeline *p)
3796 struct thread *t = &p->threads[p->thread_id];
3797 struct instruction *ip = t->ip;
3800 __instr_alu_shr_hi_exec(p, t, ip);
3807 instr_alu_and_exec(struct rte_swx_pipeline *p)
3809 struct thread *t = &p->threads[p->thread_id];
3810 struct instruction *ip = t->ip;
3813 __instr_alu_and_exec(p, t, ip);
3820 instr_alu_and_mh_exec(struct rte_swx_pipeline *p)
3822 struct thread *t = &p->threads[p->thread_id];
3823 struct instruction *ip = t->ip;
3826 __instr_alu_and_mh_exec(p, t, ip);
3833 instr_alu_and_hm_exec(struct rte_swx_pipeline *p)
3835 struct thread *t = &p->threads[p->thread_id];
3836 struct instruction *ip = t->ip;
3839 __instr_alu_and_hm_exec(p, t, ip);
3846 instr_alu_and_hh_exec(struct rte_swx_pipeline *p)
3848 struct thread *t = &p->threads[p->thread_id];
3849 struct instruction *ip = t->ip;
3852 __instr_alu_and_hh_exec(p, t, ip);
3859 instr_alu_and_i_exec(struct rte_swx_pipeline *p)
3861 struct thread *t = &p->threads[p->thread_id];
3862 struct instruction *ip = t->ip;
3865 __instr_alu_and_i_exec(p, t, ip);
3872 instr_alu_or_exec(struct rte_swx_pipeline *p)
3874 struct thread *t = &p->threads[p->thread_id];
3875 struct instruction *ip = t->ip;
3878 __instr_alu_or_exec(p, t, ip);
3885 instr_alu_or_mh_exec(struct rte_swx_pipeline *p)
3887 struct thread *t = &p->threads[p->thread_id];
3888 struct instruction *ip = t->ip;
3891 __instr_alu_or_mh_exec(p, t, ip);
3898 instr_alu_or_hm_exec(struct rte_swx_pipeline *p)
3900 struct thread *t = &p->threads[p->thread_id];
3901 struct instruction *ip = t->ip;
3904 __instr_alu_or_hm_exec(p, t, ip);
3911 instr_alu_or_hh_exec(struct rte_swx_pipeline *p)
3913 struct thread *t = &p->threads[p->thread_id];
3914 struct instruction *ip = t->ip;
3917 __instr_alu_or_hh_exec(p, t, ip);
3924 instr_alu_or_i_exec(struct rte_swx_pipeline *p)
3926 struct thread *t = &p->threads[p->thread_id];
3927 struct instruction *ip = t->ip;
3930 __instr_alu_or_i_exec(p, t, ip);
3937 instr_alu_xor_exec(struct rte_swx_pipeline *p)
3939 struct thread *t = &p->threads[p->thread_id];
3940 struct instruction *ip = t->ip;
3943 __instr_alu_xor_exec(p, t, ip);
3950 instr_alu_xor_mh_exec(struct rte_swx_pipeline *p)
3952 struct thread *t = &p->threads[p->thread_id];
3953 struct instruction *ip = t->ip;
3956 __instr_alu_xor_mh_exec(p, t, ip);
3963 instr_alu_xor_hm_exec(struct rte_swx_pipeline *p)
3965 struct thread *t = &p->threads[p->thread_id];
3966 struct instruction *ip = t->ip;
3969 __instr_alu_xor_hm_exec(p, t, ip);
3976 instr_alu_xor_hh_exec(struct rte_swx_pipeline *p)
3978 struct thread *t = &p->threads[p->thread_id];
3979 struct instruction *ip = t->ip;
3982 __instr_alu_xor_hh_exec(p, t, ip);
3989 instr_alu_xor_i_exec(struct rte_swx_pipeline *p)
3991 struct thread *t = &p->threads[p->thread_id];
3992 struct instruction *ip = t->ip;
3995 __instr_alu_xor_i_exec(p, t, ip);
4002 instr_alu_ckadd_field_exec(struct rte_swx_pipeline *p)
4004 struct thread *t = &p->threads[p->thread_id];
4005 struct instruction *ip = t->ip;
4008 __instr_alu_ckadd_field_exec(p, t, ip);
4015 instr_alu_cksub_field_exec(struct rte_swx_pipeline *p)
4017 struct thread *t = &p->threads[p->thread_id];
4018 struct instruction *ip = t->ip;
4021 __instr_alu_cksub_field_exec(p, t, ip);
4028 instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline *p)
4030 struct thread *t = &p->threads[p->thread_id];
4031 struct instruction *ip = t->ip;
4034 __instr_alu_ckadd_struct20_exec(p, t, ip);
4041 instr_alu_ckadd_struct_exec(struct rte_swx_pipeline *p)
4043 struct thread *t = &p->threads[p->thread_id];
4044 struct instruction *ip = t->ip;
4047 __instr_alu_ckadd_struct_exec(p, t, ip);
4056 static struct regarray *
4057 regarray_find(struct rte_swx_pipeline *p, const char *name);
4060 instr_regprefetch_translate(struct rte_swx_pipeline *p,
4061 struct action *action,
4064 struct instruction *instr,
4065 struct instruction_data *data __rte_unused)
4067 char *regarray = tokens[1], *idx = tokens[2];
4070 uint32_t idx_struct_id, idx_val;
4072 CHECK(n_tokens == 3, EINVAL);
4074 r = regarray_find(p, regarray);
4077 /* REGPREFETCH_RH, REGPREFETCH_RM. */
4078 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4080 CHECK(!fidx->var_size, EINVAL);
4082 instr->type = INSTR_REGPREFETCH_RM;
4084 instr->type = INSTR_REGPREFETCH_RH;
4086 instr->regarray.regarray_id = r->id;
4087 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4088 instr->regarray.idx.n_bits = fidx->n_bits;
4089 instr->regarray.idx.offset = fidx->offset / 8;
4090 instr->regarray.dstsrc_val = 0; /* Unused. */
4094 /* REGPREFETCH_RI. */
4095 idx_val = strtoul(idx, &idx, 0);
4096 CHECK(!idx[0], EINVAL);
4098 instr->type = INSTR_REGPREFETCH_RI;
4099 instr->regarray.regarray_id = r->id;
4100 instr->regarray.idx_val = idx_val;
4101 instr->regarray.dstsrc_val = 0; /* Unused. */
4106 instr_regrd_translate(struct rte_swx_pipeline *p,
4107 struct action *action,
4110 struct instruction *instr,
4111 struct instruction_data *data __rte_unused)
4113 char *dst = tokens[1], *regarray = tokens[2], *idx = tokens[3];
4115 struct field *fdst, *fidx;
4116 uint32_t dst_struct_id, idx_struct_id, idx_val;
4118 CHECK(n_tokens == 4, EINVAL);
4120 r = regarray_find(p, regarray);
4123 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4124 CHECK(fdst, EINVAL);
4125 CHECK(!fdst->var_size, EINVAL);
4127 /* REGRD_HRH, REGRD_HRM, REGRD_MRH, REGRD_MRM. */
4128 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4130 CHECK(!fidx->var_size, EINVAL);
4132 instr->type = INSTR_REGRD_MRM;
4133 if (dst[0] == 'h' && idx[0] != 'h')
4134 instr->type = INSTR_REGRD_HRM;
4135 if (dst[0] != 'h' && idx[0] == 'h')
4136 instr->type = INSTR_REGRD_MRH;
4137 if (dst[0] == 'h' && idx[0] == 'h')
4138 instr->type = INSTR_REGRD_HRH;
4140 instr->regarray.regarray_id = r->id;
4141 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4142 instr->regarray.idx.n_bits = fidx->n_bits;
4143 instr->regarray.idx.offset = fidx->offset / 8;
4144 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
4145 instr->regarray.dstsrc.n_bits = fdst->n_bits;
4146 instr->regarray.dstsrc.offset = fdst->offset / 8;
4150 /* REGRD_MRI, REGRD_HRI. */
4151 idx_val = strtoul(idx, &idx, 0);
4152 CHECK(!idx[0], EINVAL);
4154 instr->type = INSTR_REGRD_MRI;
4156 instr->type = INSTR_REGRD_HRI;
4158 instr->regarray.regarray_id = r->id;
4159 instr->regarray.idx_val = idx_val;
4160 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
4161 instr->regarray.dstsrc.n_bits = fdst->n_bits;
4162 instr->regarray.dstsrc.offset = fdst->offset / 8;
4167 instr_regwr_translate(struct rte_swx_pipeline *p,
4168 struct action *action,
4171 struct instruction *instr,
4172 struct instruction_data *data __rte_unused)
4174 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
4176 struct field *fidx, *fsrc;
4178 uint32_t idx_struct_id, idx_val, src_struct_id;
4180 CHECK(n_tokens == 4, EINVAL);
4182 r = regarray_find(p, regarray);
4185 /* REGWR_RHH, REGWR_RHM, REGWR_RMH, REGWR_RMM. */
4186 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4187 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4189 CHECK(!fidx->var_size, EINVAL);
4190 CHECK(!fsrc->var_size, EINVAL);
4192 instr->type = INSTR_REGWR_RMM;
4193 if (idx[0] == 'h' && src[0] != 'h')
4194 instr->type = INSTR_REGWR_RHM;
4195 if (idx[0] != 'h' && src[0] == 'h')
4196 instr->type = INSTR_REGWR_RMH;
4197 if (idx[0] == 'h' && src[0] == 'h')
4198 instr->type = INSTR_REGWR_RHH;
4200 instr->regarray.regarray_id = r->id;
4201 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4202 instr->regarray.idx.n_bits = fidx->n_bits;
4203 instr->regarray.idx.offset = fidx->offset / 8;
4204 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4205 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4206 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4210 /* REGWR_RHI, REGWR_RMI. */
4211 if (fidx && !fsrc) {
4212 CHECK(!fidx->var_size, EINVAL);
4214 src_val = strtoull(src, &src, 0);
4215 CHECK(!src[0], EINVAL);
4217 instr->type = INSTR_REGWR_RMI;
4219 instr->type = INSTR_REGWR_RHI;
4221 instr->regarray.regarray_id = r->id;
4222 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4223 instr->regarray.idx.n_bits = fidx->n_bits;
4224 instr->regarray.idx.offset = fidx->offset / 8;
4225 instr->regarray.dstsrc_val = src_val;
4229 /* REGWR_RIH, REGWR_RIM. */
4230 if (!fidx && fsrc) {
4231 idx_val = strtoul(idx, &idx, 0);
4232 CHECK(!idx[0], EINVAL);
4234 CHECK(!fsrc->var_size, EINVAL);
4236 instr->type = INSTR_REGWR_RIM;
4238 instr->type = INSTR_REGWR_RIH;
4240 instr->regarray.regarray_id = r->id;
4241 instr->regarray.idx_val = idx_val;
4242 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4243 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4244 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4249 src_val = strtoull(src, &src, 0);
4250 CHECK(!src[0], EINVAL);
4252 idx_val = strtoul(idx, &idx, 0);
4253 CHECK(!idx[0], EINVAL);
4255 instr->type = INSTR_REGWR_RII;
4256 instr->regarray.idx_val = idx_val;
4257 instr->regarray.dstsrc_val = src_val;
4263 instr_regadd_translate(struct rte_swx_pipeline *p,
4264 struct action *action,
4267 struct instruction *instr,
4268 struct instruction_data *data __rte_unused)
4270 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
4272 struct field *fidx, *fsrc;
4274 uint32_t idx_struct_id, idx_val, src_struct_id;
4276 CHECK(n_tokens == 4, EINVAL);
4278 r = regarray_find(p, regarray);
4281 /* REGADD_RHH, REGADD_RHM, REGADD_RMH, REGADD_RMM. */
4282 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4283 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4285 CHECK(!fidx->var_size, EINVAL);
4286 CHECK(!fsrc->var_size, EINVAL);
4288 instr->type = INSTR_REGADD_RMM;
4289 if (idx[0] == 'h' && src[0] != 'h')
4290 instr->type = INSTR_REGADD_RHM;
4291 if (idx[0] != 'h' && src[0] == 'h')
4292 instr->type = INSTR_REGADD_RMH;
4293 if (idx[0] == 'h' && src[0] == 'h')
4294 instr->type = INSTR_REGADD_RHH;
4296 instr->regarray.regarray_id = r->id;
4297 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4298 instr->regarray.idx.n_bits = fidx->n_bits;
4299 instr->regarray.idx.offset = fidx->offset / 8;
4300 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4301 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4302 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4306 /* REGADD_RHI, REGADD_RMI. */
4307 if (fidx && !fsrc) {
4308 CHECK(!fidx->var_size, EINVAL);
4310 src_val = strtoull(src, &src, 0);
4311 CHECK(!src[0], EINVAL);
4313 instr->type = INSTR_REGADD_RMI;
4315 instr->type = INSTR_REGADD_RHI;
4317 instr->regarray.regarray_id = r->id;
4318 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4319 instr->regarray.idx.n_bits = fidx->n_bits;
4320 instr->regarray.idx.offset = fidx->offset / 8;
4321 instr->regarray.dstsrc_val = src_val;
4325 /* REGADD_RIH, REGADD_RIM. */
4326 if (!fidx && fsrc) {
4327 idx_val = strtoul(idx, &idx, 0);
4328 CHECK(!idx[0], EINVAL);
4330 CHECK(!fsrc->var_size, EINVAL);
4332 instr->type = INSTR_REGADD_RIM;
4334 instr->type = INSTR_REGADD_RIH;
4336 instr->regarray.regarray_id = r->id;
4337 instr->regarray.idx_val = idx_val;
4338 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4339 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4340 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4345 src_val = strtoull(src, &src, 0);
4346 CHECK(!src[0], EINVAL);
4348 idx_val = strtoul(idx, &idx, 0);
4349 CHECK(!idx[0], EINVAL);
4351 instr->type = INSTR_REGADD_RII;
4352 instr->regarray.idx_val = idx_val;
4353 instr->regarray.dstsrc_val = src_val;
4358 instr_regprefetch_rh_exec(struct rte_swx_pipeline *p)
4360 struct thread *t = &p->threads[p->thread_id];
4361 struct instruction *ip = t->ip;
4364 __instr_regprefetch_rh_exec(p, t, ip);
4371 instr_regprefetch_rm_exec(struct rte_swx_pipeline *p)
4373 struct thread *t = &p->threads[p->thread_id];
4374 struct instruction *ip = t->ip;
4377 __instr_regprefetch_rm_exec(p, t, ip);
4384 instr_regprefetch_ri_exec(struct rte_swx_pipeline *p)
4386 struct thread *t = &p->threads[p->thread_id];
4387 struct instruction *ip = t->ip;
4390 __instr_regprefetch_ri_exec(p, t, ip);
4397 instr_regrd_hrh_exec(struct rte_swx_pipeline *p)
4399 struct thread *t = &p->threads[p->thread_id];
4400 struct instruction *ip = t->ip;
4403 __instr_regrd_hrh_exec(p, t, ip);
4410 instr_regrd_hrm_exec(struct rte_swx_pipeline *p)
4412 struct thread *t = &p->threads[p->thread_id];
4413 struct instruction *ip = t->ip;
4416 __instr_regrd_hrm_exec(p, t, ip);
4423 instr_regrd_mrh_exec(struct rte_swx_pipeline *p)
4425 struct thread *t = &p->threads[p->thread_id];
4426 struct instruction *ip = t->ip;
4429 __instr_regrd_mrh_exec(p, t, ip);
4436 instr_regrd_mrm_exec(struct rte_swx_pipeline *p)
4438 struct thread *t = &p->threads[p->thread_id];
4439 struct instruction *ip = t->ip;
4442 __instr_regrd_mrm_exec(p, t, ip);
4449 instr_regrd_hri_exec(struct rte_swx_pipeline *p)
4451 struct thread *t = &p->threads[p->thread_id];
4452 struct instruction *ip = t->ip;
4455 __instr_regrd_hri_exec(p, t, ip);
4462 instr_regrd_mri_exec(struct rte_swx_pipeline *p)
4464 struct thread *t = &p->threads[p->thread_id];
4465 struct instruction *ip = t->ip;
4468 __instr_regrd_mri_exec(p, t, ip);
4475 instr_regwr_rhh_exec(struct rte_swx_pipeline *p)
4477 struct thread *t = &p->threads[p->thread_id];
4478 struct instruction *ip = t->ip;
4481 __instr_regwr_rhh_exec(p, t, ip);
4488 instr_regwr_rhm_exec(struct rte_swx_pipeline *p)
4490 struct thread *t = &p->threads[p->thread_id];
4491 struct instruction *ip = t->ip;
4494 __instr_regwr_rhm_exec(p, t, ip);
4501 instr_regwr_rmh_exec(struct rte_swx_pipeline *p)
4503 struct thread *t = &p->threads[p->thread_id];
4504 struct instruction *ip = t->ip;
4507 __instr_regwr_rmh_exec(p, t, ip);
4514 instr_regwr_rmm_exec(struct rte_swx_pipeline *p)
4516 struct thread *t = &p->threads[p->thread_id];
4517 struct instruction *ip = t->ip;
4520 __instr_regwr_rmm_exec(p, t, ip);
4527 instr_regwr_rhi_exec(struct rte_swx_pipeline *p)
4529 struct thread *t = &p->threads[p->thread_id];
4530 struct instruction *ip = t->ip;
4533 __instr_regwr_rhi_exec(p, t, ip);
4540 instr_regwr_rmi_exec(struct rte_swx_pipeline *p)
4542 struct thread *t = &p->threads[p->thread_id];
4543 struct instruction *ip = t->ip;
4546 __instr_regwr_rmi_exec(p, t, ip);
4553 instr_regwr_rih_exec(struct rte_swx_pipeline *p)
4555 struct thread *t = &p->threads[p->thread_id];
4556 struct instruction *ip = t->ip;
4559 __instr_regwr_rih_exec(p, t, ip);
4566 instr_regwr_rim_exec(struct rte_swx_pipeline *p)
4568 struct thread *t = &p->threads[p->thread_id];
4569 struct instruction *ip = t->ip;
4572 __instr_regwr_rim_exec(p, t, ip);
4579 instr_regwr_rii_exec(struct rte_swx_pipeline *p)
4581 struct thread *t = &p->threads[p->thread_id];
4582 struct instruction *ip = t->ip;
4585 __instr_regwr_rii_exec(p, t, ip);
4592 instr_regadd_rhh_exec(struct rte_swx_pipeline *p)
4594 struct thread *t = &p->threads[p->thread_id];
4595 struct instruction *ip = t->ip;
4598 __instr_regadd_rhh_exec(p, t, ip);
4605 instr_regadd_rhm_exec(struct rte_swx_pipeline *p)
4607 struct thread *t = &p->threads[p->thread_id];
4608 struct instruction *ip = t->ip;
4611 __instr_regadd_rhm_exec(p, t, ip);
4618 instr_regadd_rmh_exec(struct rte_swx_pipeline *p)
4620 struct thread *t = &p->threads[p->thread_id];
4621 struct instruction *ip = t->ip;
4624 __instr_regadd_rmh_exec(p, t, ip);
4631 instr_regadd_rmm_exec(struct rte_swx_pipeline *p)
4633 struct thread *t = &p->threads[p->thread_id];
4634 struct instruction *ip = t->ip;
4637 __instr_regadd_rmm_exec(p, t, ip);
4644 instr_regadd_rhi_exec(struct rte_swx_pipeline *p)
4646 struct thread *t = &p->threads[p->thread_id];
4647 struct instruction *ip = t->ip;
4650 __instr_regadd_rhi_exec(p, t, ip);
4657 instr_regadd_rmi_exec(struct rte_swx_pipeline *p)
4659 struct thread *t = &p->threads[p->thread_id];
4660 struct instruction *ip = t->ip;
4663 __instr_regadd_rmi_exec(p, t, ip);
4670 instr_regadd_rih_exec(struct rte_swx_pipeline *p)
4672 struct thread *t = &p->threads[p->thread_id];
4673 struct instruction *ip = t->ip;
4676 __instr_regadd_rih_exec(p, t, ip);
4683 instr_regadd_rim_exec(struct rte_swx_pipeline *p)
4685 struct thread *t = &p->threads[p->thread_id];
4686 struct instruction *ip = t->ip;
4689 __instr_regadd_rim_exec(p, t, ip);
4696 instr_regadd_rii_exec(struct rte_swx_pipeline *p)
4698 struct thread *t = &p->threads[p->thread_id];
4699 struct instruction *ip = t->ip;
4702 __instr_regadd_rii_exec(p, t, ip);
4711 static struct metarray *
4712 metarray_find(struct rte_swx_pipeline *p, const char *name);
4715 instr_metprefetch_translate(struct rte_swx_pipeline *p,
4716 struct action *action,
4719 struct instruction *instr,
4720 struct instruction_data *data __rte_unused)
4722 char *metarray = tokens[1], *idx = tokens[2];
4725 uint32_t idx_struct_id, idx_val;
4727 CHECK(n_tokens == 3, EINVAL);
4729 m = metarray_find(p, metarray);
4732 /* METPREFETCH_H, METPREFETCH_M. */
4733 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4735 CHECK(!fidx->var_size, EINVAL);
4737 instr->type = INSTR_METPREFETCH_M;
4739 instr->type = INSTR_METPREFETCH_H;
4741 instr->meter.metarray_id = m->id;
4742 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4743 instr->meter.idx.n_bits = fidx->n_bits;
4744 instr->meter.idx.offset = fidx->offset / 8;
4748 /* METPREFETCH_I. */
4749 idx_val = strtoul(idx, &idx, 0);
4750 CHECK(!idx[0], EINVAL);
4752 instr->type = INSTR_METPREFETCH_I;
4753 instr->meter.metarray_id = m->id;
4754 instr->meter.idx_val = idx_val;
4759 instr_meter_translate(struct rte_swx_pipeline *p,
4760 struct action *action,
4763 struct instruction *instr,
4764 struct instruction_data *data __rte_unused)
4766 char *metarray = tokens[1], *idx = tokens[2], *length = tokens[3];
4767 char *color_in = tokens[4], *color_out = tokens[5];
4769 struct field *fidx, *flength, *fcin, *fcout;
4770 uint32_t idx_struct_id, length_struct_id;
4771 uint32_t color_in_struct_id, color_out_struct_id;
4773 CHECK(n_tokens == 6, EINVAL);
4775 m = metarray_find(p, metarray);
4778 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4780 flength = struct_field_parse(p, action, length, &length_struct_id);
4781 CHECK(flength, EINVAL);
4782 CHECK(!flength->var_size, EINVAL);
4784 fcin = struct_field_parse(p, action, color_in, &color_in_struct_id);
4786 fcout = struct_field_parse(p, NULL, color_out, &color_out_struct_id);
4787 CHECK(fcout, EINVAL);
4788 CHECK(!fcout->var_size, EINVAL);
4790 /* index = HMEFT, length = HMEFT, color_in = MEFT, color_out = MEF. */
4792 CHECK(!fidx->var_size, EINVAL);
4793 CHECK(!fcin->var_size, EINVAL);
4795 instr->type = INSTR_METER_MMM;
4796 if (idx[0] == 'h' && length[0] == 'h')
4797 instr->type = INSTR_METER_HHM;
4798 if (idx[0] == 'h' && length[0] != 'h')
4799 instr->type = INSTR_METER_HMM;
4800 if (idx[0] != 'h' && length[0] == 'h')
4801 instr->type = INSTR_METER_MHM;
4803 instr->meter.metarray_id = m->id;
4805 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4806 instr->meter.idx.n_bits = fidx->n_bits;
4807 instr->meter.idx.offset = fidx->offset / 8;
4809 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4810 instr->meter.length.n_bits = flength->n_bits;
4811 instr->meter.length.offset = flength->offset / 8;
4813 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
4814 instr->meter.color_in.n_bits = fcin->n_bits;
4815 instr->meter.color_in.offset = fcin->offset / 8;
4817 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4818 instr->meter.color_out.n_bits = fcout->n_bits;
4819 instr->meter.color_out.offset = fcout->offset / 8;
4822 /* index = HMEFT, length = HMEFT, color_in = I, color_out = MEF. */
4823 if (fidx && !fcin) {
4824 uint32_t color_in_val;
4826 CHECK(!fidx->var_size, EINVAL);
4828 color_in_val = strtoul(color_in, &color_in, 0);
4829 CHECK(!color_in[0], EINVAL);
4831 instr->type = INSTR_METER_MMI;
4832 if (idx[0] == 'h' && length[0] == 'h')
4833 instr->type = INSTR_METER_HHI;
4834 if (idx[0] == 'h' && length[0] != 'h')
4835 instr->type = INSTR_METER_HMI;
4836 if (idx[0] != 'h' && length[0] == 'h')
4837 instr->type = INSTR_METER_MHI;
4839 instr->meter.metarray_id = m->id;
4841 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4842 instr->meter.idx.n_bits = fidx->n_bits;
4843 instr->meter.idx.offset = fidx->offset / 8;
4845 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4846 instr->meter.length.n_bits = flength->n_bits;
4847 instr->meter.length.offset = flength->offset / 8;
4849 instr->meter.color_in_val = color_in_val;
4851 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4852 instr->meter.color_out.n_bits = fcout->n_bits;
4853 instr->meter.color_out.offset = fcout->offset / 8;
4856 /* index = I, length = HMEFT, color_in = MEFT, color_out = MEF. */
4857 if (!fidx && fcin) {
4860 idx_val = strtoul(idx, &idx, 0);
4861 CHECK(!idx[0], EINVAL);
4863 CHECK(!fcin->var_size, EINVAL);
4865 instr->type = INSTR_METER_IMM;
4866 if (length[0] == 'h')
4867 instr->type = INSTR_METER_IHM;
4869 instr->meter.metarray_id = m->id;
4871 instr->meter.idx_val = idx_val;
4873 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4874 instr->meter.length.n_bits = flength->n_bits;
4875 instr->meter.length.offset = flength->offset / 8;
4877 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
4878 instr->meter.color_in.n_bits = fcin->n_bits;
4879 instr->meter.color_in.offset = fcin->offset / 8;
4881 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4882 instr->meter.color_out.n_bits = fcout->n_bits;
4883 instr->meter.color_out.offset = fcout->offset / 8;
4886 /* index = I, length = HMEFT, color_in = I, color_out = MEF. */
4887 if (!fidx && !fcin) {
4888 uint32_t idx_val, color_in_val;
4890 idx_val = strtoul(idx, &idx, 0);
4891 CHECK(!idx[0], EINVAL);
4893 color_in_val = strtoul(color_in, &color_in, 0);
4894 CHECK(!color_in[0], EINVAL);
4896 instr->type = INSTR_METER_IMI;
4897 if (length[0] == 'h')
4898 instr->type = INSTR_METER_IHI;
4900 instr->meter.metarray_id = m->id;
4902 instr->meter.idx_val = idx_val;
4904 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4905 instr->meter.length.n_bits = flength->n_bits;
4906 instr->meter.length.offset = flength->offset / 8;
4908 instr->meter.color_in_val = color_in_val;
4910 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4911 instr->meter.color_out.n_bits = fcout->n_bits;
4912 instr->meter.color_out.offset = fcout->offset / 8;
4919 instr_metprefetch_h_exec(struct rte_swx_pipeline *p)
4921 struct thread *t = &p->threads[p->thread_id];
4922 struct instruction *ip = t->ip;
4925 __instr_metprefetch_h_exec(p, t, ip);
4932 instr_metprefetch_m_exec(struct rte_swx_pipeline *p)
4934 struct thread *t = &p->threads[p->thread_id];
4935 struct instruction *ip = t->ip;
4938 __instr_metprefetch_m_exec(p, t, ip);
4945 instr_metprefetch_i_exec(struct rte_swx_pipeline *p)
4947 struct thread *t = &p->threads[p->thread_id];
4948 struct instruction *ip = t->ip;
4951 __instr_metprefetch_i_exec(p, t, ip);
4958 instr_meter_hhm_exec(struct rte_swx_pipeline *p)
4960 struct thread *t = &p->threads[p->thread_id];
4961 struct instruction *ip = t->ip;
4964 __instr_meter_hhm_exec(p, t, ip);
4971 instr_meter_hhi_exec(struct rte_swx_pipeline *p)
4973 struct thread *t = &p->threads[p->thread_id];
4974 struct instruction *ip = t->ip;
4977 __instr_meter_hhi_exec(p, t, ip);
4984 instr_meter_hmm_exec(struct rte_swx_pipeline *p)
4986 struct thread *t = &p->threads[p->thread_id];
4987 struct instruction *ip = t->ip;
4990 __instr_meter_hmm_exec(p, t, ip);
4997 instr_meter_hmi_exec(struct rte_swx_pipeline *p)
4999 struct thread *t = &p->threads[p->thread_id];
5000 struct instruction *ip = t->ip;
5003 __instr_meter_hmi_exec(p, t, ip);
5010 instr_meter_mhm_exec(struct rte_swx_pipeline *p)
5012 struct thread *t = &p->threads[p->thread_id];
5013 struct instruction *ip = t->ip;
5016 __instr_meter_mhm_exec(p, t, ip);
5023 instr_meter_mhi_exec(struct rte_swx_pipeline *p)
5025 struct thread *t = &p->threads[p->thread_id];
5026 struct instruction *ip = t->ip;
5029 __instr_meter_mhi_exec(p, t, ip);
5036 instr_meter_mmm_exec(struct rte_swx_pipeline *p)
5038 struct thread *t = &p->threads[p->thread_id];
5039 struct instruction *ip = t->ip;
5042 __instr_meter_mmm_exec(p, t, ip);
5049 instr_meter_mmi_exec(struct rte_swx_pipeline *p)
5051 struct thread *t = &p->threads[p->thread_id];
5052 struct instruction *ip = t->ip;
5055 __instr_meter_mmi_exec(p, t, ip);
5062 instr_meter_ihm_exec(struct rte_swx_pipeline *p)
5064 struct thread *t = &p->threads[p->thread_id];
5065 struct instruction *ip = t->ip;
5068 __instr_meter_ihm_exec(p, t, ip);
5075 instr_meter_ihi_exec(struct rte_swx_pipeline *p)
5077 struct thread *t = &p->threads[p->thread_id];
5078 struct instruction *ip = t->ip;
5081 __instr_meter_ihi_exec(p, t, ip);
5088 instr_meter_imm_exec(struct rte_swx_pipeline *p)
5090 struct thread *t = &p->threads[p->thread_id];
5091 struct instruction *ip = t->ip;
5094 __instr_meter_imm_exec(p, t, ip);
5101 instr_meter_imi_exec(struct rte_swx_pipeline *p)
5103 struct thread *t = &p->threads[p->thread_id];
5104 struct instruction *ip = t->ip;
5107 __instr_meter_imi_exec(p, t, ip);
5117 instr_jmp_translate(struct rte_swx_pipeline *p __rte_unused,
5118 struct action *action __rte_unused,
5121 struct instruction *instr,
5122 struct instruction_data *data)
5124 CHECK(n_tokens == 2, EINVAL);
5126 strcpy(data->jmp_label, tokens[1]);
5128 instr->type = INSTR_JMP;
5129 instr->jmp.ip = NULL; /* Resolved later. */
5134 instr_jmp_valid_translate(struct rte_swx_pipeline *p,
5135 struct action *action __rte_unused,
5138 struct instruction *instr,
5139 struct instruction_data *data)
5143 CHECK(n_tokens == 3, EINVAL);
5145 strcpy(data->jmp_label, tokens[1]);
5147 h = header_parse(p, tokens[2]);
5150 instr->type = INSTR_JMP_VALID;
5151 instr->jmp.ip = NULL; /* Resolved later. */
5152 instr->jmp.header_id = h->id;
5157 instr_jmp_invalid_translate(struct rte_swx_pipeline *p,
5158 struct action *action __rte_unused,
5161 struct instruction *instr,
5162 struct instruction_data *data)
5166 CHECK(n_tokens == 3, EINVAL);
5168 strcpy(data->jmp_label, tokens[1]);
5170 h = header_parse(p, tokens[2]);
5173 instr->type = INSTR_JMP_INVALID;
5174 instr->jmp.ip = NULL; /* Resolved later. */
5175 instr->jmp.header_id = h->id;
5180 instr_jmp_hit_translate(struct rte_swx_pipeline *p __rte_unused,
5181 struct action *action,
5184 struct instruction *instr,
5185 struct instruction_data *data)
5187 CHECK(!action, EINVAL);
5188 CHECK(n_tokens == 2, EINVAL);
5190 strcpy(data->jmp_label, tokens[1]);
5192 instr->type = INSTR_JMP_HIT;
5193 instr->jmp.ip = NULL; /* Resolved later. */
5198 instr_jmp_miss_translate(struct rte_swx_pipeline *p __rte_unused,
5199 struct action *action,
5202 struct instruction *instr,
5203 struct instruction_data *data)
5205 CHECK(!action, EINVAL);
5206 CHECK(n_tokens == 2, EINVAL);
5208 strcpy(data->jmp_label, tokens[1]);
5210 instr->type = INSTR_JMP_MISS;
5211 instr->jmp.ip = NULL; /* Resolved later. */
5216 instr_jmp_action_hit_translate(struct rte_swx_pipeline *p,
5217 struct action *action,
5220 struct instruction *instr,
5221 struct instruction_data *data)
5225 CHECK(!action, EINVAL);
5226 CHECK(n_tokens == 3, EINVAL);
5228 strcpy(data->jmp_label, tokens[1]);
5230 a = action_find(p, tokens[2]);
5233 instr->type = INSTR_JMP_ACTION_HIT;
5234 instr->jmp.ip = NULL; /* Resolved later. */
5235 instr->jmp.action_id = a->id;
5240 instr_jmp_action_miss_translate(struct rte_swx_pipeline *p,
5241 struct action *action,
5244 struct instruction *instr,
5245 struct instruction_data *data)
5249 CHECK(!action, EINVAL);
5250 CHECK(n_tokens == 3, EINVAL);
5252 strcpy(data->jmp_label, tokens[1]);
5254 a = action_find(p, tokens[2]);
5257 instr->type = INSTR_JMP_ACTION_MISS;
5258 instr->jmp.ip = NULL; /* Resolved later. */
5259 instr->jmp.action_id = a->id;
5264 instr_jmp_eq_translate(struct rte_swx_pipeline *p,
5265 struct action *action,
5268 struct instruction *instr,
5269 struct instruction_data *data)
5271 char *a = tokens[2], *b = tokens[3];
5272 struct field *fa, *fb;
5274 uint32_t a_struct_id, b_struct_id;
5276 CHECK(n_tokens == 4, EINVAL);
5278 strcpy(data->jmp_label, tokens[1]);
5280 fa = struct_field_parse(p, action, a, &a_struct_id);
5282 CHECK(!fa->var_size, EINVAL);
5284 /* JMP_EQ, JMP_EQ_MH, JMP_EQ_HM, JMP_EQ_HH. */
5285 fb = struct_field_parse(p, action, b, &b_struct_id);
5287 CHECK(!fb->var_size, EINVAL);
5289 instr->type = INSTR_JMP_EQ;
5290 if (a[0] != 'h' && b[0] == 'h')
5291 instr->type = INSTR_JMP_EQ_MH;
5292 if (a[0] == 'h' && b[0] != 'h')
5293 instr->type = INSTR_JMP_EQ_HM;
5294 if (a[0] == 'h' && b[0] == 'h')
5295 instr->type = INSTR_JMP_EQ_HH;
5296 instr->jmp.ip = NULL; /* Resolved later. */
5298 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5299 instr->jmp.a.n_bits = fa->n_bits;
5300 instr->jmp.a.offset = fa->offset / 8;
5301 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5302 instr->jmp.b.n_bits = fb->n_bits;
5303 instr->jmp.b.offset = fb->offset / 8;
5308 b_val = strtoull(b, &b, 0);
5309 CHECK(!b[0], EINVAL);
5312 b_val = hton64(b_val) >> (64 - fa->n_bits);
5314 instr->type = INSTR_JMP_EQ_I;
5315 instr->jmp.ip = NULL; /* Resolved later. */
5316 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5317 instr->jmp.a.n_bits = fa->n_bits;
5318 instr->jmp.a.offset = fa->offset / 8;
5319 instr->jmp.b_val = b_val;
5324 instr_jmp_neq_translate(struct rte_swx_pipeline *p,
5325 struct action *action,
5328 struct instruction *instr,
5329 struct instruction_data *data)
5331 char *a = tokens[2], *b = tokens[3];
5332 struct field *fa, *fb;
5334 uint32_t a_struct_id, b_struct_id;
5336 CHECK(n_tokens == 4, EINVAL);
5338 strcpy(data->jmp_label, tokens[1]);
5340 fa = struct_field_parse(p, action, a, &a_struct_id);
5342 CHECK(!fa->var_size, EINVAL);
5344 /* JMP_NEQ, JMP_NEQ_MH, JMP_NEQ_HM, JMP_NEQ_HH. */
5345 fb = struct_field_parse(p, action, b, &b_struct_id);
5347 CHECK(!fb->var_size, EINVAL);
5349 instr->type = INSTR_JMP_NEQ;
5350 if (a[0] != 'h' && b[0] == 'h')
5351 instr->type = INSTR_JMP_NEQ_MH;
5352 if (a[0] == 'h' && b[0] != 'h')
5353 instr->type = INSTR_JMP_NEQ_HM;
5354 if (a[0] == 'h' && b[0] == 'h')
5355 instr->type = INSTR_JMP_NEQ_HH;
5356 instr->jmp.ip = NULL; /* Resolved later. */
5358 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5359 instr->jmp.a.n_bits = fa->n_bits;
5360 instr->jmp.a.offset = fa->offset / 8;
5361 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5362 instr->jmp.b.n_bits = fb->n_bits;
5363 instr->jmp.b.offset = fb->offset / 8;
5368 b_val = strtoull(b, &b, 0);
5369 CHECK(!b[0], EINVAL);
5372 b_val = hton64(b_val) >> (64 - fa->n_bits);
5374 instr->type = INSTR_JMP_NEQ_I;
5375 instr->jmp.ip = NULL; /* Resolved later. */
5376 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5377 instr->jmp.a.n_bits = fa->n_bits;
5378 instr->jmp.a.offset = fa->offset / 8;
5379 instr->jmp.b_val = b_val;
5384 instr_jmp_lt_translate(struct rte_swx_pipeline *p,
5385 struct action *action,
5388 struct instruction *instr,
5389 struct instruction_data *data)
5391 char *a = tokens[2], *b = tokens[3];
5392 struct field *fa, *fb;
5394 uint32_t a_struct_id, b_struct_id;
5396 CHECK(n_tokens == 4, EINVAL);
5398 strcpy(data->jmp_label, tokens[1]);
5400 fa = struct_field_parse(p, action, a, &a_struct_id);
5402 CHECK(!fa->var_size, EINVAL);
5404 /* JMP_LT, JMP_LT_MH, JMP_LT_HM, JMP_LT_HH. */
5405 fb = struct_field_parse(p, action, b, &b_struct_id);
5407 CHECK(!fb->var_size, EINVAL);
5409 instr->type = INSTR_JMP_LT;
5410 if (a[0] == 'h' && b[0] != 'h')
5411 instr->type = INSTR_JMP_LT_HM;
5412 if (a[0] != 'h' && b[0] == 'h')
5413 instr->type = INSTR_JMP_LT_MH;
5414 if (a[0] == 'h' && b[0] == 'h')
5415 instr->type = INSTR_JMP_LT_HH;
5416 instr->jmp.ip = NULL; /* Resolved later. */
5418 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5419 instr->jmp.a.n_bits = fa->n_bits;
5420 instr->jmp.a.offset = fa->offset / 8;
5421 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5422 instr->jmp.b.n_bits = fb->n_bits;
5423 instr->jmp.b.offset = fb->offset / 8;
5427 /* JMP_LT_MI, JMP_LT_HI. */
5428 b_val = strtoull(b, &b, 0);
5429 CHECK(!b[0], EINVAL);
5431 instr->type = INSTR_JMP_LT_MI;
5433 instr->type = INSTR_JMP_LT_HI;
5434 instr->jmp.ip = NULL; /* Resolved later. */
5436 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5437 instr->jmp.a.n_bits = fa->n_bits;
5438 instr->jmp.a.offset = fa->offset / 8;
5439 instr->jmp.b_val = b_val;
5444 instr_jmp_gt_translate(struct rte_swx_pipeline *p,
5445 struct action *action,
5448 struct instruction *instr,
5449 struct instruction_data *data)
5451 char *a = tokens[2], *b = tokens[3];
5452 struct field *fa, *fb;
5454 uint32_t a_struct_id, b_struct_id;
5456 CHECK(n_tokens == 4, EINVAL);
5458 strcpy(data->jmp_label, tokens[1]);
5460 fa = struct_field_parse(p, action, a, &a_struct_id);
5462 CHECK(!fa->var_size, EINVAL);
5464 /* JMP_GT, JMP_GT_MH, JMP_GT_HM, JMP_GT_HH. */
5465 fb = struct_field_parse(p, action, b, &b_struct_id);
5467 CHECK(!fb->var_size, EINVAL);
5469 instr->type = INSTR_JMP_GT;
5470 if (a[0] == 'h' && b[0] != 'h')
5471 instr->type = INSTR_JMP_GT_HM;
5472 if (a[0] != 'h' && b[0] == 'h')
5473 instr->type = INSTR_JMP_GT_MH;
5474 if (a[0] == 'h' && b[0] == 'h')
5475 instr->type = INSTR_JMP_GT_HH;
5476 instr->jmp.ip = NULL; /* Resolved later. */
5478 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5479 instr->jmp.a.n_bits = fa->n_bits;
5480 instr->jmp.a.offset = fa->offset / 8;
5481 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5482 instr->jmp.b.n_bits = fb->n_bits;
5483 instr->jmp.b.offset = fb->offset / 8;
5487 /* JMP_GT_MI, JMP_GT_HI. */
5488 b_val = strtoull(b, &b, 0);
5489 CHECK(!b[0], EINVAL);
5491 instr->type = INSTR_JMP_GT_MI;
5493 instr->type = INSTR_JMP_GT_HI;
5494 instr->jmp.ip = NULL; /* Resolved later. */
5496 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5497 instr->jmp.a.n_bits = fa->n_bits;
5498 instr->jmp.a.offset = fa->offset / 8;
5499 instr->jmp.b_val = b_val;
5504 instr_jmp_exec(struct rte_swx_pipeline *p)
5506 struct thread *t = &p->threads[p->thread_id];
5507 struct instruction *ip = t->ip;
5509 TRACE("[Thread %2u] jmp\n", p->thread_id);
5511 thread_ip_set(t, ip->jmp.ip);
5515 instr_jmp_valid_exec(struct rte_swx_pipeline *p)
5517 struct thread *t = &p->threads[p->thread_id];
5518 struct instruction *ip = t->ip;
5519 uint32_t header_id = ip->jmp.header_id;
5521 TRACE("[Thread %2u] jmpv\n", p->thread_id);
5523 t->ip = HEADER_VALID(t, header_id) ? ip->jmp.ip : (t->ip + 1);
5527 instr_jmp_invalid_exec(struct rte_swx_pipeline *p)
5529 struct thread *t = &p->threads[p->thread_id];
5530 struct instruction *ip = t->ip;
5531 uint32_t header_id = ip->jmp.header_id;
5533 TRACE("[Thread %2u] jmpnv\n", p->thread_id);
5535 t->ip = HEADER_VALID(t, header_id) ? (t->ip + 1) : ip->jmp.ip;
5539 instr_jmp_hit_exec(struct rte_swx_pipeline *p)
5541 struct thread *t = &p->threads[p->thread_id];
5542 struct instruction *ip = t->ip;
5543 struct instruction *ip_next[] = {t->ip + 1, ip->jmp.ip};
5545 TRACE("[Thread %2u] jmph\n", p->thread_id);
5547 t->ip = ip_next[t->hit];
5551 instr_jmp_miss_exec(struct rte_swx_pipeline *p)
5553 struct thread *t = &p->threads[p->thread_id];
5554 struct instruction *ip = t->ip;
5555 struct instruction *ip_next[] = {ip->jmp.ip, t->ip + 1};
5557 TRACE("[Thread %2u] jmpnh\n", p->thread_id);
5559 t->ip = ip_next[t->hit];
5563 instr_jmp_action_hit_exec(struct rte_swx_pipeline *p)
5565 struct thread *t = &p->threads[p->thread_id];
5566 struct instruction *ip = t->ip;
5568 TRACE("[Thread %2u] jmpa\n", p->thread_id);
5570 t->ip = (ip->jmp.action_id == t->action_id) ? ip->jmp.ip : (t->ip + 1);
5574 instr_jmp_action_miss_exec(struct rte_swx_pipeline *p)
5576 struct thread *t = &p->threads[p->thread_id];
5577 struct instruction *ip = t->ip;
5579 TRACE("[Thread %2u] jmpna\n", p->thread_id);
5581 t->ip = (ip->jmp.action_id == t->action_id) ? (t->ip + 1) : ip->jmp.ip;
5585 instr_jmp_eq_exec(struct rte_swx_pipeline *p)
5587 struct thread *t = &p->threads[p->thread_id];
5588 struct instruction *ip = t->ip;
5590 TRACE("[Thread %2u] jmpeq\n", p->thread_id);
5596 instr_jmp_eq_mh_exec(struct rte_swx_pipeline *p)
5598 struct thread *t = &p->threads[p->thread_id];
5599 struct instruction *ip = t->ip;
5601 TRACE("[Thread %2u] jmpeq (mh)\n", p->thread_id);
5603 JMP_CMP_MH(t, ip, ==);
5607 instr_jmp_eq_hm_exec(struct rte_swx_pipeline *p)
5609 struct thread *t = &p->threads[p->thread_id];
5610 struct instruction *ip = t->ip;
5612 TRACE("[Thread %2u] jmpeq (hm)\n", p->thread_id);
5614 JMP_CMP_HM(t, ip, ==);
5618 instr_jmp_eq_hh_exec(struct rte_swx_pipeline *p)
5620 struct thread *t = &p->threads[p->thread_id];
5621 struct instruction *ip = t->ip;
5623 TRACE("[Thread %2u] jmpeq (hh)\n", p->thread_id);
5625 JMP_CMP_HH_FAST(t, ip, ==);
5629 instr_jmp_eq_i_exec(struct rte_swx_pipeline *p)
5631 struct thread *t = &p->threads[p->thread_id];
5632 struct instruction *ip = t->ip;
5634 TRACE("[Thread %2u] jmpeq (i)\n", p->thread_id);
5636 JMP_CMP_I(t, ip, ==);
5640 instr_jmp_neq_exec(struct rte_swx_pipeline *p)
5642 struct thread *t = &p->threads[p->thread_id];
5643 struct instruction *ip = t->ip;
5645 TRACE("[Thread %2u] jmpneq\n", p->thread_id);
5651 instr_jmp_neq_mh_exec(struct rte_swx_pipeline *p)
5653 struct thread *t = &p->threads[p->thread_id];
5654 struct instruction *ip = t->ip;
5656 TRACE("[Thread %2u] jmpneq (mh)\n", p->thread_id);
5658 JMP_CMP_MH(t, ip, !=);
5662 instr_jmp_neq_hm_exec(struct rte_swx_pipeline *p)
5664 struct thread *t = &p->threads[p->thread_id];
5665 struct instruction *ip = t->ip;
5667 TRACE("[Thread %2u] jmpneq (hm)\n", p->thread_id);
5669 JMP_CMP_HM(t, ip, !=);
5673 instr_jmp_neq_hh_exec(struct rte_swx_pipeline *p)
5675 struct thread *t = &p->threads[p->thread_id];
5676 struct instruction *ip = t->ip;
5678 TRACE("[Thread %2u] jmpneq (hh)\n", p->thread_id);
5680 JMP_CMP_HH_FAST(t, ip, !=);
5684 instr_jmp_neq_i_exec(struct rte_swx_pipeline *p)
5686 struct thread *t = &p->threads[p->thread_id];
5687 struct instruction *ip = t->ip;
5689 TRACE("[Thread %2u] jmpneq (i)\n", p->thread_id);
5691 JMP_CMP_I(t, ip, !=);
5695 instr_jmp_lt_exec(struct rte_swx_pipeline *p)
5697 struct thread *t = &p->threads[p->thread_id];
5698 struct instruction *ip = t->ip;
5700 TRACE("[Thread %2u] jmplt\n", p->thread_id);
5706 instr_jmp_lt_mh_exec(struct rte_swx_pipeline *p)
5708 struct thread *t = &p->threads[p->thread_id];
5709 struct instruction *ip = t->ip;
5711 TRACE("[Thread %2u] jmplt (mh)\n", p->thread_id);
5713 JMP_CMP_MH(t, ip, <);
5717 instr_jmp_lt_hm_exec(struct rte_swx_pipeline *p)
5719 struct thread *t = &p->threads[p->thread_id];
5720 struct instruction *ip = t->ip;
5722 TRACE("[Thread %2u] jmplt (hm)\n", p->thread_id);
5724 JMP_CMP_HM(t, ip, <);
5728 instr_jmp_lt_hh_exec(struct rte_swx_pipeline *p)
5730 struct thread *t = &p->threads[p->thread_id];
5731 struct instruction *ip = t->ip;
5733 TRACE("[Thread %2u] jmplt (hh)\n", p->thread_id);
5735 JMP_CMP_HH(t, ip, <);
5739 instr_jmp_lt_mi_exec(struct rte_swx_pipeline *p)
5741 struct thread *t = &p->threads[p->thread_id];
5742 struct instruction *ip = t->ip;
5744 TRACE("[Thread %2u] jmplt (mi)\n", p->thread_id);
5746 JMP_CMP_MI(t, ip, <);
5750 instr_jmp_lt_hi_exec(struct rte_swx_pipeline *p)
5752 struct thread *t = &p->threads[p->thread_id];
5753 struct instruction *ip = t->ip;
5755 TRACE("[Thread %2u] jmplt (hi)\n", p->thread_id);
5757 JMP_CMP_HI(t, ip, <);
5761 instr_jmp_gt_exec(struct rte_swx_pipeline *p)
5763 struct thread *t = &p->threads[p->thread_id];
5764 struct instruction *ip = t->ip;
5766 TRACE("[Thread %2u] jmpgt\n", p->thread_id);
5772 instr_jmp_gt_mh_exec(struct rte_swx_pipeline *p)
5774 struct thread *t = &p->threads[p->thread_id];
5775 struct instruction *ip = t->ip;
5777 TRACE("[Thread %2u] jmpgt (mh)\n", p->thread_id);
5779 JMP_CMP_MH(t, ip, >);
5783 instr_jmp_gt_hm_exec(struct rte_swx_pipeline *p)
5785 struct thread *t = &p->threads[p->thread_id];
5786 struct instruction *ip = t->ip;
5788 TRACE("[Thread %2u] jmpgt (hm)\n", p->thread_id);
5790 JMP_CMP_HM(t, ip, >);
5794 instr_jmp_gt_hh_exec(struct rte_swx_pipeline *p)
5796 struct thread *t = &p->threads[p->thread_id];
5797 struct instruction *ip = t->ip;
5799 TRACE("[Thread %2u] jmpgt (hh)\n", p->thread_id);
5801 JMP_CMP_HH(t, ip, >);
5805 instr_jmp_gt_mi_exec(struct rte_swx_pipeline *p)
5807 struct thread *t = &p->threads[p->thread_id];
5808 struct instruction *ip = t->ip;
5810 TRACE("[Thread %2u] jmpgt (mi)\n", p->thread_id);
5812 JMP_CMP_MI(t, ip, >);
5816 instr_jmp_gt_hi_exec(struct rte_swx_pipeline *p)
5818 struct thread *t = &p->threads[p->thread_id];
5819 struct instruction *ip = t->ip;
5821 TRACE("[Thread %2u] jmpgt (hi)\n", p->thread_id);
5823 JMP_CMP_HI(t, ip, >);
5830 instr_return_translate(struct rte_swx_pipeline *p __rte_unused,
5831 struct action *action,
5832 char **tokens __rte_unused,
5834 struct instruction *instr,
5835 struct instruction_data *data __rte_unused)
5837 CHECK(action, EINVAL);
5838 CHECK(n_tokens == 1, EINVAL);
5840 instr->type = INSTR_RETURN;
5845 instr_return_exec(struct rte_swx_pipeline *p)
5847 struct thread *t = &p->threads[p->thread_id];
5849 TRACE("[Thread %2u] return\n", p->thread_id);
5855 instr_translate(struct rte_swx_pipeline *p,
5856 struct action *action,
5858 struct instruction *instr,
5859 struct instruction_data *data)
5861 char *tokens[RTE_SWX_INSTRUCTION_TOKENS_MAX];
5862 int n_tokens = 0, tpos = 0;
5864 /* Parse the instruction string into tokens. */
5868 token = strtok_r(string, " \t\v", &string);
5872 CHECK(n_tokens < RTE_SWX_INSTRUCTION_TOKENS_MAX, EINVAL);
5873 CHECK_NAME(token, EINVAL);
5875 tokens[n_tokens] = token;
5879 CHECK(n_tokens, EINVAL);
5881 /* Handle the optional instruction label. */
5882 if ((n_tokens >= 2) && !strcmp(tokens[1], ":")) {
5883 strcpy(data->label, tokens[0]);
5886 CHECK(n_tokens - tpos, EINVAL);
5889 /* Identify the instruction type. */
5890 if (!strcmp(tokens[tpos], "rx"))
5891 return instr_rx_translate(p,
5898 if (!strcmp(tokens[tpos], "tx"))
5899 return instr_tx_translate(p,
5906 if (!strcmp(tokens[tpos], "drop"))
5907 return instr_drop_translate(p,
5914 if (!strcmp(tokens[tpos], "mirror"))
5915 return instr_mirror_translate(p,
5922 if (!strcmp(tokens[tpos], "recirculate"))
5923 return instr_recirculate_translate(p,
5930 if (!strcmp(tokens[tpos], "recircid"))
5931 return instr_recircid_translate(p,
5938 if (!strcmp(tokens[tpos], "extract"))
5939 return instr_hdr_extract_translate(p,
5946 if (!strcmp(tokens[tpos], "lookahead"))
5947 return instr_hdr_lookahead_translate(p,
5954 if (!strcmp(tokens[tpos], "emit"))
5955 return instr_hdr_emit_translate(p,
5962 if (!strcmp(tokens[tpos], "validate"))
5963 return instr_hdr_validate_translate(p,
5970 if (!strcmp(tokens[tpos], "invalidate"))
5971 return instr_hdr_invalidate_translate(p,
5978 if (!strcmp(tokens[tpos], "mov"))
5979 return instr_mov_translate(p,
5986 if (!strcmp(tokens[tpos], "add"))
5987 return instr_alu_add_translate(p,
5994 if (!strcmp(tokens[tpos], "sub"))
5995 return instr_alu_sub_translate(p,
6002 if (!strcmp(tokens[tpos], "ckadd"))
6003 return instr_alu_ckadd_translate(p,
6010 if (!strcmp(tokens[tpos], "cksub"))
6011 return instr_alu_cksub_translate(p,
6018 if (!strcmp(tokens[tpos], "and"))
6019 return instr_alu_and_translate(p,
6026 if (!strcmp(tokens[tpos], "or"))
6027 return instr_alu_or_translate(p,
6034 if (!strcmp(tokens[tpos], "xor"))
6035 return instr_alu_xor_translate(p,
6042 if (!strcmp(tokens[tpos], "shl"))
6043 return instr_alu_shl_translate(p,
6050 if (!strcmp(tokens[tpos], "shr"))
6051 return instr_alu_shr_translate(p,
6058 if (!strcmp(tokens[tpos], "regprefetch"))
6059 return instr_regprefetch_translate(p,
6066 if (!strcmp(tokens[tpos], "regrd"))
6067 return instr_regrd_translate(p,
6074 if (!strcmp(tokens[tpos], "regwr"))
6075 return instr_regwr_translate(p,
6082 if (!strcmp(tokens[tpos], "regadd"))
6083 return instr_regadd_translate(p,
6090 if (!strcmp(tokens[tpos], "metprefetch"))
6091 return instr_metprefetch_translate(p,
6098 if (!strcmp(tokens[tpos], "meter"))
6099 return instr_meter_translate(p,
6106 if (!strcmp(tokens[tpos], "table"))
6107 return instr_table_translate(p,
6114 if (!strcmp(tokens[tpos], "learn"))
6115 return instr_learn_translate(p,
6121 if (!strcmp(tokens[tpos], "rearm"))
6122 return instr_rearm_translate(p,
6129 if (!strcmp(tokens[tpos], "forget"))
6130 return instr_forget_translate(p,
6137 if (!strcmp(tokens[tpos], "extern"))
6138 return instr_extern_translate(p,
6145 if (!strcmp(tokens[tpos], "jmp"))
6146 return instr_jmp_translate(p,
6153 if (!strcmp(tokens[tpos], "jmpv"))
6154 return instr_jmp_valid_translate(p,
6161 if (!strcmp(tokens[tpos], "jmpnv"))
6162 return instr_jmp_invalid_translate(p,
6169 if (!strcmp(tokens[tpos], "jmph"))
6170 return instr_jmp_hit_translate(p,
6177 if (!strcmp(tokens[tpos], "jmpnh"))
6178 return instr_jmp_miss_translate(p,
6185 if (!strcmp(tokens[tpos], "jmpa"))
6186 return instr_jmp_action_hit_translate(p,
6193 if (!strcmp(tokens[tpos], "jmpna"))
6194 return instr_jmp_action_miss_translate(p,
6201 if (!strcmp(tokens[tpos], "jmpeq"))
6202 return instr_jmp_eq_translate(p,
6209 if (!strcmp(tokens[tpos], "jmpneq"))
6210 return instr_jmp_neq_translate(p,
6217 if (!strcmp(tokens[tpos], "jmplt"))
6218 return instr_jmp_lt_translate(p,
6225 if (!strcmp(tokens[tpos], "jmpgt"))
6226 return instr_jmp_gt_translate(p,
6233 if (!strcmp(tokens[tpos], "return"))
6234 return instr_return_translate(p,
6244 static struct instruction_data *
6245 label_find(struct instruction_data *data, uint32_t n, const char *label)
6249 for (i = 0; i < n; i++)
6250 if (!strcmp(label, data[i].label))
6257 label_is_used(struct instruction_data *data, uint32_t n, const char *label)
6259 uint32_t count = 0, i;
6264 for (i = 0; i < n; i++)
6265 if (!strcmp(label, data[i].jmp_label))
6272 instr_label_check(struct instruction_data *instruction_data,
6273 uint32_t n_instructions)
6277 /* Check that all instruction labels are unique. */
6278 for (i = 0; i < n_instructions; i++) {
6279 struct instruction_data *data = &instruction_data[i];
6280 char *label = data->label;
6286 for (j = i + 1; j < n_instructions; j++)
6287 CHECK(strcmp(label, instruction_data[j].label), EINVAL);
6290 /* Check that no jump instruction (either conditional or not) can jump to itself (loop). */
6291 for (i = 0; i < n_instructions; i++) {
6292 struct instruction_data *data = &instruction_data[i];
6293 char *label = data->label;
6294 char *jmp_label = data->jmp_label;
6296 /* Continue if this instruction does not have a label or it is not a jump. */
6297 if (!label[0] || !jmp_label[0])
6300 CHECK(strcmp(label, jmp_label), EINVAL);
6303 /* Get users for each instruction label. */
6304 for (i = 0; i < n_instructions; i++) {
6305 struct instruction_data *data = &instruction_data[i];
6306 char *label = data->label;
6308 data->n_users = label_is_used(instruction_data,
6317 instr_jmp_resolve(struct instruction *instructions,
6318 struct instruction_data *instruction_data,
6319 uint32_t n_instructions)
6323 for (i = 0; i < n_instructions; i++) {
6324 struct instruction *instr = &instructions[i];
6325 struct instruction_data *data = &instruction_data[i];
6326 struct instruction_data *found;
6328 if (!instruction_is_jmp(instr))
6331 found = label_find(instruction_data,
6334 CHECK(found, EINVAL);
6336 instr->jmp.ip = &instructions[found - instruction_data];
6343 instr_verify(struct rte_swx_pipeline *p __rte_unused,
6345 struct instruction *instr,
6346 struct instruction_data *data __rte_unused,
6347 uint32_t n_instructions)
6350 enum instruction_type type;
6353 /* Check that the first instruction is rx. */
6354 CHECK(instr[0].type == INSTR_RX, EINVAL);
6356 /* Check that there is at least one tx instruction. */
6357 for (i = 0; i < n_instructions; i++) {
6358 type = instr[i].type;
6360 if (instruction_is_tx(type))
6363 CHECK(i < n_instructions, EINVAL);
6365 /* Check that the last instruction is either tx or unconditional
6368 type = instr[n_instructions - 1].type;
6369 CHECK(instruction_is_tx(type) || (type == INSTR_JMP), EINVAL);
6373 enum instruction_type type;
6376 /* Check that there is at least one return or tx instruction. */
6377 for (i = 0; i < n_instructions; i++) {
6378 type = instr[i].type;
6380 if ((type == INSTR_RETURN) || instruction_is_tx(type))
6383 CHECK(i < n_instructions, EINVAL);
6390 instr_compact(struct instruction *instructions,
6391 struct instruction_data *instruction_data,
6392 uint32_t n_instructions)
6394 uint32_t i, pos = 0;
6396 /* Eliminate the invalid instructions that have been optimized out. */
6397 for (i = 0; i < n_instructions; i++) {
6398 struct instruction *instr = &instructions[i];
6399 struct instruction_data *data = &instruction_data[i];
6405 memcpy(&instructions[pos], instr, sizeof(*instr));
6406 memcpy(&instruction_data[pos], data, sizeof(*data));
6416 instr_pattern_extract_many_search(struct instruction *instr,
6417 struct instruction_data *data,
6419 uint32_t *n_pattern_instr)
6423 for (i = 0; i < n_instr; i++) {
6424 if (data[i].invalid)
6427 if (instr[i].type != INSTR_HDR_EXTRACT)
6430 if (i == RTE_DIM(instr->io.hdr.header_id))
6433 if (i && data[i].n_users)
6440 *n_pattern_instr = i;
6445 instr_pattern_extract_many_replace(struct instruction *instr,
6446 struct instruction_data *data,
6451 for (i = 1; i < n_instr; i++) {
6453 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
6454 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
6455 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
6457 data[i].invalid = 1;
6462 instr_pattern_extract_many_optimize(struct instruction *instructions,
6463 struct instruction_data *instruction_data,
6464 uint32_t n_instructions)
6468 for (i = 0; i < n_instructions; ) {
6469 struct instruction *instr = &instructions[i];
6470 struct instruction_data *data = &instruction_data[i];
6471 uint32_t n_instr = 0;
6475 detected = instr_pattern_extract_many_search(instr,
6480 instr_pattern_extract_many_replace(instr,
6487 /* No pattern starting at the current instruction. */
6491 /* Eliminate the invalid instructions that have been optimized out. */
6492 n_instructions = instr_compact(instructions,
6496 return n_instructions;
6500 instr_pattern_emit_many_tx_search(struct instruction *instr,
6501 struct instruction_data *data,
6503 uint32_t *n_pattern_instr)
6507 for (i = 0; i < n_instr; i++) {
6508 if (data[i].invalid)
6511 if (instr[i].type != INSTR_HDR_EMIT)
6514 if (i == RTE_DIM(instr->io.hdr.header_id))
6517 if (i && data[i].n_users)
6524 if (instr[i].type != INSTR_TX)
6527 if (data[i].n_users)
6532 *n_pattern_instr = i;
6537 instr_pattern_emit_many_tx_replace(struct instruction *instr,
6538 struct instruction_data *data,
6543 /* Any emit instruction in addition to the first one. */
6544 for (i = 1; i < n_instr - 1; i++) {
6546 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
6547 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
6548 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
6550 data[i].invalid = 1;
6553 /* The TX instruction is the last one in the pattern. */
6555 instr[0].io.io.offset = instr[i].io.io.offset;
6556 instr[0].io.io.n_bits = instr[i].io.io.n_bits;
6557 data[i].invalid = 1;
6561 instr_pattern_emit_many_tx_optimize(struct instruction *instructions,
6562 struct instruction_data *instruction_data,
6563 uint32_t n_instructions)
6567 for (i = 0; i < n_instructions; ) {
6568 struct instruction *instr = &instructions[i];
6569 struct instruction_data *data = &instruction_data[i];
6570 uint32_t n_instr = 0;
6573 /* Emit many + TX. */
6574 detected = instr_pattern_emit_many_tx_search(instr,
6579 instr_pattern_emit_many_tx_replace(instr,
6586 /* No pattern starting at the current instruction. */
6590 /* Eliminate the invalid instructions that have been optimized out. */
6591 n_instructions = instr_compact(instructions,
6595 return n_instructions;
6599 action_arg_src_mov_count(struct action *a,
6601 struct instruction *instructions,
6602 struct instruction_data *instruction_data,
6603 uint32_t n_instructions);
6606 instr_pattern_mov_all_validate_search(struct rte_swx_pipeline *p,
6608 struct instruction *instr,
6609 struct instruction_data *data,
6611 struct instruction *instructions,
6612 struct instruction_data *instruction_data,
6613 uint32_t n_instructions,
6614 uint32_t *n_pattern_instr)
6617 uint32_t src_field_id, i, j;
6619 /* Prerequisites. */
6623 /* First instruction: MOV_HM. */
6624 if (data[0].invalid || (instr[0].type != INSTR_MOV_HM))
6627 h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
6628 if (!h || h->st->var_size)
6631 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
6632 if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
6635 if (src_field_id == a->st->n_fields)
6638 if (instr[0].mov.dst.offset ||
6639 (instr[0].mov.dst.n_bits != h->st->fields[0].n_bits) ||
6640 instr[0].mov.src.struct_id ||
6641 (instr[0].mov.src.n_bits != a->st->fields[src_field_id].n_bits) ||
6642 (instr[0].mov.dst.n_bits != instr[0].mov.src.n_bits))
6645 if ((n_instr < h->st->n_fields + 1) ||
6646 (a->st->n_fields < src_field_id + h->st->n_fields + 1))
6649 /* Subsequent instructions: MOV_HM. */
6650 for (i = 1; i < h->st->n_fields; i++)
6651 if (data[i].invalid ||
6653 (instr[i].type != INSTR_MOV_HM) ||
6654 (instr[i].mov.dst.struct_id != h->struct_id) ||
6655 (instr[i].mov.dst.offset != h->st->fields[i].offset / 8) ||
6656 (instr[i].mov.dst.n_bits != h->st->fields[i].n_bits) ||
6657 instr[i].mov.src.struct_id ||
6658 (instr[i].mov.src.offset != a->st->fields[src_field_id + i].offset / 8) ||
6659 (instr[i].mov.src.n_bits != a->st->fields[src_field_id + i].n_bits) ||
6660 (instr[i].mov.dst.n_bits != instr[i].mov.src.n_bits))
6663 /* Last instruction: HDR_VALIDATE. */
6664 if ((instr[i].type != INSTR_HDR_VALIDATE) ||
6665 (instr[i].valid.header_id != h->id))
6668 /* Check that none of the action args that are used as source for this
6669 * DMA transfer are not used as source in any other mov instruction.
6671 for (j = src_field_id; j < src_field_id + h->st->n_fields; j++) {
6674 n_users = action_arg_src_mov_count(a,
6683 *n_pattern_instr = 1 + i;
6688 instr_pattern_mov_all_validate_replace(struct rte_swx_pipeline *p,
6690 struct instruction *instr,
6691 struct instruction_data *data,
6695 uint32_t src_field_id, src_offset, i;
6697 /* Read from the instructions before they are modified. */
6698 h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
6702 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
6703 if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
6706 if (src_field_id == a->st->n_fields)
6709 src_offset = instr[0].mov.src.offset;
6711 /* Modify the instructions. */
6712 instr[0].type = INSTR_DMA_HT;
6713 instr[0].dma.dst.header_id[0] = h->id;
6714 instr[0].dma.dst.struct_id[0] = h->struct_id;
6715 instr[0].dma.src.offset[0] = (uint8_t)src_offset;
6716 instr[0].dma.n_bytes[0] = h->st->n_bits / 8;
6718 for (i = 1; i < n_instr; i++)
6719 data[i].invalid = 1;
6721 /* Update the endianness of the action arguments to header endianness. */
6722 for (i = 0; i < h->st->n_fields; i++)
6723 a->args_endianness[src_field_id + i] = 1;
6727 instr_pattern_mov_all_validate_optimize(struct rte_swx_pipeline *p,
6729 struct instruction *instructions,
6730 struct instruction_data *instruction_data,
6731 uint32_t n_instructions)
6736 return n_instructions;
6738 for (i = 0; i < n_instructions; ) {
6739 struct instruction *instr = &instructions[i];
6740 struct instruction_data *data = &instruction_data[i];
6741 uint32_t n_instr = 0;
6744 /* Mov all + validate. */
6745 detected = instr_pattern_mov_all_validate_search(p,
6755 instr_pattern_mov_all_validate_replace(p, a, instr, data, n_instr);
6760 /* No pattern starting at the current instruction. */
6764 /* Eliminate the invalid instructions that have been optimized out. */
6765 n_instructions = instr_compact(instructions,
6769 return n_instructions;
6773 instr_pattern_dma_many_search(struct instruction *instr,
6774 struct instruction_data *data,
6776 uint32_t *n_pattern_instr)
6780 for (i = 0; i < n_instr; i++) {
6781 if (data[i].invalid)
6784 if (instr[i].type != INSTR_DMA_HT)
6787 if (i == RTE_DIM(instr->dma.dst.header_id))
6790 if (i && data[i].n_users)
6797 *n_pattern_instr = i;
6802 instr_pattern_dma_many_replace(struct instruction *instr,
6803 struct instruction_data *data,
6808 for (i = 1; i < n_instr; i++) {
6810 instr[0].dma.dst.header_id[i] = instr[i].dma.dst.header_id[0];
6811 instr[0].dma.dst.struct_id[i] = instr[i].dma.dst.struct_id[0];
6812 instr[0].dma.src.offset[i] = instr[i].dma.src.offset[0];
6813 instr[0].dma.n_bytes[i] = instr[i].dma.n_bytes[0];
6815 data[i].invalid = 1;
6820 instr_pattern_dma_many_optimize(struct instruction *instructions,
6821 struct instruction_data *instruction_data,
6822 uint32_t n_instructions)
6826 for (i = 0; i < n_instructions; ) {
6827 struct instruction *instr = &instructions[i];
6828 struct instruction_data *data = &instruction_data[i];
6829 uint32_t n_instr = 0;
6833 detected = instr_pattern_dma_many_search(instr,
6838 instr_pattern_dma_many_replace(instr, data, n_instr);
6843 /* No pattern starting at the current instruction. */
6847 /* Eliminate the invalid instructions that have been optimized out. */
6848 n_instructions = instr_compact(instructions,
6852 return n_instructions;
6856 instr_optimize(struct rte_swx_pipeline *p,
6858 struct instruction *instructions,
6859 struct instruction_data *instruction_data,
6860 uint32_t n_instructions)
6863 n_instructions = instr_pattern_extract_many_optimize(instructions,
6867 /* Emit many + TX. */
6868 n_instructions = instr_pattern_emit_many_tx_optimize(instructions,
6872 /* Mov all + validate. */
6873 n_instructions = instr_pattern_mov_all_validate_optimize(p,
6880 n_instructions = instr_pattern_dma_many_optimize(instructions,
6884 return n_instructions;
6888 instruction_config(struct rte_swx_pipeline *p,
6890 const char **instructions,
6891 uint32_t n_instructions)
6893 struct instruction *instr = NULL;
6894 struct instruction_data *data = NULL;
6898 CHECK(n_instructions, EINVAL);
6899 CHECK(instructions, EINVAL);
6900 for (i = 0; i < n_instructions; i++)
6901 CHECK_INSTRUCTION(instructions[i], EINVAL);
6903 /* Memory allocation. */
6904 instr = calloc(n_instructions, sizeof(struct instruction));
6910 data = calloc(n_instructions, sizeof(struct instruction_data));
6916 for (i = 0; i < n_instructions; i++) {
6917 char *string = strdup(instructions[i]);
6923 err = instr_translate(p, a, string, &instr[i], &data[i]);
6932 err = instr_label_check(data, n_instructions);
6936 err = instr_verify(p, a, instr, data, n_instructions);
6940 n_instructions = instr_optimize(p, a, instr, data, n_instructions);
6942 err = instr_jmp_resolve(instr, data, n_instructions);
6947 a->instructions = instr;
6948 a->instruction_data = data;
6949 a->n_instructions = n_instructions;
6951 p->instructions = instr;
6952 p->instruction_data = data;
6953 p->n_instructions = n_instructions;
6964 static instr_exec_t instruction_table[] = {
6965 [INSTR_RX] = instr_rx_exec,
6966 [INSTR_TX] = instr_tx_exec,
6967 [INSTR_TX_I] = instr_tx_i_exec,
6968 [INSTR_DROP] = instr_drop_exec,
6969 [INSTR_MIRROR] = instr_mirror_exec,
6970 [INSTR_RECIRCULATE] = instr_recirculate_exec,
6971 [INSTR_RECIRCID] = instr_recircid_exec,
6973 [INSTR_HDR_EXTRACT] = instr_hdr_extract_exec,
6974 [INSTR_HDR_EXTRACT2] = instr_hdr_extract2_exec,
6975 [INSTR_HDR_EXTRACT3] = instr_hdr_extract3_exec,
6976 [INSTR_HDR_EXTRACT4] = instr_hdr_extract4_exec,
6977 [INSTR_HDR_EXTRACT5] = instr_hdr_extract5_exec,
6978 [INSTR_HDR_EXTRACT6] = instr_hdr_extract6_exec,
6979 [INSTR_HDR_EXTRACT7] = instr_hdr_extract7_exec,
6980 [INSTR_HDR_EXTRACT8] = instr_hdr_extract8_exec,
6981 [INSTR_HDR_EXTRACT_M] = instr_hdr_extract_m_exec,
6982 [INSTR_HDR_LOOKAHEAD] = instr_hdr_lookahead_exec,
6984 [INSTR_HDR_EMIT] = instr_hdr_emit_exec,
6985 [INSTR_HDR_EMIT_TX] = instr_hdr_emit_tx_exec,
6986 [INSTR_HDR_EMIT2_TX] = instr_hdr_emit2_tx_exec,
6987 [INSTR_HDR_EMIT3_TX] = instr_hdr_emit3_tx_exec,
6988 [INSTR_HDR_EMIT4_TX] = instr_hdr_emit4_tx_exec,
6989 [INSTR_HDR_EMIT5_TX] = instr_hdr_emit5_tx_exec,
6990 [INSTR_HDR_EMIT6_TX] = instr_hdr_emit6_tx_exec,
6991 [INSTR_HDR_EMIT7_TX] = instr_hdr_emit7_tx_exec,
6992 [INSTR_HDR_EMIT8_TX] = instr_hdr_emit8_tx_exec,
6994 [INSTR_HDR_VALIDATE] = instr_hdr_validate_exec,
6995 [INSTR_HDR_INVALIDATE] = instr_hdr_invalidate_exec,
6997 [INSTR_MOV] = instr_mov_exec,
6998 [INSTR_MOV_MH] = instr_mov_mh_exec,
6999 [INSTR_MOV_HM] = instr_mov_hm_exec,
7000 [INSTR_MOV_HH] = instr_mov_hh_exec,
7001 [INSTR_MOV_I] = instr_mov_i_exec,
7003 [INSTR_DMA_HT] = instr_dma_ht_exec,
7004 [INSTR_DMA_HT2] = instr_dma_ht2_exec,
7005 [INSTR_DMA_HT3] = instr_dma_ht3_exec,
7006 [INSTR_DMA_HT4] = instr_dma_ht4_exec,
7007 [INSTR_DMA_HT5] = instr_dma_ht5_exec,
7008 [INSTR_DMA_HT6] = instr_dma_ht6_exec,
7009 [INSTR_DMA_HT7] = instr_dma_ht7_exec,
7010 [INSTR_DMA_HT8] = instr_dma_ht8_exec,
7012 [INSTR_ALU_ADD] = instr_alu_add_exec,
7013 [INSTR_ALU_ADD_MH] = instr_alu_add_mh_exec,
7014 [INSTR_ALU_ADD_HM] = instr_alu_add_hm_exec,
7015 [INSTR_ALU_ADD_HH] = instr_alu_add_hh_exec,
7016 [INSTR_ALU_ADD_MI] = instr_alu_add_mi_exec,
7017 [INSTR_ALU_ADD_HI] = instr_alu_add_hi_exec,
7019 [INSTR_ALU_SUB] = instr_alu_sub_exec,
7020 [INSTR_ALU_SUB_MH] = instr_alu_sub_mh_exec,
7021 [INSTR_ALU_SUB_HM] = instr_alu_sub_hm_exec,
7022 [INSTR_ALU_SUB_HH] = instr_alu_sub_hh_exec,
7023 [INSTR_ALU_SUB_MI] = instr_alu_sub_mi_exec,
7024 [INSTR_ALU_SUB_HI] = instr_alu_sub_hi_exec,
7026 [INSTR_ALU_CKADD_FIELD] = instr_alu_ckadd_field_exec,
7027 [INSTR_ALU_CKADD_STRUCT] = instr_alu_ckadd_struct_exec,
7028 [INSTR_ALU_CKADD_STRUCT20] = instr_alu_ckadd_struct20_exec,
7029 [INSTR_ALU_CKSUB_FIELD] = instr_alu_cksub_field_exec,
7031 [INSTR_ALU_AND] = instr_alu_and_exec,
7032 [INSTR_ALU_AND_MH] = instr_alu_and_mh_exec,
7033 [INSTR_ALU_AND_HM] = instr_alu_and_hm_exec,
7034 [INSTR_ALU_AND_HH] = instr_alu_and_hh_exec,
7035 [INSTR_ALU_AND_I] = instr_alu_and_i_exec,
7037 [INSTR_ALU_OR] = instr_alu_or_exec,
7038 [INSTR_ALU_OR_MH] = instr_alu_or_mh_exec,
7039 [INSTR_ALU_OR_HM] = instr_alu_or_hm_exec,
7040 [INSTR_ALU_OR_HH] = instr_alu_or_hh_exec,
7041 [INSTR_ALU_OR_I] = instr_alu_or_i_exec,
7043 [INSTR_ALU_XOR] = instr_alu_xor_exec,
7044 [INSTR_ALU_XOR_MH] = instr_alu_xor_mh_exec,
7045 [INSTR_ALU_XOR_HM] = instr_alu_xor_hm_exec,
7046 [INSTR_ALU_XOR_HH] = instr_alu_xor_hh_exec,
7047 [INSTR_ALU_XOR_I] = instr_alu_xor_i_exec,
7049 [INSTR_ALU_SHL] = instr_alu_shl_exec,
7050 [INSTR_ALU_SHL_MH] = instr_alu_shl_mh_exec,
7051 [INSTR_ALU_SHL_HM] = instr_alu_shl_hm_exec,
7052 [INSTR_ALU_SHL_HH] = instr_alu_shl_hh_exec,
7053 [INSTR_ALU_SHL_MI] = instr_alu_shl_mi_exec,
7054 [INSTR_ALU_SHL_HI] = instr_alu_shl_hi_exec,
7056 [INSTR_ALU_SHR] = instr_alu_shr_exec,
7057 [INSTR_ALU_SHR_MH] = instr_alu_shr_mh_exec,
7058 [INSTR_ALU_SHR_HM] = instr_alu_shr_hm_exec,
7059 [INSTR_ALU_SHR_HH] = instr_alu_shr_hh_exec,
7060 [INSTR_ALU_SHR_MI] = instr_alu_shr_mi_exec,
7061 [INSTR_ALU_SHR_HI] = instr_alu_shr_hi_exec,
7063 [INSTR_REGPREFETCH_RH] = instr_regprefetch_rh_exec,
7064 [INSTR_REGPREFETCH_RM] = instr_regprefetch_rm_exec,
7065 [INSTR_REGPREFETCH_RI] = instr_regprefetch_ri_exec,
7067 [INSTR_REGRD_HRH] = instr_regrd_hrh_exec,
7068 [INSTR_REGRD_HRM] = instr_regrd_hrm_exec,
7069 [INSTR_REGRD_MRH] = instr_regrd_mrh_exec,
7070 [INSTR_REGRD_MRM] = instr_regrd_mrm_exec,
7071 [INSTR_REGRD_HRI] = instr_regrd_hri_exec,
7072 [INSTR_REGRD_MRI] = instr_regrd_mri_exec,
7074 [INSTR_REGWR_RHH] = instr_regwr_rhh_exec,
7075 [INSTR_REGWR_RHM] = instr_regwr_rhm_exec,
7076 [INSTR_REGWR_RMH] = instr_regwr_rmh_exec,
7077 [INSTR_REGWR_RMM] = instr_regwr_rmm_exec,
7078 [INSTR_REGWR_RHI] = instr_regwr_rhi_exec,
7079 [INSTR_REGWR_RMI] = instr_regwr_rmi_exec,
7080 [INSTR_REGWR_RIH] = instr_regwr_rih_exec,
7081 [INSTR_REGWR_RIM] = instr_regwr_rim_exec,
7082 [INSTR_REGWR_RII] = instr_regwr_rii_exec,
7084 [INSTR_REGADD_RHH] = instr_regadd_rhh_exec,
7085 [INSTR_REGADD_RHM] = instr_regadd_rhm_exec,
7086 [INSTR_REGADD_RMH] = instr_regadd_rmh_exec,
7087 [INSTR_REGADD_RMM] = instr_regadd_rmm_exec,
7088 [INSTR_REGADD_RHI] = instr_regadd_rhi_exec,
7089 [INSTR_REGADD_RMI] = instr_regadd_rmi_exec,
7090 [INSTR_REGADD_RIH] = instr_regadd_rih_exec,
7091 [INSTR_REGADD_RIM] = instr_regadd_rim_exec,
7092 [INSTR_REGADD_RII] = instr_regadd_rii_exec,
7094 [INSTR_METPREFETCH_H] = instr_metprefetch_h_exec,
7095 [INSTR_METPREFETCH_M] = instr_metprefetch_m_exec,
7096 [INSTR_METPREFETCH_I] = instr_metprefetch_i_exec,
7098 [INSTR_METER_HHM] = instr_meter_hhm_exec,
7099 [INSTR_METER_HHI] = instr_meter_hhi_exec,
7100 [INSTR_METER_HMM] = instr_meter_hmm_exec,
7101 [INSTR_METER_HMI] = instr_meter_hmi_exec,
7102 [INSTR_METER_MHM] = instr_meter_mhm_exec,
7103 [INSTR_METER_MHI] = instr_meter_mhi_exec,
7104 [INSTR_METER_MMM] = instr_meter_mmm_exec,
7105 [INSTR_METER_MMI] = instr_meter_mmi_exec,
7106 [INSTR_METER_IHM] = instr_meter_ihm_exec,
7107 [INSTR_METER_IHI] = instr_meter_ihi_exec,
7108 [INSTR_METER_IMM] = instr_meter_imm_exec,
7109 [INSTR_METER_IMI] = instr_meter_imi_exec,
7111 [INSTR_TABLE] = instr_table_exec,
7112 [INSTR_TABLE_AF] = instr_table_af_exec,
7113 [INSTR_SELECTOR] = instr_selector_exec,
7114 [INSTR_LEARNER] = instr_learner_exec,
7115 [INSTR_LEARNER_AF] = instr_learner_af_exec,
7116 [INSTR_LEARNER_LEARN] = instr_learn_exec,
7117 [INSTR_LEARNER_REARM] = instr_rearm_exec,
7118 [INSTR_LEARNER_REARM_NEW] = instr_rearm_new_exec,
7119 [INSTR_LEARNER_FORGET] = instr_forget_exec,
7120 [INSTR_EXTERN_OBJ] = instr_extern_obj_exec,
7121 [INSTR_EXTERN_FUNC] = instr_extern_func_exec,
7123 [INSTR_JMP] = instr_jmp_exec,
7124 [INSTR_JMP_VALID] = instr_jmp_valid_exec,
7125 [INSTR_JMP_INVALID] = instr_jmp_invalid_exec,
7126 [INSTR_JMP_HIT] = instr_jmp_hit_exec,
7127 [INSTR_JMP_MISS] = instr_jmp_miss_exec,
7128 [INSTR_JMP_ACTION_HIT] = instr_jmp_action_hit_exec,
7129 [INSTR_JMP_ACTION_MISS] = instr_jmp_action_miss_exec,
7131 [INSTR_JMP_EQ] = instr_jmp_eq_exec,
7132 [INSTR_JMP_EQ_MH] = instr_jmp_eq_mh_exec,
7133 [INSTR_JMP_EQ_HM] = instr_jmp_eq_hm_exec,
7134 [INSTR_JMP_EQ_HH] = instr_jmp_eq_hh_exec,
7135 [INSTR_JMP_EQ_I] = instr_jmp_eq_i_exec,
7137 [INSTR_JMP_NEQ] = instr_jmp_neq_exec,
7138 [INSTR_JMP_NEQ_MH] = instr_jmp_neq_mh_exec,
7139 [INSTR_JMP_NEQ_HM] = instr_jmp_neq_hm_exec,
7140 [INSTR_JMP_NEQ_HH] = instr_jmp_neq_hh_exec,
7141 [INSTR_JMP_NEQ_I] = instr_jmp_neq_i_exec,
7143 [INSTR_JMP_LT] = instr_jmp_lt_exec,
7144 [INSTR_JMP_LT_MH] = instr_jmp_lt_mh_exec,
7145 [INSTR_JMP_LT_HM] = instr_jmp_lt_hm_exec,
7146 [INSTR_JMP_LT_HH] = instr_jmp_lt_hh_exec,
7147 [INSTR_JMP_LT_MI] = instr_jmp_lt_mi_exec,
7148 [INSTR_JMP_LT_HI] = instr_jmp_lt_hi_exec,
7150 [INSTR_JMP_GT] = instr_jmp_gt_exec,
7151 [INSTR_JMP_GT_MH] = instr_jmp_gt_mh_exec,
7152 [INSTR_JMP_GT_HM] = instr_jmp_gt_hm_exec,
7153 [INSTR_JMP_GT_HH] = instr_jmp_gt_hh_exec,
7154 [INSTR_JMP_GT_MI] = instr_jmp_gt_mi_exec,
7155 [INSTR_JMP_GT_HI] = instr_jmp_gt_hi_exec,
7157 [INSTR_RETURN] = instr_return_exec,
7161 instruction_table_build(struct rte_swx_pipeline *p)
7163 p->instruction_table = calloc(RTE_SWX_PIPELINE_INSTRUCTION_TABLE_SIZE_MAX,
7164 sizeof(struct instr_exec_t *));
7165 if (!p->instruction_table)
7168 memcpy(p->instruction_table, instruction_table, sizeof(instruction_table));
7174 instruction_table_build_free(struct rte_swx_pipeline *p)
7176 if (!p->instruction_table)
7179 free(p->instruction_table);
7180 p->instruction_table = NULL;
7184 instruction_table_free(struct rte_swx_pipeline *p)
7186 instruction_table_build_free(p);
7190 instr_exec(struct rte_swx_pipeline *p)
7192 struct thread *t = &p->threads[p->thread_id];
7193 struct instruction *ip = t->ip;
7194 instr_exec_t instr = p->instruction_table[ip->type];
7202 static struct action *
7203 action_find(struct rte_swx_pipeline *p, const char *name)
7205 struct action *elem;
7210 TAILQ_FOREACH(elem, &p->actions, node)
7211 if (strcmp(elem->name, name) == 0)
7217 static struct action *
7218 action_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7220 struct action *action = NULL;
7222 TAILQ_FOREACH(action, &p->actions, node)
7223 if (action->id == id)
7229 static struct field *
7230 action_field_find(struct action *a, const char *name)
7232 return a->st ? struct_type_field_find(a->st, name) : NULL;
7235 static struct field *
7236 action_field_parse(struct action *action, const char *name)
7238 if (name[0] != 't' || name[1] != '.')
7241 return action_field_find(action, &name[2]);
7245 action_has_nbo_args(struct action *a)
7249 /* Return if the action does not have any args. */
7251 return 0; /* FALSE */
7253 for (i = 0; i < a->st->n_fields; i++)
7254 if (a->args_endianness[i])
7255 return 1; /* TRUE */
7257 return 0; /* FALSE */
7261 action_does_learning(struct action *a)
7265 for (i = 0; i < a->n_instructions; i++)
7266 switch (a->instructions[i].type) {
7267 case INSTR_LEARNER_LEARN:
7268 return 1; /* TRUE */
7270 case INSTR_LEARNER_FORGET:
7271 return 1; /* TRUE */
7277 return 0; /* FALSE */
7281 rte_swx_pipeline_action_config(struct rte_swx_pipeline *p,
7283 const char *args_struct_type_name,
7284 const char **instructions,
7285 uint32_t n_instructions)
7287 struct struct_type *args_struct_type = NULL;
7288 struct action *a = NULL;
7293 CHECK_NAME(name, EINVAL);
7294 CHECK(!action_find(p, name), EEXIST);
7296 if (args_struct_type_name) {
7297 CHECK_NAME(args_struct_type_name, EINVAL);
7298 args_struct_type = struct_type_find(p, args_struct_type_name);
7299 CHECK(args_struct_type, EINVAL);
7300 CHECK(!args_struct_type->var_size, EINVAL);
7303 /* Node allocation. */
7304 a = calloc(1, sizeof(struct action));
7310 if (args_struct_type) {
7311 a->args_endianness = calloc(args_struct_type->n_fields, sizeof(int));
7312 if (!a->args_endianness) {
7318 /* Node initialization. */
7319 strcpy(a->name, name);
7320 a->st = args_struct_type;
7321 a->id = p->n_actions;
7323 /* Instruction translation. */
7324 status = instruction_config(p, a, instructions, n_instructions);
7328 /* Node add to tailq. */
7329 TAILQ_INSERT_TAIL(&p->actions, a, node);
7338 free(a->args_endianness);
7339 free(a->instructions);
7340 free(a->instruction_data);
7347 action_build(struct rte_swx_pipeline *p)
7349 struct action *action;
7351 /* p->action_instructions. */
7352 p->action_instructions = calloc(p->n_actions, sizeof(struct instruction *));
7353 CHECK(p->action_instructions, ENOMEM);
7355 TAILQ_FOREACH(action, &p->actions, node)
7356 p->action_instructions[action->id] = action->instructions;
7358 /* p->action_funcs. */
7359 p->action_funcs = calloc(p->n_actions, sizeof(action_func_t));
7360 CHECK(p->action_funcs, ENOMEM);
7366 action_build_free(struct rte_swx_pipeline *p)
7368 free(p->action_funcs);
7369 p->action_funcs = NULL;
7371 free(p->action_instructions);
7372 p->action_instructions = NULL;
7376 action_free(struct rte_swx_pipeline *p)
7378 action_build_free(p);
7381 struct action *action;
7383 action = TAILQ_FIRST(&p->actions);
7387 TAILQ_REMOVE(&p->actions, action, node);
7388 free(action->args_endianness);
7389 free(action->instructions);
7390 free(action->instruction_data);
7396 action_arg_src_mov_count(struct action *a,
7398 struct instruction *instructions,
7399 struct instruction_data *instruction_data,
7400 uint32_t n_instructions)
7402 uint32_t offset, n_users = 0, i;
7405 (arg_id >= a->st->n_fields) ||
7407 !instruction_data ||
7411 offset = a->st->fields[arg_id].offset / 8;
7413 for (i = 0; i < n_instructions; i++) {
7414 struct instruction *instr = &instructions[i];
7415 struct instruction_data *data = &instruction_data[i];
7417 if (data->invalid ||
7418 ((instr->type != INSTR_MOV) && (instr->type != INSTR_MOV_HM)) ||
7419 instr->mov.src.struct_id ||
7420 (instr->mov.src.offset != offset))
7429 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
7430 #define field_ntoh(val, n_bits) (ntoh64((val) << (64 - n_bits)))
7431 #define field_hton(val, n_bits) (hton64((val) << (64 - n_bits)))
7433 #define field_ntoh(val, n_bits) (val)
7434 #define field_hton(val, n_bits) (val)
7437 #define ACTION_ARGS_TOKENS_MAX 256
7440 action_args_parse(struct action *a, const char *args, uint8_t *data)
7442 char *tokens[ACTION_ARGS_TOKENS_MAX], *s0 = NULL, *s;
7443 uint32_t n_tokens = 0, offset = 0, i;
7447 if (!a->st || !args || !args[0]) {
7452 /* Memory allocation. */
7459 /* Parse the string into tokens. */
7463 token = strtok_r(s, " \f\n\r\t\v", &s);
7467 if (n_tokens >= RTE_DIM(tokens)) {
7472 tokens[n_tokens] = token;
7477 if (n_tokens != a->st->n_fields * 2) {
7482 /* Process the action arguments. */
7483 for (i = 0; i < a->st->n_fields; i++) {
7484 struct field *f = &a->st->fields[i];
7485 char *arg_name = tokens[i * 2];
7486 char *arg_val = tokens[i * 2 + 1];
7489 if (strcmp(arg_name, f->name)) {
7494 val = strtoull(arg_val, &arg_val, 0);
7500 /* Endianness conversion. */
7501 if (a->args_endianness[i])
7502 val = field_hton(val, f->n_bits);
7504 /* Copy to entry. */
7505 memcpy(&data[offset], (uint8_t *)&val, f->n_bits / 8);
7506 offset += f->n_bits / 8;
7517 static struct table_type *
7518 table_type_find(struct rte_swx_pipeline *p, const char *name)
7520 struct table_type *elem;
7522 TAILQ_FOREACH(elem, &p->table_types, node)
7523 if (strcmp(elem->name, name) == 0)
7529 static struct table_type *
7530 table_type_resolve(struct rte_swx_pipeline *p,
7531 const char *recommended_type_name,
7532 enum rte_swx_table_match_type match_type)
7534 struct table_type *elem;
7536 /* Only consider the recommended type if the match type is correct. */
7537 if (recommended_type_name)
7538 TAILQ_FOREACH(elem, &p->table_types, node)
7539 if (!strcmp(elem->name, recommended_type_name) &&
7540 (elem->match_type == match_type))
7543 /* Ignore the recommended type and get the first element with this match
7546 TAILQ_FOREACH(elem, &p->table_types, node)
7547 if (elem->match_type == match_type)
7553 static struct table *
7554 table_find(struct rte_swx_pipeline *p, const char *name)
7558 TAILQ_FOREACH(elem, &p->tables, node)
7559 if (strcmp(elem->name, name) == 0)
7565 static struct table *
7566 table_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7568 struct table *table = NULL;
7570 TAILQ_FOREACH(table, &p->tables, node)
7571 if (table->id == id)
7578 rte_swx_pipeline_table_type_register(struct rte_swx_pipeline *p,
7580 enum rte_swx_table_match_type match_type,
7581 struct rte_swx_table_ops *ops)
7583 struct table_type *elem;
7587 CHECK_NAME(name, EINVAL);
7588 CHECK(!table_type_find(p, name), EEXIST);
7591 CHECK(ops->create, EINVAL);
7592 CHECK(ops->lkp, EINVAL);
7593 CHECK(ops->free, EINVAL);
7595 /* Node allocation. */
7596 elem = calloc(1, sizeof(struct table_type));
7597 CHECK(elem, ENOMEM);
7599 /* Node initialization. */
7600 strcpy(elem->name, name);
7601 elem->match_type = match_type;
7602 memcpy(&elem->ops, ops, sizeof(*ops));
7604 /* Node add to tailq. */
7605 TAILQ_INSERT_TAIL(&p->table_types, elem, node);
7611 table_match_type_resolve(struct rte_swx_match_field_params *fields,
7613 enum rte_swx_table_match_type *match_type)
7615 uint32_t n_fields_em = 0, n_fields_lpm = 0, i;
7617 for (i = 0; i < n_fields; i++) {
7618 struct rte_swx_match_field_params *f = &fields[i];
7620 if (f->match_type == RTE_SWX_TABLE_MATCH_EXACT)
7623 if (f->match_type == RTE_SWX_TABLE_MATCH_LPM)
7627 if ((n_fields_lpm > 1) ||
7628 (n_fields_lpm && (n_fields_em != n_fields - 1)))
7631 *match_type = (n_fields_em == n_fields) ?
7632 RTE_SWX_TABLE_MATCH_EXACT :
7633 RTE_SWX_TABLE_MATCH_WILDCARD;
7639 table_match_fields_check(struct rte_swx_pipeline *p,
7640 struct rte_swx_pipeline_table_params *params,
7641 struct header **header)
7643 struct header *h0 = NULL;
7644 struct field *hf, *mf;
7645 uint32_t *offset = NULL, i;
7648 /* Return if no match fields. */
7649 if (!params->n_fields) {
7650 if (params->fields) {
7661 /* Memory allocation. */
7662 offset = calloc(params->n_fields, sizeof(uint32_t));
7668 /* Check that all the match fields belong to either the same header or
7671 hf = header_field_parse(p, params->fields[0].name, &h0);
7672 mf = metadata_field_parse(p, params->fields[0].name);
7673 if ((!hf && !mf) || (hf && hf->var_size)) {
7678 offset[0] = h0 ? hf->offset : mf->offset;
7680 for (i = 1; i < params->n_fields; i++)
7684 hf = header_field_parse(p, params->fields[i].name, &h);
7685 if (!hf || (h->id != h0->id) || hf->var_size) {
7690 offset[i] = hf->offset;
7692 mf = metadata_field_parse(p, params->fields[i].name);
7698 offset[i] = mf->offset;
7701 /* Check that there are no duplicated match fields. */
7702 for (i = 0; i < params->n_fields; i++) {
7705 for (j = 0; j < i; j++)
7706 if (offset[j] == offset[i]) {
7722 rte_swx_pipeline_table_config(struct rte_swx_pipeline *p,
7724 struct rte_swx_pipeline_table_params *params,
7725 const char *recommended_table_type_name,
7729 struct table_type *type;
7730 struct table *t = NULL;
7731 struct action *default_action;
7732 struct header *header = NULL;
7733 uint32_t action_data_size_max = 0, i;
7738 CHECK_NAME(name, EINVAL);
7739 CHECK(!table_find(p, name), EEXIST);
7740 CHECK(!selector_find(p, name), EEXIST);
7741 CHECK(!learner_find(p, name), EEXIST);
7743 CHECK(params, EINVAL);
7746 status = table_match_fields_check(p, params, &header);
7750 /* Action checks. */
7751 CHECK(params->n_actions, EINVAL);
7752 CHECK(params->action_names, EINVAL);
7753 for (i = 0; i < params->n_actions; i++) {
7754 const char *action_name = params->action_names[i];
7756 uint32_t action_data_size;
7757 int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
7759 CHECK_NAME(action_name, EINVAL);
7761 a = action_find(p, action_name);
7763 CHECK(!action_does_learning(a), EINVAL);
7765 action_data_size = a->st ? a->st->n_bits / 8 : 0;
7766 if (action_data_size > action_data_size_max)
7767 action_data_size_max = action_data_size;
7769 if (params->action_is_for_table_entries)
7770 action_is_for_table_entries = params->action_is_for_table_entries[i];
7771 if (params->action_is_for_default_entry)
7772 action_is_for_default_entry = params->action_is_for_default_entry[i];
7773 CHECK(action_is_for_table_entries || action_is_for_default_entry, EINVAL);
7776 CHECK_NAME(params->default_action_name, EINVAL);
7777 for (i = 0; i < p->n_actions; i++)
7778 if (!strcmp(params->action_names[i],
7779 params->default_action_name))
7781 CHECK(i < params->n_actions, EINVAL);
7782 CHECK(!params->action_is_for_default_entry || params->action_is_for_default_entry[i],
7785 default_action = action_find(p, params->default_action_name);
7786 CHECK((default_action->st && params->default_action_args) || !params->default_action_args,
7789 /* Table type checks. */
7790 if (recommended_table_type_name)
7791 CHECK_NAME(recommended_table_type_name, EINVAL);
7793 if (params->n_fields) {
7794 enum rte_swx_table_match_type match_type;
7796 status = table_match_type_resolve(params->fields, params->n_fields, &match_type);
7800 type = table_type_resolve(p, recommended_table_type_name, match_type);
7801 CHECK(type, EINVAL);
7806 /* Memory allocation. */
7807 t = calloc(1, sizeof(struct table));
7813 t->fields = calloc(params->n_fields, sizeof(struct match_field));
7819 t->actions = calloc(params->n_actions, sizeof(struct action *));
7825 if (action_data_size_max) {
7826 t->default_action_data = calloc(1, action_data_size_max);
7827 if (!t->default_action_data) {
7833 t->action_is_for_table_entries = calloc(params->n_actions, sizeof(int));
7834 if (!t->action_is_for_table_entries) {
7839 t->action_is_for_default_entry = calloc(params->n_actions, sizeof(int));
7840 if (!t->action_is_for_default_entry) {
7845 /* Node initialization. */
7846 strcpy(t->name, name);
7847 if (args && args[0])
7848 strcpy(t->args, args);
7851 for (i = 0; i < params->n_fields; i++) {
7852 struct rte_swx_match_field_params *field = ¶ms->fields[i];
7853 struct match_field *f = &t->fields[i];
7855 f->match_type = field->match_type;
7857 header_field_parse(p, field->name, NULL) :
7858 metadata_field_parse(p, field->name);
7860 t->n_fields = params->n_fields;
7863 for (i = 0; i < params->n_actions; i++) {
7864 int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
7866 if (params->action_is_for_table_entries)
7867 action_is_for_table_entries = params->action_is_for_table_entries[i];
7868 if (params->action_is_for_default_entry)
7869 action_is_for_default_entry = params->action_is_for_default_entry[i];
7871 t->actions[i] = action_find(p, params->action_names[i]);
7872 t->action_is_for_table_entries[i] = action_is_for_table_entries;
7873 t->action_is_for_default_entry[i] = action_is_for_default_entry;
7875 t->default_action = default_action;
7876 if (default_action->st) {
7877 status = action_args_parse(default_action,
7878 params->default_action_args,
7879 t->default_action_data);
7884 t->n_actions = params->n_actions;
7885 t->default_action_is_const = params->default_action_is_const;
7886 t->action_data_size_max = action_data_size_max;
7889 t->id = p->n_tables;
7891 /* Node add to tailq. */
7892 TAILQ_INSERT_TAIL(&p->tables, t, node);
7901 free(t->action_is_for_default_entry);
7902 free(t->action_is_for_table_entries);
7903 free(t->default_action_data);
7911 static struct rte_swx_table_params *
7912 table_params_get(struct table *table)
7914 struct rte_swx_table_params *params;
7915 struct field *first, *last;
7917 uint32_t key_size, key_offset, action_data_size, i;
7919 /* Memory allocation. */
7920 params = calloc(1, sizeof(struct rte_swx_table_params));
7924 /* Find first (smallest offset) and last (biggest offset) match fields. */
7925 first = table->fields[0].field;
7926 last = table->fields[0].field;
7928 for (i = 0; i < table->n_fields; i++) {
7929 struct field *f = table->fields[i].field;
7931 if (f->offset < first->offset)
7934 if (f->offset > last->offset)
7938 /* Key offset and size. */
7939 key_offset = first->offset / 8;
7940 key_size = (last->offset + last->n_bits - first->offset) / 8;
7942 /* Memory allocation. */
7943 key_mask = calloc(1, key_size);
7950 for (i = 0; i < table->n_fields; i++) {
7951 struct field *f = table->fields[i].field;
7952 uint32_t start = (f->offset - first->offset) / 8;
7953 size_t size = f->n_bits / 8;
7955 memset(&key_mask[start], 0xFF, size);
7958 /* Action data size. */
7959 action_data_size = 0;
7960 for (i = 0; i < table->n_actions; i++) {
7961 struct action *action = table->actions[i];
7962 uint32_t ads = action->st ? action->st->n_bits / 8 : 0;
7964 if (ads > action_data_size)
7965 action_data_size = ads;
7969 params->match_type = table->type->match_type;
7970 params->key_size = key_size;
7971 params->key_offset = key_offset;
7972 params->key_mask0 = key_mask;
7973 params->action_data_size = action_data_size;
7974 params->n_keys_max = table->size;
7980 table_params_free(struct rte_swx_table_params *params)
7985 free(params->key_mask0);
7990 table_stub_lkp(void *table __rte_unused,
7991 void *mailbox __rte_unused,
7992 uint8_t **key __rte_unused,
7993 uint64_t *action_id __rte_unused,
7994 uint8_t **action_data __rte_unused,
7998 return 1; /* DONE. */
8002 table_build(struct rte_swx_pipeline *p)
8006 /* Per pipeline: table statistics. */
8007 p->table_stats = calloc(p->n_tables, sizeof(struct table_statistics));
8008 CHECK(p->table_stats, ENOMEM);
8010 for (i = 0; i < p->n_tables; i++) {
8011 p->table_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
8012 CHECK(p->table_stats[i].n_pkts_action, ENOMEM);
8015 /* Per thread: table runt-time. */
8016 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8017 struct thread *t = &p->threads[i];
8018 struct table *table;
8020 t->tables = calloc(p->n_tables, sizeof(struct table_runtime));
8021 CHECK(t->tables, ENOMEM);
8023 TAILQ_FOREACH(table, &p->tables, node) {
8024 struct table_runtime *r = &t->tables[table->id];
8029 size = table->type->ops.mailbox_size_get();
8032 r->func = table->type->ops.lkp;
8036 r->mailbox = calloc(1, size);
8037 CHECK(r->mailbox, ENOMEM);
8041 r->key = table->header ?
8042 &t->structs[table->header->struct_id] :
8043 &t->structs[p->metadata_struct_id];
8045 r->func = table_stub_lkp;
8054 table_build_free(struct rte_swx_pipeline *p)
8058 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8059 struct thread *t = &p->threads[i];
8065 for (j = 0; j < p->n_tables; j++) {
8066 struct table_runtime *r = &t->tables[j];
8075 if (p->table_stats) {
8076 for (i = 0; i < p->n_tables; i++)
8077 free(p->table_stats[i].n_pkts_action);
8079 free(p->table_stats);
8084 table_free(struct rte_swx_pipeline *p)
8086 table_build_free(p);
8092 elem = TAILQ_FIRST(&p->tables);
8096 TAILQ_REMOVE(&p->tables, elem, node);
8098 free(elem->actions);
8099 free(elem->default_action_data);
8105 struct table_type *elem;
8107 elem = TAILQ_FIRST(&p->table_types);
8111 TAILQ_REMOVE(&p->table_types, elem, node);
8119 static struct selector *
8120 selector_find(struct rte_swx_pipeline *p, const char *name)
8124 TAILQ_FOREACH(s, &p->selectors, node)
8125 if (strcmp(s->name, name) == 0)
8131 static struct selector *
8132 selector_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8134 struct selector *s = NULL;
8136 TAILQ_FOREACH(s, &p->selectors, node)
8144 selector_fields_check(struct rte_swx_pipeline *p,
8145 struct rte_swx_pipeline_selector_params *params,
8146 struct header **header)
8148 struct header *h0 = NULL;
8149 struct field *hf, *mf;
8152 /* Return if no selector fields. */
8153 if (!params->n_selector_fields || !params->selector_field_names)
8156 /* Check that all the selector fields either belong to the same header
8157 * or are all meta-data fields.
8159 hf = header_field_parse(p, params->selector_field_names[0], &h0);
8160 mf = metadata_field_parse(p, params->selector_field_names[0]);
8164 for (i = 1; i < params->n_selector_fields; i++)
8168 hf = header_field_parse(p, params->selector_field_names[i], &h);
8169 if (!hf || (h->id != h0->id))
8172 mf = metadata_field_parse(p, params->selector_field_names[i]);
8177 /* Check that there are no duplicated match fields. */
8178 for (i = 0; i < params->n_selector_fields; i++) {
8179 const char *field_name = params->selector_field_names[i];
8182 for (j = i + 1; j < params->n_selector_fields; j++)
8183 if (!strcmp(params->selector_field_names[j], field_name))
8195 rte_swx_pipeline_selector_config(struct rte_swx_pipeline *p,
8197 struct rte_swx_pipeline_selector_params *params)
8200 struct header *selector_header = NULL;
8201 struct field *group_id_field, *member_id_field;
8207 CHECK_NAME(name, EINVAL);
8208 CHECK(!table_find(p, name), EEXIST);
8209 CHECK(!selector_find(p, name), EEXIST);
8210 CHECK(!learner_find(p, name), EEXIST);
8212 CHECK(params, EINVAL);
8214 CHECK_NAME(params->group_id_field_name, EINVAL);
8215 group_id_field = metadata_field_parse(p, params->group_id_field_name);
8216 CHECK(group_id_field, EINVAL);
8218 for (i = 0; i < params->n_selector_fields; i++) {
8219 const char *field_name = params->selector_field_names[i];
8221 CHECK_NAME(field_name, EINVAL);
8223 status = selector_fields_check(p, params, &selector_header);
8227 CHECK_NAME(params->member_id_field_name, EINVAL);
8228 member_id_field = metadata_field_parse(p, params->member_id_field_name);
8229 CHECK(member_id_field, EINVAL);
8231 CHECK(params->n_groups_max, EINVAL);
8233 CHECK(params->n_members_per_group_max, EINVAL);
8235 /* Memory allocation. */
8236 s = calloc(1, sizeof(struct selector));
8242 s->selector_fields = calloc(params->n_selector_fields, sizeof(struct field *));
8243 if (!s->selector_fields) {
8248 /* Node initialization. */
8249 strcpy(s->name, name);
8251 s->group_id_field = group_id_field;
8253 for (i = 0; i < params->n_selector_fields; i++) {
8254 const char *field_name = params->selector_field_names[i];
8256 s->selector_fields[i] = selector_header ?
8257 header_field_parse(p, field_name, NULL) :
8258 metadata_field_parse(p, field_name);
8261 s->n_selector_fields = params->n_selector_fields;
8263 s->selector_header = selector_header;
8265 s->member_id_field = member_id_field;
8267 s->n_groups_max = params->n_groups_max;
8269 s->n_members_per_group_max = params->n_members_per_group_max;
8271 s->id = p->n_selectors;
8273 /* Node add to tailq. */
8274 TAILQ_INSERT_TAIL(&p->selectors, s, node);
8283 free(s->selector_fields);
8291 selector_params_free(struct rte_swx_table_selector_params *params)
8296 free(params->selector_mask);
8301 static struct rte_swx_table_selector_params *
8302 selector_table_params_get(struct selector *s)
8304 struct rte_swx_table_selector_params *params = NULL;
8305 struct field *first, *last;
8308 /* Memory allocation. */
8309 params = calloc(1, sizeof(struct rte_swx_table_selector_params));
8314 params->group_id_offset = s->group_id_field->offset / 8;
8316 /* Find first (smallest offset) and last (biggest offset) selector fields. */
8317 first = s->selector_fields[0];
8318 last = s->selector_fields[0];
8320 for (i = 0; i < s->n_selector_fields; i++) {
8321 struct field *f = s->selector_fields[i];
8323 if (f->offset < first->offset)
8326 if (f->offset > last->offset)
8330 /* Selector offset and size. */
8331 params->selector_offset = first->offset / 8;
8332 params->selector_size = (last->offset + last->n_bits - first->offset) / 8;
8334 /* Memory allocation. */
8335 params->selector_mask = calloc(1, params->selector_size);
8336 if (!params->selector_mask)
8339 /* Selector mask. */
8340 for (i = 0; i < s->n_selector_fields; i++) {
8341 struct field *f = s->selector_fields[i];
8342 uint32_t start = (f->offset - first->offset) / 8;
8343 size_t size = f->n_bits / 8;
8345 memset(¶ms->selector_mask[start], 0xFF, size);
8349 params->member_id_offset = s->member_id_field->offset / 8;
8351 /* Maximum number of groups. */
8352 params->n_groups_max = s->n_groups_max;
8354 /* Maximum number of members per group. */
8355 params->n_members_per_group_max = s->n_members_per_group_max;
8360 selector_params_free(params);
8365 selector_build_free(struct rte_swx_pipeline *p)
8369 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8370 struct thread *t = &p->threads[i];
8376 for (j = 0; j < p->n_selectors; j++) {
8377 struct selector_runtime *r = &t->selectors[j];
8383 t->selectors = NULL;
8386 free(p->selector_stats);
8387 p->selector_stats = NULL;
8391 selector_build(struct rte_swx_pipeline *p)
8396 /* Per pipeline: selector statistics. */
8397 p->selector_stats = calloc(p->n_selectors, sizeof(struct selector_statistics));
8398 if (!p->selector_stats) {
8403 /* Per thread: selector run-time. */
8404 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8405 struct thread *t = &p->threads[i];
8408 t->selectors = calloc(p->n_selectors, sizeof(struct selector_runtime));
8409 if (!t->selectors) {
8414 TAILQ_FOREACH(s, &p->selectors, node) {
8415 struct selector_runtime *r = &t->selectors[s->id];
8419 size = rte_swx_table_selector_mailbox_size_get();
8421 r->mailbox = calloc(1, size);
8428 /* r->group_id_buffer. */
8429 r->group_id_buffer = &t->structs[p->metadata_struct_id];
8431 /* r->selector_buffer. */
8432 r->selector_buffer = s->selector_header ?
8433 &t->structs[s->selector_header->struct_id] :
8434 &t->structs[p->metadata_struct_id];
8436 /* r->member_id_buffer. */
8437 r->member_id_buffer = &t->structs[p->metadata_struct_id];
8444 selector_build_free(p);
8449 selector_free(struct rte_swx_pipeline *p)
8451 selector_build_free(p);
8453 /* Selector tables. */
8455 struct selector *elem;
8457 elem = TAILQ_FIRST(&p->selectors);
8461 TAILQ_REMOVE(&p->selectors, elem, node);
8462 free(elem->selector_fields);
8470 static struct learner *
8471 learner_find(struct rte_swx_pipeline *p, const char *name)
8475 TAILQ_FOREACH(l, &p->learners, node)
8476 if (!strcmp(l->name, name))
8482 static struct learner *
8483 learner_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8485 struct learner *l = NULL;
8487 TAILQ_FOREACH(l, &p->learners, node)
8495 learner_match_fields_check(struct rte_swx_pipeline *p,
8496 struct rte_swx_pipeline_learner_params *params,
8497 struct header **header)
8499 struct header *h0 = NULL;
8500 struct field *hf, *mf;
8503 /* Return if no match fields. */
8504 if (!params->n_fields || !params->field_names)
8507 /* Check that all the match fields either belong to the same header
8508 * or are all meta-data fields.
8510 hf = header_field_parse(p, params->field_names[0], &h0);
8511 mf = metadata_field_parse(p, params->field_names[0]);
8515 for (i = 1; i < params->n_fields; i++)
8519 hf = header_field_parse(p, params->field_names[i], &h);
8520 if (!hf || (h->id != h0->id))
8523 mf = metadata_field_parse(p, params->field_names[i]);
8528 /* Check that there are no duplicated match fields. */
8529 for (i = 0; i < params->n_fields; i++) {
8530 const char *field_name = params->field_names[i];
8533 for (j = i + 1; j < params->n_fields; j++)
8534 if (!strcmp(params->field_names[j], field_name))
8546 learner_action_args_check(struct rte_swx_pipeline *p, struct action *a, const char *mf_name)
8548 struct struct_type *mst = p->metadata_st, *ast = a->st;
8549 struct field *mf, *af;
8559 /* Check that mf_name is the name of a valid meta-data field. */
8560 CHECK_NAME(mf_name, EINVAL);
8561 mf = metadata_field_parse(p, mf_name);
8564 /* Check that there are enough meta-data fields, starting with the mf_name field, to cover
8565 * all the action arguments.
8567 mf_pos = mf - mst->fields;
8568 CHECK(mst->n_fields - mf_pos >= ast->n_fields, EINVAL);
8570 /* Check that the size of each of the identified meta-data fields matches exactly the size
8571 * of the corresponding action argument.
8573 for (i = 0; i < ast->n_fields; i++) {
8574 mf = &mst->fields[mf_pos + i];
8575 af = &ast->fields[i];
8577 CHECK(mf->n_bits == af->n_bits, EINVAL);
8584 learner_action_learning_check(struct rte_swx_pipeline *p,
8585 struct action *action,
8586 const char **action_names,
8591 /* For each "learn" instruction of the current action, check that the learned action (i.e.
8592 * the action passed as argument to the "learn" instruction) is also enabled for the
8593 * current learner table.
8595 for (i = 0; i < action->n_instructions; i++) {
8596 struct instruction *instr = &action->instructions[i];
8597 uint32_t found = 0, j;
8599 if (instr->type != INSTR_LEARNER_LEARN)
8602 for (j = 0; j < n_actions; j++) {
8605 a = action_find(p, action_names[j]);
8609 if (a->id == instr->learn.action_id)
8621 rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p,
8623 struct rte_swx_pipeline_learner_params *params,
8626 uint32_t n_timeouts)
8628 struct learner *l = NULL;
8629 struct action *default_action;
8630 struct header *header = NULL;
8631 uint32_t action_data_size_max = 0, i;
8636 CHECK_NAME(name, EINVAL);
8637 CHECK(!table_find(p, name), EEXIST);
8638 CHECK(!selector_find(p, name), EEXIST);
8639 CHECK(!learner_find(p, name), EEXIST);
8641 CHECK(params, EINVAL);
8644 status = learner_match_fields_check(p, params, &header);
8648 /* Action checks. */
8649 CHECK(params->n_actions, EINVAL);
8650 CHECK(params->action_names, EINVAL);
8651 for (i = 0; i < params->n_actions; i++) {
8652 const char *action_name = params->action_names[i];
8654 uint32_t action_data_size;
8655 int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
8657 CHECK_NAME(action_name, EINVAL);
8659 a = action_find(p, action_name);
8662 status = learner_action_learning_check(p,
8664 params->action_names,
8669 action_data_size = a->st ? a->st->n_bits / 8 : 0;
8670 if (action_data_size > action_data_size_max)
8671 action_data_size_max = action_data_size;
8673 if (params->action_is_for_table_entries)
8674 action_is_for_table_entries = params->action_is_for_table_entries[i];
8675 if (params->action_is_for_default_entry)
8676 action_is_for_default_entry = params->action_is_for_default_entry[i];
8677 CHECK(action_is_for_table_entries || action_is_for_default_entry, EINVAL);
8680 CHECK_NAME(params->default_action_name, EINVAL);
8681 for (i = 0; i < p->n_actions; i++)
8682 if (!strcmp(params->action_names[i],
8683 params->default_action_name))
8685 CHECK(i < params->n_actions, EINVAL);
8686 CHECK(!params->action_is_for_default_entry || params->action_is_for_default_entry[i],
8689 default_action = action_find(p, params->default_action_name);
8690 CHECK((default_action->st && params->default_action_args) || !params->default_action_args,
8693 /* Any other checks. */
8694 CHECK(size, EINVAL);
8695 CHECK(timeout, EINVAL);
8696 CHECK(n_timeouts && (n_timeouts < RTE_SWX_TABLE_LEARNER_N_KEY_TIMEOUTS_MAX), EINVAL);
8698 /* Memory allocation. */
8699 l = calloc(1, sizeof(struct learner));
8705 l->fields = calloc(params->n_fields, sizeof(struct field *));
8711 l->actions = calloc(params->n_actions, sizeof(struct action *));
8717 if (action_data_size_max) {
8718 l->default_action_data = calloc(1, action_data_size_max);
8719 if (!l->default_action_data) {
8725 l->action_is_for_table_entries = calloc(params->n_actions, sizeof(int));
8726 if (!l->action_is_for_table_entries) {
8731 l->action_is_for_default_entry = calloc(params->n_actions, sizeof(int));
8732 if (!l->action_is_for_default_entry) {
8737 /* Node initialization. */
8738 strcpy(l->name, name);
8740 for (i = 0; i < params->n_fields; i++) {
8741 const char *field_name = params->field_names[i];
8743 l->fields[i] = header ?
8744 header_field_parse(p, field_name, NULL) :
8745 metadata_field_parse(p, field_name);
8748 l->n_fields = params->n_fields;
8752 for (i = 0; i < params->n_actions; i++) {
8753 int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
8755 if (params->action_is_for_table_entries)
8756 action_is_for_table_entries = params->action_is_for_table_entries[i];
8757 if (params->action_is_for_default_entry)
8758 action_is_for_default_entry = params->action_is_for_default_entry[i];
8760 l->actions[i] = action_find(p, params->action_names[i]);
8761 l->action_is_for_table_entries[i] = action_is_for_table_entries;
8762 l->action_is_for_default_entry[i] = action_is_for_default_entry;
8765 l->default_action = default_action;
8767 if (default_action->st) {
8768 status = action_args_parse(default_action,
8769 params->default_action_args,
8770 l->default_action_data);
8775 l->n_actions = params->n_actions;
8777 l->default_action_is_const = params->default_action_is_const;
8779 l->action_data_size_max = action_data_size_max;
8783 for (i = 0; i < n_timeouts; i++)
8784 l->timeout[i] = timeout[i];
8786 l->n_timeouts = n_timeouts;
8788 l->id = p->n_learners;
8790 /* Node add to tailq. */
8791 TAILQ_INSERT_TAIL(&p->learners, l, node);
8800 free(l->action_is_for_default_entry);
8801 free(l->action_is_for_table_entries);
8802 free(l->default_action_data);
8811 learner_params_free(struct rte_swx_table_learner_params *params)
8816 free(params->key_mask0);
8818 free(params->key_timeout);
8823 static struct rte_swx_table_learner_params *
8824 learner_params_get(struct learner *l)
8826 struct rte_swx_table_learner_params *params = NULL;
8827 struct field *first, *last;
8830 /* Memory allocation. */
8831 params = calloc(1, sizeof(struct rte_swx_table_learner_params));
8835 /* Find first (smallest offset) and last (biggest offset) match fields. */
8836 first = l->fields[0];
8837 last = l->fields[0];
8839 for (i = 0; i < l->n_fields; i++) {
8840 struct field *f = l->fields[i];
8842 if (f->offset < first->offset)
8845 if (f->offset > last->offset)
8849 /* Key offset and size. */
8850 params->key_offset = first->offset / 8;
8851 params->key_size = (last->offset + last->n_bits - first->offset) / 8;
8853 /* Memory allocation. */
8854 params->key_mask0 = calloc(1, params->key_size);
8855 if (!params->key_mask0)
8859 for (i = 0; i < l->n_fields; i++) {
8860 struct field *f = l->fields[i];
8861 uint32_t start = (f->offset - first->offset) / 8;
8862 size_t size = f->n_bits / 8;
8864 memset(¶ms->key_mask0[start], 0xFF, size);
8867 /* Action data size. */
8868 params->action_data_size = l->action_data_size_max;
8870 /* Maximum number of keys. */
8871 params->n_keys_max = l->size;
8873 /* Memory allocation. */
8874 params->key_timeout = calloc(l->n_timeouts, sizeof(uint32_t));
8875 if (!params->key_timeout)
8879 for (i = 0; i < l->n_timeouts; i++)
8880 params->key_timeout[i] = l->timeout[i];
8882 params->n_key_timeouts = l->n_timeouts;
8887 learner_params_free(params);
8892 learner_build_free(struct rte_swx_pipeline *p)
8896 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8897 struct thread *t = &p->threads[i];
8903 for (j = 0; j < p->n_learners; j++) {
8904 struct learner_runtime *r = &t->learners[j];
8913 if (p->learner_stats) {
8914 for (i = 0; i < p->n_learners; i++)
8915 free(p->learner_stats[i].n_pkts_action);
8917 free(p->learner_stats);
8922 learner_build(struct rte_swx_pipeline *p)
8927 /* Per pipeline: learner statistics. */
8928 p->learner_stats = calloc(p->n_learners, sizeof(struct learner_statistics));
8929 CHECK(p->learner_stats, ENOMEM);
8931 for (i = 0; i < p->n_learners; i++) {
8932 p->learner_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
8933 CHECK(p->learner_stats[i].n_pkts_action, ENOMEM);
8936 /* Per thread: learner run-time. */
8937 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8938 struct thread *t = &p->threads[i];
8941 t->learners = calloc(p->n_learners, sizeof(struct learner_runtime));
8947 TAILQ_FOREACH(l, &p->learners, node) {
8948 struct learner_runtime *r = &t->learners[l->id];
8952 size = rte_swx_table_learner_mailbox_size_get();
8954 r->mailbox = calloc(1, size);
8962 r->key = l->header ?
8963 &t->structs[l->header->struct_id] :
8964 &t->structs[p->metadata_struct_id];
8971 learner_build_free(p);
8976 learner_free(struct rte_swx_pipeline *p)
8978 learner_build_free(p);
8980 /* Learner tables. */
8984 l = TAILQ_FIRST(&p->learners);
8988 TAILQ_REMOVE(&p->learners, l, node);
8991 free(l->default_action_data);
9000 table_state_build(struct rte_swx_pipeline *p)
9002 struct table *table;
9006 p->table_state = calloc(p->n_tables + p->n_selectors + p->n_learners,
9007 sizeof(struct rte_swx_table_state));
9008 CHECK(p->table_state, ENOMEM);
9010 TAILQ_FOREACH(table, &p->tables, node) {
9011 struct rte_swx_table_state *ts = &p->table_state[table->id];
9014 struct rte_swx_table_params *params;
9017 params = table_params_get(table);
9018 CHECK(params, ENOMEM);
9020 ts->obj = table->type->ops.create(params,
9025 table_params_free(params);
9026 CHECK(ts->obj, ENODEV);
9029 /* ts->default_action_data. */
9030 if (table->action_data_size_max) {
9031 ts->default_action_data =
9032 malloc(table->action_data_size_max);
9033 CHECK(ts->default_action_data, ENOMEM);
9035 memcpy(ts->default_action_data,
9036 table->default_action_data,
9037 table->action_data_size_max);
9040 /* ts->default_action_id. */
9041 ts->default_action_id = table->default_action->id;
9044 TAILQ_FOREACH(s, &p->selectors, node) {
9045 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + s->id];
9046 struct rte_swx_table_selector_params *params;
9049 params = selector_table_params_get(s);
9050 CHECK(params, ENOMEM);
9052 ts->obj = rte_swx_table_selector_create(params, NULL, p->numa_node);
9054 selector_params_free(params);
9055 CHECK(ts->obj, ENODEV);
9058 TAILQ_FOREACH(l, &p->learners, node) {
9059 struct rte_swx_table_state *ts = &p->table_state[p->n_tables +
9060 p->n_selectors + l->id];
9061 struct rte_swx_table_learner_params *params;
9064 params = learner_params_get(l);
9065 CHECK(params, ENOMEM);
9067 ts->obj = rte_swx_table_learner_create(params, p->numa_node);
9068 learner_params_free(params);
9069 CHECK(ts->obj, ENODEV);
9071 /* ts->default_action_data. */
9072 if (l->action_data_size_max) {
9073 ts->default_action_data = malloc(l->action_data_size_max);
9074 CHECK(ts->default_action_data, ENOMEM);
9076 memcpy(ts->default_action_data,
9077 l->default_action_data,
9078 l->action_data_size_max);
9081 /* ts->default_action_id. */
9082 ts->default_action_id = l->default_action->id;
9089 table_state_build_free(struct rte_swx_pipeline *p)
9093 if (!p->table_state)
9096 for (i = 0; i < p->n_tables; i++) {
9097 struct rte_swx_table_state *ts = &p->table_state[i];
9098 struct table *table = table_find_by_id(p, i);
9101 if (table->type && ts->obj)
9102 table->type->ops.free(ts->obj);
9104 /* ts->default_action_data. */
9105 free(ts->default_action_data);
9108 for (i = 0; i < p->n_selectors; i++) {
9109 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + i];
9113 rte_swx_table_selector_free(ts->obj);
9116 for (i = 0; i < p->n_learners; i++) {
9117 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + p->n_selectors + i];
9121 rte_swx_table_learner_free(ts->obj);
9123 /* ts->default_action_data. */
9124 free(ts->default_action_data);
9127 free(p->table_state);
9128 p->table_state = NULL;
9132 table_state_free(struct rte_swx_pipeline *p)
9134 table_state_build_free(p);
9140 static struct regarray *
9141 regarray_find(struct rte_swx_pipeline *p, const char *name)
9143 struct regarray *elem;
9145 TAILQ_FOREACH(elem, &p->regarrays, node)
9146 if (!strcmp(elem->name, name))
9152 static struct regarray *
9153 regarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9155 struct regarray *elem = NULL;
9157 TAILQ_FOREACH(elem, &p->regarrays, node)
9165 rte_swx_pipeline_regarray_config(struct rte_swx_pipeline *p,
9174 CHECK_NAME(name, EINVAL);
9175 CHECK(!regarray_find(p, name), EEXIST);
9177 CHECK(size, EINVAL);
9178 size = rte_align32pow2(size);
9180 /* Memory allocation. */
9181 r = calloc(1, sizeof(struct regarray));
9184 /* Node initialization. */
9185 strcpy(r->name, name);
9186 r->init_val = init_val;
9188 r->id = p->n_regarrays;
9190 /* Node add to tailq. */
9191 TAILQ_INSERT_TAIL(&p->regarrays, r, node);
9198 regarray_build(struct rte_swx_pipeline *p)
9200 struct regarray *regarray;
9202 if (!p->n_regarrays)
9205 p->regarray_runtime = calloc(p->n_regarrays, sizeof(struct regarray_runtime));
9206 CHECK(p->regarray_runtime, ENOMEM);
9208 TAILQ_FOREACH(regarray, &p->regarrays, node) {
9209 struct regarray_runtime *r = &p->regarray_runtime[regarray->id];
9212 r->regarray = env_malloc(regarray->size * sizeof(uint64_t),
9213 RTE_CACHE_LINE_SIZE,
9215 CHECK(r->regarray, ENOMEM);
9217 if (regarray->init_val)
9218 for (i = 0; i < regarray->size; i++)
9219 r->regarray[i] = regarray->init_val;
9221 r->size_mask = regarray->size - 1;
9228 regarray_build_free(struct rte_swx_pipeline *p)
9232 if (!p->regarray_runtime)
9235 for (i = 0; i < p->n_regarrays; i++) {
9236 struct regarray *regarray = regarray_find_by_id(p, i);
9237 struct regarray_runtime *r = &p->regarray_runtime[i];
9239 env_free(r->regarray, regarray->size * sizeof(uint64_t));
9242 free(p->regarray_runtime);
9243 p->regarray_runtime = NULL;
9247 regarray_free(struct rte_swx_pipeline *p)
9249 regarray_build_free(p);
9252 struct regarray *elem;
9254 elem = TAILQ_FIRST(&p->regarrays);
9258 TAILQ_REMOVE(&p->regarrays, elem, node);
9266 static struct meter_profile *
9267 meter_profile_find(struct rte_swx_pipeline *p, const char *name)
9269 struct meter_profile *elem;
9271 TAILQ_FOREACH(elem, &p->meter_profiles, node)
9272 if (!strcmp(elem->name, name))
9278 static struct metarray *
9279 metarray_find(struct rte_swx_pipeline *p, const char *name)
9281 struct metarray *elem;
9283 TAILQ_FOREACH(elem, &p->metarrays, node)
9284 if (!strcmp(elem->name, name))
9290 static struct metarray *
9291 metarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9293 struct metarray *elem = NULL;
9295 TAILQ_FOREACH(elem, &p->metarrays, node)
9303 rte_swx_pipeline_metarray_config(struct rte_swx_pipeline *p,
9311 CHECK_NAME(name, EINVAL);
9312 CHECK(!metarray_find(p, name), EEXIST);
9314 CHECK(size, EINVAL);
9315 size = rte_align32pow2(size);
9317 /* Memory allocation. */
9318 m = calloc(1, sizeof(struct metarray));
9321 /* Node initialization. */
9322 strcpy(m->name, name);
9324 m->id = p->n_metarrays;
9326 /* Node add to tailq. */
9327 TAILQ_INSERT_TAIL(&p->metarrays, m, node);
9333 struct meter_profile meter_profile_default = {
9342 .cir_bytes_per_period = 1,
9344 .pir_bytes_per_period = 1,
9351 meter_init(struct meter *m)
9353 memset(m, 0, sizeof(struct meter));
9354 rte_meter_trtcm_config(&m->m, &meter_profile_default.profile);
9355 m->profile = &meter_profile_default;
9356 m->color_mask = RTE_COLOR_GREEN;
9358 meter_profile_default.n_users++;
9362 metarray_build(struct rte_swx_pipeline *p)
9366 if (!p->n_metarrays)
9369 p->metarray_runtime = calloc(p->n_metarrays, sizeof(struct metarray_runtime));
9370 CHECK(p->metarray_runtime, ENOMEM);
9372 TAILQ_FOREACH(m, &p->metarrays, node) {
9373 struct metarray_runtime *r = &p->metarray_runtime[m->id];
9376 r->metarray = env_malloc(m->size * sizeof(struct meter),
9377 RTE_CACHE_LINE_SIZE,
9379 CHECK(r->metarray, ENOMEM);
9381 for (i = 0; i < m->size; i++)
9382 meter_init(&r->metarray[i]);
9384 r->size_mask = m->size - 1;
9391 metarray_build_free(struct rte_swx_pipeline *p)
9395 if (!p->metarray_runtime)
9398 for (i = 0; i < p->n_metarrays; i++) {
9399 struct metarray *m = metarray_find_by_id(p, i);
9400 struct metarray_runtime *r = &p->metarray_runtime[i];
9402 env_free(r->metarray, m->size * sizeof(struct meter));
9405 free(p->metarray_runtime);
9406 p->metarray_runtime = NULL;
9410 metarray_free(struct rte_swx_pipeline *p)
9412 metarray_build_free(p);
9416 struct metarray *elem;
9418 elem = TAILQ_FIRST(&p->metarrays);
9422 TAILQ_REMOVE(&p->metarrays, elem, node);
9426 /* Meter profiles. */
9428 struct meter_profile *elem;
9430 elem = TAILQ_FIRST(&p->meter_profiles);
9434 TAILQ_REMOVE(&p->meter_profiles, elem, node);
9443 rte_swx_pipeline_free(struct rte_swx_pipeline *p)
9452 free(p->instruction_data);
9453 free(p->instructions);
9457 table_state_free(p);
9462 instruction_table_free(p);
9465 extern_func_free(p);
9479 port_in_types_register(struct rte_swx_pipeline *p)
9483 status = rte_swx_pipeline_port_in_type_register(p,
9485 &rte_swx_port_ethdev_reader_ops);
9489 status = rte_swx_pipeline_port_in_type_register(p,
9491 &rte_swx_port_ring_reader_ops);
9495 #ifdef RTE_PORT_PCAP
9496 status = rte_swx_pipeline_port_in_type_register(p,
9498 &rte_swx_port_source_ops);
9503 status = rte_swx_pipeline_port_in_type_register(p,
9505 &rte_swx_port_fd_reader_ops);
9513 port_out_types_register(struct rte_swx_pipeline *p)
9517 status = rte_swx_pipeline_port_out_type_register(p,
9519 &rte_swx_port_ethdev_writer_ops);
9523 status = rte_swx_pipeline_port_out_type_register(p,
9525 &rte_swx_port_ring_writer_ops);
9529 status = rte_swx_pipeline_port_out_type_register(p,
9531 &rte_swx_port_sink_ops);
9535 status = rte_swx_pipeline_port_out_type_register(p,
9537 &rte_swx_port_fd_writer_ops);
9545 table_types_register(struct rte_swx_pipeline *p)
9549 status = rte_swx_pipeline_table_type_register(p,
9551 RTE_SWX_TABLE_MATCH_EXACT,
9552 &rte_swx_table_exact_match_ops);
9556 status = rte_swx_pipeline_table_type_register(p,
9558 RTE_SWX_TABLE_MATCH_WILDCARD,
9559 &rte_swx_table_wildcard_match_ops);
9567 rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
9569 struct rte_swx_pipeline *pipeline = NULL;
9572 /* Check input parameters. */
9575 /* Memory allocation. */
9576 pipeline = calloc(1, sizeof(struct rte_swx_pipeline));
9582 /* Initialization. */
9583 TAILQ_INIT(&pipeline->struct_types);
9584 TAILQ_INIT(&pipeline->port_in_types);
9585 TAILQ_INIT(&pipeline->ports_in);
9586 TAILQ_INIT(&pipeline->port_out_types);
9587 TAILQ_INIT(&pipeline->ports_out);
9588 TAILQ_INIT(&pipeline->extern_types);
9589 TAILQ_INIT(&pipeline->extern_objs);
9590 TAILQ_INIT(&pipeline->extern_funcs);
9591 TAILQ_INIT(&pipeline->headers);
9592 TAILQ_INIT(&pipeline->actions);
9593 TAILQ_INIT(&pipeline->table_types);
9594 TAILQ_INIT(&pipeline->tables);
9595 TAILQ_INIT(&pipeline->selectors);
9596 TAILQ_INIT(&pipeline->learners);
9597 TAILQ_INIT(&pipeline->regarrays);
9598 TAILQ_INIT(&pipeline->meter_profiles);
9599 TAILQ_INIT(&pipeline->metarrays);
9601 pipeline->n_structs = 1; /* Struct 0 is reserved for action_data. */
9602 pipeline->numa_node = numa_node;
9604 status = port_in_types_register(pipeline);
9608 status = port_out_types_register(pipeline);
9612 status = table_types_register(pipeline);
9620 rte_swx_pipeline_free(pipeline);
9625 rte_swx_pipeline_instructions_config(struct rte_swx_pipeline *p,
9626 const char **instructions,
9627 uint32_t n_instructions)
9632 err = instruction_config(p, NULL, instructions, n_instructions);
9636 /* Thread instruction pointer reset. */
9637 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9638 struct thread *t = &p->threads[i];
9640 thread_ip_reset(p, t);
9647 pipeline_compile(struct rte_swx_pipeline *p);
9650 rte_swx_pipeline_build(struct rte_swx_pipeline *p)
9652 struct rte_swx_port_sink_params drop_port_params = {
9658 CHECK(p->build_done == 0, EEXIST);
9660 status = port_in_build(p);
9665 status = rte_swx_pipeline_port_out_config(p,
9672 status = port_out_build(p);
9676 status = mirroring_build(p);
9680 status = struct_build(p);
9684 status = extern_obj_build(p);
9688 status = extern_func_build(p);
9692 status = header_build(p);
9696 status = metadata_build(p);
9700 status = instruction_table_build(p);
9704 status = action_build(p);
9708 status = table_build(p);
9712 status = selector_build(p);
9716 status = learner_build(p);
9720 status = table_state_build(p);
9724 status = regarray_build(p);
9728 status = metarray_build(p);
9734 pipeline_compile(p);
9739 metarray_build_free(p);
9740 regarray_build_free(p);
9741 table_state_build_free(p);
9742 learner_build_free(p);
9743 selector_build_free(p);
9744 table_build_free(p);
9745 action_build_free(p);
9746 instruction_table_build_free(p);
9747 metadata_build_free(p);
9748 header_build_free(p);
9749 extern_func_build_free(p);
9750 extern_obj_build_free(p);
9751 mirroring_build_free(p);
9752 port_out_build_free(p);
9753 port_in_build_free(p);
9754 struct_build_free(p);
9760 rte_swx_pipeline_run(struct rte_swx_pipeline *p, uint32_t n_instructions)
9764 for (i = 0; i < n_instructions; i++)
9769 rte_swx_pipeline_flush(struct rte_swx_pipeline *p)
9773 for (i = 0; i < p->n_ports_out; i++) {
9774 struct port_out_runtime *port = &p->out[i];
9777 port->flush(port->obj);
9785 rte_swx_ctl_pipeline_info_get(struct rte_swx_pipeline *p,
9786 struct rte_swx_ctl_pipeline_info *pipeline)
9788 struct action *action;
9789 struct table *table;
9790 uint32_t n_actions = 0, n_tables = 0;
9792 if (!p || !pipeline)
9795 TAILQ_FOREACH(action, &p->actions, node)
9798 TAILQ_FOREACH(table, &p->tables, node)
9801 pipeline->n_ports_in = p->n_ports_in;
9802 pipeline->n_ports_out = p->n_ports_out;
9803 pipeline->n_mirroring_slots = p->n_mirroring_slots;
9804 pipeline->n_mirroring_sessions = p->n_mirroring_sessions;
9805 pipeline->n_actions = n_actions;
9806 pipeline->n_tables = n_tables;
9807 pipeline->n_selectors = p->n_selectors;
9808 pipeline->n_learners = p->n_learners;
9809 pipeline->n_regarrays = p->n_regarrays;
9810 pipeline->n_metarrays = p->n_metarrays;
9816 rte_swx_ctl_pipeline_numa_node_get(struct rte_swx_pipeline *p, int *numa_node)
9818 if (!p || !numa_node)
9821 *numa_node = p->numa_node;
9826 rte_swx_ctl_action_info_get(struct rte_swx_pipeline *p,
9828 struct rte_swx_ctl_action_info *action)
9830 struct action *a = NULL;
9832 if (!p || (action_id >= p->n_actions) || !action)
9835 a = action_find_by_id(p, action_id);
9839 strcpy(action->name, a->name);
9840 action->n_args = a->st ? a->st->n_fields : 0;
9845 rte_swx_ctl_action_arg_info_get(struct rte_swx_pipeline *p,
9847 uint32_t action_arg_id,
9848 struct rte_swx_ctl_action_arg_info *action_arg)
9850 struct action *a = NULL;
9851 struct field *arg = NULL;
9853 if (!p || (action_id >= p->n_actions) || !action_arg)
9856 a = action_find_by_id(p, action_id);
9857 if (!a || !a->st || (action_arg_id >= a->st->n_fields))
9860 arg = &a->st->fields[action_arg_id];
9861 strcpy(action_arg->name, arg->name);
9862 action_arg->n_bits = arg->n_bits;
9863 action_arg->is_network_byte_order = a->args_endianness[action_arg_id];
9869 rte_swx_ctl_table_info_get(struct rte_swx_pipeline *p,
9871 struct rte_swx_ctl_table_info *table)
9873 struct table *t = NULL;
9878 t = table_find_by_id(p, table_id);
9882 strcpy(table->name, t->name);
9883 strcpy(table->args, t->args);
9884 table->n_match_fields = t->n_fields;
9885 table->n_actions = t->n_actions;
9886 table->default_action_is_const = t->default_action_is_const;
9887 table->size = t->size;
9892 rte_swx_ctl_table_match_field_info_get(struct rte_swx_pipeline *p,
9894 uint32_t match_field_id,
9895 struct rte_swx_ctl_table_match_field_info *match_field)
9898 struct match_field *f;
9900 if (!p || (table_id >= p->n_tables) || !match_field)
9903 t = table_find_by_id(p, table_id);
9904 if (!t || (match_field_id >= t->n_fields))
9907 f = &t->fields[match_field_id];
9908 match_field->match_type = f->match_type;
9909 match_field->is_header = t->header ? 1 : 0;
9910 match_field->n_bits = f->field->n_bits;
9911 match_field->offset = f->field->offset;
9917 rte_swx_ctl_table_action_info_get(struct rte_swx_pipeline *p,
9919 uint32_t table_action_id,
9920 struct rte_swx_ctl_table_action_info *table_action)
9924 if (!p || (table_id >= p->n_tables) || !table_action)
9927 t = table_find_by_id(p, table_id);
9928 if (!t || (table_action_id >= t->n_actions))
9931 table_action->action_id = t->actions[table_action_id]->id;
9933 table_action->action_is_for_table_entries = t->action_is_for_table_entries[table_action_id];
9934 table_action->action_is_for_default_entry = t->action_is_for_default_entry[table_action_id];
9940 rte_swx_ctl_table_ops_get(struct rte_swx_pipeline *p,
9942 struct rte_swx_table_ops *table_ops,
9947 if (!p || (table_id >= p->n_tables))
9950 t = table_find_by_id(p, table_id);
9956 memcpy(table_ops, &t->type->ops, sizeof(*table_ops));
9966 rte_swx_ctl_selector_info_get(struct rte_swx_pipeline *p,
9967 uint32_t selector_id,
9968 struct rte_swx_ctl_selector_info *selector)
9970 struct selector *s = NULL;
9972 if (!p || !selector)
9975 s = selector_find_by_id(p, selector_id);
9979 strcpy(selector->name, s->name);
9981 selector->n_selector_fields = s->n_selector_fields;
9982 selector->n_groups_max = s->n_groups_max;
9983 selector->n_members_per_group_max = s->n_members_per_group_max;
9989 rte_swx_ctl_selector_group_id_field_info_get(struct rte_swx_pipeline *p,
9990 uint32_t selector_id,
9991 struct rte_swx_ctl_table_match_field_info *field)
9995 if (!p || (selector_id >= p->n_selectors) || !field)
9998 s = selector_find_by_id(p, selector_id);
10002 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10003 field->is_header = 0;
10004 field->n_bits = s->group_id_field->n_bits;
10005 field->offset = s->group_id_field->offset;
10011 rte_swx_ctl_selector_field_info_get(struct rte_swx_pipeline *p,
10012 uint32_t selector_id,
10013 uint32_t selector_field_id,
10014 struct rte_swx_ctl_table_match_field_info *field)
10016 struct selector *s;
10019 if (!p || (selector_id >= p->n_selectors) || !field)
10022 s = selector_find_by_id(p, selector_id);
10023 if (!s || (selector_field_id >= s->n_selector_fields))
10026 f = s->selector_fields[selector_field_id];
10027 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10028 field->is_header = s->selector_header ? 1 : 0;
10029 field->n_bits = f->n_bits;
10030 field->offset = f->offset;
10036 rte_swx_ctl_selector_member_id_field_info_get(struct rte_swx_pipeline *p,
10037 uint32_t selector_id,
10038 struct rte_swx_ctl_table_match_field_info *field)
10040 struct selector *s;
10042 if (!p || (selector_id >= p->n_selectors) || !field)
10045 s = selector_find_by_id(p, selector_id);
10049 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10050 field->is_header = 0;
10051 field->n_bits = s->member_id_field->n_bits;
10052 field->offset = s->member_id_field->offset;
10058 rte_swx_ctl_learner_info_get(struct rte_swx_pipeline *p,
10059 uint32_t learner_id,
10060 struct rte_swx_ctl_learner_info *learner)
10062 struct learner *l = NULL;
10064 if (!p || !learner)
10067 l = learner_find_by_id(p, learner_id);
10071 strcpy(learner->name, l->name);
10073 learner->n_match_fields = l->n_fields;
10074 learner->n_actions = l->n_actions;
10075 learner->default_action_is_const = l->default_action_is_const;
10076 learner->size = l->size;
10077 learner->n_key_timeouts = l->n_timeouts;
10083 rte_swx_ctl_learner_match_field_info_get(struct rte_swx_pipeline *p,
10084 uint32_t learner_id,
10085 uint32_t match_field_id,
10086 struct rte_swx_ctl_table_match_field_info *match_field)
10091 if (!p || (learner_id >= p->n_learners) || !match_field)
10094 l = learner_find_by_id(p, learner_id);
10095 if (!l || (match_field_id >= l->n_fields))
10098 f = l->fields[match_field_id];
10099 match_field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10100 match_field->is_header = l->header ? 1 : 0;
10101 match_field->n_bits = f->n_bits;
10102 match_field->offset = f->offset;
10108 rte_swx_ctl_learner_action_info_get(struct rte_swx_pipeline *p,
10109 uint32_t learner_id,
10110 uint32_t learner_action_id,
10111 struct rte_swx_ctl_table_action_info *learner_action)
10115 if (!p || (learner_id >= p->n_learners) || !learner_action)
10118 l = learner_find_by_id(p, learner_id);
10119 if (!l || (learner_action_id >= l->n_actions))
10122 learner_action->action_id = l->actions[learner_action_id]->id;
10124 learner_action->action_is_for_table_entries =
10125 l->action_is_for_table_entries[learner_action_id];
10127 learner_action->action_is_for_default_entry =
10128 l->action_is_for_default_entry[learner_action_id];
10134 rte_swx_ctl_pipeline_learner_timeout_get(struct rte_swx_pipeline *p,
10135 uint32_t learner_id,
10136 uint32_t timeout_id,
10141 if (!p || (learner_id >= p->n_learners) || !timeout)
10144 l = learner_find_by_id(p, learner_id);
10145 if (!l || (timeout_id >= l->n_timeouts))
10148 *timeout = l->timeout[timeout_id];
10153 rte_swx_ctl_pipeline_learner_timeout_set(struct rte_swx_pipeline *p,
10154 uint32_t learner_id,
10155 uint32_t timeout_id,
10159 struct rte_swx_table_state *ts;
10162 if (!p || (learner_id >= p->n_learners) || !timeout)
10165 l = learner_find_by_id(p, learner_id);
10166 if (!l || (timeout_id >= l->n_timeouts))
10169 if (!p->build_done)
10172 ts = &p->table_state[p->n_tables + p->n_selectors + l->id];
10174 status = rte_swx_table_learner_timeout_update(ts->obj, timeout_id, timeout);
10178 l->timeout[timeout_id] = timeout;
10184 rte_swx_pipeline_table_state_get(struct rte_swx_pipeline *p,
10185 struct rte_swx_table_state **table_state)
10187 if (!p || !table_state || !p->build_done)
10190 *table_state = p->table_state;
10195 rte_swx_pipeline_table_state_set(struct rte_swx_pipeline *p,
10196 struct rte_swx_table_state *table_state)
10198 if (!p || !table_state || !p->build_done)
10201 p->table_state = table_state;
10206 rte_swx_ctl_pipeline_port_in_stats_read(struct rte_swx_pipeline *p,
10208 struct rte_swx_port_in_stats *stats)
10210 struct port_in *port;
10215 port = port_in_find(p, port_id);
10219 port->type->ops.stats_read(port->obj, stats);
10224 rte_swx_ctl_pipeline_port_out_stats_read(struct rte_swx_pipeline *p,
10226 struct rte_swx_port_out_stats *stats)
10228 struct port_out *port;
10233 port = port_out_find(p, port_id);
10237 port->type->ops.stats_read(port->obj, stats);
10242 rte_swx_ctl_pipeline_table_stats_read(struct rte_swx_pipeline *p,
10243 const char *table_name,
10244 struct rte_swx_table_stats *stats)
10246 struct table *table;
10247 struct table_statistics *table_stats;
10249 if (!p || !table_name || !table_name[0] || !stats || !stats->n_pkts_action)
10252 table = table_find(p, table_name);
10256 table_stats = &p->table_stats[table->id];
10258 memcpy(stats->n_pkts_action,
10259 table_stats->n_pkts_action,
10260 p->n_actions * sizeof(uint64_t));
10262 stats->n_pkts_hit = table_stats->n_pkts_hit[1];
10263 stats->n_pkts_miss = table_stats->n_pkts_hit[0];
10269 rte_swx_ctl_pipeline_selector_stats_read(struct rte_swx_pipeline *p,
10270 const char *selector_name,
10271 struct rte_swx_pipeline_selector_stats *stats)
10273 struct selector *s;
10275 if (!p || !selector_name || !selector_name[0] || !stats)
10278 s = selector_find(p, selector_name);
10282 stats->n_pkts = p->selector_stats[s->id].n_pkts;
10288 rte_swx_ctl_pipeline_learner_stats_read(struct rte_swx_pipeline *p,
10289 const char *learner_name,
10290 struct rte_swx_learner_stats *stats)
10293 struct learner_statistics *learner_stats;
10295 if (!p || !learner_name || !learner_name[0] || !stats || !stats->n_pkts_action)
10298 l = learner_find(p, learner_name);
10302 learner_stats = &p->learner_stats[l->id];
10304 memcpy(stats->n_pkts_action,
10305 learner_stats->n_pkts_action,
10306 p->n_actions * sizeof(uint64_t));
10308 stats->n_pkts_hit = learner_stats->n_pkts_hit[1];
10309 stats->n_pkts_miss = learner_stats->n_pkts_hit[0];
10311 stats->n_pkts_learn_ok = learner_stats->n_pkts_learn[0];
10312 stats->n_pkts_learn_err = learner_stats->n_pkts_learn[1];
10314 stats->n_pkts_rearm = learner_stats->n_pkts_rearm;
10315 stats->n_pkts_forget = learner_stats->n_pkts_forget;
10321 rte_swx_ctl_regarray_info_get(struct rte_swx_pipeline *p,
10322 uint32_t regarray_id,
10323 struct rte_swx_ctl_regarray_info *regarray)
10325 struct regarray *r;
10327 if (!p || !regarray)
10330 r = regarray_find_by_id(p, regarray_id);
10334 strcpy(regarray->name, r->name);
10335 regarray->size = r->size;
10340 rte_swx_ctl_pipeline_regarray_read(struct rte_swx_pipeline *p,
10341 const char *regarray_name,
10342 uint32_t regarray_index,
10345 struct regarray *regarray;
10346 struct regarray_runtime *r;
10348 if (!p || !regarray_name || !value)
10351 regarray = regarray_find(p, regarray_name);
10352 if (!regarray || (regarray_index >= regarray->size))
10355 r = &p->regarray_runtime[regarray->id];
10356 *value = r->regarray[regarray_index];
10361 rte_swx_ctl_pipeline_regarray_write(struct rte_swx_pipeline *p,
10362 const char *regarray_name,
10363 uint32_t regarray_index,
10366 struct regarray *regarray;
10367 struct regarray_runtime *r;
10369 if (!p || !regarray_name)
10372 regarray = regarray_find(p, regarray_name);
10373 if (!regarray || (regarray_index >= regarray->size))
10376 r = &p->regarray_runtime[regarray->id];
10377 r->regarray[regarray_index] = value;
10382 rte_swx_ctl_metarray_info_get(struct rte_swx_pipeline *p,
10383 uint32_t metarray_id,
10384 struct rte_swx_ctl_metarray_info *metarray)
10386 struct metarray *m;
10388 if (!p || !metarray)
10391 m = metarray_find_by_id(p, metarray_id);
10395 strcpy(metarray->name, m->name);
10396 metarray->size = m->size;
10401 rte_swx_ctl_meter_profile_add(struct rte_swx_pipeline *p,
10403 struct rte_meter_trtcm_params *params)
10405 struct meter_profile *mp;
10409 CHECK_NAME(name, EINVAL);
10410 CHECK(params, EINVAL);
10411 CHECK(!meter_profile_find(p, name), EEXIST);
10413 /* Node allocation. */
10414 mp = calloc(1, sizeof(struct meter_profile));
10417 /* Node initialization. */
10418 strcpy(mp->name, name);
10419 memcpy(&mp->params, params, sizeof(struct rte_meter_trtcm_params));
10420 status = rte_meter_trtcm_profile_config(&mp->profile, params);
10426 /* Node add to tailq. */
10427 TAILQ_INSERT_TAIL(&p->meter_profiles, mp, node);
10433 rte_swx_ctl_meter_profile_delete(struct rte_swx_pipeline *p,
10436 struct meter_profile *mp;
10439 CHECK_NAME(name, EINVAL);
10441 mp = meter_profile_find(p, name);
10443 CHECK(!mp->n_users, EBUSY);
10445 /* Remove node from tailq. */
10446 TAILQ_REMOVE(&p->meter_profiles, mp, node);
10453 rte_swx_ctl_meter_reset(struct rte_swx_pipeline *p,
10454 const char *metarray_name,
10455 uint32_t metarray_index)
10457 struct meter_profile *mp_old;
10458 struct metarray *metarray;
10459 struct metarray_runtime *metarray_runtime;
10463 CHECK_NAME(metarray_name, EINVAL);
10465 metarray = metarray_find(p, metarray_name);
10466 CHECK(metarray, EINVAL);
10467 CHECK(metarray_index < metarray->size, EINVAL);
10469 metarray_runtime = &p->metarray_runtime[metarray->id];
10470 m = &metarray_runtime->metarray[metarray_index];
10471 mp_old = m->profile;
10481 rte_swx_ctl_meter_set(struct rte_swx_pipeline *p,
10482 const char *metarray_name,
10483 uint32_t metarray_index,
10484 const char *profile_name)
10486 struct meter_profile *mp, *mp_old;
10487 struct metarray *metarray;
10488 struct metarray_runtime *metarray_runtime;
10492 CHECK_NAME(metarray_name, EINVAL);
10494 metarray = metarray_find(p, metarray_name);
10495 CHECK(metarray, EINVAL);
10496 CHECK(metarray_index < metarray->size, EINVAL);
10498 mp = meter_profile_find(p, profile_name);
10501 metarray_runtime = &p->metarray_runtime[metarray->id];
10502 m = &metarray_runtime->metarray[metarray_index];
10503 mp_old = m->profile;
10505 memset(m, 0, sizeof(struct meter));
10506 rte_meter_trtcm_config(&m->m, &mp->profile);
10508 m->color_mask = RTE_COLORS;
10517 rte_swx_ctl_meter_stats_read(struct rte_swx_pipeline *p,
10518 const char *metarray_name,
10519 uint32_t metarray_index,
10520 struct rte_swx_ctl_meter_stats *stats)
10522 struct metarray *metarray;
10523 struct metarray_runtime *metarray_runtime;
10527 CHECK_NAME(metarray_name, EINVAL);
10529 metarray = metarray_find(p, metarray_name);
10530 CHECK(metarray, EINVAL);
10531 CHECK(metarray_index < metarray->size, EINVAL);
10533 CHECK(stats, EINVAL);
10535 metarray_runtime = &p->metarray_runtime[metarray->id];
10536 m = &metarray_runtime->metarray[metarray_index];
10538 memcpy(stats->n_pkts, m->n_pkts, sizeof(m->n_pkts));
10539 memcpy(stats->n_bytes, m->n_bytes, sizeof(m->n_bytes));
10545 rte_swx_ctl_pipeline_mirroring_session_set(struct rte_swx_pipeline *p,
10546 uint32_t session_id,
10547 struct rte_swx_pipeline_mirroring_session_params *params)
10549 struct mirroring_session *s;
10552 CHECK(p->build_done, EEXIST);
10553 CHECK(session_id < p->n_mirroring_sessions, EINVAL);
10554 CHECK(params, EINVAL);
10555 CHECK(params->port_id < p->n_ports_out, EINVAL);
10557 s = &p->mirroring_sessions[session_id];
10558 s->port_id = params->port_id;
10559 s->fast_clone = params->fast_clone;
10560 s->truncation_length = params->truncation_length ? params->truncation_length : UINT32_MAX;
10566 * Pipeline compilation.
10568 static const char *
10569 instr_type_to_name(struct instruction *instr)
10571 switch (instr->type) {
10572 case INSTR_RX: return "INSTR_RX";
10574 case INSTR_TX: return "INSTR_TX";
10575 case INSTR_TX_I: return "INSTR_TX_I";
10576 case INSTR_DROP: return "INSTR_DROP";
10577 case INSTR_MIRROR: return "INSTR_MIRROR";
10578 case INSTR_RECIRCULATE: return "INSTR_RECIRCULATE";
10579 case INSTR_RECIRCID: return "INSTR_RECIRCID";
10581 case INSTR_HDR_EXTRACT: return "INSTR_HDR_EXTRACT";
10582 case INSTR_HDR_EXTRACT2: return "INSTR_HDR_EXTRACT2";
10583 case INSTR_HDR_EXTRACT3: return "INSTR_HDR_EXTRACT3";
10584 case INSTR_HDR_EXTRACT4: return "INSTR_HDR_EXTRACT4";
10585 case INSTR_HDR_EXTRACT5: return "INSTR_HDR_EXTRACT5";
10586 case INSTR_HDR_EXTRACT6: return "INSTR_HDR_EXTRACT6";
10587 case INSTR_HDR_EXTRACT7: return "INSTR_HDR_EXTRACT7";
10588 case INSTR_HDR_EXTRACT8: return "INSTR_HDR_EXTRACT8";
10590 case INSTR_HDR_EXTRACT_M: return "INSTR_HDR_EXTRACT_M";
10592 case INSTR_HDR_LOOKAHEAD: return "INSTR_HDR_LOOKAHEAD";
10594 case INSTR_HDR_EMIT: return "INSTR_HDR_EMIT";
10595 case INSTR_HDR_EMIT_TX: return "INSTR_HDR_EMIT_TX";
10596 case INSTR_HDR_EMIT2_TX: return "INSTR_HDR_EMIT2_TX";
10597 case INSTR_HDR_EMIT3_TX: return "INSTR_HDR_EMIT3_TX";
10598 case INSTR_HDR_EMIT4_TX: return "INSTR_HDR_EMIT4_TX";
10599 case INSTR_HDR_EMIT5_TX: return "INSTR_HDR_EMIT5_TX";
10600 case INSTR_HDR_EMIT6_TX: return "INSTR_HDR_EMIT6_TX";
10601 case INSTR_HDR_EMIT7_TX: return "INSTR_HDR_EMIT7_TX";
10602 case INSTR_HDR_EMIT8_TX: return "INSTR_HDR_EMIT8_TX";
10604 case INSTR_HDR_VALIDATE: return "INSTR_HDR_VALIDATE";
10605 case INSTR_HDR_INVALIDATE: return "INSTR_HDR_INVALIDATE";
10607 case INSTR_MOV: return "INSTR_MOV";
10608 case INSTR_MOV_MH: return "INSTR_MOV_MH";
10609 case INSTR_MOV_HM: return "INSTR_MOV_HM";
10610 case INSTR_MOV_HH: return "INSTR_MOV_HH";
10611 case INSTR_MOV_I: return "INSTR_MOV_I";
10613 case INSTR_DMA_HT: return "INSTR_DMA_HT";
10614 case INSTR_DMA_HT2: return "INSTR_DMA_HT2";
10615 case INSTR_DMA_HT3: return "INSTR_DMA_HT3";
10616 case INSTR_DMA_HT4: return "INSTR_DMA_HT4";
10617 case INSTR_DMA_HT5: return "INSTR_DMA_HT5";
10618 case INSTR_DMA_HT6: return "INSTR_DMA_HT6";
10619 case INSTR_DMA_HT7: return "INSTR_DMA_HT7";
10620 case INSTR_DMA_HT8: return "INSTR_DMA_HT8";
10622 case INSTR_ALU_ADD: return "INSTR_ALU_ADD";
10623 case INSTR_ALU_ADD_MH: return "INSTR_ALU_ADD_MH";
10624 case INSTR_ALU_ADD_HM: return "INSTR_ALU_ADD_HM";
10625 case INSTR_ALU_ADD_HH: return "INSTR_ALU_ADD_HH";
10626 case INSTR_ALU_ADD_MI: return "INSTR_ALU_ADD_MI";
10627 case INSTR_ALU_ADD_HI: return "INSTR_ALU_ADD_HI";
10629 case INSTR_ALU_SUB: return "INSTR_ALU_SUB";
10630 case INSTR_ALU_SUB_MH: return "INSTR_ALU_SUB_MH";
10631 case INSTR_ALU_SUB_HM: return "INSTR_ALU_SUB_HM";
10632 case INSTR_ALU_SUB_HH: return "INSTR_ALU_SUB_HH";
10633 case INSTR_ALU_SUB_MI: return "INSTR_ALU_SUB_MI";
10634 case INSTR_ALU_SUB_HI: return "INSTR_ALU_SUB_HI";
10636 case INSTR_ALU_CKADD_FIELD: return "INSTR_ALU_CKADD_FIELD";
10637 case INSTR_ALU_CKADD_STRUCT20: return "INSTR_ALU_CKADD_STRUCT20";
10638 case INSTR_ALU_CKADD_STRUCT: return "INSTR_ALU_CKADD_STRUCT";
10639 case INSTR_ALU_CKSUB_FIELD: return "INSTR_ALU_CKSUB_FIELD";
10641 case INSTR_ALU_AND: return "INSTR_ALU_AND";
10642 case INSTR_ALU_AND_MH: return "INSTR_ALU_AND_MH";
10643 case INSTR_ALU_AND_HM: return "INSTR_ALU_AND_HM";
10644 case INSTR_ALU_AND_HH: return "INSTR_ALU_AND_HH";
10645 case INSTR_ALU_AND_I: return "INSTR_ALU_AND_I";
10647 case INSTR_ALU_OR: return "INSTR_ALU_OR";
10648 case INSTR_ALU_OR_MH: return "INSTR_ALU_OR_MH";
10649 case INSTR_ALU_OR_HM: return "INSTR_ALU_OR_HM";
10650 case INSTR_ALU_OR_HH: return "INSTR_ALU_OR_HH";
10651 case INSTR_ALU_OR_I: return "INSTR_ALU_OR_I";
10653 case INSTR_ALU_XOR: return "INSTR_ALU_XOR";
10654 case INSTR_ALU_XOR_MH: return "INSTR_ALU_XOR_MH";
10655 case INSTR_ALU_XOR_HM: return "INSTR_ALU_XOR_HM";
10656 case INSTR_ALU_XOR_HH: return "INSTR_ALU_XOR_HH";
10657 case INSTR_ALU_XOR_I: return "INSTR_ALU_XOR_I";
10659 case INSTR_ALU_SHL: return "INSTR_ALU_SHL";
10660 case INSTR_ALU_SHL_MH: return "INSTR_ALU_SHL_MH";
10661 case INSTR_ALU_SHL_HM: return "INSTR_ALU_SHL_HM";
10662 case INSTR_ALU_SHL_HH: return "INSTR_ALU_SHL_HH";
10663 case INSTR_ALU_SHL_MI: return "INSTR_ALU_SHL_MI";
10664 case INSTR_ALU_SHL_HI: return "INSTR_ALU_SHL_HI";
10666 case INSTR_ALU_SHR: return "INSTR_ALU_SHR";
10667 case INSTR_ALU_SHR_MH: return "INSTR_ALU_SHR_MH";
10668 case INSTR_ALU_SHR_HM: return "INSTR_ALU_SHR_HM";
10669 case INSTR_ALU_SHR_HH: return "INSTR_ALU_SHR_HH";
10670 case INSTR_ALU_SHR_MI: return "INSTR_ALU_SHR_MI";
10671 case INSTR_ALU_SHR_HI: return "INSTR_ALU_SHR_HI";
10673 case INSTR_REGPREFETCH_RH: return "INSTR_REGPREFETCH_RH";
10674 case INSTR_REGPREFETCH_RM: return "INSTR_REGPREFETCH_RM";
10675 case INSTR_REGPREFETCH_RI: return "INSTR_REGPREFETCH_RI";
10677 case INSTR_REGRD_HRH: return "INSTR_REGRD_HRH";
10678 case INSTR_REGRD_HRM: return "INSTR_REGRD_HRM";
10679 case INSTR_REGRD_HRI: return "INSTR_REGRD_HRI";
10680 case INSTR_REGRD_MRH: return "INSTR_REGRD_MRH";
10681 case INSTR_REGRD_MRM: return "INSTR_REGRD_MRM";
10682 case INSTR_REGRD_MRI: return "INSTR_REGRD_MRI";
10684 case INSTR_REGWR_RHH: return "INSTR_REGWR_RHH";
10685 case INSTR_REGWR_RHM: return "INSTR_REGWR_RHM";
10686 case INSTR_REGWR_RHI: return "INSTR_REGWR_RHI";
10687 case INSTR_REGWR_RMH: return "INSTR_REGWR_RMH";
10688 case INSTR_REGWR_RMM: return "INSTR_REGWR_RMM";
10689 case INSTR_REGWR_RMI: return "INSTR_REGWR_RMI";
10690 case INSTR_REGWR_RIH: return "INSTR_REGWR_RIH";
10691 case INSTR_REGWR_RIM: return "INSTR_REGWR_RIM";
10692 case INSTR_REGWR_RII: return "INSTR_REGWR_RII";
10694 case INSTR_REGADD_RHH: return "INSTR_REGADD_RHH";
10695 case INSTR_REGADD_RHM: return "INSTR_REGADD_RHM";
10696 case INSTR_REGADD_RHI: return "INSTR_REGADD_RHI";
10697 case INSTR_REGADD_RMH: return "INSTR_REGADD_RMH";
10698 case INSTR_REGADD_RMM: return "INSTR_REGADD_RMM";
10699 case INSTR_REGADD_RMI: return "INSTR_REGADD_RMI";
10700 case INSTR_REGADD_RIH: return "INSTR_REGADD_RIH";
10701 case INSTR_REGADD_RIM: return "INSTR_REGADD_RIM";
10702 case INSTR_REGADD_RII: return "INSTR_REGADD_RII";
10704 case INSTR_METPREFETCH_H: return "INSTR_METPREFETCH_H";
10705 case INSTR_METPREFETCH_M: return "INSTR_METPREFETCH_M";
10706 case INSTR_METPREFETCH_I: return "INSTR_METPREFETCH_I";
10708 case INSTR_METER_HHM: return "INSTR_METER_HHM";
10709 case INSTR_METER_HHI: return "INSTR_METER_HHI";
10710 case INSTR_METER_HMM: return "INSTR_METER_HMM";
10711 case INSTR_METER_HMI: return "INSTR_METER_HMI";
10712 case INSTR_METER_MHM: return "INSTR_METER_MHM";
10713 case INSTR_METER_MHI: return "INSTR_METER_MHI";
10714 case INSTR_METER_MMM: return "INSTR_METER_MMM";
10715 case INSTR_METER_MMI: return "INSTR_METER_MMI";
10716 case INSTR_METER_IHM: return "INSTR_METER_IHM";
10717 case INSTR_METER_IHI: return "INSTR_METER_IHI";
10718 case INSTR_METER_IMM: return "INSTR_METER_IMM";
10719 case INSTR_METER_IMI: return "INSTR_METER_IMI";
10721 case INSTR_TABLE: return "INSTR_TABLE";
10722 case INSTR_TABLE_AF: return "INSTR_TABLE_AF";
10723 case INSTR_SELECTOR: return "INSTR_SELECTOR";
10724 case INSTR_LEARNER: return "INSTR_LEARNER";
10725 case INSTR_LEARNER_AF: return "INSTR_LEARNER_AF";
10727 case INSTR_LEARNER_LEARN: return "INSTR_LEARNER_LEARN";
10728 case INSTR_LEARNER_REARM: return "INSTR_LEARNER_REARM";
10729 case INSTR_LEARNER_REARM_NEW: return "INSTR_LEARNER_REARM_NEW";
10730 case INSTR_LEARNER_FORGET: return "INSTR_LEARNER_FORGET";
10732 case INSTR_EXTERN_OBJ: return "INSTR_EXTERN_OBJ";
10733 case INSTR_EXTERN_FUNC: return "INSTR_EXTERN_FUNC";
10735 case INSTR_JMP: return "INSTR_JMP";
10736 case INSTR_JMP_VALID: return "INSTR_JMP_VALID";
10737 case INSTR_JMP_INVALID: return "INSTR_JMP_INVALID";
10738 case INSTR_JMP_HIT: return "INSTR_JMP_HIT";
10739 case INSTR_JMP_MISS: return "INSTR_JMP_MISS";
10740 case INSTR_JMP_ACTION_HIT: return "INSTR_JMP_ACTION_HIT";
10741 case INSTR_JMP_ACTION_MISS: return "INSTR_JMP_ACTION_MISS";
10742 case INSTR_JMP_EQ: return "INSTR_JMP_EQ";
10743 case INSTR_JMP_EQ_MH: return "INSTR_JMP_EQ_MH";
10744 case INSTR_JMP_EQ_HM: return "INSTR_JMP_EQ_HM";
10745 case INSTR_JMP_EQ_HH: return "INSTR_JMP_EQ_HH";
10746 case INSTR_JMP_EQ_I: return "INSTR_JMP_EQ_I";
10747 case INSTR_JMP_NEQ: return "INSTR_JMP_NEQ";
10748 case INSTR_JMP_NEQ_MH: return "INSTR_JMP_NEQ_MH";
10749 case INSTR_JMP_NEQ_HM: return "INSTR_JMP_NEQ_HM";
10750 case INSTR_JMP_NEQ_HH: return "INSTR_JMP_NEQ_HH";
10751 case INSTR_JMP_NEQ_I: return "INSTR_JMP_NEQ_I";
10752 case INSTR_JMP_LT: return "INSTR_JMP_LT";
10753 case INSTR_JMP_LT_MH: return "INSTR_JMP_LT_MH";
10754 case INSTR_JMP_LT_HM: return "INSTR_JMP_LT_HM";
10755 case INSTR_JMP_LT_HH: return "INSTR_JMP_LT_HH";
10756 case INSTR_JMP_LT_MI: return "INSTR_JMP_LT_MI";
10757 case INSTR_JMP_LT_HI: return "INSTR_JMP_LT_HI";
10758 case INSTR_JMP_GT: return "INSTR_JMP_GT";
10759 case INSTR_JMP_GT_MH: return "INSTR_JMP_GT_MH";
10760 case INSTR_JMP_GT_HM: return "INSTR_JMP_GT_HM";
10761 case INSTR_JMP_GT_HH: return "INSTR_JMP_GT_HH";
10762 case INSTR_JMP_GT_MI: return "INSTR_JMP_GT_MI";
10763 case INSTR_JMP_GT_HI: return "INSTR_JMP_GT_HI";
10765 case INSTR_RETURN: return "INSTR_RETURN";
10767 default: return "INSTR_UNKNOWN";
10772 (*instruction_export_t)(struct instruction *, FILE *);
10775 instr_io_export(struct instruction *instr, FILE *f)
10777 uint32_t n_io = 0, n_io_imm = 0, n_hdrs = 0, i;
10779 /* n_io, n_io_imm, n_hdrs. */
10780 if (instr->type == INSTR_RX ||
10781 instr->type == INSTR_TX ||
10782 instr->type == INSTR_HDR_EXTRACT_M ||
10783 (instr->type >= INSTR_HDR_EMIT_TX && instr->type <= INSTR_HDR_EMIT8_TX))
10786 if (instr->type == INSTR_TX_I)
10789 if (instr->type >= INSTR_HDR_EXTRACT && instr->type <= INSTR_HDR_EXTRACT8)
10790 n_hdrs = 1 + (instr->type - INSTR_HDR_EXTRACT);
10792 if (instr->type == INSTR_HDR_EXTRACT_M ||
10793 instr->type == INSTR_HDR_LOOKAHEAD ||
10794 instr->type == INSTR_HDR_EMIT)
10797 if (instr->type >= INSTR_HDR_EMIT_TX && instr->type <= INSTR_HDR_EMIT8_TX)
10798 n_hdrs = 1 + (instr->type - INSTR_HDR_EMIT_TX);
10803 "\t\t.type = %s,\n",
10804 instr_type_to_name(instr));
10807 if (n_io || n_io_imm || n_hdrs)
10815 "\t\t\t\t.offset = %u,\n"
10816 "\t\t\t\t.n_bits = %u,\n"
10818 instr->io.io.offset,
10819 instr->io.io.n_bits);
10824 "\t\t\t\t.val = %u,\n"
10828 /* instr.io.hdr. */
10833 /* instr.io.hdr.header_id. */
10835 "\t\t\t.header_id = {");
10837 for (i = 0; i < n_hdrs; i++)
10840 instr->io.hdr.header_id[i]);
10845 /* instr.io.hdr.struct_id. */
10847 "\t\t\t.struct_id = {");
10849 for (i = 0; i < n_hdrs; i++)
10852 instr->io.hdr.struct_id[i]);
10857 /* instr.io.hdr.n_bytes. */
10859 "\t\t\t.n_bytes = {");
10861 for (i = 0; i < n_hdrs; i++)
10864 instr->io.hdr.n_bytes[i]);
10869 /* instr.io.hdr - closing curly brace. */
10874 /* instr.io - closing curly brace. */
10875 if (n_io || n_io_imm || n_hdrs)
10879 /* instr - closing curly brace. */
10885 instr_mirror_export(struct instruction *instr, FILE *f)
10889 "\t\t.type = %s,\n"
10890 "\t\t.mirror = {\n"
10892 "\t\t\t\t.struct_id = %u,\n"
10893 "\t\t\t\t.n_bits = %u,\n"
10894 "\t\t\t\t.offset = %u,\n"
10897 "\t\t\t\t.struct_id = %u,\n"
10898 "\t\t\t\t.n_bits = %u,\n"
10899 "\t\t\t\t.offset = %u,\n"
10903 instr_type_to_name(instr),
10904 instr->mirror.dst.struct_id,
10905 instr->mirror.dst.n_bits,
10906 instr->mirror.dst.offset,
10907 instr->mirror.src.struct_id,
10908 instr->mirror.src.n_bits,
10909 instr->mirror.src.offset);
10913 instr_recirculate_export(struct instruction *instr, FILE *f)
10917 "\t\t.type = %s,\n"
10919 instr_type_to_name(instr));
10923 instr_recircid_export(struct instruction *instr, FILE *f)
10927 "\t\t.type = %s,\n"
10929 "\t\t\t.offset = %u,\n"
10930 "\t\t\t.n_bits = %u,\n"
10933 instr_type_to_name(instr),
10934 instr->io.io.offset,
10935 instr->io.io.n_bits);
10939 instr_hdr_validate_export(struct instruction *instr, FILE *f)
10943 "\t\t.type = %s,\n"
10945 "\t\t\t.header_id = %u,\n"
10948 instr_type_to_name(instr),
10949 instr->valid.header_id);
10953 instr_mov_export(struct instruction *instr, FILE *f)
10955 if (instr->type != INSTR_MOV_I)
10958 "\t\t.type = %s,\n"
10961 "\t\t\t\t.struct_id = %u,\n"
10962 "\t\t\t\t.n_bits = %u,\n"
10963 "\t\t\t\t.offset = %u,\n"
10966 "\t\t\t\t.struct_id = %u,\n"
10967 "\t\t\t\t.n_bits = %u,\n"
10968 "\t\t\t\t.offset = %u,\n"
10972 instr_type_to_name(instr),
10973 instr->mov.dst.struct_id,
10974 instr->mov.dst.n_bits,
10975 instr->mov.dst.offset,
10976 instr->mov.src.struct_id,
10977 instr->mov.src.n_bits,
10978 instr->mov.src.offset);
10982 "\t\t.type = %s,\n"
10985 "\t\t\t\t.struct_id = %u,\n"
10986 "\t\t\t\t.n_bits = %u,\n"
10987 "\t\t\t\t.offset = %u,\n"
10989 "\t\t\t.src_val = %" PRIu64 ",\n"
10992 instr_type_to_name(instr),
10993 instr->mov.dst.struct_id,
10994 instr->mov.dst.n_bits,
10995 instr->mov.dst.offset,
10996 instr->mov.src_val);
11000 instr_dma_ht_export(struct instruction *instr, FILE *f)
11002 uint32_t n_dma = 0, i;
11005 n_dma = 1 + (instr->type - INSTR_DMA_HT);
11010 "\t\t.type = %s,\n",
11011 instr_type_to_name(instr));
11017 /* instr.dma.dst. */
11019 "\t\t\t.dst = {\n");
11021 /* instr.dma.dst.header_id. */
11023 "\t\t\t\t.header_id = {");
11025 for (i = 0; i < n_dma; i++)
11028 instr->dma.dst.header_id[i]);
11033 /* instr.dma.dst.struct_id. */
11035 "\t\t\t\t.struct_id = {");
11037 for (i = 0; i < n_dma; i++)
11040 instr->dma.dst.struct_id[i]);
11045 /* instr.dma.dst - closing curly brace. */
11049 /* instr.dma.src. */
11051 "\t\t\t.src = {\n");
11053 /* instr.dma.src.offset. */
11055 "\t\t\t\t.offset = {");
11057 for (i = 0; i < n_dma; i++)
11060 instr->dma.src.offset[i]);
11065 /* instr.dma.src - closing curly brace. */
11069 /* instr.dma.n_bytes. */
11071 "\t\t\t.n_bytes = {");
11073 for (i = 0; i < n_dma; i++)
11076 instr->dma.n_bytes[i]);
11081 /* instr.dma - closing curly brace. */
11085 /* instr - closing curly brace. */
11091 instr_alu_export(struct instruction *instr, FILE *f)
11095 if (instr->type == INSTR_ALU_ADD_MI ||
11096 instr->type == INSTR_ALU_ADD_HI ||
11097 instr->type == INSTR_ALU_SUB_MI ||
11098 instr->type == INSTR_ALU_SUB_HI ||
11099 instr->type == INSTR_ALU_SHL_MI ||
11100 instr->type == INSTR_ALU_SHL_HI ||
11101 instr->type == INSTR_ALU_SHR_MI ||
11102 instr->type == INSTR_ALU_SHR_HI ||
11103 instr->type == INSTR_ALU_AND_I ||
11104 instr->type == INSTR_ALU_OR_I ||
11105 instr->type == INSTR_ALU_XOR_I)
11111 "\t\t.type = %s,\n"
11114 "\t\t\t\t.struct_id = %u,\n"
11115 "\t\t\t\t.n_bits = %u,\n"
11116 "\t\t\t\t.offset = %u,\n"
11119 "\t\t\t\t.struct_id = %u,\n"
11120 "\t\t\t\t.n_bits = %u,\n"
11121 "\t\t\t\t.offset = %u,\n"
11125 instr_type_to_name(instr),
11126 instr->alu.dst.struct_id,
11127 instr->alu.dst.n_bits,
11128 instr->alu.dst.offset,
11129 instr->alu.src.struct_id,
11130 instr->alu.src.n_bits,
11131 instr->alu.src.offset);
11135 "\t\t.type = %s,\n"
11138 "\t\t\t\t.struct_id = %u,\n"
11139 "\t\t\t\t.n_bits = %u,\n"
11140 "\t\t\t\t.offset = %u,\n"
11142 "\t\t\t.src_val = %" PRIu64 ",\n"
11145 instr_type_to_name(instr),
11146 instr->alu.dst.struct_id,
11147 instr->alu.dst.n_bits,
11148 instr->alu.dst.offset,
11149 instr->alu.src_val);
11153 instr_reg_export(struct instruction *instr __rte_unused, FILE *f __rte_unused)
11155 int prefetch = 0, idx_imm = 0, src_imm = 0;
11157 if (instr->type == INSTR_REGPREFETCH_RH ||
11158 instr->type == INSTR_REGPREFETCH_RM ||
11159 instr->type == INSTR_REGPREFETCH_RI)
11162 /* index is the 3rd operand for the regrd instruction and the 2nd
11163 * operand for the regwr and regadd instructions.
11165 if (instr->type == INSTR_REGPREFETCH_RI ||
11166 instr->type == INSTR_REGRD_HRI ||
11167 instr->type == INSTR_REGRD_MRI ||
11168 instr->type == INSTR_REGWR_RIH ||
11169 instr->type == INSTR_REGWR_RIM ||
11170 instr->type == INSTR_REGWR_RII ||
11171 instr->type == INSTR_REGADD_RIH ||
11172 instr->type == INSTR_REGADD_RIM ||
11173 instr->type == INSTR_REGADD_RII)
11176 /* src is the 3rd operand for the regwr and regadd instructions. */
11177 if (instr->type == INSTR_REGWR_RHI ||
11178 instr->type == INSTR_REGWR_RMI ||
11179 instr->type == INSTR_REGWR_RII ||
11180 instr->type == INSTR_REGADD_RHI ||
11181 instr->type == INSTR_REGADD_RMI ||
11182 instr->type == INSTR_REGADD_RII)
11185 /* instr.regarray.regarray_id. */
11188 "\t\t.type = %s,\n"
11189 "\t\t.regarray = {\n"
11190 "\t\t\t.regarray_id = %u,\n",
11191 instr_type_to_name(instr),
11192 instr->regarray.regarray_id);
11194 /* instr.regarray.idx / instr.regarray.idx_val. */
11197 "\t\t\t\t.idx = {\n"
11198 "\t\t\t\t\t.struct_id = %u,\n"
11199 "\t\t\t\t\t.n_bits = %u,\n"
11200 "\t\t\t\t\t.offset = %u,\n"
11202 instr->regarray.idx.struct_id,
11203 instr->regarray.idx.n_bits,
11204 instr->regarray.idx.offset);
11207 "\t\t\t\t.idx_val = %u,\n",
11208 instr->regarray.idx_val);
11210 /* instr.regarray.dstsrc / instr.regarray.dstsrc_val. */
11214 "\t\t\t\t.dstsrc = {\n"
11215 "\t\t\t\t\t.struct_id = %u,\n"
11216 "\t\t\t\t\t.n_bits = %u,\n"
11217 "\t\t\t\t\t.offset = %u,\n"
11219 instr->regarray.dstsrc.struct_id,
11220 instr->regarray.dstsrc.n_bits,
11221 instr->regarray.dstsrc.offset);
11224 "\t\t\t\t.dstsrc_val = %" PRIu64 ",\n",
11225 instr->regarray.dstsrc_val);
11228 /* instr.regarray and instr - closing curly braces. */
11235 instr_meter_export(struct instruction *instr __rte_unused, FILE *f __rte_unused)
11237 int prefetch = 0, idx_imm = 0, color_in_imm = 0;
11239 if (instr->type == INSTR_METPREFETCH_H ||
11240 instr->type == INSTR_METPREFETCH_M ||
11241 instr->type == INSTR_METPREFETCH_I)
11245 if (instr->type == INSTR_METPREFETCH_I ||
11246 instr->type == INSTR_METER_IHM ||
11247 instr->type == INSTR_METER_IHI ||
11248 instr->type == INSTR_METER_IMM ||
11249 instr->type == INSTR_METER_IMI)
11252 /* color_in_imm. */
11253 if (instr->type == INSTR_METER_HHI ||
11254 instr->type == INSTR_METER_HMI ||
11255 instr->type == INSTR_METER_MHI ||
11256 instr->type == INSTR_METER_MMI ||
11257 instr->type == INSTR_METER_IHI ||
11258 instr->type == INSTR_METER_IMI)
11261 /* instr.meter.metarray_id. */
11264 "\t\t.type = %s,\n"
11266 "\t\t\t.metarray_id = %u,\n",
11267 instr_type_to_name(instr),
11268 instr->meter.metarray_id);
11270 /* instr.meter.idx / instr.meter.idx_val. */
11274 "\t\t\t\t.struct_id = %u,\n"
11275 "\t\t\t\t.n_bits = %u,\n"
11276 "\t\t\t\t.offset = %u,\n"
11278 instr->meter.idx.struct_id,
11279 instr->meter.idx.n_bits,
11280 instr->meter.idx.offset);
11283 "\t\t\t.idx_val = %u,\n",
11284 instr->meter.idx_val);
11287 /* instr.meter.length. */
11289 "\t\t\t.length = {\n"
11290 "\t\t\t\t.struct_id = %u,\n"
11291 "\t\t\t\t.n_bits = %u,\n"
11292 "\t\t\t\t.offset = %u,\n"
11294 instr->meter.length.struct_id,
11295 instr->meter.length.n_bits,
11296 instr->meter.length.offset);
11298 /* instr.meter.color_in / instr.meter.color_in_val. */
11301 "\t\t\t.color_in = {\n"
11302 "\t\t\t\t.struct_id = %u,\n"
11303 "\t\t\t\t.n_bits = %u,\n"
11304 "\t\t\t\t.offset = %u,\n"
11306 instr->meter.color_in.struct_id,
11307 instr->meter.color_in.n_bits,
11308 instr->meter.color_in.offset);
11311 "\t\t\t.color_in_val = %u,\n",
11312 (uint32_t)instr->meter.color_in_val);
11314 /* instr.meter.color_out. */
11316 "\t\t\t.color_out = {\n"
11317 "\t\t\t\t.struct_id = %u,\n"
11318 "\t\t\t\t.n_bits = %u,\n"
11319 "\t\t\t\t.offset = %u,\n"
11321 instr->meter.color_out.struct_id,
11322 instr->meter.color_out.n_bits,
11323 instr->meter.color_out.offset);
11326 /* instr.meter and instr - closing curly braces. */
11333 instr_table_export(struct instruction *instr,
11338 "\t\t.type = %s,\n"
11340 "\t\t\t.table_id = %u,\n"
11343 instr_type_to_name(instr),
11344 instr->table.table_id);
11348 instr_learn_export(struct instruction *instr, FILE *f)
11352 "\t\t.type = %s,\n"
11354 "\t\t\t.action_id = %u,\n"
11355 "\t\t\t.mf_first_arg_offset = %u,\n"
11356 "\t\t\t.mf_timeout_id_offset = %u,\n"
11357 "\t\t\t.mf_timeout_id_n_bits = %u,\n"
11360 instr_type_to_name(instr),
11361 instr->learn.action_id,
11362 instr->learn.mf_first_arg_offset,
11363 instr->learn.mf_timeout_id_offset,
11364 instr->learn.mf_timeout_id_n_bits);
11368 instr_rearm_export(struct instruction *instr, FILE *f)
11370 if (instr->type == INSTR_LEARNER_REARM)
11373 "\t\t.type = %s,\n"
11375 instr_type_to_name(instr));
11379 "\t\t.type = %s,\n"
11381 "\t\t\t.mf_timeout_id_offset = %u,\n"
11382 "\t\t\t.mf_timeout_id_n_bits = %u,\n"
11385 instr_type_to_name(instr),
11386 instr->learn.mf_timeout_id_offset,
11387 instr->learn.mf_timeout_id_n_bits);
11391 instr_forget_export(struct instruction *instr, FILE *f)
11395 "\t\t.type = %s,\n"
11397 instr_type_to_name(instr));
11401 instr_extern_export(struct instruction *instr, FILE *f)
11403 if (instr->type == INSTR_EXTERN_OBJ)
11406 "\t\t.type = %s,\n"
11407 "\t\t.ext_obj = {\n"
11408 "\t\t\t.ext_obj_id = %u,\n"
11409 "\t\t\t.func_id = %u,\n"
11412 instr_type_to_name(instr),
11413 instr->ext_obj.ext_obj_id,
11414 instr->ext_obj.func_id);
11418 "\t\t.type = %s,\n"
11419 "\t\t.ext_func = {\n"
11420 "\t\t\t.ext_func_id = %u,\n"
11423 instr_type_to_name(instr),
11424 instr->ext_func.ext_func_id);
11428 instr_jmp_export(struct instruction *instr, FILE *f __rte_unused)
11432 "\t\t.type = %s,\n"
11434 "\t\t\t.ip = NULL,\n",
11435 instr_type_to_name(instr));
11437 switch (instr->type) {
11438 case INSTR_JMP_VALID:
11439 case INSTR_JMP_INVALID:
11441 "\t\t\t.header_id = %u,\n",
11442 instr->jmp.header_id);
11445 case INSTR_JMP_ACTION_HIT:
11446 case INSTR_JMP_ACTION_MISS:
11448 "\t\t\t.action_id = %u,\n",
11449 instr->jmp.action_id);
11453 case INSTR_JMP_EQ_MH:
11454 case INSTR_JMP_EQ_HM:
11455 case INSTR_JMP_EQ_HH:
11456 case INSTR_JMP_NEQ:
11457 case INSTR_JMP_NEQ_MH:
11458 case INSTR_JMP_NEQ_HM:
11459 case INSTR_JMP_NEQ_HH:
11461 case INSTR_JMP_LT_MH:
11462 case INSTR_JMP_LT_HM:
11463 case INSTR_JMP_LT_HH:
11465 case INSTR_JMP_GT_MH:
11466 case INSTR_JMP_GT_HM:
11467 case INSTR_JMP_GT_HH:
11470 "\t\t\t\t.struct_id = %u,\n"
11471 "\t\t\t\t.n_bits = %u,\n"
11472 "\t\t\t\t.offset = %u,\n"
11475 "\t\t\t\t.struct_id = %u,\n"
11476 "\t\t\t\t.n_bits = %u,\n"
11477 "\t\t\t\t.offset = %u,\n"
11479 instr->jmp.a.struct_id,
11480 instr->jmp.a.n_bits,
11481 instr->jmp.a.offset,
11482 instr->jmp.b.struct_id,
11483 instr->jmp.b.n_bits,
11484 instr->jmp.b.offset);
11487 case INSTR_JMP_EQ_I:
11488 case INSTR_JMP_NEQ_I:
11489 case INSTR_JMP_LT_MI:
11490 case INSTR_JMP_LT_HI:
11491 case INSTR_JMP_GT_MI:
11492 case INSTR_JMP_GT_HI:
11495 "\t\t\t\t.struct_id = %u,\n"
11496 "\t\t\t\t.n_bits = %u,\n"
11497 "\t\t\t\t.offset = %u,\n"
11499 "\t\t\t.b_val = %" PRIu64 ",\n",
11500 instr->jmp.a.struct_id,
11501 instr->jmp.a.n_bits,
11502 instr->jmp.a.offset,
11516 instr_return_export(struct instruction *instr,
11521 "\t\t.type = %s,\n",
11522 instr_type_to_name(instr));
11528 static instruction_export_t export_table[] = {
11529 [INSTR_RX] = instr_io_export,
11531 [INSTR_TX] = instr_io_export,
11532 [INSTR_TX_I] = instr_io_export,
11533 [INSTR_DROP] = instr_io_export,
11534 [INSTR_MIRROR] = instr_mirror_export,
11535 [INSTR_RECIRCULATE] = instr_recirculate_export,
11536 [INSTR_RECIRCID] = instr_recircid_export,
11538 [INSTR_HDR_EXTRACT] = instr_io_export,
11539 [INSTR_HDR_EXTRACT2] = instr_io_export,
11540 [INSTR_HDR_EXTRACT3] = instr_io_export,
11541 [INSTR_HDR_EXTRACT4] = instr_io_export,
11542 [INSTR_HDR_EXTRACT5] = instr_io_export,
11543 [INSTR_HDR_EXTRACT6] = instr_io_export,
11544 [INSTR_HDR_EXTRACT7] = instr_io_export,
11545 [INSTR_HDR_EXTRACT8] = instr_io_export,
11547 [INSTR_HDR_EXTRACT_M] = instr_io_export,
11549 [INSTR_HDR_LOOKAHEAD] = instr_io_export,
11551 [INSTR_HDR_EMIT] = instr_io_export,
11552 [INSTR_HDR_EMIT_TX] = instr_io_export,
11553 [INSTR_HDR_EMIT2_TX] = instr_io_export,
11554 [INSTR_HDR_EMIT3_TX] = instr_io_export,
11555 [INSTR_HDR_EMIT4_TX] = instr_io_export,
11556 [INSTR_HDR_EMIT5_TX] = instr_io_export,
11557 [INSTR_HDR_EMIT6_TX] = instr_io_export,
11558 [INSTR_HDR_EMIT7_TX] = instr_io_export,
11559 [INSTR_HDR_EMIT8_TX] = instr_io_export,
11561 [INSTR_HDR_VALIDATE] = instr_hdr_validate_export,
11562 [INSTR_HDR_INVALIDATE] = instr_hdr_validate_export,
11564 [INSTR_MOV] = instr_mov_export,
11565 [INSTR_MOV_MH] = instr_mov_export,
11566 [INSTR_MOV_HM] = instr_mov_export,
11567 [INSTR_MOV_HH] = instr_mov_export,
11568 [INSTR_MOV_I] = instr_mov_export,
11570 [INSTR_DMA_HT] = instr_dma_ht_export,
11571 [INSTR_DMA_HT2] = instr_dma_ht_export,
11572 [INSTR_DMA_HT3] = instr_dma_ht_export,
11573 [INSTR_DMA_HT4] = instr_dma_ht_export,
11574 [INSTR_DMA_HT5] = instr_dma_ht_export,
11575 [INSTR_DMA_HT6] = instr_dma_ht_export,
11576 [INSTR_DMA_HT7] = instr_dma_ht_export,
11577 [INSTR_DMA_HT8] = instr_dma_ht_export,
11579 [INSTR_ALU_ADD] = instr_alu_export,
11580 [INSTR_ALU_ADD_MH] = instr_alu_export,
11581 [INSTR_ALU_ADD_HM] = instr_alu_export,
11582 [INSTR_ALU_ADD_HH] = instr_alu_export,
11583 [INSTR_ALU_ADD_MI] = instr_alu_export,
11584 [INSTR_ALU_ADD_HI] = instr_alu_export,
11586 [INSTR_ALU_SUB] = instr_alu_export,
11587 [INSTR_ALU_SUB_MH] = instr_alu_export,
11588 [INSTR_ALU_SUB_HM] = instr_alu_export,
11589 [INSTR_ALU_SUB_HH] = instr_alu_export,
11590 [INSTR_ALU_SUB_MI] = instr_alu_export,
11591 [INSTR_ALU_SUB_HI] = instr_alu_export,
11593 [INSTR_ALU_CKADD_FIELD] = instr_alu_export,
11594 [INSTR_ALU_CKADD_STRUCT] = instr_alu_export,
11595 [INSTR_ALU_CKADD_STRUCT20] = instr_alu_export,
11596 [INSTR_ALU_CKSUB_FIELD] = instr_alu_export,
11598 [INSTR_ALU_AND] = instr_alu_export,
11599 [INSTR_ALU_AND_MH] = instr_alu_export,
11600 [INSTR_ALU_AND_HM] = instr_alu_export,
11601 [INSTR_ALU_AND_HH] = instr_alu_export,
11602 [INSTR_ALU_AND_I] = instr_alu_export,
11604 [INSTR_ALU_OR] = instr_alu_export,
11605 [INSTR_ALU_OR_MH] = instr_alu_export,
11606 [INSTR_ALU_OR_HM] = instr_alu_export,
11607 [INSTR_ALU_OR_HH] = instr_alu_export,
11608 [INSTR_ALU_OR_I] = instr_alu_export,
11610 [INSTR_ALU_XOR] = instr_alu_export,
11611 [INSTR_ALU_XOR_MH] = instr_alu_export,
11612 [INSTR_ALU_XOR_HM] = instr_alu_export,
11613 [INSTR_ALU_XOR_HH] = instr_alu_export,
11614 [INSTR_ALU_XOR_I] = instr_alu_export,
11616 [INSTR_ALU_SHL] = instr_alu_export,
11617 [INSTR_ALU_SHL_MH] = instr_alu_export,
11618 [INSTR_ALU_SHL_HM] = instr_alu_export,
11619 [INSTR_ALU_SHL_HH] = instr_alu_export,
11620 [INSTR_ALU_SHL_MI] = instr_alu_export,
11621 [INSTR_ALU_SHL_HI] = instr_alu_export,
11623 [INSTR_ALU_SHR] = instr_alu_export,
11624 [INSTR_ALU_SHR_MH] = instr_alu_export,
11625 [INSTR_ALU_SHR_HM] = instr_alu_export,
11626 [INSTR_ALU_SHR_HH] = instr_alu_export,
11627 [INSTR_ALU_SHR_MI] = instr_alu_export,
11628 [INSTR_ALU_SHR_HI] = instr_alu_export,
11630 [INSTR_REGPREFETCH_RH] = instr_reg_export,
11631 [INSTR_REGPREFETCH_RM] = instr_reg_export,
11632 [INSTR_REGPREFETCH_RI] = instr_reg_export,
11634 [INSTR_REGRD_HRH] = instr_reg_export,
11635 [INSTR_REGRD_HRM] = instr_reg_export,
11636 [INSTR_REGRD_MRH] = instr_reg_export,
11637 [INSTR_REGRD_MRM] = instr_reg_export,
11638 [INSTR_REGRD_HRI] = instr_reg_export,
11639 [INSTR_REGRD_MRI] = instr_reg_export,
11641 [INSTR_REGWR_RHH] = instr_reg_export,
11642 [INSTR_REGWR_RHM] = instr_reg_export,
11643 [INSTR_REGWR_RMH] = instr_reg_export,
11644 [INSTR_REGWR_RMM] = instr_reg_export,
11645 [INSTR_REGWR_RHI] = instr_reg_export,
11646 [INSTR_REGWR_RMI] = instr_reg_export,
11647 [INSTR_REGWR_RIH] = instr_reg_export,
11648 [INSTR_REGWR_RIM] = instr_reg_export,
11649 [INSTR_REGWR_RII] = instr_reg_export,
11651 [INSTR_REGADD_RHH] = instr_reg_export,
11652 [INSTR_REGADD_RHM] = instr_reg_export,
11653 [INSTR_REGADD_RMH] = instr_reg_export,
11654 [INSTR_REGADD_RMM] = instr_reg_export,
11655 [INSTR_REGADD_RHI] = instr_reg_export,
11656 [INSTR_REGADD_RMI] = instr_reg_export,
11657 [INSTR_REGADD_RIH] = instr_reg_export,
11658 [INSTR_REGADD_RIM] = instr_reg_export,
11659 [INSTR_REGADD_RII] = instr_reg_export,
11661 [INSTR_METPREFETCH_H] = instr_meter_export,
11662 [INSTR_METPREFETCH_M] = instr_meter_export,
11663 [INSTR_METPREFETCH_I] = instr_meter_export,
11665 [INSTR_METER_HHM] = instr_meter_export,
11666 [INSTR_METER_HHI] = instr_meter_export,
11667 [INSTR_METER_HMM] = instr_meter_export,
11668 [INSTR_METER_HMI] = instr_meter_export,
11669 [INSTR_METER_MHM] = instr_meter_export,
11670 [INSTR_METER_MHI] = instr_meter_export,
11671 [INSTR_METER_MMM] = instr_meter_export,
11672 [INSTR_METER_MMI] = instr_meter_export,
11673 [INSTR_METER_IHM] = instr_meter_export,
11674 [INSTR_METER_IHI] = instr_meter_export,
11675 [INSTR_METER_IMM] = instr_meter_export,
11676 [INSTR_METER_IMI] = instr_meter_export,
11678 [INSTR_TABLE] = instr_table_export,
11679 [INSTR_TABLE_AF] = instr_table_export,
11680 [INSTR_SELECTOR] = instr_table_export,
11681 [INSTR_LEARNER] = instr_table_export,
11682 [INSTR_LEARNER_AF] = instr_table_export,
11684 [INSTR_LEARNER_LEARN] = instr_learn_export,
11685 [INSTR_LEARNER_REARM] = instr_rearm_export,
11686 [INSTR_LEARNER_REARM_NEW] = instr_rearm_export,
11687 [INSTR_LEARNER_FORGET] = instr_forget_export,
11689 [INSTR_EXTERN_OBJ] = instr_extern_export,
11690 [INSTR_EXTERN_FUNC] = instr_extern_export,
11692 [INSTR_JMP] = instr_jmp_export,
11693 [INSTR_JMP_VALID] = instr_jmp_export,
11694 [INSTR_JMP_INVALID] = instr_jmp_export,
11695 [INSTR_JMP_HIT] = instr_jmp_export,
11696 [INSTR_JMP_MISS] = instr_jmp_export,
11697 [INSTR_JMP_ACTION_HIT] = instr_jmp_export,
11698 [INSTR_JMP_ACTION_MISS] = instr_jmp_export,
11700 [INSTR_JMP_EQ] = instr_jmp_export,
11701 [INSTR_JMP_EQ_MH] = instr_jmp_export,
11702 [INSTR_JMP_EQ_HM] = instr_jmp_export,
11703 [INSTR_JMP_EQ_HH] = instr_jmp_export,
11704 [INSTR_JMP_EQ_I] = instr_jmp_export,
11706 [INSTR_JMP_NEQ] = instr_jmp_export,
11707 [INSTR_JMP_NEQ_MH] = instr_jmp_export,
11708 [INSTR_JMP_NEQ_HM] = instr_jmp_export,
11709 [INSTR_JMP_NEQ_HH] = instr_jmp_export,
11710 [INSTR_JMP_NEQ_I] = instr_jmp_export,
11712 [INSTR_JMP_LT] = instr_jmp_export,
11713 [INSTR_JMP_LT_MH] = instr_jmp_export,
11714 [INSTR_JMP_LT_HM] = instr_jmp_export,
11715 [INSTR_JMP_LT_HH] = instr_jmp_export,
11716 [INSTR_JMP_LT_MI] = instr_jmp_export,
11717 [INSTR_JMP_LT_HI] = instr_jmp_export,
11719 [INSTR_JMP_GT] = instr_jmp_export,
11720 [INSTR_JMP_GT_MH] = instr_jmp_export,
11721 [INSTR_JMP_GT_HM] = instr_jmp_export,
11722 [INSTR_JMP_GT_HH] = instr_jmp_export,
11723 [INSTR_JMP_GT_MI] = instr_jmp_export,
11724 [INSTR_JMP_GT_HI] = instr_jmp_export,
11726 [INSTR_RETURN] = instr_return_export,
11730 action_data_codegen(struct action *a, FILE *f)
11735 "static const struct instruction action_%s_instructions[] = {\n",
11738 for (i = 0; i < a->n_instructions; i++) {
11739 struct instruction *instr = &a->instructions[i];
11740 instruction_export_t func = export_table[instr->type];
11745 fprintf(f, "};\n");
11748 static const char *
11749 instr_type_to_func(struct instruction *instr)
11751 switch (instr->type) {
11752 case INSTR_RX: return NULL;
11754 case INSTR_TX: return "__instr_tx_exec";
11755 case INSTR_TX_I: return "__instr_tx_i_exec";
11756 case INSTR_DROP: return "__instr_drop_exec";
11757 case INSTR_MIRROR: return "__instr_mirror_exec";
11758 case INSTR_RECIRCULATE: return "__instr_recirculate_exec";
11759 case INSTR_RECIRCID: return "__instr_recircid_exec";
11761 case INSTR_HDR_EXTRACT: return "__instr_hdr_extract_exec";
11762 case INSTR_HDR_EXTRACT2: return "__instr_hdr_extract2_exec";
11763 case INSTR_HDR_EXTRACT3: return "__instr_hdr_extract3_exec";
11764 case INSTR_HDR_EXTRACT4: return "__instr_hdr_extract4_exec";
11765 case INSTR_HDR_EXTRACT5: return "__instr_hdr_extract5_exec";
11766 case INSTR_HDR_EXTRACT6: return "__instr_hdr_extract6_exec";
11767 case INSTR_HDR_EXTRACT7: return "__instr_hdr_extract7_exec";
11768 case INSTR_HDR_EXTRACT8: return "__instr_hdr_extract8_exec";
11770 case INSTR_HDR_EXTRACT_M: return "__instr_hdr_extract_m_exec";
11772 case INSTR_HDR_LOOKAHEAD: return "__instr_hdr_lookahead_exec";
11774 case INSTR_HDR_EMIT: return "__instr_hdr_emit_exec";
11775 case INSTR_HDR_EMIT_TX: return "__instr_hdr_emit_tx_exec";
11776 case INSTR_HDR_EMIT2_TX: return "__instr_hdr_emit2_tx_exec";
11777 case INSTR_HDR_EMIT3_TX: return "__instr_hdr_emit3_tx_exec";
11778 case INSTR_HDR_EMIT4_TX: return "__instr_hdr_emit4_tx_exec";
11779 case INSTR_HDR_EMIT5_TX: return "__instr_hdr_emit5_tx_exec";
11780 case INSTR_HDR_EMIT6_TX: return "__instr_hdr_emit6_tx_exec";
11781 case INSTR_HDR_EMIT7_TX: return "__instr_hdr_emit7_tx_exec";
11782 case INSTR_HDR_EMIT8_TX: return "__instr_hdr_emit8_tx_exec";
11784 case INSTR_HDR_VALIDATE: return "__instr_hdr_validate_exec";
11785 case INSTR_HDR_INVALIDATE: return "__instr_hdr_invalidate_exec";
11787 case INSTR_MOV: return "__instr_mov_exec";
11788 case INSTR_MOV_MH: return "__instr_mov_mh_exec";
11789 case INSTR_MOV_HM: return "__instr_mov_hm_exec";
11790 case INSTR_MOV_HH: return "__instr_mov_hh_exec";
11791 case INSTR_MOV_I: return "__instr_mov_i_exec";
11793 case INSTR_DMA_HT: return "__instr_dma_ht_exec";
11794 case INSTR_DMA_HT2: return "__instr_dma_ht2_exec";
11795 case INSTR_DMA_HT3: return "__instr_dma_ht3_exec";
11796 case INSTR_DMA_HT4: return "__instr_dma_ht4_exec";
11797 case INSTR_DMA_HT5: return "__instr_dma_ht5_exec";
11798 case INSTR_DMA_HT6: return "__instr_dma_ht6_exec";
11799 case INSTR_DMA_HT7: return "__instr_dma_ht7_exec";
11800 case INSTR_DMA_HT8: return "__instr_dma_ht8_exec";
11802 case INSTR_ALU_ADD: return "__instr_alu_add_exec";
11803 case INSTR_ALU_ADD_MH: return "__instr_alu_add_mh_exec";
11804 case INSTR_ALU_ADD_HM: return "__instr_alu_add_hm_exec";
11805 case INSTR_ALU_ADD_HH: return "__instr_alu_add_hh_exec";
11806 case INSTR_ALU_ADD_MI: return "__instr_alu_add_mi_exec";
11807 case INSTR_ALU_ADD_HI: return "__instr_alu_add_hi_exec";
11809 case INSTR_ALU_SUB: return "__instr_alu_sub_exec";
11810 case INSTR_ALU_SUB_MH: return "__instr_alu_sub_mh_exec";
11811 case INSTR_ALU_SUB_HM: return "__instr_alu_sub_hm_exec";
11812 case INSTR_ALU_SUB_HH: return "__instr_alu_sub_hh_exec";
11813 case INSTR_ALU_SUB_MI: return "__instr_alu_sub_mi_exec";
11814 case INSTR_ALU_SUB_HI: return "__instr_alu_sub_hi_exec";
11816 case INSTR_ALU_CKADD_FIELD: return "__instr_alu_ckadd_field_exec";
11817 case INSTR_ALU_CKADD_STRUCT20: return "__instr_alu_ckadd_struct20_exec";
11818 case INSTR_ALU_CKADD_STRUCT: return "__instr_alu_ckadd_struct_exec";
11819 case INSTR_ALU_CKSUB_FIELD: return "__instr_alu_cksub_field_exec";
11821 case INSTR_ALU_AND: return "__instr_alu_and_exec";
11822 case INSTR_ALU_AND_MH: return "__instr_alu_and_mh_exec";
11823 case INSTR_ALU_AND_HM: return "__instr_alu_and_hm_exec";
11824 case INSTR_ALU_AND_HH: return "__instr_alu_and_hh_exec";
11825 case INSTR_ALU_AND_I: return "__instr_alu_and_i_exec";
11827 case INSTR_ALU_OR: return "__instr_alu_or_exec";
11828 case INSTR_ALU_OR_MH: return "__instr_alu_or_mh_exec";
11829 case INSTR_ALU_OR_HM: return "__instr_alu_or_hm_exec";
11830 case INSTR_ALU_OR_HH: return "__instr_alu_or_hh_exec";
11831 case INSTR_ALU_OR_I: return "__instr_alu_or_i_exec";
11833 case INSTR_ALU_XOR: return "__instr_alu_xor_exec";
11834 case INSTR_ALU_XOR_MH: return "__instr_alu_xor_mh_exec";
11835 case INSTR_ALU_XOR_HM: return "__instr_alu_xor_hm_exec";
11836 case INSTR_ALU_XOR_HH: return "__instr_alu_xor_hh_exec";
11837 case INSTR_ALU_XOR_I: return "__instr_alu_xor_i_exec";
11839 case INSTR_ALU_SHL: return "__instr_alu_shl_exec";
11840 case INSTR_ALU_SHL_MH: return "__instr_alu_shl_mh_exec";
11841 case INSTR_ALU_SHL_HM: return "__instr_alu_shl_hm_exec";
11842 case INSTR_ALU_SHL_HH: return "__instr_alu_shl_hh_exec";
11843 case INSTR_ALU_SHL_MI: return "__instr_alu_shl_mi_exec";
11844 case INSTR_ALU_SHL_HI: return "__instr_alu_shl_hi_exec";
11846 case INSTR_ALU_SHR: return "__instr_alu_shr_exec";
11847 case INSTR_ALU_SHR_MH: return "__instr_alu_shr_mh_exec";
11848 case INSTR_ALU_SHR_HM: return "__instr_alu_shr_hm_exec";
11849 case INSTR_ALU_SHR_HH: return "__instr_alu_shr_hh_exec";
11850 case INSTR_ALU_SHR_MI: return "__instr_alu_shr_mi_exec";
11851 case INSTR_ALU_SHR_HI: return "__instr_alu_shr_hi_exec";
11853 case INSTR_REGPREFETCH_RH: return "__instr_regprefetch_rh_exec";
11854 case INSTR_REGPREFETCH_RM: return "__instr_regprefetch_rm_exec";
11855 case INSTR_REGPREFETCH_RI: return "__instr_regprefetch_ri_exec";
11857 case INSTR_REGRD_HRH: return "__instr_regrd_hrh_exec";
11858 case INSTR_REGRD_HRM: return "__instr_regrd_hrm_exec";
11859 case INSTR_REGRD_HRI: return "__instr_regrd_hri_exec";
11860 case INSTR_REGRD_MRH: return "__instr_regrd_mrh_exec";
11861 case INSTR_REGRD_MRM: return "__instr_regrd_mrm_exec";
11862 case INSTR_REGRD_MRI: return "__instr_regrd_mri_exec";
11864 case INSTR_REGWR_RHH: return "__instr_regwr_rhh_exec";
11865 case INSTR_REGWR_RHM: return "__instr_regwr_rhm_exec";
11866 case INSTR_REGWR_RHI: return "__instr_regwr_rhi_exec";
11867 case INSTR_REGWR_RMH: return "__instr_regwr_rmh_exec";
11868 case INSTR_REGWR_RMM: return "__instr_regwr_rmm_exec";
11869 case INSTR_REGWR_RMI: return "__instr_regwr_rmi_exec";
11870 case INSTR_REGWR_RIH: return "__instr_regwr_rih_exec";
11871 case INSTR_REGWR_RIM: return "__instr_regwr_rim_exec";
11872 case INSTR_REGWR_RII: return "__instr_regwr_rii_exec";
11874 case INSTR_REGADD_RHH: return "__instr_regadd_rhh_exec";
11875 case INSTR_REGADD_RHM: return "__instr_regadd_rhm_exec";
11876 case INSTR_REGADD_RHI: return "__instr_regadd_rhi_exec";
11877 case INSTR_REGADD_RMH: return "__instr_regadd_rmh_exec";
11878 case INSTR_REGADD_RMM: return "__instr_regadd_rmm_exec";
11879 case INSTR_REGADD_RMI: return "__instr_regadd_rmi_exec";
11880 case INSTR_REGADD_RIH: return "__instr_regadd_rih_exec";
11881 case INSTR_REGADD_RIM: return "__instr_regadd_rim_exec";
11882 case INSTR_REGADD_RII: return "__instr_regadd_rii_exec";
11884 case INSTR_METPREFETCH_H: return "__instr_metprefetch_h_exec";
11885 case INSTR_METPREFETCH_M: return "__instr_metprefetch_m_exec";
11886 case INSTR_METPREFETCH_I: return "__instr_metprefetch_i_exec";
11888 case INSTR_METER_HHM: return "__instr_meter_hhm_exec";
11889 case INSTR_METER_HHI: return "__instr_meter_hhi_exec";
11890 case INSTR_METER_HMM: return "__instr_meter_hmm_exec";
11891 case INSTR_METER_HMI: return "__instr_meter_hmi_exec";
11892 case INSTR_METER_MHM: return "__instr_meter_mhm_exec";
11893 case INSTR_METER_MHI: return "__instr_meter_mhi_exec";
11894 case INSTR_METER_MMM: return "__instr_meter_mmm_exec";
11895 case INSTR_METER_MMI: return "__instr_meter_mmi_exec";
11896 case INSTR_METER_IHM: return "__instr_meter_ihm_exec";
11897 case INSTR_METER_IHI: return "__instr_meter_ihi_exec";
11898 case INSTR_METER_IMM: return "__instr_meter_imm_exec";
11899 case INSTR_METER_IMI: return "__instr_meter_imi_exec";
11901 case INSTR_TABLE: return NULL;
11902 case INSTR_TABLE_AF: return NULL;
11903 case INSTR_SELECTOR: return NULL;
11904 case INSTR_LEARNER: return NULL;
11905 case INSTR_LEARNER_AF: return NULL;
11907 case INSTR_LEARNER_LEARN: return "__instr_learn_exec";
11908 case INSTR_LEARNER_REARM: return "__instr_rearm_exec";
11909 case INSTR_LEARNER_REARM_NEW: return "__instr_rearm_new_exec";
11910 case INSTR_LEARNER_FORGET: return "__instr_forget_exec";
11912 case INSTR_EXTERN_OBJ: return NULL;
11913 case INSTR_EXTERN_FUNC: return NULL;
11915 case INSTR_JMP: return NULL;
11916 case INSTR_JMP_VALID: return NULL;
11917 case INSTR_JMP_INVALID: return NULL;
11918 case INSTR_JMP_HIT: return NULL;
11919 case INSTR_JMP_MISS: return NULL;
11920 case INSTR_JMP_ACTION_HIT: return NULL;
11921 case INSTR_JMP_ACTION_MISS: return NULL;
11922 case INSTR_JMP_EQ: return NULL;
11923 case INSTR_JMP_EQ_MH: return NULL;
11924 case INSTR_JMP_EQ_HM: return NULL;
11925 case INSTR_JMP_EQ_HH: return NULL;
11926 case INSTR_JMP_EQ_I: return NULL;
11927 case INSTR_JMP_NEQ: return NULL;
11928 case INSTR_JMP_NEQ_MH: return NULL;
11929 case INSTR_JMP_NEQ_HM: return NULL;
11930 case INSTR_JMP_NEQ_HH: return NULL;
11931 case INSTR_JMP_NEQ_I: return NULL;
11932 case INSTR_JMP_LT: return NULL;
11933 case INSTR_JMP_LT_MH: return NULL;
11934 case INSTR_JMP_LT_HM: return NULL;
11935 case INSTR_JMP_LT_HH: return NULL;
11936 case INSTR_JMP_LT_MI: return NULL;
11937 case INSTR_JMP_LT_HI: return NULL;
11938 case INSTR_JMP_GT: return NULL;
11939 case INSTR_JMP_GT_MH: return NULL;
11940 case INSTR_JMP_GT_HM: return NULL;
11941 case INSTR_JMP_GT_HH: return NULL;
11942 case INSTR_JMP_GT_MI: return NULL;
11943 case INSTR_JMP_GT_HI: return NULL;
11945 case INSTR_RETURN: return NULL;
11947 default: return NULL;
11952 action_instr_does_tx_codegen(struct action *a,
11953 uint32_t instr_pos,
11954 struct instruction *instr,
11958 "%s(p, t, &action_%s_instructions[%u]);\n"
11959 "\tthread_ip_reset(p, t);\n"
11960 "\tinstr_rx_exec(p);\n"
11962 instr_type_to_func(instr),
11968 action_instr_extern_obj_codegen(struct action *a,
11969 uint32_t instr_pos,
11973 "while (!__instr_extern_obj_exec(p, t, &action_%s_instructions[%u]));\n",
11979 action_instr_extern_func_codegen(struct action *a,
11980 uint32_t instr_pos,
11984 "while (!__instr_extern_func_exec(p, t, &action_%s_instructions[%u]));\n",
11990 action_instr_jmp_codegen(struct action *a,
11991 uint32_t instr_pos,
11992 struct instruction *instr,
11993 struct instruction_data *data,
11996 switch (instr->type) {
12003 case INSTR_JMP_VALID:
12005 "if (HEADER_VALID(t, action_%s_instructions[%u].jmp.header_id))\n"
12012 case INSTR_JMP_INVALID:
12014 "if (!HEADER_VALID(t, action_%s_instructions[%u].jmp.header_id))\n"
12021 case INSTR_JMP_HIT:
12028 case INSTR_JMP_MISS:
12035 case INSTR_JMP_ACTION_HIT:
12037 "if (t->action_id == action_%s_instructions[%u].jmp.action_id)\n"
12044 case INSTR_JMP_ACTION_MISS:
12046 "if (t->action_id != action_%s_instructions[%u].jmp.action_id)\n"
12055 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) == "
12056 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
12065 case INSTR_JMP_EQ_MH:
12067 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) == "
12068 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
12077 case INSTR_JMP_EQ_HM:
12079 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) == "
12080 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
12089 case INSTR_JMP_EQ_HH:
12091 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) == "
12092 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
12101 case INSTR_JMP_EQ_I:
12103 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) == "
12104 "action_%s_instructions[%u].jmp.b_val)\n"
12113 case INSTR_JMP_NEQ:
12115 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) != "
12116 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
12125 case INSTR_JMP_NEQ_MH:
12127 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) != "
12128 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
12137 case INSTR_JMP_NEQ_HM:
12139 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) != "
12140 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
12149 case INSTR_JMP_NEQ_HH:
12151 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) != "
12152 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
12161 case INSTR_JMP_NEQ_I:
12163 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) != "
12164 "action_%s_instructions[%u].jmp.b_val)\n"
12175 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) < "
12176 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
12185 case INSTR_JMP_LT_MH:
12187 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) < "
12188 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
12197 case INSTR_JMP_LT_HM:
12199 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) < "
12200 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
12209 case INSTR_JMP_LT_HH:
12211 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) < "
12212 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
12221 case INSTR_JMP_LT_MI:
12223 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) < "
12224 "action_%s_instructions[%u].jmp.b_val)\n"
12233 case INSTR_JMP_LT_HI:
12235 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) < "
12236 "action_%s_instructions[%u].jmp.b_val)\n"
12247 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) > "
12248 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
12257 case INSTR_JMP_GT_MH:
12259 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) > "
12260 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
12269 case INSTR_JMP_GT_HM:
12271 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) > "
12272 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
12281 case INSTR_JMP_GT_HH:
12283 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) > "
12284 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
12293 case INSTR_JMP_GT_MI:
12295 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) > "
12296 "action_%s_instructions[%u].jmp.b_val)\n"
12305 case INSTR_JMP_GT_HI:
12307 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) > "
12308 "action_%s_instructions[%u].jmp.b_val)\n"
12323 action_instr_return_codegen(FILE *f)
12330 action_instr_codegen(struct action *a, FILE *f)
12336 "action_%s_run(struct rte_swx_pipeline *p)\n"
12338 "\tstruct thread *t = &p->threads[p->thread_id];\n"
12342 for (i = 0; i < a->n_instructions; i++) {
12343 struct instruction *instr = &a->instructions[i];
12344 struct instruction_data *data = &a->instruction_data[i];
12346 /* Label, if present. */
12347 if (data->label[0])
12348 fprintf(f, "\n%s : ", data->label);
12350 fprintf(f, "\n\t");
12352 /* TX instruction type. */
12353 if (instruction_does_tx(instr)) {
12354 action_instr_does_tx_codegen(a, i, instr, f);
12358 /* Extern object/function instruction type. */
12359 if (instr->type == INSTR_EXTERN_OBJ) {
12360 action_instr_extern_obj_codegen(a, i, f);
12364 if (instr->type == INSTR_EXTERN_FUNC) {
12365 action_instr_extern_func_codegen(a, i, f);
12369 /* Jump instruction type. */
12370 if (instruction_is_jmp(instr)) {
12371 action_instr_jmp_codegen(a, i, instr, data, f);
12375 /* Return instruction type. */
12376 if (instr->type == INSTR_RETURN) {
12377 action_instr_return_codegen(f);
12381 /* Any other instruction type. */
12383 "%s(p, t, &action_%s_instructions[%u]);\n",
12384 instr_type_to_func(instr),
12389 fprintf(f, "}\n\n");
12392 struct instruction_group {
12393 TAILQ_ENTRY(instruction_group) node;
12397 uint32_t first_instr_id;
12399 uint32_t last_instr_id;
12404 TAILQ_HEAD(instruction_group_list, instruction_group);
12406 static struct instruction_group *
12407 instruction_group_list_group_find(struct instruction_group_list *igl, uint32_t instruction_id)
12409 struct instruction_group *g;
12411 TAILQ_FOREACH(g, igl, node)
12412 if ((g->first_instr_id <= instruction_id) && (instruction_id <= g->last_instr_id))
12419 instruction_group_list_free(struct instruction_group_list *igl)
12425 struct instruction_group *g;
12427 g = TAILQ_FIRST(igl);
12431 TAILQ_REMOVE(igl, g, node);
12438 static struct instruction_group_list *
12439 instruction_group_list_create(struct rte_swx_pipeline *p)
12441 struct instruction_group_list *igl = NULL;
12442 struct instruction_group *g = NULL;
12443 uint32_t n_groups = 0, i;
12445 if (!p || !p->instructions || !p->instruction_data || !p->n_instructions)
12449 igl = calloc(1, sizeof(struct instruction_group_list));
12455 /* Allocate the first group. */
12456 g = calloc(1, sizeof(struct instruction_group));
12460 /* Iteration 1: Separate the instructions into groups based on the thread yield
12461 * instructions. Do not worry about the jump instructions at this point.
12463 for (i = 0; i < p->n_instructions; i++) {
12464 struct instruction *instr = &p->instructions[i];
12466 /* Check for thread yield instructions. */
12467 if (!instruction_does_thread_yield(instr))
12470 /* If the current group contains at least one instruction, then finalize it (with
12471 * the previous instruction), add it to the list and allocate a new group (that
12472 * starts with the current instruction).
12474 if (i - g->first_instr_id) {
12475 /* Finalize the group. */
12476 g->last_instr_id = i - 1;
12478 /* Add the group to the list. Advance the number of groups. */
12479 TAILQ_INSERT_TAIL(igl, g, node);
12482 /* Allocate a new group. */
12483 g = calloc(1, sizeof(struct instruction_group));
12487 /* Initialize the new group. */
12488 g->group_id = n_groups;
12489 g->first_instr_id = i;
12492 /* Finalize the current group (with the current instruction, therefore this group
12493 * contains just the current thread yield instruction), add it to the list and
12494 * allocate a new group (that starts with the next instruction).
12497 /* Finalize the group. */
12498 g->last_instr_id = i;
12500 /* Add the group to the list. Advance the number of groups. */
12501 TAILQ_INSERT_TAIL(igl, g, node);
12504 /* Allocate a new group. */
12505 g = calloc(1, sizeof(struct instruction_group));
12509 /* Initialize the new group. */
12510 g->group_id = n_groups;
12511 g->first_instr_id = i + 1;
12514 /* Handle the last group. */
12515 if (i - g->first_instr_id) {
12516 /* Finalize the group. */
12517 g->last_instr_id = i - 1;
12519 /* Add the group to the list. Advance the number of groups. */
12520 TAILQ_INSERT_TAIL(igl, g, node);
12527 /* Iteration 2: Handle jumps. If the current group contains an instruction which represents
12528 * the destination of a jump instruction located in a different group ("far jump"), then the
12529 * current group has to be split, so that the instruction representing the far jump
12530 * destination is at the start of its group.
12533 int is_modified = 0;
12535 for (i = 0; i < p->n_instructions; i++) {
12536 struct instruction_data *data = &p->instruction_data[i];
12537 struct instruction_group *g;
12540 /* Continue when the current instruction is not a jump destination. */
12541 if (!data->n_users)
12544 g = instruction_group_list_group_find(igl, i);
12548 /* Find out all the jump instructions with this destination. */
12549 for (j = 0; j < p->n_instructions; j++) {
12550 struct instruction *jmp_instr = &p->instructions[j];
12551 struct instruction_data *jmp_data = &p->instruction_data[j];
12552 struct instruction_group *jmp_g, *new_g;
12554 /* Continue when not a jump instruction. Even when jump instruction,
12555 * continue when the jump destination is not this instruction.
12557 if (!instruction_is_jmp(jmp_instr) ||
12558 strcmp(jmp_data->jmp_label, data->label))
12561 jmp_g = instruction_group_list_group_find(igl, j);
12565 /* Continue when both the jump instruction and the jump destination
12566 * instruction are in the same group. Even when in different groups,
12567 * still continue if the jump destination instruction is already the
12568 * first instruction of its group.
12570 if ((jmp_g->group_id == g->group_id) || (g->first_instr_id == i))
12573 /* Split the group of the current jump destination instruction to
12574 * make this instruction the first instruction of a new group.
12576 new_g = calloc(1, sizeof(struct instruction_group));
12580 new_g->group_id = n_groups;
12581 new_g->first_instr_id = i;
12582 new_g->last_instr_id = g->last_instr_id;
12584 g->last_instr_id = i - 1;
12586 TAILQ_INSERT_AFTER(igl, g, new_g, node);
12590 /* The decision to split this group (to make the current instruction
12591 * the first instruction of a new group) is already taken and fully
12592 * implemented, so no need to search for more reasons to do it.
12598 /* Re-evaluate everything, as at least one group got split, so some jumps that were
12599 * previously considered local (i.e. the jump destination is in the same group as
12600 * the jump instruction) can now be "far jumps" (i.e. the jump destination is in a
12601 * different group than the jump instruction). Wost case scenario: each instruction
12602 * that is a jump destination ends up as the first instruction of its group.
12608 /* Re-assign the group IDs to be in incremental order. */
12610 TAILQ_FOREACH(g, igl, node) {
12619 instruction_group_list_free(igl);
12627 pipeline_instr_does_tx_codegen(struct rte_swx_pipeline *p __rte_unused,
12628 uint32_t instr_pos,
12629 struct instruction *instr,
12633 "%s(p, t, &pipeline_instructions[%u]);\n"
12634 "\tthread_ip_reset(p, t);\n"
12635 "\tinstr_rx_exec(p);\n"
12637 instr_type_to_func(instr),
12642 pipeline_instr_jmp_codegen(struct rte_swx_pipeline *p,
12643 struct instruction_group_list *igl,
12644 uint32_t jmp_instr_id,
12645 struct instruction *jmp_instr,
12646 struct instruction_data *jmp_data,
12649 struct instruction_group *jmp_g, *g;
12650 struct instruction_data *data;
12653 switch (jmp_instr->type) {
12657 case INSTR_JMP_VALID:
12659 "if (HEADER_VALID(t, pipeline_instructions[%u].jmp.header_id))",
12663 case INSTR_JMP_INVALID:
12665 "if (!HEADER_VALID(t, pipeline_instructions[%u].jmp.header_id))",
12669 case INSTR_JMP_HIT:
12674 case INSTR_JMP_MISS:
12679 case INSTR_JMP_ACTION_HIT:
12681 "if (t->action_id == pipeline_instructions[%u].jmp.action_id)",
12685 case INSTR_JMP_ACTION_MISS:
12687 "if (t->action_id != pipeline_instructions[%u].jmp.action_id)",
12693 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) == "
12694 "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
12699 case INSTR_JMP_EQ_MH:
12701 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) == "
12702 "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
12707 case INSTR_JMP_EQ_HM:
12709 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) == "
12710 "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
12715 case INSTR_JMP_EQ_HH:
12717 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) == "
12718 "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
12723 case INSTR_JMP_EQ_I:
12725 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) == "
12726 "pipeline_instructions[%u].jmp.b_val)",
12731 case INSTR_JMP_NEQ:
12733 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) != "
12734 "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
12739 case INSTR_JMP_NEQ_MH:
12741 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) != "
12742 "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
12747 case INSTR_JMP_NEQ_HM:
12749 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) != "
12750 "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
12755 case INSTR_JMP_NEQ_HH:
12757 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) != "
12758 "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
12763 case INSTR_JMP_NEQ_I:
12765 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) != "
12766 "pipeline_instructions[%u].jmp.b_val)",
12773 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) < "
12774 "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
12779 case INSTR_JMP_LT_MH:
12781 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) < "
12782 "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
12787 case INSTR_JMP_LT_HM:
12789 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) < "
12790 "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
12795 case INSTR_JMP_LT_HH:
12797 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) < "
12798 "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
12803 case INSTR_JMP_LT_MI:
12805 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) < "
12806 "pipeline_instructions[%u].jmp.b_val)",
12811 case INSTR_JMP_LT_HI:
12813 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) < "
12814 "pipeline_instructions[%u].jmp.b_val)",
12821 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) > "
12822 "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
12827 case INSTR_JMP_GT_MH:
12829 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) > "
12830 "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
12835 case INSTR_JMP_GT_HM:
12837 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) > "
12838 "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
12843 case INSTR_JMP_GT_HH:
12845 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) > "
12846 "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
12851 case INSTR_JMP_GT_MI:
12853 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) > "
12854 "pipeline_instructions[%u].jmp.b_val)",
12859 case INSTR_JMP_GT_HI:
12861 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) > "
12862 "pipeline_instructions[%u].jmp.b_val)",
12871 /* Find the instruction group of the jump instruction. */
12872 jmp_g = instruction_group_list_group_find(igl, jmp_instr_id);
12876 /* Find the instruction group of the jump destination instruction. */
12877 data = label_find(p->instruction_data, p->n_instructions, jmp_data->jmp_label);
12881 instr_id = data - p->instruction_data;
12883 g = instruction_group_list_group_find(igl, instr_id);
12887 /* Code generation for "near" jump (same instruction group) or "far" jump (different
12888 * instruction group).
12890 if (g->group_id == jmp_g->group_id)
12892 "\n\t\tgoto %s;\n",
12893 jmp_data->jmp_label);
12897 "\t\tthread_ip_set(t, &p->instructions[%u]);\n"
12906 instruction_group_list_codegen(struct instruction_group_list *igl,
12907 struct rte_swx_pipeline *p,
12910 struct instruction_group *g;
12912 int is_required = 0;
12914 /* Check if code generation is required. */
12915 TAILQ_FOREACH(g, igl, node)
12916 if (g->first_instr_id < g->last_instr_id)
12922 /* Generate the code for the pipeline instruction array. */
12924 "static const struct instruction pipeline_instructions[] = {\n");
12926 for (i = 0; i < p->n_instructions; i++) {
12927 struct instruction *instr = &p->instructions[i];
12928 instruction_export_t func = export_table[instr->type];
12933 fprintf(f, "};\n\n");
12935 /* Generate the code for the pipeline functions: one function for each instruction group
12936 * that contains more than one instruction.
12938 TAILQ_FOREACH(g, igl, node) {
12939 struct instruction *last_instr;
12942 /* Skip if group contains a single instruction. */
12943 if (g->last_instr_id == g->first_instr_id)
12946 /* Generate new pipeline function. */
12949 "pipeline_func_%u(struct rte_swx_pipeline *p)\n"
12951 "\tstruct thread *t = &p->threads[p->thread_id];\n"
12955 /* Generate the code for each pipeline instruction. */
12956 for (j = g->first_instr_id; j <= g->last_instr_id; j++) {
12957 struct instruction *instr = &p->instructions[j];
12958 struct instruction_data *data = &p->instruction_data[j];
12960 /* Label, if present. */
12961 if (data->label[0])
12962 fprintf(f, "\n%s : ", data->label);
12964 fprintf(f, "\n\t");
12966 /* TX instruction type. */
12967 if (instruction_does_tx(instr)) {
12968 pipeline_instr_does_tx_codegen(p, j, instr, f);
12972 /* Jump instruction type. */
12973 if (instruction_is_jmp(instr)) {
12974 pipeline_instr_jmp_codegen(p, igl, j, instr, data, f);
12978 /* Any other instruction type. */
12980 "%s(p, t, &pipeline_instructions[%u]);\n",
12981 instr_type_to_func(instr),
12985 /* Finalize the generated pipeline function. For some instructions such as TX,
12986 * emit-many-and-TX and unconditional jump, the next instruction has been already
12987 * decided unconditionally and the instruction pointer of the current thread set
12988 * accordingly; for all the other instructions, the instruction pointer must be
12991 last_instr = &p->instructions[g->last_instr_id];
12993 if (!instruction_does_tx(last_instr) && (last_instr->type != INSTR_JMP))
12995 "thread_ip_inc(p);\n");
13004 instruction_group_list_custom_instructions_count(struct instruction_group_list *igl)
13006 struct instruction_group *g;
13007 uint32_t n_custom_instr = 0;
13009 /* Groups with a single instruction: no function is generated for this group, the group
13010 * keeps its current instruction. Groups with more than two instructions: one function and
13011 * the associated custom instruction get generated for each such group.
13013 TAILQ_FOREACH(g, igl, node) {
13014 if (g->first_instr_id == g->last_instr_id)
13020 return n_custom_instr;
13024 pipeline_codegen(struct rte_swx_pipeline *p, struct instruction_group_list *igl)
13029 /* Create the .c file. */
13030 f = fopen("/tmp/pipeline.c", "w");
13034 /* Include the .h file. */
13035 fprintf(f, "#include \"rte_swx_pipeline_internal.h\"\n");
13037 /* Add the code for each action. */
13038 TAILQ_FOREACH(a, &p->actions, node) {
13039 fprintf(f, "/**\n * Action %s\n */\n\n", a->name);
13041 action_data_codegen(a, f);
13045 action_instr_codegen(a, f);
13050 /* Add the pipeline code. */
13051 instruction_group_list_codegen(igl, p, f);
13053 /* Close the .c file. */
13059 #ifndef RTE_SWX_PIPELINE_CMD_MAX_SIZE
13060 #define RTE_SWX_PIPELINE_CMD_MAX_SIZE 4096
13064 pipeline_libload(struct rte_swx_pipeline *p, struct instruction_group_list *igl)
13067 struct instruction_group *g;
13068 char *dir_in, *buffer = NULL;
13069 const char *dir_out;
13072 /* Get the environment variables. */
13073 dir_in = getenv("RTE_INSTALL_DIR");
13081 /* Memory allocation for the command buffer. */
13082 buffer = malloc(RTE_SWX_PIPELINE_CMD_MAX_SIZE);
13089 RTE_SWX_PIPELINE_CMD_MAX_SIZE,
13090 "gcc -c -O3 -fpic -Wno-deprecated-declarations -o %s/pipeline.o %s/pipeline.c "
13091 "-I %s/lib/pipeline "
13092 "-I %s/lib/eal/include "
13093 "-I %s/lib/eal/x86/include "
13094 "-I %s/lib/eal/include/generic "
13098 "-I %s/lib/pipeline "
13101 "-I %s/lib/eal/linux/include "
13102 ">%s/pipeline.log 2>&1 "
13104 "gcc -shared %s/pipeline.o -o %s/libpipeline.so "
13105 ">>%s/pipeline.log 2>&1",
13124 /* Build the shared object library. */
13125 status = system(buffer);
13129 /* Open library. */
13131 RTE_SWX_PIPELINE_CMD_MAX_SIZE,
13132 "%s/libpipeline.so",
13135 p->lib = dlopen(buffer, RTLD_LAZY);
13141 /* Get the action function symbols. */
13142 TAILQ_FOREACH(a, &p->actions, node) {
13143 snprintf(buffer, RTE_SWX_PIPELINE_CMD_MAX_SIZE, "action_%s_run", a->name);
13145 p->action_funcs[a->id] = dlsym(p->lib, buffer);
13146 if (!p->action_funcs[a->id]) {
13152 /* Get the pipeline function symbols. */
13153 TAILQ_FOREACH(g, igl, node) {
13154 if (g->first_instr_id == g->last_instr_id)
13157 snprintf(buffer, RTE_SWX_PIPELINE_CMD_MAX_SIZE, "pipeline_func_%u", g->group_id);
13159 g->func = dlsym(p->lib, buffer);
13167 if (status && p->lib) {
13178 pipeline_adjust_check(struct rte_swx_pipeline *p __rte_unused,
13179 struct instruction_group_list *igl)
13181 uint32_t n_custom_instr = instruction_group_list_custom_instructions_count(igl);
13183 /* Check that enough space is available within the pipeline instruction table to store all
13184 * the custom instructions.
13186 if (INSTR_CUSTOM_0 + n_custom_instr > RTE_SWX_PIPELINE_INSTRUCTION_TABLE_SIZE_MAX)
13193 pipeline_adjust(struct rte_swx_pipeline *p, struct instruction_group_list *igl)
13195 struct instruction_group *g;
13198 /* Pipeline table instructions. */
13199 for (i = 0; i < p->n_instructions; i++) {
13200 struct instruction *instr = &p->instructions[i];
13202 if (instr->type == INSTR_TABLE)
13203 instr->type = INSTR_TABLE_AF;
13205 if (instr->type == INSTR_LEARNER)
13206 instr->type = INSTR_LEARNER_AF;
13209 /* Pipeline custom instructions. */
13211 TAILQ_FOREACH(g, igl, node) {
13212 struct instruction *instr = &p->instructions[g->first_instr_id];
13215 if (g->first_instr_id == g->last_instr_id)
13218 /* Install a new custom instruction. */
13219 p->instruction_table[INSTR_CUSTOM_0 + i] = g->func;
13221 /* First instruction of the group: change its type to the new custom instruction. */
13222 instr->type = INSTR_CUSTOM_0 + i;
13224 /* All the subsequent instructions of the group: invalidate. */
13225 for (j = g->first_instr_id + 1; j <= g->last_instr_id; j++) {
13226 struct instruction_data *data = &p->instruction_data[j];
13234 /* Remove the invalidated instructions. */
13235 p->n_instructions = instr_compact(p->instructions, p->instruction_data, p->n_instructions);
13237 /* Resolve the jump destination for any "standalone" jump instructions (i.e. those jump
13238 * instructions that are the only instruction within their group, so they were left
13241 instr_jmp_resolve(p->instructions, p->instruction_data, p->n_instructions);
13245 pipeline_compile(struct rte_swx_pipeline *p)
13247 struct instruction_group_list *igl = NULL;
13250 igl = instruction_group_list_create(p);
13256 /* Code generation. */
13257 status = pipeline_codegen(p, igl);
13261 /* Build and load the shared object library. */
13262 status = pipeline_libload(p, igl);
13266 /* Adjust instructions. */
13267 status = pipeline_adjust_check(p, igl);
13271 pipeline_adjust(p, igl);
13274 instruction_group_list_free(igl);