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_is_jmp(struct instruction *instr)
1382 switch (instr->type) {
1384 case INSTR_JMP_VALID:
1385 case INSTR_JMP_INVALID:
1387 case INSTR_JMP_MISS:
1388 case INSTR_JMP_ACTION_HIT:
1389 case INSTR_JMP_ACTION_MISS:
1391 case INSTR_JMP_EQ_MH:
1392 case INSTR_JMP_EQ_HM:
1393 case INSTR_JMP_EQ_HH:
1394 case INSTR_JMP_EQ_I:
1396 case INSTR_JMP_NEQ_MH:
1397 case INSTR_JMP_NEQ_HM:
1398 case INSTR_JMP_NEQ_HH:
1399 case INSTR_JMP_NEQ_I:
1401 case INSTR_JMP_LT_MH:
1402 case INSTR_JMP_LT_HM:
1403 case INSTR_JMP_LT_HH:
1404 case INSTR_JMP_LT_MI:
1405 case INSTR_JMP_LT_HI:
1407 case INSTR_JMP_GT_MH:
1408 case INSTR_JMP_GT_HM:
1409 case INSTR_JMP_GT_HH:
1410 case INSTR_JMP_GT_MI:
1411 case INSTR_JMP_GT_HI:
1419 static struct field *
1420 action_field_parse(struct action *action, const char *name);
1422 static struct field *
1423 struct_field_parse(struct rte_swx_pipeline *p,
1424 struct action *action,
1426 uint32_t *struct_id)
1433 struct header *header;
1435 f = header_field_parse(p, name, &header);
1439 *struct_id = header->struct_id;
1445 f = metadata_field_parse(p, name);
1449 *struct_id = p->metadata_struct_id;
1458 f = action_field_parse(action, name);
1468 struct extern_obj *obj;
1470 f = extern_obj_mailbox_field_parse(p, name, &obj);
1474 *struct_id = obj->struct_id;
1480 struct extern_func *func;
1482 f = extern_func_mailbox_field_parse(p, name, &func);
1486 *struct_id = func->struct_id;
1499 instr_rx_translate(struct rte_swx_pipeline *p,
1500 struct action *action,
1503 struct instruction *instr,
1504 struct instruction_data *data __rte_unused)
1508 CHECK(!action, EINVAL);
1509 CHECK(n_tokens == 2, EINVAL);
1511 f = metadata_field_parse(p, tokens[1]);
1514 instr->type = INSTR_RX;
1515 instr->io.io.offset = f->offset / 8;
1516 instr->io.io.n_bits = f->n_bits;
1524 instr_tx_translate(struct rte_swx_pipeline *p,
1525 struct action *action __rte_unused,
1528 struct instruction *instr,
1529 struct instruction_data *data __rte_unused)
1531 char *port = tokens[1];
1535 CHECK(n_tokens == 2, EINVAL);
1537 f = metadata_field_parse(p, port);
1539 instr->type = INSTR_TX;
1540 instr->io.io.offset = f->offset / 8;
1541 instr->io.io.n_bits = f->n_bits;
1546 port_val = strtoul(port, &port, 0);
1547 CHECK(!port[0], EINVAL);
1549 instr->type = INSTR_TX_I;
1550 instr->io.io.val = port_val;
1555 instr_drop_translate(struct rte_swx_pipeline *p,
1556 struct action *action __rte_unused,
1557 char **tokens __rte_unused,
1559 struct instruction *instr,
1560 struct instruction_data *data __rte_unused)
1562 CHECK(n_tokens == 1, EINVAL);
1565 instr->type = INSTR_TX_I;
1566 instr->io.io.val = p->n_ports_out - 1;
1571 instr_tx_exec(struct rte_swx_pipeline *p)
1573 struct thread *t = &p->threads[p->thread_id];
1574 struct instruction *ip = t->ip;
1576 __instr_tx_exec(p, t, ip);
1579 thread_ip_reset(p, t);
1584 instr_tx_i_exec(struct rte_swx_pipeline *p)
1586 struct thread *t = &p->threads[p->thread_id];
1587 struct instruction *ip = t->ip;
1589 __instr_tx_i_exec(p, t, ip);
1592 thread_ip_reset(p, t);
1600 instr_hdr_extract_translate(struct rte_swx_pipeline *p,
1601 struct action *action,
1604 struct instruction *instr,
1605 struct instruction_data *data __rte_unused)
1609 CHECK(!action, EINVAL);
1610 CHECK((n_tokens == 2) || (n_tokens == 3), EINVAL);
1612 h = header_parse(p, tokens[1]);
1615 if (n_tokens == 2) {
1616 CHECK(!h->st->var_size, EINVAL);
1618 instr->type = INSTR_HDR_EXTRACT;
1619 instr->io.hdr.header_id[0] = h->id;
1620 instr->io.hdr.struct_id[0] = h->struct_id;
1621 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
1625 CHECK(h->st->var_size, EINVAL);
1627 mf = metadata_field_parse(p, tokens[2]);
1629 CHECK(!mf->var_size, EINVAL);
1631 instr->type = INSTR_HDR_EXTRACT_M;
1632 instr->io.io.offset = mf->offset / 8;
1633 instr->io.io.n_bits = mf->n_bits;
1634 instr->io.hdr.header_id[0] = h->id;
1635 instr->io.hdr.struct_id[0] = h->struct_id;
1636 instr->io.hdr.n_bytes[0] = h->st->n_bits_min / 8;
1643 instr_hdr_lookahead_translate(struct rte_swx_pipeline *p,
1644 struct action *action,
1647 struct instruction *instr,
1648 struct instruction_data *data __rte_unused)
1652 CHECK(!action, EINVAL);
1653 CHECK(n_tokens == 2, EINVAL);
1655 h = header_parse(p, tokens[1]);
1657 CHECK(!h->st->var_size, EINVAL);
1659 instr->type = INSTR_HDR_LOOKAHEAD;
1660 instr->io.hdr.header_id[0] = h->id;
1661 instr->io.hdr.struct_id[0] = h->struct_id;
1662 instr->io.hdr.n_bytes[0] = 0; /* Unused. */
1668 instr_hdr_extract_exec(struct rte_swx_pipeline *p)
1670 struct thread *t = &p->threads[p->thread_id];
1671 struct instruction *ip = t->ip;
1673 __instr_hdr_extract_exec(p, t, ip);
1680 instr_hdr_extract2_exec(struct rte_swx_pipeline *p)
1682 struct thread *t = &p->threads[p->thread_id];
1683 struct instruction *ip = t->ip;
1685 __instr_hdr_extract2_exec(p, t, ip);
1692 instr_hdr_extract3_exec(struct rte_swx_pipeline *p)
1694 struct thread *t = &p->threads[p->thread_id];
1695 struct instruction *ip = t->ip;
1697 __instr_hdr_extract3_exec(p, t, ip);
1704 instr_hdr_extract4_exec(struct rte_swx_pipeline *p)
1706 struct thread *t = &p->threads[p->thread_id];
1707 struct instruction *ip = t->ip;
1709 __instr_hdr_extract4_exec(p, t, ip);
1716 instr_hdr_extract5_exec(struct rte_swx_pipeline *p)
1718 struct thread *t = &p->threads[p->thread_id];
1719 struct instruction *ip = t->ip;
1721 __instr_hdr_extract5_exec(p, t, ip);
1728 instr_hdr_extract6_exec(struct rte_swx_pipeline *p)
1730 struct thread *t = &p->threads[p->thread_id];
1731 struct instruction *ip = t->ip;
1733 __instr_hdr_extract6_exec(p, t, ip);
1740 instr_hdr_extract7_exec(struct rte_swx_pipeline *p)
1742 struct thread *t = &p->threads[p->thread_id];
1743 struct instruction *ip = t->ip;
1745 __instr_hdr_extract7_exec(p, t, ip);
1752 instr_hdr_extract8_exec(struct rte_swx_pipeline *p)
1754 struct thread *t = &p->threads[p->thread_id];
1755 struct instruction *ip = t->ip;
1757 __instr_hdr_extract8_exec(p, t, ip);
1764 instr_hdr_extract_m_exec(struct rte_swx_pipeline *p)
1766 struct thread *t = &p->threads[p->thread_id];
1767 struct instruction *ip = t->ip;
1769 __instr_hdr_extract_m_exec(p, t, ip);
1776 instr_hdr_lookahead_exec(struct rte_swx_pipeline *p)
1778 struct thread *t = &p->threads[p->thread_id];
1779 struct instruction *ip = t->ip;
1781 __instr_hdr_lookahead_exec(p, t, ip);
1791 instr_hdr_emit_translate(struct rte_swx_pipeline *p,
1792 struct action *action __rte_unused,
1795 struct instruction *instr,
1796 struct instruction_data *data __rte_unused)
1800 CHECK(n_tokens == 2, EINVAL);
1802 h = header_parse(p, tokens[1]);
1805 instr->type = INSTR_HDR_EMIT;
1806 instr->io.hdr.header_id[0] = h->id;
1807 instr->io.hdr.struct_id[0] = h->struct_id;
1808 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
1813 instr_hdr_emit_exec(struct rte_swx_pipeline *p)
1815 struct thread *t = &p->threads[p->thread_id];
1816 struct instruction *ip = t->ip;
1818 __instr_hdr_emit_exec(p, t, ip);
1825 instr_hdr_emit_tx_exec(struct rte_swx_pipeline *p)
1827 struct thread *t = &p->threads[p->thread_id];
1828 struct instruction *ip = t->ip;
1830 __instr_hdr_emit_tx_exec(p, t, ip);
1833 thread_ip_reset(p, t);
1838 instr_hdr_emit2_tx_exec(struct rte_swx_pipeline *p)
1840 struct thread *t = &p->threads[p->thread_id];
1841 struct instruction *ip = t->ip;
1843 __instr_hdr_emit2_tx_exec(p, t, ip);
1846 thread_ip_reset(p, t);
1851 instr_hdr_emit3_tx_exec(struct rte_swx_pipeline *p)
1853 struct thread *t = &p->threads[p->thread_id];
1854 struct instruction *ip = t->ip;
1856 __instr_hdr_emit3_tx_exec(p, t, ip);
1859 thread_ip_reset(p, t);
1864 instr_hdr_emit4_tx_exec(struct rte_swx_pipeline *p)
1866 struct thread *t = &p->threads[p->thread_id];
1867 struct instruction *ip = t->ip;
1869 __instr_hdr_emit4_tx_exec(p, t, ip);
1872 thread_ip_reset(p, t);
1877 instr_hdr_emit5_tx_exec(struct rte_swx_pipeline *p)
1879 struct thread *t = &p->threads[p->thread_id];
1880 struct instruction *ip = t->ip;
1882 __instr_hdr_emit5_tx_exec(p, t, ip);
1885 thread_ip_reset(p, t);
1890 instr_hdr_emit6_tx_exec(struct rte_swx_pipeline *p)
1892 struct thread *t = &p->threads[p->thread_id];
1893 struct instruction *ip = t->ip;
1895 __instr_hdr_emit6_tx_exec(p, t, ip);
1898 thread_ip_reset(p, t);
1903 instr_hdr_emit7_tx_exec(struct rte_swx_pipeline *p)
1905 struct thread *t = &p->threads[p->thread_id];
1906 struct instruction *ip = t->ip;
1908 __instr_hdr_emit7_tx_exec(p, t, ip);
1911 thread_ip_reset(p, t);
1916 instr_hdr_emit8_tx_exec(struct rte_swx_pipeline *p)
1918 struct thread *t = &p->threads[p->thread_id];
1919 struct instruction *ip = t->ip;
1921 __instr_hdr_emit8_tx_exec(p, t, ip);
1924 thread_ip_reset(p, t);
1932 instr_hdr_validate_translate(struct rte_swx_pipeline *p,
1933 struct action *action __rte_unused,
1936 struct instruction *instr,
1937 struct instruction_data *data __rte_unused)
1941 CHECK(n_tokens == 2, EINVAL);
1943 h = header_parse(p, tokens[1]);
1946 instr->type = INSTR_HDR_VALIDATE;
1947 instr->valid.header_id = h->id;
1952 instr_hdr_validate_exec(struct rte_swx_pipeline *p)
1954 struct thread *t = &p->threads[p->thread_id];
1955 struct instruction *ip = t->ip;
1957 __instr_hdr_validate_exec(p, t, ip);
1967 instr_hdr_invalidate_translate(struct rte_swx_pipeline *p,
1968 struct action *action __rte_unused,
1971 struct instruction *instr,
1972 struct instruction_data *data __rte_unused)
1976 CHECK(n_tokens == 2, EINVAL);
1978 h = header_parse(p, tokens[1]);
1981 instr->type = INSTR_HDR_INVALIDATE;
1982 instr->valid.header_id = h->id;
1987 instr_hdr_invalidate_exec(struct rte_swx_pipeline *p)
1989 struct thread *t = &p->threads[p->thread_id];
1990 struct instruction *ip = t->ip;
1992 __instr_hdr_invalidate_exec(p, t, ip);
2001 static struct table *
2002 table_find(struct rte_swx_pipeline *p, const char *name);
2004 static struct selector *
2005 selector_find(struct rte_swx_pipeline *p, const char *name);
2007 static struct learner *
2008 learner_find(struct rte_swx_pipeline *p, const char *name);
2011 instr_table_translate(struct rte_swx_pipeline *p,
2012 struct action *action,
2015 struct instruction *instr,
2016 struct instruction_data *data __rte_unused)
2022 CHECK(!action, EINVAL);
2023 CHECK(n_tokens == 2, EINVAL);
2025 t = table_find(p, tokens[1]);
2027 instr->type = INSTR_TABLE;
2028 instr->table.table_id = t->id;
2032 s = selector_find(p, tokens[1]);
2034 instr->type = INSTR_SELECTOR;
2035 instr->table.table_id = s->id;
2039 l = learner_find(p, tokens[1]);
2041 instr->type = INSTR_LEARNER;
2042 instr->table.table_id = l->id;
2050 instr_table_exec(struct rte_swx_pipeline *p)
2052 struct thread *t = &p->threads[p->thread_id];
2053 struct instruction *ip = t->ip;
2054 uint32_t table_id = ip->table.table_id;
2055 struct rte_swx_table_state *ts = &t->table_state[table_id];
2056 struct table_runtime *table = &t->tables[table_id];
2057 struct table_statistics *stats = &p->table_stats[table_id];
2058 uint64_t action_id, n_pkts_hit, n_pkts_action;
2059 uint8_t *action_data;
2063 done = table->func(ts->obj,
2071 TRACE("[Thread %2u] table %u (not finalized)\n",
2079 action_id = hit ? action_id : ts->default_action_id;
2080 action_data = hit ? action_data : ts->default_action_data;
2081 n_pkts_hit = stats->n_pkts_hit[hit];
2082 n_pkts_action = stats->n_pkts_action[action_id];
2084 TRACE("[Thread %2u] table %u (%s, action %u)\n",
2087 hit ? "hit" : "miss",
2088 (uint32_t)action_id);
2090 t->action_id = action_id;
2091 t->structs[0] = action_data;
2093 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2094 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2097 thread_ip_action_call(p, t, action_id);
2101 instr_selector_exec(struct rte_swx_pipeline *p)
2103 struct thread *t = &p->threads[p->thread_id];
2104 struct instruction *ip = t->ip;
2105 uint32_t selector_id = ip->table.table_id;
2106 struct rte_swx_table_state *ts = &t->table_state[p->n_tables + selector_id];
2107 struct selector_runtime *selector = &t->selectors[selector_id];
2108 struct selector_statistics *stats = &p->selector_stats[selector_id];
2109 uint64_t n_pkts = stats->n_pkts;
2113 done = rte_swx_table_selector_select(ts->obj,
2115 selector->group_id_buffer,
2116 selector->selector_buffer,
2117 selector->member_id_buffer);
2120 TRACE("[Thread %2u] selector %u (not finalized)\n",
2129 TRACE("[Thread %2u] selector %u\n",
2133 stats->n_pkts = n_pkts + 1;
2140 instr_learner_exec(struct rte_swx_pipeline *p)
2142 struct thread *t = &p->threads[p->thread_id];
2143 struct instruction *ip = t->ip;
2144 uint32_t learner_id = ip->table.table_id;
2145 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2146 p->n_selectors + learner_id];
2147 struct learner_runtime *l = &t->learners[learner_id];
2148 struct learner_statistics *stats = &p->learner_stats[learner_id];
2149 uint64_t action_id, n_pkts_hit, n_pkts_action, time;
2150 uint8_t *action_data;
2154 time = rte_get_tsc_cycles();
2156 done = rte_swx_table_learner_lookup(ts->obj,
2165 TRACE("[Thread %2u] learner %u (not finalized)\n",
2173 action_id = hit ? action_id : ts->default_action_id;
2174 action_data = hit ? action_data : ts->default_action_data;
2175 n_pkts_hit = stats->n_pkts_hit[hit];
2176 n_pkts_action = stats->n_pkts_action[action_id];
2178 TRACE("[Thread %2u] learner %u (%s, action %u)\n",
2181 hit ? "hit" : "miss",
2182 (uint32_t)action_id);
2184 t->action_id = action_id;
2185 t->structs[0] = action_data;
2187 t->learner_id = learner_id;
2189 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2190 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2193 thread_ip_action_call(p, t, action_id);
2199 static struct action *
2200 action_find(struct rte_swx_pipeline *p, const char *name);
2203 action_has_nbo_args(struct action *a);
2206 instr_learn_translate(struct rte_swx_pipeline *p,
2207 struct action *action,
2210 struct instruction *instr,
2211 struct instruction_data *data __rte_unused)
2215 CHECK(action, EINVAL);
2216 CHECK(n_tokens == 2, EINVAL);
2218 a = action_find(p, tokens[1]);
2220 CHECK(!action_has_nbo_args(a), EINVAL);
2222 instr->type = INSTR_LEARNER_LEARN;
2223 instr->learn.action_id = a->id;
2229 instr_learn_exec(struct rte_swx_pipeline *p)
2231 struct thread *t = &p->threads[p->thread_id];
2232 struct instruction *ip = t->ip;
2234 __instr_learn_exec(p, t, ip);
2244 instr_forget_translate(struct rte_swx_pipeline *p __rte_unused,
2245 struct action *action,
2246 char **tokens __rte_unused,
2248 struct instruction *instr,
2249 struct instruction_data *data __rte_unused)
2251 CHECK(action, EINVAL);
2252 CHECK(n_tokens == 1, EINVAL);
2254 instr->type = INSTR_LEARNER_FORGET;
2260 instr_forget_exec(struct rte_swx_pipeline *p)
2262 struct thread *t = &p->threads[p->thread_id];
2263 struct instruction *ip = t->ip;
2265 __instr_forget_exec(p, t, ip);
2275 instr_extern_translate(struct rte_swx_pipeline *p,
2276 struct action *action __rte_unused,
2279 struct instruction *instr,
2280 struct instruction_data *data __rte_unused)
2282 char *token = tokens[1];
2284 CHECK(n_tokens == 2, EINVAL);
2286 if (token[0] == 'e') {
2287 struct extern_obj *obj;
2288 struct extern_type_member_func *func;
2290 func = extern_obj_member_func_parse(p, token, &obj);
2291 CHECK(func, EINVAL);
2293 instr->type = INSTR_EXTERN_OBJ;
2294 instr->ext_obj.ext_obj_id = obj->id;
2295 instr->ext_obj.func_id = func->id;
2300 if (token[0] == 'f') {
2301 struct extern_func *func;
2303 func = extern_func_parse(p, token);
2304 CHECK(func, EINVAL);
2306 instr->type = INSTR_EXTERN_FUNC;
2307 instr->ext_func.ext_func_id = func->id;
2316 instr_extern_obj_exec(struct rte_swx_pipeline *p)
2318 struct thread *t = &p->threads[p->thread_id];
2319 struct instruction *ip = t->ip;
2322 /* Extern object member function execute. */
2323 done = __instr_extern_obj_exec(p, t, ip);
2326 thread_ip_inc_cond(t, done);
2327 thread_yield_cond(p, done ^ 1);
2331 instr_extern_func_exec(struct rte_swx_pipeline *p)
2333 struct thread *t = &p->threads[p->thread_id];
2334 struct instruction *ip = t->ip;
2337 /* Extern function execute. */
2338 done = __instr_extern_func_exec(p, t, ip);
2341 thread_ip_inc_cond(t, done);
2342 thread_yield_cond(p, done ^ 1);
2349 instr_mov_translate(struct rte_swx_pipeline *p,
2350 struct action *action,
2353 struct instruction *instr,
2354 struct instruction_data *data __rte_unused)
2356 char *dst = tokens[1], *src = tokens[2];
2357 struct field *fdst, *fsrc;
2359 uint32_t dst_struct_id = 0, src_struct_id = 0;
2361 CHECK(n_tokens == 3, EINVAL);
2363 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2364 CHECK(fdst, EINVAL);
2365 CHECK(!fdst->var_size, EINVAL);
2367 /* MOV, MOV_MH, MOV_HM or MOV_HH. */
2368 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2370 CHECK(!fsrc->var_size, EINVAL);
2372 instr->type = INSTR_MOV;
2373 if (dst[0] != 'h' && src[0] == 'h')
2374 instr->type = INSTR_MOV_MH;
2375 if (dst[0] == 'h' && src[0] != 'h')
2376 instr->type = INSTR_MOV_HM;
2377 if (dst[0] == 'h' && src[0] == 'h')
2378 instr->type = INSTR_MOV_HH;
2380 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
2381 instr->mov.dst.n_bits = fdst->n_bits;
2382 instr->mov.dst.offset = fdst->offset / 8;
2383 instr->mov.src.struct_id = (uint8_t)src_struct_id;
2384 instr->mov.src.n_bits = fsrc->n_bits;
2385 instr->mov.src.offset = fsrc->offset / 8;
2390 src_val = strtoull(src, &src, 0);
2391 CHECK(!src[0], EINVAL);
2394 src_val = hton64(src_val) >> (64 - fdst->n_bits);
2396 instr->type = INSTR_MOV_I;
2397 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
2398 instr->mov.dst.n_bits = fdst->n_bits;
2399 instr->mov.dst.offset = fdst->offset / 8;
2400 instr->mov.src_val = src_val;
2405 instr_mov_exec(struct rte_swx_pipeline *p)
2407 struct thread *t = &p->threads[p->thread_id];
2408 struct instruction *ip = t->ip;
2410 __instr_mov_exec(p, t, ip);
2417 instr_mov_mh_exec(struct rte_swx_pipeline *p)
2419 struct thread *t = &p->threads[p->thread_id];
2420 struct instruction *ip = t->ip;
2422 __instr_mov_mh_exec(p, t, ip);
2429 instr_mov_hm_exec(struct rte_swx_pipeline *p)
2431 struct thread *t = &p->threads[p->thread_id];
2432 struct instruction *ip = t->ip;
2434 __instr_mov_hm_exec(p, t, ip);
2441 instr_mov_hh_exec(struct rte_swx_pipeline *p)
2443 struct thread *t = &p->threads[p->thread_id];
2444 struct instruction *ip = t->ip;
2446 __instr_mov_hh_exec(p, t, ip);
2453 instr_mov_i_exec(struct rte_swx_pipeline *p)
2455 struct thread *t = &p->threads[p->thread_id];
2456 struct instruction *ip = t->ip;
2458 __instr_mov_i_exec(p, t, ip);
2468 instr_dma_ht_exec(struct rte_swx_pipeline *p)
2470 struct thread *t = &p->threads[p->thread_id];
2471 struct instruction *ip = t->ip;
2473 __instr_dma_ht_exec(p, t, ip);
2480 instr_dma_ht2_exec(struct rte_swx_pipeline *p)
2482 struct thread *t = &p->threads[p->thread_id];
2483 struct instruction *ip = t->ip;
2485 __instr_dma_ht2_exec(p, t, ip);
2492 instr_dma_ht3_exec(struct rte_swx_pipeline *p)
2494 struct thread *t = &p->threads[p->thread_id];
2495 struct instruction *ip = t->ip;
2497 __instr_dma_ht3_exec(p, t, ip);
2504 instr_dma_ht4_exec(struct rte_swx_pipeline *p)
2506 struct thread *t = &p->threads[p->thread_id];
2507 struct instruction *ip = t->ip;
2509 __instr_dma_ht4_exec(p, t, ip);
2516 instr_dma_ht5_exec(struct rte_swx_pipeline *p)
2518 struct thread *t = &p->threads[p->thread_id];
2519 struct instruction *ip = t->ip;
2521 __instr_dma_ht5_exec(p, t, ip);
2528 instr_dma_ht6_exec(struct rte_swx_pipeline *p)
2530 struct thread *t = &p->threads[p->thread_id];
2531 struct instruction *ip = t->ip;
2533 __instr_dma_ht6_exec(p, t, ip);
2540 instr_dma_ht7_exec(struct rte_swx_pipeline *p)
2542 struct thread *t = &p->threads[p->thread_id];
2543 struct instruction *ip = t->ip;
2545 __instr_dma_ht7_exec(p, t, ip);
2552 instr_dma_ht8_exec(struct rte_swx_pipeline *p)
2554 struct thread *t = &p->threads[p->thread_id];
2555 struct instruction *ip = t->ip;
2557 __instr_dma_ht8_exec(p, t, ip);
2567 instr_alu_add_translate(struct rte_swx_pipeline *p,
2568 struct action *action,
2571 struct instruction *instr,
2572 struct instruction_data *data __rte_unused)
2574 char *dst = tokens[1], *src = tokens[2];
2575 struct field *fdst, *fsrc;
2577 uint32_t dst_struct_id = 0, src_struct_id = 0;
2579 CHECK(n_tokens == 3, EINVAL);
2581 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2582 CHECK(fdst, EINVAL);
2583 CHECK(!fdst->var_size, EINVAL);
2585 /* ADD, ADD_HM, ADD_MH, ADD_HH. */
2586 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2588 CHECK(!fsrc->var_size, EINVAL);
2590 instr->type = INSTR_ALU_ADD;
2591 if (dst[0] == 'h' && src[0] != 'h')
2592 instr->type = INSTR_ALU_ADD_HM;
2593 if (dst[0] != 'h' && src[0] == 'h')
2594 instr->type = INSTR_ALU_ADD_MH;
2595 if (dst[0] == 'h' && src[0] == 'h')
2596 instr->type = INSTR_ALU_ADD_HH;
2598 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2599 instr->alu.dst.n_bits = fdst->n_bits;
2600 instr->alu.dst.offset = fdst->offset / 8;
2601 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2602 instr->alu.src.n_bits = fsrc->n_bits;
2603 instr->alu.src.offset = fsrc->offset / 8;
2607 /* ADD_MI, ADD_HI. */
2608 src_val = strtoull(src, &src, 0);
2609 CHECK(!src[0], EINVAL);
2611 instr->type = INSTR_ALU_ADD_MI;
2613 instr->type = INSTR_ALU_ADD_HI;
2615 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2616 instr->alu.dst.n_bits = fdst->n_bits;
2617 instr->alu.dst.offset = fdst->offset / 8;
2618 instr->alu.src_val = src_val;
2623 instr_alu_sub_translate(struct rte_swx_pipeline *p,
2624 struct action *action,
2627 struct instruction *instr,
2628 struct instruction_data *data __rte_unused)
2630 char *dst = tokens[1], *src = tokens[2];
2631 struct field *fdst, *fsrc;
2633 uint32_t dst_struct_id = 0, src_struct_id = 0;
2635 CHECK(n_tokens == 3, EINVAL);
2637 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2638 CHECK(fdst, EINVAL);
2639 CHECK(!fdst->var_size, EINVAL);
2641 /* SUB, SUB_HM, SUB_MH, SUB_HH. */
2642 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2644 CHECK(!fsrc->var_size, EINVAL);
2646 instr->type = INSTR_ALU_SUB;
2647 if (dst[0] == 'h' && src[0] != 'h')
2648 instr->type = INSTR_ALU_SUB_HM;
2649 if (dst[0] != 'h' && src[0] == 'h')
2650 instr->type = INSTR_ALU_SUB_MH;
2651 if (dst[0] == 'h' && src[0] == 'h')
2652 instr->type = INSTR_ALU_SUB_HH;
2654 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2655 instr->alu.dst.n_bits = fdst->n_bits;
2656 instr->alu.dst.offset = fdst->offset / 8;
2657 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2658 instr->alu.src.n_bits = fsrc->n_bits;
2659 instr->alu.src.offset = fsrc->offset / 8;
2663 /* SUB_MI, SUB_HI. */
2664 src_val = strtoull(src, &src, 0);
2665 CHECK(!src[0], EINVAL);
2667 instr->type = INSTR_ALU_SUB_MI;
2669 instr->type = INSTR_ALU_SUB_HI;
2671 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2672 instr->alu.dst.n_bits = fdst->n_bits;
2673 instr->alu.dst.offset = fdst->offset / 8;
2674 instr->alu.src_val = src_val;
2679 instr_alu_ckadd_translate(struct rte_swx_pipeline *p,
2680 struct action *action __rte_unused,
2683 struct instruction *instr,
2684 struct instruction_data *data __rte_unused)
2686 char *dst = tokens[1], *src = tokens[2];
2687 struct header *hdst, *hsrc;
2688 struct field *fdst, *fsrc;
2690 CHECK(n_tokens == 3, EINVAL);
2692 fdst = header_field_parse(p, dst, &hdst);
2693 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
2694 CHECK(!fdst->var_size, EINVAL);
2697 fsrc = header_field_parse(p, src, &hsrc);
2699 CHECK(!fsrc->var_size, EINVAL);
2701 instr->type = INSTR_ALU_CKADD_FIELD;
2702 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2703 instr->alu.dst.n_bits = fdst->n_bits;
2704 instr->alu.dst.offset = fdst->offset / 8;
2705 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2706 instr->alu.src.n_bits = fsrc->n_bits;
2707 instr->alu.src.offset = fsrc->offset / 8;
2711 /* CKADD_STRUCT, CKADD_STRUCT20. */
2712 hsrc = header_parse(p, src);
2713 CHECK(hsrc, EINVAL);
2714 CHECK(!hsrc->st->var_size, EINVAL);
2716 instr->type = INSTR_ALU_CKADD_STRUCT;
2717 if ((hsrc->st->n_bits / 8) == 20)
2718 instr->type = INSTR_ALU_CKADD_STRUCT20;
2720 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2721 instr->alu.dst.n_bits = fdst->n_bits;
2722 instr->alu.dst.offset = fdst->offset / 8;
2723 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2724 instr->alu.src.n_bits = hsrc->st->n_bits;
2725 instr->alu.src.offset = 0; /* Unused. */
2730 instr_alu_cksub_translate(struct rte_swx_pipeline *p,
2731 struct action *action __rte_unused,
2734 struct instruction *instr,
2735 struct instruction_data *data __rte_unused)
2737 char *dst = tokens[1], *src = tokens[2];
2738 struct header *hdst, *hsrc;
2739 struct field *fdst, *fsrc;
2741 CHECK(n_tokens == 3, EINVAL);
2743 fdst = header_field_parse(p, dst, &hdst);
2744 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
2745 CHECK(!fdst->var_size, EINVAL);
2747 fsrc = header_field_parse(p, src, &hsrc);
2748 CHECK(fsrc, EINVAL);
2749 CHECK(!fsrc->var_size, EINVAL);
2751 instr->type = INSTR_ALU_CKSUB_FIELD;
2752 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2753 instr->alu.dst.n_bits = fdst->n_bits;
2754 instr->alu.dst.offset = fdst->offset / 8;
2755 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2756 instr->alu.src.n_bits = fsrc->n_bits;
2757 instr->alu.src.offset = fsrc->offset / 8;
2762 instr_alu_shl_translate(struct rte_swx_pipeline *p,
2763 struct action *action,
2766 struct instruction *instr,
2767 struct instruction_data *data __rte_unused)
2769 char *dst = tokens[1], *src = tokens[2];
2770 struct field *fdst, *fsrc;
2772 uint32_t dst_struct_id = 0, src_struct_id = 0;
2774 CHECK(n_tokens == 3, EINVAL);
2776 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2777 CHECK(fdst, EINVAL);
2778 CHECK(!fdst->var_size, EINVAL);
2780 /* SHL, SHL_HM, SHL_MH, SHL_HH. */
2781 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2783 CHECK(!fsrc->var_size, EINVAL);
2785 instr->type = INSTR_ALU_SHL;
2786 if (dst[0] == 'h' && src[0] != 'h')
2787 instr->type = INSTR_ALU_SHL_HM;
2788 if (dst[0] != 'h' && src[0] == 'h')
2789 instr->type = INSTR_ALU_SHL_MH;
2790 if (dst[0] == 'h' && src[0] == 'h')
2791 instr->type = INSTR_ALU_SHL_HH;
2793 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2794 instr->alu.dst.n_bits = fdst->n_bits;
2795 instr->alu.dst.offset = fdst->offset / 8;
2796 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2797 instr->alu.src.n_bits = fsrc->n_bits;
2798 instr->alu.src.offset = fsrc->offset / 8;
2802 /* SHL_MI, SHL_HI. */
2803 src_val = strtoull(src, &src, 0);
2804 CHECK(!src[0], EINVAL);
2806 instr->type = INSTR_ALU_SHL_MI;
2808 instr->type = INSTR_ALU_SHL_HI;
2810 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2811 instr->alu.dst.n_bits = fdst->n_bits;
2812 instr->alu.dst.offset = fdst->offset / 8;
2813 instr->alu.src_val = src_val;
2818 instr_alu_shr_translate(struct rte_swx_pipeline *p,
2819 struct action *action,
2822 struct instruction *instr,
2823 struct instruction_data *data __rte_unused)
2825 char *dst = tokens[1], *src = tokens[2];
2826 struct field *fdst, *fsrc;
2828 uint32_t dst_struct_id = 0, src_struct_id = 0;
2830 CHECK(n_tokens == 3, EINVAL);
2832 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2833 CHECK(fdst, EINVAL);
2834 CHECK(!fdst->var_size, EINVAL);
2836 /* SHR, SHR_HM, SHR_MH, SHR_HH. */
2837 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2839 CHECK(!fsrc->var_size, EINVAL);
2841 instr->type = INSTR_ALU_SHR;
2842 if (dst[0] == 'h' && src[0] != 'h')
2843 instr->type = INSTR_ALU_SHR_HM;
2844 if (dst[0] != 'h' && src[0] == 'h')
2845 instr->type = INSTR_ALU_SHR_MH;
2846 if (dst[0] == 'h' && src[0] == 'h')
2847 instr->type = INSTR_ALU_SHR_HH;
2849 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2850 instr->alu.dst.n_bits = fdst->n_bits;
2851 instr->alu.dst.offset = fdst->offset / 8;
2852 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2853 instr->alu.src.n_bits = fsrc->n_bits;
2854 instr->alu.src.offset = fsrc->offset / 8;
2858 /* SHR_MI, SHR_HI. */
2859 src_val = strtoull(src, &src, 0);
2860 CHECK(!src[0], EINVAL);
2862 instr->type = INSTR_ALU_SHR_MI;
2864 instr->type = INSTR_ALU_SHR_HI;
2866 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2867 instr->alu.dst.n_bits = fdst->n_bits;
2868 instr->alu.dst.offset = fdst->offset / 8;
2869 instr->alu.src_val = src_val;
2874 instr_alu_and_translate(struct rte_swx_pipeline *p,
2875 struct action *action,
2878 struct instruction *instr,
2879 struct instruction_data *data __rte_unused)
2881 char *dst = tokens[1], *src = tokens[2];
2882 struct field *fdst, *fsrc;
2884 uint32_t dst_struct_id = 0, src_struct_id = 0;
2886 CHECK(n_tokens == 3, EINVAL);
2888 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2889 CHECK(fdst, EINVAL);
2890 CHECK(!fdst->var_size, EINVAL);
2892 /* AND, AND_MH, AND_HM, AND_HH. */
2893 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2895 CHECK(!fsrc->var_size, EINVAL);
2897 instr->type = INSTR_ALU_AND;
2898 if (dst[0] != 'h' && src[0] == 'h')
2899 instr->type = INSTR_ALU_AND_MH;
2900 if (dst[0] == 'h' && src[0] != 'h')
2901 instr->type = INSTR_ALU_AND_HM;
2902 if (dst[0] == 'h' && src[0] == 'h')
2903 instr->type = INSTR_ALU_AND_HH;
2905 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2906 instr->alu.dst.n_bits = fdst->n_bits;
2907 instr->alu.dst.offset = fdst->offset / 8;
2908 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2909 instr->alu.src.n_bits = fsrc->n_bits;
2910 instr->alu.src.offset = fsrc->offset / 8;
2915 src_val = strtoull(src, &src, 0);
2916 CHECK(!src[0], EINVAL);
2919 src_val = hton64(src_val) >> (64 - fdst->n_bits);
2921 instr->type = INSTR_ALU_AND_I;
2922 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2923 instr->alu.dst.n_bits = fdst->n_bits;
2924 instr->alu.dst.offset = fdst->offset / 8;
2925 instr->alu.src_val = src_val;
2930 instr_alu_or_translate(struct rte_swx_pipeline *p,
2931 struct action *action,
2934 struct instruction *instr,
2935 struct instruction_data *data __rte_unused)
2937 char *dst = tokens[1], *src = tokens[2];
2938 struct field *fdst, *fsrc;
2940 uint32_t dst_struct_id = 0, src_struct_id = 0;
2942 CHECK(n_tokens == 3, EINVAL);
2944 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2945 CHECK(fdst, EINVAL);
2946 CHECK(!fdst->var_size, EINVAL);
2948 /* OR, OR_MH, OR_HM, OR_HH. */
2949 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2951 CHECK(!fsrc->var_size, EINVAL);
2953 instr->type = INSTR_ALU_OR;
2954 if (dst[0] != 'h' && src[0] == 'h')
2955 instr->type = INSTR_ALU_OR_MH;
2956 if (dst[0] == 'h' && src[0] != 'h')
2957 instr->type = INSTR_ALU_OR_HM;
2958 if (dst[0] == 'h' && src[0] == 'h')
2959 instr->type = INSTR_ALU_OR_HH;
2961 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2962 instr->alu.dst.n_bits = fdst->n_bits;
2963 instr->alu.dst.offset = fdst->offset / 8;
2964 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2965 instr->alu.src.n_bits = fsrc->n_bits;
2966 instr->alu.src.offset = fsrc->offset / 8;
2971 src_val = strtoull(src, &src, 0);
2972 CHECK(!src[0], EINVAL);
2975 src_val = hton64(src_val) >> (64 - fdst->n_bits);
2977 instr->type = INSTR_ALU_OR_I;
2978 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2979 instr->alu.dst.n_bits = fdst->n_bits;
2980 instr->alu.dst.offset = fdst->offset / 8;
2981 instr->alu.src_val = src_val;
2986 instr_alu_xor_translate(struct rte_swx_pipeline *p,
2987 struct action *action,
2990 struct instruction *instr,
2991 struct instruction_data *data __rte_unused)
2993 char *dst = tokens[1], *src = tokens[2];
2994 struct field *fdst, *fsrc;
2996 uint32_t dst_struct_id = 0, src_struct_id = 0;
2998 CHECK(n_tokens == 3, EINVAL);
3000 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3001 CHECK(fdst, EINVAL);
3002 CHECK(!fdst->var_size, EINVAL);
3004 /* XOR, XOR_MH, XOR_HM, XOR_HH. */
3005 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3007 CHECK(!fsrc->var_size, EINVAL);
3009 instr->type = INSTR_ALU_XOR;
3010 if (dst[0] != 'h' && src[0] == 'h')
3011 instr->type = INSTR_ALU_XOR_MH;
3012 if (dst[0] == 'h' && src[0] != 'h')
3013 instr->type = INSTR_ALU_XOR_HM;
3014 if (dst[0] == 'h' && src[0] == 'h')
3015 instr->type = INSTR_ALU_XOR_HH;
3017 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3018 instr->alu.dst.n_bits = fdst->n_bits;
3019 instr->alu.dst.offset = fdst->offset / 8;
3020 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3021 instr->alu.src.n_bits = fsrc->n_bits;
3022 instr->alu.src.offset = fsrc->offset / 8;
3027 src_val = strtoull(src, &src, 0);
3028 CHECK(!src[0], EINVAL);
3031 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3033 instr->type = INSTR_ALU_XOR_I;
3034 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3035 instr->alu.dst.n_bits = fdst->n_bits;
3036 instr->alu.dst.offset = fdst->offset / 8;
3037 instr->alu.src_val = src_val;
3042 instr_alu_add_exec(struct rte_swx_pipeline *p)
3044 struct thread *t = &p->threads[p->thread_id];
3045 struct instruction *ip = t->ip;
3047 TRACE("[Thread %2u] add\n", p->thread_id);
3057 instr_alu_add_mh_exec(struct rte_swx_pipeline *p)
3059 struct thread *t = &p->threads[p->thread_id];
3060 struct instruction *ip = t->ip;
3062 TRACE("[Thread %2u] add (mh)\n", p->thread_id);
3072 instr_alu_add_hm_exec(struct rte_swx_pipeline *p)
3074 struct thread *t = &p->threads[p->thread_id];
3075 struct instruction *ip = t->ip;
3077 TRACE("[Thread %2u] add (hm)\n", p->thread_id);
3087 instr_alu_add_hh_exec(struct rte_swx_pipeline *p)
3089 struct thread *t = &p->threads[p->thread_id];
3090 struct instruction *ip = t->ip;
3092 TRACE("[Thread %2u] add (hh)\n", p->thread_id);
3102 instr_alu_add_mi_exec(struct rte_swx_pipeline *p)
3104 struct thread *t = &p->threads[p->thread_id];
3105 struct instruction *ip = t->ip;
3107 TRACE("[Thread %2u] add (mi)\n", p->thread_id);
3117 instr_alu_add_hi_exec(struct rte_swx_pipeline *p)
3119 struct thread *t = &p->threads[p->thread_id];
3120 struct instruction *ip = t->ip;
3122 TRACE("[Thread %2u] add (hi)\n", p->thread_id);
3132 instr_alu_sub_exec(struct rte_swx_pipeline *p)
3134 struct thread *t = &p->threads[p->thread_id];
3135 struct instruction *ip = t->ip;
3137 TRACE("[Thread %2u] sub\n", p->thread_id);
3147 instr_alu_sub_mh_exec(struct rte_swx_pipeline *p)
3149 struct thread *t = &p->threads[p->thread_id];
3150 struct instruction *ip = t->ip;
3152 TRACE("[Thread %2u] sub (mh)\n", p->thread_id);
3162 instr_alu_sub_hm_exec(struct rte_swx_pipeline *p)
3164 struct thread *t = &p->threads[p->thread_id];
3165 struct instruction *ip = t->ip;
3167 TRACE("[Thread %2u] sub (hm)\n", p->thread_id);
3177 instr_alu_sub_hh_exec(struct rte_swx_pipeline *p)
3179 struct thread *t = &p->threads[p->thread_id];
3180 struct instruction *ip = t->ip;
3182 TRACE("[Thread %2u] sub (hh)\n", p->thread_id);
3192 instr_alu_sub_mi_exec(struct rte_swx_pipeline *p)
3194 struct thread *t = &p->threads[p->thread_id];
3195 struct instruction *ip = t->ip;
3197 TRACE("[Thread %2u] sub (mi)\n", p->thread_id);
3207 instr_alu_sub_hi_exec(struct rte_swx_pipeline *p)
3209 struct thread *t = &p->threads[p->thread_id];
3210 struct instruction *ip = t->ip;
3212 TRACE("[Thread %2u] sub (hi)\n", p->thread_id);
3222 instr_alu_shl_exec(struct rte_swx_pipeline *p)
3224 struct thread *t = &p->threads[p->thread_id];
3225 struct instruction *ip = t->ip;
3227 TRACE("[Thread %2u] shl\n", p->thread_id);
3237 instr_alu_shl_mh_exec(struct rte_swx_pipeline *p)
3239 struct thread *t = &p->threads[p->thread_id];
3240 struct instruction *ip = t->ip;
3242 TRACE("[Thread %2u] shl (mh)\n", p->thread_id);
3252 instr_alu_shl_hm_exec(struct rte_swx_pipeline *p)
3254 struct thread *t = &p->threads[p->thread_id];
3255 struct instruction *ip = t->ip;
3257 TRACE("[Thread %2u] shl (hm)\n", p->thread_id);
3267 instr_alu_shl_hh_exec(struct rte_swx_pipeline *p)
3269 struct thread *t = &p->threads[p->thread_id];
3270 struct instruction *ip = t->ip;
3272 TRACE("[Thread %2u] shl (hh)\n", p->thread_id);
3282 instr_alu_shl_mi_exec(struct rte_swx_pipeline *p)
3284 struct thread *t = &p->threads[p->thread_id];
3285 struct instruction *ip = t->ip;
3287 TRACE("[Thread %2u] shl (mi)\n", p->thread_id);
3297 instr_alu_shl_hi_exec(struct rte_swx_pipeline *p)
3299 struct thread *t = &p->threads[p->thread_id];
3300 struct instruction *ip = t->ip;
3302 TRACE("[Thread %2u] shl (hi)\n", p->thread_id);
3312 instr_alu_shr_exec(struct rte_swx_pipeline *p)
3314 struct thread *t = &p->threads[p->thread_id];
3315 struct instruction *ip = t->ip;
3317 TRACE("[Thread %2u] shr\n", p->thread_id);
3327 instr_alu_shr_mh_exec(struct rte_swx_pipeline *p)
3329 struct thread *t = &p->threads[p->thread_id];
3330 struct instruction *ip = t->ip;
3332 TRACE("[Thread %2u] shr (mh)\n", p->thread_id);
3342 instr_alu_shr_hm_exec(struct rte_swx_pipeline *p)
3344 struct thread *t = &p->threads[p->thread_id];
3345 struct instruction *ip = t->ip;
3347 TRACE("[Thread %2u] shr (hm)\n", p->thread_id);
3357 instr_alu_shr_hh_exec(struct rte_swx_pipeline *p)
3359 struct thread *t = &p->threads[p->thread_id];
3360 struct instruction *ip = t->ip;
3362 TRACE("[Thread %2u] shr (hh)\n", p->thread_id);
3372 instr_alu_shr_mi_exec(struct rte_swx_pipeline *p)
3374 struct thread *t = &p->threads[p->thread_id];
3375 struct instruction *ip = t->ip;
3377 TRACE("[Thread %2u] shr (mi)\n", p->thread_id);
3387 instr_alu_shr_hi_exec(struct rte_swx_pipeline *p)
3389 struct thread *t = &p->threads[p->thread_id];
3390 struct instruction *ip = t->ip;
3392 TRACE("[Thread %2u] shr (hi)\n", p->thread_id);
3402 instr_alu_and_exec(struct rte_swx_pipeline *p)
3404 struct thread *t = &p->threads[p->thread_id];
3405 struct instruction *ip = t->ip;
3407 TRACE("[Thread %2u] and\n", p->thread_id);
3417 instr_alu_and_mh_exec(struct rte_swx_pipeline *p)
3419 struct thread *t = &p->threads[p->thread_id];
3420 struct instruction *ip = t->ip;
3422 TRACE("[Thread %2u] and (mh)\n", p->thread_id);
3432 instr_alu_and_hm_exec(struct rte_swx_pipeline *p)
3434 struct thread *t = &p->threads[p->thread_id];
3435 struct instruction *ip = t->ip;
3437 TRACE("[Thread %2u] and (hm)\n", p->thread_id);
3440 ALU_HM_FAST(t, ip, &);
3447 instr_alu_and_hh_exec(struct rte_swx_pipeline *p)
3449 struct thread *t = &p->threads[p->thread_id];
3450 struct instruction *ip = t->ip;
3452 TRACE("[Thread %2u] and (hh)\n", p->thread_id);
3455 ALU_HH_FAST(t, ip, &);
3462 instr_alu_and_i_exec(struct rte_swx_pipeline *p)
3464 struct thread *t = &p->threads[p->thread_id];
3465 struct instruction *ip = t->ip;
3467 TRACE("[Thread %2u] and (i)\n", p->thread_id);
3477 instr_alu_or_exec(struct rte_swx_pipeline *p)
3479 struct thread *t = &p->threads[p->thread_id];
3480 struct instruction *ip = t->ip;
3482 TRACE("[Thread %2u] or\n", p->thread_id);
3492 instr_alu_or_mh_exec(struct rte_swx_pipeline *p)
3494 struct thread *t = &p->threads[p->thread_id];
3495 struct instruction *ip = t->ip;
3497 TRACE("[Thread %2u] or (mh)\n", p->thread_id);
3507 instr_alu_or_hm_exec(struct rte_swx_pipeline *p)
3509 struct thread *t = &p->threads[p->thread_id];
3510 struct instruction *ip = t->ip;
3512 TRACE("[Thread %2u] or (hm)\n", p->thread_id);
3515 ALU_HM_FAST(t, ip, |);
3522 instr_alu_or_hh_exec(struct rte_swx_pipeline *p)
3524 struct thread *t = &p->threads[p->thread_id];
3525 struct instruction *ip = t->ip;
3527 TRACE("[Thread %2u] or (hh)\n", p->thread_id);
3530 ALU_HH_FAST(t, ip, |);
3537 instr_alu_or_i_exec(struct rte_swx_pipeline *p)
3539 struct thread *t = &p->threads[p->thread_id];
3540 struct instruction *ip = t->ip;
3542 TRACE("[Thread %2u] or (i)\n", p->thread_id);
3552 instr_alu_xor_exec(struct rte_swx_pipeline *p)
3554 struct thread *t = &p->threads[p->thread_id];
3555 struct instruction *ip = t->ip;
3557 TRACE("[Thread %2u] xor\n", p->thread_id);
3567 instr_alu_xor_mh_exec(struct rte_swx_pipeline *p)
3569 struct thread *t = &p->threads[p->thread_id];
3570 struct instruction *ip = t->ip;
3572 TRACE("[Thread %2u] xor (mh)\n", p->thread_id);
3582 instr_alu_xor_hm_exec(struct rte_swx_pipeline *p)
3584 struct thread *t = &p->threads[p->thread_id];
3585 struct instruction *ip = t->ip;
3587 TRACE("[Thread %2u] xor (hm)\n", p->thread_id);
3590 ALU_HM_FAST(t, ip, ^);
3597 instr_alu_xor_hh_exec(struct rte_swx_pipeline *p)
3599 struct thread *t = &p->threads[p->thread_id];
3600 struct instruction *ip = t->ip;
3602 TRACE("[Thread %2u] xor (hh)\n", p->thread_id);
3605 ALU_HH_FAST(t, ip, ^);
3612 instr_alu_xor_i_exec(struct rte_swx_pipeline *p)
3614 struct thread *t = &p->threads[p->thread_id];
3615 struct instruction *ip = t->ip;
3617 TRACE("[Thread %2u] xor (i)\n", p->thread_id);
3627 instr_alu_ckadd_field_exec(struct rte_swx_pipeline *p)
3629 struct thread *t = &p->threads[p->thread_id];
3630 struct instruction *ip = t->ip;
3631 uint8_t *dst_struct, *src_struct;
3632 uint16_t *dst16_ptr, dst;
3633 uint64_t *src64_ptr, src64, src64_mask, src;
3636 TRACE("[Thread %2u] ckadd (field)\n", p->thread_id);
3639 dst_struct = t->structs[ip->alu.dst.struct_id];
3640 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
3643 src_struct = t->structs[ip->alu.src.struct_id];
3644 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
3646 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
3647 src = src64 & src64_mask;
3652 /* The first input (r) is a 16-bit number. The second and the third
3653 * inputs are 32-bit numbers. In the worst case scenario, the sum of the
3654 * three numbers (output r) is a 34-bit number.
3656 r += (src >> 32) + (src & 0xFFFFFFFF);
3658 /* The first input is a 16-bit number. The second input is an 18-bit
3659 * number. In the worst case scenario, the sum of the two numbers is a
3662 r = (r & 0xFFFF) + (r >> 16);
3664 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
3665 * a 3-bit number (0 .. 7). Their sum is a 17-bit number (0 .. 0x10006).
3667 r = (r & 0xFFFF) + (r >> 16);
3669 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
3670 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
3671 * 0x10006), the output r is (0 .. 7). So no carry bit can be generated,
3672 * therefore the output r is always a 16-bit number.
3674 r = (r & 0xFFFF) + (r >> 16);
3679 *dst16_ptr = (uint16_t)r;
3686 instr_alu_cksub_field_exec(struct rte_swx_pipeline *p)
3688 struct thread *t = &p->threads[p->thread_id];
3689 struct instruction *ip = t->ip;
3690 uint8_t *dst_struct, *src_struct;
3691 uint16_t *dst16_ptr, dst;
3692 uint64_t *src64_ptr, src64, src64_mask, src;
3695 TRACE("[Thread %2u] cksub (field)\n", p->thread_id);
3698 dst_struct = t->structs[ip->alu.dst.struct_id];
3699 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
3702 src_struct = t->structs[ip->alu.src.struct_id];
3703 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
3705 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
3706 src = src64 & src64_mask;
3711 /* Subtraction in 1's complement arithmetic (i.e. a '- b) is the same as
3712 * the following sequence of operations in 2's complement arithmetic:
3713 * a '- b = (a - b) % 0xFFFF.
3715 * In order to prevent an underflow for the below subtraction, in which
3716 * a 33-bit number (the subtrahend) is taken out of a 16-bit number (the
3717 * minuend), we first add a multiple of the 0xFFFF modulus to the
3718 * minuend. The number we add to the minuend needs to be a 34-bit number
3719 * or higher, so for readability reasons we picked the 36-bit multiple.
3720 * We are effectively turning the 16-bit minuend into a 36-bit number:
3721 * (a - b) % 0xFFFF = (a + 0xFFFF00000 - b) % 0xFFFF.
3723 r += 0xFFFF00000ULL; /* The output r is a 36-bit number. */
3725 /* A 33-bit number is subtracted from a 36-bit number (the input r). The
3726 * result (the output r) is a 36-bit number.
3728 r -= (src >> 32) + (src & 0xFFFFFFFF);
3730 /* The first input is a 16-bit number. The second input is a 20-bit
3731 * number. Their sum is a 21-bit number.
3733 r = (r & 0xFFFF) + (r >> 16);
3735 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
3736 * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1001E).
3738 r = (r & 0xFFFF) + (r >> 16);
3740 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
3741 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
3742 * 0x1001E), the output r is (0 .. 31). So no carry bit can be
3743 * generated, therefore the output r is always a 16-bit number.
3745 r = (r & 0xFFFF) + (r >> 16);
3750 *dst16_ptr = (uint16_t)r;
3757 instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline *p)
3759 struct thread *t = &p->threads[p->thread_id];
3760 struct instruction *ip = t->ip;
3761 uint8_t *dst_struct, *src_struct;
3762 uint16_t *dst16_ptr;
3763 uint32_t *src32_ptr;
3766 TRACE("[Thread %2u] ckadd (struct of 20 bytes)\n", p->thread_id);
3769 dst_struct = t->structs[ip->alu.dst.struct_id];
3770 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
3772 src_struct = t->structs[ip->alu.src.struct_id];
3773 src32_ptr = (uint32_t *)&src_struct[0];
3775 r0 = src32_ptr[0]; /* r0 is a 32-bit number. */
3776 r1 = src32_ptr[1]; /* r1 is a 32-bit number. */
3777 r0 += src32_ptr[2]; /* The output r0 is a 33-bit number. */
3778 r1 += src32_ptr[3]; /* The output r1 is a 33-bit number. */
3779 r0 += r1 + src32_ptr[4]; /* The output r0 is a 35-bit number. */
3781 /* The first input is a 16-bit number. The second input is a 19-bit
3782 * number. Their sum is a 20-bit number.
3784 r0 = (r0 & 0xFFFF) + (r0 >> 16);
3786 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
3787 * a 4-bit number (0 .. 15). The sum is a 17-bit number (0 .. 0x1000E).
3789 r0 = (r0 & 0xFFFF) + (r0 >> 16);
3791 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
3792 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
3793 * 0x1000E), the output r is (0 .. 15). So no carry bit can be
3794 * generated, therefore the output r is always a 16-bit number.
3796 r0 = (r0 & 0xFFFF) + (r0 >> 16);
3799 r0 = r0 ? r0 : 0xFFFF;
3801 *dst16_ptr = (uint16_t)r0;
3808 instr_alu_ckadd_struct_exec(struct rte_swx_pipeline *p)
3810 struct thread *t = &p->threads[p->thread_id];
3811 struct instruction *ip = t->ip;
3812 uint8_t *dst_struct, *src_struct;
3813 uint16_t *dst16_ptr;
3814 uint32_t *src32_ptr;
3818 TRACE("[Thread %2u] ckadd (struct)\n", p->thread_id);
3821 dst_struct = t->structs[ip->alu.dst.struct_id];
3822 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
3824 src_struct = t->structs[ip->alu.src.struct_id];
3825 src32_ptr = (uint32_t *)&src_struct[0];
3827 /* The max number of 32-bit words in a 256-byte header is 8 = 2^3.
3828 * Therefore, in the worst case scenario, a 35-bit number is added to a
3829 * 16-bit number (the input r), so the output r is 36-bit number.
3831 for (i = 0; i < ip->alu.src.n_bits / 32; i++, src32_ptr++)
3834 /* The first input is a 16-bit number. The second input is a 20-bit
3835 * number. Their sum is a 21-bit number.
3837 r = (r & 0xFFFF) + (r >> 16);
3839 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
3840 * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1000E).
3842 r = (r & 0xFFFF) + (r >> 16);
3844 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
3845 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
3846 * 0x1001E), the output r is (0 .. 31). So no carry bit can be
3847 * generated, therefore the output r is always a 16-bit number.
3849 r = (r & 0xFFFF) + (r >> 16);
3854 *dst16_ptr = (uint16_t)r;
3863 static struct regarray *
3864 regarray_find(struct rte_swx_pipeline *p, const char *name);
3867 instr_regprefetch_translate(struct rte_swx_pipeline *p,
3868 struct action *action,
3871 struct instruction *instr,
3872 struct instruction_data *data __rte_unused)
3874 char *regarray = tokens[1], *idx = tokens[2];
3877 uint32_t idx_struct_id, idx_val;
3879 CHECK(n_tokens == 3, EINVAL);
3881 r = regarray_find(p, regarray);
3884 /* REGPREFETCH_RH, REGPREFETCH_RM. */
3885 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
3887 CHECK(!fidx->var_size, EINVAL);
3889 instr->type = INSTR_REGPREFETCH_RM;
3891 instr->type = INSTR_REGPREFETCH_RH;
3893 instr->regarray.regarray_id = r->id;
3894 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
3895 instr->regarray.idx.n_bits = fidx->n_bits;
3896 instr->regarray.idx.offset = fidx->offset / 8;
3897 instr->regarray.dstsrc_val = 0; /* Unused. */
3901 /* REGPREFETCH_RI. */
3902 idx_val = strtoul(idx, &idx, 0);
3903 CHECK(!idx[0], EINVAL);
3905 instr->type = INSTR_REGPREFETCH_RI;
3906 instr->regarray.regarray_id = r->id;
3907 instr->regarray.idx_val = idx_val;
3908 instr->regarray.dstsrc_val = 0; /* Unused. */
3913 instr_regrd_translate(struct rte_swx_pipeline *p,
3914 struct action *action,
3917 struct instruction *instr,
3918 struct instruction_data *data __rte_unused)
3920 char *dst = tokens[1], *regarray = tokens[2], *idx = tokens[3];
3922 struct field *fdst, *fidx;
3923 uint32_t dst_struct_id, idx_struct_id, idx_val;
3925 CHECK(n_tokens == 4, EINVAL);
3927 r = regarray_find(p, regarray);
3930 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3931 CHECK(fdst, EINVAL);
3932 CHECK(!fdst->var_size, EINVAL);
3934 /* REGRD_HRH, REGRD_HRM, REGRD_MRH, REGRD_MRM. */
3935 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
3937 CHECK(!fidx->var_size, EINVAL);
3939 instr->type = INSTR_REGRD_MRM;
3940 if (dst[0] == 'h' && idx[0] != 'h')
3941 instr->type = INSTR_REGRD_HRM;
3942 if (dst[0] != 'h' && idx[0] == 'h')
3943 instr->type = INSTR_REGRD_MRH;
3944 if (dst[0] == 'h' && idx[0] == 'h')
3945 instr->type = INSTR_REGRD_HRH;
3947 instr->regarray.regarray_id = r->id;
3948 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
3949 instr->regarray.idx.n_bits = fidx->n_bits;
3950 instr->regarray.idx.offset = fidx->offset / 8;
3951 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
3952 instr->regarray.dstsrc.n_bits = fdst->n_bits;
3953 instr->regarray.dstsrc.offset = fdst->offset / 8;
3957 /* REGRD_MRI, REGRD_HRI. */
3958 idx_val = strtoul(idx, &idx, 0);
3959 CHECK(!idx[0], EINVAL);
3961 instr->type = INSTR_REGRD_MRI;
3963 instr->type = INSTR_REGRD_HRI;
3965 instr->regarray.regarray_id = r->id;
3966 instr->regarray.idx_val = idx_val;
3967 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
3968 instr->regarray.dstsrc.n_bits = fdst->n_bits;
3969 instr->regarray.dstsrc.offset = fdst->offset / 8;
3974 instr_regwr_translate(struct rte_swx_pipeline *p,
3975 struct action *action,
3978 struct instruction *instr,
3979 struct instruction_data *data __rte_unused)
3981 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
3983 struct field *fidx, *fsrc;
3985 uint32_t idx_struct_id, idx_val, src_struct_id;
3987 CHECK(n_tokens == 4, EINVAL);
3989 r = regarray_find(p, regarray);
3992 /* REGWR_RHH, REGWR_RHM, REGWR_RMH, REGWR_RMM. */
3993 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
3994 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3996 CHECK(!fidx->var_size, EINVAL);
3997 CHECK(!fsrc->var_size, EINVAL);
3999 instr->type = INSTR_REGWR_RMM;
4000 if (idx[0] == 'h' && src[0] != 'h')
4001 instr->type = INSTR_REGWR_RHM;
4002 if (idx[0] != 'h' && src[0] == 'h')
4003 instr->type = INSTR_REGWR_RMH;
4004 if (idx[0] == 'h' && src[0] == 'h')
4005 instr->type = INSTR_REGWR_RHH;
4007 instr->regarray.regarray_id = r->id;
4008 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4009 instr->regarray.idx.n_bits = fidx->n_bits;
4010 instr->regarray.idx.offset = fidx->offset / 8;
4011 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4012 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4013 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4017 /* REGWR_RHI, REGWR_RMI. */
4018 if (fidx && !fsrc) {
4019 CHECK(!fidx->var_size, EINVAL);
4021 src_val = strtoull(src, &src, 0);
4022 CHECK(!src[0], EINVAL);
4024 instr->type = INSTR_REGWR_RMI;
4026 instr->type = INSTR_REGWR_RHI;
4028 instr->regarray.regarray_id = r->id;
4029 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4030 instr->regarray.idx.n_bits = fidx->n_bits;
4031 instr->regarray.idx.offset = fidx->offset / 8;
4032 instr->regarray.dstsrc_val = src_val;
4036 /* REGWR_RIH, REGWR_RIM. */
4037 if (!fidx && fsrc) {
4038 idx_val = strtoul(idx, &idx, 0);
4039 CHECK(!idx[0], EINVAL);
4041 CHECK(!fsrc->var_size, EINVAL);
4043 instr->type = INSTR_REGWR_RIM;
4045 instr->type = INSTR_REGWR_RIH;
4047 instr->regarray.regarray_id = r->id;
4048 instr->regarray.idx_val = idx_val;
4049 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4050 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4051 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4056 src_val = strtoull(src, &src, 0);
4057 CHECK(!src[0], EINVAL);
4059 idx_val = strtoul(idx, &idx, 0);
4060 CHECK(!idx[0], EINVAL);
4062 instr->type = INSTR_REGWR_RII;
4063 instr->regarray.idx_val = idx_val;
4064 instr->regarray.dstsrc_val = src_val;
4070 instr_regadd_translate(struct rte_swx_pipeline *p,
4071 struct action *action,
4074 struct instruction *instr,
4075 struct instruction_data *data __rte_unused)
4077 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
4079 struct field *fidx, *fsrc;
4081 uint32_t idx_struct_id, idx_val, src_struct_id;
4083 CHECK(n_tokens == 4, EINVAL);
4085 r = regarray_find(p, regarray);
4088 /* REGADD_RHH, REGADD_RHM, REGADD_RMH, REGADD_RMM. */
4089 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4090 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4092 CHECK(!fidx->var_size, EINVAL);
4093 CHECK(!fsrc->var_size, EINVAL);
4095 instr->type = INSTR_REGADD_RMM;
4096 if (idx[0] == 'h' && src[0] != 'h')
4097 instr->type = INSTR_REGADD_RHM;
4098 if (idx[0] != 'h' && src[0] == 'h')
4099 instr->type = INSTR_REGADD_RMH;
4100 if (idx[0] == 'h' && src[0] == 'h')
4101 instr->type = INSTR_REGADD_RHH;
4103 instr->regarray.regarray_id = r->id;
4104 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4105 instr->regarray.idx.n_bits = fidx->n_bits;
4106 instr->regarray.idx.offset = fidx->offset / 8;
4107 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4108 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4109 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4113 /* REGADD_RHI, REGADD_RMI. */
4114 if (fidx && !fsrc) {
4115 CHECK(!fidx->var_size, EINVAL);
4117 src_val = strtoull(src, &src, 0);
4118 CHECK(!src[0], EINVAL);
4120 instr->type = INSTR_REGADD_RMI;
4122 instr->type = INSTR_REGADD_RHI;
4124 instr->regarray.regarray_id = r->id;
4125 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4126 instr->regarray.idx.n_bits = fidx->n_bits;
4127 instr->regarray.idx.offset = fidx->offset / 8;
4128 instr->regarray.dstsrc_val = src_val;
4132 /* REGADD_RIH, REGADD_RIM. */
4133 if (!fidx && fsrc) {
4134 idx_val = strtoul(idx, &idx, 0);
4135 CHECK(!idx[0], EINVAL);
4137 CHECK(!fsrc->var_size, EINVAL);
4139 instr->type = INSTR_REGADD_RIM;
4141 instr->type = INSTR_REGADD_RIH;
4143 instr->regarray.regarray_id = r->id;
4144 instr->regarray.idx_val = idx_val;
4145 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4146 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4147 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4152 src_val = strtoull(src, &src, 0);
4153 CHECK(!src[0], EINVAL);
4155 idx_val = strtoul(idx, &idx, 0);
4156 CHECK(!idx[0], EINVAL);
4158 instr->type = INSTR_REGADD_RII;
4159 instr->regarray.idx_val = idx_val;
4160 instr->regarray.dstsrc_val = src_val;
4164 static inline uint64_t *
4165 instr_regarray_regarray(struct rte_swx_pipeline *p, struct instruction *ip)
4167 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4171 static inline uint64_t
4172 instr_regarray_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
4174 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4176 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
4177 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
4178 uint64_t idx64 = *idx64_ptr;
4179 uint64_t idx64_mask = UINT64_MAX >> (64 - ip->regarray.idx.n_bits);
4180 uint64_t idx = idx64 & idx64_mask & r->size_mask;
4185 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4187 static inline uint64_t
4188 instr_regarray_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
4190 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4192 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
4193 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
4194 uint64_t idx64 = *idx64_ptr;
4195 uint64_t idx = (ntoh64(idx64) >> (64 - ip->regarray.idx.n_bits)) & r->size_mask;
4202 #define instr_regarray_idx_nbo instr_regarray_idx_hbo
4206 static inline uint64_t
4207 instr_regarray_idx_imm(struct rte_swx_pipeline *p, struct instruction *ip)
4209 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4211 uint64_t idx = ip->regarray.idx_val & r->size_mask;
4216 static inline uint64_t
4217 instr_regarray_src_hbo(struct thread *t, struct instruction *ip)
4219 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
4220 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
4221 uint64_t src64 = *src64_ptr;
4222 uint64_t src64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
4223 uint64_t src = src64 & src64_mask;
4228 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4230 static inline uint64_t
4231 instr_regarray_src_nbo(struct thread *t, struct instruction *ip)
4233 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
4234 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
4235 uint64_t src64 = *src64_ptr;
4236 uint64_t src = ntoh64(src64) >> (64 - ip->regarray.dstsrc.n_bits);
4243 #define instr_regarray_src_nbo instr_regarray_src_hbo
4248 instr_regarray_dst_hbo_src_hbo_set(struct thread *t, struct instruction *ip, uint64_t src)
4250 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
4251 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
4252 uint64_t dst64 = *dst64_ptr;
4253 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
4255 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
4259 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4262 instr_regarray_dst_nbo_src_hbo_set(struct thread *t, struct instruction *ip, uint64_t src)
4264 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
4265 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
4266 uint64_t dst64 = *dst64_ptr;
4267 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
4269 src = hton64(src) >> (64 - ip->regarray.dstsrc.n_bits);
4270 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
4275 #define instr_regarray_dst_nbo_src_hbo_set instr_regarray_dst_hbo_src_hbo_set
4280 instr_regprefetch_rh_exec(struct rte_swx_pipeline *p)
4282 struct thread *t = &p->threads[p->thread_id];
4283 struct instruction *ip = t->ip;
4284 uint64_t *regarray, idx;
4286 TRACE("[Thread %2u] regprefetch (r[h])\n", p->thread_id);
4289 regarray = instr_regarray_regarray(p, ip);
4290 idx = instr_regarray_idx_nbo(p, t, ip);
4291 rte_prefetch0(®array[idx]);
4298 instr_regprefetch_rm_exec(struct rte_swx_pipeline *p)
4300 struct thread *t = &p->threads[p->thread_id];
4301 struct instruction *ip = t->ip;
4302 uint64_t *regarray, idx;
4304 TRACE("[Thread %2u] regprefetch (r[m])\n", p->thread_id);
4307 regarray = instr_regarray_regarray(p, ip);
4308 idx = instr_regarray_idx_hbo(p, t, ip);
4309 rte_prefetch0(®array[idx]);
4316 instr_regprefetch_ri_exec(struct rte_swx_pipeline *p)
4318 struct thread *t = &p->threads[p->thread_id];
4319 struct instruction *ip = t->ip;
4320 uint64_t *regarray, idx;
4322 TRACE("[Thread %2u] regprefetch (r[i])\n", p->thread_id);
4325 regarray = instr_regarray_regarray(p, ip);
4326 idx = instr_regarray_idx_imm(p, ip);
4327 rte_prefetch0(®array[idx]);
4334 instr_regrd_hrh_exec(struct rte_swx_pipeline *p)
4336 struct thread *t = &p->threads[p->thread_id];
4337 struct instruction *ip = t->ip;
4338 uint64_t *regarray, idx;
4340 TRACE("[Thread %2u] regrd (h = r[h])\n", p->thread_id);
4343 regarray = instr_regarray_regarray(p, ip);
4344 idx = instr_regarray_idx_nbo(p, t, ip);
4345 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
4352 instr_regrd_hrm_exec(struct rte_swx_pipeline *p)
4354 struct thread *t = &p->threads[p->thread_id];
4355 struct instruction *ip = t->ip;
4356 uint64_t *regarray, idx;
4358 TRACE("[Thread %2u] regrd (h = r[m])\n", p->thread_id);
4361 regarray = instr_regarray_regarray(p, ip);
4362 idx = instr_regarray_idx_hbo(p, t, ip);
4363 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
4370 instr_regrd_mrh_exec(struct rte_swx_pipeline *p)
4372 struct thread *t = &p->threads[p->thread_id];
4373 struct instruction *ip = t->ip;
4374 uint64_t *regarray, idx;
4376 TRACE("[Thread %2u] regrd (m = r[h])\n", p->thread_id);
4379 regarray = instr_regarray_regarray(p, ip);
4380 idx = instr_regarray_idx_nbo(p, t, ip);
4381 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
4388 instr_regrd_mrm_exec(struct rte_swx_pipeline *p)
4390 struct thread *t = &p->threads[p->thread_id];
4391 struct instruction *ip = t->ip;
4392 uint64_t *regarray, idx;
4395 regarray = instr_regarray_regarray(p, ip);
4396 idx = instr_regarray_idx_hbo(p, t, ip);
4397 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
4404 instr_regrd_hri_exec(struct rte_swx_pipeline *p)
4406 struct thread *t = &p->threads[p->thread_id];
4407 struct instruction *ip = t->ip;
4408 uint64_t *regarray, idx;
4410 TRACE("[Thread %2u] regrd (h = r[i])\n", p->thread_id);
4413 regarray = instr_regarray_regarray(p, ip);
4414 idx = instr_regarray_idx_imm(p, ip);
4415 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
4422 instr_regrd_mri_exec(struct rte_swx_pipeline *p)
4424 struct thread *t = &p->threads[p->thread_id];
4425 struct instruction *ip = t->ip;
4426 uint64_t *regarray, idx;
4428 TRACE("[Thread %2u] regrd (m = r[i])\n", p->thread_id);
4431 regarray = instr_regarray_regarray(p, ip);
4432 idx = instr_regarray_idx_imm(p, ip);
4433 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
4440 instr_regwr_rhh_exec(struct rte_swx_pipeline *p)
4442 struct thread *t = &p->threads[p->thread_id];
4443 struct instruction *ip = t->ip;
4444 uint64_t *regarray, idx, src;
4446 TRACE("[Thread %2u] regwr (r[h] = h)\n", p->thread_id);
4449 regarray = instr_regarray_regarray(p, ip);
4450 idx = instr_regarray_idx_nbo(p, t, ip);
4451 src = instr_regarray_src_nbo(t, ip);
4452 regarray[idx] = src;
4459 instr_regwr_rhm_exec(struct rte_swx_pipeline *p)
4461 struct thread *t = &p->threads[p->thread_id];
4462 struct instruction *ip = t->ip;
4463 uint64_t *regarray, idx, src;
4465 TRACE("[Thread %2u] regwr (r[h] = m)\n", p->thread_id);
4468 regarray = instr_regarray_regarray(p, ip);
4469 idx = instr_regarray_idx_nbo(p, t, ip);
4470 src = instr_regarray_src_hbo(t, ip);
4471 regarray[idx] = src;
4478 instr_regwr_rmh_exec(struct rte_swx_pipeline *p)
4480 struct thread *t = &p->threads[p->thread_id];
4481 struct instruction *ip = t->ip;
4482 uint64_t *regarray, idx, src;
4484 TRACE("[Thread %2u] regwr (r[m] = h)\n", p->thread_id);
4487 regarray = instr_regarray_regarray(p, ip);
4488 idx = instr_regarray_idx_hbo(p, t, ip);
4489 src = instr_regarray_src_nbo(t, ip);
4490 regarray[idx] = src;
4497 instr_regwr_rmm_exec(struct rte_swx_pipeline *p)
4499 struct thread *t = &p->threads[p->thread_id];
4500 struct instruction *ip = t->ip;
4501 uint64_t *regarray, idx, src;
4503 TRACE("[Thread %2u] regwr (r[m] = m)\n", p->thread_id);
4506 regarray = instr_regarray_regarray(p, ip);
4507 idx = instr_regarray_idx_hbo(p, t, ip);
4508 src = instr_regarray_src_hbo(t, ip);
4509 regarray[idx] = src;
4516 instr_regwr_rhi_exec(struct rte_swx_pipeline *p)
4518 struct thread *t = &p->threads[p->thread_id];
4519 struct instruction *ip = t->ip;
4520 uint64_t *regarray, idx, src;
4522 TRACE("[Thread %2u] regwr (r[h] = i)\n", p->thread_id);
4525 regarray = instr_regarray_regarray(p, ip);
4526 idx = instr_regarray_idx_nbo(p, t, ip);
4527 src = ip->regarray.dstsrc_val;
4528 regarray[idx] = src;
4535 instr_regwr_rmi_exec(struct rte_swx_pipeline *p)
4537 struct thread *t = &p->threads[p->thread_id];
4538 struct instruction *ip = t->ip;
4539 uint64_t *regarray, idx, src;
4541 TRACE("[Thread %2u] regwr (r[m] = i)\n", p->thread_id);
4544 regarray = instr_regarray_regarray(p, ip);
4545 idx = instr_regarray_idx_hbo(p, t, ip);
4546 src = ip->regarray.dstsrc_val;
4547 regarray[idx] = src;
4554 instr_regwr_rih_exec(struct rte_swx_pipeline *p)
4556 struct thread *t = &p->threads[p->thread_id];
4557 struct instruction *ip = t->ip;
4558 uint64_t *regarray, idx, src;
4560 TRACE("[Thread %2u] regwr (r[i] = h)\n", p->thread_id);
4563 regarray = instr_regarray_regarray(p, ip);
4564 idx = instr_regarray_idx_imm(p, ip);
4565 src = instr_regarray_src_nbo(t, ip);
4566 regarray[idx] = src;
4573 instr_regwr_rim_exec(struct rte_swx_pipeline *p)
4575 struct thread *t = &p->threads[p->thread_id];
4576 struct instruction *ip = t->ip;
4577 uint64_t *regarray, idx, src;
4579 TRACE("[Thread %2u] regwr (r[i] = m)\n", p->thread_id);
4582 regarray = instr_regarray_regarray(p, ip);
4583 idx = instr_regarray_idx_imm(p, ip);
4584 src = instr_regarray_src_hbo(t, ip);
4585 regarray[idx] = src;
4592 instr_regwr_rii_exec(struct rte_swx_pipeline *p)
4594 struct thread *t = &p->threads[p->thread_id];
4595 struct instruction *ip = t->ip;
4596 uint64_t *regarray, idx, src;
4598 TRACE("[Thread %2u] regwr (r[i] = i)\n", p->thread_id);
4601 regarray = instr_regarray_regarray(p, ip);
4602 idx = instr_regarray_idx_imm(p, ip);
4603 src = ip->regarray.dstsrc_val;
4604 regarray[idx] = src;
4611 instr_regadd_rhh_exec(struct rte_swx_pipeline *p)
4613 struct thread *t = &p->threads[p->thread_id];
4614 struct instruction *ip = t->ip;
4615 uint64_t *regarray, idx, src;
4617 TRACE("[Thread %2u] regadd (r[h] += h)\n", p->thread_id);
4620 regarray = instr_regarray_regarray(p, ip);
4621 idx = instr_regarray_idx_nbo(p, t, ip);
4622 src = instr_regarray_src_nbo(t, ip);
4623 regarray[idx] += src;
4630 instr_regadd_rhm_exec(struct rte_swx_pipeline *p)
4632 struct thread *t = &p->threads[p->thread_id];
4633 struct instruction *ip = t->ip;
4634 uint64_t *regarray, idx, src;
4636 TRACE("[Thread %2u] regadd (r[h] += m)\n", p->thread_id);
4639 regarray = instr_regarray_regarray(p, ip);
4640 idx = instr_regarray_idx_nbo(p, t, ip);
4641 src = instr_regarray_src_hbo(t, ip);
4642 regarray[idx] += src;
4649 instr_regadd_rmh_exec(struct rte_swx_pipeline *p)
4651 struct thread *t = &p->threads[p->thread_id];
4652 struct instruction *ip = t->ip;
4653 uint64_t *regarray, idx, src;
4655 TRACE("[Thread %2u] regadd (r[m] += h)\n", p->thread_id);
4658 regarray = instr_regarray_regarray(p, ip);
4659 idx = instr_regarray_idx_hbo(p, t, ip);
4660 src = instr_regarray_src_nbo(t, ip);
4661 regarray[idx] += src;
4668 instr_regadd_rmm_exec(struct rte_swx_pipeline *p)
4670 struct thread *t = &p->threads[p->thread_id];
4671 struct instruction *ip = t->ip;
4672 uint64_t *regarray, idx, src;
4674 TRACE("[Thread %2u] regadd (r[m] += m)\n", p->thread_id);
4677 regarray = instr_regarray_regarray(p, ip);
4678 idx = instr_regarray_idx_hbo(p, t, ip);
4679 src = instr_regarray_src_hbo(t, ip);
4680 regarray[idx] += src;
4687 instr_regadd_rhi_exec(struct rte_swx_pipeline *p)
4689 struct thread *t = &p->threads[p->thread_id];
4690 struct instruction *ip = t->ip;
4691 uint64_t *regarray, idx, src;
4693 TRACE("[Thread %2u] regadd (r[h] += i)\n", p->thread_id);
4696 regarray = instr_regarray_regarray(p, ip);
4697 idx = instr_regarray_idx_nbo(p, t, ip);
4698 src = ip->regarray.dstsrc_val;
4699 regarray[idx] += src;
4706 instr_regadd_rmi_exec(struct rte_swx_pipeline *p)
4708 struct thread *t = &p->threads[p->thread_id];
4709 struct instruction *ip = t->ip;
4710 uint64_t *regarray, idx, src;
4712 TRACE("[Thread %2u] regadd (r[m] += i)\n", p->thread_id);
4715 regarray = instr_regarray_regarray(p, ip);
4716 idx = instr_regarray_idx_hbo(p, t, ip);
4717 src = ip->regarray.dstsrc_val;
4718 regarray[idx] += src;
4725 instr_regadd_rih_exec(struct rte_swx_pipeline *p)
4727 struct thread *t = &p->threads[p->thread_id];
4728 struct instruction *ip = t->ip;
4729 uint64_t *regarray, idx, src;
4731 TRACE("[Thread %2u] regadd (r[i] += h)\n", p->thread_id);
4734 regarray = instr_regarray_regarray(p, ip);
4735 idx = instr_regarray_idx_imm(p, ip);
4736 src = instr_regarray_src_nbo(t, ip);
4737 regarray[idx] += src;
4744 instr_regadd_rim_exec(struct rte_swx_pipeline *p)
4746 struct thread *t = &p->threads[p->thread_id];
4747 struct instruction *ip = t->ip;
4748 uint64_t *regarray, idx, src;
4750 TRACE("[Thread %2u] regadd (r[i] += m)\n", p->thread_id);
4753 regarray = instr_regarray_regarray(p, ip);
4754 idx = instr_regarray_idx_imm(p, ip);
4755 src = instr_regarray_src_hbo(t, ip);
4756 regarray[idx] += src;
4763 instr_regadd_rii_exec(struct rte_swx_pipeline *p)
4765 struct thread *t = &p->threads[p->thread_id];
4766 struct instruction *ip = t->ip;
4767 uint64_t *regarray, idx, src;
4769 TRACE("[Thread %2u] regadd (r[i] += i)\n", p->thread_id);
4772 regarray = instr_regarray_regarray(p, ip);
4773 idx = instr_regarray_idx_imm(p, ip);
4774 src = ip->regarray.dstsrc_val;
4775 regarray[idx] += src;
4784 static struct metarray *
4785 metarray_find(struct rte_swx_pipeline *p, const char *name);
4788 instr_metprefetch_translate(struct rte_swx_pipeline *p,
4789 struct action *action,
4792 struct instruction *instr,
4793 struct instruction_data *data __rte_unused)
4795 char *metarray = tokens[1], *idx = tokens[2];
4798 uint32_t idx_struct_id, idx_val;
4800 CHECK(n_tokens == 3, EINVAL);
4802 m = metarray_find(p, metarray);
4805 /* METPREFETCH_H, METPREFETCH_M. */
4806 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4808 CHECK(!fidx->var_size, EINVAL);
4810 instr->type = INSTR_METPREFETCH_M;
4812 instr->type = INSTR_METPREFETCH_H;
4814 instr->meter.metarray_id = m->id;
4815 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4816 instr->meter.idx.n_bits = fidx->n_bits;
4817 instr->meter.idx.offset = fidx->offset / 8;
4821 /* METPREFETCH_I. */
4822 idx_val = strtoul(idx, &idx, 0);
4823 CHECK(!idx[0], EINVAL);
4825 instr->type = INSTR_METPREFETCH_I;
4826 instr->meter.metarray_id = m->id;
4827 instr->meter.idx_val = idx_val;
4832 instr_meter_translate(struct rte_swx_pipeline *p,
4833 struct action *action,
4836 struct instruction *instr,
4837 struct instruction_data *data __rte_unused)
4839 char *metarray = tokens[1], *idx = tokens[2], *length = tokens[3];
4840 char *color_in = tokens[4], *color_out = tokens[5];
4842 struct field *fidx, *flength, *fcin, *fcout;
4843 uint32_t idx_struct_id, length_struct_id;
4844 uint32_t color_in_struct_id, color_out_struct_id;
4846 CHECK(n_tokens == 6, EINVAL);
4848 m = metarray_find(p, metarray);
4851 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4853 flength = struct_field_parse(p, action, length, &length_struct_id);
4854 CHECK(flength, EINVAL);
4855 CHECK(!flength->var_size, EINVAL);
4857 fcin = struct_field_parse(p, action, color_in, &color_in_struct_id);
4859 fcout = struct_field_parse(p, NULL, color_out, &color_out_struct_id);
4860 CHECK(fcout, EINVAL);
4861 CHECK(!fcout->var_size, EINVAL);
4863 /* index = HMEFT, length = HMEFT, color_in = MEFT, color_out = MEF. */
4865 CHECK(!fidx->var_size, EINVAL);
4866 CHECK(!fcin->var_size, EINVAL);
4868 instr->type = INSTR_METER_MMM;
4869 if (idx[0] == 'h' && length[0] == 'h')
4870 instr->type = INSTR_METER_HHM;
4871 if (idx[0] == 'h' && length[0] != 'h')
4872 instr->type = INSTR_METER_HMM;
4873 if (idx[0] != 'h' && length[0] == 'h')
4874 instr->type = INSTR_METER_MHM;
4876 instr->meter.metarray_id = m->id;
4878 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4879 instr->meter.idx.n_bits = fidx->n_bits;
4880 instr->meter.idx.offset = fidx->offset / 8;
4882 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4883 instr->meter.length.n_bits = flength->n_bits;
4884 instr->meter.length.offset = flength->offset / 8;
4886 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
4887 instr->meter.color_in.n_bits = fcin->n_bits;
4888 instr->meter.color_in.offset = fcin->offset / 8;
4890 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4891 instr->meter.color_out.n_bits = fcout->n_bits;
4892 instr->meter.color_out.offset = fcout->offset / 8;
4897 /* index = HMEFT, length = HMEFT, color_in = I, color_out = MEF. */
4898 if (fidx && !fcin) {
4899 uint32_t color_in_val;
4901 CHECK(!fidx->var_size, EINVAL);
4903 color_in_val = strtoul(color_in, &color_in, 0);
4904 CHECK(!color_in[0], EINVAL);
4906 instr->type = INSTR_METER_MMI;
4907 if (idx[0] == 'h' && length[0] == 'h')
4908 instr->type = INSTR_METER_HHI;
4909 if (idx[0] == 'h' && length[0] != 'h')
4910 instr->type = INSTR_METER_HMI;
4911 if (idx[0] != 'h' && length[0] == 'h')
4912 instr->type = INSTR_METER_MHI;
4914 instr->meter.metarray_id = m->id;
4916 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4917 instr->meter.idx.n_bits = fidx->n_bits;
4918 instr->meter.idx.offset = fidx->offset / 8;
4920 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4921 instr->meter.length.n_bits = flength->n_bits;
4922 instr->meter.length.offset = flength->offset / 8;
4924 instr->meter.color_in_val = color_in_val;
4926 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4927 instr->meter.color_out.n_bits = fcout->n_bits;
4928 instr->meter.color_out.offset = fcout->offset / 8;
4933 /* index = I, length = HMEFT, color_in = MEFT, color_out = MEF. */
4934 if (!fidx && fcin) {
4937 idx_val = strtoul(idx, &idx, 0);
4938 CHECK(!idx[0], EINVAL);
4940 CHECK(!fcin->var_size, EINVAL);
4942 instr->type = INSTR_METER_IMM;
4943 if (length[0] == 'h')
4944 instr->type = INSTR_METER_IHM;
4946 instr->meter.metarray_id = m->id;
4948 instr->meter.idx_val = idx_val;
4950 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4951 instr->meter.length.n_bits = flength->n_bits;
4952 instr->meter.length.offset = flength->offset / 8;
4954 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
4955 instr->meter.color_in.n_bits = fcin->n_bits;
4956 instr->meter.color_in.offset = fcin->offset / 8;
4958 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4959 instr->meter.color_out.n_bits = fcout->n_bits;
4960 instr->meter.color_out.offset = fcout->offset / 8;
4965 /* index = I, length = HMEFT, color_in = I, color_out = MEF. */
4966 if (!fidx && !fcin) {
4967 uint32_t idx_val, color_in_val;
4969 idx_val = strtoul(idx, &idx, 0);
4970 CHECK(!idx[0], EINVAL);
4972 color_in_val = strtoul(color_in, &color_in, 0);
4973 CHECK(!color_in[0], EINVAL);
4975 instr->type = INSTR_METER_IMI;
4976 if (length[0] == 'h')
4977 instr->type = INSTR_METER_IHI;
4979 instr->meter.metarray_id = m->id;
4981 instr->meter.idx_val = idx_val;
4983 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4984 instr->meter.length.n_bits = flength->n_bits;
4985 instr->meter.length.offset = flength->offset / 8;
4987 instr->meter.color_in_val = color_in_val;
4989 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4990 instr->meter.color_out.n_bits = fcout->n_bits;
4991 instr->meter.color_out.offset = fcout->offset / 8;
4999 static inline struct meter *
5000 instr_meter_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
5002 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
5004 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
5005 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
5006 uint64_t idx64 = *idx64_ptr;
5007 uint64_t idx64_mask = UINT64_MAX >> (64 - (ip)->meter.idx.n_bits);
5008 uint64_t idx = idx64 & idx64_mask & r->size_mask;
5010 return &r->metarray[idx];
5013 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5015 static inline struct meter *
5016 instr_meter_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
5018 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
5020 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
5021 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
5022 uint64_t idx64 = *idx64_ptr;
5023 uint64_t idx = (ntoh64(idx64) >> (64 - ip->meter.idx.n_bits)) & r->size_mask;
5025 return &r->metarray[idx];
5030 #define instr_meter_idx_nbo instr_meter_idx_hbo
5034 static inline struct meter *
5035 instr_meter_idx_imm(struct rte_swx_pipeline *p, struct instruction *ip)
5037 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
5039 uint64_t idx = ip->meter.idx_val & r->size_mask;
5041 return &r->metarray[idx];
5044 static inline uint32_t
5045 instr_meter_length_hbo(struct thread *t, struct instruction *ip)
5047 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
5048 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
5049 uint64_t src64 = *src64_ptr;
5050 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->meter.length.n_bits);
5051 uint64_t src = src64 & src64_mask;
5053 return (uint32_t)src;
5056 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5058 static inline uint32_t
5059 instr_meter_length_nbo(struct thread *t, struct instruction *ip)
5061 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
5062 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
5063 uint64_t src64 = *src64_ptr;
5064 uint64_t src = ntoh64(src64) >> (64 - ip->meter.length.n_bits);
5066 return (uint32_t)src;
5071 #define instr_meter_length_nbo instr_meter_length_hbo
5075 static inline enum rte_color
5076 instr_meter_color_in_hbo(struct thread *t, struct instruction *ip)
5078 uint8_t *src_struct = t->structs[ip->meter.color_in.struct_id];
5079 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.color_in.offset];
5080 uint64_t src64 = *src64_ptr;
5081 uint64_t src64_mask = UINT64_MAX >> (64 - ip->meter.color_in.n_bits);
5082 uint64_t src = src64 & src64_mask;
5084 return (enum rte_color)src;
5088 instr_meter_color_out_hbo_set(struct thread *t, struct instruction *ip, enum rte_color color_out)
5090 uint8_t *dst_struct = t->structs[ip->meter.color_out.struct_id];
5091 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->meter.color_out.offset];
5092 uint64_t dst64 = *dst64_ptr;
5093 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->meter.color_out.n_bits);
5095 uint64_t src = (uint64_t)color_out;
5097 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
5101 instr_metprefetch_h_exec(struct rte_swx_pipeline *p)
5103 struct thread *t = &p->threads[p->thread_id];
5104 struct instruction *ip = t->ip;
5107 TRACE("[Thread %2u] metprefetch (h)\n", p->thread_id);
5110 m = instr_meter_idx_nbo(p, t, ip);
5118 instr_metprefetch_m_exec(struct rte_swx_pipeline *p)
5120 struct thread *t = &p->threads[p->thread_id];
5121 struct instruction *ip = t->ip;
5124 TRACE("[Thread %2u] metprefetch (m)\n", p->thread_id);
5127 m = instr_meter_idx_hbo(p, t, ip);
5135 instr_metprefetch_i_exec(struct rte_swx_pipeline *p)
5137 struct thread *t = &p->threads[p->thread_id];
5138 struct instruction *ip = t->ip;
5141 TRACE("[Thread %2u] metprefetch (i)\n", p->thread_id);
5144 m = instr_meter_idx_imm(p, ip);
5152 instr_meter_hhm_exec(struct rte_swx_pipeline *p)
5154 struct thread *t = &p->threads[p->thread_id];
5155 struct instruction *ip = t->ip;
5157 uint64_t time, n_pkts, n_bytes;
5159 enum rte_color color_in, color_out;
5161 TRACE("[Thread %2u] meter (hhm)\n", p->thread_id);
5164 m = instr_meter_idx_nbo(p, t, ip);
5165 rte_prefetch0(m->n_pkts);
5166 time = rte_get_tsc_cycles();
5167 length = instr_meter_length_nbo(t, ip);
5168 color_in = instr_meter_color_in_hbo(t, ip);
5170 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5171 &m->profile->profile,
5176 color_out &= m->color_mask;
5178 n_pkts = m->n_pkts[color_out];
5179 n_bytes = m->n_bytes[color_out];
5181 instr_meter_color_out_hbo_set(t, ip, color_out);
5183 m->n_pkts[color_out] = n_pkts + 1;
5184 m->n_bytes[color_out] = n_bytes + length;
5191 instr_meter_hhi_exec(struct rte_swx_pipeline *p)
5193 struct thread *t = &p->threads[p->thread_id];
5194 struct instruction *ip = t->ip;
5196 uint64_t time, n_pkts, n_bytes;
5198 enum rte_color color_in, color_out;
5200 TRACE("[Thread %2u] meter (hhi)\n", p->thread_id);
5203 m = instr_meter_idx_nbo(p, t, ip);
5204 rte_prefetch0(m->n_pkts);
5205 time = rte_get_tsc_cycles();
5206 length = instr_meter_length_nbo(t, ip);
5207 color_in = (enum rte_color)ip->meter.color_in_val;
5209 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5210 &m->profile->profile,
5215 color_out &= m->color_mask;
5217 n_pkts = m->n_pkts[color_out];
5218 n_bytes = m->n_bytes[color_out];
5220 instr_meter_color_out_hbo_set(t, ip, color_out);
5222 m->n_pkts[color_out] = n_pkts + 1;
5223 m->n_bytes[color_out] = n_bytes + length;
5230 instr_meter_hmm_exec(struct rte_swx_pipeline *p)
5232 struct thread *t = &p->threads[p->thread_id];
5233 struct instruction *ip = t->ip;
5235 uint64_t time, n_pkts, n_bytes;
5237 enum rte_color color_in, color_out;
5239 TRACE("[Thread %2u] meter (hmm)\n", p->thread_id);
5242 m = instr_meter_idx_nbo(p, t, ip);
5243 rte_prefetch0(m->n_pkts);
5244 time = rte_get_tsc_cycles();
5245 length = instr_meter_length_hbo(t, ip);
5246 color_in = instr_meter_color_in_hbo(t, ip);
5248 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5249 &m->profile->profile,
5254 color_out &= m->color_mask;
5256 n_pkts = m->n_pkts[color_out];
5257 n_bytes = m->n_bytes[color_out];
5259 instr_meter_color_out_hbo_set(t, ip, color_out);
5261 m->n_pkts[color_out] = n_pkts + 1;
5262 m->n_bytes[color_out] = n_bytes + length;
5268 instr_meter_hmi_exec(struct rte_swx_pipeline *p)
5270 struct thread *t = &p->threads[p->thread_id];
5271 struct instruction *ip = t->ip;
5273 uint64_t time, n_pkts, n_bytes;
5275 enum rte_color color_in, color_out;
5277 TRACE("[Thread %2u] meter (hmi)\n", p->thread_id);
5280 m = instr_meter_idx_nbo(p, t, ip);
5281 rte_prefetch0(m->n_pkts);
5282 time = rte_get_tsc_cycles();
5283 length = instr_meter_length_hbo(t, ip);
5284 color_in = (enum rte_color)ip->meter.color_in_val;
5286 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5287 &m->profile->profile,
5292 color_out &= m->color_mask;
5294 n_pkts = m->n_pkts[color_out];
5295 n_bytes = m->n_bytes[color_out];
5297 instr_meter_color_out_hbo_set(t, ip, color_out);
5299 m->n_pkts[color_out] = n_pkts + 1;
5300 m->n_bytes[color_out] = n_bytes + length;
5307 instr_meter_mhm_exec(struct rte_swx_pipeline *p)
5309 struct thread *t = &p->threads[p->thread_id];
5310 struct instruction *ip = t->ip;
5312 uint64_t time, n_pkts, n_bytes;
5314 enum rte_color color_in, color_out;
5316 TRACE("[Thread %2u] meter (mhm)\n", p->thread_id);
5319 m = instr_meter_idx_hbo(p, t, ip);
5320 rte_prefetch0(m->n_pkts);
5321 time = rte_get_tsc_cycles();
5322 length = instr_meter_length_nbo(t, ip);
5323 color_in = instr_meter_color_in_hbo(t, ip);
5325 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5326 &m->profile->profile,
5331 color_out &= m->color_mask;
5333 n_pkts = m->n_pkts[color_out];
5334 n_bytes = m->n_bytes[color_out];
5336 instr_meter_color_out_hbo_set(t, ip, color_out);
5338 m->n_pkts[color_out] = n_pkts + 1;
5339 m->n_bytes[color_out] = n_bytes + length;
5346 instr_meter_mhi_exec(struct rte_swx_pipeline *p)
5348 struct thread *t = &p->threads[p->thread_id];
5349 struct instruction *ip = t->ip;
5351 uint64_t time, n_pkts, n_bytes;
5353 enum rte_color color_in, color_out;
5355 TRACE("[Thread %2u] meter (mhi)\n", p->thread_id);
5358 m = instr_meter_idx_hbo(p, t, ip);
5359 rte_prefetch0(m->n_pkts);
5360 time = rte_get_tsc_cycles();
5361 length = instr_meter_length_nbo(t, ip);
5362 color_in = (enum rte_color)ip->meter.color_in_val;
5364 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5365 &m->profile->profile,
5370 color_out &= m->color_mask;
5372 n_pkts = m->n_pkts[color_out];
5373 n_bytes = m->n_bytes[color_out];
5375 instr_meter_color_out_hbo_set(t, ip, color_out);
5377 m->n_pkts[color_out] = n_pkts + 1;
5378 m->n_bytes[color_out] = n_bytes + length;
5385 instr_meter_mmm_exec(struct rte_swx_pipeline *p)
5387 struct thread *t = &p->threads[p->thread_id];
5388 struct instruction *ip = t->ip;
5390 uint64_t time, n_pkts, n_bytes;
5392 enum rte_color color_in, color_out;
5394 TRACE("[Thread %2u] meter (mmm)\n", p->thread_id);
5397 m = instr_meter_idx_hbo(p, t, ip);
5398 rte_prefetch0(m->n_pkts);
5399 time = rte_get_tsc_cycles();
5400 length = instr_meter_length_hbo(t, ip);
5401 color_in = instr_meter_color_in_hbo(t, ip);
5403 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5404 &m->profile->profile,
5409 color_out &= m->color_mask;
5411 n_pkts = m->n_pkts[color_out];
5412 n_bytes = m->n_bytes[color_out];
5414 instr_meter_color_out_hbo_set(t, ip, color_out);
5416 m->n_pkts[color_out] = n_pkts + 1;
5417 m->n_bytes[color_out] = n_bytes + length;
5424 instr_meter_mmi_exec(struct rte_swx_pipeline *p)
5426 struct thread *t = &p->threads[p->thread_id];
5427 struct instruction *ip = t->ip;
5429 uint64_t time, n_pkts, n_bytes;
5431 enum rte_color color_in, color_out;
5433 TRACE("[Thread %2u] meter (mmi)\n", p->thread_id);
5436 m = instr_meter_idx_hbo(p, t, ip);
5437 rte_prefetch0(m->n_pkts);
5438 time = rte_get_tsc_cycles();
5439 length = instr_meter_length_hbo(t, ip);
5440 color_in = (enum rte_color)ip->meter.color_in_val;
5442 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5443 &m->profile->profile,
5448 color_out &= m->color_mask;
5450 n_pkts = m->n_pkts[color_out];
5451 n_bytes = m->n_bytes[color_out];
5453 instr_meter_color_out_hbo_set(t, ip, color_out);
5455 m->n_pkts[color_out] = n_pkts + 1;
5456 m->n_bytes[color_out] = n_bytes + length;
5463 instr_meter_ihm_exec(struct rte_swx_pipeline *p)
5465 struct thread *t = &p->threads[p->thread_id];
5466 struct instruction *ip = t->ip;
5468 uint64_t time, n_pkts, n_bytes;
5470 enum rte_color color_in, color_out;
5472 TRACE("[Thread %2u] meter (ihm)\n", p->thread_id);
5475 m = instr_meter_idx_imm(p, ip);
5476 rte_prefetch0(m->n_pkts);
5477 time = rte_get_tsc_cycles();
5478 length = instr_meter_length_nbo(t, ip);
5479 color_in = instr_meter_color_in_hbo(t, ip);
5481 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5482 &m->profile->profile,
5487 color_out &= m->color_mask;
5489 n_pkts = m->n_pkts[color_out];
5490 n_bytes = m->n_bytes[color_out];
5492 instr_meter_color_out_hbo_set(t, ip, color_out);
5494 m->n_pkts[color_out] = n_pkts + 1;
5495 m->n_bytes[color_out] = n_bytes + length;
5502 instr_meter_ihi_exec(struct rte_swx_pipeline *p)
5504 struct thread *t = &p->threads[p->thread_id];
5505 struct instruction *ip = t->ip;
5507 uint64_t time, n_pkts, n_bytes;
5509 enum rte_color color_in, color_out;
5511 TRACE("[Thread %2u] meter (ihi)\n", p->thread_id);
5514 m = instr_meter_idx_imm(p, ip);
5515 rte_prefetch0(m->n_pkts);
5516 time = rte_get_tsc_cycles();
5517 length = instr_meter_length_nbo(t, ip);
5518 color_in = (enum rte_color)ip->meter.color_in_val;
5520 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5521 &m->profile->profile,
5526 color_out &= m->color_mask;
5528 n_pkts = m->n_pkts[color_out];
5529 n_bytes = m->n_bytes[color_out];
5531 instr_meter_color_out_hbo_set(t, ip, color_out);
5533 m->n_pkts[color_out] = n_pkts + 1;
5534 m->n_bytes[color_out] = n_bytes + length;
5541 instr_meter_imm_exec(struct rte_swx_pipeline *p)
5543 struct thread *t = &p->threads[p->thread_id];
5544 struct instruction *ip = t->ip;
5546 uint64_t time, n_pkts, n_bytes;
5548 enum rte_color color_in, color_out;
5550 TRACE("[Thread %2u] meter (imm)\n", p->thread_id);
5553 m = instr_meter_idx_imm(p, ip);
5554 rte_prefetch0(m->n_pkts);
5555 time = rte_get_tsc_cycles();
5556 length = instr_meter_length_hbo(t, ip);
5557 color_in = instr_meter_color_in_hbo(t, ip);
5559 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5560 &m->profile->profile,
5565 color_out &= m->color_mask;
5567 n_pkts = m->n_pkts[color_out];
5568 n_bytes = m->n_bytes[color_out];
5570 instr_meter_color_out_hbo_set(t, ip, color_out);
5572 m->n_pkts[color_out] = n_pkts + 1;
5573 m->n_bytes[color_out] = n_bytes + length;
5579 instr_meter_imi_exec(struct rte_swx_pipeline *p)
5581 struct thread *t = &p->threads[p->thread_id];
5582 struct instruction *ip = t->ip;
5584 uint64_t time, n_pkts, n_bytes;
5586 enum rte_color color_in, color_out;
5588 TRACE("[Thread %2u] meter (imi)\n", p->thread_id);
5591 m = instr_meter_idx_imm(p, ip);
5592 rte_prefetch0(m->n_pkts);
5593 time = rte_get_tsc_cycles();
5594 length = instr_meter_length_hbo(t, ip);
5595 color_in = (enum rte_color)ip->meter.color_in_val;
5597 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5598 &m->profile->profile,
5603 color_out &= m->color_mask;
5605 n_pkts = m->n_pkts[color_out];
5606 n_bytes = m->n_bytes[color_out];
5608 instr_meter_color_out_hbo_set(t, ip, color_out);
5610 m->n_pkts[color_out] = n_pkts + 1;
5611 m->n_bytes[color_out] = n_bytes + length;
5621 instr_jmp_translate(struct rte_swx_pipeline *p __rte_unused,
5622 struct action *action __rte_unused,
5625 struct instruction *instr,
5626 struct instruction_data *data)
5628 CHECK(n_tokens == 2, EINVAL);
5630 strcpy(data->jmp_label, tokens[1]);
5632 instr->type = INSTR_JMP;
5633 instr->jmp.ip = NULL; /* Resolved later. */
5638 instr_jmp_valid_translate(struct rte_swx_pipeline *p,
5639 struct action *action __rte_unused,
5642 struct instruction *instr,
5643 struct instruction_data *data)
5647 CHECK(n_tokens == 3, EINVAL);
5649 strcpy(data->jmp_label, tokens[1]);
5651 h = header_parse(p, tokens[2]);
5654 instr->type = INSTR_JMP_VALID;
5655 instr->jmp.ip = NULL; /* Resolved later. */
5656 instr->jmp.header_id = h->id;
5661 instr_jmp_invalid_translate(struct rte_swx_pipeline *p,
5662 struct action *action __rte_unused,
5665 struct instruction *instr,
5666 struct instruction_data *data)
5670 CHECK(n_tokens == 3, EINVAL);
5672 strcpy(data->jmp_label, tokens[1]);
5674 h = header_parse(p, tokens[2]);
5677 instr->type = INSTR_JMP_INVALID;
5678 instr->jmp.ip = NULL; /* Resolved later. */
5679 instr->jmp.header_id = h->id;
5684 instr_jmp_hit_translate(struct rte_swx_pipeline *p __rte_unused,
5685 struct action *action,
5688 struct instruction *instr,
5689 struct instruction_data *data)
5691 CHECK(!action, EINVAL);
5692 CHECK(n_tokens == 2, EINVAL);
5694 strcpy(data->jmp_label, tokens[1]);
5696 instr->type = INSTR_JMP_HIT;
5697 instr->jmp.ip = NULL; /* Resolved later. */
5702 instr_jmp_miss_translate(struct rte_swx_pipeline *p __rte_unused,
5703 struct action *action,
5706 struct instruction *instr,
5707 struct instruction_data *data)
5709 CHECK(!action, EINVAL);
5710 CHECK(n_tokens == 2, EINVAL);
5712 strcpy(data->jmp_label, tokens[1]);
5714 instr->type = INSTR_JMP_MISS;
5715 instr->jmp.ip = NULL; /* Resolved later. */
5720 instr_jmp_action_hit_translate(struct rte_swx_pipeline *p,
5721 struct action *action,
5724 struct instruction *instr,
5725 struct instruction_data *data)
5729 CHECK(!action, EINVAL);
5730 CHECK(n_tokens == 3, EINVAL);
5732 strcpy(data->jmp_label, tokens[1]);
5734 a = action_find(p, tokens[2]);
5737 instr->type = INSTR_JMP_ACTION_HIT;
5738 instr->jmp.ip = NULL; /* Resolved later. */
5739 instr->jmp.action_id = a->id;
5744 instr_jmp_action_miss_translate(struct rte_swx_pipeline *p,
5745 struct action *action,
5748 struct instruction *instr,
5749 struct instruction_data *data)
5753 CHECK(!action, EINVAL);
5754 CHECK(n_tokens == 3, EINVAL);
5756 strcpy(data->jmp_label, tokens[1]);
5758 a = action_find(p, tokens[2]);
5761 instr->type = INSTR_JMP_ACTION_MISS;
5762 instr->jmp.ip = NULL; /* Resolved later. */
5763 instr->jmp.action_id = a->id;
5768 instr_jmp_eq_translate(struct rte_swx_pipeline *p,
5769 struct action *action,
5772 struct instruction *instr,
5773 struct instruction_data *data)
5775 char *a = tokens[2], *b = tokens[3];
5776 struct field *fa, *fb;
5778 uint32_t a_struct_id, b_struct_id;
5780 CHECK(n_tokens == 4, EINVAL);
5782 strcpy(data->jmp_label, tokens[1]);
5784 fa = struct_field_parse(p, action, a, &a_struct_id);
5786 CHECK(!fa->var_size, EINVAL);
5788 /* JMP_EQ, JMP_EQ_MH, JMP_EQ_HM, JMP_EQ_HH. */
5789 fb = struct_field_parse(p, action, b, &b_struct_id);
5791 CHECK(!fb->var_size, EINVAL);
5793 instr->type = INSTR_JMP_EQ;
5794 if (a[0] != 'h' && b[0] == 'h')
5795 instr->type = INSTR_JMP_EQ_MH;
5796 if (a[0] == 'h' && b[0] != 'h')
5797 instr->type = INSTR_JMP_EQ_HM;
5798 if (a[0] == 'h' && b[0] == 'h')
5799 instr->type = INSTR_JMP_EQ_HH;
5800 instr->jmp.ip = NULL; /* Resolved later. */
5802 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5803 instr->jmp.a.n_bits = fa->n_bits;
5804 instr->jmp.a.offset = fa->offset / 8;
5805 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5806 instr->jmp.b.n_bits = fb->n_bits;
5807 instr->jmp.b.offset = fb->offset / 8;
5812 b_val = strtoull(b, &b, 0);
5813 CHECK(!b[0], EINVAL);
5816 b_val = hton64(b_val) >> (64 - fa->n_bits);
5818 instr->type = INSTR_JMP_EQ_I;
5819 instr->jmp.ip = NULL; /* Resolved later. */
5820 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5821 instr->jmp.a.n_bits = fa->n_bits;
5822 instr->jmp.a.offset = fa->offset / 8;
5823 instr->jmp.b_val = b_val;
5828 instr_jmp_neq_translate(struct rte_swx_pipeline *p,
5829 struct action *action,
5832 struct instruction *instr,
5833 struct instruction_data *data)
5835 char *a = tokens[2], *b = tokens[3];
5836 struct field *fa, *fb;
5838 uint32_t a_struct_id, b_struct_id;
5840 CHECK(n_tokens == 4, EINVAL);
5842 strcpy(data->jmp_label, tokens[1]);
5844 fa = struct_field_parse(p, action, a, &a_struct_id);
5846 CHECK(!fa->var_size, EINVAL);
5848 /* JMP_NEQ, JMP_NEQ_MH, JMP_NEQ_HM, JMP_NEQ_HH. */
5849 fb = struct_field_parse(p, action, b, &b_struct_id);
5851 CHECK(!fb->var_size, EINVAL);
5853 instr->type = INSTR_JMP_NEQ;
5854 if (a[0] != 'h' && b[0] == 'h')
5855 instr->type = INSTR_JMP_NEQ_MH;
5856 if (a[0] == 'h' && b[0] != 'h')
5857 instr->type = INSTR_JMP_NEQ_HM;
5858 if (a[0] == 'h' && b[0] == 'h')
5859 instr->type = INSTR_JMP_NEQ_HH;
5860 instr->jmp.ip = NULL; /* Resolved later. */
5862 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5863 instr->jmp.a.n_bits = fa->n_bits;
5864 instr->jmp.a.offset = fa->offset / 8;
5865 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5866 instr->jmp.b.n_bits = fb->n_bits;
5867 instr->jmp.b.offset = fb->offset / 8;
5872 b_val = strtoull(b, &b, 0);
5873 CHECK(!b[0], EINVAL);
5876 b_val = hton64(b_val) >> (64 - fa->n_bits);
5878 instr->type = INSTR_JMP_NEQ_I;
5879 instr->jmp.ip = NULL; /* Resolved later. */
5880 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5881 instr->jmp.a.n_bits = fa->n_bits;
5882 instr->jmp.a.offset = fa->offset / 8;
5883 instr->jmp.b_val = b_val;
5888 instr_jmp_lt_translate(struct rte_swx_pipeline *p,
5889 struct action *action,
5892 struct instruction *instr,
5893 struct instruction_data *data)
5895 char *a = tokens[2], *b = tokens[3];
5896 struct field *fa, *fb;
5898 uint32_t a_struct_id, b_struct_id;
5900 CHECK(n_tokens == 4, EINVAL);
5902 strcpy(data->jmp_label, tokens[1]);
5904 fa = struct_field_parse(p, action, a, &a_struct_id);
5906 CHECK(!fa->var_size, EINVAL);
5908 /* JMP_LT, JMP_LT_MH, JMP_LT_HM, JMP_LT_HH. */
5909 fb = struct_field_parse(p, action, b, &b_struct_id);
5911 CHECK(!fb->var_size, EINVAL);
5913 instr->type = INSTR_JMP_LT;
5914 if (a[0] == 'h' && b[0] != 'h')
5915 instr->type = INSTR_JMP_LT_HM;
5916 if (a[0] != 'h' && b[0] == 'h')
5917 instr->type = INSTR_JMP_LT_MH;
5918 if (a[0] == 'h' && b[0] == 'h')
5919 instr->type = INSTR_JMP_LT_HH;
5920 instr->jmp.ip = NULL; /* Resolved later. */
5922 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5923 instr->jmp.a.n_bits = fa->n_bits;
5924 instr->jmp.a.offset = fa->offset / 8;
5925 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5926 instr->jmp.b.n_bits = fb->n_bits;
5927 instr->jmp.b.offset = fb->offset / 8;
5931 /* JMP_LT_MI, JMP_LT_HI. */
5932 b_val = strtoull(b, &b, 0);
5933 CHECK(!b[0], EINVAL);
5935 instr->type = INSTR_JMP_LT_MI;
5937 instr->type = INSTR_JMP_LT_HI;
5938 instr->jmp.ip = NULL; /* Resolved later. */
5940 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5941 instr->jmp.a.n_bits = fa->n_bits;
5942 instr->jmp.a.offset = fa->offset / 8;
5943 instr->jmp.b_val = b_val;
5948 instr_jmp_gt_translate(struct rte_swx_pipeline *p,
5949 struct action *action,
5952 struct instruction *instr,
5953 struct instruction_data *data)
5955 char *a = tokens[2], *b = tokens[3];
5956 struct field *fa, *fb;
5958 uint32_t a_struct_id, b_struct_id;
5960 CHECK(n_tokens == 4, EINVAL);
5962 strcpy(data->jmp_label, tokens[1]);
5964 fa = struct_field_parse(p, action, a, &a_struct_id);
5966 CHECK(!fa->var_size, EINVAL);
5968 /* JMP_GT, JMP_GT_MH, JMP_GT_HM, JMP_GT_HH. */
5969 fb = struct_field_parse(p, action, b, &b_struct_id);
5971 CHECK(!fb->var_size, EINVAL);
5973 instr->type = INSTR_JMP_GT;
5974 if (a[0] == 'h' && b[0] != 'h')
5975 instr->type = INSTR_JMP_GT_HM;
5976 if (a[0] != 'h' && b[0] == 'h')
5977 instr->type = INSTR_JMP_GT_MH;
5978 if (a[0] == 'h' && b[0] == 'h')
5979 instr->type = INSTR_JMP_GT_HH;
5980 instr->jmp.ip = NULL; /* Resolved later. */
5982 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5983 instr->jmp.a.n_bits = fa->n_bits;
5984 instr->jmp.a.offset = fa->offset / 8;
5985 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5986 instr->jmp.b.n_bits = fb->n_bits;
5987 instr->jmp.b.offset = fb->offset / 8;
5991 /* JMP_GT_MI, JMP_GT_HI. */
5992 b_val = strtoull(b, &b, 0);
5993 CHECK(!b[0], EINVAL);
5995 instr->type = INSTR_JMP_GT_MI;
5997 instr->type = INSTR_JMP_GT_HI;
5998 instr->jmp.ip = NULL; /* Resolved later. */
6000 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6001 instr->jmp.a.n_bits = fa->n_bits;
6002 instr->jmp.a.offset = fa->offset / 8;
6003 instr->jmp.b_val = b_val;
6008 instr_jmp_exec(struct rte_swx_pipeline *p)
6010 struct thread *t = &p->threads[p->thread_id];
6011 struct instruction *ip = t->ip;
6013 TRACE("[Thread %2u] jmp\n", p->thread_id);
6015 thread_ip_set(t, ip->jmp.ip);
6019 instr_jmp_valid_exec(struct rte_swx_pipeline *p)
6021 struct thread *t = &p->threads[p->thread_id];
6022 struct instruction *ip = t->ip;
6023 uint32_t header_id = ip->jmp.header_id;
6025 TRACE("[Thread %2u] jmpv\n", p->thread_id);
6027 t->ip = HEADER_VALID(t, header_id) ? ip->jmp.ip : (t->ip + 1);
6031 instr_jmp_invalid_exec(struct rte_swx_pipeline *p)
6033 struct thread *t = &p->threads[p->thread_id];
6034 struct instruction *ip = t->ip;
6035 uint32_t header_id = ip->jmp.header_id;
6037 TRACE("[Thread %2u] jmpnv\n", p->thread_id);
6039 t->ip = HEADER_VALID(t, header_id) ? (t->ip + 1) : ip->jmp.ip;
6043 instr_jmp_hit_exec(struct rte_swx_pipeline *p)
6045 struct thread *t = &p->threads[p->thread_id];
6046 struct instruction *ip = t->ip;
6047 struct instruction *ip_next[] = {t->ip + 1, ip->jmp.ip};
6049 TRACE("[Thread %2u] jmph\n", p->thread_id);
6051 t->ip = ip_next[t->hit];
6055 instr_jmp_miss_exec(struct rte_swx_pipeline *p)
6057 struct thread *t = &p->threads[p->thread_id];
6058 struct instruction *ip = t->ip;
6059 struct instruction *ip_next[] = {ip->jmp.ip, t->ip + 1};
6061 TRACE("[Thread %2u] jmpnh\n", p->thread_id);
6063 t->ip = ip_next[t->hit];
6067 instr_jmp_action_hit_exec(struct rte_swx_pipeline *p)
6069 struct thread *t = &p->threads[p->thread_id];
6070 struct instruction *ip = t->ip;
6072 TRACE("[Thread %2u] jmpa\n", p->thread_id);
6074 t->ip = (ip->jmp.action_id == t->action_id) ? ip->jmp.ip : (t->ip + 1);
6078 instr_jmp_action_miss_exec(struct rte_swx_pipeline *p)
6080 struct thread *t = &p->threads[p->thread_id];
6081 struct instruction *ip = t->ip;
6083 TRACE("[Thread %2u] jmpna\n", p->thread_id);
6085 t->ip = (ip->jmp.action_id == t->action_id) ? (t->ip + 1) : ip->jmp.ip;
6089 instr_jmp_eq_exec(struct rte_swx_pipeline *p)
6091 struct thread *t = &p->threads[p->thread_id];
6092 struct instruction *ip = t->ip;
6094 TRACE("[Thread %2u] jmpeq\n", p->thread_id);
6100 instr_jmp_eq_mh_exec(struct rte_swx_pipeline *p)
6102 struct thread *t = &p->threads[p->thread_id];
6103 struct instruction *ip = t->ip;
6105 TRACE("[Thread %2u] jmpeq (mh)\n", p->thread_id);
6107 JMP_CMP_MH(t, ip, ==);
6111 instr_jmp_eq_hm_exec(struct rte_swx_pipeline *p)
6113 struct thread *t = &p->threads[p->thread_id];
6114 struct instruction *ip = t->ip;
6116 TRACE("[Thread %2u] jmpeq (hm)\n", p->thread_id);
6118 JMP_CMP_HM(t, ip, ==);
6122 instr_jmp_eq_hh_exec(struct rte_swx_pipeline *p)
6124 struct thread *t = &p->threads[p->thread_id];
6125 struct instruction *ip = t->ip;
6127 TRACE("[Thread %2u] jmpeq (hh)\n", p->thread_id);
6129 JMP_CMP_HH_FAST(t, ip, ==);
6133 instr_jmp_eq_i_exec(struct rte_swx_pipeline *p)
6135 struct thread *t = &p->threads[p->thread_id];
6136 struct instruction *ip = t->ip;
6138 TRACE("[Thread %2u] jmpeq (i)\n", p->thread_id);
6140 JMP_CMP_I(t, ip, ==);
6144 instr_jmp_neq_exec(struct rte_swx_pipeline *p)
6146 struct thread *t = &p->threads[p->thread_id];
6147 struct instruction *ip = t->ip;
6149 TRACE("[Thread %2u] jmpneq\n", p->thread_id);
6155 instr_jmp_neq_mh_exec(struct rte_swx_pipeline *p)
6157 struct thread *t = &p->threads[p->thread_id];
6158 struct instruction *ip = t->ip;
6160 TRACE("[Thread %2u] jmpneq (mh)\n", p->thread_id);
6162 JMP_CMP_MH(t, ip, !=);
6166 instr_jmp_neq_hm_exec(struct rte_swx_pipeline *p)
6168 struct thread *t = &p->threads[p->thread_id];
6169 struct instruction *ip = t->ip;
6171 TRACE("[Thread %2u] jmpneq (hm)\n", p->thread_id);
6173 JMP_CMP_HM(t, ip, !=);
6177 instr_jmp_neq_hh_exec(struct rte_swx_pipeline *p)
6179 struct thread *t = &p->threads[p->thread_id];
6180 struct instruction *ip = t->ip;
6182 TRACE("[Thread %2u] jmpneq (hh)\n", p->thread_id);
6184 JMP_CMP_HH_FAST(t, ip, !=);
6188 instr_jmp_neq_i_exec(struct rte_swx_pipeline *p)
6190 struct thread *t = &p->threads[p->thread_id];
6191 struct instruction *ip = t->ip;
6193 TRACE("[Thread %2u] jmpneq (i)\n", p->thread_id);
6195 JMP_CMP_I(t, ip, !=);
6199 instr_jmp_lt_exec(struct rte_swx_pipeline *p)
6201 struct thread *t = &p->threads[p->thread_id];
6202 struct instruction *ip = t->ip;
6204 TRACE("[Thread %2u] jmplt\n", p->thread_id);
6210 instr_jmp_lt_mh_exec(struct rte_swx_pipeline *p)
6212 struct thread *t = &p->threads[p->thread_id];
6213 struct instruction *ip = t->ip;
6215 TRACE("[Thread %2u] jmplt (mh)\n", p->thread_id);
6217 JMP_CMP_MH(t, ip, <);
6221 instr_jmp_lt_hm_exec(struct rte_swx_pipeline *p)
6223 struct thread *t = &p->threads[p->thread_id];
6224 struct instruction *ip = t->ip;
6226 TRACE("[Thread %2u] jmplt (hm)\n", p->thread_id);
6228 JMP_CMP_HM(t, ip, <);
6232 instr_jmp_lt_hh_exec(struct rte_swx_pipeline *p)
6234 struct thread *t = &p->threads[p->thread_id];
6235 struct instruction *ip = t->ip;
6237 TRACE("[Thread %2u] jmplt (hh)\n", p->thread_id);
6239 JMP_CMP_HH(t, ip, <);
6243 instr_jmp_lt_mi_exec(struct rte_swx_pipeline *p)
6245 struct thread *t = &p->threads[p->thread_id];
6246 struct instruction *ip = t->ip;
6248 TRACE("[Thread %2u] jmplt (mi)\n", p->thread_id);
6250 JMP_CMP_MI(t, ip, <);
6254 instr_jmp_lt_hi_exec(struct rte_swx_pipeline *p)
6256 struct thread *t = &p->threads[p->thread_id];
6257 struct instruction *ip = t->ip;
6259 TRACE("[Thread %2u] jmplt (hi)\n", p->thread_id);
6261 JMP_CMP_HI(t, ip, <);
6265 instr_jmp_gt_exec(struct rte_swx_pipeline *p)
6267 struct thread *t = &p->threads[p->thread_id];
6268 struct instruction *ip = t->ip;
6270 TRACE("[Thread %2u] jmpgt\n", p->thread_id);
6276 instr_jmp_gt_mh_exec(struct rte_swx_pipeline *p)
6278 struct thread *t = &p->threads[p->thread_id];
6279 struct instruction *ip = t->ip;
6281 TRACE("[Thread %2u] jmpgt (mh)\n", p->thread_id);
6283 JMP_CMP_MH(t, ip, >);
6287 instr_jmp_gt_hm_exec(struct rte_swx_pipeline *p)
6289 struct thread *t = &p->threads[p->thread_id];
6290 struct instruction *ip = t->ip;
6292 TRACE("[Thread %2u] jmpgt (hm)\n", p->thread_id);
6294 JMP_CMP_HM(t, ip, >);
6298 instr_jmp_gt_hh_exec(struct rte_swx_pipeline *p)
6300 struct thread *t = &p->threads[p->thread_id];
6301 struct instruction *ip = t->ip;
6303 TRACE("[Thread %2u] jmpgt (hh)\n", p->thread_id);
6305 JMP_CMP_HH(t, ip, >);
6309 instr_jmp_gt_mi_exec(struct rte_swx_pipeline *p)
6311 struct thread *t = &p->threads[p->thread_id];
6312 struct instruction *ip = t->ip;
6314 TRACE("[Thread %2u] jmpgt (mi)\n", p->thread_id);
6316 JMP_CMP_MI(t, ip, >);
6320 instr_jmp_gt_hi_exec(struct rte_swx_pipeline *p)
6322 struct thread *t = &p->threads[p->thread_id];
6323 struct instruction *ip = t->ip;
6325 TRACE("[Thread %2u] jmpgt (hi)\n", p->thread_id);
6327 JMP_CMP_HI(t, ip, >);
6334 instr_return_translate(struct rte_swx_pipeline *p __rte_unused,
6335 struct action *action,
6336 char **tokens __rte_unused,
6338 struct instruction *instr,
6339 struct instruction_data *data __rte_unused)
6341 CHECK(action, EINVAL);
6342 CHECK(n_tokens == 1, EINVAL);
6344 instr->type = INSTR_RETURN;
6349 instr_return_exec(struct rte_swx_pipeline *p)
6351 struct thread *t = &p->threads[p->thread_id];
6353 TRACE("[Thread %2u] return\n", p->thread_id);
6359 instr_translate(struct rte_swx_pipeline *p,
6360 struct action *action,
6362 struct instruction *instr,
6363 struct instruction_data *data)
6365 char *tokens[RTE_SWX_INSTRUCTION_TOKENS_MAX];
6366 int n_tokens = 0, tpos = 0;
6368 /* Parse the instruction string into tokens. */
6372 token = strtok_r(string, " \t\v", &string);
6376 CHECK(n_tokens < RTE_SWX_INSTRUCTION_TOKENS_MAX, EINVAL);
6377 CHECK_NAME(token, EINVAL);
6379 tokens[n_tokens] = token;
6383 CHECK(n_tokens, EINVAL);
6385 /* Handle the optional instruction label. */
6386 if ((n_tokens >= 2) && !strcmp(tokens[1], ":")) {
6387 strcpy(data->label, tokens[0]);
6390 CHECK(n_tokens - tpos, EINVAL);
6393 /* Identify the instruction type. */
6394 if (!strcmp(tokens[tpos], "rx"))
6395 return instr_rx_translate(p,
6402 if (!strcmp(tokens[tpos], "tx"))
6403 return instr_tx_translate(p,
6410 if (!strcmp(tokens[tpos], "drop"))
6411 return instr_drop_translate(p,
6418 if (!strcmp(tokens[tpos], "extract"))
6419 return instr_hdr_extract_translate(p,
6426 if (!strcmp(tokens[tpos], "lookahead"))
6427 return instr_hdr_lookahead_translate(p,
6434 if (!strcmp(tokens[tpos], "emit"))
6435 return instr_hdr_emit_translate(p,
6442 if (!strcmp(tokens[tpos], "validate"))
6443 return instr_hdr_validate_translate(p,
6450 if (!strcmp(tokens[tpos], "invalidate"))
6451 return instr_hdr_invalidate_translate(p,
6458 if (!strcmp(tokens[tpos], "mov"))
6459 return instr_mov_translate(p,
6466 if (!strcmp(tokens[tpos], "add"))
6467 return instr_alu_add_translate(p,
6474 if (!strcmp(tokens[tpos], "sub"))
6475 return instr_alu_sub_translate(p,
6482 if (!strcmp(tokens[tpos], "ckadd"))
6483 return instr_alu_ckadd_translate(p,
6490 if (!strcmp(tokens[tpos], "cksub"))
6491 return instr_alu_cksub_translate(p,
6498 if (!strcmp(tokens[tpos], "and"))
6499 return instr_alu_and_translate(p,
6506 if (!strcmp(tokens[tpos], "or"))
6507 return instr_alu_or_translate(p,
6514 if (!strcmp(tokens[tpos], "xor"))
6515 return instr_alu_xor_translate(p,
6522 if (!strcmp(tokens[tpos], "shl"))
6523 return instr_alu_shl_translate(p,
6530 if (!strcmp(tokens[tpos], "shr"))
6531 return instr_alu_shr_translate(p,
6538 if (!strcmp(tokens[tpos], "regprefetch"))
6539 return instr_regprefetch_translate(p,
6546 if (!strcmp(tokens[tpos], "regrd"))
6547 return instr_regrd_translate(p,
6554 if (!strcmp(tokens[tpos], "regwr"))
6555 return instr_regwr_translate(p,
6562 if (!strcmp(tokens[tpos], "regadd"))
6563 return instr_regadd_translate(p,
6570 if (!strcmp(tokens[tpos], "metprefetch"))
6571 return instr_metprefetch_translate(p,
6578 if (!strcmp(tokens[tpos], "meter"))
6579 return instr_meter_translate(p,
6586 if (!strcmp(tokens[tpos], "table"))
6587 return instr_table_translate(p,
6594 if (!strcmp(tokens[tpos], "learn"))
6595 return instr_learn_translate(p,
6602 if (!strcmp(tokens[tpos], "forget"))
6603 return instr_forget_translate(p,
6610 if (!strcmp(tokens[tpos], "extern"))
6611 return instr_extern_translate(p,
6618 if (!strcmp(tokens[tpos], "jmp"))
6619 return instr_jmp_translate(p,
6626 if (!strcmp(tokens[tpos], "jmpv"))
6627 return instr_jmp_valid_translate(p,
6634 if (!strcmp(tokens[tpos], "jmpnv"))
6635 return instr_jmp_invalid_translate(p,
6642 if (!strcmp(tokens[tpos], "jmph"))
6643 return instr_jmp_hit_translate(p,
6650 if (!strcmp(tokens[tpos], "jmpnh"))
6651 return instr_jmp_miss_translate(p,
6658 if (!strcmp(tokens[tpos], "jmpa"))
6659 return instr_jmp_action_hit_translate(p,
6666 if (!strcmp(tokens[tpos], "jmpna"))
6667 return instr_jmp_action_miss_translate(p,
6674 if (!strcmp(tokens[tpos], "jmpeq"))
6675 return instr_jmp_eq_translate(p,
6682 if (!strcmp(tokens[tpos], "jmpneq"))
6683 return instr_jmp_neq_translate(p,
6690 if (!strcmp(tokens[tpos], "jmplt"))
6691 return instr_jmp_lt_translate(p,
6698 if (!strcmp(tokens[tpos], "jmpgt"))
6699 return instr_jmp_gt_translate(p,
6706 if (!strcmp(tokens[tpos], "return"))
6707 return instr_return_translate(p,
6717 static struct instruction_data *
6718 label_find(struct instruction_data *data, uint32_t n, const char *label)
6722 for (i = 0; i < n; i++)
6723 if (!strcmp(label, data[i].label))
6730 label_is_used(struct instruction_data *data, uint32_t n, const char *label)
6732 uint32_t count = 0, i;
6737 for (i = 0; i < n; i++)
6738 if (!strcmp(label, data[i].jmp_label))
6745 instr_label_check(struct instruction_data *instruction_data,
6746 uint32_t n_instructions)
6750 /* Check that all instruction labels are unique. */
6751 for (i = 0; i < n_instructions; i++) {
6752 struct instruction_data *data = &instruction_data[i];
6753 char *label = data->label;
6759 for (j = i + 1; j < n_instructions; j++)
6760 CHECK(strcmp(label, data[j].label), EINVAL);
6763 /* Get users for each instruction label. */
6764 for (i = 0; i < n_instructions; i++) {
6765 struct instruction_data *data = &instruction_data[i];
6766 char *label = data->label;
6768 data->n_users = label_is_used(instruction_data,
6777 instr_jmp_resolve(struct instruction *instructions,
6778 struct instruction_data *instruction_data,
6779 uint32_t n_instructions)
6783 for (i = 0; i < n_instructions; i++) {
6784 struct instruction *instr = &instructions[i];
6785 struct instruction_data *data = &instruction_data[i];
6786 struct instruction_data *found;
6788 if (!instruction_is_jmp(instr))
6791 found = label_find(instruction_data,
6794 CHECK(found, EINVAL);
6796 instr->jmp.ip = &instructions[found - instruction_data];
6803 instr_verify(struct rte_swx_pipeline *p __rte_unused,
6805 struct instruction *instr,
6806 struct instruction_data *data __rte_unused,
6807 uint32_t n_instructions)
6810 enum instruction_type type;
6813 /* Check that the first instruction is rx. */
6814 CHECK(instr[0].type == INSTR_RX, EINVAL);
6816 /* Check that there is at least one tx instruction. */
6817 for (i = 0; i < n_instructions; i++) {
6818 type = instr[i].type;
6820 if (instruction_is_tx(type))
6823 CHECK(i < n_instructions, EINVAL);
6825 /* Check that the last instruction is either tx or unconditional
6828 type = instr[n_instructions - 1].type;
6829 CHECK(instruction_is_tx(type) || (type == INSTR_JMP), EINVAL);
6833 enum instruction_type type;
6836 /* Check that there is at least one return or tx instruction. */
6837 for (i = 0; i < n_instructions; i++) {
6838 type = instr[i].type;
6840 if ((type == INSTR_RETURN) || instruction_is_tx(type))
6843 CHECK(i < n_instructions, EINVAL);
6850 instr_compact(struct instruction *instructions,
6851 struct instruction_data *instruction_data,
6852 uint32_t n_instructions)
6854 uint32_t i, pos = 0;
6856 /* Eliminate the invalid instructions that have been optimized out. */
6857 for (i = 0; i < n_instructions; i++) {
6858 struct instruction *instr = &instructions[i];
6859 struct instruction_data *data = &instruction_data[i];
6865 memcpy(&instructions[pos], instr, sizeof(*instr));
6866 memcpy(&instruction_data[pos], data, sizeof(*data));
6876 instr_pattern_extract_many_search(struct instruction *instr,
6877 struct instruction_data *data,
6879 uint32_t *n_pattern_instr)
6883 for (i = 0; i < n_instr; i++) {
6884 if (data[i].invalid)
6887 if (instr[i].type != INSTR_HDR_EXTRACT)
6890 if (i == RTE_DIM(instr->io.hdr.header_id))
6893 if (i && data[i].n_users)
6900 *n_pattern_instr = i;
6905 instr_pattern_extract_many_replace(struct instruction *instr,
6906 struct instruction_data *data,
6911 for (i = 1; i < n_instr; i++) {
6913 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
6914 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
6915 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
6917 data[i].invalid = 1;
6922 instr_pattern_extract_many_optimize(struct instruction *instructions,
6923 struct instruction_data *instruction_data,
6924 uint32_t n_instructions)
6928 for (i = 0; i < n_instructions; ) {
6929 struct instruction *instr = &instructions[i];
6930 struct instruction_data *data = &instruction_data[i];
6931 uint32_t n_instr = 0;
6935 detected = instr_pattern_extract_many_search(instr,
6940 instr_pattern_extract_many_replace(instr,
6947 /* No pattern starting at the current instruction. */
6951 /* Eliminate the invalid instructions that have been optimized out. */
6952 n_instructions = instr_compact(instructions,
6956 return n_instructions;
6960 instr_pattern_emit_many_tx_search(struct instruction *instr,
6961 struct instruction_data *data,
6963 uint32_t *n_pattern_instr)
6967 for (i = 0; i < n_instr; i++) {
6968 if (data[i].invalid)
6971 if (instr[i].type != INSTR_HDR_EMIT)
6974 if (i == RTE_DIM(instr->io.hdr.header_id))
6977 if (i && data[i].n_users)
6984 if (!instruction_is_tx(instr[i].type))
6987 if (data[i].n_users)
6992 *n_pattern_instr = i;
6997 instr_pattern_emit_many_tx_replace(struct instruction *instr,
6998 struct instruction_data *data,
7003 /* Any emit instruction in addition to the first one. */
7004 for (i = 1; i < n_instr - 1; i++) {
7006 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
7007 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
7008 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
7010 data[i].invalid = 1;
7013 /* The TX instruction is the last one in the pattern. */
7015 instr[0].io.io.offset = instr[i].io.io.offset;
7016 instr[0].io.io.n_bits = instr[i].io.io.n_bits;
7017 data[i].invalid = 1;
7021 instr_pattern_emit_many_tx_optimize(struct instruction *instructions,
7022 struct instruction_data *instruction_data,
7023 uint32_t n_instructions)
7027 for (i = 0; i < n_instructions; ) {
7028 struct instruction *instr = &instructions[i];
7029 struct instruction_data *data = &instruction_data[i];
7030 uint32_t n_instr = 0;
7033 /* Emit many + TX. */
7034 detected = instr_pattern_emit_many_tx_search(instr,
7039 instr_pattern_emit_many_tx_replace(instr,
7046 /* No pattern starting at the current instruction. */
7050 /* Eliminate the invalid instructions that have been optimized out. */
7051 n_instructions = instr_compact(instructions,
7055 return n_instructions;
7059 action_arg_src_mov_count(struct action *a,
7061 struct instruction *instructions,
7062 struct instruction_data *instruction_data,
7063 uint32_t n_instructions);
7066 instr_pattern_mov_all_validate_search(struct rte_swx_pipeline *p,
7068 struct instruction *instr,
7069 struct instruction_data *data,
7071 struct instruction *instructions,
7072 struct instruction_data *instruction_data,
7073 uint32_t n_instructions,
7074 uint32_t *n_pattern_instr)
7077 uint32_t src_field_id, i, j;
7079 /* Prerequisites. */
7083 /* First instruction: MOV_HM. */
7084 if (data[0].invalid || (instr[0].type != INSTR_MOV_HM))
7087 h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
7088 if (!h || h->st->var_size)
7091 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
7092 if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
7095 if (src_field_id == a->st->n_fields)
7098 if (instr[0].mov.dst.offset ||
7099 (instr[0].mov.dst.n_bits != h->st->fields[0].n_bits) ||
7100 instr[0].mov.src.struct_id ||
7101 (instr[0].mov.src.n_bits != a->st->fields[src_field_id].n_bits) ||
7102 (instr[0].mov.dst.n_bits != instr[0].mov.src.n_bits))
7105 if ((n_instr < h->st->n_fields + 1) ||
7106 (a->st->n_fields < src_field_id + h->st->n_fields + 1))
7109 /* Subsequent instructions: MOV_HM. */
7110 for (i = 1; i < h->st->n_fields; i++)
7111 if (data[i].invalid ||
7113 (instr[i].type != INSTR_MOV_HM) ||
7114 (instr[i].mov.dst.struct_id != h->struct_id) ||
7115 (instr[i].mov.dst.offset != h->st->fields[i].offset / 8) ||
7116 (instr[i].mov.dst.n_bits != h->st->fields[i].n_bits) ||
7117 instr[i].mov.src.struct_id ||
7118 (instr[i].mov.src.offset != a->st->fields[src_field_id + i].offset / 8) ||
7119 (instr[i].mov.src.n_bits != a->st->fields[src_field_id + i].n_bits) ||
7120 (instr[i].mov.dst.n_bits != instr[i].mov.src.n_bits))
7123 /* Last instruction: HDR_VALIDATE. */
7124 if ((instr[i].type != INSTR_HDR_VALIDATE) ||
7125 (instr[i].valid.header_id != h->id))
7128 /* Check that none of the action args that are used as source for this
7129 * DMA transfer are not used as source in any other mov instruction.
7131 for (j = src_field_id; j < src_field_id + h->st->n_fields; j++) {
7134 n_users = action_arg_src_mov_count(a,
7143 *n_pattern_instr = 1 + i;
7148 instr_pattern_mov_all_validate_replace(struct rte_swx_pipeline *p,
7150 struct instruction *instr,
7151 struct instruction_data *data,
7155 uint32_t src_field_id, src_offset, i;
7157 /* Read from the instructions before they are modified. */
7158 h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
7162 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
7163 if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
7166 if (src_field_id == a->st->n_fields)
7169 src_offset = instr[0].mov.src.offset;
7171 /* Modify the instructions. */
7172 instr[0].type = INSTR_DMA_HT;
7173 instr[0].dma.dst.header_id[0] = h->id;
7174 instr[0].dma.dst.struct_id[0] = h->struct_id;
7175 instr[0].dma.src.offset[0] = (uint8_t)src_offset;
7176 instr[0].dma.n_bytes[0] = h->st->n_bits / 8;
7178 for (i = 1; i < n_instr; i++)
7179 data[i].invalid = 1;
7181 /* Update the endianness of the action arguments to header endianness. */
7182 for (i = 0; i < h->st->n_fields; i++)
7183 a->args_endianness[src_field_id + i] = 1;
7187 instr_pattern_mov_all_validate_optimize(struct rte_swx_pipeline *p,
7189 struct instruction *instructions,
7190 struct instruction_data *instruction_data,
7191 uint32_t n_instructions)
7196 return n_instructions;
7198 for (i = 0; i < n_instructions; ) {
7199 struct instruction *instr = &instructions[i];
7200 struct instruction_data *data = &instruction_data[i];
7201 uint32_t n_instr = 0;
7204 /* Mov all + validate. */
7205 detected = instr_pattern_mov_all_validate_search(p,
7215 instr_pattern_mov_all_validate_replace(p, a, instr, data, n_instr);
7220 /* No pattern starting at the current instruction. */
7224 /* Eliminate the invalid instructions that have been optimized out. */
7225 n_instructions = instr_compact(instructions,
7229 return n_instructions;
7233 instr_pattern_dma_many_search(struct instruction *instr,
7234 struct instruction_data *data,
7236 uint32_t *n_pattern_instr)
7240 for (i = 0; i < n_instr; i++) {
7241 if (data[i].invalid)
7244 if (instr[i].type != INSTR_DMA_HT)
7247 if (i == RTE_DIM(instr->dma.dst.header_id))
7250 if (i && data[i].n_users)
7257 *n_pattern_instr = i;
7262 instr_pattern_dma_many_replace(struct instruction *instr,
7263 struct instruction_data *data,
7268 for (i = 1; i < n_instr; i++) {
7270 instr[0].dma.dst.header_id[i] = instr[i].dma.dst.header_id[0];
7271 instr[0].dma.dst.struct_id[i] = instr[i].dma.dst.struct_id[0];
7272 instr[0].dma.src.offset[i] = instr[i].dma.src.offset[0];
7273 instr[0].dma.n_bytes[i] = instr[i].dma.n_bytes[0];
7275 data[i].invalid = 1;
7280 instr_pattern_dma_many_optimize(struct instruction *instructions,
7281 struct instruction_data *instruction_data,
7282 uint32_t n_instructions)
7286 for (i = 0; i < n_instructions; ) {
7287 struct instruction *instr = &instructions[i];
7288 struct instruction_data *data = &instruction_data[i];
7289 uint32_t n_instr = 0;
7293 detected = instr_pattern_dma_many_search(instr,
7298 instr_pattern_dma_many_replace(instr, data, n_instr);
7303 /* No pattern starting at the current instruction. */
7307 /* Eliminate the invalid instructions that have been optimized out. */
7308 n_instructions = instr_compact(instructions,
7312 return n_instructions;
7316 instr_optimize(struct rte_swx_pipeline *p,
7318 struct instruction *instructions,
7319 struct instruction_data *instruction_data,
7320 uint32_t n_instructions)
7323 n_instructions = instr_pattern_extract_many_optimize(instructions,
7327 /* Emit many + TX. */
7328 n_instructions = instr_pattern_emit_many_tx_optimize(instructions,
7332 /* Mov all + validate. */
7333 n_instructions = instr_pattern_mov_all_validate_optimize(p,
7340 n_instructions = instr_pattern_dma_many_optimize(instructions,
7344 return n_instructions;
7348 instruction_config(struct rte_swx_pipeline *p,
7350 const char **instructions,
7351 uint32_t n_instructions)
7353 struct instruction *instr = NULL;
7354 struct instruction_data *data = NULL;
7358 CHECK(n_instructions, EINVAL);
7359 CHECK(instructions, EINVAL);
7360 for (i = 0; i < n_instructions; i++)
7361 CHECK_INSTRUCTION(instructions[i], EINVAL);
7363 /* Memory allocation. */
7364 instr = calloc(n_instructions, sizeof(struct instruction));
7370 data = calloc(n_instructions, sizeof(struct instruction_data));
7376 for (i = 0; i < n_instructions; i++) {
7377 char *string = strdup(instructions[i]);
7383 err = instr_translate(p, a, string, &instr[i], &data[i]);
7392 err = instr_label_check(data, n_instructions);
7396 err = instr_verify(p, a, instr, data, n_instructions);
7400 n_instructions = instr_optimize(p, a, instr, data, n_instructions);
7402 err = instr_jmp_resolve(instr, data, n_instructions);
7407 a->instructions = instr;
7408 a->n_instructions = n_instructions;
7410 p->instructions = instr;
7411 p->n_instructions = n_instructions;
7423 typedef void (*instr_exec_t)(struct rte_swx_pipeline *);
7425 static instr_exec_t instruction_table[] = {
7426 [INSTR_RX] = instr_rx_exec,
7427 [INSTR_TX] = instr_tx_exec,
7428 [INSTR_TX_I] = instr_tx_i_exec,
7430 [INSTR_HDR_EXTRACT] = instr_hdr_extract_exec,
7431 [INSTR_HDR_EXTRACT2] = instr_hdr_extract2_exec,
7432 [INSTR_HDR_EXTRACT3] = instr_hdr_extract3_exec,
7433 [INSTR_HDR_EXTRACT4] = instr_hdr_extract4_exec,
7434 [INSTR_HDR_EXTRACT5] = instr_hdr_extract5_exec,
7435 [INSTR_HDR_EXTRACT6] = instr_hdr_extract6_exec,
7436 [INSTR_HDR_EXTRACT7] = instr_hdr_extract7_exec,
7437 [INSTR_HDR_EXTRACT8] = instr_hdr_extract8_exec,
7438 [INSTR_HDR_EXTRACT_M] = instr_hdr_extract_m_exec,
7439 [INSTR_HDR_LOOKAHEAD] = instr_hdr_lookahead_exec,
7441 [INSTR_HDR_EMIT] = instr_hdr_emit_exec,
7442 [INSTR_HDR_EMIT_TX] = instr_hdr_emit_tx_exec,
7443 [INSTR_HDR_EMIT2_TX] = instr_hdr_emit2_tx_exec,
7444 [INSTR_HDR_EMIT3_TX] = instr_hdr_emit3_tx_exec,
7445 [INSTR_HDR_EMIT4_TX] = instr_hdr_emit4_tx_exec,
7446 [INSTR_HDR_EMIT5_TX] = instr_hdr_emit5_tx_exec,
7447 [INSTR_HDR_EMIT6_TX] = instr_hdr_emit6_tx_exec,
7448 [INSTR_HDR_EMIT7_TX] = instr_hdr_emit7_tx_exec,
7449 [INSTR_HDR_EMIT8_TX] = instr_hdr_emit8_tx_exec,
7451 [INSTR_HDR_VALIDATE] = instr_hdr_validate_exec,
7452 [INSTR_HDR_INVALIDATE] = instr_hdr_invalidate_exec,
7454 [INSTR_MOV] = instr_mov_exec,
7455 [INSTR_MOV_MH] = instr_mov_mh_exec,
7456 [INSTR_MOV_HM] = instr_mov_hm_exec,
7457 [INSTR_MOV_HH] = instr_mov_hh_exec,
7458 [INSTR_MOV_I] = instr_mov_i_exec,
7460 [INSTR_DMA_HT] = instr_dma_ht_exec,
7461 [INSTR_DMA_HT2] = instr_dma_ht2_exec,
7462 [INSTR_DMA_HT3] = instr_dma_ht3_exec,
7463 [INSTR_DMA_HT4] = instr_dma_ht4_exec,
7464 [INSTR_DMA_HT5] = instr_dma_ht5_exec,
7465 [INSTR_DMA_HT6] = instr_dma_ht6_exec,
7466 [INSTR_DMA_HT7] = instr_dma_ht7_exec,
7467 [INSTR_DMA_HT8] = instr_dma_ht8_exec,
7469 [INSTR_ALU_ADD] = instr_alu_add_exec,
7470 [INSTR_ALU_ADD_MH] = instr_alu_add_mh_exec,
7471 [INSTR_ALU_ADD_HM] = instr_alu_add_hm_exec,
7472 [INSTR_ALU_ADD_HH] = instr_alu_add_hh_exec,
7473 [INSTR_ALU_ADD_MI] = instr_alu_add_mi_exec,
7474 [INSTR_ALU_ADD_HI] = instr_alu_add_hi_exec,
7476 [INSTR_ALU_SUB] = instr_alu_sub_exec,
7477 [INSTR_ALU_SUB_MH] = instr_alu_sub_mh_exec,
7478 [INSTR_ALU_SUB_HM] = instr_alu_sub_hm_exec,
7479 [INSTR_ALU_SUB_HH] = instr_alu_sub_hh_exec,
7480 [INSTR_ALU_SUB_MI] = instr_alu_sub_mi_exec,
7481 [INSTR_ALU_SUB_HI] = instr_alu_sub_hi_exec,
7483 [INSTR_ALU_CKADD_FIELD] = instr_alu_ckadd_field_exec,
7484 [INSTR_ALU_CKADD_STRUCT] = instr_alu_ckadd_struct_exec,
7485 [INSTR_ALU_CKADD_STRUCT20] = instr_alu_ckadd_struct20_exec,
7486 [INSTR_ALU_CKSUB_FIELD] = instr_alu_cksub_field_exec,
7488 [INSTR_ALU_AND] = instr_alu_and_exec,
7489 [INSTR_ALU_AND_MH] = instr_alu_and_mh_exec,
7490 [INSTR_ALU_AND_HM] = instr_alu_and_hm_exec,
7491 [INSTR_ALU_AND_HH] = instr_alu_and_hh_exec,
7492 [INSTR_ALU_AND_I] = instr_alu_and_i_exec,
7494 [INSTR_ALU_OR] = instr_alu_or_exec,
7495 [INSTR_ALU_OR_MH] = instr_alu_or_mh_exec,
7496 [INSTR_ALU_OR_HM] = instr_alu_or_hm_exec,
7497 [INSTR_ALU_OR_HH] = instr_alu_or_hh_exec,
7498 [INSTR_ALU_OR_I] = instr_alu_or_i_exec,
7500 [INSTR_ALU_XOR] = instr_alu_xor_exec,
7501 [INSTR_ALU_XOR_MH] = instr_alu_xor_mh_exec,
7502 [INSTR_ALU_XOR_HM] = instr_alu_xor_hm_exec,
7503 [INSTR_ALU_XOR_HH] = instr_alu_xor_hh_exec,
7504 [INSTR_ALU_XOR_I] = instr_alu_xor_i_exec,
7506 [INSTR_ALU_SHL] = instr_alu_shl_exec,
7507 [INSTR_ALU_SHL_MH] = instr_alu_shl_mh_exec,
7508 [INSTR_ALU_SHL_HM] = instr_alu_shl_hm_exec,
7509 [INSTR_ALU_SHL_HH] = instr_alu_shl_hh_exec,
7510 [INSTR_ALU_SHL_MI] = instr_alu_shl_mi_exec,
7511 [INSTR_ALU_SHL_HI] = instr_alu_shl_hi_exec,
7513 [INSTR_ALU_SHR] = instr_alu_shr_exec,
7514 [INSTR_ALU_SHR_MH] = instr_alu_shr_mh_exec,
7515 [INSTR_ALU_SHR_HM] = instr_alu_shr_hm_exec,
7516 [INSTR_ALU_SHR_HH] = instr_alu_shr_hh_exec,
7517 [INSTR_ALU_SHR_MI] = instr_alu_shr_mi_exec,
7518 [INSTR_ALU_SHR_HI] = instr_alu_shr_hi_exec,
7520 [INSTR_REGPREFETCH_RH] = instr_regprefetch_rh_exec,
7521 [INSTR_REGPREFETCH_RM] = instr_regprefetch_rm_exec,
7522 [INSTR_REGPREFETCH_RI] = instr_regprefetch_ri_exec,
7524 [INSTR_REGRD_HRH] = instr_regrd_hrh_exec,
7525 [INSTR_REGRD_HRM] = instr_regrd_hrm_exec,
7526 [INSTR_REGRD_MRH] = instr_regrd_mrh_exec,
7527 [INSTR_REGRD_MRM] = instr_regrd_mrm_exec,
7528 [INSTR_REGRD_HRI] = instr_regrd_hri_exec,
7529 [INSTR_REGRD_MRI] = instr_regrd_mri_exec,
7531 [INSTR_REGWR_RHH] = instr_regwr_rhh_exec,
7532 [INSTR_REGWR_RHM] = instr_regwr_rhm_exec,
7533 [INSTR_REGWR_RMH] = instr_regwr_rmh_exec,
7534 [INSTR_REGWR_RMM] = instr_regwr_rmm_exec,
7535 [INSTR_REGWR_RHI] = instr_regwr_rhi_exec,
7536 [INSTR_REGWR_RMI] = instr_regwr_rmi_exec,
7537 [INSTR_REGWR_RIH] = instr_regwr_rih_exec,
7538 [INSTR_REGWR_RIM] = instr_regwr_rim_exec,
7539 [INSTR_REGWR_RII] = instr_regwr_rii_exec,
7541 [INSTR_REGADD_RHH] = instr_regadd_rhh_exec,
7542 [INSTR_REGADD_RHM] = instr_regadd_rhm_exec,
7543 [INSTR_REGADD_RMH] = instr_regadd_rmh_exec,
7544 [INSTR_REGADD_RMM] = instr_regadd_rmm_exec,
7545 [INSTR_REGADD_RHI] = instr_regadd_rhi_exec,
7546 [INSTR_REGADD_RMI] = instr_regadd_rmi_exec,
7547 [INSTR_REGADD_RIH] = instr_regadd_rih_exec,
7548 [INSTR_REGADD_RIM] = instr_regadd_rim_exec,
7549 [INSTR_REGADD_RII] = instr_regadd_rii_exec,
7551 [INSTR_METPREFETCH_H] = instr_metprefetch_h_exec,
7552 [INSTR_METPREFETCH_M] = instr_metprefetch_m_exec,
7553 [INSTR_METPREFETCH_I] = instr_metprefetch_i_exec,
7555 [INSTR_METER_HHM] = instr_meter_hhm_exec,
7556 [INSTR_METER_HHI] = instr_meter_hhi_exec,
7557 [INSTR_METER_HMM] = instr_meter_hmm_exec,
7558 [INSTR_METER_HMI] = instr_meter_hmi_exec,
7559 [INSTR_METER_MHM] = instr_meter_mhm_exec,
7560 [INSTR_METER_MHI] = instr_meter_mhi_exec,
7561 [INSTR_METER_MMM] = instr_meter_mmm_exec,
7562 [INSTR_METER_MMI] = instr_meter_mmi_exec,
7563 [INSTR_METER_IHM] = instr_meter_ihm_exec,
7564 [INSTR_METER_IHI] = instr_meter_ihi_exec,
7565 [INSTR_METER_IMM] = instr_meter_imm_exec,
7566 [INSTR_METER_IMI] = instr_meter_imi_exec,
7568 [INSTR_TABLE] = instr_table_exec,
7569 [INSTR_SELECTOR] = instr_selector_exec,
7570 [INSTR_LEARNER] = instr_learner_exec,
7571 [INSTR_LEARNER_LEARN] = instr_learn_exec,
7572 [INSTR_LEARNER_FORGET] = instr_forget_exec,
7573 [INSTR_EXTERN_OBJ] = instr_extern_obj_exec,
7574 [INSTR_EXTERN_FUNC] = instr_extern_func_exec,
7576 [INSTR_JMP] = instr_jmp_exec,
7577 [INSTR_JMP_VALID] = instr_jmp_valid_exec,
7578 [INSTR_JMP_INVALID] = instr_jmp_invalid_exec,
7579 [INSTR_JMP_HIT] = instr_jmp_hit_exec,
7580 [INSTR_JMP_MISS] = instr_jmp_miss_exec,
7581 [INSTR_JMP_ACTION_HIT] = instr_jmp_action_hit_exec,
7582 [INSTR_JMP_ACTION_MISS] = instr_jmp_action_miss_exec,
7584 [INSTR_JMP_EQ] = instr_jmp_eq_exec,
7585 [INSTR_JMP_EQ_MH] = instr_jmp_eq_mh_exec,
7586 [INSTR_JMP_EQ_HM] = instr_jmp_eq_hm_exec,
7587 [INSTR_JMP_EQ_HH] = instr_jmp_eq_hh_exec,
7588 [INSTR_JMP_EQ_I] = instr_jmp_eq_i_exec,
7590 [INSTR_JMP_NEQ] = instr_jmp_neq_exec,
7591 [INSTR_JMP_NEQ_MH] = instr_jmp_neq_mh_exec,
7592 [INSTR_JMP_NEQ_HM] = instr_jmp_neq_hm_exec,
7593 [INSTR_JMP_NEQ_HH] = instr_jmp_neq_hh_exec,
7594 [INSTR_JMP_NEQ_I] = instr_jmp_neq_i_exec,
7596 [INSTR_JMP_LT] = instr_jmp_lt_exec,
7597 [INSTR_JMP_LT_MH] = instr_jmp_lt_mh_exec,
7598 [INSTR_JMP_LT_HM] = instr_jmp_lt_hm_exec,
7599 [INSTR_JMP_LT_HH] = instr_jmp_lt_hh_exec,
7600 [INSTR_JMP_LT_MI] = instr_jmp_lt_mi_exec,
7601 [INSTR_JMP_LT_HI] = instr_jmp_lt_hi_exec,
7603 [INSTR_JMP_GT] = instr_jmp_gt_exec,
7604 [INSTR_JMP_GT_MH] = instr_jmp_gt_mh_exec,
7605 [INSTR_JMP_GT_HM] = instr_jmp_gt_hm_exec,
7606 [INSTR_JMP_GT_HH] = instr_jmp_gt_hh_exec,
7607 [INSTR_JMP_GT_MI] = instr_jmp_gt_mi_exec,
7608 [INSTR_JMP_GT_HI] = instr_jmp_gt_hi_exec,
7610 [INSTR_RETURN] = instr_return_exec,
7614 instr_exec(struct rte_swx_pipeline *p)
7616 struct thread *t = &p->threads[p->thread_id];
7617 struct instruction *ip = t->ip;
7618 instr_exec_t instr = instruction_table[ip->type];
7626 static struct action *
7627 action_find(struct rte_swx_pipeline *p, const char *name)
7629 struct action *elem;
7634 TAILQ_FOREACH(elem, &p->actions, node)
7635 if (strcmp(elem->name, name) == 0)
7641 static struct action *
7642 action_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7644 struct action *action = NULL;
7646 TAILQ_FOREACH(action, &p->actions, node)
7647 if (action->id == id)
7653 static struct field *
7654 action_field_find(struct action *a, const char *name)
7656 return a->st ? struct_type_field_find(a->st, name) : NULL;
7659 static struct field *
7660 action_field_parse(struct action *action, const char *name)
7662 if (name[0] != 't' || name[1] != '.')
7665 return action_field_find(action, &name[2]);
7669 action_has_nbo_args(struct action *a)
7673 /* Return if the action does not have any args. */
7675 return 0; /* FALSE */
7677 for (i = 0; i < a->st->n_fields; i++)
7678 if (a->args_endianness[i])
7679 return 1; /* TRUE */
7681 return 0; /* FALSE */
7685 action_does_learning(struct action *a)
7689 for (i = 0; i < a->n_instructions; i++)
7690 switch (a->instructions[i].type) {
7691 case INSTR_LEARNER_LEARN:
7692 return 1; /* TRUE */
7694 case INSTR_LEARNER_FORGET:
7695 return 1; /* TRUE */
7701 return 0; /* FALSE */
7705 rte_swx_pipeline_action_config(struct rte_swx_pipeline *p,
7707 const char *args_struct_type_name,
7708 const char **instructions,
7709 uint32_t n_instructions)
7711 struct struct_type *args_struct_type = NULL;
7717 CHECK_NAME(name, EINVAL);
7718 CHECK(!action_find(p, name), EEXIST);
7720 if (args_struct_type_name) {
7721 CHECK_NAME(args_struct_type_name, EINVAL);
7722 args_struct_type = struct_type_find(p, args_struct_type_name);
7723 CHECK(args_struct_type, EINVAL);
7724 CHECK(!args_struct_type->var_size, EINVAL);
7727 /* Node allocation. */
7728 a = calloc(1, sizeof(struct action));
7730 if (args_struct_type) {
7731 a->args_endianness = calloc(args_struct_type->n_fields, sizeof(int));
7732 if (!a->args_endianness) {
7738 /* Node initialization. */
7739 strcpy(a->name, name);
7740 a->st = args_struct_type;
7741 a->id = p->n_actions;
7743 /* Instruction translation. */
7744 err = instruction_config(p, a, instructions, n_instructions);
7746 free(a->args_endianness);
7751 /* Node add to tailq. */
7752 TAILQ_INSERT_TAIL(&p->actions, a, node);
7759 action_build(struct rte_swx_pipeline *p)
7761 struct action *action;
7763 p->action_instructions = calloc(p->n_actions,
7764 sizeof(struct instruction *));
7765 CHECK(p->action_instructions, ENOMEM);
7767 TAILQ_FOREACH(action, &p->actions, node)
7768 p->action_instructions[action->id] = action->instructions;
7774 action_build_free(struct rte_swx_pipeline *p)
7776 free(p->action_instructions);
7777 p->action_instructions = NULL;
7781 action_free(struct rte_swx_pipeline *p)
7783 action_build_free(p);
7786 struct action *action;
7788 action = TAILQ_FIRST(&p->actions);
7792 TAILQ_REMOVE(&p->actions, action, node);
7793 free(action->instructions);
7799 action_arg_src_mov_count(struct action *a,
7801 struct instruction *instructions,
7802 struct instruction_data *instruction_data,
7803 uint32_t n_instructions)
7805 uint32_t offset, n_users = 0, i;
7808 (arg_id >= a->st->n_fields) ||
7810 !instruction_data ||
7814 offset = a->st->fields[arg_id].offset / 8;
7816 for (i = 0; i < n_instructions; i++) {
7817 struct instruction *instr = &instructions[i];
7818 struct instruction_data *data = &instruction_data[i];
7820 if (data->invalid ||
7821 ((instr->type != INSTR_MOV) && (instr->type != INSTR_MOV_HM)) ||
7822 instr->mov.src.struct_id ||
7823 (instr->mov.src.offset != offset))
7835 static struct table_type *
7836 table_type_find(struct rte_swx_pipeline *p, const char *name)
7838 struct table_type *elem;
7840 TAILQ_FOREACH(elem, &p->table_types, node)
7841 if (strcmp(elem->name, name) == 0)
7847 static struct table_type *
7848 table_type_resolve(struct rte_swx_pipeline *p,
7849 const char *recommended_type_name,
7850 enum rte_swx_table_match_type match_type)
7852 struct table_type *elem;
7854 /* Only consider the recommended type if the match type is correct. */
7855 if (recommended_type_name)
7856 TAILQ_FOREACH(elem, &p->table_types, node)
7857 if (!strcmp(elem->name, recommended_type_name) &&
7858 (elem->match_type == match_type))
7861 /* Ignore the recommended type and get the first element with this match
7864 TAILQ_FOREACH(elem, &p->table_types, node)
7865 if (elem->match_type == match_type)
7871 static struct table *
7872 table_find(struct rte_swx_pipeline *p, const char *name)
7876 TAILQ_FOREACH(elem, &p->tables, node)
7877 if (strcmp(elem->name, name) == 0)
7883 static struct table *
7884 table_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7886 struct table *table = NULL;
7888 TAILQ_FOREACH(table, &p->tables, node)
7889 if (table->id == id)
7896 rte_swx_pipeline_table_type_register(struct rte_swx_pipeline *p,
7898 enum rte_swx_table_match_type match_type,
7899 struct rte_swx_table_ops *ops)
7901 struct table_type *elem;
7905 CHECK_NAME(name, EINVAL);
7906 CHECK(!table_type_find(p, name), EEXIST);
7909 CHECK(ops->create, EINVAL);
7910 CHECK(ops->lkp, EINVAL);
7911 CHECK(ops->free, EINVAL);
7913 /* Node allocation. */
7914 elem = calloc(1, sizeof(struct table_type));
7915 CHECK(elem, ENOMEM);
7917 /* Node initialization. */
7918 strcpy(elem->name, name);
7919 elem->match_type = match_type;
7920 memcpy(&elem->ops, ops, sizeof(*ops));
7922 /* Node add to tailq. */
7923 TAILQ_INSERT_TAIL(&p->table_types, elem, node);
7929 table_match_type_resolve(struct rte_swx_match_field_params *fields,
7931 enum rte_swx_table_match_type *match_type)
7933 uint32_t n_fields_em = 0, n_fields_lpm = 0, i;
7935 for (i = 0; i < n_fields; i++) {
7936 struct rte_swx_match_field_params *f = &fields[i];
7938 if (f->match_type == RTE_SWX_TABLE_MATCH_EXACT)
7941 if (f->match_type == RTE_SWX_TABLE_MATCH_LPM)
7945 if ((n_fields_lpm > 1) ||
7946 (n_fields_lpm && (n_fields_em != n_fields - 1)))
7949 *match_type = (n_fields_em == n_fields) ?
7950 RTE_SWX_TABLE_MATCH_EXACT :
7951 RTE_SWX_TABLE_MATCH_WILDCARD;
7957 table_match_fields_check(struct rte_swx_pipeline *p,
7958 struct rte_swx_pipeline_table_params *params,
7959 struct header **header)
7961 struct header *h0 = NULL;
7962 struct field *hf, *mf;
7963 uint32_t *offset = NULL, i;
7966 /* Return if no match fields. */
7967 if (!params->n_fields) {
7968 if (params->fields) {
7979 /* Memory allocation. */
7980 offset = calloc(params->n_fields, sizeof(uint32_t));
7986 /* Check that all the match fields belong to either the same header or
7989 hf = header_field_parse(p, params->fields[0].name, &h0);
7990 mf = metadata_field_parse(p, params->fields[0].name);
7991 if ((!hf && !mf) || (hf && hf->var_size)) {
7996 offset[0] = h0 ? hf->offset : mf->offset;
7998 for (i = 1; i < params->n_fields; i++)
8002 hf = header_field_parse(p, params->fields[i].name, &h);
8003 if (!hf || (h->id != h0->id) || hf->var_size) {
8008 offset[i] = hf->offset;
8010 mf = metadata_field_parse(p, params->fields[i].name);
8016 offset[i] = mf->offset;
8019 /* Check that there are no duplicated match fields. */
8020 for (i = 0; i < params->n_fields; i++) {
8023 for (j = 0; j < i; j++)
8024 if (offset[j] == offset[i]) {
8040 rte_swx_pipeline_table_config(struct rte_swx_pipeline *p,
8042 struct rte_swx_pipeline_table_params *params,
8043 const char *recommended_table_type_name,
8047 struct table_type *type;
8049 struct action *default_action;
8050 struct header *header = NULL;
8051 uint32_t action_data_size_max = 0, i;
8056 CHECK_NAME(name, EINVAL);
8057 CHECK(!table_find(p, name), EEXIST);
8058 CHECK(!selector_find(p, name), EEXIST);
8059 CHECK(!learner_find(p, name), EEXIST);
8061 CHECK(params, EINVAL);
8064 status = table_match_fields_check(p, params, &header);
8068 /* Action checks. */
8069 CHECK(params->n_actions, EINVAL);
8070 CHECK(params->action_names, EINVAL);
8071 for (i = 0; i < params->n_actions; i++) {
8072 const char *action_name = params->action_names[i];
8074 uint32_t action_data_size;
8076 CHECK_NAME(action_name, EINVAL);
8078 a = action_find(p, action_name);
8080 CHECK(!action_does_learning(a), EINVAL);
8082 action_data_size = a->st ? a->st->n_bits / 8 : 0;
8083 if (action_data_size > action_data_size_max)
8084 action_data_size_max = action_data_size;
8087 CHECK_NAME(params->default_action_name, EINVAL);
8088 for (i = 0; i < p->n_actions; i++)
8089 if (!strcmp(params->action_names[i],
8090 params->default_action_name))
8092 CHECK(i < params->n_actions, EINVAL);
8093 default_action = action_find(p, params->default_action_name);
8094 CHECK((default_action->st && params->default_action_data) ||
8095 !params->default_action_data, EINVAL);
8097 /* Table type checks. */
8098 if (recommended_table_type_name)
8099 CHECK_NAME(recommended_table_type_name, EINVAL);
8101 if (params->n_fields) {
8102 enum rte_swx_table_match_type match_type;
8104 status = table_match_type_resolve(params->fields, params->n_fields, &match_type);
8108 type = table_type_resolve(p, recommended_table_type_name, match_type);
8109 CHECK(type, EINVAL);
8114 /* Memory allocation. */
8115 t = calloc(1, sizeof(struct table));
8118 t->fields = calloc(params->n_fields, sizeof(struct match_field));
8124 t->actions = calloc(params->n_actions, sizeof(struct action *));
8131 if (action_data_size_max) {
8132 t->default_action_data = calloc(1, action_data_size_max);
8133 if (!t->default_action_data) {
8141 /* Node initialization. */
8142 strcpy(t->name, name);
8143 if (args && args[0])
8144 strcpy(t->args, args);
8147 for (i = 0; i < params->n_fields; i++) {
8148 struct rte_swx_match_field_params *field = ¶ms->fields[i];
8149 struct match_field *f = &t->fields[i];
8151 f->match_type = field->match_type;
8153 header_field_parse(p, field->name, NULL) :
8154 metadata_field_parse(p, field->name);
8156 t->n_fields = params->n_fields;
8159 for (i = 0; i < params->n_actions; i++)
8160 t->actions[i] = action_find(p, params->action_names[i]);
8161 t->default_action = default_action;
8162 if (default_action->st)
8163 memcpy(t->default_action_data,
8164 params->default_action_data,
8165 default_action->st->n_bits / 8);
8166 t->n_actions = params->n_actions;
8167 t->default_action_is_const = params->default_action_is_const;
8168 t->action_data_size_max = action_data_size_max;
8171 t->id = p->n_tables;
8173 /* Node add to tailq. */
8174 TAILQ_INSERT_TAIL(&p->tables, t, node);
8180 static struct rte_swx_table_params *
8181 table_params_get(struct table *table)
8183 struct rte_swx_table_params *params;
8184 struct field *first, *last;
8186 uint32_t key_size, key_offset, action_data_size, i;
8188 /* Memory allocation. */
8189 params = calloc(1, sizeof(struct rte_swx_table_params));
8193 /* Find first (smallest offset) and last (biggest offset) match fields. */
8194 first = table->fields[0].field;
8195 last = table->fields[0].field;
8197 for (i = 0; i < table->n_fields; i++) {
8198 struct field *f = table->fields[i].field;
8200 if (f->offset < first->offset)
8203 if (f->offset > last->offset)
8207 /* Key offset and size. */
8208 key_offset = first->offset / 8;
8209 key_size = (last->offset + last->n_bits - first->offset) / 8;
8211 /* Memory allocation. */
8212 key_mask = calloc(1, key_size);
8219 for (i = 0; i < table->n_fields; i++) {
8220 struct field *f = table->fields[i].field;
8221 uint32_t start = (f->offset - first->offset) / 8;
8222 size_t size = f->n_bits / 8;
8224 memset(&key_mask[start], 0xFF, size);
8227 /* Action data size. */
8228 action_data_size = 0;
8229 for (i = 0; i < table->n_actions; i++) {
8230 struct action *action = table->actions[i];
8231 uint32_t ads = action->st ? action->st->n_bits / 8 : 0;
8233 if (ads > action_data_size)
8234 action_data_size = ads;
8238 params->match_type = table->type->match_type;
8239 params->key_size = key_size;
8240 params->key_offset = key_offset;
8241 params->key_mask0 = key_mask;
8242 params->action_data_size = action_data_size;
8243 params->n_keys_max = table->size;
8249 table_params_free(struct rte_swx_table_params *params)
8254 free(params->key_mask0);
8259 table_stub_lkp(void *table __rte_unused,
8260 void *mailbox __rte_unused,
8261 uint8_t **key __rte_unused,
8262 uint64_t *action_id __rte_unused,
8263 uint8_t **action_data __rte_unused,
8267 return 1; /* DONE. */
8271 table_build(struct rte_swx_pipeline *p)
8275 /* Per pipeline: table statistics. */
8276 p->table_stats = calloc(p->n_tables, sizeof(struct table_statistics));
8277 CHECK(p->table_stats, ENOMEM);
8279 for (i = 0; i < p->n_tables; i++) {
8280 p->table_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
8281 CHECK(p->table_stats[i].n_pkts_action, ENOMEM);
8284 /* Per thread: table runt-time. */
8285 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8286 struct thread *t = &p->threads[i];
8287 struct table *table;
8289 t->tables = calloc(p->n_tables, sizeof(struct table_runtime));
8290 CHECK(t->tables, ENOMEM);
8292 TAILQ_FOREACH(table, &p->tables, node) {
8293 struct table_runtime *r = &t->tables[table->id];
8298 size = table->type->ops.mailbox_size_get();
8301 r->func = table->type->ops.lkp;
8305 r->mailbox = calloc(1, size);
8306 CHECK(r->mailbox, ENOMEM);
8310 r->key = table->header ?
8311 &t->structs[table->header->struct_id] :
8312 &t->structs[p->metadata_struct_id];
8314 r->func = table_stub_lkp;
8323 table_build_free(struct rte_swx_pipeline *p)
8327 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8328 struct thread *t = &p->threads[i];
8334 for (j = 0; j < p->n_tables; j++) {
8335 struct table_runtime *r = &t->tables[j];
8344 if (p->table_stats) {
8345 for (i = 0; i < p->n_tables; i++)
8346 free(p->table_stats[i].n_pkts_action);
8348 free(p->table_stats);
8353 table_free(struct rte_swx_pipeline *p)
8355 table_build_free(p);
8361 elem = TAILQ_FIRST(&p->tables);
8365 TAILQ_REMOVE(&p->tables, elem, node);
8367 free(elem->actions);
8368 free(elem->default_action_data);
8374 struct table_type *elem;
8376 elem = TAILQ_FIRST(&p->table_types);
8380 TAILQ_REMOVE(&p->table_types, elem, node);
8388 static struct selector *
8389 selector_find(struct rte_swx_pipeline *p, const char *name)
8393 TAILQ_FOREACH(s, &p->selectors, node)
8394 if (strcmp(s->name, name) == 0)
8400 static struct selector *
8401 selector_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8403 struct selector *s = NULL;
8405 TAILQ_FOREACH(s, &p->selectors, node)
8413 selector_fields_check(struct rte_swx_pipeline *p,
8414 struct rte_swx_pipeline_selector_params *params,
8415 struct header **header)
8417 struct header *h0 = NULL;
8418 struct field *hf, *mf;
8421 /* Return if no selector fields. */
8422 if (!params->n_selector_fields || !params->selector_field_names)
8425 /* Check that all the selector fields either belong to the same header
8426 * or are all meta-data fields.
8428 hf = header_field_parse(p, params->selector_field_names[0], &h0);
8429 mf = metadata_field_parse(p, params->selector_field_names[0]);
8433 for (i = 1; i < params->n_selector_fields; i++)
8437 hf = header_field_parse(p, params->selector_field_names[i], &h);
8438 if (!hf || (h->id != h0->id))
8441 mf = metadata_field_parse(p, params->selector_field_names[i]);
8446 /* Check that there are no duplicated match fields. */
8447 for (i = 0; i < params->n_selector_fields; i++) {
8448 const char *field_name = params->selector_field_names[i];
8451 for (j = i + 1; j < params->n_selector_fields; j++)
8452 if (!strcmp(params->selector_field_names[j], field_name))
8464 rte_swx_pipeline_selector_config(struct rte_swx_pipeline *p,
8466 struct rte_swx_pipeline_selector_params *params)
8469 struct header *selector_header = NULL;
8470 struct field *group_id_field, *member_id_field;
8476 CHECK_NAME(name, EINVAL);
8477 CHECK(!table_find(p, name), EEXIST);
8478 CHECK(!selector_find(p, name), EEXIST);
8479 CHECK(!learner_find(p, name), EEXIST);
8481 CHECK(params, EINVAL);
8483 CHECK_NAME(params->group_id_field_name, EINVAL);
8484 group_id_field = metadata_field_parse(p, params->group_id_field_name);
8485 CHECK(group_id_field, EINVAL);
8487 for (i = 0; i < params->n_selector_fields; i++) {
8488 const char *field_name = params->selector_field_names[i];
8490 CHECK_NAME(field_name, EINVAL);
8492 status = selector_fields_check(p, params, &selector_header);
8496 CHECK_NAME(params->member_id_field_name, EINVAL);
8497 member_id_field = metadata_field_parse(p, params->member_id_field_name);
8498 CHECK(member_id_field, EINVAL);
8500 CHECK(params->n_groups_max, EINVAL);
8502 CHECK(params->n_members_per_group_max, EINVAL);
8504 /* Memory allocation. */
8505 s = calloc(1, sizeof(struct selector));
8511 s->selector_fields = calloc(params->n_selector_fields, sizeof(struct field *));
8512 if (!s->selector_fields) {
8517 /* Node initialization. */
8518 strcpy(s->name, name);
8520 s->group_id_field = group_id_field;
8522 for (i = 0; i < params->n_selector_fields; i++) {
8523 const char *field_name = params->selector_field_names[i];
8525 s->selector_fields[i] = selector_header ?
8526 header_field_parse(p, field_name, NULL) :
8527 metadata_field_parse(p, field_name);
8530 s->n_selector_fields = params->n_selector_fields;
8532 s->selector_header = selector_header;
8534 s->member_id_field = member_id_field;
8536 s->n_groups_max = params->n_groups_max;
8538 s->n_members_per_group_max = params->n_members_per_group_max;
8540 s->id = p->n_selectors;
8542 /* Node add to tailq. */
8543 TAILQ_INSERT_TAIL(&p->selectors, s, node);
8552 free(s->selector_fields);
8560 selector_params_free(struct rte_swx_table_selector_params *params)
8565 free(params->selector_mask);
8570 static struct rte_swx_table_selector_params *
8571 selector_table_params_get(struct selector *s)
8573 struct rte_swx_table_selector_params *params = NULL;
8574 struct field *first, *last;
8577 /* Memory allocation. */
8578 params = calloc(1, sizeof(struct rte_swx_table_selector_params));
8583 params->group_id_offset = s->group_id_field->offset / 8;
8585 /* Find first (smallest offset) and last (biggest offset) selector fields. */
8586 first = s->selector_fields[0];
8587 last = s->selector_fields[0];
8589 for (i = 0; i < s->n_selector_fields; i++) {
8590 struct field *f = s->selector_fields[i];
8592 if (f->offset < first->offset)
8595 if (f->offset > last->offset)
8599 /* Selector offset and size. */
8600 params->selector_offset = first->offset / 8;
8601 params->selector_size = (last->offset + last->n_bits - first->offset) / 8;
8603 /* Memory allocation. */
8604 params->selector_mask = calloc(1, params->selector_size);
8605 if (!params->selector_mask)
8608 /* Selector mask. */
8609 for (i = 0; i < s->n_selector_fields; i++) {
8610 struct field *f = s->selector_fields[i];
8611 uint32_t start = (f->offset - first->offset) / 8;
8612 size_t size = f->n_bits / 8;
8614 memset(¶ms->selector_mask[start], 0xFF, size);
8618 params->member_id_offset = s->member_id_field->offset / 8;
8620 /* Maximum number of groups. */
8621 params->n_groups_max = s->n_groups_max;
8623 /* Maximum number of members per group. */
8624 params->n_members_per_group_max = s->n_members_per_group_max;
8629 selector_params_free(params);
8634 selector_build_free(struct rte_swx_pipeline *p)
8638 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8639 struct thread *t = &p->threads[i];
8645 for (j = 0; j < p->n_selectors; j++) {
8646 struct selector_runtime *r = &t->selectors[j];
8652 t->selectors = NULL;
8655 free(p->selector_stats);
8656 p->selector_stats = NULL;
8660 selector_build(struct rte_swx_pipeline *p)
8665 /* Per pipeline: selector statistics. */
8666 p->selector_stats = calloc(p->n_selectors, sizeof(struct selector_statistics));
8667 if (!p->selector_stats) {
8672 /* Per thread: selector run-time. */
8673 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8674 struct thread *t = &p->threads[i];
8677 t->selectors = calloc(p->n_selectors, sizeof(struct selector_runtime));
8678 if (!t->selectors) {
8683 TAILQ_FOREACH(s, &p->selectors, node) {
8684 struct selector_runtime *r = &t->selectors[s->id];
8688 size = rte_swx_table_selector_mailbox_size_get();
8690 r->mailbox = calloc(1, size);
8697 /* r->group_id_buffer. */
8698 r->group_id_buffer = &t->structs[p->metadata_struct_id];
8700 /* r->selector_buffer. */
8701 r->selector_buffer = s->selector_header ?
8702 &t->structs[s->selector_header->struct_id] :
8703 &t->structs[p->metadata_struct_id];
8705 /* r->member_id_buffer. */
8706 r->member_id_buffer = &t->structs[p->metadata_struct_id];
8713 selector_build_free(p);
8718 selector_free(struct rte_swx_pipeline *p)
8720 selector_build_free(p);
8722 /* Selector tables. */
8724 struct selector *elem;
8726 elem = TAILQ_FIRST(&p->selectors);
8730 TAILQ_REMOVE(&p->selectors, elem, node);
8731 free(elem->selector_fields);
8739 static struct learner *
8740 learner_find(struct rte_swx_pipeline *p, const char *name)
8744 TAILQ_FOREACH(l, &p->learners, node)
8745 if (!strcmp(l->name, name))
8751 static struct learner *
8752 learner_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8754 struct learner *l = NULL;
8756 TAILQ_FOREACH(l, &p->learners, node)
8764 learner_match_fields_check(struct rte_swx_pipeline *p,
8765 struct rte_swx_pipeline_learner_params *params,
8766 struct header **header)
8768 struct header *h0 = NULL;
8769 struct field *hf, *mf;
8772 /* Return if no match fields. */
8773 if (!params->n_fields || !params->field_names)
8776 /* Check that all the match fields either belong to the same header
8777 * or are all meta-data fields.
8779 hf = header_field_parse(p, params->field_names[0], &h0);
8780 mf = metadata_field_parse(p, params->field_names[0]);
8784 for (i = 1; i < params->n_fields; i++)
8788 hf = header_field_parse(p, params->field_names[i], &h);
8789 if (!hf || (h->id != h0->id))
8792 mf = metadata_field_parse(p, params->field_names[i]);
8797 /* Check that there are no duplicated match fields. */
8798 for (i = 0; i < params->n_fields; i++) {
8799 const char *field_name = params->field_names[i];
8802 for (j = i + 1; j < params->n_fields; j++)
8803 if (!strcmp(params->field_names[j], field_name))
8815 learner_action_args_check(struct rte_swx_pipeline *p, struct action *a, const char *mf_name)
8817 struct struct_type *mst = p->metadata_st, *ast = a->st;
8818 struct field *mf, *af;
8828 /* Check that mf_name is the name of a valid meta-data field. */
8829 CHECK_NAME(mf_name, EINVAL);
8830 mf = metadata_field_parse(p, mf_name);
8833 /* Check that there are enough meta-data fields, starting with the mf_name field, to cover
8834 * all the action arguments.
8836 mf_pos = mf - mst->fields;
8837 CHECK(mst->n_fields - mf_pos >= ast->n_fields, EINVAL);
8839 /* Check that the size of each of the identified meta-data fields matches exactly the size
8840 * of the corresponding action argument.
8842 for (i = 0; i < ast->n_fields; i++) {
8843 mf = &mst->fields[mf_pos + i];
8844 af = &ast->fields[i];
8846 CHECK(mf->n_bits == af->n_bits, EINVAL);
8853 learner_action_learning_check(struct rte_swx_pipeline *p,
8854 struct action *action,
8855 const char **action_names,
8860 /* For each "learn" instruction of the current action, check that the learned action (i.e.
8861 * the action passed as argument to the "learn" instruction) is also enabled for the
8862 * current learner table.
8864 for (i = 0; i < action->n_instructions; i++) {
8865 struct instruction *instr = &action->instructions[i];
8866 uint32_t found = 0, j;
8868 if (instr->type != INSTR_LEARNER_LEARN)
8871 for (j = 0; j < n_actions; j++) {
8874 a = action_find(p, action_names[j]);
8878 if (a->id == instr->learn.action_id)
8890 rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p,
8892 struct rte_swx_pipeline_learner_params *params,
8896 struct learner *l = NULL;
8897 struct action *default_action;
8898 struct header *header = NULL;
8899 uint32_t action_data_size_max = 0, i;
8904 CHECK_NAME(name, EINVAL);
8905 CHECK(!table_find(p, name), EEXIST);
8906 CHECK(!selector_find(p, name), EEXIST);
8907 CHECK(!learner_find(p, name), EEXIST);
8909 CHECK(params, EINVAL);
8912 status = learner_match_fields_check(p, params, &header);
8916 /* Action checks. */
8917 CHECK(params->n_actions, EINVAL);
8919 CHECK(params->action_names, EINVAL);
8920 for (i = 0; i < params->n_actions; i++) {
8921 const char *action_name = params->action_names[i];
8922 const char *action_field_name = params->action_field_names[i];
8924 uint32_t action_data_size;
8926 CHECK_NAME(action_name, EINVAL);
8928 a = action_find(p, action_name);
8931 status = learner_action_args_check(p, a, action_field_name);
8935 status = learner_action_learning_check(p,
8937 params->action_names,
8942 action_data_size = a->st ? a->st->n_bits / 8 : 0;
8943 if (action_data_size > action_data_size_max)
8944 action_data_size_max = action_data_size;
8947 CHECK_NAME(params->default_action_name, EINVAL);
8948 for (i = 0; i < p->n_actions; i++)
8949 if (!strcmp(params->action_names[i],
8950 params->default_action_name))
8952 CHECK(i < params->n_actions, EINVAL);
8954 default_action = action_find(p, params->default_action_name);
8955 CHECK((default_action->st && params->default_action_data) ||
8956 !params->default_action_data, EINVAL);
8958 /* Any other checks. */
8959 CHECK(size, EINVAL);
8960 CHECK(timeout, EINVAL);
8962 /* Memory allocation. */
8963 l = calloc(1, sizeof(struct learner));
8967 l->fields = calloc(params->n_fields, sizeof(struct field *));
8971 l->actions = calloc(params->n_actions, sizeof(struct action *));
8975 l->action_arg = calloc(params->n_actions, sizeof(struct field *));
8979 if (action_data_size_max) {
8980 l->default_action_data = calloc(1, action_data_size_max);
8981 if (!l->default_action_data)
8985 /* Node initialization. */
8986 strcpy(l->name, name);
8988 for (i = 0; i < params->n_fields; i++) {
8989 const char *field_name = params->field_names[i];
8991 l->fields[i] = header ?
8992 header_field_parse(p, field_name, NULL) :
8993 metadata_field_parse(p, field_name);
8996 l->n_fields = params->n_fields;
9000 for (i = 0; i < params->n_actions; i++) {
9001 const char *mf_name = params->action_field_names[i];
9003 l->actions[i] = action_find(p, params->action_names[i]);
9005 l->action_arg[i] = mf_name ? metadata_field_parse(p, mf_name) : NULL;
9008 l->default_action = default_action;
9010 if (default_action->st)
9011 memcpy(l->default_action_data,
9012 params->default_action_data,
9013 default_action->st->n_bits / 8);
9015 l->n_actions = params->n_actions;
9017 l->default_action_is_const = params->default_action_is_const;
9019 l->action_data_size_max = action_data_size_max;
9023 l->timeout = timeout;
9025 l->id = p->n_learners;
9027 /* Node add to tailq. */
9028 TAILQ_INSERT_TAIL(&p->learners, l, node);
9037 free(l->action_arg);
9046 learner_params_free(struct rte_swx_table_learner_params *params)
9051 free(params->key_mask0);
9056 static struct rte_swx_table_learner_params *
9057 learner_params_get(struct learner *l)
9059 struct rte_swx_table_learner_params *params = NULL;
9060 struct field *first, *last;
9063 /* Memory allocation. */
9064 params = calloc(1, sizeof(struct rte_swx_table_learner_params));
9068 /* Find first (smallest offset) and last (biggest offset) match fields. */
9069 first = l->fields[0];
9070 last = l->fields[0];
9072 for (i = 0; i < l->n_fields; i++) {
9073 struct field *f = l->fields[i];
9075 if (f->offset < first->offset)
9078 if (f->offset > last->offset)
9082 /* Key offset and size. */
9083 params->key_offset = first->offset / 8;
9084 params->key_size = (last->offset + last->n_bits - first->offset) / 8;
9086 /* Memory allocation. */
9087 params->key_mask0 = calloc(1, params->key_size);
9088 if (!params->key_mask0)
9092 for (i = 0; i < l->n_fields; i++) {
9093 struct field *f = l->fields[i];
9094 uint32_t start = (f->offset - first->offset) / 8;
9095 size_t size = f->n_bits / 8;
9097 memset(¶ms->key_mask0[start], 0xFF, size);
9100 /* Action data size. */
9101 params->action_data_size = l->action_data_size_max;
9103 /* Maximum number of keys. */
9104 params->n_keys_max = l->size;
9107 params->key_timeout = l->timeout;
9112 learner_params_free(params);
9117 learner_build_free(struct rte_swx_pipeline *p)
9121 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9122 struct thread *t = &p->threads[i];
9128 for (j = 0; j < p->n_learners; j++) {
9129 struct learner_runtime *r = &t->learners[j];
9132 free(r->action_data);
9139 if (p->learner_stats) {
9140 for (i = 0; i < p->n_learners; i++)
9141 free(p->learner_stats[i].n_pkts_action);
9143 free(p->learner_stats);
9148 learner_build(struct rte_swx_pipeline *p)
9153 /* Per pipeline: learner statistics. */
9154 p->learner_stats = calloc(p->n_learners, sizeof(struct learner_statistics));
9155 CHECK(p->learner_stats, ENOMEM);
9157 for (i = 0; i < p->n_learners; i++) {
9158 p->learner_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
9159 CHECK(p->learner_stats[i].n_pkts_action, ENOMEM);
9162 /* Per thread: learner run-time. */
9163 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9164 struct thread *t = &p->threads[i];
9167 t->learners = calloc(p->n_learners, sizeof(struct learner_runtime));
9173 TAILQ_FOREACH(l, &p->learners, node) {
9174 struct learner_runtime *r = &t->learners[l->id];
9179 size = rte_swx_table_learner_mailbox_size_get();
9181 r->mailbox = calloc(1, size);
9189 r->key = l->header ?
9190 &t->structs[l->header->struct_id] :
9191 &t->structs[p->metadata_struct_id];
9193 /* r->action_data. */
9194 r->action_data = calloc(p->n_actions, sizeof(uint8_t *));
9195 if (!r->action_data) {
9200 for (j = 0; j < l->n_actions; j++) {
9201 struct action *a = l->actions[j];
9202 struct field *mf = l->action_arg[j];
9203 uint8_t *m = t->structs[p->metadata_struct_id];
9205 r->action_data[a->id] = mf ? &m[mf->offset / 8] : NULL;
9213 learner_build_free(p);
9218 learner_free(struct rte_swx_pipeline *p)
9220 learner_build_free(p);
9222 /* Learner tables. */
9226 l = TAILQ_FIRST(&p->learners);
9230 TAILQ_REMOVE(&p->learners, l, node);
9233 free(l->action_arg);
9234 free(l->default_action_data);
9243 table_state_build(struct rte_swx_pipeline *p)
9245 struct table *table;
9249 p->table_state = calloc(p->n_tables + p->n_selectors,
9250 sizeof(struct rte_swx_table_state));
9251 CHECK(p->table_state, ENOMEM);
9253 TAILQ_FOREACH(table, &p->tables, node) {
9254 struct rte_swx_table_state *ts = &p->table_state[table->id];
9257 struct rte_swx_table_params *params;
9260 params = table_params_get(table);
9261 CHECK(params, ENOMEM);
9263 ts->obj = table->type->ops.create(params,
9268 table_params_free(params);
9269 CHECK(ts->obj, ENODEV);
9272 /* ts->default_action_data. */
9273 if (table->action_data_size_max) {
9274 ts->default_action_data =
9275 malloc(table->action_data_size_max);
9276 CHECK(ts->default_action_data, ENOMEM);
9278 memcpy(ts->default_action_data,
9279 table->default_action_data,
9280 table->action_data_size_max);
9283 /* ts->default_action_id. */
9284 ts->default_action_id = table->default_action->id;
9287 TAILQ_FOREACH(s, &p->selectors, node) {
9288 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + s->id];
9289 struct rte_swx_table_selector_params *params;
9292 params = selector_table_params_get(s);
9293 CHECK(params, ENOMEM);
9295 ts->obj = rte_swx_table_selector_create(params, NULL, p->numa_node);
9297 selector_params_free(params);
9298 CHECK(ts->obj, ENODEV);
9301 TAILQ_FOREACH(l, &p->learners, node) {
9302 struct rte_swx_table_state *ts = &p->table_state[p->n_tables +
9303 p->n_selectors + l->id];
9304 struct rte_swx_table_learner_params *params;
9307 params = learner_params_get(l);
9308 CHECK(params, ENOMEM);
9310 ts->obj = rte_swx_table_learner_create(params, p->numa_node);
9311 learner_params_free(params);
9312 CHECK(ts->obj, ENODEV);
9314 /* ts->default_action_data. */
9315 if (l->action_data_size_max) {
9316 ts->default_action_data = malloc(l->action_data_size_max);
9317 CHECK(ts->default_action_data, ENOMEM);
9319 memcpy(ts->default_action_data,
9320 l->default_action_data,
9321 l->action_data_size_max);
9324 /* ts->default_action_id. */
9325 ts->default_action_id = l->default_action->id;
9332 table_state_build_free(struct rte_swx_pipeline *p)
9336 if (!p->table_state)
9339 for (i = 0; i < p->n_tables; i++) {
9340 struct rte_swx_table_state *ts = &p->table_state[i];
9341 struct table *table = table_find_by_id(p, i);
9344 if (table->type && ts->obj)
9345 table->type->ops.free(ts->obj);
9347 /* ts->default_action_data. */
9348 free(ts->default_action_data);
9351 for (i = 0; i < p->n_selectors; i++) {
9352 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + i];
9356 rte_swx_table_selector_free(ts->obj);
9359 for (i = 0; i < p->n_learners; i++) {
9360 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + p->n_selectors + i];
9364 rte_swx_table_learner_free(ts->obj);
9366 /* ts->default_action_data. */
9367 free(ts->default_action_data);
9370 free(p->table_state);
9371 p->table_state = NULL;
9375 table_state_free(struct rte_swx_pipeline *p)
9377 table_state_build_free(p);
9383 static struct regarray *
9384 regarray_find(struct rte_swx_pipeline *p, const char *name)
9386 struct regarray *elem;
9388 TAILQ_FOREACH(elem, &p->regarrays, node)
9389 if (!strcmp(elem->name, name))
9395 static struct regarray *
9396 regarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9398 struct regarray *elem = NULL;
9400 TAILQ_FOREACH(elem, &p->regarrays, node)
9408 rte_swx_pipeline_regarray_config(struct rte_swx_pipeline *p,
9417 CHECK_NAME(name, EINVAL);
9418 CHECK(!regarray_find(p, name), EEXIST);
9420 CHECK(size, EINVAL);
9421 size = rte_align32pow2(size);
9423 /* Memory allocation. */
9424 r = calloc(1, sizeof(struct regarray));
9427 /* Node initialization. */
9428 strcpy(r->name, name);
9429 r->init_val = init_val;
9431 r->id = p->n_regarrays;
9433 /* Node add to tailq. */
9434 TAILQ_INSERT_TAIL(&p->regarrays, r, node);
9441 regarray_build(struct rte_swx_pipeline *p)
9443 struct regarray *regarray;
9445 if (!p->n_regarrays)
9448 p->regarray_runtime = calloc(p->n_regarrays, sizeof(struct regarray_runtime));
9449 CHECK(p->regarray_runtime, ENOMEM);
9451 TAILQ_FOREACH(regarray, &p->regarrays, node) {
9452 struct regarray_runtime *r = &p->regarray_runtime[regarray->id];
9455 r->regarray = env_malloc(regarray->size * sizeof(uint64_t),
9456 RTE_CACHE_LINE_SIZE,
9458 CHECK(r->regarray, ENOMEM);
9460 if (regarray->init_val)
9461 for (i = 0; i < regarray->size; i++)
9462 r->regarray[i] = regarray->init_val;
9464 r->size_mask = regarray->size - 1;
9471 regarray_build_free(struct rte_swx_pipeline *p)
9475 if (!p->regarray_runtime)
9478 for (i = 0; i < p->n_regarrays; i++) {
9479 struct regarray *regarray = regarray_find_by_id(p, i);
9480 struct regarray_runtime *r = &p->regarray_runtime[i];
9482 env_free(r->regarray, regarray->size * sizeof(uint64_t));
9485 free(p->regarray_runtime);
9486 p->regarray_runtime = NULL;
9490 regarray_free(struct rte_swx_pipeline *p)
9492 regarray_build_free(p);
9495 struct regarray *elem;
9497 elem = TAILQ_FIRST(&p->regarrays);
9501 TAILQ_REMOVE(&p->regarrays, elem, node);
9509 static struct meter_profile *
9510 meter_profile_find(struct rte_swx_pipeline *p, const char *name)
9512 struct meter_profile *elem;
9514 TAILQ_FOREACH(elem, &p->meter_profiles, node)
9515 if (!strcmp(elem->name, name))
9521 static struct metarray *
9522 metarray_find(struct rte_swx_pipeline *p, const char *name)
9524 struct metarray *elem;
9526 TAILQ_FOREACH(elem, &p->metarrays, node)
9527 if (!strcmp(elem->name, name))
9533 static struct metarray *
9534 metarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9536 struct metarray *elem = NULL;
9538 TAILQ_FOREACH(elem, &p->metarrays, node)
9546 rte_swx_pipeline_metarray_config(struct rte_swx_pipeline *p,
9554 CHECK_NAME(name, EINVAL);
9555 CHECK(!metarray_find(p, name), EEXIST);
9557 CHECK(size, EINVAL);
9558 size = rte_align32pow2(size);
9560 /* Memory allocation. */
9561 m = calloc(1, sizeof(struct metarray));
9564 /* Node initialization. */
9565 strcpy(m->name, name);
9567 m->id = p->n_metarrays;
9569 /* Node add to tailq. */
9570 TAILQ_INSERT_TAIL(&p->metarrays, m, node);
9576 struct meter_profile meter_profile_default = {
9585 .cir_bytes_per_period = 1,
9587 .pir_bytes_per_period = 1,
9594 meter_init(struct meter *m)
9596 memset(m, 0, sizeof(struct meter));
9597 rte_meter_trtcm_config(&m->m, &meter_profile_default.profile);
9598 m->profile = &meter_profile_default;
9599 m->color_mask = RTE_COLOR_GREEN;
9601 meter_profile_default.n_users++;
9605 metarray_build(struct rte_swx_pipeline *p)
9609 if (!p->n_metarrays)
9612 p->metarray_runtime = calloc(p->n_metarrays, sizeof(struct metarray_runtime));
9613 CHECK(p->metarray_runtime, ENOMEM);
9615 TAILQ_FOREACH(m, &p->metarrays, node) {
9616 struct metarray_runtime *r = &p->metarray_runtime[m->id];
9619 r->metarray = env_malloc(m->size * sizeof(struct meter),
9620 RTE_CACHE_LINE_SIZE,
9622 CHECK(r->metarray, ENOMEM);
9624 for (i = 0; i < m->size; i++)
9625 meter_init(&r->metarray[i]);
9627 r->size_mask = m->size - 1;
9634 metarray_build_free(struct rte_swx_pipeline *p)
9638 if (!p->metarray_runtime)
9641 for (i = 0; i < p->n_metarrays; i++) {
9642 struct metarray *m = metarray_find_by_id(p, i);
9643 struct metarray_runtime *r = &p->metarray_runtime[i];
9645 env_free(r->metarray, m->size * sizeof(struct meter));
9648 free(p->metarray_runtime);
9649 p->metarray_runtime = NULL;
9653 metarray_free(struct rte_swx_pipeline *p)
9655 metarray_build_free(p);
9659 struct metarray *elem;
9661 elem = TAILQ_FIRST(&p->metarrays);
9665 TAILQ_REMOVE(&p->metarrays, elem, node);
9669 /* Meter profiles. */
9671 struct meter_profile *elem;
9673 elem = TAILQ_FIRST(&p->meter_profiles);
9677 TAILQ_REMOVE(&p->meter_profiles, elem, node);
9686 rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
9688 struct rte_swx_pipeline *pipeline;
9690 /* Check input parameters. */
9693 /* Memory allocation. */
9694 pipeline = calloc(1, sizeof(struct rte_swx_pipeline));
9695 CHECK(pipeline, ENOMEM);
9697 /* Initialization. */
9698 TAILQ_INIT(&pipeline->struct_types);
9699 TAILQ_INIT(&pipeline->port_in_types);
9700 TAILQ_INIT(&pipeline->ports_in);
9701 TAILQ_INIT(&pipeline->port_out_types);
9702 TAILQ_INIT(&pipeline->ports_out);
9703 TAILQ_INIT(&pipeline->extern_types);
9704 TAILQ_INIT(&pipeline->extern_objs);
9705 TAILQ_INIT(&pipeline->extern_funcs);
9706 TAILQ_INIT(&pipeline->headers);
9707 TAILQ_INIT(&pipeline->actions);
9708 TAILQ_INIT(&pipeline->table_types);
9709 TAILQ_INIT(&pipeline->tables);
9710 TAILQ_INIT(&pipeline->selectors);
9711 TAILQ_INIT(&pipeline->learners);
9712 TAILQ_INIT(&pipeline->regarrays);
9713 TAILQ_INIT(&pipeline->meter_profiles);
9714 TAILQ_INIT(&pipeline->metarrays);
9716 pipeline->n_structs = 1; /* Struct 0 is reserved for action_data. */
9717 pipeline->numa_node = numa_node;
9724 rte_swx_pipeline_free(struct rte_swx_pipeline *p)
9729 free(p->instructions);
9733 table_state_free(p);
9740 extern_func_free(p);
9750 rte_swx_pipeline_instructions_config(struct rte_swx_pipeline *p,
9751 const char **instructions,
9752 uint32_t n_instructions)
9757 err = instruction_config(p, NULL, instructions, n_instructions);
9761 /* Thread instruction pointer reset. */
9762 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9763 struct thread *t = &p->threads[i];
9765 thread_ip_reset(p, t);
9772 rte_swx_pipeline_build(struct rte_swx_pipeline *p)
9777 CHECK(p->build_done == 0, EEXIST);
9779 status = port_in_build(p);
9783 status = port_out_build(p);
9787 status = struct_build(p);
9791 status = extern_obj_build(p);
9795 status = extern_func_build(p);
9799 status = header_build(p);
9803 status = metadata_build(p);
9807 status = action_build(p);
9811 status = table_build(p);
9815 status = selector_build(p);
9819 status = learner_build(p);
9823 status = table_state_build(p);
9827 status = regarray_build(p);
9831 status = metarray_build(p);
9839 metarray_build_free(p);
9840 regarray_build_free(p);
9841 table_state_build_free(p);
9842 learner_build_free(p);
9843 selector_build_free(p);
9844 table_build_free(p);
9845 action_build_free(p);
9846 metadata_build_free(p);
9847 header_build_free(p);
9848 extern_func_build_free(p);
9849 extern_obj_build_free(p);
9850 port_out_build_free(p);
9851 port_in_build_free(p);
9852 struct_build_free(p);
9858 rte_swx_pipeline_run(struct rte_swx_pipeline *p, uint32_t n_instructions)
9862 for (i = 0; i < n_instructions; i++)
9867 rte_swx_pipeline_flush(struct rte_swx_pipeline *p)
9871 for (i = 0; i < p->n_ports_out; i++) {
9872 struct port_out_runtime *port = &p->out[i];
9875 port->flush(port->obj);
9883 rte_swx_ctl_pipeline_info_get(struct rte_swx_pipeline *p,
9884 struct rte_swx_ctl_pipeline_info *pipeline)
9886 struct action *action;
9887 struct table *table;
9888 uint32_t n_actions = 0, n_tables = 0;
9890 if (!p || !pipeline)
9893 TAILQ_FOREACH(action, &p->actions, node)
9896 TAILQ_FOREACH(table, &p->tables, node)
9899 pipeline->n_ports_in = p->n_ports_in;
9900 pipeline->n_ports_out = p->n_ports_out;
9901 pipeline->n_actions = n_actions;
9902 pipeline->n_tables = n_tables;
9903 pipeline->n_selectors = p->n_selectors;
9904 pipeline->n_learners = p->n_learners;
9905 pipeline->n_regarrays = p->n_regarrays;
9906 pipeline->n_metarrays = p->n_metarrays;
9912 rte_swx_ctl_pipeline_numa_node_get(struct rte_swx_pipeline *p, int *numa_node)
9914 if (!p || !numa_node)
9917 *numa_node = p->numa_node;
9922 rte_swx_ctl_action_info_get(struct rte_swx_pipeline *p,
9924 struct rte_swx_ctl_action_info *action)
9926 struct action *a = NULL;
9928 if (!p || (action_id >= p->n_actions) || !action)
9931 a = action_find_by_id(p, action_id);
9935 strcpy(action->name, a->name);
9936 action->n_args = a->st ? a->st->n_fields : 0;
9941 rte_swx_ctl_action_arg_info_get(struct rte_swx_pipeline *p,
9943 uint32_t action_arg_id,
9944 struct rte_swx_ctl_action_arg_info *action_arg)
9946 struct action *a = NULL;
9947 struct field *arg = NULL;
9949 if (!p || (action_id >= p->n_actions) || !action_arg)
9952 a = action_find_by_id(p, action_id);
9953 if (!a || !a->st || (action_arg_id >= a->st->n_fields))
9956 arg = &a->st->fields[action_arg_id];
9957 strcpy(action_arg->name, arg->name);
9958 action_arg->n_bits = arg->n_bits;
9959 action_arg->is_network_byte_order = a->args_endianness[action_arg_id];
9965 rte_swx_ctl_table_info_get(struct rte_swx_pipeline *p,
9967 struct rte_swx_ctl_table_info *table)
9969 struct table *t = NULL;
9974 t = table_find_by_id(p, table_id);
9978 strcpy(table->name, t->name);
9979 strcpy(table->args, t->args);
9980 table->n_match_fields = t->n_fields;
9981 table->n_actions = t->n_actions;
9982 table->default_action_is_const = t->default_action_is_const;
9983 table->size = t->size;
9988 rte_swx_ctl_table_match_field_info_get(struct rte_swx_pipeline *p,
9990 uint32_t match_field_id,
9991 struct rte_swx_ctl_table_match_field_info *match_field)
9994 struct match_field *f;
9996 if (!p || (table_id >= p->n_tables) || !match_field)
9999 t = table_find_by_id(p, table_id);
10000 if (!t || (match_field_id >= t->n_fields))
10003 f = &t->fields[match_field_id];
10004 match_field->match_type = f->match_type;
10005 match_field->is_header = t->header ? 1 : 0;
10006 match_field->n_bits = f->field->n_bits;
10007 match_field->offset = f->field->offset;
10013 rte_swx_ctl_table_action_info_get(struct rte_swx_pipeline *p,
10015 uint32_t table_action_id,
10016 struct rte_swx_ctl_table_action_info *table_action)
10020 if (!p || (table_id >= p->n_tables) || !table_action)
10023 t = table_find_by_id(p, table_id);
10024 if (!t || (table_action_id >= t->n_actions))
10027 table_action->action_id = t->actions[table_action_id]->id;
10033 rte_swx_ctl_table_ops_get(struct rte_swx_pipeline *p,
10035 struct rte_swx_table_ops *table_ops,
10040 if (!p || (table_id >= p->n_tables))
10043 t = table_find_by_id(p, table_id);
10049 memcpy(table_ops, &t->type->ops, sizeof(*table_ops));
10059 rte_swx_ctl_selector_info_get(struct rte_swx_pipeline *p,
10060 uint32_t selector_id,
10061 struct rte_swx_ctl_selector_info *selector)
10063 struct selector *s = NULL;
10065 if (!p || !selector)
10068 s = selector_find_by_id(p, selector_id);
10072 strcpy(selector->name, s->name);
10074 selector->n_selector_fields = s->n_selector_fields;
10075 selector->n_groups_max = s->n_groups_max;
10076 selector->n_members_per_group_max = s->n_members_per_group_max;
10082 rte_swx_ctl_selector_group_id_field_info_get(struct rte_swx_pipeline *p,
10083 uint32_t selector_id,
10084 struct rte_swx_ctl_table_match_field_info *field)
10086 struct selector *s;
10088 if (!p || (selector_id >= p->n_selectors) || !field)
10091 s = selector_find_by_id(p, selector_id);
10095 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10096 field->is_header = 0;
10097 field->n_bits = s->group_id_field->n_bits;
10098 field->offset = s->group_id_field->offset;
10104 rte_swx_ctl_selector_field_info_get(struct rte_swx_pipeline *p,
10105 uint32_t selector_id,
10106 uint32_t selector_field_id,
10107 struct rte_swx_ctl_table_match_field_info *field)
10109 struct selector *s;
10112 if (!p || (selector_id >= p->n_selectors) || !field)
10115 s = selector_find_by_id(p, selector_id);
10116 if (!s || (selector_field_id >= s->n_selector_fields))
10119 f = s->selector_fields[selector_field_id];
10120 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10121 field->is_header = s->selector_header ? 1 : 0;
10122 field->n_bits = f->n_bits;
10123 field->offset = f->offset;
10129 rte_swx_ctl_selector_member_id_field_info_get(struct rte_swx_pipeline *p,
10130 uint32_t selector_id,
10131 struct rte_swx_ctl_table_match_field_info *field)
10133 struct selector *s;
10135 if (!p || (selector_id >= p->n_selectors) || !field)
10138 s = selector_find_by_id(p, selector_id);
10142 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10143 field->is_header = 0;
10144 field->n_bits = s->member_id_field->n_bits;
10145 field->offset = s->member_id_field->offset;
10151 rte_swx_ctl_learner_info_get(struct rte_swx_pipeline *p,
10152 uint32_t learner_id,
10153 struct rte_swx_ctl_learner_info *learner)
10155 struct learner *l = NULL;
10157 if (!p || !learner)
10160 l = learner_find_by_id(p, learner_id);
10164 strcpy(learner->name, l->name);
10166 learner->n_match_fields = l->n_fields;
10167 learner->n_actions = l->n_actions;
10168 learner->default_action_is_const = l->default_action_is_const;
10169 learner->size = l->size;
10175 rte_swx_ctl_learner_match_field_info_get(struct rte_swx_pipeline *p,
10176 uint32_t learner_id,
10177 uint32_t match_field_id,
10178 struct rte_swx_ctl_table_match_field_info *match_field)
10183 if (!p || (learner_id >= p->n_learners) || !match_field)
10186 l = learner_find_by_id(p, learner_id);
10187 if (!l || (match_field_id >= l->n_fields))
10190 f = l->fields[match_field_id];
10191 match_field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10192 match_field->is_header = l->header ? 1 : 0;
10193 match_field->n_bits = f->n_bits;
10194 match_field->offset = f->offset;
10200 rte_swx_ctl_learner_action_info_get(struct rte_swx_pipeline *p,
10201 uint32_t learner_id,
10202 uint32_t learner_action_id,
10203 struct rte_swx_ctl_table_action_info *learner_action)
10207 if (!p || (learner_id >= p->n_learners) || !learner_action)
10210 l = learner_find_by_id(p, learner_id);
10211 if (!l || (learner_action_id >= l->n_actions))
10214 learner_action->action_id = l->actions[learner_action_id]->id;
10220 rte_swx_pipeline_table_state_get(struct rte_swx_pipeline *p,
10221 struct rte_swx_table_state **table_state)
10223 if (!p || !table_state || !p->build_done)
10226 *table_state = p->table_state;
10231 rte_swx_pipeline_table_state_set(struct rte_swx_pipeline *p,
10232 struct rte_swx_table_state *table_state)
10234 if (!p || !table_state || !p->build_done)
10237 p->table_state = table_state;
10242 rte_swx_ctl_pipeline_port_in_stats_read(struct rte_swx_pipeline *p,
10244 struct rte_swx_port_in_stats *stats)
10246 struct port_in *port;
10251 port = port_in_find(p, port_id);
10255 port->type->ops.stats_read(port->obj, stats);
10260 rte_swx_ctl_pipeline_port_out_stats_read(struct rte_swx_pipeline *p,
10262 struct rte_swx_port_out_stats *stats)
10264 struct port_out *port;
10269 port = port_out_find(p, port_id);
10273 port->type->ops.stats_read(port->obj, stats);
10278 rte_swx_ctl_pipeline_table_stats_read(struct rte_swx_pipeline *p,
10279 const char *table_name,
10280 struct rte_swx_table_stats *stats)
10282 struct table *table;
10283 struct table_statistics *table_stats;
10285 if (!p || !table_name || !table_name[0] || !stats || !stats->n_pkts_action)
10288 table = table_find(p, table_name);
10292 table_stats = &p->table_stats[table->id];
10294 memcpy(stats->n_pkts_action,
10295 table_stats->n_pkts_action,
10296 p->n_actions * sizeof(uint64_t));
10298 stats->n_pkts_hit = table_stats->n_pkts_hit[1];
10299 stats->n_pkts_miss = table_stats->n_pkts_hit[0];
10305 rte_swx_ctl_pipeline_selector_stats_read(struct rte_swx_pipeline *p,
10306 const char *selector_name,
10307 struct rte_swx_pipeline_selector_stats *stats)
10309 struct selector *s;
10311 if (!p || !selector_name || !selector_name[0] || !stats)
10314 s = selector_find(p, selector_name);
10318 stats->n_pkts = p->selector_stats[s->id].n_pkts;
10324 rte_swx_ctl_pipeline_learner_stats_read(struct rte_swx_pipeline *p,
10325 const char *learner_name,
10326 struct rte_swx_learner_stats *stats)
10329 struct learner_statistics *learner_stats;
10331 if (!p || !learner_name || !learner_name[0] || !stats || !stats->n_pkts_action)
10334 l = learner_find(p, learner_name);
10338 learner_stats = &p->learner_stats[l->id];
10340 memcpy(stats->n_pkts_action,
10341 learner_stats->n_pkts_action,
10342 p->n_actions * sizeof(uint64_t));
10344 stats->n_pkts_hit = learner_stats->n_pkts_hit[1];
10345 stats->n_pkts_miss = learner_stats->n_pkts_hit[0];
10347 stats->n_pkts_learn_ok = learner_stats->n_pkts_learn[0];
10348 stats->n_pkts_learn_err = learner_stats->n_pkts_learn[1];
10350 stats->n_pkts_forget = learner_stats->n_pkts_forget;
10356 rte_swx_ctl_regarray_info_get(struct rte_swx_pipeline *p,
10357 uint32_t regarray_id,
10358 struct rte_swx_ctl_regarray_info *regarray)
10360 struct regarray *r;
10362 if (!p || !regarray)
10365 r = regarray_find_by_id(p, regarray_id);
10369 strcpy(regarray->name, r->name);
10370 regarray->size = r->size;
10375 rte_swx_ctl_pipeline_regarray_read(struct rte_swx_pipeline *p,
10376 const char *regarray_name,
10377 uint32_t regarray_index,
10380 struct regarray *regarray;
10381 struct regarray_runtime *r;
10383 if (!p || !regarray_name || !value)
10386 regarray = regarray_find(p, regarray_name);
10387 if (!regarray || (regarray_index >= regarray->size))
10390 r = &p->regarray_runtime[regarray->id];
10391 *value = r->regarray[regarray_index];
10396 rte_swx_ctl_pipeline_regarray_write(struct rte_swx_pipeline *p,
10397 const char *regarray_name,
10398 uint32_t regarray_index,
10401 struct regarray *regarray;
10402 struct regarray_runtime *r;
10404 if (!p || !regarray_name)
10407 regarray = regarray_find(p, regarray_name);
10408 if (!regarray || (regarray_index >= regarray->size))
10411 r = &p->regarray_runtime[regarray->id];
10412 r->regarray[regarray_index] = value;
10417 rte_swx_ctl_metarray_info_get(struct rte_swx_pipeline *p,
10418 uint32_t metarray_id,
10419 struct rte_swx_ctl_metarray_info *metarray)
10421 struct metarray *m;
10423 if (!p || !metarray)
10426 m = metarray_find_by_id(p, metarray_id);
10430 strcpy(metarray->name, m->name);
10431 metarray->size = m->size;
10436 rte_swx_ctl_meter_profile_add(struct rte_swx_pipeline *p,
10438 struct rte_meter_trtcm_params *params)
10440 struct meter_profile *mp;
10444 CHECK_NAME(name, EINVAL);
10445 CHECK(params, EINVAL);
10446 CHECK(!meter_profile_find(p, name), EEXIST);
10448 /* Node allocation. */
10449 mp = calloc(1, sizeof(struct meter_profile));
10452 /* Node initialization. */
10453 strcpy(mp->name, name);
10454 memcpy(&mp->params, params, sizeof(struct rte_meter_trtcm_params));
10455 status = rte_meter_trtcm_profile_config(&mp->profile, params);
10461 /* Node add to tailq. */
10462 TAILQ_INSERT_TAIL(&p->meter_profiles, mp, node);
10468 rte_swx_ctl_meter_profile_delete(struct rte_swx_pipeline *p,
10471 struct meter_profile *mp;
10474 CHECK_NAME(name, EINVAL);
10476 mp = meter_profile_find(p, name);
10478 CHECK(!mp->n_users, EBUSY);
10480 /* Remove node from tailq. */
10481 TAILQ_REMOVE(&p->meter_profiles, mp, node);
10488 rte_swx_ctl_meter_reset(struct rte_swx_pipeline *p,
10489 const char *metarray_name,
10490 uint32_t metarray_index)
10492 struct meter_profile *mp_old;
10493 struct metarray *metarray;
10494 struct metarray_runtime *metarray_runtime;
10498 CHECK_NAME(metarray_name, EINVAL);
10500 metarray = metarray_find(p, metarray_name);
10501 CHECK(metarray, EINVAL);
10502 CHECK(metarray_index < metarray->size, EINVAL);
10504 metarray_runtime = &p->metarray_runtime[metarray->id];
10505 m = &metarray_runtime->metarray[metarray_index];
10506 mp_old = m->profile;
10516 rte_swx_ctl_meter_set(struct rte_swx_pipeline *p,
10517 const char *metarray_name,
10518 uint32_t metarray_index,
10519 const char *profile_name)
10521 struct meter_profile *mp, *mp_old;
10522 struct metarray *metarray;
10523 struct metarray_runtime *metarray_runtime;
10527 CHECK_NAME(metarray_name, EINVAL);
10529 metarray = metarray_find(p, metarray_name);
10530 CHECK(metarray, EINVAL);
10531 CHECK(metarray_index < metarray->size, EINVAL);
10533 mp = meter_profile_find(p, profile_name);
10536 metarray_runtime = &p->metarray_runtime[metarray->id];
10537 m = &metarray_runtime->metarray[metarray_index];
10538 mp_old = m->profile;
10540 memset(m, 0, sizeof(struct meter));
10541 rte_meter_trtcm_config(&m->m, &mp->profile);
10543 m->color_mask = RTE_COLORS;
10552 rte_swx_ctl_meter_stats_read(struct rte_swx_pipeline *p,
10553 const char *metarray_name,
10554 uint32_t metarray_index,
10555 struct rte_swx_ctl_meter_stats *stats)
10557 struct metarray *metarray;
10558 struct metarray_runtime *metarray_runtime;
10562 CHECK_NAME(metarray_name, EINVAL);
10564 metarray = metarray_find(p, metarray_name);
10565 CHECK(metarray, EINVAL);
10566 CHECK(metarray_index < metarray->size, EINVAL);
10568 CHECK(stats, EINVAL);
10570 metarray_runtime = &p->metarray_runtime[metarray->id];
10571 m = &metarray_runtime->metarray[metarray_index];
10573 memcpy(stats->n_pkts, m->n_pkts, sizeof(m->n_pkts));
10574 memcpy(stats->n_bytes, m->n_bytes, sizeof(m->n_bytes));