1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2020 Intel Corporation
10 #include "rte_swx_pipeline_internal.h"
12 #define CHECK(condition, err_code) \
18 #define CHECK_NAME(name, err_code) \
21 (strnlen((name), RTE_SWX_NAME_SIZE) < RTE_SWX_NAME_SIZE), \
24 #define CHECK_INSTRUCTION(instr, err_code) \
27 (strnlen((instr), RTE_SWX_INSTRUCTION_SIZE) < \
28 RTE_SWX_INSTRUCTION_SIZE), \
34 #ifndef RTE_SWX_PIPELINE_HUGE_PAGES_DISABLE
36 #include <rte_malloc.h>
39 env_malloc(size_t size, size_t alignment, int numa_node)
41 return rte_zmalloc_socket(NULL, size, alignment, numa_node);
45 env_free(void *start, size_t size __rte_unused)
55 env_malloc(size_t size, size_t alignment __rte_unused, int numa_node)
59 if (numa_available() == -1)
62 start = numa_alloc_onnode(size, numa_node);
66 memset(start, 0, size);
71 env_free(void *start, size_t size)
73 if (numa_available() == -1)
76 numa_free(start, size);
84 static struct struct_type *
85 struct_type_find(struct rte_swx_pipeline *p, const char *name)
87 struct struct_type *elem;
89 TAILQ_FOREACH(elem, &p->struct_types, node)
90 if (strcmp(elem->name, name) == 0)
97 struct_type_field_find(struct struct_type *st, const char *name)
101 for (i = 0; i < st->n_fields; i++) {
102 struct field *f = &st->fields[i];
104 if (strcmp(f->name, name) == 0)
112 rte_swx_pipeline_struct_type_register(struct rte_swx_pipeline *p,
114 struct rte_swx_field_params *fields,
116 int last_field_has_variable_size)
118 struct struct_type *st;
122 CHECK_NAME(name, EINVAL);
123 CHECK(fields, EINVAL);
124 CHECK(n_fields, EINVAL);
126 for (i = 0; i < n_fields; i++) {
127 struct rte_swx_field_params *f = &fields[i];
128 int var_size = ((i == n_fields - 1) && last_field_has_variable_size) ? 1 : 0;
131 CHECK_NAME(f->name, EINVAL);
132 CHECK(f->n_bits, EINVAL);
133 CHECK((f->n_bits <= 64) || var_size, EINVAL);
134 CHECK((f->n_bits & 7) == 0, EINVAL);
136 for (j = 0; j < i; j++) {
137 struct rte_swx_field_params *f_prev = &fields[j];
139 CHECK(strcmp(f->name, f_prev->name), EINVAL);
143 CHECK(!struct_type_find(p, name), EEXIST);
145 /* Node allocation. */
146 st = calloc(1, sizeof(struct struct_type));
149 st->fields = calloc(n_fields, sizeof(struct field));
155 /* Node initialization. */
156 strcpy(st->name, name);
157 for (i = 0; i < n_fields; i++) {
158 struct field *dst = &st->fields[i];
159 struct rte_swx_field_params *src = &fields[i];
160 int var_size = ((i == n_fields - 1) && last_field_has_variable_size) ? 1 : 0;
162 strcpy(dst->name, src->name);
163 dst->n_bits = src->n_bits;
164 dst->offset = st->n_bits;
165 dst->var_size = var_size;
167 st->n_bits += src->n_bits;
168 st->n_bits_min += var_size ? 0 : src->n_bits;
170 st->n_fields = n_fields;
171 st->var_size = last_field_has_variable_size;
173 /* Node add to tailq. */
174 TAILQ_INSERT_TAIL(&p->struct_types, st, node);
180 struct_build(struct rte_swx_pipeline *p)
184 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
185 struct thread *t = &p->threads[i];
187 t->structs = calloc(p->n_structs, sizeof(uint8_t *));
188 CHECK(t->structs, ENOMEM);
195 struct_build_free(struct rte_swx_pipeline *p)
199 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
200 struct thread *t = &p->threads[i];
208 struct_free(struct rte_swx_pipeline *p)
210 struct_build_free(p);
214 struct struct_type *elem;
216 elem = TAILQ_FIRST(&p->struct_types);
220 TAILQ_REMOVE(&p->struct_types, elem, node);
229 static struct port_in_type *
230 port_in_type_find(struct rte_swx_pipeline *p, const char *name)
232 struct port_in_type *elem;
237 TAILQ_FOREACH(elem, &p->port_in_types, node)
238 if (strcmp(elem->name, name) == 0)
245 rte_swx_pipeline_port_in_type_register(struct rte_swx_pipeline *p,
247 struct rte_swx_port_in_ops *ops)
249 struct port_in_type *elem;
252 CHECK_NAME(name, EINVAL);
254 CHECK(ops->create, EINVAL);
255 CHECK(ops->free, EINVAL);
256 CHECK(ops->pkt_rx, EINVAL);
257 CHECK(ops->stats_read, EINVAL);
259 CHECK(!port_in_type_find(p, name), EEXIST);
261 /* Node allocation. */
262 elem = calloc(1, sizeof(struct port_in_type));
265 /* Node initialization. */
266 strcpy(elem->name, name);
267 memcpy(&elem->ops, ops, sizeof(*ops));
269 /* Node add to tailq. */
270 TAILQ_INSERT_TAIL(&p->port_in_types, elem, node);
275 static struct port_in *
276 port_in_find(struct rte_swx_pipeline *p, uint32_t port_id)
278 struct port_in *port;
280 TAILQ_FOREACH(port, &p->ports_in, node)
281 if (port->id == port_id)
288 rte_swx_pipeline_port_in_config(struct rte_swx_pipeline *p,
290 const char *port_type_name,
293 struct port_in_type *type = NULL;
294 struct port_in *port = NULL;
299 CHECK(!port_in_find(p, port_id), EINVAL);
301 CHECK_NAME(port_type_name, EINVAL);
302 type = port_in_type_find(p, port_type_name);
305 obj = type->ops.create(args);
308 /* Node allocation. */
309 port = calloc(1, sizeof(struct port_in));
312 /* Node initialization. */
317 /* Node add to tailq. */
318 TAILQ_INSERT_TAIL(&p->ports_in, port, node);
319 if (p->n_ports_in < port_id + 1)
320 p->n_ports_in = port_id + 1;
326 port_in_build(struct rte_swx_pipeline *p)
328 struct port_in *port;
331 CHECK(p->n_ports_in, EINVAL);
332 CHECK(rte_is_power_of_2(p->n_ports_in), EINVAL);
334 for (i = 0; i < p->n_ports_in; i++)
335 CHECK(port_in_find(p, i), EINVAL);
337 p->in = calloc(p->n_ports_in, sizeof(struct port_in_runtime));
338 CHECK(p->in, ENOMEM);
340 TAILQ_FOREACH(port, &p->ports_in, node) {
341 struct port_in_runtime *in = &p->in[port->id];
343 in->pkt_rx = port->type->ops.pkt_rx;
351 port_in_build_free(struct rte_swx_pipeline *p)
358 port_in_free(struct rte_swx_pipeline *p)
360 port_in_build_free(p);
364 struct port_in *port;
366 port = TAILQ_FIRST(&p->ports_in);
370 TAILQ_REMOVE(&p->ports_in, port, node);
371 port->type->ops.free(port->obj);
375 /* Input port types. */
377 struct port_in_type *elem;
379 elem = TAILQ_FIRST(&p->port_in_types);
383 TAILQ_REMOVE(&p->port_in_types, elem, node);
391 static struct port_out_type *
392 port_out_type_find(struct rte_swx_pipeline *p, const char *name)
394 struct port_out_type *elem;
399 TAILQ_FOREACH(elem, &p->port_out_types, node)
400 if (!strcmp(elem->name, name))
407 rte_swx_pipeline_port_out_type_register(struct rte_swx_pipeline *p,
409 struct rte_swx_port_out_ops *ops)
411 struct port_out_type *elem;
414 CHECK_NAME(name, EINVAL);
416 CHECK(ops->create, EINVAL);
417 CHECK(ops->free, EINVAL);
418 CHECK(ops->pkt_tx, EINVAL);
419 CHECK(ops->stats_read, EINVAL);
421 CHECK(!port_out_type_find(p, name), EEXIST);
423 /* Node allocation. */
424 elem = calloc(1, sizeof(struct port_out_type));
427 /* Node initialization. */
428 strcpy(elem->name, name);
429 memcpy(&elem->ops, ops, sizeof(*ops));
431 /* Node add to tailq. */
432 TAILQ_INSERT_TAIL(&p->port_out_types, elem, node);
437 static struct port_out *
438 port_out_find(struct rte_swx_pipeline *p, uint32_t port_id)
440 struct port_out *port;
442 TAILQ_FOREACH(port, &p->ports_out, node)
443 if (port->id == port_id)
450 rte_swx_pipeline_port_out_config(struct rte_swx_pipeline *p,
452 const char *port_type_name,
455 struct port_out_type *type = NULL;
456 struct port_out *port = NULL;
461 CHECK(!port_out_find(p, port_id), EINVAL);
463 CHECK_NAME(port_type_name, EINVAL);
464 type = port_out_type_find(p, port_type_name);
467 obj = type->ops.create(args);
470 /* Node allocation. */
471 port = calloc(1, sizeof(struct port_out));
474 /* Node initialization. */
479 /* Node add to tailq. */
480 TAILQ_INSERT_TAIL(&p->ports_out, port, node);
481 if (p->n_ports_out < port_id + 1)
482 p->n_ports_out = port_id + 1;
488 port_out_build(struct rte_swx_pipeline *p)
490 struct port_out *port;
493 CHECK(p->n_ports_out, EINVAL);
495 for (i = 0; i < p->n_ports_out; i++)
496 CHECK(port_out_find(p, i), EINVAL);
498 p->out = calloc(p->n_ports_out, sizeof(struct port_out_runtime));
499 CHECK(p->out, ENOMEM);
501 TAILQ_FOREACH(port, &p->ports_out, node) {
502 struct port_out_runtime *out = &p->out[port->id];
504 out->pkt_tx = port->type->ops.pkt_tx;
505 out->flush = port->type->ops.flush;
506 out->obj = port->obj;
513 port_out_build_free(struct rte_swx_pipeline *p)
520 port_out_free(struct rte_swx_pipeline *p)
522 port_out_build_free(p);
526 struct port_out *port;
528 port = TAILQ_FIRST(&p->ports_out);
532 TAILQ_REMOVE(&p->ports_out, port, node);
533 port->type->ops.free(port->obj);
537 /* Output port types. */
539 struct port_out_type *elem;
541 elem = TAILQ_FIRST(&p->port_out_types);
545 TAILQ_REMOVE(&p->port_out_types, elem, node);
553 static struct extern_type *
554 extern_type_find(struct rte_swx_pipeline *p, const char *name)
556 struct extern_type *elem;
558 TAILQ_FOREACH(elem, &p->extern_types, node)
559 if (strcmp(elem->name, name) == 0)
565 static struct extern_type_member_func *
566 extern_type_member_func_find(struct extern_type *type, const char *name)
568 struct extern_type_member_func *elem;
570 TAILQ_FOREACH(elem, &type->funcs, node)
571 if (strcmp(elem->name, name) == 0)
577 static struct extern_obj *
578 extern_obj_find(struct rte_swx_pipeline *p, const char *name)
580 struct extern_obj *elem;
582 TAILQ_FOREACH(elem, &p->extern_objs, node)
583 if (strcmp(elem->name, name) == 0)
589 static struct extern_type_member_func *
590 extern_obj_member_func_parse(struct rte_swx_pipeline *p,
592 struct extern_obj **obj)
594 struct extern_obj *object;
595 struct extern_type_member_func *func;
596 char *object_name, *func_name;
598 if (name[0] != 'e' || name[1] != '.')
601 object_name = strdup(&name[2]);
605 func_name = strchr(object_name, '.');
614 object = extern_obj_find(p, object_name);
620 func = extern_type_member_func_find(object->type, func_name);
633 static struct field *
634 extern_obj_mailbox_field_parse(struct rte_swx_pipeline *p,
636 struct extern_obj **object)
638 struct extern_obj *obj;
640 char *obj_name, *field_name;
642 if ((name[0] != 'e') || (name[1] != '.'))
645 obj_name = strdup(&name[2]);
649 field_name = strchr(obj_name, '.');
658 obj = extern_obj_find(p, obj_name);
664 f = struct_type_field_find(obj->type->mailbox_struct_type, field_name);
678 rte_swx_pipeline_extern_type_register(struct rte_swx_pipeline *p,
680 const char *mailbox_struct_type_name,
681 rte_swx_extern_type_constructor_t constructor,
682 rte_swx_extern_type_destructor_t destructor)
684 struct extern_type *elem;
685 struct struct_type *mailbox_struct_type;
689 CHECK_NAME(name, EINVAL);
690 CHECK(!extern_type_find(p, name), EEXIST);
692 CHECK_NAME(mailbox_struct_type_name, EINVAL);
693 mailbox_struct_type = struct_type_find(p, mailbox_struct_type_name);
694 CHECK(mailbox_struct_type, EINVAL);
695 CHECK(!mailbox_struct_type->var_size, EINVAL);
697 CHECK(constructor, EINVAL);
698 CHECK(destructor, EINVAL);
700 /* Node allocation. */
701 elem = calloc(1, sizeof(struct extern_type));
704 /* Node initialization. */
705 strcpy(elem->name, name);
706 elem->mailbox_struct_type = mailbox_struct_type;
707 elem->constructor = constructor;
708 elem->destructor = destructor;
709 TAILQ_INIT(&elem->funcs);
711 /* Node add to tailq. */
712 TAILQ_INSERT_TAIL(&p->extern_types, elem, node);
718 rte_swx_pipeline_extern_type_member_func_register(struct rte_swx_pipeline *p,
719 const char *extern_type_name,
721 rte_swx_extern_type_member_func_t member_func)
723 struct extern_type *type;
724 struct extern_type_member_func *type_member;
728 CHECK_NAME(extern_type_name, EINVAL);
729 type = extern_type_find(p, extern_type_name);
731 CHECK(type->n_funcs < RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX, ENOSPC);
733 CHECK_NAME(name, EINVAL);
734 CHECK(!extern_type_member_func_find(type, name), EEXIST);
736 CHECK(member_func, EINVAL);
738 /* Node allocation. */
739 type_member = calloc(1, sizeof(struct extern_type_member_func));
740 CHECK(type_member, ENOMEM);
742 /* Node initialization. */
743 strcpy(type_member->name, name);
744 type_member->func = member_func;
745 type_member->id = type->n_funcs;
747 /* Node add to tailq. */
748 TAILQ_INSERT_TAIL(&type->funcs, type_member, node);
755 rte_swx_pipeline_extern_object_config(struct rte_swx_pipeline *p,
756 const char *extern_type_name,
760 struct extern_type *type;
761 struct extern_obj *obj;
766 CHECK_NAME(extern_type_name, EINVAL);
767 type = extern_type_find(p, extern_type_name);
770 CHECK_NAME(name, EINVAL);
771 CHECK(!extern_obj_find(p, name), EEXIST);
773 /* Node allocation. */
774 obj = calloc(1, sizeof(struct extern_obj));
777 /* Object construction. */
778 obj_handle = type->constructor(args);
784 /* Node initialization. */
785 strcpy(obj->name, name);
787 obj->obj = obj_handle;
788 obj->struct_id = p->n_structs;
789 obj->id = p->n_extern_objs;
791 /* Node add to tailq. */
792 TAILQ_INSERT_TAIL(&p->extern_objs, obj, node);
800 extern_obj_build(struct rte_swx_pipeline *p)
804 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
805 struct thread *t = &p->threads[i];
806 struct extern_obj *obj;
808 t->extern_objs = calloc(p->n_extern_objs,
809 sizeof(struct extern_obj_runtime));
810 CHECK(t->extern_objs, ENOMEM);
812 TAILQ_FOREACH(obj, &p->extern_objs, node) {
813 struct extern_obj_runtime *r =
814 &t->extern_objs[obj->id];
815 struct extern_type_member_func *func;
816 uint32_t mailbox_size =
817 obj->type->mailbox_struct_type->n_bits / 8;
821 r->mailbox = calloc(1, mailbox_size);
822 CHECK(r->mailbox, ENOMEM);
824 TAILQ_FOREACH(func, &obj->type->funcs, node)
825 r->funcs[func->id] = func->func;
827 t->structs[obj->struct_id] = r->mailbox;
835 extern_obj_build_free(struct rte_swx_pipeline *p)
839 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
840 struct thread *t = &p->threads[i];
846 for (j = 0; j < p->n_extern_objs; j++) {
847 struct extern_obj_runtime *r = &t->extern_objs[j];
852 free(t->extern_objs);
853 t->extern_objs = NULL;
858 extern_obj_free(struct rte_swx_pipeline *p)
860 extern_obj_build_free(p);
862 /* Extern objects. */
864 struct extern_obj *elem;
866 elem = TAILQ_FIRST(&p->extern_objs);
870 TAILQ_REMOVE(&p->extern_objs, elem, node);
872 elem->type->destructor(elem->obj);
878 struct extern_type *elem;
880 elem = TAILQ_FIRST(&p->extern_types);
884 TAILQ_REMOVE(&p->extern_types, elem, node);
887 struct extern_type_member_func *func;
889 func = TAILQ_FIRST(&elem->funcs);
893 TAILQ_REMOVE(&elem->funcs, func, node);
904 static struct extern_func *
905 extern_func_find(struct rte_swx_pipeline *p, const char *name)
907 struct extern_func *elem;
909 TAILQ_FOREACH(elem, &p->extern_funcs, node)
910 if (strcmp(elem->name, name) == 0)
916 static struct extern_func *
917 extern_func_parse(struct rte_swx_pipeline *p,
920 if (name[0] != 'f' || name[1] != '.')
923 return extern_func_find(p, &name[2]);
926 static struct field *
927 extern_func_mailbox_field_parse(struct rte_swx_pipeline *p,
929 struct extern_func **function)
931 struct extern_func *func;
933 char *func_name, *field_name;
935 if ((name[0] != 'f') || (name[1] != '.'))
938 func_name = strdup(&name[2]);
942 field_name = strchr(func_name, '.');
951 func = extern_func_find(p, func_name);
957 f = struct_type_field_find(func->mailbox_struct_type, field_name);
971 rte_swx_pipeline_extern_func_register(struct rte_swx_pipeline *p,
973 const char *mailbox_struct_type_name,
974 rte_swx_extern_func_t func)
976 struct extern_func *f;
977 struct struct_type *mailbox_struct_type;
981 CHECK_NAME(name, EINVAL);
982 CHECK(!extern_func_find(p, name), EEXIST);
984 CHECK_NAME(mailbox_struct_type_name, EINVAL);
985 mailbox_struct_type = struct_type_find(p, mailbox_struct_type_name);
986 CHECK(mailbox_struct_type, EINVAL);
987 CHECK(!mailbox_struct_type->var_size, EINVAL);
991 /* Node allocation. */
992 f = calloc(1, sizeof(struct extern_func));
995 /* Node initialization. */
996 strcpy(f->name, name);
997 f->mailbox_struct_type = mailbox_struct_type;
999 f->struct_id = p->n_structs;
1000 f->id = p->n_extern_funcs;
1002 /* Node add to tailq. */
1003 TAILQ_INSERT_TAIL(&p->extern_funcs, f, node);
1004 p->n_extern_funcs++;
1011 extern_func_build(struct rte_swx_pipeline *p)
1015 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1016 struct thread *t = &p->threads[i];
1017 struct extern_func *func;
1019 /* Memory allocation. */
1020 t->extern_funcs = calloc(p->n_extern_funcs,
1021 sizeof(struct extern_func_runtime));
1022 CHECK(t->extern_funcs, ENOMEM);
1024 /* Extern function. */
1025 TAILQ_FOREACH(func, &p->extern_funcs, node) {
1026 struct extern_func_runtime *r =
1027 &t->extern_funcs[func->id];
1028 uint32_t mailbox_size =
1029 func->mailbox_struct_type->n_bits / 8;
1031 r->func = func->func;
1033 r->mailbox = calloc(1, mailbox_size);
1034 CHECK(r->mailbox, ENOMEM);
1036 t->structs[func->struct_id] = r->mailbox;
1044 extern_func_build_free(struct rte_swx_pipeline *p)
1048 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1049 struct thread *t = &p->threads[i];
1052 if (!t->extern_funcs)
1055 for (j = 0; j < p->n_extern_funcs; j++) {
1056 struct extern_func_runtime *r = &t->extern_funcs[j];
1061 free(t->extern_funcs);
1062 t->extern_funcs = NULL;
1067 extern_func_free(struct rte_swx_pipeline *p)
1069 extern_func_build_free(p);
1072 struct extern_func *elem;
1074 elem = TAILQ_FIRST(&p->extern_funcs);
1078 TAILQ_REMOVE(&p->extern_funcs, elem, node);
1086 static struct header *
1087 header_find(struct rte_swx_pipeline *p, const char *name)
1089 struct header *elem;
1091 TAILQ_FOREACH(elem, &p->headers, node)
1092 if (strcmp(elem->name, name) == 0)
1098 static struct header *
1099 header_find_by_struct_id(struct rte_swx_pipeline *p, uint32_t struct_id)
1101 struct header *elem;
1103 TAILQ_FOREACH(elem, &p->headers, node)
1104 if (elem->struct_id == struct_id)
1110 static struct header *
1111 header_parse(struct rte_swx_pipeline *p,
1114 if (name[0] != 'h' || name[1] != '.')
1117 return header_find(p, &name[2]);
1120 static struct field *
1121 header_field_parse(struct rte_swx_pipeline *p,
1123 struct header **header)
1127 char *header_name, *field_name;
1129 if ((name[0] != 'h') || (name[1] != '.'))
1132 header_name = strdup(&name[2]);
1136 field_name = strchr(header_name, '.');
1145 h = header_find(p, header_name);
1151 f = struct_type_field_find(h->st, field_name);
1165 rte_swx_pipeline_packet_header_register(struct rte_swx_pipeline *p,
1167 const char *struct_type_name)
1169 struct struct_type *st;
1171 size_t n_headers_max;
1174 CHECK_NAME(name, EINVAL);
1175 CHECK_NAME(struct_type_name, EINVAL);
1177 CHECK(!header_find(p, name), EEXIST);
1179 st = struct_type_find(p, struct_type_name);
1182 n_headers_max = RTE_SIZEOF_FIELD(struct thread, valid_headers) * 8;
1183 CHECK(p->n_headers < n_headers_max, ENOSPC);
1185 /* Node allocation. */
1186 h = calloc(1, sizeof(struct header));
1189 /* Node initialization. */
1190 strcpy(h->name, name);
1192 h->struct_id = p->n_structs;
1193 h->id = p->n_headers;
1195 /* Node add to tailq. */
1196 TAILQ_INSERT_TAIL(&p->headers, h, node);
1204 header_build(struct rte_swx_pipeline *p)
1207 uint32_t n_bytes = 0, i;
1209 TAILQ_FOREACH(h, &p->headers, node) {
1210 n_bytes += h->st->n_bits / 8;
1213 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1214 struct thread *t = &p->threads[i];
1215 uint32_t offset = 0;
1217 t->headers = calloc(p->n_headers,
1218 sizeof(struct header_runtime));
1219 CHECK(t->headers, ENOMEM);
1221 t->headers_out = calloc(p->n_headers,
1222 sizeof(struct header_out_runtime));
1223 CHECK(t->headers_out, ENOMEM);
1225 t->header_storage = calloc(1, n_bytes);
1226 CHECK(t->header_storage, ENOMEM);
1228 t->header_out_storage = calloc(1, n_bytes);
1229 CHECK(t->header_out_storage, ENOMEM);
1231 TAILQ_FOREACH(h, &p->headers, node) {
1232 uint8_t *header_storage;
1233 uint32_t n_bytes = h->st->n_bits / 8;
1235 header_storage = &t->header_storage[offset];
1238 t->headers[h->id].ptr0 = header_storage;
1239 t->headers[h->id].n_bytes = n_bytes;
1241 t->structs[h->struct_id] = header_storage;
1249 header_build_free(struct rte_swx_pipeline *p)
1253 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1254 struct thread *t = &p->threads[i];
1256 free(t->headers_out);
1257 t->headers_out = NULL;
1262 free(t->header_out_storage);
1263 t->header_out_storage = NULL;
1265 free(t->header_storage);
1266 t->header_storage = NULL;
1271 header_free(struct rte_swx_pipeline *p)
1273 header_build_free(p);
1276 struct header *elem;
1278 elem = TAILQ_FIRST(&p->headers);
1282 TAILQ_REMOVE(&p->headers, elem, node);
1290 static struct field *
1291 metadata_field_parse(struct rte_swx_pipeline *p, const char *name)
1293 if (!p->metadata_st)
1296 if (name[0] != 'm' || name[1] != '.')
1299 return struct_type_field_find(p->metadata_st, &name[2]);
1303 rte_swx_pipeline_packet_metadata_register(struct rte_swx_pipeline *p,
1304 const char *struct_type_name)
1306 struct struct_type *st = NULL;
1310 CHECK_NAME(struct_type_name, EINVAL);
1311 st = struct_type_find(p, struct_type_name);
1313 CHECK(!st->var_size, EINVAL);
1314 CHECK(!p->metadata_st, EINVAL);
1316 p->metadata_st = st;
1317 p->metadata_struct_id = p->n_structs;
1325 metadata_build(struct rte_swx_pipeline *p)
1327 uint32_t n_bytes = p->metadata_st->n_bits / 8;
1330 /* Thread-level initialization. */
1331 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1332 struct thread *t = &p->threads[i];
1335 metadata = calloc(1, n_bytes);
1336 CHECK(metadata, ENOMEM);
1338 t->metadata = metadata;
1339 t->structs[p->metadata_struct_id] = metadata;
1346 metadata_build_free(struct rte_swx_pipeline *p)
1350 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1351 struct thread *t = &p->threads[i];
1359 metadata_free(struct rte_swx_pipeline *p)
1361 metadata_build_free(p);
1368 instruction_is_tx(enum instruction_type type)
1381 instruction_does_tx(struct instruction *instr)
1383 switch (instr->type) {
1386 case INSTR_HDR_EMIT_TX:
1387 case INSTR_HDR_EMIT2_TX:
1388 case INSTR_HDR_EMIT3_TX:
1389 case INSTR_HDR_EMIT4_TX:
1390 case INSTR_HDR_EMIT5_TX:
1391 case INSTR_HDR_EMIT6_TX:
1392 case INSTR_HDR_EMIT7_TX:
1393 case INSTR_HDR_EMIT8_TX:
1401 instruction_is_jmp(struct instruction *instr)
1403 switch (instr->type) {
1405 case INSTR_JMP_VALID:
1406 case INSTR_JMP_INVALID:
1408 case INSTR_JMP_MISS:
1409 case INSTR_JMP_ACTION_HIT:
1410 case INSTR_JMP_ACTION_MISS:
1412 case INSTR_JMP_EQ_MH:
1413 case INSTR_JMP_EQ_HM:
1414 case INSTR_JMP_EQ_HH:
1415 case INSTR_JMP_EQ_I:
1417 case INSTR_JMP_NEQ_MH:
1418 case INSTR_JMP_NEQ_HM:
1419 case INSTR_JMP_NEQ_HH:
1420 case INSTR_JMP_NEQ_I:
1422 case INSTR_JMP_LT_MH:
1423 case INSTR_JMP_LT_HM:
1424 case INSTR_JMP_LT_HH:
1425 case INSTR_JMP_LT_MI:
1426 case INSTR_JMP_LT_HI:
1428 case INSTR_JMP_GT_MH:
1429 case INSTR_JMP_GT_HM:
1430 case INSTR_JMP_GT_HH:
1431 case INSTR_JMP_GT_MI:
1432 case INSTR_JMP_GT_HI:
1441 instruction_does_thread_yield(struct instruction *instr)
1443 switch (instr->type) {
1446 case INSTR_TABLE_AF:
1447 case INSTR_SELECTOR:
1449 case INSTR_LEARNER_AF:
1450 case INSTR_EXTERN_OBJ:
1451 case INSTR_EXTERN_FUNC:
1458 static struct field *
1459 action_field_parse(struct action *action, const char *name);
1461 static struct field *
1462 struct_field_parse(struct rte_swx_pipeline *p,
1463 struct action *action,
1465 uint32_t *struct_id)
1472 struct header *header;
1474 f = header_field_parse(p, name, &header);
1478 *struct_id = header->struct_id;
1484 f = metadata_field_parse(p, name);
1488 *struct_id = p->metadata_struct_id;
1497 f = action_field_parse(action, name);
1507 struct extern_obj *obj;
1509 f = extern_obj_mailbox_field_parse(p, name, &obj);
1513 *struct_id = obj->struct_id;
1519 struct extern_func *func;
1521 f = extern_func_mailbox_field_parse(p, name, &func);
1525 *struct_id = func->struct_id;
1538 instr_rx_translate(struct rte_swx_pipeline *p,
1539 struct action *action,
1542 struct instruction *instr,
1543 struct instruction_data *data __rte_unused)
1547 CHECK(!action, EINVAL);
1548 CHECK(n_tokens == 2, EINVAL);
1550 f = metadata_field_parse(p, tokens[1]);
1553 instr->type = INSTR_RX;
1554 instr->io.io.offset = f->offset / 8;
1555 instr->io.io.n_bits = f->n_bits;
1563 instr_tx_translate(struct rte_swx_pipeline *p,
1564 struct action *action __rte_unused,
1567 struct instruction *instr,
1568 struct instruction_data *data __rte_unused)
1570 char *port = tokens[1];
1574 CHECK(n_tokens == 2, EINVAL);
1576 f = metadata_field_parse(p, port);
1578 instr->type = INSTR_TX;
1579 instr->io.io.offset = f->offset / 8;
1580 instr->io.io.n_bits = f->n_bits;
1585 port_val = strtoul(port, &port, 0);
1586 CHECK(!port[0], EINVAL);
1588 instr->type = INSTR_TX_I;
1589 instr->io.io.val = port_val;
1594 instr_drop_translate(struct rte_swx_pipeline *p,
1595 struct action *action __rte_unused,
1596 char **tokens __rte_unused,
1598 struct instruction *instr,
1599 struct instruction_data *data __rte_unused)
1601 CHECK(n_tokens == 1, EINVAL);
1604 instr->type = INSTR_TX_I;
1605 instr->io.io.val = p->n_ports_out - 1;
1610 instr_tx_exec(struct rte_swx_pipeline *p)
1612 struct thread *t = &p->threads[p->thread_id];
1613 struct instruction *ip = t->ip;
1615 __instr_tx_exec(p, t, ip);
1618 thread_ip_reset(p, t);
1623 instr_tx_i_exec(struct rte_swx_pipeline *p)
1625 struct thread *t = &p->threads[p->thread_id];
1626 struct instruction *ip = t->ip;
1628 __instr_tx_i_exec(p, t, ip);
1631 thread_ip_reset(p, t);
1639 instr_hdr_extract_translate(struct rte_swx_pipeline *p,
1640 struct action *action,
1643 struct instruction *instr,
1644 struct instruction_data *data __rte_unused)
1648 CHECK(!action, EINVAL);
1649 CHECK((n_tokens == 2) || (n_tokens == 3), EINVAL);
1651 h = header_parse(p, tokens[1]);
1654 if (n_tokens == 2) {
1655 CHECK(!h->st->var_size, EINVAL);
1657 instr->type = INSTR_HDR_EXTRACT;
1658 instr->io.hdr.header_id[0] = h->id;
1659 instr->io.hdr.struct_id[0] = h->struct_id;
1660 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
1664 CHECK(h->st->var_size, EINVAL);
1666 mf = metadata_field_parse(p, tokens[2]);
1668 CHECK(!mf->var_size, EINVAL);
1670 instr->type = INSTR_HDR_EXTRACT_M;
1671 instr->io.io.offset = mf->offset / 8;
1672 instr->io.io.n_bits = mf->n_bits;
1673 instr->io.hdr.header_id[0] = h->id;
1674 instr->io.hdr.struct_id[0] = h->struct_id;
1675 instr->io.hdr.n_bytes[0] = h->st->n_bits_min / 8;
1682 instr_hdr_lookahead_translate(struct rte_swx_pipeline *p,
1683 struct action *action,
1686 struct instruction *instr,
1687 struct instruction_data *data __rte_unused)
1691 CHECK(!action, EINVAL);
1692 CHECK(n_tokens == 2, EINVAL);
1694 h = header_parse(p, tokens[1]);
1696 CHECK(!h->st->var_size, EINVAL);
1698 instr->type = INSTR_HDR_LOOKAHEAD;
1699 instr->io.hdr.header_id[0] = h->id;
1700 instr->io.hdr.struct_id[0] = h->struct_id;
1701 instr->io.hdr.n_bytes[0] = 0; /* Unused. */
1707 instr_hdr_extract_exec(struct rte_swx_pipeline *p)
1709 struct thread *t = &p->threads[p->thread_id];
1710 struct instruction *ip = t->ip;
1712 __instr_hdr_extract_exec(p, t, ip);
1719 instr_hdr_extract2_exec(struct rte_swx_pipeline *p)
1721 struct thread *t = &p->threads[p->thread_id];
1722 struct instruction *ip = t->ip;
1724 __instr_hdr_extract2_exec(p, t, ip);
1731 instr_hdr_extract3_exec(struct rte_swx_pipeline *p)
1733 struct thread *t = &p->threads[p->thread_id];
1734 struct instruction *ip = t->ip;
1736 __instr_hdr_extract3_exec(p, t, ip);
1743 instr_hdr_extract4_exec(struct rte_swx_pipeline *p)
1745 struct thread *t = &p->threads[p->thread_id];
1746 struct instruction *ip = t->ip;
1748 __instr_hdr_extract4_exec(p, t, ip);
1755 instr_hdr_extract5_exec(struct rte_swx_pipeline *p)
1757 struct thread *t = &p->threads[p->thread_id];
1758 struct instruction *ip = t->ip;
1760 __instr_hdr_extract5_exec(p, t, ip);
1767 instr_hdr_extract6_exec(struct rte_swx_pipeline *p)
1769 struct thread *t = &p->threads[p->thread_id];
1770 struct instruction *ip = t->ip;
1772 __instr_hdr_extract6_exec(p, t, ip);
1779 instr_hdr_extract7_exec(struct rte_swx_pipeline *p)
1781 struct thread *t = &p->threads[p->thread_id];
1782 struct instruction *ip = t->ip;
1784 __instr_hdr_extract7_exec(p, t, ip);
1791 instr_hdr_extract8_exec(struct rte_swx_pipeline *p)
1793 struct thread *t = &p->threads[p->thread_id];
1794 struct instruction *ip = t->ip;
1796 __instr_hdr_extract8_exec(p, t, ip);
1803 instr_hdr_extract_m_exec(struct rte_swx_pipeline *p)
1805 struct thread *t = &p->threads[p->thread_id];
1806 struct instruction *ip = t->ip;
1808 __instr_hdr_extract_m_exec(p, t, ip);
1815 instr_hdr_lookahead_exec(struct rte_swx_pipeline *p)
1817 struct thread *t = &p->threads[p->thread_id];
1818 struct instruction *ip = t->ip;
1820 __instr_hdr_lookahead_exec(p, t, ip);
1830 instr_hdr_emit_translate(struct rte_swx_pipeline *p,
1831 struct action *action __rte_unused,
1834 struct instruction *instr,
1835 struct instruction_data *data __rte_unused)
1839 CHECK(n_tokens == 2, EINVAL);
1841 h = header_parse(p, tokens[1]);
1844 instr->type = INSTR_HDR_EMIT;
1845 instr->io.hdr.header_id[0] = h->id;
1846 instr->io.hdr.struct_id[0] = h->struct_id;
1847 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
1852 instr_hdr_emit_exec(struct rte_swx_pipeline *p)
1854 struct thread *t = &p->threads[p->thread_id];
1855 struct instruction *ip = t->ip;
1857 __instr_hdr_emit_exec(p, t, ip);
1864 instr_hdr_emit_tx_exec(struct rte_swx_pipeline *p)
1866 struct thread *t = &p->threads[p->thread_id];
1867 struct instruction *ip = t->ip;
1869 __instr_hdr_emit_tx_exec(p, t, ip);
1872 thread_ip_reset(p, t);
1877 instr_hdr_emit2_tx_exec(struct rte_swx_pipeline *p)
1879 struct thread *t = &p->threads[p->thread_id];
1880 struct instruction *ip = t->ip;
1882 __instr_hdr_emit2_tx_exec(p, t, ip);
1885 thread_ip_reset(p, t);
1890 instr_hdr_emit3_tx_exec(struct rte_swx_pipeline *p)
1892 struct thread *t = &p->threads[p->thread_id];
1893 struct instruction *ip = t->ip;
1895 __instr_hdr_emit3_tx_exec(p, t, ip);
1898 thread_ip_reset(p, t);
1903 instr_hdr_emit4_tx_exec(struct rte_swx_pipeline *p)
1905 struct thread *t = &p->threads[p->thread_id];
1906 struct instruction *ip = t->ip;
1908 __instr_hdr_emit4_tx_exec(p, t, ip);
1911 thread_ip_reset(p, t);
1916 instr_hdr_emit5_tx_exec(struct rte_swx_pipeline *p)
1918 struct thread *t = &p->threads[p->thread_id];
1919 struct instruction *ip = t->ip;
1921 __instr_hdr_emit5_tx_exec(p, t, ip);
1924 thread_ip_reset(p, t);
1929 instr_hdr_emit6_tx_exec(struct rte_swx_pipeline *p)
1931 struct thread *t = &p->threads[p->thread_id];
1932 struct instruction *ip = t->ip;
1934 __instr_hdr_emit6_tx_exec(p, t, ip);
1937 thread_ip_reset(p, t);
1942 instr_hdr_emit7_tx_exec(struct rte_swx_pipeline *p)
1944 struct thread *t = &p->threads[p->thread_id];
1945 struct instruction *ip = t->ip;
1947 __instr_hdr_emit7_tx_exec(p, t, ip);
1950 thread_ip_reset(p, t);
1955 instr_hdr_emit8_tx_exec(struct rte_swx_pipeline *p)
1957 struct thread *t = &p->threads[p->thread_id];
1958 struct instruction *ip = t->ip;
1960 __instr_hdr_emit8_tx_exec(p, t, ip);
1963 thread_ip_reset(p, t);
1971 instr_hdr_validate_translate(struct rte_swx_pipeline *p,
1972 struct action *action __rte_unused,
1975 struct instruction *instr,
1976 struct instruction_data *data __rte_unused)
1980 CHECK(n_tokens == 2, EINVAL);
1982 h = header_parse(p, tokens[1]);
1985 instr->type = INSTR_HDR_VALIDATE;
1986 instr->valid.header_id = h->id;
1991 instr_hdr_validate_exec(struct rte_swx_pipeline *p)
1993 struct thread *t = &p->threads[p->thread_id];
1994 struct instruction *ip = t->ip;
1996 __instr_hdr_validate_exec(p, t, ip);
2006 instr_hdr_invalidate_translate(struct rte_swx_pipeline *p,
2007 struct action *action __rte_unused,
2010 struct instruction *instr,
2011 struct instruction_data *data __rte_unused)
2015 CHECK(n_tokens == 2, EINVAL);
2017 h = header_parse(p, tokens[1]);
2020 instr->type = INSTR_HDR_INVALIDATE;
2021 instr->valid.header_id = h->id;
2026 instr_hdr_invalidate_exec(struct rte_swx_pipeline *p)
2028 struct thread *t = &p->threads[p->thread_id];
2029 struct instruction *ip = t->ip;
2031 __instr_hdr_invalidate_exec(p, t, ip);
2040 static struct table *
2041 table_find(struct rte_swx_pipeline *p, const char *name);
2043 static struct selector *
2044 selector_find(struct rte_swx_pipeline *p, const char *name);
2046 static struct learner *
2047 learner_find(struct rte_swx_pipeline *p, const char *name);
2050 instr_table_translate(struct rte_swx_pipeline *p,
2051 struct action *action,
2054 struct instruction *instr,
2055 struct instruction_data *data __rte_unused)
2061 CHECK(!action, EINVAL);
2062 CHECK(n_tokens == 2, EINVAL);
2064 t = table_find(p, tokens[1]);
2066 instr->type = INSTR_TABLE;
2067 instr->table.table_id = t->id;
2071 s = selector_find(p, tokens[1]);
2073 instr->type = INSTR_SELECTOR;
2074 instr->table.table_id = s->id;
2078 l = learner_find(p, tokens[1]);
2080 instr->type = INSTR_LEARNER;
2081 instr->table.table_id = l->id;
2089 instr_table_exec(struct rte_swx_pipeline *p)
2091 struct thread *t = &p->threads[p->thread_id];
2092 struct instruction *ip = t->ip;
2093 uint32_t table_id = ip->table.table_id;
2094 struct rte_swx_table_state *ts = &t->table_state[table_id];
2095 struct table_runtime *table = &t->tables[table_id];
2096 struct table_statistics *stats = &p->table_stats[table_id];
2097 uint64_t action_id, n_pkts_hit, n_pkts_action;
2098 uint8_t *action_data;
2102 done = table->func(ts->obj,
2110 TRACE("[Thread %2u] table %u (not finalized)\n",
2118 action_id = hit ? action_id : ts->default_action_id;
2119 action_data = hit ? action_data : ts->default_action_data;
2120 n_pkts_hit = stats->n_pkts_hit[hit];
2121 n_pkts_action = stats->n_pkts_action[action_id];
2123 TRACE("[Thread %2u] table %u (%s, action %u)\n",
2126 hit ? "hit" : "miss",
2127 (uint32_t)action_id);
2129 t->action_id = action_id;
2130 t->structs[0] = action_data;
2132 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2133 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2136 thread_ip_action_call(p, t, action_id);
2140 instr_table_af_exec(struct rte_swx_pipeline *p)
2142 struct thread *t = &p->threads[p->thread_id];
2143 struct instruction *ip = t->ip;
2144 uint32_t table_id = ip->table.table_id;
2145 struct rte_swx_table_state *ts = &t->table_state[table_id];
2146 struct table_runtime *table = &t->tables[table_id];
2147 struct table_statistics *stats = &p->table_stats[table_id];
2148 uint64_t action_id, n_pkts_hit, n_pkts_action;
2149 uint8_t *action_data;
2150 action_func_t action_func;
2154 done = table->func(ts->obj,
2162 TRACE("[Thread %2u] table %u (not finalized)\n",
2170 action_id = hit ? action_id : ts->default_action_id;
2171 action_data = hit ? action_data : ts->default_action_data;
2172 action_func = p->action_funcs[action_id];
2173 n_pkts_hit = stats->n_pkts_hit[hit];
2174 n_pkts_action = stats->n_pkts_action[action_id];
2176 TRACE("[Thread %2u] table %u (%s, action %u)\n",
2179 hit ? "hit" : "miss",
2180 (uint32_t)action_id);
2182 t->action_id = action_id;
2183 t->structs[0] = action_data;
2185 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2186 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2196 instr_selector_exec(struct rte_swx_pipeline *p)
2198 struct thread *t = &p->threads[p->thread_id];
2199 struct instruction *ip = t->ip;
2200 uint32_t selector_id = ip->table.table_id;
2201 struct rte_swx_table_state *ts = &t->table_state[p->n_tables + selector_id];
2202 struct selector_runtime *selector = &t->selectors[selector_id];
2203 struct selector_statistics *stats = &p->selector_stats[selector_id];
2204 uint64_t n_pkts = stats->n_pkts;
2208 done = rte_swx_table_selector_select(ts->obj,
2210 selector->group_id_buffer,
2211 selector->selector_buffer,
2212 selector->member_id_buffer);
2215 TRACE("[Thread %2u] selector %u (not finalized)\n",
2224 TRACE("[Thread %2u] selector %u\n",
2228 stats->n_pkts = n_pkts + 1;
2235 instr_learner_exec(struct rte_swx_pipeline *p)
2237 struct thread *t = &p->threads[p->thread_id];
2238 struct instruction *ip = t->ip;
2239 uint32_t learner_id = ip->table.table_id;
2240 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2241 p->n_selectors + learner_id];
2242 struct learner_runtime *l = &t->learners[learner_id];
2243 struct learner_statistics *stats = &p->learner_stats[learner_id];
2244 uint64_t action_id, n_pkts_hit, n_pkts_action, time;
2245 uint8_t *action_data;
2249 time = rte_get_tsc_cycles();
2251 done = rte_swx_table_learner_lookup(ts->obj,
2260 TRACE("[Thread %2u] learner %u (not finalized)\n",
2268 action_id = hit ? action_id : ts->default_action_id;
2269 action_data = hit ? action_data : ts->default_action_data;
2270 n_pkts_hit = stats->n_pkts_hit[hit];
2271 n_pkts_action = stats->n_pkts_action[action_id];
2273 TRACE("[Thread %2u] learner %u (%s, action %u)\n",
2276 hit ? "hit" : "miss",
2277 (uint32_t)action_id);
2279 t->action_id = action_id;
2280 t->structs[0] = action_data;
2282 t->learner_id = learner_id;
2284 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2285 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2288 thread_ip_action_call(p, t, action_id);
2292 instr_learner_af_exec(struct rte_swx_pipeline *p)
2294 struct thread *t = &p->threads[p->thread_id];
2295 struct instruction *ip = t->ip;
2296 uint32_t learner_id = ip->table.table_id;
2297 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2298 p->n_selectors + learner_id];
2299 struct learner_runtime *l = &t->learners[learner_id];
2300 struct learner_statistics *stats = &p->learner_stats[learner_id];
2301 uint64_t action_id, n_pkts_hit, n_pkts_action, time;
2302 uint8_t *action_data;
2303 action_func_t action_func;
2307 time = rte_get_tsc_cycles();
2309 done = rte_swx_table_learner_lookup(ts->obj,
2318 TRACE("[Thread %2u] learner %u (not finalized)\n",
2326 action_id = hit ? action_id : ts->default_action_id;
2327 action_data = hit ? action_data : ts->default_action_data;
2328 action_func = p->action_funcs[action_id];
2329 n_pkts_hit = stats->n_pkts_hit[hit];
2330 n_pkts_action = stats->n_pkts_action[action_id];
2332 TRACE("[Thread %2u] learner %u (%s, action %u)\n",
2335 hit ? "hit" : "miss",
2336 (uint32_t)action_id);
2338 t->action_id = action_id;
2339 t->structs[0] = action_data;
2341 t->learner_id = learner_id;
2343 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2344 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2347 thread_ip_action_call(p, t, action_id);
2356 static struct action *
2357 action_find(struct rte_swx_pipeline *p, const char *name);
2360 action_has_nbo_args(struct action *a);
2363 learner_action_args_check(struct rte_swx_pipeline *p, struct action *a, const char *mf_name);
2366 instr_learn_translate(struct rte_swx_pipeline *p,
2367 struct action *action,
2370 struct instruction *instr,
2371 struct instruction_data *data __rte_unused)
2374 const char *mf_name;
2375 uint32_t mf_offset = 0;
2377 CHECK(action, EINVAL);
2378 CHECK((n_tokens == 2) || (n_tokens == 3), EINVAL);
2380 a = action_find(p, tokens[1]);
2382 CHECK(!action_has_nbo_args(a), EINVAL);
2384 mf_name = (n_tokens > 2) ? tokens[2] : NULL;
2385 CHECK(!learner_action_args_check(p, a, mf_name), EINVAL);
2390 mf = metadata_field_parse(p, mf_name);
2393 mf_offset = mf->offset / 8;
2396 instr->type = INSTR_LEARNER_LEARN;
2397 instr->learn.action_id = a->id;
2398 instr->learn.mf_offset = mf_offset;
2404 instr_learn_exec(struct rte_swx_pipeline *p)
2406 struct thread *t = &p->threads[p->thread_id];
2407 struct instruction *ip = t->ip;
2409 __instr_learn_exec(p, t, ip);
2419 instr_forget_translate(struct rte_swx_pipeline *p __rte_unused,
2420 struct action *action,
2421 char **tokens __rte_unused,
2423 struct instruction *instr,
2424 struct instruction_data *data __rte_unused)
2426 CHECK(action, EINVAL);
2427 CHECK(n_tokens == 1, EINVAL);
2429 instr->type = INSTR_LEARNER_FORGET;
2435 instr_forget_exec(struct rte_swx_pipeline *p)
2437 struct thread *t = &p->threads[p->thread_id];
2438 struct instruction *ip = t->ip;
2440 __instr_forget_exec(p, t, ip);
2450 instr_extern_translate(struct rte_swx_pipeline *p,
2451 struct action *action __rte_unused,
2454 struct instruction *instr,
2455 struct instruction_data *data __rte_unused)
2457 char *token = tokens[1];
2459 CHECK(n_tokens == 2, EINVAL);
2461 if (token[0] == 'e') {
2462 struct extern_obj *obj;
2463 struct extern_type_member_func *func;
2465 func = extern_obj_member_func_parse(p, token, &obj);
2466 CHECK(func, EINVAL);
2468 instr->type = INSTR_EXTERN_OBJ;
2469 instr->ext_obj.ext_obj_id = obj->id;
2470 instr->ext_obj.func_id = func->id;
2475 if (token[0] == 'f') {
2476 struct extern_func *func;
2478 func = extern_func_parse(p, token);
2479 CHECK(func, EINVAL);
2481 instr->type = INSTR_EXTERN_FUNC;
2482 instr->ext_func.ext_func_id = func->id;
2491 instr_extern_obj_exec(struct rte_swx_pipeline *p)
2493 struct thread *t = &p->threads[p->thread_id];
2494 struct instruction *ip = t->ip;
2497 /* Extern object member function execute. */
2498 done = __instr_extern_obj_exec(p, t, ip);
2501 thread_ip_inc_cond(t, done);
2502 thread_yield_cond(p, done ^ 1);
2506 instr_extern_func_exec(struct rte_swx_pipeline *p)
2508 struct thread *t = &p->threads[p->thread_id];
2509 struct instruction *ip = t->ip;
2512 /* Extern function execute. */
2513 done = __instr_extern_func_exec(p, t, ip);
2516 thread_ip_inc_cond(t, done);
2517 thread_yield_cond(p, done ^ 1);
2524 instr_mov_translate(struct rte_swx_pipeline *p,
2525 struct action *action,
2528 struct instruction *instr,
2529 struct instruction_data *data __rte_unused)
2531 char *dst = tokens[1], *src = tokens[2];
2532 struct field *fdst, *fsrc;
2534 uint32_t dst_struct_id = 0, src_struct_id = 0;
2536 CHECK(n_tokens == 3, EINVAL);
2538 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2539 CHECK(fdst, EINVAL);
2540 CHECK(!fdst->var_size, EINVAL);
2542 /* MOV, MOV_MH, MOV_HM or MOV_HH. */
2543 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2545 CHECK(!fsrc->var_size, EINVAL);
2547 instr->type = INSTR_MOV;
2548 if (dst[0] != 'h' && src[0] == 'h')
2549 instr->type = INSTR_MOV_MH;
2550 if (dst[0] == 'h' && src[0] != 'h')
2551 instr->type = INSTR_MOV_HM;
2552 if (dst[0] == 'h' && src[0] == 'h')
2553 instr->type = INSTR_MOV_HH;
2555 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
2556 instr->mov.dst.n_bits = fdst->n_bits;
2557 instr->mov.dst.offset = fdst->offset / 8;
2558 instr->mov.src.struct_id = (uint8_t)src_struct_id;
2559 instr->mov.src.n_bits = fsrc->n_bits;
2560 instr->mov.src.offset = fsrc->offset / 8;
2565 src_val = strtoull(src, &src, 0);
2566 CHECK(!src[0], EINVAL);
2569 src_val = hton64(src_val) >> (64 - fdst->n_bits);
2571 instr->type = INSTR_MOV_I;
2572 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
2573 instr->mov.dst.n_bits = fdst->n_bits;
2574 instr->mov.dst.offset = fdst->offset / 8;
2575 instr->mov.src_val = src_val;
2580 instr_mov_exec(struct rte_swx_pipeline *p)
2582 struct thread *t = &p->threads[p->thread_id];
2583 struct instruction *ip = t->ip;
2585 __instr_mov_exec(p, t, ip);
2592 instr_mov_mh_exec(struct rte_swx_pipeline *p)
2594 struct thread *t = &p->threads[p->thread_id];
2595 struct instruction *ip = t->ip;
2597 __instr_mov_mh_exec(p, t, ip);
2604 instr_mov_hm_exec(struct rte_swx_pipeline *p)
2606 struct thread *t = &p->threads[p->thread_id];
2607 struct instruction *ip = t->ip;
2609 __instr_mov_hm_exec(p, t, ip);
2616 instr_mov_hh_exec(struct rte_swx_pipeline *p)
2618 struct thread *t = &p->threads[p->thread_id];
2619 struct instruction *ip = t->ip;
2621 __instr_mov_hh_exec(p, t, ip);
2628 instr_mov_i_exec(struct rte_swx_pipeline *p)
2630 struct thread *t = &p->threads[p->thread_id];
2631 struct instruction *ip = t->ip;
2633 __instr_mov_i_exec(p, t, ip);
2643 instr_dma_ht_exec(struct rte_swx_pipeline *p)
2645 struct thread *t = &p->threads[p->thread_id];
2646 struct instruction *ip = t->ip;
2648 __instr_dma_ht_exec(p, t, ip);
2655 instr_dma_ht2_exec(struct rte_swx_pipeline *p)
2657 struct thread *t = &p->threads[p->thread_id];
2658 struct instruction *ip = t->ip;
2660 __instr_dma_ht2_exec(p, t, ip);
2667 instr_dma_ht3_exec(struct rte_swx_pipeline *p)
2669 struct thread *t = &p->threads[p->thread_id];
2670 struct instruction *ip = t->ip;
2672 __instr_dma_ht3_exec(p, t, ip);
2679 instr_dma_ht4_exec(struct rte_swx_pipeline *p)
2681 struct thread *t = &p->threads[p->thread_id];
2682 struct instruction *ip = t->ip;
2684 __instr_dma_ht4_exec(p, t, ip);
2691 instr_dma_ht5_exec(struct rte_swx_pipeline *p)
2693 struct thread *t = &p->threads[p->thread_id];
2694 struct instruction *ip = t->ip;
2696 __instr_dma_ht5_exec(p, t, ip);
2703 instr_dma_ht6_exec(struct rte_swx_pipeline *p)
2705 struct thread *t = &p->threads[p->thread_id];
2706 struct instruction *ip = t->ip;
2708 __instr_dma_ht6_exec(p, t, ip);
2715 instr_dma_ht7_exec(struct rte_swx_pipeline *p)
2717 struct thread *t = &p->threads[p->thread_id];
2718 struct instruction *ip = t->ip;
2720 __instr_dma_ht7_exec(p, t, ip);
2727 instr_dma_ht8_exec(struct rte_swx_pipeline *p)
2729 struct thread *t = &p->threads[p->thread_id];
2730 struct instruction *ip = t->ip;
2732 __instr_dma_ht8_exec(p, t, ip);
2742 instr_alu_add_translate(struct rte_swx_pipeline *p,
2743 struct action *action,
2746 struct instruction *instr,
2747 struct instruction_data *data __rte_unused)
2749 char *dst = tokens[1], *src = tokens[2];
2750 struct field *fdst, *fsrc;
2752 uint32_t dst_struct_id = 0, src_struct_id = 0;
2754 CHECK(n_tokens == 3, EINVAL);
2756 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2757 CHECK(fdst, EINVAL);
2758 CHECK(!fdst->var_size, EINVAL);
2760 /* ADD, ADD_HM, ADD_MH, ADD_HH. */
2761 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2763 CHECK(!fsrc->var_size, EINVAL);
2765 instr->type = INSTR_ALU_ADD;
2766 if (dst[0] == 'h' && src[0] != 'h')
2767 instr->type = INSTR_ALU_ADD_HM;
2768 if (dst[0] != 'h' && src[0] == 'h')
2769 instr->type = INSTR_ALU_ADD_MH;
2770 if (dst[0] == 'h' && src[0] == 'h')
2771 instr->type = INSTR_ALU_ADD_HH;
2773 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2774 instr->alu.dst.n_bits = fdst->n_bits;
2775 instr->alu.dst.offset = fdst->offset / 8;
2776 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2777 instr->alu.src.n_bits = fsrc->n_bits;
2778 instr->alu.src.offset = fsrc->offset / 8;
2782 /* ADD_MI, ADD_HI. */
2783 src_val = strtoull(src, &src, 0);
2784 CHECK(!src[0], EINVAL);
2786 instr->type = INSTR_ALU_ADD_MI;
2788 instr->type = INSTR_ALU_ADD_HI;
2790 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2791 instr->alu.dst.n_bits = fdst->n_bits;
2792 instr->alu.dst.offset = fdst->offset / 8;
2793 instr->alu.src_val = src_val;
2798 instr_alu_sub_translate(struct rte_swx_pipeline *p,
2799 struct action *action,
2802 struct instruction *instr,
2803 struct instruction_data *data __rte_unused)
2805 char *dst = tokens[1], *src = tokens[2];
2806 struct field *fdst, *fsrc;
2808 uint32_t dst_struct_id = 0, src_struct_id = 0;
2810 CHECK(n_tokens == 3, EINVAL);
2812 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2813 CHECK(fdst, EINVAL);
2814 CHECK(!fdst->var_size, EINVAL);
2816 /* SUB, SUB_HM, SUB_MH, SUB_HH. */
2817 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2819 CHECK(!fsrc->var_size, EINVAL);
2821 instr->type = INSTR_ALU_SUB;
2822 if (dst[0] == 'h' && src[0] != 'h')
2823 instr->type = INSTR_ALU_SUB_HM;
2824 if (dst[0] != 'h' && src[0] == 'h')
2825 instr->type = INSTR_ALU_SUB_MH;
2826 if (dst[0] == 'h' && src[0] == 'h')
2827 instr->type = INSTR_ALU_SUB_HH;
2829 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2830 instr->alu.dst.n_bits = fdst->n_bits;
2831 instr->alu.dst.offset = fdst->offset / 8;
2832 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2833 instr->alu.src.n_bits = fsrc->n_bits;
2834 instr->alu.src.offset = fsrc->offset / 8;
2838 /* SUB_MI, SUB_HI. */
2839 src_val = strtoull(src, &src, 0);
2840 CHECK(!src[0], EINVAL);
2842 instr->type = INSTR_ALU_SUB_MI;
2844 instr->type = INSTR_ALU_SUB_HI;
2846 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2847 instr->alu.dst.n_bits = fdst->n_bits;
2848 instr->alu.dst.offset = fdst->offset / 8;
2849 instr->alu.src_val = src_val;
2854 instr_alu_ckadd_translate(struct rte_swx_pipeline *p,
2855 struct action *action __rte_unused,
2858 struct instruction *instr,
2859 struct instruction_data *data __rte_unused)
2861 char *dst = tokens[1], *src = tokens[2];
2862 struct header *hdst, *hsrc;
2863 struct field *fdst, *fsrc;
2865 CHECK(n_tokens == 3, EINVAL);
2867 fdst = header_field_parse(p, dst, &hdst);
2868 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
2869 CHECK(!fdst->var_size, EINVAL);
2872 fsrc = header_field_parse(p, src, &hsrc);
2874 CHECK(!fsrc->var_size, EINVAL);
2876 instr->type = INSTR_ALU_CKADD_FIELD;
2877 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2878 instr->alu.dst.n_bits = fdst->n_bits;
2879 instr->alu.dst.offset = fdst->offset / 8;
2880 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2881 instr->alu.src.n_bits = fsrc->n_bits;
2882 instr->alu.src.offset = fsrc->offset / 8;
2886 /* CKADD_STRUCT, CKADD_STRUCT20. */
2887 hsrc = header_parse(p, src);
2888 CHECK(hsrc, EINVAL);
2889 CHECK(!hsrc->st->var_size, EINVAL);
2891 instr->type = INSTR_ALU_CKADD_STRUCT;
2892 if ((hsrc->st->n_bits / 8) == 20)
2893 instr->type = INSTR_ALU_CKADD_STRUCT20;
2895 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2896 instr->alu.dst.n_bits = fdst->n_bits;
2897 instr->alu.dst.offset = fdst->offset / 8;
2898 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2899 instr->alu.src.n_bits = hsrc->st->n_bits;
2900 instr->alu.src.offset = 0; /* Unused. */
2905 instr_alu_cksub_translate(struct rte_swx_pipeline *p,
2906 struct action *action __rte_unused,
2909 struct instruction *instr,
2910 struct instruction_data *data __rte_unused)
2912 char *dst = tokens[1], *src = tokens[2];
2913 struct header *hdst, *hsrc;
2914 struct field *fdst, *fsrc;
2916 CHECK(n_tokens == 3, EINVAL);
2918 fdst = header_field_parse(p, dst, &hdst);
2919 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
2920 CHECK(!fdst->var_size, EINVAL);
2922 fsrc = header_field_parse(p, src, &hsrc);
2923 CHECK(fsrc, EINVAL);
2924 CHECK(!fsrc->var_size, EINVAL);
2926 instr->type = INSTR_ALU_CKSUB_FIELD;
2927 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2928 instr->alu.dst.n_bits = fdst->n_bits;
2929 instr->alu.dst.offset = fdst->offset / 8;
2930 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2931 instr->alu.src.n_bits = fsrc->n_bits;
2932 instr->alu.src.offset = fsrc->offset / 8;
2937 instr_alu_shl_translate(struct rte_swx_pipeline *p,
2938 struct action *action,
2941 struct instruction *instr,
2942 struct instruction_data *data __rte_unused)
2944 char *dst = tokens[1], *src = tokens[2];
2945 struct field *fdst, *fsrc;
2947 uint32_t dst_struct_id = 0, src_struct_id = 0;
2949 CHECK(n_tokens == 3, EINVAL);
2951 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2952 CHECK(fdst, EINVAL);
2953 CHECK(!fdst->var_size, EINVAL);
2955 /* SHL, SHL_HM, SHL_MH, SHL_HH. */
2956 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2958 CHECK(!fsrc->var_size, EINVAL);
2960 instr->type = INSTR_ALU_SHL;
2961 if (dst[0] == 'h' && src[0] != 'h')
2962 instr->type = INSTR_ALU_SHL_HM;
2963 if (dst[0] != 'h' && src[0] == 'h')
2964 instr->type = INSTR_ALU_SHL_MH;
2965 if (dst[0] == 'h' && src[0] == 'h')
2966 instr->type = INSTR_ALU_SHL_HH;
2968 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2969 instr->alu.dst.n_bits = fdst->n_bits;
2970 instr->alu.dst.offset = fdst->offset / 8;
2971 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2972 instr->alu.src.n_bits = fsrc->n_bits;
2973 instr->alu.src.offset = fsrc->offset / 8;
2977 /* SHL_MI, SHL_HI. */
2978 src_val = strtoull(src, &src, 0);
2979 CHECK(!src[0], EINVAL);
2981 instr->type = INSTR_ALU_SHL_MI;
2983 instr->type = INSTR_ALU_SHL_HI;
2985 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2986 instr->alu.dst.n_bits = fdst->n_bits;
2987 instr->alu.dst.offset = fdst->offset / 8;
2988 instr->alu.src_val = src_val;
2993 instr_alu_shr_translate(struct rte_swx_pipeline *p,
2994 struct action *action,
2997 struct instruction *instr,
2998 struct instruction_data *data __rte_unused)
3000 char *dst = tokens[1], *src = tokens[2];
3001 struct field *fdst, *fsrc;
3003 uint32_t dst_struct_id = 0, src_struct_id = 0;
3005 CHECK(n_tokens == 3, EINVAL);
3007 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3008 CHECK(fdst, EINVAL);
3009 CHECK(!fdst->var_size, EINVAL);
3011 /* SHR, SHR_HM, SHR_MH, SHR_HH. */
3012 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3014 CHECK(!fsrc->var_size, EINVAL);
3016 instr->type = INSTR_ALU_SHR;
3017 if (dst[0] == 'h' && src[0] != 'h')
3018 instr->type = INSTR_ALU_SHR_HM;
3019 if (dst[0] != 'h' && src[0] == 'h')
3020 instr->type = INSTR_ALU_SHR_MH;
3021 if (dst[0] == 'h' && src[0] == 'h')
3022 instr->type = INSTR_ALU_SHR_HH;
3024 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3025 instr->alu.dst.n_bits = fdst->n_bits;
3026 instr->alu.dst.offset = fdst->offset / 8;
3027 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3028 instr->alu.src.n_bits = fsrc->n_bits;
3029 instr->alu.src.offset = fsrc->offset / 8;
3033 /* SHR_MI, SHR_HI. */
3034 src_val = strtoull(src, &src, 0);
3035 CHECK(!src[0], EINVAL);
3037 instr->type = INSTR_ALU_SHR_MI;
3039 instr->type = INSTR_ALU_SHR_HI;
3041 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3042 instr->alu.dst.n_bits = fdst->n_bits;
3043 instr->alu.dst.offset = fdst->offset / 8;
3044 instr->alu.src_val = src_val;
3049 instr_alu_and_translate(struct rte_swx_pipeline *p,
3050 struct action *action,
3053 struct instruction *instr,
3054 struct instruction_data *data __rte_unused)
3056 char *dst = tokens[1], *src = tokens[2];
3057 struct field *fdst, *fsrc;
3059 uint32_t dst_struct_id = 0, src_struct_id = 0;
3061 CHECK(n_tokens == 3, EINVAL);
3063 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3064 CHECK(fdst, EINVAL);
3065 CHECK(!fdst->var_size, EINVAL);
3067 /* AND, AND_MH, AND_HM, AND_HH. */
3068 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3070 CHECK(!fsrc->var_size, EINVAL);
3072 instr->type = INSTR_ALU_AND;
3073 if (dst[0] != 'h' && src[0] == 'h')
3074 instr->type = INSTR_ALU_AND_MH;
3075 if (dst[0] == 'h' && src[0] != 'h')
3076 instr->type = INSTR_ALU_AND_HM;
3077 if (dst[0] == 'h' && src[0] == 'h')
3078 instr->type = INSTR_ALU_AND_HH;
3080 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3081 instr->alu.dst.n_bits = fdst->n_bits;
3082 instr->alu.dst.offset = fdst->offset / 8;
3083 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3084 instr->alu.src.n_bits = fsrc->n_bits;
3085 instr->alu.src.offset = fsrc->offset / 8;
3090 src_val = strtoull(src, &src, 0);
3091 CHECK(!src[0], EINVAL);
3094 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3096 instr->type = INSTR_ALU_AND_I;
3097 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3098 instr->alu.dst.n_bits = fdst->n_bits;
3099 instr->alu.dst.offset = fdst->offset / 8;
3100 instr->alu.src_val = src_val;
3105 instr_alu_or_translate(struct rte_swx_pipeline *p,
3106 struct action *action,
3109 struct instruction *instr,
3110 struct instruction_data *data __rte_unused)
3112 char *dst = tokens[1], *src = tokens[2];
3113 struct field *fdst, *fsrc;
3115 uint32_t dst_struct_id = 0, src_struct_id = 0;
3117 CHECK(n_tokens == 3, EINVAL);
3119 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3120 CHECK(fdst, EINVAL);
3121 CHECK(!fdst->var_size, EINVAL);
3123 /* OR, OR_MH, OR_HM, OR_HH. */
3124 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3126 CHECK(!fsrc->var_size, EINVAL);
3128 instr->type = INSTR_ALU_OR;
3129 if (dst[0] != 'h' && src[0] == 'h')
3130 instr->type = INSTR_ALU_OR_MH;
3131 if (dst[0] == 'h' && src[0] != 'h')
3132 instr->type = INSTR_ALU_OR_HM;
3133 if (dst[0] == 'h' && src[0] == 'h')
3134 instr->type = INSTR_ALU_OR_HH;
3136 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3137 instr->alu.dst.n_bits = fdst->n_bits;
3138 instr->alu.dst.offset = fdst->offset / 8;
3139 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3140 instr->alu.src.n_bits = fsrc->n_bits;
3141 instr->alu.src.offset = fsrc->offset / 8;
3146 src_val = strtoull(src, &src, 0);
3147 CHECK(!src[0], EINVAL);
3150 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3152 instr->type = INSTR_ALU_OR_I;
3153 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3154 instr->alu.dst.n_bits = fdst->n_bits;
3155 instr->alu.dst.offset = fdst->offset / 8;
3156 instr->alu.src_val = src_val;
3161 instr_alu_xor_translate(struct rte_swx_pipeline *p,
3162 struct action *action,
3165 struct instruction *instr,
3166 struct instruction_data *data __rte_unused)
3168 char *dst = tokens[1], *src = tokens[2];
3169 struct field *fdst, *fsrc;
3171 uint32_t dst_struct_id = 0, src_struct_id = 0;
3173 CHECK(n_tokens == 3, EINVAL);
3175 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3176 CHECK(fdst, EINVAL);
3177 CHECK(!fdst->var_size, EINVAL);
3179 /* XOR, XOR_MH, XOR_HM, XOR_HH. */
3180 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3182 CHECK(!fsrc->var_size, EINVAL);
3184 instr->type = INSTR_ALU_XOR;
3185 if (dst[0] != 'h' && src[0] == 'h')
3186 instr->type = INSTR_ALU_XOR_MH;
3187 if (dst[0] == 'h' && src[0] != 'h')
3188 instr->type = INSTR_ALU_XOR_HM;
3189 if (dst[0] == 'h' && src[0] == 'h')
3190 instr->type = INSTR_ALU_XOR_HH;
3192 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3193 instr->alu.dst.n_bits = fdst->n_bits;
3194 instr->alu.dst.offset = fdst->offset / 8;
3195 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3196 instr->alu.src.n_bits = fsrc->n_bits;
3197 instr->alu.src.offset = fsrc->offset / 8;
3202 src_val = strtoull(src, &src, 0);
3203 CHECK(!src[0], EINVAL);
3206 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3208 instr->type = INSTR_ALU_XOR_I;
3209 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3210 instr->alu.dst.n_bits = fdst->n_bits;
3211 instr->alu.dst.offset = fdst->offset / 8;
3212 instr->alu.src_val = src_val;
3217 instr_alu_add_exec(struct rte_swx_pipeline *p)
3219 struct thread *t = &p->threads[p->thread_id];
3220 struct instruction *ip = t->ip;
3223 __instr_alu_add_exec(p, t, ip);
3230 instr_alu_add_mh_exec(struct rte_swx_pipeline *p)
3232 struct thread *t = &p->threads[p->thread_id];
3233 struct instruction *ip = t->ip;
3236 __instr_alu_add_mh_exec(p, t, ip);
3243 instr_alu_add_hm_exec(struct rte_swx_pipeline *p)
3245 struct thread *t = &p->threads[p->thread_id];
3246 struct instruction *ip = t->ip;
3249 __instr_alu_add_hm_exec(p, t, ip);
3256 instr_alu_add_hh_exec(struct rte_swx_pipeline *p)
3258 struct thread *t = &p->threads[p->thread_id];
3259 struct instruction *ip = t->ip;
3262 __instr_alu_add_hh_exec(p, t, ip);
3269 instr_alu_add_mi_exec(struct rte_swx_pipeline *p)
3271 struct thread *t = &p->threads[p->thread_id];
3272 struct instruction *ip = t->ip;
3275 __instr_alu_add_mi_exec(p, t, ip);
3282 instr_alu_add_hi_exec(struct rte_swx_pipeline *p)
3284 struct thread *t = &p->threads[p->thread_id];
3285 struct instruction *ip = t->ip;
3288 __instr_alu_add_hi_exec(p, t, ip);
3295 instr_alu_sub_exec(struct rte_swx_pipeline *p)
3297 struct thread *t = &p->threads[p->thread_id];
3298 struct instruction *ip = t->ip;
3301 __instr_alu_sub_exec(p, t, ip);
3308 instr_alu_sub_mh_exec(struct rte_swx_pipeline *p)
3310 struct thread *t = &p->threads[p->thread_id];
3311 struct instruction *ip = t->ip;
3314 __instr_alu_sub_mh_exec(p, t, ip);
3321 instr_alu_sub_hm_exec(struct rte_swx_pipeline *p)
3323 struct thread *t = &p->threads[p->thread_id];
3324 struct instruction *ip = t->ip;
3327 __instr_alu_sub_hm_exec(p, t, ip);
3334 instr_alu_sub_hh_exec(struct rte_swx_pipeline *p)
3336 struct thread *t = &p->threads[p->thread_id];
3337 struct instruction *ip = t->ip;
3340 __instr_alu_sub_hh_exec(p, t, ip);
3347 instr_alu_sub_mi_exec(struct rte_swx_pipeline *p)
3349 struct thread *t = &p->threads[p->thread_id];
3350 struct instruction *ip = t->ip;
3353 __instr_alu_sub_mi_exec(p, t, ip);
3360 instr_alu_sub_hi_exec(struct rte_swx_pipeline *p)
3362 struct thread *t = &p->threads[p->thread_id];
3363 struct instruction *ip = t->ip;
3366 __instr_alu_sub_hi_exec(p, t, ip);
3373 instr_alu_shl_exec(struct rte_swx_pipeline *p)
3375 struct thread *t = &p->threads[p->thread_id];
3376 struct instruction *ip = t->ip;
3379 __instr_alu_shl_exec(p, t, ip);
3386 instr_alu_shl_mh_exec(struct rte_swx_pipeline *p)
3388 struct thread *t = &p->threads[p->thread_id];
3389 struct instruction *ip = t->ip;
3392 __instr_alu_shl_mh_exec(p, t, ip);
3399 instr_alu_shl_hm_exec(struct rte_swx_pipeline *p)
3401 struct thread *t = &p->threads[p->thread_id];
3402 struct instruction *ip = t->ip;
3405 __instr_alu_shl_hm_exec(p, t, ip);
3412 instr_alu_shl_hh_exec(struct rte_swx_pipeline *p)
3414 struct thread *t = &p->threads[p->thread_id];
3415 struct instruction *ip = t->ip;
3418 __instr_alu_shl_hh_exec(p, t, ip);
3425 instr_alu_shl_mi_exec(struct rte_swx_pipeline *p)
3427 struct thread *t = &p->threads[p->thread_id];
3428 struct instruction *ip = t->ip;
3431 __instr_alu_shl_mi_exec(p, t, ip);
3438 instr_alu_shl_hi_exec(struct rte_swx_pipeline *p)
3440 struct thread *t = &p->threads[p->thread_id];
3441 struct instruction *ip = t->ip;
3444 __instr_alu_shl_hi_exec(p, t, ip);
3451 instr_alu_shr_exec(struct rte_swx_pipeline *p)
3453 struct thread *t = &p->threads[p->thread_id];
3454 struct instruction *ip = t->ip;
3457 __instr_alu_shr_exec(p, t, ip);
3464 instr_alu_shr_mh_exec(struct rte_swx_pipeline *p)
3466 struct thread *t = &p->threads[p->thread_id];
3467 struct instruction *ip = t->ip;
3470 __instr_alu_shr_mh_exec(p, t, ip);
3477 instr_alu_shr_hm_exec(struct rte_swx_pipeline *p)
3479 struct thread *t = &p->threads[p->thread_id];
3480 struct instruction *ip = t->ip;
3483 __instr_alu_shr_hm_exec(p, t, ip);
3490 instr_alu_shr_hh_exec(struct rte_swx_pipeline *p)
3492 struct thread *t = &p->threads[p->thread_id];
3493 struct instruction *ip = t->ip;
3496 __instr_alu_shr_hh_exec(p, t, ip);
3503 instr_alu_shr_mi_exec(struct rte_swx_pipeline *p)
3505 struct thread *t = &p->threads[p->thread_id];
3506 struct instruction *ip = t->ip;
3509 __instr_alu_shr_mi_exec(p, t, ip);
3516 instr_alu_shr_hi_exec(struct rte_swx_pipeline *p)
3518 struct thread *t = &p->threads[p->thread_id];
3519 struct instruction *ip = t->ip;
3522 __instr_alu_shr_hi_exec(p, t, ip);
3529 instr_alu_and_exec(struct rte_swx_pipeline *p)
3531 struct thread *t = &p->threads[p->thread_id];
3532 struct instruction *ip = t->ip;
3535 __instr_alu_and_exec(p, t, ip);
3542 instr_alu_and_mh_exec(struct rte_swx_pipeline *p)
3544 struct thread *t = &p->threads[p->thread_id];
3545 struct instruction *ip = t->ip;
3548 __instr_alu_and_mh_exec(p, t, ip);
3555 instr_alu_and_hm_exec(struct rte_swx_pipeline *p)
3557 struct thread *t = &p->threads[p->thread_id];
3558 struct instruction *ip = t->ip;
3561 __instr_alu_and_hm_exec(p, t, ip);
3568 instr_alu_and_hh_exec(struct rte_swx_pipeline *p)
3570 struct thread *t = &p->threads[p->thread_id];
3571 struct instruction *ip = t->ip;
3574 __instr_alu_and_hh_exec(p, t, ip);
3581 instr_alu_and_i_exec(struct rte_swx_pipeline *p)
3583 struct thread *t = &p->threads[p->thread_id];
3584 struct instruction *ip = t->ip;
3587 __instr_alu_and_i_exec(p, t, ip);
3594 instr_alu_or_exec(struct rte_swx_pipeline *p)
3596 struct thread *t = &p->threads[p->thread_id];
3597 struct instruction *ip = t->ip;
3600 __instr_alu_or_exec(p, t, ip);
3607 instr_alu_or_mh_exec(struct rte_swx_pipeline *p)
3609 struct thread *t = &p->threads[p->thread_id];
3610 struct instruction *ip = t->ip;
3613 __instr_alu_or_mh_exec(p, t, ip);
3620 instr_alu_or_hm_exec(struct rte_swx_pipeline *p)
3622 struct thread *t = &p->threads[p->thread_id];
3623 struct instruction *ip = t->ip;
3626 __instr_alu_or_hm_exec(p, t, ip);
3633 instr_alu_or_hh_exec(struct rte_swx_pipeline *p)
3635 struct thread *t = &p->threads[p->thread_id];
3636 struct instruction *ip = t->ip;
3639 __instr_alu_or_hh_exec(p, t, ip);
3646 instr_alu_or_i_exec(struct rte_swx_pipeline *p)
3648 struct thread *t = &p->threads[p->thread_id];
3649 struct instruction *ip = t->ip;
3652 __instr_alu_or_i_exec(p, t, ip);
3659 instr_alu_xor_exec(struct rte_swx_pipeline *p)
3661 struct thread *t = &p->threads[p->thread_id];
3662 struct instruction *ip = t->ip;
3665 __instr_alu_xor_exec(p, t, ip);
3672 instr_alu_xor_mh_exec(struct rte_swx_pipeline *p)
3674 struct thread *t = &p->threads[p->thread_id];
3675 struct instruction *ip = t->ip;
3678 __instr_alu_xor_mh_exec(p, t, ip);
3685 instr_alu_xor_hm_exec(struct rte_swx_pipeline *p)
3687 struct thread *t = &p->threads[p->thread_id];
3688 struct instruction *ip = t->ip;
3691 __instr_alu_xor_hm_exec(p, t, ip);
3698 instr_alu_xor_hh_exec(struct rte_swx_pipeline *p)
3700 struct thread *t = &p->threads[p->thread_id];
3701 struct instruction *ip = t->ip;
3704 __instr_alu_xor_hh_exec(p, t, ip);
3711 instr_alu_xor_i_exec(struct rte_swx_pipeline *p)
3713 struct thread *t = &p->threads[p->thread_id];
3714 struct instruction *ip = t->ip;
3717 __instr_alu_xor_i_exec(p, t, ip);
3724 instr_alu_ckadd_field_exec(struct rte_swx_pipeline *p)
3726 struct thread *t = &p->threads[p->thread_id];
3727 struct instruction *ip = t->ip;
3730 __instr_alu_ckadd_field_exec(p, t, ip);
3737 instr_alu_cksub_field_exec(struct rte_swx_pipeline *p)
3739 struct thread *t = &p->threads[p->thread_id];
3740 struct instruction *ip = t->ip;
3743 __instr_alu_cksub_field_exec(p, t, ip);
3750 instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline *p)
3752 struct thread *t = &p->threads[p->thread_id];
3753 struct instruction *ip = t->ip;
3756 __instr_alu_ckadd_struct20_exec(p, t, ip);
3763 instr_alu_ckadd_struct_exec(struct rte_swx_pipeline *p)
3765 struct thread *t = &p->threads[p->thread_id];
3766 struct instruction *ip = t->ip;
3769 __instr_alu_ckadd_struct_exec(p, t, ip);
3778 static struct regarray *
3779 regarray_find(struct rte_swx_pipeline *p, const char *name);
3782 instr_regprefetch_translate(struct rte_swx_pipeline *p,
3783 struct action *action,
3786 struct instruction *instr,
3787 struct instruction_data *data __rte_unused)
3789 char *regarray = tokens[1], *idx = tokens[2];
3792 uint32_t idx_struct_id, idx_val;
3794 CHECK(n_tokens == 3, EINVAL);
3796 r = regarray_find(p, regarray);
3799 /* REGPREFETCH_RH, REGPREFETCH_RM. */
3800 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
3802 CHECK(!fidx->var_size, EINVAL);
3804 instr->type = INSTR_REGPREFETCH_RM;
3806 instr->type = INSTR_REGPREFETCH_RH;
3808 instr->regarray.regarray_id = r->id;
3809 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
3810 instr->regarray.idx.n_bits = fidx->n_bits;
3811 instr->regarray.idx.offset = fidx->offset / 8;
3812 instr->regarray.dstsrc_val = 0; /* Unused. */
3816 /* REGPREFETCH_RI. */
3817 idx_val = strtoul(idx, &idx, 0);
3818 CHECK(!idx[0], EINVAL);
3820 instr->type = INSTR_REGPREFETCH_RI;
3821 instr->regarray.regarray_id = r->id;
3822 instr->regarray.idx_val = idx_val;
3823 instr->regarray.dstsrc_val = 0; /* Unused. */
3828 instr_regrd_translate(struct rte_swx_pipeline *p,
3829 struct action *action,
3832 struct instruction *instr,
3833 struct instruction_data *data __rte_unused)
3835 char *dst = tokens[1], *regarray = tokens[2], *idx = tokens[3];
3837 struct field *fdst, *fidx;
3838 uint32_t dst_struct_id, idx_struct_id, idx_val;
3840 CHECK(n_tokens == 4, EINVAL);
3842 r = regarray_find(p, regarray);
3845 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3846 CHECK(fdst, EINVAL);
3847 CHECK(!fdst->var_size, EINVAL);
3849 /* REGRD_HRH, REGRD_HRM, REGRD_MRH, REGRD_MRM. */
3850 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
3852 CHECK(!fidx->var_size, EINVAL);
3854 instr->type = INSTR_REGRD_MRM;
3855 if (dst[0] == 'h' && idx[0] != 'h')
3856 instr->type = INSTR_REGRD_HRM;
3857 if (dst[0] != 'h' && idx[0] == 'h')
3858 instr->type = INSTR_REGRD_MRH;
3859 if (dst[0] == 'h' && idx[0] == 'h')
3860 instr->type = INSTR_REGRD_HRH;
3862 instr->regarray.regarray_id = r->id;
3863 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
3864 instr->regarray.idx.n_bits = fidx->n_bits;
3865 instr->regarray.idx.offset = fidx->offset / 8;
3866 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
3867 instr->regarray.dstsrc.n_bits = fdst->n_bits;
3868 instr->regarray.dstsrc.offset = fdst->offset / 8;
3872 /* REGRD_MRI, REGRD_HRI. */
3873 idx_val = strtoul(idx, &idx, 0);
3874 CHECK(!idx[0], EINVAL);
3876 instr->type = INSTR_REGRD_MRI;
3878 instr->type = INSTR_REGRD_HRI;
3880 instr->regarray.regarray_id = r->id;
3881 instr->regarray.idx_val = idx_val;
3882 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
3883 instr->regarray.dstsrc.n_bits = fdst->n_bits;
3884 instr->regarray.dstsrc.offset = fdst->offset / 8;
3889 instr_regwr_translate(struct rte_swx_pipeline *p,
3890 struct action *action,
3893 struct instruction *instr,
3894 struct instruction_data *data __rte_unused)
3896 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
3898 struct field *fidx, *fsrc;
3900 uint32_t idx_struct_id, idx_val, src_struct_id;
3902 CHECK(n_tokens == 4, EINVAL);
3904 r = regarray_find(p, regarray);
3907 /* REGWR_RHH, REGWR_RHM, REGWR_RMH, REGWR_RMM. */
3908 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
3909 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3911 CHECK(!fidx->var_size, EINVAL);
3912 CHECK(!fsrc->var_size, EINVAL);
3914 instr->type = INSTR_REGWR_RMM;
3915 if (idx[0] == 'h' && src[0] != 'h')
3916 instr->type = INSTR_REGWR_RHM;
3917 if (idx[0] != 'h' && src[0] == 'h')
3918 instr->type = INSTR_REGWR_RMH;
3919 if (idx[0] == 'h' && src[0] == 'h')
3920 instr->type = INSTR_REGWR_RHH;
3922 instr->regarray.regarray_id = r->id;
3923 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
3924 instr->regarray.idx.n_bits = fidx->n_bits;
3925 instr->regarray.idx.offset = fidx->offset / 8;
3926 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
3927 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
3928 instr->regarray.dstsrc.offset = fsrc->offset / 8;
3932 /* REGWR_RHI, REGWR_RMI. */
3933 if (fidx && !fsrc) {
3934 CHECK(!fidx->var_size, EINVAL);
3936 src_val = strtoull(src, &src, 0);
3937 CHECK(!src[0], EINVAL);
3939 instr->type = INSTR_REGWR_RMI;
3941 instr->type = INSTR_REGWR_RHI;
3943 instr->regarray.regarray_id = r->id;
3944 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
3945 instr->regarray.idx.n_bits = fidx->n_bits;
3946 instr->regarray.idx.offset = fidx->offset / 8;
3947 instr->regarray.dstsrc_val = src_val;
3951 /* REGWR_RIH, REGWR_RIM. */
3952 if (!fidx && fsrc) {
3953 idx_val = strtoul(idx, &idx, 0);
3954 CHECK(!idx[0], EINVAL);
3956 CHECK(!fsrc->var_size, EINVAL);
3958 instr->type = INSTR_REGWR_RIM;
3960 instr->type = INSTR_REGWR_RIH;
3962 instr->regarray.regarray_id = r->id;
3963 instr->regarray.idx_val = idx_val;
3964 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
3965 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
3966 instr->regarray.dstsrc.offset = fsrc->offset / 8;
3971 src_val = strtoull(src, &src, 0);
3972 CHECK(!src[0], EINVAL);
3974 idx_val = strtoul(idx, &idx, 0);
3975 CHECK(!idx[0], EINVAL);
3977 instr->type = INSTR_REGWR_RII;
3978 instr->regarray.idx_val = idx_val;
3979 instr->regarray.dstsrc_val = src_val;
3985 instr_regadd_translate(struct rte_swx_pipeline *p,
3986 struct action *action,
3989 struct instruction *instr,
3990 struct instruction_data *data __rte_unused)
3992 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
3994 struct field *fidx, *fsrc;
3996 uint32_t idx_struct_id, idx_val, src_struct_id;
3998 CHECK(n_tokens == 4, EINVAL);
4000 r = regarray_find(p, regarray);
4003 /* REGADD_RHH, REGADD_RHM, REGADD_RMH, REGADD_RMM. */
4004 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4005 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4007 CHECK(!fidx->var_size, EINVAL);
4008 CHECK(!fsrc->var_size, EINVAL);
4010 instr->type = INSTR_REGADD_RMM;
4011 if (idx[0] == 'h' && src[0] != 'h')
4012 instr->type = INSTR_REGADD_RHM;
4013 if (idx[0] != 'h' && src[0] == 'h')
4014 instr->type = INSTR_REGADD_RMH;
4015 if (idx[0] == 'h' && src[0] == 'h')
4016 instr->type = INSTR_REGADD_RHH;
4018 instr->regarray.regarray_id = r->id;
4019 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4020 instr->regarray.idx.n_bits = fidx->n_bits;
4021 instr->regarray.idx.offset = fidx->offset / 8;
4022 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4023 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4024 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4028 /* REGADD_RHI, REGADD_RMI. */
4029 if (fidx && !fsrc) {
4030 CHECK(!fidx->var_size, EINVAL);
4032 src_val = strtoull(src, &src, 0);
4033 CHECK(!src[0], EINVAL);
4035 instr->type = INSTR_REGADD_RMI;
4037 instr->type = INSTR_REGADD_RHI;
4039 instr->regarray.regarray_id = r->id;
4040 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4041 instr->regarray.idx.n_bits = fidx->n_bits;
4042 instr->regarray.idx.offset = fidx->offset / 8;
4043 instr->regarray.dstsrc_val = src_val;
4047 /* REGADD_RIH, REGADD_RIM. */
4048 if (!fidx && fsrc) {
4049 idx_val = strtoul(idx, &idx, 0);
4050 CHECK(!idx[0], EINVAL);
4052 CHECK(!fsrc->var_size, EINVAL);
4054 instr->type = INSTR_REGADD_RIM;
4056 instr->type = INSTR_REGADD_RIH;
4058 instr->regarray.regarray_id = r->id;
4059 instr->regarray.idx_val = idx_val;
4060 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4061 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4062 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4067 src_val = strtoull(src, &src, 0);
4068 CHECK(!src[0], EINVAL);
4070 idx_val = strtoul(idx, &idx, 0);
4071 CHECK(!idx[0], EINVAL);
4073 instr->type = INSTR_REGADD_RII;
4074 instr->regarray.idx_val = idx_val;
4075 instr->regarray.dstsrc_val = src_val;
4080 instr_regprefetch_rh_exec(struct rte_swx_pipeline *p)
4082 struct thread *t = &p->threads[p->thread_id];
4083 struct instruction *ip = t->ip;
4086 __instr_regprefetch_rh_exec(p, t, ip);
4093 instr_regprefetch_rm_exec(struct rte_swx_pipeline *p)
4095 struct thread *t = &p->threads[p->thread_id];
4096 struct instruction *ip = t->ip;
4099 __instr_regprefetch_rm_exec(p, t, ip);
4106 instr_regprefetch_ri_exec(struct rte_swx_pipeline *p)
4108 struct thread *t = &p->threads[p->thread_id];
4109 struct instruction *ip = t->ip;
4112 __instr_regprefetch_ri_exec(p, t, ip);
4119 instr_regrd_hrh_exec(struct rte_swx_pipeline *p)
4121 struct thread *t = &p->threads[p->thread_id];
4122 struct instruction *ip = t->ip;
4125 __instr_regrd_hrh_exec(p, t, ip);
4132 instr_regrd_hrm_exec(struct rte_swx_pipeline *p)
4134 struct thread *t = &p->threads[p->thread_id];
4135 struct instruction *ip = t->ip;
4138 __instr_regrd_hrm_exec(p, t, ip);
4145 instr_regrd_mrh_exec(struct rte_swx_pipeline *p)
4147 struct thread *t = &p->threads[p->thread_id];
4148 struct instruction *ip = t->ip;
4151 __instr_regrd_mrh_exec(p, t, ip);
4158 instr_regrd_mrm_exec(struct rte_swx_pipeline *p)
4160 struct thread *t = &p->threads[p->thread_id];
4161 struct instruction *ip = t->ip;
4164 __instr_regrd_mrm_exec(p, t, ip);
4171 instr_regrd_hri_exec(struct rte_swx_pipeline *p)
4173 struct thread *t = &p->threads[p->thread_id];
4174 struct instruction *ip = t->ip;
4177 __instr_regrd_hri_exec(p, t, ip);
4184 instr_regrd_mri_exec(struct rte_swx_pipeline *p)
4186 struct thread *t = &p->threads[p->thread_id];
4187 struct instruction *ip = t->ip;
4190 __instr_regrd_mri_exec(p, t, ip);
4197 instr_regwr_rhh_exec(struct rte_swx_pipeline *p)
4199 struct thread *t = &p->threads[p->thread_id];
4200 struct instruction *ip = t->ip;
4203 __instr_regwr_rhh_exec(p, t, ip);
4210 instr_regwr_rhm_exec(struct rte_swx_pipeline *p)
4212 struct thread *t = &p->threads[p->thread_id];
4213 struct instruction *ip = t->ip;
4216 __instr_regwr_rhm_exec(p, t, ip);
4223 instr_regwr_rmh_exec(struct rte_swx_pipeline *p)
4225 struct thread *t = &p->threads[p->thread_id];
4226 struct instruction *ip = t->ip;
4229 __instr_regwr_rmh_exec(p, t, ip);
4236 instr_regwr_rmm_exec(struct rte_swx_pipeline *p)
4238 struct thread *t = &p->threads[p->thread_id];
4239 struct instruction *ip = t->ip;
4242 __instr_regwr_rmm_exec(p, t, ip);
4249 instr_regwr_rhi_exec(struct rte_swx_pipeline *p)
4251 struct thread *t = &p->threads[p->thread_id];
4252 struct instruction *ip = t->ip;
4255 __instr_regwr_rhi_exec(p, t, ip);
4262 instr_regwr_rmi_exec(struct rte_swx_pipeline *p)
4264 struct thread *t = &p->threads[p->thread_id];
4265 struct instruction *ip = t->ip;
4268 __instr_regwr_rmi_exec(p, t, ip);
4275 instr_regwr_rih_exec(struct rte_swx_pipeline *p)
4277 struct thread *t = &p->threads[p->thread_id];
4278 struct instruction *ip = t->ip;
4281 __instr_regwr_rih_exec(p, t, ip);
4288 instr_regwr_rim_exec(struct rte_swx_pipeline *p)
4290 struct thread *t = &p->threads[p->thread_id];
4291 struct instruction *ip = t->ip;
4294 __instr_regwr_rim_exec(p, t, ip);
4301 instr_regwr_rii_exec(struct rte_swx_pipeline *p)
4303 struct thread *t = &p->threads[p->thread_id];
4304 struct instruction *ip = t->ip;
4307 __instr_regwr_rii_exec(p, t, ip);
4314 instr_regadd_rhh_exec(struct rte_swx_pipeline *p)
4316 struct thread *t = &p->threads[p->thread_id];
4317 struct instruction *ip = t->ip;
4320 __instr_regadd_rhh_exec(p, t, ip);
4327 instr_regadd_rhm_exec(struct rte_swx_pipeline *p)
4329 struct thread *t = &p->threads[p->thread_id];
4330 struct instruction *ip = t->ip;
4333 __instr_regadd_rhm_exec(p, t, ip);
4340 instr_regadd_rmh_exec(struct rte_swx_pipeline *p)
4342 struct thread *t = &p->threads[p->thread_id];
4343 struct instruction *ip = t->ip;
4346 __instr_regadd_rmh_exec(p, t, ip);
4353 instr_regadd_rmm_exec(struct rte_swx_pipeline *p)
4355 struct thread *t = &p->threads[p->thread_id];
4356 struct instruction *ip = t->ip;
4359 __instr_regadd_rmm_exec(p, t, ip);
4366 instr_regadd_rhi_exec(struct rte_swx_pipeline *p)
4368 struct thread *t = &p->threads[p->thread_id];
4369 struct instruction *ip = t->ip;
4372 __instr_regadd_rhi_exec(p, t, ip);
4379 instr_regadd_rmi_exec(struct rte_swx_pipeline *p)
4381 struct thread *t = &p->threads[p->thread_id];
4382 struct instruction *ip = t->ip;
4385 __instr_regadd_rmi_exec(p, t, ip);
4392 instr_regadd_rih_exec(struct rte_swx_pipeline *p)
4394 struct thread *t = &p->threads[p->thread_id];
4395 struct instruction *ip = t->ip;
4398 __instr_regadd_rih_exec(p, t, ip);
4405 instr_regadd_rim_exec(struct rte_swx_pipeline *p)
4407 struct thread *t = &p->threads[p->thread_id];
4408 struct instruction *ip = t->ip;
4411 __instr_regadd_rim_exec(p, t, ip);
4418 instr_regadd_rii_exec(struct rte_swx_pipeline *p)
4420 struct thread *t = &p->threads[p->thread_id];
4421 struct instruction *ip = t->ip;
4424 __instr_regadd_rii_exec(p, t, ip);
4433 static struct metarray *
4434 metarray_find(struct rte_swx_pipeline *p, const char *name);
4437 instr_metprefetch_translate(struct rte_swx_pipeline *p,
4438 struct action *action,
4441 struct instruction *instr,
4442 struct instruction_data *data __rte_unused)
4444 char *metarray = tokens[1], *idx = tokens[2];
4447 uint32_t idx_struct_id, idx_val;
4449 CHECK(n_tokens == 3, EINVAL);
4451 m = metarray_find(p, metarray);
4454 /* METPREFETCH_H, METPREFETCH_M. */
4455 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4457 CHECK(!fidx->var_size, EINVAL);
4459 instr->type = INSTR_METPREFETCH_M;
4461 instr->type = INSTR_METPREFETCH_H;
4463 instr->meter.metarray_id = m->id;
4464 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4465 instr->meter.idx.n_bits = fidx->n_bits;
4466 instr->meter.idx.offset = fidx->offset / 8;
4470 /* METPREFETCH_I. */
4471 idx_val = strtoul(idx, &idx, 0);
4472 CHECK(!idx[0], EINVAL);
4474 instr->type = INSTR_METPREFETCH_I;
4475 instr->meter.metarray_id = m->id;
4476 instr->meter.idx_val = idx_val;
4481 instr_meter_translate(struct rte_swx_pipeline *p,
4482 struct action *action,
4485 struct instruction *instr,
4486 struct instruction_data *data __rte_unused)
4488 char *metarray = tokens[1], *idx = tokens[2], *length = tokens[3];
4489 char *color_in = tokens[4], *color_out = tokens[5];
4491 struct field *fidx, *flength, *fcin, *fcout;
4492 uint32_t idx_struct_id, length_struct_id;
4493 uint32_t color_in_struct_id, color_out_struct_id;
4495 CHECK(n_tokens == 6, EINVAL);
4497 m = metarray_find(p, metarray);
4500 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4502 flength = struct_field_parse(p, action, length, &length_struct_id);
4503 CHECK(flength, EINVAL);
4504 CHECK(!flength->var_size, EINVAL);
4506 fcin = struct_field_parse(p, action, color_in, &color_in_struct_id);
4508 fcout = struct_field_parse(p, NULL, color_out, &color_out_struct_id);
4509 CHECK(fcout, EINVAL);
4510 CHECK(!fcout->var_size, EINVAL);
4512 /* index = HMEFT, length = HMEFT, color_in = MEFT, color_out = MEF. */
4514 CHECK(!fidx->var_size, EINVAL);
4515 CHECK(!fcin->var_size, EINVAL);
4517 instr->type = INSTR_METER_MMM;
4518 if (idx[0] == 'h' && length[0] == 'h')
4519 instr->type = INSTR_METER_HHM;
4520 if (idx[0] == 'h' && length[0] != 'h')
4521 instr->type = INSTR_METER_HMM;
4522 if (idx[0] != 'h' && length[0] == 'h')
4523 instr->type = INSTR_METER_MHM;
4525 instr->meter.metarray_id = m->id;
4527 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4528 instr->meter.idx.n_bits = fidx->n_bits;
4529 instr->meter.idx.offset = fidx->offset / 8;
4531 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4532 instr->meter.length.n_bits = flength->n_bits;
4533 instr->meter.length.offset = flength->offset / 8;
4535 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
4536 instr->meter.color_in.n_bits = fcin->n_bits;
4537 instr->meter.color_in.offset = fcin->offset / 8;
4539 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4540 instr->meter.color_out.n_bits = fcout->n_bits;
4541 instr->meter.color_out.offset = fcout->offset / 8;
4546 /* index = HMEFT, length = HMEFT, color_in = I, color_out = MEF. */
4547 if (fidx && !fcin) {
4548 uint32_t color_in_val;
4550 CHECK(!fidx->var_size, EINVAL);
4552 color_in_val = strtoul(color_in, &color_in, 0);
4553 CHECK(!color_in[0], EINVAL);
4555 instr->type = INSTR_METER_MMI;
4556 if (idx[0] == 'h' && length[0] == 'h')
4557 instr->type = INSTR_METER_HHI;
4558 if (idx[0] == 'h' && length[0] != 'h')
4559 instr->type = INSTR_METER_HMI;
4560 if (idx[0] != 'h' && length[0] == 'h')
4561 instr->type = INSTR_METER_MHI;
4563 instr->meter.metarray_id = m->id;
4565 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4566 instr->meter.idx.n_bits = fidx->n_bits;
4567 instr->meter.idx.offset = fidx->offset / 8;
4569 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4570 instr->meter.length.n_bits = flength->n_bits;
4571 instr->meter.length.offset = flength->offset / 8;
4573 instr->meter.color_in_val = color_in_val;
4575 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4576 instr->meter.color_out.n_bits = fcout->n_bits;
4577 instr->meter.color_out.offset = fcout->offset / 8;
4582 /* index = I, length = HMEFT, color_in = MEFT, color_out = MEF. */
4583 if (!fidx && fcin) {
4586 idx_val = strtoul(idx, &idx, 0);
4587 CHECK(!idx[0], EINVAL);
4589 CHECK(!fcin->var_size, EINVAL);
4591 instr->type = INSTR_METER_IMM;
4592 if (length[0] == 'h')
4593 instr->type = INSTR_METER_IHM;
4595 instr->meter.metarray_id = m->id;
4597 instr->meter.idx_val = idx_val;
4599 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4600 instr->meter.length.n_bits = flength->n_bits;
4601 instr->meter.length.offset = flength->offset / 8;
4603 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
4604 instr->meter.color_in.n_bits = fcin->n_bits;
4605 instr->meter.color_in.offset = fcin->offset / 8;
4607 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4608 instr->meter.color_out.n_bits = fcout->n_bits;
4609 instr->meter.color_out.offset = fcout->offset / 8;
4614 /* index = I, length = HMEFT, color_in = I, color_out = MEF. */
4615 if (!fidx && !fcin) {
4616 uint32_t idx_val, color_in_val;
4618 idx_val = strtoul(idx, &idx, 0);
4619 CHECK(!idx[0], EINVAL);
4621 color_in_val = strtoul(color_in, &color_in, 0);
4622 CHECK(!color_in[0], EINVAL);
4624 instr->type = INSTR_METER_IMI;
4625 if (length[0] == 'h')
4626 instr->type = INSTR_METER_IHI;
4628 instr->meter.metarray_id = m->id;
4630 instr->meter.idx_val = idx_val;
4632 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4633 instr->meter.length.n_bits = flength->n_bits;
4634 instr->meter.length.offset = flength->offset / 8;
4636 instr->meter.color_in_val = color_in_val;
4638 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4639 instr->meter.color_out.n_bits = fcout->n_bits;
4640 instr->meter.color_out.offset = fcout->offset / 8;
4649 instr_metprefetch_h_exec(struct rte_swx_pipeline *p)
4651 struct thread *t = &p->threads[p->thread_id];
4652 struct instruction *ip = t->ip;
4655 __instr_metprefetch_h_exec(p, t, ip);
4662 instr_metprefetch_m_exec(struct rte_swx_pipeline *p)
4664 struct thread *t = &p->threads[p->thread_id];
4665 struct instruction *ip = t->ip;
4668 __instr_metprefetch_m_exec(p, t, ip);
4675 instr_metprefetch_i_exec(struct rte_swx_pipeline *p)
4677 struct thread *t = &p->threads[p->thread_id];
4678 struct instruction *ip = t->ip;
4681 __instr_metprefetch_i_exec(p, t, ip);
4688 instr_meter_hhm_exec(struct rte_swx_pipeline *p)
4690 struct thread *t = &p->threads[p->thread_id];
4691 struct instruction *ip = t->ip;
4694 __instr_meter_hhm_exec(p, t, ip);
4701 instr_meter_hhi_exec(struct rte_swx_pipeline *p)
4703 struct thread *t = &p->threads[p->thread_id];
4704 struct instruction *ip = t->ip;
4707 __instr_meter_hhi_exec(p, t, ip);
4714 instr_meter_hmm_exec(struct rte_swx_pipeline *p)
4716 struct thread *t = &p->threads[p->thread_id];
4717 struct instruction *ip = t->ip;
4720 __instr_meter_hmm_exec(p, t, ip);
4727 instr_meter_hmi_exec(struct rte_swx_pipeline *p)
4729 struct thread *t = &p->threads[p->thread_id];
4730 struct instruction *ip = t->ip;
4733 __instr_meter_hmi_exec(p, t, ip);
4740 instr_meter_mhm_exec(struct rte_swx_pipeline *p)
4742 struct thread *t = &p->threads[p->thread_id];
4743 struct instruction *ip = t->ip;
4746 __instr_meter_mhm_exec(p, t, ip);
4753 instr_meter_mhi_exec(struct rte_swx_pipeline *p)
4755 struct thread *t = &p->threads[p->thread_id];
4756 struct instruction *ip = t->ip;
4759 __instr_meter_mhi_exec(p, t, ip);
4766 instr_meter_mmm_exec(struct rte_swx_pipeline *p)
4768 struct thread *t = &p->threads[p->thread_id];
4769 struct instruction *ip = t->ip;
4772 __instr_meter_mmm_exec(p, t, ip);
4779 instr_meter_mmi_exec(struct rte_swx_pipeline *p)
4781 struct thread *t = &p->threads[p->thread_id];
4782 struct instruction *ip = t->ip;
4785 __instr_meter_mmi_exec(p, t, ip);
4792 instr_meter_ihm_exec(struct rte_swx_pipeline *p)
4794 struct thread *t = &p->threads[p->thread_id];
4795 struct instruction *ip = t->ip;
4798 __instr_meter_ihm_exec(p, t, ip);
4805 instr_meter_ihi_exec(struct rte_swx_pipeline *p)
4807 struct thread *t = &p->threads[p->thread_id];
4808 struct instruction *ip = t->ip;
4811 __instr_meter_ihi_exec(p, t, ip);
4818 instr_meter_imm_exec(struct rte_swx_pipeline *p)
4820 struct thread *t = &p->threads[p->thread_id];
4821 struct instruction *ip = t->ip;
4824 __instr_meter_imm_exec(p, t, ip);
4831 instr_meter_imi_exec(struct rte_swx_pipeline *p)
4833 struct thread *t = &p->threads[p->thread_id];
4834 struct instruction *ip = t->ip;
4837 __instr_meter_imi_exec(p, t, ip);
4847 instr_jmp_translate(struct rte_swx_pipeline *p __rte_unused,
4848 struct action *action __rte_unused,
4851 struct instruction *instr,
4852 struct instruction_data *data)
4854 CHECK(n_tokens == 2, EINVAL);
4856 strcpy(data->jmp_label, tokens[1]);
4858 instr->type = INSTR_JMP;
4859 instr->jmp.ip = NULL; /* Resolved later. */
4864 instr_jmp_valid_translate(struct rte_swx_pipeline *p,
4865 struct action *action __rte_unused,
4868 struct instruction *instr,
4869 struct instruction_data *data)
4873 CHECK(n_tokens == 3, EINVAL);
4875 strcpy(data->jmp_label, tokens[1]);
4877 h = header_parse(p, tokens[2]);
4880 instr->type = INSTR_JMP_VALID;
4881 instr->jmp.ip = NULL; /* Resolved later. */
4882 instr->jmp.header_id = h->id;
4887 instr_jmp_invalid_translate(struct rte_swx_pipeline *p,
4888 struct action *action __rte_unused,
4891 struct instruction *instr,
4892 struct instruction_data *data)
4896 CHECK(n_tokens == 3, EINVAL);
4898 strcpy(data->jmp_label, tokens[1]);
4900 h = header_parse(p, tokens[2]);
4903 instr->type = INSTR_JMP_INVALID;
4904 instr->jmp.ip = NULL; /* Resolved later. */
4905 instr->jmp.header_id = h->id;
4910 instr_jmp_hit_translate(struct rte_swx_pipeline *p __rte_unused,
4911 struct action *action,
4914 struct instruction *instr,
4915 struct instruction_data *data)
4917 CHECK(!action, EINVAL);
4918 CHECK(n_tokens == 2, EINVAL);
4920 strcpy(data->jmp_label, tokens[1]);
4922 instr->type = INSTR_JMP_HIT;
4923 instr->jmp.ip = NULL; /* Resolved later. */
4928 instr_jmp_miss_translate(struct rte_swx_pipeline *p __rte_unused,
4929 struct action *action,
4932 struct instruction *instr,
4933 struct instruction_data *data)
4935 CHECK(!action, EINVAL);
4936 CHECK(n_tokens == 2, EINVAL);
4938 strcpy(data->jmp_label, tokens[1]);
4940 instr->type = INSTR_JMP_MISS;
4941 instr->jmp.ip = NULL; /* Resolved later. */
4946 instr_jmp_action_hit_translate(struct rte_swx_pipeline *p,
4947 struct action *action,
4950 struct instruction *instr,
4951 struct instruction_data *data)
4955 CHECK(!action, EINVAL);
4956 CHECK(n_tokens == 3, EINVAL);
4958 strcpy(data->jmp_label, tokens[1]);
4960 a = action_find(p, tokens[2]);
4963 instr->type = INSTR_JMP_ACTION_HIT;
4964 instr->jmp.ip = NULL; /* Resolved later. */
4965 instr->jmp.action_id = a->id;
4970 instr_jmp_action_miss_translate(struct rte_swx_pipeline *p,
4971 struct action *action,
4974 struct instruction *instr,
4975 struct instruction_data *data)
4979 CHECK(!action, EINVAL);
4980 CHECK(n_tokens == 3, EINVAL);
4982 strcpy(data->jmp_label, tokens[1]);
4984 a = action_find(p, tokens[2]);
4987 instr->type = INSTR_JMP_ACTION_MISS;
4988 instr->jmp.ip = NULL; /* Resolved later. */
4989 instr->jmp.action_id = a->id;
4994 instr_jmp_eq_translate(struct rte_swx_pipeline *p,
4995 struct action *action,
4998 struct instruction *instr,
4999 struct instruction_data *data)
5001 char *a = tokens[2], *b = tokens[3];
5002 struct field *fa, *fb;
5004 uint32_t a_struct_id, b_struct_id;
5006 CHECK(n_tokens == 4, EINVAL);
5008 strcpy(data->jmp_label, tokens[1]);
5010 fa = struct_field_parse(p, action, a, &a_struct_id);
5012 CHECK(!fa->var_size, EINVAL);
5014 /* JMP_EQ, JMP_EQ_MH, JMP_EQ_HM, JMP_EQ_HH. */
5015 fb = struct_field_parse(p, action, b, &b_struct_id);
5017 CHECK(!fb->var_size, EINVAL);
5019 instr->type = INSTR_JMP_EQ;
5020 if (a[0] != 'h' && b[0] == 'h')
5021 instr->type = INSTR_JMP_EQ_MH;
5022 if (a[0] == 'h' && b[0] != 'h')
5023 instr->type = INSTR_JMP_EQ_HM;
5024 if (a[0] == 'h' && b[0] == 'h')
5025 instr->type = INSTR_JMP_EQ_HH;
5026 instr->jmp.ip = NULL; /* Resolved later. */
5028 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5029 instr->jmp.a.n_bits = fa->n_bits;
5030 instr->jmp.a.offset = fa->offset / 8;
5031 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5032 instr->jmp.b.n_bits = fb->n_bits;
5033 instr->jmp.b.offset = fb->offset / 8;
5038 b_val = strtoull(b, &b, 0);
5039 CHECK(!b[0], EINVAL);
5042 b_val = hton64(b_val) >> (64 - fa->n_bits);
5044 instr->type = INSTR_JMP_EQ_I;
5045 instr->jmp.ip = NULL; /* Resolved later. */
5046 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5047 instr->jmp.a.n_bits = fa->n_bits;
5048 instr->jmp.a.offset = fa->offset / 8;
5049 instr->jmp.b_val = b_val;
5054 instr_jmp_neq_translate(struct rte_swx_pipeline *p,
5055 struct action *action,
5058 struct instruction *instr,
5059 struct instruction_data *data)
5061 char *a = tokens[2], *b = tokens[3];
5062 struct field *fa, *fb;
5064 uint32_t a_struct_id, b_struct_id;
5066 CHECK(n_tokens == 4, EINVAL);
5068 strcpy(data->jmp_label, tokens[1]);
5070 fa = struct_field_parse(p, action, a, &a_struct_id);
5072 CHECK(!fa->var_size, EINVAL);
5074 /* JMP_NEQ, JMP_NEQ_MH, JMP_NEQ_HM, JMP_NEQ_HH. */
5075 fb = struct_field_parse(p, action, b, &b_struct_id);
5077 CHECK(!fb->var_size, EINVAL);
5079 instr->type = INSTR_JMP_NEQ;
5080 if (a[0] != 'h' && b[0] == 'h')
5081 instr->type = INSTR_JMP_NEQ_MH;
5082 if (a[0] == 'h' && b[0] != 'h')
5083 instr->type = INSTR_JMP_NEQ_HM;
5084 if (a[0] == 'h' && b[0] == 'h')
5085 instr->type = INSTR_JMP_NEQ_HH;
5086 instr->jmp.ip = NULL; /* Resolved later. */
5088 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5089 instr->jmp.a.n_bits = fa->n_bits;
5090 instr->jmp.a.offset = fa->offset / 8;
5091 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5092 instr->jmp.b.n_bits = fb->n_bits;
5093 instr->jmp.b.offset = fb->offset / 8;
5098 b_val = strtoull(b, &b, 0);
5099 CHECK(!b[0], EINVAL);
5102 b_val = hton64(b_val) >> (64 - fa->n_bits);
5104 instr->type = INSTR_JMP_NEQ_I;
5105 instr->jmp.ip = NULL; /* Resolved later. */
5106 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5107 instr->jmp.a.n_bits = fa->n_bits;
5108 instr->jmp.a.offset = fa->offset / 8;
5109 instr->jmp.b_val = b_val;
5114 instr_jmp_lt_translate(struct rte_swx_pipeline *p,
5115 struct action *action,
5118 struct instruction *instr,
5119 struct instruction_data *data)
5121 char *a = tokens[2], *b = tokens[3];
5122 struct field *fa, *fb;
5124 uint32_t a_struct_id, b_struct_id;
5126 CHECK(n_tokens == 4, EINVAL);
5128 strcpy(data->jmp_label, tokens[1]);
5130 fa = struct_field_parse(p, action, a, &a_struct_id);
5132 CHECK(!fa->var_size, EINVAL);
5134 /* JMP_LT, JMP_LT_MH, JMP_LT_HM, JMP_LT_HH. */
5135 fb = struct_field_parse(p, action, b, &b_struct_id);
5137 CHECK(!fb->var_size, EINVAL);
5139 instr->type = INSTR_JMP_LT;
5140 if (a[0] == 'h' && b[0] != 'h')
5141 instr->type = INSTR_JMP_LT_HM;
5142 if (a[0] != 'h' && b[0] == 'h')
5143 instr->type = INSTR_JMP_LT_MH;
5144 if (a[0] == 'h' && b[0] == 'h')
5145 instr->type = INSTR_JMP_LT_HH;
5146 instr->jmp.ip = NULL; /* Resolved later. */
5148 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5149 instr->jmp.a.n_bits = fa->n_bits;
5150 instr->jmp.a.offset = fa->offset / 8;
5151 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5152 instr->jmp.b.n_bits = fb->n_bits;
5153 instr->jmp.b.offset = fb->offset / 8;
5157 /* JMP_LT_MI, JMP_LT_HI. */
5158 b_val = strtoull(b, &b, 0);
5159 CHECK(!b[0], EINVAL);
5161 instr->type = INSTR_JMP_LT_MI;
5163 instr->type = INSTR_JMP_LT_HI;
5164 instr->jmp.ip = NULL; /* Resolved later. */
5166 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5167 instr->jmp.a.n_bits = fa->n_bits;
5168 instr->jmp.a.offset = fa->offset / 8;
5169 instr->jmp.b_val = b_val;
5174 instr_jmp_gt_translate(struct rte_swx_pipeline *p,
5175 struct action *action,
5178 struct instruction *instr,
5179 struct instruction_data *data)
5181 char *a = tokens[2], *b = tokens[3];
5182 struct field *fa, *fb;
5184 uint32_t a_struct_id, b_struct_id;
5186 CHECK(n_tokens == 4, EINVAL);
5188 strcpy(data->jmp_label, tokens[1]);
5190 fa = struct_field_parse(p, action, a, &a_struct_id);
5192 CHECK(!fa->var_size, EINVAL);
5194 /* JMP_GT, JMP_GT_MH, JMP_GT_HM, JMP_GT_HH. */
5195 fb = struct_field_parse(p, action, b, &b_struct_id);
5197 CHECK(!fb->var_size, EINVAL);
5199 instr->type = INSTR_JMP_GT;
5200 if (a[0] == 'h' && b[0] != 'h')
5201 instr->type = INSTR_JMP_GT_HM;
5202 if (a[0] != 'h' && b[0] == 'h')
5203 instr->type = INSTR_JMP_GT_MH;
5204 if (a[0] == 'h' && b[0] == 'h')
5205 instr->type = INSTR_JMP_GT_HH;
5206 instr->jmp.ip = NULL; /* Resolved later. */
5208 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5209 instr->jmp.a.n_bits = fa->n_bits;
5210 instr->jmp.a.offset = fa->offset / 8;
5211 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5212 instr->jmp.b.n_bits = fb->n_bits;
5213 instr->jmp.b.offset = fb->offset / 8;
5217 /* JMP_GT_MI, JMP_GT_HI. */
5218 b_val = strtoull(b, &b, 0);
5219 CHECK(!b[0], EINVAL);
5221 instr->type = INSTR_JMP_GT_MI;
5223 instr->type = INSTR_JMP_GT_HI;
5224 instr->jmp.ip = NULL; /* Resolved later. */
5226 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5227 instr->jmp.a.n_bits = fa->n_bits;
5228 instr->jmp.a.offset = fa->offset / 8;
5229 instr->jmp.b_val = b_val;
5234 instr_jmp_exec(struct rte_swx_pipeline *p)
5236 struct thread *t = &p->threads[p->thread_id];
5237 struct instruction *ip = t->ip;
5239 TRACE("[Thread %2u] jmp\n", p->thread_id);
5241 thread_ip_set(t, ip->jmp.ip);
5245 instr_jmp_valid_exec(struct rte_swx_pipeline *p)
5247 struct thread *t = &p->threads[p->thread_id];
5248 struct instruction *ip = t->ip;
5249 uint32_t header_id = ip->jmp.header_id;
5251 TRACE("[Thread %2u] jmpv\n", p->thread_id);
5253 t->ip = HEADER_VALID(t, header_id) ? ip->jmp.ip : (t->ip + 1);
5257 instr_jmp_invalid_exec(struct rte_swx_pipeline *p)
5259 struct thread *t = &p->threads[p->thread_id];
5260 struct instruction *ip = t->ip;
5261 uint32_t header_id = ip->jmp.header_id;
5263 TRACE("[Thread %2u] jmpnv\n", p->thread_id);
5265 t->ip = HEADER_VALID(t, header_id) ? (t->ip + 1) : ip->jmp.ip;
5269 instr_jmp_hit_exec(struct rte_swx_pipeline *p)
5271 struct thread *t = &p->threads[p->thread_id];
5272 struct instruction *ip = t->ip;
5273 struct instruction *ip_next[] = {t->ip + 1, ip->jmp.ip};
5275 TRACE("[Thread %2u] jmph\n", p->thread_id);
5277 t->ip = ip_next[t->hit];
5281 instr_jmp_miss_exec(struct rte_swx_pipeline *p)
5283 struct thread *t = &p->threads[p->thread_id];
5284 struct instruction *ip = t->ip;
5285 struct instruction *ip_next[] = {ip->jmp.ip, t->ip + 1};
5287 TRACE("[Thread %2u] jmpnh\n", p->thread_id);
5289 t->ip = ip_next[t->hit];
5293 instr_jmp_action_hit_exec(struct rte_swx_pipeline *p)
5295 struct thread *t = &p->threads[p->thread_id];
5296 struct instruction *ip = t->ip;
5298 TRACE("[Thread %2u] jmpa\n", p->thread_id);
5300 t->ip = (ip->jmp.action_id == t->action_id) ? ip->jmp.ip : (t->ip + 1);
5304 instr_jmp_action_miss_exec(struct rte_swx_pipeline *p)
5306 struct thread *t = &p->threads[p->thread_id];
5307 struct instruction *ip = t->ip;
5309 TRACE("[Thread %2u] jmpna\n", p->thread_id);
5311 t->ip = (ip->jmp.action_id == t->action_id) ? (t->ip + 1) : ip->jmp.ip;
5315 instr_jmp_eq_exec(struct rte_swx_pipeline *p)
5317 struct thread *t = &p->threads[p->thread_id];
5318 struct instruction *ip = t->ip;
5320 TRACE("[Thread %2u] jmpeq\n", p->thread_id);
5326 instr_jmp_eq_mh_exec(struct rte_swx_pipeline *p)
5328 struct thread *t = &p->threads[p->thread_id];
5329 struct instruction *ip = t->ip;
5331 TRACE("[Thread %2u] jmpeq (mh)\n", p->thread_id);
5333 JMP_CMP_MH(t, ip, ==);
5337 instr_jmp_eq_hm_exec(struct rte_swx_pipeline *p)
5339 struct thread *t = &p->threads[p->thread_id];
5340 struct instruction *ip = t->ip;
5342 TRACE("[Thread %2u] jmpeq (hm)\n", p->thread_id);
5344 JMP_CMP_HM(t, ip, ==);
5348 instr_jmp_eq_hh_exec(struct rte_swx_pipeline *p)
5350 struct thread *t = &p->threads[p->thread_id];
5351 struct instruction *ip = t->ip;
5353 TRACE("[Thread %2u] jmpeq (hh)\n", p->thread_id);
5355 JMP_CMP_HH_FAST(t, ip, ==);
5359 instr_jmp_eq_i_exec(struct rte_swx_pipeline *p)
5361 struct thread *t = &p->threads[p->thread_id];
5362 struct instruction *ip = t->ip;
5364 TRACE("[Thread %2u] jmpeq (i)\n", p->thread_id);
5366 JMP_CMP_I(t, ip, ==);
5370 instr_jmp_neq_exec(struct rte_swx_pipeline *p)
5372 struct thread *t = &p->threads[p->thread_id];
5373 struct instruction *ip = t->ip;
5375 TRACE("[Thread %2u] jmpneq\n", p->thread_id);
5381 instr_jmp_neq_mh_exec(struct rte_swx_pipeline *p)
5383 struct thread *t = &p->threads[p->thread_id];
5384 struct instruction *ip = t->ip;
5386 TRACE("[Thread %2u] jmpneq (mh)\n", p->thread_id);
5388 JMP_CMP_MH(t, ip, !=);
5392 instr_jmp_neq_hm_exec(struct rte_swx_pipeline *p)
5394 struct thread *t = &p->threads[p->thread_id];
5395 struct instruction *ip = t->ip;
5397 TRACE("[Thread %2u] jmpneq (hm)\n", p->thread_id);
5399 JMP_CMP_HM(t, ip, !=);
5403 instr_jmp_neq_hh_exec(struct rte_swx_pipeline *p)
5405 struct thread *t = &p->threads[p->thread_id];
5406 struct instruction *ip = t->ip;
5408 TRACE("[Thread %2u] jmpneq (hh)\n", p->thread_id);
5410 JMP_CMP_HH_FAST(t, ip, !=);
5414 instr_jmp_neq_i_exec(struct rte_swx_pipeline *p)
5416 struct thread *t = &p->threads[p->thread_id];
5417 struct instruction *ip = t->ip;
5419 TRACE("[Thread %2u] jmpneq (i)\n", p->thread_id);
5421 JMP_CMP_I(t, ip, !=);
5425 instr_jmp_lt_exec(struct rte_swx_pipeline *p)
5427 struct thread *t = &p->threads[p->thread_id];
5428 struct instruction *ip = t->ip;
5430 TRACE("[Thread %2u] jmplt\n", p->thread_id);
5436 instr_jmp_lt_mh_exec(struct rte_swx_pipeline *p)
5438 struct thread *t = &p->threads[p->thread_id];
5439 struct instruction *ip = t->ip;
5441 TRACE("[Thread %2u] jmplt (mh)\n", p->thread_id);
5443 JMP_CMP_MH(t, ip, <);
5447 instr_jmp_lt_hm_exec(struct rte_swx_pipeline *p)
5449 struct thread *t = &p->threads[p->thread_id];
5450 struct instruction *ip = t->ip;
5452 TRACE("[Thread %2u] jmplt (hm)\n", p->thread_id);
5454 JMP_CMP_HM(t, ip, <);
5458 instr_jmp_lt_hh_exec(struct rte_swx_pipeline *p)
5460 struct thread *t = &p->threads[p->thread_id];
5461 struct instruction *ip = t->ip;
5463 TRACE("[Thread %2u] jmplt (hh)\n", p->thread_id);
5465 JMP_CMP_HH(t, ip, <);
5469 instr_jmp_lt_mi_exec(struct rte_swx_pipeline *p)
5471 struct thread *t = &p->threads[p->thread_id];
5472 struct instruction *ip = t->ip;
5474 TRACE("[Thread %2u] jmplt (mi)\n", p->thread_id);
5476 JMP_CMP_MI(t, ip, <);
5480 instr_jmp_lt_hi_exec(struct rte_swx_pipeline *p)
5482 struct thread *t = &p->threads[p->thread_id];
5483 struct instruction *ip = t->ip;
5485 TRACE("[Thread %2u] jmplt (hi)\n", p->thread_id);
5487 JMP_CMP_HI(t, ip, <);
5491 instr_jmp_gt_exec(struct rte_swx_pipeline *p)
5493 struct thread *t = &p->threads[p->thread_id];
5494 struct instruction *ip = t->ip;
5496 TRACE("[Thread %2u] jmpgt\n", p->thread_id);
5502 instr_jmp_gt_mh_exec(struct rte_swx_pipeline *p)
5504 struct thread *t = &p->threads[p->thread_id];
5505 struct instruction *ip = t->ip;
5507 TRACE("[Thread %2u] jmpgt (mh)\n", p->thread_id);
5509 JMP_CMP_MH(t, ip, >);
5513 instr_jmp_gt_hm_exec(struct rte_swx_pipeline *p)
5515 struct thread *t = &p->threads[p->thread_id];
5516 struct instruction *ip = t->ip;
5518 TRACE("[Thread %2u] jmpgt (hm)\n", p->thread_id);
5520 JMP_CMP_HM(t, ip, >);
5524 instr_jmp_gt_hh_exec(struct rte_swx_pipeline *p)
5526 struct thread *t = &p->threads[p->thread_id];
5527 struct instruction *ip = t->ip;
5529 TRACE("[Thread %2u] jmpgt (hh)\n", p->thread_id);
5531 JMP_CMP_HH(t, ip, >);
5535 instr_jmp_gt_mi_exec(struct rte_swx_pipeline *p)
5537 struct thread *t = &p->threads[p->thread_id];
5538 struct instruction *ip = t->ip;
5540 TRACE("[Thread %2u] jmpgt (mi)\n", p->thread_id);
5542 JMP_CMP_MI(t, ip, >);
5546 instr_jmp_gt_hi_exec(struct rte_swx_pipeline *p)
5548 struct thread *t = &p->threads[p->thread_id];
5549 struct instruction *ip = t->ip;
5551 TRACE("[Thread %2u] jmpgt (hi)\n", p->thread_id);
5553 JMP_CMP_HI(t, ip, >);
5560 instr_return_translate(struct rte_swx_pipeline *p __rte_unused,
5561 struct action *action,
5562 char **tokens __rte_unused,
5564 struct instruction *instr,
5565 struct instruction_data *data __rte_unused)
5567 CHECK(action, EINVAL);
5568 CHECK(n_tokens == 1, EINVAL);
5570 instr->type = INSTR_RETURN;
5575 instr_return_exec(struct rte_swx_pipeline *p)
5577 struct thread *t = &p->threads[p->thread_id];
5579 TRACE("[Thread %2u] return\n", p->thread_id);
5585 instr_translate(struct rte_swx_pipeline *p,
5586 struct action *action,
5588 struct instruction *instr,
5589 struct instruction_data *data)
5591 char *tokens[RTE_SWX_INSTRUCTION_TOKENS_MAX];
5592 int n_tokens = 0, tpos = 0;
5594 /* Parse the instruction string into tokens. */
5598 token = strtok_r(string, " \t\v", &string);
5602 CHECK(n_tokens < RTE_SWX_INSTRUCTION_TOKENS_MAX, EINVAL);
5603 CHECK_NAME(token, EINVAL);
5605 tokens[n_tokens] = token;
5609 CHECK(n_tokens, EINVAL);
5611 /* Handle the optional instruction label. */
5612 if ((n_tokens >= 2) && !strcmp(tokens[1], ":")) {
5613 strcpy(data->label, tokens[0]);
5616 CHECK(n_tokens - tpos, EINVAL);
5619 /* Identify the instruction type. */
5620 if (!strcmp(tokens[tpos], "rx"))
5621 return instr_rx_translate(p,
5628 if (!strcmp(tokens[tpos], "tx"))
5629 return instr_tx_translate(p,
5636 if (!strcmp(tokens[tpos], "drop"))
5637 return instr_drop_translate(p,
5644 if (!strcmp(tokens[tpos], "extract"))
5645 return instr_hdr_extract_translate(p,
5652 if (!strcmp(tokens[tpos], "lookahead"))
5653 return instr_hdr_lookahead_translate(p,
5660 if (!strcmp(tokens[tpos], "emit"))
5661 return instr_hdr_emit_translate(p,
5668 if (!strcmp(tokens[tpos], "validate"))
5669 return instr_hdr_validate_translate(p,
5676 if (!strcmp(tokens[tpos], "invalidate"))
5677 return instr_hdr_invalidate_translate(p,
5684 if (!strcmp(tokens[tpos], "mov"))
5685 return instr_mov_translate(p,
5692 if (!strcmp(tokens[tpos], "add"))
5693 return instr_alu_add_translate(p,
5700 if (!strcmp(tokens[tpos], "sub"))
5701 return instr_alu_sub_translate(p,
5708 if (!strcmp(tokens[tpos], "ckadd"))
5709 return instr_alu_ckadd_translate(p,
5716 if (!strcmp(tokens[tpos], "cksub"))
5717 return instr_alu_cksub_translate(p,
5724 if (!strcmp(tokens[tpos], "and"))
5725 return instr_alu_and_translate(p,
5732 if (!strcmp(tokens[tpos], "or"))
5733 return instr_alu_or_translate(p,
5740 if (!strcmp(tokens[tpos], "xor"))
5741 return instr_alu_xor_translate(p,
5748 if (!strcmp(tokens[tpos], "shl"))
5749 return instr_alu_shl_translate(p,
5756 if (!strcmp(tokens[tpos], "shr"))
5757 return instr_alu_shr_translate(p,
5764 if (!strcmp(tokens[tpos], "regprefetch"))
5765 return instr_regprefetch_translate(p,
5772 if (!strcmp(tokens[tpos], "regrd"))
5773 return instr_regrd_translate(p,
5780 if (!strcmp(tokens[tpos], "regwr"))
5781 return instr_regwr_translate(p,
5788 if (!strcmp(tokens[tpos], "regadd"))
5789 return instr_regadd_translate(p,
5796 if (!strcmp(tokens[tpos], "metprefetch"))
5797 return instr_metprefetch_translate(p,
5804 if (!strcmp(tokens[tpos], "meter"))
5805 return instr_meter_translate(p,
5812 if (!strcmp(tokens[tpos], "table"))
5813 return instr_table_translate(p,
5820 if (!strcmp(tokens[tpos], "learn"))
5821 return instr_learn_translate(p,
5828 if (!strcmp(tokens[tpos], "forget"))
5829 return instr_forget_translate(p,
5836 if (!strcmp(tokens[tpos], "extern"))
5837 return instr_extern_translate(p,
5844 if (!strcmp(tokens[tpos], "jmp"))
5845 return instr_jmp_translate(p,
5852 if (!strcmp(tokens[tpos], "jmpv"))
5853 return instr_jmp_valid_translate(p,
5860 if (!strcmp(tokens[tpos], "jmpnv"))
5861 return instr_jmp_invalid_translate(p,
5868 if (!strcmp(tokens[tpos], "jmph"))
5869 return instr_jmp_hit_translate(p,
5876 if (!strcmp(tokens[tpos], "jmpnh"))
5877 return instr_jmp_miss_translate(p,
5884 if (!strcmp(tokens[tpos], "jmpa"))
5885 return instr_jmp_action_hit_translate(p,
5892 if (!strcmp(tokens[tpos], "jmpna"))
5893 return instr_jmp_action_miss_translate(p,
5900 if (!strcmp(tokens[tpos], "jmpeq"))
5901 return instr_jmp_eq_translate(p,
5908 if (!strcmp(tokens[tpos], "jmpneq"))
5909 return instr_jmp_neq_translate(p,
5916 if (!strcmp(tokens[tpos], "jmplt"))
5917 return instr_jmp_lt_translate(p,
5924 if (!strcmp(tokens[tpos], "jmpgt"))
5925 return instr_jmp_gt_translate(p,
5932 if (!strcmp(tokens[tpos], "return"))
5933 return instr_return_translate(p,
5943 static struct instruction_data *
5944 label_find(struct instruction_data *data, uint32_t n, const char *label)
5948 for (i = 0; i < n; i++)
5949 if (!strcmp(label, data[i].label))
5956 label_is_used(struct instruction_data *data, uint32_t n, const char *label)
5958 uint32_t count = 0, i;
5963 for (i = 0; i < n; i++)
5964 if (!strcmp(label, data[i].jmp_label))
5971 instr_label_check(struct instruction_data *instruction_data,
5972 uint32_t n_instructions)
5976 /* Check that all instruction labels are unique. */
5977 for (i = 0; i < n_instructions; i++) {
5978 struct instruction_data *data = &instruction_data[i];
5979 char *label = data->label;
5985 for (j = i + 1; j < n_instructions; j++)
5986 CHECK(strcmp(label, instruction_data[j].label), EINVAL);
5989 /* Get users for each instruction label. */
5990 for (i = 0; i < n_instructions; i++) {
5991 struct instruction_data *data = &instruction_data[i];
5992 char *label = data->label;
5994 data->n_users = label_is_used(instruction_data,
6003 instr_jmp_resolve(struct instruction *instructions,
6004 struct instruction_data *instruction_data,
6005 uint32_t n_instructions)
6009 for (i = 0; i < n_instructions; i++) {
6010 struct instruction *instr = &instructions[i];
6011 struct instruction_data *data = &instruction_data[i];
6012 struct instruction_data *found;
6014 if (!instruction_is_jmp(instr))
6017 found = label_find(instruction_data,
6020 CHECK(found, EINVAL);
6022 instr->jmp.ip = &instructions[found - instruction_data];
6029 instr_verify(struct rte_swx_pipeline *p __rte_unused,
6031 struct instruction *instr,
6032 struct instruction_data *data __rte_unused,
6033 uint32_t n_instructions)
6036 enum instruction_type type;
6039 /* Check that the first instruction is rx. */
6040 CHECK(instr[0].type == INSTR_RX, EINVAL);
6042 /* Check that there is at least one tx instruction. */
6043 for (i = 0; i < n_instructions; i++) {
6044 type = instr[i].type;
6046 if (instruction_is_tx(type))
6049 CHECK(i < n_instructions, EINVAL);
6051 /* Check that the last instruction is either tx or unconditional
6054 type = instr[n_instructions - 1].type;
6055 CHECK(instruction_is_tx(type) || (type == INSTR_JMP), EINVAL);
6059 enum instruction_type type;
6062 /* Check that there is at least one return or tx instruction. */
6063 for (i = 0; i < n_instructions; i++) {
6064 type = instr[i].type;
6066 if ((type == INSTR_RETURN) || instruction_is_tx(type))
6069 CHECK(i < n_instructions, EINVAL);
6076 instr_compact(struct instruction *instructions,
6077 struct instruction_data *instruction_data,
6078 uint32_t n_instructions)
6080 uint32_t i, pos = 0;
6082 /* Eliminate the invalid instructions that have been optimized out. */
6083 for (i = 0; i < n_instructions; i++) {
6084 struct instruction *instr = &instructions[i];
6085 struct instruction_data *data = &instruction_data[i];
6091 memcpy(&instructions[pos], instr, sizeof(*instr));
6092 memcpy(&instruction_data[pos], data, sizeof(*data));
6102 instr_pattern_extract_many_search(struct instruction *instr,
6103 struct instruction_data *data,
6105 uint32_t *n_pattern_instr)
6109 for (i = 0; i < n_instr; i++) {
6110 if (data[i].invalid)
6113 if (instr[i].type != INSTR_HDR_EXTRACT)
6116 if (i == RTE_DIM(instr->io.hdr.header_id))
6119 if (i && data[i].n_users)
6126 *n_pattern_instr = i;
6131 instr_pattern_extract_many_replace(struct instruction *instr,
6132 struct instruction_data *data,
6137 for (i = 1; i < n_instr; i++) {
6139 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
6140 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
6141 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
6143 data[i].invalid = 1;
6148 instr_pattern_extract_many_optimize(struct instruction *instructions,
6149 struct instruction_data *instruction_data,
6150 uint32_t n_instructions)
6154 for (i = 0; i < n_instructions; ) {
6155 struct instruction *instr = &instructions[i];
6156 struct instruction_data *data = &instruction_data[i];
6157 uint32_t n_instr = 0;
6161 detected = instr_pattern_extract_many_search(instr,
6166 instr_pattern_extract_many_replace(instr,
6173 /* No pattern starting at the current instruction. */
6177 /* Eliminate the invalid instructions that have been optimized out. */
6178 n_instructions = instr_compact(instructions,
6182 return n_instructions;
6186 instr_pattern_emit_many_tx_search(struct instruction *instr,
6187 struct instruction_data *data,
6189 uint32_t *n_pattern_instr)
6193 for (i = 0; i < n_instr; i++) {
6194 if (data[i].invalid)
6197 if (instr[i].type != INSTR_HDR_EMIT)
6200 if (i == RTE_DIM(instr->io.hdr.header_id))
6203 if (i && data[i].n_users)
6210 if (!instruction_is_tx(instr[i].type))
6213 if (data[i].n_users)
6218 *n_pattern_instr = i;
6223 instr_pattern_emit_many_tx_replace(struct instruction *instr,
6224 struct instruction_data *data,
6229 /* Any emit instruction in addition to the first one. */
6230 for (i = 1; i < n_instr - 1; i++) {
6232 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
6233 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
6234 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
6236 data[i].invalid = 1;
6239 /* The TX instruction is the last one in the pattern. */
6241 instr[0].io.io.offset = instr[i].io.io.offset;
6242 instr[0].io.io.n_bits = instr[i].io.io.n_bits;
6243 data[i].invalid = 1;
6247 instr_pattern_emit_many_tx_optimize(struct instruction *instructions,
6248 struct instruction_data *instruction_data,
6249 uint32_t n_instructions)
6253 for (i = 0; i < n_instructions; ) {
6254 struct instruction *instr = &instructions[i];
6255 struct instruction_data *data = &instruction_data[i];
6256 uint32_t n_instr = 0;
6259 /* Emit many + TX. */
6260 detected = instr_pattern_emit_many_tx_search(instr,
6265 instr_pattern_emit_many_tx_replace(instr,
6272 /* No pattern starting at the current instruction. */
6276 /* Eliminate the invalid instructions that have been optimized out. */
6277 n_instructions = instr_compact(instructions,
6281 return n_instructions;
6285 action_arg_src_mov_count(struct action *a,
6287 struct instruction *instructions,
6288 struct instruction_data *instruction_data,
6289 uint32_t n_instructions);
6292 instr_pattern_mov_all_validate_search(struct rte_swx_pipeline *p,
6294 struct instruction *instr,
6295 struct instruction_data *data,
6297 struct instruction *instructions,
6298 struct instruction_data *instruction_data,
6299 uint32_t n_instructions,
6300 uint32_t *n_pattern_instr)
6303 uint32_t src_field_id, i, j;
6305 /* Prerequisites. */
6309 /* First instruction: MOV_HM. */
6310 if (data[0].invalid || (instr[0].type != INSTR_MOV_HM))
6313 h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
6314 if (!h || h->st->var_size)
6317 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
6318 if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
6321 if (src_field_id == a->st->n_fields)
6324 if (instr[0].mov.dst.offset ||
6325 (instr[0].mov.dst.n_bits != h->st->fields[0].n_bits) ||
6326 instr[0].mov.src.struct_id ||
6327 (instr[0].mov.src.n_bits != a->st->fields[src_field_id].n_bits) ||
6328 (instr[0].mov.dst.n_bits != instr[0].mov.src.n_bits))
6331 if ((n_instr < h->st->n_fields + 1) ||
6332 (a->st->n_fields < src_field_id + h->st->n_fields + 1))
6335 /* Subsequent instructions: MOV_HM. */
6336 for (i = 1; i < h->st->n_fields; i++)
6337 if (data[i].invalid ||
6339 (instr[i].type != INSTR_MOV_HM) ||
6340 (instr[i].mov.dst.struct_id != h->struct_id) ||
6341 (instr[i].mov.dst.offset != h->st->fields[i].offset / 8) ||
6342 (instr[i].mov.dst.n_bits != h->st->fields[i].n_bits) ||
6343 instr[i].mov.src.struct_id ||
6344 (instr[i].mov.src.offset != a->st->fields[src_field_id + i].offset / 8) ||
6345 (instr[i].mov.src.n_bits != a->st->fields[src_field_id + i].n_bits) ||
6346 (instr[i].mov.dst.n_bits != instr[i].mov.src.n_bits))
6349 /* Last instruction: HDR_VALIDATE. */
6350 if ((instr[i].type != INSTR_HDR_VALIDATE) ||
6351 (instr[i].valid.header_id != h->id))
6354 /* Check that none of the action args that are used as source for this
6355 * DMA transfer are not used as source in any other mov instruction.
6357 for (j = src_field_id; j < src_field_id + h->st->n_fields; j++) {
6360 n_users = action_arg_src_mov_count(a,
6369 *n_pattern_instr = 1 + i;
6374 instr_pattern_mov_all_validate_replace(struct rte_swx_pipeline *p,
6376 struct instruction *instr,
6377 struct instruction_data *data,
6381 uint32_t src_field_id, src_offset, i;
6383 /* Read from the instructions before they are modified. */
6384 h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
6388 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
6389 if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
6392 if (src_field_id == a->st->n_fields)
6395 src_offset = instr[0].mov.src.offset;
6397 /* Modify the instructions. */
6398 instr[0].type = INSTR_DMA_HT;
6399 instr[0].dma.dst.header_id[0] = h->id;
6400 instr[0].dma.dst.struct_id[0] = h->struct_id;
6401 instr[0].dma.src.offset[0] = (uint8_t)src_offset;
6402 instr[0].dma.n_bytes[0] = h->st->n_bits / 8;
6404 for (i = 1; i < n_instr; i++)
6405 data[i].invalid = 1;
6407 /* Update the endianness of the action arguments to header endianness. */
6408 for (i = 0; i < h->st->n_fields; i++)
6409 a->args_endianness[src_field_id + i] = 1;
6413 instr_pattern_mov_all_validate_optimize(struct rte_swx_pipeline *p,
6415 struct instruction *instructions,
6416 struct instruction_data *instruction_data,
6417 uint32_t n_instructions)
6422 return n_instructions;
6424 for (i = 0; i < n_instructions; ) {
6425 struct instruction *instr = &instructions[i];
6426 struct instruction_data *data = &instruction_data[i];
6427 uint32_t n_instr = 0;
6430 /* Mov all + validate. */
6431 detected = instr_pattern_mov_all_validate_search(p,
6441 instr_pattern_mov_all_validate_replace(p, a, instr, data, n_instr);
6446 /* No pattern starting at the current instruction. */
6450 /* Eliminate the invalid instructions that have been optimized out. */
6451 n_instructions = instr_compact(instructions,
6455 return n_instructions;
6459 instr_pattern_dma_many_search(struct instruction *instr,
6460 struct instruction_data *data,
6462 uint32_t *n_pattern_instr)
6466 for (i = 0; i < n_instr; i++) {
6467 if (data[i].invalid)
6470 if (instr[i].type != INSTR_DMA_HT)
6473 if (i == RTE_DIM(instr->dma.dst.header_id))
6476 if (i && data[i].n_users)
6483 *n_pattern_instr = i;
6488 instr_pattern_dma_many_replace(struct instruction *instr,
6489 struct instruction_data *data,
6494 for (i = 1; i < n_instr; i++) {
6496 instr[0].dma.dst.header_id[i] = instr[i].dma.dst.header_id[0];
6497 instr[0].dma.dst.struct_id[i] = instr[i].dma.dst.struct_id[0];
6498 instr[0].dma.src.offset[i] = instr[i].dma.src.offset[0];
6499 instr[0].dma.n_bytes[i] = instr[i].dma.n_bytes[0];
6501 data[i].invalid = 1;
6506 instr_pattern_dma_many_optimize(struct instruction *instructions,
6507 struct instruction_data *instruction_data,
6508 uint32_t n_instructions)
6512 for (i = 0; i < n_instructions; ) {
6513 struct instruction *instr = &instructions[i];
6514 struct instruction_data *data = &instruction_data[i];
6515 uint32_t n_instr = 0;
6519 detected = instr_pattern_dma_many_search(instr,
6524 instr_pattern_dma_many_replace(instr, data, n_instr);
6529 /* No pattern starting at the current instruction. */
6533 /* Eliminate the invalid instructions that have been optimized out. */
6534 n_instructions = instr_compact(instructions,
6538 return n_instructions;
6542 instr_optimize(struct rte_swx_pipeline *p,
6544 struct instruction *instructions,
6545 struct instruction_data *instruction_data,
6546 uint32_t n_instructions)
6549 n_instructions = instr_pattern_extract_many_optimize(instructions,
6553 /* Emit many + TX. */
6554 n_instructions = instr_pattern_emit_many_tx_optimize(instructions,
6558 /* Mov all + validate. */
6559 n_instructions = instr_pattern_mov_all_validate_optimize(p,
6566 n_instructions = instr_pattern_dma_many_optimize(instructions,
6570 return n_instructions;
6574 instruction_config(struct rte_swx_pipeline *p,
6576 const char **instructions,
6577 uint32_t n_instructions)
6579 struct instruction *instr = NULL;
6580 struct instruction_data *data = NULL;
6584 CHECK(n_instructions, EINVAL);
6585 CHECK(instructions, EINVAL);
6586 for (i = 0; i < n_instructions; i++)
6587 CHECK_INSTRUCTION(instructions[i], EINVAL);
6589 /* Memory allocation. */
6590 instr = calloc(n_instructions, sizeof(struct instruction));
6596 data = calloc(n_instructions, sizeof(struct instruction_data));
6602 for (i = 0; i < n_instructions; i++) {
6603 char *string = strdup(instructions[i]);
6609 err = instr_translate(p, a, string, &instr[i], &data[i]);
6618 err = instr_label_check(data, n_instructions);
6622 err = instr_verify(p, a, instr, data, n_instructions);
6626 n_instructions = instr_optimize(p, a, instr, data, n_instructions);
6628 err = instr_jmp_resolve(instr, data, n_instructions);
6633 a->instructions = instr;
6634 a->instruction_data = data;
6635 a->n_instructions = n_instructions;
6637 p->instructions = instr;
6638 p->instruction_data = data;
6639 p->n_instructions = n_instructions;
6650 static instr_exec_t instruction_table[] = {
6651 [INSTR_RX] = instr_rx_exec,
6652 [INSTR_TX] = instr_tx_exec,
6653 [INSTR_TX_I] = instr_tx_i_exec,
6655 [INSTR_HDR_EXTRACT] = instr_hdr_extract_exec,
6656 [INSTR_HDR_EXTRACT2] = instr_hdr_extract2_exec,
6657 [INSTR_HDR_EXTRACT3] = instr_hdr_extract3_exec,
6658 [INSTR_HDR_EXTRACT4] = instr_hdr_extract4_exec,
6659 [INSTR_HDR_EXTRACT5] = instr_hdr_extract5_exec,
6660 [INSTR_HDR_EXTRACT6] = instr_hdr_extract6_exec,
6661 [INSTR_HDR_EXTRACT7] = instr_hdr_extract7_exec,
6662 [INSTR_HDR_EXTRACT8] = instr_hdr_extract8_exec,
6663 [INSTR_HDR_EXTRACT_M] = instr_hdr_extract_m_exec,
6664 [INSTR_HDR_LOOKAHEAD] = instr_hdr_lookahead_exec,
6666 [INSTR_HDR_EMIT] = instr_hdr_emit_exec,
6667 [INSTR_HDR_EMIT_TX] = instr_hdr_emit_tx_exec,
6668 [INSTR_HDR_EMIT2_TX] = instr_hdr_emit2_tx_exec,
6669 [INSTR_HDR_EMIT3_TX] = instr_hdr_emit3_tx_exec,
6670 [INSTR_HDR_EMIT4_TX] = instr_hdr_emit4_tx_exec,
6671 [INSTR_HDR_EMIT5_TX] = instr_hdr_emit5_tx_exec,
6672 [INSTR_HDR_EMIT6_TX] = instr_hdr_emit6_tx_exec,
6673 [INSTR_HDR_EMIT7_TX] = instr_hdr_emit7_tx_exec,
6674 [INSTR_HDR_EMIT8_TX] = instr_hdr_emit8_tx_exec,
6676 [INSTR_HDR_VALIDATE] = instr_hdr_validate_exec,
6677 [INSTR_HDR_INVALIDATE] = instr_hdr_invalidate_exec,
6679 [INSTR_MOV] = instr_mov_exec,
6680 [INSTR_MOV_MH] = instr_mov_mh_exec,
6681 [INSTR_MOV_HM] = instr_mov_hm_exec,
6682 [INSTR_MOV_HH] = instr_mov_hh_exec,
6683 [INSTR_MOV_I] = instr_mov_i_exec,
6685 [INSTR_DMA_HT] = instr_dma_ht_exec,
6686 [INSTR_DMA_HT2] = instr_dma_ht2_exec,
6687 [INSTR_DMA_HT3] = instr_dma_ht3_exec,
6688 [INSTR_DMA_HT4] = instr_dma_ht4_exec,
6689 [INSTR_DMA_HT5] = instr_dma_ht5_exec,
6690 [INSTR_DMA_HT6] = instr_dma_ht6_exec,
6691 [INSTR_DMA_HT7] = instr_dma_ht7_exec,
6692 [INSTR_DMA_HT8] = instr_dma_ht8_exec,
6694 [INSTR_ALU_ADD] = instr_alu_add_exec,
6695 [INSTR_ALU_ADD_MH] = instr_alu_add_mh_exec,
6696 [INSTR_ALU_ADD_HM] = instr_alu_add_hm_exec,
6697 [INSTR_ALU_ADD_HH] = instr_alu_add_hh_exec,
6698 [INSTR_ALU_ADD_MI] = instr_alu_add_mi_exec,
6699 [INSTR_ALU_ADD_HI] = instr_alu_add_hi_exec,
6701 [INSTR_ALU_SUB] = instr_alu_sub_exec,
6702 [INSTR_ALU_SUB_MH] = instr_alu_sub_mh_exec,
6703 [INSTR_ALU_SUB_HM] = instr_alu_sub_hm_exec,
6704 [INSTR_ALU_SUB_HH] = instr_alu_sub_hh_exec,
6705 [INSTR_ALU_SUB_MI] = instr_alu_sub_mi_exec,
6706 [INSTR_ALU_SUB_HI] = instr_alu_sub_hi_exec,
6708 [INSTR_ALU_CKADD_FIELD] = instr_alu_ckadd_field_exec,
6709 [INSTR_ALU_CKADD_STRUCT] = instr_alu_ckadd_struct_exec,
6710 [INSTR_ALU_CKADD_STRUCT20] = instr_alu_ckadd_struct20_exec,
6711 [INSTR_ALU_CKSUB_FIELD] = instr_alu_cksub_field_exec,
6713 [INSTR_ALU_AND] = instr_alu_and_exec,
6714 [INSTR_ALU_AND_MH] = instr_alu_and_mh_exec,
6715 [INSTR_ALU_AND_HM] = instr_alu_and_hm_exec,
6716 [INSTR_ALU_AND_HH] = instr_alu_and_hh_exec,
6717 [INSTR_ALU_AND_I] = instr_alu_and_i_exec,
6719 [INSTR_ALU_OR] = instr_alu_or_exec,
6720 [INSTR_ALU_OR_MH] = instr_alu_or_mh_exec,
6721 [INSTR_ALU_OR_HM] = instr_alu_or_hm_exec,
6722 [INSTR_ALU_OR_HH] = instr_alu_or_hh_exec,
6723 [INSTR_ALU_OR_I] = instr_alu_or_i_exec,
6725 [INSTR_ALU_XOR] = instr_alu_xor_exec,
6726 [INSTR_ALU_XOR_MH] = instr_alu_xor_mh_exec,
6727 [INSTR_ALU_XOR_HM] = instr_alu_xor_hm_exec,
6728 [INSTR_ALU_XOR_HH] = instr_alu_xor_hh_exec,
6729 [INSTR_ALU_XOR_I] = instr_alu_xor_i_exec,
6731 [INSTR_ALU_SHL] = instr_alu_shl_exec,
6732 [INSTR_ALU_SHL_MH] = instr_alu_shl_mh_exec,
6733 [INSTR_ALU_SHL_HM] = instr_alu_shl_hm_exec,
6734 [INSTR_ALU_SHL_HH] = instr_alu_shl_hh_exec,
6735 [INSTR_ALU_SHL_MI] = instr_alu_shl_mi_exec,
6736 [INSTR_ALU_SHL_HI] = instr_alu_shl_hi_exec,
6738 [INSTR_ALU_SHR] = instr_alu_shr_exec,
6739 [INSTR_ALU_SHR_MH] = instr_alu_shr_mh_exec,
6740 [INSTR_ALU_SHR_HM] = instr_alu_shr_hm_exec,
6741 [INSTR_ALU_SHR_HH] = instr_alu_shr_hh_exec,
6742 [INSTR_ALU_SHR_MI] = instr_alu_shr_mi_exec,
6743 [INSTR_ALU_SHR_HI] = instr_alu_shr_hi_exec,
6745 [INSTR_REGPREFETCH_RH] = instr_regprefetch_rh_exec,
6746 [INSTR_REGPREFETCH_RM] = instr_regprefetch_rm_exec,
6747 [INSTR_REGPREFETCH_RI] = instr_regprefetch_ri_exec,
6749 [INSTR_REGRD_HRH] = instr_regrd_hrh_exec,
6750 [INSTR_REGRD_HRM] = instr_regrd_hrm_exec,
6751 [INSTR_REGRD_MRH] = instr_regrd_mrh_exec,
6752 [INSTR_REGRD_MRM] = instr_regrd_mrm_exec,
6753 [INSTR_REGRD_HRI] = instr_regrd_hri_exec,
6754 [INSTR_REGRD_MRI] = instr_regrd_mri_exec,
6756 [INSTR_REGWR_RHH] = instr_regwr_rhh_exec,
6757 [INSTR_REGWR_RHM] = instr_regwr_rhm_exec,
6758 [INSTR_REGWR_RMH] = instr_regwr_rmh_exec,
6759 [INSTR_REGWR_RMM] = instr_regwr_rmm_exec,
6760 [INSTR_REGWR_RHI] = instr_regwr_rhi_exec,
6761 [INSTR_REGWR_RMI] = instr_regwr_rmi_exec,
6762 [INSTR_REGWR_RIH] = instr_regwr_rih_exec,
6763 [INSTR_REGWR_RIM] = instr_regwr_rim_exec,
6764 [INSTR_REGWR_RII] = instr_regwr_rii_exec,
6766 [INSTR_REGADD_RHH] = instr_regadd_rhh_exec,
6767 [INSTR_REGADD_RHM] = instr_regadd_rhm_exec,
6768 [INSTR_REGADD_RMH] = instr_regadd_rmh_exec,
6769 [INSTR_REGADD_RMM] = instr_regadd_rmm_exec,
6770 [INSTR_REGADD_RHI] = instr_regadd_rhi_exec,
6771 [INSTR_REGADD_RMI] = instr_regadd_rmi_exec,
6772 [INSTR_REGADD_RIH] = instr_regadd_rih_exec,
6773 [INSTR_REGADD_RIM] = instr_regadd_rim_exec,
6774 [INSTR_REGADD_RII] = instr_regadd_rii_exec,
6776 [INSTR_METPREFETCH_H] = instr_metprefetch_h_exec,
6777 [INSTR_METPREFETCH_M] = instr_metprefetch_m_exec,
6778 [INSTR_METPREFETCH_I] = instr_metprefetch_i_exec,
6780 [INSTR_METER_HHM] = instr_meter_hhm_exec,
6781 [INSTR_METER_HHI] = instr_meter_hhi_exec,
6782 [INSTR_METER_HMM] = instr_meter_hmm_exec,
6783 [INSTR_METER_HMI] = instr_meter_hmi_exec,
6784 [INSTR_METER_MHM] = instr_meter_mhm_exec,
6785 [INSTR_METER_MHI] = instr_meter_mhi_exec,
6786 [INSTR_METER_MMM] = instr_meter_mmm_exec,
6787 [INSTR_METER_MMI] = instr_meter_mmi_exec,
6788 [INSTR_METER_IHM] = instr_meter_ihm_exec,
6789 [INSTR_METER_IHI] = instr_meter_ihi_exec,
6790 [INSTR_METER_IMM] = instr_meter_imm_exec,
6791 [INSTR_METER_IMI] = instr_meter_imi_exec,
6793 [INSTR_TABLE] = instr_table_exec,
6794 [INSTR_TABLE_AF] = instr_table_af_exec,
6795 [INSTR_SELECTOR] = instr_selector_exec,
6796 [INSTR_LEARNER] = instr_learner_exec,
6797 [INSTR_LEARNER_AF] = instr_learner_af_exec,
6798 [INSTR_LEARNER_LEARN] = instr_learn_exec,
6799 [INSTR_LEARNER_FORGET] = instr_forget_exec,
6800 [INSTR_EXTERN_OBJ] = instr_extern_obj_exec,
6801 [INSTR_EXTERN_FUNC] = instr_extern_func_exec,
6803 [INSTR_JMP] = instr_jmp_exec,
6804 [INSTR_JMP_VALID] = instr_jmp_valid_exec,
6805 [INSTR_JMP_INVALID] = instr_jmp_invalid_exec,
6806 [INSTR_JMP_HIT] = instr_jmp_hit_exec,
6807 [INSTR_JMP_MISS] = instr_jmp_miss_exec,
6808 [INSTR_JMP_ACTION_HIT] = instr_jmp_action_hit_exec,
6809 [INSTR_JMP_ACTION_MISS] = instr_jmp_action_miss_exec,
6811 [INSTR_JMP_EQ] = instr_jmp_eq_exec,
6812 [INSTR_JMP_EQ_MH] = instr_jmp_eq_mh_exec,
6813 [INSTR_JMP_EQ_HM] = instr_jmp_eq_hm_exec,
6814 [INSTR_JMP_EQ_HH] = instr_jmp_eq_hh_exec,
6815 [INSTR_JMP_EQ_I] = instr_jmp_eq_i_exec,
6817 [INSTR_JMP_NEQ] = instr_jmp_neq_exec,
6818 [INSTR_JMP_NEQ_MH] = instr_jmp_neq_mh_exec,
6819 [INSTR_JMP_NEQ_HM] = instr_jmp_neq_hm_exec,
6820 [INSTR_JMP_NEQ_HH] = instr_jmp_neq_hh_exec,
6821 [INSTR_JMP_NEQ_I] = instr_jmp_neq_i_exec,
6823 [INSTR_JMP_LT] = instr_jmp_lt_exec,
6824 [INSTR_JMP_LT_MH] = instr_jmp_lt_mh_exec,
6825 [INSTR_JMP_LT_HM] = instr_jmp_lt_hm_exec,
6826 [INSTR_JMP_LT_HH] = instr_jmp_lt_hh_exec,
6827 [INSTR_JMP_LT_MI] = instr_jmp_lt_mi_exec,
6828 [INSTR_JMP_LT_HI] = instr_jmp_lt_hi_exec,
6830 [INSTR_JMP_GT] = instr_jmp_gt_exec,
6831 [INSTR_JMP_GT_MH] = instr_jmp_gt_mh_exec,
6832 [INSTR_JMP_GT_HM] = instr_jmp_gt_hm_exec,
6833 [INSTR_JMP_GT_HH] = instr_jmp_gt_hh_exec,
6834 [INSTR_JMP_GT_MI] = instr_jmp_gt_mi_exec,
6835 [INSTR_JMP_GT_HI] = instr_jmp_gt_hi_exec,
6837 [INSTR_RETURN] = instr_return_exec,
6841 instruction_table_build(struct rte_swx_pipeline *p)
6843 p->instruction_table = calloc(RTE_SWX_PIPELINE_INSTRUCTION_TABLE_SIZE_MAX,
6844 sizeof(struct instr_exec_t *));
6845 if (!p->instruction_table)
6848 memcpy(p->instruction_table, instruction_table, sizeof(instruction_table));
6854 instruction_table_build_free(struct rte_swx_pipeline *p)
6856 if (!p->instruction_table)
6859 free(p->instruction_table);
6860 p->instruction_table = NULL;
6864 instruction_table_free(struct rte_swx_pipeline *p)
6866 instruction_table_build_free(p);
6870 instr_exec(struct rte_swx_pipeline *p)
6872 struct thread *t = &p->threads[p->thread_id];
6873 struct instruction *ip = t->ip;
6874 instr_exec_t instr = p->instruction_table[ip->type];
6882 static struct action *
6883 action_find(struct rte_swx_pipeline *p, const char *name)
6885 struct action *elem;
6890 TAILQ_FOREACH(elem, &p->actions, node)
6891 if (strcmp(elem->name, name) == 0)
6897 static struct action *
6898 action_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
6900 struct action *action = NULL;
6902 TAILQ_FOREACH(action, &p->actions, node)
6903 if (action->id == id)
6909 static struct field *
6910 action_field_find(struct action *a, const char *name)
6912 return a->st ? struct_type_field_find(a->st, name) : NULL;
6915 static struct field *
6916 action_field_parse(struct action *action, const char *name)
6918 if (name[0] != 't' || name[1] != '.')
6921 return action_field_find(action, &name[2]);
6925 action_has_nbo_args(struct action *a)
6929 /* Return if the action does not have any args. */
6931 return 0; /* FALSE */
6933 for (i = 0; i < a->st->n_fields; i++)
6934 if (a->args_endianness[i])
6935 return 1; /* TRUE */
6937 return 0; /* FALSE */
6941 action_does_learning(struct action *a)
6945 for (i = 0; i < a->n_instructions; i++)
6946 switch (a->instructions[i].type) {
6947 case INSTR_LEARNER_LEARN:
6948 return 1; /* TRUE */
6950 case INSTR_LEARNER_FORGET:
6951 return 1; /* TRUE */
6957 return 0; /* FALSE */
6961 rte_swx_pipeline_action_config(struct rte_swx_pipeline *p,
6963 const char *args_struct_type_name,
6964 const char **instructions,
6965 uint32_t n_instructions)
6967 struct struct_type *args_struct_type = NULL;
6973 CHECK_NAME(name, EINVAL);
6974 CHECK(!action_find(p, name), EEXIST);
6976 if (args_struct_type_name) {
6977 CHECK_NAME(args_struct_type_name, EINVAL);
6978 args_struct_type = struct_type_find(p, args_struct_type_name);
6979 CHECK(args_struct_type, EINVAL);
6980 CHECK(!args_struct_type->var_size, EINVAL);
6983 /* Node allocation. */
6984 a = calloc(1, sizeof(struct action));
6986 if (args_struct_type) {
6987 a->args_endianness = calloc(args_struct_type->n_fields, sizeof(int));
6988 if (!a->args_endianness) {
6994 /* Node initialization. */
6995 strcpy(a->name, name);
6996 a->st = args_struct_type;
6997 a->id = p->n_actions;
6999 /* Instruction translation. */
7000 err = instruction_config(p, a, instructions, n_instructions);
7002 free(a->args_endianness);
7007 /* Node add to tailq. */
7008 TAILQ_INSERT_TAIL(&p->actions, a, node);
7015 action_build(struct rte_swx_pipeline *p)
7017 struct action *action;
7019 /* p->action_instructions. */
7020 p->action_instructions = calloc(p->n_actions, sizeof(struct instruction *));
7021 CHECK(p->action_instructions, ENOMEM);
7023 TAILQ_FOREACH(action, &p->actions, node)
7024 p->action_instructions[action->id] = action->instructions;
7026 /* p->action_funcs. */
7027 p->action_funcs = calloc(p->n_actions, sizeof(action_func_t));
7028 CHECK(p->action_funcs, ENOMEM);
7034 action_build_free(struct rte_swx_pipeline *p)
7036 free(p->action_funcs);
7037 p->action_funcs = NULL;
7039 free(p->action_instructions);
7040 p->action_instructions = NULL;
7044 action_free(struct rte_swx_pipeline *p)
7046 action_build_free(p);
7049 struct action *action;
7051 action = TAILQ_FIRST(&p->actions);
7055 TAILQ_REMOVE(&p->actions, action, node);
7056 free(action->instruction_data);
7057 free(action->instructions);
7063 action_arg_src_mov_count(struct action *a,
7065 struct instruction *instructions,
7066 struct instruction_data *instruction_data,
7067 uint32_t n_instructions)
7069 uint32_t offset, n_users = 0, i;
7072 (arg_id >= a->st->n_fields) ||
7074 !instruction_data ||
7078 offset = a->st->fields[arg_id].offset / 8;
7080 for (i = 0; i < n_instructions; i++) {
7081 struct instruction *instr = &instructions[i];
7082 struct instruction_data *data = &instruction_data[i];
7084 if (data->invalid ||
7085 ((instr->type != INSTR_MOV) && (instr->type != INSTR_MOV_HM)) ||
7086 instr->mov.src.struct_id ||
7087 (instr->mov.src.offset != offset))
7099 static struct table_type *
7100 table_type_find(struct rte_swx_pipeline *p, const char *name)
7102 struct table_type *elem;
7104 TAILQ_FOREACH(elem, &p->table_types, node)
7105 if (strcmp(elem->name, name) == 0)
7111 static struct table_type *
7112 table_type_resolve(struct rte_swx_pipeline *p,
7113 const char *recommended_type_name,
7114 enum rte_swx_table_match_type match_type)
7116 struct table_type *elem;
7118 /* Only consider the recommended type if the match type is correct. */
7119 if (recommended_type_name)
7120 TAILQ_FOREACH(elem, &p->table_types, node)
7121 if (!strcmp(elem->name, recommended_type_name) &&
7122 (elem->match_type == match_type))
7125 /* Ignore the recommended type and get the first element with this match
7128 TAILQ_FOREACH(elem, &p->table_types, node)
7129 if (elem->match_type == match_type)
7135 static struct table *
7136 table_find(struct rte_swx_pipeline *p, const char *name)
7140 TAILQ_FOREACH(elem, &p->tables, node)
7141 if (strcmp(elem->name, name) == 0)
7147 static struct table *
7148 table_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7150 struct table *table = NULL;
7152 TAILQ_FOREACH(table, &p->tables, node)
7153 if (table->id == id)
7160 rte_swx_pipeline_table_type_register(struct rte_swx_pipeline *p,
7162 enum rte_swx_table_match_type match_type,
7163 struct rte_swx_table_ops *ops)
7165 struct table_type *elem;
7169 CHECK_NAME(name, EINVAL);
7170 CHECK(!table_type_find(p, name), EEXIST);
7173 CHECK(ops->create, EINVAL);
7174 CHECK(ops->lkp, EINVAL);
7175 CHECK(ops->free, EINVAL);
7177 /* Node allocation. */
7178 elem = calloc(1, sizeof(struct table_type));
7179 CHECK(elem, ENOMEM);
7181 /* Node initialization. */
7182 strcpy(elem->name, name);
7183 elem->match_type = match_type;
7184 memcpy(&elem->ops, ops, sizeof(*ops));
7186 /* Node add to tailq. */
7187 TAILQ_INSERT_TAIL(&p->table_types, elem, node);
7193 table_match_type_resolve(struct rte_swx_match_field_params *fields,
7195 enum rte_swx_table_match_type *match_type)
7197 uint32_t n_fields_em = 0, n_fields_lpm = 0, i;
7199 for (i = 0; i < n_fields; i++) {
7200 struct rte_swx_match_field_params *f = &fields[i];
7202 if (f->match_type == RTE_SWX_TABLE_MATCH_EXACT)
7205 if (f->match_type == RTE_SWX_TABLE_MATCH_LPM)
7209 if ((n_fields_lpm > 1) ||
7210 (n_fields_lpm && (n_fields_em != n_fields - 1)))
7213 *match_type = (n_fields_em == n_fields) ?
7214 RTE_SWX_TABLE_MATCH_EXACT :
7215 RTE_SWX_TABLE_MATCH_WILDCARD;
7221 table_match_fields_check(struct rte_swx_pipeline *p,
7222 struct rte_swx_pipeline_table_params *params,
7223 struct header **header)
7225 struct header *h0 = NULL;
7226 struct field *hf, *mf;
7227 uint32_t *offset = NULL, i;
7230 /* Return if no match fields. */
7231 if (!params->n_fields) {
7232 if (params->fields) {
7243 /* Memory allocation. */
7244 offset = calloc(params->n_fields, sizeof(uint32_t));
7250 /* Check that all the match fields belong to either the same header or
7253 hf = header_field_parse(p, params->fields[0].name, &h0);
7254 mf = metadata_field_parse(p, params->fields[0].name);
7255 if ((!hf && !mf) || (hf && hf->var_size)) {
7260 offset[0] = h0 ? hf->offset : mf->offset;
7262 for (i = 1; i < params->n_fields; i++)
7266 hf = header_field_parse(p, params->fields[i].name, &h);
7267 if (!hf || (h->id != h0->id) || hf->var_size) {
7272 offset[i] = hf->offset;
7274 mf = metadata_field_parse(p, params->fields[i].name);
7280 offset[i] = mf->offset;
7283 /* Check that there are no duplicated match fields. */
7284 for (i = 0; i < params->n_fields; i++) {
7287 for (j = 0; j < i; j++)
7288 if (offset[j] == offset[i]) {
7304 rte_swx_pipeline_table_config(struct rte_swx_pipeline *p,
7306 struct rte_swx_pipeline_table_params *params,
7307 const char *recommended_table_type_name,
7311 struct table_type *type;
7312 struct table *t = NULL;
7313 struct action *default_action;
7314 struct header *header = NULL;
7315 uint32_t action_data_size_max = 0, i;
7320 CHECK_NAME(name, EINVAL);
7321 CHECK(!table_find(p, name), EEXIST);
7322 CHECK(!selector_find(p, name), EEXIST);
7323 CHECK(!learner_find(p, name), EEXIST);
7325 CHECK(params, EINVAL);
7328 status = table_match_fields_check(p, params, &header);
7332 /* Action checks. */
7333 CHECK(params->n_actions, EINVAL);
7334 CHECK(params->action_names, EINVAL);
7335 for (i = 0; i < params->n_actions; i++) {
7336 const char *action_name = params->action_names[i];
7338 uint32_t action_data_size;
7339 int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
7341 CHECK_NAME(action_name, EINVAL);
7343 a = action_find(p, action_name);
7345 CHECK(!action_does_learning(a), EINVAL);
7347 action_data_size = a->st ? a->st->n_bits / 8 : 0;
7348 if (action_data_size > action_data_size_max)
7349 action_data_size_max = action_data_size;
7351 if (params->action_is_for_table_entries)
7352 action_is_for_table_entries = params->action_is_for_table_entries[i];
7353 if (params->action_is_for_default_entry)
7354 action_is_for_default_entry = params->action_is_for_default_entry[i];
7355 CHECK(action_is_for_table_entries || action_is_for_default_entry, EINVAL);
7358 CHECK_NAME(params->default_action_name, EINVAL);
7359 for (i = 0; i < p->n_actions; i++)
7360 if (!strcmp(params->action_names[i],
7361 params->default_action_name))
7363 CHECK(i < params->n_actions, EINVAL);
7364 CHECK(!params->action_is_for_default_entry || params->action_is_for_default_entry[i],
7367 default_action = action_find(p, params->default_action_name);
7368 CHECK((default_action->st && params->default_action_data) ||
7369 !params->default_action_data, EINVAL);
7371 /* Table type checks. */
7372 if (recommended_table_type_name)
7373 CHECK_NAME(recommended_table_type_name, EINVAL);
7375 if (params->n_fields) {
7376 enum rte_swx_table_match_type match_type;
7378 status = table_match_type_resolve(params->fields, params->n_fields, &match_type);
7382 type = table_type_resolve(p, recommended_table_type_name, match_type);
7383 CHECK(type, EINVAL);
7388 /* Memory allocation. */
7389 t = calloc(1, sizeof(struct table));
7393 t->fields = calloc(params->n_fields, sizeof(struct match_field));
7397 t->actions = calloc(params->n_actions, sizeof(struct action *));
7401 if (action_data_size_max) {
7402 t->default_action_data = calloc(1, action_data_size_max);
7403 if (!t->default_action_data)
7407 t->action_is_for_table_entries = calloc(params->n_actions, sizeof(int));
7408 if (!t->action_is_for_table_entries)
7411 t->action_is_for_default_entry = calloc(params->n_actions, sizeof(int));
7412 if (!t->action_is_for_default_entry)
7415 /* Node initialization. */
7416 strcpy(t->name, name);
7417 if (args && args[0])
7418 strcpy(t->args, args);
7421 for (i = 0; i < params->n_fields; i++) {
7422 struct rte_swx_match_field_params *field = ¶ms->fields[i];
7423 struct match_field *f = &t->fields[i];
7425 f->match_type = field->match_type;
7427 header_field_parse(p, field->name, NULL) :
7428 metadata_field_parse(p, field->name);
7430 t->n_fields = params->n_fields;
7433 for (i = 0; i < params->n_actions; i++) {
7434 int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
7436 if (params->action_is_for_table_entries)
7437 action_is_for_table_entries = params->action_is_for_table_entries[i];
7438 if (params->action_is_for_default_entry)
7439 action_is_for_default_entry = params->action_is_for_default_entry[i];
7441 t->actions[i] = action_find(p, params->action_names[i]);
7442 t->action_is_for_table_entries[i] = action_is_for_table_entries;
7443 t->action_is_for_default_entry[i] = action_is_for_default_entry;
7445 t->default_action = default_action;
7446 if (default_action->st)
7447 memcpy(t->default_action_data,
7448 params->default_action_data,
7449 default_action->st->n_bits / 8);
7450 t->n_actions = params->n_actions;
7451 t->default_action_is_const = params->default_action_is_const;
7452 t->action_data_size_max = action_data_size_max;
7455 t->id = p->n_tables;
7457 /* Node add to tailq. */
7458 TAILQ_INSERT_TAIL(&p->tables, t, node);
7467 free(t->action_is_for_default_entry);
7468 free(t->action_is_for_table_entries);
7469 free(t->default_action_data);
7477 static struct rte_swx_table_params *
7478 table_params_get(struct table *table)
7480 struct rte_swx_table_params *params;
7481 struct field *first, *last;
7483 uint32_t key_size, key_offset, action_data_size, i;
7485 /* Memory allocation. */
7486 params = calloc(1, sizeof(struct rte_swx_table_params));
7490 /* Find first (smallest offset) and last (biggest offset) match fields. */
7491 first = table->fields[0].field;
7492 last = table->fields[0].field;
7494 for (i = 0; i < table->n_fields; i++) {
7495 struct field *f = table->fields[i].field;
7497 if (f->offset < first->offset)
7500 if (f->offset > last->offset)
7504 /* Key offset and size. */
7505 key_offset = first->offset / 8;
7506 key_size = (last->offset + last->n_bits - first->offset) / 8;
7508 /* Memory allocation. */
7509 key_mask = calloc(1, key_size);
7516 for (i = 0; i < table->n_fields; i++) {
7517 struct field *f = table->fields[i].field;
7518 uint32_t start = (f->offset - first->offset) / 8;
7519 size_t size = f->n_bits / 8;
7521 memset(&key_mask[start], 0xFF, size);
7524 /* Action data size. */
7525 action_data_size = 0;
7526 for (i = 0; i < table->n_actions; i++) {
7527 struct action *action = table->actions[i];
7528 uint32_t ads = action->st ? action->st->n_bits / 8 : 0;
7530 if (ads > action_data_size)
7531 action_data_size = ads;
7535 params->match_type = table->type->match_type;
7536 params->key_size = key_size;
7537 params->key_offset = key_offset;
7538 params->key_mask0 = key_mask;
7539 params->action_data_size = action_data_size;
7540 params->n_keys_max = table->size;
7546 table_params_free(struct rte_swx_table_params *params)
7551 free(params->key_mask0);
7556 table_stub_lkp(void *table __rte_unused,
7557 void *mailbox __rte_unused,
7558 uint8_t **key __rte_unused,
7559 uint64_t *action_id __rte_unused,
7560 uint8_t **action_data __rte_unused,
7564 return 1; /* DONE. */
7568 table_build(struct rte_swx_pipeline *p)
7572 /* Per pipeline: table statistics. */
7573 p->table_stats = calloc(p->n_tables, sizeof(struct table_statistics));
7574 CHECK(p->table_stats, ENOMEM);
7576 for (i = 0; i < p->n_tables; i++) {
7577 p->table_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
7578 CHECK(p->table_stats[i].n_pkts_action, ENOMEM);
7581 /* Per thread: table runt-time. */
7582 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
7583 struct thread *t = &p->threads[i];
7584 struct table *table;
7586 t->tables = calloc(p->n_tables, sizeof(struct table_runtime));
7587 CHECK(t->tables, ENOMEM);
7589 TAILQ_FOREACH(table, &p->tables, node) {
7590 struct table_runtime *r = &t->tables[table->id];
7595 size = table->type->ops.mailbox_size_get();
7598 r->func = table->type->ops.lkp;
7602 r->mailbox = calloc(1, size);
7603 CHECK(r->mailbox, ENOMEM);
7607 r->key = table->header ?
7608 &t->structs[table->header->struct_id] :
7609 &t->structs[p->metadata_struct_id];
7611 r->func = table_stub_lkp;
7620 table_build_free(struct rte_swx_pipeline *p)
7624 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
7625 struct thread *t = &p->threads[i];
7631 for (j = 0; j < p->n_tables; j++) {
7632 struct table_runtime *r = &t->tables[j];
7641 if (p->table_stats) {
7642 for (i = 0; i < p->n_tables; i++)
7643 free(p->table_stats[i].n_pkts_action);
7645 free(p->table_stats);
7650 table_free(struct rte_swx_pipeline *p)
7652 table_build_free(p);
7658 elem = TAILQ_FIRST(&p->tables);
7662 TAILQ_REMOVE(&p->tables, elem, node);
7664 free(elem->actions);
7665 free(elem->default_action_data);
7671 struct table_type *elem;
7673 elem = TAILQ_FIRST(&p->table_types);
7677 TAILQ_REMOVE(&p->table_types, elem, node);
7685 static struct selector *
7686 selector_find(struct rte_swx_pipeline *p, const char *name)
7690 TAILQ_FOREACH(s, &p->selectors, node)
7691 if (strcmp(s->name, name) == 0)
7697 static struct selector *
7698 selector_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7700 struct selector *s = NULL;
7702 TAILQ_FOREACH(s, &p->selectors, node)
7710 selector_fields_check(struct rte_swx_pipeline *p,
7711 struct rte_swx_pipeline_selector_params *params,
7712 struct header **header)
7714 struct header *h0 = NULL;
7715 struct field *hf, *mf;
7718 /* Return if no selector fields. */
7719 if (!params->n_selector_fields || !params->selector_field_names)
7722 /* Check that all the selector fields either belong to the same header
7723 * or are all meta-data fields.
7725 hf = header_field_parse(p, params->selector_field_names[0], &h0);
7726 mf = metadata_field_parse(p, params->selector_field_names[0]);
7730 for (i = 1; i < params->n_selector_fields; i++)
7734 hf = header_field_parse(p, params->selector_field_names[i], &h);
7735 if (!hf || (h->id != h0->id))
7738 mf = metadata_field_parse(p, params->selector_field_names[i]);
7743 /* Check that there are no duplicated match fields. */
7744 for (i = 0; i < params->n_selector_fields; i++) {
7745 const char *field_name = params->selector_field_names[i];
7748 for (j = i + 1; j < params->n_selector_fields; j++)
7749 if (!strcmp(params->selector_field_names[j], field_name))
7761 rte_swx_pipeline_selector_config(struct rte_swx_pipeline *p,
7763 struct rte_swx_pipeline_selector_params *params)
7766 struct header *selector_header = NULL;
7767 struct field *group_id_field, *member_id_field;
7773 CHECK_NAME(name, EINVAL);
7774 CHECK(!table_find(p, name), EEXIST);
7775 CHECK(!selector_find(p, name), EEXIST);
7776 CHECK(!learner_find(p, name), EEXIST);
7778 CHECK(params, EINVAL);
7780 CHECK_NAME(params->group_id_field_name, EINVAL);
7781 group_id_field = metadata_field_parse(p, params->group_id_field_name);
7782 CHECK(group_id_field, EINVAL);
7784 for (i = 0; i < params->n_selector_fields; i++) {
7785 const char *field_name = params->selector_field_names[i];
7787 CHECK_NAME(field_name, EINVAL);
7789 status = selector_fields_check(p, params, &selector_header);
7793 CHECK_NAME(params->member_id_field_name, EINVAL);
7794 member_id_field = metadata_field_parse(p, params->member_id_field_name);
7795 CHECK(member_id_field, EINVAL);
7797 CHECK(params->n_groups_max, EINVAL);
7799 CHECK(params->n_members_per_group_max, EINVAL);
7801 /* Memory allocation. */
7802 s = calloc(1, sizeof(struct selector));
7808 s->selector_fields = calloc(params->n_selector_fields, sizeof(struct field *));
7809 if (!s->selector_fields) {
7814 /* Node initialization. */
7815 strcpy(s->name, name);
7817 s->group_id_field = group_id_field;
7819 for (i = 0; i < params->n_selector_fields; i++) {
7820 const char *field_name = params->selector_field_names[i];
7822 s->selector_fields[i] = selector_header ?
7823 header_field_parse(p, field_name, NULL) :
7824 metadata_field_parse(p, field_name);
7827 s->n_selector_fields = params->n_selector_fields;
7829 s->selector_header = selector_header;
7831 s->member_id_field = member_id_field;
7833 s->n_groups_max = params->n_groups_max;
7835 s->n_members_per_group_max = params->n_members_per_group_max;
7837 s->id = p->n_selectors;
7839 /* Node add to tailq. */
7840 TAILQ_INSERT_TAIL(&p->selectors, s, node);
7849 free(s->selector_fields);
7857 selector_params_free(struct rte_swx_table_selector_params *params)
7862 free(params->selector_mask);
7867 static struct rte_swx_table_selector_params *
7868 selector_table_params_get(struct selector *s)
7870 struct rte_swx_table_selector_params *params = NULL;
7871 struct field *first, *last;
7874 /* Memory allocation. */
7875 params = calloc(1, sizeof(struct rte_swx_table_selector_params));
7880 params->group_id_offset = s->group_id_field->offset / 8;
7882 /* Find first (smallest offset) and last (biggest offset) selector fields. */
7883 first = s->selector_fields[0];
7884 last = s->selector_fields[0];
7886 for (i = 0; i < s->n_selector_fields; i++) {
7887 struct field *f = s->selector_fields[i];
7889 if (f->offset < first->offset)
7892 if (f->offset > last->offset)
7896 /* Selector offset and size. */
7897 params->selector_offset = first->offset / 8;
7898 params->selector_size = (last->offset + last->n_bits - first->offset) / 8;
7900 /* Memory allocation. */
7901 params->selector_mask = calloc(1, params->selector_size);
7902 if (!params->selector_mask)
7905 /* Selector mask. */
7906 for (i = 0; i < s->n_selector_fields; i++) {
7907 struct field *f = s->selector_fields[i];
7908 uint32_t start = (f->offset - first->offset) / 8;
7909 size_t size = f->n_bits / 8;
7911 memset(¶ms->selector_mask[start], 0xFF, size);
7915 params->member_id_offset = s->member_id_field->offset / 8;
7917 /* Maximum number of groups. */
7918 params->n_groups_max = s->n_groups_max;
7920 /* Maximum number of members per group. */
7921 params->n_members_per_group_max = s->n_members_per_group_max;
7926 selector_params_free(params);
7931 selector_build_free(struct rte_swx_pipeline *p)
7935 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
7936 struct thread *t = &p->threads[i];
7942 for (j = 0; j < p->n_selectors; j++) {
7943 struct selector_runtime *r = &t->selectors[j];
7949 t->selectors = NULL;
7952 free(p->selector_stats);
7953 p->selector_stats = NULL;
7957 selector_build(struct rte_swx_pipeline *p)
7962 /* Per pipeline: selector statistics. */
7963 p->selector_stats = calloc(p->n_selectors, sizeof(struct selector_statistics));
7964 if (!p->selector_stats) {
7969 /* Per thread: selector run-time. */
7970 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
7971 struct thread *t = &p->threads[i];
7974 t->selectors = calloc(p->n_selectors, sizeof(struct selector_runtime));
7975 if (!t->selectors) {
7980 TAILQ_FOREACH(s, &p->selectors, node) {
7981 struct selector_runtime *r = &t->selectors[s->id];
7985 size = rte_swx_table_selector_mailbox_size_get();
7987 r->mailbox = calloc(1, size);
7994 /* r->group_id_buffer. */
7995 r->group_id_buffer = &t->structs[p->metadata_struct_id];
7997 /* r->selector_buffer. */
7998 r->selector_buffer = s->selector_header ?
7999 &t->structs[s->selector_header->struct_id] :
8000 &t->structs[p->metadata_struct_id];
8002 /* r->member_id_buffer. */
8003 r->member_id_buffer = &t->structs[p->metadata_struct_id];
8010 selector_build_free(p);
8015 selector_free(struct rte_swx_pipeline *p)
8017 selector_build_free(p);
8019 /* Selector tables. */
8021 struct selector *elem;
8023 elem = TAILQ_FIRST(&p->selectors);
8027 TAILQ_REMOVE(&p->selectors, elem, node);
8028 free(elem->selector_fields);
8036 static struct learner *
8037 learner_find(struct rte_swx_pipeline *p, const char *name)
8041 TAILQ_FOREACH(l, &p->learners, node)
8042 if (!strcmp(l->name, name))
8048 static struct learner *
8049 learner_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8051 struct learner *l = NULL;
8053 TAILQ_FOREACH(l, &p->learners, node)
8061 learner_match_fields_check(struct rte_swx_pipeline *p,
8062 struct rte_swx_pipeline_learner_params *params,
8063 struct header **header)
8065 struct header *h0 = NULL;
8066 struct field *hf, *mf;
8069 /* Return if no match fields. */
8070 if (!params->n_fields || !params->field_names)
8073 /* Check that all the match fields either belong to the same header
8074 * or are all meta-data fields.
8076 hf = header_field_parse(p, params->field_names[0], &h0);
8077 mf = metadata_field_parse(p, params->field_names[0]);
8081 for (i = 1; i < params->n_fields; i++)
8085 hf = header_field_parse(p, params->field_names[i], &h);
8086 if (!hf || (h->id != h0->id))
8089 mf = metadata_field_parse(p, params->field_names[i]);
8094 /* Check that there are no duplicated match fields. */
8095 for (i = 0; i < params->n_fields; i++) {
8096 const char *field_name = params->field_names[i];
8099 for (j = i + 1; j < params->n_fields; j++)
8100 if (!strcmp(params->field_names[j], field_name))
8112 learner_action_args_check(struct rte_swx_pipeline *p, struct action *a, const char *mf_name)
8114 struct struct_type *mst = p->metadata_st, *ast = a->st;
8115 struct field *mf, *af;
8125 /* Check that mf_name is the name of a valid meta-data field. */
8126 CHECK_NAME(mf_name, EINVAL);
8127 mf = metadata_field_parse(p, mf_name);
8130 /* Check that there are enough meta-data fields, starting with the mf_name field, to cover
8131 * all the action arguments.
8133 mf_pos = mf - mst->fields;
8134 CHECK(mst->n_fields - mf_pos >= ast->n_fields, EINVAL);
8136 /* Check that the size of each of the identified meta-data fields matches exactly the size
8137 * of the corresponding action argument.
8139 for (i = 0; i < ast->n_fields; i++) {
8140 mf = &mst->fields[mf_pos + i];
8141 af = &ast->fields[i];
8143 CHECK(mf->n_bits == af->n_bits, EINVAL);
8150 learner_action_learning_check(struct rte_swx_pipeline *p,
8151 struct action *action,
8152 const char **action_names,
8157 /* For each "learn" instruction of the current action, check that the learned action (i.e.
8158 * the action passed as argument to the "learn" instruction) is also enabled for the
8159 * current learner table.
8161 for (i = 0; i < action->n_instructions; i++) {
8162 struct instruction *instr = &action->instructions[i];
8163 uint32_t found = 0, j;
8165 if (instr->type != INSTR_LEARNER_LEARN)
8168 for (j = 0; j < n_actions; j++) {
8171 a = action_find(p, action_names[j]);
8175 if (a->id == instr->learn.action_id)
8187 rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p,
8189 struct rte_swx_pipeline_learner_params *params,
8193 struct learner *l = NULL;
8194 struct action *default_action;
8195 struct header *header = NULL;
8196 uint32_t action_data_size_max = 0, i;
8201 CHECK_NAME(name, EINVAL);
8202 CHECK(!table_find(p, name), EEXIST);
8203 CHECK(!selector_find(p, name), EEXIST);
8204 CHECK(!learner_find(p, name), EEXIST);
8206 CHECK(params, EINVAL);
8209 status = learner_match_fields_check(p, params, &header);
8213 /* Action checks. */
8214 CHECK(params->n_actions, EINVAL);
8215 CHECK(params->action_names, EINVAL);
8216 for (i = 0; i < params->n_actions; i++) {
8217 const char *action_name = params->action_names[i];
8219 uint32_t action_data_size;
8220 int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
8222 CHECK_NAME(action_name, EINVAL);
8224 a = action_find(p, action_name);
8227 status = learner_action_learning_check(p,
8229 params->action_names,
8234 action_data_size = a->st ? a->st->n_bits / 8 : 0;
8235 if (action_data_size > action_data_size_max)
8236 action_data_size_max = action_data_size;
8238 if (params->action_is_for_table_entries)
8239 action_is_for_table_entries = params->action_is_for_table_entries[i];
8240 if (params->action_is_for_default_entry)
8241 action_is_for_default_entry = params->action_is_for_default_entry[i];
8242 CHECK(action_is_for_table_entries || action_is_for_default_entry, EINVAL);
8245 CHECK_NAME(params->default_action_name, EINVAL);
8246 for (i = 0; i < p->n_actions; i++)
8247 if (!strcmp(params->action_names[i],
8248 params->default_action_name))
8250 CHECK(i < params->n_actions, EINVAL);
8251 CHECK(!params->action_is_for_default_entry || params->action_is_for_default_entry[i],
8254 default_action = action_find(p, params->default_action_name);
8255 CHECK((default_action->st && params->default_action_data) ||
8256 !params->default_action_data, EINVAL);
8258 /* Any other checks. */
8259 CHECK(size, EINVAL);
8260 CHECK(timeout, EINVAL);
8262 /* Memory allocation. */
8263 l = calloc(1, sizeof(struct learner));
8267 l->fields = calloc(params->n_fields, sizeof(struct field *));
8271 l->actions = calloc(params->n_actions, sizeof(struct action *));
8275 if (action_data_size_max) {
8276 l->default_action_data = calloc(1, action_data_size_max);
8277 if (!l->default_action_data)
8281 l->action_is_for_table_entries = calloc(params->n_actions, sizeof(int));
8282 if (!l->action_is_for_table_entries)
8285 l->action_is_for_default_entry = calloc(params->n_actions, sizeof(int));
8286 if (!l->action_is_for_default_entry)
8289 /* Node initialization. */
8290 strcpy(l->name, name);
8292 for (i = 0; i < params->n_fields; i++) {
8293 const char *field_name = params->field_names[i];
8295 l->fields[i] = header ?
8296 header_field_parse(p, field_name, NULL) :
8297 metadata_field_parse(p, field_name);
8300 l->n_fields = params->n_fields;
8304 for (i = 0; i < params->n_actions; i++) {
8305 int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
8307 if (params->action_is_for_table_entries)
8308 action_is_for_table_entries = params->action_is_for_table_entries[i];
8309 if (params->action_is_for_default_entry)
8310 action_is_for_default_entry = params->action_is_for_default_entry[i];
8312 l->actions[i] = action_find(p, params->action_names[i]);
8313 l->action_is_for_table_entries[i] = action_is_for_table_entries;
8314 l->action_is_for_default_entry[i] = action_is_for_default_entry;
8317 l->default_action = default_action;
8319 if (default_action->st)
8320 memcpy(l->default_action_data,
8321 params->default_action_data,
8322 default_action->st->n_bits / 8);
8324 l->n_actions = params->n_actions;
8326 l->default_action_is_const = params->default_action_is_const;
8328 l->action_data_size_max = action_data_size_max;
8332 l->timeout = timeout;
8334 l->id = p->n_learners;
8336 /* Node add to tailq. */
8337 TAILQ_INSERT_TAIL(&p->learners, l, node);
8346 free(l->action_is_for_default_entry);
8347 free(l->action_is_for_table_entries);
8348 free(l->default_action_data);
8357 learner_params_free(struct rte_swx_table_learner_params *params)
8362 free(params->key_mask0);
8367 static struct rte_swx_table_learner_params *
8368 learner_params_get(struct learner *l)
8370 struct rte_swx_table_learner_params *params = NULL;
8371 struct field *first, *last;
8374 /* Memory allocation. */
8375 params = calloc(1, sizeof(struct rte_swx_table_learner_params));
8379 /* Find first (smallest offset) and last (biggest offset) match fields. */
8380 first = l->fields[0];
8381 last = l->fields[0];
8383 for (i = 0; i < l->n_fields; i++) {
8384 struct field *f = l->fields[i];
8386 if (f->offset < first->offset)
8389 if (f->offset > last->offset)
8393 /* Key offset and size. */
8394 params->key_offset = first->offset / 8;
8395 params->key_size = (last->offset + last->n_bits - first->offset) / 8;
8397 /* Memory allocation. */
8398 params->key_mask0 = calloc(1, params->key_size);
8399 if (!params->key_mask0)
8403 for (i = 0; i < l->n_fields; i++) {
8404 struct field *f = l->fields[i];
8405 uint32_t start = (f->offset - first->offset) / 8;
8406 size_t size = f->n_bits / 8;
8408 memset(¶ms->key_mask0[start], 0xFF, size);
8411 /* Action data size. */
8412 params->action_data_size = l->action_data_size_max;
8414 /* Maximum number of keys. */
8415 params->n_keys_max = l->size;
8418 params->key_timeout = l->timeout;
8423 learner_params_free(params);
8428 learner_build_free(struct rte_swx_pipeline *p)
8432 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8433 struct thread *t = &p->threads[i];
8439 for (j = 0; j < p->n_learners; j++) {
8440 struct learner_runtime *r = &t->learners[j];
8449 if (p->learner_stats) {
8450 for (i = 0; i < p->n_learners; i++)
8451 free(p->learner_stats[i].n_pkts_action);
8453 free(p->learner_stats);
8458 learner_build(struct rte_swx_pipeline *p)
8463 /* Per pipeline: learner statistics. */
8464 p->learner_stats = calloc(p->n_learners, sizeof(struct learner_statistics));
8465 CHECK(p->learner_stats, ENOMEM);
8467 for (i = 0; i < p->n_learners; i++) {
8468 p->learner_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
8469 CHECK(p->learner_stats[i].n_pkts_action, ENOMEM);
8472 /* Per thread: learner run-time. */
8473 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8474 struct thread *t = &p->threads[i];
8477 t->learners = calloc(p->n_learners, sizeof(struct learner_runtime));
8483 TAILQ_FOREACH(l, &p->learners, node) {
8484 struct learner_runtime *r = &t->learners[l->id];
8488 size = rte_swx_table_learner_mailbox_size_get();
8490 r->mailbox = calloc(1, size);
8498 r->key = l->header ?
8499 &t->structs[l->header->struct_id] :
8500 &t->structs[p->metadata_struct_id];
8507 learner_build_free(p);
8512 learner_free(struct rte_swx_pipeline *p)
8514 learner_build_free(p);
8516 /* Learner tables. */
8520 l = TAILQ_FIRST(&p->learners);
8524 TAILQ_REMOVE(&p->learners, l, node);
8527 free(l->default_action_data);
8536 table_state_build(struct rte_swx_pipeline *p)
8538 struct table *table;
8542 p->table_state = calloc(p->n_tables + p->n_selectors,
8543 sizeof(struct rte_swx_table_state));
8544 CHECK(p->table_state, ENOMEM);
8546 TAILQ_FOREACH(table, &p->tables, node) {
8547 struct rte_swx_table_state *ts = &p->table_state[table->id];
8550 struct rte_swx_table_params *params;
8553 params = table_params_get(table);
8554 CHECK(params, ENOMEM);
8556 ts->obj = table->type->ops.create(params,
8561 table_params_free(params);
8562 CHECK(ts->obj, ENODEV);
8565 /* ts->default_action_data. */
8566 if (table->action_data_size_max) {
8567 ts->default_action_data =
8568 malloc(table->action_data_size_max);
8569 CHECK(ts->default_action_data, ENOMEM);
8571 memcpy(ts->default_action_data,
8572 table->default_action_data,
8573 table->action_data_size_max);
8576 /* ts->default_action_id. */
8577 ts->default_action_id = table->default_action->id;
8580 TAILQ_FOREACH(s, &p->selectors, node) {
8581 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + s->id];
8582 struct rte_swx_table_selector_params *params;
8585 params = selector_table_params_get(s);
8586 CHECK(params, ENOMEM);
8588 ts->obj = rte_swx_table_selector_create(params, NULL, p->numa_node);
8590 selector_params_free(params);
8591 CHECK(ts->obj, ENODEV);
8594 TAILQ_FOREACH(l, &p->learners, node) {
8595 struct rte_swx_table_state *ts = &p->table_state[p->n_tables +
8596 p->n_selectors + l->id];
8597 struct rte_swx_table_learner_params *params;
8600 params = learner_params_get(l);
8601 CHECK(params, ENOMEM);
8603 ts->obj = rte_swx_table_learner_create(params, p->numa_node);
8604 learner_params_free(params);
8605 CHECK(ts->obj, ENODEV);
8607 /* ts->default_action_data. */
8608 if (l->action_data_size_max) {
8609 ts->default_action_data = malloc(l->action_data_size_max);
8610 CHECK(ts->default_action_data, ENOMEM);
8612 memcpy(ts->default_action_data,
8613 l->default_action_data,
8614 l->action_data_size_max);
8617 /* ts->default_action_id. */
8618 ts->default_action_id = l->default_action->id;
8625 table_state_build_free(struct rte_swx_pipeline *p)
8629 if (!p->table_state)
8632 for (i = 0; i < p->n_tables; i++) {
8633 struct rte_swx_table_state *ts = &p->table_state[i];
8634 struct table *table = table_find_by_id(p, i);
8637 if (table->type && ts->obj)
8638 table->type->ops.free(ts->obj);
8640 /* ts->default_action_data. */
8641 free(ts->default_action_data);
8644 for (i = 0; i < p->n_selectors; i++) {
8645 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + i];
8649 rte_swx_table_selector_free(ts->obj);
8652 for (i = 0; i < p->n_learners; i++) {
8653 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + p->n_selectors + i];
8657 rte_swx_table_learner_free(ts->obj);
8659 /* ts->default_action_data. */
8660 free(ts->default_action_data);
8663 free(p->table_state);
8664 p->table_state = NULL;
8668 table_state_free(struct rte_swx_pipeline *p)
8670 table_state_build_free(p);
8676 static struct regarray *
8677 regarray_find(struct rte_swx_pipeline *p, const char *name)
8679 struct regarray *elem;
8681 TAILQ_FOREACH(elem, &p->regarrays, node)
8682 if (!strcmp(elem->name, name))
8688 static struct regarray *
8689 regarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8691 struct regarray *elem = NULL;
8693 TAILQ_FOREACH(elem, &p->regarrays, node)
8701 rte_swx_pipeline_regarray_config(struct rte_swx_pipeline *p,
8710 CHECK_NAME(name, EINVAL);
8711 CHECK(!regarray_find(p, name), EEXIST);
8713 CHECK(size, EINVAL);
8714 size = rte_align32pow2(size);
8716 /* Memory allocation. */
8717 r = calloc(1, sizeof(struct regarray));
8720 /* Node initialization. */
8721 strcpy(r->name, name);
8722 r->init_val = init_val;
8724 r->id = p->n_regarrays;
8726 /* Node add to tailq. */
8727 TAILQ_INSERT_TAIL(&p->regarrays, r, node);
8734 regarray_build(struct rte_swx_pipeline *p)
8736 struct regarray *regarray;
8738 if (!p->n_regarrays)
8741 p->regarray_runtime = calloc(p->n_regarrays, sizeof(struct regarray_runtime));
8742 CHECK(p->regarray_runtime, ENOMEM);
8744 TAILQ_FOREACH(regarray, &p->regarrays, node) {
8745 struct regarray_runtime *r = &p->regarray_runtime[regarray->id];
8748 r->regarray = env_malloc(regarray->size * sizeof(uint64_t),
8749 RTE_CACHE_LINE_SIZE,
8751 CHECK(r->regarray, ENOMEM);
8753 if (regarray->init_val)
8754 for (i = 0; i < regarray->size; i++)
8755 r->regarray[i] = regarray->init_val;
8757 r->size_mask = regarray->size - 1;
8764 regarray_build_free(struct rte_swx_pipeline *p)
8768 if (!p->regarray_runtime)
8771 for (i = 0; i < p->n_regarrays; i++) {
8772 struct regarray *regarray = regarray_find_by_id(p, i);
8773 struct regarray_runtime *r = &p->regarray_runtime[i];
8775 env_free(r->regarray, regarray->size * sizeof(uint64_t));
8778 free(p->regarray_runtime);
8779 p->regarray_runtime = NULL;
8783 regarray_free(struct rte_swx_pipeline *p)
8785 regarray_build_free(p);
8788 struct regarray *elem;
8790 elem = TAILQ_FIRST(&p->regarrays);
8794 TAILQ_REMOVE(&p->regarrays, elem, node);
8802 static struct meter_profile *
8803 meter_profile_find(struct rte_swx_pipeline *p, const char *name)
8805 struct meter_profile *elem;
8807 TAILQ_FOREACH(elem, &p->meter_profiles, node)
8808 if (!strcmp(elem->name, name))
8814 static struct metarray *
8815 metarray_find(struct rte_swx_pipeline *p, const char *name)
8817 struct metarray *elem;
8819 TAILQ_FOREACH(elem, &p->metarrays, node)
8820 if (!strcmp(elem->name, name))
8826 static struct metarray *
8827 metarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8829 struct metarray *elem = NULL;
8831 TAILQ_FOREACH(elem, &p->metarrays, node)
8839 rte_swx_pipeline_metarray_config(struct rte_swx_pipeline *p,
8847 CHECK_NAME(name, EINVAL);
8848 CHECK(!metarray_find(p, name), EEXIST);
8850 CHECK(size, EINVAL);
8851 size = rte_align32pow2(size);
8853 /* Memory allocation. */
8854 m = calloc(1, sizeof(struct metarray));
8857 /* Node initialization. */
8858 strcpy(m->name, name);
8860 m->id = p->n_metarrays;
8862 /* Node add to tailq. */
8863 TAILQ_INSERT_TAIL(&p->metarrays, m, node);
8869 struct meter_profile meter_profile_default = {
8878 .cir_bytes_per_period = 1,
8880 .pir_bytes_per_period = 1,
8887 meter_init(struct meter *m)
8889 memset(m, 0, sizeof(struct meter));
8890 rte_meter_trtcm_config(&m->m, &meter_profile_default.profile);
8891 m->profile = &meter_profile_default;
8892 m->color_mask = RTE_COLOR_GREEN;
8894 meter_profile_default.n_users++;
8898 metarray_build(struct rte_swx_pipeline *p)
8902 if (!p->n_metarrays)
8905 p->metarray_runtime = calloc(p->n_metarrays, sizeof(struct metarray_runtime));
8906 CHECK(p->metarray_runtime, ENOMEM);
8908 TAILQ_FOREACH(m, &p->metarrays, node) {
8909 struct metarray_runtime *r = &p->metarray_runtime[m->id];
8912 r->metarray = env_malloc(m->size * sizeof(struct meter),
8913 RTE_CACHE_LINE_SIZE,
8915 CHECK(r->metarray, ENOMEM);
8917 for (i = 0; i < m->size; i++)
8918 meter_init(&r->metarray[i]);
8920 r->size_mask = m->size - 1;
8927 metarray_build_free(struct rte_swx_pipeline *p)
8931 if (!p->metarray_runtime)
8934 for (i = 0; i < p->n_metarrays; i++) {
8935 struct metarray *m = metarray_find_by_id(p, i);
8936 struct metarray_runtime *r = &p->metarray_runtime[i];
8938 env_free(r->metarray, m->size * sizeof(struct meter));
8941 free(p->metarray_runtime);
8942 p->metarray_runtime = NULL;
8946 metarray_free(struct rte_swx_pipeline *p)
8948 metarray_build_free(p);
8952 struct metarray *elem;
8954 elem = TAILQ_FIRST(&p->metarrays);
8958 TAILQ_REMOVE(&p->metarrays, elem, node);
8962 /* Meter profiles. */
8964 struct meter_profile *elem;
8966 elem = TAILQ_FIRST(&p->meter_profiles);
8970 TAILQ_REMOVE(&p->meter_profiles, elem, node);
8979 rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
8981 struct rte_swx_pipeline *pipeline;
8983 /* Check input parameters. */
8986 /* Memory allocation. */
8987 pipeline = calloc(1, sizeof(struct rte_swx_pipeline));
8988 CHECK(pipeline, ENOMEM);
8990 /* Initialization. */
8991 TAILQ_INIT(&pipeline->struct_types);
8992 TAILQ_INIT(&pipeline->port_in_types);
8993 TAILQ_INIT(&pipeline->ports_in);
8994 TAILQ_INIT(&pipeline->port_out_types);
8995 TAILQ_INIT(&pipeline->ports_out);
8996 TAILQ_INIT(&pipeline->extern_types);
8997 TAILQ_INIT(&pipeline->extern_objs);
8998 TAILQ_INIT(&pipeline->extern_funcs);
8999 TAILQ_INIT(&pipeline->headers);
9000 TAILQ_INIT(&pipeline->actions);
9001 TAILQ_INIT(&pipeline->table_types);
9002 TAILQ_INIT(&pipeline->tables);
9003 TAILQ_INIT(&pipeline->selectors);
9004 TAILQ_INIT(&pipeline->learners);
9005 TAILQ_INIT(&pipeline->regarrays);
9006 TAILQ_INIT(&pipeline->meter_profiles);
9007 TAILQ_INIT(&pipeline->metarrays);
9009 pipeline->n_structs = 1; /* Struct 0 is reserved for action_data. */
9010 pipeline->numa_node = numa_node;
9017 rte_swx_pipeline_free(struct rte_swx_pipeline *p)
9026 free(p->instruction_data);
9027 free(p->instructions);
9031 table_state_free(p);
9036 instruction_table_free(p);
9039 extern_func_free(p);
9052 rte_swx_pipeline_instructions_config(struct rte_swx_pipeline *p,
9053 const char **instructions,
9054 uint32_t n_instructions)
9059 err = instruction_config(p, NULL, instructions, n_instructions);
9063 /* Thread instruction pointer reset. */
9064 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9065 struct thread *t = &p->threads[i];
9067 thread_ip_reset(p, t);
9074 pipeline_compile(struct rte_swx_pipeline *p);
9077 rte_swx_pipeline_build(struct rte_swx_pipeline *p)
9082 CHECK(p->build_done == 0, EEXIST);
9084 status = port_in_build(p);
9088 status = port_out_build(p);
9092 status = struct_build(p);
9096 status = extern_obj_build(p);
9100 status = extern_func_build(p);
9104 status = header_build(p);
9108 status = metadata_build(p);
9112 status = instruction_table_build(p);
9116 status = action_build(p);
9120 status = table_build(p);
9124 status = selector_build(p);
9128 status = learner_build(p);
9132 status = table_state_build(p);
9136 status = regarray_build(p);
9140 status = metarray_build(p);
9146 pipeline_compile(p);
9151 metarray_build_free(p);
9152 regarray_build_free(p);
9153 table_state_build_free(p);
9154 learner_build_free(p);
9155 selector_build_free(p);
9156 table_build_free(p);
9157 action_build_free(p);
9158 instruction_table_build_free(p);
9159 metadata_build_free(p);
9160 header_build_free(p);
9161 extern_func_build_free(p);
9162 extern_obj_build_free(p);
9163 port_out_build_free(p);
9164 port_in_build_free(p);
9165 struct_build_free(p);
9171 rte_swx_pipeline_run(struct rte_swx_pipeline *p, uint32_t n_instructions)
9175 for (i = 0; i < n_instructions; i++)
9180 rte_swx_pipeline_flush(struct rte_swx_pipeline *p)
9184 for (i = 0; i < p->n_ports_out; i++) {
9185 struct port_out_runtime *port = &p->out[i];
9188 port->flush(port->obj);
9196 rte_swx_ctl_pipeline_info_get(struct rte_swx_pipeline *p,
9197 struct rte_swx_ctl_pipeline_info *pipeline)
9199 struct action *action;
9200 struct table *table;
9201 uint32_t n_actions = 0, n_tables = 0;
9203 if (!p || !pipeline)
9206 TAILQ_FOREACH(action, &p->actions, node)
9209 TAILQ_FOREACH(table, &p->tables, node)
9212 pipeline->n_ports_in = p->n_ports_in;
9213 pipeline->n_ports_out = p->n_ports_out;
9214 pipeline->n_actions = n_actions;
9215 pipeline->n_tables = n_tables;
9216 pipeline->n_selectors = p->n_selectors;
9217 pipeline->n_learners = p->n_learners;
9218 pipeline->n_regarrays = p->n_regarrays;
9219 pipeline->n_metarrays = p->n_metarrays;
9225 rte_swx_ctl_pipeline_numa_node_get(struct rte_swx_pipeline *p, int *numa_node)
9227 if (!p || !numa_node)
9230 *numa_node = p->numa_node;
9235 rte_swx_ctl_action_info_get(struct rte_swx_pipeline *p,
9237 struct rte_swx_ctl_action_info *action)
9239 struct action *a = NULL;
9241 if (!p || (action_id >= p->n_actions) || !action)
9244 a = action_find_by_id(p, action_id);
9248 strcpy(action->name, a->name);
9249 action->n_args = a->st ? a->st->n_fields : 0;
9254 rte_swx_ctl_action_arg_info_get(struct rte_swx_pipeline *p,
9256 uint32_t action_arg_id,
9257 struct rte_swx_ctl_action_arg_info *action_arg)
9259 struct action *a = NULL;
9260 struct field *arg = NULL;
9262 if (!p || (action_id >= p->n_actions) || !action_arg)
9265 a = action_find_by_id(p, action_id);
9266 if (!a || !a->st || (action_arg_id >= a->st->n_fields))
9269 arg = &a->st->fields[action_arg_id];
9270 strcpy(action_arg->name, arg->name);
9271 action_arg->n_bits = arg->n_bits;
9272 action_arg->is_network_byte_order = a->args_endianness[action_arg_id];
9278 rte_swx_ctl_table_info_get(struct rte_swx_pipeline *p,
9280 struct rte_swx_ctl_table_info *table)
9282 struct table *t = NULL;
9287 t = table_find_by_id(p, table_id);
9291 strcpy(table->name, t->name);
9292 strcpy(table->args, t->args);
9293 table->n_match_fields = t->n_fields;
9294 table->n_actions = t->n_actions;
9295 table->default_action_is_const = t->default_action_is_const;
9296 table->size = t->size;
9301 rte_swx_ctl_table_match_field_info_get(struct rte_swx_pipeline *p,
9303 uint32_t match_field_id,
9304 struct rte_swx_ctl_table_match_field_info *match_field)
9307 struct match_field *f;
9309 if (!p || (table_id >= p->n_tables) || !match_field)
9312 t = table_find_by_id(p, table_id);
9313 if (!t || (match_field_id >= t->n_fields))
9316 f = &t->fields[match_field_id];
9317 match_field->match_type = f->match_type;
9318 match_field->is_header = t->header ? 1 : 0;
9319 match_field->n_bits = f->field->n_bits;
9320 match_field->offset = f->field->offset;
9326 rte_swx_ctl_table_action_info_get(struct rte_swx_pipeline *p,
9328 uint32_t table_action_id,
9329 struct rte_swx_ctl_table_action_info *table_action)
9333 if (!p || (table_id >= p->n_tables) || !table_action)
9336 t = table_find_by_id(p, table_id);
9337 if (!t || (table_action_id >= t->n_actions))
9340 table_action->action_id = t->actions[table_action_id]->id;
9342 table_action->action_is_for_table_entries = t->action_is_for_table_entries[table_action_id];
9343 table_action->action_is_for_default_entry = t->action_is_for_default_entry[table_action_id];
9349 rte_swx_ctl_table_ops_get(struct rte_swx_pipeline *p,
9351 struct rte_swx_table_ops *table_ops,
9356 if (!p || (table_id >= p->n_tables))
9359 t = table_find_by_id(p, table_id);
9365 memcpy(table_ops, &t->type->ops, sizeof(*table_ops));
9375 rte_swx_ctl_selector_info_get(struct rte_swx_pipeline *p,
9376 uint32_t selector_id,
9377 struct rte_swx_ctl_selector_info *selector)
9379 struct selector *s = NULL;
9381 if (!p || !selector)
9384 s = selector_find_by_id(p, selector_id);
9388 strcpy(selector->name, s->name);
9390 selector->n_selector_fields = s->n_selector_fields;
9391 selector->n_groups_max = s->n_groups_max;
9392 selector->n_members_per_group_max = s->n_members_per_group_max;
9398 rte_swx_ctl_selector_group_id_field_info_get(struct rte_swx_pipeline *p,
9399 uint32_t selector_id,
9400 struct rte_swx_ctl_table_match_field_info *field)
9404 if (!p || (selector_id >= p->n_selectors) || !field)
9407 s = selector_find_by_id(p, selector_id);
9411 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
9412 field->is_header = 0;
9413 field->n_bits = s->group_id_field->n_bits;
9414 field->offset = s->group_id_field->offset;
9420 rte_swx_ctl_selector_field_info_get(struct rte_swx_pipeline *p,
9421 uint32_t selector_id,
9422 uint32_t selector_field_id,
9423 struct rte_swx_ctl_table_match_field_info *field)
9428 if (!p || (selector_id >= p->n_selectors) || !field)
9431 s = selector_find_by_id(p, selector_id);
9432 if (!s || (selector_field_id >= s->n_selector_fields))
9435 f = s->selector_fields[selector_field_id];
9436 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
9437 field->is_header = s->selector_header ? 1 : 0;
9438 field->n_bits = f->n_bits;
9439 field->offset = f->offset;
9445 rte_swx_ctl_selector_member_id_field_info_get(struct rte_swx_pipeline *p,
9446 uint32_t selector_id,
9447 struct rte_swx_ctl_table_match_field_info *field)
9451 if (!p || (selector_id >= p->n_selectors) || !field)
9454 s = selector_find_by_id(p, selector_id);
9458 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
9459 field->is_header = 0;
9460 field->n_bits = s->member_id_field->n_bits;
9461 field->offset = s->member_id_field->offset;
9467 rte_swx_ctl_learner_info_get(struct rte_swx_pipeline *p,
9468 uint32_t learner_id,
9469 struct rte_swx_ctl_learner_info *learner)
9471 struct learner *l = NULL;
9476 l = learner_find_by_id(p, learner_id);
9480 strcpy(learner->name, l->name);
9482 learner->n_match_fields = l->n_fields;
9483 learner->n_actions = l->n_actions;
9484 learner->default_action_is_const = l->default_action_is_const;
9485 learner->size = l->size;
9491 rte_swx_ctl_learner_match_field_info_get(struct rte_swx_pipeline *p,
9492 uint32_t learner_id,
9493 uint32_t match_field_id,
9494 struct rte_swx_ctl_table_match_field_info *match_field)
9499 if (!p || (learner_id >= p->n_learners) || !match_field)
9502 l = learner_find_by_id(p, learner_id);
9503 if (!l || (match_field_id >= l->n_fields))
9506 f = l->fields[match_field_id];
9507 match_field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
9508 match_field->is_header = l->header ? 1 : 0;
9509 match_field->n_bits = f->n_bits;
9510 match_field->offset = f->offset;
9516 rte_swx_ctl_learner_action_info_get(struct rte_swx_pipeline *p,
9517 uint32_t learner_id,
9518 uint32_t learner_action_id,
9519 struct rte_swx_ctl_table_action_info *learner_action)
9523 if (!p || (learner_id >= p->n_learners) || !learner_action)
9526 l = learner_find_by_id(p, learner_id);
9527 if (!l || (learner_action_id >= l->n_actions))
9530 learner_action->action_id = l->actions[learner_action_id]->id;
9532 learner_action->action_is_for_table_entries =
9533 l->action_is_for_table_entries[learner_action_id];
9535 learner_action->action_is_for_default_entry =
9536 l->action_is_for_default_entry[learner_action_id];
9542 rte_swx_pipeline_table_state_get(struct rte_swx_pipeline *p,
9543 struct rte_swx_table_state **table_state)
9545 if (!p || !table_state || !p->build_done)
9548 *table_state = p->table_state;
9553 rte_swx_pipeline_table_state_set(struct rte_swx_pipeline *p,
9554 struct rte_swx_table_state *table_state)
9556 if (!p || !table_state || !p->build_done)
9559 p->table_state = table_state;
9564 rte_swx_ctl_pipeline_port_in_stats_read(struct rte_swx_pipeline *p,
9566 struct rte_swx_port_in_stats *stats)
9568 struct port_in *port;
9573 port = port_in_find(p, port_id);
9577 port->type->ops.stats_read(port->obj, stats);
9582 rte_swx_ctl_pipeline_port_out_stats_read(struct rte_swx_pipeline *p,
9584 struct rte_swx_port_out_stats *stats)
9586 struct port_out *port;
9591 port = port_out_find(p, port_id);
9595 port->type->ops.stats_read(port->obj, stats);
9600 rte_swx_ctl_pipeline_table_stats_read(struct rte_swx_pipeline *p,
9601 const char *table_name,
9602 struct rte_swx_table_stats *stats)
9604 struct table *table;
9605 struct table_statistics *table_stats;
9607 if (!p || !table_name || !table_name[0] || !stats || !stats->n_pkts_action)
9610 table = table_find(p, table_name);
9614 table_stats = &p->table_stats[table->id];
9616 memcpy(stats->n_pkts_action,
9617 table_stats->n_pkts_action,
9618 p->n_actions * sizeof(uint64_t));
9620 stats->n_pkts_hit = table_stats->n_pkts_hit[1];
9621 stats->n_pkts_miss = table_stats->n_pkts_hit[0];
9627 rte_swx_ctl_pipeline_selector_stats_read(struct rte_swx_pipeline *p,
9628 const char *selector_name,
9629 struct rte_swx_pipeline_selector_stats *stats)
9633 if (!p || !selector_name || !selector_name[0] || !stats)
9636 s = selector_find(p, selector_name);
9640 stats->n_pkts = p->selector_stats[s->id].n_pkts;
9646 rte_swx_ctl_pipeline_learner_stats_read(struct rte_swx_pipeline *p,
9647 const char *learner_name,
9648 struct rte_swx_learner_stats *stats)
9651 struct learner_statistics *learner_stats;
9653 if (!p || !learner_name || !learner_name[0] || !stats || !stats->n_pkts_action)
9656 l = learner_find(p, learner_name);
9660 learner_stats = &p->learner_stats[l->id];
9662 memcpy(stats->n_pkts_action,
9663 learner_stats->n_pkts_action,
9664 p->n_actions * sizeof(uint64_t));
9666 stats->n_pkts_hit = learner_stats->n_pkts_hit[1];
9667 stats->n_pkts_miss = learner_stats->n_pkts_hit[0];
9669 stats->n_pkts_learn_ok = learner_stats->n_pkts_learn[0];
9670 stats->n_pkts_learn_err = learner_stats->n_pkts_learn[1];
9672 stats->n_pkts_forget = learner_stats->n_pkts_forget;
9678 rte_swx_ctl_regarray_info_get(struct rte_swx_pipeline *p,
9679 uint32_t regarray_id,
9680 struct rte_swx_ctl_regarray_info *regarray)
9684 if (!p || !regarray)
9687 r = regarray_find_by_id(p, regarray_id);
9691 strcpy(regarray->name, r->name);
9692 regarray->size = r->size;
9697 rte_swx_ctl_pipeline_regarray_read(struct rte_swx_pipeline *p,
9698 const char *regarray_name,
9699 uint32_t regarray_index,
9702 struct regarray *regarray;
9703 struct regarray_runtime *r;
9705 if (!p || !regarray_name || !value)
9708 regarray = regarray_find(p, regarray_name);
9709 if (!regarray || (regarray_index >= regarray->size))
9712 r = &p->regarray_runtime[regarray->id];
9713 *value = r->regarray[regarray_index];
9718 rte_swx_ctl_pipeline_regarray_write(struct rte_swx_pipeline *p,
9719 const char *regarray_name,
9720 uint32_t regarray_index,
9723 struct regarray *regarray;
9724 struct regarray_runtime *r;
9726 if (!p || !regarray_name)
9729 regarray = regarray_find(p, regarray_name);
9730 if (!regarray || (regarray_index >= regarray->size))
9733 r = &p->regarray_runtime[regarray->id];
9734 r->regarray[regarray_index] = value;
9739 rte_swx_ctl_metarray_info_get(struct rte_swx_pipeline *p,
9740 uint32_t metarray_id,
9741 struct rte_swx_ctl_metarray_info *metarray)
9745 if (!p || !metarray)
9748 m = metarray_find_by_id(p, metarray_id);
9752 strcpy(metarray->name, m->name);
9753 metarray->size = m->size;
9758 rte_swx_ctl_meter_profile_add(struct rte_swx_pipeline *p,
9760 struct rte_meter_trtcm_params *params)
9762 struct meter_profile *mp;
9766 CHECK_NAME(name, EINVAL);
9767 CHECK(params, EINVAL);
9768 CHECK(!meter_profile_find(p, name), EEXIST);
9770 /* Node allocation. */
9771 mp = calloc(1, sizeof(struct meter_profile));
9774 /* Node initialization. */
9775 strcpy(mp->name, name);
9776 memcpy(&mp->params, params, sizeof(struct rte_meter_trtcm_params));
9777 status = rte_meter_trtcm_profile_config(&mp->profile, params);
9783 /* Node add to tailq. */
9784 TAILQ_INSERT_TAIL(&p->meter_profiles, mp, node);
9790 rte_swx_ctl_meter_profile_delete(struct rte_swx_pipeline *p,
9793 struct meter_profile *mp;
9796 CHECK_NAME(name, EINVAL);
9798 mp = meter_profile_find(p, name);
9800 CHECK(!mp->n_users, EBUSY);
9802 /* Remove node from tailq. */
9803 TAILQ_REMOVE(&p->meter_profiles, mp, node);
9810 rte_swx_ctl_meter_reset(struct rte_swx_pipeline *p,
9811 const char *metarray_name,
9812 uint32_t metarray_index)
9814 struct meter_profile *mp_old;
9815 struct metarray *metarray;
9816 struct metarray_runtime *metarray_runtime;
9820 CHECK_NAME(metarray_name, EINVAL);
9822 metarray = metarray_find(p, metarray_name);
9823 CHECK(metarray, EINVAL);
9824 CHECK(metarray_index < metarray->size, EINVAL);
9826 metarray_runtime = &p->metarray_runtime[metarray->id];
9827 m = &metarray_runtime->metarray[metarray_index];
9828 mp_old = m->profile;
9838 rte_swx_ctl_meter_set(struct rte_swx_pipeline *p,
9839 const char *metarray_name,
9840 uint32_t metarray_index,
9841 const char *profile_name)
9843 struct meter_profile *mp, *mp_old;
9844 struct metarray *metarray;
9845 struct metarray_runtime *metarray_runtime;
9849 CHECK_NAME(metarray_name, EINVAL);
9851 metarray = metarray_find(p, metarray_name);
9852 CHECK(metarray, EINVAL);
9853 CHECK(metarray_index < metarray->size, EINVAL);
9855 mp = meter_profile_find(p, profile_name);
9858 metarray_runtime = &p->metarray_runtime[metarray->id];
9859 m = &metarray_runtime->metarray[metarray_index];
9860 mp_old = m->profile;
9862 memset(m, 0, sizeof(struct meter));
9863 rte_meter_trtcm_config(&m->m, &mp->profile);
9865 m->color_mask = RTE_COLORS;
9874 rte_swx_ctl_meter_stats_read(struct rte_swx_pipeline *p,
9875 const char *metarray_name,
9876 uint32_t metarray_index,
9877 struct rte_swx_ctl_meter_stats *stats)
9879 struct metarray *metarray;
9880 struct metarray_runtime *metarray_runtime;
9884 CHECK_NAME(metarray_name, EINVAL);
9886 metarray = metarray_find(p, metarray_name);
9887 CHECK(metarray, EINVAL);
9888 CHECK(metarray_index < metarray->size, EINVAL);
9890 CHECK(stats, EINVAL);
9892 metarray_runtime = &p->metarray_runtime[metarray->id];
9893 m = &metarray_runtime->metarray[metarray_index];
9895 memcpy(stats->n_pkts, m->n_pkts, sizeof(m->n_pkts));
9896 memcpy(stats->n_bytes, m->n_bytes, sizeof(m->n_bytes));
9902 * Pipeline compilation.
9905 instr_type_to_name(struct instruction *instr)
9907 switch (instr->type) {
9908 case INSTR_RX: return "INSTR_RX";
9910 case INSTR_TX: return "INSTR_TX";
9911 case INSTR_TX_I: return "INSTR_TX_I";
9913 case INSTR_HDR_EXTRACT: return "INSTR_HDR_EXTRACT";
9914 case INSTR_HDR_EXTRACT2: return "INSTR_HDR_EXTRACT2";
9915 case INSTR_HDR_EXTRACT3: return "INSTR_HDR_EXTRACT3";
9916 case INSTR_HDR_EXTRACT4: return "INSTR_HDR_EXTRACT4";
9917 case INSTR_HDR_EXTRACT5: return "INSTR_HDR_EXTRACT5";
9918 case INSTR_HDR_EXTRACT6: return "INSTR_HDR_EXTRACT6";
9919 case INSTR_HDR_EXTRACT7: return "INSTR_HDR_EXTRACT7";
9920 case INSTR_HDR_EXTRACT8: return "INSTR_HDR_EXTRACT8";
9922 case INSTR_HDR_EXTRACT_M: return "INSTR_HDR_EXTRACT_M";
9924 case INSTR_HDR_LOOKAHEAD: return "INSTR_HDR_LOOKAHEAD";
9926 case INSTR_HDR_EMIT: return "INSTR_HDR_EMIT";
9927 case INSTR_HDR_EMIT_TX: return "INSTR_HDR_EMIT_TX";
9928 case INSTR_HDR_EMIT2_TX: return "INSTR_HDR_EMIT2_TX";
9929 case INSTR_HDR_EMIT3_TX: return "INSTR_HDR_EMIT3_TX";
9930 case INSTR_HDR_EMIT4_TX: return "INSTR_HDR_EMIT4_TX";
9931 case INSTR_HDR_EMIT5_TX: return "INSTR_HDR_EMIT5_TX";
9932 case INSTR_HDR_EMIT6_TX: return "INSTR_HDR_EMIT6_TX";
9933 case INSTR_HDR_EMIT7_TX: return "INSTR_HDR_EMIT7_TX";
9934 case INSTR_HDR_EMIT8_TX: return "INSTR_HDR_EMIT8_TX";
9936 case INSTR_HDR_VALIDATE: return "INSTR_HDR_VALIDATE";
9937 case INSTR_HDR_INVALIDATE: return "INSTR_HDR_INVALIDATE";
9939 case INSTR_MOV: return "INSTR_MOV";
9940 case INSTR_MOV_MH: return "INSTR_MOV_MH";
9941 case INSTR_MOV_HM: return "INSTR_MOV_HM";
9942 case INSTR_MOV_HH: return "INSTR_MOV_HH";
9943 case INSTR_MOV_I: return "INSTR_MOV_I";
9945 case INSTR_DMA_HT: return "INSTR_DMA_HT";
9946 case INSTR_DMA_HT2: return "INSTR_DMA_HT2";
9947 case INSTR_DMA_HT3: return "INSTR_DMA_HT3";
9948 case INSTR_DMA_HT4: return "INSTR_DMA_HT4";
9949 case INSTR_DMA_HT5: return "INSTR_DMA_HT5";
9950 case INSTR_DMA_HT6: return "INSTR_DMA_HT6";
9951 case INSTR_DMA_HT7: return "INSTR_DMA_HT7";
9952 case INSTR_DMA_HT8: return "INSTR_DMA_HT8";
9954 case INSTR_ALU_ADD: return "INSTR_ALU_ADD";
9955 case INSTR_ALU_ADD_MH: return "INSTR_ALU_ADD_MH";
9956 case INSTR_ALU_ADD_HM: return "INSTR_ALU_ADD_HM";
9957 case INSTR_ALU_ADD_HH: return "INSTR_ALU_ADD_HH";
9958 case INSTR_ALU_ADD_MI: return "INSTR_ALU_ADD_MI";
9959 case INSTR_ALU_ADD_HI: return "INSTR_ALU_ADD_HI";
9961 case INSTR_ALU_SUB: return "INSTR_ALU_SUB";
9962 case INSTR_ALU_SUB_MH: return "INSTR_ALU_SUB_MH";
9963 case INSTR_ALU_SUB_HM: return "INSTR_ALU_SUB_HM";
9964 case INSTR_ALU_SUB_HH: return "INSTR_ALU_SUB_HH";
9965 case INSTR_ALU_SUB_MI: return "INSTR_ALU_SUB_MI";
9966 case INSTR_ALU_SUB_HI: return "INSTR_ALU_SUB_HI";
9968 case INSTR_ALU_CKADD_FIELD: return "INSTR_ALU_CKADD_FIELD";
9969 case INSTR_ALU_CKADD_STRUCT20: return "INSTR_ALU_CKADD_STRUCT20";
9970 case INSTR_ALU_CKADD_STRUCT: return "INSTR_ALU_CKADD_STRUCT";
9971 case INSTR_ALU_CKSUB_FIELD: return "INSTR_ALU_CKSUB_FIELD";
9973 case INSTR_ALU_AND: return "INSTR_ALU_AND";
9974 case INSTR_ALU_AND_MH: return "INSTR_ALU_AND_MH";
9975 case INSTR_ALU_AND_HM: return "INSTR_ALU_AND_HM";
9976 case INSTR_ALU_AND_HH: return "INSTR_ALU_AND_HH";
9977 case INSTR_ALU_AND_I: return "INSTR_ALU_AND_I";
9979 case INSTR_ALU_OR: return "INSTR_ALU_OR";
9980 case INSTR_ALU_OR_MH: return "INSTR_ALU_OR_MH";
9981 case INSTR_ALU_OR_HM: return "INSTR_ALU_OR_HM";
9982 case INSTR_ALU_OR_HH: return "INSTR_ALU_OR_HH";
9983 case INSTR_ALU_OR_I: return "INSTR_ALU_OR_I";
9985 case INSTR_ALU_XOR: return "INSTR_ALU_XOR";
9986 case INSTR_ALU_XOR_MH: return "INSTR_ALU_XOR_MH";
9987 case INSTR_ALU_XOR_HM: return "INSTR_ALU_XOR_HM";
9988 case INSTR_ALU_XOR_HH: return "INSTR_ALU_XOR_HH";
9989 case INSTR_ALU_XOR_I: return "INSTR_ALU_XOR_I";
9991 case INSTR_ALU_SHL: return "INSTR_ALU_SHL";
9992 case INSTR_ALU_SHL_MH: return "INSTR_ALU_SHL_MH";
9993 case INSTR_ALU_SHL_HM: return "INSTR_ALU_SHL_HM";
9994 case INSTR_ALU_SHL_HH: return "INSTR_ALU_SHL_HH";
9995 case INSTR_ALU_SHL_MI: return "INSTR_ALU_SHL_MI";
9996 case INSTR_ALU_SHL_HI: return "INSTR_ALU_SHL_HI";
9998 case INSTR_ALU_SHR: return "INSTR_ALU_SHR";
9999 case INSTR_ALU_SHR_MH: return "INSTR_ALU_SHR_MH";
10000 case INSTR_ALU_SHR_HM: return "INSTR_ALU_SHR_HM";
10001 case INSTR_ALU_SHR_HH: return "INSTR_ALU_SHR_HH";
10002 case INSTR_ALU_SHR_MI: return "INSTR_ALU_SHR_MI";
10003 case INSTR_ALU_SHR_HI: return "INSTR_ALU_SHR_HI";
10005 case INSTR_REGPREFETCH_RH: return "INSTR_REGPREFETCH_RH";
10006 case INSTR_REGPREFETCH_RM: return "INSTR_REGPREFETCH_RM";
10007 case INSTR_REGPREFETCH_RI: return "INSTR_REGPREFETCH_RI";
10009 case INSTR_REGRD_HRH: return "INSTR_REGRD_HRH";
10010 case INSTR_REGRD_HRM: return "INSTR_REGRD_HRM";
10011 case INSTR_REGRD_HRI: return "INSTR_REGRD_HRI";
10012 case INSTR_REGRD_MRH: return "INSTR_REGRD_MRH";
10013 case INSTR_REGRD_MRM: return "INSTR_REGRD_MRM";
10014 case INSTR_REGRD_MRI: return "INSTR_REGRD_MRI";
10016 case INSTR_REGWR_RHH: return "INSTR_REGWR_RHH";
10017 case INSTR_REGWR_RHM: return "INSTR_REGWR_RHM";
10018 case INSTR_REGWR_RHI: return "INSTR_REGWR_RHI";
10019 case INSTR_REGWR_RMH: return "INSTR_REGWR_RMH";
10020 case INSTR_REGWR_RMM: return "INSTR_REGWR_RMM";
10021 case INSTR_REGWR_RMI: return "INSTR_REGWR_RMI";
10022 case INSTR_REGWR_RIH: return "INSTR_REGWR_RIH";
10023 case INSTR_REGWR_RIM: return "INSTR_REGWR_RIM";
10024 case INSTR_REGWR_RII: return "INSTR_REGWR_RII";
10026 case INSTR_REGADD_RHH: return "INSTR_REGADD_RHH";
10027 case INSTR_REGADD_RHM: return "INSTR_REGADD_RHM";
10028 case INSTR_REGADD_RHI: return "INSTR_REGADD_RHI";
10029 case INSTR_REGADD_RMH: return "INSTR_REGADD_RMH";
10030 case INSTR_REGADD_RMM: return "INSTR_REGADD_RMM";
10031 case INSTR_REGADD_RMI: return "INSTR_REGADD_RMI";
10032 case INSTR_REGADD_RIH: return "INSTR_REGADD_RIH";
10033 case INSTR_REGADD_RIM: return "INSTR_REGADD_RIM";
10034 case INSTR_REGADD_RII: return "INSTR_REGADD_RII";
10036 case INSTR_METPREFETCH_H: return "INSTR_METPREFETCH_H";
10037 case INSTR_METPREFETCH_M: return "INSTR_METPREFETCH_M";
10038 case INSTR_METPREFETCH_I: return "INSTR_METPREFETCH_I";
10040 case INSTR_METER_HHM: return "INSTR_METER_HHM";
10041 case INSTR_METER_HHI: return "INSTR_METER_HHI";
10042 case INSTR_METER_HMM: return "INSTR_METER_HMM";
10043 case INSTR_METER_HMI: return "INSTR_METER_HMI";
10044 case INSTR_METER_MHM: return "INSTR_METER_MHM";
10045 case INSTR_METER_MHI: return "INSTR_METER_MHI";
10046 case INSTR_METER_MMM: return "INSTR_METER_MMM";
10047 case INSTR_METER_MMI: return "INSTR_METER_MMI";
10048 case INSTR_METER_IHM: return "INSTR_METER_IHM";
10049 case INSTR_METER_IHI: return "INSTR_METER_IHI";
10050 case INSTR_METER_IMM: return "INSTR_METER_IMM";
10051 case INSTR_METER_IMI: return "INSTR_METER_IMI";
10053 case INSTR_TABLE: return "INSTR_TABLE";
10054 case INSTR_TABLE_AF: return "INSTR_TABLE_AF";
10055 case INSTR_SELECTOR: return "INSTR_SELECTOR";
10056 case INSTR_LEARNER: return "INSTR_LEARNER";
10057 case INSTR_LEARNER_AF: return "INSTR_LEARNER_AF";
10059 case INSTR_LEARNER_LEARN: return "INSTR_LEARNER_LEARN";
10060 case INSTR_LEARNER_FORGET: return "INSTR_LEARNER_FORGET";
10062 case INSTR_EXTERN_OBJ: return "INSTR_EXTERN_OBJ";
10063 case INSTR_EXTERN_FUNC: return "INSTR_EXTERN_FUNC";
10065 case INSTR_JMP: return "INSTR_JMP";
10066 case INSTR_JMP_VALID: return "INSTR_JMP_VALID";
10067 case INSTR_JMP_INVALID: return "INSTR_JMP_INVALID";
10068 case INSTR_JMP_HIT: return "INSTR_JMP_HIT";
10069 case INSTR_JMP_MISS: return "INSTR_JMP_MISS";
10070 case INSTR_JMP_ACTION_HIT: return "INSTR_JMP_ACTION_HIT";
10071 case INSTR_JMP_ACTION_MISS: return "INSTR_JMP_ACTION_MISS";
10072 case INSTR_JMP_EQ: return "INSTR_JMP_EQ";
10073 case INSTR_JMP_EQ_MH: return "INSTR_JMP_EQ_MH";
10074 case INSTR_JMP_EQ_HM: return "INSTR_JMP_EQ_HM";
10075 case INSTR_JMP_EQ_HH: return "INSTR_JMP_EQ_HH";
10076 case INSTR_JMP_EQ_I: return "INSTR_JMP_EQ_I";
10077 case INSTR_JMP_NEQ: return "INSTR_JMP_NEQ";
10078 case INSTR_JMP_NEQ_MH: return "INSTR_JMP_NEQ_MH";
10079 case INSTR_JMP_NEQ_HM: return "INSTR_JMP_NEQ_HM";
10080 case INSTR_JMP_NEQ_HH: return "INSTR_JMP_NEQ_HH";
10081 case INSTR_JMP_NEQ_I: return "INSTR_JMP_NEQ_I";
10082 case INSTR_JMP_LT: return "INSTR_JMP_LT";
10083 case INSTR_JMP_LT_MH: return "INSTR_JMP_LT_MH";
10084 case INSTR_JMP_LT_HM: return "INSTR_JMP_LT_HM";
10085 case INSTR_JMP_LT_HH: return "INSTR_JMP_LT_HH";
10086 case INSTR_JMP_LT_MI: return "INSTR_JMP_LT_MI";
10087 case INSTR_JMP_LT_HI: return "INSTR_JMP_LT_HI";
10088 case INSTR_JMP_GT: return "INSTR_JMP_GT";
10089 case INSTR_JMP_GT_MH: return "INSTR_JMP_GT_MH";
10090 case INSTR_JMP_GT_HM: return "INSTR_JMP_GT_HM";
10091 case INSTR_JMP_GT_HH: return "INSTR_JMP_GT_HH";
10092 case INSTR_JMP_GT_MI: return "INSTR_JMP_GT_MI";
10093 case INSTR_JMP_GT_HI: return "INSTR_JMP_GT_HI";
10095 case INSTR_RETURN: return "INSTR_RETURN";
10097 default: return "INSTR_UNKNOWN";
10102 (*instruction_export_t)(struct instruction *, FILE *);
10105 instr_io_export(struct instruction *instr, FILE *f)
10107 uint32_t n_io = 0, n_io_imm = 0, n_hdrs = 0, i;
10109 /* n_io, n_io_imm, n_hdrs. */
10110 if (instr->type == INSTR_RX ||
10111 instr->type == INSTR_TX ||
10112 instr->type == INSTR_HDR_EXTRACT_M ||
10113 (instr->type >= INSTR_HDR_EMIT_TX && instr->type <= INSTR_HDR_EMIT8_TX))
10116 if (instr->type == INSTR_TX_I)
10119 if (instr->type >= INSTR_HDR_EXTRACT && instr->type <= INSTR_HDR_EXTRACT8)
10120 n_hdrs = 1 + (instr->type - INSTR_HDR_EXTRACT);
10122 if (instr->type == INSTR_HDR_EXTRACT_M ||
10123 instr->type == INSTR_HDR_LOOKAHEAD ||
10124 instr->type == INSTR_HDR_EMIT)
10127 if (instr->type >= INSTR_HDR_EMIT_TX && instr->type <= INSTR_HDR_EMIT8_TX)
10128 n_hdrs = 1 + (instr->type - INSTR_HDR_EMIT_TX);
10133 "\t\t.type = %s,\n",
10134 instr_type_to_name(instr));
10144 "\t\t\t\t.offset = %u,\n"
10145 "\t\t\t\t.n_bits = %u,\n"
10147 instr->io.io.offset,
10148 instr->io.io.n_bits);
10153 "\t\t\t\t.val = %u,\n"
10157 /* instr.io.hdr. */
10162 /* instr.io.hdr.header_id. */
10164 "\t\t\t.header_id = {");
10166 for (i = 0; i < n_hdrs; i++)
10169 instr->io.hdr.header_id[i]);
10174 /* instr.io.hdr.struct_id. */
10176 "\t\t\t.struct_id = {");
10178 for (i = 0; i < n_hdrs; i++)
10181 instr->io.hdr.struct_id[i]);
10186 /* instr.io.hdr.n_bytes. */
10188 "\t\t\t.n_bytes = {");
10190 for (i = 0; i < n_hdrs; i++)
10193 instr->io.hdr.n_bytes[i]);
10198 /* instr.io.hdr - closing curly brace. */
10203 /* instr.io - closing curly brace. */
10207 /* instr - closing curly brace. */
10213 instr_hdr_validate_export(struct instruction *instr, FILE *f)
10217 "\t\t.type = %s,\n"
10219 "\t\t\t.header_id = %u,\n"
10222 instr_type_to_name(instr),
10223 instr->valid.header_id);
10227 instr_mov_export(struct instruction *instr, FILE *f)
10229 if (instr->type != INSTR_MOV_I)
10232 "\t\t.type = %s,\n"
10235 "\t\t\t\t.struct_id = %u,\n"
10236 "\t\t\t\t.n_bits = %u,\n"
10237 "\t\t\t\t.offset = %u,\n"
10240 "\t\t\t\t.struct_id = %u,\n"
10241 "\t\t\t\t.n_bits = %u,\n"
10242 "\t\t\t\t.offset = %u,\n"
10246 instr_type_to_name(instr),
10247 instr->mov.dst.struct_id,
10248 instr->mov.dst.n_bits,
10249 instr->mov.dst.offset,
10250 instr->mov.src.struct_id,
10251 instr->mov.src.n_bits,
10252 instr->mov.src.offset);
10256 "\t\t.type = %s,\n"
10259 "\t\t\t\t.struct_id = %u,\n"
10260 "\t\t\t\t.n_bits = %u,\n"
10261 "\t\t\t\t.offset = %u,\n"
10263 "\t\t\t.src_val = %" PRIu64 ",\n"
10266 instr_type_to_name(instr),
10267 instr->mov.dst.struct_id,
10268 instr->mov.dst.n_bits,
10269 instr->mov.dst.offset,
10270 instr->mov.src_val);
10274 instr_dma_ht_export(struct instruction *instr, FILE *f)
10276 uint32_t n_dma = 0, i;
10279 n_dma = 1 + (instr->type - INSTR_DMA_HT);
10284 "\t\t.type = %s,\n",
10285 instr_type_to_name(instr));
10291 /* instr.dma.dst. */
10293 "\t\t\t.dst = {\n");
10295 /* instr.dma.dst.header_id. */
10297 "\t\t\t\t.header_id = {");
10299 for (i = 0; i < n_dma; i++)
10302 instr->dma.dst.header_id[i]);
10307 /* instr.dma.dst.struct_id. */
10309 "\t\t\t\t.struct_id = {");
10311 for (i = 0; i < n_dma; i++)
10314 instr->dma.dst.struct_id[i]);
10319 /* instr.dma.dst - closing curly brace. */
10323 /* instr.dma.src. */
10325 "\t\t\t.src = {\n");
10327 /* instr.dma.src.offset. */
10329 "\t\t\t\t.offset = {");
10331 for (i = 0; i < n_dma; i++)
10334 instr->dma.src.offset[i]);
10339 /* instr.dma.src - closing curly brace. */
10343 /* instr.dma.n_bytes. */
10345 "\t\t\t.n_bytes = {");
10347 for (i = 0; i < n_dma; i++)
10350 instr->dma.n_bytes[i]);
10355 /* instr.dma - closing curly brace. */
10359 /* instr - closing curly brace. */
10365 instr_alu_export(struct instruction *instr, FILE *f)
10369 if (instr->type == INSTR_ALU_ADD_MI ||
10370 instr->type == INSTR_ALU_ADD_HI ||
10371 instr->type == INSTR_ALU_SUB_MI ||
10372 instr->type == INSTR_ALU_SUB_HI ||
10373 instr->type == INSTR_ALU_SHL_MI ||
10374 instr->type == INSTR_ALU_SHL_HI ||
10375 instr->type == INSTR_ALU_SHR_MI ||
10376 instr->type == INSTR_ALU_SHR_HI ||
10377 instr->type == INSTR_ALU_AND_I ||
10378 instr->type == INSTR_ALU_OR_I ||
10379 instr->type == INSTR_ALU_XOR_I)
10385 "\t\t.type = %s,\n"
10388 "\t\t\t\t.struct_id = %u,\n"
10389 "\t\t\t\t.n_bits = %u,\n"
10390 "\t\t\t\t.offset = %u,\n"
10393 "\t\t\t\t.struct_id = %u,\n"
10394 "\t\t\t\t.n_bits = %u,\n"
10395 "\t\t\t\t.offset = %u,\n"
10399 instr_type_to_name(instr),
10400 instr->alu.dst.struct_id,
10401 instr->alu.dst.n_bits,
10402 instr->alu.dst.offset,
10403 instr->alu.src.struct_id,
10404 instr->alu.src.n_bits,
10405 instr->alu.src.offset);
10409 "\t\t.type = %s,\n"
10412 "\t\t\t\t.struct_id = %u,\n"
10413 "\t\t\t\t.n_bits = %u,\n"
10414 "\t\t\t\t.offset = %u,\n"
10416 "\t\t\t.src_val = %" PRIu64 ",\n"
10419 instr_type_to_name(instr),
10420 instr->alu.dst.struct_id,
10421 instr->alu.dst.n_bits,
10422 instr->alu.dst.offset,
10423 instr->alu.src_val);
10427 instr_reg_export(struct instruction *instr __rte_unused, FILE *f __rte_unused)
10429 int prefetch = 0, idx_imm = 0, src_imm = 0;
10431 if (instr->type == INSTR_REGPREFETCH_RH ||
10432 instr->type == INSTR_REGPREFETCH_RM ||
10433 instr->type == INSTR_REGPREFETCH_RI)
10436 /* index is the 3rd operand for the regrd instruction and the 2nd
10437 * operand for the regwr and regadd instructions.
10439 if (instr->type == INSTR_REGPREFETCH_RI ||
10440 instr->type == INSTR_REGRD_HRI ||
10441 instr->type == INSTR_REGRD_MRI ||
10442 instr->type == INSTR_REGWR_RIH ||
10443 instr->type == INSTR_REGWR_RIM ||
10444 instr->type == INSTR_REGWR_RII ||
10445 instr->type == INSTR_REGADD_RIH ||
10446 instr->type == INSTR_REGADD_RIM ||
10447 instr->type == INSTR_REGADD_RII)
10450 /* src is the 3rd operand for the regwr and regadd instructions. */
10451 if (instr->type == INSTR_REGWR_RHI ||
10452 instr->type == INSTR_REGWR_RMI ||
10453 instr->type == INSTR_REGWR_RII ||
10454 instr->type == INSTR_REGADD_RHI ||
10455 instr->type == INSTR_REGADD_RMI ||
10456 instr->type == INSTR_REGADD_RII)
10459 /* instr.regarray.regarray_id. */
10462 "\t\t.type = %s,\n"
10463 "\t\t.regarray = {\n"
10464 "\t\t\t.regarray_id = %u,\n",
10465 instr_type_to_name(instr),
10466 instr->regarray.regarray_id);
10468 /* instr.regarray.idx / instr.regarray.idx_val. */
10471 "\t\t\t\t.idx = {\n"
10472 "\t\t\t\t\t.struct_id = %u,\n"
10473 "\t\t\t\t\t.n_bits = %u,\n"
10474 "\t\t\t\t\t.offset = %u,\n"
10476 instr->regarray.idx.struct_id,
10477 instr->regarray.idx.n_bits,
10478 instr->regarray.idx.offset);
10481 "\t\t\t\t.idx_val = %u,\n",
10482 instr->regarray.idx_val);
10484 /* instr.regarray.dstsrc / instr.regarray.dstsrc_val. */
10488 "\t\t\t\t.dstsrc = {\n"
10489 "\t\t\t\t\t.struct_id = %u,\n"
10490 "\t\t\t\t\t.n_bits = %u,\n"
10491 "\t\t\t\t\t.offset = %u,\n"
10493 instr->regarray.dstsrc.struct_id,
10494 instr->regarray.dstsrc.n_bits,
10495 instr->regarray.dstsrc.offset);
10498 "\t\t\t\t.dstsrc_val = %" PRIu64 ",\n",
10499 instr->regarray.dstsrc_val);
10502 /* instr.regarray and instr - closing curly braces. */
10509 instr_meter_export(struct instruction *instr __rte_unused, FILE *f __rte_unused)
10511 int prefetch = 0, idx_imm = 0, color_in_imm = 0;
10513 if (instr->type == INSTR_METPREFETCH_H ||
10514 instr->type == INSTR_METPREFETCH_M ||
10515 instr->type == INSTR_METPREFETCH_I)
10519 if (instr->type == INSTR_METPREFETCH_I ||
10520 instr->type == INSTR_METER_IHM ||
10521 instr->type == INSTR_METER_IHI ||
10522 instr->type == INSTR_METER_IMM ||
10523 instr->type == INSTR_METER_IMI)
10526 /* color_in_imm. */
10527 if (instr->type == INSTR_METER_HHI ||
10528 instr->type == INSTR_METER_HMI ||
10529 instr->type == INSTR_METER_MHI ||
10530 instr->type == INSTR_METER_MMI ||
10531 instr->type == INSTR_METER_IHI ||
10532 instr->type == INSTR_METER_IMI)
10535 /* instr.meter.metarray_id. */
10538 "\t\t.type = %s,\n"
10540 "\t\t\t.metarray_id = %u,\n",
10541 instr_type_to_name(instr),
10542 instr->meter.metarray_id);
10544 /* instr.meter.idx / instr.meter.idx_val. */
10548 "\t\t\t\t.struct_id = %u,\n"
10549 "\t\t\t\t.n_bits = %u,\n"
10550 "\t\t\t\t.offset = %u,\n"
10552 instr->meter.idx.struct_id,
10553 instr->meter.idx.n_bits,
10554 instr->meter.idx.offset);
10557 "\t\t\t.idx_val = %u,\n",
10558 instr->meter.idx_val);
10561 /* instr.meter.length. */
10563 "\t\t\t.length = {\n"
10564 "\t\t\t\t.struct_id = %u,\n"
10565 "\t\t\t\t.n_bits = %u,\n"
10566 "\t\t\t\t.offset = %u,\n"
10568 instr->meter.length.struct_id,
10569 instr->meter.length.n_bits,
10570 instr->meter.length.offset);
10572 /* instr.meter.color_in / instr.meter.color_in_val. */
10575 "\t\t\t.color_in = {\n"
10576 "\t\t\t\t.struct_id = %u,\n"
10577 "\t\t\t\t.n_bits = %u,\n"
10578 "\t\t\t\t.offset = %u,\n"
10580 instr->meter.color_in.struct_id,
10581 instr->meter.color_in.n_bits,
10582 instr->meter.color_in.offset);
10585 "\t\t\t.color_in_val = %u,\n",
10586 (uint32_t)instr->meter.color_in_val);
10588 /* instr.meter.color_out. */
10590 "\t\t\t.color_out = {\n"
10591 "\t\t\t\t.struct_id = %u,\n"
10592 "\t\t\t\t.n_bits = %u,\n"
10593 "\t\t\t\t.offset = %u,\n"
10595 instr->meter.color_out.struct_id,
10596 instr->meter.color_out.n_bits,
10597 instr->meter.color_out.offset);
10600 /* instr.meter and instr - closing curly braces. */
10607 instr_table_export(struct instruction *instr,
10612 "\t\t.type = %s,\n"
10614 "\t\t\t.table_id = %u,\n"
10617 instr_type_to_name(instr),
10618 instr->table.table_id);
10622 instr_learn_export(struct instruction *instr, FILE *f)
10626 "\t\t.type = %s,\n"
10628 "\t\t\t\t.action_id = %u,\n"
10631 instr_type_to_name(instr),
10632 instr->learn.action_id);
10636 instr_forget_export(struct instruction *instr, FILE *f)
10640 "\t\t.type = %s,\n"
10642 instr_type_to_name(instr));
10646 instr_extern_export(struct instruction *instr, FILE *f)
10648 if (instr->type == INSTR_EXTERN_OBJ)
10651 "\t\t.type = %s,\n"
10652 "\t\t.ext_obj = {\n"
10653 "\t\t\t.ext_obj_id = %u,\n"
10654 "\t\t\t.func_id = %u,\n"
10657 instr_type_to_name(instr),
10658 instr->ext_obj.ext_obj_id,
10659 instr->ext_obj.func_id);
10663 "\t\t.type = %s,\n"
10664 "\t\t.ext_func = {\n"
10665 "\t\t\t.ext_func_id = %u,\n"
10668 instr_type_to_name(instr),
10669 instr->ext_func.ext_func_id);
10673 instr_jmp_export(struct instruction *instr, FILE *f __rte_unused)
10677 "\t\t.type = %s,\n"
10679 "\t\t\t.ip = NULL,\n",
10680 instr_type_to_name(instr));
10682 switch (instr->type) {
10683 case INSTR_JMP_VALID:
10684 case INSTR_JMP_INVALID:
10686 "\t\t\t.header_id = %u,\n",
10687 instr->jmp.header_id);
10690 case INSTR_JMP_ACTION_HIT:
10691 case INSTR_JMP_ACTION_MISS:
10693 "\t\t\t.action_id = %u,\n",
10694 instr->jmp.action_id);
10698 case INSTR_JMP_EQ_MH:
10699 case INSTR_JMP_EQ_HM:
10700 case INSTR_JMP_EQ_HH:
10701 case INSTR_JMP_NEQ:
10702 case INSTR_JMP_NEQ_MH:
10703 case INSTR_JMP_NEQ_HM:
10704 case INSTR_JMP_NEQ_HH:
10706 case INSTR_JMP_LT_MH:
10707 case INSTR_JMP_LT_HM:
10708 case INSTR_JMP_LT_HH:
10710 case INSTR_JMP_GT_MH:
10711 case INSTR_JMP_GT_HM:
10712 case INSTR_JMP_GT_HH:
10715 "\t\t\t\t.struct_id = %u,\n"
10716 "\t\t\t\t.n_bits = %u,\n"
10717 "\t\t\t\t.offset = %u,\n"
10720 "\t\t\t\t.struct_id = %u,\n"
10721 "\t\t\t\t.n_bits = %u,\n"
10722 "\t\t\t\t.offset = %u,\n"
10724 instr->jmp.a.struct_id,
10725 instr->jmp.a.n_bits,
10726 instr->jmp.a.offset,
10727 instr->jmp.b.struct_id,
10728 instr->jmp.b.n_bits,
10729 instr->jmp.b.offset);
10732 case INSTR_JMP_EQ_I:
10733 case INSTR_JMP_NEQ_I:
10734 case INSTR_JMP_LT_MI:
10735 case INSTR_JMP_LT_HI:
10736 case INSTR_JMP_GT_MI:
10737 case INSTR_JMP_GT_HI:
10740 "\t\t\t\t.struct_id = %u,\n"
10741 "\t\t\t\t.n_bits = %u,\n"
10742 "\t\t\t\t.offset = %u,\n"
10744 "\t\t\t.b_val = %" PRIu64 ",\n",
10745 instr->jmp.a.struct_id,
10746 instr->jmp.a.n_bits,
10747 instr->jmp.a.offset,
10761 instr_return_export(struct instruction *instr,
10766 "\t\t.type = %s,\n",
10767 instr_type_to_name(instr));
10773 static instruction_export_t export_table[] = {
10774 [INSTR_RX] = instr_io_export,
10776 [INSTR_TX] = instr_io_export,
10777 [INSTR_TX_I] = instr_io_export,
10779 [INSTR_HDR_EXTRACT] = instr_io_export,
10780 [INSTR_HDR_EXTRACT2] = instr_io_export,
10781 [INSTR_HDR_EXTRACT3] = instr_io_export,
10782 [INSTR_HDR_EXTRACT4] = instr_io_export,
10783 [INSTR_HDR_EXTRACT5] = instr_io_export,
10784 [INSTR_HDR_EXTRACT6] = instr_io_export,
10785 [INSTR_HDR_EXTRACT7] = instr_io_export,
10786 [INSTR_HDR_EXTRACT8] = instr_io_export,
10788 [INSTR_HDR_EXTRACT_M] = instr_io_export,
10790 [INSTR_HDR_LOOKAHEAD] = instr_io_export,
10792 [INSTR_HDR_EMIT] = instr_io_export,
10793 [INSTR_HDR_EMIT_TX] = instr_io_export,
10794 [INSTR_HDR_EMIT2_TX] = instr_io_export,
10795 [INSTR_HDR_EMIT3_TX] = instr_io_export,
10796 [INSTR_HDR_EMIT4_TX] = instr_io_export,
10797 [INSTR_HDR_EMIT5_TX] = instr_io_export,
10798 [INSTR_HDR_EMIT6_TX] = instr_io_export,
10799 [INSTR_HDR_EMIT7_TX] = instr_io_export,
10800 [INSTR_HDR_EMIT8_TX] = instr_io_export,
10802 [INSTR_HDR_VALIDATE] = instr_hdr_validate_export,
10803 [INSTR_HDR_INVALIDATE] = instr_hdr_validate_export,
10805 [INSTR_MOV] = instr_mov_export,
10806 [INSTR_MOV_MH] = instr_mov_export,
10807 [INSTR_MOV_HM] = instr_mov_export,
10808 [INSTR_MOV_HH] = instr_mov_export,
10809 [INSTR_MOV_I] = instr_mov_export,
10811 [INSTR_DMA_HT] = instr_dma_ht_export,
10812 [INSTR_DMA_HT2] = instr_dma_ht_export,
10813 [INSTR_DMA_HT3] = instr_dma_ht_export,
10814 [INSTR_DMA_HT4] = instr_dma_ht_export,
10815 [INSTR_DMA_HT5] = instr_dma_ht_export,
10816 [INSTR_DMA_HT6] = instr_dma_ht_export,
10817 [INSTR_DMA_HT7] = instr_dma_ht_export,
10818 [INSTR_DMA_HT8] = instr_dma_ht_export,
10820 [INSTR_ALU_ADD] = instr_alu_export,
10821 [INSTR_ALU_ADD_MH] = instr_alu_export,
10822 [INSTR_ALU_ADD_HM] = instr_alu_export,
10823 [INSTR_ALU_ADD_HH] = instr_alu_export,
10824 [INSTR_ALU_ADD_MI] = instr_alu_export,
10825 [INSTR_ALU_ADD_HI] = instr_alu_export,
10827 [INSTR_ALU_SUB] = instr_alu_export,
10828 [INSTR_ALU_SUB_MH] = instr_alu_export,
10829 [INSTR_ALU_SUB_HM] = instr_alu_export,
10830 [INSTR_ALU_SUB_HH] = instr_alu_export,
10831 [INSTR_ALU_SUB_MI] = instr_alu_export,
10832 [INSTR_ALU_SUB_HI] = instr_alu_export,
10834 [INSTR_ALU_CKADD_FIELD] = instr_alu_export,
10835 [INSTR_ALU_CKADD_STRUCT] = instr_alu_export,
10836 [INSTR_ALU_CKADD_STRUCT20] = instr_alu_export,
10837 [INSTR_ALU_CKSUB_FIELD] = instr_alu_export,
10839 [INSTR_ALU_AND] = instr_alu_export,
10840 [INSTR_ALU_AND_MH] = instr_alu_export,
10841 [INSTR_ALU_AND_HM] = instr_alu_export,
10842 [INSTR_ALU_AND_HH] = instr_alu_export,
10843 [INSTR_ALU_AND_I] = instr_alu_export,
10845 [INSTR_ALU_OR] = instr_alu_export,
10846 [INSTR_ALU_OR_MH] = instr_alu_export,
10847 [INSTR_ALU_OR_HM] = instr_alu_export,
10848 [INSTR_ALU_OR_HH] = instr_alu_export,
10849 [INSTR_ALU_OR_I] = instr_alu_export,
10851 [INSTR_ALU_XOR] = instr_alu_export,
10852 [INSTR_ALU_XOR_MH] = instr_alu_export,
10853 [INSTR_ALU_XOR_HM] = instr_alu_export,
10854 [INSTR_ALU_XOR_HH] = instr_alu_export,
10855 [INSTR_ALU_XOR_I] = instr_alu_export,
10857 [INSTR_ALU_SHL] = instr_alu_export,
10858 [INSTR_ALU_SHL_MH] = instr_alu_export,
10859 [INSTR_ALU_SHL_HM] = instr_alu_export,
10860 [INSTR_ALU_SHL_HH] = instr_alu_export,
10861 [INSTR_ALU_SHL_MI] = instr_alu_export,
10862 [INSTR_ALU_SHL_HI] = instr_alu_export,
10864 [INSTR_ALU_SHR] = instr_alu_export,
10865 [INSTR_ALU_SHR_MH] = instr_alu_export,
10866 [INSTR_ALU_SHR_HM] = instr_alu_export,
10867 [INSTR_ALU_SHR_HH] = instr_alu_export,
10868 [INSTR_ALU_SHR_MI] = instr_alu_export,
10869 [INSTR_ALU_SHR_HI] = instr_alu_export,
10871 [INSTR_REGPREFETCH_RH] = instr_reg_export,
10872 [INSTR_REGPREFETCH_RM] = instr_reg_export,
10873 [INSTR_REGPREFETCH_RI] = instr_reg_export,
10875 [INSTR_REGRD_HRH] = instr_reg_export,
10876 [INSTR_REGRD_HRM] = instr_reg_export,
10877 [INSTR_REGRD_MRH] = instr_reg_export,
10878 [INSTR_REGRD_MRM] = instr_reg_export,
10879 [INSTR_REGRD_HRI] = instr_reg_export,
10880 [INSTR_REGRD_MRI] = instr_reg_export,
10882 [INSTR_REGWR_RHH] = instr_reg_export,
10883 [INSTR_REGWR_RHM] = instr_reg_export,
10884 [INSTR_REGWR_RMH] = instr_reg_export,
10885 [INSTR_REGWR_RMM] = instr_reg_export,
10886 [INSTR_REGWR_RHI] = instr_reg_export,
10887 [INSTR_REGWR_RMI] = instr_reg_export,
10888 [INSTR_REGWR_RIH] = instr_reg_export,
10889 [INSTR_REGWR_RIM] = instr_reg_export,
10890 [INSTR_REGWR_RII] = instr_reg_export,
10892 [INSTR_REGADD_RHH] = instr_reg_export,
10893 [INSTR_REGADD_RHM] = instr_reg_export,
10894 [INSTR_REGADD_RMH] = instr_reg_export,
10895 [INSTR_REGADD_RMM] = instr_reg_export,
10896 [INSTR_REGADD_RHI] = instr_reg_export,
10897 [INSTR_REGADD_RMI] = instr_reg_export,
10898 [INSTR_REGADD_RIH] = instr_reg_export,
10899 [INSTR_REGADD_RIM] = instr_reg_export,
10900 [INSTR_REGADD_RII] = instr_reg_export,
10902 [INSTR_METPREFETCH_H] = instr_meter_export,
10903 [INSTR_METPREFETCH_M] = instr_meter_export,
10904 [INSTR_METPREFETCH_I] = instr_meter_export,
10906 [INSTR_METER_HHM] = instr_meter_export,
10907 [INSTR_METER_HHI] = instr_meter_export,
10908 [INSTR_METER_HMM] = instr_meter_export,
10909 [INSTR_METER_HMI] = instr_meter_export,
10910 [INSTR_METER_MHM] = instr_meter_export,
10911 [INSTR_METER_MHI] = instr_meter_export,
10912 [INSTR_METER_MMM] = instr_meter_export,
10913 [INSTR_METER_MMI] = instr_meter_export,
10914 [INSTR_METER_IHM] = instr_meter_export,
10915 [INSTR_METER_IHI] = instr_meter_export,
10916 [INSTR_METER_IMM] = instr_meter_export,
10917 [INSTR_METER_IMI] = instr_meter_export,
10919 [INSTR_TABLE] = instr_table_export,
10920 [INSTR_TABLE_AF] = instr_table_export,
10921 [INSTR_SELECTOR] = instr_table_export,
10922 [INSTR_LEARNER] = instr_table_export,
10923 [INSTR_LEARNER_AF] = instr_table_export,
10925 [INSTR_LEARNER_LEARN] = instr_learn_export,
10926 [INSTR_LEARNER_FORGET] = instr_forget_export,
10928 [INSTR_EXTERN_OBJ] = instr_extern_export,
10929 [INSTR_EXTERN_FUNC] = instr_extern_export,
10931 [INSTR_JMP] = instr_jmp_export,
10932 [INSTR_JMP_VALID] = instr_jmp_export,
10933 [INSTR_JMP_INVALID] = instr_jmp_export,
10934 [INSTR_JMP_HIT] = instr_jmp_export,
10935 [INSTR_JMP_MISS] = instr_jmp_export,
10936 [INSTR_JMP_ACTION_HIT] = instr_jmp_export,
10937 [INSTR_JMP_ACTION_MISS] = instr_jmp_export,
10939 [INSTR_JMP_EQ] = instr_jmp_export,
10940 [INSTR_JMP_EQ_MH] = instr_jmp_export,
10941 [INSTR_JMP_EQ_HM] = instr_jmp_export,
10942 [INSTR_JMP_EQ_HH] = instr_jmp_export,
10943 [INSTR_JMP_EQ_I] = instr_jmp_export,
10945 [INSTR_JMP_NEQ] = instr_jmp_export,
10946 [INSTR_JMP_NEQ_MH] = instr_jmp_export,
10947 [INSTR_JMP_NEQ_HM] = instr_jmp_export,
10948 [INSTR_JMP_NEQ_HH] = instr_jmp_export,
10949 [INSTR_JMP_NEQ_I] = instr_jmp_export,
10951 [INSTR_JMP_LT] = instr_jmp_export,
10952 [INSTR_JMP_LT_MH] = instr_jmp_export,
10953 [INSTR_JMP_LT_HM] = instr_jmp_export,
10954 [INSTR_JMP_LT_HH] = instr_jmp_export,
10955 [INSTR_JMP_LT_MI] = instr_jmp_export,
10956 [INSTR_JMP_LT_HI] = instr_jmp_export,
10958 [INSTR_JMP_GT] = instr_jmp_export,
10959 [INSTR_JMP_GT_MH] = instr_jmp_export,
10960 [INSTR_JMP_GT_HM] = instr_jmp_export,
10961 [INSTR_JMP_GT_HH] = instr_jmp_export,
10962 [INSTR_JMP_GT_MI] = instr_jmp_export,
10963 [INSTR_JMP_GT_HI] = instr_jmp_export,
10965 [INSTR_RETURN] = instr_return_export,
10969 action_data_codegen(struct action *a, FILE *f)
10974 "static const struct instruction action_%s_instructions[] = {\n",
10977 for (i = 0; i < a->n_instructions; i++) {
10978 struct instruction *instr = &a->instructions[i];
10979 instruction_export_t func = export_table[instr->type];
10984 fprintf(f, "};\n");
10987 static const char *
10988 instr_type_to_func(struct instruction *instr)
10990 switch (instr->type) {
10991 case INSTR_RX: return NULL;
10993 case INSTR_TX: return "__instr_tx_exec";
10994 case INSTR_TX_I: return "__instr_tx_i_exec";
10996 case INSTR_HDR_EXTRACT: return "__instr_hdr_extract_exec";
10997 case INSTR_HDR_EXTRACT2: return "__instr_hdr_extract2_exec";
10998 case INSTR_HDR_EXTRACT3: return "__instr_hdr_extract3_exec";
10999 case INSTR_HDR_EXTRACT4: return "__instr_hdr_extract4_exec";
11000 case INSTR_HDR_EXTRACT5: return "__instr_hdr_extract5_exec";
11001 case INSTR_HDR_EXTRACT6: return "__instr_hdr_extract6_exec";
11002 case INSTR_HDR_EXTRACT7: return "__instr_hdr_extract7_exec";
11003 case INSTR_HDR_EXTRACT8: return "__instr_hdr_extract8_exec";
11005 case INSTR_HDR_EXTRACT_M: return "__instr_hdr_extract_m_exec";
11007 case INSTR_HDR_LOOKAHEAD: return "__instr_hdr_lookahead_exec";
11009 case INSTR_HDR_EMIT: return "__instr_hdr_emit_exec";
11010 case INSTR_HDR_EMIT_TX: return "__instr_hdr_emit_tx_exec";
11011 case INSTR_HDR_EMIT2_TX: return "__instr_hdr_emit2_tx_exec";
11012 case INSTR_HDR_EMIT3_TX: return "__instr_hdr_emit3_tx_exec";
11013 case INSTR_HDR_EMIT4_TX: return "__instr_hdr_emit4_tx_exec";
11014 case INSTR_HDR_EMIT5_TX: return "__instr_hdr_emit5_tx_exec";
11015 case INSTR_HDR_EMIT6_TX: return "__instr_hdr_emit6_tx_exec";
11016 case INSTR_HDR_EMIT7_TX: return "__instr_hdr_emit7_tx_exec";
11017 case INSTR_HDR_EMIT8_TX: return "__instr_hdr_emit8_tx_exec";
11019 case INSTR_HDR_VALIDATE: return "__instr_hdr_validate_exec";
11020 case INSTR_HDR_INVALIDATE: return "__instr_hdr_invalidate_exec";
11022 case INSTR_MOV: return "__instr_mov_exec";
11023 case INSTR_MOV_MH: return "__instr_mov_mh_exec";
11024 case INSTR_MOV_HM: return "__instr_mov_hm_exec";
11025 case INSTR_MOV_HH: return "__instr_mov_hh_exec";
11026 case INSTR_MOV_I: return "__instr_mov_i_exec";
11028 case INSTR_DMA_HT: return "__instr_dma_ht_exec";
11029 case INSTR_DMA_HT2: return "__instr_dma_ht2_exec";
11030 case INSTR_DMA_HT3: return "__instr_dma_ht3_exec";
11031 case INSTR_DMA_HT4: return "__instr_dma_ht4_exec";
11032 case INSTR_DMA_HT5: return "__instr_dma_ht5_exec";
11033 case INSTR_DMA_HT6: return "__instr_dma_ht6_exec";
11034 case INSTR_DMA_HT7: return "__instr_dma_ht7_exec";
11035 case INSTR_DMA_HT8: return "__instr_dma_ht8_exec";
11037 case INSTR_ALU_ADD: return "__instr_alu_add_exec";
11038 case INSTR_ALU_ADD_MH: return "__instr_alu_add_mh_exec";
11039 case INSTR_ALU_ADD_HM: return "__instr_alu_add_hm_exec";
11040 case INSTR_ALU_ADD_HH: return "__instr_alu_add_hh_exec";
11041 case INSTR_ALU_ADD_MI: return "__instr_alu_add_mi_exec";
11042 case INSTR_ALU_ADD_HI: return "__instr_alu_add_hi_exec";
11044 case INSTR_ALU_SUB: return "__instr_alu_sub_exec";
11045 case INSTR_ALU_SUB_MH: return "__instr_alu_sub_mh_exec";
11046 case INSTR_ALU_SUB_HM: return "__instr_alu_sub_hm_exec";
11047 case INSTR_ALU_SUB_HH: return "__instr_alu_sub_hh_exec";
11048 case INSTR_ALU_SUB_MI: return "__instr_alu_sub_mi_exec";
11049 case INSTR_ALU_SUB_HI: return "__instr_alu_sub_hi_exec";
11051 case INSTR_ALU_CKADD_FIELD: return "__instr_alu_ckadd_field_exec";
11052 case INSTR_ALU_CKADD_STRUCT20: return "__instr_alu_ckadd_struct20_exec";
11053 case INSTR_ALU_CKADD_STRUCT: return "__instr_alu_ckadd_struct_exec";
11054 case INSTR_ALU_CKSUB_FIELD: return "__instr_alu_cksub_field_exec";
11056 case INSTR_ALU_AND: return "__instr_alu_and_exec";
11057 case INSTR_ALU_AND_MH: return "__instr_alu_and_mh_exec";
11058 case INSTR_ALU_AND_HM: return "__instr_alu_and_hm_exec";
11059 case INSTR_ALU_AND_HH: return "__instr_alu_and_hh_exec";
11060 case INSTR_ALU_AND_I: return "__instr_alu_and_i_exec";
11062 case INSTR_ALU_OR: return "__instr_alu_or_exec";
11063 case INSTR_ALU_OR_MH: return "__instr_alu_or_mh_exec";
11064 case INSTR_ALU_OR_HM: return "__instr_alu_or_hm_exec";
11065 case INSTR_ALU_OR_HH: return "__instr_alu_or_hh_exec";
11066 case INSTR_ALU_OR_I: return "__instr_alu_or_i_exec";
11068 case INSTR_ALU_XOR: return "__instr_alu_xor_exec";
11069 case INSTR_ALU_XOR_MH: return "__instr_alu_xor_mh_exec";
11070 case INSTR_ALU_XOR_HM: return "__instr_alu_xor_hm_exec";
11071 case INSTR_ALU_XOR_HH: return "__instr_alu_xor_hh_exec";
11072 case INSTR_ALU_XOR_I: return "__instr_alu_xor_i_exec";
11074 case INSTR_ALU_SHL: return "__instr_alu_shl_exec";
11075 case INSTR_ALU_SHL_MH: return "__instr_alu_shl_mh_exec";
11076 case INSTR_ALU_SHL_HM: return "__instr_alu_shl_hm_exec";
11077 case INSTR_ALU_SHL_HH: return "__instr_alu_shl_hh_exec";
11078 case INSTR_ALU_SHL_MI: return "__instr_alu_shl_mi_exec";
11079 case INSTR_ALU_SHL_HI: return "__instr_alu_shl_hi_exec";
11081 case INSTR_ALU_SHR: return "__instr_alu_shr_exec";
11082 case INSTR_ALU_SHR_MH: return "__instr_alu_shr_mh_exec";
11083 case INSTR_ALU_SHR_HM: return "__instr_alu_shr_hm_exec";
11084 case INSTR_ALU_SHR_HH: return "__instr_alu_shr_hh_exec";
11085 case INSTR_ALU_SHR_MI: return "__instr_alu_shr_mi_exec";
11086 case INSTR_ALU_SHR_HI: return "__instr_alu_shr_hi_exec";
11088 case INSTR_REGPREFETCH_RH: return "__instr_regprefetch_rh_exec";
11089 case INSTR_REGPREFETCH_RM: return "__instr_regprefetch_rm_exec";
11090 case INSTR_REGPREFETCH_RI: return "__instr_regprefetch_ri_exec";
11092 case INSTR_REGRD_HRH: return "__instr_regrd_hrh_exec";
11093 case INSTR_REGRD_HRM: return "__instr_regrd_hrm_exec";
11094 case INSTR_REGRD_HRI: return "__instr_regrd_hri_exec";
11095 case INSTR_REGRD_MRH: return "__instr_regrd_mrh_exec";
11096 case INSTR_REGRD_MRM: return "__instr_regrd_mrm_exec";
11097 case INSTR_REGRD_MRI: return "__instr_regrd_mri_exec";
11099 case INSTR_REGWR_RHH: return "__instr_regwr_rhh_exec";
11100 case INSTR_REGWR_RHM: return "__instr_regwr_rhm_exec";
11101 case INSTR_REGWR_RHI: return "__instr_regwr_rhi_exec";
11102 case INSTR_REGWR_RMH: return "__instr_regwr_rmh_exec";
11103 case INSTR_REGWR_RMM: return "__instr_regwr_rmm_exec";
11104 case INSTR_REGWR_RMI: return "__instr_regwr_rmi_exec";
11105 case INSTR_REGWR_RIH: return "__instr_regwr_rih_exec";
11106 case INSTR_REGWR_RIM: return "__instr_regwr_rim_exec";
11107 case INSTR_REGWR_RII: return "__instr_regwr_rii_exec";
11109 case INSTR_REGADD_RHH: return "__instr_regadd_rhh_exec";
11110 case INSTR_REGADD_RHM: return "__instr_regadd_rhm_exec";
11111 case INSTR_REGADD_RHI: return "__instr_regadd_rhi_exec";
11112 case INSTR_REGADD_RMH: return "__instr_regadd_rmh_exec";
11113 case INSTR_REGADD_RMM: return "__instr_regadd_rmm_exec";
11114 case INSTR_REGADD_RMI: return "__instr_regadd_rmi_exec";
11115 case INSTR_REGADD_RIH: return "__instr_regadd_rih_exec";
11116 case INSTR_REGADD_RIM: return "__instr_regadd_rim_exec";
11117 case INSTR_REGADD_RII: return "__instr_regadd_rii_exec";
11119 case INSTR_METPREFETCH_H: return "__instr_metprefetch_h_exec";
11120 case INSTR_METPREFETCH_M: return "__instr_metprefetch_m_exec";
11121 case INSTR_METPREFETCH_I: return "__instr_metprefetch_i_exec";
11123 case INSTR_METER_HHM: return "__instr_meter_hhm_exec";
11124 case INSTR_METER_HHI: return "__instr_meter_hhi_exec";
11125 case INSTR_METER_HMM: return "__instr_meter_hmm_exec";
11126 case INSTR_METER_HMI: return "__instr_meter_hmi_exec";
11127 case INSTR_METER_MHM: return "__instr_meter_mhm_exec";
11128 case INSTR_METER_MHI: return "__instr_meter_mhi_exec";
11129 case INSTR_METER_MMM: return "__instr_meter_mmm_exec";
11130 case INSTR_METER_MMI: return "__instr_meter_mmi_exec";
11131 case INSTR_METER_IHM: return "__instr_meter_ihm_exec";
11132 case INSTR_METER_IHI: return "__instr_meter_ihi_exec";
11133 case INSTR_METER_IMM: return "__instr_meter_imm_exec";
11134 case INSTR_METER_IMI: return "__instr_meter_imi_exec";
11136 case INSTR_TABLE: return NULL;
11137 case INSTR_TABLE_AF: return NULL;
11138 case INSTR_SELECTOR: return NULL;
11139 case INSTR_LEARNER: return NULL;
11140 case INSTR_LEARNER_AF: return NULL;
11142 case INSTR_LEARNER_LEARN: return "__instr_learn_exec";
11143 case INSTR_LEARNER_FORGET: return "__instr_forget_exec";
11145 case INSTR_EXTERN_OBJ: return NULL;
11146 case INSTR_EXTERN_FUNC: return NULL;
11148 case INSTR_JMP: return NULL;
11149 case INSTR_JMP_VALID: return NULL;
11150 case INSTR_JMP_INVALID: return NULL;
11151 case INSTR_JMP_HIT: return NULL;
11152 case INSTR_JMP_MISS: return NULL;
11153 case INSTR_JMP_ACTION_HIT: return NULL;
11154 case INSTR_JMP_ACTION_MISS: return NULL;
11155 case INSTR_JMP_EQ: return NULL;
11156 case INSTR_JMP_EQ_MH: return NULL;
11157 case INSTR_JMP_EQ_HM: return NULL;
11158 case INSTR_JMP_EQ_HH: return NULL;
11159 case INSTR_JMP_EQ_I: return NULL;
11160 case INSTR_JMP_NEQ: return NULL;
11161 case INSTR_JMP_NEQ_MH: return NULL;
11162 case INSTR_JMP_NEQ_HM: return NULL;
11163 case INSTR_JMP_NEQ_HH: return NULL;
11164 case INSTR_JMP_NEQ_I: return NULL;
11165 case INSTR_JMP_LT: return NULL;
11166 case INSTR_JMP_LT_MH: return NULL;
11167 case INSTR_JMP_LT_HM: return NULL;
11168 case INSTR_JMP_LT_HH: return NULL;
11169 case INSTR_JMP_LT_MI: return NULL;
11170 case INSTR_JMP_LT_HI: return NULL;
11171 case INSTR_JMP_GT: return NULL;
11172 case INSTR_JMP_GT_MH: return NULL;
11173 case INSTR_JMP_GT_HM: return NULL;
11174 case INSTR_JMP_GT_HH: return NULL;
11175 case INSTR_JMP_GT_MI: return NULL;
11176 case INSTR_JMP_GT_HI: return NULL;
11178 case INSTR_RETURN: return NULL;
11180 default: return NULL;
11185 action_instr_does_tx_codegen(struct action *a,
11186 uint32_t instr_pos,
11187 struct instruction *instr,
11191 "%s(p, t, &action_%s_instructions[%u]);\n"
11192 "\tthread_ip_reset(p, t);\n"
11193 "\tinstr_rx_exec(p);\n"
11195 instr_type_to_func(instr),
11201 action_instr_extern_obj_codegen(struct action *a,
11202 uint32_t instr_pos,
11206 "while (!__instr_extern_obj_exec(p, t, &action_%s_instructions[%u]));\n",
11212 action_instr_extern_func_codegen(struct action *a,
11213 uint32_t instr_pos,
11217 "while (!__instr_extern_func_exec(p, t, &action_%s_instructions[%u]));\n",
11223 action_instr_jmp_codegen(struct action *a,
11224 uint32_t instr_pos,
11225 struct instruction *instr,
11226 struct instruction_data *data,
11229 switch (instr->type) {
11236 case INSTR_JMP_VALID:
11238 "if (HEADER_VALID(t, action_%s_instructions[%u].jmp.header_id))\n"
11245 case INSTR_JMP_INVALID:
11247 "if (!HEADER_VALID(t, action_%s_instructions[%u].jmp.header_id))\n"
11254 case INSTR_JMP_HIT:
11261 case INSTR_JMP_MISS:
11268 case INSTR_JMP_ACTION_HIT:
11270 "if (t->action_id == action_%s_instructions[%u].jmp.action_id)\n"
11277 case INSTR_JMP_ACTION_MISS:
11279 "if (t->action_id != action_%s_instructions[%u].jmp.action_id)\n"
11288 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) == "
11289 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
11298 case INSTR_JMP_EQ_MH:
11300 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) == "
11301 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
11310 case INSTR_JMP_EQ_HM:
11312 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) == "
11313 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
11322 case INSTR_JMP_EQ_HH:
11324 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) == "
11325 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
11334 case INSTR_JMP_EQ_I:
11336 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) == "
11337 "action_%s_instructions[%u].jmp.b_val)\n"
11346 case INSTR_JMP_NEQ:
11348 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) != "
11349 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
11358 case INSTR_JMP_NEQ_MH:
11360 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) != "
11361 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
11370 case INSTR_JMP_NEQ_HM:
11372 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) != "
11373 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
11382 case INSTR_JMP_NEQ_HH:
11384 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) != "
11385 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
11394 case INSTR_JMP_NEQ_I:
11396 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) != "
11397 "action_%s_instructions[%u].jmp.b_val)\n"
11408 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) < "
11409 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
11418 case INSTR_JMP_LT_MH:
11420 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) < "
11421 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
11430 case INSTR_JMP_LT_HM:
11432 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) < "
11433 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
11442 case INSTR_JMP_LT_HH:
11444 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) < "
11445 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
11454 case INSTR_JMP_LT_MI:
11456 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) < "
11457 "action_%s_instructions[%u].jmp.b_val)\n"
11466 case INSTR_JMP_LT_HI:
11468 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) < "
11469 "action_%s_instructions[%u].jmp.b_val)\n"
11480 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) > "
11481 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
11490 case INSTR_JMP_GT_MH:
11492 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) > "
11493 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
11502 case INSTR_JMP_GT_HM:
11504 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) > "
11505 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
11514 case INSTR_JMP_GT_HH:
11516 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) > "
11517 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
11526 case INSTR_JMP_GT_MI:
11528 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) > "
11529 "action_%s_instructions[%u].jmp.b_val)\n"
11538 case INSTR_JMP_GT_HI:
11540 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) > "
11541 "action_%s_instructions[%u].jmp.b_val)\n"
11556 action_instr_return_codegen(FILE *f)
11563 action_instr_codegen(struct action *a, FILE *f)
11569 "action_%s_run(struct rte_swx_pipeline *p)\n"
11571 "\tstruct thread *t = &p->threads[p->thread_id];\n"
11575 for (i = 0; i < a->n_instructions; i++) {
11576 struct instruction *instr = &a->instructions[i];
11577 struct instruction_data *data = &a->instruction_data[i];
11579 /* Label, if present. */
11580 if (data->label[0])
11581 fprintf(f, "\n%s : ", data->label);
11583 fprintf(f, "\n\t");
11585 /* TX instruction type. */
11586 if (instruction_does_tx(instr)) {
11587 action_instr_does_tx_codegen(a, i, instr, f);
11591 /* Extern object/function instruction type. */
11592 if (instr->type == INSTR_EXTERN_OBJ) {
11593 action_instr_extern_obj_codegen(a, i, f);
11597 if (instr->type == INSTR_EXTERN_FUNC) {
11598 action_instr_extern_func_codegen(a, i, f);
11602 /* Jump instruction type. */
11603 if (instruction_is_jmp(instr)) {
11604 action_instr_jmp_codegen(a, i, instr, data, f);
11608 /* Return instruction type. */
11609 if (instr->type == INSTR_RETURN) {
11610 action_instr_return_codegen(f);
11614 /* Any other instruction type. */
11616 "%s(p, t, &action_%s_instructions[%u]);\n",
11617 instr_type_to_func(instr),
11622 fprintf(f, "}\n\n");
11625 struct instruction_group {
11626 TAILQ_ENTRY(instruction_group) node;
11630 uint32_t first_instr_id;
11632 uint32_t last_instr_id;
11637 TAILQ_HEAD(instruction_group_list, instruction_group);
11639 static struct instruction_group *
11640 instruction_group_list_group_find(struct instruction_group_list *igl, uint32_t instruction_id)
11642 struct instruction_group *g;
11644 TAILQ_FOREACH(g, igl, node)
11645 if ((g->first_instr_id <= instruction_id) && (instruction_id <= g->last_instr_id))
11652 instruction_group_list_free(struct instruction_group_list *igl)
11658 struct instruction_group *g;
11660 g = TAILQ_FIRST(igl);
11664 TAILQ_REMOVE(igl, g, node);
11671 static struct instruction_group_list *
11672 instruction_group_list_create(struct rte_swx_pipeline *p)
11674 struct instruction_group_list *igl = NULL;
11675 struct instruction_group *g = NULL;
11676 uint32_t n_groups = 0, i;
11678 if (!p || !p->instructions || !p->instruction_data || !p->n_instructions)
11682 igl = calloc(1, sizeof(struct instruction_group_list));
11688 /* Allocate the first group. */
11689 g = calloc(1, sizeof(struct instruction_group));
11693 /* Iteration 1: Separate the instructions into groups based on the thread yield
11694 * instructions. Do not worry about the jump instructions at this point.
11696 for (i = 0; i < p->n_instructions; i++) {
11697 struct instruction *instr = &p->instructions[i];
11699 /* Check for thread yield instructions. */
11700 if (!instruction_does_thread_yield(instr))
11703 /* If the current group contains at least one instruction, then finalize it (with
11704 * the previous instruction), add it to the list and allocate a new group (that
11705 * starts with the current instruction).
11707 if (i - g->first_instr_id) {
11708 /* Finalize the group. */
11709 g->last_instr_id = i - 1;
11711 /* Add the group to the list. Advance the number of groups. */
11712 TAILQ_INSERT_TAIL(igl, g, node);
11715 /* Allocate a new group. */
11716 g = calloc(1, sizeof(struct instruction_group));
11720 /* Initialize the new group. */
11721 g->group_id = n_groups;
11722 g->first_instr_id = i;
11725 /* Finalize the current group (with the current instruction, therefore this group
11726 * contains just the current thread yield instruction), add it to the list and
11727 * allocate a new group (that starts with the next instruction).
11730 /* Finalize the group. */
11731 g->last_instr_id = i;
11733 /* Add the group to the list. Advance the number of groups. */
11734 TAILQ_INSERT_TAIL(igl, g, node);
11737 /* Allocate a new group. */
11738 g = calloc(1, sizeof(struct instruction_group));
11742 /* Initialize the new group. */
11743 g->group_id = n_groups;
11744 g->first_instr_id = i + 1;
11747 /* Handle the last group. */
11748 if (i - g->first_instr_id) {
11749 /* Finalize the group. */
11750 g->last_instr_id = i - 1;
11752 /* Add the group to the list. Advance the number of groups. */
11753 TAILQ_INSERT_TAIL(igl, g, node);
11760 /* Iteration 2: Handle jumps. If the current group contains an instruction which represents
11761 * the destination of a jump instruction located in a different group ("far jump"), then the
11762 * current group has to be split, so that the instruction representing the far jump
11763 * destination is at the start of its group.
11766 int is_modified = 0;
11768 for (i = 0; i < p->n_instructions; i++) {
11769 struct instruction_data *data = &p->instruction_data[i];
11770 struct instruction_group *g;
11773 /* Continue when the current instruction is not a jump destination. */
11774 if (!data->n_users)
11777 g = instruction_group_list_group_find(igl, i);
11781 /* Find out all the jump instructions with this destination. */
11782 for (j = 0; j < p->n_instructions; j++) {
11783 struct instruction *jmp_instr = &p->instructions[j];
11784 struct instruction_data *jmp_data = &p->instruction_data[j];
11785 struct instruction_group *jmp_g, *new_g;
11787 /* Continue when not a jump instruction. Even when jump instruction,
11788 * continue when the jump destination is not this instruction.
11790 if (!instruction_is_jmp(jmp_instr) ||
11791 strcmp(jmp_data->jmp_label, data->label))
11794 jmp_g = instruction_group_list_group_find(igl, j);
11798 /* Continue when both the jump instruction and the jump destination
11799 * instruction are in the same group. Even when in different groups,
11800 * still continue if the jump destination instruction is already the
11801 * first instruction of its group.
11803 if ((jmp_g->group_id == g->group_id) || (g->first_instr_id == i))
11806 /* Split the group of the current jump destination instruction to
11807 * make this instruction the first instruction of a new group.
11809 new_g = calloc(1, sizeof(struct instruction_group));
11813 new_g->group_id = n_groups;
11814 new_g->first_instr_id = i;
11815 new_g->last_instr_id = g->last_instr_id;
11817 g->last_instr_id = i - 1;
11819 TAILQ_INSERT_AFTER(igl, g, new_g, node);
11823 /* The decision to split this group (to make the current instruction
11824 * the first instruction of a new group) is already taken and fully
11825 * implemented, so no need to search for more reasons to do it.
11831 /* Re-evaluate everything, as at least one group got split, so some jumps that were
11832 * previously considered local (i.e. the jump destination is in the same group as
11833 * the jump instruction) can now be "far jumps" (i.e. the jump destination is in a
11834 * different group than the jump instruction). Wost case scenario: each instruction
11835 * that is a jump destination ends up as the first instruction of its group.
11841 /* Re-assign the group IDs to be in incremental order. */
11843 TAILQ_FOREACH(g, igl, node) {
11852 instruction_group_list_free(igl);
11860 pipeline_instr_does_tx_codegen(struct rte_swx_pipeline *p __rte_unused,
11861 uint32_t instr_pos,
11862 struct instruction *instr,
11866 "%s(p, t, &pipeline_instructions[%u]);\n"
11867 "\tthread_ip_reset(p, t);\n"
11868 "\tinstr_rx_exec(p);\n"
11870 instr_type_to_func(instr),
11875 pipeline_instr_jmp_codegen(struct rte_swx_pipeline *p,
11876 struct instruction_group_list *igl,
11877 uint32_t jmp_instr_id,
11878 struct instruction *jmp_instr,
11879 struct instruction_data *jmp_data,
11882 struct instruction_group *jmp_g, *g;
11883 struct instruction_data *data;
11886 switch (jmp_instr->type) {
11890 case INSTR_JMP_VALID:
11892 "if (HEADER_VALID(t, pipeline_instructions[%u].jmp.header_id))",
11896 case INSTR_JMP_INVALID:
11898 "if (!HEADER_VALID(t, pipeline_instructions[%u].jmp.header_id))",
11902 case INSTR_JMP_HIT:
11907 case INSTR_JMP_MISS:
11912 case INSTR_JMP_ACTION_HIT:
11914 "if (t->action_id == pipeline_instructions[%u].jmp.action_id)",
11918 case INSTR_JMP_ACTION_MISS:
11920 "if (t->action_id != pipeline_instructions[%u].jmp.action_id)",
11926 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) == "
11927 "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
11932 case INSTR_JMP_EQ_MH:
11934 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) == "
11935 "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
11940 case INSTR_JMP_EQ_HM:
11942 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) == "
11943 "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
11948 case INSTR_JMP_EQ_HH:
11950 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) == "
11951 "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
11956 case INSTR_JMP_EQ_I:
11958 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) == "
11959 "pipeline_instructions[%u].jmp.b_val)",
11964 case INSTR_JMP_NEQ:
11966 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) != "
11967 "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
11972 case INSTR_JMP_NEQ_MH:
11974 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) != "
11975 "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
11980 case INSTR_JMP_NEQ_HM:
11982 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) != "
11983 "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
11988 case INSTR_JMP_NEQ_HH:
11990 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) != "
11991 "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
11996 case INSTR_JMP_NEQ_I:
11998 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) != "
11999 "pipeline_instructions[%u].jmp.b_val)",
12006 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) < "
12007 "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
12012 case INSTR_JMP_LT_MH:
12014 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) < "
12015 "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
12020 case INSTR_JMP_LT_HM:
12022 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) < "
12023 "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
12028 case INSTR_JMP_LT_HH:
12030 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) < "
12031 "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
12036 case INSTR_JMP_LT_MI:
12038 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) < "
12039 "pipeline_instructions[%u].jmp.b_val)",
12044 case INSTR_JMP_LT_HI:
12046 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) < "
12047 "pipeline_instructions[%u].jmp.b_val)",
12054 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) > "
12055 "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
12060 case INSTR_JMP_GT_MH:
12062 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) > "
12063 "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
12068 case INSTR_JMP_GT_HM:
12070 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) > "
12071 "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
12076 case INSTR_JMP_GT_HH:
12078 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) > "
12079 "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
12084 case INSTR_JMP_GT_MI:
12086 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) > "
12087 "pipeline_instructions[%u].jmp.b_val)",
12092 case INSTR_JMP_GT_HI:
12094 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) > "
12095 "pipeline_instructions[%u].jmp.b_val)",
12104 /* Find the instruction group of the jump instruction. */
12105 jmp_g = instruction_group_list_group_find(igl, jmp_instr_id);
12109 /* Find the instruction group of the jump destination instruction. */
12110 data = label_find(p->instruction_data, p->n_instructions, jmp_data->jmp_label);
12114 instr_id = data - p->instruction_data;
12116 g = instruction_group_list_group_find(igl, instr_id);
12120 /* Code generation for "near" jump (same instruction group) or "far" jump (different
12121 * instruction group).
12123 if (g->group_id == jmp_g->group_id)
12125 "\n\t\tgoto %s;\n",
12126 jmp_data->jmp_label);
12130 "\t\tthread_ip_set(t, &p->instructions[%u]);\n"
12139 instruction_group_list_codegen(struct instruction_group_list *igl,
12140 struct rte_swx_pipeline *p,
12143 struct instruction_group *g;
12145 int is_required = 0;
12147 /* Check if code generation is required. */
12148 TAILQ_FOREACH(g, igl, node)
12149 if (g->first_instr_id < g->last_instr_id)
12155 /* Generate the code for the pipeline instruction array. */
12157 "static const struct instruction pipeline_instructions[] = {\n");
12159 for (i = 0; i < p->n_instructions; i++) {
12160 struct instruction *instr = &p->instructions[i];
12161 instruction_export_t func = export_table[instr->type];
12166 fprintf(f, "};\n\n");
12168 /* Generate the code for the pipeline functions: one function for each instruction group
12169 * that contains more than one instruction.
12171 TAILQ_FOREACH(g, igl, node) {
12172 struct instruction *last_instr;
12175 /* Skip if group contains a single instruction. */
12176 if (g->last_instr_id == g->first_instr_id)
12179 /* Generate new pipeline function. */
12182 "pipeline_func_%u(struct rte_swx_pipeline *p)\n"
12184 "\tstruct thread *t = &p->threads[p->thread_id];\n"
12188 /* Generate the code for each pipeline instruction. */
12189 for (j = g->first_instr_id; j <= g->last_instr_id; j++) {
12190 struct instruction *instr = &p->instructions[j];
12191 struct instruction_data *data = &p->instruction_data[j];
12193 /* Label, if present. */
12194 if (data->label[0])
12195 fprintf(f, "\n%s : ", data->label);
12197 fprintf(f, "\n\t");
12199 /* TX instruction type. */
12200 if (instruction_does_tx(instr)) {
12201 pipeline_instr_does_tx_codegen(p, j, instr, f);
12205 /* Jump instruction type. */
12206 if (instruction_is_jmp(instr)) {
12207 pipeline_instr_jmp_codegen(p, igl, j, instr, data, f);
12211 /* Any other instruction type. */
12213 "%s(p, t, &pipeline_instructions[%u]);\n",
12214 instr_type_to_func(instr),
12218 /* Finalize the generated pipeline function. For some instructions such as TX,
12219 * emit-many-and-TX and unconditional jump, the next instruction has been already
12220 * decided unconditionally and the instruction pointer of the current thread set
12221 * accordingly; for all the other instructions, the instruction pointer must be
12224 last_instr = &p->instructions[g->last_instr_id];
12226 if (!instruction_does_tx(last_instr) && (last_instr->type != INSTR_JMP))
12228 "thread_ip_inc(p);\n");
12237 instruction_group_list_custom_instructions_count(struct instruction_group_list *igl)
12239 struct instruction_group *g;
12240 uint32_t n_custom_instr = 0;
12242 /* Groups with a single instruction: no function is generated for this group, the group
12243 * keeps its current instruction. Groups with more than two instructions: one function and
12244 * the associated custom instruction get generated for each such group.
12246 TAILQ_FOREACH(g, igl, node) {
12247 if (g->first_instr_id == g->last_instr_id)
12253 return n_custom_instr;
12257 pipeline_codegen(struct rte_swx_pipeline *p, struct instruction_group_list *igl)
12262 /* Create the .c file. */
12263 f = fopen("/tmp/pipeline.c", "w");
12267 /* Include the .h file. */
12268 fprintf(f, "#include \"rte_swx_pipeline_internal.h\"\n");
12270 /* Add the code for each action. */
12271 TAILQ_FOREACH(a, &p->actions, node) {
12272 fprintf(f, "/**\n * Action %s\n */\n\n", a->name);
12274 action_data_codegen(a, f);
12278 action_instr_codegen(a, f);
12283 /* Add the pipeline code. */
12284 instruction_group_list_codegen(igl, p, f);
12286 /* Close the .c file. */
12292 #ifndef RTE_SWX_PIPELINE_CMD_MAX_SIZE
12293 #define RTE_SWX_PIPELINE_CMD_MAX_SIZE 4096
12297 pipeline_libload(struct rte_swx_pipeline *p, struct instruction_group_list *igl)
12300 struct instruction_group *g;
12301 char *dir_in, *buffer = NULL;
12302 const char *dir_out;
12305 /* Get the environment variables. */
12306 dir_in = getenv("RTE_INSTALL_DIR");
12314 /* Memory allocation for the command buffer. */
12315 buffer = malloc(RTE_SWX_PIPELINE_CMD_MAX_SIZE);
12322 RTE_SWX_PIPELINE_CMD_MAX_SIZE,
12323 "gcc -c -O3 -fpic -Wno-deprecated-declarations -o %s/pipeline.o %s/pipeline.c "
12324 "-I %s/lib/pipeline "
12325 "-I %s/lib/eal/include "
12326 "-I %s/lib/eal/x86/include "
12327 "-I %s/lib/eal/include/generic "
12331 "-I %s/lib/pipeline "
12334 "-I %s/lib/eal/linux/include "
12335 ">%s/pipeline.log 2>&1 "
12337 "gcc -shared %s/pipeline.o -o %s/libpipeline.so "
12338 ">>%s/pipeline.log 2>&1",
12357 /* Build the shared object library. */
12358 status = system(buffer);
12362 /* Open library. */
12364 RTE_SWX_PIPELINE_CMD_MAX_SIZE,
12365 "%s/libpipeline.so",
12368 p->lib = dlopen(buffer, RTLD_LAZY);
12374 /* Get the action function symbols. */
12375 TAILQ_FOREACH(a, &p->actions, node) {
12376 snprintf(buffer, RTE_SWX_PIPELINE_CMD_MAX_SIZE, "action_%s_run", a->name);
12378 p->action_funcs[a->id] = dlsym(p->lib, buffer);
12379 if (!p->action_funcs[a->id]) {
12385 /* Get the pipeline function symbols. */
12386 TAILQ_FOREACH(g, igl, node) {
12387 if (g->first_instr_id == g->last_instr_id)
12390 snprintf(buffer, RTE_SWX_PIPELINE_CMD_MAX_SIZE, "pipeline_func_%u", g->group_id);
12392 g->func = dlsym(p->lib, buffer);
12400 if (status && p->lib) {
12411 pipeline_adjust_check(struct rte_swx_pipeline *p __rte_unused,
12412 struct instruction_group_list *igl)
12414 uint32_t n_custom_instr = instruction_group_list_custom_instructions_count(igl);
12416 /* Check that enough space is available within the pipeline instruction table to store all
12417 * the custom instructions.
12419 if (INSTR_CUSTOM_0 + n_custom_instr > RTE_SWX_PIPELINE_INSTRUCTION_TABLE_SIZE_MAX)
12426 pipeline_adjust(struct rte_swx_pipeline *p, struct instruction_group_list *igl)
12428 struct instruction_group *g;
12431 /* Pipeline table instructions. */
12432 for (i = 0; i < p->n_instructions; i++) {
12433 struct instruction *instr = &p->instructions[i];
12435 if (instr->type == INSTR_TABLE)
12436 instr->type = INSTR_TABLE_AF;
12438 if (instr->type == INSTR_LEARNER)
12439 instr->type = INSTR_LEARNER_AF;
12442 /* Pipeline custom instructions. */
12444 TAILQ_FOREACH(g, igl, node) {
12445 struct instruction *instr = &p->instructions[g->first_instr_id];
12448 if (g->first_instr_id == g->last_instr_id)
12451 /* Install a new custom instruction. */
12452 p->instruction_table[INSTR_CUSTOM_0 + i] = g->func;
12454 /* First instruction of the group: change its type to the new custom instruction. */
12455 instr->type = INSTR_CUSTOM_0 + i;
12457 /* All the subsequent instructions of the group: invalidate. */
12458 for (j = g->first_instr_id + 1; j <= g->last_instr_id; j++) {
12459 struct instruction_data *data = &p->instruction_data[j];
12467 /* Remove the invalidated instructions. */
12468 p->n_instructions = instr_compact(p->instructions, p->instruction_data, p->n_instructions);
12470 /* Resolve the jump destination for any "standalone" jump instructions (i.e. those jump
12471 * instructions that are the only instruction within their group, so they were left
12474 instr_jmp_resolve(p->instructions, p->instruction_data, p->n_instructions);
12478 pipeline_compile(struct rte_swx_pipeline *p)
12480 struct instruction_group_list *igl = NULL;
12483 igl = instruction_group_list_create(p);
12489 /* Code generation. */
12490 status = pipeline_codegen(p, igl);
12494 /* Build and load the shared object library. */
12495 status = pipeline_libload(p, igl);
12499 /* Adjust instructions. */
12500 status = pipeline_adjust_check(p, igl);
12504 pipeline_adjust(p, igl);
12507 instruction_group_list_free(igl);