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)
1382 instruction_does_tx(struct instruction *instr)
1384 switch (instr->type) {
1388 case INSTR_HDR_EMIT_TX:
1389 case INSTR_HDR_EMIT2_TX:
1390 case INSTR_HDR_EMIT3_TX:
1391 case INSTR_HDR_EMIT4_TX:
1392 case INSTR_HDR_EMIT5_TX:
1393 case INSTR_HDR_EMIT6_TX:
1394 case INSTR_HDR_EMIT7_TX:
1395 case INSTR_HDR_EMIT8_TX:
1403 instruction_is_jmp(struct instruction *instr)
1405 switch (instr->type) {
1407 case INSTR_JMP_VALID:
1408 case INSTR_JMP_INVALID:
1410 case INSTR_JMP_MISS:
1411 case INSTR_JMP_ACTION_HIT:
1412 case INSTR_JMP_ACTION_MISS:
1414 case INSTR_JMP_EQ_MH:
1415 case INSTR_JMP_EQ_HM:
1416 case INSTR_JMP_EQ_HH:
1417 case INSTR_JMP_EQ_I:
1419 case INSTR_JMP_NEQ_MH:
1420 case INSTR_JMP_NEQ_HM:
1421 case INSTR_JMP_NEQ_HH:
1422 case INSTR_JMP_NEQ_I:
1424 case INSTR_JMP_LT_MH:
1425 case INSTR_JMP_LT_HM:
1426 case INSTR_JMP_LT_HH:
1427 case INSTR_JMP_LT_MI:
1428 case INSTR_JMP_LT_HI:
1430 case INSTR_JMP_GT_MH:
1431 case INSTR_JMP_GT_HM:
1432 case INSTR_JMP_GT_HH:
1433 case INSTR_JMP_GT_MI:
1434 case INSTR_JMP_GT_HI:
1443 instruction_does_thread_yield(struct instruction *instr)
1445 switch (instr->type) {
1448 case INSTR_TABLE_AF:
1449 case INSTR_SELECTOR:
1451 case INSTR_LEARNER_AF:
1452 case INSTR_EXTERN_OBJ:
1453 case INSTR_EXTERN_FUNC:
1460 static struct field *
1461 action_field_parse(struct action *action, const char *name);
1463 static struct field *
1464 struct_field_parse(struct rte_swx_pipeline *p,
1465 struct action *action,
1467 uint32_t *struct_id)
1474 struct header *header;
1476 f = header_field_parse(p, name, &header);
1480 *struct_id = header->struct_id;
1486 f = metadata_field_parse(p, name);
1490 *struct_id = p->metadata_struct_id;
1499 f = action_field_parse(action, name);
1509 struct extern_obj *obj;
1511 f = extern_obj_mailbox_field_parse(p, name, &obj);
1515 *struct_id = obj->struct_id;
1521 struct extern_func *func;
1523 f = extern_func_mailbox_field_parse(p, name, &func);
1527 *struct_id = func->struct_id;
1540 instr_rx_translate(struct rte_swx_pipeline *p,
1541 struct action *action,
1544 struct instruction *instr,
1545 struct instruction_data *data __rte_unused)
1549 CHECK(!action, EINVAL);
1550 CHECK(n_tokens == 2, EINVAL);
1552 f = metadata_field_parse(p, tokens[1]);
1555 instr->type = INSTR_RX;
1556 instr->io.io.offset = f->offset / 8;
1557 instr->io.io.n_bits = f->n_bits;
1565 instr_tx_translate(struct rte_swx_pipeline *p,
1566 struct action *action __rte_unused,
1569 struct instruction *instr,
1570 struct instruction_data *data __rte_unused)
1572 char *port = tokens[1];
1576 CHECK(n_tokens == 2, EINVAL);
1578 f = metadata_field_parse(p, port);
1580 instr->type = INSTR_TX;
1581 instr->io.io.offset = f->offset / 8;
1582 instr->io.io.n_bits = f->n_bits;
1587 port_val = strtoul(port, &port, 0);
1588 CHECK(!port[0], EINVAL);
1590 instr->type = INSTR_TX_I;
1591 instr->io.io.val = port_val;
1596 instr_drop_translate(struct rte_swx_pipeline *p __rte_unused,
1597 struct action *action __rte_unused,
1598 char **tokens __rte_unused,
1600 struct instruction *instr,
1601 struct instruction_data *data __rte_unused)
1603 CHECK(n_tokens == 1, EINVAL);
1606 instr->type = INSTR_DROP;
1611 instr_tx_exec(struct rte_swx_pipeline *p)
1613 struct thread *t = &p->threads[p->thread_id];
1614 struct instruction *ip = t->ip;
1616 __instr_tx_exec(p, t, ip);
1619 thread_ip_reset(p, t);
1624 instr_tx_i_exec(struct rte_swx_pipeline *p)
1626 struct thread *t = &p->threads[p->thread_id];
1627 struct instruction *ip = t->ip;
1629 __instr_tx_i_exec(p, t, ip);
1632 thread_ip_reset(p, t);
1637 instr_drop_exec(struct rte_swx_pipeline *p)
1639 struct thread *t = &p->threads[p->thread_id];
1640 struct instruction *ip = t->ip;
1642 __instr_drop_exec(p, t, ip);
1645 thread_ip_reset(p, t);
1653 instr_hdr_extract_translate(struct rte_swx_pipeline *p,
1654 struct action *action,
1657 struct instruction *instr,
1658 struct instruction_data *data __rte_unused)
1662 CHECK(!action, EINVAL);
1663 CHECK((n_tokens == 2) || (n_tokens == 3), EINVAL);
1665 h = header_parse(p, tokens[1]);
1668 if (n_tokens == 2) {
1669 CHECK(!h->st->var_size, EINVAL);
1671 instr->type = INSTR_HDR_EXTRACT;
1672 instr->io.hdr.header_id[0] = h->id;
1673 instr->io.hdr.struct_id[0] = h->struct_id;
1674 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
1678 CHECK(h->st->var_size, EINVAL);
1680 mf = metadata_field_parse(p, tokens[2]);
1682 CHECK(!mf->var_size, EINVAL);
1684 instr->type = INSTR_HDR_EXTRACT_M;
1685 instr->io.io.offset = mf->offset / 8;
1686 instr->io.io.n_bits = mf->n_bits;
1687 instr->io.hdr.header_id[0] = h->id;
1688 instr->io.hdr.struct_id[0] = h->struct_id;
1689 instr->io.hdr.n_bytes[0] = h->st->n_bits_min / 8;
1696 instr_hdr_lookahead_translate(struct rte_swx_pipeline *p,
1697 struct action *action,
1700 struct instruction *instr,
1701 struct instruction_data *data __rte_unused)
1705 CHECK(!action, EINVAL);
1706 CHECK(n_tokens == 2, EINVAL);
1708 h = header_parse(p, tokens[1]);
1710 CHECK(!h->st->var_size, EINVAL);
1712 instr->type = INSTR_HDR_LOOKAHEAD;
1713 instr->io.hdr.header_id[0] = h->id;
1714 instr->io.hdr.struct_id[0] = h->struct_id;
1715 instr->io.hdr.n_bytes[0] = 0; /* Unused. */
1721 instr_hdr_extract_exec(struct rte_swx_pipeline *p)
1723 struct thread *t = &p->threads[p->thread_id];
1724 struct instruction *ip = t->ip;
1726 __instr_hdr_extract_exec(p, t, ip);
1733 instr_hdr_extract2_exec(struct rte_swx_pipeline *p)
1735 struct thread *t = &p->threads[p->thread_id];
1736 struct instruction *ip = t->ip;
1738 __instr_hdr_extract2_exec(p, t, ip);
1745 instr_hdr_extract3_exec(struct rte_swx_pipeline *p)
1747 struct thread *t = &p->threads[p->thread_id];
1748 struct instruction *ip = t->ip;
1750 __instr_hdr_extract3_exec(p, t, ip);
1757 instr_hdr_extract4_exec(struct rte_swx_pipeline *p)
1759 struct thread *t = &p->threads[p->thread_id];
1760 struct instruction *ip = t->ip;
1762 __instr_hdr_extract4_exec(p, t, ip);
1769 instr_hdr_extract5_exec(struct rte_swx_pipeline *p)
1771 struct thread *t = &p->threads[p->thread_id];
1772 struct instruction *ip = t->ip;
1774 __instr_hdr_extract5_exec(p, t, ip);
1781 instr_hdr_extract6_exec(struct rte_swx_pipeline *p)
1783 struct thread *t = &p->threads[p->thread_id];
1784 struct instruction *ip = t->ip;
1786 __instr_hdr_extract6_exec(p, t, ip);
1793 instr_hdr_extract7_exec(struct rte_swx_pipeline *p)
1795 struct thread *t = &p->threads[p->thread_id];
1796 struct instruction *ip = t->ip;
1798 __instr_hdr_extract7_exec(p, t, ip);
1805 instr_hdr_extract8_exec(struct rte_swx_pipeline *p)
1807 struct thread *t = &p->threads[p->thread_id];
1808 struct instruction *ip = t->ip;
1810 __instr_hdr_extract8_exec(p, t, ip);
1817 instr_hdr_extract_m_exec(struct rte_swx_pipeline *p)
1819 struct thread *t = &p->threads[p->thread_id];
1820 struct instruction *ip = t->ip;
1822 __instr_hdr_extract_m_exec(p, t, ip);
1829 instr_hdr_lookahead_exec(struct rte_swx_pipeline *p)
1831 struct thread *t = &p->threads[p->thread_id];
1832 struct instruction *ip = t->ip;
1834 __instr_hdr_lookahead_exec(p, t, ip);
1844 instr_hdr_emit_translate(struct rte_swx_pipeline *p,
1845 struct action *action __rte_unused,
1848 struct instruction *instr,
1849 struct instruction_data *data __rte_unused)
1853 CHECK(n_tokens == 2, EINVAL);
1855 h = header_parse(p, tokens[1]);
1858 instr->type = INSTR_HDR_EMIT;
1859 instr->io.hdr.header_id[0] = h->id;
1860 instr->io.hdr.struct_id[0] = h->struct_id;
1861 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
1866 instr_hdr_emit_exec(struct rte_swx_pipeline *p)
1868 struct thread *t = &p->threads[p->thread_id];
1869 struct instruction *ip = t->ip;
1871 __instr_hdr_emit_exec(p, t, ip);
1878 instr_hdr_emit_tx_exec(struct rte_swx_pipeline *p)
1880 struct thread *t = &p->threads[p->thread_id];
1881 struct instruction *ip = t->ip;
1883 __instr_hdr_emit_tx_exec(p, t, ip);
1886 thread_ip_reset(p, t);
1891 instr_hdr_emit2_tx_exec(struct rte_swx_pipeline *p)
1893 struct thread *t = &p->threads[p->thread_id];
1894 struct instruction *ip = t->ip;
1896 __instr_hdr_emit2_tx_exec(p, t, ip);
1899 thread_ip_reset(p, t);
1904 instr_hdr_emit3_tx_exec(struct rte_swx_pipeline *p)
1906 struct thread *t = &p->threads[p->thread_id];
1907 struct instruction *ip = t->ip;
1909 __instr_hdr_emit3_tx_exec(p, t, ip);
1912 thread_ip_reset(p, t);
1917 instr_hdr_emit4_tx_exec(struct rte_swx_pipeline *p)
1919 struct thread *t = &p->threads[p->thread_id];
1920 struct instruction *ip = t->ip;
1922 __instr_hdr_emit4_tx_exec(p, t, ip);
1925 thread_ip_reset(p, t);
1930 instr_hdr_emit5_tx_exec(struct rte_swx_pipeline *p)
1932 struct thread *t = &p->threads[p->thread_id];
1933 struct instruction *ip = t->ip;
1935 __instr_hdr_emit5_tx_exec(p, t, ip);
1938 thread_ip_reset(p, t);
1943 instr_hdr_emit6_tx_exec(struct rte_swx_pipeline *p)
1945 struct thread *t = &p->threads[p->thread_id];
1946 struct instruction *ip = t->ip;
1948 __instr_hdr_emit6_tx_exec(p, t, ip);
1951 thread_ip_reset(p, t);
1956 instr_hdr_emit7_tx_exec(struct rte_swx_pipeline *p)
1958 struct thread *t = &p->threads[p->thread_id];
1959 struct instruction *ip = t->ip;
1961 __instr_hdr_emit7_tx_exec(p, t, ip);
1964 thread_ip_reset(p, t);
1969 instr_hdr_emit8_tx_exec(struct rte_swx_pipeline *p)
1971 struct thread *t = &p->threads[p->thread_id];
1972 struct instruction *ip = t->ip;
1974 __instr_hdr_emit8_tx_exec(p, t, ip);
1977 thread_ip_reset(p, t);
1985 instr_hdr_validate_translate(struct rte_swx_pipeline *p,
1986 struct action *action __rte_unused,
1989 struct instruction *instr,
1990 struct instruction_data *data __rte_unused)
1994 CHECK(n_tokens == 2, EINVAL);
1996 h = header_parse(p, tokens[1]);
1999 instr->type = INSTR_HDR_VALIDATE;
2000 instr->valid.header_id = h->id;
2005 instr_hdr_validate_exec(struct rte_swx_pipeline *p)
2007 struct thread *t = &p->threads[p->thread_id];
2008 struct instruction *ip = t->ip;
2010 __instr_hdr_validate_exec(p, t, ip);
2020 instr_hdr_invalidate_translate(struct rte_swx_pipeline *p,
2021 struct action *action __rte_unused,
2024 struct instruction *instr,
2025 struct instruction_data *data __rte_unused)
2029 CHECK(n_tokens == 2, EINVAL);
2031 h = header_parse(p, tokens[1]);
2034 instr->type = INSTR_HDR_INVALIDATE;
2035 instr->valid.header_id = h->id;
2040 instr_hdr_invalidate_exec(struct rte_swx_pipeline *p)
2042 struct thread *t = &p->threads[p->thread_id];
2043 struct instruction *ip = t->ip;
2045 __instr_hdr_invalidate_exec(p, t, ip);
2054 static struct table *
2055 table_find(struct rte_swx_pipeline *p, const char *name);
2057 static struct selector *
2058 selector_find(struct rte_swx_pipeline *p, const char *name);
2060 static struct learner *
2061 learner_find(struct rte_swx_pipeline *p, const char *name);
2064 instr_table_translate(struct rte_swx_pipeline *p,
2065 struct action *action,
2068 struct instruction *instr,
2069 struct instruction_data *data __rte_unused)
2075 CHECK(!action, EINVAL);
2076 CHECK(n_tokens == 2, EINVAL);
2078 t = table_find(p, tokens[1]);
2080 instr->type = INSTR_TABLE;
2081 instr->table.table_id = t->id;
2085 s = selector_find(p, tokens[1]);
2087 instr->type = INSTR_SELECTOR;
2088 instr->table.table_id = s->id;
2092 l = learner_find(p, tokens[1]);
2094 instr->type = INSTR_LEARNER;
2095 instr->table.table_id = l->id;
2103 instr_table_exec(struct rte_swx_pipeline *p)
2105 struct thread *t = &p->threads[p->thread_id];
2106 struct instruction *ip = t->ip;
2107 uint32_t table_id = ip->table.table_id;
2108 struct rte_swx_table_state *ts = &t->table_state[table_id];
2109 struct table_runtime *table = &t->tables[table_id];
2110 struct table_statistics *stats = &p->table_stats[table_id];
2111 uint64_t action_id, n_pkts_hit, n_pkts_action;
2112 uint8_t *action_data;
2116 done = table->func(ts->obj,
2124 TRACE("[Thread %2u] table %u (not finalized)\n",
2132 action_id = hit ? action_id : ts->default_action_id;
2133 action_data = hit ? action_data : ts->default_action_data;
2134 n_pkts_hit = stats->n_pkts_hit[hit];
2135 n_pkts_action = stats->n_pkts_action[action_id];
2137 TRACE("[Thread %2u] table %u (%s, action %u)\n",
2140 hit ? "hit" : "miss",
2141 (uint32_t)action_id);
2143 t->action_id = action_id;
2144 t->structs[0] = action_data;
2146 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2147 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2150 thread_ip_action_call(p, t, action_id);
2154 instr_table_af_exec(struct rte_swx_pipeline *p)
2156 struct thread *t = &p->threads[p->thread_id];
2157 struct instruction *ip = t->ip;
2158 uint32_t table_id = ip->table.table_id;
2159 struct rte_swx_table_state *ts = &t->table_state[table_id];
2160 struct table_runtime *table = &t->tables[table_id];
2161 struct table_statistics *stats = &p->table_stats[table_id];
2162 uint64_t action_id, n_pkts_hit, n_pkts_action;
2163 uint8_t *action_data;
2164 action_func_t action_func;
2168 done = table->func(ts->obj,
2176 TRACE("[Thread %2u] table %u (not finalized)\n",
2184 action_id = hit ? action_id : ts->default_action_id;
2185 action_data = hit ? action_data : ts->default_action_data;
2186 action_func = p->action_funcs[action_id];
2187 n_pkts_hit = stats->n_pkts_hit[hit];
2188 n_pkts_action = stats->n_pkts_action[action_id];
2190 TRACE("[Thread %2u] table %u (%s, action %u)\n",
2193 hit ? "hit" : "miss",
2194 (uint32_t)action_id);
2196 t->action_id = action_id;
2197 t->structs[0] = action_data;
2199 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2200 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2210 instr_selector_exec(struct rte_swx_pipeline *p)
2212 struct thread *t = &p->threads[p->thread_id];
2213 struct instruction *ip = t->ip;
2214 uint32_t selector_id = ip->table.table_id;
2215 struct rte_swx_table_state *ts = &t->table_state[p->n_tables + selector_id];
2216 struct selector_runtime *selector = &t->selectors[selector_id];
2217 struct selector_statistics *stats = &p->selector_stats[selector_id];
2218 uint64_t n_pkts = stats->n_pkts;
2222 done = rte_swx_table_selector_select(ts->obj,
2224 selector->group_id_buffer,
2225 selector->selector_buffer,
2226 selector->member_id_buffer);
2229 TRACE("[Thread %2u] selector %u (not finalized)\n",
2238 TRACE("[Thread %2u] selector %u\n",
2242 stats->n_pkts = n_pkts + 1;
2249 instr_learner_exec(struct rte_swx_pipeline *p)
2251 struct thread *t = &p->threads[p->thread_id];
2252 struct instruction *ip = t->ip;
2253 uint32_t learner_id = ip->table.table_id;
2254 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2255 p->n_selectors + learner_id];
2256 struct learner_runtime *l = &t->learners[learner_id];
2257 struct learner_statistics *stats = &p->learner_stats[learner_id];
2258 uint64_t action_id, n_pkts_hit, n_pkts_action, time;
2259 uint8_t *action_data;
2263 time = rte_get_tsc_cycles();
2265 done = rte_swx_table_learner_lookup(ts->obj,
2274 TRACE("[Thread %2u] learner %u (not finalized)\n",
2282 action_id = hit ? action_id : ts->default_action_id;
2283 action_data = hit ? action_data : ts->default_action_data;
2284 n_pkts_hit = stats->n_pkts_hit[hit];
2285 n_pkts_action = stats->n_pkts_action[action_id];
2287 TRACE("[Thread %2u] learner %u (%s, action %u)\n",
2290 hit ? "hit" : "miss",
2291 (uint32_t)action_id);
2293 t->action_id = action_id;
2294 t->structs[0] = action_data;
2296 t->learner_id = learner_id;
2298 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2299 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2302 thread_ip_action_call(p, t, action_id);
2306 instr_learner_af_exec(struct rte_swx_pipeline *p)
2308 struct thread *t = &p->threads[p->thread_id];
2309 struct instruction *ip = t->ip;
2310 uint32_t learner_id = ip->table.table_id;
2311 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2312 p->n_selectors + learner_id];
2313 struct learner_runtime *l = &t->learners[learner_id];
2314 struct learner_statistics *stats = &p->learner_stats[learner_id];
2315 uint64_t action_id, n_pkts_hit, n_pkts_action, time;
2316 uint8_t *action_data;
2317 action_func_t action_func;
2321 time = rte_get_tsc_cycles();
2323 done = rte_swx_table_learner_lookup(ts->obj,
2332 TRACE("[Thread %2u] learner %u (not finalized)\n",
2340 action_id = hit ? action_id : ts->default_action_id;
2341 action_data = hit ? action_data : ts->default_action_data;
2342 action_func = p->action_funcs[action_id];
2343 n_pkts_hit = stats->n_pkts_hit[hit];
2344 n_pkts_action = stats->n_pkts_action[action_id];
2346 TRACE("[Thread %2u] learner %u (%s, action %u)\n",
2349 hit ? "hit" : "miss",
2350 (uint32_t)action_id);
2352 t->action_id = action_id;
2353 t->structs[0] = action_data;
2355 t->learner_id = learner_id;
2357 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2358 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2361 thread_ip_action_call(p, t, action_id);
2370 static struct action *
2371 action_find(struct rte_swx_pipeline *p, const char *name);
2374 action_has_nbo_args(struct action *a);
2377 learner_action_args_check(struct rte_swx_pipeline *p, struct action *a, const char *mf_name);
2380 instr_learn_translate(struct rte_swx_pipeline *p,
2381 struct action *action,
2384 struct instruction *instr,
2385 struct instruction_data *data __rte_unused)
2388 const char *mf_name;
2389 uint32_t mf_offset = 0;
2391 CHECK(action, EINVAL);
2392 CHECK((n_tokens == 2) || (n_tokens == 3), EINVAL);
2394 a = action_find(p, tokens[1]);
2396 CHECK(!action_has_nbo_args(a), EINVAL);
2398 mf_name = (n_tokens > 2) ? tokens[2] : NULL;
2399 CHECK(!learner_action_args_check(p, a, mf_name), EINVAL);
2404 mf = metadata_field_parse(p, mf_name);
2407 mf_offset = mf->offset / 8;
2410 instr->type = INSTR_LEARNER_LEARN;
2411 instr->learn.action_id = a->id;
2412 instr->learn.mf_offset = mf_offset;
2418 instr_learn_exec(struct rte_swx_pipeline *p)
2420 struct thread *t = &p->threads[p->thread_id];
2421 struct instruction *ip = t->ip;
2423 __instr_learn_exec(p, t, ip);
2433 instr_forget_translate(struct rte_swx_pipeline *p __rte_unused,
2434 struct action *action,
2435 char **tokens __rte_unused,
2437 struct instruction *instr,
2438 struct instruction_data *data __rte_unused)
2440 CHECK(action, EINVAL);
2441 CHECK(n_tokens == 1, EINVAL);
2443 instr->type = INSTR_LEARNER_FORGET;
2449 instr_forget_exec(struct rte_swx_pipeline *p)
2451 struct thread *t = &p->threads[p->thread_id];
2452 struct instruction *ip = t->ip;
2454 __instr_forget_exec(p, t, ip);
2464 instr_extern_translate(struct rte_swx_pipeline *p,
2465 struct action *action __rte_unused,
2468 struct instruction *instr,
2469 struct instruction_data *data __rte_unused)
2471 char *token = tokens[1];
2473 CHECK(n_tokens == 2, EINVAL);
2475 if (token[0] == 'e') {
2476 struct extern_obj *obj;
2477 struct extern_type_member_func *func;
2479 func = extern_obj_member_func_parse(p, token, &obj);
2480 CHECK(func, EINVAL);
2482 instr->type = INSTR_EXTERN_OBJ;
2483 instr->ext_obj.ext_obj_id = obj->id;
2484 instr->ext_obj.func_id = func->id;
2489 if (token[0] == 'f') {
2490 struct extern_func *func;
2492 func = extern_func_parse(p, token);
2493 CHECK(func, EINVAL);
2495 instr->type = INSTR_EXTERN_FUNC;
2496 instr->ext_func.ext_func_id = func->id;
2505 instr_extern_obj_exec(struct rte_swx_pipeline *p)
2507 struct thread *t = &p->threads[p->thread_id];
2508 struct instruction *ip = t->ip;
2511 /* Extern object member function execute. */
2512 done = __instr_extern_obj_exec(p, t, ip);
2515 thread_ip_inc_cond(t, done);
2516 thread_yield_cond(p, done ^ 1);
2520 instr_extern_func_exec(struct rte_swx_pipeline *p)
2522 struct thread *t = &p->threads[p->thread_id];
2523 struct instruction *ip = t->ip;
2526 /* Extern function execute. */
2527 done = __instr_extern_func_exec(p, t, ip);
2530 thread_ip_inc_cond(t, done);
2531 thread_yield_cond(p, done ^ 1);
2538 instr_mov_translate(struct rte_swx_pipeline *p,
2539 struct action *action,
2542 struct instruction *instr,
2543 struct instruction_data *data __rte_unused)
2545 char *dst = tokens[1], *src = tokens[2];
2546 struct field *fdst, *fsrc;
2548 uint32_t dst_struct_id = 0, src_struct_id = 0;
2550 CHECK(n_tokens == 3, EINVAL);
2552 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2553 CHECK(fdst, EINVAL);
2554 CHECK(!fdst->var_size, EINVAL);
2556 /* MOV, MOV_MH, MOV_HM or MOV_HH. */
2557 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2559 CHECK(!fsrc->var_size, EINVAL);
2561 instr->type = INSTR_MOV;
2562 if (dst[0] != 'h' && src[0] == 'h')
2563 instr->type = INSTR_MOV_MH;
2564 if (dst[0] == 'h' && src[0] != 'h')
2565 instr->type = INSTR_MOV_HM;
2566 if (dst[0] == 'h' && src[0] == 'h')
2567 instr->type = INSTR_MOV_HH;
2569 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
2570 instr->mov.dst.n_bits = fdst->n_bits;
2571 instr->mov.dst.offset = fdst->offset / 8;
2572 instr->mov.src.struct_id = (uint8_t)src_struct_id;
2573 instr->mov.src.n_bits = fsrc->n_bits;
2574 instr->mov.src.offset = fsrc->offset / 8;
2579 src_val = strtoull(src, &src, 0);
2580 CHECK(!src[0], EINVAL);
2583 src_val = hton64(src_val) >> (64 - fdst->n_bits);
2585 instr->type = INSTR_MOV_I;
2586 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
2587 instr->mov.dst.n_bits = fdst->n_bits;
2588 instr->mov.dst.offset = fdst->offset / 8;
2589 instr->mov.src_val = src_val;
2594 instr_mov_exec(struct rte_swx_pipeline *p)
2596 struct thread *t = &p->threads[p->thread_id];
2597 struct instruction *ip = t->ip;
2599 __instr_mov_exec(p, t, ip);
2606 instr_mov_mh_exec(struct rte_swx_pipeline *p)
2608 struct thread *t = &p->threads[p->thread_id];
2609 struct instruction *ip = t->ip;
2611 __instr_mov_mh_exec(p, t, ip);
2618 instr_mov_hm_exec(struct rte_swx_pipeline *p)
2620 struct thread *t = &p->threads[p->thread_id];
2621 struct instruction *ip = t->ip;
2623 __instr_mov_hm_exec(p, t, ip);
2630 instr_mov_hh_exec(struct rte_swx_pipeline *p)
2632 struct thread *t = &p->threads[p->thread_id];
2633 struct instruction *ip = t->ip;
2635 __instr_mov_hh_exec(p, t, ip);
2642 instr_mov_i_exec(struct rte_swx_pipeline *p)
2644 struct thread *t = &p->threads[p->thread_id];
2645 struct instruction *ip = t->ip;
2647 __instr_mov_i_exec(p, t, ip);
2657 instr_dma_ht_exec(struct rte_swx_pipeline *p)
2659 struct thread *t = &p->threads[p->thread_id];
2660 struct instruction *ip = t->ip;
2662 __instr_dma_ht_exec(p, t, ip);
2669 instr_dma_ht2_exec(struct rte_swx_pipeline *p)
2671 struct thread *t = &p->threads[p->thread_id];
2672 struct instruction *ip = t->ip;
2674 __instr_dma_ht2_exec(p, t, ip);
2681 instr_dma_ht3_exec(struct rte_swx_pipeline *p)
2683 struct thread *t = &p->threads[p->thread_id];
2684 struct instruction *ip = t->ip;
2686 __instr_dma_ht3_exec(p, t, ip);
2693 instr_dma_ht4_exec(struct rte_swx_pipeline *p)
2695 struct thread *t = &p->threads[p->thread_id];
2696 struct instruction *ip = t->ip;
2698 __instr_dma_ht4_exec(p, t, ip);
2705 instr_dma_ht5_exec(struct rte_swx_pipeline *p)
2707 struct thread *t = &p->threads[p->thread_id];
2708 struct instruction *ip = t->ip;
2710 __instr_dma_ht5_exec(p, t, ip);
2717 instr_dma_ht6_exec(struct rte_swx_pipeline *p)
2719 struct thread *t = &p->threads[p->thread_id];
2720 struct instruction *ip = t->ip;
2722 __instr_dma_ht6_exec(p, t, ip);
2729 instr_dma_ht7_exec(struct rte_swx_pipeline *p)
2731 struct thread *t = &p->threads[p->thread_id];
2732 struct instruction *ip = t->ip;
2734 __instr_dma_ht7_exec(p, t, ip);
2741 instr_dma_ht8_exec(struct rte_swx_pipeline *p)
2743 struct thread *t = &p->threads[p->thread_id];
2744 struct instruction *ip = t->ip;
2746 __instr_dma_ht8_exec(p, t, ip);
2756 instr_alu_add_translate(struct rte_swx_pipeline *p,
2757 struct action *action,
2760 struct instruction *instr,
2761 struct instruction_data *data __rte_unused)
2763 char *dst = tokens[1], *src = tokens[2];
2764 struct field *fdst, *fsrc;
2766 uint32_t dst_struct_id = 0, src_struct_id = 0;
2768 CHECK(n_tokens == 3, EINVAL);
2770 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2771 CHECK(fdst, EINVAL);
2772 CHECK(!fdst->var_size, EINVAL);
2774 /* ADD, ADD_HM, ADD_MH, ADD_HH. */
2775 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2777 CHECK(!fsrc->var_size, EINVAL);
2779 instr->type = INSTR_ALU_ADD;
2780 if (dst[0] == 'h' && src[0] != 'h')
2781 instr->type = INSTR_ALU_ADD_HM;
2782 if (dst[0] != 'h' && src[0] == 'h')
2783 instr->type = INSTR_ALU_ADD_MH;
2784 if (dst[0] == 'h' && src[0] == 'h')
2785 instr->type = INSTR_ALU_ADD_HH;
2787 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2788 instr->alu.dst.n_bits = fdst->n_bits;
2789 instr->alu.dst.offset = fdst->offset / 8;
2790 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2791 instr->alu.src.n_bits = fsrc->n_bits;
2792 instr->alu.src.offset = fsrc->offset / 8;
2796 /* ADD_MI, ADD_HI. */
2797 src_val = strtoull(src, &src, 0);
2798 CHECK(!src[0], EINVAL);
2800 instr->type = INSTR_ALU_ADD_MI;
2802 instr->type = INSTR_ALU_ADD_HI;
2804 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2805 instr->alu.dst.n_bits = fdst->n_bits;
2806 instr->alu.dst.offset = fdst->offset / 8;
2807 instr->alu.src_val = src_val;
2812 instr_alu_sub_translate(struct rte_swx_pipeline *p,
2813 struct action *action,
2816 struct instruction *instr,
2817 struct instruction_data *data __rte_unused)
2819 char *dst = tokens[1], *src = tokens[2];
2820 struct field *fdst, *fsrc;
2822 uint32_t dst_struct_id = 0, src_struct_id = 0;
2824 CHECK(n_tokens == 3, EINVAL);
2826 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2827 CHECK(fdst, EINVAL);
2828 CHECK(!fdst->var_size, EINVAL);
2830 /* SUB, SUB_HM, SUB_MH, SUB_HH. */
2831 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2833 CHECK(!fsrc->var_size, EINVAL);
2835 instr->type = INSTR_ALU_SUB;
2836 if (dst[0] == 'h' && src[0] != 'h')
2837 instr->type = INSTR_ALU_SUB_HM;
2838 if (dst[0] != 'h' && src[0] == 'h')
2839 instr->type = INSTR_ALU_SUB_MH;
2840 if (dst[0] == 'h' && src[0] == 'h')
2841 instr->type = INSTR_ALU_SUB_HH;
2843 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2844 instr->alu.dst.n_bits = fdst->n_bits;
2845 instr->alu.dst.offset = fdst->offset / 8;
2846 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2847 instr->alu.src.n_bits = fsrc->n_bits;
2848 instr->alu.src.offset = fsrc->offset / 8;
2852 /* SUB_MI, SUB_HI. */
2853 src_val = strtoull(src, &src, 0);
2854 CHECK(!src[0], EINVAL);
2856 instr->type = INSTR_ALU_SUB_MI;
2858 instr->type = INSTR_ALU_SUB_HI;
2860 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2861 instr->alu.dst.n_bits = fdst->n_bits;
2862 instr->alu.dst.offset = fdst->offset / 8;
2863 instr->alu.src_val = src_val;
2868 instr_alu_ckadd_translate(struct rte_swx_pipeline *p,
2869 struct action *action __rte_unused,
2872 struct instruction *instr,
2873 struct instruction_data *data __rte_unused)
2875 char *dst = tokens[1], *src = tokens[2];
2876 struct header *hdst, *hsrc;
2877 struct field *fdst, *fsrc;
2879 CHECK(n_tokens == 3, EINVAL);
2881 fdst = header_field_parse(p, dst, &hdst);
2882 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
2883 CHECK(!fdst->var_size, EINVAL);
2886 fsrc = header_field_parse(p, src, &hsrc);
2888 CHECK(!fsrc->var_size, EINVAL);
2890 instr->type = INSTR_ALU_CKADD_FIELD;
2891 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2892 instr->alu.dst.n_bits = fdst->n_bits;
2893 instr->alu.dst.offset = fdst->offset / 8;
2894 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2895 instr->alu.src.n_bits = fsrc->n_bits;
2896 instr->alu.src.offset = fsrc->offset / 8;
2900 /* CKADD_STRUCT, CKADD_STRUCT20. */
2901 hsrc = header_parse(p, src);
2902 CHECK(hsrc, EINVAL);
2903 CHECK(!hsrc->st->var_size, EINVAL);
2905 instr->type = INSTR_ALU_CKADD_STRUCT;
2906 if ((hsrc->st->n_bits / 8) == 20)
2907 instr->type = INSTR_ALU_CKADD_STRUCT20;
2909 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2910 instr->alu.dst.n_bits = fdst->n_bits;
2911 instr->alu.dst.offset = fdst->offset / 8;
2912 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2913 instr->alu.src.n_bits = hsrc->st->n_bits;
2914 instr->alu.src.offset = 0; /* Unused. */
2919 instr_alu_cksub_translate(struct rte_swx_pipeline *p,
2920 struct action *action __rte_unused,
2923 struct instruction *instr,
2924 struct instruction_data *data __rte_unused)
2926 char *dst = tokens[1], *src = tokens[2];
2927 struct header *hdst, *hsrc;
2928 struct field *fdst, *fsrc;
2930 CHECK(n_tokens == 3, EINVAL);
2932 fdst = header_field_parse(p, dst, &hdst);
2933 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
2934 CHECK(!fdst->var_size, EINVAL);
2936 fsrc = header_field_parse(p, src, &hsrc);
2937 CHECK(fsrc, EINVAL);
2938 CHECK(!fsrc->var_size, EINVAL);
2940 instr->type = INSTR_ALU_CKSUB_FIELD;
2941 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2942 instr->alu.dst.n_bits = fdst->n_bits;
2943 instr->alu.dst.offset = fdst->offset / 8;
2944 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2945 instr->alu.src.n_bits = fsrc->n_bits;
2946 instr->alu.src.offset = fsrc->offset / 8;
2951 instr_alu_shl_translate(struct rte_swx_pipeline *p,
2952 struct action *action,
2955 struct instruction *instr,
2956 struct instruction_data *data __rte_unused)
2958 char *dst = tokens[1], *src = tokens[2];
2959 struct field *fdst, *fsrc;
2961 uint32_t dst_struct_id = 0, src_struct_id = 0;
2963 CHECK(n_tokens == 3, EINVAL);
2965 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2966 CHECK(fdst, EINVAL);
2967 CHECK(!fdst->var_size, EINVAL);
2969 /* SHL, SHL_HM, SHL_MH, SHL_HH. */
2970 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2972 CHECK(!fsrc->var_size, EINVAL);
2974 instr->type = INSTR_ALU_SHL;
2975 if (dst[0] == 'h' && src[0] != 'h')
2976 instr->type = INSTR_ALU_SHL_HM;
2977 if (dst[0] != 'h' && src[0] == 'h')
2978 instr->type = INSTR_ALU_SHL_MH;
2979 if (dst[0] == 'h' && src[0] == 'h')
2980 instr->type = INSTR_ALU_SHL_HH;
2982 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2983 instr->alu.dst.n_bits = fdst->n_bits;
2984 instr->alu.dst.offset = fdst->offset / 8;
2985 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2986 instr->alu.src.n_bits = fsrc->n_bits;
2987 instr->alu.src.offset = fsrc->offset / 8;
2991 /* SHL_MI, SHL_HI. */
2992 src_val = strtoull(src, &src, 0);
2993 CHECK(!src[0], EINVAL);
2995 instr->type = INSTR_ALU_SHL_MI;
2997 instr->type = INSTR_ALU_SHL_HI;
2999 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3000 instr->alu.dst.n_bits = fdst->n_bits;
3001 instr->alu.dst.offset = fdst->offset / 8;
3002 instr->alu.src_val = src_val;
3007 instr_alu_shr_translate(struct rte_swx_pipeline *p,
3008 struct action *action,
3011 struct instruction *instr,
3012 struct instruction_data *data __rte_unused)
3014 char *dst = tokens[1], *src = tokens[2];
3015 struct field *fdst, *fsrc;
3017 uint32_t dst_struct_id = 0, src_struct_id = 0;
3019 CHECK(n_tokens == 3, EINVAL);
3021 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3022 CHECK(fdst, EINVAL);
3023 CHECK(!fdst->var_size, EINVAL);
3025 /* SHR, SHR_HM, SHR_MH, SHR_HH. */
3026 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3028 CHECK(!fsrc->var_size, EINVAL);
3030 instr->type = INSTR_ALU_SHR;
3031 if (dst[0] == 'h' && src[0] != 'h')
3032 instr->type = INSTR_ALU_SHR_HM;
3033 if (dst[0] != 'h' && src[0] == 'h')
3034 instr->type = INSTR_ALU_SHR_MH;
3035 if (dst[0] == 'h' && src[0] == 'h')
3036 instr->type = INSTR_ALU_SHR_HH;
3038 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3039 instr->alu.dst.n_bits = fdst->n_bits;
3040 instr->alu.dst.offset = fdst->offset / 8;
3041 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3042 instr->alu.src.n_bits = fsrc->n_bits;
3043 instr->alu.src.offset = fsrc->offset / 8;
3047 /* SHR_MI, SHR_HI. */
3048 src_val = strtoull(src, &src, 0);
3049 CHECK(!src[0], EINVAL);
3051 instr->type = INSTR_ALU_SHR_MI;
3053 instr->type = INSTR_ALU_SHR_HI;
3055 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3056 instr->alu.dst.n_bits = fdst->n_bits;
3057 instr->alu.dst.offset = fdst->offset / 8;
3058 instr->alu.src_val = src_val;
3063 instr_alu_and_translate(struct rte_swx_pipeline *p,
3064 struct action *action,
3067 struct instruction *instr,
3068 struct instruction_data *data __rte_unused)
3070 char *dst = tokens[1], *src = tokens[2];
3071 struct field *fdst, *fsrc;
3073 uint32_t dst_struct_id = 0, src_struct_id = 0;
3075 CHECK(n_tokens == 3, EINVAL);
3077 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3078 CHECK(fdst, EINVAL);
3079 CHECK(!fdst->var_size, EINVAL);
3081 /* AND, AND_MH, AND_HM, AND_HH. */
3082 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3084 CHECK(!fsrc->var_size, EINVAL);
3086 instr->type = INSTR_ALU_AND;
3087 if (dst[0] != 'h' && src[0] == 'h')
3088 instr->type = INSTR_ALU_AND_MH;
3089 if (dst[0] == 'h' && src[0] != 'h')
3090 instr->type = INSTR_ALU_AND_HM;
3091 if (dst[0] == 'h' && src[0] == 'h')
3092 instr->type = INSTR_ALU_AND_HH;
3094 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3095 instr->alu.dst.n_bits = fdst->n_bits;
3096 instr->alu.dst.offset = fdst->offset / 8;
3097 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3098 instr->alu.src.n_bits = fsrc->n_bits;
3099 instr->alu.src.offset = fsrc->offset / 8;
3104 src_val = strtoull(src, &src, 0);
3105 CHECK(!src[0], EINVAL);
3108 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3110 instr->type = INSTR_ALU_AND_I;
3111 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3112 instr->alu.dst.n_bits = fdst->n_bits;
3113 instr->alu.dst.offset = fdst->offset / 8;
3114 instr->alu.src_val = src_val;
3119 instr_alu_or_translate(struct rte_swx_pipeline *p,
3120 struct action *action,
3123 struct instruction *instr,
3124 struct instruction_data *data __rte_unused)
3126 char *dst = tokens[1], *src = tokens[2];
3127 struct field *fdst, *fsrc;
3129 uint32_t dst_struct_id = 0, src_struct_id = 0;
3131 CHECK(n_tokens == 3, EINVAL);
3133 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3134 CHECK(fdst, EINVAL);
3135 CHECK(!fdst->var_size, EINVAL);
3137 /* OR, OR_MH, OR_HM, OR_HH. */
3138 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3140 CHECK(!fsrc->var_size, EINVAL);
3142 instr->type = INSTR_ALU_OR;
3143 if (dst[0] != 'h' && src[0] == 'h')
3144 instr->type = INSTR_ALU_OR_MH;
3145 if (dst[0] == 'h' && src[0] != 'h')
3146 instr->type = INSTR_ALU_OR_HM;
3147 if (dst[0] == 'h' && src[0] == 'h')
3148 instr->type = INSTR_ALU_OR_HH;
3150 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3151 instr->alu.dst.n_bits = fdst->n_bits;
3152 instr->alu.dst.offset = fdst->offset / 8;
3153 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3154 instr->alu.src.n_bits = fsrc->n_bits;
3155 instr->alu.src.offset = fsrc->offset / 8;
3160 src_val = strtoull(src, &src, 0);
3161 CHECK(!src[0], EINVAL);
3164 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3166 instr->type = INSTR_ALU_OR_I;
3167 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3168 instr->alu.dst.n_bits = fdst->n_bits;
3169 instr->alu.dst.offset = fdst->offset / 8;
3170 instr->alu.src_val = src_val;
3175 instr_alu_xor_translate(struct rte_swx_pipeline *p,
3176 struct action *action,
3179 struct instruction *instr,
3180 struct instruction_data *data __rte_unused)
3182 char *dst = tokens[1], *src = tokens[2];
3183 struct field *fdst, *fsrc;
3185 uint32_t dst_struct_id = 0, src_struct_id = 0;
3187 CHECK(n_tokens == 3, EINVAL);
3189 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3190 CHECK(fdst, EINVAL);
3191 CHECK(!fdst->var_size, EINVAL);
3193 /* XOR, XOR_MH, XOR_HM, XOR_HH. */
3194 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3196 CHECK(!fsrc->var_size, EINVAL);
3198 instr->type = INSTR_ALU_XOR;
3199 if (dst[0] != 'h' && src[0] == 'h')
3200 instr->type = INSTR_ALU_XOR_MH;
3201 if (dst[0] == 'h' && src[0] != 'h')
3202 instr->type = INSTR_ALU_XOR_HM;
3203 if (dst[0] == 'h' && src[0] == 'h')
3204 instr->type = INSTR_ALU_XOR_HH;
3206 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3207 instr->alu.dst.n_bits = fdst->n_bits;
3208 instr->alu.dst.offset = fdst->offset / 8;
3209 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3210 instr->alu.src.n_bits = fsrc->n_bits;
3211 instr->alu.src.offset = fsrc->offset / 8;
3216 src_val = strtoull(src, &src, 0);
3217 CHECK(!src[0], EINVAL);
3220 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3222 instr->type = INSTR_ALU_XOR_I;
3223 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3224 instr->alu.dst.n_bits = fdst->n_bits;
3225 instr->alu.dst.offset = fdst->offset / 8;
3226 instr->alu.src_val = src_val;
3231 instr_alu_add_exec(struct rte_swx_pipeline *p)
3233 struct thread *t = &p->threads[p->thread_id];
3234 struct instruction *ip = t->ip;
3237 __instr_alu_add_exec(p, t, ip);
3244 instr_alu_add_mh_exec(struct rte_swx_pipeline *p)
3246 struct thread *t = &p->threads[p->thread_id];
3247 struct instruction *ip = t->ip;
3250 __instr_alu_add_mh_exec(p, t, ip);
3257 instr_alu_add_hm_exec(struct rte_swx_pipeline *p)
3259 struct thread *t = &p->threads[p->thread_id];
3260 struct instruction *ip = t->ip;
3263 __instr_alu_add_hm_exec(p, t, ip);
3270 instr_alu_add_hh_exec(struct rte_swx_pipeline *p)
3272 struct thread *t = &p->threads[p->thread_id];
3273 struct instruction *ip = t->ip;
3276 __instr_alu_add_hh_exec(p, t, ip);
3283 instr_alu_add_mi_exec(struct rte_swx_pipeline *p)
3285 struct thread *t = &p->threads[p->thread_id];
3286 struct instruction *ip = t->ip;
3289 __instr_alu_add_mi_exec(p, t, ip);
3296 instr_alu_add_hi_exec(struct rte_swx_pipeline *p)
3298 struct thread *t = &p->threads[p->thread_id];
3299 struct instruction *ip = t->ip;
3302 __instr_alu_add_hi_exec(p, t, ip);
3309 instr_alu_sub_exec(struct rte_swx_pipeline *p)
3311 struct thread *t = &p->threads[p->thread_id];
3312 struct instruction *ip = t->ip;
3315 __instr_alu_sub_exec(p, t, ip);
3322 instr_alu_sub_mh_exec(struct rte_swx_pipeline *p)
3324 struct thread *t = &p->threads[p->thread_id];
3325 struct instruction *ip = t->ip;
3328 __instr_alu_sub_mh_exec(p, t, ip);
3335 instr_alu_sub_hm_exec(struct rte_swx_pipeline *p)
3337 struct thread *t = &p->threads[p->thread_id];
3338 struct instruction *ip = t->ip;
3341 __instr_alu_sub_hm_exec(p, t, ip);
3348 instr_alu_sub_hh_exec(struct rte_swx_pipeline *p)
3350 struct thread *t = &p->threads[p->thread_id];
3351 struct instruction *ip = t->ip;
3354 __instr_alu_sub_hh_exec(p, t, ip);
3361 instr_alu_sub_mi_exec(struct rte_swx_pipeline *p)
3363 struct thread *t = &p->threads[p->thread_id];
3364 struct instruction *ip = t->ip;
3367 __instr_alu_sub_mi_exec(p, t, ip);
3374 instr_alu_sub_hi_exec(struct rte_swx_pipeline *p)
3376 struct thread *t = &p->threads[p->thread_id];
3377 struct instruction *ip = t->ip;
3380 __instr_alu_sub_hi_exec(p, t, ip);
3387 instr_alu_shl_exec(struct rte_swx_pipeline *p)
3389 struct thread *t = &p->threads[p->thread_id];
3390 struct instruction *ip = t->ip;
3393 __instr_alu_shl_exec(p, t, ip);
3400 instr_alu_shl_mh_exec(struct rte_swx_pipeline *p)
3402 struct thread *t = &p->threads[p->thread_id];
3403 struct instruction *ip = t->ip;
3406 __instr_alu_shl_mh_exec(p, t, ip);
3413 instr_alu_shl_hm_exec(struct rte_swx_pipeline *p)
3415 struct thread *t = &p->threads[p->thread_id];
3416 struct instruction *ip = t->ip;
3419 __instr_alu_shl_hm_exec(p, t, ip);
3426 instr_alu_shl_hh_exec(struct rte_swx_pipeline *p)
3428 struct thread *t = &p->threads[p->thread_id];
3429 struct instruction *ip = t->ip;
3432 __instr_alu_shl_hh_exec(p, t, ip);
3439 instr_alu_shl_mi_exec(struct rte_swx_pipeline *p)
3441 struct thread *t = &p->threads[p->thread_id];
3442 struct instruction *ip = t->ip;
3445 __instr_alu_shl_mi_exec(p, t, ip);
3452 instr_alu_shl_hi_exec(struct rte_swx_pipeline *p)
3454 struct thread *t = &p->threads[p->thread_id];
3455 struct instruction *ip = t->ip;
3458 __instr_alu_shl_hi_exec(p, t, ip);
3465 instr_alu_shr_exec(struct rte_swx_pipeline *p)
3467 struct thread *t = &p->threads[p->thread_id];
3468 struct instruction *ip = t->ip;
3471 __instr_alu_shr_exec(p, t, ip);
3478 instr_alu_shr_mh_exec(struct rte_swx_pipeline *p)
3480 struct thread *t = &p->threads[p->thread_id];
3481 struct instruction *ip = t->ip;
3484 __instr_alu_shr_mh_exec(p, t, ip);
3491 instr_alu_shr_hm_exec(struct rte_swx_pipeline *p)
3493 struct thread *t = &p->threads[p->thread_id];
3494 struct instruction *ip = t->ip;
3497 __instr_alu_shr_hm_exec(p, t, ip);
3504 instr_alu_shr_hh_exec(struct rte_swx_pipeline *p)
3506 struct thread *t = &p->threads[p->thread_id];
3507 struct instruction *ip = t->ip;
3510 __instr_alu_shr_hh_exec(p, t, ip);
3517 instr_alu_shr_mi_exec(struct rte_swx_pipeline *p)
3519 struct thread *t = &p->threads[p->thread_id];
3520 struct instruction *ip = t->ip;
3523 __instr_alu_shr_mi_exec(p, t, ip);
3530 instr_alu_shr_hi_exec(struct rte_swx_pipeline *p)
3532 struct thread *t = &p->threads[p->thread_id];
3533 struct instruction *ip = t->ip;
3536 __instr_alu_shr_hi_exec(p, t, ip);
3543 instr_alu_and_exec(struct rte_swx_pipeline *p)
3545 struct thread *t = &p->threads[p->thread_id];
3546 struct instruction *ip = t->ip;
3549 __instr_alu_and_exec(p, t, ip);
3556 instr_alu_and_mh_exec(struct rte_swx_pipeline *p)
3558 struct thread *t = &p->threads[p->thread_id];
3559 struct instruction *ip = t->ip;
3562 __instr_alu_and_mh_exec(p, t, ip);
3569 instr_alu_and_hm_exec(struct rte_swx_pipeline *p)
3571 struct thread *t = &p->threads[p->thread_id];
3572 struct instruction *ip = t->ip;
3575 __instr_alu_and_hm_exec(p, t, ip);
3582 instr_alu_and_hh_exec(struct rte_swx_pipeline *p)
3584 struct thread *t = &p->threads[p->thread_id];
3585 struct instruction *ip = t->ip;
3588 __instr_alu_and_hh_exec(p, t, ip);
3595 instr_alu_and_i_exec(struct rte_swx_pipeline *p)
3597 struct thread *t = &p->threads[p->thread_id];
3598 struct instruction *ip = t->ip;
3601 __instr_alu_and_i_exec(p, t, ip);
3608 instr_alu_or_exec(struct rte_swx_pipeline *p)
3610 struct thread *t = &p->threads[p->thread_id];
3611 struct instruction *ip = t->ip;
3614 __instr_alu_or_exec(p, t, ip);
3621 instr_alu_or_mh_exec(struct rte_swx_pipeline *p)
3623 struct thread *t = &p->threads[p->thread_id];
3624 struct instruction *ip = t->ip;
3627 __instr_alu_or_mh_exec(p, t, ip);
3634 instr_alu_or_hm_exec(struct rte_swx_pipeline *p)
3636 struct thread *t = &p->threads[p->thread_id];
3637 struct instruction *ip = t->ip;
3640 __instr_alu_or_hm_exec(p, t, ip);
3647 instr_alu_or_hh_exec(struct rte_swx_pipeline *p)
3649 struct thread *t = &p->threads[p->thread_id];
3650 struct instruction *ip = t->ip;
3653 __instr_alu_or_hh_exec(p, t, ip);
3660 instr_alu_or_i_exec(struct rte_swx_pipeline *p)
3662 struct thread *t = &p->threads[p->thread_id];
3663 struct instruction *ip = t->ip;
3666 __instr_alu_or_i_exec(p, t, ip);
3673 instr_alu_xor_exec(struct rte_swx_pipeline *p)
3675 struct thread *t = &p->threads[p->thread_id];
3676 struct instruction *ip = t->ip;
3679 __instr_alu_xor_exec(p, t, ip);
3686 instr_alu_xor_mh_exec(struct rte_swx_pipeline *p)
3688 struct thread *t = &p->threads[p->thread_id];
3689 struct instruction *ip = t->ip;
3692 __instr_alu_xor_mh_exec(p, t, ip);
3699 instr_alu_xor_hm_exec(struct rte_swx_pipeline *p)
3701 struct thread *t = &p->threads[p->thread_id];
3702 struct instruction *ip = t->ip;
3705 __instr_alu_xor_hm_exec(p, t, ip);
3712 instr_alu_xor_hh_exec(struct rte_swx_pipeline *p)
3714 struct thread *t = &p->threads[p->thread_id];
3715 struct instruction *ip = t->ip;
3718 __instr_alu_xor_hh_exec(p, t, ip);
3725 instr_alu_xor_i_exec(struct rte_swx_pipeline *p)
3727 struct thread *t = &p->threads[p->thread_id];
3728 struct instruction *ip = t->ip;
3731 __instr_alu_xor_i_exec(p, t, ip);
3738 instr_alu_ckadd_field_exec(struct rte_swx_pipeline *p)
3740 struct thread *t = &p->threads[p->thread_id];
3741 struct instruction *ip = t->ip;
3744 __instr_alu_ckadd_field_exec(p, t, ip);
3751 instr_alu_cksub_field_exec(struct rte_swx_pipeline *p)
3753 struct thread *t = &p->threads[p->thread_id];
3754 struct instruction *ip = t->ip;
3757 __instr_alu_cksub_field_exec(p, t, ip);
3764 instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline *p)
3766 struct thread *t = &p->threads[p->thread_id];
3767 struct instruction *ip = t->ip;
3770 __instr_alu_ckadd_struct20_exec(p, t, ip);
3777 instr_alu_ckadd_struct_exec(struct rte_swx_pipeline *p)
3779 struct thread *t = &p->threads[p->thread_id];
3780 struct instruction *ip = t->ip;
3783 __instr_alu_ckadd_struct_exec(p, t, ip);
3792 static struct regarray *
3793 regarray_find(struct rte_swx_pipeline *p, const char *name);
3796 instr_regprefetch_translate(struct rte_swx_pipeline *p,
3797 struct action *action,
3800 struct instruction *instr,
3801 struct instruction_data *data __rte_unused)
3803 char *regarray = tokens[1], *idx = tokens[2];
3806 uint32_t idx_struct_id, idx_val;
3808 CHECK(n_tokens == 3, EINVAL);
3810 r = regarray_find(p, regarray);
3813 /* REGPREFETCH_RH, REGPREFETCH_RM. */
3814 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
3816 CHECK(!fidx->var_size, EINVAL);
3818 instr->type = INSTR_REGPREFETCH_RM;
3820 instr->type = INSTR_REGPREFETCH_RH;
3822 instr->regarray.regarray_id = r->id;
3823 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
3824 instr->regarray.idx.n_bits = fidx->n_bits;
3825 instr->regarray.idx.offset = fidx->offset / 8;
3826 instr->regarray.dstsrc_val = 0; /* Unused. */
3830 /* REGPREFETCH_RI. */
3831 idx_val = strtoul(idx, &idx, 0);
3832 CHECK(!idx[0], EINVAL);
3834 instr->type = INSTR_REGPREFETCH_RI;
3835 instr->regarray.regarray_id = r->id;
3836 instr->regarray.idx_val = idx_val;
3837 instr->regarray.dstsrc_val = 0; /* Unused. */
3842 instr_regrd_translate(struct rte_swx_pipeline *p,
3843 struct action *action,
3846 struct instruction *instr,
3847 struct instruction_data *data __rte_unused)
3849 char *dst = tokens[1], *regarray = tokens[2], *idx = tokens[3];
3851 struct field *fdst, *fidx;
3852 uint32_t dst_struct_id, idx_struct_id, idx_val;
3854 CHECK(n_tokens == 4, EINVAL);
3856 r = regarray_find(p, regarray);
3859 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3860 CHECK(fdst, EINVAL);
3861 CHECK(!fdst->var_size, EINVAL);
3863 /* REGRD_HRH, REGRD_HRM, REGRD_MRH, REGRD_MRM. */
3864 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
3866 CHECK(!fidx->var_size, EINVAL);
3868 instr->type = INSTR_REGRD_MRM;
3869 if (dst[0] == 'h' && idx[0] != 'h')
3870 instr->type = INSTR_REGRD_HRM;
3871 if (dst[0] != 'h' && idx[0] == 'h')
3872 instr->type = INSTR_REGRD_MRH;
3873 if (dst[0] == 'h' && idx[0] == 'h')
3874 instr->type = INSTR_REGRD_HRH;
3876 instr->regarray.regarray_id = r->id;
3877 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
3878 instr->regarray.idx.n_bits = fidx->n_bits;
3879 instr->regarray.idx.offset = fidx->offset / 8;
3880 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
3881 instr->regarray.dstsrc.n_bits = fdst->n_bits;
3882 instr->regarray.dstsrc.offset = fdst->offset / 8;
3886 /* REGRD_MRI, REGRD_HRI. */
3887 idx_val = strtoul(idx, &idx, 0);
3888 CHECK(!idx[0], EINVAL);
3890 instr->type = INSTR_REGRD_MRI;
3892 instr->type = INSTR_REGRD_HRI;
3894 instr->regarray.regarray_id = r->id;
3895 instr->regarray.idx_val = idx_val;
3896 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
3897 instr->regarray.dstsrc.n_bits = fdst->n_bits;
3898 instr->regarray.dstsrc.offset = fdst->offset / 8;
3903 instr_regwr_translate(struct rte_swx_pipeline *p,
3904 struct action *action,
3907 struct instruction *instr,
3908 struct instruction_data *data __rte_unused)
3910 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
3912 struct field *fidx, *fsrc;
3914 uint32_t idx_struct_id, idx_val, src_struct_id;
3916 CHECK(n_tokens == 4, EINVAL);
3918 r = regarray_find(p, regarray);
3921 /* REGWR_RHH, REGWR_RHM, REGWR_RMH, REGWR_RMM. */
3922 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
3923 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3925 CHECK(!fidx->var_size, EINVAL);
3926 CHECK(!fsrc->var_size, EINVAL);
3928 instr->type = INSTR_REGWR_RMM;
3929 if (idx[0] == 'h' && src[0] != 'h')
3930 instr->type = INSTR_REGWR_RHM;
3931 if (idx[0] != 'h' && src[0] == 'h')
3932 instr->type = INSTR_REGWR_RMH;
3933 if (idx[0] == 'h' && src[0] == 'h')
3934 instr->type = INSTR_REGWR_RHH;
3936 instr->regarray.regarray_id = r->id;
3937 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
3938 instr->regarray.idx.n_bits = fidx->n_bits;
3939 instr->regarray.idx.offset = fidx->offset / 8;
3940 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
3941 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
3942 instr->regarray.dstsrc.offset = fsrc->offset / 8;
3946 /* REGWR_RHI, REGWR_RMI. */
3947 if (fidx && !fsrc) {
3948 CHECK(!fidx->var_size, EINVAL);
3950 src_val = strtoull(src, &src, 0);
3951 CHECK(!src[0], EINVAL);
3953 instr->type = INSTR_REGWR_RMI;
3955 instr->type = INSTR_REGWR_RHI;
3957 instr->regarray.regarray_id = r->id;
3958 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
3959 instr->regarray.idx.n_bits = fidx->n_bits;
3960 instr->regarray.idx.offset = fidx->offset / 8;
3961 instr->regarray.dstsrc_val = src_val;
3965 /* REGWR_RIH, REGWR_RIM. */
3966 if (!fidx && fsrc) {
3967 idx_val = strtoul(idx, &idx, 0);
3968 CHECK(!idx[0], EINVAL);
3970 CHECK(!fsrc->var_size, EINVAL);
3972 instr->type = INSTR_REGWR_RIM;
3974 instr->type = INSTR_REGWR_RIH;
3976 instr->regarray.regarray_id = r->id;
3977 instr->regarray.idx_val = idx_val;
3978 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
3979 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
3980 instr->regarray.dstsrc.offset = fsrc->offset / 8;
3985 src_val = strtoull(src, &src, 0);
3986 CHECK(!src[0], EINVAL);
3988 idx_val = strtoul(idx, &idx, 0);
3989 CHECK(!idx[0], EINVAL);
3991 instr->type = INSTR_REGWR_RII;
3992 instr->regarray.idx_val = idx_val;
3993 instr->regarray.dstsrc_val = src_val;
3999 instr_regadd_translate(struct rte_swx_pipeline *p,
4000 struct action *action,
4003 struct instruction *instr,
4004 struct instruction_data *data __rte_unused)
4006 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
4008 struct field *fidx, *fsrc;
4010 uint32_t idx_struct_id, idx_val, src_struct_id;
4012 CHECK(n_tokens == 4, EINVAL);
4014 r = regarray_find(p, regarray);
4017 /* REGADD_RHH, REGADD_RHM, REGADD_RMH, REGADD_RMM. */
4018 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4019 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4021 CHECK(!fidx->var_size, EINVAL);
4022 CHECK(!fsrc->var_size, EINVAL);
4024 instr->type = INSTR_REGADD_RMM;
4025 if (idx[0] == 'h' && src[0] != 'h')
4026 instr->type = INSTR_REGADD_RHM;
4027 if (idx[0] != 'h' && src[0] == 'h')
4028 instr->type = INSTR_REGADD_RMH;
4029 if (idx[0] == 'h' && src[0] == 'h')
4030 instr->type = INSTR_REGADD_RHH;
4032 instr->regarray.regarray_id = r->id;
4033 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4034 instr->regarray.idx.n_bits = fidx->n_bits;
4035 instr->regarray.idx.offset = fidx->offset / 8;
4036 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4037 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4038 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4042 /* REGADD_RHI, REGADD_RMI. */
4043 if (fidx && !fsrc) {
4044 CHECK(!fidx->var_size, EINVAL);
4046 src_val = strtoull(src, &src, 0);
4047 CHECK(!src[0], EINVAL);
4049 instr->type = INSTR_REGADD_RMI;
4051 instr->type = INSTR_REGADD_RHI;
4053 instr->regarray.regarray_id = r->id;
4054 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4055 instr->regarray.idx.n_bits = fidx->n_bits;
4056 instr->regarray.idx.offset = fidx->offset / 8;
4057 instr->regarray.dstsrc_val = src_val;
4061 /* REGADD_RIH, REGADD_RIM. */
4062 if (!fidx && fsrc) {
4063 idx_val = strtoul(idx, &idx, 0);
4064 CHECK(!idx[0], EINVAL);
4066 CHECK(!fsrc->var_size, EINVAL);
4068 instr->type = INSTR_REGADD_RIM;
4070 instr->type = INSTR_REGADD_RIH;
4072 instr->regarray.regarray_id = r->id;
4073 instr->regarray.idx_val = idx_val;
4074 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4075 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4076 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4081 src_val = strtoull(src, &src, 0);
4082 CHECK(!src[0], EINVAL);
4084 idx_val = strtoul(idx, &idx, 0);
4085 CHECK(!idx[0], EINVAL);
4087 instr->type = INSTR_REGADD_RII;
4088 instr->regarray.idx_val = idx_val;
4089 instr->regarray.dstsrc_val = src_val;
4094 instr_regprefetch_rh_exec(struct rte_swx_pipeline *p)
4096 struct thread *t = &p->threads[p->thread_id];
4097 struct instruction *ip = t->ip;
4100 __instr_regprefetch_rh_exec(p, t, ip);
4107 instr_regprefetch_rm_exec(struct rte_swx_pipeline *p)
4109 struct thread *t = &p->threads[p->thread_id];
4110 struct instruction *ip = t->ip;
4113 __instr_regprefetch_rm_exec(p, t, ip);
4120 instr_regprefetch_ri_exec(struct rte_swx_pipeline *p)
4122 struct thread *t = &p->threads[p->thread_id];
4123 struct instruction *ip = t->ip;
4126 __instr_regprefetch_ri_exec(p, t, ip);
4133 instr_regrd_hrh_exec(struct rte_swx_pipeline *p)
4135 struct thread *t = &p->threads[p->thread_id];
4136 struct instruction *ip = t->ip;
4139 __instr_regrd_hrh_exec(p, t, ip);
4146 instr_regrd_hrm_exec(struct rte_swx_pipeline *p)
4148 struct thread *t = &p->threads[p->thread_id];
4149 struct instruction *ip = t->ip;
4152 __instr_regrd_hrm_exec(p, t, ip);
4159 instr_regrd_mrh_exec(struct rte_swx_pipeline *p)
4161 struct thread *t = &p->threads[p->thread_id];
4162 struct instruction *ip = t->ip;
4165 __instr_regrd_mrh_exec(p, t, ip);
4172 instr_regrd_mrm_exec(struct rte_swx_pipeline *p)
4174 struct thread *t = &p->threads[p->thread_id];
4175 struct instruction *ip = t->ip;
4178 __instr_regrd_mrm_exec(p, t, ip);
4185 instr_regrd_hri_exec(struct rte_swx_pipeline *p)
4187 struct thread *t = &p->threads[p->thread_id];
4188 struct instruction *ip = t->ip;
4191 __instr_regrd_hri_exec(p, t, ip);
4198 instr_regrd_mri_exec(struct rte_swx_pipeline *p)
4200 struct thread *t = &p->threads[p->thread_id];
4201 struct instruction *ip = t->ip;
4204 __instr_regrd_mri_exec(p, t, ip);
4211 instr_regwr_rhh_exec(struct rte_swx_pipeline *p)
4213 struct thread *t = &p->threads[p->thread_id];
4214 struct instruction *ip = t->ip;
4217 __instr_regwr_rhh_exec(p, t, ip);
4224 instr_regwr_rhm_exec(struct rte_swx_pipeline *p)
4226 struct thread *t = &p->threads[p->thread_id];
4227 struct instruction *ip = t->ip;
4230 __instr_regwr_rhm_exec(p, t, ip);
4237 instr_regwr_rmh_exec(struct rte_swx_pipeline *p)
4239 struct thread *t = &p->threads[p->thread_id];
4240 struct instruction *ip = t->ip;
4243 __instr_regwr_rmh_exec(p, t, ip);
4250 instr_regwr_rmm_exec(struct rte_swx_pipeline *p)
4252 struct thread *t = &p->threads[p->thread_id];
4253 struct instruction *ip = t->ip;
4256 __instr_regwr_rmm_exec(p, t, ip);
4263 instr_regwr_rhi_exec(struct rte_swx_pipeline *p)
4265 struct thread *t = &p->threads[p->thread_id];
4266 struct instruction *ip = t->ip;
4269 __instr_regwr_rhi_exec(p, t, ip);
4276 instr_regwr_rmi_exec(struct rte_swx_pipeline *p)
4278 struct thread *t = &p->threads[p->thread_id];
4279 struct instruction *ip = t->ip;
4282 __instr_regwr_rmi_exec(p, t, ip);
4289 instr_regwr_rih_exec(struct rte_swx_pipeline *p)
4291 struct thread *t = &p->threads[p->thread_id];
4292 struct instruction *ip = t->ip;
4295 __instr_regwr_rih_exec(p, t, ip);
4302 instr_regwr_rim_exec(struct rte_swx_pipeline *p)
4304 struct thread *t = &p->threads[p->thread_id];
4305 struct instruction *ip = t->ip;
4308 __instr_regwr_rim_exec(p, t, ip);
4315 instr_regwr_rii_exec(struct rte_swx_pipeline *p)
4317 struct thread *t = &p->threads[p->thread_id];
4318 struct instruction *ip = t->ip;
4321 __instr_regwr_rii_exec(p, t, ip);
4328 instr_regadd_rhh_exec(struct rte_swx_pipeline *p)
4330 struct thread *t = &p->threads[p->thread_id];
4331 struct instruction *ip = t->ip;
4334 __instr_regadd_rhh_exec(p, t, ip);
4341 instr_regadd_rhm_exec(struct rte_swx_pipeline *p)
4343 struct thread *t = &p->threads[p->thread_id];
4344 struct instruction *ip = t->ip;
4347 __instr_regadd_rhm_exec(p, t, ip);
4354 instr_regadd_rmh_exec(struct rte_swx_pipeline *p)
4356 struct thread *t = &p->threads[p->thread_id];
4357 struct instruction *ip = t->ip;
4360 __instr_regadd_rmh_exec(p, t, ip);
4367 instr_regadd_rmm_exec(struct rte_swx_pipeline *p)
4369 struct thread *t = &p->threads[p->thread_id];
4370 struct instruction *ip = t->ip;
4373 __instr_regadd_rmm_exec(p, t, ip);
4380 instr_regadd_rhi_exec(struct rte_swx_pipeline *p)
4382 struct thread *t = &p->threads[p->thread_id];
4383 struct instruction *ip = t->ip;
4386 __instr_regadd_rhi_exec(p, t, ip);
4393 instr_regadd_rmi_exec(struct rte_swx_pipeline *p)
4395 struct thread *t = &p->threads[p->thread_id];
4396 struct instruction *ip = t->ip;
4399 __instr_regadd_rmi_exec(p, t, ip);
4406 instr_regadd_rih_exec(struct rte_swx_pipeline *p)
4408 struct thread *t = &p->threads[p->thread_id];
4409 struct instruction *ip = t->ip;
4412 __instr_regadd_rih_exec(p, t, ip);
4419 instr_regadd_rim_exec(struct rte_swx_pipeline *p)
4421 struct thread *t = &p->threads[p->thread_id];
4422 struct instruction *ip = t->ip;
4425 __instr_regadd_rim_exec(p, t, ip);
4432 instr_regadd_rii_exec(struct rte_swx_pipeline *p)
4434 struct thread *t = &p->threads[p->thread_id];
4435 struct instruction *ip = t->ip;
4438 __instr_regadd_rii_exec(p, t, ip);
4447 static struct metarray *
4448 metarray_find(struct rte_swx_pipeline *p, const char *name);
4451 instr_metprefetch_translate(struct rte_swx_pipeline *p,
4452 struct action *action,
4455 struct instruction *instr,
4456 struct instruction_data *data __rte_unused)
4458 char *metarray = tokens[1], *idx = tokens[2];
4461 uint32_t idx_struct_id, idx_val;
4463 CHECK(n_tokens == 3, EINVAL);
4465 m = metarray_find(p, metarray);
4468 /* METPREFETCH_H, METPREFETCH_M. */
4469 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4471 CHECK(!fidx->var_size, EINVAL);
4473 instr->type = INSTR_METPREFETCH_M;
4475 instr->type = INSTR_METPREFETCH_H;
4477 instr->meter.metarray_id = m->id;
4478 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4479 instr->meter.idx.n_bits = fidx->n_bits;
4480 instr->meter.idx.offset = fidx->offset / 8;
4484 /* METPREFETCH_I. */
4485 idx_val = strtoul(idx, &idx, 0);
4486 CHECK(!idx[0], EINVAL);
4488 instr->type = INSTR_METPREFETCH_I;
4489 instr->meter.metarray_id = m->id;
4490 instr->meter.idx_val = idx_val;
4495 instr_meter_translate(struct rte_swx_pipeline *p,
4496 struct action *action,
4499 struct instruction *instr,
4500 struct instruction_data *data __rte_unused)
4502 char *metarray = tokens[1], *idx = tokens[2], *length = tokens[3];
4503 char *color_in = tokens[4], *color_out = tokens[5];
4505 struct field *fidx, *flength, *fcin, *fcout;
4506 uint32_t idx_struct_id, length_struct_id;
4507 uint32_t color_in_struct_id, color_out_struct_id;
4509 CHECK(n_tokens == 6, EINVAL);
4511 m = metarray_find(p, metarray);
4514 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4516 flength = struct_field_parse(p, action, length, &length_struct_id);
4517 CHECK(flength, EINVAL);
4518 CHECK(!flength->var_size, EINVAL);
4520 fcin = struct_field_parse(p, action, color_in, &color_in_struct_id);
4522 fcout = struct_field_parse(p, NULL, color_out, &color_out_struct_id);
4523 CHECK(fcout, EINVAL);
4524 CHECK(!fcout->var_size, EINVAL);
4526 /* index = HMEFT, length = HMEFT, color_in = MEFT, color_out = MEF. */
4528 CHECK(!fidx->var_size, EINVAL);
4529 CHECK(!fcin->var_size, EINVAL);
4531 instr->type = INSTR_METER_MMM;
4532 if (idx[0] == 'h' && length[0] == 'h')
4533 instr->type = INSTR_METER_HHM;
4534 if (idx[0] == 'h' && length[0] != 'h')
4535 instr->type = INSTR_METER_HMM;
4536 if (idx[0] != 'h' && length[0] == 'h')
4537 instr->type = INSTR_METER_MHM;
4539 instr->meter.metarray_id = m->id;
4541 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4542 instr->meter.idx.n_bits = fidx->n_bits;
4543 instr->meter.idx.offset = fidx->offset / 8;
4545 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4546 instr->meter.length.n_bits = flength->n_bits;
4547 instr->meter.length.offset = flength->offset / 8;
4549 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
4550 instr->meter.color_in.n_bits = fcin->n_bits;
4551 instr->meter.color_in.offset = fcin->offset / 8;
4553 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4554 instr->meter.color_out.n_bits = fcout->n_bits;
4555 instr->meter.color_out.offset = fcout->offset / 8;
4558 /* index = HMEFT, length = HMEFT, color_in = I, color_out = MEF. */
4559 if (fidx && !fcin) {
4560 uint32_t color_in_val;
4562 CHECK(!fidx->var_size, EINVAL);
4564 color_in_val = strtoul(color_in, &color_in, 0);
4565 CHECK(!color_in[0], EINVAL);
4567 instr->type = INSTR_METER_MMI;
4568 if (idx[0] == 'h' && length[0] == 'h')
4569 instr->type = INSTR_METER_HHI;
4570 if (idx[0] == 'h' && length[0] != 'h')
4571 instr->type = INSTR_METER_HMI;
4572 if (idx[0] != 'h' && length[0] == 'h')
4573 instr->type = INSTR_METER_MHI;
4575 instr->meter.metarray_id = m->id;
4577 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4578 instr->meter.idx.n_bits = fidx->n_bits;
4579 instr->meter.idx.offset = fidx->offset / 8;
4581 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4582 instr->meter.length.n_bits = flength->n_bits;
4583 instr->meter.length.offset = flength->offset / 8;
4585 instr->meter.color_in_val = color_in_val;
4587 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4588 instr->meter.color_out.n_bits = fcout->n_bits;
4589 instr->meter.color_out.offset = fcout->offset / 8;
4592 /* index = I, length = HMEFT, color_in = MEFT, color_out = MEF. */
4593 if (!fidx && fcin) {
4596 idx_val = strtoul(idx, &idx, 0);
4597 CHECK(!idx[0], EINVAL);
4599 CHECK(!fcin->var_size, EINVAL);
4601 instr->type = INSTR_METER_IMM;
4602 if (length[0] == 'h')
4603 instr->type = INSTR_METER_IHM;
4605 instr->meter.metarray_id = m->id;
4607 instr->meter.idx_val = idx_val;
4609 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4610 instr->meter.length.n_bits = flength->n_bits;
4611 instr->meter.length.offset = flength->offset / 8;
4613 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
4614 instr->meter.color_in.n_bits = fcin->n_bits;
4615 instr->meter.color_in.offset = fcin->offset / 8;
4617 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4618 instr->meter.color_out.n_bits = fcout->n_bits;
4619 instr->meter.color_out.offset = fcout->offset / 8;
4622 /* index = I, length = HMEFT, color_in = I, color_out = MEF. */
4623 if (!fidx && !fcin) {
4624 uint32_t idx_val, color_in_val;
4626 idx_val = strtoul(idx, &idx, 0);
4627 CHECK(!idx[0], EINVAL);
4629 color_in_val = strtoul(color_in, &color_in, 0);
4630 CHECK(!color_in[0], EINVAL);
4632 instr->type = INSTR_METER_IMI;
4633 if (length[0] == 'h')
4634 instr->type = INSTR_METER_IHI;
4636 instr->meter.metarray_id = m->id;
4638 instr->meter.idx_val = idx_val;
4640 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4641 instr->meter.length.n_bits = flength->n_bits;
4642 instr->meter.length.offset = flength->offset / 8;
4644 instr->meter.color_in_val = color_in_val;
4646 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4647 instr->meter.color_out.n_bits = fcout->n_bits;
4648 instr->meter.color_out.offset = fcout->offset / 8;
4655 instr_metprefetch_h_exec(struct rte_swx_pipeline *p)
4657 struct thread *t = &p->threads[p->thread_id];
4658 struct instruction *ip = t->ip;
4661 __instr_metprefetch_h_exec(p, t, ip);
4668 instr_metprefetch_m_exec(struct rte_swx_pipeline *p)
4670 struct thread *t = &p->threads[p->thread_id];
4671 struct instruction *ip = t->ip;
4674 __instr_metprefetch_m_exec(p, t, ip);
4681 instr_metprefetch_i_exec(struct rte_swx_pipeline *p)
4683 struct thread *t = &p->threads[p->thread_id];
4684 struct instruction *ip = t->ip;
4687 __instr_metprefetch_i_exec(p, t, ip);
4694 instr_meter_hhm_exec(struct rte_swx_pipeline *p)
4696 struct thread *t = &p->threads[p->thread_id];
4697 struct instruction *ip = t->ip;
4700 __instr_meter_hhm_exec(p, t, ip);
4707 instr_meter_hhi_exec(struct rte_swx_pipeline *p)
4709 struct thread *t = &p->threads[p->thread_id];
4710 struct instruction *ip = t->ip;
4713 __instr_meter_hhi_exec(p, t, ip);
4720 instr_meter_hmm_exec(struct rte_swx_pipeline *p)
4722 struct thread *t = &p->threads[p->thread_id];
4723 struct instruction *ip = t->ip;
4726 __instr_meter_hmm_exec(p, t, ip);
4733 instr_meter_hmi_exec(struct rte_swx_pipeline *p)
4735 struct thread *t = &p->threads[p->thread_id];
4736 struct instruction *ip = t->ip;
4739 __instr_meter_hmi_exec(p, t, ip);
4746 instr_meter_mhm_exec(struct rte_swx_pipeline *p)
4748 struct thread *t = &p->threads[p->thread_id];
4749 struct instruction *ip = t->ip;
4752 __instr_meter_mhm_exec(p, t, ip);
4759 instr_meter_mhi_exec(struct rte_swx_pipeline *p)
4761 struct thread *t = &p->threads[p->thread_id];
4762 struct instruction *ip = t->ip;
4765 __instr_meter_mhi_exec(p, t, ip);
4772 instr_meter_mmm_exec(struct rte_swx_pipeline *p)
4774 struct thread *t = &p->threads[p->thread_id];
4775 struct instruction *ip = t->ip;
4778 __instr_meter_mmm_exec(p, t, ip);
4785 instr_meter_mmi_exec(struct rte_swx_pipeline *p)
4787 struct thread *t = &p->threads[p->thread_id];
4788 struct instruction *ip = t->ip;
4791 __instr_meter_mmi_exec(p, t, ip);
4798 instr_meter_ihm_exec(struct rte_swx_pipeline *p)
4800 struct thread *t = &p->threads[p->thread_id];
4801 struct instruction *ip = t->ip;
4804 __instr_meter_ihm_exec(p, t, ip);
4811 instr_meter_ihi_exec(struct rte_swx_pipeline *p)
4813 struct thread *t = &p->threads[p->thread_id];
4814 struct instruction *ip = t->ip;
4817 __instr_meter_ihi_exec(p, t, ip);
4824 instr_meter_imm_exec(struct rte_swx_pipeline *p)
4826 struct thread *t = &p->threads[p->thread_id];
4827 struct instruction *ip = t->ip;
4830 __instr_meter_imm_exec(p, t, ip);
4837 instr_meter_imi_exec(struct rte_swx_pipeline *p)
4839 struct thread *t = &p->threads[p->thread_id];
4840 struct instruction *ip = t->ip;
4843 __instr_meter_imi_exec(p, t, ip);
4853 instr_jmp_translate(struct rte_swx_pipeline *p __rte_unused,
4854 struct action *action __rte_unused,
4857 struct instruction *instr,
4858 struct instruction_data *data)
4860 CHECK(n_tokens == 2, EINVAL);
4862 strcpy(data->jmp_label, tokens[1]);
4864 instr->type = INSTR_JMP;
4865 instr->jmp.ip = NULL; /* Resolved later. */
4870 instr_jmp_valid_translate(struct rte_swx_pipeline *p,
4871 struct action *action __rte_unused,
4874 struct instruction *instr,
4875 struct instruction_data *data)
4879 CHECK(n_tokens == 3, EINVAL);
4881 strcpy(data->jmp_label, tokens[1]);
4883 h = header_parse(p, tokens[2]);
4886 instr->type = INSTR_JMP_VALID;
4887 instr->jmp.ip = NULL; /* Resolved later. */
4888 instr->jmp.header_id = h->id;
4893 instr_jmp_invalid_translate(struct rte_swx_pipeline *p,
4894 struct action *action __rte_unused,
4897 struct instruction *instr,
4898 struct instruction_data *data)
4902 CHECK(n_tokens == 3, EINVAL);
4904 strcpy(data->jmp_label, tokens[1]);
4906 h = header_parse(p, tokens[2]);
4909 instr->type = INSTR_JMP_INVALID;
4910 instr->jmp.ip = NULL; /* Resolved later. */
4911 instr->jmp.header_id = h->id;
4916 instr_jmp_hit_translate(struct rte_swx_pipeline *p __rte_unused,
4917 struct action *action,
4920 struct instruction *instr,
4921 struct instruction_data *data)
4923 CHECK(!action, EINVAL);
4924 CHECK(n_tokens == 2, EINVAL);
4926 strcpy(data->jmp_label, tokens[1]);
4928 instr->type = INSTR_JMP_HIT;
4929 instr->jmp.ip = NULL; /* Resolved later. */
4934 instr_jmp_miss_translate(struct rte_swx_pipeline *p __rte_unused,
4935 struct action *action,
4938 struct instruction *instr,
4939 struct instruction_data *data)
4941 CHECK(!action, EINVAL);
4942 CHECK(n_tokens == 2, EINVAL);
4944 strcpy(data->jmp_label, tokens[1]);
4946 instr->type = INSTR_JMP_MISS;
4947 instr->jmp.ip = NULL; /* Resolved later. */
4952 instr_jmp_action_hit_translate(struct rte_swx_pipeline *p,
4953 struct action *action,
4956 struct instruction *instr,
4957 struct instruction_data *data)
4961 CHECK(!action, EINVAL);
4962 CHECK(n_tokens == 3, EINVAL);
4964 strcpy(data->jmp_label, tokens[1]);
4966 a = action_find(p, tokens[2]);
4969 instr->type = INSTR_JMP_ACTION_HIT;
4970 instr->jmp.ip = NULL; /* Resolved later. */
4971 instr->jmp.action_id = a->id;
4976 instr_jmp_action_miss_translate(struct rte_swx_pipeline *p,
4977 struct action *action,
4980 struct instruction *instr,
4981 struct instruction_data *data)
4985 CHECK(!action, EINVAL);
4986 CHECK(n_tokens == 3, EINVAL);
4988 strcpy(data->jmp_label, tokens[1]);
4990 a = action_find(p, tokens[2]);
4993 instr->type = INSTR_JMP_ACTION_MISS;
4994 instr->jmp.ip = NULL; /* Resolved later. */
4995 instr->jmp.action_id = a->id;
5000 instr_jmp_eq_translate(struct rte_swx_pipeline *p,
5001 struct action *action,
5004 struct instruction *instr,
5005 struct instruction_data *data)
5007 char *a = tokens[2], *b = tokens[3];
5008 struct field *fa, *fb;
5010 uint32_t a_struct_id, b_struct_id;
5012 CHECK(n_tokens == 4, EINVAL);
5014 strcpy(data->jmp_label, tokens[1]);
5016 fa = struct_field_parse(p, action, a, &a_struct_id);
5018 CHECK(!fa->var_size, EINVAL);
5020 /* JMP_EQ, JMP_EQ_MH, JMP_EQ_HM, JMP_EQ_HH. */
5021 fb = struct_field_parse(p, action, b, &b_struct_id);
5023 CHECK(!fb->var_size, EINVAL);
5025 instr->type = INSTR_JMP_EQ;
5026 if (a[0] != 'h' && b[0] == 'h')
5027 instr->type = INSTR_JMP_EQ_MH;
5028 if (a[0] == 'h' && b[0] != 'h')
5029 instr->type = INSTR_JMP_EQ_HM;
5030 if (a[0] == 'h' && b[0] == 'h')
5031 instr->type = INSTR_JMP_EQ_HH;
5032 instr->jmp.ip = NULL; /* Resolved later. */
5034 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5035 instr->jmp.a.n_bits = fa->n_bits;
5036 instr->jmp.a.offset = fa->offset / 8;
5037 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5038 instr->jmp.b.n_bits = fb->n_bits;
5039 instr->jmp.b.offset = fb->offset / 8;
5044 b_val = strtoull(b, &b, 0);
5045 CHECK(!b[0], EINVAL);
5048 b_val = hton64(b_val) >> (64 - fa->n_bits);
5050 instr->type = INSTR_JMP_EQ_I;
5051 instr->jmp.ip = NULL; /* Resolved later. */
5052 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5053 instr->jmp.a.n_bits = fa->n_bits;
5054 instr->jmp.a.offset = fa->offset / 8;
5055 instr->jmp.b_val = b_val;
5060 instr_jmp_neq_translate(struct rte_swx_pipeline *p,
5061 struct action *action,
5064 struct instruction *instr,
5065 struct instruction_data *data)
5067 char *a = tokens[2], *b = tokens[3];
5068 struct field *fa, *fb;
5070 uint32_t a_struct_id, b_struct_id;
5072 CHECK(n_tokens == 4, EINVAL);
5074 strcpy(data->jmp_label, tokens[1]);
5076 fa = struct_field_parse(p, action, a, &a_struct_id);
5078 CHECK(!fa->var_size, EINVAL);
5080 /* JMP_NEQ, JMP_NEQ_MH, JMP_NEQ_HM, JMP_NEQ_HH. */
5081 fb = struct_field_parse(p, action, b, &b_struct_id);
5083 CHECK(!fb->var_size, EINVAL);
5085 instr->type = INSTR_JMP_NEQ;
5086 if (a[0] != 'h' && b[0] == 'h')
5087 instr->type = INSTR_JMP_NEQ_MH;
5088 if (a[0] == 'h' && b[0] != 'h')
5089 instr->type = INSTR_JMP_NEQ_HM;
5090 if (a[0] == 'h' && b[0] == 'h')
5091 instr->type = INSTR_JMP_NEQ_HH;
5092 instr->jmp.ip = NULL; /* Resolved later. */
5094 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5095 instr->jmp.a.n_bits = fa->n_bits;
5096 instr->jmp.a.offset = fa->offset / 8;
5097 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5098 instr->jmp.b.n_bits = fb->n_bits;
5099 instr->jmp.b.offset = fb->offset / 8;
5104 b_val = strtoull(b, &b, 0);
5105 CHECK(!b[0], EINVAL);
5108 b_val = hton64(b_val) >> (64 - fa->n_bits);
5110 instr->type = INSTR_JMP_NEQ_I;
5111 instr->jmp.ip = NULL; /* Resolved later. */
5112 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5113 instr->jmp.a.n_bits = fa->n_bits;
5114 instr->jmp.a.offset = fa->offset / 8;
5115 instr->jmp.b_val = b_val;
5120 instr_jmp_lt_translate(struct rte_swx_pipeline *p,
5121 struct action *action,
5124 struct instruction *instr,
5125 struct instruction_data *data)
5127 char *a = tokens[2], *b = tokens[3];
5128 struct field *fa, *fb;
5130 uint32_t a_struct_id, b_struct_id;
5132 CHECK(n_tokens == 4, EINVAL);
5134 strcpy(data->jmp_label, tokens[1]);
5136 fa = struct_field_parse(p, action, a, &a_struct_id);
5138 CHECK(!fa->var_size, EINVAL);
5140 /* JMP_LT, JMP_LT_MH, JMP_LT_HM, JMP_LT_HH. */
5141 fb = struct_field_parse(p, action, b, &b_struct_id);
5143 CHECK(!fb->var_size, EINVAL);
5145 instr->type = INSTR_JMP_LT;
5146 if (a[0] == 'h' && b[0] != 'h')
5147 instr->type = INSTR_JMP_LT_HM;
5148 if (a[0] != 'h' && b[0] == 'h')
5149 instr->type = INSTR_JMP_LT_MH;
5150 if (a[0] == 'h' && b[0] == 'h')
5151 instr->type = INSTR_JMP_LT_HH;
5152 instr->jmp.ip = NULL; /* Resolved later. */
5154 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5155 instr->jmp.a.n_bits = fa->n_bits;
5156 instr->jmp.a.offset = fa->offset / 8;
5157 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5158 instr->jmp.b.n_bits = fb->n_bits;
5159 instr->jmp.b.offset = fb->offset / 8;
5163 /* JMP_LT_MI, JMP_LT_HI. */
5164 b_val = strtoull(b, &b, 0);
5165 CHECK(!b[0], EINVAL);
5167 instr->type = INSTR_JMP_LT_MI;
5169 instr->type = INSTR_JMP_LT_HI;
5170 instr->jmp.ip = NULL; /* Resolved later. */
5172 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5173 instr->jmp.a.n_bits = fa->n_bits;
5174 instr->jmp.a.offset = fa->offset / 8;
5175 instr->jmp.b_val = b_val;
5180 instr_jmp_gt_translate(struct rte_swx_pipeline *p,
5181 struct action *action,
5184 struct instruction *instr,
5185 struct instruction_data *data)
5187 char *a = tokens[2], *b = tokens[3];
5188 struct field *fa, *fb;
5190 uint32_t a_struct_id, b_struct_id;
5192 CHECK(n_tokens == 4, EINVAL);
5194 strcpy(data->jmp_label, tokens[1]);
5196 fa = struct_field_parse(p, action, a, &a_struct_id);
5198 CHECK(!fa->var_size, EINVAL);
5200 /* JMP_GT, JMP_GT_MH, JMP_GT_HM, JMP_GT_HH. */
5201 fb = struct_field_parse(p, action, b, &b_struct_id);
5203 CHECK(!fb->var_size, EINVAL);
5205 instr->type = INSTR_JMP_GT;
5206 if (a[0] == 'h' && b[0] != 'h')
5207 instr->type = INSTR_JMP_GT_HM;
5208 if (a[0] != 'h' && b[0] == 'h')
5209 instr->type = INSTR_JMP_GT_MH;
5210 if (a[0] == 'h' && b[0] == 'h')
5211 instr->type = INSTR_JMP_GT_HH;
5212 instr->jmp.ip = NULL; /* Resolved later. */
5214 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5215 instr->jmp.a.n_bits = fa->n_bits;
5216 instr->jmp.a.offset = fa->offset / 8;
5217 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5218 instr->jmp.b.n_bits = fb->n_bits;
5219 instr->jmp.b.offset = fb->offset / 8;
5223 /* JMP_GT_MI, JMP_GT_HI. */
5224 b_val = strtoull(b, &b, 0);
5225 CHECK(!b[0], EINVAL);
5227 instr->type = INSTR_JMP_GT_MI;
5229 instr->type = INSTR_JMP_GT_HI;
5230 instr->jmp.ip = NULL; /* Resolved later. */
5232 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5233 instr->jmp.a.n_bits = fa->n_bits;
5234 instr->jmp.a.offset = fa->offset / 8;
5235 instr->jmp.b_val = b_val;
5240 instr_jmp_exec(struct rte_swx_pipeline *p)
5242 struct thread *t = &p->threads[p->thread_id];
5243 struct instruction *ip = t->ip;
5245 TRACE("[Thread %2u] jmp\n", p->thread_id);
5247 thread_ip_set(t, ip->jmp.ip);
5251 instr_jmp_valid_exec(struct rte_swx_pipeline *p)
5253 struct thread *t = &p->threads[p->thread_id];
5254 struct instruction *ip = t->ip;
5255 uint32_t header_id = ip->jmp.header_id;
5257 TRACE("[Thread %2u] jmpv\n", p->thread_id);
5259 t->ip = HEADER_VALID(t, header_id) ? ip->jmp.ip : (t->ip + 1);
5263 instr_jmp_invalid_exec(struct rte_swx_pipeline *p)
5265 struct thread *t = &p->threads[p->thread_id];
5266 struct instruction *ip = t->ip;
5267 uint32_t header_id = ip->jmp.header_id;
5269 TRACE("[Thread %2u] jmpnv\n", p->thread_id);
5271 t->ip = HEADER_VALID(t, header_id) ? (t->ip + 1) : ip->jmp.ip;
5275 instr_jmp_hit_exec(struct rte_swx_pipeline *p)
5277 struct thread *t = &p->threads[p->thread_id];
5278 struct instruction *ip = t->ip;
5279 struct instruction *ip_next[] = {t->ip + 1, ip->jmp.ip};
5281 TRACE("[Thread %2u] jmph\n", p->thread_id);
5283 t->ip = ip_next[t->hit];
5287 instr_jmp_miss_exec(struct rte_swx_pipeline *p)
5289 struct thread *t = &p->threads[p->thread_id];
5290 struct instruction *ip = t->ip;
5291 struct instruction *ip_next[] = {ip->jmp.ip, t->ip + 1};
5293 TRACE("[Thread %2u] jmpnh\n", p->thread_id);
5295 t->ip = ip_next[t->hit];
5299 instr_jmp_action_hit_exec(struct rte_swx_pipeline *p)
5301 struct thread *t = &p->threads[p->thread_id];
5302 struct instruction *ip = t->ip;
5304 TRACE("[Thread %2u] jmpa\n", p->thread_id);
5306 t->ip = (ip->jmp.action_id == t->action_id) ? ip->jmp.ip : (t->ip + 1);
5310 instr_jmp_action_miss_exec(struct rte_swx_pipeline *p)
5312 struct thread *t = &p->threads[p->thread_id];
5313 struct instruction *ip = t->ip;
5315 TRACE("[Thread %2u] jmpna\n", p->thread_id);
5317 t->ip = (ip->jmp.action_id == t->action_id) ? (t->ip + 1) : ip->jmp.ip;
5321 instr_jmp_eq_exec(struct rte_swx_pipeline *p)
5323 struct thread *t = &p->threads[p->thread_id];
5324 struct instruction *ip = t->ip;
5326 TRACE("[Thread %2u] jmpeq\n", p->thread_id);
5332 instr_jmp_eq_mh_exec(struct rte_swx_pipeline *p)
5334 struct thread *t = &p->threads[p->thread_id];
5335 struct instruction *ip = t->ip;
5337 TRACE("[Thread %2u] jmpeq (mh)\n", p->thread_id);
5339 JMP_CMP_MH(t, ip, ==);
5343 instr_jmp_eq_hm_exec(struct rte_swx_pipeline *p)
5345 struct thread *t = &p->threads[p->thread_id];
5346 struct instruction *ip = t->ip;
5348 TRACE("[Thread %2u] jmpeq (hm)\n", p->thread_id);
5350 JMP_CMP_HM(t, ip, ==);
5354 instr_jmp_eq_hh_exec(struct rte_swx_pipeline *p)
5356 struct thread *t = &p->threads[p->thread_id];
5357 struct instruction *ip = t->ip;
5359 TRACE("[Thread %2u] jmpeq (hh)\n", p->thread_id);
5361 JMP_CMP_HH_FAST(t, ip, ==);
5365 instr_jmp_eq_i_exec(struct rte_swx_pipeline *p)
5367 struct thread *t = &p->threads[p->thread_id];
5368 struct instruction *ip = t->ip;
5370 TRACE("[Thread %2u] jmpeq (i)\n", p->thread_id);
5372 JMP_CMP_I(t, ip, ==);
5376 instr_jmp_neq_exec(struct rte_swx_pipeline *p)
5378 struct thread *t = &p->threads[p->thread_id];
5379 struct instruction *ip = t->ip;
5381 TRACE("[Thread %2u] jmpneq\n", p->thread_id);
5387 instr_jmp_neq_mh_exec(struct rte_swx_pipeline *p)
5389 struct thread *t = &p->threads[p->thread_id];
5390 struct instruction *ip = t->ip;
5392 TRACE("[Thread %2u] jmpneq (mh)\n", p->thread_id);
5394 JMP_CMP_MH(t, ip, !=);
5398 instr_jmp_neq_hm_exec(struct rte_swx_pipeline *p)
5400 struct thread *t = &p->threads[p->thread_id];
5401 struct instruction *ip = t->ip;
5403 TRACE("[Thread %2u] jmpneq (hm)\n", p->thread_id);
5405 JMP_CMP_HM(t, ip, !=);
5409 instr_jmp_neq_hh_exec(struct rte_swx_pipeline *p)
5411 struct thread *t = &p->threads[p->thread_id];
5412 struct instruction *ip = t->ip;
5414 TRACE("[Thread %2u] jmpneq (hh)\n", p->thread_id);
5416 JMP_CMP_HH_FAST(t, ip, !=);
5420 instr_jmp_neq_i_exec(struct rte_swx_pipeline *p)
5422 struct thread *t = &p->threads[p->thread_id];
5423 struct instruction *ip = t->ip;
5425 TRACE("[Thread %2u] jmpneq (i)\n", p->thread_id);
5427 JMP_CMP_I(t, ip, !=);
5431 instr_jmp_lt_exec(struct rte_swx_pipeline *p)
5433 struct thread *t = &p->threads[p->thread_id];
5434 struct instruction *ip = t->ip;
5436 TRACE("[Thread %2u] jmplt\n", p->thread_id);
5442 instr_jmp_lt_mh_exec(struct rte_swx_pipeline *p)
5444 struct thread *t = &p->threads[p->thread_id];
5445 struct instruction *ip = t->ip;
5447 TRACE("[Thread %2u] jmplt (mh)\n", p->thread_id);
5449 JMP_CMP_MH(t, ip, <);
5453 instr_jmp_lt_hm_exec(struct rte_swx_pipeline *p)
5455 struct thread *t = &p->threads[p->thread_id];
5456 struct instruction *ip = t->ip;
5458 TRACE("[Thread %2u] jmplt (hm)\n", p->thread_id);
5460 JMP_CMP_HM(t, ip, <);
5464 instr_jmp_lt_hh_exec(struct rte_swx_pipeline *p)
5466 struct thread *t = &p->threads[p->thread_id];
5467 struct instruction *ip = t->ip;
5469 TRACE("[Thread %2u] jmplt (hh)\n", p->thread_id);
5471 JMP_CMP_HH(t, ip, <);
5475 instr_jmp_lt_mi_exec(struct rte_swx_pipeline *p)
5477 struct thread *t = &p->threads[p->thread_id];
5478 struct instruction *ip = t->ip;
5480 TRACE("[Thread %2u] jmplt (mi)\n", p->thread_id);
5482 JMP_CMP_MI(t, ip, <);
5486 instr_jmp_lt_hi_exec(struct rte_swx_pipeline *p)
5488 struct thread *t = &p->threads[p->thread_id];
5489 struct instruction *ip = t->ip;
5491 TRACE("[Thread %2u] jmplt (hi)\n", p->thread_id);
5493 JMP_CMP_HI(t, ip, <);
5497 instr_jmp_gt_exec(struct rte_swx_pipeline *p)
5499 struct thread *t = &p->threads[p->thread_id];
5500 struct instruction *ip = t->ip;
5502 TRACE("[Thread %2u] jmpgt\n", p->thread_id);
5508 instr_jmp_gt_mh_exec(struct rte_swx_pipeline *p)
5510 struct thread *t = &p->threads[p->thread_id];
5511 struct instruction *ip = t->ip;
5513 TRACE("[Thread %2u] jmpgt (mh)\n", p->thread_id);
5515 JMP_CMP_MH(t, ip, >);
5519 instr_jmp_gt_hm_exec(struct rte_swx_pipeline *p)
5521 struct thread *t = &p->threads[p->thread_id];
5522 struct instruction *ip = t->ip;
5524 TRACE("[Thread %2u] jmpgt (hm)\n", p->thread_id);
5526 JMP_CMP_HM(t, ip, >);
5530 instr_jmp_gt_hh_exec(struct rte_swx_pipeline *p)
5532 struct thread *t = &p->threads[p->thread_id];
5533 struct instruction *ip = t->ip;
5535 TRACE("[Thread %2u] jmpgt (hh)\n", p->thread_id);
5537 JMP_CMP_HH(t, ip, >);
5541 instr_jmp_gt_mi_exec(struct rte_swx_pipeline *p)
5543 struct thread *t = &p->threads[p->thread_id];
5544 struct instruction *ip = t->ip;
5546 TRACE("[Thread %2u] jmpgt (mi)\n", p->thread_id);
5548 JMP_CMP_MI(t, ip, >);
5552 instr_jmp_gt_hi_exec(struct rte_swx_pipeline *p)
5554 struct thread *t = &p->threads[p->thread_id];
5555 struct instruction *ip = t->ip;
5557 TRACE("[Thread %2u] jmpgt (hi)\n", p->thread_id);
5559 JMP_CMP_HI(t, ip, >);
5566 instr_return_translate(struct rte_swx_pipeline *p __rte_unused,
5567 struct action *action,
5568 char **tokens __rte_unused,
5570 struct instruction *instr,
5571 struct instruction_data *data __rte_unused)
5573 CHECK(action, EINVAL);
5574 CHECK(n_tokens == 1, EINVAL);
5576 instr->type = INSTR_RETURN;
5581 instr_return_exec(struct rte_swx_pipeline *p)
5583 struct thread *t = &p->threads[p->thread_id];
5585 TRACE("[Thread %2u] return\n", p->thread_id);
5591 instr_translate(struct rte_swx_pipeline *p,
5592 struct action *action,
5594 struct instruction *instr,
5595 struct instruction_data *data)
5597 char *tokens[RTE_SWX_INSTRUCTION_TOKENS_MAX];
5598 int n_tokens = 0, tpos = 0;
5600 /* Parse the instruction string into tokens. */
5604 token = strtok_r(string, " \t\v", &string);
5608 CHECK(n_tokens < RTE_SWX_INSTRUCTION_TOKENS_MAX, EINVAL);
5609 CHECK_NAME(token, EINVAL);
5611 tokens[n_tokens] = token;
5615 CHECK(n_tokens, EINVAL);
5617 /* Handle the optional instruction label. */
5618 if ((n_tokens >= 2) && !strcmp(tokens[1], ":")) {
5619 strcpy(data->label, tokens[0]);
5622 CHECK(n_tokens - tpos, EINVAL);
5625 /* Identify the instruction type. */
5626 if (!strcmp(tokens[tpos], "rx"))
5627 return instr_rx_translate(p,
5634 if (!strcmp(tokens[tpos], "tx"))
5635 return instr_tx_translate(p,
5642 if (!strcmp(tokens[tpos], "drop"))
5643 return instr_drop_translate(p,
5650 if (!strcmp(tokens[tpos], "extract"))
5651 return instr_hdr_extract_translate(p,
5658 if (!strcmp(tokens[tpos], "lookahead"))
5659 return instr_hdr_lookahead_translate(p,
5666 if (!strcmp(tokens[tpos], "emit"))
5667 return instr_hdr_emit_translate(p,
5674 if (!strcmp(tokens[tpos], "validate"))
5675 return instr_hdr_validate_translate(p,
5682 if (!strcmp(tokens[tpos], "invalidate"))
5683 return instr_hdr_invalidate_translate(p,
5690 if (!strcmp(tokens[tpos], "mov"))
5691 return instr_mov_translate(p,
5698 if (!strcmp(tokens[tpos], "add"))
5699 return instr_alu_add_translate(p,
5706 if (!strcmp(tokens[tpos], "sub"))
5707 return instr_alu_sub_translate(p,
5714 if (!strcmp(tokens[tpos], "ckadd"))
5715 return instr_alu_ckadd_translate(p,
5722 if (!strcmp(tokens[tpos], "cksub"))
5723 return instr_alu_cksub_translate(p,
5730 if (!strcmp(tokens[tpos], "and"))
5731 return instr_alu_and_translate(p,
5738 if (!strcmp(tokens[tpos], "or"))
5739 return instr_alu_or_translate(p,
5746 if (!strcmp(tokens[tpos], "xor"))
5747 return instr_alu_xor_translate(p,
5754 if (!strcmp(tokens[tpos], "shl"))
5755 return instr_alu_shl_translate(p,
5762 if (!strcmp(tokens[tpos], "shr"))
5763 return instr_alu_shr_translate(p,
5770 if (!strcmp(tokens[tpos], "regprefetch"))
5771 return instr_regprefetch_translate(p,
5778 if (!strcmp(tokens[tpos], "regrd"))
5779 return instr_regrd_translate(p,
5786 if (!strcmp(tokens[tpos], "regwr"))
5787 return instr_regwr_translate(p,
5794 if (!strcmp(tokens[tpos], "regadd"))
5795 return instr_regadd_translate(p,
5802 if (!strcmp(tokens[tpos], "metprefetch"))
5803 return instr_metprefetch_translate(p,
5810 if (!strcmp(tokens[tpos], "meter"))
5811 return instr_meter_translate(p,
5818 if (!strcmp(tokens[tpos], "table"))
5819 return instr_table_translate(p,
5826 if (!strcmp(tokens[tpos], "learn"))
5827 return instr_learn_translate(p,
5834 if (!strcmp(tokens[tpos], "forget"))
5835 return instr_forget_translate(p,
5842 if (!strcmp(tokens[tpos], "extern"))
5843 return instr_extern_translate(p,
5850 if (!strcmp(tokens[tpos], "jmp"))
5851 return instr_jmp_translate(p,
5858 if (!strcmp(tokens[tpos], "jmpv"))
5859 return instr_jmp_valid_translate(p,
5866 if (!strcmp(tokens[tpos], "jmpnv"))
5867 return instr_jmp_invalid_translate(p,
5874 if (!strcmp(tokens[tpos], "jmph"))
5875 return instr_jmp_hit_translate(p,
5882 if (!strcmp(tokens[tpos], "jmpnh"))
5883 return instr_jmp_miss_translate(p,
5890 if (!strcmp(tokens[tpos], "jmpa"))
5891 return instr_jmp_action_hit_translate(p,
5898 if (!strcmp(tokens[tpos], "jmpna"))
5899 return instr_jmp_action_miss_translate(p,
5906 if (!strcmp(tokens[tpos], "jmpeq"))
5907 return instr_jmp_eq_translate(p,
5914 if (!strcmp(tokens[tpos], "jmpneq"))
5915 return instr_jmp_neq_translate(p,
5922 if (!strcmp(tokens[tpos], "jmplt"))
5923 return instr_jmp_lt_translate(p,
5930 if (!strcmp(tokens[tpos], "jmpgt"))
5931 return instr_jmp_gt_translate(p,
5938 if (!strcmp(tokens[tpos], "return"))
5939 return instr_return_translate(p,
5949 static struct instruction_data *
5950 label_find(struct instruction_data *data, uint32_t n, const char *label)
5954 for (i = 0; i < n; i++)
5955 if (!strcmp(label, data[i].label))
5962 label_is_used(struct instruction_data *data, uint32_t n, const char *label)
5964 uint32_t count = 0, i;
5969 for (i = 0; i < n; i++)
5970 if (!strcmp(label, data[i].jmp_label))
5977 instr_label_check(struct instruction_data *instruction_data,
5978 uint32_t n_instructions)
5982 /* Check that all instruction labels are unique. */
5983 for (i = 0; i < n_instructions; i++) {
5984 struct instruction_data *data = &instruction_data[i];
5985 char *label = data->label;
5991 for (j = i + 1; j < n_instructions; j++)
5992 CHECK(strcmp(label, instruction_data[j].label), EINVAL);
5995 /* Get users for each instruction label. */
5996 for (i = 0; i < n_instructions; i++) {
5997 struct instruction_data *data = &instruction_data[i];
5998 char *label = data->label;
6000 data->n_users = label_is_used(instruction_data,
6009 instr_jmp_resolve(struct instruction *instructions,
6010 struct instruction_data *instruction_data,
6011 uint32_t n_instructions)
6015 for (i = 0; i < n_instructions; i++) {
6016 struct instruction *instr = &instructions[i];
6017 struct instruction_data *data = &instruction_data[i];
6018 struct instruction_data *found;
6020 if (!instruction_is_jmp(instr))
6023 found = label_find(instruction_data,
6026 CHECK(found, EINVAL);
6028 instr->jmp.ip = &instructions[found - instruction_data];
6035 instr_verify(struct rte_swx_pipeline *p __rte_unused,
6037 struct instruction *instr,
6038 struct instruction_data *data __rte_unused,
6039 uint32_t n_instructions)
6042 enum instruction_type type;
6045 /* Check that the first instruction is rx. */
6046 CHECK(instr[0].type == INSTR_RX, EINVAL);
6048 /* Check that there is at least one tx instruction. */
6049 for (i = 0; i < n_instructions; i++) {
6050 type = instr[i].type;
6052 if (instruction_is_tx(type))
6055 CHECK(i < n_instructions, EINVAL);
6057 /* Check that the last instruction is either tx or unconditional
6060 type = instr[n_instructions - 1].type;
6061 CHECK(instruction_is_tx(type) || (type == INSTR_JMP), EINVAL);
6065 enum instruction_type type;
6068 /* Check that there is at least one return or tx instruction. */
6069 for (i = 0; i < n_instructions; i++) {
6070 type = instr[i].type;
6072 if ((type == INSTR_RETURN) || instruction_is_tx(type))
6075 CHECK(i < n_instructions, EINVAL);
6082 instr_compact(struct instruction *instructions,
6083 struct instruction_data *instruction_data,
6084 uint32_t n_instructions)
6086 uint32_t i, pos = 0;
6088 /* Eliminate the invalid instructions that have been optimized out. */
6089 for (i = 0; i < n_instructions; i++) {
6090 struct instruction *instr = &instructions[i];
6091 struct instruction_data *data = &instruction_data[i];
6097 memcpy(&instructions[pos], instr, sizeof(*instr));
6098 memcpy(&instruction_data[pos], data, sizeof(*data));
6108 instr_pattern_extract_many_search(struct instruction *instr,
6109 struct instruction_data *data,
6111 uint32_t *n_pattern_instr)
6115 for (i = 0; i < n_instr; i++) {
6116 if (data[i].invalid)
6119 if (instr[i].type != INSTR_HDR_EXTRACT)
6122 if (i == RTE_DIM(instr->io.hdr.header_id))
6125 if (i && data[i].n_users)
6132 *n_pattern_instr = i;
6137 instr_pattern_extract_many_replace(struct instruction *instr,
6138 struct instruction_data *data,
6143 for (i = 1; i < n_instr; i++) {
6145 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
6146 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
6147 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
6149 data[i].invalid = 1;
6154 instr_pattern_extract_many_optimize(struct instruction *instructions,
6155 struct instruction_data *instruction_data,
6156 uint32_t n_instructions)
6160 for (i = 0; i < n_instructions; ) {
6161 struct instruction *instr = &instructions[i];
6162 struct instruction_data *data = &instruction_data[i];
6163 uint32_t n_instr = 0;
6167 detected = instr_pattern_extract_many_search(instr,
6172 instr_pattern_extract_many_replace(instr,
6179 /* No pattern starting at the current instruction. */
6183 /* Eliminate the invalid instructions that have been optimized out. */
6184 n_instructions = instr_compact(instructions,
6188 return n_instructions;
6192 instr_pattern_emit_many_tx_search(struct instruction *instr,
6193 struct instruction_data *data,
6195 uint32_t *n_pattern_instr)
6199 for (i = 0; i < n_instr; i++) {
6200 if (data[i].invalid)
6203 if (instr[i].type != INSTR_HDR_EMIT)
6206 if (i == RTE_DIM(instr->io.hdr.header_id))
6209 if (i && data[i].n_users)
6216 if (instr[i].type != INSTR_TX)
6219 if (data[i].n_users)
6224 *n_pattern_instr = i;
6229 instr_pattern_emit_many_tx_replace(struct instruction *instr,
6230 struct instruction_data *data,
6235 /* Any emit instruction in addition to the first one. */
6236 for (i = 1; i < n_instr - 1; i++) {
6238 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
6239 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
6240 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
6242 data[i].invalid = 1;
6245 /* The TX instruction is the last one in the pattern. */
6247 instr[0].io.io.offset = instr[i].io.io.offset;
6248 instr[0].io.io.n_bits = instr[i].io.io.n_bits;
6249 data[i].invalid = 1;
6253 instr_pattern_emit_many_tx_optimize(struct instruction *instructions,
6254 struct instruction_data *instruction_data,
6255 uint32_t n_instructions)
6259 for (i = 0; i < n_instructions; ) {
6260 struct instruction *instr = &instructions[i];
6261 struct instruction_data *data = &instruction_data[i];
6262 uint32_t n_instr = 0;
6265 /* Emit many + TX. */
6266 detected = instr_pattern_emit_many_tx_search(instr,
6271 instr_pattern_emit_many_tx_replace(instr,
6278 /* No pattern starting at the current instruction. */
6282 /* Eliminate the invalid instructions that have been optimized out. */
6283 n_instructions = instr_compact(instructions,
6287 return n_instructions;
6291 action_arg_src_mov_count(struct action *a,
6293 struct instruction *instructions,
6294 struct instruction_data *instruction_data,
6295 uint32_t n_instructions);
6298 instr_pattern_mov_all_validate_search(struct rte_swx_pipeline *p,
6300 struct instruction *instr,
6301 struct instruction_data *data,
6303 struct instruction *instructions,
6304 struct instruction_data *instruction_data,
6305 uint32_t n_instructions,
6306 uint32_t *n_pattern_instr)
6309 uint32_t src_field_id, i, j;
6311 /* Prerequisites. */
6315 /* First instruction: MOV_HM. */
6316 if (data[0].invalid || (instr[0].type != INSTR_MOV_HM))
6319 h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
6320 if (!h || h->st->var_size)
6323 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
6324 if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
6327 if (src_field_id == a->st->n_fields)
6330 if (instr[0].mov.dst.offset ||
6331 (instr[0].mov.dst.n_bits != h->st->fields[0].n_bits) ||
6332 instr[0].mov.src.struct_id ||
6333 (instr[0].mov.src.n_bits != a->st->fields[src_field_id].n_bits) ||
6334 (instr[0].mov.dst.n_bits != instr[0].mov.src.n_bits))
6337 if ((n_instr < h->st->n_fields + 1) ||
6338 (a->st->n_fields < src_field_id + h->st->n_fields + 1))
6341 /* Subsequent instructions: MOV_HM. */
6342 for (i = 1; i < h->st->n_fields; i++)
6343 if (data[i].invalid ||
6345 (instr[i].type != INSTR_MOV_HM) ||
6346 (instr[i].mov.dst.struct_id != h->struct_id) ||
6347 (instr[i].mov.dst.offset != h->st->fields[i].offset / 8) ||
6348 (instr[i].mov.dst.n_bits != h->st->fields[i].n_bits) ||
6349 instr[i].mov.src.struct_id ||
6350 (instr[i].mov.src.offset != a->st->fields[src_field_id + i].offset / 8) ||
6351 (instr[i].mov.src.n_bits != a->st->fields[src_field_id + i].n_bits) ||
6352 (instr[i].mov.dst.n_bits != instr[i].mov.src.n_bits))
6355 /* Last instruction: HDR_VALIDATE. */
6356 if ((instr[i].type != INSTR_HDR_VALIDATE) ||
6357 (instr[i].valid.header_id != h->id))
6360 /* Check that none of the action args that are used as source for this
6361 * DMA transfer are not used as source in any other mov instruction.
6363 for (j = src_field_id; j < src_field_id + h->st->n_fields; j++) {
6366 n_users = action_arg_src_mov_count(a,
6375 *n_pattern_instr = 1 + i;
6380 instr_pattern_mov_all_validate_replace(struct rte_swx_pipeline *p,
6382 struct instruction *instr,
6383 struct instruction_data *data,
6387 uint32_t src_field_id, src_offset, i;
6389 /* Read from the instructions before they are modified. */
6390 h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
6394 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
6395 if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
6398 if (src_field_id == a->st->n_fields)
6401 src_offset = instr[0].mov.src.offset;
6403 /* Modify the instructions. */
6404 instr[0].type = INSTR_DMA_HT;
6405 instr[0].dma.dst.header_id[0] = h->id;
6406 instr[0].dma.dst.struct_id[0] = h->struct_id;
6407 instr[0].dma.src.offset[0] = (uint8_t)src_offset;
6408 instr[0].dma.n_bytes[0] = h->st->n_bits / 8;
6410 for (i = 1; i < n_instr; i++)
6411 data[i].invalid = 1;
6413 /* Update the endianness of the action arguments to header endianness. */
6414 for (i = 0; i < h->st->n_fields; i++)
6415 a->args_endianness[src_field_id + i] = 1;
6419 instr_pattern_mov_all_validate_optimize(struct rte_swx_pipeline *p,
6421 struct instruction *instructions,
6422 struct instruction_data *instruction_data,
6423 uint32_t n_instructions)
6428 return n_instructions;
6430 for (i = 0; i < n_instructions; ) {
6431 struct instruction *instr = &instructions[i];
6432 struct instruction_data *data = &instruction_data[i];
6433 uint32_t n_instr = 0;
6436 /* Mov all + validate. */
6437 detected = instr_pattern_mov_all_validate_search(p,
6447 instr_pattern_mov_all_validate_replace(p, a, instr, data, n_instr);
6452 /* No pattern starting at the current instruction. */
6456 /* Eliminate the invalid instructions that have been optimized out. */
6457 n_instructions = instr_compact(instructions,
6461 return n_instructions;
6465 instr_pattern_dma_many_search(struct instruction *instr,
6466 struct instruction_data *data,
6468 uint32_t *n_pattern_instr)
6472 for (i = 0; i < n_instr; i++) {
6473 if (data[i].invalid)
6476 if (instr[i].type != INSTR_DMA_HT)
6479 if (i == RTE_DIM(instr->dma.dst.header_id))
6482 if (i && data[i].n_users)
6489 *n_pattern_instr = i;
6494 instr_pattern_dma_many_replace(struct instruction *instr,
6495 struct instruction_data *data,
6500 for (i = 1; i < n_instr; i++) {
6502 instr[0].dma.dst.header_id[i] = instr[i].dma.dst.header_id[0];
6503 instr[0].dma.dst.struct_id[i] = instr[i].dma.dst.struct_id[0];
6504 instr[0].dma.src.offset[i] = instr[i].dma.src.offset[0];
6505 instr[0].dma.n_bytes[i] = instr[i].dma.n_bytes[0];
6507 data[i].invalid = 1;
6512 instr_pattern_dma_many_optimize(struct instruction *instructions,
6513 struct instruction_data *instruction_data,
6514 uint32_t n_instructions)
6518 for (i = 0; i < n_instructions; ) {
6519 struct instruction *instr = &instructions[i];
6520 struct instruction_data *data = &instruction_data[i];
6521 uint32_t n_instr = 0;
6525 detected = instr_pattern_dma_many_search(instr,
6530 instr_pattern_dma_many_replace(instr, data, n_instr);
6535 /* No pattern starting at the current instruction. */
6539 /* Eliminate the invalid instructions that have been optimized out. */
6540 n_instructions = instr_compact(instructions,
6544 return n_instructions;
6548 instr_optimize(struct rte_swx_pipeline *p,
6550 struct instruction *instructions,
6551 struct instruction_data *instruction_data,
6552 uint32_t n_instructions)
6555 n_instructions = instr_pattern_extract_many_optimize(instructions,
6559 /* Emit many + TX. */
6560 n_instructions = instr_pattern_emit_many_tx_optimize(instructions,
6564 /* Mov all + validate. */
6565 n_instructions = instr_pattern_mov_all_validate_optimize(p,
6572 n_instructions = instr_pattern_dma_many_optimize(instructions,
6576 return n_instructions;
6580 instruction_config(struct rte_swx_pipeline *p,
6582 const char **instructions,
6583 uint32_t n_instructions)
6585 struct instruction *instr = NULL;
6586 struct instruction_data *data = NULL;
6590 CHECK(n_instructions, EINVAL);
6591 CHECK(instructions, EINVAL);
6592 for (i = 0; i < n_instructions; i++)
6593 CHECK_INSTRUCTION(instructions[i], EINVAL);
6595 /* Memory allocation. */
6596 instr = calloc(n_instructions, sizeof(struct instruction));
6602 data = calloc(n_instructions, sizeof(struct instruction_data));
6608 for (i = 0; i < n_instructions; i++) {
6609 char *string = strdup(instructions[i]);
6615 err = instr_translate(p, a, string, &instr[i], &data[i]);
6624 err = instr_label_check(data, n_instructions);
6628 err = instr_verify(p, a, instr, data, n_instructions);
6632 n_instructions = instr_optimize(p, a, instr, data, n_instructions);
6634 err = instr_jmp_resolve(instr, data, n_instructions);
6639 a->instructions = instr;
6640 a->instruction_data = data;
6641 a->n_instructions = n_instructions;
6643 p->instructions = instr;
6644 p->instruction_data = data;
6645 p->n_instructions = n_instructions;
6656 static instr_exec_t instruction_table[] = {
6657 [INSTR_RX] = instr_rx_exec,
6658 [INSTR_TX] = instr_tx_exec,
6659 [INSTR_TX_I] = instr_tx_i_exec,
6660 [INSTR_DROP] = instr_drop_exec,
6662 [INSTR_HDR_EXTRACT] = instr_hdr_extract_exec,
6663 [INSTR_HDR_EXTRACT2] = instr_hdr_extract2_exec,
6664 [INSTR_HDR_EXTRACT3] = instr_hdr_extract3_exec,
6665 [INSTR_HDR_EXTRACT4] = instr_hdr_extract4_exec,
6666 [INSTR_HDR_EXTRACT5] = instr_hdr_extract5_exec,
6667 [INSTR_HDR_EXTRACT6] = instr_hdr_extract6_exec,
6668 [INSTR_HDR_EXTRACT7] = instr_hdr_extract7_exec,
6669 [INSTR_HDR_EXTRACT8] = instr_hdr_extract8_exec,
6670 [INSTR_HDR_EXTRACT_M] = instr_hdr_extract_m_exec,
6671 [INSTR_HDR_LOOKAHEAD] = instr_hdr_lookahead_exec,
6673 [INSTR_HDR_EMIT] = instr_hdr_emit_exec,
6674 [INSTR_HDR_EMIT_TX] = instr_hdr_emit_tx_exec,
6675 [INSTR_HDR_EMIT2_TX] = instr_hdr_emit2_tx_exec,
6676 [INSTR_HDR_EMIT3_TX] = instr_hdr_emit3_tx_exec,
6677 [INSTR_HDR_EMIT4_TX] = instr_hdr_emit4_tx_exec,
6678 [INSTR_HDR_EMIT5_TX] = instr_hdr_emit5_tx_exec,
6679 [INSTR_HDR_EMIT6_TX] = instr_hdr_emit6_tx_exec,
6680 [INSTR_HDR_EMIT7_TX] = instr_hdr_emit7_tx_exec,
6681 [INSTR_HDR_EMIT8_TX] = instr_hdr_emit8_tx_exec,
6683 [INSTR_HDR_VALIDATE] = instr_hdr_validate_exec,
6684 [INSTR_HDR_INVALIDATE] = instr_hdr_invalidate_exec,
6686 [INSTR_MOV] = instr_mov_exec,
6687 [INSTR_MOV_MH] = instr_mov_mh_exec,
6688 [INSTR_MOV_HM] = instr_mov_hm_exec,
6689 [INSTR_MOV_HH] = instr_mov_hh_exec,
6690 [INSTR_MOV_I] = instr_mov_i_exec,
6692 [INSTR_DMA_HT] = instr_dma_ht_exec,
6693 [INSTR_DMA_HT2] = instr_dma_ht2_exec,
6694 [INSTR_DMA_HT3] = instr_dma_ht3_exec,
6695 [INSTR_DMA_HT4] = instr_dma_ht4_exec,
6696 [INSTR_DMA_HT5] = instr_dma_ht5_exec,
6697 [INSTR_DMA_HT6] = instr_dma_ht6_exec,
6698 [INSTR_DMA_HT7] = instr_dma_ht7_exec,
6699 [INSTR_DMA_HT8] = instr_dma_ht8_exec,
6701 [INSTR_ALU_ADD] = instr_alu_add_exec,
6702 [INSTR_ALU_ADD_MH] = instr_alu_add_mh_exec,
6703 [INSTR_ALU_ADD_HM] = instr_alu_add_hm_exec,
6704 [INSTR_ALU_ADD_HH] = instr_alu_add_hh_exec,
6705 [INSTR_ALU_ADD_MI] = instr_alu_add_mi_exec,
6706 [INSTR_ALU_ADD_HI] = instr_alu_add_hi_exec,
6708 [INSTR_ALU_SUB] = instr_alu_sub_exec,
6709 [INSTR_ALU_SUB_MH] = instr_alu_sub_mh_exec,
6710 [INSTR_ALU_SUB_HM] = instr_alu_sub_hm_exec,
6711 [INSTR_ALU_SUB_HH] = instr_alu_sub_hh_exec,
6712 [INSTR_ALU_SUB_MI] = instr_alu_sub_mi_exec,
6713 [INSTR_ALU_SUB_HI] = instr_alu_sub_hi_exec,
6715 [INSTR_ALU_CKADD_FIELD] = instr_alu_ckadd_field_exec,
6716 [INSTR_ALU_CKADD_STRUCT] = instr_alu_ckadd_struct_exec,
6717 [INSTR_ALU_CKADD_STRUCT20] = instr_alu_ckadd_struct20_exec,
6718 [INSTR_ALU_CKSUB_FIELD] = instr_alu_cksub_field_exec,
6720 [INSTR_ALU_AND] = instr_alu_and_exec,
6721 [INSTR_ALU_AND_MH] = instr_alu_and_mh_exec,
6722 [INSTR_ALU_AND_HM] = instr_alu_and_hm_exec,
6723 [INSTR_ALU_AND_HH] = instr_alu_and_hh_exec,
6724 [INSTR_ALU_AND_I] = instr_alu_and_i_exec,
6726 [INSTR_ALU_OR] = instr_alu_or_exec,
6727 [INSTR_ALU_OR_MH] = instr_alu_or_mh_exec,
6728 [INSTR_ALU_OR_HM] = instr_alu_or_hm_exec,
6729 [INSTR_ALU_OR_HH] = instr_alu_or_hh_exec,
6730 [INSTR_ALU_OR_I] = instr_alu_or_i_exec,
6732 [INSTR_ALU_XOR] = instr_alu_xor_exec,
6733 [INSTR_ALU_XOR_MH] = instr_alu_xor_mh_exec,
6734 [INSTR_ALU_XOR_HM] = instr_alu_xor_hm_exec,
6735 [INSTR_ALU_XOR_HH] = instr_alu_xor_hh_exec,
6736 [INSTR_ALU_XOR_I] = instr_alu_xor_i_exec,
6738 [INSTR_ALU_SHL] = instr_alu_shl_exec,
6739 [INSTR_ALU_SHL_MH] = instr_alu_shl_mh_exec,
6740 [INSTR_ALU_SHL_HM] = instr_alu_shl_hm_exec,
6741 [INSTR_ALU_SHL_HH] = instr_alu_shl_hh_exec,
6742 [INSTR_ALU_SHL_MI] = instr_alu_shl_mi_exec,
6743 [INSTR_ALU_SHL_HI] = instr_alu_shl_hi_exec,
6745 [INSTR_ALU_SHR] = instr_alu_shr_exec,
6746 [INSTR_ALU_SHR_MH] = instr_alu_shr_mh_exec,
6747 [INSTR_ALU_SHR_HM] = instr_alu_shr_hm_exec,
6748 [INSTR_ALU_SHR_HH] = instr_alu_shr_hh_exec,
6749 [INSTR_ALU_SHR_MI] = instr_alu_shr_mi_exec,
6750 [INSTR_ALU_SHR_HI] = instr_alu_shr_hi_exec,
6752 [INSTR_REGPREFETCH_RH] = instr_regprefetch_rh_exec,
6753 [INSTR_REGPREFETCH_RM] = instr_regprefetch_rm_exec,
6754 [INSTR_REGPREFETCH_RI] = instr_regprefetch_ri_exec,
6756 [INSTR_REGRD_HRH] = instr_regrd_hrh_exec,
6757 [INSTR_REGRD_HRM] = instr_regrd_hrm_exec,
6758 [INSTR_REGRD_MRH] = instr_regrd_mrh_exec,
6759 [INSTR_REGRD_MRM] = instr_regrd_mrm_exec,
6760 [INSTR_REGRD_HRI] = instr_regrd_hri_exec,
6761 [INSTR_REGRD_MRI] = instr_regrd_mri_exec,
6763 [INSTR_REGWR_RHH] = instr_regwr_rhh_exec,
6764 [INSTR_REGWR_RHM] = instr_regwr_rhm_exec,
6765 [INSTR_REGWR_RMH] = instr_regwr_rmh_exec,
6766 [INSTR_REGWR_RMM] = instr_regwr_rmm_exec,
6767 [INSTR_REGWR_RHI] = instr_regwr_rhi_exec,
6768 [INSTR_REGWR_RMI] = instr_regwr_rmi_exec,
6769 [INSTR_REGWR_RIH] = instr_regwr_rih_exec,
6770 [INSTR_REGWR_RIM] = instr_regwr_rim_exec,
6771 [INSTR_REGWR_RII] = instr_regwr_rii_exec,
6773 [INSTR_REGADD_RHH] = instr_regadd_rhh_exec,
6774 [INSTR_REGADD_RHM] = instr_regadd_rhm_exec,
6775 [INSTR_REGADD_RMH] = instr_regadd_rmh_exec,
6776 [INSTR_REGADD_RMM] = instr_regadd_rmm_exec,
6777 [INSTR_REGADD_RHI] = instr_regadd_rhi_exec,
6778 [INSTR_REGADD_RMI] = instr_regadd_rmi_exec,
6779 [INSTR_REGADD_RIH] = instr_regadd_rih_exec,
6780 [INSTR_REGADD_RIM] = instr_regadd_rim_exec,
6781 [INSTR_REGADD_RII] = instr_regadd_rii_exec,
6783 [INSTR_METPREFETCH_H] = instr_metprefetch_h_exec,
6784 [INSTR_METPREFETCH_M] = instr_metprefetch_m_exec,
6785 [INSTR_METPREFETCH_I] = instr_metprefetch_i_exec,
6787 [INSTR_METER_HHM] = instr_meter_hhm_exec,
6788 [INSTR_METER_HHI] = instr_meter_hhi_exec,
6789 [INSTR_METER_HMM] = instr_meter_hmm_exec,
6790 [INSTR_METER_HMI] = instr_meter_hmi_exec,
6791 [INSTR_METER_MHM] = instr_meter_mhm_exec,
6792 [INSTR_METER_MHI] = instr_meter_mhi_exec,
6793 [INSTR_METER_MMM] = instr_meter_mmm_exec,
6794 [INSTR_METER_MMI] = instr_meter_mmi_exec,
6795 [INSTR_METER_IHM] = instr_meter_ihm_exec,
6796 [INSTR_METER_IHI] = instr_meter_ihi_exec,
6797 [INSTR_METER_IMM] = instr_meter_imm_exec,
6798 [INSTR_METER_IMI] = instr_meter_imi_exec,
6800 [INSTR_TABLE] = instr_table_exec,
6801 [INSTR_TABLE_AF] = instr_table_af_exec,
6802 [INSTR_SELECTOR] = instr_selector_exec,
6803 [INSTR_LEARNER] = instr_learner_exec,
6804 [INSTR_LEARNER_AF] = instr_learner_af_exec,
6805 [INSTR_LEARNER_LEARN] = instr_learn_exec,
6806 [INSTR_LEARNER_FORGET] = instr_forget_exec,
6807 [INSTR_EXTERN_OBJ] = instr_extern_obj_exec,
6808 [INSTR_EXTERN_FUNC] = instr_extern_func_exec,
6810 [INSTR_JMP] = instr_jmp_exec,
6811 [INSTR_JMP_VALID] = instr_jmp_valid_exec,
6812 [INSTR_JMP_INVALID] = instr_jmp_invalid_exec,
6813 [INSTR_JMP_HIT] = instr_jmp_hit_exec,
6814 [INSTR_JMP_MISS] = instr_jmp_miss_exec,
6815 [INSTR_JMP_ACTION_HIT] = instr_jmp_action_hit_exec,
6816 [INSTR_JMP_ACTION_MISS] = instr_jmp_action_miss_exec,
6818 [INSTR_JMP_EQ] = instr_jmp_eq_exec,
6819 [INSTR_JMP_EQ_MH] = instr_jmp_eq_mh_exec,
6820 [INSTR_JMP_EQ_HM] = instr_jmp_eq_hm_exec,
6821 [INSTR_JMP_EQ_HH] = instr_jmp_eq_hh_exec,
6822 [INSTR_JMP_EQ_I] = instr_jmp_eq_i_exec,
6824 [INSTR_JMP_NEQ] = instr_jmp_neq_exec,
6825 [INSTR_JMP_NEQ_MH] = instr_jmp_neq_mh_exec,
6826 [INSTR_JMP_NEQ_HM] = instr_jmp_neq_hm_exec,
6827 [INSTR_JMP_NEQ_HH] = instr_jmp_neq_hh_exec,
6828 [INSTR_JMP_NEQ_I] = instr_jmp_neq_i_exec,
6830 [INSTR_JMP_LT] = instr_jmp_lt_exec,
6831 [INSTR_JMP_LT_MH] = instr_jmp_lt_mh_exec,
6832 [INSTR_JMP_LT_HM] = instr_jmp_lt_hm_exec,
6833 [INSTR_JMP_LT_HH] = instr_jmp_lt_hh_exec,
6834 [INSTR_JMP_LT_MI] = instr_jmp_lt_mi_exec,
6835 [INSTR_JMP_LT_HI] = instr_jmp_lt_hi_exec,
6837 [INSTR_JMP_GT] = instr_jmp_gt_exec,
6838 [INSTR_JMP_GT_MH] = instr_jmp_gt_mh_exec,
6839 [INSTR_JMP_GT_HM] = instr_jmp_gt_hm_exec,
6840 [INSTR_JMP_GT_HH] = instr_jmp_gt_hh_exec,
6841 [INSTR_JMP_GT_MI] = instr_jmp_gt_mi_exec,
6842 [INSTR_JMP_GT_HI] = instr_jmp_gt_hi_exec,
6844 [INSTR_RETURN] = instr_return_exec,
6848 instruction_table_build(struct rte_swx_pipeline *p)
6850 p->instruction_table = calloc(RTE_SWX_PIPELINE_INSTRUCTION_TABLE_SIZE_MAX,
6851 sizeof(struct instr_exec_t *));
6852 if (!p->instruction_table)
6855 memcpy(p->instruction_table, instruction_table, sizeof(instruction_table));
6861 instruction_table_build_free(struct rte_swx_pipeline *p)
6863 if (!p->instruction_table)
6866 free(p->instruction_table);
6867 p->instruction_table = NULL;
6871 instruction_table_free(struct rte_swx_pipeline *p)
6873 instruction_table_build_free(p);
6877 instr_exec(struct rte_swx_pipeline *p)
6879 struct thread *t = &p->threads[p->thread_id];
6880 struct instruction *ip = t->ip;
6881 instr_exec_t instr = p->instruction_table[ip->type];
6889 static struct action *
6890 action_find(struct rte_swx_pipeline *p, const char *name)
6892 struct action *elem;
6897 TAILQ_FOREACH(elem, &p->actions, node)
6898 if (strcmp(elem->name, name) == 0)
6904 static struct action *
6905 action_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
6907 struct action *action = NULL;
6909 TAILQ_FOREACH(action, &p->actions, node)
6910 if (action->id == id)
6916 static struct field *
6917 action_field_find(struct action *a, const char *name)
6919 return a->st ? struct_type_field_find(a->st, name) : NULL;
6922 static struct field *
6923 action_field_parse(struct action *action, const char *name)
6925 if (name[0] != 't' || name[1] != '.')
6928 return action_field_find(action, &name[2]);
6932 action_has_nbo_args(struct action *a)
6936 /* Return if the action does not have any args. */
6938 return 0; /* FALSE */
6940 for (i = 0; i < a->st->n_fields; i++)
6941 if (a->args_endianness[i])
6942 return 1; /* TRUE */
6944 return 0; /* FALSE */
6948 action_does_learning(struct action *a)
6952 for (i = 0; i < a->n_instructions; i++)
6953 switch (a->instructions[i].type) {
6954 case INSTR_LEARNER_LEARN:
6955 return 1; /* TRUE */
6957 case INSTR_LEARNER_FORGET:
6958 return 1; /* TRUE */
6964 return 0; /* FALSE */
6968 rte_swx_pipeline_action_config(struct rte_swx_pipeline *p,
6970 const char *args_struct_type_name,
6971 const char **instructions,
6972 uint32_t n_instructions)
6974 struct struct_type *args_struct_type = NULL;
6980 CHECK_NAME(name, EINVAL);
6981 CHECK(!action_find(p, name), EEXIST);
6983 if (args_struct_type_name) {
6984 CHECK_NAME(args_struct_type_name, EINVAL);
6985 args_struct_type = struct_type_find(p, args_struct_type_name);
6986 CHECK(args_struct_type, EINVAL);
6987 CHECK(!args_struct_type->var_size, EINVAL);
6990 /* Node allocation. */
6991 a = calloc(1, sizeof(struct action));
6993 if (args_struct_type) {
6994 a->args_endianness = calloc(args_struct_type->n_fields, sizeof(int));
6995 if (!a->args_endianness) {
7001 /* Node initialization. */
7002 strcpy(a->name, name);
7003 a->st = args_struct_type;
7004 a->id = p->n_actions;
7006 /* Instruction translation. */
7007 err = instruction_config(p, a, instructions, n_instructions);
7009 free(a->args_endianness);
7014 /* Node add to tailq. */
7015 TAILQ_INSERT_TAIL(&p->actions, a, node);
7022 action_build(struct rte_swx_pipeline *p)
7024 struct action *action;
7026 /* p->action_instructions. */
7027 p->action_instructions = calloc(p->n_actions, sizeof(struct instruction *));
7028 CHECK(p->action_instructions, ENOMEM);
7030 TAILQ_FOREACH(action, &p->actions, node)
7031 p->action_instructions[action->id] = action->instructions;
7033 /* p->action_funcs. */
7034 p->action_funcs = calloc(p->n_actions, sizeof(action_func_t));
7035 CHECK(p->action_funcs, ENOMEM);
7041 action_build_free(struct rte_swx_pipeline *p)
7043 free(p->action_funcs);
7044 p->action_funcs = NULL;
7046 free(p->action_instructions);
7047 p->action_instructions = NULL;
7051 action_free(struct rte_swx_pipeline *p)
7053 action_build_free(p);
7056 struct action *action;
7058 action = TAILQ_FIRST(&p->actions);
7062 TAILQ_REMOVE(&p->actions, action, node);
7063 free(action->instruction_data);
7064 free(action->instructions);
7070 action_arg_src_mov_count(struct action *a,
7072 struct instruction *instructions,
7073 struct instruction_data *instruction_data,
7074 uint32_t n_instructions)
7076 uint32_t offset, n_users = 0, i;
7079 (arg_id >= a->st->n_fields) ||
7081 !instruction_data ||
7085 offset = a->st->fields[arg_id].offset / 8;
7087 for (i = 0; i < n_instructions; i++) {
7088 struct instruction *instr = &instructions[i];
7089 struct instruction_data *data = &instruction_data[i];
7091 if (data->invalid ||
7092 ((instr->type != INSTR_MOV) && (instr->type != INSTR_MOV_HM)) ||
7093 instr->mov.src.struct_id ||
7094 (instr->mov.src.offset != offset))
7106 static struct table_type *
7107 table_type_find(struct rte_swx_pipeline *p, const char *name)
7109 struct table_type *elem;
7111 TAILQ_FOREACH(elem, &p->table_types, node)
7112 if (strcmp(elem->name, name) == 0)
7118 static struct table_type *
7119 table_type_resolve(struct rte_swx_pipeline *p,
7120 const char *recommended_type_name,
7121 enum rte_swx_table_match_type match_type)
7123 struct table_type *elem;
7125 /* Only consider the recommended type if the match type is correct. */
7126 if (recommended_type_name)
7127 TAILQ_FOREACH(elem, &p->table_types, node)
7128 if (!strcmp(elem->name, recommended_type_name) &&
7129 (elem->match_type == match_type))
7132 /* Ignore the recommended type and get the first element with this match
7135 TAILQ_FOREACH(elem, &p->table_types, node)
7136 if (elem->match_type == match_type)
7142 static struct table *
7143 table_find(struct rte_swx_pipeline *p, const char *name)
7147 TAILQ_FOREACH(elem, &p->tables, node)
7148 if (strcmp(elem->name, name) == 0)
7154 static struct table *
7155 table_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7157 struct table *table = NULL;
7159 TAILQ_FOREACH(table, &p->tables, node)
7160 if (table->id == id)
7167 rte_swx_pipeline_table_type_register(struct rte_swx_pipeline *p,
7169 enum rte_swx_table_match_type match_type,
7170 struct rte_swx_table_ops *ops)
7172 struct table_type *elem;
7176 CHECK_NAME(name, EINVAL);
7177 CHECK(!table_type_find(p, name), EEXIST);
7180 CHECK(ops->create, EINVAL);
7181 CHECK(ops->lkp, EINVAL);
7182 CHECK(ops->free, EINVAL);
7184 /* Node allocation. */
7185 elem = calloc(1, sizeof(struct table_type));
7186 CHECK(elem, ENOMEM);
7188 /* Node initialization. */
7189 strcpy(elem->name, name);
7190 elem->match_type = match_type;
7191 memcpy(&elem->ops, ops, sizeof(*ops));
7193 /* Node add to tailq. */
7194 TAILQ_INSERT_TAIL(&p->table_types, elem, node);
7200 table_match_type_resolve(struct rte_swx_match_field_params *fields,
7202 enum rte_swx_table_match_type *match_type)
7204 uint32_t n_fields_em = 0, n_fields_lpm = 0, i;
7206 for (i = 0; i < n_fields; i++) {
7207 struct rte_swx_match_field_params *f = &fields[i];
7209 if (f->match_type == RTE_SWX_TABLE_MATCH_EXACT)
7212 if (f->match_type == RTE_SWX_TABLE_MATCH_LPM)
7216 if ((n_fields_lpm > 1) ||
7217 (n_fields_lpm && (n_fields_em != n_fields - 1)))
7220 *match_type = (n_fields_em == n_fields) ?
7221 RTE_SWX_TABLE_MATCH_EXACT :
7222 RTE_SWX_TABLE_MATCH_WILDCARD;
7228 table_match_fields_check(struct rte_swx_pipeline *p,
7229 struct rte_swx_pipeline_table_params *params,
7230 struct header **header)
7232 struct header *h0 = NULL;
7233 struct field *hf, *mf;
7234 uint32_t *offset = NULL, i;
7237 /* Return if no match fields. */
7238 if (!params->n_fields) {
7239 if (params->fields) {
7250 /* Memory allocation. */
7251 offset = calloc(params->n_fields, sizeof(uint32_t));
7257 /* Check that all the match fields belong to either the same header or
7260 hf = header_field_parse(p, params->fields[0].name, &h0);
7261 mf = metadata_field_parse(p, params->fields[0].name);
7262 if ((!hf && !mf) || (hf && hf->var_size)) {
7267 offset[0] = h0 ? hf->offset : mf->offset;
7269 for (i = 1; i < params->n_fields; i++)
7273 hf = header_field_parse(p, params->fields[i].name, &h);
7274 if (!hf || (h->id != h0->id) || hf->var_size) {
7279 offset[i] = hf->offset;
7281 mf = metadata_field_parse(p, params->fields[i].name);
7287 offset[i] = mf->offset;
7290 /* Check that there are no duplicated match fields. */
7291 for (i = 0; i < params->n_fields; i++) {
7294 for (j = 0; j < i; j++)
7295 if (offset[j] == offset[i]) {
7311 rte_swx_pipeline_table_config(struct rte_swx_pipeline *p,
7313 struct rte_swx_pipeline_table_params *params,
7314 const char *recommended_table_type_name,
7318 struct table_type *type;
7319 struct table *t = NULL;
7320 struct action *default_action;
7321 struct header *header = NULL;
7322 uint32_t action_data_size_max = 0, i;
7327 CHECK_NAME(name, EINVAL);
7328 CHECK(!table_find(p, name), EEXIST);
7329 CHECK(!selector_find(p, name), EEXIST);
7330 CHECK(!learner_find(p, name), EEXIST);
7332 CHECK(params, EINVAL);
7335 status = table_match_fields_check(p, params, &header);
7339 /* Action checks. */
7340 CHECK(params->n_actions, EINVAL);
7341 CHECK(params->action_names, EINVAL);
7342 for (i = 0; i < params->n_actions; i++) {
7343 const char *action_name = params->action_names[i];
7345 uint32_t action_data_size;
7346 int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
7348 CHECK_NAME(action_name, EINVAL);
7350 a = action_find(p, action_name);
7352 CHECK(!action_does_learning(a), EINVAL);
7354 action_data_size = a->st ? a->st->n_bits / 8 : 0;
7355 if (action_data_size > action_data_size_max)
7356 action_data_size_max = action_data_size;
7358 if (params->action_is_for_table_entries)
7359 action_is_for_table_entries = params->action_is_for_table_entries[i];
7360 if (params->action_is_for_default_entry)
7361 action_is_for_default_entry = params->action_is_for_default_entry[i];
7362 CHECK(action_is_for_table_entries || action_is_for_default_entry, EINVAL);
7365 CHECK_NAME(params->default_action_name, EINVAL);
7366 for (i = 0; i < p->n_actions; i++)
7367 if (!strcmp(params->action_names[i],
7368 params->default_action_name))
7370 CHECK(i < params->n_actions, EINVAL);
7371 CHECK(!params->action_is_for_default_entry || params->action_is_for_default_entry[i],
7374 default_action = action_find(p, params->default_action_name);
7375 CHECK((default_action->st && params->default_action_data) ||
7376 !params->default_action_data, EINVAL);
7378 /* Table type checks. */
7379 if (recommended_table_type_name)
7380 CHECK_NAME(recommended_table_type_name, EINVAL);
7382 if (params->n_fields) {
7383 enum rte_swx_table_match_type match_type;
7385 status = table_match_type_resolve(params->fields, params->n_fields, &match_type);
7389 type = table_type_resolve(p, recommended_table_type_name, match_type);
7390 CHECK(type, EINVAL);
7395 /* Memory allocation. */
7396 t = calloc(1, sizeof(struct table));
7400 t->fields = calloc(params->n_fields, sizeof(struct match_field));
7404 t->actions = calloc(params->n_actions, sizeof(struct action *));
7408 if (action_data_size_max) {
7409 t->default_action_data = calloc(1, action_data_size_max);
7410 if (!t->default_action_data)
7414 t->action_is_for_table_entries = calloc(params->n_actions, sizeof(int));
7415 if (!t->action_is_for_table_entries)
7418 t->action_is_for_default_entry = calloc(params->n_actions, sizeof(int));
7419 if (!t->action_is_for_default_entry)
7422 /* Node initialization. */
7423 strcpy(t->name, name);
7424 if (args && args[0])
7425 strcpy(t->args, args);
7428 for (i = 0; i < params->n_fields; i++) {
7429 struct rte_swx_match_field_params *field = ¶ms->fields[i];
7430 struct match_field *f = &t->fields[i];
7432 f->match_type = field->match_type;
7434 header_field_parse(p, field->name, NULL) :
7435 metadata_field_parse(p, field->name);
7437 t->n_fields = params->n_fields;
7440 for (i = 0; i < params->n_actions; i++) {
7441 int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
7443 if (params->action_is_for_table_entries)
7444 action_is_for_table_entries = params->action_is_for_table_entries[i];
7445 if (params->action_is_for_default_entry)
7446 action_is_for_default_entry = params->action_is_for_default_entry[i];
7448 t->actions[i] = action_find(p, params->action_names[i]);
7449 t->action_is_for_table_entries[i] = action_is_for_table_entries;
7450 t->action_is_for_default_entry[i] = action_is_for_default_entry;
7452 t->default_action = default_action;
7453 if (default_action->st)
7454 memcpy(t->default_action_data,
7455 params->default_action_data,
7456 default_action->st->n_bits / 8);
7457 t->n_actions = params->n_actions;
7458 t->default_action_is_const = params->default_action_is_const;
7459 t->action_data_size_max = action_data_size_max;
7462 t->id = p->n_tables;
7464 /* Node add to tailq. */
7465 TAILQ_INSERT_TAIL(&p->tables, t, node);
7474 free(t->action_is_for_default_entry);
7475 free(t->action_is_for_table_entries);
7476 free(t->default_action_data);
7484 static struct rte_swx_table_params *
7485 table_params_get(struct table *table)
7487 struct rte_swx_table_params *params;
7488 struct field *first, *last;
7490 uint32_t key_size, key_offset, action_data_size, i;
7492 /* Memory allocation. */
7493 params = calloc(1, sizeof(struct rte_swx_table_params));
7497 /* Find first (smallest offset) and last (biggest offset) match fields. */
7498 first = table->fields[0].field;
7499 last = table->fields[0].field;
7501 for (i = 0; i < table->n_fields; i++) {
7502 struct field *f = table->fields[i].field;
7504 if (f->offset < first->offset)
7507 if (f->offset > last->offset)
7511 /* Key offset and size. */
7512 key_offset = first->offset / 8;
7513 key_size = (last->offset + last->n_bits - first->offset) / 8;
7515 /* Memory allocation. */
7516 key_mask = calloc(1, key_size);
7523 for (i = 0; i < table->n_fields; i++) {
7524 struct field *f = table->fields[i].field;
7525 uint32_t start = (f->offset - first->offset) / 8;
7526 size_t size = f->n_bits / 8;
7528 memset(&key_mask[start], 0xFF, size);
7531 /* Action data size. */
7532 action_data_size = 0;
7533 for (i = 0; i < table->n_actions; i++) {
7534 struct action *action = table->actions[i];
7535 uint32_t ads = action->st ? action->st->n_bits / 8 : 0;
7537 if (ads > action_data_size)
7538 action_data_size = ads;
7542 params->match_type = table->type->match_type;
7543 params->key_size = key_size;
7544 params->key_offset = key_offset;
7545 params->key_mask0 = key_mask;
7546 params->action_data_size = action_data_size;
7547 params->n_keys_max = table->size;
7553 table_params_free(struct rte_swx_table_params *params)
7558 free(params->key_mask0);
7563 table_stub_lkp(void *table __rte_unused,
7564 void *mailbox __rte_unused,
7565 uint8_t **key __rte_unused,
7566 uint64_t *action_id __rte_unused,
7567 uint8_t **action_data __rte_unused,
7571 return 1; /* DONE. */
7575 table_build(struct rte_swx_pipeline *p)
7579 /* Per pipeline: table statistics. */
7580 p->table_stats = calloc(p->n_tables, sizeof(struct table_statistics));
7581 CHECK(p->table_stats, ENOMEM);
7583 for (i = 0; i < p->n_tables; i++) {
7584 p->table_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
7585 CHECK(p->table_stats[i].n_pkts_action, ENOMEM);
7588 /* Per thread: table runt-time. */
7589 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
7590 struct thread *t = &p->threads[i];
7591 struct table *table;
7593 t->tables = calloc(p->n_tables, sizeof(struct table_runtime));
7594 CHECK(t->tables, ENOMEM);
7596 TAILQ_FOREACH(table, &p->tables, node) {
7597 struct table_runtime *r = &t->tables[table->id];
7602 size = table->type->ops.mailbox_size_get();
7605 r->func = table->type->ops.lkp;
7609 r->mailbox = calloc(1, size);
7610 CHECK(r->mailbox, ENOMEM);
7614 r->key = table->header ?
7615 &t->structs[table->header->struct_id] :
7616 &t->structs[p->metadata_struct_id];
7618 r->func = table_stub_lkp;
7627 table_build_free(struct rte_swx_pipeline *p)
7631 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
7632 struct thread *t = &p->threads[i];
7638 for (j = 0; j < p->n_tables; j++) {
7639 struct table_runtime *r = &t->tables[j];
7648 if (p->table_stats) {
7649 for (i = 0; i < p->n_tables; i++)
7650 free(p->table_stats[i].n_pkts_action);
7652 free(p->table_stats);
7657 table_free(struct rte_swx_pipeline *p)
7659 table_build_free(p);
7665 elem = TAILQ_FIRST(&p->tables);
7669 TAILQ_REMOVE(&p->tables, elem, node);
7671 free(elem->actions);
7672 free(elem->default_action_data);
7678 struct table_type *elem;
7680 elem = TAILQ_FIRST(&p->table_types);
7684 TAILQ_REMOVE(&p->table_types, elem, node);
7692 static struct selector *
7693 selector_find(struct rte_swx_pipeline *p, const char *name)
7697 TAILQ_FOREACH(s, &p->selectors, node)
7698 if (strcmp(s->name, name) == 0)
7704 static struct selector *
7705 selector_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7707 struct selector *s = NULL;
7709 TAILQ_FOREACH(s, &p->selectors, node)
7717 selector_fields_check(struct rte_swx_pipeline *p,
7718 struct rte_swx_pipeline_selector_params *params,
7719 struct header **header)
7721 struct header *h0 = NULL;
7722 struct field *hf, *mf;
7725 /* Return if no selector fields. */
7726 if (!params->n_selector_fields || !params->selector_field_names)
7729 /* Check that all the selector fields either belong to the same header
7730 * or are all meta-data fields.
7732 hf = header_field_parse(p, params->selector_field_names[0], &h0);
7733 mf = metadata_field_parse(p, params->selector_field_names[0]);
7737 for (i = 1; i < params->n_selector_fields; i++)
7741 hf = header_field_parse(p, params->selector_field_names[i], &h);
7742 if (!hf || (h->id != h0->id))
7745 mf = metadata_field_parse(p, params->selector_field_names[i]);
7750 /* Check that there are no duplicated match fields. */
7751 for (i = 0; i < params->n_selector_fields; i++) {
7752 const char *field_name = params->selector_field_names[i];
7755 for (j = i + 1; j < params->n_selector_fields; j++)
7756 if (!strcmp(params->selector_field_names[j], field_name))
7768 rte_swx_pipeline_selector_config(struct rte_swx_pipeline *p,
7770 struct rte_swx_pipeline_selector_params *params)
7773 struct header *selector_header = NULL;
7774 struct field *group_id_field, *member_id_field;
7780 CHECK_NAME(name, EINVAL);
7781 CHECK(!table_find(p, name), EEXIST);
7782 CHECK(!selector_find(p, name), EEXIST);
7783 CHECK(!learner_find(p, name), EEXIST);
7785 CHECK(params, EINVAL);
7787 CHECK_NAME(params->group_id_field_name, EINVAL);
7788 group_id_field = metadata_field_parse(p, params->group_id_field_name);
7789 CHECK(group_id_field, EINVAL);
7791 for (i = 0; i < params->n_selector_fields; i++) {
7792 const char *field_name = params->selector_field_names[i];
7794 CHECK_NAME(field_name, EINVAL);
7796 status = selector_fields_check(p, params, &selector_header);
7800 CHECK_NAME(params->member_id_field_name, EINVAL);
7801 member_id_field = metadata_field_parse(p, params->member_id_field_name);
7802 CHECK(member_id_field, EINVAL);
7804 CHECK(params->n_groups_max, EINVAL);
7806 CHECK(params->n_members_per_group_max, EINVAL);
7808 /* Memory allocation. */
7809 s = calloc(1, sizeof(struct selector));
7815 s->selector_fields = calloc(params->n_selector_fields, sizeof(struct field *));
7816 if (!s->selector_fields) {
7821 /* Node initialization. */
7822 strcpy(s->name, name);
7824 s->group_id_field = group_id_field;
7826 for (i = 0; i < params->n_selector_fields; i++) {
7827 const char *field_name = params->selector_field_names[i];
7829 s->selector_fields[i] = selector_header ?
7830 header_field_parse(p, field_name, NULL) :
7831 metadata_field_parse(p, field_name);
7834 s->n_selector_fields = params->n_selector_fields;
7836 s->selector_header = selector_header;
7838 s->member_id_field = member_id_field;
7840 s->n_groups_max = params->n_groups_max;
7842 s->n_members_per_group_max = params->n_members_per_group_max;
7844 s->id = p->n_selectors;
7846 /* Node add to tailq. */
7847 TAILQ_INSERT_TAIL(&p->selectors, s, node);
7856 free(s->selector_fields);
7864 selector_params_free(struct rte_swx_table_selector_params *params)
7869 free(params->selector_mask);
7874 static struct rte_swx_table_selector_params *
7875 selector_table_params_get(struct selector *s)
7877 struct rte_swx_table_selector_params *params = NULL;
7878 struct field *first, *last;
7881 /* Memory allocation. */
7882 params = calloc(1, sizeof(struct rte_swx_table_selector_params));
7887 params->group_id_offset = s->group_id_field->offset / 8;
7889 /* Find first (smallest offset) and last (biggest offset) selector fields. */
7890 first = s->selector_fields[0];
7891 last = s->selector_fields[0];
7893 for (i = 0; i < s->n_selector_fields; i++) {
7894 struct field *f = s->selector_fields[i];
7896 if (f->offset < first->offset)
7899 if (f->offset > last->offset)
7903 /* Selector offset and size. */
7904 params->selector_offset = first->offset / 8;
7905 params->selector_size = (last->offset + last->n_bits - first->offset) / 8;
7907 /* Memory allocation. */
7908 params->selector_mask = calloc(1, params->selector_size);
7909 if (!params->selector_mask)
7912 /* Selector mask. */
7913 for (i = 0; i < s->n_selector_fields; i++) {
7914 struct field *f = s->selector_fields[i];
7915 uint32_t start = (f->offset - first->offset) / 8;
7916 size_t size = f->n_bits / 8;
7918 memset(¶ms->selector_mask[start], 0xFF, size);
7922 params->member_id_offset = s->member_id_field->offset / 8;
7924 /* Maximum number of groups. */
7925 params->n_groups_max = s->n_groups_max;
7927 /* Maximum number of members per group. */
7928 params->n_members_per_group_max = s->n_members_per_group_max;
7933 selector_params_free(params);
7938 selector_build_free(struct rte_swx_pipeline *p)
7942 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
7943 struct thread *t = &p->threads[i];
7949 for (j = 0; j < p->n_selectors; j++) {
7950 struct selector_runtime *r = &t->selectors[j];
7956 t->selectors = NULL;
7959 free(p->selector_stats);
7960 p->selector_stats = NULL;
7964 selector_build(struct rte_swx_pipeline *p)
7969 /* Per pipeline: selector statistics. */
7970 p->selector_stats = calloc(p->n_selectors, sizeof(struct selector_statistics));
7971 if (!p->selector_stats) {
7976 /* Per thread: selector run-time. */
7977 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
7978 struct thread *t = &p->threads[i];
7981 t->selectors = calloc(p->n_selectors, sizeof(struct selector_runtime));
7982 if (!t->selectors) {
7987 TAILQ_FOREACH(s, &p->selectors, node) {
7988 struct selector_runtime *r = &t->selectors[s->id];
7992 size = rte_swx_table_selector_mailbox_size_get();
7994 r->mailbox = calloc(1, size);
8001 /* r->group_id_buffer. */
8002 r->group_id_buffer = &t->structs[p->metadata_struct_id];
8004 /* r->selector_buffer. */
8005 r->selector_buffer = s->selector_header ?
8006 &t->structs[s->selector_header->struct_id] :
8007 &t->structs[p->metadata_struct_id];
8009 /* r->member_id_buffer. */
8010 r->member_id_buffer = &t->structs[p->metadata_struct_id];
8017 selector_build_free(p);
8022 selector_free(struct rte_swx_pipeline *p)
8024 selector_build_free(p);
8026 /* Selector tables. */
8028 struct selector *elem;
8030 elem = TAILQ_FIRST(&p->selectors);
8034 TAILQ_REMOVE(&p->selectors, elem, node);
8035 free(elem->selector_fields);
8043 static struct learner *
8044 learner_find(struct rte_swx_pipeline *p, const char *name)
8048 TAILQ_FOREACH(l, &p->learners, node)
8049 if (!strcmp(l->name, name))
8055 static struct learner *
8056 learner_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8058 struct learner *l = NULL;
8060 TAILQ_FOREACH(l, &p->learners, node)
8068 learner_match_fields_check(struct rte_swx_pipeline *p,
8069 struct rte_swx_pipeline_learner_params *params,
8070 struct header **header)
8072 struct header *h0 = NULL;
8073 struct field *hf, *mf;
8076 /* Return if no match fields. */
8077 if (!params->n_fields || !params->field_names)
8080 /* Check that all the match fields either belong to the same header
8081 * or are all meta-data fields.
8083 hf = header_field_parse(p, params->field_names[0], &h0);
8084 mf = metadata_field_parse(p, params->field_names[0]);
8088 for (i = 1; i < params->n_fields; i++)
8092 hf = header_field_parse(p, params->field_names[i], &h);
8093 if (!hf || (h->id != h0->id))
8096 mf = metadata_field_parse(p, params->field_names[i]);
8101 /* Check that there are no duplicated match fields. */
8102 for (i = 0; i < params->n_fields; i++) {
8103 const char *field_name = params->field_names[i];
8106 for (j = i + 1; j < params->n_fields; j++)
8107 if (!strcmp(params->field_names[j], field_name))
8119 learner_action_args_check(struct rte_swx_pipeline *p, struct action *a, const char *mf_name)
8121 struct struct_type *mst = p->metadata_st, *ast = a->st;
8122 struct field *mf, *af;
8132 /* Check that mf_name is the name of a valid meta-data field. */
8133 CHECK_NAME(mf_name, EINVAL);
8134 mf = metadata_field_parse(p, mf_name);
8137 /* Check that there are enough meta-data fields, starting with the mf_name field, to cover
8138 * all the action arguments.
8140 mf_pos = mf - mst->fields;
8141 CHECK(mst->n_fields - mf_pos >= ast->n_fields, EINVAL);
8143 /* Check that the size of each of the identified meta-data fields matches exactly the size
8144 * of the corresponding action argument.
8146 for (i = 0; i < ast->n_fields; i++) {
8147 mf = &mst->fields[mf_pos + i];
8148 af = &ast->fields[i];
8150 CHECK(mf->n_bits == af->n_bits, EINVAL);
8157 learner_action_learning_check(struct rte_swx_pipeline *p,
8158 struct action *action,
8159 const char **action_names,
8164 /* For each "learn" instruction of the current action, check that the learned action (i.e.
8165 * the action passed as argument to the "learn" instruction) is also enabled for the
8166 * current learner table.
8168 for (i = 0; i < action->n_instructions; i++) {
8169 struct instruction *instr = &action->instructions[i];
8170 uint32_t found = 0, j;
8172 if (instr->type != INSTR_LEARNER_LEARN)
8175 for (j = 0; j < n_actions; j++) {
8178 a = action_find(p, action_names[j]);
8182 if (a->id == instr->learn.action_id)
8194 rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p,
8196 struct rte_swx_pipeline_learner_params *params,
8200 struct learner *l = NULL;
8201 struct action *default_action;
8202 struct header *header = NULL;
8203 uint32_t action_data_size_max = 0, i;
8208 CHECK_NAME(name, EINVAL);
8209 CHECK(!table_find(p, name), EEXIST);
8210 CHECK(!selector_find(p, name), EEXIST);
8211 CHECK(!learner_find(p, name), EEXIST);
8213 CHECK(params, EINVAL);
8216 status = learner_match_fields_check(p, params, &header);
8220 /* Action checks. */
8221 CHECK(params->n_actions, EINVAL);
8222 CHECK(params->action_names, EINVAL);
8223 for (i = 0; i < params->n_actions; i++) {
8224 const char *action_name = params->action_names[i];
8226 uint32_t action_data_size;
8227 int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
8229 CHECK_NAME(action_name, EINVAL);
8231 a = action_find(p, action_name);
8234 status = learner_action_learning_check(p,
8236 params->action_names,
8241 action_data_size = a->st ? a->st->n_bits / 8 : 0;
8242 if (action_data_size > action_data_size_max)
8243 action_data_size_max = action_data_size;
8245 if (params->action_is_for_table_entries)
8246 action_is_for_table_entries = params->action_is_for_table_entries[i];
8247 if (params->action_is_for_default_entry)
8248 action_is_for_default_entry = params->action_is_for_default_entry[i];
8249 CHECK(action_is_for_table_entries || action_is_for_default_entry, EINVAL);
8252 CHECK_NAME(params->default_action_name, EINVAL);
8253 for (i = 0; i < p->n_actions; i++)
8254 if (!strcmp(params->action_names[i],
8255 params->default_action_name))
8257 CHECK(i < params->n_actions, EINVAL);
8258 CHECK(!params->action_is_for_default_entry || params->action_is_for_default_entry[i],
8261 default_action = action_find(p, params->default_action_name);
8262 CHECK((default_action->st && params->default_action_data) ||
8263 !params->default_action_data, EINVAL);
8265 /* Any other checks. */
8266 CHECK(size, EINVAL);
8267 CHECK(timeout, EINVAL);
8269 /* Memory allocation. */
8270 l = calloc(1, sizeof(struct learner));
8274 l->fields = calloc(params->n_fields, sizeof(struct field *));
8278 l->actions = calloc(params->n_actions, sizeof(struct action *));
8282 if (action_data_size_max) {
8283 l->default_action_data = calloc(1, action_data_size_max);
8284 if (!l->default_action_data)
8288 l->action_is_for_table_entries = calloc(params->n_actions, sizeof(int));
8289 if (!l->action_is_for_table_entries)
8292 l->action_is_for_default_entry = calloc(params->n_actions, sizeof(int));
8293 if (!l->action_is_for_default_entry)
8296 /* Node initialization. */
8297 strcpy(l->name, name);
8299 for (i = 0; i < params->n_fields; i++) {
8300 const char *field_name = params->field_names[i];
8302 l->fields[i] = header ?
8303 header_field_parse(p, field_name, NULL) :
8304 metadata_field_parse(p, field_name);
8307 l->n_fields = params->n_fields;
8311 for (i = 0; i < params->n_actions; i++) {
8312 int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
8314 if (params->action_is_for_table_entries)
8315 action_is_for_table_entries = params->action_is_for_table_entries[i];
8316 if (params->action_is_for_default_entry)
8317 action_is_for_default_entry = params->action_is_for_default_entry[i];
8319 l->actions[i] = action_find(p, params->action_names[i]);
8320 l->action_is_for_table_entries[i] = action_is_for_table_entries;
8321 l->action_is_for_default_entry[i] = action_is_for_default_entry;
8324 l->default_action = default_action;
8326 if (default_action->st)
8327 memcpy(l->default_action_data,
8328 params->default_action_data,
8329 default_action->st->n_bits / 8);
8331 l->n_actions = params->n_actions;
8333 l->default_action_is_const = params->default_action_is_const;
8335 l->action_data_size_max = action_data_size_max;
8339 l->timeout = timeout;
8341 l->id = p->n_learners;
8343 /* Node add to tailq. */
8344 TAILQ_INSERT_TAIL(&p->learners, l, node);
8353 free(l->action_is_for_default_entry);
8354 free(l->action_is_for_table_entries);
8355 free(l->default_action_data);
8364 learner_params_free(struct rte_swx_table_learner_params *params)
8369 free(params->key_mask0);
8374 static struct rte_swx_table_learner_params *
8375 learner_params_get(struct learner *l)
8377 struct rte_swx_table_learner_params *params = NULL;
8378 struct field *first, *last;
8381 /* Memory allocation. */
8382 params = calloc(1, sizeof(struct rte_swx_table_learner_params));
8386 /* Find first (smallest offset) and last (biggest offset) match fields. */
8387 first = l->fields[0];
8388 last = l->fields[0];
8390 for (i = 0; i < l->n_fields; i++) {
8391 struct field *f = l->fields[i];
8393 if (f->offset < first->offset)
8396 if (f->offset > last->offset)
8400 /* Key offset and size. */
8401 params->key_offset = first->offset / 8;
8402 params->key_size = (last->offset + last->n_bits - first->offset) / 8;
8404 /* Memory allocation. */
8405 params->key_mask0 = calloc(1, params->key_size);
8406 if (!params->key_mask0)
8410 for (i = 0; i < l->n_fields; i++) {
8411 struct field *f = l->fields[i];
8412 uint32_t start = (f->offset - first->offset) / 8;
8413 size_t size = f->n_bits / 8;
8415 memset(¶ms->key_mask0[start], 0xFF, size);
8418 /* Action data size. */
8419 params->action_data_size = l->action_data_size_max;
8421 /* Maximum number of keys. */
8422 params->n_keys_max = l->size;
8425 params->key_timeout = l->timeout;
8430 learner_params_free(params);
8435 learner_build_free(struct rte_swx_pipeline *p)
8439 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8440 struct thread *t = &p->threads[i];
8446 for (j = 0; j < p->n_learners; j++) {
8447 struct learner_runtime *r = &t->learners[j];
8456 if (p->learner_stats) {
8457 for (i = 0; i < p->n_learners; i++)
8458 free(p->learner_stats[i].n_pkts_action);
8460 free(p->learner_stats);
8465 learner_build(struct rte_swx_pipeline *p)
8470 /* Per pipeline: learner statistics. */
8471 p->learner_stats = calloc(p->n_learners, sizeof(struct learner_statistics));
8472 CHECK(p->learner_stats, ENOMEM);
8474 for (i = 0; i < p->n_learners; i++) {
8475 p->learner_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
8476 CHECK(p->learner_stats[i].n_pkts_action, ENOMEM);
8479 /* Per thread: learner run-time. */
8480 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8481 struct thread *t = &p->threads[i];
8484 t->learners = calloc(p->n_learners, sizeof(struct learner_runtime));
8490 TAILQ_FOREACH(l, &p->learners, node) {
8491 struct learner_runtime *r = &t->learners[l->id];
8495 size = rte_swx_table_learner_mailbox_size_get();
8497 r->mailbox = calloc(1, size);
8505 r->key = l->header ?
8506 &t->structs[l->header->struct_id] :
8507 &t->structs[p->metadata_struct_id];
8514 learner_build_free(p);
8519 learner_free(struct rte_swx_pipeline *p)
8521 learner_build_free(p);
8523 /* Learner tables. */
8527 l = TAILQ_FIRST(&p->learners);
8531 TAILQ_REMOVE(&p->learners, l, node);
8534 free(l->default_action_data);
8543 table_state_build(struct rte_swx_pipeline *p)
8545 struct table *table;
8549 p->table_state = calloc(p->n_tables + p->n_selectors,
8550 sizeof(struct rte_swx_table_state));
8551 CHECK(p->table_state, ENOMEM);
8553 TAILQ_FOREACH(table, &p->tables, node) {
8554 struct rte_swx_table_state *ts = &p->table_state[table->id];
8557 struct rte_swx_table_params *params;
8560 params = table_params_get(table);
8561 CHECK(params, ENOMEM);
8563 ts->obj = table->type->ops.create(params,
8568 table_params_free(params);
8569 CHECK(ts->obj, ENODEV);
8572 /* ts->default_action_data. */
8573 if (table->action_data_size_max) {
8574 ts->default_action_data =
8575 malloc(table->action_data_size_max);
8576 CHECK(ts->default_action_data, ENOMEM);
8578 memcpy(ts->default_action_data,
8579 table->default_action_data,
8580 table->action_data_size_max);
8583 /* ts->default_action_id. */
8584 ts->default_action_id = table->default_action->id;
8587 TAILQ_FOREACH(s, &p->selectors, node) {
8588 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + s->id];
8589 struct rte_swx_table_selector_params *params;
8592 params = selector_table_params_get(s);
8593 CHECK(params, ENOMEM);
8595 ts->obj = rte_swx_table_selector_create(params, NULL, p->numa_node);
8597 selector_params_free(params);
8598 CHECK(ts->obj, ENODEV);
8601 TAILQ_FOREACH(l, &p->learners, node) {
8602 struct rte_swx_table_state *ts = &p->table_state[p->n_tables +
8603 p->n_selectors + l->id];
8604 struct rte_swx_table_learner_params *params;
8607 params = learner_params_get(l);
8608 CHECK(params, ENOMEM);
8610 ts->obj = rte_swx_table_learner_create(params, p->numa_node);
8611 learner_params_free(params);
8612 CHECK(ts->obj, ENODEV);
8614 /* ts->default_action_data. */
8615 if (l->action_data_size_max) {
8616 ts->default_action_data = malloc(l->action_data_size_max);
8617 CHECK(ts->default_action_data, ENOMEM);
8619 memcpy(ts->default_action_data,
8620 l->default_action_data,
8621 l->action_data_size_max);
8624 /* ts->default_action_id. */
8625 ts->default_action_id = l->default_action->id;
8632 table_state_build_free(struct rte_swx_pipeline *p)
8636 if (!p->table_state)
8639 for (i = 0; i < p->n_tables; i++) {
8640 struct rte_swx_table_state *ts = &p->table_state[i];
8641 struct table *table = table_find_by_id(p, i);
8644 if (table->type && ts->obj)
8645 table->type->ops.free(ts->obj);
8647 /* ts->default_action_data. */
8648 free(ts->default_action_data);
8651 for (i = 0; i < p->n_selectors; i++) {
8652 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + i];
8656 rte_swx_table_selector_free(ts->obj);
8659 for (i = 0; i < p->n_learners; i++) {
8660 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + p->n_selectors + i];
8664 rte_swx_table_learner_free(ts->obj);
8666 /* ts->default_action_data. */
8667 free(ts->default_action_data);
8670 free(p->table_state);
8671 p->table_state = NULL;
8675 table_state_free(struct rte_swx_pipeline *p)
8677 table_state_build_free(p);
8683 static struct regarray *
8684 regarray_find(struct rte_swx_pipeline *p, const char *name)
8686 struct regarray *elem;
8688 TAILQ_FOREACH(elem, &p->regarrays, node)
8689 if (!strcmp(elem->name, name))
8695 static struct regarray *
8696 regarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8698 struct regarray *elem = NULL;
8700 TAILQ_FOREACH(elem, &p->regarrays, node)
8708 rte_swx_pipeline_regarray_config(struct rte_swx_pipeline *p,
8717 CHECK_NAME(name, EINVAL);
8718 CHECK(!regarray_find(p, name), EEXIST);
8720 CHECK(size, EINVAL);
8721 size = rte_align32pow2(size);
8723 /* Memory allocation. */
8724 r = calloc(1, sizeof(struct regarray));
8727 /* Node initialization. */
8728 strcpy(r->name, name);
8729 r->init_val = init_val;
8731 r->id = p->n_regarrays;
8733 /* Node add to tailq. */
8734 TAILQ_INSERT_TAIL(&p->regarrays, r, node);
8741 regarray_build(struct rte_swx_pipeline *p)
8743 struct regarray *regarray;
8745 if (!p->n_regarrays)
8748 p->regarray_runtime = calloc(p->n_regarrays, sizeof(struct regarray_runtime));
8749 CHECK(p->regarray_runtime, ENOMEM);
8751 TAILQ_FOREACH(regarray, &p->regarrays, node) {
8752 struct regarray_runtime *r = &p->regarray_runtime[regarray->id];
8755 r->regarray = env_malloc(regarray->size * sizeof(uint64_t),
8756 RTE_CACHE_LINE_SIZE,
8758 CHECK(r->regarray, ENOMEM);
8760 if (regarray->init_val)
8761 for (i = 0; i < regarray->size; i++)
8762 r->regarray[i] = regarray->init_val;
8764 r->size_mask = regarray->size - 1;
8771 regarray_build_free(struct rte_swx_pipeline *p)
8775 if (!p->regarray_runtime)
8778 for (i = 0; i < p->n_regarrays; i++) {
8779 struct regarray *regarray = regarray_find_by_id(p, i);
8780 struct regarray_runtime *r = &p->regarray_runtime[i];
8782 env_free(r->regarray, regarray->size * sizeof(uint64_t));
8785 free(p->regarray_runtime);
8786 p->regarray_runtime = NULL;
8790 regarray_free(struct rte_swx_pipeline *p)
8792 regarray_build_free(p);
8795 struct regarray *elem;
8797 elem = TAILQ_FIRST(&p->regarrays);
8801 TAILQ_REMOVE(&p->regarrays, elem, node);
8809 static struct meter_profile *
8810 meter_profile_find(struct rte_swx_pipeline *p, const char *name)
8812 struct meter_profile *elem;
8814 TAILQ_FOREACH(elem, &p->meter_profiles, node)
8815 if (!strcmp(elem->name, name))
8821 static struct metarray *
8822 metarray_find(struct rte_swx_pipeline *p, const char *name)
8824 struct metarray *elem;
8826 TAILQ_FOREACH(elem, &p->metarrays, node)
8827 if (!strcmp(elem->name, name))
8833 static struct metarray *
8834 metarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8836 struct metarray *elem = NULL;
8838 TAILQ_FOREACH(elem, &p->metarrays, node)
8846 rte_swx_pipeline_metarray_config(struct rte_swx_pipeline *p,
8854 CHECK_NAME(name, EINVAL);
8855 CHECK(!metarray_find(p, name), EEXIST);
8857 CHECK(size, EINVAL);
8858 size = rte_align32pow2(size);
8860 /* Memory allocation. */
8861 m = calloc(1, sizeof(struct metarray));
8864 /* Node initialization. */
8865 strcpy(m->name, name);
8867 m->id = p->n_metarrays;
8869 /* Node add to tailq. */
8870 TAILQ_INSERT_TAIL(&p->metarrays, m, node);
8876 struct meter_profile meter_profile_default = {
8885 .cir_bytes_per_period = 1,
8887 .pir_bytes_per_period = 1,
8894 meter_init(struct meter *m)
8896 memset(m, 0, sizeof(struct meter));
8897 rte_meter_trtcm_config(&m->m, &meter_profile_default.profile);
8898 m->profile = &meter_profile_default;
8899 m->color_mask = RTE_COLOR_GREEN;
8901 meter_profile_default.n_users++;
8905 metarray_build(struct rte_swx_pipeline *p)
8909 if (!p->n_metarrays)
8912 p->metarray_runtime = calloc(p->n_metarrays, sizeof(struct metarray_runtime));
8913 CHECK(p->metarray_runtime, ENOMEM);
8915 TAILQ_FOREACH(m, &p->metarrays, node) {
8916 struct metarray_runtime *r = &p->metarray_runtime[m->id];
8919 r->metarray = env_malloc(m->size * sizeof(struct meter),
8920 RTE_CACHE_LINE_SIZE,
8922 CHECK(r->metarray, ENOMEM);
8924 for (i = 0; i < m->size; i++)
8925 meter_init(&r->metarray[i]);
8927 r->size_mask = m->size - 1;
8934 metarray_build_free(struct rte_swx_pipeline *p)
8938 if (!p->metarray_runtime)
8941 for (i = 0; i < p->n_metarrays; i++) {
8942 struct metarray *m = metarray_find_by_id(p, i);
8943 struct metarray_runtime *r = &p->metarray_runtime[i];
8945 env_free(r->metarray, m->size * sizeof(struct meter));
8948 free(p->metarray_runtime);
8949 p->metarray_runtime = NULL;
8953 metarray_free(struct rte_swx_pipeline *p)
8955 metarray_build_free(p);
8959 struct metarray *elem;
8961 elem = TAILQ_FIRST(&p->metarrays);
8965 TAILQ_REMOVE(&p->metarrays, elem, node);
8969 /* Meter profiles. */
8971 struct meter_profile *elem;
8973 elem = TAILQ_FIRST(&p->meter_profiles);
8977 TAILQ_REMOVE(&p->meter_profiles, elem, node);
8986 rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
8988 struct rte_swx_pipeline *pipeline;
8990 /* Check input parameters. */
8993 /* Memory allocation. */
8994 pipeline = calloc(1, sizeof(struct rte_swx_pipeline));
8995 CHECK(pipeline, ENOMEM);
8997 /* Initialization. */
8998 TAILQ_INIT(&pipeline->struct_types);
8999 TAILQ_INIT(&pipeline->port_in_types);
9000 TAILQ_INIT(&pipeline->ports_in);
9001 TAILQ_INIT(&pipeline->port_out_types);
9002 TAILQ_INIT(&pipeline->ports_out);
9003 TAILQ_INIT(&pipeline->extern_types);
9004 TAILQ_INIT(&pipeline->extern_objs);
9005 TAILQ_INIT(&pipeline->extern_funcs);
9006 TAILQ_INIT(&pipeline->headers);
9007 TAILQ_INIT(&pipeline->actions);
9008 TAILQ_INIT(&pipeline->table_types);
9009 TAILQ_INIT(&pipeline->tables);
9010 TAILQ_INIT(&pipeline->selectors);
9011 TAILQ_INIT(&pipeline->learners);
9012 TAILQ_INIT(&pipeline->regarrays);
9013 TAILQ_INIT(&pipeline->meter_profiles);
9014 TAILQ_INIT(&pipeline->metarrays);
9016 pipeline->n_structs = 1; /* Struct 0 is reserved for action_data. */
9017 pipeline->numa_node = numa_node;
9024 rte_swx_pipeline_free(struct rte_swx_pipeline *p)
9033 free(p->instruction_data);
9034 free(p->instructions);
9038 table_state_free(p);
9043 instruction_table_free(p);
9046 extern_func_free(p);
9059 rte_swx_pipeline_instructions_config(struct rte_swx_pipeline *p,
9060 const char **instructions,
9061 uint32_t n_instructions)
9066 err = instruction_config(p, NULL, instructions, n_instructions);
9070 /* Thread instruction pointer reset. */
9071 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9072 struct thread *t = &p->threads[i];
9074 thread_ip_reset(p, t);
9081 pipeline_compile(struct rte_swx_pipeline *p);
9084 rte_swx_pipeline_build(struct rte_swx_pipeline *p)
9089 CHECK(p->build_done == 0, EEXIST);
9091 status = port_in_build(p);
9095 status = port_out_build(p);
9099 status = struct_build(p);
9103 status = extern_obj_build(p);
9107 status = extern_func_build(p);
9111 status = header_build(p);
9115 status = metadata_build(p);
9119 status = instruction_table_build(p);
9123 status = action_build(p);
9127 status = table_build(p);
9131 status = selector_build(p);
9135 status = learner_build(p);
9139 status = table_state_build(p);
9143 status = regarray_build(p);
9147 status = metarray_build(p);
9153 pipeline_compile(p);
9158 metarray_build_free(p);
9159 regarray_build_free(p);
9160 table_state_build_free(p);
9161 learner_build_free(p);
9162 selector_build_free(p);
9163 table_build_free(p);
9164 action_build_free(p);
9165 instruction_table_build_free(p);
9166 metadata_build_free(p);
9167 header_build_free(p);
9168 extern_func_build_free(p);
9169 extern_obj_build_free(p);
9170 port_out_build_free(p);
9171 port_in_build_free(p);
9172 struct_build_free(p);
9178 rte_swx_pipeline_run(struct rte_swx_pipeline *p, uint32_t n_instructions)
9182 for (i = 0; i < n_instructions; i++)
9187 rte_swx_pipeline_flush(struct rte_swx_pipeline *p)
9191 for (i = 0; i < p->n_ports_out; i++) {
9192 struct port_out_runtime *port = &p->out[i];
9195 port->flush(port->obj);
9203 rte_swx_ctl_pipeline_info_get(struct rte_swx_pipeline *p,
9204 struct rte_swx_ctl_pipeline_info *pipeline)
9206 struct action *action;
9207 struct table *table;
9208 uint32_t n_actions = 0, n_tables = 0;
9210 if (!p || !pipeline)
9213 TAILQ_FOREACH(action, &p->actions, node)
9216 TAILQ_FOREACH(table, &p->tables, node)
9219 pipeline->n_ports_in = p->n_ports_in;
9220 pipeline->n_ports_out = p->n_ports_out;
9221 pipeline->n_actions = n_actions;
9222 pipeline->n_tables = n_tables;
9223 pipeline->n_selectors = p->n_selectors;
9224 pipeline->n_learners = p->n_learners;
9225 pipeline->n_regarrays = p->n_regarrays;
9226 pipeline->n_metarrays = p->n_metarrays;
9232 rte_swx_ctl_pipeline_numa_node_get(struct rte_swx_pipeline *p, int *numa_node)
9234 if (!p || !numa_node)
9237 *numa_node = p->numa_node;
9242 rte_swx_ctl_action_info_get(struct rte_swx_pipeline *p,
9244 struct rte_swx_ctl_action_info *action)
9246 struct action *a = NULL;
9248 if (!p || (action_id >= p->n_actions) || !action)
9251 a = action_find_by_id(p, action_id);
9255 strcpy(action->name, a->name);
9256 action->n_args = a->st ? a->st->n_fields : 0;
9261 rte_swx_ctl_action_arg_info_get(struct rte_swx_pipeline *p,
9263 uint32_t action_arg_id,
9264 struct rte_swx_ctl_action_arg_info *action_arg)
9266 struct action *a = NULL;
9267 struct field *arg = NULL;
9269 if (!p || (action_id >= p->n_actions) || !action_arg)
9272 a = action_find_by_id(p, action_id);
9273 if (!a || !a->st || (action_arg_id >= a->st->n_fields))
9276 arg = &a->st->fields[action_arg_id];
9277 strcpy(action_arg->name, arg->name);
9278 action_arg->n_bits = arg->n_bits;
9279 action_arg->is_network_byte_order = a->args_endianness[action_arg_id];
9285 rte_swx_ctl_table_info_get(struct rte_swx_pipeline *p,
9287 struct rte_swx_ctl_table_info *table)
9289 struct table *t = NULL;
9294 t = table_find_by_id(p, table_id);
9298 strcpy(table->name, t->name);
9299 strcpy(table->args, t->args);
9300 table->n_match_fields = t->n_fields;
9301 table->n_actions = t->n_actions;
9302 table->default_action_is_const = t->default_action_is_const;
9303 table->size = t->size;
9308 rte_swx_ctl_table_match_field_info_get(struct rte_swx_pipeline *p,
9310 uint32_t match_field_id,
9311 struct rte_swx_ctl_table_match_field_info *match_field)
9314 struct match_field *f;
9316 if (!p || (table_id >= p->n_tables) || !match_field)
9319 t = table_find_by_id(p, table_id);
9320 if (!t || (match_field_id >= t->n_fields))
9323 f = &t->fields[match_field_id];
9324 match_field->match_type = f->match_type;
9325 match_field->is_header = t->header ? 1 : 0;
9326 match_field->n_bits = f->field->n_bits;
9327 match_field->offset = f->field->offset;
9333 rte_swx_ctl_table_action_info_get(struct rte_swx_pipeline *p,
9335 uint32_t table_action_id,
9336 struct rte_swx_ctl_table_action_info *table_action)
9340 if (!p || (table_id >= p->n_tables) || !table_action)
9343 t = table_find_by_id(p, table_id);
9344 if (!t || (table_action_id >= t->n_actions))
9347 table_action->action_id = t->actions[table_action_id]->id;
9349 table_action->action_is_for_table_entries = t->action_is_for_table_entries[table_action_id];
9350 table_action->action_is_for_default_entry = t->action_is_for_default_entry[table_action_id];
9356 rte_swx_ctl_table_ops_get(struct rte_swx_pipeline *p,
9358 struct rte_swx_table_ops *table_ops,
9363 if (!p || (table_id >= p->n_tables))
9366 t = table_find_by_id(p, table_id);
9372 memcpy(table_ops, &t->type->ops, sizeof(*table_ops));
9382 rte_swx_ctl_selector_info_get(struct rte_swx_pipeline *p,
9383 uint32_t selector_id,
9384 struct rte_swx_ctl_selector_info *selector)
9386 struct selector *s = NULL;
9388 if (!p || !selector)
9391 s = selector_find_by_id(p, selector_id);
9395 strcpy(selector->name, s->name);
9397 selector->n_selector_fields = s->n_selector_fields;
9398 selector->n_groups_max = s->n_groups_max;
9399 selector->n_members_per_group_max = s->n_members_per_group_max;
9405 rte_swx_ctl_selector_group_id_field_info_get(struct rte_swx_pipeline *p,
9406 uint32_t selector_id,
9407 struct rte_swx_ctl_table_match_field_info *field)
9411 if (!p || (selector_id >= p->n_selectors) || !field)
9414 s = selector_find_by_id(p, selector_id);
9418 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
9419 field->is_header = 0;
9420 field->n_bits = s->group_id_field->n_bits;
9421 field->offset = s->group_id_field->offset;
9427 rte_swx_ctl_selector_field_info_get(struct rte_swx_pipeline *p,
9428 uint32_t selector_id,
9429 uint32_t selector_field_id,
9430 struct rte_swx_ctl_table_match_field_info *field)
9435 if (!p || (selector_id >= p->n_selectors) || !field)
9438 s = selector_find_by_id(p, selector_id);
9439 if (!s || (selector_field_id >= s->n_selector_fields))
9442 f = s->selector_fields[selector_field_id];
9443 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
9444 field->is_header = s->selector_header ? 1 : 0;
9445 field->n_bits = f->n_bits;
9446 field->offset = f->offset;
9452 rte_swx_ctl_selector_member_id_field_info_get(struct rte_swx_pipeline *p,
9453 uint32_t selector_id,
9454 struct rte_swx_ctl_table_match_field_info *field)
9458 if (!p || (selector_id >= p->n_selectors) || !field)
9461 s = selector_find_by_id(p, selector_id);
9465 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
9466 field->is_header = 0;
9467 field->n_bits = s->member_id_field->n_bits;
9468 field->offset = s->member_id_field->offset;
9474 rte_swx_ctl_learner_info_get(struct rte_swx_pipeline *p,
9475 uint32_t learner_id,
9476 struct rte_swx_ctl_learner_info *learner)
9478 struct learner *l = NULL;
9483 l = learner_find_by_id(p, learner_id);
9487 strcpy(learner->name, l->name);
9489 learner->n_match_fields = l->n_fields;
9490 learner->n_actions = l->n_actions;
9491 learner->default_action_is_const = l->default_action_is_const;
9492 learner->size = l->size;
9498 rte_swx_ctl_learner_match_field_info_get(struct rte_swx_pipeline *p,
9499 uint32_t learner_id,
9500 uint32_t match_field_id,
9501 struct rte_swx_ctl_table_match_field_info *match_field)
9506 if (!p || (learner_id >= p->n_learners) || !match_field)
9509 l = learner_find_by_id(p, learner_id);
9510 if (!l || (match_field_id >= l->n_fields))
9513 f = l->fields[match_field_id];
9514 match_field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
9515 match_field->is_header = l->header ? 1 : 0;
9516 match_field->n_bits = f->n_bits;
9517 match_field->offset = f->offset;
9523 rte_swx_ctl_learner_action_info_get(struct rte_swx_pipeline *p,
9524 uint32_t learner_id,
9525 uint32_t learner_action_id,
9526 struct rte_swx_ctl_table_action_info *learner_action)
9530 if (!p || (learner_id >= p->n_learners) || !learner_action)
9533 l = learner_find_by_id(p, learner_id);
9534 if (!l || (learner_action_id >= l->n_actions))
9537 learner_action->action_id = l->actions[learner_action_id]->id;
9539 learner_action->action_is_for_table_entries =
9540 l->action_is_for_table_entries[learner_action_id];
9542 learner_action->action_is_for_default_entry =
9543 l->action_is_for_default_entry[learner_action_id];
9549 rte_swx_pipeline_table_state_get(struct rte_swx_pipeline *p,
9550 struct rte_swx_table_state **table_state)
9552 if (!p || !table_state || !p->build_done)
9555 *table_state = p->table_state;
9560 rte_swx_pipeline_table_state_set(struct rte_swx_pipeline *p,
9561 struct rte_swx_table_state *table_state)
9563 if (!p || !table_state || !p->build_done)
9566 p->table_state = table_state;
9571 rte_swx_ctl_pipeline_port_in_stats_read(struct rte_swx_pipeline *p,
9573 struct rte_swx_port_in_stats *stats)
9575 struct port_in *port;
9580 port = port_in_find(p, port_id);
9584 port->type->ops.stats_read(port->obj, stats);
9589 rte_swx_ctl_pipeline_port_out_stats_read(struct rte_swx_pipeline *p,
9591 struct rte_swx_port_out_stats *stats)
9593 struct port_out *port;
9598 port = port_out_find(p, port_id);
9602 port->type->ops.stats_read(port->obj, stats);
9607 rte_swx_ctl_pipeline_table_stats_read(struct rte_swx_pipeline *p,
9608 const char *table_name,
9609 struct rte_swx_table_stats *stats)
9611 struct table *table;
9612 struct table_statistics *table_stats;
9614 if (!p || !table_name || !table_name[0] || !stats || !stats->n_pkts_action)
9617 table = table_find(p, table_name);
9621 table_stats = &p->table_stats[table->id];
9623 memcpy(stats->n_pkts_action,
9624 table_stats->n_pkts_action,
9625 p->n_actions * sizeof(uint64_t));
9627 stats->n_pkts_hit = table_stats->n_pkts_hit[1];
9628 stats->n_pkts_miss = table_stats->n_pkts_hit[0];
9634 rte_swx_ctl_pipeline_selector_stats_read(struct rte_swx_pipeline *p,
9635 const char *selector_name,
9636 struct rte_swx_pipeline_selector_stats *stats)
9640 if (!p || !selector_name || !selector_name[0] || !stats)
9643 s = selector_find(p, selector_name);
9647 stats->n_pkts = p->selector_stats[s->id].n_pkts;
9653 rte_swx_ctl_pipeline_learner_stats_read(struct rte_swx_pipeline *p,
9654 const char *learner_name,
9655 struct rte_swx_learner_stats *stats)
9658 struct learner_statistics *learner_stats;
9660 if (!p || !learner_name || !learner_name[0] || !stats || !stats->n_pkts_action)
9663 l = learner_find(p, learner_name);
9667 learner_stats = &p->learner_stats[l->id];
9669 memcpy(stats->n_pkts_action,
9670 learner_stats->n_pkts_action,
9671 p->n_actions * sizeof(uint64_t));
9673 stats->n_pkts_hit = learner_stats->n_pkts_hit[1];
9674 stats->n_pkts_miss = learner_stats->n_pkts_hit[0];
9676 stats->n_pkts_learn_ok = learner_stats->n_pkts_learn[0];
9677 stats->n_pkts_learn_err = learner_stats->n_pkts_learn[1];
9679 stats->n_pkts_forget = learner_stats->n_pkts_forget;
9685 rte_swx_ctl_regarray_info_get(struct rte_swx_pipeline *p,
9686 uint32_t regarray_id,
9687 struct rte_swx_ctl_regarray_info *regarray)
9691 if (!p || !regarray)
9694 r = regarray_find_by_id(p, regarray_id);
9698 strcpy(regarray->name, r->name);
9699 regarray->size = r->size;
9704 rte_swx_ctl_pipeline_regarray_read(struct rte_swx_pipeline *p,
9705 const char *regarray_name,
9706 uint32_t regarray_index,
9709 struct regarray *regarray;
9710 struct regarray_runtime *r;
9712 if (!p || !regarray_name || !value)
9715 regarray = regarray_find(p, regarray_name);
9716 if (!regarray || (regarray_index >= regarray->size))
9719 r = &p->regarray_runtime[regarray->id];
9720 *value = r->regarray[regarray_index];
9725 rte_swx_ctl_pipeline_regarray_write(struct rte_swx_pipeline *p,
9726 const char *regarray_name,
9727 uint32_t regarray_index,
9730 struct regarray *regarray;
9731 struct regarray_runtime *r;
9733 if (!p || !regarray_name)
9736 regarray = regarray_find(p, regarray_name);
9737 if (!regarray || (regarray_index >= regarray->size))
9740 r = &p->regarray_runtime[regarray->id];
9741 r->regarray[regarray_index] = value;
9746 rte_swx_ctl_metarray_info_get(struct rte_swx_pipeline *p,
9747 uint32_t metarray_id,
9748 struct rte_swx_ctl_metarray_info *metarray)
9752 if (!p || !metarray)
9755 m = metarray_find_by_id(p, metarray_id);
9759 strcpy(metarray->name, m->name);
9760 metarray->size = m->size;
9765 rte_swx_ctl_meter_profile_add(struct rte_swx_pipeline *p,
9767 struct rte_meter_trtcm_params *params)
9769 struct meter_profile *mp;
9773 CHECK_NAME(name, EINVAL);
9774 CHECK(params, EINVAL);
9775 CHECK(!meter_profile_find(p, name), EEXIST);
9777 /* Node allocation. */
9778 mp = calloc(1, sizeof(struct meter_profile));
9781 /* Node initialization. */
9782 strcpy(mp->name, name);
9783 memcpy(&mp->params, params, sizeof(struct rte_meter_trtcm_params));
9784 status = rte_meter_trtcm_profile_config(&mp->profile, params);
9790 /* Node add to tailq. */
9791 TAILQ_INSERT_TAIL(&p->meter_profiles, mp, node);
9797 rte_swx_ctl_meter_profile_delete(struct rte_swx_pipeline *p,
9800 struct meter_profile *mp;
9803 CHECK_NAME(name, EINVAL);
9805 mp = meter_profile_find(p, name);
9807 CHECK(!mp->n_users, EBUSY);
9809 /* Remove node from tailq. */
9810 TAILQ_REMOVE(&p->meter_profiles, mp, node);
9817 rte_swx_ctl_meter_reset(struct rte_swx_pipeline *p,
9818 const char *metarray_name,
9819 uint32_t metarray_index)
9821 struct meter_profile *mp_old;
9822 struct metarray *metarray;
9823 struct metarray_runtime *metarray_runtime;
9827 CHECK_NAME(metarray_name, EINVAL);
9829 metarray = metarray_find(p, metarray_name);
9830 CHECK(metarray, EINVAL);
9831 CHECK(metarray_index < metarray->size, EINVAL);
9833 metarray_runtime = &p->metarray_runtime[metarray->id];
9834 m = &metarray_runtime->metarray[metarray_index];
9835 mp_old = m->profile;
9845 rte_swx_ctl_meter_set(struct rte_swx_pipeline *p,
9846 const char *metarray_name,
9847 uint32_t metarray_index,
9848 const char *profile_name)
9850 struct meter_profile *mp, *mp_old;
9851 struct metarray *metarray;
9852 struct metarray_runtime *metarray_runtime;
9856 CHECK_NAME(metarray_name, EINVAL);
9858 metarray = metarray_find(p, metarray_name);
9859 CHECK(metarray, EINVAL);
9860 CHECK(metarray_index < metarray->size, EINVAL);
9862 mp = meter_profile_find(p, profile_name);
9865 metarray_runtime = &p->metarray_runtime[metarray->id];
9866 m = &metarray_runtime->metarray[metarray_index];
9867 mp_old = m->profile;
9869 memset(m, 0, sizeof(struct meter));
9870 rte_meter_trtcm_config(&m->m, &mp->profile);
9872 m->color_mask = RTE_COLORS;
9881 rte_swx_ctl_meter_stats_read(struct rte_swx_pipeline *p,
9882 const char *metarray_name,
9883 uint32_t metarray_index,
9884 struct rte_swx_ctl_meter_stats *stats)
9886 struct metarray *metarray;
9887 struct metarray_runtime *metarray_runtime;
9891 CHECK_NAME(metarray_name, EINVAL);
9893 metarray = metarray_find(p, metarray_name);
9894 CHECK(metarray, EINVAL);
9895 CHECK(metarray_index < metarray->size, EINVAL);
9897 CHECK(stats, EINVAL);
9899 metarray_runtime = &p->metarray_runtime[metarray->id];
9900 m = &metarray_runtime->metarray[metarray_index];
9902 memcpy(stats->n_pkts, m->n_pkts, sizeof(m->n_pkts));
9903 memcpy(stats->n_bytes, m->n_bytes, sizeof(m->n_bytes));
9909 * Pipeline compilation.
9912 instr_type_to_name(struct instruction *instr)
9914 switch (instr->type) {
9915 case INSTR_RX: return "INSTR_RX";
9917 case INSTR_TX: return "INSTR_TX";
9918 case INSTR_TX_I: return "INSTR_TX_I";
9919 case INSTR_DROP: return "INSTR_DROP";
9921 case INSTR_HDR_EXTRACT: return "INSTR_HDR_EXTRACT";
9922 case INSTR_HDR_EXTRACT2: return "INSTR_HDR_EXTRACT2";
9923 case INSTR_HDR_EXTRACT3: return "INSTR_HDR_EXTRACT3";
9924 case INSTR_HDR_EXTRACT4: return "INSTR_HDR_EXTRACT4";
9925 case INSTR_HDR_EXTRACT5: return "INSTR_HDR_EXTRACT5";
9926 case INSTR_HDR_EXTRACT6: return "INSTR_HDR_EXTRACT6";
9927 case INSTR_HDR_EXTRACT7: return "INSTR_HDR_EXTRACT7";
9928 case INSTR_HDR_EXTRACT8: return "INSTR_HDR_EXTRACT8";
9930 case INSTR_HDR_EXTRACT_M: return "INSTR_HDR_EXTRACT_M";
9932 case INSTR_HDR_LOOKAHEAD: return "INSTR_HDR_LOOKAHEAD";
9934 case INSTR_HDR_EMIT: return "INSTR_HDR_EMIT";
9935 case INSTR_HDR_EMIT_TX: return "INSTR_HDR_EMIT_TX";
9936 case INSTR_HDR_EMIT2_TX: return "INSTR_HDR_EMIT2_TX";
9937 case INSTR_HDR_EMIT3_TX: return "INSTR_HDR_EMIT3_TX";
9938 case INSTR_HDR_EMIT4_TX: return "INSTR_HDR_EMIT4_TX";
9939 case INSTR_HDR_EMIT5_TX: return "INSTR_HDR_EMIT5_TX";
9940 case INSTR_HDR_EMIT6_TX: return "INSTR_HDR_EMIT6_TX";
9941 case INSTR_HDR_EMIT7_TX: return "INSTR_HDR_EMIT7_TX";
9942 case INSTR_HDR_EMIT8_TX: return "INSTR_HDR_EMIT8_TX";
9944 case INSTR_HDR_VALIDATE: return "INSTR_HDR_VALIDATE";
9945 case INSTR_HDR_INVALIDATE: return "INSTR_HDR_INVALIDATE";
9947 case INSTR_MOV: return "INSTR_MOV";
9948 case INSTR_MOV_MH: return "INSTR_MOV_MH";
9949 case INSTR_MOV_HM: return "INSTR_MOV_HM";
9950 case INSTR_MOV_HH: return "INSTR_MOV_HH";
9951 case INSTR_MOV_I: return "INSTR_MOV_I";
9953 case INSTR_DMA_HT: return "INSTR_DMA_HT";
9954 case INSTR_DMA_HT2: return "INSTR_DMA_HT2";
9955 case INSTR_DMA_HT3: return "INSTR_DMA_HT3";
9956 case INSTR_DMA_HT4: return "INSTR_DMA_HT4";
9957 case INSTR_DMA_HT5: return "INSTR_DMA_HT5";
9958 case INSTR_DMA_HT6: return "INSTR_DMA_HT6";
9959 case INSTR_DMA_HT7: return "INSTR_DMA_HT7";
9960 case INSTR_DMA_HT8: return "INSTR_DMA_HT8";
9962 case INSTR_ALU_ADD: return "INSTR_ALU_ADD";
9963 case INSTR_ALU_ADD_MH: return "INSTR_ALU_ADD_MH";
9964 case INSTR_ALU_ADD_HM: return "INSTR_ALU_ADD_HM";
9965 case INSTR_ALU_ADD_HH: return "INSTR_ALU_ADD_HH";
9966 case INSTR_ALU_ADD_MI: return "INSTR_ALU_ADD_MI";
9967 case INSTR_ALU_ADD_HI: return "INSTR_ALU_ADD_HI";
9969 case INSTR_ALU_SUB: return "INSTR_ALU_SUB";
9970 case INSTR_ALU_SUB_MH: return "INSTR_ALU_SUB_MH";
9971 case INSTR_ALU_SUB_HM: return "INSTR_ALU_SUB_HM";
9972 case INSTR_ALU_SUB_HH: return "INSTR_ALU_SUB_HH";
9973 case INSTR_ALU_SUB_MI: return "INSTR_ALU_SUB_MI";
9974 case INSTR_ALU_SUB_HI: return "INSTR_ALU_SUB_HI";
9976 case INSTR_ALU_CKADD_FIELD: return "INSTR_ALU_CKADD_FIELD";
9977 case INSTR_ALU_CKADD_STRUCT20: return "INSTR_ALU_CKADD_STRUCT20";
9978 case INSTR_ALU_CKADD_STRUCT: return "INSTR_ALU_CKADD_STRUCT";
9979 case INSTR_ALU_CKSUB_FIELD: return "INSTR_ALU_CKSUB_FIELD";
9981 case INSTR_ALU_AND: return "INSTR_ALU_AND";
9982 case INSTR_ALU_AND_MH: return "INSTR_ALU_AND_MH";
9983 case INSTR_ALU_AND_HM: return "INSTR_ALU_AND_HM";
9984 case INSTR_ALU_AND_HH: return "INSTR_ALU_AND_HH";
9985 case INSTR_ALU_AND_I: return "INSTR_ALU_AND_I";
9987 case INSTR_ALU_OR: return "INSTR_ALU_OR";
9988 case INSTR_ALU_OR_MH: return "INSTR_ALU_OR_MH";
9989 case INSTR_ALU_OR_HM: return "INSTR_ALU_OR_HM";
9990 case INSTR_ALU_OR_HH: return "INSTR_ALU_OR_HH";
9991 case INSTR_ALU_OR_I: return "INSTR_ALU_OR_I";
9993 case INSTR_ALU_XOR: return "INSTR_ALU_XOR";
9994 case INSTR_ALU_XOR_MH: return "INSTR_ALU_XOR_MH";
9995 case INSTR_ALU_XOR_HM: return "INSTR_ALU_XOR_HM";
9996 case INSTR_ALU_XOR_HH: return "INSTR_ALU_XOR_HH";
9997 case INSTR_ALU_XOR_I: return "INSTR_ALU_XOR_I";
9999 case INSTR_ALU_SHL: return "INSTR_ALU_SHL";
10000 case INSTR_ALU_SHL_MH: return "INSTR_ALU_SHL_MH";
10001 case INSTR_ALU_SHL_HM: return "INSTR_ALU_SHL_HM";
10002 case INSTR_ALU_SHL_HH: return "INSTR_ALU_SHL_HH";
10003 case INSTR_ALU_SHL_MI: return "INSTR_ALU_SHL_MI";
10004 case INSTR_ALU_SHL_HI: return "INSTR_ALU_SHL_HI";
10006 case INSTR_ALU_SHR: return "INSTR_ALU_SHR";
10007 case INSTR_ALU_SHR_MH: return "INSTR_ALU_SHR_MH";
10008 case INSTR_ALU_SHR_HM: return "INSTR_ALU_SHR_HM";
10009 case INSTR_ALU_SHR_HH: return "INSTR_ALU_SHR_HH";
10010 case INSTR_ALU_SHR_MI: return "INSTR_ALU_SHR_MI";
10011 case INSTR_ALU_SHR_HI: return "INSTR_ALU_SHR_HI";
10013 case INSTR_REGPREFETCH_RH: return "INSTR_REGPREFETCH_RH";
10014 case INSTR_REGPREFETCH_RM: return "INSTR_REGPREFETCH_RM";
10015 case INSTR_REGPREFETCH_RI: return "INSTR_REGPREFETCH_RI";
10017 case INSTR_REGRD_HRH: return "INSTR_REGRD_HRH";
10018 case INSTR_REGRD_HRM: return "INSTR_REGRD_HRM";
10019 case INSTR_REGRD_HRI: return "INSTR_REGRD_HRI";
10020 case INSTR_REGRD_MRH: return "INSTR_REGRD_MRH";
10021 case INSTR_REGRD_MRM: return "INSTR_REGRD_MRM";
10022 case INSTR_REGRD_MRI: return "INSTR_REGRD_MRI";
10024 case INSTR_REGWR_RHH: return "INSTR_REGWR_RHH";
10025 case INSTR_REGWR_RHM: return "INSTR_REGWR_RHM";
10026 case INSTR_REGWR_RHI: return "INSTR_REGWR_RHI";
10027 case INSTR_REGWR_RMH: return "INSTR_REGWR_RMH";
10028 case INSTR_REGWR_RMM: return "INSTR_REGWR_RMM";
10029 case INSTR_REGWR_RMI: return "INSTR_REGWR_RMI";
10030 case INSTR_REGWR_RIH: return "INSTR_REGWR_RIH";
10031 case INSTR_REGWR_RIM: return "INSTR_REGWR_RIM";
10032 case INSTR_REGWR_RII: return "INSTR_REGWR_RII";
10034 case INSTR_REGADD_RHH: return "INSTR_REGADD_RHH";
10035 case INSTR_REGADD_RHM: return "INSTR_REGADD_RHM";
10036 case INSTR_REGADD_RHI: return "INSTR_REGADD_RHI";
10037 case INSTR_REGADD_RMH: return "INSTR_REGADD_RMH";
10038 case INSTR_REGADD_RMM: return "INSTR_REGADD_RMM";
10039 case INSTR_REGADD_RMI: return "INSTR_REGADD_RMI";
10040 case INSTR_REGADD_RIH: return "INSTR_REGADD_RIH";
10041 case INSTR_REGADD_RIM: return "INSTR_REGADD_RIM";
10042 case INSTR_REGADD_RII: return "INSTR_REGADD_RII";
10044 case INSTR_METPREFETCH_H: return "INSTR_METPREFETCH_H";
10045 case INSTR_METPREFETCH_M: return "INSTR_METPREFETCH_M";
10046 case INSTR_METPREFETCH_I: return "INSTR_METPREFETCH_I";
10048 case INSTR_METER_HHM: return "INSTR_METER_HHM";
10049 case INSTR_METER_HHI: return "INSTR_METER_HHI";
10050 case INSTR_METER_HMM: return "INSTR_METER_HMM";
10051 case INSTR_METER_HMI: return "INSTR_METER_HMI";
10052 case INSTR_METER_MHM: return "INSTR_METER_MHM";
10053 case INSTR_METER_MHI: return "INSTR_METER_MHI";
10054 case INSTR_METER_MMM: return "INSTR_METER_MMM";
10055 case INSTR_METER_MMI: return "INSTR_METER_MMI";
10056 case INSTR_METER_IHM: return "INSTR_METER_IHM";
10057 case INSTR_METER_IHI: return "INSTR_METER_IHI";
10058 case INSTR_METER_IMM: return "INSTR_METER_IMM";
10059 case INSTR_METER_IMI: return "INSTR_METER_IMI";
10061 case INSTR_TABLE: return "INSTR_TABLE";
10062 case INSTR_TABLE_AF: return "INSTR_TABLE_AF";
10063 case INSTR_SELECTOR: return "INSTR_SELECTOR";
10064 case INSTR_LEARNER: return "INSTR_LEARNER";
10065 case INSTR_LEARNER_AF: return "INSTR_LEARNER_AF";
10067 case INSTR_LEARNER_LEARN: return "INSTR_LEARNER_LEARN";
10068 case INSTR_LEARNER_FORGET: return "INSTR_LEARNER_FORGET";
10070 case INSTR_EXTERN_OBJ: return "INSTR_EXTERN_OBJ";
10071 case INSTR_EXTERN_FUNC: return "INSTR_EXTERN_FUNC";
10073 case INSTR_JMP: return "INSTR_JMP";
10074 case INSTR_JMP_VALID: return "INSTR_JMP_VALID";
10075 case INSTR_JMP_INVALID: return "INSTR_JMP_INVALID";
10076 case INSTR_JMP_HIT: return "INSTR_JMP_HIT";
10077 case INSTR_JMP_MISS: return "INSTR_JMP_MISS";
10078 case INSTR_JMP_ACTION_HIT: return "INSTR_JMP_ACTION_HIT";
10079 case INSTR_JMP_ACTION_MISS: return "INSTR_JMP_ACTION_MISS";
10080 case INSTR_JMP_EQ: return "INSTR_JMP_EQ";
10081 case INSTR_JMP_EQ_MH: return "INSTR_JMP_EQ_MH";
10082 case INSTR_JMP_EQ_HM: return "INSTR_JMP_EQ_HM";
10083 case INSTR_JMP_EQ_HH: return "INSTR_JMP_EQ_HH";
10084 case INSTR_JMP_EQ_I: return "INSTR_JMP_EQ_I";
10085 case INSTR_JMP_NEQ: return "INSTR_JMP_NEQ";
10086 case INSTR_JMP_NEQ_MH: return "INSTR_JMP_NEQ_MH";
10087 case INSTR_JMP_NEQ_HM: return "INSTR_JMP_NEQ_HM";
10088 case INSTR_JMP_NEQ_HH: return "INSTR_JMP_NEQ_HH";
10089 case INSTR_JMP_NEQ_I: return "INSTR_JMP_NEQ_I";
10090 case INSTR_JMP_LT: return "INSTR_JMP_LT";
10091 case INSTR_JMP_LT_MH: return "INSTR_JMP_LT_MH";
10092 case INSTR_JMP_LT_HM: return "INSTR_JMP_LT_HM";
10093 case INSTR_JMP_LT_HH: return "INSTR_JMP_LT_HH";
10094 case INSTR_JMP_LT_MI: return "INSTR_JMP_LT_MI";
10095 case INSTR_JMP_LT_HI: return "INSTR_JMP_LT_HI";
10096 case INSTR_JMP_GT: return "INSTR_JMP_GT";
10097 case INSTR_JMP_GT_MH: return "INSTR_JMP_GT_MH";
10098 case INSTR_JMP_GT_HM: return "INSTR_JMP_GT_HM";
10099 case INSTR_JMP_GT_HH: return "INSTR_JMP_GT_HH";
10100 case INSTR_JMP_GT_MI: return "INSTR_JMP_GT_MI";
10101 case INSTR_JMP_GT_HI: return "INSTR_JMP_GT_HI";
10103 case INSTR_RETURN: return "INSTR_RETURN";
10105 default: return "INSTR_UNKNOWN";
10110 (*instruction_export_t)(struct instruction *, FILE *);
10113 instr_io_export(struct instruction *instr, FILE *f)
10115 uint32_t n_io = 0, n_io_imm = 0, n_hdrs = 0, i;
10117 /* n_io, n_io_imm, n_hdrs. */
10118 if (instr->type == INSTR_RX ||
10119 instr->type == INSTR_TX ||
10120 instr->type == INSTR_HDR_EXTRACT_M ||
10121 (instr->type >= INSTR_HDR_EMIT_TX && instr->type <= INSTR_HDR_EMIT8_TX))
10124 if (instr->type == INSTR_TX_I)
10127 if (instr->type >= INSTR_HDR_EXTRACT && instr->type <= INSTR_HDR_EXTRACT8)
10128 n_hdrs = 1 + (instr->type - INSTR_HDR_EXTRACT);
10130 if (instr->type == INSTR_HDR_EXTRACT_M ||
10131 instr->type == INSTR_HDR_LOOKAHEAD ||
10132 instr->type == INSTR_HDR_EMIT)
10135 if (instr->type >= INSTR_HDR_EMIT_TX && instr->type <= INSTR_HDR_EMIT8_TX)
10136 n_hdrs = 1 + (instr->type - INSTR_HDR_EMIT_TX);
10141 "\t\t.type = %s,\n",
10142 instr_type_to_name(instr));
10145 if (n_io || n_io_imm || n_hdrs)
10153 "\t\t\t\t.offset = %u,\n"
10154 "\t\t\t\t.n_bits = %u,\n"
10156 instr->io.io.offset,
10157 instr->io.io.n_bits);
10162 "\t\t\t\t.val = %u,\n"
10166 /* instr.io.hdr. */
10171 /* instr.io.hdr.header_id. */
10173 "\t\t\t.header_id = {");
10175 for (i = 0; i < n_hdrs; i++)
10178 instr->io.hdr.header_id[i]);
10183 /* instr.io.hdr.struct_id. */
10185 "\t\t\t.struct_id = {");
10187 for (i = 0; i < n_hdrs; i++)
10190 instr->io.hdr.struct_id[i]);
10195 /* instr.io.hdr.n_bytes. */
10197 "\t\t\t.n_bytes = {");
10199 for (i = 0; i < n_hdrs; i++)
10202 instr->io.hdr.n_bytes[i]);
10207 /* instr.io.hdr - closing curly brace. */
10212 /* instr.io - closing curly brace. */
10213 if (n_io || n_io_imm || n_hdrs)
10217 /* instr - closing curly brace. */
10223 instr_hdr_validate_export(struct instruction *instr, FILE *f)
10227 "\t\t.type = %s,\n"
10229 "\t\t\t.header_id = %u,\n"
10232 instr_type_to_name(instr),
10233 instr->valid.header_id);
10237 instr_mov_export(struct instruction *instr, FILE *f)
10239 if (instr->type != INSTR_MOV_I)
10242 "\t\t.type = %s,\n"
10245 "\t\t\t\t.struct_id = %u,\n"
10246 "\t\t\t\t.n_bits = %u,\n"
10247 "\t\t\t\t.offset = %u,\n"
10250 "\t\t\t\t.struct_id = %u,\n"
10251 "\t\t\t\t.n_bits = %u,\n"
10252 "\t\t\t\t.offset = %u,\n"
10256 instr_type_to_name(instr),
10257 instr->mov.dst.struct_id,
10258 instr->mov.dst.n_bits,
10259 instr->mov.dst.offset,
10260 instr->mov.src.struct_id,
10261 instr->mov.src.n_bits,
10262 instr->mov.src.offset);
10266 "\t\t.type = %s,\n"
10269 "\t\t\t\t.struct_id = %u,\n"
10270 "\t\t\t\t.n_bits = %u,\n"
10271 "\t\t\t\t.offset = %u,\n"
10273 "\t\t\t.src_val = %" PRIu64 ",\n"
10276 instr_type_to_name(instr),
10277 instr->mov.dst.struct_id,
10278 instr->mov.dst.n_bits,
10279 instr->mov.dst.offset,
10280 instr->mov.src_val);
10284 instr_dma_ht_export(struct instruction *instr, FILE *f)
10286 uint32_t n_dma = 0, i;
10289 n_dma = 1 + (instr->type - INSTR_DMA_HT);
10294 "\t\t.type = %s,\n",
10295 instr_type_to_name(instr));
10301 /* instr.dma.dst. */
10303 "\t\t\t.dst = {\n");
10305 /* instr.dma.dst.header_id. */
10307 "\t\t\t\t.header_id = {");
10309 for (i = 0; i < n_dma; i++)
10312 instr->dma.dst.header_id[i]);
10317 /* instr.dma.dst.struct_id. */
10319 "\t\t\t\t.struct_id = {");
10321 for (i = 0; i < n_dma; i++)
10324 instr->dma.dst.struct_id[i]);
10329 /* instr.dma.dst - closing curly brace. */
10333 /* instr.dma.src. */
10335 "\t\t\t.src = {\n");
10337 /* instr.dma.src.offset. */
10339 "\t\t\t\t.offset = {");
10341 for (i = 0; i < n_dma; i++)
10344 instr->dma.src.offset[i]);
10349 /* instr.dma.src - closing curly brace. */
10353 /* instr.dma.n_bytes. */
10355 "\t\t\t.n_bytes = {");
10357 for (i = 0; i < n_dma; i++)
10360 instr->dma.n_bytes[i]);
10365 /* instr.dma - closing curly brace. */
10369 /* instr - closing curly brace. */
10375 instr_alu_export(struct instruction *instr, FILE *f)
10379 if (instr->type == INSTR_ALU_ADD_MI ||
10380 instr->type == INSTR_ALU_ADD_HI ||
10381 instr->type == INSTR_ALU_SUB_MI ||
10382 instr->type == INSTR_ALU_SUB_HI ||
10383 instr->type == INSTR_ALU_SHL_MI ||
10384 instr->type == INSTR_ALU_SHL_HI ||
10385 instr->type == INSTR_ALU_SHR_MI ||
10386 instr->type == INSTR_ALU_SHR_HI ||
10387 instr->type == INSTR_ALU_AND_I ||
10388 instr->type == INSTR_ALU_OR_I ||
10389 instr->type == INSTR_ALU_XOR_I)
10395 "\t\t.type = %s,\n"
10398 "\t\t\t\t.struct_id = %u,\n"
10399 "\t\t\t\t.n_bits = %u,\n"
10400 "\t\t\t\t.offset = %u,\n"
10403 "\t\t\t\t.struct_id = %u,\n"
10404 "\t\t\t\t.n_bits = %u,\n"
10405 "\t\t\t\t.offset = %u,\n"
10409 instr_type_to_name(instr),
10410 instr->alu.dst.struct_id,
10411 instr->alu.dst.n_bits,
10412 instr->alu.dst.offset,
10413 instr->alu.src.struct_id,
10414 instr->alu.src.n_bits,
10415 instr->alu.src.offset);
10419 "\t\t.type = %s,\n"
10422 "\t\t\t\t.struct_id = %u,\n"
10423 "\t\t\t\t.n_bits = %u,\n"
10424 "\t\t\t\t.offset = %u,\n"
10426 "\t\t\t.src_val = %" PRIu64 ",\n"
10429 instr_type_to_name(instr),
10430 instr->alu.dst.struct_id,
10431 instr->alu.dst.n_bits,
10432 instr->alu.dst.offset,
10433 instr->alu.src_val);
10437 instr_reg_export(struct instruction *instr __rte_unused, FILE *f __rte_unused)
10439 int prefetch = 0, idx_imm = 0, src_imm = 0;
10441 if (instr->type == INSTR_REGPREFETCH_RH ||
10442 instr->type == INSTR_REGPREFETCH_RM ||
10443 instr->type == INSTR_REGPREFETCH_RI)
10446 /* index is the 3rd operand for the regrd instruction and the 2nd
10447 * operand for the regwr and regadd instructions.
10449 if (instr->type == INSTR_REGPREFETCH_RI ||
10450 instr->type == INSTR_REGRD_HRI ||
10451 instr->type == INSTR_REGRD_MRI ||
10452 instr->type == INSTR_REGWR_RIH ||
10453 instr->type == INSTR_REGWR_RIM ||
10454 instr->type == INSTR_REGWR_RII ||
10455 instr->type == INSTR_REGADD_RIH ||
10456 instr->type == INSTR_REGADD_RIM ||
10457 instr->type == INSTR_REGADD_RII)
10460 /* src is the 3rd operand for the regwr and regadd instructions. */
10461 if (instr->type == INSTR_REGWR_RHI ||
10462 instr->type == INSTR_REGWR_RMI ||
10463 instr->type == INSTR_REGWR_RII ||
10464 instr->type == INSTR_REGADD_RHI ||
10465 instr->type == INSTR_REGADD_RMI ||
10466 instr->type == INSTR_REGADD_RII)
10469 /* instr.regarray.regarray_id. */
10472 "\t\t.type = %s,\n"
10473 "\t\t.regarray = {\n"
10474 "\t\t\t.regarray_id = %u,\n",
10475 instr_type_to_name(instr),
10476 instr->regarray.regarray_id);
10478 /* instr.regarray.idx / instr.regarray.idx_val. */
10481 "\t\t\t\t.idx = {\n"
10482 "\t\t\t\t\t.struct_id = %u,\n"
10483 "\t\t\t\t\t.n_bits = %u,\n"
10484 "\t\t\t\t\t.offset = %u,\n"
10486 instr->regarray.idx.struct_id,
10487 instr->regarray.idx.n_bits,
10488 instr->regarray.idx.offset);
10491 "\t\t\t\t.idx_val = %u,\n",
10492 instr->regarray.idx_val);
10494 /* instr.regarray.dstsrc / instr.regarray.dstsrc_val. */
10498 "\t\t\t\t.dstsrc = {\n"
10499 "\t\t\t\t\t.struct_id = %u,\n"
10500 "\t\t\t\t\t.n_bits = %u,\n"
10501 "\t\t\t\t\t.offset = %u,\n"
10503 instr->regarray.dstsrc.struct_id,
10504 instr->regarray.dstsrc.n_bits,
10505 instr->regarray.dstsrc.offset);
10508 "\t\t\t\t.dstsrc_val = %" PRIu64 ",\n",
10509 instr->regarray.dstsrc_val);
10512 /* instr.regarray and instr - closing curly braces. */
10519 instr_meter_export(struct instruction *instr __rte_unused, FILE *f __rte_unused)
10521 int prefetch = 0, idx_imm = 0, color_in_imm = 0;
10523 if (instr->type == INSTR_METPREFETCH_H ||
10524 instr->type == INSTR_METPREFETCH_M ||
10525 instr->type == INSTR_METPREFETCH_I)
10529 if (instr->type == INSTR_METPREFETCH_I ||
10530 instr->type == INSTR_METER_IHM ||
10531 instr->type == INSTR_METER_IHI ||
10532 instr->type == INSTR_METER_IMM ||
10533 instr->type == INSTR_METER_IMI)
10536 /* color_in_imm. */
10537 if (instr->type == INSTR_METER_HHI ||
10538 instr->type == INSTR_METER_HMI ||
10539 instr->type == INSTR_METER_MHI ||
10540 instr->type == INSTR_METER_MMI ||
10541 instr->type == INSTR_METER_IHI ||
10542 instr->type == INSTR_METER_IMI)
10545 /* instr.meter.metarray_id. */
10548 "\t\t.type = %s,\n"
10550 "\t\t\t.metarray_id = %u,\n",
10551 instr_type_to_name(instr),
10552 instr->meter.metarray_id);
10554 /* instr.meter.idx / instr.meter.idx_val. */
10558 "\t\t\t\t.struct_id = %u,\n"
10559 "\t\t\t\t.n_bits = %u,\n"
10560 "\t\t\t\t.offset = %u,\n"
10562 instr->meter.idx.struct_id,
10563 instr->meter.idx.n_bits,
10564 instr->meter.idx.offset);
10567 "\t\t\t.idx_val = %u,\n",
10568 instr->meter.idx_val);
10571 /* instr.meter.length. */
10573 "\t\t\t.length = {\n"
10574 "\t\t\t\t.struct_id = %u,\n"
10575 "\t\t\t\t.n_bits = %u,\n"
10576 "\t\t\t\t.offset = %u,\n"
10578 instr->meter.length.struct_id,
10579 instr->meter.length.n_bits,
10580 instr->meter.length.offset);
10582 /* instr.meter.color_in / instr.meter.color_in_val. */
10585 "\t\t\t.color_in = {\n"
10586 "\t\t\t\t.struct_id = %u,\n"
10587 "\t\t\t\t.n_bits = %u,\n"
10588 "\t\t\t\t.offset = %u,\n"
10590 instr->meter.color_in.struct_id,
10591 instr->meter.color_in.n_bits,
10592 instr->meter.color_in.offset);
10595 "\t\t\t.color_in_val = %u,\n",
10596 (uint32_t)instr->meter.color_in_val);
10598 /* instr.meter.color_out. */
10600 "\t\t\t.color_out = {\n"
10601 "\t\t\t\t.struct_id = %u,\n"
10602 "\t\t\t\t.n_bits = %u,\n"
10603 "\t\t\t\t.offset = %u,\n"
10605 instr->meter.color_out.struct_id,
10606 instr->meter.color_out.n_bits,
10607 instr->meter.color_out.offset);
10610 /* instr.meter and instr - closing curly braces. */
10617 instr_table_export(struct instruction *instr,
10622 "\t\t.type = %s,\n"
10624 "\t\t\t.table_id = %u,\n"
10627 instr_type_to_name(instr),
10628 instr->table.table_id);
10632 instr_learn_export(struct instruction *instr, FILE *f)
10636 "\t\t.type = %s,\n"
10638 "\t\t\t\t.action_id = %u,\n"
10641 instr_type_to_name(instr),
10642 instr->learn.action_id);
10646 instr_forget_export(struct instruction *instr, FILE *f)
10650 "\t\t.type = %s,\n"
10652 instr_type_to_name(instr));
10656 instr_extern_export(struct instruction *instr, FILE *f)
10658 if (instr->type == INSTR_EXTERN_OBJ)
10661 "\t\t.type = %s,\n"
10662 "\t\t.ext_obj = {\n"
10663 "\t\t\t.ext_obj_id = %u,\n"
10664 "\t\t\t.func_id = %u,\n"
10667 instr_type_to_name(instr),
10668 instr->ext_obj.ext_obj_id,
10669 instr->ext_obj.func_id);
10673 "\t\t.type = %s,\n"
10674 "\t\t.ext_func = {\n"
10675 "\t\t\t.ext_func_id = %u,\n"
10678 instr_type_to_name(instr),
10679 instr->ext_func.ext_func_id);
10683 instr_jmp_export(struct instruction *instr, FILE *f __rte_unused)
10687 "\t\t.type = %s,\n"
10689 "\t\t\t.ip = NULL,\n",
10690 instr_type_to_name(instr));
10692 switch (instr->type) {
10693 case INSTR_JMP_VALID:
10694 case INSTR_JMP_INVALID:
10696 "\t\t\t.header_id = %u,\n",
10697 instr->jmp.header_id);
10700 case INSTR_JMP_ACTION_HIT:
10701 case INSTR_JMP_ACTION_MISS:
10703 "\t\t\t.action_id = %u,\n",
10704 instr->jmp.action_id);
10708 case INSTR_JMP_EQ_MH:
10709 case INSTR_JMP_EQ_HM:
10710 case INSTR_JMP_EQ_HH:
10711 case INSTR_JMP_NEQ:
10712 case INSTR_JMP_NEQ_MH:
10713 case INSTR_JMP_NEQ_HM:
10714 case INSTR_JMP_NEQ_HH:
10716 case INSTR_JMP_LT_MH:
10717 case INSTR_JMP_LT_HM:
10718 case INSTR_JMP_LT_HH:
10720 case INSTR_JMP_GT_MH:
10721 case INSTR_JMP_GT_HM:
10722 case INSTR_JMP_GT_HH:
10725 "\t\t\t\t.struct_id = %u,\n"
10726 "\t\t\t\t.n_bits = %u,\n"
10727 "\t\t\t\t.offset = %u,\n"
10730 "\t\t\t\t.struct_id = %u,\n"
10731 "\t\t\t\t.n_bits = %u,\n"
10732 "\t\t\t\t.offset = %u,\n"
10734 instr->jmp.a.struct_id,
10735 instr->jmp.a.n_bits,
10736 instr->jmp.a.offset,
10737 instr->jmp.b.struct_id,
10738 instr->jmp.b.n_bits,
10739 instr->jmp.b.offset);
10742 case INSTR_JMP_EQ_I:
10743 case INSTR_JMP_NEQ_I:
10744 case INSTR_JMP_LT_MI:
10745 case INSTR_JMP_LT_HI:
10746 case INSTR_JMP_GT_MI:
10747 case INSTR_JMP_GT_HI:
10750 "\t\t\t\t.struct_id = %u,\n"
10751 "\t\t\t\t.n_bits = %u,\n"
10752 "\t\t\t\t.offset = %u,\n"
10754 "\t\t\t.b_val = %" PRIu64 ",\n",
10755 instr->jmp.a.struct_id,
10756 instr->jmp.a.n_bits,
10757 instr->jmp.a.offset,
10771 instr_return_export(struct instruction *instr,
10776 "\t\t.type = %s,\n",
10777 instr_type_to_name(instr));
10783 static instruction_export_t export_table[] = {
10784 [INSTR_RX] = instr_io_export,
10786 [INSTR_TX] = instr_io_export,
10787 [INSTR_TX_I] = instr_io_export,
10788 [INSTR_DROP] = instr_io_export,
10790 [INSTR_HDR_EXTRACT] = instr_io_export,
10791 [INSTR_HDR_EXTRACT2] = instr_io_export,
10792 [INSTR_HDR_EXTRACT3] = instr_io_export,
10793 [INSTR_HDR_EXTRACT4] = instr_io_export,
10794 [INSTR_HDR_EXTRACT5] = instr_io_export,
10795 [INSTR_HDR_EXTRACT6] = instr_io_export,
10796 [INSTR_HDR_EXTRACT7] = instr_io_export,
10797 [INSTR_HDR_EXTRACT8] = instr_io_export,
10799 [INSTR_HDR_EXTRACT_M] = instr_io_export,
10801 [INSTR_HDR_LOOKAHEAD] = instr_io_export,
10803 [INSTR_HDR_EMIT] = instr_io_export,
10804 [INSTR_HDR_EMIT_TX] = instr_io_export,
10805 [INSTR_HDR_EMIT2_TX] = instr_io_export,
10806 [INSTR_HDR_EMIT3_TX] = instr_io_export,
10807 [INSTR_HDR_EMIT4_TX] = instr_io_export,
10808 [INSTR_HDR_EMIT5_TX] = instr_io_export,
10809 [INSTR_HDR_EMIT6_TX] = instr_io_export,
10810 [INSTR_HDR_EMIT7_TX] = instr_io_export,
10811 [INSTR_HDR_EMIT8_TX] = instr_io_export,
10813 [INSTR_HDR_VALIDATE] = instr_hdr_validate_export,
10814 [INSTR_HDR_INVALIDATE] = instr_hdr_validate_export,
10816 [INSTR_MOV] = instr_mov_export,
10817 [INSTR_MOV_MH] = instr_mov_export,
10818 [INSTR_MOV_HM] = instr_mov_export,
10819 [INSTR_MOV_HH] = instr_mov_export,
10820 [INSTR_MOV_I] = instr_mov_export,
10822 [INSTR_DMA_HT] = instr_dma_ht_export,
10823 [INSTR_DMA_HT2] = instr_dma_ht_export,
10824 [INSTR_DMA_HT3] = instr_dma_ht_export,
10825 [INSTR_DMA_HT4] = instr_dma_ht_export,
10826 [INSTR_DMA_HT5] = instr_dma_ht_export,
10827 [INSTR_DMA_HT6] = instr_dma_ht_export,
10828 [INSTR_DMA_HT7] = instr_dma_ht_export,
10829 [INSTR_DMA_HT8] = instr_dma_ht_export,
10831 [INSTR_ALU_ADD] = instr_alu_export,
10832 [INSTR_ALU_ADD_MH] = instr_alu_export,
10833 [INSTR_ALU_ADD_HM] = instr_alu_export,
10834 [INSTR_ALU_ADD_HH] = instr_alu_export,
10835 [INSTR_ALU_ADD_MI] = instr_alu_export,
10836 [INSTR_ALU_ADD_HI] = instr_alu_export,
10838 [INSTR_ALU_SUB] = instr_alu_export,
10839 [INSTR_ALU_SUB_MH] = instr_alu_export,
10840 [INSTR_ALU_SUB_HM] = instr_alu_export,
10841 [INSTR_ALU_SUB_HH] = instr_alu_export,
10842 [INSTR_ALU_SUB_MI] = instr_alu_export,
10843 [INSTR_ALU_SUB_HI] = instr_alu_export,
10845 [INSTR_ALU_CKADD_FIELD] = instr_alu_export,
10846 [INSTR_ALU_CKADD_STRUCT] = instr_alu_export,
10847 [INSTR_ALU_CKADD_STRUCT20] = instr_alu_export,
10848 [INSTR_ALU_CKSUB_FIELD] = instr_alu_export,
10850 [INSTR_ALU_AND] = instr_alu_export,
10851 [INSTR_ALU_AND_MH] = instr_alu_export,
10852 [INSTR_ALU_AND_HM] = instr_alu_export,
10853 [INSTR_ALU_AND_HH] = instr_alu_export,
10854 [INSTR_ALU_AND_I] = instr_alu_export,
10856 [INSTR_ALU_OR] = instr_alu_export,
10857 [INSTR_ALU_OR_MH] = instr_alu_export,
10858 [INSTR_ALU_OR_HM] = instr_alu_export,
10859 [INSTR_ALU_OR_HH] = instr_alu_export,
10860 [INSTR_ALU_OR_I] = instr_alu_export,
10862 [INSTR_ALU_XOR] = instr_alu_export,
10863 [INSTR_ALU_XOR_MH] = instr_alu_export,
10864 [INSTR_ALU_XOR_HM] = instr_alu_export,
10865 [INSTR_ALU_XOR_HH] = instr_alu_export,
10866 [INSTR_ALU_XOR_I] = instr_alu_export,
10868 [INSTR_ALU_SHL] = instr_alu_export,
10869 [INSTR_ALU_SHL_MH] = instr_alu_export,
10870 [INSTR_ALU_SHL_HM] = instr_alu_export,
10871 [INSTR_ALU_SHL_HH] = instr_alu_export,
10872 [INSTR_ALU_SHL_MI] = instr_alu_export,
10873 [INSTR_ALU_SHL_HI] = instr_alu_export,
10875 [INSTR_ALU_SHR] = instr_alu_export,
10876 [INSTR_ALU_SHR_MH] = instr_alu_export,
10877 [INSTR_ALU_SHR_HM] = instr_alu_export,
10878 [INSTR_ALU_SHR_HH] = instr_alu_export,
10879 [INSTR_ALU_SHR_MI] = instr_alu_export,
10880 [INSTR_ALU_SHR_HI] = instr_alu_export,
10882 [INSTR_REGPREFETCH_RH] = instr_reg_export,
10883 [INSTR_REGPREFETCH_RM] = instr_reg_export,
10884 [INSTR_REGPREFETCH_RI] = instr_reg_export,
10886 [INSTR_REGRD_HRH] = instr_reg_export,
10887 [INSTR_REGRD_HRM] = instr_reg_export,
10888 [INSTR_REGRD_MRH] = instr_reg_export,
10889 [INSTR_REGRD_MRM] = instr_reg_export,
10890 [INSTR_REGRD_HRI] = instr_reg_export,
10891 [INSTR_REGRD_MRI] = instr_reg_export,
10893 [INSTR_REGWR_RHH] = instr_reg_export,
10894 [INSTR_REGWR_RHM] = instr_reg_export,
10895 [INSTR_REGWR_RMH] = instr_reg_export,
10896 [INSTR_REGWR_RMM] = instr_reg_export,
10897 [INSTR_REGWR_RHI] = instr_reg_export,
10898 [INSTR_REGWR_RMI] = instr_reg_export,
10899 [INSTR_REGWR_RIH] = instr_reg_export,
10900 [INSTR_REGWR_RIM] = instr_reg_export,
10901 [INSTR_REGWR_RII] = instr_reg_export,
10903 [INSTR_REGADD_RHH] = instr_reg_export,
10904 [INSTR_REGADD_RHM] = instr_reg_export,
10905 [INSTR_REGADD_RMH] = instr_reg_export,
10906 [INSTR_REGADD_RMM] = instr_reg_export,
10907 [INSTR_REGADD_RHI] = instr_reg_export,
10908 [INSTR_REGADD_RMI] = instr_reg_export,
10909 [INSTR_REGADD_RIH] = instr_reg_export,
10910 [INSTR_REGADD_RIM] = instr_reg_export,
10911 [INSTR_REGADD_RII] = instr_reg_export,
10913 [INSTR_METPREFETCH_H] = instr_meter_export,
10914 [INSTR_METPREFETCH_M] = instr_meter_export,
10915 [INSTR_METPREFETCH_I] = instr_meter_export,
10917 [INSTR_METER_HHM] = instr_meter_export,
10918 [INSTR_METER_HHI] = instr_meter_export,
10919 [INSTR_METER_HMM] = instr_meter_export,
10920 [INSTR_METER_HMI] = instr_meter_export,
10921 [INSTR_METER_MHM] = instr_meter_export,
10922 [INSTR_METER_MHI] = instr_meter_export,
10923 [INSTR_METER_MMM] = instr_meter_export,
10924 [INSTR_METER_MMI] = instr_meter_export,
10925 [INSTR_METER_IHM] = instr_meter_export,
10926 [INSTR_METER_IHI] = instr_meter_export,
10927 [INSTR_METER_IMM] = instr_meter_export,
10928 [INSTR_METER_IMI] = instr_meter_export,
10930 [INSTR_TABLE] = instr_table_export,
10931 [INSTR_TABLE_AF] = instr_table_export,
10932 [INSTR_SELECTOR] = instr_table_export,
10933 [INSTR_LEARNER] = instr_table_export,
10934 [INSTR_LEARNER_AF] = instr_table_export,
10936 [INSTR_LEARNER_LEARN] = instr_learn_export,
10937 [INSTR_LEARNER_FORGET] = instr_forget_export,
10939 [INSTR_EXTERN_OBJ] = instr_extern_export,
10940 [INSTR_EXTERN_FUNC] = instr_extern_export,
10942 [INSTR_JMP] = instr_jmp_export,
10943 [INSTR_JMP_VALID] = instr_jmp_export,
10944 [INSTR_JMP_INVALID] = instr_jmp_export,
10945 [INSTR_JMP_HIT] = instr_jmp_export,
10946 [INSTR_JMP_MISS] = instr_jmp_export,
10947 [INSTR_JMP_ACTION_HIT] = instr_jmp_export,
10948 [INSTR_JMP_ACTION_MISS] = instr_jmp_export,
10950 [INSTR_JMP_EQ] = instr_jmp_export,
10951 [INSTR_JMP_EQ_MH] = instr_jmp_export,
10952 [INSTR_JMP_EQ_HM] = instr_jmp_export,
10953 [INSTR_JMP_EQ_HH] = instr_jmp_export,
10954 [INSTR_JMP_EQ_I] = instr_jmp_export,
10956 [INSTR_JMP_NEQ] = instr_jmp_export,
10957 [INSTR_JMP_NEQ_MH] = instr_jmp_export,
10958 [INSTR_JMP_NEQ_HM] = instr_jmp_export,
10959 [INSTR_JMP_NEQ_HH] = instr_jmp_export,
10960 [INSTR_JMP_NEQ_I] = instr_jmp_export,
10962 [INSTR_JMP_LT] = instr_jmp_export,
10963 [INSTR_JMP_LT_MH] = instr_jmp_export,
10964 [INSTR_JMP_LT_HM] = instr_jmp_export,
10965 [INSTR_JMP_LT_HH] = instr_jmp_export,
10966 [INSTR_JMP_LT_MI] = instr_jmp_export,
10967 [INSTR_JMP_LT_HI] = instr_jmp_export,
10969 [INSTR_JMP_GT] = instr_jmp_export,
10970 [INSTR_JMP_GT_MH] = instr_jmp_export,
10971 [INSTR_JMP_GT_HM] = instr_jmp_export,
10972 [INSTR_JMP_GT_HH] = instr_jmp_export,
10973 [INSTR_JMP_GT_MI] = instr_jmp_export,
10974 [INSTR_JMP_GT_HI] = instr_jmp_export,
10976 [INSTR_RETURN] = instr_return_export,
10980 action_data_codegen(struct action *a, FILE *f)
10985 "static const struct instruction action_%s_instructions[] = {\n",
10988 for (i = 0; i < a->n_instructions; i++) {
10989 struct instruction *instr = &a->instructions[i];
10990 instruction_export_t func = export_table[instr->type];
10995 fprintf(f, "};\n");
10998 static const char *
10999 instr_type_to_func(struct instruction *instr)
11001 switch (instr->type) {
11002 case INSTR_RX: return NULL;
11004 case INSTR_TX: return "__instr_tx_exec";
11005 case INSTR_TX_I: return "__instr_tx_i_exec";
11006 case INSTR_DROP: return "__instr_drop_exec";
11008 case INSTR_HDR_EXTRACT: return "__instr_hdr_extract_exec";
11009 case INSTR_HDR_EXTRACT2: return "__instr_hdr_extract2_exec";
11010 case INSTR_HDR_EXTRACT3: return "__instr_hdr_extract3_exec";
11011 case INSTR_HDR_EXTRACT4: return "__instr_hdr_extract4_exec";
11012 case INSTR_HDR_EXTRACT5: return "__instr_hdr_extract5_exec";
11013 case INSTR_HDR_EXTRACT6: return "__instr_hdr_extract6_exec";
11014 case INSTR_HDR_EXTRACT7: return "__instr_hdr_extract7_exec";
11015 case INSTR_HDR_EXTRACT8: return "__instr_hdr_extract8_exec";
11017 case INSTR_HDR_EXTRACT_M: return "__instr_hdr_extract_m_exec";
11019 case INSTR_HDR_LOOKAHEAD: return "__instr_hdr_lookahead_exec";
11021 case INSTR_HDR_EMIT: return "__instr_hdr_emit_exec";
11022 case INSTR_HDR_EMIT_TX: return "__instr_hdr_emit_tx_exec";
11023 case INSTR_HDR_EMIT2_TX: return "__instr_hdr_emit2_tx_exec";
11024 case INSTR_HDR_EMIT3_TX: return "__instr_hdr_emit3_tx_exec";
11025 case INSTR_HDR_EMIT4_TX: return "__instr_hdr_emit4_tx_exec";
11026 case INSTR_HDR_EMIT5_TX: return "__instr_hdr_emit5_tx_exec";
11027 case INSTR_HDR_EMIT6_TX: return "__instr_hdr_emit6_tx_exec";
11028 case INSTR_HDR_EMIT7_TX: return "__instr_hdr_emit7_tx_exec";
11029 case INSTR_HDR_EMIT8_TX: return "__instr_hdr_emit8_tx_exec";
11031 case INSTR_HDR_VALIDATE: return "__instr_hdr_validate_exec";
11032 case INSTR_HDR_INVALIDATE: return "__instr_hdr_invalidate_exec";
11034 case INSTR_MOV: return "__instr_mov_exec";
11035 case INSTR_MOV_MH: return "__instr_mov_mh_exec";
11036 case INSTR_MOV_HM: return "__instr_mov_hm_exec";
11037 case INSTR_MOV_HH: return "__instr_mov_hh_exec";
11038 case INSTR_MOV_I: return "__instr_mov_i_exec";
11040 case INSTR_DMA_HT: return "__instr_dma_ht_exec";
11041 case INSTR_DMA_HT2: return "__instr_dma_ht2_exec";
11042 case INSTR_DMA_HT3: return "__instr_dma_ht3_exec";
11043 case INSTR_DMA_HT4: return "__instr_dma_ht4_exec";
11044 case INSTR_DMA_HT5: return "__instr_dma_ht5_exec";
11045 case INSTR_DMA_HT6: return "__instr_dma_ht6_exec";
11046 case INSTR_DMA_HT7: return "__instr_dma_ht7_exec";
11047 case INSTR_DMA_HT8: return "__instr_dma_ht8_exec";
11049 case INSTR_ALU_ADD: return "__instr_alu_add_exec";
11050 case INSTR_ALU_ADD_MH: return "__instr_alu_add_mh_exec";
11051 case INSTR_ALU_ADD_HM: return "__instr_alu_add_hm_exec";
11052 case INSTR_ALU_ADD_HH: return "__instr_alu_add_hh_exec";
11053 case INSTR_ALU_ADD_MI: return "__instr_alu_add_mi_exec";
11054 case INSTR_ALU_ADD_HI: return "__instr_alu_add_hi_exec";
11056 case INSTR_ALU_SUB: return "__instr_alu_sub_exec";
11057 case INSTR_ALU_SUB_MH: return "__instr_alu_sub_mh_exec";
11058 case INSTR_ALU_SUB_HM: return "__instr_alu_sub_hm_exec";
11059 case INSTR_ALU_SUB_HH: return "__instr_alu_sub_hh_exec";
11060 case INSTR_ALU_SUB_MI: return "__instr_alu_sub_mi_exec";
11061 case INSTR_ALU_SUB_HI: return "__instr_alu_sub_hi_exec";
11063 case INSTR_ALU_CKADD_FIELD: return "__instr_alu_ckadd_field_exec";
11064 case INSTR_ALU_CKADD_STRUCT20: return "__instr_alu_ckadd_struct20_exec";
11065 case INSTR_ALU_CKADD_STRUCT: return "__instr_alu_ckadd_struct_exec";
11066 case INSTR_ALU_CKSUB_FIELD: return "__instr_alu_cksub_field_exec";
11068 case INSTR_ALU_AND: return "__instr_alu_and_exec";
11069 case INSTR_ALU_AND_MH: return "__instr_alu_and_mh_exec";
11070 case INSTR_ALU_AND_HM: return "__instr_alu_and_hm_exec";
11071 case INSTR_ALU_AND_HH: return "__instr_alu_and_hh_exec";
11072 case INSTR_ALU_AND_I: return "__instr_alu_and_i_exec";
11074 case INSTR_ALU_OR: return "__instr_alu_or_exec";
11075 case INSTR_ALU_OR_MH: return "__instr_alu_or_mh_exec";
11076 case INSTR_ALU_OR_HM: return "__instr_alu_or_hm_exec";
11077 case INSTR_ALU_OR_HH: return "__instr_alu_or_hh_exec";
11078 case INSTR_ALU_OR_I: return "__instr_alu_or_i_exec";
11080 case INSTR_ALU_XOR: return "__instr_alu_xor_exec";
11081 case INSTR_ALU_XOR_MH: return "__instr_alu_xor_mh_exec";
11082 case INSTR_ALU_XOR_HM: return "__instr_alu_xor_hm_exec";
11083 case INSTR_ALU_XOR_HH: return "__instr_alu_xor_hh_exec";
11084 case INSTR_ALU_XOR_I: return "__instr_alu_xor_i_exec";
11086 case INSTR_ALU_SHL: return "__instr_alu_shl_exec";
11087 case INSTR_ALU_SHL_MH: return "__instr_alu_shl_mh_exec";
11088 case INSTR_ALU_SHL_HM: return "__instr_alu_shl_hm_exec";
11089 case INSTR_ALU_SHL_HH: return "__instr_alu_shl_hh_exec";
11090 case INSTR_ALU_SHL_MI: return "__instr_alu_shl_mi_exec";
11091 case INSTR_ALU_SHL_HI: return "__instr_alu_shl_hi_exec";
11093 case INSTR_ALU_SHR: return "__instr_alu_shr_exec";
11094 case INSTR_ALU_SHR_MH: return "__instr_alu_shr_mh_exec";
11095 case INSTR_ALU_SHR_HM: return "__instr_alu_shr_hm_exec";
11096 case INSTR_ALU_SHR_HH: return "__instr_alu_shr_hh_exec";
11097 case INSTR_ALU_SHR_MI: return "__instr_alu_shr_mi_exec";
11098 case INSTR_ALU_SHR_HI: return "__instr_alu_shr_hi_exec";
11100 case INSTR_REGPREFETCH_RH: return "__instr_regprefetch_rh_exec";
11101 case INSTR_REGPREFETCH_RM: return "__instr_regprefetch_rm_exec";
11102 case INSTR_REGPREFETCH_RI: return "__instr_regprefetch_ri_exec";
11104 case INSTR_REGRD_HRH: return "__instr_regrd_hrh_exec";
11105 case INSTR_REGRD_HRM: return "__instr_regrd_hrm_exec";
11106 case INSTR_REGRD_HRI: return "__instr_regrd_hri_exec";
11107 case INSTR_REGRD_MRH: return "__instr_regrd_mrh_exec";
11108 case INSTR_REGRD_MRM: return "__instr_regrd_mrm_exec";
11109 case INSTR_REGRD_MRI: return "__instr_regrd_mri_exec";
11111 case INSTR_REGWR_RHH: return "__instr_regwr_rhh_exec";
11112 case INSTR_REGWR_RHM: return "__instr_regwr_rhm_exec";
11113 case INSTR_REGWR_RHI: return "__instr_regwr_rhi_exec";
11114 case INSTR_REGWR_RMH: return "__instr_regwr_rmh_exec";
11115 case INSTR_REGWR_RMM: return "__instr_regwr_rmm_exec";
11116 case INSTR_REGWR_RMI: return "__instr_regwr_rmi_exec";
11117 case INSTR_REGWR_RIH: return "__instr_regwr_rih_exec";
11118 case INSTR_REGWR_RIM: return "__instr_regwr_rim_exec";
11119 case INSTR_REGWR_RII: return "__instr_regwr_rii_exec";
11121 case INSTR_REGADD_RHH: return "__instr_regadd_rhh_exec";
11122 case INSTR_REGADD_RHM: return "__instr_regadd_rhm_exec";
11123 case INSTR_REGADD_RHI: return "__instr_regadd_rhi_exec";
11124 case INSTR_REGADD_RMH: return "__instr_regadd_rmh_exec";
11125 case INSTR_REGADD_RMM: return "__instr_regadd_rmm_exec";
11126 case INSTR_REGADD_RMI: return "__instr_regadd_rmi_exec";
11127 case INSTR_REGADD_RIH: return "__instr_regadd_rih_exec";
11128 case INSTR_REGADD_RIM: return "__instr_regadd_rim_exec";
11129 case INSTR_REGADD_RII: return "__instr_regadd_rii_exec";
11131 case INSTR_METPREFETCH_H: return "__instr_metprefetch_h_exec";
11132 case INSTR_METPREFETCH_M: return "__instr_metprefetch_m_exec";
11133 case INSTR_METPREFETCH_I: return "__instr_metprefetch_i_exec";
11135 case INSTR_METER_HHM: return "__instr_meter_hhm_exec";
11136 case INSTR_METER_HHI: return "__instr_meter_hhi_exec";
11137 case INSTR_METER_HMM: return "__instr_meter_hmm_exec";
11138 case INSTR_METER_HMI: return "__instr_meter_hmi_exec";
11139 case INSTR_METER_MHM: return "__instr_meter_mhm_exec";
11140 case INSTR_METER_MHI: return "__instr_meter_mhi_exec";
11141 case INSTR_METER_MMM: return "__instr_meter_mmm_exec";
11142 case INSTR_METER_MMI: return "__instr_meter_mmi_exec";
11143 case INSTR_METER_IHM: return "__instr_meter_ihm_exec";
11144 case INSTR_METER_IHI: return "__instr_meter_ihi_exec";
11145 case INSTR_METER_IMM: return "__instr_meter_imm_exec";
11146 case INSTR_METER_IMI: return "__instr_meter_imi_exec";
11148 case INSTR_TABLE: return NULL;
11149 case INSTR_TABLE_AF: return NULL;
11150 case INSTR_SELECTOR: return NULL;
11151 case INSTR_LEARNER: return NULL;
11152 case INSTR_LEARNER_AF: return NULL;
11154 case INSTR_LEARNER_LEARN: return "__instr_learn_exec";
11155 case INSTR_LEARNER_FORGET: return "__instr_forget_exec";
11157 case INSTR_EXTERN_OBJ: return NULL;
11158 case INSTR_EXTERN_FUNC: return NULL;
11160 case INSTR_JMP: return NULL;
11161 case INSTR_JMP_VALID: return NULL;
11162 case INSTR_JMP_INVALID: return NULL;
11163 case INSTR_JMP_HIT: return NULL;
11164 case INSTR_JMP_MISS: return NULL;
11165 case INSTR_JMP_ACTION_HIT: return NULL;
11166 case INSTR_JMP_ACTION_MISS: return NULL;
11167 case INSTR_JMP_EQ: return NULL;
11168 case INSTR_JMP_EQ_MH: return NULL;
11169 case INSTR_JMP_EQ_HM: return NULL;
11170 case INSTR_JMP_EQ_HH: return NULL;
11171 case INSTR_JMP_EQ_I: return NULL;
11172 case INSTR_JMP_NEQ: return NULL;
11173 case INSTR_JMP_NEQ_MH: return NULL;
11174 case INSTR_JMP_NEQ_HM: return NULL;
11175 case INSTR_JMP_NEQ_HH: return NULL;
11176 case INSTR_JMP_NEQ_I: return NULL;
11177 case INSTR_JMP_LT: return NULL;
11178 case INSTR_JMP_LT_MH: return NULL;
11179 case INSTR_JMP_LT_HM: return NULL;
11180 case INSTR_JMP_LT_HH: return NULL;
11181 case INSTR_JMP_LT_MI: return NULL;
11182 case INSTR_JMP_LT_HI: return NULL;
11183 case INSTR_JMP_GT: return NULL;
11184 case INSTR_JMP_GT_MH: return NULL;
11185 case INSTR_JMP_GT_HM: return NULL;
11186 case INSTR_JMP_GT_HH: return NULL;
11187 case INSTR_JMP_GT_MI: return NULL;
11188 case INSTR_JMP_GT_HI: return NULL;
11190 case INSTR_RETURN: return NULL;
11192 default: return NULL;
11197 action_instr_does_tx_codegen(struct action *a,
11198 uint32_t instr_pos,
11199 struct instruction *instr,
11203 "%s(p, t, &action_%s_instructions[%u]);\n"
11204 "\tthread_ip_reset(p, t);\n"
11205 "\tinstr_rx_exec(p);\n"
11207 instr_type_to_func(instr),
11213 action_instr_extern_obj_codegen(struct action *a,
11214 uint32_t instr_pos,
11218 "while (!__instr_extern_obj_exec(p, t, &action_%s_instructions[%u]));\n",
11224 action_instr_extern_func_codegen(struct action *a,
11225 uint32_t instr_pos,
11229 "while (!__instr_extern_func_exec(p, t, &action_%s_instructions[%u]));\n",
11235 action_instr_jmp_codegen(struct action *a,
11236 uint32_t instr_pos,
11237 struct instruction *instr,
11238 struct instruction_data *data,
11241 switch (instr->type) {
11248 case INSTR_JMP_VALID:
11250 "if (HEADER_VALID(t, action_%s_instructions[%u].jmp.header_id))\n"
11257 case INSTR_JMP_INVALID:
11259 "if (!HEADER_VALID(t, action_%s_instructions[%u].jmp.header_id))\n"
11266 case INSTR_JMP_HIT:
11273 case INSTR_JMP_MISS:
11280 case INSTR_JMP_ACTION_HIT:
11282 "if (t->action_id == action_%s_instructions[%u].jmp.action_id)\n"
11289 case INSTR_JMP_ACTION_MISS:
11291 "if (t->action_id != action_%s_instructions[%u].jmp.action_id)\n"
11300 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) == "
11301 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
11310 case INSTR_JMP_EQ_MH:
11312 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) == "
11313 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
11322 case INSTR_JMP_EQ_HM:
11324 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) == "
11325 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
11334 case INSTR_JMP_EQ_HH:
11336 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) == "
11337 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
11346 case INSTR_JMP_EQ_I:
11348 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) == "
11349 "action_%s_instructions[%u].jmp.b_val)\n"
11358 case INSTR_JMP_NEQ:
11360 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) != "
11361 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
11370 case INSTR_JMP_NEQ_MH:
11372 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) != "
11373 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
11382 case INSTR_JMP_NEQ_HM:
11384 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) != "
11385 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
11394 case INSTR_JMP_NEQ_HH:
11396 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) != "
11397 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
11406 case INSTR_JMP_NEQ_I:
11408 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) != "
11409 "action_%s_instructions[%u].jmp.b_val)\n"
11420 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) < "
11421 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
11430 case INSTR_JMP_LT_MH:
11432 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) < "
11433 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
11442 case INSTR_JMP_LT_HM:
11444 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) < "
11445 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
11454 case INSTR_JMP_LT_HH:
11456 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) < "
11457 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
11466 case INSTR_JMP_LT_MI:
11468 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) < "
11469 "action_%s_instructions[%u].jmp.b_val)\n"
11478 case INSTR_JMP_LT_HI:
11480 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) < "
11481 "action_%s_instructions[%u].jmp.b_val)\n"
11492 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) > "
11493 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
11502 case INSTR_JMP_GT_MH:
11504 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) > "
11505 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
11514 case INSTR_JMP_GT_HM:
11516 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) > "
11517 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
11526 case INSTR_JMP_GT_HH:
11528 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) > "
11529 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
11538 case INSTR_JMP_GT_MI:
11540 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) > "
11541 "action_%s_instructions[%u].jmp.b_val)\n"
11550 case INSTR_JMP_GT_HI:
11552 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) > "
11553 "action_%s_instructions[%u].jmp.b_val)\n"
11568 action_instr_return_codegen(FILE *f)
11575 action_instr_codegen(struct action *a, FILE *f)
11581 "action_%s_run(struct rte_swx_pipeline *p)\n"
11583 "\tstruct thread *t = &p->threads[p->thread_id];\n"
11587 for (i = 0; i < a->n_instructions; i++) {
11588 struct instruction *instr = &a->instructions[i];
11589 struct instruction_data *data = &a->instruction_data[i];
11591 /* Label, if present. */
11592 if (data->label[0])
11593 fprintf(f, "\n%s : ", data->label);
11595 fprintf(f, "\n\t");
11597 /* TX instruction type. */
11598 if (instruction_does_tx(instr)) {
11599 action_instr_does_tx_codegen(a, i, instr, f);
11603 /* Extern object/function instruction type. */
11604 if (instr->type == INSTR_EXTERN_OBJ) {
11605 action_instr_extern_obj_codegen(a, i, f);
11609 if (instr->type == INSTR_EXTERN_FUNC) {
11610 action_instr_extern_func_codegen(a, i, f);
11614 /* Jump instruction type. */
11615 if (instruction_is_jmp(instr)) {
11616 action_instr_jmp_codegen(a, i, instr, data, f);
11620 /* Return instruction type. */
11621 if (instr->type == INSTR_RETURN) {
11622 action_instr_return_codegen(f);
11626 /* Any other instruction type. */
11628 "%s(p, t, &action_%s_instructions[%u]);\n",
11629 instr_type_to_func(instr),
11634 fprintf(f, "}\n\n");
11637 struct instruction_group {
11638 TAILQ_ENTRY(instruction_group) node;
11642 uint32_t first_instr_id;
11644 uint32_t last_instr_id;
11649 TAILQ_HEAD(instruction_group_list, instruction_group);
11651 static struct instruction_group *
11652 instruction_group_list_group_find(struct instruction_group_list *igl, uint32_t instruction_id)
11654 struct instruction_group *g;
11656 TAILQ_FOREACH(g, igl, node)
11657 if ((g->first_instr_id <= instruction_id) && (instruction_id <= g->last_instr_id))
11664 instruction_group_list_free(struct instruction_group_list *igl)
11670 struct instruction_group *g;
11672 g = TAILQ_FIRST(igl);
11676 TAILQ_REMOVE(igl, g, node);
11683 static struct instruction_group_list *
11684 instruction_group_list_create(struct rte_swx_pipeline *p)
11686 struct instruction_group_list *igl = NULL;
11687 struct instruction_group *g = NULL;
11688 uint32_t n_groups = 0, i;
11690 if (!p || !p->instructions || !p->instruction_data || !p->n_instructions)
11694 igl = calloc(1, sizeof(struct instruction_group_list));
11700 /* Allocate the first group. */
11701 g = calloc(1, sizeof(struct instruction_group));
11705 /* Iteration 1: Separate the instructions into groups based on the thread yield
11706 * instructions. Do not worry about the jump instructions at this point.
11708 for (i = 0; i < p->n_instructions; i++) {
11709 struct instruction *instr = &p->instructions[i];
11711 /* Check for thread yield instructions. */
11712 if (!instruction_does_thread_yield(instr))
11715 /* If the current group contains at least one instruction, then finalize it (with
11716 * the previous instruction), add it to the list and allocate a new group (that
11717 * starts with the current instruction).
11719 if (i - g->first_instr_id) {
11720 /* Finalize the group. */
11721 g->last_instr_id = i - 1;
11723 /* Add the group to the list. Advance the number of groups. */
11724 TAILQ_INSERT_TAIL(igl, g, node);
11727 /* Allocate a new group. */
11728 g = calloc(1, sizeof(struct instruction_group));
11732 /* Initialize the new group. */
11733 g->group_id = n_groups;
11734 g->first_instr_id = i;
11737 /* Finalize the current group (with the current instruction, therefore this group
11738 * contains just the current thread yield instruction), add it to the list and
11739 * allocate a new group (that starts with the next instruction).
11742 /* Finalize the group. */
11743 g->last_instr_id = i;
11745 /* Add the group to the list. Advance the number of groups. */
11746 TAILQ_INSERT_TAIL(igl, g, node);
11749 /* Allocate a new group. */
11750 g = calloc(1, sizeof(struct instruction_group));
11754 /* Initialize the new group. */
11755 g->group_id = n_groups;
11756 g->first_instr_id = i + 1;
11759 /* Handle the last group. */
11760 if (i - g->first_instr_id) {
11761 /* Finalize the group. */
11762 g->last_instr_id = i - 1;
11764 /* Add the group to the list. Advance the number of groups. */
11765 TAILQ_INSERT_TAIL(igl, g, node);
11772 /* Iteration 2: Handle jumps. If the current group contains an instruction which represents
11773 * the destination of a jump instruction located in a different group ("far jump"), then the
11774 * current group has to be split, so that the instruction representing the far jump
11775 * destination is at the start of its group.
11778 int is_modified = 0;
11780 for (i = 0; i < p->n_instructions; i++) {
11781 struct instruction_data *data = &p->instruction_data[i];
11782 struct instruction_group *g;
11785 /* Continue when the current instruction is not a jump destination. */
11786 if (!data->n_users)
11789 g = instruction_group_list_group_find(igl, i);
11793 /* Find out all the jump instructions with this destination. */
11794 for (j = 0; j < p->n_instructions; j++) {
11795 struct instruction *jmp_instr = &p->instructions[j];
11796 struct instruction_data *jmp_data = &p->instruction_data[j];
11797 struct instruction_group *jmp_g, *new_g;
11799 /* Continue when not a jump instruction. Even when jump instruction,
11800 * continue when the jump destination is not this instruction.
11802 if (!instruction_is_jmp(jmp_instr) ||
11803 strcmp(jmp_data->jmp_label, data->label))
11806 jmp_g = instruction_group_list_group_find(igl, j);
11810 /* Continue when both the jump instruction and the jump destination
11811 * instruction are in the same group. Even when in different groups,
11812 * still continue if the jump destination instruction is already the
11813 * first instruction of its group.
11815 if ((jmp_g->group_id == g->group_id) || (g->first_instr_id == i))
11818 /* Split the group of the current jump destination instruction to
11819 * make this instruction the first instruction of a new group.
11821 new_g = calloc(1, sizeof(struct instruction_group));
11825 new_g->group_id = n_groups;
11826 new_g->first_instr_id = i;
11827 new_g->last_instr_id = g->last_instr_id;
11829 g->last_instr_id = i - 1;
11831 TAILQ_INSERT_AFTER(igl, g, new_g, node);
11835 /* The decision to split this group (to make the current instruction
11836 * the first instruction of a new group) is already taken and fully
11837 * implemented, so no need to search for more reasons to do it.
11843 /* Re-evaluate everything, as at least one group got split, so some jumps that were
11844 * previously considered local (i.e. the jump destination is in the same group as
11845 * the jump instruction) can now be "far jumps" (i.e. the jump destination is in a
11846 * different group than the jump instruction). Wost case scenario: each instruction
11847 * that is a jump destination ends up as the first instruction of its group.
11853 /* Re-assign the group IDs to be in incremental order. */
11855 TAILQ_FOREACH(g, igl, node) {
11864 instruction_group_list_free(igl);
11872 pipeline_instr_does_tx_codegen(struct rte_swx_pipeline *p __rte_unused,
11873 uint32_t instr_pos,
11874 struct instruction *instr,
11878 "%s(p, t, &pipeline_instructions[%u]);\n"
11879 "\tthread_ip_reset(p, t);\n"
11880 "\tinstr_rx_exec(p);\n"
11882 instr_type_to_func(instr),
11887 pipeline_instr_jmp_codegen(struct rte_swx_pipeline *p,
11888 struct instruction_group_list *igl,
11889 uint32_t jmp_instr_id,
11890 struct instruction *jmp_instr,
11891 struct instruction_data *jmp_data,
11894 struct instruction_group *jmp_g, *g;
11895 struct instruction_data *data;
11898 switch (jmp_instr->type) {
11902 case INSTR_JMP_VALID:
11904 "if (HEADER_VALID(t, pipeline_instructions[%u].jmp.header_id))",
11908 case INSTR_JMP_INVALID:
11910 "if (!HEADER_VALID(t, pipeline_instructions[%u].jmp.header_id))",
11914 case INSTR_JMP_HIT:
11919 case INSTR_JMP_MISS:
11924 case INSTR_JMP_ACTION_HIT:
11926 "if (t->action_id == pipeline_instructions[%u].jmp.action_id)",
11930 case INSTR_JMP_ACTION_MISS:
11932 "if (t->action_id != pipeline_instructions[%u].jmp.action_id)",
11938 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) == "
11939 "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
11944 case INSTR_JMP_EQ_MH:
11946 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) == "
11947 "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
11952 case INSTR_JMP_EQ_HM:
11954 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) == "
11955 "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
11960 case INSTR_JMP_EQ_HH:
11962 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) == "
11963 "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
11968 case INSTR_JMP_EQ_I:
11970 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) == "
11971 "pipeline_instructions[%u].jmp.b_val)",
11976 case INSTR_JMP_NEQ:
11978 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) != "
11979 "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
11984 case INSTR_JMP_NEQ_MH:
11986 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) != "
11987 "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
11992 case INSTR_JMP_NEQ_HM:
11994 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) != "
11995 "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
12000 case INSTR_JMP_NEQ_HH:
12002 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) != "
12003 "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
12008 case INSTR_JMP_NEQ_I:
12010 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) != "
12011 "pipeline_instructions[%u].jmp.b_val)",
12018 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) < "
12019 "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
12024 case INSTR_JMP_LT_MH:
12026 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) < "
12027 "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
12032 case INSTR_JMP_LT_HM:
12034 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) < "
12035 "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
12040 case INSTR_JMP_LT_HH:
12042 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) < "
12043 "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
12048 case INSTR_JMP_LT_MI:
12050 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) < "
12051 "pipeline_instructions[%u].jmp.b_val)",
12056 case INSTR_JMP_LT_HI:
12058 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) < "
12059 "pipeline_instructions[%u].jmp.b_val)",
12066 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) > "
12067 "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
12072 case INSTR_JMP_GT_MH:
12074 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) > "
12075 "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
12080 case INSTR_JMP_GT_HM:
12082 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) > "
12083 "instr_operand_hbo(t, &pipeline_instructions[%u].jmp.b))",
12088 case INSTR_JMP_GT_HH:
12090 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) > "
12091 "instr_operand_nbo(t, &pipeline_instructions[%u].jmp.b))",
12096 case INSTR_JMP_GT_MI:
12098 "if (instr_operand_hbo(t, &pipeline_instructions[%u].jmp.a) > "
12099 "pipeline_instructions[%u].jmp.b_val)",
12104 case INSTR_JMP_GT_HI:
12106 "if (instr_operand_nbo(t, &pipeline_instructions[%u].jmp.a) > "
12107 "pipeline_instructions[%u].jmp.b_val)",
12116 /* Find the instruction group of the jump instruction. */
12117 jmp_g = instruction_group_list_group_find(igl, jmp_instr_id);
12121 /* Find the instruction group of the jump destination instruction. */
12122 data = label_find(p->instruction_data, p->n_instructions, jmp_data->jmp_label);
12126 instr_id = data - p->instruction_data;
12128 g = instruction_group_list_group_find(igl, instr_id);
12132 /* Code generation for "near" jump (same instruction group) or "far" jump (different
12133 * instruction group).
12135 if (g->group_id == jmp_g->group_id)
12137 "\n\t\tgoto %s;\n",
12138 jmp_data->jmp_label);
12142 "\t\tthread_ip_set(t, &p->instructions[%u]);\n"
12151 instruction_group_list_codegen(struct instruction_group_list *igl,
12152 struct rte_swx_pipeline *p,
12155 struct instruction_group *g;
12157 int is_required = 0;
12159 /* Check if code generation is required. */
12160 TAILQ_FOREACH(g, igl, node)
12161 if (g->first_instr_id < g->last_instr_id)
12167 /* Generate the code for the pipeline instruction array. */
12169 "static const struct instruction pipeline_instructions[] = {\n");
12171 for (i = 0; i < p->n_instructions; i++) {
12172 struct instruction *instr = &p->instructions[i];
12173 instruction_export_t func = export_table[instr->type];
12178 fprintf(f, "};\n\n");
12180 /* Generate the code for the pipeline functions: one function for each instruction group
12181 * that contains more than one instruction.
12183 TAILQ_FOREACH(g, igl, node) {
12184 struct instruction *last_instr;
12187 /* Skip if group contains a single instruction. */
12188 if (g->last_instr_id == g->first_instr_id)
12191 /* Generate new pipeline function. */
12194 "pipeline_func_%u(struct rte_swx_pipeline *p)\n"
12196 "\tstruct thread *t = &p->threads[p->thread_id];\n"
12200 /* Generate the code for each pipeline instruction. */
12201 for (j = g->first_instr_id; j <= g->last_instr_id; j++) {
12202 struct instruction *instr = &p->instructions[j];
12203 struct instruction_data *data = &p->instruction_data[j];
12205 /* Label, if present. */
12206 if (data->label[0])
12207 fprintf(f, "\n%s : ", data->label);
12209 fprintf(f, "\n\t");
12211 /* TX instruction type. */
12212 if (instruction_does_tx(instr)) {
12213 pipeline_instr_does_tx_codegen(p, j, instr, f);
12217 /* Jump instruction type. */
12218 if (instruction_is_jmp(instr)) {
12219 pipeline_instr_jmp_codegen(p, igl, j, instr, data, f);
12223 /* Any other instruction type. */
12225 "%s(p, t, &pipeline_instructions[%u]);\n",
12226 instr_type_to_func(instr),
12230 /* Finalize the generated pipeline function. For some instructions such as TX,
12231 * emit-many-and-TX and unconditional jump, the next instruction has been already
12232 * decided unconditionally and the instruction pointer of the current thread set
12233 * accordingly; for all the other instructions, the instruction pointer must be
12236 last_instr = &p->instructions[g->last_instr_id];
12238 if (!instruction_does_tx(last_instr) && (last_instr->type != INSTR_JMP))
12240 "thread_ip_inc(p);\n");
12249 instruction_group_list_custom_instructions_count(struct instruction_group_list *igl)
12251 struct instruction_group *g;
12252 uint32_t n_custom_instr = 0;
12254 /* Groups with a single instruction: no function is generated for this group, the group
12255 * keeps its current instruction. Groups with more than two instructions: one function and
12256 * the associated custom instruction get generated for each such group.
12258 TAILQ_FOREACH(g, igl, node) {
12259 if (g->first_instr_id == g->last_instr_id)
12265 return n_custom_instr;
12269 pipeline_codegen(struct rte_swx_pipeline *p, struct instruction_group_list *igl)
12274 /* Create the .c file. */
12275 f = fopen("/tmp/pipeline.c", "w");
12279 /* Include the .h file. */
12280 fprintf(f, "#include \"rte_swx_pipeline_internal.h\"\n");
12282 /* Add the code for each action. */
12283 TAILQ_FOREACH(a, &p->actions, node) {
12284 fprintf(f, "/**\n * Action %s\n */\n\n", a->name);
12286 action_data_codegen(a, f);
12290 action_instr_codegen(a, f);
12295 /* Add the pipeline code. */
12296 instruction_group_list_codegen(igl, p, f);
12298 /* Close the .c file. */
12304 #ifndef RTE_SWX_PIPELINE_CMD_MAX_SIZE
12305 #define RTE_SWX_PIPELINE_CMD_MAX_SIZE 4096
12309 pipeline_libload(struct rte_swx_pipeline *p, struct instruction_group_list *igl)
12312 struct instruction_group *g;
12313 char *dir_in, *buffer = NULL;
12314 const char *dir_out;
12317 /* Get the environment variables. */
12318 dir_in = getenv("RTE_INSTALL_DIR");
12326 /* Memory allocation for the command buffer. */
12327 buffer = malloc(RTE_SWX_PIPELINE_CMD_MAX_SIZE);
12334 RTE_SWX_PIPELINE_CMD_MAX_SIZE,
12335 "gcc -c -O3 -fpic -Wno-deprecated-declarations -o %s/pipeline.o %s/pipeline.c "
12336 "-I %s/lib/pipeline "
12337 "-I %s/lib/eal/include "
12338 "-I %s/lib/eal/x86/include "
12339 "-I %s/lib/eal/include/generic "
12343 "-I %s/lib/pipeline "
12346 "-I %s/lib/eal/linux/include "
12347 ">%s/pipeline.log 2>&1 "
12349 "gcc -shared %s/pipeline.o -o %s/libpipeline.so "
12350 ">>%s/pipeline.log 2>&1",
12369 /* Build the shared object library. */
12370 status = system(buffer);
12374 /* Open library. */
12376 RTE_SWX_PIPELINE_CMD_MAX_SIZE,
12377 "%s/libpipeline.so",
12380 p->lib = dlopen(buffer, RTLD_LAZY);
12386 /* Get the action function symbols. */
12387 TAILQ_FOREACH(a, &p->actions, node) {
12388 snprintf(buffer, RTE_SWX_PIPELINE_CMD_MAX_SIZE, "action_%s_run", a->name);
12390 p->action_funcs[a->id] = dlsym(p->lib, buffer);
12391 if (!p->action_funcs[a->id]) {
12397 /* Get the pipeline function symbols. */
12398 TAILQ_FOREACH(g, igl, node) {
12399 if (g->first_instr_id == g->last_instr_id)
12402 snprintf(buffer, RTE_SWX_PIPELINE_CMD_MAX_SIZE, "pipeline_func_%u", g->group_id);
12404 g->func = dlsym(p->lib, buffer);
12412 if (status && p->lib) {
12423 pipeline_adjust_check(struct rte_swx_pipeline *p __rte_unused,
12424 struct instruction_group_list *igl)
12426 uint32_t n_custom_instr = instruction_group_list_custom_instructions_count(igl);
12428 /* Check that enough space is available within the pipeline instruction table to store all
12429 * the custom instructions.
12431 if (INSTR_CUSTOM_0 + n_custom_instr > RTE_SWX_PIPELINE_INSTRUCTION_TABLE_SIZE_MAX)
12438 pipeline_adjust(struct rte_swx_pipeline *p, struct instruction_group_list *igl)
12440 struct instruction_group *g;
12443 /* Pipeline table instructions. */
12444 for (i = 0; i < p->n_instructions; i++) {
12445 struct instruction *instr = &p->instructions[i];
12447 if (instr->type == INSTR_TABLE)
12448 instr->type = INSTR_TABLE_AF;
12450 if (instr->type == INSTR_LEARNER)
12451 instr->type = INSTR_LEARNER_AF;
12454 /* Pipeline custom instructions. */
12456 TAILQ_FOREACH(g, igl, node) {
12457 struct instruction *instr = &p->instructions[g->first_instr_id];
12460 if (g->first_instr_id == g->last_instr_id)
12463 /* Install a new custom instruction. */
12464 p->instruction_table[INSTR_CUSTOM_0 + i] = g->func;
12466 /* First instruction of the group: change its type to the new custom instruction. */
12467 instr->type = INSTR_CUSTOM_0 + i;
12469 /* All the subsequent instructions of the group: invalidate. */
12470 for (j = g->first_instr_id + 1; j <= g->last_instr_id; j++) {
12471 struct instruction_data *data = &p->instruction_data[j];
12479 /* Remove the invalidated instructions. */
12480 p->n_instructions = instr_compact(p->instructions, p->instruction_data, p->n_instructions);
12482 /* Resolve the jump destination for any "standalone" jump instructions (i.e. those jump
12483 * instructions that are the only instruction within their group, so they were left
12486 instr_jmp_resolve(p->instructions, p->instruction_data, p->n_instructions);
12490 pipeline_compile(struct rte_swx_pipeline *p)
12492 struct instruction_group_list *igl = NULL;
12495 igl = instruction_group_list_create(p);
12501 /* Code generation. */
12502 status = pipeline_codegen(p, igl);
12506 /* Build and load the shared object library. */
12507 status = pipeline_libload(p, igl);
12511 /* Adjust instructions. */
12512 status = pipeline_adjust_check(p, igl);
12516 pipeline_adjust(p, igl);
12519 instruction_group_list_free(igl);