1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2020 Intel Corporation
9 #include "rte_swx_pipeline_internal.h"
11 #define CHECK(condition, err_code) \
17 #define CHECK_NAME(name, err_code) \
20 (strnlen((name), RTE_SWX_NAME_SIZE) < RTE_SWX_NAME_SIZE), \
23 #define CHECK_INSTRUCTION(instr, err_code) \
26 (strnlen((instr), RTE_SWX_INSTRUCTION_SIZE) < \
27 RTE_SWX_INSTRUCTION_SIZE), \
33 #ifndef RTE_SWX_PIPELINE_HUGE_PAGES_DISABLE
35 #include <rte_malloc.h>
38 env_malloc(size_t size, size_t alignment, int numa_node)
40 return rte_zmalloc_socket(NULL, size, alignment, numa_node);
44 env_free(void *start, size_t size __rte_unused)
54 env_malloc(size_t size, size_t alignment __rte_unused, int numa_node)
58 if (numa_available() == -1)
61 start = numa_alloc_onnode(size, numa_node);
65 memset(start, 0, size);
70 env_free(void *start, size_t size)
72 if (numa_available() == -1)
75 numa_free(start, size);
83 static struct struct_type *
84 struct_type_find(struct rte_swx_pipeline *p, const char *name)
86 struct struct_type *elem;
88 TAILQ_FOREACH(elem, &p->struct_types, node)
89 if (strcmp(elem->name, name) == 0)
96 struct_type_field_find(struct struct_type *st, const char *name)
100 for (i = 0; i < st->n_fields; i++) {
101 struct field *f = &st->fields[i];
103 if (strcmp(f->name, name) == 0)
111 rte_swx_pipeline_struct_type_register(struct rte_swx_pipeline *p,
113 struct rte_swx_field_params *fields,
115 int last_field_has_variable_size)
117 struct struct_type *st;
121 CHECK_NAME(name, EINVAL);
122 CHECK(fields, EINVAL);
123 CHECK(n_fields, EINVAL);
125 for (i = 0; i < n_fields; i++) {
126 struct rte_swx_field_params *f = &fields[i];
127 int var_size = ((i == n_fields - 1) && last_field_has_variable_size) ? 1 : 0;
130 CHECK_NAME(f->name, EINVAL);
131 CHECK(f->n_bits, EINVAL);
132 CHECK((f->n_bits <= 64) || var_size, EINVAL);
133 CHECK((f->n_bits & 7) == 0, EINVAL);
135 for (j = 0; j < i; j++) {
136 struct rte_swx_field_params *f_prev = &fields[j];
138 CHECK(strcmp(f->name, f_prev->name), EINVAL);
142 CHECK(!struct_type_find(p, name), EEXIST);
144 /* Node allocation. */
145 st = calloc(1, sizeof(struct struct_type));
148 st->fields = calloc(n_fields, sizeof(struct field));
154 /* Node initialization. */
155 strcpy(st->name, name);
156 for (i = 0; i < n_fields; i++) {
157 struct field *dst = &st->fields[i];
158 struct rte_swx_field_params *src = &fields[i];
159 int var_size = ((i == n_fields - 1) && last_field_has_variable_size) ? 1 : 0;
161 strcpy(dst->name, src->name);
162 dst->n_bits = src->n_bits;
163 dst->offset = st->n_bits;
164 dst->var_size = var_size;
166 st->n_bits += src->n_bits;
167 st->n_bits_min += var_size ? 0 : src->n_bits;
169 st->n_fields = n_fields;
170 st->var_size = last_field_has_variable_size;
172 /* Node add to tailq. */
173 TAILQ_INSERT_TAIL(&p->struct_types, st, node);
179 struct_build(struct rte_swx_pipeline *p)
183 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
184 struct thread *t = &p->threads[i];
186 t->structs = calloc(p->n_structs, sizeof(uint8_t *));
187 CHECK(t->structs, ENOMEM);
194 struct_build_free(struct rte_swx_pipeline *p)
198 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
199 struct thread *t = &p->threads[i];
207 struct_free(struct rte_swx_pipeline *p)
209 struct_build_free(p);
213 struct struct_type *elem;
215 elem = TAILQ_FIRST(&p->struct_types);
219 TAILQ_REMOVE(&p->struct_types, elem, node);
228 static struct port_in_type *
229 port_in_type_find(struct rte_swx_pipeline *p, const char *name)
231 struct port_in_type *elem;
236 TAILQ_FOREACH(elem, &p->port_in_types, node)
237 if (strcmp(elem->name, name) == 0)
244 rte_swx_pipeline_port_in_type_register(struct rte_swx_pipeline *p,
246 struct rte_swx_port_in_ops *ops)
248 struct port_in_type *elem;
251 CHECK_NAME(name, EINVAL);
253 CHECK(ops->create, EINVAL);
254 CHECK(ops->free, EINVAL);
255 CHECK(ops->pkt_rx, EINVAL);
256 CHECK(ops->stats_read, EINVAL);
258 CHECK(!port_in_type_find(p, name), EEXIST);
260 /* Node allocation. */
261 elem = calloc(1, sizeof(struct port_in_type));
264 /* Node initialization. */
265 strcpy(elem->name, name);
266 memcpy(&elem->ops, ops, sizeof(*ops));
268 /* Node add to tailq. */
269 TAILQ_INSERT_TAIL(&p->port_in_types, elem, node);
274 static struct port_in *
275 port_in_find(struct rte_swx_pipeline *p, uint32_t port_id)
277 struct port_in *port;
279 TAILQ_FOREACH(port, &p->ports_in, node)
280 if (port->id == port_id)
287 rte_swx_pipeline_port_in_config(struct rte_swx_pipeline *p,
289 const char *port_type_name,
292 struct port_in_type *type = NULL;
293 struct port_in *port = NULL;
298 CHECK(!port_in_find(p, port_id), EINVAL);
300 CHECK_NAME(port_type_name, EINVAL);
301 type = port_in_type_find(p, port_type_name);
304 obj = type->ops.create(args);
307 /* Node allocation. */
308 port = calloc(1, sizeof(struct port_in));
311 /* Node initialization. */
316 /* Node add to tailq. */
317 TAILQ_INSERT_TAIL(&p->ports_in, port, node);
318 if (p->n_ports_in < port_id + 1)
319 p->n_ports_in = port_id + 1;
325 port_in_build(struct rte_swx_pipeline *p)
327 struct port_in *port;
330 CHECK(p->n_ports_in, EINVAL);
331 CHECK(rte_is_power_of_2(p->n_ports_in), EINVAL);
333 for (i = 0; i < p->n_ports_in; i++)
334 CHECK(port_in_find(p, i), EINVAL);
336 p->in = calloc(p->n_ports_in, sizeof(struct port_in_runtime));
337 CHECK(p->in, ENOMEM);
339 TAILQ_FOREACH(port, &p->ports_in, node) {
340 struct port_in_runtime *in = &p->in[port->id];
342 in->pkt_rx = port->type->ops.pkt_rx;
350 port_in_build_free(struct rte_swx_pipeline *p)
357 port_in_free(struct rte_swx_pipeline *p)
359 port_in_build_free(p);
363 struct port_in *port;
365 port = TAILQ_FIRST(&p->ports_in);
369 TAILQ_REMOVE(&p->ports_in, port, node);
370 port->type->ops.free(port->obj);
374 /* Input port types. */
376 struct port_in_type *elem;
378 elem = TAILQ_FIRST(&p->port_in_types);
382 TAILQ_REMOVE(&p->port_in_types, elem, node);
390 static struct port_out_type *
391 port_out_type_find(struct rte_swx_pipeline *p, const char *name)
393 struct port_out_type *elem;
398 TAILQ_FOREACH(elem, &p->port_out_types, node)
399 if (!strcmp(elem->name, name))
406 rte_swx_pipeline_port_out_type_register(struct rte_swx_pipeline *p,
408 struct rte_swx_port_out_ops *ops)
410 struct port_out_type *elem;
413 CHECK_NAME(name, EINVAL);
415 CHECK(ops->create, EINVAL);
416 CHECK(ops->free, EINVAL);
417 CHECK(ops->pkt_tx, EINVAL);
418 CHECK(ops->stats_read, EINVAL);
420 CHECK(!port_out_type_find(p, name), EEXIST);
422 /* Node allocation. */
423 elem = calloc(1, sizeof(struct port_out_type));
426 /* Node initialization. */
427 strcpy(elem->name, name);
428 memcpy(&elem->ops, ops, sizeof(*ops));
430 /* Node add to tailq. */
431 TAILQ_INSERT_TAIL(&p->port_out_types, elem, node);
436 static struct port_out *
437 port_out_find(struct rte_swx_pipeline *p, uint32_t port_id)
439 struct port_out *port;
441 TAILQ_FOREACH(port, &p->ports_out, node)
442 if (port->id == port_id)
449 rte_swx_pipeline_port_out_config(struct rte_swx_pipeline *p,
451 const char *port_type_name,
454 struct port_out_type *type = NULL;
455 struct port_out *port = NULL;
460 CHECK(!port_out_find(p, port_id), EINVAL);
462 CHECK_NAME(port_type_name, EINVAL);
463 type = port_out_type_find(p, port_type_name);
466 obj = type->ops.create(args);
469 /* Node allocation. */
470 port = calloc(1, sizeof(struct port_out));
473 /* Node initialization. */
478 /* Node add to tailq. */
479 TAILQ_INSERT_TAIL(&p->ports_out, port, node);
480 if (p->n_ports_out < port_id + 1)
481 p->n_ports_out = port_id + 1;
487 port_out_build(struct rte_swx_pipeline *p)
489 struct port_out *port;
492 CHECK(p->n_ports_out, EINVAL);
494 for (i = 0; i < p->n_ports_out; i++)
495 CHECK(port_out_find(p, i), EINVAL);
497 p->out = calloc(p->n_ports_out, sizeof(struct port_out_runtime));
498 CHECK(p->out, ENOMEM);
500 TAILQ_FOREACH(port, &p->ports_out, node) {
501 struct port_out_runtime *out = &p->out[port->id];
503 out->pkt_tx = port->type->ops.pkt_tx;
504 out->flush = port->type->ops.flush;
505 out->obj = port->obj;
512 port_out_build_free(struct rte_swx_pipeline *p)
519 port_out_free(struct rte_swx_pipeline *p)
521 port_out_build_free(p);
525 struct port_out *port;
527 port = TAILQ_FIRST(&p->ports_out);
531 TAILQ_REMOVE(&p->ports_out, port, node);
532 port->type->ops.free(port->obj);
536 /* Output port types. */
538 struct port_out_type *elem;
540 elem = TAILQ_FIRST(&p->port_out_types);
544 TAILQ_REMOVE(&p->port_out_types, elem, node);
552 static struct extern_type *
553 extern_type_find(struct rte_swx_pipeline *p, const char *name)
555 struct extern_type *elem;
557 TAILQ_FOREACH(elem, &p->extern_types, node)
558 if (strcmp(elem->name, name) == 0)
564 static struct extern_type_member_func *
565 extern_type_member_func_find(struct extern_type *type, const char *name)
567 struct extern_type_member_func *elem;
569 TAILQ_FOREACH(elem, &type->funcs, node)
570 if (strcmp(elem->name, name) == 0)
576 static struct extern_obj *
577 extern_obj_find(struct rte_swx_pipeline *p, const char *name)
579 struct extern_obj *elem;
581 TAILQ_FOREACH(elem, &p->extern_objs, node)
582 if (strcmp(elem->name, name) == 0)
588 static struct extern_type_member_func *
589 extern_obj_member_func_parse(struct rte_swx_pipeline *p,
591 struct extern_obj **obj)
593 struct extern_obj *object;
594 struct extern_type_member_func *func;
595 char *object_name, *func_name;
597 if (name[0] != 'e' || name[1] != '.')
600 object_name = strdup(&name[2]);
604 func_name = strchr(object_name, '.');
613 object = extern_obj_find(p, object_name);
619 func = extern_type_member_func_find(object->type, func_name);
632 static struct field *
633 extern_obj_mailbox_field_parse(struct rte_swx_pipeline *p,
635 struct extern_obj **object)
637 struct extern_obj *obj;
639 char *obj_name, *field_name;
641 if ((name[0] != 'e') || (name[1] != '.'))
644 obj_name = strdup(&name[2]);
648 field_name = strchr(obj_name, '.');
657 obj = extern_obj_find(p, obj_name);
663 f = struct_type_field_find(obj->type->mailbox_struct_type, field_name);
677 rte_swx_pipeline_extern_type_register(struct rte_swx_pipeline *p,
679 const char *mailbox_struct_type_name,
680 rte_swx_extern_type_constructor_t constructor,
681 rte_swx_extern_type_destructor_t destructor)
683 struct extern_type *elem;
684 struct struct_type *mailbox_struct_type;
688 CHECK_NAME(name, EINVAL);
689 CHECK(!extern_type_find(p, name), EEXIST);
691 CHECK_NAME(mailbox_struct_type_name, EINVAL);
692 mailbox_struct_type = struct_type_find(p, mailbox_struct_type_name);
693 CHECK(mailbox_struct_type, EINVAL);
694 CHECK(!mailbox_struct_type->var_size, EINVAL);
696 CHECK(constructor, EINVAL);
697 CHECK(destructor, EINVAL);
699 /* Node allocation. */
700 elem = calloc(1, sizeof(struct extern_type));
703 /* Node initialization. */
704 strcpy(elem->name, name);
705 elem->mailbox_struct_type = mailbox_struct_type;
706 elem->constructor = constructor;
707 elem->destructor = destructor;
708 TAILQ_INIT(&elem->funcs);
710 /* Node add to tailq. */
711 TAILQ_INSERT_TAIL(&p->extern_types, elem, node);
717 rte_swx_pipeline_extern_type_member_func_register(struct rte_swx_pipeline *p,
718 const char *extern_type_name,
720 rte_swx_extern_type_member_func_t member_func)
722 struct extern_type *type;
723 struct extern_type_member_func *type_member;
727 CHECK_NAME(extern_type_name, EINVAL);
728 type = extern_type_find(p, extern_type_name);
730 CHECK(type->n_funcs < RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX, ENOSPC);
732 CHECK_NAME(name, EINVAL);
733 CHECK(!extern_type_member_func_find(type, name), EEXIST);
735 CHECK(member_func, EINVAL);
737 /* Node allocation. */
738 type_member = calloc(1, sizeof(struct extern_type_member_func));
739 CHECK(type_member, ENOMEM);
741 /* Node initialization. */
742 strcpy(type_member->name, name);
743 type_member->func = member_func;
744 type_member->id = type->n_funcs;
746 /* Node add to tailq. */
747 TAILQ_INSERT_TAIL(&type->funcs, type_member, node);
754 rte_swx_pipeline_extern_object_config(struct rte_swx_pipeline *p,
755 const char *extern_type_name,
759 struct extern_type *type;
760 struct extern_obj *obj;
765 CHECK_NAME(extern_type_name, EINVAL);
766 type = extern_type_find(p, extern_type_name);
769 CHECK_NAME(name, EINVAL);
770 CHECK(!extern_obj_find(p, name), EEXIST);
772 /* Node allocation. */
773 obj = calloc(1, sizeof(struct extern_obj));
776 /* Object construction. */
777 obj_handle = type->constructor(args);
783 /* Node initialization. */
784 strcpy(obj->name, name);
786 obj->obj = obj_handle;
787 obj->struct_id = p->n_structs;
788 obj->id = p->n_extern_objs;
790 /* Node add to tailq. */
791 TAILQ_INSERT_TAIL(&p->extern_objs, obj, node);
799 extern_obj_build(struct rte_swx_pipeline *p)
803 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
804 struct thread *t = &p->threads[i];
805 struct extern_obj *obj;
807 t->extern_objs = calloc(p->n_extern_objs,
808 sizeof(struct extern_obj_runtime));
809 CHECK(t->extern_objs, ENOMEM);
811 TAILQ_FOREACH(obj, &p->extern_objs, node) {
812 struct extern_obj_runtime *r =
813 &t->extern_objs[obj->id];
814 struct extern_type_member_func *func;
815 uint32_t mailbox_size =
816 obj->type->mailbox_struct_type->n_bits / 8;
820 r->mailbox = calloc(1, mailbox_size);
821 CHECK(r->mailbox, ENOMEM);
823 TAILQ_FOREACH(func, &obj->type->funcs, node)
824 r->funcs[func->id] = func->func;
826 t->structs[obj->struct_id] = r->mailbox;
834 extern_obj_build_free(struct rte_swx_pipeline *p)
838 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
839 struct thread *t = &p->threads[i];
845 for (j = 0; j < p->n_extern_objs; j++) {
846 struct extern_obj_runtime *r = &t->extern_objs[j];
851 free(t->extern_objs);
852 t->extern_objs = NULL;
857 extern_obj_free(struct rte_swx_pipeline *p)
859 extern_obj_build_free(p);
861 /* Extern objects. */
863 struct extern_obj *elem;
865 elem = TAILQ_FIRST(&p->extern_objs);
869 TAILQ_REMOVE(&p->extern_objs, elem, node);
871 elem->type->destructor(elem->obj);
877 struct extern_type *elem;
879 elem = TAILQ_FIRST(&p->extern_types);
883 TAILQ_REMOVE(&p->extern_types, elem, node);
886 struct extern_type_member_func *func;
888 func = TAILQ_FIRST(&elem->funcs);
892 TAILQ_REMOVE(&elem->funcs, func, node);
903 static struct extern_func *
904 extern_func_find(struct rte_swx_pipeline *p, const char *name)
906 struct extern_func *elem;
908 TAILQ_FOREACH(elem, &p->extern_funcs, node)
909 if (strcmp(elem->name, name) == 0)
915 static struct extern_func *
916 extern_func_parse(struct rte_swx_pipeline *p,
919 if (name[0] != 'f' || name[1] != '.')
922 return extern_func_find(p, &name[2]);
925 static struct field *
926 extern_func_mailbox_field_parse(struct rte_swx_pipeline *p,
928 struct extern_func **function)
930 struct extern_func *func;
932 char *func_name, *field_name;
934 if ((name[0] != 'f') || (name[1] != '.'))
937 func_name = strdup(&name[2]);
941 field_name = strchr(func_name, '.');
950 func = extern_func_find(p, func_name);
956 f = struct_type_field_find(func->mailbox_struct_type, field_name);
970 rte_swx_pipeline_extern_func_register(struct rte_swx_pipeline *p,
972 const char *mailbox_struct_type_name,
973 rte_swx_extern_func_t func)
975 struct extern_func *f;
976 struct struct_type *mailbox_struct_type;
980 CHECK_NAME(name, EINVAL);
981 CHECK(!extern_func_find(p, name), EEXIST);
983 CHECK_NAME(mailbox_struct_type_name, EINVAL);
984 mailbox_struct_type = struct_type_find(p, mailbox_struct_type_name);
985 CHECK(mailbox_struct_type, EINVAL);
986 CHECK(!mailbox_struct_type->var_size, EINVAL);
990 /* Node allocation. */
991 f = calloc(1, sizeof(struct extern_func));
994 /* Node initialization. */
995 strcpy(f->name, name);
996 f->mailbox_struct_type = mailbox_struct_type;
998 f->struct_id = p->n_structs;
999 f->id = p->n_extern_funcs;
1001 /* Node add to tailq. */
1002 TAILQ_INSERT_TAIL(&p->extern_funcs, f, node);
1003 p->n_extern_funcs++;
1010 extern_func_build(struct rte_swx_pipeline *p)
1014 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1015 struct thread *t = &p->threads[i];
1016 struct extern_func *func;
1018 /* Memory allocation. */
1019 t->extern_funcs = calloc(p->n_extern_funcs,
1020 sizeof(struct extern_func_runtime));
1021 CHECK(t->extern_funcs, ENOMEM);
1023 /* Extern function. */
1024 TAILQ_FOREACH(func, &p->extern_funcs, node) {
1025 struct extern_func_runtime *r =
1026 &t->extern_funcs[func->id];
1027 uint32_t mailbox_size =
1028 func->mailbox_struct_type->n_bits / 8;
1030 r->func = func->func;
1032 r->mailbox = calloc(1, mailbox_size);
1033 CHECK(r->mailbox, ENOMEM);
1035 t->structs[func->struct_id] = r->mailbox;
1043 extern_func_build_free(struct rte_swx_pipeline *p)
1047 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1048 struct thread *t = &p->threads[i];
1051 if (!t->extern_funcs)
1054 for (j = 0; j < p->n_extern_funcs; j++) {
1055 struct extern_func_runtime *r = &t->extern_funcs[j];
1060 free(t->extern_funcs);
1061 t->extern_funcs = NULL;
1066 extern_func_free(struct rte_swx_pipeline *p)
1068 extern_func_build_free(p);
1071 struct extern_func *elem;
1073 elem = TAILQ_FIRST(&p->extern_funcs);
1077 TAILQ_REMOVE(&p->extern_funcs, elem, node);
1085 static struct header *
1086 header_find(struct rte_swx_pipeline *p, const char *name)
1088 struct header *elem;
1090 TAILQ_FOREACH(elem, &p->headers, node)
1091 if (strcmp(elem->name, name) == 0)
1097 static struct header *
1098 header_find_by_struct_id(struct rte_swx_pipeline *p, uint32_t struct_id)
1100 struct header *elem;
1102 TAILQ_FOREACH(elem, &p->headers, node)
1103 if (elem->struct_id == struct_id)
1109 static struct header *
1110 header_parse(struct rte_swx_pipeline *p,
1113 if (name[0] != 'h' || name[1] != '.')
1116 return header_find(p, &name[2]);
1119 static struct field *
1120 header_field_parse(struct rte_swx_pipeline *p,
1122 struct header **header)
1126 char *header_name, *field_name;
1128 if ((name[0] != 'h') || (name[1] != '.'))
1131 header_name = strdup(&name[2]);
1135 field_name = strchr(header_name, '.');
1144 h = header_find(p, header_name);
1150 f = struct_type_field_find(h->st, field_name);
1164 rte_swx_pipeline_packet_header_register(struct rte_swx_pipeline *p,
1166 const char *struct_type_name)
1168 struct struct_type *st;
1170 size_t n_headers_max;
1173 CHECK_NAME(name, EINVAL);
1174 CHECK_NAME(struct_type_name, EINVAL);
1176 CHECK(!header_find(p, name), EEXIST);
1178 st = struct_type_find(p, struct_type_name);
1181 n_headers_max = RTE_SIZEOF_FIELD(struct thread, valid_headers) * 8;
1182 CHECK(p->n_headers < n_headers_max, ENOSPC);
1184 /* Node allocation. */
1185 h = calloc(1, sizeof(struct header));
1188 /* Node initialization. */
1189 strcpy(h->name, name);
1191 h->struct_id = p->n_structs;
1192 h->id = p->n_headers;
1194 /* Node add to tailq. */
1195 TAILQ_INSERT_TAIL(&p->headers, h, node);
1203 header_build(struct rte_swx_pipeline *p)
1206 uint32_t n_bytes = 0, i;
1208 TAILQ_FOREACH(h, &p->headers, node) {
1209 n_bytes += h->st->n_bits / 8;
1212 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1213 struct thread *t = &p->threads[i];
1214 uint32_t offset = 0;
1216 t->headers = calloc(p->n_headers,
1217 sizeof(struct header_runtime));
1218 CHECK(t->headers, ENOMEM);
1220 t->headers_out = calloc(p->n_headers,
1221 sizeof(struct header_out_runtime));
1222 CHECK(t->headers_out, ENOMEM);
1224 t->header_storage = calloc(1, n_bytes);
1225 CHECK(t->header_storage, ENOMEM);
1227 t->header_out_storage = calloc(1, n_bytes);
1228 CHECK(t->header_out_storage, ENOMEM);
1230 TAILQ_FOREACH(h, &p->headers, node) {
1231 uint8_t *header_storage;
1232 uint32_t n_bytes = h->st->n_bits / 8;
1234 header_storage = &t->header_storage[offset];
1237 t->headers[h->id].ptr0 = header_storage;
1238 t->headers[h->id].n_bytes = n_bytes;
1240 t->structs[h->struct_id] = header_storage;
1248 header_build_free(struct rte_swx_pipeline *p)
1252 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1253 struct thread *t = &p->threads[i];
1255 free(t->headers_out);
1256 t->headers_out = NULL;
1261 free(t->header_out_storage);
1262 t->header_out_storage = NULL;
1264 free(t->header_storage);
1265 t->header_storage = NULL;
1270 header_free(struct rte_swx_pipeline *p)
1272 header_build_free(p);
1275 struct header *elem;
1277 elem = TAILQ_FIRST(&p->headers);
1281 TAILQ_REMOVE(&p->headers, elem, node);
1289 static struct field *
1290 metadata_field_parse(struct rte_swx_pipeline *p, const char *name)
1292 if (!p->metadata_st)
1295 if (name[0] != 'm' || name[1] != '.')
1298 return struct_type_field_find(p->metadata_st, &name[2]);
1302 rte_swx_pipeline_packet_metadata_register(struct rte_swx_pipeline *p,
1303 const char *struct_type_name)
1305 struct struct_type *st = NULL;
1309 CHECK_NAME(struct_type_name, EINVAL);
1310 st = struct_type_find(p, struct_type_name);
1312 CHECK(!st->var_size, EINVAL);
1313 CHECK(!p->metadata_st, EINVAL);
1315 p->metadata_st = st;
1316 p->metadata_struct_id = p->n_structs;
1324 metadata_build(struct rte_swx_pipeline *p)
1326 uint32_t n_bytes = p->metadata_st->n_bits / 8;
1329 /* Thread-level initialization. */
1330 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1331 struct thread *t = &p->threads[i];
1334 metadata = calloc(1, n_bytes);
1335 CHECK(metadata, ENOMEM);
1337 t->metadata = metadata;
1338 t->structs[p->metadata_struct_id] = metadata;
1345 metadata_build_free(struct rte_swx_pipeline *p)
1349 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1350 struct thread *t = &p->threads[i];
1358 metadata_free(struct rte_swx_pipeline *p)
1360 metadata_build_free(p);
1367 instruction_is_tx(enum instruction_type type)
1380 instruction_does_tx(struct instruction *instr)
1382 switch (instr->type) {
1385 case INSTR_HDR_EMIT_TX:
1386 case INSTR_HDR_EMIT2_TX:
1387 case INSTR_HDR_EMIT3_TX:
1388 case INSTR_HDR_EMIT4_TX:
1389 case INSTR_HDR_EMIT5_TX:
1390 case INSTR_HDR_EMIT6_TX:
1391 case INSTR_HDR_EMIT7_TX:
1392 case INSTR_HDR_EMIT8_TX:
1400 instruction_is_jmp(struct instruction *instr)
1402 switch (instr->type) {
1404 case INSTR_JMP_VALID:
1405 case INSTR_JMP_INVALID:
1407 case INSTR_JMP_MISS:
1408 case INSTR_JMP_ACTION_HIT:
1409 case INSTR_JMP_ACTION_MISS:
1411 case INSTR_JMP_EQ_MH:
1412 case INSTR_JMP_EQ_HM:
1413 case INSTR_JMP_EQ_HH:
1414 case INSTR_JMP_EQ_I:
1416 case INSTR_JMP_NEQ_MH:
1417 case INSTR_JMP_NEQ_HM:
1418 case INSTR_JMP_NEQ_HH:
1419 case INSTR_JMP_NEQ_I:
1421 case INSTR_JMP_LT_MH:
1422 case INSTR_JMP_LT_HM:
1423 case INSTR_JMP_LT_HH:
1424 case INSTR_JMP_LT_MI:
1425 case INSTR_JMP_LT_HI:
1427 case INSTR_JMP_GT_MH:
1428 case INSTR_JMP_GT_HM:
1429 case INSTR_JMP_GT_HH:
1430 case INSTR_JMP_GT_MI:
1431 case INSTR_JMP_GT_HI:
1439 static struct field *
1440 action_field_parse(struct action *action, const char *name);
1442 static struct field *
1443 struct_field_parse(struct rte_swx_pipeline *p,
1444 struct action *action,
1446 uint32_t *struct_id)
1453 struct header *header;
1455 f = header_field_parse(p, name, &header);
1459 *struct_id = header->struct_id;
1465 f = metadata_field_parse(p, name);
1469 *struct_id = p->metadata_struct_id;
1478 f = action_field_parse(action, name);
1488 struct extern_obj *obj;
1490 f = extern_obj_mailbox_field_parse(p, name, &obj);
1494 *struct_id = obj->struct_id;
1500 struct extern_func *func;
1502 f = extern_func_mailbox_field_parse(p, name, &func);
1506 *struct_id = func->struct_id;
1519 instr_rx_translate(struct rte_swx_pipeline *p,
1520 struct action *action,
1523 struct instruction *instr,
1524 struct instruction_data *data __rte_unused)
1528 CHECK(!action, EINVAL);
1529 CHECK(n_tokens == 2, EINVAL);
1531 f = metadata_field_parse(p, tokens[1]);
1534 instr->type = INSTR_RX;
1535 instr->io.io.offset = f->offset / 8;
1536 instr->io.io.n_bits = f->n_bits;
1544 instr_tx_translate(struct rte_swx_pipeline *p,
1545 struct action *action __rte_unused,
1548 struct instruction *instr,
1549 struct instruction_data *data __rte_unused)
1551 char *port = tokens[1];
1555 CHECK(n_tokens == 2, EINVAL);
1557 f = metadata_field_parse(p, port);
1559 instr->type = INSTR_TX;
1560 instr->io.io.offset = f->offset / 8;
1561 instr->io.io.n_bits = f->n_bits;
1566 port_val = strtoul(port, &port, 0);
1567 CHECK(!port[0], EINVAL);
1569 instr->type = INSTR_TX_I;
1570 instr->io.io.val = port_val;
1575 instr_drop_translate(struct rte_swx_pipeline *p,
1576 struct action *action __rte_unused,
1577 char **tokens __rte_unused,
1579 struct instruction *instr,
1580 struct instruction_data *data __rte_unused)
1582 CHECK(n_tokens == 1, EINVAL);
1585 instr->type = INSTR_TX_I;
1586 instr->io.io.val = p->n_ports_out - 1;
1591 instr_tx_exec(struct rte_swx_pipeline *p)
1593 struct thread *t = &p->threads[p->thread_id];
1594 struct instruction *ip = t->ip;
1596 __instr_tx_exec(p, t, ip);
1599 thread_ip_reset(p, t);
1604 instr_tx_i_exec(struct rte_swx_pipeline *p)
1606 struct thread *t = &p->threads[p->thread_id];
1607 struct instruction *ip = t->ip;
1609 __instr_tx_i_exec(p, t, ip);
1612 thread_ip_reset(p, t);
1620 instr_hdr_extract_translate(struct rte_swx_pipeline *p,
1621 struct action *action,
1624 struct instruction *instr,
1625 struct instruction_data *data __rte_unused)
1629 CHECK(!action, EINVAL);
1630 CHECK((n_tokens == 2) || (n_tokens == 3), EINVAL);
1632 h = header_parse(p, tokens[1]);
1635 if (n_tokens == 2) {
1636 CHECK(!h->st->var_size, EINVAL);
1638 instr->type = INSTR_HDR_EXTRACT;
1639 instr->io.hdr.header_id[0] = h->id;
1640 instr->io.hdr.struct_id[0] = h->struct_id;
1641 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
1645 CHECK(h->st->var_size, EINVAL);
1647 mf = metadata_field_parse(p, tokens[2]);
1649 CHECK(!mf->var_size, EINVAL);
1651 instr->type = INSTR_HDR_EXTRACT_M;
1652 instr->io.io.offset = mf->offset / 8;
1653 instr->io.io.n_bits = mf->n_bits;
1654 instr->io.hdr.header_id[0] = h->id;
1655 instr->io.hdr.struct_id[0] = h->struct_id;
1656 instr->io.hdr.n_bytes[0] = h->st->n_bits_min / 8;
1663 instr_hdr_lookahead_translate(struct rte_swx_pipeline *p,
1664 struct action *action,
1667 struct instruction *instr,
1668 struct instruction_data *data __rte_unused)
1672 CHECK(!action, EINVAL);
1673 CHECK(n_tokens == 2, EINVAL);
1675 h = header_parse(p, tokens[1]);
1677 CHECK(!h->st->var_size, EINVAL);
1679 instr->type = INSTR_HDR_LOOKAHEAD;
1680 instr->io.hdr.header_id[0] = h->id;
1681 instr->io.hdr.struct_id[0] = h->struct_id;
1682 instr->io.hdr.n_bytes[0] = 0; /* Unused. */
1688 instr_hdr_extract_exec(struct rte_swx_pipeline *p)
1690 struct thread *t = &p->threads[p->thread_id];
1691 struct instruction *ip = t->ip;
1693 __instr_hdr_extract_exec(p, t, ip);
1700 instr_hdr_extract2_exec(struct rte_swx_pipeline *p)
1702 struct thread *t = &p->threads[p->thread_id];
1703 struct instruction *ip = t->ip;
1705 __instr_hdr_extract2_exec(p, t, ip);
1712 instr_hdr_extract3_exec(struct rte_swx_pipeline *p)
1714 struct thread *t = &p->threads[p->thread_id];
1715 struct instruction *ip = t->ip;
1717 __instr_hdr_extract3_exec(p, t, ip);
1724 instr_hdr_extract4_exec(struct rte_swx_pipeline *p)
1726 struct thread *t = &p->threads[p->thread_id];
1727 struct instruction *ip = t->ip;
1729 __instr_hdr_extract4_exec(p, t, ip);
1736 instr_hdr_extract5_exec(struct rte_swx_pipeline *p)
1738 struct thread *t = &p->threads[p->thread_id];
1739 struct instruction *ip = t->ip;
1741 __instr_hdr_extract5_exec(p, t, ip);
1748 instr_hdr_extract6_exec(struct rte_swx_pipeline *p)
1750 struct thread *t = &p->threads[p->thread_id];
1751 struct instruction *ip = t->ip;
1753 __instr_hdr_extract6_exec(p, t, ip);
1760 instr_hdr_extract7_exec(struct rte_swx_pipeline *p)
1762 struct thread *t = &p->threads[p->thread_id];
1763 struct instruction *ip = t->ip;
1765 __instr_hdr_extract7_exec(p, t, ip);
1772 instr_hdr_extract8_exec(struct rte_swx_pipeline *p)
1774 struct thread *t = &p->threads[p->thread_id];
1775 struct instruction *ip = t->ip;
1777 __instr_hdr_extract8_exec(p, t, ip);
1784 instr_hdr_extract_m_exec(struct rte_swx_pipeline *p)
1786 struct thread *t = &p->threads[p->thread_id];
1787 struct instruction *ip = t->ip;
1789 __instr_hdr_extract_m_exec(p, t, ip);
1796 instr_hdr_lookahead_exec(struct rte_swx_pipeline *p)
1798 struct thread *t = &p->threads[p->thread_id];
1799 struct instruction *ip = t->ip;
1801 __instr_hdr_lookahead_exec(p, t, ip);
1811 instr_hdr_emit_translate(struct rte_swx_pipeline *p,
1812 struct action *action __rte_unused,
1815 struct instruction *instr,
1816 struct instruction_data *data __rte_unused)
1820 CHECK(n_tokens == 2, EINVAL);
1822 h = header_parse(p, tokens[1]);
1825 instr->type = INSTR_HDR_EMIT;
1826 instr->io.hdr.header_id[0] = h->id;
1827 instr->io.hdr.struct_id[0] = h->struct_id;
1828 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
1833 instr_hdr_emit_exec(struct rte_swx_pipeline *p)
1835 struct thread *t = &p->threads[p->thread_id];
1836 struct instruction *ip = t->ip;
1838 __instr_hdr_emit_exec(p, t, ip);
1845 instr_hdr_emit_tx_exec(struct rte_swx_pipeline *p)
1847 struct thread *t = &p->threads[p->thread_id];
1848 struct instruction *ip = t->ip;
1850 __instr_hdr_emit_tx_exec(p, t, ip);
1853 thread_ip_reset(p, t);
1858 instr_hdr_emit2_tx_exec(struct rte_swx_pipeline *p)
1860 struct thread *t = &p->threads[p->thread_id];
1861 struct instruction *ip = t->ip;
1863 __instr_hdr_emit2_tx_exec(p, t, ip);
1866 thread_ip_reset(p, t);
1871 instr_hdr_emit3_tx_exec(struct rte_swx_pipeline *p)
1873 struct thread *t = &p->threads[p->thread_id];
1874 struct instruction *ip = t->ip;
1876 __instr_hdr_emit3_tx_exec(p, t, ip);
1879 thread_ip_reset(p, t);
1884 instr_hdr_emit4_tx_exec(struct rte_swx_pipeline *p)
1886 struct thread *t = &p->threads[p->thread_id];
1887 struct instruction *ip = t->ip;
1889 __instr_hdr_emit4_tx_exec(p, t, ip);
1892 thread_ip_reset(p, t);
1897 instr_hdr_emit5_tx_exec(struct rte_swx_pipeline *p)
1899 struct thread *t = &p->threads[p->thread_id];
1900 struct instruction *ip = t->ip;
1902 __instr_hdr_emit5_tx_exec(p, t, ip);
1905 thread_ip_reset(p, t);
1910 instr_hdr_emit6_tx_exec(struct rte_swx_pipeline *p)
1912 struct thread *t = &p->threads[p->thread_id];
1913 struct instruction *ip = t->ip;
1915 __instr_hdr_emit6_tx_exec(p, t, ip);
1918 thread_ip_reset(p, t);
1923 instr_hdr_emit7_tx_exec(struct rte_swx_pipeline *p)
1925 struct thread *t = &p->threads[p->thread_id];
1926 struct instruction *ip = t->ip;
1928 __instr_hdr_emit7_tx_exec(p, t, ip);
1931 thread_ip_reset(p, t);
1936 instr_hdr_emit8_tx_exec(struct rte_swx_pipeline *p)
1938 struct thread *t = &p->threads[p->thread_id];
1939 struct instruction *ip = t->ip;
1941 __instr_hdr_emit8_tx_exec(p, t, ip);
1944 thread_ip_reset(p, t);
1952 instr_hdr_validate_translate(struct rte_swx_pipeline *p,
1953 struct action *action __rte_unused,
1956 struct instruction *instr,
1957 struct instruction_data *data __rte_unused)
1961 CHECK(n_tokens == 2, EINVAL);
1963 h = header_parse(p, tokens[1]);
1966 instr->type = INSTR_HDR_VALIDATE;
1967 instr->valid.header_id = h->id;
1972 instr_hdr_validate_exec(struct rte_swx_pipeline *p)
1974 struct thread *t = &p->threads[p->thread_id];
1975 struct instruction *ip = t->ip;
1977 __instr_hdr_validate_exec(p, t, ip);
1987 instr_hdr_invalidate_translate(struct rte_swx_pipeline *p,
1988 struct action *action __rte_unused,
1991 struct instruction *instr,
1992 struct instruction_data *data __rte_unused)
1996 CHECK(n_tokens == 2, EINVAL);
1998 h = header_parse(p, tokens[1]);
2001 instr->type = INSTR_HDR_INVALIDATE;
2002 instr->valid.header_id = h->id;
2007 instr_hdr_invalidate_exec(struct rte_swx_pipeline *p)
2009 struct thread *t = &p->threads[p->thread_id];
2010 struct instruction *ip = t->ip;
2012 __instr_hdr_invalidate_exec(p, t, ip);
2021 static struct table *
2022 table_find(struct rte_swx_pipeline *p, const char *name);
2024 static struct selector *
2025 selector_find(struct rte_swx_pipeline *p, const char *name);
2027 static struct learner *
2028 learner_find(struct rte_swx_pipeline *p, const char *name);
2031 instr_table_translate(struct rte_swx_pipeline *p,
2032 struct action *action,
2035 struct instruction *instr,
2036 struct instruction_data *data __rte_unused)
2042 CHECK(!action, EINVAL);
2043 CHECK(n_tokens == 2, EINVAL);
2045 t = table_find(p, tokens[1]);
2047 instr->type = INSTR_TABLE;
2048 instr->table.table_id = t->id;
2052 s = selector_find(p, tokens[1]);
2054 instr->type = INSTR_SELECTOR;
2055 instr->table.table_id = s->id;
2059 l = learner_find(p, tokens[1]);
2061 instr->type = INSTR_LEARNER;
2062 instr->table.table_id = l->id;
2070 instr_table_exec(struct rte_swx_pipeline *p)
2072 struct thread *t = &p->threads[p->thread_id];
2073 struct instruction *ip = t->ip;
2074 uint32_t table_id = ip->table.table_id;
2075 struct rte_swx_table_state *ts = &t->table_state[table_id];
2076 struct table_runtime *table = &t->tables[table_id];
2077 struct table_statistics *stats = &p->table_stats[table_id];
2078 uint64_t action_id, n_pkts_hit, n_pkts_action;
2079 uint8_t *action_data;
2083 done = table->func(ts->obj,
2091 TRACE("[Thread %2u] table %u (not finalized)\n",
2099 action_id = hit ? action_id : ts->default_action_id;
2100 action_data = hit ? action_data : ts->default_action_data;
2101 n_pkts_hit = stats->n_pkts_hit[hit];
2102 n_pkts_action = stats->n_pkts_action[action_id];
2104 TRACE("[Thread %2u] table %u (%s, action %u)\n",
2107 hit ? "hit" : "miss",
2108 (uint32_t)action_id);
2110 t->action_id = action_id;
2111 t->structs[0] = action_data;
2113 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2114 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2117 thread_ip_action_call(p, t, action_id);
2121 instr_table_af_exec(struct rte_swx_pipeline *p)
2123 struct thread *t = &p->threads[p->thread_id];
2124 struct instruction *ip = t->ip;
2125 uint32_t table_id = ip->table.table_id;
2126 struct rte_swx_table_state *ts = &t->table_state[table_id];
2127 struct table_runtime *table = &t->tables[table_id];
2128 struct table_statistics *stats = &p->table_stats[table_id];
2129 uint64_t action_id, n_pkts_hit, n_pkts_action;
2130 uint8_t *action_data;
2131 action_func_t action_func;
2135 done = table->func(ts->obj,
2143 TRACE("[Thread %2u] table %u (not finalized)\n",
2151 action_id = hit ? action_id : ts->default_action_id;
2152 action_data = hit ? action_data : ts->default_action_data;
2153 action_func = p->action_funcs[action_id];
2154 n_pkts_hit = stats->n_pkts_hit[hit];
2155 n_pkts_action = stats->n_pkts_action[action_id];
2157 TRACE("[Thread %2u] table %u (%s, action %u)\n",
2160 hit ? "hit" : "miss",
2161 (uint32_t)action_id);
2163 t->action_id = action_id;
2164 t->structs[0] = action_data;
2166 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2167 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2177 instr_selector_exec(struct rte_swx_pipeline *p)
2179 struct thread *t = &p->threads[p->thread_id];
2180 struct instruction *ip = t->ip;
2181 uint32_t selector_id = ip->table.table_id;
2182 struct rte_swx_table_state *ts = &t->table_state[p->n_tables + selector_id];
2183 struct selector_runtime *selector = &t->selectors[selector_id];
2184 struct selector_statistics *stats = &p->selector_stats[selector_id];
2185 uint64_t n_pkts = stats->n_pkts;
2189 done = rte_swx_table_selector_select(ts->obj,
2191 selector->group_id_buffer,
2192 selector->selector_buffer,
2193 selector->member_id_buffer);
2196 TRACE("[Thread %2u] selector %u (not finalized)\n",
2205 TRACE("[Thread %2u] selector %u\n",
2209 stats->n_pkts = n_pkts + 1;
2216 instr_learner_exec(struct rte_swx_pipeline *p)
2218 struct thread *t = &p->threads[p->thread_id];
2219 struct instruction *ip = t->ip;
2220 uint32_t learner_id = ip->table.table_id;
2221 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2222 p->n_selectors + learner_id];
2223 struct learner_runtime *l = &t->learners[learner_id];
2224 struct learner_statistics *stats = &p->learner_stats[learner_id];
2225 uint64_t action_id, n_pkts_hit, n_pkts_action, time;
2226 uint8_t *action_data;
2230 time = rte_get_tsc_cycles();
2232 done = rte_swx_table_learner_lookup(ts->obj,
2241 TRACE("[Thread %2u] learner %u (not finalized)\n",
2249 action_id = hit ? action_id : ts->default_action_id;
2250 action_data = hit ? action_data : ts->default_action_data;
2251 n_pkts_hit = stats->n_pkts_hit[hit];
2252 n_pkts_action = stats->n_pkts_action[action_id];
2254 TRACE("[Thread %2u] learner %u (%s, action %u)\n",
2257 hit ? "hit" : "miss",
2258 (uint32_t)action_id);
2260 t->action_id = action_id;
2261 t->structs[0] = action_data;
2263 t->learner_id = learner_id;
2265 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2266 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2269 thread_ip_action_call(p, t, action_id);
2273 instr_learner_af_exec(struct rte_swx_pipeline *p)
2275 struct thread *t = &p->threads[p->thread_id];
2276 struct instruction *ip = t->ip;
2277 uint32_t learner_id = ip->table.table_id;
2278 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2279 p->n_selectors + learner_id];
2280 struct learner_runtime *l = &t->learners[learner_id];
2281 struct learner_statistics *stats = &p->learner_stats[learner_id];
2282 uint64_t action_id, n_pkts_hit, n_pkts_action, time;
2283 uint8_t *action_data;
2284 action_func_t action_func;
2288 time = rte_get_tsc_cycles();
2290 done = rte_swx_table_learner_lookup(ts->obj,
2299 TRACE("[Thread %2u] learner %u (not finalized)\n",
2307 action_id = hit ? action_id : ts->default_action_id;
2308 action_data = hit ? action_data : ts->default_action_data;
2309 action_func = p->action_funcs[action_id];
2310 n_pkts_hit = stats->n_pkts_hit[hit];
2311 n_pkts_action = stats->n_pkts_action[action_id];
2313 TRACE("[Thread %2u] learner %u (%s, action %u)\n",
2316 hit ? "hit" : "miss",
2317 (uint32_t)action_id);
2319 t->action_id = action_id;
2320 t->structs[0] = action_data;
2322 t->learner_id = learner_id;
2324 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2325 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2328 thread_ip_action_call(p, t, action_id);
2337 static struct action *
2338 action_find(struct rte_swx_pipeline *p, const char *name);
2341 action_has_nbo_args(struct action *a);
2344 instr_learn_translate(struct rte_swx_pipeline *p,
2345 struct action *action,
2348 struct instruction *instr,
2349 struct instruction_data *data __rte_unused)
2353 CHECK(action, EINVAL);
2354 CHECK(n_tokens == 2, EINVAL);
2356 a = action_find(p, tokens[1]);
2358 CHECK(!action_has_nbo_args(a), EINVAL);
2360 instr->type = INSTR_LEARNER_LEARN;
2361 instr->learn.action_id = a->id;
2367 instr_learn_exec(struct rte_swx_pipeline *p)
2369 struct thread *t = &p->threads[p->thread_id];
2370 struct instruction *ip = t->ip;
2372 __instr_learn_exec(p, t, ip);
2382 instr_forget_translate(struct rte_swx_pipeline *p __rte_unused,
2383 struct action *action,
2384 char **tokens __rte_unused,
2386 struct instruction *instr,
2387 struct instruction_data *data __rte_unused)
2389 CHECK(action, EINVAL);
2390 CHECK(n_tokens == 1, EINVAL);
2392 instr->type = INSTR_LEARNER_FORGET;
2398 instr_forget_exec(struct rte_swx_pipeline *p)
2400 struct thread *t = &p->threads[p->thread_id];
2401 struct instruction *ip = t->ip;
2403 __instr_forget_exec(p, t, ip);
2413 instr_extern_translate(struct rte_swx_pipeline *p,
2414 struct action *action __rte_unused,
2417 struct instruction *instr,
2418 struct instruction_data *data __rte_unused)
2420 char *token = tokens[1];
2422 CHECK(n_tokens == 2, EINVAL);
2424 if (token[0] == 'e') {
2425 struct extern_obj *obj;
2426 struct extern_type_member_func *func;
2428 func = extern_obj_member_func_parse(p, token, &obj);
2429 CHECK(func, EINVAL);
2431 instr->type = INSTR_EXTERN_OBJ;
2432 instr->ext_obj.ext_obj_id = obj->id;
2433 instr->ext_obj.func_id = func->id;
2438 if (token[0] == 'f') {
2439 struct extern_func *func;
2441 func = extern_func_parse(p, token);
2442 CHECK(func, EINVAL);
2444 instr->type = INSTR_EXTERN_FUNC;
2445 instr->ext_func.ext_func_id = func->id;
2454 instr_extern_obj_exec(struct rte_swx_pipeline *p)
2456 struct thread *t = &p->threads[p->thread_id];
2457 struct instruction *ip = t->ip;
2460 /* Extern object member function execute. */
2461 done = __instr_extern_obj_exec(p, t, ip);
2464 thread_ip_inc_cond(t, done);
2465 thread_yield_cond(p, done ^ 1);
2469 instr_extern_func_exec(struct rte_swx_pipeline *p)
2471 struct thread *t = &p->threads[p->thread_id];
2472 struct instruction *ip = t->ip;
2475 /* Extern function execute. */
2476 done = __instr_extern_func_exec(p, t, ip);
2479 thread_ip_inc_cond(t, done);
2480 thread_yield_cond(p, done ^ 1);
2487 instr_mov_translate(struct rte_swx_pipeline *p,
2488 struct action *action,
2491 struct instruction *instr,
2492 struct instruction_data *data __rte_unused)
2494 char *dst = tokens[1], *src = tokens[2];
2495 struct field *fdst, *fsrc;
2497 uint32_t dst_struct_id = 0, src_struct_id = 0;
2499 CHECK(n_tokens == 3, EINVAL);
2501 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2502 CHECK(fdst, EINVAL);
2503 CHECK(!fdst->var_size, EINVAL);
2505 /* MOV, MOV_MH, MOV_HM or MOV_HH. */
2506 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2508 CHECK(!fsrc->var_size, EINVAL);
2510 instr->type = INSTR_MOV;
2511 if (dst[0] != 'h' && src[0] == 'h')
2512 instr->type = INSTR_MOV_MH;
2513 if (dst[0] == 'h' && src[0] != 'h')
2514 instr->type = INSTR_MOV_HM;
2515 if (dst[0] == 'h' && src[0] == 'h')
2516 instr->type = INSTR_MOV_HH;
2518 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
2519 instr->mov.dst.n_bits = fdst->n_bits;
2520 instr->mov.dst.offset = fdst->offset / 8;
2521 instr->mov.src.struct_id = (uint8_t)src_struct_id;
2522 instr->mov.src.n_bits = fsrc->n_bits;
2523 instr->mov.src.offset = fsrc->offset / 8;
2528 src_val = strtoull(src, &src, 0);
2529 CHECK(!src[0], EINVAL);
2532 src_val = hton64(src_val) >> (64 - fdst->n_bits);
2534 instr->type = INSTR_MOV_I;
2535 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
2536 instr->mov.dst.n_bits = fdst->n_bits;
2537 instr->mov.dst.offset = fdst->offset / 8;
2538 instr->mov.src_val = src_val;
2543 instr_mov_exec(struct rte_swx_pipeline *p)
2545 struct thread *t = &p->threads[p->thread_id];
2546 struct instruction *ip = t->ip;
2548 __instr_mov_exec(p, t, ip);
2555 instr_mov_mh_exec(struct rte_swx_pipeline *p)
2557 struct thread *t = &p->threads[p->thread_id];
2558 struct instruction *ip = t->ip;
2560 __instr_mov_mh_exec(p, t, ip);
2567 instr_mov_hm_exec(struct rte_swx_pipeline *p)
2569 struct thread *t = &p->threads[p->thread_id];
2570 struct instruction *ip = t->ip;
2572 __instr_mov_hm_exec(p, t, ip);
2579 instr_mov_hh_exec(struct rte_swx_pipeline *p)
2581 struct thread *t = &p->threads[p->thread_id];
2582 struct instruction *ip = t->ip;
2584 __instr_mov_hh_exec(p, t, ip);
2591 instr_mov_i_exec(struct rte_swx_pipeline *p)
2593 struct thread *t = &p->threads[p->thread_id];
2594 struct instruction *ip = t->ip;
2596 __instr_mov_i_exec(p, t, ip);
2606 instr_dma_ht_exec(struct rte_swx_pipeline *p)
2608 struct thread *t = &p->threads[p->thread_id];
2609 struct instruction *ip = t->ip;
2611 __instr_dma_ht_exec(p, t, ip);
2618 instr_dma_ht2_exec(struct rte_swx_pipeline *p)
2620 struct thread *t = &p->threads[p->thread_id];
2621 struct instruction *ip = t->ip;
2623 __instr_dma_ht2_exec(p, t, ip);
2630 instr_dma_ht3_exec(struct rte_swx_pipeline *p)
2632 struct thread *t = &p->threads[p->thread_id];
2633 struct instruction *ip = t->ip;
2635 __instr_dma_ht3_exec(p, t, ip);
2642 instr_dma_ht4_exec(struct rte_swx_pipeline *p)
2644 struct thread *t = &p->threads[p->thread_id];
2645 struct instruction *ip = t->ip;
2647 __instr_dma_ht4_exec(p, t, ip);
2654 instr_dma_ht5_exec(struct rte_swx_pipeline *p)
2656 struct thread *t = &p->threads[p->thread_id];
2657 struct instruction *ip = t->ip;
2659 __instr_dma_ht5_exec(p, t, ip);
2666 instr_dma_ht6_exec(struct rte_swx_pipeline *p)
2668 struct thread *t = &p->threads[p->thread_id];
2669 struct instruction *ip = t->ip;
2671 __instr_dma_ht6_exec(p, t, ip);
2678 instr_dma_ht7_exec(struct rte_swx_pipeline *p)
2680 struct thread *t = &p->threads[p->thread_id];
2681 struct instruction *ip = t->ip;
2683 __instr_dma_ht7_exec(p, t, ip);
2690 instr_dma_ht8_exec(struct rte_swx_pipeline *p)
2692 struct thread *t = &p->threads[p->thread_id];
2693 struct instruction *ip = t->ip;
2695 __instr_dma_ht8_exec(p, t, ip);
2705 instr_alu_add_translate(struct rte_swx_pipeline *p,
2706 struct action *action,
2709 struct instruction *instr,
2710 struct instruction_data *data __rte_unused)
2712 char *dst = tokens[1], *src = tokens[2];
2713 struct field *fdst, *fsrc;
2715 uint32_t dst_struct_id = 0, src_struct_id = 0;
2717 CHECK(n_tokens == 3, EINVAL);
2719 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2720 CHECK(fdst, EINVAL);
2721 CHECK(!fdst->var_size, EINVAL);
2723 /* ADD, ADD_HM, ADD_MH, ADD_HH. */
2724 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2726 CHECK(!fsrc->var_size, EINVAL);
2728 instr->type = INSTR_ALU_ADD;
2729 if (dst[0] == 'h' && src[0] != 'h')
2730 instr->type = INSTR_ALU_ADD_HM;
2731 if (dst[0] != 'h' && src[0] == 'h')
2732 instr->type = INSTR_ALU_ADD_MH;
2733 if (dst[0] == 'h' && src[0] == 'h')
2734 instr->type = INSTR_ALU_ADD_HH;
2736 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2737 instr->alu.dst.n_bits = fdst->n_bits;
2738 instr->alu.dst.offset = fdst->offset / 8;
2739 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2740 instr->alu.src.n_bits = fsrc->n_bits;
2741 instr->alu.src.offset = fsrc->offset / 8;
2745 /* ADD_MI, ADD_HI. */
2746 src_val = strtoull(src, &src, 0);
2747 CHECK(!src[0], EINVAL);
2749 instr->type = INSTR_ALU_ADD_MI;
2751 instr->type = INSTR_ALU_ADD_HI;
2753 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2754 instr->alu.dst.n_bits = fdst->n_bits;
2755 instr->alu.dst.offset = fdst->offset / 8;
2756 instr->alu.src_val = src_val;
2761 instr_alu_sub_translate(struct rte_swx_pipeline *p,
2762 struct action *action,
2765 struct instruction *instr,
2766 struct instruction_data *data __rte_unused)
2768 char *dst = tokens[1], *src = tokens[2];
2769 struct field *fdst, *fsrc;
2771 uint32_t dst_struct_id = 0, src_struct_id = 0;
2773 CHECK(n_tokens == 3, EINVAL);
2775 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2776 CHECK(fdst, EINVAL);
2777 CHECK(!fdst->var_size, EINVAL);
2779 /* SUB, SUB_HM, SUB_MH, SUB_HH. */
2780 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2782 CHECK(!fsrc->var_size, EINVAL);
2784 instr->type = INSTR_ALU_SUB;
2785 if (dst[0] == 'h' && src[0] != 'h')
2786 instr->type = INSTR_ALU_SUB_HM;
2787 if (dst[0] != 'h' && src[0] == 'h')
2788 instr->type = INSTR_ALU_SUB_MH;
2789 if (dst[0] == 'h' && src[0] == 'h')
2790 instr->type = INSTR_ALU_SUB_HH;
2792 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2793 instr->alu.dst.n_bits = fdst->n_bits;
2794 instr->alu.dst.offset = fdst->offset / 8;
2795 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2796 instr->alu.src.n_bits = fsrc->n_bits;
2797 instr->alu.src.offset = fsrc->offset / 8;
2801 /* SUB_MI, SUB_HI. */
2802 src_val = strtoull(src, &src, 0);
2803 CHECK(!src[0], EINVAL);
2805 instr->type = INSTR_ALU_SUB_MI;
2807 instr->type = INSTR_ALU_SUB_HI;
2809 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2810 instr->alu.dst.n_bits = fdst->n_bits;
2811 instr->alu.dst.offset = fdst->offset / 8;
2812 instr->alu.src_val = src_val;
2817 instr_alu_ckadd_translate(struct rte_swx_pipeline *p,
2818 struct action *action __rte_unused,
2821 struct instruction *instr,
2822 struct instruction_data *data __rte_unused)
2824 char *dst = tokens[1], *src = tokens[2];
2825 struct header *hdst, *hsrc;
2826 struct field *fdst, *fsrc;
2828 CHECK(n_tokens == 3, EINVAL);
2830 fdst = header_field_parse(p, dst, &hdst);
2831 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
2832 CHECK(!fdst->var_size, EINVAL);
2835 fsrc = header_field_parse(p, src, &hsrc);
2837 CHECK(!fsrc->var_size, EINVAL);
2839 instr->type = INSTR_ALU_CKADD_FIELD;
2840 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2841 instr->alu.dst.n_bits = fdst->n_bits;
2842 instr->alu.dst.offset = fdst->offset / 8;
2843 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2844 instr->alu.src.n_bits = fsrc->n_bits;
2845 instr->alu.src.offset = fsrc->offset / 8;
2849 /* CKADD_STRUCT, CKADD_STRUCT20. */
2850 hsrc = header_parse(p, src);
2851 CHECK(hsrc, EINVAL);
2852 CHECK(!hsrc->st->var_size, EINVAL);
2854 instr->type = INSTR_ALU_CKADD_STRUCT;
2855 if ((hsrc->st->n_bits / 8) == 20)
2856 instr->type = INSTR_ALU_CKADD_STRUCT20;
2858 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2859 instr->alu.dst.n_bits = fdst->n_bits;
2860 instr->alu.dst.offset = fdst->offset / 8;
2861 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2862 instr->alu.src.n_bits = hsrc->st->n_bits;
2863 instr->alu.src.offset = 0; /* Unused. */
2868 instr_alu_cksub_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);
2885 fsrc = header_field_parse(p, src, &hsrc);
2886 CHECK(fsrc, EINVAL);
2887 CHECK(!fsrc->var_size, EINVAL);
2889 instr->type = INSTR_ALU_CKSUB_FIELD;
2890 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2891 instr->alu.dst.n_bits = fdst->n_bits;
2892 instr->alu.dst.offset = fdst->offset / 8;
2893 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2894 instr->alu.src.n_bits = fsrc->n_bits;
2895 instr->alu.src.offset = fsrc->offset / 8;
2900 instr_alu_shl_translate(struct rte_swx_pipeline *p,
2901 struct action *action,
2904 struct instruction *instr,
2905 struct instruction_data *data __rte_unused)
2907 char *dst = tokens[1], *src = tokens[2];
2908 struct field *fdst, *fsrc;
2910 uint32_t dst_struct_id = 0, src_struct_id = 0;
2912 CHECK(n_tokens == 3, EINVAL);
2914 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2915 CHECK(fdst, EINVAL);
2916 CHECK(!fdst->var_size, EINVAL);
2918 /* SHL, SHL_HM, SHL_MH, SHL_HH. */
2919 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2921 CHECK(!fsrc->var_size, EINVAL);
2923 instr->type = INSTR_ALU_SHL;
2924 if (dst[0] == 'h' && src[0] != 'h')
2925 instr->type = INSTR_ALU_SHL_HM;
2926 if (dst[0] != 'h' && src[0] == 'h')
2927 instr->type = INSTR_ALU_SHL_MH;
2928 if (dst[0] == 'h' && src[0] == 'h')
2929 instr->type = INSTR_ALU_SHL_HH;
2931 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2932 instr->alu.dst.n_bits = fdst->n_bits;
2933 instr->alu.dst.offset = fdst->offset / 8;
2934 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2935 instr->alu.src.n_bits = fsrc->n_bits;
2936 instr->alu.src.offset = fsrc->offset / 8;
2940 /* SHL_MI, SHL_HI. */
2941 src_val = strtoull(src, &src, 0);
2942 CHECK(!src[0], EINVAL);
2944 instr->type = INSTR_ALU_SHL_MI;
2946 instr->type = INSTR_ALU_SHL_HI;
2948 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2949 instr->alu.dst.n_bits = fdst->n_bits;
2950 instr->alu.dst.offset = fdst->offset / 8;
2951 instr->alu.src_val = src_val;
2956 instr_alu_shr_translate(struct rte_swx_pipeline *p,
2957 struct action *action,
2960 struct instruction *instr,
2961 struct instruction_data *data __rte_unused)
2963 char *dst = tokens[1], *src = tokens[2];
2964 struct field *fdst, *fsrc;
2966 uint32_t dst_struct_id = 0, src_struct_id = 0;
2968 CHECK(n_tokens == 3, EINVAL);
2970 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2971 CHECK(fdst, EINVAL);
2972 CHECK(!fdst->var_size, EINVAL);
2974 /* SHR, SHR_HM, SHR_MH, SHR_HH. */
2975 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2977 CHECK(!fsrc->var_size, EINVAL);
2979 instr->type = INSTR_ALU_SHR;
2980 if (dst[0] == 'h' && src[0] != 'h')
2981 instr->type = INSTR_ALU_SHR_HM;
2982 if (dst[0] != 'h' && src[0] == 'h')
2983 instr->type = INSTR_ALU_SHR_MH;
2984 if (dst[0] == 'h' && src[0] == 'h')
2985 instr->type = INSTR_ALU_SHR_HH;
2987 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2988 instr->alu.dst.n_bits = fdst->n_bits;
2989 instr->alu.dst.offset = fdst->offset / 8;
2990 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2991 instr->alu.src.n_bits = fsrc->n_bits;
2992 instr->alu.src.offset = fsrc->offset / 8;
2996 /* SHR_MI, SHR_HI. */
2997 src_val = strtoull(src, &src, 0);
2998 CHECK(!src[0], EINVAL);
3000 instr->type = INSTR_ALU_SHR_MI;
3002 instr->type = INSTR_ALU_SHR_HI;
3004 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3005 instr->alu.dst.n_bits = fdst->n_bits;
3006 instr->alu.dst.offset = fdst->offset / 8;
3007 instr->alu.src_val = src_val;
3012 instr_alu_and_translate(struct rte_swx_pipeline *p,
3013 struct action *action,
3016 struct instruction *instr,
3017 struct instruction_data *data __rte_unused)
3019 char *dst = tokens[1], *src = tokens[2];
3020 struct field *fdst, *fsrc;
3022 uint32_t dst_struct_id = 0, src_struct_id = 0;
3024 CHECK(n_tokens == 3, EINVAL);
3026 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3027 CHECK(fdst, EINVAL);
3028 CHECK(!fdst->var_size, EINVAL);
3030 /* AND, AND_MH, AND_HM, AND_HH. */
3031 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3033 CHECK(!fsrc->var_size, EINVAL);
3035 instr->type = INSTR_ALU_AND;
3036 if (dst[0] != 'h' && src[0] == 'h')
3037 instr->type = INSTR_ALU_AND_MH;
3038 if (dst[0] == 'h' && src[0] != 'h')
3039 instr->type = INSTR_ALU_AND_HM;
3040 if (dst[0] == 'h' && src[0] == 'h')
3041 instr->type = INSTR_ALU_AND_HH;
3043 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3044 instr->alu.dst.n_bits = fdst->n_bits;
3045 instr->alu.dst.offset = fdst->offset / 8;
3046 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3047 instr->alu.src.n_bits = fsrc->n_bits;
3048 instr->alu.src.offset = fsrc->offset / 8;
3053 src_val = strtoull(src, &src, 0);
3054 CHECK(!src[0], EINVAL);
3057 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3059 instr->type = INSTR_ALU_AND_I;
3060 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3061 instr->alu.dst.n_bits = fdst->n_bits;
3062 instr->alu.dst.offset = fdst->offset / 8;
3063 instr->alu.src_val = src_val;
3068 instr_alu_or_translate(struct rte_swx_pipeline *p,
3069 struct action *action,
3072 struct instruction *instr,
3073 struct instruction_data *data __rte_unused)
3075 char *dst = tokens[1], *src = tokens[2];
3076 struct field *fdst, *fsrc;
3078 uint32_t dst_struct_id = 0, src_struct_id = 0;
3080 CHECK(n_tokens == 3, EINVAL);
3082 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3083 CHECK(fdst, EINVAL);
3084 CHECK(!fdst->var_size, EINVAL);
3086 /* OR, OR_MH, OR_HM, OR_HH. */
3087 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3089 CHECK(!fsrc->var_size, EINVAL);
3091 instr->type = INSTR_ALU_OR;
3092 if (dst[0] != 'h' && src[0] == 'h')
3093 instr->type = INSTR_ALU_OR_MH;
3094 if (dst[0] == 'h' && src[0] != 'h')
3095 instr->type = INSTR_ALU_OR_HM;
3096 if (dst[0] == 'h' && src[0] == 'h')
3097 instr->type = INSTR_ALU_OR_HH;
3099 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3100 instr->alu.dst.n_bits = fdst->n_bits;
3101 instr->alu.dst.offset = fdst->offset / 8;
3102 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3103 instr->alu.src.n_bits = fsrc->n_bits;
3104 instr->alu.src.offset = fsrc->offset / 8;
3109 src_val = strtoull(src, &src, 0);
3110 CHECK(!src[0], EINVAL);
3113 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3115 instr->type = INSTR_ALU_OR_I;
3116 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3117 instr->alu.dst.n_bits = fdst->n_bits;
3118 instr->alu.dst.offset = fdst->offset / 8;
3119 instr->alu.src_val = src_val;
3124 instr_alu_xor_translate(struct rte_swx_pipeline *p,
3125 struct action *action,
3128 struct instruction *instr,
3129 struct instruction_data *data __rte_unused)
3131 char *dst = tokens[1], *src = tokens[2];
3132 struct field *fdst, *fsrc;
3134 uint32_t dst_struct_id = 0, src_struct_id = 0;
3136 CHECK(n_tokens == 3, EINVAL);
3138 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3139 CHECK(fdst, EINVAL);
3140 CHECK(!fdst->var_size, EINVAL);
3142 /* XOR, XOR_MH, XOR_HM, XOR_HH. */
3143 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3145 CHECK(!fsrc->var_size, EINVAL);
3147 instr->type = INSTR_ALU_XOR;
3148 if (dst[0] != 'h' && src[0] == 'h')
3149 instr->type = INSTR_ALU_XOR_MH;
3150 if (dst[0] == 'h' && src[0] != 'h')
3151 instr->type = INSTR_ALU_XOR_HM;
3152 if (dst[0] == 'h' && src[0] == 'h')
3153 instr->type = INSTR_ALU_XOR_HH;
3155 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3156 instr->alu.dst.n_bits = fdst->n_bits;
3157 instr->alu.dst.offset = fdst->offset / 8;
3158 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3159 instr->alu.src.n_bits = fsrc->n_bits;
3160 instr->alu.src.offset = fsrc->offset / 8;
3165 src_val = strtoull(src, &src, 0);
3166 CHECK(!src[0], EINVAL);
3169 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3171 instr->type = INSTR_ALU_XOR_I;
3172 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3173 instr->alu.dst.n_bits = fdst->n_bits;
3174 instr->alu.dst.offset = fdst->offset / 8;
3175 instr->alu.src_val = src_val;
3180 instr_alu_add_exec(struct rte_swx_pipeline *p)
3182 struct thread *t = &p->threads[p->thread_id];
3183 struct instruction *ip = t->ip;
3186 __instr_alu_add_exec(p, t, ip);
3193 instr_alu_add_mh_exec(struct rte_swx_pipeline *p)
3195 struct thread *t = &p->threads[p->thread_id];
3196 struct instruction *ip = t->ip;
3199 __instr_alu_add_mh_exec(p, t, ip);
3206 instr_alu_add_hm_exec(struct rte_swx_pipeline *p)
3208 struct thread *t = &p->threads[p->thread_id];
3209 struct instruction *ip = t->ip;
3212 __instr_alu_add_hm_exec(p, t, ip);
3219 instr_alu_add_hh_exec(struct rte_swx_pipeline *p)
3221 struct thread *t = &p->threads[p->thread_id];
3222 struct instruction *ip = t->ip;
3225 __instr_alu_add_hh_exec(p, t, ip);
3232 instr_alu_add_mi_exec(struct rte_swx_pipeline *p)
3234 struct thread *t = &p->threads[p->thread_id];
3235 struct instruction *ip = t->ip;
3238 __instr_alu_add_mi_exec(p, t, ip);
3245 instr_alu_add_hi_exec(struct rte_swx_pipeline *p)
3247 struct thread *t = &p->threads[p->thread_id];
3248 struct instruction *ip = t->ip;
3251 __instr_alu_add_hi_exec(p, t, ip);
3258 instr_alu_sub_exec(struct rte_swx_pipeline *p)
3260 struct thread *t = &p->threads[p->thread_id];
3261 struct instruction *ip = t->ip;
3264 __instr_alu_sub_exec(p, t, ip);
3271 instr_alu_sub_mh_exec(struct rte_swx_pipeline *p)
3273 struct thread *t = &p->threads[p->thread_id];
3274 struct instruction *ip = t->ip;
3277 __instr_alu_sub_mh_exec(p, t, ip);
3284 instr_alu_sub_hm_exec(struct rte_swx_pipeline *p)
3286 struct thread *t = &p->threads[p->thread_id];
3287 struct instruction *ip = t->ip;
3290 __instr_alu_sub_hm_exec(p, t, ip);
3297 instr_alu_sub_hh_exec(struct rte_swx_pipeline *p)
3299 struct thread *t = &p->threads[p->thread_id];
3300 struct instruction *ip = t->ip;
3303 __instr_alu_sub_hh_exec(p, t, ip);
3310 instr_alu_sub_mi_exec(struct rte_swx_pipeline *p)
3312 struct thread *t = &p->threads[p->thread_id];
3313 struct instruction *ip = t->ip;
3316 __instr_alu_sub_mi_exec(p, t, ip);
3323 instr_alu_sub_hi_exec(struct rte_swx_pipeline *p)
3325 struct thread *t = &p->threads[p->thread_id];
3326 struct instruction *ip = t->ip;
3329 __instr_alu_sub_hi_exec(p, t, ip);
3336 instr_alu_shl_exec(struct rte_swx_pipeline *p)
3338 struct thread *t = &p->threads[p->thread_id];
3339 struct instruction *ip = t->ip;
3342 __instr_alu_shl_exec(p, t, ip);
3349 instr_alu_shl_mh_exec(struct rte_swx_pipeline *p)
3351 struct thread *t = &p->threads[p->thread_id];
3352 struct instruction *ip = t->ip;
3355 __instr_alu_shl_mh_exec(p, t, ip);
3362 instr_alu_shl_hm_exec(struct rte_swx_pipeline *p)
3364 struct thread *t = &p->threads[p->thread_id];
3365 struct instruction *ip = t->ip;
3368 __instr_alu_shl_hm_exec(p, t, ip);
3375 instr_alu_shl_hh_exec(struct rte_swx_pipeline *p)
3377 struct thread *t = &p->threads[p->thread_id];
3378 struct instruction *ip = t->ip;
3381 __instr_alu_shl_hh_exec(p, t, ip);
3388 instr_alu_shl_mi_exec(struct rte_swx_pipeline *p)
3390 struct thread *t = &p->threads[p->thread_id];
3391 struct instruction *ip = t->ip;
3394 __instr_alu_shl_mi_exec(p, t, ip);
3401 instr_alu_shl_hi_exec(struct rte_swx_pipeline *p)
3403 struct thread *t = &p->threads[p->thread_id];
3404 struct instruction *ip = t->ip;
3407 __instr_alu_shl_hi_exec(p, t, ip);
3414 instr_alu_shr_exec(struct rte_swx_pipeline *p)
3416 struct thread *t = &p->threads[p->thread_id];
3417 struct instruction *ip = t->ip;
3420 __instr_alu_shr_exec(p, t, ip);
3427 instr_alu_shr_mh_exec(struct rte_swx_pipeline *p)
3429 struct thread *t = &p->threads[p->thread_id];
3430 struct instruction *ip = t->ip;
3433 __instr_alu_shr_mh_exec(p, t, ip);
3440 instr_alu_shr_hm_exec(struct rte_swx_pipeline *p)
3442 struct thread *t = &p->threads[p->thread_id];
3443 struct instruction *ip = t->ip;
3446 __instr_alu_shr_hm_exec(p, t, ip);
3453 instr_alu_shr_hh_exec(struct rte_swx_pipeline *p)
3455 struct thread *t = &p->threads[p->thread_id];
3456 struct instruction *ip = t->ip;
3459 __instr_alu_shr_hh_exec(p, t, ip);
3466 instr_alu_shr_mi_exec(struct rte_swx_pipeline *p)
3468 struct thread *t = &p->threads[p->thread_id];
3469 struct instruction *ip = t->ip;
3472 __instr_alu_shr_mi_exec(p, t, ip);
3479 instr_alu_shr_hi_exec(struct rte_swx_pipeline *p)
3481 struct thread *t = &p->threads[p->thread_id];
3482 struct instruction *ip = t->ip;
3485 __instr_alu_shr_hi_exec(p, t, ip);
3492 instr_alu_and_exec(struct rte_swx_pipeline *p)
3494 struct thread *t = &p->threads[p->thread_id];
3495 struct instruction *ip = t->ip;
3498 __instr_alu_and_exec(p, t, ip);
3505 instr_alu_and_mh_exec(struct rte_swx_pipeline *p)
3507 struct thread *t = &p->threads[p->thread_id];
3508 struct instruction *ip = t->ip;
3511 __instr_alu_and_mh_exec(p, t, ip);
3518 instr_alu_and_hm_exec(struct rte_swx_pipeline *p)
3520 struct thread *t = &p->threads[p->thread_id];
3521 struct instruction *ip = t->ip;
3524 __instr_alu_and_hm_exec(p, t, ip);
3531 instr_alu_and_hh_exec(struct rte_swx_pipeline *p)
3533 struct thread *t = &p->threads[p->thread_id];
3534 struct instruction *ip = t->ip;
3537 __instr_alu_and_hh_exec(p, t, ip);
3544 instr_alu_and_i_exec(struct rte_swx_pipeline *p)
3546 struct thread *t = &p->threads[p->thread_id];
3547 struct instruction *ip = t->ip;
3550 __instr_alu_and_i_exec(p, t, ip);
3557 instr_alu_or_exec(struct rte_swx_pipeline *p)
3559 struct thread *t = &p->threads[p->thread_id];
3560 struct instruction *ip = t->ip;
3563 __instr_alu_or_exec(p, t, ip);
3570 instr_alu_or_mh_exec(struct rte_swx_pipeline *p)
3572 struct thread *t = &p->threads[p->thread_id];
3573 struct instruction *ip = t->ip;
3576 __instr_alu_or_mh_exec(p, t, ip);
3583 instr_alu_or_hm_exec(struct rte_swx_pipeline *p)
3585 struct thread *t = &p->threads[p->thread_id];
3586 struct instruction *ip = t->ip;
3589 __instr_alu_or_hm_exec(p, t, ip);
3596 instr_alu_or_hh_exec(struct rte_swx_pipeline *p)
3598 struct thread *t = &p->threads[p->thread_id];
3599 struct instruction *ip = t->ip;
3602 __instr_alu_or_hh_exec(p, t, ip);
3609 instr_alu_or_i_exec(struct rte_swx_pipeline *p)
3611 struct thread *t = &p->threads[p->thread_id];
3612 struct instruction *ip = t->ip;
3615 __instr_alu_or_i_exec(p, t, ip);
3622 instr_alu_xor_exec(struct rte_swx_pipeline *p)
3624 struct thread *t = &p->threads[p->thread_id];
3625 struct instruction *ip = t->ip;
3628 __instr_alu_xor_exec(p, t, ip);
3635 instr_alu_xor_mh_exec(struct rte_swx_pipeline *p)
3637 struct thread *t = &p->threads[p->thread_id];
3638 struct instruction *ip = t->ip;
3641 __instr_alu_xor_mh_exec(p, t, ip);
3648 instr_alu_xor_hm_exec(struct rte_swx_pipeline *p)
3650 struct thread *t = &p->threads[p->thread_id];
3651 struct instruction *ip = t->ip;
3654 __instr_alu_xor_hm_exec(p, t, ip);
3661 instr_alu_xor_hh_exec(struct rte_swx_pipeline *p)
3663 struct thread *t = &p->threads[p->thread_id];
3664 struct instruction *ip = t->ip;
3667 __instr_alu_xor_hh_exec(p, t, ip);
3674 instr_alu_xor_i_exec(struct rte_swx_pipeline *p)
3676 struct thread *t = &p->threads[p->thread_id];
3677 struct instruction *ip = t->ip;
3680 __instr_alu_xor_i_exec(p, t, ip);
3687 instr_alu_ckadd_field_exec(struct rte_swx_pipeline *p)
3689 struct thread *t = &p->threads[p->thread_id];
3690 struct instruction *ip = t->ip;
3693 __instr_alu_ckadd_field_exec(p, t, ip);
3700 instr_alu_cksub_field_exec(struct rte_swx_pipeline *p)
3702 struct thread *t = &p->threads[p->thread_id];
3703 struct instruction *ip = t->ip;
3706 __instr_alu_cksub_field_exec(p, t, ip);
3713 instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline *p)
3715 struct thread *t = &p->threads[p->thread_id];
3716 struct instruction *ip = t->ip;
3719 __instr_alu_ckadd_struct20_exec(p, t, ip);
3726 instr_alu_ckadd_struct_exec(struct rte_swx_pipeline *p)
3728 struct thread *t = &p->threads[p->thread_id];
3729 struct instruction *ip = t->ip;
3732 __instr_alu_ckadd_struct_exec(p, t, ip);
3741 static struct regarray *
3742 regarray_find(struct rte_swx_pipeline *p, const char *name);
3745 instr_regprefetch_translate(struct rte_swx_pipeline *p,
3746 struct action *action,
3749 struct instruction *instr,
3750 struct instruction_data *data __rte_unused)
3752 char *regarray = tokens[1], *idx = tokens[2];
3755 uint32_t idx_struct_id, idx_val;
3757 CHECK(n_tokens == 3, EINVAL);
3759 r = regarray_find(p, regarray);
3762 /* REGPREFETCH_RH, REGPREFETCH_RM. */
3763 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
3765 CHECK(!fidx->var_size, EINVAL);
3767 instr->type = INSTR_REGPREFETCH_RM;
3769 instr->type = INSTR_REGPREFETCH_RH;
3771 instr->regarray.regarray_id = r->id;
3772 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
3773 instr->regarray.idx.n_bits = fidx->n_bits;
3774 instr->regarray.idx.offset = fidx->offset / 8;
3775 instr->regarray.dstsrc_val = 0; /* Unused. */
3779 /* REGPREFETCH_RI. */
3780 idx_val = strtoul(idx, &idx, 0);
3781 CHECK(!idx[0], EINVAL);
3783 instr->type = INSTR_REGPREFETCH_RI;
3784 instr->regarray.regarray_id = r->id;
3785 instr->regarray.idx_val = idx_val;
3786 instr->regarray.dstsrc_val = 0; /* Unused. */
3791 instr_regrd_translate(struct rte_swx_pipeline *p,
3792 struct action *action,
3795 struct instruction *instr,
3796 struct instruction_data *data __rte_unused)
3798 char *dst = tokens[1], *regarray = tokens[2], *idx = tokens[3];
3800 struct field *fdst, *fidx;
3801 uint32_t dst_struct_id, idx_struct_id, idx_val;
3803 CHECK(n_tokens == 4, EINVAL);
3805 r = regarray_find(p, regarray);
3808 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3809 CHECK(fdst, EINVAL);
3810 CHECK(!fdst->var_size, EINVAL);
3812 /* REGRD_HRH, REGRD_HRM, REGRD_MRH, REGRD_MRM. */
3813 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
3815 CHECK(!fidx->var_size, EINVAL);
3817 instr->type = INSTR_REGRD_MRM;
3818 if (dst[0] == 'h' && idx[0] != 'h')
3819 instr->type = INSTR_REGRD_HRM;
3820 if (dst[0] != 'h' && idx[0] == 'h')
3821 instr->type = INSTR_REGRD_MRH;
3822 if (dst[0] == 'h' && idx[0] == 'h')
3823 instr->type = INSTR_REGRD_HRH;
3825 instr->regarray.regarray_id = r->id;
3826 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
3827 instr->regarray.idx.n_bits = fidx->n_bits;
3828 instr->regarray.idx.offset = fidx->offset / 8;
3829 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
3830 instr->regarray.dstsrc.n_bits = fdst->n_bits;
3831 instr->regarray.dstsrc.offset = fdst->offset / 8;
3835 /* REGRD_MRI, REGRD_HRI. */
3836 idx_val = strtoul(idx, &idx, 0);
3837 CHECK(!idx[0], EINVAL);
3839 instr->type = INSTR_REGRD_MRI;
3841 instr->type = INSTR_REGRD_HRI;
3843 instr->regarray.regarray_id = r->id;
3844 instr->regarray.idx_val = idx_val;
3845 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
3846 instr->regarray.dstsrc.n_bits = fdst->n_bits;
3847 instr->regarray.dstsrc.offset = fdst->offset / 8;
3852 instr_regwr_translate(struct rte_swx_pipeline *p,
3853 struct action *action,
3856 struct instruction *instr,
3857 struct instruction_data *data __rte_unused)
3859 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
3861 struct field *fidx, *fsrc;
3863 uint32_t idx_struct_id, idx_val, src_struct_id;
3865 CHECK(n_tokens == 4, EINVAL);
3867 r = regarray_find(p, regarray);
3870 /* REGWR_RHH, REGWR_RHM, REGWR_RMH, REGWR_RMM. */
3871 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
3872 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3874 CHECK(!fidx->var_size, EINVAL);
3875 CHECK(!fsrc->var_size, EINVAL);
3877 instr->type = INSTR_REGWR_RMM;
3878 if (idx[0] == 'h' && src[0] != 'h')
3879 instr->type = INSTR_REGWR_RHM;
3880 if (idx[0] != 'h' && src[0] == 'h')
3881 instr->type = INSTR_REGWR_RMH;
3882 if (idx[0] == 'h' && src[0] == 'h')
3883 instr->type = INSTR_REGWR_RHH;
3885 instr->regarray.regarray_id = r->id;
3886 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
3887 instr->regarray.idx.n_bits = fidx->n_bits;
3888 instr->regarray.idx.offset = fidx->offset / 8;
3889 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
3890 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
3891 instr->regarray.dstsrc.offset = fsrc->offset / 8;
3895 /* REGWR_RHI, REGWR_RMI. */
3896 if (fidx && !fsrc) {
3897 CHECK(!fidx->var_size, EINVAL);
3899 src_val = strtoull(src, &src, 0);
3900 CHECK(!src[0], EINVAL);
3902 instr->type = INSTR_REGWR_RMI;
3904 instr->type = INSTR_REGWR_RHI;
3906 instr->regarray.regarray_id = r->id;
3907 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
3908 instr->regarray.idx.n_bits = fidx->n_bits;
3909 instr->regarray.idx.offset = fidx->offset / 8;
3910 instr->regarray.dstsrc_val = src_val;
3914 /* REGWR_RIH, REGWR_RIM. */
3915 if (!fidx && fsrc) {
3916 idx_val = strtoul(idx, &idx, 0);
3917 CHECK(!idx[0], EINVAL);
3919 CHECK(!fsrc->var_size, EINVAL);
3921 instr->type = INSTR_REGWR_RIM;
3923 instr->type = INSTR_REGWR_RIH;
3925 instr->regarray.regarray_id = r->id;
3926 instr->regarray.idx_val = idx_val;
3927 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
3928 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
3929 instr->regarray.dstsrc.offset = fsrc->offset / 8;
3934 src_val = strtoull(src, &src, 0);
3935 CHECK(!src[0], EINVAL);
3937 idx_val = strtoul(idx, &idx, 0);
3938 CHECK(!idx[0], EINVAL);
3940 instr->type = INSTR_REGWR_RII;
3941 instr->regarray.idx_val = idx_val;
3942 instr->regarray.dstsrc_val = src_val;
3948 instr_regadd_translate(struct rte_swx_pipeline *p,
3949 struct action *action,
3952 struct instruction *instr,
3953 struct instruction_data *data __rte_unused)
3955 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
3957 struct field *fidx, *fsrc;
3959 uint32_t idx_struct_id, idx_val, src_struct_id;
3961 CHECK(n_tokens == 4, EINVAL);
3963 r = regarray_find(p, regarray);
3966 /* REGADD_RHH, REGADD_RHM, REGADD_RMH, REGADD_RMM. */
3967 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
3968 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3970 CHECK(!fidx->var_size, EINVAL);
3971 CHECK(!fsrc->var_size, EINVAL);
3973 instr->type = INSTR_REGADD_RMM;
3974 if (idx[0] == 'h' && src[0] != 'h')
3975 instr->type = INSTR_REGADD_RHM;
3976 if (idx[0] != 'h' && src[0] == 'h')
3977 instr->type = INSTR_REGADD_RMH;
3978 if (idx[0] == 'h' && src[0] == 'h')
3979 instr->type = INSTR_REGADD_RHH;
3981 instr->regarray.regarray_id = r->id;
3982 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
3983 instr->regarray.idx.n_bits = fidx->n_bits;
3984 instr->regarray.idx.offset = fidx->offset / 8;
3985 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
3986 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
3987 instr->regarray.dstsrc.offset = fsrc->offset / 8;
3991 /* REGADD_RHI, REGADD_RMI. */
3992 if (fidx && !fsrc) {
3993 CHECK(!fidx->var_size, EINVAL);
3995 src_val = strtoull(src, &src, 0);
3996 CHECK(!src[0], EINVAL);
3998 instr->type = INSTR_REGADD_RMI;
4000 instr->type = INSTR_REGADD_RHI;
4002 instr->regarray.regarray_id = r->id;
4003 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4004 instr->regarray.idx.n_bits = fidx->n_bits;
4005 instr->regarray.idx.offset = fidx->offset / 8;
4006 instr->regarray.dstsrc_val = src_val;
4010 /* REGADD_RIH, REGADD_RIM. */
4011 if (!fidx && fsrc) {
4012 idx_val = strtoul(idx, &idx, 0);
4013 CHECK(!idx[0], EINVAL);
4015 CHECK(!fsrc->var_size, EINVAL);
4017 instr->type = INSTR_REGADD_RIM;
4019 instr->type = INSTR_REGADD_RIH;
4021 instr->regarray.regarray_id = r->id;
4022 instr->regarray.idx_val = idx_val;
4023 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4024 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4025 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4030 src_val = strtoull(src, &src, 0);
4031 CHECK(!src[0], EINVAL);
4033 idx_val = strtoul(idx, &idx, 0);
4034 CHECK(!idx[0], EINVAL);
4036 instr->type = INSTR_REGADD_RII;
4037 instr->regarray.idx_val = idx_val;
4038 instr->regarray.dstsrc_val = src_val;
4043 instr_regprefetch_rh_exec(struct rte_swx_pipeline *p)
4045 struct thread *t = &p->threads[p->thread_id];
4046 struct instruction *ip = t->ip;
4049 __instr_regprefetch_rh_exec(p, t, ip);
4056 instr_regprefetch_rm_exec(struct rte_swx_pipeline *p)
4058 struct thread *t = &p->threads[p->thread_id];
4059 struct instruction *ip = t->ip;
4062 __instr_regprefetch_rm_exec(p, t, ip);
4069 instr_regprefetch_ri_exec(struct rte_swx_pipeline *p)
4071 struct thread *t = &p->threads[p->thread_id];
4072 struct instruction *ip = t->ip;
4075 __instr_regprefetch_ri_exec(p, t, ip);
4082 instr_regrd_hrh_exec(struct rte_swx_pipeline *p)
4084 struct thread *t = &p->threads[p->thread_id];
4085 struct instruction *ip = t->ip;
4088 __instr_regrd_hrh_exec(p, t, ip);
4095 instr_regrd_hrm_exec(struct rte_swx_pipeline *p)
4097 struct thread *t = &p->threads[p->thread_id];
4098 struct instruction *ip = t->ip;
4101 __instr_regrd_hrm_exec(p, t, ip);
4108 instr_regrd_mrh_exec(struct rte_swx_pipeline *p)
4110 struct thread *t = &p->threads[p->thread_id];
4111 struct instruction *ip = t->ip;
4114 __instr_regrd_mrh_exec(p, t, ip);
4121 instr_regrd_mrm_exec(struct rte_swx_pipeline *p)
4123 struct thread *t = &p->threads[p->thread_id];
4124 struct instruction *ip = t->ip;
4127 __instr_regrd_mrm_exec(p, t, ip);
4134 instr_regrd_hri_exec(struct rte_swx_pipeline *p)
4136 struct thread *t = &p->threads[p->thread_id];
4137 struct instruction *ip = t->ip;
4140 __instr_regrd_hri_exec(p, t, ip);
4147 instr_regrd_mri_exec(struct rte_swx_pipeline *p)
4149 struct thread *t = &p->threads[p->thread_id];
4150 struct instruction *ip = t->ip;
4153 __instr_regrd_mri_exec(p, t, ip);
4160 instr_regwr_rhh_exec(struct rte_swx_pipeline *p)
4162 struct thread *t = &p->threads[p->thread_id];
4163 struct instruction *ip = t->ip;
4166 __instr_regwr_rhh_exec(p, t, ip);
4173 instr_regwr_rhm_exec(struct rte_swx_pipeline *p)
4175 struct thread *t = &p->threads[p->thread_id];
4176 struct instruction *ip = t->ip;
4179 __instr_regwr_rhm_exec(p, t, ip);
4186 instr_regwr_rmh_exec(struct rte_swx_pipeline *p)
4188 struct thread *t = &p->threads[p->thread_id];
4189 struct instruction *ip = t->ip;
4192 __instr_regwr_rmh_exec(p, t, ip);
4199 instr_regwr_rmm_exec(struct rte_swx_pipeline *p)
4201 struct thread *t = &p->threads[p->thread_id];
4202 struct instruction *ip = t->ip;
4205 __instr_regwr_rmm_exec(p, t, ip);
4212 instr_regwr_rhi_exec(struct rte_swx_pipeline *p)
4214 struct thread *t = &p->threads[p->thread_id];
4215 struct instruction *ip = t->ip;
4218 __instr_regwr_rhi_exec(p, t, ip);
4225 instr_regwr_rmi_exec(struct rte_swx_pipeline *p)
4227 struct thread *t = &p->threads[p->thread_id];
4228 struct instruction *ip = t->ip;
4231 __instr_regwr_rmi_exec(p, t, ip);
4238 instr_regwr_rih_exec(struct rte_swx_pipeline *p)
4240 struct thread *t = &p->threads[p->thread_id];
4241 struct instruction *ip = t->ip;
4244 __instr_regwr_rih_exec(p, t, ip);
4251 instr_regwr_rim_exec(struct rte_swx_pipeline *p)
4253 struct thread *t = &p->threads[p->thread_id];
4254 struct instruction *ip = t->ip;
4257 __instr_regwr_rim_exec(p, t, ip);
4264 instr_regwr_rii_exec(struct rte_swx_pipeline *p)
4266 struct thread *t = &p->threads[p->thread_id];
4267 struct instruction *ip = t->ip;
4270 __instr_regwr_rii_exec(p, t, ip);
4277 instr_regadd_rhh_exec(struct rte_swx_pipeline *p)
4279 struct thread *t = &p->threads[p->thread_id];
4280 struct instruction *ip = t->ip;
4283 __instr_regadd_rhh_exec(p, t, ip);
4290 instr_regadd_rhm_exec(struct rte_swx_pipeline *p)
4292 struct thread *t = &p->threads[p->thread_id];
4293 struct instruction *ip = t->ip;
4296 __instr_regadd_rhm_exec(p, t, ip);
4303 instr_regadd_rmh_exec(struct rte_swx_pipeline *p)
4305 struct thread *t = &p->threads[p->thread_id];
4306 struct instruction *ip = t->ip;
4309 __instr_regadd_rmh_exec(p, t, ip);
4316 instr_regadd_rmm_exec(struct rte_swx_pipeline *p)
4318 struct thread *t = &p->threads[p->thread_id];
4319 struct instruction *ip = t->ip;
4322 __instr_regadd_rmm_exec(p, t, ip);
4329 instr_regadd_rhi_exec(struct rte_swx_pipeline *p)
4331 struct thread *t = &p->threads[p->thread_id];
4332 struct instruction *ip = t->ip;
4335 __instr_regadd_rhi_exec(p, t, ip);
4342 instr_regadd_rmi_exec(struct rte_swx_pipeline *p)
4344 struct thread *t = &p->threads[p->thread_id];
4345 struct instruction *ip = t->ip;
4348 __instr_regadd_rmi_exec(p, t, ip);
4355 instr_regadd_rih_exec(struct rte_swx_pipeline *p)
4357 struct thread *t = &p->threads[p->thread_id];
4358 struct instruction *ip = t->ip;
4361 __instr_regadd_rih_exec(p, t, ip);
4368 instr_regadd_rim_exec(struct rte_swx_pipeline *p)
4370 struct thread *t = &p->threads[p->thread_id];
4371 struct instruction *ip = t->ip;
4374 __instr_regadd_rim_exec(p, t, ip);
4381 instr_regadd_rii_exec(struct rte_swx_pipeline *p)
4383 struct thread *t = &p->threads[p->thread_id];
4384 struct instruction *ip = t->ip;
4387 __instr_regadd_rii_exec(p, t, ip);
4396 static struct metarray *
4397 metarray_find(struct rte_swx_pipeline *p, const char *name);
4400 instr_metprefetch_translate(struct rte_swx_pipeline *p,
4401 struct action *action,
4404 struct instruction *instr,
4405 struct instruction_data *data __rte_unused)
4407 char *metarray = tokens[1], *idx = tokens[2];
4410 uint32_t idx_struct_id, idx_val;
4412 CHECK(n_tokens == 3, EINVAL);
4414 m = metarray_find(p, metarray);
4417 /* METPREFETCH_H, METPREFETCH_M. */
4418 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4420 CHECK(!fidx->var_size, EINVAL);
4422 instr->type = INSTR_METPREFETCH_M;
4424 instr->type = INSTR_METPREFETCH_H;
4426 instr->meter.metarray_id = m->id;
4427 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4428 instr->meter.idx.n_bits = fidx->n_bits;
4429 instr->meter.idx.offset = fidx->offset / 8;
4433 /* METPREFETCH_I. */
4434 idx_val = strtoul(idx, &idx, 0);
4435 CHECK(!idx[0], EINVAL);
4437 instr->type = INSTR_METPREFETCH_I;
4438 instr->meter.metarray_id = m->id;
4439 instr->meter.idx_val = idx_val;
4444 instr_meter_translate(struct rte_swx_pipeline *p,
4445 struct action *action,
4448 struct instruction *instr,
4449 struct instruction_data *data __rte_unused)
4451 char *metarray = tokens[1], *idx = tokens[2], *length = tokens[3];
4452 char *color_in = tokens[4], *color_out = tokens[5];
4454 struct field *fidx, *flength, *fcin, *fcout;
4455 uint32_t idx_struct_id, length_struct_id;
4456 uint32_t color_in_struct_id, color_out_struct_id;
4458 CHECK(n_tokens == 6, EINVAL);
4460 m = metarray_find(p, metarray);
4463 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4465 flength = struct_field_parse(p, action, length, &length_struct_id);
4466 CHECK(flength, EINVAL);
4467 CHECK(!flength->var_size, EINVAL);
4469 fcin = struct_field_parse(p, action, color_in, &color_in_struct_id);
4471 fcout = struct_field_parse(p, NULL, color_out, &color_out_struct_id);
4472 CHECK(fcout, EINVAL);
4473 CHECK(!fcout->var_size, EINVAL);
4475 /* index = HMEFT, length = HMEFT, color_in = MEFT, color_out = MEF. */
4477 CHECK(!fidx->var_size, EINVAL);
4478 CHECK(!fcin->var_size, EINVAL);
4480 instr->type = INSTR_METER_MMM;
4481 if (idx[0] == 'h' && length[0] == 'h')
4482 instr->type = INSTR_METER_HHM;
4483 if (idx[0] == 'h' && length[0] != 'h')
4484 instr->type = INSTR_METER_HMM;
4485 if (idx[0] != 'h' && length[0] == 'h')
4486 instr->type = INSTR_METER_MHM;
4488 instr->meter.metarray_id = m->id;
4490 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4491 instr->meter.idx.n_bits = fidx->n_bits;
4492 instr->meter.idx.offset = fidx->offset / 8;
4494 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4495 instr->meter.length.n_bits = flength->n_bits;
4496 instr->meter.length.offset = flength->offset / 8;
4498 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
4499 instr->meter.color_in.n_bits = fcin->n_bits;
4500 instr->meter.color_in.offset = fcin->offset / 8;
4502 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4503 instr->meter.color_out.n_bits = fcout->n_bits;
4504 instr->meter.color_out.offset = fcout->offset / 8;
4509 /* index = HMEFT, length = HMEFT, color_in = I, color_out = MEF. */
4510 if (fidx && !fcin) {
4511 uint32_t color_in_val;
4513 CHECK(!fidx->var_size, EINVAL);
4515 color_in_val = strtoul(color_in, &color_in, 0);
4516 CHECK(!color_in[0], EINVAL);
4518 instr->type = INSTR_METER_MMI;
4519 if (idx[0] == 'h' && length[0] == 'h')
4520 instr->type = INSTR_METER_HHI;
4521 if (idx[0] == 'h' && length[0] != 'h')
4522 instr->type = INSTR_METER_HMI;
4523 if (idx[0] != 'h' && length[0] == 'h')
4524 instr->type = INSTR_METER_MHI;
4526 instr->meter.metarray_id = m->id;
4528 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4529 instr->meter.idx.n_bits = fidx->n_bits;
4530 instr->meter.idx.offset = fidx->offset / 8;
4532 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4533 instr->meter.length.n_bits = flength->n_bits;
4534 instr->meter.length.offset = flength->offset / 8;
4536 instr->meter.color_in_val = color_in_val;
4538 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4539 instr->meter.color_out.n_bits = fcout->n_bits;
4540 instr->meter.color_out.offset = fcout->offset / 8;
4545 /* index = I, length = HMEFT, color_in = MEFT, color_out = MEF. */
4546 if (!fidx && fcin) {
4549 idx_val = strtoul(idx, &idx, 0);
4550 CHECK(!idx[0], EINVAL);
4552 CHECK(!fcin->var_size, EINVAL);
4554 instr->type = INSTR_METER_IMM;
4555 if (length[0] == 'h')
4556 instr->type = INSTR_METER_IHM;
4558 instr->meter.metarray_id = m->id;
4560 instr->meter.idx_val = idx_val;
4562 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4563 instr->meter.length.n_bits = flength->n_bits;
4564 instr->meter.length.offset = flength->offset / 8;
4566 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
4567 instr->meter.color_in.n_bits = fcin->n_bits;
4568 instr->meter.color_in.offset = fcin->offset / 8;
4570 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4571 instr->meter.color_out.n_bits = fcout->n_bits;
4572 instr->meter.color_out.offset = fcout->offset / 8;
4577 /* index = I, length = HMEFT, color_in = I, color_out = MEF. */
4578 if (!fidx && !fcin) {
4579 uint32_t idx_val, color_in_val;
4581 idx_val = strtoul(idx, &idx, 0);
4582 CHECK(!idx[0], EINVAL);
4584 color_in_val = strtoul(color_in, &color_in, 0);
4585 CHECK(!color_in[0], EINVAL);
4587 instr->type = INSTR_METER_IMI;
4588 if (length[0] == 'h')
4589 instr->type = INSTR_METER_IHI;
4591 instr->meter.metarray_id = m->id;
4593 instr->meter.idx_val = idx_val;
4595 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4596 instr->meter.length.n_bits = flength->n_bits;
4597 instr->meter.length.offset = flength->offset / 8;
4599 instr->meter.color_in_val = color_in_val;
4601 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4602 instr->meter.color_out.n_bits = fcout->n_bits;
4603 instr->meter.color_out.offset = fcout->offset / 8;
4612 instr_metprefetch_h_exec(struct rte_swx_pipeline *p)
4614 struct thread *t = &p->threads[p->thread_id];
4615 struct instruction *ip = t->ip;
4618 __instr_metprefetch_h_exec(p, t, ip);
4625 instr_metprefetch_m_exec(struct rte_swx_pipeline *p)
4627 struct thread *t = &p->threads[p->thread_id];
4628 struct instruction *ip = t->ip;
4631 __instr_metprefetch_m_exec(p, t, ip);
4638 instr_metprefetch_i_exec(struct rte_swx_pipeline *p)
4640 struct thread *t = &p->threads[p->thread_id];
4641 struct instruction *ip = t->ip;
4644 __instr_metprefetch_i_exec(p, t, ip);
4651 instr_meter_hhm_exec(struct rte_swx_pipeline *p)
4653 struct thread *t = &p->threads[p->thread_id];
4654 struct instruction *ip = t->ip;
4657 __instr_meter_hhm_exec(p, t, ip);
4664 instr_meter_hhi_exec(struct rte_swx_pipeline *p)
4666 struct thread *t = &p->threads[p->thread_id];
4667 struct instruction *ip = t->ip;
4670 __instr_meter_hhi_exec(p, t, ip);
4677 instr_meter_hmm_exec(struct rte_swx_pipeline *p)
4679 struct thread *t = &p->threads[p->thread_id];
4680 struct instruction *ip = t->ip;
4683 __instr_meter_hmm_exec(p, t, ip);
4690 instr_meter_hmi_exec(struct rte_swx_pipeline *p)
4692 struct thread *t = &p->threads[p->thread_id];
4693 struct instruction *ip = t->ip;
4696 __instr_meter_hmi_exec(p, t, ip);
4703 instr_meter_mhm_exec(struct rte_swx_pipeline *p)
4705 struct thread *t = &p->threads[p->thread_id];
4706 struct instruction *ip = t->ip;
4709 __instr_meter_mhm_exec(p, t, ip);
4716 instr_meter_mhi_exec(struct rte_swx_pipeline *p)
4718 struct thread *t = &p->threads[p->thread_id];
4719 struct instruction *ip = t->ip;
4722 __instr_meter_mhi_exec(p, t, ip);
4729 instr_meter_mmm_exec(struct rte_swx_pipeline *p)
4731 struct thread *t = &p->threads[p->thread_id];
4732 struct instruction *ip = t->ip;
4735 __instr_meter_mmm_exec(p, t, ip);
4742 instr_meter_mmi_exec(struct rte_swx_pipeline *p)
4744 struct thread *t = &p->threads[p->thread_id];
4745 struct instruction *ip = t->ip;
4748 __instr_meter_mmi_exec(p, t, ip);
4755 instr_meter_ihm_exec(struct rte_swx_pipeline *p)
4757 struct thread *t = &p->threads[p->thread_id];
4758 struct instruction *ip = t->ip;
4761 __instr_meter_ihm_exec(p, t, ip);
4768 instr_meter_ihi_exec(struct rte_swx_pipeline *p)
4770 struct thread *t = &p->threads[p->thread_id];
4771 struct instruction *ip = t->ip;
4774 __instr_meter_ihi_exec(p, t, ip);
4781 instr_meter_imm_exec(struct rte_swx_pipeline *p)
4783 struct thread *t = &p->threads[p->thread_id];
4784 struct instruction *ip = t->ip;
4787 __instr_meter_imm_exec(p, t, ip);
4794 instr_meter_imi_exec(struct rte_swx_pipeline *p)
4796 struct thread *t = &p->threads[p->thread_id];
4797 struct instruction *ip = t->ip;
4800 __instr_meter_imi_exec(p, t, ip);
4810 instr_jmp_translate(struct rte_swx_pipeline *p __rte_unused,
4811 struct action *action __rte_unused,
4814 struct instruction *instr,
4815 struct instruction_data *data)
4817 CHECK(n_tokens == 2, EINVAL);
4819 strcpy(data->jmp_label, tokens[1]);
4821 instr->type = INSTR_JMP;
4822 instr->jmp.ip = NULL; /* Resolved later. */
4827 instr_jmp_valid_translate(struct rte_swx_pipeline *p,
4828 struct action *action __rte_unused,
4831 struct instruction *instr,
4832 struct instruction_data *data)
4836 CHECK(n_tokens == 3, EINVAL);
4838 strcpy(data->jmp_label, tokens[1]);
4840 h = header_parse(p, tokens[2]);
4843 instr->type = INSTR_JMP_VALID;
4844 instr->jmp.ip = NULL; /* Resolved later. */
4845 instr->jmp.header_id = h->id;
4850 instr_jmp_invalid_translate(struct rte_swx_pipeline *p,
4851 struct action *action __rte_unused,
4854 struct instruction *instr,
4855 struct instruction_data *data)
4859 CHECK(n_tokens == 3, EINVAL);
4861 strcpy(data->jmp_label, tokens[1]);
4863 h = header_parse(p, tokens[2]);
4866 instr->type = INSTR_JMP_INVALID;
4867 instr->jmp.ip = NULL; /* Resolved later. */
4868 instr->jmp.header_id = h->id;
4873 instr_jmp_hit_translate(struct rte_swx_pipeline *p __rte_unused,
4874 struct action *action,
4877 struct instruction *instr,
4878 struct instruction_data *data)
4880 CHECK(!action, EINVAL);
4881 CHECK(n_tokens == 2, EINVAL);
4883 strcpy(data->jmp_label, tokens[1]);
4885 instr->type = INSTR_JMP_HIT;
4886 instr->jmp.ip = NULL; /* Resolved later. */
4891 instr_jmp_miss_translate(struct rte_swx_pipeline *p __rte_unused,
4892 struct action *action,
4895 struct instruction *instr,
4896 struct instruction_data *data)
4898 CHECK(!action, EINVAL);
4899 CHECK(n_tokens == 2, EINVAL);
4901 strcpy(data->jmp_label, tokens[1]);
4903 instr->type = INSTR_JMP_MISS;
4904 instr->jmp.ip = NULL; /* Resolved later. */
4909 instr_jmp_action_hit_translate(struct rte_swx_pipeline *p,
4910 struct action *action,
4913 struct instruction *instr,
4914 struct instruction_data *data)
4918 CHECK(!action, EINVAL);
4919 CHECK(n_tokens == 3, EINVAL);
4921 strcpy(data->jmp_label, tokens[1]);
4923 a = action_find(p, tokens[2]);
4926 instr->type = INSTR_JMP_ACTION_HIT;
4927 instr->jmp.ip = NULL; /* Resolved later. */
4928 instr->jmp.action_id = a->id;
4933 instr_jmp_action_miss_translate(struct rte_swx_pipeline *p,
4934 struct action *action,
4937 struct instruction *instr,
4938 struct instruction_data *data)
4942 CHECK(!action, EINVAL);
4943 CHECK(n_tokens == 3, EINVAL);
4945 strcpy(data->jmp_label, tokens[1]);
4947 a = action_find(p, tokens[2]);
4950 instr->type = INSTR_JMP_ACTION_MISS;
4951 instr->jmp.ip = NULL; /* Resolved later. */
4952 instr->jmp.action_id = a->id;
4957 instr_jmp_eq_translate(struct rte_swx_pipeline *p,
4958 struct action *action,
4961 struct instruction *instr,
4962 struct instruction_data *data)
4964 char *a = tokens[2], *b = tokens[3];
4965 struct field *fa, *fb;
4967 uint32_t a_struct_id, b_struct_id;
4969 CHECK(n_tokens == 4, EINVAL);
4971 strcpy(data->jmp_label, tokens[1]);
4973 fa = struct_field_parse(p, action, a, &a_struct_id);
4975 CHECK(!fa->var_size, EINVAL);
4977 /* JMP_EQ, JMP_EQ_MH, JMP_EQ_HM, JMP_EQ_HH. */
4978 fb = struct_field_parse(p, action, b, &b_struct_id);
4980 CHECK(!fb->var_size, EINVAL);
4982 instr->type = INSTR_JMP_EQ;
4983 if (a[0] != 'h' && b[0] == 'h')
4984 instr->type = INSTR_JMP_EQ_MH;
4985 if (a[0] == 'h' && b[0] != 'h')
4986 instr->type = INSTR_JMP_EQ_HM;
4987 if (a[0] == 'h' && b[0] == 'h')
4988 instr->type = INSTR_JMP_EQ_HH;
4989 instr->jmp.ip = NULL; /* Resolved later. */
4991 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
4992 instr->jmp.a.n_bits = fa->n_bits;
4993 instr->jmp.a.offset = fa->offset / 8;
4994 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
4995 instr->jmp.b.n_bits = fb->n_bits;
4996 instr->jmp.b.offset = fb->offset / 8;
5001 b_val = strtoull(b, &b, 0);
5002 CHECK(!b[0], EINVAL);
5005 b_val = hton64(b_val) >> (64 - fa->n_bits);
5007 instr->type = INSTR_JMP_EQ_I;
5008 instr->jmp.ip = NULL; /* Resolved later. */
5009 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5010 instr->jmp.a.n_bits = fa->n_bits;
5011 instr->jmp.a.offset = fa->offset / 8;
5012 instr->jmp.b_val = b_val;
5017 instr_jmp_neq_translate(struct rte_swx_pipeline *p,
5018 struct action *action,
5021 struct instruction *instr,
5022 struct instruction_data *data)
5024 char *a = tokens[2], *b = tokens[3];
5025 struct field *fa, *fb;
5027 uint32_t a_struct_id, b_struct_id;
5029 CHECK(n_tokens == 4, EINVAL);
5031 strcpy(data->jmp_label, tokens[1]);
5033 fa = struct_field_parse(p, action, a, &a_struct_id);
5035 CHECK(!fa->var_size, EINVAL);
5037 /* JMP_NEQ, JMP_NEQ_MH, JMP_NEQ_HM, JMP_NEQ_HH. */
5038 fb = struct_field_parse(p, action, b, &b_struct_id);
5040 CHECK(!fb->var_size, EINVAL);
5042 instr->type = INSTR_JMP_NEQ;
5043 if (a[0] != 'h' && b[0] == 'h')
5044 instr->type = INSTR_JMP_NEQ_MH;
5045 if (a[0] == 'h' && b[0] != 'h')
5046 instr->type = INSTR_JMP_NEQ_HM;
5047 if (a[0] == 'h' && b[0] == 'h')
5048 instr->type = INSTR_JMP_NEQ_HH;
5049 instr->jmp.ip = NULL; /* Resolved later. */
5051 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5052 instr->jmp.a.n_bits = fa->n_bits;
5053 instr->jmp.a.offset = fa->offset / 8;
5054 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5055 instr->jmp.b.n_bits = fb->n_bits;
5056 instr->jmp.b.offset = fb->offset / 8;
5061 b_val = strtoull(b, &b, 0);
5062 CHECK(!b[0], EINVAL);
5065 b_val = hton64(b_val) >> (64 - fa->n_bits);
5067 instr->type = INSTR_JMP_NEQ_I;
5068 instr->jmp.ip = NULL; /* Resolved later. */
5069 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5070 instr->jmp.a.n_bits = fa->n_bits;
5071 instr->jmp.a.offset = fa->offset / 8;
5072 instr->jmp.b_val = b_val;
5077 instr_jmp_lt_translate(struct rte_swx_pipeline *p,
5078 struct action *action,
5081 struct instruction *instr,
5082 struct instruction_data *data)
5084 char *a = tokens[2], *b = tokens[3];
5085 struct field *fa, *fb;
5087 uint32_t a_struct_id, b_struct_id;
5089 CHECK(n_tokens == 4, EINVAL);
5091 strcpy(data->jmp_label, tokens[1]);
5093 fa = struct_field_parse(p, action, a, &a_struct_id);
5095 CHECK(!fa->var_size, EINVAL);
5097 /* JMP_LT, JMP_LT_MH, JMP_LT_HM, JMP_LT_HH. */
5098 fb = struct_field_parse(p, action, b, &b_struct_id);
5100 CHECK(!fb->var_size, EINVAL);
5102 instr->type = INSTR_JMP_LT;
5103 if (a[0] == 'h' && b[0] != 'h')
5104 instr->type = INSTR_JMP_LT_HM;
5105 if (a[0] != 'h' && b[0] == 'h')
5106 instr->type = INSTR_JMP_LT_MH;
5107 if (a[0] == 'h' && b[0] == 'h')
5108 instr->type = INSTR_JMP_LT_HH;
5109 instr->jmp.ip = NULL; /* Resolved later. */
5111 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5112 instr->jmp.a.n_bits = fa->n_bits;
5113 instr->jmp.a.offset = fa->offset / 8;
5114 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5115 instr->jmp.b.n_bits = fb->n_bits;
5116 instr->jmp.b.offset = fb->offset / 8;
5120 /* JMP_LT_MI, JMP_LT_HI. */
5121 b_val = strtoull(b, &b, 0);
5122 CHECK(!b[0], EINVAL);
5124 instr->type = INSTR_JMP_LT_MI;
5126 instr->type = INSTR_JMP_LT_HI;
5127 instr->jmp.ip = NULL; /* Resolved later. */
5129 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5130 instr->jmp.a.n_bits = fa->n_bits;
5131 instr->jmp.a.offset = fa->offset / 8;
5132 instr->jmp.b_val = b_val;
5137 instr_jmp_gt_translate(struct rte_swx_pipeline *p,
5138 struct action *action,
5141 struct instruction *instr,
5142 struct instruction_data *data)
5144 char *a = tokens[2], *b = tokens[3];
5145 struct field *fa, *fb;
5147 uint32_t a_struct_id, b_struct_id;
5149 CHECK(n_tokens == 4, EINVAL);
5151 strcpy(data->jmp_label, tokens[1]);
5153 fa = struct_field_parse(p, action, a, &a_struct_id);
5155 CHECK(!fa->var_size, EINVAL);
5157 /* JMP_GT, JMP_GT_MH, JMP_GT_HM, JMP_GT_HH. */
5158 fb = struct_field_parse(p, action, b, &b_struct_id);
5160 CHECK(!fb->var_size, EINVAL);
5162 instr->type = INSTR_JMP_GT;
5163 if (a[0] == 'h' && b[0] != 'h')
5164 instr->type = INSTR_JMP_GT_HM;
5165 if (a[0] != 'h' && b[0] == 'h')
5166 instr->type = INSTR_JMP_GT_MH;
5167 if (a[0] == 'h' && b[0] == 'h')
5168 instr->type = INSTR_JMP_GT_HH;
5169 instr->jmp.ip = NULL; /* Resolved later. */
5171 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5172 instr->jmp.a.n_bits = fa->n_bits;
5173 instr->jmp.a.offset = fa->offset / 8;
5174 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5175 instr->jmp.b.n_bits = fb->n_bits;
5176 instr->jmp.b.offset = fb->offset / 8;
5180 /* JMP_GT_MI, JMP_GT_HI. */
5181 b_val = strtoull(b, &b, 0);
5182 CHECK(!b[0], EINVAL);
5184 instr->type = INSTR_JMP_GT_MI;
5186 instr->type = INSTR_JMP_GT_HI;
5187 instr->jmp.ip = NULL; /* Resolved later. */
5189 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5190 instr->jmp.a.n_bits = fa->n_bits;
5191 instr->jmp.a.offset = fa->offset / 8;
5192 instr->jmp.b_val = b_val;
5197 instr_jmp_exec(struct rte_swx_pipeline *p)
5199 struct thread *t = &p->threads[p->thread_id];
5200 struct instruction *ip = t->ip;
5202 TRACE("[Thread %2u] jmp\n", p->thread_id);
5204 thread_ip_set(t, ip->jmp.ip);
5208 instr_jmp_valid_exec(struct rte_swx_pipeline *p)
5210 struct thread *t = &p->threads[p->thread_id];
5211 struct instruction *ip = t->ip;
5212 uint32_t header_id = ip->jmp.header_id;
5214 TRACE("[Thread %2u] jmpv\n", p->thread_id);
5216 t->ip = HEADER_VALID(t, header_id) ? ip->jmp.ip : (t->ip + 1);
5220 instr_jmp_invalid_exec(struct rte_swx_pipeline *p)
5222 struct thread *t = &p->threads[p->thread_id];
5223 struct instruction *ip = t->ip;
5224 uint32_t header_id = ip->jmp.header_id;
5226 TRACE("[Thread %2u] jmpnv\n", p->thread_id);
5228 t->ip = HEADER_VALID(t, header_id) ? (t->ip + 1) : ip->jmp.ip;
5232 instr_jmp_hit_exec(struct rte_swx_pipeline *p)
5234 struct thread *t = &p->threads[p->thread_id];
5235 struct instruction *ip = t->ip;
5236 struct instruction *ip_next[] = {t->ip + 1, ip->jmp.ip};
5238 TRACE("[Thread %2u] jmph\n", p->thread_id);
5240 t->ip = ip_next[t->hit];
5244 instr_jmp_miss_exec(struct rte_swx_pipeline *p)
5246 struct thread *t = &p->threads[p->thread_id];
5247 struct instruction *ip = t->ip;
5248 struct instruction *ip_next[] = {ip->jmp.ip, t->ip + 1};
5250 TRACE("[Thread %2u] jmpnh\n", p->thread_id);
5252 t->ip = ip_next[t->hit];
5256 instr_jmp_action_hit_exec(struct rte_swx_pipeline *p)
5258 struct thread *t = &p->threads[p->thread_id];
5259 struct instruction *ip = t->ip;
5261 TRACE("[Thread %2u] jmpa\n", p->thread_id);
5263 t->ip = (ip->jmp.action_id == t->action_id) ? ip->jmp.ip : (t->ip + 1);
5267 instr_jmp_action_miss_exec(struct rte_swx_pipeline *p)
5269 struct thread *t = &p->threads[p->thread_id];
5270 struct instruction *ip = t->ip;
5272 TRACE("[Thread %2u] jmpna\n", p->thread_id);
5274 t->ip = (ip->jmp.action_id == t->action_id) ? (t->ip + 1) : ip->jmp.ip;
5278 instr_jmp_eq_exec(struct rte_swx_pipeline *p)
5280 struct thread *t = &p->threads[p->thread_id];
5281 struct instruction *ip = t->ip;
5283 TRACE("[Thread %2u] jmpeq\n", p->thread_id);
5289 instr_jmp_eq_mh_exec(struct rte_swx_pipeline *p)
5291 struct thread *t = &p->threads[p->thread_id];
5292 struct instruction *ip = t->ip;
5294 TRACE("[Thread %2u] jmpeq (mh)\n", p->thread_id);
5296 JMP_CMP_MH(t, ip, ==);
5300 instr_jmp_eq_hm_exec(struct rte_swx_pipeline *p)
5302 struct thread *t = &p->threads[p->thread_id];
5303 struct instruction *ip = t->ip;
5305 TRACE("[Thread %2u] jmpeq (hm)\n", p->thread_id);
5307 JMP_CMP_HM(t, ip, ==);
5311 instr_jmp_eq_hh_exec(struct rte_swx_pipeline *p)
5313 struct thread *t = &p->threads[p->thread_id];
5314 struct instruction *ip = t->ip;
5316 TRACE("[Thread %2u] jmpeq (hh)\n", p->thread_id);
5318 JMP_CMP_HH_FAST(t, ip, ==);
5322 instr_jmp_eq_i_exec(struct rte_swx_pipeline *p)
5324 struct thread *t = &p->threads[p->thread_id];
5325 struct instruction *ip = t->ip;
5327 TRACE("[Thread %2u] jmpeq (i)\n", p->thread_id);
5329 JMP_CMP_I(t, ip, ==);
5333 instr_jmp_neq_exec(struct rte_swx_pipeline *p)
5335 struct thread *t = &p->threads[p->thread_id];
5336 struct instruction *ip = t->ip;
5338 TRACE("[Thread %2u] jmpneq\n", p->thread_id);
5344 instr_jmp_neq_mh_exec(struct rte_swx_pipeline *p)
5346 struct thread *t = &p->threads[p->thread_id];
5347 struct instruction *ip = t->ip;
5349 TRACE("[Thread %2u] jmpneq (mh)\n", p->thread_id);
5351 JMP_CMP_MH(t, ip, !=);
5355 instr_jmp_neq_hm_exec(struct rte_swx_pipeline *p)
5357 struct thread *t = &p->threads[p->thread_id];
5358 struct instruction *ip = t->ip;
5360 TRACE("[Thread %2u] jmpneq (hm)\n", p->thread_id);
5362 JMP_CMP_HM(t, ip, !=);
5366 instr_jmp_neq_hh_exec(struct rte_swx_pipeline *p)
5368 struct thread *t = &p->threads[p->thread_id];
5369 struct instruction *ip = t->ip;
5371 TRACE("[Thread %2u] jmpneq (hh)\n", p->thread_id);
5373 JMP_CMP_HH_FAST(t, ip, !=);
5377 instr_jmp_neq_i_exec(struct rte_swx_pipeline *p)
5379 struct thread *t = &p->threads[p->thread_id];
5380 struct instruction *ip = t->ip;
5382 TRACE("[Thread %2u] jmpneq (i)\n", p->thread_id);
5384 JMP_CMP_I(t, ip, !=);
5388 instr_jmp_lt_exec(struct rte_swx_pipeline *p)
5390 struct thread *t = &p->threads[p->thread_id];
5391 struct instruction *ip = t->ip;
5393 TRACE("[Thread %2u] jmplt\n", p->thread_id);
5399 instr_jmp_lt_mh_exec(struct rte_swx_pipeline *p)
5401 struct thread *t = &p->threads[p->thread_id];
5402 struct instruction *ip = t->ip;
5404 TRACE("[Thread %2u] jmplt (mh)\n", p->thread_id);
5406 JMP_CMP_MH(t, ip, <);
5410 instr_jmp_lt_hm_exec(struct rte_swx_pipeline *p)
5412 struct thread *t = &p->threads[p->thread_id];
5413 struct instruction *ip = t->ip;
5415 TRACE("[Thread %2u] jmplt (hm)\n", p->thread_id);
5417 JMP_CMP_HM(t, ip, <);
5421 instr_jmp_lt_hh_exec(struct rte_swx_pipeline *p)
5423 struct thread *t = &p->threads[p->thread_id];
5424 struct instruction *ip = t->ip;
5426 TRACE("[Thread %2u] jmplt (hh)\n", p->thread_id);
5428 JMP_CMP_HH(t, ip, <);
5432 instr_jmp_lt_mi_exec(struct rte_swx_pipeline *p)
5434 struct thread *t = &p->threads[p->thread_id];
5435 struct instruction *ip = t->ip;
5437 TRACE("[Thread %2u] jmplt (mi)\n", p->thread_id);
5439 JMP_CMP_MI(t, ip, <);
5443 instr_jmp_lt_hi_exec(struct rte_swx_pipeline *p)
5445 struct thread *t = &p->threads[p->thread_id];
5446 struct instruction *ip = t->ip;
5448 TRACE("[Thread %2u] jmplt (hi)\n", p->thread_id);
5450 JMP_CMP_HI(t, ip, <);
5454 instr_jmp_gt_exec(struct rte_swx_pipeline *p)
5456 struct thread *t = &p->threads[p->thread_id];
5457 struct instruction *ip = t->ip;
5459 TRACE("[Thread %2u] jmpgt\n", p->thread_id);
5465 instr_jmp_gt_mh_exec(struct rte_swx_pipeline *p)
5467 struct thread *t = &p->threads[p->thread_id];
5468 struct instruction *ip = t->ip;
5470 TRACE("[Thread %2u] jmpgt (mh)\n", p->thread_id);
5472 JMP_CMP_MH(t, ip, >);
5476 instr_jmp_gt_hm_exec(struct rte_swx_pipeline *p)
5478 struct thread *t = &p->threads[p->thread_id];
5479 struct instruction *ip = t->ip;
5481 TRACE("[Thread %2u] jmpgt (hm)\n", p->thread_id);
5483 JMP_CMP_HM(t, ip, >);
5487 instr_jmp_gt_hh_exec(struct rte_swx_pipeline *p)
5489 struct thread *t = &p->threads[p->thread_id];
5490 struct instruction *ip = t->ip;
5492 TRACE("[Thread %2u] jmpgt (hh)\n", p->thread_id);
5494 JMP_CMP_HH(t, ip, >);
5498 instr_jmp_gt_mi_exec(struct rte_swx_pipeline *p)
5500 struct thread *t = &p->threads[p->thread_id];
5501 struct instruction *ip = t->ip;
5503 TRACE("[Thread %2u] jmpgt (mi)\n", p->thread_id);
5505 JMP_CMP_MI(t, ip, >);
5509 instr_jmp_gt_hi_exec(struct rte_swx_pipeline *p)
5511 struct thread *t = &p->threads[p->thread_id];
5512 struct instruction *ip = t->ip;
5514 TRACE("[Thread %2u] jmpgt (hi)\n", p->thread_id);
5516 JMP_CMP_HI(t, ip, >);
5523 instr_return_translate(struct rte_swx_pipeline *p __rte_unused,
5524 struct action *action,
5525 char **tokens __rte_unused,
5527 struct instruction *instr,
5528 struct instruction_data *data __rte_unused)
5530 CHECK(action, EINVAL);
5531 CHECK(n_tokens == 1, EINVAL);
5533 instr->type = INSTR_RETURN;
5538 instr_return_exec(struct rte_swx_pipeline *p)
5540 struct thread *t = &p->threads[p->thread_id];
5542 TRACE("[Thread %2u] return\n", p->thread_id);
5548 instr_translate(struct rte_swx_pipeline *p,
5549 struct action *action,
5551 struct instruction *instr,
5552 struct instruction_data *data)
5554 char *tokens[RTE_SWX_INSTRUCTION_TOKENS_MAX];
5555 int n_tokens = 0, tpos = 0;
5557 /* Parse the instruction string into tokens. */
5561 token = strtok_r(string, " \t\v", &string);
5565 CHECK(n_tokens < RTE_SWX_INSTRUCTION_TOKENS_MAX, EINVAL);
5566 CHECK_NAME(token, EINVAL);
5568 tokens[n_tokens] = token;
5572 CHECK(n_tokens, EINVAL);
5574 /* Handle the optional instruction label. */
5575 if ((n_tokens >= 2) && !strcmp(tokens[1], ":")) {
5576 strcpy(data->label, tokens[0]);
5579 CHECK(n_tokens - tpos, EINVAL);
5582 /* Identify the instruction type. */
5583 if (!strcmp(tokens[tpos], "rx"))
5584 return instr_rx_translate(p,
5591 if (!strcmp(tokens[tpos], "tx"))
5592 return instr_tx_translate(p,
5599 if (!strcmp(tokens[tpos], "drop"))
5600 return instr_drop_translate(p,
5607 if (!strcmp(tokens[tpos], "extract"))
5608 return instr_hdr_extract_translate(p,
5615 if (!strcmp(tokens[tpos], "lookahead"))
5616 return instr_hdr_lookahead_translate(p,
5623 if (!strcmp(tokens[tpos], "emit"))
5624 return instr_hdr_emit_translate(p,
5631 if (!strcmp(tokens[tpos], "validate"))
5632 return instr_hdr_validate_translate(p,
5639 if (!strcmp(tokens[tpos], "invalidate"))
5640 return instr_hdr_invalidate_translate(p,
5647 if (!strcmp(tokens[tpos], "mov"))
5648 return instr_mov_translate(p,
5655 if (!strcmp(tokens[tpos], "add"))
5656 return instr_alu_add_translate(p,
5663 if (!strcmp(tokens[tpos], "sub"))
5664 return instr_alu_sub_translate(p,
5671 if (!strcmp(tokens[tpos], "ckadd"))
5672 return instr_alu_ckadd_translate(p,
5679 if (!strcmp(tokens[tpos], "cksub"))
5680 return instr_alu_cksub_translate(p,
5687 if (!strcmp(tokens[tpos], "and"))
5688 return instr_alu_and_translate(p,
5695 if (!strcmp(tokens[tpos], "or"))
5696 return instr_alu_or_translate(p,
5703 if (!strcmp(tokens[tpos], "xor"))
5704 return instr_alu_xor_translate(p,
5711 if (!strcmp(tokens[tpos], "shl"))
5712 return instr_alu_shl_translate(p,
5719 if (!strcmp(tokens[tpos], "shr"))
5720 return instr_alu_shr_translate(p,
5727 if (!strcmp(tokens[tpos], "regprefetch"))
5728 return instr_regprefetch_translate(p,
5735 if (!strcmp(tokens[tpos], "regrd"))
5736 return instr_regrd_translate(p,
5743 if (!strcmp(tokens[tpos], "regwr"))
5744 return instr_regwr_translate(p,
5751 if (!strcmp(tokens[tpos], "regadd"))
5752 return instr_regadd_translate(p,
5759 if (!strcmp(tokens[tpos], "metprefetch"))
5760 return instr_metprefetch_translate(p,
5767 if (!strcmp(tokens[tpos], "meter"))
5768 return instr_meter_translate(p,
5775 if (!strcmp(tokens[tpos], "table"))
5776 return instr_table_translate(p,
5783 if (!strcmp(tokens[tpos], "learn"))
5784 return instr_learn_translate(p,
5791 if (!strcmp(tokens[tpos], "forget"))
5792 return instr_forget_translate(p,
5799 if (!strcmp(tokens[tpos], "extern"))
5800 return instr_extern_translate(p,
5807 if (!strcmp(tokens[tpos], "jmp"))
5808 return instr_jmp_translate(p,
5815 if (!strcmp(tokens[tpos], "jmpv"))
5816 return instr_jmp_valid_translate(p,
5823 if (!strcmp(tokens[tpos], "jmpnv"))
5824 return instr_jmp_invalid_translate(p,
5831 if (!strcmp(tokens[tpos], "jmph"))
5832 return instr_jmp_hit_translate(p,
5839 if (!strcmp(tokens[tpos], "jmpnh"))
5840 return instr_jmp_miss_translate(p,
5847 if (!strcmp(tokens[tpos], "jmpa"))
5848 return instr_jmp_action_hit_translate(p,
5855 if (!strcmp(tokens[tpos], "jmpna"))
5856 return instr_jmp_action_miss_translate(p,
5863 if (!strcmp(tokens[tpos], "jmpeq"))
5864 return instr_jmp_eq_translate(p,
5871 if (!strcmp(tokens[tpos], "jmpneq"))
5872 return instr_jmp_neq_translate(p,
5879 if (!strcmp(tokens[tpos], "jmplt"))
5880 return instr_jmp_lt_translate(p,
5887 if (!strcmp(tokens[tpos], "jmpgt"))
5888 return instr_jmp_gt_translate(p,
5895 if (!strcmp(tokens[tpos], "return"))
5896 return instr_return_translate(p,
5906 static struct instruction_data *
5907 label_find(struct instruction_data *data, uint32_t n, const char *label)
5911 for (i = 0; i < n; i++)
5912 if (!strcmp(label, data[i].label))
5919 label_is_used(struct instruction_data *data, uint32_t n, const char *label)
5921 uint32_t count = 0, i;
5926 for (i = 0; i < n; i++)
5927 if (!strcmp(label, data[i].jmp_label))
5934 instr_label_check(struct instruction_data *instruction_data,
5935 uint32_t n_instructions)
5939 /* Check that all instruction labels are unique. */
5940 for (i = 0; i < n_instructions; i++) {
5941 struct instruction_data *data = &instruction_data[i];
5942 char *label = data->label;
5948 for (j = i + 1; j < n_instructions; j++)
5949 CHECK(strcmp(label, data[j].label), EINVAL);
5952 /* Get users for each instruction label. */
5953 for (i = 0; i < n_instructions; i++) {
5954 struct instruction_data *data = &instruction_data[i];
5955 char *label = data->label;
5957 data->n_users = label_is_used(instruction_data,
5966 instr_jmp_resolve(struct instruction *instructions,
5967 struct instruction_data *instruction_data,
5968 uint32_t n_instructions)
5972 for (i = 0; i < n_instructions; i++) {
5973 struct instruction *instr = &instructions[i];
5974 struct instruction_data *data = &instruction_data[i];
5975 struct instruction_data *found;
5977 if (!instruction_is_jmp(instr))
5980 found = label_find(instruction_data,
5983 CHECK(found, EINVAL);
5985 instr->jmp.ip = &instructions[found - instruction_data];
5992 instr_verify(struct rte_swx_pipeline *p __rte_unused,
5994 struct instruction *instr,
5995 struct instruction_data *data __rte_unused,
5996 uint32_t n_instructions)
5999 enum instruction_type type;
6002 /* Check that the first instruction is rx. */
6003 CHECK(instr[0].type == INSTR_RX, EINVAL);
6005 /* Check that there is at least one tx instruction. */
6006 for (i = 0; i < n_instructions; i++) {
6007 type = instr[i].type;
6009 if (instruction_is_tx(type))
6012 CHECK(i < n_instructions, EINVAL);
6014 /* Check that the last instruction is either tx or unconditional
6017 type = instr[n_instructions - 1].type;
6018 CHECK(instruction_is_tx(type) || (type == INSTR_JMP), EINVAL);
6022 enum instruction_type type;
6025 /* Check that there is at least one return or tx instruction. */
6026 for (i = 0; i < n_instructions; i++) {
6027 type = instr[i].type;
6029 if ((type == INSTR_RETURN) || instruction_is_tx(type))
6032 CHECK(i < n_instructions, EINVAL);
6039 instr_compact(struct instruction *instructions,
6040 struct instruction_data *instruction_data,
6041 uint32_t n_instructions)
6043 uint32_t i, pos = 0;
6045 /* Eliminate the invalid instructions that have been optimized out. */
6046 for (i = 0; i < n_instructions; i++) {
6047 struct instruction *instr = &instructions[i];
6048 struct instruction_data *data = &instruction_data[i];
6054 memcpy(&instructions[pos], instr, sizeof(*instr));
6055 memcpy(&instruction_data[pos], data, sizeof(*data));
6065 instr_pattern_extract_many_search(struct instruction *instr,
6066 struct instruction_data *data,
6068 uint32_t *n_pattern_instr)
6072 for (i = 0; i < n_instr; i++) {
6073 if (data[i].invalid)
6076 if (instr[i].type != INSTR_HDR_EXTRACT)
6079 if (i == RTE_DIM(instr->io.hdr.header_id))
6082 if (i && data[i].n_users)
6089 *n_pattern_instr = i;
6094 instr_pattern_extract_many_replace(struct instruction *instr,
6095 struct instruction_data *data,
6100 for (i = 1; i < n_instr; i++) {
6102 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
6103 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
6104 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
6106 data[i].invalid = 1;
6111 instr_pattern_extract_many_optimize(struct instruction *instructions,
6112 struct instruction_data *instruction_data,
6113 uint32_t n_instructions)
6117 for (i = 0; i < n_instructions; ) {
6118 struct instruction *instr = &instructions[i];
6119 struct instruction_data *data = &instruction_data[i];
6120 uint32_t n_instr = 0;
6124 detected = instr_pattern_extract_many_search(instr,
6129 instr_pattern_extract_many_replace(instr,
6136 /* No pattern starting at the current instruction. */
6140 /* Eliminate the invalid instructions that have been optimized out. */
6141 n_instructions = instr_compact(instructions,
6145 return n_instructions;
6149 instr_pattern_emit_many_tx_search(struct instruction *instr,
6150 struct instruction_data *data,
6152 uint32_t *n_pattern_instr)
6156 for (i = 0; i < n_instr; i++) {
6157 if (data[i].invalid)
6160 if (instr[i].type != INSTR_HDR_EMIT)
6163 if (i == RTE_DIM(instr->io.hdr.header_id))
6166 if (i && data[i].n_users)
6173 if (!instruction_is_tx(instr[i].type))
6176 if (data[i].n_users)
6181 *n_pattern_instr = i;
6186 instr_pattern_emit_many_tx_replace(struct instruction *instr,
6187 struct instruction_data *data,
6192 /* Any emit instruction in addition to the first one. */
6193 for (i = 1; i < n_instr - 1; i++) {
6195 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
6196 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
6197 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
6199 data[i].invalid = 1;
6202 /* The TX instruction is the last one in the pattern. */
6204 instr[0].io.io.offset = instr[i].io.io.offset;
6205 instr[0].io.io.n_bits = instr[i].io.io.n_bits;
6206 data[i].invalid = 1;
6210 instr_pattern_emit_many_tx_optimize(struct instruction *instructions,
6211 struct instruction_data *instruction_data,
6212 uint32_t n_instructions)
6216 for (i = 0; i < n_instructions; ) {
6217 struct instruction *instr = &instructions[i];
6218 struct instruction_data *data = &instruction_data[i];
6219 uint32_t n_instr = 0;
6222 /* Emit many + TX. */
6223 detected = instr_pattern_emit_many_tx_search(instr,
6228 instr_pattern_emit_many_tx_replace(instr,
6235 /* No pattern starting at the current instruction. */
6239 /* Eliminate the invalid instructions that have been optimized out. */
6240 n_instructions = instr_compact(instructions,
6244 return n_instructions;
6248 action_arg_src_mov_count(struct action *a,
6250 struct instruction *instructions,
6251 struct instruction_data *instruction_data,
6252 uint32_t n_instructions);
6255 instr_pattern_mov_all_validate_search(struct rte_swx_pipeline *p,
6257 struct instruction *instr,
6258 struct instruction_data *data,
6260 struct instruction *instructions,
6261 struct instruction_data *instruction_data,
6262 uint32_t n_instructions,
6263 uint32_t *n_pattern_instr)
6266 uint32_t src_field_id, i, j;
6268 /* Prerequisites. */
6272 /* First instruction: MOV_HM. */
6273 if (data[0].invalid || (instr[0].type != INSTR_MOV_HM))
6276 h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
6277 if (!h || h->st->var_size)
6280 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
6281 if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
6284 if (src_field_id == a->st->n_fields)
6287 if (instr[0].mov.dst.offset ||
6288 (instr[0].mov.dst.n_bits != h->st->fields[0].n_bits) ||
6289 instr[0].mov.src.struct_id ||
6290 (instr[0].mov.src.n_bits != a->st->fields[src_field_id].n_bits) ||
6291 (instr[0].mov.dst.n_bits != instr[0].mov.src.n_bits))
6294 if ((n_instr < h->st->n_fields + 1) ||
6295 (a->st->n_fields < src_field_id + h->st->n_fields + 1))
6298 /* Subsequent instructions: MOV_HM. */
6299 for (i = 1; i < h->st->n_fields; i++)
6300 if (data[i].invalid ||
6302 (instr[i].type != INSTR_MOV_HM) ||
6303 (instr[i].mov.dst.struct_id != h->struct_id) ||
6304 (instr[i].mov.dst.offset != h->st->fields[i].offset / 8) ||
6305 (instr[i].mov.dst.n_bits != h->st->fields[i].n_bits) ||
6306 instr[i].mov.src.struct_id ||
6307 (instr[i].mov.src.offset != a->st->fields[src_field_id + i].offset / 8) ||
6308 (instr[i].mov.src.n_bits != a->st->fields[src_field_id + i].n_bits) ||
6309 (instr[i].mov.dst.n_bits != instr[i].mov.src.n_bits))
6312 /* Last instruction: HDR_VALIDATE. */
6313 if ((instr[i].type != INSTR_HDR_VALIDATE) ||
6314 (instr[i].valid.header_id != h->id))
6317 /* Check that none of the action args that are used as source for this
6318 * DMA transfer are not used as source in any other mov instruction.
6320 for (j = src_field_id; j < src_field_id + h->st->n_fields; j++) {
6323 n_users = action_arg_src_mov_count(a,
6332 *n_pattern_instr = 1 + i;
6337 instr_pattern_mov_all_validate_replace(struct rte_swx_pipeline *p,
6339 struct instruction *instr,
6340 struct instruction_data *data,
6344 uint32_t src_field_id, src_offset, i;
6346 /* Read from the instructions before they are modified. */
6347 h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
6351 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
6352 if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
6355 if (src_field_id == a->st->n_fields)
6358 src_offset = instr[0].mov.src.offset;
6360 /* Modify the instructions. */
6361 instr[0].type = INSTR_DMA_HT;
6362 instr[0].dma.dst.header_id[0] = h->id;
6363 instr[0].dma.dst.struct_id[0] = h->struct_id;
6364 instr[0].dma.src.offset[0] = (uint8_t)src_offset;
6365 instr[0].dma.n_bytes[0] = h->st->n_bits / 8;
6367 for (i = 1; i < n_instr; i++)
6368 data[i].invalid = 1;
6370 /* Update the endianness of the action arguments to header endianness. */
6371 for (i = 0; i < h->st->n_fields; i++)
6372 a->args_endianness[src_field_id + i] = 1;
6376 instr_pattern_mov_all_validate_optimize(struct rte_swx_pipeline *p,
6378 struct instruction *instructions,
6379 struct instruction_data *instruction_data,
6380 uint32_t n_instructions)
6385 return n_instructions;
6387 for (i = 0; i < n_instructions; ) {
6388 struct instruction *instr = &instructions[i];
6389 struct instruction_data *data = &instruction_data[i];
6390 uint32_t n_instr = 0;
6393 /* Mov all + validate. */
6394 detected = instr_pattern_mov_all_validate_search(p,
6404 instr_pattern_mov_all_validate_replace(p, a, instr, data, n_instr);
6409 /* No pattern starting at the current instruction. */
6413 /* Eliminate the invalid instructions that have been optimized out. */
6414 n_instructions = instr_compact(instructions,
6418 return n_instructions;
6422 instr_pattern_dma_many_search(struct instruction *instr,
6423 struct instruction_data *data,
6425 uint32_t *n_pattern_instr)
6429 for (i = 0; i < n_instr; i++) {
6430 if (data[i].invalid)
6433 if (instr[i].type != INSTR_DMA_HT)
6436 if (i == RTE_DIM(instr->dma.dst.header_id))
6439 if (i && data[i].n_users)
6446 *n_pattern_instr = i;
6451 instr_pattern_dma_many_replace(struct instruction *instr,
6452 struct instruction_data *data,
6457 for (i = 1; i < n_instr; i++) {
6459 instr[0].dma.dst.header_id[i] = instr[i].dma.dst.header_id[0];
6460 instr[0].dma.dst.struct_id[i] = instr[i].dma.dst.struct_id[0];
6461 instr[0].dma.src.offset[i] = instr[i].dma.src.offset[0];
6462 instr[0].dma.n_bytes[i] = instr[i].dma.n_bytes[0];
6464 data[i].invalid = 1;
6469 instr_pattern_dma_many_optimize(struct instruction *instructions,
6470 struct instruction_data *instruction_data,
6471 uint32_t n_instructions)
6475 for (i = 0; i < n_instructions; ) {
6476 struct instruction *instr = &instructions[i];
6477 struct instruction_data *data = &instruction_data[i];
6478 uint32_t n_instr = 0;
6482 detected = instr_pattern_dma_many_search(instr,
6487 instr_pattern_dma_many_replace(instr, data, n_instr);
6492 /* No pattern starting at the current instruction. */
6496 /* Eliminate the invalid instructions that have been optimized out. */
6497 n_instructions = instr_compact(instructions,
6501 return n_instructions;
6505 instr_optimize(struct rte_swx_pipeline *p,
6507 struct instruction *instructions,
6508 struct instruction_data *instruction_data,
6509 uint32_t n_instructions)
6512 n_instructions = instr_pattern_extract_many_optimize(instructions,
6516 /* Emit many + TX. */
6517 n_instructions = instr_pattern_emit_many_tx_optimize(instructions,
6521 /* Mov all + validate. */
6522 n_instructions = instr_pattern_mov_all_validate_optimize(p,
6529 n_instructions = instr_pattern_dma_many_optimize(instructions,
6533 return n_instructions;
6537 instruction_config(struct rte_swx_pipeline *p,
6539 const char **instructions,
6540 uint32_t n_instructions)
6542 struct instruction *instr = NULL;
6543 struct instruction_data *data = NULL;
6547 CHECK(n_instructions, EINVAL);
6548 CHECK(instructions, EINVAL);
6549 for (i = 0; i < n_instructions; i++)
6550 CHECK_INSTRUCTION(instructions[i], EINVAL);
6552 /* Memory allocation. */
6553 instr = calloc(n_instructions, sizeof(struct instruction));
6559 data = calloc(n_instructions, sizeof(struct instruction_data));
6565 for (i = 0; i < n_instructions; i++) {
6566 char *string = strdup(instructions[i]);
6572 err = instr_translate(p, a, string, &instr[i], &data[i]);
6581 err = instr_label_check(data, n_instructions);
6585 err = instr_verify(p, a, instr, data, n_instructions);
6589 n_instructions = instr_optimize(p, a, instr, data, n_instructions);
6591 err = instr_jmp_resolve(instr, data, n_instructions);
6596 a->instructions = instr;
6597 a->instruction_data = data;
6598 a->n_instructions = n_instructions;
6600 p->instructions = instr;
6601 p->instruction_data = data;
6602 p->n_instructions = n_instructions;
6613 static instr_exec_t instruction_table[] = {
6614 [INSTR_RX] = instr_rx_exec,
6615 [INSTR_TX] = instr_tx_exec,
6616 [INSTR_TX_I] = instr_tx_i_exec,
6618 [INSTR_HDR_EXTRACT] = instr_hdr_extract_exec,
6619 [INSTR_HDR_EXTRACT2] = instr_hdr_extract2_exec,
6620 [INSTR_HDR_EXTRACT3] = instr_hdr_extract3_exec,
6621 [INSTR_HDR_EXTRACT4] = instr_hdr_extract4_exec,
6622 [INSTR_HDR_EXTRACT5] = instr_hdr_extract5_exec,
6623 [INSTR_HDR_EXTRACT6] = instr_hdr_extract6_exec,
6624 [INSTR_HDR_EXTRACT7] = instr_hdr_extract7_exec,
6625 [INSTR_HDR_EXTRACT8] = instr_hdr_extract8_exec,
6626 [INSTR_HDR_EXTRACT_M] = instr_hdr_extract_m_exec,
6627 [INSTR_HDR_LOOKAHEAD] = instr_hdr_lookahead_exec,
6629 [INSTR_HDR_EMIT] = instr_hdr_emit_exec,
6630 [INSTR_HDR_EMIT_TX] = instr_hdr_emit_tx_exec,
6631 [INSTR_HDR_EMIT2_TX] = instr_hdr_emit2_tx_exec,
6632 [INSTR_HDR_EMIT3_TX] = instr_hdr_emit3_tx_exec,
6633 [INSTR_HDR_EMIT4_TX] = instr_hdr_emit4_tx_exec,
6634 [INSTR_HDR_EMIT5_TX] = instr_hdr_emit5_tx_exec,
6635 [INSTR_HDR_EMIT6_TX] = instr_hdr_emit6_tx_exec,
6636 [INSTR_HDR_EMIT7_TX] = instr_hdr_emit7_tx_exec,
6637 [INSTR_HDR_EMIT8_TX] = instr_hdr_emit8_tx_exec,
6639 [INSTR_HDR_VALIDATE] = instr_hdr_validate_exec,
6640 [INSTR_HDR_INVALIDATE] = instr_hdr_invalidate_exec,
6642 [INSTR_MOV] = instr_mov_exec,
6643 [INSTR_MOV_MH] = instr_mov_mh_exec,
6644 [INSTR_MOV_HM] = instr_mov_hm_exec,
6645 [INSTR_MOV_HH] = instr_mov_hh_exec,
6646 [INSTR_MOV_I] = instr_mov_i_exec,
6648 [INSTR_DMA_HT] = instr_dma_ht_exec,
6649 [INSTR_DMA_HT2] = instr_dma_ht2_exec,
6650 [INSTR_DMA_HT3] = instr_dma_ht3_exec,
6651 [INSTR_DMA_HT4] = instr_dma_ht4_exec,
6652 [INSTR_DMA_HT5] = instr_dma_ht5_exec,
6653 [INSTR_DMA_HT6] = instr_dma_ht6_exec,
6654 [INSTR_DMA_HT7] = instr_dma_ht7_exec,
6655 [INSTR_DMA_HT8] = instr_dma_ht8_exec,
6657 [INSTR_ALU_ADD] = instr_alu_add_exec,
6658 [INSTR_ALU_ADD_MH] = instr_alu_add_mh_exec,
6659 [INSTR_ALU_ADD_HM] = instr_alu_add_hm_exec,
6660 [INSTR_ALU_ADD_HH] = instr_alu_add_hh_exec,
6661 [INSTR_ALU_ADD_MI] = instr_alu_add_mi_exec,
6662 [INSTR_ALU_ADD_HI] = instr_alu_add_hi_exec,
6664 [INSTR_ALU_SUB] = instr_alu_sub_exec,
6665 [INSTR_ALU_SUB_MH] = instr_alu_sub_mh_exec,
6666 [INSTR_ALU_SUB_HM] = instr_alu_sub_hm_exec,
6667 [INSTR_ALU_SUB_HH] = instr_alu_sub_hh_exec,
6668 [INSTR_ALU_SUB_MI] = instr_alu_sub_mi_exec,
6669 [INSTR_ALU_SUB_HI] = instr_alu_sub_hi_exec,
6671 [INSTR_ALU_CKADD_FIELD] = instr_alu_ckadd_field_exec,
6672 [INSTR_ALU_CKADD_STRUCT] = instr_alu_ckadd_struct_exec,
6673 [INSTR_ALU_CKADD_STRUCT20] = instr_alu_ckadd_struct20_exec,
6674 [INSTR_ALU_CKSUB_FIELD] = instr_alu_cksub_field_exec,
6676 [INSTR_ALU_AND] = instr_alu_and_exec,
6677 [INSTR_ALU_AND_MH] = instr_alu_and_mh_exec,
6678 [INSTR_ALU_AND_HM] = instr_alu_and_hm_exec,
6679 [INSTR_ALU_AND_HH] = instr_alu_and_hh_exec,
6680 [INSTR_ALU_AND_I] = instr_alu_and_i_exec,
6682 [INSTR_ALU_OR] = instr_alu_or_exec,
6683 [INSTR_ALU_OR_MH] = instr_alu_or_mh_exec,
6684 [INSTR_ALU_OR_HM] = instr_alu_or_hm_exec,
6685 [INSTR_ALU_OR_HH] = instr_alu_or_hh_exec,
6686 [INSTR_ALU_OR_I] = instr_alu_or_i_exec,
6688 [INSTR_ALU_XOR] = instr_alu_xor_exec,
6689 [INSTR_ALU_XOR_MH] = instr_alu_xor_mh_exec,
6690 [INSTR_ALU_XOR_HM] = instr_alu_xor_hm_exec,
6691 [INSTR_ALU_XOR_HH] = instr_alu_xor_hh_exec,
6692 [INSTR_ALU_XOR_I] = instr_alu_xor_i_exec,
6694 [INSTR_ALU_SHL] = instr_alu_shl_exec,
6695 [INSTR_ALU_SHL_MH] = instr_alu_shl_mh_exec,
6696 [INSTR_ALU_SHL_HM] = instr_alu_shl_hm_exec,
6697 [INSTR_ALU_SHL_HH] = instr_alu_shl_hh_exec,
6698 [INSTR_ALU_SHL_MI] = instr_alu_shl_mi_exec,
6699 [INSTR_ALU_SHL_HI] = instr_alu_shl_hi_exec,
6701 [INSTR_ALU_SHR] = instr_alu_shr_exec,
6702 [INSTR_ALU_SHR_MH] = instr_alu_shr_mh_exec,
6703 [INSTR_ALU_SHR_HM] = instr_alu_shr_hm_exec,
6704 [INSTR_ALU_SHR_HH] = instr_alu_shr_hh_exec,
6705 [INSTR_ALU_SHR_MI] = instr_alu_shr_mi_exec,
6706 [INSTR_ALU_SHR_HI] = instr_alu_shr_hi_exec,
6708 [INSTR_REGPREFETCH_RH] = instr_regprefetch_rh_exec,
6709 [INSTR_REGPREFETCH_RM] = instr_regprefetch_rm_exec,
6710 [INSTR_REGPREFETCH_RI] = instr_regprefetch_ri_exec,
6712 [INSTR_REGRD_HRH] = instr_regrd_hrh_exec,
6713 [INSTR_REGRD_HRM] = instr_regrd_hrm_exec,
6714 [INSTR_REGRD_MRH] = instr_regrd_mrh_exec,
6715 [INSTR_REGRD_MRM] = instr_regrd_mrm_exec,
6716 [INSTR_REGRD_HRI] = instr_regrd_hri_exec,
6717 [INSTR_REGRD_MRI] = instr_regrd_mri_exec,
6719 [INSTR_REGWR_RHH] = instr_regwr_rhh_exec,
6720 [INSTR_REGWR_RHM] = instr_regwr_rhm_exec,
6721 [INSTR_REGWR_RMH] = instr_regwr_rmh_exec,
6722 [INSTR_REGWR_RMM] = instr_regwr_rmm_exec,
6723 [INSTR_REGWR_RHI] = instr_regwr_rhi_exec,
6724 [INSTR_REGWR_RMI] = instr_regwr_rmi_exec,
6725 [INSTR_REGWR_RIH] = instr_regwr_rih_exec,
6726 [INSTR_REGWR_RIM] = instr_regwr_rim_exec,
6727 [INSTR_REGWR_RII] = instr_regwr_rii_exec,
6729 [INSTR_REGADD_RHH] = instr_regadd_rhh_exec,
6730 [INSTR_REGADD_RHM] = instr_regadd_rhm_exec,
6731 [INSTR_REGADD_RMH] = instr_regadd_rmh_exec,
6732 [INSTR_REGADD_RMM] = instr_regadd_rmm_exec,
6733 [INSTR_REGADD_RHI] = instr_regadd_rhi_exec,
6734 [INSTR_REGADD_RMI] = instr_regadd_rmi_exec,
6735 [INSTR_REGADD_RIH] = instr_regadd_rih_exec,
6736 [INSTR_REGADD_RIM] = instr_regadd_rim_exec,
6737 [INSTR_REGADD_RII] = instr_regadd_rii_exec,
6739 [INSTR_METPREFETCH_H] = instr_metprefetch_h_exec,
6740 [INSTR_METPREFETCH_M] = instr_metprefetch_m_exec,
6741 [INSTR_METPREFETCH_I] = instr_metprefetch_i_exec,
6743 [INSTR_METER_HHM] = instr_meter_hhm_exec,
6744 [INSTR_METER_HHI] = instr_meter_hhi_exec,
6745 [INSTR_METER_HMM] = instr_meter_hmm_exec,
6746 [INSTR_METER_HMI] = instr_meter_hmi_exec,
6747 [INSTR_METER_MHM] = instr_meter_mhm_exec,
6748 [INSTR_METER_MHI] = instr_meter_mhi_exec,
6749 [INSTR_METER_MMM] = instr_meter_mmm_exec,
6750 [INSTR_METER_MMI] = instr_meter_mmi_exec,
6751 [INSTR_METER_IHM] = instr_meter_ihm_exec,
6752 [INSTR_METER_IHI] = instr_meter_ihi_exec,
6753 [INSTR_METER_IMM] = instr_meter_imm_exec,
6754 [INSTR_METER_IMI] = instr_meter_imi_exec,
6756 [INSTR_TABLE] = instr_table_exec,
6757 [INSTR_TABLE_AF] = instr_table_af_exec,
6758 [INSTR_SELECTOR] = instr_selector_exec,
6759 [INSTR_LEARNER] = instr_learner_exec,
6760 [INSTR_LEARNER_AF] = instr_learner_af_exec,
6761 [INSTR_LEARNER_LEARN] = instr_learn_exec,
6762 [INSTR_LEARNER_FORGET] = instr_forget_exec,
6763 [INSTR_EXTERN_OBJ] = instr_extern_obj_exec,
6764 [INSTR_EXTERN_FUNC] = instr_extern_func_exec,
6766 [INSTR_JMP] = instr_jmp_exec,
6767 [INSTR_JMP_VALID] = instr_jmp_valid_exec,
6768 [INSTR_JMP_INVALID] = instr_jmp_invalid_exec,
6769 [INSTR_JMP_HIT] = instr_jmp_hit_exec,
6770 [INSTR_JMP_MISS] = instr_jmp_miss_exec,
6771 [INSTR_JMP_ACTION_HIT] = instr_jmp_action_hit_exec,
6772 [INSTR_JMP_ACTION_MISS] = instr_jmp_action_miss_exec,
6774 [INSTR_JMP_EQ] = instr_jmp_eq_exec,
6775 [INSTR_JMP_EQ_MH] = instr_jmp_eq_mh_exec,
6776 [INSTR_JMP_EQ_HM] = instr_jmp_eq_hm_exec,
6777 [INSTR_JMP_EQ_HH] = instr_jmp_eq_hh_exec,
6778 [INSTR_JMP_EQ_I] = instr_jmp_eq_i_exec,
6780 [INSTR_JMP_NEQ] = instr_jmp_neq_exec,
6781 [INSTR_JMP_NEQ_MH] = instr_jmp_neq_mh_exec,
6782 [INSTR_JMP_NEQ_HM] = instr_jmp_neq_hm_exec,
6783 [INSTR_JMP_NEQ_HH] = instr_jmp_neq_hh_exec,
6784 [INSTR_JMP_NEQ_I] = instr_jmp_neq_i_exec,
6786 [INSTR_JMP_LT] = instr_jmp_lt_exec,
6787 [INSTR_JMP_LT_MH] = instr_jmp_lt_mh_exec,
6788 [INSTR_JMP_LT_HM] = instr_jmp_lt_hm_exec,
6789 [INSTR_JMP_LT_HH] = instr_jmp_lt_hh_exec,
6790 [INSTR_JMP_LT_MI] = instr_jmp_lt_mi_exec,
6791 [INSTR_JMP_LT_HI] = instr_jmp_lt_hi_exec,
6793 [INSTR_JMP_GT] = instr_jmp_gt_exec,
6794 [INSTR_JMP_GT_MH] = instr_jmp_gt_mh_exec,
6795 [INSTR_JMP_GT_HM] = instr_jmp_gt_hm_exec,
6796 [INSTR_JMP_GT_HH] = instr_jmp_gt_hh_exec,
6797 [INSTR_JMP_GT_MI] = instr_jmp_gt_mi_exec,
6798 [INSTR_JMP_GT_HI] = instr_jmp_gt_hi_exec,
6800 [INSTR_RETURN] = instr_return_exec,
6804 instruction_table_build(struct rte_swx_pipeline *p)
6806 p->instruction_table = calloc(RTE_SWX_PIPELINE_INSTRUCTION_TABLE_SIZE_MAX,
6807 sizeof(struct instr_exec_t *));
6808 if (!p->instruction_table)
6811 memcpy(p->instruction_table, instruction_table, sizeof(instruction_table));
6817 instruction_table_build_free(struct rte_swx_pipeline *p)
6819 if (!p->instruction_table)
6822 free(p->instruction_table);
6823 p->instruction_table = NULL;
6827 instruction_table_free(struct rte_swx_pipeline *p)
6829 instruction_table_build_free(p);
6833 instr_exec(struct rte_swx_pipeline *p)
6835 struct thread *t = &p->threads[p->thread_id];
6836 struct instruction *ip = t->ip;
6837 instr_exec_t instr = p->instruction_table[ip->type];
6845 static struct action *
6846 action_find(struct rte_swx_pipeline *p, const char *name)
6848 struct action *elem;
6853 TAILQ_FOREACH(elem, &p->actions, node)
6854 if (strcmp(elem->name, name) == 0)
6860 static struct action *
6861 action_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
6863 struct action *action = NULL;
6865 TAILQ_FOREACH(action, &p->actions, node)
6866 if (action->id == id)
6872 static struct field *
6873 action_field_find(struct action *a, const char *name)
6875 return a->st ? struct_type_field_find(a->st, name) : NULL;
6878 static struct field *
6879 action_field_parse(struct action *action, const char *name)
6881 if (name[0] != 't' || name[1] != '.')
6884 return action_field_find(action, &name[2]);
6888 action_has_nbo_args(struct action *a)
6892 /* Return if the action does not have any args. */
6894 return 0; /* FALSE */
6896 for (i = 0; i < a->st->n_fields; i++)
6897 if (a->args_endianness[i])
6898 return 1; /* TRUE */
6900 return 0; /* FALSE */
6904 action_does_learning(struct action *a)
6908 for (i = 0; i < a->n_instructions; i++)
6909 switch (a->instructions[i].type) {
6910 case INSTR_LEARNER_LEARN:
6911 return 1; /* TRUE */
6913 case INSTR_LEARNER_FORGET:
6914 return 1; /* TRUE */
6920 return 0; /* FALSE */
6924 rte_swx_pipeline_action_config(struct rte_swx_pipeline *p,
6926 const char *args_struct_type_name,
6927 const char **instructions,
6928 uint32_t n_instructions)
6930 struct struct_type *args_struct_type = NULL;
6936 CHECK_NAME(name, EINVAL);
6937 CHECK(!action_find(p, name), EEXIST);
6939 if (args_struct_type_name) {
6940 CHECK_NAME(args_struct_type_name, EINVAL);
6941 args_struct_type = struct_type_find(p, args_struct_type_name);
6942 CHECK(args_struct_type, EINVAL);
6943 CHECK(!args_struct_type->var_size, EINVAL);
6946 /* Node allocation. */
6947 a = calloc(1, sizeof(struct action));
6949 if (args_struct_type) {
6950 a->args_endianness = calloc(args_struct_type->n_fields, sizeof(int));
6951 if (!a->args_endianness) {
6957 /* Node initialization. */
6958 strcpy(a->name, name);
6959 a->st = args_struct_type;
6960 a->id = p->n_actions;
6962 /* Instruction translation. */
6963 err = instruction_config(p, a, instructions, n_instructions);
6965 free(a->args_endianness);
6970 /* Node add to tailq. */
6971 TAILQ_INSERT_TAIL(&p->actions, a, node);
6978 action_build(struct rte_swx_pipeline *p)
6980 struct action *action;
6982 /* p->action_instructions. */
6983 p->action_instructions = calloc(p->n_actions, sizeof(struct instruction *));
6984 CHECK(p->action_instructions, ENOMEM);
6986 TAILQ_FOREACH(action, &p->actions, node)
6987 p->action_instructions[action->id] = action->instructions;
6989 /* p->action_funcs. */
6990 p->action_funcs = calloc(p->n_actions, sizeof(action_func_t));
6991 CHECK(p->action_funcs, ENOMEM);
6997 action_build_free(struct rte_swx_pipeline *p)
6999 free(p->action_funcs);
7000 p->action_funcs = NULL;
7002 free(p->action_instructions);
7003 p->action_instructions = NULL;
7007 action_free(struct rte_swx_pipeline *p)
7009 action_build_free(p);
7012 struct action *action;
7014 action = TAILQ_FIRST(&p->actions);
7018 TAILQ_REMOVE(&p->actions, action, node);
7019 free(action->instruction_data);
7020 free(action->instructions);
7026 action_arg_src_mov_count(struct action *a,
7028 struct instruction *instructions,
7029 struct instruction_data *instruction_data,
7030 uint32_t n_instructions)
7032 uint32_t offset, n_users = 0, i;
7035 (arg_id >= a->st->n_fields) ||
7037 !instruction_data ||
7041 offset = a->st->fields[arg_id].offset / 8;
7043 for (i = 0; i < n_instructions; i++) {
7044 struct instruction *instr = &instructions[i];
7045 struct instruction_data *data = &instruction_data[i];
7047 if (data->invalid ||
7048 ((instr->type != INSTR_MOV) && (instr->type != INSTR_MOV_HM)) ||
7049 instr->mov.src.struct_id ||
7050 (instr->mov.src.offset != offset))
7062 static struct table_type *
7063 table_type_find(struct rte_swx_pipeline *p, const char *name)
7065 struct table_type *elem;
7067 TAILQ_FOREACH(elem, &p->table_types, node)
7068 if (strcmp(elem->name, name) == 0)
7074 static struct table_type *
7075 table_type_resolve(struct rte_swx_pipeline *p,
7076 const char *recommended_type_name,
7077 enum rte_swx_table_match_type match_type)
7079 struct table_type *elem;
7081 /* Only consider the recommended type if the match type is correct. */
7082 if (recommended_type_name)
7083 TAILQ_FOREACH(elem, &p->table_types, node)
7084 if (!strcmp(elem->name, recommended_type_name) &&
7085 (elem->match_type == match_type))
7088 /* Ignore the recommended type and get the first element with this match
7091 TAILQ_FOREACH(elem, &p->table_types, node)
7092 if (elem->match_type == match_type)
7098 static struct table *
7099 table_find(struct rte_swx_pipeline *p, const char *name)
7103 TAILQ_FOREACH(elem, &p->tables, node)
7104 if (strcmp(elem->name, name) == 0)
7110 static struct table *
7111 table_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7113 struct table *table = NULL;
7115 TAILQ_FOREACH(table, &p->tables, node)
7116 if (table->id == id)
7123 rte_swx_pipeline_table_type_register(struct rte_swx_pipeline *p,
7125 enum rte_swx_table_match_type match_type,
7126 struct rte_swx_table_ops *ops)
7128 struct table_type *elem;
7132 CHECK_NAME(name, EINVAL);
7133 CHECK(!table_type_find(p, name), EEXIST);
7136 CHECK(ops->create, EINVAL);
7137 CHECK(ops->lkp, EINVAL);
7138 CHECK(ops->free, EINVAL);
7140 /* Node allocation. */
7141 elem = calloc(1, sizeof(struct table_type));
7142 CHECK(elem, ENOMEM);
7144 /* Node initialization. */
7145 strcpy(elem->name, name);
7146 elem->match_type = match_type;
7147 memcpy(&elem->ops, ops, sizeof(*ops));
7149 /* Node add to tailq. */
7150 TAILQ_INSERT_TAIL(&p->table_types, elem, node);
7156 table_match_type_resolve(struct rte_swx_match_field_params *fields,
7158 enum rte_swx_table_match_type *match_type)
7160 uint32_t n_fields_em = 0, n_fields_lpm = 0, i;
7162 for (i = 0; i < n_fields; i++) {
7163 struct rte_swx_match_field_params *f = &fields[i];
7165 if (f->match_type == RTE_SWX_TABLE_MATCH_EXACT)
7168 if (f->match_type == RTE_SWX_TABLE_MATCH_LPM)
7172 if ((n_fields_lpm > 1) ||
7173 (n_fields_lpm && (n_fields_em != n_fields - 1)))
7176 *match_type = (n_fields_em == n_fields) ?
7177 RTE_SWX_TABLE_MATCH_EXACT :
7178 RTE_SWX_TABLE_MATCH_WILDCARD;
7184 table_match_fields_check(struct rte_swx_pipeline *p,
7185 struct rte_swx_pipeline_table_params *params,
7186 struct header **header)
7188 struct header *h0 = NULL;
7189 struct field *hf, *mf;
7190 uint32_t *offset = NULL, i;
7193 /* Return if no match fields. */
7194 if (!params->n_fields) {
7195 if (params->fields) {
7206 /* Memory allocation. */
7207 offset = calloc(params->n_fields, sizeof(uint32_t));
7213 /* Check that all the match fields belong to either the same header or
7216 hf = header_field_parse(p, params->fields[0].name, &h0);
7217 mf = metadata_field_parse(p, params->fields[0].name);
7218 if ((!hf && !mf) || (hf && hf->var_size)) {
7223 offset[0] = h0 ? hf->offset : mf->offset;
7225 for (i = 1; i < params->n_fields; i++)
7229 hf = header_field_parse(p, params->fields[i].name, &h);
7230 if (!hf || (h->id != h0->id) || hf->var_size) {
7235 offset[i] = hf->offset;
7237 mf = metadata_field_parse(p, params->fields[i].name);
7243 offset[i] = mf->offset;
7246 /* Check that there are no duplicated match fields. */
7247 for (i = 0; i < params->n_fields; i++) {
7250 for (j = 0; j < i; j++)
7251 if (offset[j] == offset[i]) {
7267 rte_swx_pipeline_table_config(struct rte_swx_pipeline *p,
7269 struct rte_swx_pipeline_table_params *params,
7270 const char *recommended_table_type_name,
7274 struct table_type *type;
7276 struct action *default_action;
7277 struct header *header = NULL;
7278 uint32_t action_data_size_max = 0, i;
7283 CHECK_NAME(name, EINVAL);
7284 CHECK(!table_find(p, name), EEXIST);
7285 CHECK(!selector_find(p, name), EEXIST);
7286 CHECK(!learner_find(p, name), EEXIST);
7288 CHECK(params, EINVAL);
7291 status = table_match_fields_check(p, params, &header);
7295 /* Action checks. */
7296 CHECK(params->n_actions, EINVAL);
7297 CHECK(params->action_names, EINVAL);
7298 for (i = 0; i < params->n_actions; i++) {
7299 const char *action_name = params->action_names[i];
7301 uint32_t action_data_size;
7303 CHECK_NAME(action_name, EINVAL);
7305 a = action_find(p, action_name);
7307 CHECK(!action_does_learning(a), EINVAL);
7309 action_data_size = a->st ? a->st->n_bits / 8 : 0;
7310 if (action_data_size > action_data_size_max)
7311 action_data_size_max = action_data_size;
7314 CHECK_NAME(params->default_action_name, EINVAL);
7315 for (i = 0; i < p->n_actions; i++)
7316 if (!strcmp(params->action_names[i],
7317 params->default_action_name))
7319 CHECK(i < params->n_actions, EINVAL);
7320 default_action = action_find(p, params->default_action_name);
7321 CHECK((default_action->st && params->default_action_data) ||
7322 !params->default_action_data, EINVAL);
7324 /* Table type checks. */
7325 if (recommended_table_type_name)
7326 CHECK_NAME(recommended_table_type_name, EINVAL);
7328 if (params->n_fields) {
7329 enum rte_swx_table_match_type match_type;
7331 status = table_match_type_resolve(params->fields, params->n_fields, &match_type);
7335 type = table_type_resolve(p, recommended_table_type_name, match_type);
7336 CHECK(type, EINVAL);
7341 /* Memory allocation. */
7342 t = calloc(1, sizeof(struct table));
7345 t->fields = calloc(params->n_fields, sizeof(struct match_field));
7351 t->actions = calloc(params->n_actions, sizeof(struct action *));
7358 if (action_data_size_max) {
7359 t->default_action_data = calloc(1, action_data_size_max);
7360 if (!t->default_action_data) {
7368 /* Node initialization. */
7369 strcpy(t->name, name);
7370 if (args && args[0])
7371 strcpy(t->args, args);
7374 for (i = 0; i < params->n_fields; i++) {
7375 struct rte_swx_match_field_params *field = ¶ms->fields[i];
7376 struct match_field *f = &t->fields[i];
7378 f->match_type = field->match_type;
7380 header_field_parse(p, field->name, NULL) :
7381 metadata_field_parse(p, field->name);
7383 t->n_fields = params->n_fields;
7386 for (i = 0; i < params->n_actions; i++)
7387 t->actions[i] = action_find(p, params->action_names[i]);
7388 t->default_action = default_action;
7389 if (default_action->st)
7390 memcpy(t->default_action_data,
7391 params->default_action_data,
7392 default_action->st->n_bits / 8);
7393 t->n_actions = params->n_actions;
7394 t->default_action_is_const = params->default_action_is_const;
7395 t->action_data_size_max = action_data_size_max;
7398 t->id = p->n_tables;
7400 /* Node add to tailq. */
7401 TAILQ_INSERT_TAIL(&p->tables, t, node);
7407 static struct rte_swx_table_params *
7408 table_params_get(struct table *table)
7410 struct rte_swx_table_params *params;
7411 struct field *first, *last;
7413 uint32_t key_size, key_offset, action_data_size, i;
7415 /* Memory allocation. */
7416 params = calloc(1, sizeof(struct rte_swx_table_params));
7420 /* Find first (smallest offset) and last (biggest offset) match fields. */
7421 first = table->fields[0].field;
7422 last = table->fields[0].field;
7424 for (i = 0; i < table->n_fields; i++) {
7425 struct field *f = table->fields[i].field;
7427 if (f->offset < first->offset)
7430 if (f->offset > last->offset)
7434 /* Key offset and size. */
7435 key_offset = first->offset / 8;
7436 key_size = (last->offset + last->n_bits - first->offset) / 8;
7438 /* Memory allocation. */
7439 key_mask = calloc(1, key_size);
7446 for (i = 0; i < table->n_fields; i++) {
7447 struct field *f = table->fields[i].field;
7448 uint32_t start = (f->offset - first->offset) / 8;
7449 size_t size = f->n_bits / 8;
7451 memset(&key_mask[start], 0xFF, size);
7454 /* Action data size. */
7455 action_data_size = 0;
7456 for (i = 0; i < table->n_actions; i++) {
7457 struct action *action = table->actions[i];
7458 uint32_t ads = action->st ? action->st->n_bits / 8 : 0;
7460 if (ads > action_data_size)
7461 action_data_size = ads;
7465 params->match_type = table->type->match_type;
7466 params->key_size = key_size;
7467 params->key_offset = key_offset;
7468 params->key_mask0 = key_mask;
7469 params->action_data_size = action_data_size;
7470 params->n_keys_max = table->size;
7476 table_params_free(struct rte_swx_table_params *params)
7481 free(params->key_mask0);
7486 table_stub_lkp(void *table __rte_unused,
7487 void *mailbox __rte_unused,
7488 uint8_t **key __rte_unused,
7489 uint64_t *action_id __rte_unused,
7490 uint8_t **action_data __rte_unused,
7494 return 1; /* DONE. */
7498 table_build(struct rte_swx_pipeline *p)
7502 /* Per pipeline: table statistics. */
7503 p->table_stats = calloc(p->n_tables, sizeof(struct table_statistics));
7504 CHECK(p->table_stats, ENOMEM);
7506 for (i = 0; i < p->n_tables; i++) {
7507 p->table_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
7508 CHECK(p->table_stats[i].n_pkts_action, ENOMEM);
7511 /* Per thread: table runt-time. */
7512 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
7513 struct thread *t = &p->threads[i];
7514 struct table *table;
7516 t->tables = calloc(p->n_tables, sizeof(struct table_runtime));
7517 CHECK(t->tables, ENOMEM);
7519 TAILQ_FOREACH(table, &p->tables, node) {
7520 struct table_runtime *r = &t->tables[table->id];
7525 size = table->type->ops.mailbox_size_get();
7528 r->func = table->type->ops.lkp;
7532 r->mailbox = calloc(1, size);
7533 CHECK(r->mailbox, ENOMEM);
7537 r->key = table->header ?
7538 &t->structs[table->header->struct_id] :
7539 &t->structs[p->metadata_struct_id];
7541 r->func = table_stub_lkp;
7550 table_build_free(struct rte_swx_pipeline *p)
7554 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
7555 struct thread *t = &p->threads[i];
7561 for (j = 0; j < p->n_tables; j++) {
7562 struct table_runtime *r = &t->tables[j];
7571 if (p->table_stats) {
7572 for (i = 0; i < p->n_tables; i++)
7573 free(p->table_stats[i].n_pkts_action);
7575 free(p->table_stats);
7580 table_free(struct rte_swx_pipeline *p)
7582 table_build_free(p);
7588 elem = TAILQ_FIRST(&p->tables);
7592 TAILQ_REMOVE(&p->tables, elem, node);
7594 free(elem->actions);
7595 free(elem->default_action_data);
7601 struct table_type *elem;
7603 elem = TAILQ_FIRST(&p->table_types);
7607 TAILQ_REMOVE(&p->table_types, elem, node);
7615 static struct selector *
7616 selector_find(struct rte_swx_pipeline *p, const char *name)
7620 TAILQ_FOREACH(s, &p->selectors, node)
7621 if (strcmp(s->name, name) == 0)
7627 static struct selector *
7628 selector_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7630 struct selector *s = NULL;
7632 TAILQ_FOREACH(s, &p->selectors, node)
7640 selector_fields_check(struct rte_swx_pipeline *p,
7641 struct rte_swx_pipeline_selector_params *params,
7642 struct header **header)
7644 struct header *h0 = NULL;
7645 struct field *hf, *mf;
7648 /* Return if no selector fields. */
7649 if (!params->n_selector_fields || !params->selector_field_names)
7652 /* Check that all the selector fields either belong to the same header
7653 * or are all meta-data fields.
7655 hf = header_field_parse(p, params->selector_field_names[0], &h0);
7656 mf = metadata_field_parse(p, params->selector_field_names[0]);
7660 for (i = 1; i < params->n_selector_fields; i++)
7664 hf = header_field_parse(p, params->selector_field_names[i], &h);
7665 if (!hf || (h->id != h0->id))
7668 mf = metadata_field_parse(p, params->selector_field_names[i]);
7673 /* Check that there are no duplicated match fields. */
7674 for (i = 0; i < params->n_selector_fields; i++) {
7675 const char *field_name = params->selector_field_names[i];
7678 for (j = i + 1; j < params->n_selector_fields; j++)
7679 if (!strcmp(params->selector_field_names[j], field_name))
7691 rte_swx_pipeline_selector_config(struct rte_swx_pipeline *p,
7693 struct rte_swx_pipeline_selector_params *params)
7696 struct header *selector_header = NULL;
7697 struct field *group_id_field, *member_id_field;
7703 CHECK_NAME(name, EINVAL);
7704 CHECK(!table_find(p, name), EEXIST);
7705 CHECK(!selector_find(p, name), EEXIST);
7706 CHECK(!learner_find(p, name), EEXIST);
7708 CHECK(params, EINVAL);
7710 CHECK_NAME(params->group_id_field_name, EINVAL);
7711 group_id_field = metadata_field_parse(p, params->group_id_field_name);
7712 CHECK(group_id_field, EINVAL);
7714 for (i = 0; i < params->n_selector_fields; i++) {
7715 const char *field_name = params->selector_field_names[i];
7717 CHECK_NAME(field_name, EINVAL);
7719 status = selector_fields_check(p, params, &selector_header);
7723 CHECK_NAME(params->member_id_field_name, EINVAL);
7724 member_id_field = metadata_field_parse(p, params->member_id_field_name);
7725 CHECK(member_id_field, EINVAL);
7727 CHECK(params->n_groups_max, EINVAL);
7729 CHECK(params->n_members_per_group_max, EINVAL);
7731 /* Memory allocation. */
7732 s = calloc(1, sizeof(struct selector));
7738 s->selector_fields = calloc(params->n_selector_fields, sizeof(struct field *));
7739 if (!s->selector_fields) {
7744 /* Node initialization. */
7745 strcpy(s->name, name);
7747 s->group_id_field = group_id_field;
7749 for (i = 0; i < params->n_selector_fields; i++) {
7750 const char *field_name = params->selector_field_names[i];
7752 s->selector_fields[i] = selector_header ?
7753 header_field_parse(p, field_name, NULL) :
7754 metadata_field_parse(p, field_name);
7757 s->n_selector_fields = params->n_selector_fields;
7759 s->selector_header = selector_header;
7761 s->member_id_field = member_id_field;
7763 s->n_groups_max = params->n_groups_max;
7765 s->n_members_per_group_max = params->n_members_per_group_max;
7767 s->id = p->n_selectors;
7769 /* Node add to tailq. */
7770 TAILQ_INSERT_TAIL(&p->selectors, s, node);
7779 free(s->selector_fields);
7787 selector_params_free(struct rte_swx_table_selector_params *params)
7792 free(params->selector_mask);
7797 static struct rte_swx_table_selector_params *
7798 selector_table_params_get(struct selector *s)
7800 struct rte_swx_table_selector_params *params = NULL;
7801 struct field *first, *last;
7804 /* Memory allocation. */
7805 params = calloc(1, sizeof(struct rte_swx_table_selector_params));
7810 params->group_id_offset = s->group_id_field->offset / 8;
7812 /* Find first (smallest offset) and last (biggest offset) selector fields. */
7813 first = s->selector_fields[0];
7814 last = s->selector_fields[0];
7816 for (i = 0; i < s->n_selector_fields; i++) {
7817 struct field *f = s->selector_fields[i];
7819 if (f->offset < first->offset)
7822 if (f->offset > last->offset)
7826 /* Selector offset and size. */
7827 params->selector_offset = first->offset / 8;
7828 params->selector_size = (last->offset + last->n_bits - first->offset) / 8;
7830 /* Memory allocation. */
7831 params->selector_mask = calloc(1, params->selector_size);
7832 if (!params->selector_mask)
7835 /* Selector mask. */
7836 for (i = 0; i < s->n_selector_fields; i++) {
7837 struct field *f = s->selector_fields[i];
7838 uint32_t start = (f->offset - first->offset) / 8;
7839 size_t size = f->n_bits / 8;
7841 memset(¶ms->selector_mask[start], 0xFF, size);
7845 params->member_id_offset = s->member_id_field->offset / 8;
7847 /* Maximum number of groups. */
7848 params->n_groups_max = s->n_groups_max;
7850 /* Maximum number of members per group. */
7851 params->n_members_per_group_max = s->n_members_per_group_max;
7856 selector_params_free(params);
7861 selector_build_free(struct rte_swx_pipeline *p)
7865 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
7866 struct thread *t = &p->threads[i];
7872 for (j = 0; j < p->n_selectors; j++) {
7873 struct selector_runtime *r = &t->selectors[j];
7879 t->selectors = NULL;
7882 free(p->selector_stats);
7883 p->selector_stats = NULL;
7887 selector_build(struct rte_swx_pipeline *p)
7892 /* Per pipeline: selector statistics. */
7893 p->selector_stats = calloc(p->n_selectors, sizeof(struct selector_statistics));
7894 if (!p->selector_stats) {
7899 /* Per thread: selector run-time. */
7900 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
7901 struct thread *t = &p->threads[i];
7904 t->selectors = calloc(p->n_selectors, sizeof(struct selector_runtime));
7905 if (!t->selectors) {
7910 TAILQ_FOREACH(s, &p->selectors, node) {
7911 struct selector_runtime *r = &t->selectors[s->id];
7915 size = rte_swx_table_selector_mailbox_size_get();
7917 r->mailbox = calloc(1, size);
7924 /* r->group_id_buffer. */
7925 r->group_id_buffer = &t->structs[p->metadata_struct_id];
7927 /* r->selector_buffer. */
7928 r->selector_buffer = s->selector_header ?
7929 &t->structs[s->selector_header->struct_id] :
7930 &t->structs[p->metadata_struct_id];
7932 /* r->member_id_buffer. */
7933 r->member_id_buffer = &t->structs[p->metadata_struct_id];
7940 selector_build_free(p);
7945 selector_free(struct rte_swx_pipeline *p)
7947 selector_build_free(p);
7949 /* Selector tables. */
7951 struct selector *elem;
7953 elem = TAILQ_FIRST(&p->selectors);
7957 TAILQ_REMOVE(&p->selectors, elem, node);
7958 free(elem->selector_fields);
7966 static struct learner *
7967 learner_find(struct rte_swx_pipeline *p, const char *name)
7971 TAILQ_FOREACH(l, &p->learners, node)
7972 if (!strcmp(l->name, name))
7978 static struct learner *
7979 learner_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7981 struct learner *l = NULL;
7983 TAILQ_FOREACH(l, &p->learners, node)
7991 learner_match_fields_check(struct rte_swx_pipeline *p,
7992 struct rte_swx_pipeline_learner_params *params,
7993 struct header **header)
7995 struct header *h0 = NULL;
7996 struct field *hf, *mf;
7999 /* Return if no match fields. */
8000 if (!params->n_fields || !params->field_names)
8003 /* Check that all the match fields either belong to the same header
8004 * or are all meta-data fields.
8006 hf = header_field_parse(p, params->field_names[0], &h0);
8007 mf = metadata_field_parse(p, params->field_names[0]);
8011 for (i = 1; i < params->n_fields; i++)
8015 hf = header_field_parse(p, params->field_names[i], &h);
8016 if (!hf || (h->id != h0->id))
8019 mf = metadata_field_parse(p, params->field_names[i]);
8024 /* Check that there are no duplicated match fields. */
8025 for (i = 0; i < params->n_fields; i++) {
8026 const char *field_name = params->field_names[i];
8029 for (j = i + 1; j < params->n_fields; j++)
8030 if (!strcmp(params->field_names[j], field_name))
8042 learner_action_args_check(struct rte_swx_pipeline *p, struct action *a, const char *mf_name)
8044 struct struct_type *mst = p->metadata_st, *ast = a->st;
8045 struct field *mf, *af;
8055 /* Check that mf_name is the name of a valid meta-data field. */
8056 CHECK_NAME(mf_name, EINVAL);
8057 mf = metadata_field_parse(p, mf_name);
8060 /* Check that there are enough meta-data fields, starting with the mf_name field, to cover
8061 * all the action arguments.
8063 mf_pos = mf - mst->fields;
8064 CHECK(mst->n_fields - mf_pos >= ast->n_fields, EINVAL);
8066 /* Check that the size of each of the identified meta-data fields matches exactly the size
8067 * of the corresponding action argument.
8069 for (i = 0; i < ast->n_fields; i++) {
8070 mf = &mst->fields[mf_pos + i];
8071 af = &ast->fields[i];
8073 CHECK(mf->n_bits == af->n_bits, EINVAL);
8080 learner_action_learning_check(struct rte_swx_pipeline *p,
8081 struct action *action,
8082 const char **action_names,
8087 /* For each "learn" instruction of the current action, check that the learned action (i.e.
8088 * the action passed as argument to the "learn" instruction) is also enabled for the
8089 * current learner table.
8091 for (i = 0; i < action->n_instructions; i++) {
8092 struct instruction *instr = &action->instructions[i];
8093 uint32_t found = 0, j;
8095 if (instr->type != INSTR_LEARNER_LEARN)
8098 for (j = 0; j < n_actions; j++) {
8101 a = action_find(p, action_names[j]);
8105 if (a->id == instr->learn.action_id)
8117 rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p,
8119 struct rte_swx_pipeline_learner_params *params,
8123 struct learner *l = NULL;
8124 struct action *default_action;
8125 struct header *header = NULL;
8126 uint32_t action_data_size_max = 0, i;
8131 CHECK_NAME(name, EINVAL);
8132 CHECK(!table_find(p, name), EEXIST);
8133 CHECK(!selector_find(p, name), EEXIST);
8134 CHECK(!learner_find(p, name), EEXIST);
8136 CHECK(params, EINVAL);
8139 status = learner_match_fields_check(p, params, &header);
8143 /* Action checks. */
8144 CHECK(params->n_actions, EINVAL);
8146 CHECK(params->action_names, EINVAL);
8147 for (i = 0; i < params->n_actions; i++) {
8148 const char *action_name = params->action_names[i];
8149 const char *action_field_name = params->action_field_names[i];
8151 uint32_t action_data_size;
8153 CHECK_NAME(action_name, EINVAL);
8155 a = action_find(p, action_name);
8158 status = learner_action_args_check(p, a, action_field_name);
8162 status = learner_action_learning_check(p,
8164 params->action_names,
8169 action_data_size = a->st ? a->st->n_bits / 8 : 0;
8170 if (action_data_size > action_data_size_max)
8171 action_data_size_max = action_data_size;
8174 CHECK_NAME(params->default_action_name, EINVAL);
8175 for (i = 0; i < p->n_actions; i++)
8176 if (!strcmp(params->action_names[i],
8177 params->default_action_name))
8179 CHECK(i < params->n_actions, EINVAL);
8181 default_action = action_find(p, params->default_action_name);
8182 CHECK((default_action->st && params->default_action_data) ||
8183 !params->default_action_data, EINVAL);
8185 /* Any other checks. */
8186 CHECK(size, EINVAL);
8187 CHECK(timeout, EINVAL);
8189 /* Memory allocation. */
8190 l = calloc(1, sizeof(struct learner));
8194 l->fields = calloc(params->n_fields, sizeof(struct field *));
8198 l->actions = calloc(params->n_actions, sizeof(struct action *));
8202 l->action_arg = calloc(params->n_actions, sizeof(struct field *));
8206 if (action_data_size_max) {
8207 l->default_action_data = calloc(1, action_data_size_max);
8208 if (!l->default_action_data)
8212 /* Node initialization. */
8213 strcpy(l->name, name);
8215 for (i = 0; i < params->n_fields; i++) {
8216 const char *field_name = params->field_names[i];
8218 l->fields[i] = header ?
8219 header_field_parse(p, field_name, NULL) :
8220 metadata_field_parse(p, field_name);
8223 l->n_fields = params->n_fields;
8227 for (i = 0; i < params->n_actions; i++) {
8228 const char *mf_name = params->action_field_names[i];
8230 l->actions[i] = action_find(p, params->action_names[i]);
8232 l->action_arg[i] = mf_name ? metadata_field_parse(p, mf_name) : NULL;
8235 l->default_action = default_action;
8237 if (default_action->st)
8238 memcpy(l->default_action_data,
8239 params->default_action_data,
8240 default_action->st->n_bits / 8);
8242 l->n_actions = params->n_actions;
8244 l->default_action_is_const = params->default_action_is_const;
8246 l->action_data_size_max = action_data_size_max;
8250 l->timeout = timeout;
8252 l->id = p->n_learners;
8254 /* Node add to tailq. */
8255 TAILQ_INSERT_TAIL(&p->learners, l, node);
8264 free(l->action_arg);
8273 learner_params_free(struct rte_swx_table_learner_params *params)
8278 free(params->key_mask0);
8283 static struct rte_swx_table_learner_params *
8284 learner_params_get(struct learner *l)
8286 struct rte_swx_table_learner_params *params = NULL;
8287 struct field *first, *last;
8290 /* Memory allocation. */
8291 params = calloc(1, sizeof(struct rte_swx_table_learner_params));
8295 /* Find first (smallest offset) and last (biggest offset) match fields. */
8296 first = l->fields[0];
8297 last = l->fields[0];
8299 for (i = 0; i < l->n_fields; i++) {
8300 struct field *f = l->fields[i];
8302 if (f->offset < first->offset)
8305 if (f->offset > last->offset)
8309 /* Key offset and size. */
8310 params->key_offset = first->offset / 8;
8311 params->key_size = (last->offset + last->n_bits - first->offset) / 8;
8313 /* Memory allocation. */
8314 params->key_mask0 = calloc(1, params->key_size);
8315 if (!params->key_mask0)
8319 for (i = 0; i < l->n_fields; i++) {
8320 struct field *f = l->fields[i];
8321 uint32_t start = (f->offset - first->offset) / 8;
8322 size_t size = f->n_bits / 8;
8324 memset(¶ms->key_mask0[start], 0xFF, size);
8327 /* Action data size. */
8328 params->action_data_size = l->action_data_size_max;
8330 /* Maximum number of keys. */
8331 params->n_keys_max = l->size;
8334 params->key_timeout = l->timeout;
8339 learner_params_free(params);
8344 learner_build_free(struct rte_swx_pipeline *p)
8348 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8349 struct thread *t = &p->threads[i];
8355 for (j = 0; j < p->n_learners; j++) {
8356 struct learner_runtime *r = &t->learners[j];
8359 free(r->action_data);
8366 if (p->learner_stats) {
8367 for (i = 0; i < p->n_learners; i++)
8368 free(p->learner_stats[i].n_pkts_action);
8370 free(p->learner_stats);
8375 learner_build(struct rte_swx_pipeline *p)
8380 /* Per pipeline: learner statistics. */
8381 p->learner_stats = calloc(p->n_learners, sizeof(struct learner_statistics));
8382 CHECK(p->learner_stats, ENOMEM);
8384 for (i = 0; i < p->n_learners; i++) {
8385 p->learner_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
8386 CHECK(p->learner_stats[i].n_pkts_action, ENOMEM);
8389 /* Per thread: learner run-time. */
8390 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8391 struct thread *t = &p->threads[i];
8394 t->learners = calloc(p->n_learners, sizeof(struct learner_runtime));
8400 TAILQ_FOREACH(l, &p->learners, node) {
8401 struct learner_runtime *r = &t->learners[l->id];
8406 size = rte_swx_table_learner_mailbox_size_get();
8408 r->mailbox = calloc(1, size);
8416 r->key = l->header ?
8417 &t->structs[l->header->struct_id] :
8418 &t->structs[p->metadata_struct_id];
8420 /* r->action_data. */
8421 r->action_data = calloc(p->n_actions, sizeof(uint8_t *));
8422 if (!r->action_data) {
8427 for (j = 0; j < l->n_actions; j++) {
8428 struct action *a = l->actions[j];
8429 struct field *mf = l->action_arg[j];
8430 uint8_t *m = t->structs[p->metadata_struct_id];
8432 r->action_data[a->id] = mf ? &m[mf->offset / 8] : NULL;
8440 learner_build_free(p);
8445 learner_free(struct rte_swx_pipeline *p)
8447 learner_build_free(p);
8449 /* Learner tables. */
8453 l = TAILQ_FIRST(&p->learners);
8457 TAILQ_REMOVE(&p->learners, l, node);
8460 free(l->action_arg);
8461 free(l->default_action_data);
8470 table_state_build(struct rte_swx_pipeline *p)
8472 struct table *table;
8476 p->table_state = calloc(p->n_tables + p->n_selectors,
8477 sizeof(struct rte_swx_table_state));
8478 CHECK(p->table_state, ENOMEM);
8480 TAILQ_FOREACH(table, &p->tables, node) {
8481 struct rte_swx_table_state *ts = &p->table_state[table->id];
8484 struct rte_swx_table_params *params;
8487 params = table_params_get(table);
8488 CHECK(params, ENOMEM);
8490 ts->obj = table->type->ops.create(params,
8495 table_params_free(params);
8496 CHECK(ts->obj, ENODEV);
8499 /* ts->default_action_data. */
8500 if (table->action_data_size_max) {
8501 ts->default_action_data =
8502 malloc(table->action_data_size_max);
8503 CHECK(ts->default_action_data, ENOMEM);
8505 memcpy(ts->default_action_data,
8506 table->default_action_data,
8507 table->action_data_size_max);
8510 /* ts->default_action_id. */
8511 ts->default_action_id = table->default_action->id;
8514 TAILQ_FOREACH(s, &p->selectors, node) {
8515 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + s->id];
8516 struct rte_swx_table_selector_params *params;
8519 params = selector_table_params_get(s);
8520 CHECK(params, ENOMEM);
8522 ts->obj = rte_swx_table_selector_create(params, NULL, p->numa_node);
8524 selector_params_free(params);
8525 CHECK(ts->obj, ENODEV);
8528 TAILQ_FOREACH(l, &p->learners, node) {
8529 struct rte_swx_table_state *ts = &p->table_state[p->n_tables +
8530 p->n_selectors + l->id];
8531 struct rte_swx_table_learner_params *params;
8534 params = learner_params_get(l);
8535 CHECK(params, ENOMEM);
8537 ts->obj = rte_swx_table_learner_create(params, p->numa_node);
8538 learner_params_free(params);
8539 CHECK(ts->obj, ENODEV);
8541 /* ts->default_action_data. */
8542 if (l->action_data_size_max) {
8543 ts->default_action_data = malloc(l->action_data_size_max);
8544 CHECK(ts->default_action_data, ENOMEM);
8546 memcpy(ts->default_action_data,
8547 l->default_action_data,
8548 l->action_data_size_max);
8551 /* ts->default_action_id. */
8552 ts->default_action_id = l->default_action->id;
8559 table_state_build_free(struct rte_swx_pipeline *p)
8563 if (!p->table_state)
8566 for (i = 0; i < p->n_tables; i++) {
8567 struct rte_swx_table_state *ts = &p->table_state[i];
8568 struct table *table = table_find_by_id(p, i);
8571 if (table->type && ts->obj)
8572 table->type->ops.free(ts->obj);
8574 /* ts->default_action_data. */
8575 free(ts->default_action_data);
8578 for (i = 0; i < p->n_selectors; i++) {
8579 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + i];
8583 rte_swx_table_selector_free(ts->obj);
8586 for (i = 0; i < p->n_learners; i++) {
8587 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + p->n_selectors + i];
8591 rte_swx_table_learner_free(ts->obj);
8593 /* ts->default_action_data. */
8594 free(ts->default_action_data);
8597 free(p->table_state);
8598 p->table_state = NULL;
8602 table_state_free(struct rte_swx_pipeline *p)
8604 table_state_build_free(p);
8610 static struct regarray *
8611 regarray_find(struct rte_swx_pipeline *p, const char *name)
8613 struct regarray *elem;
8615 TAILQ_FOREACH(elem, &p->regarrays, node)
8616 if (!strcmp(elem->name, name))
8622 static struct regarray *
8623 regarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8625 struct regarray *elem = NULL;
8627 TAILQ_FOREACH(elem, &p->regarrays, node)
8635 rte_swx_pipeline_regarray_config(struct rte_swx_pipeline *p,
8644 CHECK_NAME(name, EINVAL);
8645 CHECK(!regarray_find(p, name), EEXIST);
8647 CHECK(size, EINVAL);
8648 size = rte_align32pow2(size);
8650 /* Memory allocation. */
8651 r = calloc(1, sizeof(struct regarray));
8654 /* Node initialization. */
8655 strcpy(r->name, name);
8656 r->init_val = init_val;
8658 r->id = p->n_regarrays;
8660 /* Node add to tailq. */
8661 TAILQ_INSERT_TAIL(&p->regarrays, r, node);
8668 regarray_build(struct rte_swx_pipeline *p)
8670 struct regarray *regarray;
8672 if (!p->n_regarrays)
8675 p->regarray_runtime = calloc(p->n_regarrays, sizeof(struct regarray_runtime));
8676 CHECK(p->regarray_runtime, ENOMEM);
8678 TAILQ_FOREACH(regarray, &p->regarrays, node) {
8679 struct regarray_runtime *r = &p->regarray_runtime[regarray->id];
8682 r->regarray = env_malloc(regarray->size * sizeof(uint64_t),
8683 RTE_CACHE_LINE_SIZE,
8685 CHECK(r->regarray, ENOMEM);
8687 if (regarray->init_val)
8688 for (i = 0; i < regarray->size; i++)
8689 r->regarray[i] = regarray->init_val;
8691 r->size_mask = regarray->size - 1;
8698 regarray_build_free(struct rte_swx_pipeline *p)
8702 if (!p->regarray_runtime)
8705 for (i = 0; i < p->n_regarrays; i++) {
8706 struct regarray *regarray = regarray_find_by_id(p, i);
8707 struct regarray_runtime *r = &p->regarray_runtime[i];
8709 env_free(r->regarray, regarray->size * sizeof(uint64_t));
8712 free(p->regarray_runtime);
8713 p->regarray_runtime = NULL;
8717 regarray_free(struct rte_swx_pipeline *p)
8719 regarray_build_free(p);
8722 struct regarray *elem;
8724 elem = TAILQ_FIRST(&p->regarrays);
8728 TAILQ_REMOVE(&p->regarrays, elem, node);
8736 static struct meter_profile *
8737 meter_profile_find(struct rte_swx_pipeline *p, const char *name)
8739 struct meter_profile *elem;
8741 TAILQ_FOREACH(elem, &p->meter_profiles, node)
8742 if (!strcmp(elem->name, name))
8748 static struct metarray *
8749 metarray_find(struct rte_swx_pipeline *p, const char *name)
8751 struct metarray *elem;
8753 TAILQ_FOREACH(elem, &p->metarrays, node)
8754 if (!strcmp(elem->name, name))
8760 static struct metarray *
8761 metarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8763 struct metarray *elem = NULL;
8765 TAILQ_FOREACH(elem, &p->metarrays, node)
8773 rte_swx_pipeline_metarray_config(struct rte_swx_pipeline *p,
8781 CHECK_NAME(name, EINVAL);
8782 CHECK(!metarray_find(p, name), EEXIST);
8784 CHECK(size, EINVAL);
8785 size = rte_align32pow2(size);
8787 /* Memory allocation. */
8788 m = calloc(1, sizeof(struct metarray));
8791 /* Node initialization. */
8792 strcpy(m->name, name);
8794 m->id = p->n_metarrays;
8796 /* Node add to tailq. */
8797 TAILQ_INSERT_TAIL(&p->metarrays, m, node);
8803 struct meter_profile meter_profile_default = {
8812 .cir_bytes_per_period = 1,
8814 .pir_bytes_per_period = 1,
8821 meter_init(struct meter *m)
8823 memset(m, 0, sizeof(struct meter));
8824 rte_meter_trtcm_config(&m->m, &meter_profile_default.profile);
8825 m->profile = &meter_profile_default;
8826 m->color_mask = RTE_COLOR_GREEN;
8828 meter_profile_default.n_users++;
8832 metarray_build(struct rte_swx_pipeline *p)
8836 if (!p->n_metarrays)
8839 p->metarray_runtime = calloc(p->n_metarrays, sizeof(struct metarray_runtime));
8840 CHECK(p->metarray_runtime, ENOMEM);
8842 TAILQ_FOREACH(m, &p->metarrays, node) {
8843 struct metarray_runtime *r = &p->metarray_runtime[m->id];
8846 r->metarray = env_malloc(m->size * sizeof(struct meter),
8847 RTE_CACHE_LINE_SIZE,
8849 CHECK(r->metarray, ENOMEM);
8851 for (i = 0; i < m->size; i++)
8852 meter_init(&r->metarray[i]);
8854 r->size_mask = m->size - 1;
8861 metarray_build_free(struct rte_swx_pipeline *p)
8865 if (!p->metarray_runtime)
8868 for (i = 0; i < p->n_metarrays; i++) {
8869 struct metarray *m = metarray_find_by_id(p, i);
8870 struct metarray_runtime *r = &p->metarray_runtime[i];
8872 env_free(r->metarray, m->size * sizeof(struct meter));
8875 free(p->metarray_runtime);
8876 p->metarray_runtime = NULL;
8880 metarray_free(struct rte_swx_pipeline *p)
8882 metarray_build_free(p);
8886 struct metarray *elem;
8888 elem = TAILQ_FIRST(&p->metarrays);
8892 TAILQ_REMOVE(&p->metarrays, elem, node);
8896 /* Meter profiles. */
8898 struct meter_profile *elem;
8900 elem = TAILQ_FIRST(&p->meter_profiles);
8904 TAILQ_REMOVE(&p->meter_profiles, elem, node);
8913 rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
8915 struct rte_swx_pipeline *pipeline;
8917 /* Check input parameters. */
8920 /* Memory allocation. */
8921 pipeline = calloc(1, sizeof(struct rte_swx_pipeline));
8922 CHECK(pipeline, ENOMEM);
8924 /* Initialization. */
8925 TAILQ_INIT(&pipeline->struct_types);
8926 TAILQ_INIT(&pipeline->port_in_types);
8927 TAILQ_INIT(&pipeline->ports_in);
8928 TAILQ_INIT(&pipeline->port_out_types);
8929 TAILQ_INIT(&pipeline->ports_out);
8930 TAILQ_INIT(&pipeline->extern_types);
8931 TAILQ_INIT(&pipeline->extern_objs);
8932 TAILQ_INIT(&pipeline->extern_funcs);
8933 TAILQ_INIT(&pipeline->headers);
8934 TAILQ_INIT(&pipeline->actions);
8935 TAILQ_INIT(&pipeline->table_types);
8936 TAILQ_INIT(&pipeline->tables);
8937 TAILQ_INIT(&pipeline->selectors);
8938 TAILQ_INIT(&pipeline->learners);
8939 TAILQ_INIT(&pipeline->regarrays);
8940 TAILQ_INIT(&pipeline->meter_profiles);
8941 TAILQ_INIT(&pipeline->metarrays);
8943 pipeline->n_structs = 1; /* Struct 0 is reserved for action_data. */
8944 pipeline->numa_node = numa_node;
8951 rte_swx_pipeline_free(struct rte_swx_pipeline *p)
8956 free(p->instruction_data);
8957 free(p->instructions);
8961 table_state_free(p);
8966 instruction_table_free(p);
8969 extern_func_free(p);
8979 rte_swx_pipeline_instructions_config(struct rte_swx_pipeline *p,
8980 const char **instructions,
8981 uint32_t n_instructions)
8986 err = instruction_config(p, NULL, instructions, n_instructions);
8990 /* Thread instruction pointer reset. */
8991 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8992 struct thread *t = &p->threads[i];
8994 thread_ip_reset(p, t);
9001 pipeline_compile(struct rte_swx_pipeline *p);
9004 rte_swx_pipeline_build(struct rte_swx_pipeline *p)
9009 CHECK(p->build_done == 0, EEXIST);
9011 status = port_in_build(p);
9015 status = port_out_build(p);
9019 status = struct_build(p);
9023 status = extern_obj_build(p);
9027 status = extern_func_build(p);
9031 status = header_build(p);
9035 status = metadata_build(p);
9039 status = instruction_table_build(p);
9043 status = action_build(p);
9047 status = table_build(p);
9051 status = selector_build(p);
9055 status = learner_build(p);
9059 status = table_state_build(p);
9063 status = regarray_build(p);
9067 status = metarray_build(p);
9073 pipeline_compile(p);
9078 metarray_build_free(p);
9079 regarray_build_free(p);
9080 table_state_build_free(p);
9081 learner_build_free(p);
9082 selector_build_free(p);
9083 table_build_free(p);
9084 action_build_free(p);
9085 instruction_table_build_free(p);
9086 metadata_build_free(p);
9087 header_build_free(p);
9088 extern_func_build_free(p);
9089 extern_obj_build_free(p);
9090 port_out_build_free(p);
9091 port_in_build_free(p);
9092 struct_build_free(p);
9098 rte_swx_pipeline_run(struct rte_swx_pipeline *p, uint32_t n_instructions)
9102 for (i = 0; i < n_instructions; i++)
9107 rte_swx_pipeline_flush(struct rte_swx_pipeline *p)
9111 for (i = 0; i < p->n_ports_out; i++) {
9112 struct port_out_runtime *port = &p->out[i];
9115 port->flush(port->obj);
9123 rte_swx_ctl_pipeline_info_get(struct rte_swx_pipeline *p,
9124 struct rte_swx_ctl_pipeline_info *pipeline)
9126 struct action *action;
9127 struct table *table;
9128 uint32_t n_actions = 0, n_tables = 0;
9130 if (!p || !pipeline)
9133 TAILQ_FOREACH(action, &p->actions, node)
9136 TAILQ_FOREACH(table, &p->tables, node)
9139 pipeline->n_ports_in = p->n_ports_in;
9140 pipeline->n_ports_out = p->n_ports_out;
9141 pipeline->n_actions = n_actions;
9142 pipeline->n_tables = n_tables;
9143 pipeline->n_selectors = p->n_selectors;
9144 pipeline->n_learners = p->n_learners;
9145 pipeline->n_regarrays = p->n_regarrays;
9146 pipeline->n_metarrays = p->n_metarrays;
9152 rte_swx_ctl_pipeline_numa_node_get(struct rte_swx_pipeline *p, int *numa_node)
9154 if (!p || !numa_node)
9157 *numa_node = p->numa_node;
9162 rte_swx_ctl_action_info_get(struct rte_swx_pipeline *p,
9164 struct rte_swx_ctl_action_info *action)
9166 struct action *a = NULL;
9168 if (!p || (action_id >= p->n_actions) || !action)
9171 a = action_find_by_id(p, action_id);
9175 strcpy(action->name, a->name);
9176 action->n_args = a->st ? a->st->n_fields : 0;
9181 rte_swx_ctl_action_arg_info_get(struct rte_swx_pipeline *p,
9183 uint32_t action_arg_id,
9184 struct rte_swx_ctl_action_arg_info *action_arg)
9186 struct action *a = NULL;
9187 struct field *arg = NULL;
9189 if (!p || (action_id >= p->n_actions) || !action_arg)
9192 a = action_find_by_id(p, action_id);
9193 if (!a || !a->st || (action_arg_id >= a->st->n_fields))
9196 arg = &a->st->fields[action_arg_id];
9197 strcpy(action_arg->name, arg->name);
9198 action_arg->n_bits = arg->n_bits;
9199 action_arg->is_network_byte_order = a->args_endianness[action_arg_id];
9205 rte_swx_ctl_table_info_get(struct rte_swx_pipeline *p,
9207 struct rte_swx_ctl_table_info *table)
9209 struct table *t = NULL;
9214 t = table_find_by_id(p, table_id);
9218 strcpy(table->name, t->name);
9219 strcpy(table->args, t->args);
9220 table->n_match_fields = t->n_fields;
9221 table->n_actions = t->n_actions;
9222 table->default_action_is_const = t->default_action_is_const;
9223 table->size = t->size;
9228 rte_swx_ctl_table_match_field_info_get(struct rte_swx_pipeline *p,
9230 uint32_t match_field_id,
9231 struct rte_swx_ctl_table_match_field_info *match_field)
9234 struct match_field *f;
9236 if (!p || (table_id >= p->n_tables) || !match_field)
9239 t = table_find_by_id(p, table_id);
9240 if (!t || (match_field_id >= t->n_fields))
9243 f = &t->fields[match_field_id];
9244 match_field->match_type = f->match_type;
9245 match_field->is_header = t->header ? 1 : 0;
9246 match_field->n_bits = f->field->n_bits;
9247 match_field->offset = f->field->offset;
9253 rte_swx_ctl_table_action_info_get(struct rte_swx_pipeline *p,
9255 uint32_t table_action_id,
9256 struct rte_swx_ctl_table_action_info *table_action)
9260 if (!p || (table_id >= p->n_tables) || !table_action)
9263 t = table_find_by_id(p, table_id);
9264 if (!t || (table_action_id >= t->n_actions))
9267 table_action->action_id = t->actions[table_action_id]->id;
9273 rte_swx_ctl_table_ops_get(struct rte_swx_pipeline *p,
9275 struct rte_swx_table_ops *table_ops,
9280 if (!p || (table_id >= p->n_tables))
9283 t = table_find_by_id(p, table_id);
9289 memcpy(table_ops, &t->type->ops, sizeof(*table_ops));
9299 rte_swx_ctl_selector_info_get(struct rte_swx_pipeline *p,
9300 uint32_t selector_id,
9301 struct rte_swx_ctl_selector_info *selector)
9303 struct selector *s = NULL;
9305 if (!p || !selector)
9308 s = selector_find_by_id(p, selector_id);
9312 strcpy(selector->name, s->name);
9314 selector->n_selector_fields = s->n_selector_fields;
9315 selector->n_groups_max = s->n_groups_max;
9316 selector->n_members_per_group_max = s->n_members_per_group_max;
9322 rte_swx_ctl_selector_group_id_field_info_get(struct rte_swx_pipeline *p,
9323 uint32_t selector_id,
9324 struct rte_swx_ctl_table_match_field_info *field)
9328 if (!p || (selector_id >= p->n_selectors) || !field)
9331 s = selector_find_by_id(p, selector_id);
9335 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
9336 field->is_header = 0;
9337 field->n_bits = s->group_id_field->n_bits;
9338 field->offset = s->group_id_field->offset;
9344 rte_swx_ctl_selector_field_info_get(struct rte_swx_pipeline *p,
9345 uint32_t selector_id,
9346 uint32_t selector_field_id,
9347 struct rte_swx_ctl_table_match_field_info *field)
9352 if (!p || (selector_id >= p->n_selectors) || !field)
9355 s = selector_find_by_id(p, selector_id);
9356 if (!s || (selector_field_id >= s->n_selector_fields))
9359 f = s->selector_fields[selector_field_id];
9360 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
9361 field->is_header = s->selector_header ? 1 : 0;
9362 field->n_bits = f->n_bits;
9363 field->offset = f->offset;
9369 rte_swx_ctl_selector_member_id_field_info_get(struct rte_swx_pipeline *p,
9370 uint32_t selector_id,
9371 struct rte_swx_ctl_table_match_field_info *field)
9375 if (!p || (selector_id >= p->n_selectors) || !field)
9378 s = selector_find_by_id(p, selector_id);
9382 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
9383 field->is_header = 0;
9384 field->n_bits = s->member_id_field->n_bits;
9385 field->offset = s->member_id_field->offset;
9391 rte_swx_ctl_learner_info_get(struct rte_swx_pipeline *p,
9392 uint32_t learner_id,
9393 struct rte_swx_ctl_learner_info *learner)
9395 struct learner *l = NULL;
9400 l = learner_find_by_id(p, learner_id);
9404 strcpy(learner->name, l->name);
9406 learner->n_match_fields = l->n_fields;
9407 learner->n_actions = l->n_actions;
9408 learner->default_action_is_const = l->default_action_is_const;
9409 learner->size = l->size;
9415 rte_swx_ctl_learner_match_field_info_get(struct rte_swx_pipeline *p,
9416 uint32_t learner_id,
9417 uint32_t match_field_id,
9418 struct rte_swx_ctl_table_match_field_info *match_field)
9423 if (!p || (learner_id >= p->n_learners) || !match_field)
9426 l = learner_find_by_id(p, learner_id);
9427 if (!l || (match_field_id >= l->n_fields))
9430 f = l->fields[match_field_id];
9431 match_field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
9432 match_field->is_header = l->header ? 1 : 0;
9433 match_field->n_bits = f->n_bits;
9434 match_field->offset = f->offset;
9440 rte_swx_ctl_learner_action_info_get(struct rte_swx_pipeline *p,
9441 uint32_t learner_id,
9442 uint32_t learner_action_id,
9443 struct rte_swx_ctl_table_action_info *learner_action)
9447 if (!p || (learner_id >= p->n_learners) || !learner_action)
9450 l = learner_find_by_id(p, learner_id);
9451 if (!l || (learner_action_id >= l->n_actions))
9454 learner_action->action_id = l->actions[learner_action_id]->id;
9460 rte_swx_pipeline_table_state_get(struct rte_swx_pipeline *p,
9461 struct rte_swx_table_state **table_state)
9463 if (!p || !table_state || !p->build_done)
9466 *table_state = p->table_state;
9471 rte_swx_pipeline_table_state_set(struct rte_swx_pipeline *p,
9472 struct rte_swx_table_state *table_state)
9474 if (!p || !table_state || !p->build_done)
9477 p->table_state = table_state;
9482 rte_swx_ctl_pipeline_port_in_stats_read(struct rte_swx_pipeline *p,
9484 struct rte_swx_port_in_stats *stats)
9486 struct port_in *port;
9491 port = port_in_find(p, port_id);
9495 port->type->ops.stats_read(port->obj, stats);
9500 rte_swx_ctl_pipeline_port_out_stats_read(struct rte_swx_pipeline *p,
9502 struct rte_swx_port_out_stats *stats)
9504 struct port_out *port;
9509 port = port_out_find(p, port_id);
9513 port->type->ops.stats_read(port->obj, stats);
9518 rte_swx_ctl_pipeline_table_stats_read(struct rte_swx_pipeline *p,
9519 const char *table_name,
9520 struct rte_swx_table_stats *stats)
9522 struct table *table;
9523 struct table_statistics *table_stats;
9525 if (!p || !table_name || !table_name[0] || !stats || !stats->n_pkts_action)
9528 table = table_find(p, table_name);
9532 table_stats = &p->table_stats[table->id];
9534 memcpy(stats->n_pkts_action,
9535 table_stats->n_pkts_action,
9536 p->n_actions * sizeof(uint64_t));
9538 stats->n_pkts_hit = table_stats->n_pkts_hit[1];
9539 stats->n_pkts_miss = table_stats->n_pkts_hit[0];
9545 rte_swx_ctl_pipeline_selector_stats_read(struct rte_swx_pipeline *p,
9546 const char *selector_name,
9547 struct rte_swx_pipeline_selector_stats *stats)
9551 if (!p || !selector_name || !selector_name[0] || !stats)
9554 s = selector_find(p, selector_name);
9558 stats->n_pkts = p->selector_stats[s->id].n_pkts;
9564 rte_swx_ctl_pipeline_learner_stats_read(struct rte_swx_pipeline *p,
9565 const char *learner_name,
9566 struct rte_swx_learner_stats *stats)
9569 struct learner_statistics *learner_stats;
9571 if (!p || !learner_name || !learner_name[0] || !stats || !stats->n_pkts_action)
9574 l = learner_find(p, learner_name);
9578 learner_stats = &p->learner_stats[l->id];
9580 memcpy(stats->n_pkts_action,
9581 learner_stats->n_pkts_action,
9582 p->n_actions * sizeof(uint64_t));
9584 stats->n_pkts_hit = learner_stats->n_pkts_hit[1];
9585 stats->n_pkts_miss = learner_stats->n_pkts_hit[0];
9587 stats->n_pkts_learn_ok = learner_stats->n_pkts_learn[0];
9588 stats->n_pkts_learn_err = learner_stats->n_pkts_learn[1];
9590 stats->n_pkts_forget = learner_stats->n_pkts_forget;
9596 rte_swx_ctl_regarray_info_get(struct rte_swx_pipeline *p,
9597 uint32_t regarray_id,
9598 struct rte_swx_ctl_regarray_info *regarray)
9602 if (!p || !regarray)
9605 r = regarray_find_by_id(p, regarray_id);
9609 strcpy(regarray->name, r->name);
9610 regarray->size = r->size;
9615 rte_swx_ctl_pipeline_regarray_read(struct rte_swx_pipeline *p,
9616 const char *regarray_name,
9617 uint32_t regarray_index,
9620 struct regarray *regarray;
9621 struct regarray_runtime *r;
9623 if (!p || !regarray_name || !value)
9626 regarray = regarray_find(p, regarray_name);
9627 if (!regarray || (regarray_index >= regarray->size))
9630 r = &p->regarray_runtime[regarray->id];
9631 *value = r->regarray[regarray_index];
9636 rte_swx_ctl_pipeline_regarray_write(struct rte_swx_pipeline *p,
9637 const char *regarray_name,
9638 uint32_t regarray_index,
9641 struct regarray *regarray;
9642 struct regarray_runtime *r;
9644 if (!p || !regarray_name)
9647 regarray = regarray_find(p, regarray_name);
9648 if (!regarray || (regarray_index >= regarray->size))
9651 r = &p->regarray_runtime[regarray->id];
9652 r->regarray[regarray_index] = value;
9657 rte_swx_ctl_metarray_info_get(struct rte_swx_pipeline *p,
9658 uint32_t metarray_id,
9659 struct rte_swx_ctl_metarray_info *metarray)
9663 if (!p || !metarray)
9666 m = metarray_find_by_id(p, metarray_id);
9670 strcpy(metarray->name, m->name);
9671 metarray->size = m->size;
9676 rte_swx_ctl_meter_profile_add(struct rte_swx_pipeline *p,
9678 struct rte_meter_trtcm_params *params)
9680 struct meter_profile *mp;
9684 CHECK_NAME(name, EINVAL);
9685 CHECK(params, EINVAL);
9686 CHECK(!meter_profile_find(p, name), EEXIST);
9688 /* Node allocation. */
9689 mp = calloc(1, sizeof(struct meter_profile));
9692 /* Node initialization. */
9693 strcpy(mp->name, name);
9694 memcpy(&mp->params, params, sizeof(struct rte_meter_trtcm_params));
9695 status = rte_meter_trtcm_profile_config(&mp->profile, params);
9701 /* Node add to tailq. */
9702 TAILQ_INSERT_TAIL(&p->meter_profiles, mp, node);
9708 rte_swx_ctl_meter_profile_delete(struct rte_swx_pipeline *p,
9711 struct meter_profile *mp;
9714 CHECK_NAME(name, EINVAL);
9716 mp = meter_profile_find(p, name);
9718 CHECK(!mp->n_users, EBUSY);
9720 /* Remove node from tailq. */
9721 TAILQ_REMOVE(&p->meter_profiles, mp, node);
9728 rte_swx_ctl_meter_reset(struct rte_swx_pipeline *p,
9729 const char *metarray_name,
9730 uint32_t metarray_index)
9732 struct meter_profile *mp_old;
9733 struct metarray *metarray;
9734 struct metarray_runtime *metarray_runtime;
9738 CHECK_NAME(metarray_name, EINVAL);
9740 metarray = metarray_find(p, metarray_name);
9741 CHECK(metarray, EINVAL);
9742 CHECK(metarray_index < metarray->size, EINVAL);
9744 metarray_runtime = &p->metarray_runtime[metarray->id];
9745 m = &metarray_runtime->metarray[metarray_index];
9746 mp_old = m->profile;
9756 rte_swx_ctl_meter_set(struct rte_swx_pipeline *p,
9757 const char *metarray_name,
9758 uint32_t metarray_index,
9759 const char *profile_name)
9761 struct meter_profile *mp, *mp_old;
9762 struct metarray *metarray;
9763 struct metarray_runtime *metarray_runtime;
9767 CHECK_NAME(metarray_name, EINVAL);
9769 metarray = metarray_find(p, metarray_name);
9770 CHECK(metarray, EINVAL);
9771 CHECK(metarray_index < metarray->size, EINVAL);
9773 mp = meter_profile_find(p, profile_name);
9776 metarray_runtime = &p->metarray_runtime[metarray->id];
9777 m = &metarray_runtime->metarray[metarray_index];
9778 mp_old = m->profile;
9780 memset(m, 0, sizeof(struct meter));
9781 rte_meter_trtcm_config(&m->m, &mp->profile);
9783 m->color_mask = RTE_COLORS;
9792 rte_swx_ctl_meter_stats_read(struct rte_swx_pipeline *p,
9793 const char *metarray_name,
9794 uint32_t metarray_index,
9795 struct rte_swx_ctl_meter_stats *stats)
9797 struct metarray *metarray;
9798 struct metarray_runtime *metarray_runtime;
9802 CHECK_NAME(metarray_name, EINVAL);
9804 metarray = metarray_find(p, metarray_name);
9805 CHECK(metarray, EINVAL);
9806 CHECK(metarray_index < metarray->size, EINVAL);
9808 CHECK(stats, EINVAL);
9810 metarray_runtime = &p->metarray_runtime[metarray->id];
9811 m = &metarray_runtime->metarray[metarray_index];
9813 memcpy(stats->n_pkts, m->n_pkts, sizeof(m->n_pkts));
9814 memcpy(stats->n_bytes, m->n_bytes, sizeof(m->n_bytes));
9820 * Pipeline compilation.
9823 instr_type_to_name(struct instruction *instr)
9825 switch (instr->type) {
9826 case INSTR_RX: return "INSTR_RX";
9828 case INSTR_TX: return "INSTR_TX";
9829 case INSTR_TX_I: return "INSTR_TX_I";
9831 case INSTR_HDR_EXTRACT: return "INSTR_HDR_EXTRACT";
9832 case INSTR_HDR_EXTRACT2: return "INSTR_HDR_EXTRACT2";
9833 case INSTR_HDR_EXTRACT3: return "INSTR_HDR_EXTRACT3";
9834 case INSTR_HDR_EXTRACT4: return "INSTR_HDR_EXTRACT4";
9835 case INSTR_HDR_EXTRACT5: return "INSTR_HDR_EXTRACT5";
9836 case INSTR_HDR_EXTRACT6: return "INSTR_HDR_EXTRACT6";
9837 case INSTR_HDR_EXTRACT7: return "INSTR_HDR_EXTRACT7";
9838 case INSTR_HDR_EXTRACT8: return "INSTR_HDR_EXTRACT8";
9840 case INSTR_HDR_EXTRACT_M: return "INSTR_HDR_EXTRACT_M";
9842 case INSTR_HDR_LOOKAHEAD: return "INSTR_HDR_LOOKAHEAD";
9844 case INSTR_HDR_EMIT: return "INSTR_HDR_EMIT";
9845 case INSTR_HDR_EMIT_TX: return "INSTR_HDR_EMIT_TX";
9846 case INSTR_HDR_EMIT2_TX: return "INSTR_HDR_EMIT2_TX";
9847 case INSTR_HDR_EMIT3_TX: return "INSTR_HDR_EMIT3_TX";
9848 case INSTR_HDR_EMIT4_TX: return "INSTR_HDR_EMIT4_TX";
9849 case INSTR_HDR_EMIT5_TX: return "INSTR_HDR_EMIT5_TX";
9850 case INSTR_HDR_EMIT6_TX: return "INSTR_HDR_EMIT6_TX";
9851 case INSTR_HDR_EMIT7_TX: return "INSTR_HDR_EMIT7_TX";
9852 case INSTR_HDR_EMIT8_TX: return "INSTR_HDR_EMIT8_TX";
9854 case INSTR_HDR_VALIDATE: return "INSTR_HDR_VALIDATE";
9855 case INSTR_HDR_INVALIDATE: return "INSTR_HDR_INVALIDATE";
9857 case INSTR_MOV: return "INSTR_MOV";
9858 case INSTR_MOV_MH: return "INSTR_MOV_MH";
9859 case INSTR_MOV_HM: return "INSTR_MOV_HM";
9860 case INSTR_MOV_HH: return "INSTR_MOV_HH";
9861 case INSTR_MOV_I: return "INSTR_MOV_I";
9863 case INSTR_DMA_HT: return "INSTR_DMA_HT";
9864 case INSTR_DMA_HT2: return "INSTR_DMA_HT2";
9865 case INSTR_DMA_HT3: return "INSTR_DMA_HT3";
9866 case INSTR_DMA_HT4: return "INSTR_DMA_HT4";
9867 case INSTR_DMA_HT5: return "INSTR_DMA_HT5";
9868 case INSTR_DMA_HT6: return "INSTR_DMA_HT6";
9869 case INSTR_DMA_HT7: return "INSTR_DMA_HT7";
9870 case INSTR_DMA_HT8: return "INSTR_DMA_HT8";
9872 case INSTR_ALU_ADD: return "INSTR_ALU_ADD";
9873 case INSTR_ALU_ADD_MH: return "INSTR_ALU_ADD_MH";
9874 case INSTR_ALU_ADD_HM: return "INSTR_ALU_ADD_HM";
9875 case INSTR_ALU_ADD_HH: return "INSTR_ALU_ADD_HH";
9876 case INSTR_ALU_ADD_MI: return "INSTR_ALU_ADD_MI";
9877 case INSTR_ALU_ADD_HI: return "INSTR_ALU_ADD_HI";
9879 case INSTR_ALU_SUB: return "INSTR_ALU_SUB";
9880 case INSTR_ALU_SUB_MH: return "INSTR_ALU_SUB_MH";
9881 case INSTR_ALU_SUB_HM: return "INSTR_ALU_SUB_HM";
9882 case INSTR_ALU_SUB_HH: return "INSTR_ALU_SUB_HH";
9883 case INSTR_ALU_SUB_MI: return "INSTR_ALU_SUB_MI";
9884 case INSTR_ALU_SUB_HI: return "INSTR_ALU_SUB_HI";
9886 case INSTR_ALU_CKADD_FIELD: return "INSTR_ALU_CKADD_FIELD";
9887 case INSTR_ALU_CKADD_STRUCT20: return "INSTR_ALU_CKADD_STRUCT20";
9888 case INSTR_ALU_CKADD_STRUCT: return "INSTR_ALU_CKADD_STRUCT";
9889 case INSTR_ALU_CKSUB_FIELD: return "INSTR_ALU_CKSUB_FIELD";
9891 case INSTR_ALU_AND: return "INSTR_ALU_AND";
9892 case INSTR_ALU_AND_MH: return "INSTR_ALU_AND_MH";
9893 case INSTR_ALU_AND_HM: return "INSTR_ALU_AND_HM";
9894 case INSTR_ALU_AND_HH: return "INSTR_ALU_AND_HH";
9895 case INSTR_ALU_AND_I: return "INSTR_ALU_AND_I";
9897 case INSTR_ALU_OR: return "INSTR_ALU_OR";
9898 case INSTR_ALU_OR_MH: return "INSTR_ALU_OR_MH";
9899 case INSTR_ALU_OR_HM: return "INSTR_ALU_OR_HM";
9900 case INSTR_ALU_OR_HH: return "INSTR_ALU_OR_HH";
9901 case INSTR_ALU_OR_I: return "INSTR_ALU_OR_I";
9903 case INSTR_ALU_XOR: return "INSTR_ALU_XOR";
9904 case INSTR_ALU_XOR_MH: return "INSTR_ALU_XOR_MH";
9905 case INSTR_ALU_XOR_HM: return "INSTR_ALU_XOR_HM";
9906 case INSTR_ALU_XOR_HH: return "INSTR_ALU_XOR_HH";
9907 case INSTR_ALU_XOR_I: return "INSTR_ALU_XOR_I";
9909 case INSTR_ALU_SHL: return "INSTR_ALU_SHL";
9910 case INSTR_ALU_SHL_MH: return "INSTR_ALU_SHL_MH";
9911 case INSTR_ALU_SHL_HM: return "INSTR_ALU_SHL_HM";
9912 case INSTR_ALU_SHL_HH: return "INSTR_ALU_SHL_HH";
9913 case INSTR_ALU_SHL_MI: return "INSTR_ALU_SHL_MI";
9914 case INSTR_ALU_SHL_HI: return "INSTR_ALU_SHL_HI";
9916 case INSTR_ALU_SHR: return "INSTR_ALU_SHR";
9917 case INSTR_ALU_SHR_MH: return "INSTR_ALU_SHR_MH";
9918 case INSTR_ALU_SHR_HM: return "INSTR_ALU_SHR_HM";
9919 case INSTR_ALU_SHR_HH: return "INSTR_ALU_SHR_HH";
9920 case INSTR_ALU_SHR_MI: return "INSTR_ALU_SHR_MI";
9921 case INSTR_ALU_SHR_HI: return "INSTR_ALU_SHR_HI";
9923 case INSTR_REGPREFETCH_RH: return "INSTR_REGPREFETCH_RH";
9924 case INSTR_REGPREFETCH_RM: return "INSTR_REGPREFETCH_RM";
9925 case INSTR_REGPREFETCH_RI: return "INSTR_REGPREFETCH_RI";
9927 case INSTR_REGRD_HRH: return "INSTR_REGRD_HRH";
9928 case INSTR_REGRD_HRM: return "INSTR_REGRD_HRM";
9929 case INSTR_REGRD_HRI: return "INSTR_REGRD_HRI";
9930 case INSTR_REGRD_MRH: return "INSTR_REGRD_MRH";
9931 case INSTR_REGRD_MRM: return "INSTR_REGRD_MRM";
9932 case INSTR_REGRD_MRI: return "INSTR_REGRD_MRI";
9934 case INSTR_REGWR_RHH: return "INSTR_REGWR_RHH";
9935 case INSTR_REGWR_RHM: return "INSTR_REGWR_RHM";
9936 case INSTR_REGWR_RHI: return "INSTR_REGWR_RHI";
9937 case INSTR_REGWR_RMH: return "INSTR_REGWR_RMH";
9938 case INSTR_REGWR_RMM: return "INSTR_REGWR_RMM";
9939 case INSTR_REGWR_RMI: return "INSTR_REGWR_RMI";
9940 case INSTR_REGWR_RIH: return "INSTR_REGWR_RIH";
9941 case INSTR_REGWR_RIM: return "INSTR_REGWR_RIM";
9942 case INSTR_REGWR_RII: return "INSTR_REGWR_RII";
9944 case INSTR_REGADD_RHH: return "INSTR_REGADD_RHH";
9945 case INSTR_REGADD_RHM: return "INSTR_REGADD_RHM";
9946 case INSTR_REGADD_RHI: return "INSTR_REGADD_RHI";
9947 case INSTR_REGADD_RMH: return "INSTR_REGADD_RMH";
9948 case INSTR_REGADD_RMM: return "INSTR_REGADD_RMM";
9949 case INSTR_REGADD_RMI: return "INSTR_REGADD_RMI";
9950 case INSTR_REGADD_RIH: return "INSTR_REGADD_RIH";
9951 case INSTR_REGADD_RIM: return "INSTR_REGADD_RIM";
9952 case INSTR_REGADD_RII: return "INSTR_REGADD_RII";
9954 case INSTR_METPREFETCH_H: return "INSTR_METPREFETCH_H";
9955 case INSTR_METPREFETCH_M: return "INSTR_METPREFETCH_M";
9956 case INSTR_METPREFETCH_I: return "INSTR_METPREFETCH_I";
9958 case INSTR_METER_HHM: return "INSTR_METER_HHM";
9959 case INSTR_METER_HHI: return "INSTR_METER_HHI";
9960 case INSTR_METER_HMM: return "INSTR_METER_HMM";
9961 case INSTR_METER_HMI: return "INSTR_METER_HMI";
9962 case INSTR_METER_MHM: return "INSTR_METER_MHM";
9963 case INSTR_METER_MHI: return "INSTR_METER_MHI";
9964 case INSTR_METER_MMM: return "INSTR_METER_MMM";
9965 case INSTR_METER_MMI: return "INSTR_METER_MMI";
9966 case INSTR_METER_IHM: return "INSTR_METER_IHM";
9967 case INSTR_METER_IHI: return "INSTR_METER_IHI";
9968 case INSTR_METER_IMM: return "INSTR_METER_IMM";
9969 case INSTR_METER_IMI: return "INSTR_METER_IMI";
9971 case INSTR_TABLE: return "INSTR_TABLE";
9972 case INSTR_TABLE_AF: return "INSTR_TABLE_AF";
9973 case INSTR_SELECTOR: return "INSTR_SELECTOR";
9974 case INSTR_LEARNER: return "INSTR_LEARNER";
9975 case INSTR_LEARNER_AF: return "INSTR_LEARNER_AF";
9977 case INSTR_LEARNER_LEARN: return "INSTR_LEARNER_LEARN";
9978 case INSTR_LEARNER_FORGET: return "INSTR_LEARNER_FORGET";
9980 case INSTR_EXTERN_OBJ: return "INSTR_EXTERN_OBJ";
9981 case INSTR_EXTERN_FUNC: return "INSTR_EXTERN_FUNC";
9983 case INSTR_JMP: return "INSTR_JMP";
9984 case INSTR_JMP_VALID: return "INSTR_JMP_VALID";
9985 case INSTR_JMP_INVALID: return "INSTR_JMP_INVALID";
9986 case INSTR_JMP_HIT: return "INSTR_JMP_HIT";
9987 case INSTR_JMP_MISS: return "INSTR_JMP_MISS";
9988 case INSTR_JMP_ACTION_HIT: return "INSTR_JMP_ACTION_HIT";
9989 case INSTR_JMP_ACTION_MISS: return "INSTR_JMP_ACTION_MISS";
9990 case INSTR_JMP_EQ: return "INSTR_JMP_EQ";
9991 case INSTR_JMP_EQ_MH: return "INSTR_JMP_EQ_MH";
9992 case INSTR_JMP_EQ_HM: return "INSTR_JMP_EQ_HM";
9993 case INSTR_JMP_EQ_HH: return "INSTR_JMP_EQ_HH";
9994 case INSTR_JMP_EQ_I: return "INSTR_JMP_EQ_I";
9995 case INSTR_JMP_NEQ: return "INSTR_JMP_NEQ";
9996 case INSTR_JMP_NEQ_MH: return "INSTR_JMP_NEQ_MH";
9997 case INSTR_JMP_NEQ_HM: return "INSTR_JMP_NEQ_HM";
9998 case INSTR_JMP_NEQ_HH: return "INSTR_JMP_NEQ_HH";
9999 case INSTR_JMP_NEQ_I: return "INSTR_JMP_NEQ_I";
10000 case INSTR_JMP_LT: return "INSTR_JMP_LT";
10001 case INSTR_JMP_LT_MH: return "INSTR_JMP_LT_MH";
10002 case INSTR_JMP_LT_HM: return "INSTR_JMP_LT_HM";
10003 case INSTR_JMP_LT_HH: return "INSTR_JMP_LT_HH";
10004 case INSTR_JMP_LT_MI: return "INSTR_JMP_LT_MI";
10005 case INSTR_JMP_LT_HI: return "INSTR_JMP_LT_HI";
10006 case INSTR_JMP_GT: return "INSTR_JMP_GT";
10007 case INSTR_JMP_GT_MH: return "INSTR_JMP_GT_MH";
10008 case INSTR_JMP_GT_HM: return "INSTR_JMP_GT_HM";
10009 case INSTR_JMP_GT_HH: return "INSTR_JMP_GT_HH";
10010 case INSTR_JMP_GT_MI: return "INSTR_JMP_GT_MI";
10011 case INSTR_JMP_GT_HI: return "INSTR_JMP_GT_HI";
10013 case INSTR_RETURN: return "INSTR_RETURN";
10015 default: return "INSTR_UNKNOWN";
10020 (*instruction_export_t)(struct instruction *, FILE *);
10023 instr_io_export(struct instruction *instr, FILE *f)
10025 uint32_t n_io = 0, n_io_imm = 0, n_hdrs = 0, i;
10027 /* n_io, n_io_imm, n_hdrs. */
10028 if (instr->type == INSTR_RX ||
10029 instr->type == INSTR_TX ||
10030 instr->type == INSTR_HDR_EXTRACT_M ||
10031 (instr->type >= INSTR_HDR_EMIT_TX && instr->type <= INSTR_HDR_EMIT8_TX))
10034 if (instr->type == INSTR_TX_I)
10037 if (instr->type >= INSTR_HDR_EXTRACT && instr->type <= INSTR_HDR_EXTRACT8)
10038 n_hdrs = 1 + (instr->type - INSTR_HDR_EXTRACT);
10040 if (instr->type == INSTR_HDR_EXTRACT_M ||
10041 instr->type == INSTR_HDR_LOOKAHEAD ||
10042 instr->type == INSTR_HDR_EMIT)
10045 if (instr->type >= INSTR_HDR_EMIT_TX && instr->type <= INSTR_HDR_EMIT8_TX)
10046 n_hdrs = 1 + (instr->type - INSTR_HDR_EMIT_TX);
10051 "\t\t.type = %s,\n",
10052 instr_type_to_name(instr));
10062 "\t\t\t\t.offset = %u,\n"
10063 "\t\t\t\t.n_bits = %u,\n"
10065 instr->io.io.offset,
10066 instr->io.io.n_bits);
10071 "\t\t\t\t.val = %u,\n"
10075 /* instr.io.hdr. */
10080 /* instr.io.hdr.header_id. */
10082 "\t\t\t.header_id = {");
10084 for (i = 0; i < n_hdrs; i++)
10087 instr->io.hdr.header_id[i]);
10092 /* instr.io.hdr.struct_id. */
10094 "\t\t\t.struct_id = {");
10096 for (i = 0; i < n_hdrs; i++)
10099 instr->io.hdr.struct_id[i]);
10104 /* instr.io.hdr.n_bytes. */
10106 "\t\t\t.n_bytes = {");
10108 for (i = 0; i < n_hdrs; i++)
10111 instr->io.hdr.n_bytes[i]);
10116 /* instr.io.hdr - closing curly brace. */
10121 /* instr.io - closing curly brace. */
10125 /* instr - closing curly brace. */
10131 instr_hdr_validate_export(struct instruction *instr, FILE *f)
10135 "\t\t.type = %s,\n"
10137 "\t\t\t.header_id = %u,\n"
10140 instr_type_to_name(instr),
10141 instr->valid.header_id);
10145 instr_mov_export(struct instruction *instr, FILE *f)
10147 if (instr->type != INSTR_MOV_I)
10150 "\t\t.type = %s,\n"
10153 "\t\t\t\t.struct_id = %u,\n"
10154 "\t\t\t\t.n_bits = %u,\n"
10155 "\t\t\t\t.offset = %u,\n"
10158 "\t\t\t\t.struct_id = %u,\n"
10159 "\t\t\t\t.n_bits = %u,\n"
10160 "\t\t\t\t.offset = %u,\n"
10164 instr_type_to_name(instr),
10165 instr->mov.dst.struct_id,
10166 instr->mov.dst.n_bits,
10167 instr->mov.dst.offset,
10168 instr->mov.src.struct_id,
10169 instr->mov.src.n_bits,
10170 instr->mov.src.offset);
10174 "\t\t.type = %s,\n"
10177 "\t\t\t\t.struct_id = %u,\n"
10178 "\t\t\t\t.n_bits = %u,\n"
10179 "\t\t\t\t.offset = %u,\n"
10181 "\t\t\t.src_val = %" PRIu64 ",\n"
10184 instr_type_to_name(instr),
10185 instr->mov.dst.struct_id,
10186 instr->mov.dst.n_bits,
10187 instr->mov.dst.offset,
10188 instr->mov.src_val);
10192 instr_dma_ht_export(struct instruction *instr, FILE *f)
10194 uint32_t n_dma = 0, i;
10197 n_dma = 1 + (instr->type - INSTR_DMA_HT);
10202 "\t\t.type = %s,\n",
10203 instr_type_to_name(instr));
10209 /* instr.dma.dst. */
10211 "\t\t\t.dst = {\n");
10213 /* instr.dma.dst.header_id. */
10215 "\t\t\t\t.header_id = {");
10217 for (i = 0; i < n_dma; i++)
10220 instr->dma.dst.header_id[i]);
10225 /* instr.dma.dst.struct_id. */
10227 "\t\t\t\t.struct_id = {");
10229 for (i = 0; i < n_dma; i++)
10232 instr->dma.dst.struct_id[i]);
10237 /* instr.dma.dst - closing curly brace. */
10241 /* instr.dma.src. */
10243 "\t\t\t.src = {\n");
10245 /* instr.dma.src.offset. */
10247 "\t\t\t\t.offset = {");
10249 for (i = 0; i < n_dma; i++)
10252 instr->dma.src.offset[i]);
10257 /* instr.dma.src - closing curly brace. */
10261 /* instr.dma.n_bytes. */
10263 "\t\t\t.n_bytes = {");
10265 for (i = 0; i < n_dma; i++)
10268 instr->dma.n_bytes[i]);
10273 /* instr.dma - closing curly brace. */
10277 /* instr - closing curly brace. */
10283 instr_alu_export(struct instruction *instr, FILE *f)
10287 if (instr->type == INSTR_ALU_ADD_MI ||
10288 instr->type == INSTR_ALU_ADD_HI ||
10289 instr->type == INSTR_ALU_SUB_MI ||
10290 instr->type == INSTR_ALU_SUB_HI ||
10291 instr->type == INSTR_ALU_SHL_MI ||
10292 instr->type == INSTR_ALU_SHL_HI ||
10293 instr->type == INSTR_ALU_SHR_MI ||
10294 instr->type == INSTR_ALU_SHR_HI ||
10295 instr->type == INSTR_ALU_AND_I ||
10296 instr->type == INSTR_ALU_OR_I ||
10297 instr->type == INSTR_ALU_XOR_I)
10303 "\t\t.type = %s,\n"
10306 "\t\t\t\t.struct_id = %u,\n"
10307 "\t\t\t\t.n_bits = %u,\n"
10308 "\t\t\t\t.offset = %u,\n"
10311 "\t\t\t\t.struct_id = %u,\n"
10312 "\t\t\t\t.n_bits = %u,\n"
10313 "\t\t\t\t.offset = %u,\n"
10317 instr_type_to_name(instr),
10318 instr->alu.dst.struct_id,
10319 instr->alu.dst.n_bits,
10320 instr->alu.dst.offset,
10321 instr->alu.src.struct_id,
10322 instr->alu.src.n_bits,
10323 instr->alu.src.offset);
10327 "\t\t.type = %s,\n"
10330 "\t\t\t\t.struct_id = %u,\n"
10331 "\t\t\t\t.n_bits = %u,\n"
10332 "\t\t\t\t.offset = %u,\n"
10334 "\t\t\t.src_val = %" PRIu64 ",\n"
10337 instr_type_to_name(instr),
10338 instr->alu.dst.struct_id,
10339 instr->alu.dst.n_bits,
10340 instr->alu.dst.offset,
10341 instr->alu.src_val);
10345 instr_reg_export(struct instruction *instr __rte_unused, FILE *f __rte_unused)
10347 int prefetch = 0, idx_imm = 0, src_imm = 0;
10349 if (instr->type == INSTR_REGPREFETCH_RH ||
10350 instr->type == INSTR_REGPREFETCH_RM ||
10351 instr->type == INSTR_REGPREFETCH_RI)
10354 /* index is the 3rd operand for the regrd instruction and the 2nd
10355 * operand for the regwr and regadd instructions.
10357 if (instr->type == INSTR_REGPREFETCH_RI ||
10358 instr->type == INSTR_REGRD_HRI ||
10359 instr->type == INSTR_REGRD_MRI ||
10360 instr->type == INSTR_REGWR_RIH ||
10361 instr->type == INSTR_REGWR_RIM ||
10362 instr->type == INSTR_REGWR_RII ||
10363 instr->type == INSTR_REGADD_RIH ||
10364 instr->type == INSTR_REGADD_RIM ||
10365 instr->type == INSTR_REGADD_RII)
10368 /* src is the 3rd operand for the regwr and regadd instructions. */
10369 if (instr->type == INSTR_REGWR_RHI ||
10370 instr->type == INSTR_REGWR_RMI ||
10371 instr->type == INSTR_REGWR_RII ||
10372 instr->type == INSTR_REGADD_RHI ||
10373 instr->type == INSTR_REGADD_RMI ||
10374 instr->type == INSTR_REGADD_RII)
10377 /* instr.regarray.regarray_id. */
10380 "\t\t.type = %s,\n"
10381 "\t\t.regarray = {\n"
10382 "\t\t\t.regarray_id = %u,\n",
10383 instr_type_to_name(instr),
10384 instr->regarray.regarray_id);
10386 /* instr.regarray.idx / instr.regarray.idx_val. */
10389 "\t\t\t\t.idx = {\n"
10390 "\t\t\t\t\t.struct_id = %u,\n"
10391 "\t\t\t\t\t.n_bits = %u,\n"
10392 "\t\t\t\t\t.offset = %u,\n"
10394 instr->regarray.idx.struct_id,
10395 instr->regarray.idx.n_bits,
10396 instr->regarray.idx.offset);
10399 "\t\t\t\t.idx_val = %u,\n",
10400 instr->regarray.idx_val);
10402 /* instr.regarray.dstsrc / instr.regarray.dstsrc_val. */
10406 "\t\t\t\t.dstsrc = {\n"
10407 "\t\t\t\t\t.struct_id = %u,\n"
10408 "\t\t\t\t\t.n_bits = %u,\n"
10409 "\t\t\t\t\t.offset = %u,\n"
10411 instr->regarray.dstsrc.struct_id,
10412 instr->regarray.dstsrc.n_bits,
10413 instr->regarray.dstsrc.offset);
10416 "\t\t\t\t.dstsrc_val = %" PRIu64 ",\n",
10417 instr->regarray.dstsrc_val);
10420 /* instr.regarray and instr - closing curly braces. */
10427 instr_meter_export(struct instruction *instr __rte_unused, FILE *f __rte_unused)
10429 int prefetch = 0, idx_imm = 0, color_in_imm = 0;
10431 if (instr->type == INSTR_METPREFETCH_H ||
10432 instr->type == INSTR_METPREFETCH_M ||
10433 instr->type == INSTR_METPREFETCH_I)
10437 if (instr->type == INSTR_METPREFETCH_I ||
10438 instr->type == INSTR_METER_IHM ||
10439 instr->type == INSTR_METER_IHI ||
10440 instr->type == INSTR_METER_IMM ||
10441 instr->type == INSTR_METER_IMI)
10444 /* color_in_imm. */
10445 if (instr->type == INSTR_METER_HHI ||
10446 instr->type == INSTR_METER_HMI ||
10447 instr->type == INSTR_METER_MHI ||
10448 instr->type == INSTR_METER_MMI ||
10449 instr->type == INSTR_METER_IHI ||
10450 instr->type == INSTR_METER_IMI)
10453 /* instr.meter.metarray_id. */
10456 "\t\t.type = %s,\n"
10458 "\t\t\t.metarray_id = %u,\n",
10459 instr_type_to_name(instr),
10460 instr->meter.metarray_id);
10462 /* instr.meter.idx / instr.meter.idx_val. */
10466 "\t\t\t\t.struct_id = %u,\n"
10467 "\t\t\t\t.n_bits = %u,\n"
10468 "\t\t\t\t.offset = %u,\n"
10470 instr->meter.idx.struct_id,
10471 instr->meter.idx.n_bits,
10472 instr->meter.idx.offset);
10475 "\t\t\t.idx_val = %u,\n",
10476 instr->meter.idx_val);
10479 /* instr.meter.length. */
10481 "\t\t\t.length = {\n"
10482 "\t\t\t\t.struct_id = %u,\n"
10483 "\t\t\t\t.n_bits = %u,\n"
10484 "\t\t\t\t.offset = %u,\n"
10486 instr->meter.length.struct_id,
10487 instr->meter.length.n_bits,
10488 instr->meter.length.offset);
10490 /* instr.meter.color_in / instr.meter.color_in_val. */
10493 "\t\t\t.color_in = {\n"
10494 "\t\t\t\t.struct_id = %u,\n"
10495 "\t\t\t\t.n_bits = %u,\n"
10496 "\t\t\t\t.offset = %u,\n"
10498 instr->meter.color_in.struct_id,
10499 instr->meter.color_in.n_bits,
10500 instr->meter.color_in.offset);
10503 "\t\t\t.color_in_val = %u,\n",
10504 (uint32_t)instr->meter.color_in_val);
10506 /* instr.meter.color_out. */
10508 "\t\t\t.color_out = {\n"
10509 "\t\t\t\t.struct_id = %u,\n"
10510 "\t\t\t\t.n_bits = %u,\n"
10511 "\t\t\t\t.offset = %u,\n"
10513 instr->meter.color_out.struct_id,
10514 instr->meter.color_out.n_bits,
10515 instr->meter.color_out.offset);
10518 /* instr.meter and instr - closing curly braces. */
10525 instr_table_export(struct instruction *instr,
10530 "\t\t.type = %s,\n"
10532 "\t\t\t.table_id = %u,\n"
10535 instr_type_to_name(instr),
10536 instr->table.table_id);
10540 instr_learn_export(struct instruction *instr, FILE *f)
10544 "\t\t.type = %s,\n"
10546 "\t\t\t\t.action_id = %u,\n"
10549 instr_type_to_name(instr),
10550 instr->learn.action_id);
10554 instr_forget_export(struct instruction *instr, FILE *f)
10558 "\t\t.type = %s,\n"
10560 instr_type_to_name(instr));
10564 instr_extern_export(struct instruction *instr, FILE *f)
10566 if (instr->type == INSTR_EXTERN_OBJ)
10569 "\t\t.type = %s,\n"
10570 "\t\t.ext_obj = {\n"
10571 "\t\t\t.ext_obj_id = %u,\n"
10572 "\t\t\t.func_id = %u,\n"
10575 instr_type_to_name(instr),
10576 instr->ext_obj.ext_obj_id,
10577 instr->ext_obj.func_id);
10581 "\t\t.type = %s,\n"
10582 "\t\t.ext_func = {\n"
10583 "\t\t\t.ext_func_id = %u,\n"
10586 instr_type_to_name(instr),
10587 instr->ext_func.ext_func_id);
10591 instr_jmp_export(struct instruction *instr, FILE *f __rte_unused)
10595 "\t\t.type = %s,\n"
10597 "\t\t\t.ip = NULL,\n",
10598 instr_type_to_name(instr));
10600 switch (instr->type) {
10601 case INSTR_JMP_VALID:
10602 case INSTR_JMP_INVALID:
10604 "\t\t\t.header_id = %u,\n",
10605 instr->jmp.header_id);
10608 case INSTR_JMP_ACTION_HIT:
10609 case INSTR_JMP_ACTION_MISS:
10611 "\t\t\t.action_id = %u,\n",
10612 instr->jmp.action_id);
10616 case INSTR_JMP_EQ_MH:
10617 case INSTR_JMP_EQ_HM:
10618 case INSTR_JMP_EQ_HH:
10619 case INSTR_JMP_NEQ:
10620 case INSTR_JMP_NEQ_MH:
10621 case INSTR_JMP_NEQ_HM:
10622 case INSTR_JMP_NEQ_HH:
10624 case INSTR_JMP_LT_MH:
10625 case INSTR_JMP_LT_HM:
10626 case INSTR_JMP_LT_HH:
10628 case INSTR_JMP_GT_MH:
10629 case INSTR_JMP_GT_HM:
10630 case INSTR_JMP_GT_HH:
10633 "\t\t\t\t.struct_id = %u,\n"
10634 "\t\t\t\t.n_bits = %u,\n"
10635 "\t\t\t\t.offset = %u,\n"
10638 "\t\t\t\t.struct_id = %u,\n"
10639 "\t\t\t\t.n_bits = %u,\n"
10640 "\t\t\t\t.offset = %u,\n"
10642 instr->jmp.a.struct_id,
10643 instr->jmp.a.n_bits,
10644 instr->jmp.a.offset,
10645 instr->jmp.b.struct_id,
10646 instr->jmp.b.n_bits,
10647 instr->jmp.b.offset);
10650 case INSTR_JMP_EQ_I:
10651 case INSTR_JMP_NEQ_I:
10652 case INSTR_JMP_LT_MI:
10653 case INSTR_JMP_LT_HI:
10654 case INSTR_JMP_GT_MI:
10655 case INSTR_JMP_GT_HI:
10658 "\t\t\t\t.struct_id = %u,\n"
10659 "\t\t\t\t.n_bits = %u,\n"
10660 "\t\t\t\t.offset = %u,\n"
10662 "\t\t\t.b_val = %" PRIu64 ",\n",
10663 instr->jmp.a.struct_id,
10664 instr->jmp.a.n_bits,
10665 instr->jmp.a.offset,
10679 instr_return_export(struct instruction *instr,
10684 "\t\t.type = %s,\n",
10685 instr_type_to_name(instr));
10691 static instruction_export_t export_table[] = {
10692 [INSTR_RX] = instr_io_export,
10694 [INSTR_TX] = instr_io_export,
10695 [INSTR_TX_I] = instr_io_export,
10697 [INSTR_HDR_EXTRACT] = instr_io_export,
10698 [INSTR_HDR_EXTRACT2] = instr_io_export,
10699 [INSTR_HDR_EXTRACT3] = instr_io_export,
10700 [INSTR_HDR_EXTRACT4] = instr_io_export,
10701 [INSTR_HDR_EXTRACT5] = instr_io_export,
10702 [INSTR_HDR_EXTRACT6] = instr_io_export,
10703 [INSTR_HDR_EXTRACT7] = instr_io_export,
10704 [INSTR_HDR_EXTRACT8] = instr_io_export,
10706 [INSTR_HDR_EXTRACT_M] = instr_io_export,
10708 [INSTR_HDR_LOOKAHEAD] = instr_io_export,
10710 [INSTR_HDR_EMIT] = instr_io_export,
10711 [INSTR_HDR_EMIT_TX] = instr_io_export,
10712 [INSTR_HDR_EMIT2_TX] = instr_io_export,
10713 [INSTR_HDR_EMIT3_TX] = instr_io_export,
10714 [INSTR_HDR_EMIT4_TX] = instr_io_export,
10715 [INSTR_HDR_EMIT5_TX] = instr_io_export,
10716 [INSTR_HDR_EMIT6_TX] = instr_io_export,
10717 [INSTR_HDR_EMIT7_TX] = instr_io_export,
10718 [INSTR_HDR_EMIT8_TX] = instr_io_export,
10720 [INSTR_HDR_VALIDATE] = instr_hdr_validate_export,
10721 [INSTR_HDR_INVALIDATE] = instr_hdr_validate_export,
10723 [INSTR_MOV] = instr_mov_export,
10724 [INSTR_MOV_MH] = instr_mov_export,
10725 [INSTR_MOV_HM] = instr_mov_export,
10726 [INSTR_MOV_HH] = instr_mov_export,
10727 [INSTR_MOV_I] = instr_mov_export,
10729 [INSTR_DMA_HT] = instr_dma_ht_export,
10730 [INSTR_DMA_HT2] = instr_dma_ht_export,
10731 [INSTR_DMA_HT3] = instr_dma_ht_export,
10732 [INSTR_DMA_HT4] = instr_dma_ht_export,
10733 [INSTR_DMA_HT5] = instr_dma_ht_export,
10734 [INSTR_DMA_HT6] = instr_dma_ht_export,
10735 [INSTR_DMA_HT7] = instr_dma_ht_export,
10736 [INSTR_DMA_HT8] = instr_dma_ht_export,
10738 [INSTR_ALU_ADD] = instr_alu_export,
10739 [INSTR_ALU_ADD_MH] = instr_alu_export,
10740 [INSTR_ALU_ADD_HM] = instr_alu_export,
10741 [INSTR_ALU_ADD_HH] = instr_alu_export,
10742 [INSTR_ALU_ADD_MI] = instr_alu_export,
10743 [INSTR_ALU_ADD_HI] = instr_alu_export,
10745 [INSTR_ALU_SUB] = instr_alu_export,
10746 [INSTR_ALU_SUB_MH] = instr_alu_export,
10747 [INSTR_ALU_SUB_HM] = instr_alu_export,
10748 [INSTR_ALU_SUB_HH] = instr_alu_export,
10749 [INSTR_ALU_SUB_MI] = instr_alu_export,
10750 [INSTR_ALU_SUB_HI] = instr_alu_export,
10752 [INSTR_ALU_CKADD_FIELD] = instr_alu_export,
10753 [INSTR_ALU_CKADD_STRUCT] = instr_alu_export,
10754 [INSTR_ALU_CKADD_STRUCT20] = instr_alu_export,
10755 [INSTR_ALU_CKSUB_FIELD] = instr_alu_export,
10757 [INSTR_ALU_AND] = instr_alu_export,
10758 [INSTR_ALU_AND_MH] = instr_alu_export,
10759 [INSTR_ALU_AND_HM] = instr_alu_export,
10760 [INSTR_ALU_AND_HH] = instr_alu_export,
10761 [INSTR_ALU_AND_I] = instr_alu_export,
10763 [INSTR_ALU_OR] = instr_alu_export,
10764 [INSTR_ALU_OR_MH] = instr_alu_export,
10765 [INSTR_ALU_OR_HM] = instr_alu_export,
10766 [INSTR_ALU_OR_HH] = instr_alu_export,
10767 [INSTR_ALU_OR_I] = instr_alu_export,
10769 [INSTR_ALU_XOR] = instr_alu_export,
10770 [INSTR_ALU_XOR_MH] = instr_alu_export,
10771 [INSTR_ALU_XOR_HM] = instr_alu_export,
10772 [INSTR_ALU_XOR_HH] = instr_alu_export,
10773 [INSTR_ALU_XOR_I] = instr_alu_export,
10775 [INSTR_ALU_SHL] = instr_alu_export,
10776 [INSTR_ALU_SHL_MH] = instr_alu_export,
10777 [INSTR_ALU_SHL_HM] = instr_alu_export,
10778 [INSTR_ALU_SHL_HH] = instr_alu_export,
10779 [INSTR_ALU_SHL_MI] = instr_alu_export,
10780 [INSTR_ALU_SHL_HI] = instr_alu_export,
10782 [INSTR_ALU_SHR] = instr_alu_export,
10783 [INSTR_ALU_SHR_MH] = instr_alu_export,
10784 [INSTR_ALU_SHR_HM] = instr_alu_export,
10785 [INSTR_ALU_SHR_HH] = instr_alu_export,
10786 [INSTR_ALU_SHR_MI] = instr_alu_export,
10787 [INSTR_ALU_SHR_HI] = instr_alu_export,
10789 [INSTR_REGPREFETCH_RH] = instr_reg_export,
10790 [INSTR_REGPREFETCH_RM] = instr_reg_export,
10791 [INSTR_REGPREFETCH_RI] = instr_reg_export,
10793 [INSTR_REGRD_HRH] = instr_reg_export,
10794 [INSTR_REGRD_HRM] = instr_reg_export,
10795 [INSTR_REGRD_MRH] = instr_reg_export,
10796 [INSTR_REGRD_MRM] = instr_reg_export,
10797 [INSTR_REGRD_HRI] = instr_reg_export,
10798 [INSTR_REGRD_MRI] = instr_reg_export,
10800 [INSTR_REGWR_RHH] = instr_reg_export,
10801 [INSTR_REGWR_RHM] = instr_reg_export,
10802 [INSTR_REGWR_RMH] = instr_reg_export,
10803 [INSTR_REGWR_RMM] = instr_reg_export,
10804 [INSTR_REGWR_RHI] = instr_reg_export,
10805 [INSTR_REGWR_RMI] = instr_reg_export,
10806 [INSTR_REGWR_RIH] = instr_reg_export,
10807 [INSTR_REGWR_RIM] = instr_reg_export,
10808 [INSTR_REGWR_RII] = instr_reg_export,
10810 [INSTR_REGADD_RHH] = instr_reg_export,
10811 [INSTR_REGADD_RHM] = instr_reg_export,
10812 [INSTR_REGADD_RMH] = instr_reg_export,
10813 [INSTR_REGADD_RMM] = instr_reg_export,
10814 [INSTR_REGADD_RHI] = instr_reg_export,
10815 [INSTR_REGADD_RMI] = instr_reg_export,
10816 [INSTR_REGADD_RIH] = instr_reg_export,
10817 [INSTR_REGADD_RIM] = instr_reg_export,
10818 [INSTR_REGADD_RII] = instr_reg_export,
10820 [INSTR_METPREFETCH_H] = instr_meter_export,
10821 [INSTR_METPREFETCH_M] = instr_meter_export,
10822 [INSTR_METPREFETCH_I] = instr_meter_export,
10824 [INSTR_METER_HHM] = instr_meter_export,
10825 [INSTR_METER_HHI] = instr_meter_export,
10826 [INSTR_METER_HMM] = instr_meter_export,
10827 [INSTR_METER_HMI] = instr_meter_export,
10828 [INSTR_METER_MHM] = instr_meter_export,
10829 [INSTR_METER_MHI] = instr_meter_export,
10830 [INSTR_METER_MMM] = instr_meter_export,
10831 [INSTR_METER_MMI] = instr_meter_export,
10832 [INSTR_METER_IHM] = instr_meter_export,
10833 [INSTR_METER_IHI] = instr_meter_export,
10834 [INSTR_METER_IMM] = instr_meter_export,
10835 [INSTR_METER_IMI] = instr_meter_export,
10837 [INSTR_TABLE] = instr_table_export,
10838 [INSTR_TABLE_AF] = instr_table_export,
10839 [INSTR_SELECTOR] = instr_table_export,
10840 [INSTR_LEARNER] = instr_table_export,
10841 [INSTR_LEARNER_AF] = instr_table_export,
10843 [INSTR_LEARNER_LEARN] = instr_learn_export,
10844 [INSTR_LEARNER_FORGET] = instr_forget_export,
10846 [INSTR_EXTERN_OBJ] = instr_extern_export,
10847 [INSTR_EXTERN_FUNC] = instr_extern_export,
10849 [INSTR_JMP] = instr_jmp_export,
10850 [INSTR_JMP_VALID] = instr_jmp_export,
10851 [INSTR_JMP_INVALID] = instr_jmp_export,
10852 [INSTR_JMP_HIT] = instr_jmp_export,
10853 [INSTR_JMP_MISS] = instr_jmp_export,
10854 [INSTR_JMP_ACTION_HIT] = instr_jmp_export,
10855 [INSTR_JMP_ACTION_MISS] = instr_jmp_export,
10857 [INSTR_JMP_EQ] = instr_jmp_export,
10858 [INSTR_JMP_EQ_MH] = instr_jmp_export,
10859 [INSTR_JMP_EQ_HM] = instr_jmp_export,
10860 [INSTR_JMP_EQ_HH] = instr_jmp_export,
10861 [INSTR_JMP_EQ_I] = instr_jmp_export,
10863 [INSTR_JMP_NEQ] = instr_jmp_export,
10864 [INSTR_JMP_NEQ_MH] = instr_jmp_export,
10865 [INSTR_JMP_NEQ_HM] = instr_jmp_export,
10866 [INSTR_JMP_NEQ_HH] = instr_jmp_export,
10867 [INSTR_JMP_NEQ_I] = instr_jmp_export,
10869 [INSTR_JMP_LT] = instr_jmp_export,
10870 [INSTR_JMP_LT_MH] = instr_jmp_export,
10871 [INSTR_JMP_LT_HM] = instr_jmp_export,
10872 [INSTR_JMP_LT_HH] = instr_jmp_export,
10873 [INSTR_JMP_LT_MI] = instr_jmp_export,
10874 [INSTR_JMP_LT_HI] = instr_jmp_export,
10876 [INSTR_JMP_GT] = instr_jmp_export,
10877 [INSTR_JMP_GT_MH] = instr_jmp_export,
10878 [INSTR_JMP_GT_HM] = instr_jmp_export,
10879 [INSTR_JMP_GT_HH] = instr_jmp_export,
10880 [INSTR_JMP_GT_MI] = instr_jmp_export,
10881 [INSTR_JMP_GT_HI] = instr_jmp_export,
10883 [INSTR_RETURN] = instr_return_export,
10887 action_data_codegen(struct action *a, FILE *f)
10892 "static const struct instruction action_%s_instructions[] = {\n",
10895 for (i = 0; i < a->n_instructions; i++) {
10896 struct instruction *instr = &a->instructions[i];
10897 instruction_export_t func = export_table[instr->type];
10902 fprintf(f, "};\n");
10905 static const char *
10906 instr_type_to_func(struct instruction *instr)
10908 switch (instr->type) {
10909 case INSTR_RX: return NULL;
10911 case INSTR_TX: return "__instr_tx_exec";
10912 case INSTR_TX_I: return "__instr_tx_i_exec";
10914 case INSTR_HDR_EXTRACT: return "__instr_hdr_extract_exec";
10915 case INSTR_HDR_EXTRACT2: return "__instr_hdr_extract2_exec";
10916 case INSTR_HDR_EXTRACT3: return "__instr_hdr_extract3_exec";
10917 case INSTR_HDR_EXTRACT4: return "__instr_hdr_extract4_exec";
10918 case INSTR_HDR_EXTRACT5: return "__instr_hdr_extract5_exec";
10919 case INSTR_HDR_EXTRACT6: return "__instr_hdr_extract6_exec";
10920 case INSTR_HDR_EXTRACT7: return "__instr_hdr_extract7_exec";
10921 case INSTR_HDR_EXTRACT8: return "__instr_hdr_extract8_exec";
10923 case INSTR_HDR_EXTRACT_M: return "__instr_hdr_extract_m_exec";
10925 case INSTR_HDR_LOOKAHEAD: return "__instr_hdr_lookahead_exec";
10927 case INSTR_HDR_EMIT: return "__instr_hdr_emit_exec";
10928 case INSTR_HDR_EMIT_TX: return "__instr_hdr_emit_tx_exec";
10929 case INSTR_HDR_EMIT2_TX: return "__instr_hdr_emit2_tx_exec";
10930 case INSTR_HDR_EMIT3_TX: return "__instr_hdr_emit3_tx_exec";
10931 case INSTR_HDR_EMIT4_TX: return "__instr_hdr_emit4_tx_exec";
10932 case INSTR_HDR_EMIT5_TX: return "__instr_hdr_emit5_tx_exec";
10933 case INSTR_HDR_EMIT6_TX: return "__instr_hdr_emit6_tx_exec";
10934 case INSTR_HDR_EMIT7_TX: return "__instr_hdr_emit7_tx_exec";
10935 case INSTR_HDR_EMIT8_TX: return "__instr_hdr_emit8_tx_exec";
10937 case INSTR_HDR_VALIDATE: return "__instr_hdr_validate_exec";
10938 case INSTR_HDR_INVALIDATE: return "__instr_hdr_invalidate_exec";
10940 case INSTR_MOV: return "__instr_mov_exec";
10941 case INSTR_MOV_MH: return "__instr_mov_mh_exec";
10942 case INSTR_MOV_HM: return "__instr_mov_hm_exec";
10943 case INSTR_MOV_HH: return "__instr_mov_hh_exec";
10944 case INSTR_MOV_I: return "__instr_mov_i_exec";
10946 case INSTR_DMA_HT: return "__instr_dma_ht_exec";
10947 case INSTR_DMA_HT2: return "__instr_dma_ht2_exec";
10948 case INSTR_DMA_HT3: return "__instr_dma_ht3_exec";
10949 case INSTR_DMA_HT4: return "__instr_dma_ht4_exec";
10950 case INSTR_DMA_HT5: return "__instr_dma_ht5_exec";
10951 case INSTR_DMA_HT6: return "__instr_dma_ht6_exec";
10952 case INSTR_DMA_HT7: return "__instr_dma_ht7_exec";
10953 case INSTR_DMA_HT8: return "__instr_dma_ht8_exec";
10955 case INSTR_ALU_ADD: return "__instr_alu_add_exec";
10956 case INSTR_ALU_ADD_MH: return "__instr_alu_add_mh_exec";
10957 case INSTR_ALU_ADD_HM: return "__instr_alu_add_hm_exec";
10958 case INSTR_ALU_ADD_HH: return "__instr_alu_add_hh_exec";
10959 case INSTR_ALU_ADD_MI: return "__instr_alu_add_mi_exec";
10960 case INSTR_ALU_ADD_HI: return "__instr_alu_add_hi_exec";
10962 case INSTR_ALU_SUB: return "__instr_alu_sub_exec";
10963 case INSTR_ALU_SUB_MH: return "__instr_alu_sub_mh_exec";
10964 case INSTR_ALU_SUB_HM: return "__instr_alu_sub_hm_exec";
10965 case INSTR_ALU_SUB_HH: return "__instr_alu_sub_hh_exec";
10966 case INSTR_ALU_SUB_MI: return "__instr_alu_sub_mi_exec";
10967 case INSTR_ALU_SUB_HI: return "__instr_alu_sub_hi_exec";
10969 case INSTR_ALU_CKADD_FIELD: return "__instr_alu_ckadd_field_exec";
10970 case INSTR_ALU_CKADD_STRUCT20: return "__instr_alu_ckadd_struct20_exec";
10971 case INSTR_ALU_CKADD_STRUCT: return "__instr_alu_ckadd_struct_exec";
10972 case INSTR_ALU_CKSUB_FIELD: return "__instr_alu_cksub_field_exec";
10974 case INSTR_ALU_AND: return "__instr_alu_and_exec";
10975 case INSTR_ALU_AND_MH: return "__instr_alu_and_mh_exec";
10976 case INSTR_ALU_AND_HM: return "__instr_alu_and_hm_exec";
10977 case INSTR_ALU_AND_HH: return "__instr_alu_and_hh_exec";
10978 case INSTR_ALU_AND_I: return "__instr_alu_and_i_exec";
10980 case INSTR_ALU_OR: return "__instr_alu_or_exec";
10981 case INSTR_ALU_OR_MH: return "__instr_alu_or_mh_exec";
10982 case INSTR_ALU_OR_HM: return "__instr_alu_or_hm_exec";
10983 case INSTR_ALU_OR_HH: return "__instr_alu_or_hh_exec";
10984 case INSTR_ALU_OR_I: return "__instr_alu_or_i_exec";
10986 case INSTR_ALU_XOR: return "__instr_alu_xor_exec";
10987 case INSTR_ALU_XOR_MH: return "__instr_alu_xor_mh_exec";
10988 case INSTR_ALU_XOR_HM: return "__instr_alu_xor_hm_exec";
10989 case INSTR_ALU_XOR_HH: return "__instr_alu_xor_hh_exec";
10990 case INSTR_ALU_XOR_I: return "__instr_alu_xor_i_exec";
10992 case INSTR_ALU_SHL: return "__instr_alu_shl_exec";
10993 case INSTR_ALU_SHL_MH: return "__instr_alu_shl_mh_exec";
10994 case INSTR_ALU_SHL_HM: return "__instr_alu_shl_hm_exec";
10995 case INSTR_ALU_SHL_HH: return "__instr_alu_shl_hh_exec";
10996 case INSTR_ALU_SHL_MI: return "__instr_alu_shl_mi_exec";
10997 case INSTR_ALU_SHL_HI: return "__instr_alu_shl_hi_exec";
10999 case INSTR_ALU_SHR: return "__instr_alu_shr_exec";
11000 case INSTR_ALU_SHR_MH: return "__instr_alu_shr_mh_exec";
11001 case INSTR_ALU_SHR_HM: return "__instr_alu_shr_hm_exec";
11002 case INSTR_ALU_SHR_HH: return "__instr_alu_shr_hh_exec";
11003 case INSTR_ALU_SHR_MI: return "__instr_alu_shr_mi_exec";
11004 case INSTR_ALU_SHR_HI: return "__instr_alu_shr_hi_exec";
11006 case INSTR_REGPREFETCH_RH: return "__instr_regprefetch_rh_exec";
11007 case INSTR_REGPREFETCH_RM: return "__instr_regprefetch_rm_exec";
11008 case INSTR_REGPREFETCH_RI: return "__instr_regprefetch_ri_exec";
11010 case INSTR_REGRD_HRH: return "__instr_regrd_hrh_exec";
11011 case INSTR_REGRD_HRM: return "__instr_regrd_hrm_exec";
11012 case INSTR_REGRD_HRI: return "__instr_regrd_hri_exec";
11013 case INSTR_REGRD_MRH: return "__instr_regrd_mrh_exec";
11014 case INSTR_REGRD_MRM: return "__instr_regrd_mrm_exec";
11015 case INSTR_REGRD_MRI: return "__instr_regrd_mri_exec";
11017 case INSTR_REGWR_RHH: return "__instr_regwr_rhh_exec";
11018 case INSTR_REGWR_RHM: return "__instr_regwr_rhm_exec";
11019 case INSTR_REGWR_RHI: return "__instr_regwr_rhi_exec";
11020 case INSTR_REGWR_RMH: return "__instr_regwr_rmh_exec";
11021 case INSTR_REGWR_RMM: return "__instr_regwr_rmm_exec";
11022 case INSTR_REGWR_RMI: return "__instr_regwr_rmi_exec";
11023 case INSTR_REGWR_RIH: return "__instr_regwr_rih_exec";
11024 case INSTR_REGWR_RIM: return "__instr_regwr_rim_exec";
11025 case INSTR_REGWR_RII: return "__instr_regwr_rii_exec";
11027 case INSTR_REGADD_RHH: return "__instr_regadd_rhh_exec";
11028 case INSTR_REGADD_RHM: return "__instr_regadd_rhm_exec";
11029 case INSTR_REGADD_RHI: return "__instr_regadd_rhi_exec";
11030 case INSTR_REGADD_RMH: return "__instr_regadd_rmh_exec";
11031 case INSTR_REGADD_RMM: return "__instr_regadd_rmm_exec";
11032 case INSTR_REGADD_RMI: return "__instr_regadd_rmi_exec";
11033 case INSTR_REGADD_RIH: return "__instr_regadd_rih_exec";
11034 case INSTR_REGADD_RIM: return "__instr_regadd_rim_exec";
11035 case INSTR_REGADD_RII: return "__instr_regadd_rii_exec";
11037 case INSTR_METPREFETCH_H: return "__instr_metprefetch_h_exec";
11038 case INSTR_METPREFETCH_M: return "__instr_metprefetch_m_exec";
11039 case INSTR_METPREFETCH_I: return "__instr_metprefetch_i_exec";
11041 case INSTR_METER_HHM: return "__instr_meter_hhm_exec";
11042 case INSTR_METER_HHI: return "__instr_meter_hhi_exec";
11043 case INSTR_METER_HMM: return "__instr_meter_hmm_exec";
11044 case INSTR_METER_HMI: return "__instr_meter_hmi_exec";
11045 case INSTR_METER_MHM: return "__instr_meter_mhm_exec";
11046 case INSTR_METER_MHI: return "__instr_meter_mhi_exec";
11047 case INSTR_METER_MMM: return "__instr_meter_mmm_exec";
11048 case INSTR_METER_MMI: return "__instr_meter_mmi_exec";
11049 case INSTR_METER_IHM: return "__instr_meter_ihm_exec";
11050 case INSTR_METER_IHI: return "__instr_meter_ihi_exec";
11051 case INSTR_METER_IMM: return "__instr_meter_imm_exec";
11052 case INSTR_METER_IMI: return "__instr_meter_imi_exec";
11054 case INSTR_TABLE: return NULL;
11055 case INSTR_TABLE_AF: return NULL;
11056 case INSTR_SELECTOR: return NULL;
11057 case INSTR_LEARNER: return NULL;
11058 case INSTR_LEARNER_AF: return NULL;
11060 case INSTR_LEARNER_LEARN: return "__instr_learn_exec";
11061 case INSTR_LEARNER_FORGET: return "__instr_forget_exec";
11063 case INSTR_EXTERN_OBJ: return NULL;
11064 case INSTR_EXTERN_FUNC: return NULL;
11066 case INSTR_JMP: return NULL;
11067 case INSTR_JMP_VALID: return NULL;
11068 case INSTR_JMP_INVALID: return NULL;
11069 case INSTR_JMP_HIT: return NULL;
11070 case INSTR_JMP_MISS: return NULL;
11071 case INSTR_JMP_ACTION_HIT: return NULL;
11072 case INSTR_JMP_ACTION_MISS: return NULL;
11073 case INSTR_JMP_EQ: return NULL;
11074 case INSTR_JMP_EQ_MH: return NULL;
11075 case INSTR_JMP_EQ_HM: return NULL;
11076 case INSTR_JMP_EQ_HH: return NULL;
11077 case INSTR_JMP_EQ_I: return NULL;
11078 case INSTR_JMP_NEQ: return NULL;
11079 case INSTR_JMP_NEQ_MH: return NULL;
11080 case INSTR_JMP_NEQ_HM: return NULL;
11081 case INSTR_JMP_NEQ_HH: return NULL;
11082 case INSTR_JMP_NEQ_I: return NULL;
11083 case INSTR_JMP_LT: return NULL;
11084 case INSTR_JMP_LT_MH: return NULL;
11085 case INSTR_JMP_LT_HM: return NULL;
11086 case INSTR_JMP_LT_HH: return NULL;
11087 case INSTR_JMP_LT_MI: return NULL;
11088 case INSTR_JMP_LT_HI: return NULL;
11089 case INSTR_JMP_GT: return NULL;
11090 case INSTR_JMP_GT_MH: return NULL;
11091 case INSTR_JMP_GT_HM: return NULL;
11092 case INSTR_JMP_GT_HH: return NULL;
11093 case INSTR_JMP_GT_MI: return NULL;
11094 case INSTR_JMP_GT_HI: return NULL;
11096 case INSTR_RETURN: return NULL;
11098 default: return NULL;
11103 action_instr_does_tx_codegen(struct action *a,
11104 uint32_t instr_pos,
11105 struct instruction *instr,
11109 "%s(p, t, &action_%s_instructions[%u]);\n"
11110 "\tthread_ip_reset(p, t);\n"
11111 "\tinstr_rx_exec(p);\n"
11113 instr_type_to_func(instr),
11119 action_instr_extern_obj_codegen(struct action *a,
11120 uint32_t instr_pos,
11124 "while (!__instr_extern_obj_exec(p, t, &action_%s_instructions[%u]));\n",
11130 action_instr_extern_func_codegen(struct action *a,
11131 uint32_t instr_pos,
11135 "while (!__instr_extern_func_exec(p, t, &action_%s_instructions[%u]));\n",
11141 action_instr_jmp_codegen(struct action *a,
11142 uint32_t instr_pos,
11143 struct instruction *instr,
11144 struct instruction_data *data,
11147 switch (instr->type) {
11154 case INSTR_JMP_VALID:
11156 "if (HEADER_VALID(t, action_%s_instructions[%u].jmp.header_id))\n"
11163 case INSTR_JMP_INVALID:
11165 "if (!HEADER_VALID(t, action_%s_instructions[%u].jmp.header_id))\n"
11172 case INSTR_JMP_HIT:
11179 case INSTR_JMP_MISS:
11186 case INSTR_JMP_ACTION_HIT:
11188 "if (t->action_id == action_%s_instructions[%u].jmp.action_id)\n"
11195 case INSTR_JMP_ACTION_MISS:
11197 "if (t->action_id != action_%s_instructions[%u].jmp.action_id)\n"
11206 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) == "
11207 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
11216 case INSTR_JMP_EQ_MH:
11218 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) == "
11219 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
11228 case INSTR_JMP_EQ_HM:
11230 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) == "
11231 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
11240 case INSTR_JMP_EQ_HH:
11242 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) == "
11243 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
11252 case INSTR_JMP_EQ_I:
11254 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) == "
11255 "action_%s_instructions[%u].jmp.b_val)\n"
11264 case INSTR_JMP_NEQ:
11266 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) != "
11267 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
11276 case INSTR_JMP_NEQ_MH:
11278 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) != "
11279 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
11288 case INSTR_JMP_NEQ_HM:
11290 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) != "
11291 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
11300 case INSTR_JMP_NEQ_HH:
11302 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) != "
11303 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
11312 case INSTR_JMP_NEQ_I:
11314 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) != "
11315 "action_%s_instructions[%u].jmp.b_val)\n"
11326 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) < "
11327 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
11336 case INSTR_JMP_LT_MH:
11338 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) < "
11339 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
11348 case INSTR_JMP_LT_HM:
11350 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) < "
11351 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
11360 case INSTR_JMP_LT_HH:
11362 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) < "
11363 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
11372 case INSTR_JMP_LT_MI:
11374 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) < "
11375 "action_%s_instructions[%u].jmp.b_val)\n"
11384 case INSTR_JMP_LT_HI:
11386 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) < "
11387 "action_%s_instructions[%u].jmp.b_val)\n"
11398 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) > "
11399 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
11408 case INSTR_JMP_GT_MH:
11410 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) > "
11411 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
11420 case INSTR_JMP_GT_HM:
11422 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) > "
11423 "instr_operand_hbo(t, &action_%s_instructions[%u].jmp.b))\n"
11432 case INSTR_JMP_GT_HH:
11434 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) > "
11435 "instr_operand_nbo(t, &action_%s_instructions[%u].jmp.b))\n"
11444 case INSTR_JMP_GT_MI:
11446 "if (instr_operand_hbo(t, &action_%s_instructions[%u].jmp.a) > "
11447 "action_%s_instructions[%u].jmp.b_val)\n"
11456 case INSTR_JMP_GT_HI:
11458 "if (instr_operand_nbo(t, &action_%s_instructions[%u].jmp.a) > "
11459 "action_%s_instructions[%u].jmp.b_val)\n"
11474 action_instr_return_codegen(FILE *f)
11481 action_instr_codegen(struct action *a, FILE *f)
11487 "action_%s_run(struct rte_swx_pipeline *p)\n"
11489 "\tstruct thread *t = &p->threads[p->thread_id];\n"
11493 for (i = 0; i < a->n_instructions; i++) {
11494 struct instruction *instr = &a->instructions[i];
11495 struct instruction_data *data = &a->instruction_data[i];
11497 /* Label, if present. */
11498 if (data->label[0])
11499 fprintf(f, "\n%s : ", data->label);
11501 fprintf(f, "\n\t");
11503 /* TX instruction type. */
11504 if (instruction_does_tx(instr)) {
11505 action_instr_does_tx_codegen(a, i, instr, f);
11509 /* Extern object/function instruction type. */
11510 if (instr->type == INSTR_EXTERN_OBJ) {
11511 action_instr_extern_obj_codegen(a, i, f);
11515 if (instr->type == INSTR_EXTERN_FUNC) {
11516 action_instr_extern_func_codegen(a, i, f);
11520 /* Jump instruction type. */
11521 if (instruction_is_jmp(instr)) {
11522 action_instr_jmp_codegen(a, i, instr, data, f);
11526 /* Return instruction type. */
11527 if (instr->type == INSTR_RETURN) {
11528 action_instr_return_codegen(f);
11532 /* Any other instruction type. */
11534 "%s(p, t, &action_%s_instructions[%u]);\n",
11535 instr_type_to_func(instr),
11540 fprintf(f, "}\n\n");
11544 pipeline_codegen(struct rte_swx_pipeline *p)
11552 /* Create the .c file. */
11553 f = fopen("/tmp/pipeline.c", "w");
11557 /* Include the .h file. */
11558 fprintf(f, "#include \"rte_swx_pipeline_internal.h\"\n");
11560 /* Add the code for each action. */
11561 TAILQ_FOREACH(a, &p->actions, node) {
11562 fprintf(f, "/**\n * Action %s\n */\n\n", a->name);
11564 action_data_codegen(a, f);
11568 action_instr_codegen(a, f);
11573 /* Close the .c file. */
11580 pipeline_compile(struct rte_swx_pipeline *p)
11584 /* Code generation. */
11585 status = pipeline_codegen(p);