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, uint32_t n_emit);
1816 __instr_hdr_emit_exec(struct rte_swx_pipeline *p, uint32_t n_emit)
1818 struct thread *t = &p->threads[p->thread_id];
1819 struct instruction *ip = t->ip;
1820 uint64_t valid_headers = t->valid_headers;
1821 uint32_t n_headers_out = t->n_headers_out;
1822 struct header_out_runtime *ho = &t->headers_out[n_headers_out - 1];
1823 uint8_t *ho_ptr = NULL;
1824 uint32_t ho_nbytes = 0, first = 1, i;
1826 for (i = 0; i < n_emit; i++) {
1827 uint32_t header_id = ip->io.hdr.header_id[i];
1828 uint32_t struct_id = ip->io.hdr.struct_id[i];
1830 struct header_runtime *hi = &t->headers[header_id];
1831 uint8_t *hi_ptr0 = hi->ptr0;
1832 uint32_t n_bytes = hi->n_bytes;
1834 uint8_t *hi_ptr = t->structs[struct_id];
1836 if (!MASK64_BIT_GET(valid_headers, header_id))
1839 TRACE("[Thread %2u]: emit header %u\n",
1847 if (!t->n_headers_out) {
1848 ho = &t->headers_out[0];
1854 ho_nbytes = n_bytes;
1861 ho_nbytes = ho->n_bytes;
1865 if (ho_ptr + ho_nbytes == hi_ptr) {
1866 ho_nbytes += n_bytes;
1868 ho->n_bytes = ho_nbytes;
1875 ho_nbytes = n_bytes;
1881 ho->n_bytes = ho_nbytes;
1882 t->n_headers_out = n_headers_out;
1886 instr_hdr_emit_exec(struct rte_swx_pipeline *p)
1888 __instr_hdr_emit_exec(p, 1);
1895 instr_hdr_emit_tx_exec(struct rte_swx_pipeline *p)
1897 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n",
1900 __instr_hdr_emit_exec(p, 1);
1905 instr_hdr_emit2_tx_exec(struct rte_swx_pipeline *p)
1907 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n",
1910 __instr_hdr_emit_exec(p, 2);
1915 instr_hdr_emit3_tx_exec(struct rte_swx_pipeline *p)
1917 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n",
1920 __instr_hdr_emit_exec(p, 3);
1925 instr_hdr_emit4_tx_exec(struct rte_swx_pipeline *p)
1927 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n",
1930 __instr_hdr_emit_exec(p, 4);
1935 instr_hdr_emit5_tx_exec(struct rte_swx_pipeline *p)
1937 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n",
1940 __instr_hdr_emit_exec(p, 5);
1945 instr_hdr_emit6_tx_exec(struct rte_swx_pipeline *p)
1947 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n",
1950 __instr_hdr_emit_exec(p, 6);
1955 instr_hdr_emit7_tx_exec(struct rte_swx_pipeline *p)
1957 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n",
1960 __instr_hdr_emit_exec(p, 7);
1965 instr_hdr_emit8_tx_exec(struct rte_swx_pipeline *p)
1967 TRACE("[Thread %2u] *** The next 9 instructions are fused. ***\n",
1970 __instr_hdr_emit_exec(p, 8);
1978 instr_hdr_validate_translate(struct rte_swx_pipeline *p,
1979 struct action *action __rte_unused,
1982 struct instruction *instr,
1983 struct instruction_data *data __rte_unused)
1987 CHECK(n_tokens == 2, EINVAL);
1989 h = header_parse(p, tokens[1]);
1992 instr->type = INSTR_HDR_VALIDATE;
1993 instr->valid.header_id = h->id;
1998 instr_hdr_validate_exec(struct rte_swx_pipeline *p)
2000 struct thread *t = &p->threads[p->thread_id];
2001 struct instruction *ip = t->ip;
2002 uint32_t header_id = ip->valid.header_id;
2004 TRACE("[Thread %2u] validate header %u\n", p->thread_id, header_id);
2007 t->valid_headers = MASK64_BIT_SET(t->valid_headers, header_id);
2017 instr_hdr_invalidate_translate(struct rte_swx_pipeline *p,
2018 struct action *action __rte_unused,
2021 struct instruction *instr,
2022 struct instruction_data *data __rte_unused)
2026 CHECK(n_tokens == 2, EINVAL);
2028 h = header_parse(p, tokens[1]);
2031 instr->type = INSTR_HDR_INVALIDATE;
2032 instr->valid.header_id = h->id;
2037 instr_hdr_invalidate_exec(struct rte_swx_pipeline *p)
2039 struct thread *t = &p->threads[p->thread_id];
2040 struct instruction *ip = t->ip;
2041 uint32_t header_id = ip->valid.header_id;
2043 TRACE("[Thread %2u] invalidate header %u\n", p->thread_id, header_id);
2046 t->valid_headers = MASK64_BIT_CLR(t->valid_headers, header_id);
2055 static struct table *
2056 table_find(struct rte_swx_pipeline *p, const char *name);
2058 static struct selector *
2059 selector_find(struct rte_swx_pipeline *p, const char *name);
2061 static struct learner *
2062 learner_find(struct rte_swx_pipeline *p, const char *name);
2065 instr_table_translate(struct rte_swx_pipeline *p,
2066 struct action *action,
2069 struct instruction *instr,
2070 struct instruction_data *data __rte_unused)
2076 CHECK(!action, EINVAL);
2077 CHECK(n_tokens == 2, EINVAL);
2079 t = table_find(p, tokens[1]);
2081 instr->type = INSTR_TABLE;
2082 instr->table.table_id = t->id;
2086 s = selector_find(p, tokens[1]);
2088 instr->type = INSTR_SELECTOR;
2089 instr->table.table_id = s->id;
2093 l = learner_find(p, tokens[1]);
2095 instr->type = INSTR_LEARNER;
2096 instr->table.table_id = l->id;
2104 instr_table_exec(struct rte_swx_pipeline *p)
2106 struct thread *t = &p->threads[p->thread_id];
2107 struct instruction *ip = t->ip;
2108 uint32_t table_id = ip->table.table_id;
2109 struct rte_swx_table_state *ts = &t->table_state[table_id];
2110 struct table_runtime *table = &t->tables[table_id];
2111 struct table_statistics *stats = &p->table_stats[table_id];
2112 uint64_t action_id, n_pkts_hit, n_pkts_action;
2113 uint8_t *action_data;
2117 done = table->func(ts->obj,
2125 TRACE("[Thread %2u] table %u (not finalized)\n",
2133 action_id = hit ? action_id : ts->default_action_id;
2134 action_data = hit ? action_data : ts->default_action_data;
2135 n_pkts_hit = stats->n_pkts_hit[hit];
2136 n_pkts_action = stats->n_pkts_action[action_id];
2138 TRACE("[Thread %2u] table %u (%s, action %u)\n",
2141 hit ? "hit" : "miss",
2142 (uint32_t)action_id);
2144 t->action_id = action_id;
2145 t->structs[0] = action_data;
2147 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2148 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2151 thread_ip_action_call(p, t, action_id);
2155 instr_selector_exec(struct rte_swx_pipeline *p)
2157 struct thread *t = &p->threads[p->thread_id];
2158 struct instruction *ip = t->ip;
2159 uint32_t selector_id = ip->table.table_id;
2160 struct rte_swx_table_state *ts = &t->table_state[p->n_tables + selector_id];
2161 struct selector_runtime *selector = &t->selectors[selector_id];
2162 struct selector_statistics *stats = &p->selector_stats[selector_id];
2163 uint64_t n_pkts = stats->n_pkts;
2167 done = rte_swx_table_selector_select(ts->obj,
2169 selector->group_id_buffer,
2170 selector->selector_buffer,
2171 selector->member_id_buffer);
2174 TRACE("[Thread %2u] selector %u (not finalized)\n",
2183 TRACE("[Thread %2u] selector %u\n",
2187 stats->n_pkts = n_pkts + 1;
2194 instr_learner_exec(struct rte_swx_pipeline *p)
2196 struct thread *t = &p->threads[p->thread_id];
2197 struct instruction *ip = t->ip;
2198 uint32_t learner_id = ip->table.table_id;
2199 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2200 p->n_selectors + learner_id];
2201 struct learner_runtime *l = &t->learners[learner_id];
2202 struct learner_statistics *stats = &p->learner_stats[learner_id];
2203 uint64_t action_id, n_pkts_hit, n_pkts_action, time;
2204 uint8_t *action_data;
2208 time = rte_get_tsc_cycles();
2210 done = rte_swx_table_learner_lookup(ts->obj,
2219 TRACE("[Thread %2u] learner %u (not finalized)\n",
2227 action_id = hit ? action_id : ts->default_action_id;
2228 action_data = hit ? action_data : ts->default_action_data;
2229 n_pkts_hit = stats->n_pkts_hit[hit];
2230 n_pkts_action = stats->n_pkts_action[action_id];
2232 TRACE("[Thread %2u] learner %u (%s, action %u)\n",
2235 hit ? "hit" : "miss",
2236 (uint32_t)action_id);
2238 t->action_id = action_id;
2239 t->structs[0] = action_data;
2241 t->learner_id = learner_id;
2243 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2244 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2247 thread_ip_action_call(p, t, action_id);
2253 static struct action *
2254 action_find(struct rte_swx_pipeline *p, const char *name);
2257 action_has_nbo_args(struct action *a);
2260 instr_learn_translate(struct rte_swx_pipeline *p,
2261 struct action *action,
2264 struct instruction *instr,
2265 struct instruction_data *data __rte_unused)
2269 CHECK(action, EINVAL);
2270 CHECK(n_tokens == 2, EINVAL);
2272 a = action_find(p, tokens[1]);
2274 CHECK(!action_has_nbo_args(a), EINVAL);
2276 instr->type = INSTR_LEARNER_LEARN;
2277 instr->learn.action_id = a->id;
2283 instr_learn_exec(struct rte_swx_pipeline *p)
2285 struct thread *t = &p->threads[p->thread_id];
2286 struct instruction *ip = t->ip;
2287 uint64_t action_id = ip->learn.action_id;
2288 uint32_t learner_id = t->learner_id;
2289 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2290 p->n_selectors + learner_id];
2291 struct learner_runtime *l = &t->learners[learner_id];
2292 struct learner_statistics *stats = &p->learner_stats[learner_id];
2296 status = rte_swx_table_learner_add(ts->obj,
2300 l->action_data[action_id]);
2302 TRACE("[Thread %2u] learner %u learn %s\n",
2305 status ? "ok" : "error");
2307 stats->n_pkts_learn[status] += 1;
2317 instr_forget_translate(struct rte_swx_pipeline *p __rte_unused,
2318 struct action *action,
2319 char **tokens __rte_unused,
2321 struct instruction *instr,
2322 struct instruction_data *data __rte_unused)
2324 CHECK(action, EINVAL);
2325 CHECK(n_tokens == 1, EINVAL);
2327 instr->type = INSTR_LEARNER_FORGET;
2333 instr_forget_exec(struct rte_swx_pipeline *p)
2335 struct thread *t = &p->threads[p->thread_id];
2336 uint32_t learner_id = t->learner_id;
2337 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2338 p->n_selectors + learner_id];
2339 struct learner_runtime *l = &t->learners[learner_id];
2340 struct learner_statistics *stats = &p->learner_stats[learner_id];
2343 rte_swx_table_learner_delete(ts->obj, l->mailbox);
2345 TRACE("[Thread %2u] learner %u forget\n",
2349 stats->n_pkts_forget += 1;
2359 instr_extern_translate(struct rte_swx_pipeline *p,
2360 struct action *action __rte_unused,
2363 struct instruction *instr,
2364 struct instruction_data *data __rte_unused)
2366 char *token = tokens[1];
2368 CHECK(n_tokens == 2, EINVAL);
2370 if (token[0] == 'e') {
2371 struct extern_obj *obj;
2372 struct extern_type_member_func *func;
2374 func = extern_obj_member_func_parse(p, token, &obj);
2375 CHECK(func, EINVAL);
2377 instr->type = INSTR_EXTERN_OBJ;
2378 instr->ext_obj.ext_obj_id = obj->id;
2379 instr->ext_obj.func_id = func->id;
2384 if (token[0] == 'f') {
2385 struct extern_func *func;
2387 func = extern_func_parse(p, token);
2388 CHECK(func, EINVAL);
2390 instr->type = INSTR_EXTERN_FUNC;
2391 instr->ext_func.ext_func_id = func->id;
2400 instr_extern_obj_exec(struct rte_swx_pipeline *p)
2402 struct thread *t = &p->threads[p->thread_id];
2403 struct instruction *ip = t->ip;
2404 uint32_t obj_id = ip->ext_obj.ext_obj_id;
2405 uint32_t func_id = ip->ext_obj.func_id;
2406 struct extern_obj_runtime *obj = &t->extern_objs[obj_id];
2407 rte_swx_extern_type_member_func_t func = obj->funcs[func_id];
2409 TRACE("[Thread %2u] extern obj %u member func %u\n",
2414 /* Extern object member function execute. */
2415 uint32_t done = func(obj->obj, obj->mailbox);
2418 thread_ip_inc_cond(t, done);
2419 thread_yield_cond(p, done ^ 1);
2423 instr_extern_func_exec(struct rte_swx_pipeline *p)
2425 struct thread *t = &p->threads[p->thread_id];
2426 struct instruction *ip = t->ip;
2427 uint32_t ext_func_id = ip->ext_func.ext_func_id;
2428 struct extern_func_runtime *ext_func = &t->extern_funcs[ext_func_id];
2429 rte_swx_extern_func_t func = ext_func->func;
2431 TRACE("[Thread %2u] extern func %u\n",
2435 /* Extern function execute. */
2436 uint32_t done = func(ext_func->mailbox);
2439 thread_ip_inc_cond(t, done);
2440 thread_yield_cond(p, done ^ 1);
2447 instr_mov_translate(struct rte_swx_pipeline *p,
2448 struct action *action,
2451 struct instruction *instr,
2452 struct instruction_data *data __rte_unused)
2454 char *dst = tokens[1], *src = tokens[2];
2455 struct field *fdst, *fsrc;
2457 uint32_t dst_struct_id = 0, src_struct_id = 0;
2459 CHECK(n_tokens == 3, EINVAL);
2461 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2462 CHECK(fdst, EINVAL);
2463 CHECK(!fdst->var_size, EINVAL);
2465 /* MOV, MOV_MH, MOV_HM or MOV_HH. */
2466 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2468 CHECK(!fsrc->var_size, EINVAL);
2470 instr->type = INSTR_MOV;
2471 if (dst[0] != 'h' && src[0] == 'h')
2472 instr->type = INSTR_MOV_MH;
2473 if (dst[0] == 'h' && src[0] != 'h')
2474 instr->type = INSTR_MOV_HM;
2475 if (dst[0] == 'h' && src[0] == 'h')
2476 instr->type = INSTR_MOV_HH;
2478 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
2479 instr->mov.dst.n_bits = fdst->n_bits;
2480 instr->mov.dst.offset = fdst->offset / 8;
2481 instr->mov.src.struct_id = (uint8_t)src_struct_id;
2482 instr->mov.src.n_bits = fsrc->n_bits;
2483 instr->mov.src.offset = fsrc->offset / 8;
2488 src_val = strtoull(src, &src, 0);
2489 CHECK(!src[0], EINVAL);
2492 src_val = hton64(src_val) >> (64 - fdst->n_bits);
2494 instr->type = INSTR_MOV_I;
2495 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
2496 instr->mov.dst.n_bits = fdst->n_bits;
2497 instr->mov.dst.offset = fdst->offset / 8;
2498 instr->mov.src_val = src_val;
2503 instr_mov_exec(struct rte_swx_pipeline *p)
2505 struct thread *t = &p->threads[p->thread_id];
2506 struct instruction *ip = t->ip;
2508 TRACE("[Thread %2u] mov\n",
2518 instr_mov_mh_exec(struct rte_swx_pipeline *p)
2520 struct thread *t = &p->threads[p->thread_id];
2521 struct instruction *ip = t->ip;
2523 TRACE("[Thread %2u] mov (mh)\n",
2533 instr_mov_hm_exec(struct rte_swx_pipeline *p)
2535 struct thread *t = &p->threads[p->thread_id];
2536 struct instruction *ip = t->ip;
2538 TRACE("[Thread %2u] mov (hm)\n",
2548 instr_mov_hh_exec(struct rte_swx_pipeline *p)
2550 struct thread *t = &p->threads[p->thread_id];
2551 struct instruction *ip = t->ip;
2553 TRACE("[Thread %2u] mov (hh)\n",
2563 instr_mov_i_exec(struct rte_swx_pipeline *p)
2565 struct thread *t = &p->threads[p->thread_id];
2566 struct instruction *ip = t->ip;
2568 TRACE("[Thread %2u] mov m.f %" PRIx64 "\n",
2582 __instr_dma_ht_exec(struct rte_swx_pipeline *p, uint32_t n_dma);
2585 __instr_dma_ht_exec(struct rte_swx_pipeline *p, uint32_t n_dma)
2587 struct thread *t = &p->threads[p->thread_id];
2588 struct instruction *ip = t->ip;
2589 uint8_t *action_data = t->structs[0];
2590 uint64_t valid_headers = t->valid_headers;
2593 for (i = 0; i < n_dma; i++) {
2594 uint32_t header_id = ip->dma.dst.header_id[i];
2595 uint32_t struct_id = ip->dma.dst.struct_id[i];
2596 uint32_t offset = ip->dma.src.offset[i];
2597 uint32_t n_bytes = ip->dma.n_bytes[i];
2599 struct header_runtime *h = &t->headers[header_id];
2600 uint8_t *h_ptr0 = h->ptr0;
2601 uint8_t *h_ptr = t->structs[struct_id];
2603 void *dst = MASK64_BIT_GET(valid_headers, header_id) ?
2605 void *src = &action_data[offset];
2607 TRACE("[Thread %2u] dma h.s t.f\n", p->thread_id);
2610 memcpy(dst, src, n_bytes);
2611 t->structs[struct_id] = dst;
2612 valid_headers = MASK64_BIT_SET(valid_headers, header_id);
2615 t->valid_headers = valid_headers;
2619 instr_dma_ht_exec(struct rte_swx_pipeline *p)
2621 __instr_dma_ht_exec(p, 1);
2628 instr_dma_ht2_exec(struct rte_swx_pipeline *p)
2630 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n",
2633 __instr_dma_ht_exec(p, 2);
2640 instr_dma_ht3_exec(struct rte_swx_pipeline *p)
2642 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n",
2645 __instr_dma_ht_exec(p, 3);
2652 instr_dma_ht4_exec(struct rte_swx_pipeline *p)
2654 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n",
2657 __instr_dma_ht_exec(p, 4);
2664 instr_dma_ht5_exec(struct rte_swx_pipeline *p)
2666 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n",
2669 __instr_dma_ht_exec(p, 5);
2676 instr_dma_ht6_exec(struct rte_swx_pipeline *p)
2678 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n",
2681 __instr_dma_ht_exec(p, 6);
2688 instr_dma_ht7_exec(struct rte_swx_pipeline *p)
2690 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n",
2693 __instr_dma_ht_exec(p, 7);
2700 instr_dma_ht8_exec(struct rte_swx_pipeline *p)
2702 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n",
2705 __instr_dma_ht_exec(p, 8);
2715 instr_alu_add_translate(struct rte_swx_pipeline *p,
2716 struct action *action,
2719 struct instruction *instr,
2720 struct instruction_data *data __rte_unused)
2722 char *dst = tokens[1], *src = tokens[2];
2723 struct field *fdst, *fsrc;
2725 uint32_t dst_struct_id = 0, src_struct_id = 0;
2727 CHECK(n_tokens == 3, EINVAL);
2729 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2730 CHECK(fdst, EINVAL);
2731 CHECK(!fdst->var_size, EINVAL);
2733 /* ADD, ADD_HM, ADD_MH, ADD_HH. */
2734 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2736 CHECK(!fsrc->var_size, EINVAL);
2738 instr->type = INSTR_ALU_ADD;
2739 if (dst[0] == 'h' && src[0] != 'h')
2740 instr->type = INSTR_ALU_ADD_HM;
2741 if (dst[0] != 'h' && src[0] == 'h')
2742 instr->type = INSTR_ALU_ADD_MH;
2743 if (dst[0] == 'h' && src[0] == 'h')
2744 instr->type = INSTR_ALU_ADD_HH;
2746 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2747 instr->alu.dst.n_bits = fdst->n_bits;
2748 instr->alu.dst.offset = fdst->offset / 8;
2749 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2750 instr->alu.src.n_bits = fsrc->n_bits;
2751 instr->alu.src.offset = fsrc->offset / 8;
2755 /* ADD_MI, ADD_HI. */
2756 src_val = strtoull(src, &src, 0);
2757 CHECK(!src[0], EINVAL);
2759 instr->type = INSTR_ALU_ADD_MI;
2761 instr->type = INSTR_ALU_ADD_HI;
2763 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2764 instr->alu.dst.n_bits = fdst->n_bits;
2765 instr->alu.dst.offset = fdst->offset / 8;
2766 instr->alu.src_val = src_val;
2771 instr_alu_sub_translate(struct rte_swx_pipeline *p,
2772 struct action *action,
2775 struct instruction *instr,
2776 struct instruction_data *data __rte_unused)
2778 char *dst = tokens[1], *src = tokens[2];
2779 struct field *fdst, *fsrc;
2781 uint32_t dst_struct_id = 0, src_struct_id = 0;
2783 CHECK(n_tokens == 3, EINVAL);
2785 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2786 CHECK(fdst, EINVAL);
2787 CHECK(!fdst->var_size, EINVAL);
2789 /* SUB, SUB_HM, SUB_MH, SUB_HH. */
2790 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2792 CHECK(!fsrc->var_size, EINVAL);
2794 instr->type = INSTR_ALU_SUB;
2795 if (dst[0] == 'h' && src[0] != 'h')
2796 instr->type = INSTR_ALU_SUB_HM;
2797 if (dst[0] != 'h' && src[0] == 'h')
2798 instr->type = INSTR_ALU_SUB_MH;
2799 if (dst[0] == 'h' && src[0] == 'h')
2800 instr->type = INSTR_ALU_SUB_HH;
2802 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2803 instr->alu.dst.n_bits = fdst->n_bits;
2804 instr->alu.dst.offset = fdst->offset / 8;
2805 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2806 instr->alu.src.n_bits = fsrc->n_bits;
2807 instr->alu.src.offset = fsrc->offset / 8;
2811 /* SUB_MI, SUB_HI. */
2812 src_val = strtoull(src, &src, 0);
2813 CHECK(!src[0], EINVAL);
2815 instr->type = INSTR_ALU_SUB_MI;
2817 instr->type = INSTR_ALU_SUB_HI;
2819 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2820 instr->alu.dst.n_bits = fdst->n_bits;
2821 instr->alu.dst.offset = fdst->offset / 8;
2822 instr->alu.src_val = src_val;
2827 instr_alu_ckadd_translate(struct rte_swx_pipeline *p,
2828 struct action *action __rte_unused,
2831 struct instruction *instr,
2832 struct instruction_data *data __rte_unused)
2834 char *dst = tokens[1], *src = tokens[2];
2835 struct header *hdst, *hsrc;
2836 struct field *fdst, *fsrc;
2838 CHECK(n_tokens == 3, EINVAL);
2840 fdst = header_field_parse(p, dst, &hdst);
2841 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
2842 CHECK(!fdst->var_size, EINVAL);
2845 fsrc = header_field_parse(p, src, &hsrc);
2847 CHECK(!fsrc->var_size, EINVAL);
2849 instr->type = INSTR_ALU_CKADD_FIELD;
2850 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2851 instr->alu.dst.n_bits = fdst->n_bits;
2852 instr->alu.dst.offset = fdst->offset / 8;
2853 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2854 instr->alu.src.n_bits = fsrc->n_bits;
2855 instr->alu.src.offset = fsrc->offset / 8;
2859 /* CKADD_STRUCT, CKADD_STRUCT20. */
2860 hsrc = header_parse(p, src);
2861 CHECK(hsrc, EINVAL);
2862 CHECK(!hsrc->st->var_size, EINVAL);
2864 instr->type = INSTR_ALU_CKADD_STRUCT;
2865 if ((hsrc->st->n_bits / 8) == 20)
2866 instr->type = INSTR_ALU_CKADD_STRUCT20;
2868 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2869 instr->alu.dst.n_bits = fdst->n_bits;
2870 instr->alu.dst.offset = fdst->offset / 8;
2871 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2872 instr->alu.src.n_bits = hsrc->st->n_bits;
2873 instr->alu.src.offset = 0; /* Unused. */
2878 instr_alu_cksub_translate(struct rte_swx_pipeline *p,
2879 struct action *action __rte_unused,
2882 struct instruction *instr,
2883 struct instruction_data *data __rte_unused)
2885 char *dst = tokens[1], *src = tokens[2];
2886 struct header *hdst, *hsrc;
2887 struct field *fdst, *fsrc;
2889 CHECK(n_tokens == 3, EINVAL);
2891 fdst = header_field_parse(p, dst, &hdst);
2892 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
2893 CHECK(!fdst->var_size, EINVAL);
2895 fsrc = header_field_parse(p, src, &hsrc);
2896 CHECK(fsrc, EINVAL);
2897 CHECK(!fsrc->var_size, EINVAL);
2899 instr->type = INSTR_ALU_CKSUB_FIELD;
2900 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2901 instr->alu.dst.n_bits = fdst->n_bits;
2902 instr->alu.dst.offset = fdst->offset / 8;
2903 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2904 instr->alu.src.n_bits = fsrc->n_bits;
2905 instr->alu.src.offset = fsrc->offset / 8;
2910 instr_alu_shl_translate(struct rte_swx_pipeline *p,
2911 struct action *action,
2914 struct instruction *instr,
2915 struct instruction_data *data __rte_unused)
2917 char *dst = tokens[1], *src = tokens[2];
2918 struct field *fdst, *fsrc;
2920 uint32_t dst_struct_id = 0, src_struct_id = 0;
2922 CHECK(n_tokens == 3, EINVAL);
2924 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2925 CHECK(fdst, EINVAL);
2926 CHECK(!fdst->var_size, EINVAL);
2928 /* SHL, SHL_HM, SHL_MH, SHL_HH. */
2929 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2931 CHECK(!fsrc->var_size, EINVAL);
2933 instr->type = INSTR_ALU_SHL;
2934 if (dst[0] == 'h' && src[0] != 'h')
2935 instr->type = INSTR_ALU_SHL_HM;
2936 if (dst[0] != 'h' && src[0] == 'h')
2937 instr->type = INSTR_ALU_SHL_MH;
2938 if (dst[0] == 'h' && src[0] == 'h')
2939 instr->type = INSTR_ALU_SHL_HH;
2941 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2942 instr->alu.dst.n_bits = fdst->n_bits;
2943 instr->alu.dst.offset = fdst->offset / 8;
2944 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2945 instr->alu.src.n_bits = fsrc->n_bits;
2946 instr->alu.src.offset = fsrc->offset / 8;
2950 /* SHL_MI, SHL_HI. */
2951 src_val = strtoull(src, &src, 0);
2952 CHECK(!src[0], EINVAL);
2954 instr->type = INSTR_ALU_SHL_MI;
2956 instr->type = INSTR_ALU_SHL_HI;
2958 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2959 instr->alu.dst.n_bits = fdst->n_bits;
2960 instr->alu.dst.offset = fdst->offset / 8;
2961 instr->alu.src_val = src_val;
2966 instr_alu_shr_translate(struct rte_swx_pipeline *p,
2967 struct action *action,
2970 struct instruction *instr,
2971 struct instruction_data *data __rte_unused)
2973 char *dst = tokens[1], *src = tokens[2];
2974 struct field *fdst, *fsrc;
2976 uint32_t dst_struct_id = 0, src_struct_id = 0;
2978 CHECK(n_tokens == 3, EINVAL);
2980 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2981 CHECK(fdst, EINVAL);
2982 CHECK(!fdst->var_size, EINVAL);
2984 /* SHR, SHR_HM, SHR_MH, SHR_HH. */
2985 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2987 CHECK(!fsrc->var_size, EINVAL);
2989 instr->type = INSTR_ALU_SHR;
2990 if (dst[0] == 'h' && src[0] != 'h')
2991 instr->type = INSTR_ALU_SHR_HM;
2992 if (dst[0] != 'h' && src[0] == 'h')
2993 instr->type = INSTR_ALU_SHR_MH;
2994 if (dst[0] == 'h' && src[0] == 'h')
2995 instr->type = INSTR_ALU_SHR_HH;
2997 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2998 instr->alu.dst.n_bits = fdst->n_bits;
2999 instr->alu.dst.offset = fdst->offset / 8;
3000 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3001 instr->alu.src.n_bits = fsrc->n_bits;
3002 instr->alu.src.offset = fsrc->offset / 8;
3006 /* SHR_MI, SHR_HI. */
3007 src_val = strtoull(src, &src, 0);
3008 CHECK(!src[0], EINVAL);
3010 instr->type = INSTR_ALU_SHR_MI;
3012 instr->type = INSTR_ALU_SHR_HI;
3014 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3015 instr->alu.dst.n_bits = fdst->n_bits;
3016 instr->alu.dst.offset = fdst->offset / 8;
3017 instr->alu.src_val = src_val;
3022 instr_alu_and_translate(struct rte_swx_pipeline *p,
3023 struct action *action,
3026 struct instruction *instr,
3027 struct instruction_data *data __rte_unused)
3029 char *dst = tokens[1], *src = tokens[2];
3030 struct field *fdst, *fsrc;
3032 uint32_t dst_struct_id = 0, src_struct_id = 0;
3034 CHECK(n_tokens == 3, EINVAL);
3036 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3037 CHECK(fdst, EINVAL);
3038 CHECK(!fdst->var_size, EINVAL);
3040 /* AND, AND_MH, AND_HM, AND_HH. */
3041 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3043 CHECK(!fsrc->var_size, EINVAL);
3045 instr->type = INSTR_ALU_AND;
3046 if (dst[0] != 'h' && src[0] == 'h')
3047 instr->type = INSTR_ALU_AND_MH;
3048 if (dst[0] == 'h' && src[0] != 'h')
3049 instr->type = INSTR_ALU_AND_HM;
3050 if (dst[0] == 'h' && src[0] == 'h')
3051 instr->type = INSTR_ALU_AND_HH;
3053 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3054 instr->alu.dst.n_bits = fdst->n_bits;
3055 instr->alu.dst.offset = fdst->offset / 8;
3056 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3057 instr->alu.src.n_bits = fsrc->n_bits;
3058 instr->alu.src.offset = fsrc->offset / 8;
3063 src_val = strtoull(src, &src, 0);
3064 CHECK(!src[0], EINVAL);
3067 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3069 instr->type = INSTR_ALU_AND_I;
3070 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3071 instr->alu.dst.n_bits = fdst->n_bits;
3072 instr->alu.dst.offset = fdst->offset / 8;
3073 instr->alu.src_val = src_val;
3078 instr_alu_or_translate(struct rte_swx_pipeline *p,
3079 struct action *action,
3082 struct instruction *instr,
3083 struct instruction_data *data __rte_unused)
3085 char *dst = tokens[1], *src = tokens[2];
3086 struct field *fdst, *fsrc;
3088 uint32_t dst_struct_id = 0, src_struct_id = 0;
3090 CHECK(n_tokens == 3, EINVAL);
3092 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3093 CHECK(fdst, EINVAL);
3094 CHECK(!fdst->var_size, EINVAL);
3096 /* OR, OR_MH, OR_HM, OR_HH. */
3097 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3099 CHECK(!fsrc->var_size, EINVAL);
3101 instr->type = INSTR_ALU_OR;
3102 if (dst[0] != 'h' && src[0] == 'h')
3103 instr->type = INSTR_ALU_OR_MH;
3104 if (dst[0] == 'h' && src[0] != 'h')
3105 instr->type = INSTR_ALU_OR_HM;
3106 if (dst[0] == 'h' && src[0] == 'h')
3107 instr->type = INSTR_ALU_OR_HH;
3109 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3110 instr->alu.dst.n_bits = fdst->n_bits;
3111 instr->alu.dst.offset = fdst->offset / 8;
3112 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3113 instr->alu.src.n_bits = fsrc->n_bits;
3114 instr->alu.src.offset = fsrc->offset / 8;
3119 src_val = strtoull(src, &src, 0);
3120 CHECK(!src[0], EINVAL);
3123 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3125 instr->type = INSTR_ALU_OR_I;
3126 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3127 instr->alu.dst.n_bits = fdst->n_bits;
3128 instr->alu.dst.offset = fdst->offset / 8;
3129 instr->alu.src_val = src_val;
3134 instr_alu_xor_translate(struct rte_swx_pipeline *p,
3135 struct action *action,
3138 struct instruction *instr,
3139 struct instruction_data *data __rte_unused)
3141 char *dst = tokens[1], *src = tokens[2];
3142 struct field *fdst, *fsrc;
3144 uint32_t dst_struct_id = 0, src_struct_id = 0;
3146 CHECK(n_tokens == 3, EINVAL);
3148 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3149 CHECK(fdst, EINVAL);
3150 CHECK(!fdst->var_size, EINVAL);
3152 /* XOR, XOR_MH, XOR_HM, XOR_HH. */
3153 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3155 CHECK(!fsrc->var_size, EINVAL);
3157 instr->type = INSTR_ALU_XOR;
3158 if (dst[0] != 'h' && src[0] == 'h')
3159 instr->type = INSTR_ALU_XOR_MH;
3160 if (dst[0] == 'h' && src[0] != 'h')
3161 instr->type = INSTR_ALU_XOR_HM;
3162 if (dst[0] == 'h' && src[0] == 'h')
3163 instr->type = INSTR_ALU_XOR_HH;
3165 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3166 instr->alu.dst.n_bits = fdst->n_bits;
3167 instr->alu.dst.offset = fdst->offset / 8;
3168 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3169 instr->alu.src.n_bits = fsrc->n_bits;
3170 instr->alu.src.offset = fsrc->offset / 8;
3175 src_val = strtoull(src, &src, 0);
3176 CHECK(!src[0], EINVAL);
3179 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3181 instr->type = INSTR_ALU_XOR_I;
3182 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3183 instr->alu.dst.n_bits = fdst->n_bits;
3184 instr->alu.dst.offset = fdst->offset / 8;
3185 instr->alu.src_val = src_val;
3190 instr_alu_add_exec(struct rte_swx_pipeline *p)
3192 struct thread *t = &p->threads[p->thread_id];
3193 struct instruction *ip = t->ip;
3195 TRACE("[Thread %2u] add\n", p->thread_id);
3205 instr_alu_add_mh_exec(struct rte_swx_pipeline *p)
3207 struct thread *t = &p->threads[p->thread_id];
3208 struct instruction *ip = t->ip;
3210 TRACE("[Thread %2u] add (mh)\n", p->thread_id);
3220 instr_alu_add_hm_exec(struct rte_swx_pipeline *p)
3222 struct thread *t = &p->threads[p->thread_id];
3223 struct instruction *ip = t->ip;
3225 TRACE("[Thread %2u] add (hm)\n", p->thread_id);
3235 instr_alu_add_hh_exec(struct rte_swx_pipeline *p)
3237 struct thread *t = &p->threads[p->thread_id];
3238 struct instruction *ip = t->ip;
3240 TRACE("[Thread %2u] add (hh)\n", p->thread_id);
3250 instr_alu_add_mi_exec(struct rte_swx_pipeline *p)
3252 struct thread *t = &p->threads[p->thread_id];
3253 struct instruction *ip = t->ip;
3255 TRACE("[Thread %2u] add (mi)\n", p->thread_id);
3265 instr_alu_add_hi_exec(struct rte_swx_pipeline *p)
3267 struct thread *t = &p->threads[p->thread_id];
3268 struct instruction *ip = t->ip;
3270 TRACE("[Thread %2u] add (hi)\n", p->thread_id);
3280 instr_alu_sub_exec(struct rte_swx_pipeline *p)
3282 struct thread *t = &p->threads[p->thread_id];
3283 struct instruction *ip = t->ip;
3285 TRACE("[Thread %2u] sub\n", p->thread_id);
3295 instr_alu_sub_mh_exec(struct rte_swx_pipeline *p)
3297 struct thread *t = &p->threads[p->thread_id];
3298 struct instruction *ip = t->ip;
3300 TRACE("[Thread %2u] sub (mh)\n", p->thread_id);
3310 instr_alu_sub_hm_exec(struct rte_swx_pipeline *p)
3312 struct thread *t = &p->threads[p->thread_id];
3313 struct instruction *ip = t->ip;
3315 TRACE("[Thread %2u] sub (hm)\n", p->thread_id);
3325 instr_alu_sub_hh_exec(struct rte_swx_pipeline *p)
3327 struct thread *t = &p->threads[p->thread_id];
3328 struct instruction *ip = t->ip;
3330 TRACE("[Thread %2u] sub (hh)\n", p->thread_id);
3340 instr_alu_sub_mi_exec(struct rte_swx_pipeline *p)
3342 struct thread *t = &p->threads[p->thread_id];
3343 struct instruction *ip = t->ip;
3345 TRACE("[Thread %2u] sub (mi)\n", p->thread_id);
3355 instr_alu_sub_hi_exec(struct rte_swx_pipeline *p)
3357 struct thread *t = &p->threads[p->thread_id];
3358 struct instruction *ip = t->ip;
3360 TRACE("[Thread %2u] sub (hi)\n", p->thread_id);
3370 instr_alu_shl_exec(struct rte_swx_pipeline *p)
3372 struct thread *t = &p->threads[p->thread_id];
3373 struct instruction *ip = t->ip;
3375 TRACE("[Thread %2u] shl\n", p->thread_id);
3385 instr_alu_shl_mh_exec(struct rte_swx_pipeline *p)
3387 struct thread *t = &p->threads[p->thread_id];
3388 struct instruction *ip = t->ip;
3390 TRACE("[Thread %2u] shl (mh)\n", p->thread_id);
3400 instr_alu_shl_hm_exec(struct rte_swx_pipeline *p)
3402 struct thread *t = &p->threads[p->thread_id];
3403 struct instruction *ip = t->ip;
3405 TRACE("[Thread %2u] shl (hm)\n", p->thread_id);
3415 instr_alu_shl_hh_exec(struct rte_swx_pipeline *p)
3417 struct thread *t = &p->threads[p->thread_id];
3418 struct instruction *ip = t->ip;
3420 TRACE("[Thread %2u] shl (hh)\n", p->thread_id);
3430 instr_alu_shl_mi_exec(struct rte_swx_pipeline *p)
3432 struct thread *t = &p->threads[p->thread_id];
3433 struct instruction *ip = t->ip;
3435 TRACE("[Thread %2u] shl (mi)\n", p->thread_id);
3445 instr_alu_shl_hi_exec(struct rte_swx_pipeline *p)
3447 struct thread *t = &p->threads[p->thread_id];
3448 struct instruction *ip = t->ip;
3450 TRACE("[Thread %2u] shl (hi)\n", p->thread_id);
3460 instr_alu_shr_exec(struct rte_swx_pipeline *p)
3462 struct thread *t = &p->threads[p->thread_id];
3463 struct instruction *ip = t->ip;
3465 TRACE("[Thread %2u] shr\n", p->thread_id);
3475 instr_alu_shr_mh_exec(struct rte_swx_pipeline *p)
3477 struct thread *t = &p->threads[p->thread_id];
3478 struct instruction *ip = t->ip;
3480 TRACE("[Thread %2u] shr (mh)\n", p->thread_id);
3490 instr_alu_shr_hm_exec(struct rte_swx_pipeline *p)
3492 struct thread *t = &p->threads[p->thread_id];
3493 struct instruction *ip = t->ip;
3495 TRACE("[Thread %2u] shr (hm)\n", p->thread_id);
3505 instr_alu_shr_hh_exec(struct rte_swx_pipeline *p)
3507 struct thread *t = &p->threads[p->thread_id];
3508 struct instruction *ip = t->ip;
3510 TRACE("[Thread %2u] shr (hh)\n", p->thread_id);
3520 instr_alu_shr_mi_exec(struct rte_swx_pipeline *p)
3522 struct thread *t = &p->threads[p->thread_id];
3523 struct instruction *ip = t->ip;
3525 TRACE("[Thread %2u] shr (mi)\n", p->thread_id);
3535 instr_alu_shr_hi_exec(struct rte_swx_pipeline *p)
3537 struct thread *t = &p->threads[p->thread_id];
3538 struct instruction *ip = t->ip;
3540 TRACE("[Thread %2u] shr (hi)\n", p->thread_id);
3550 instr_alu_and_exec(struct rte_swx_pipeline *p)
3552 struct thread *t = &p->threads[p->thread_id];
3553 struct instruction *ip = t->ip;
3555 TRACE("[Thread %2u] and\n", p->thread_id);
3565 instr_alu_and_mh_exec(struct rte_swx_pipeline *p)
3567 struct thread *t = &p->threads[p->thread_id];
3568 struct instruction *ip = t->ip;
3570 TRACE("[Thread %2u] and (mh)\n", p->thread_id);
3580 instr_alu_and_hm_exec(struct rte_swx_pipeline *p)
3582 struct thread *t = &p->threads[p->thread_id];
3583 struct instruction *ip = t->ip;
3585 TRACE("[Thread %2u] and (hm)\n", p->thread_id);
3588 ALU_HM_FAST(t, ip, &);
3595 instr_alu_and_hh_exec(struct rte_swx_pipeline *p)
3597 struct thread *t = &p->threads[p->thread_id];
3598 struct instruction *ip = t->ip;
3600 TRACE("[Thread %2u] and (hh)\n", p->thread_id);
3603 ALU_HH_FAST(t, ip, &);
3610 instr_alu_and_i_exec(struct rte_swx_pipeline *p)
3612 struct thread *t = &p->threads[p->thread_id];
3613 struct instruction *ip = t->ip;
3615 TRACE("[Thread %2u] and (i)\n", p->thread_id);
3625 instr_alu_or_exec(struct rte_swx_pipeline *p)
3627 struct thread *t = &p->threads[p->thread_id];
3628 struct instruction *ip = t->ip;
3630 TRACE("[Thread %2u] or\n", p->thread_id);
3640 instr_alu_or_mh_exec(struct rte_swx_pipeline *p)
3642 struct thread *t = &p->threads[p->thread_id];
3643 struct instruction *ip = t->ip;
3645 TRACE("[Thread %2u] or (mh)\n", p->thread_id);
3655 instr_alu_or_hm_exec(struct rte_swx_pipeline *p)
3657 struct thread *t = &p->threads[p->thread_id];
3658 struct instruction *ip = t->ip;
3660 TRACE("[Thread %2u] or (hm)\n", p->thread_id);
3663 ALU_HM_FAST(t, ip, |);
3670 instr_alu_or_hh_exec(struct rte_swx_pipeline *p)
3672 struct thread *t = &p->threads[p->thread_id];
3673 struct instruction *ip = t->ip;
3675 TRACE("[Thread %2u] or (hh)\n", p->thread_id);
3678 ALU_HH_FAST(t, ip, |);
3685 instr_alu_or_i_exec(struct rte_swx_pipeline *p)
3687 struct thread *t = &p->threads[p->thread_id];
3688 struct instruction *ip = t->ip;
3690 TRACE("[Thread %2u] or (i)\n", p->thread_id);
3700 instr_alu_xor_exec(struct rte_swx_pipeline *p)
3702 struct thread *t = &p->threads[p->thread_id];
3703 struct instruction *ip = t->ip;
3705 TRACE("[Thread %2u] xor\n", p->thread_id);
3715 instr_alu_xor_mh_exec(struct rte_swx_pipeline *p)
3717 struct thread *t = &p->threads[p->thread_id];
3718 struct instruction *ip = t->ip;
3720 TRACE("[Thread %2u] xor (mh)\n", p->thread_id);
3730 instr_alu_xor_hm_exec(struct rte_swx_pipeline *p)
3732 struct thread *t = &p->threads[p->thread_id];
3733 struct instruction *ip = t->ip;
3735 TRACE("[Thread %2u] xor (hm)\n", p->thread_id);
3738 ALU_HM_FAST(t, ip, ^);
3745 instr_alu_xor_hh_exec(struct rte_swx_pipeline *p)
3747 struct thread *t = &p->threads[p->thread_id];
3748 struct instruction *ip = t->ip;
3750 TRACE("[Thread %2u] xor (hh)\n", p->thread_id);
3753 ALU_HH_FAST(t, ip, ^);
3760 instr_alu_xor_i_exec(struct rte_swx_pipeline *p)
3762 struct thread *t = &p->threads[p->thread_id];
3763 struct instruction *ip = t->ip;
3765 TRACE("[Thread %2u] xor (i)\n", p->thread_id);
3775 instr_alu_ckadd_field_exec(struct rte_swx_pipeline *p)
3777 struct thread *t = &p->threads[p->thread_id];
3778 struct instruction *ip = t->ip;
3779 uint8_t *dst_struct, *src_struct;
3780 uint16_t *dst16_ptr, dst;
3781 uint64_t *src64_ptr, src64, src64_mask, src;
3784 TRACE("[Thread %2u] ckadd (field)\n", p->thread_id);
3787 dst_struct = t->structs[ip->alu.dst.struct_id];
3788 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
3791 src_struct = t->structs[ip->alu.src.struct_id];
3792 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
3794 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
3795 src = src64 & src64_mask;
3800 /* The first input (r) is a 16-bit number. The second and the third
3801 * inputs are 32-bit numbers. In the worst case scenario, the sum of the
3802 * three numbers (output r) is a 34-bit number.
3804 r += (src >> 32) + (src & 0xFFFFFFFF);
3806 /* The first input is a 16-bit number. The second input is an 18-bit
3807 * number. In the worst case scenario, the sum of the two numbers is a
3810 r = (r & 0xFFFF) + (r >> 16);
3812 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
3813 * a 3-bit number (0 .. 7). Their sum is a 17-bit number (0 .. 0x10006).
3815 r = (r & 0xFFFF) + (r >> 16);
3817 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
3818 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
3819 * 0x10006), the output r is (0 .. 7). So no carry bit can be generated,
3820 * therefore the output r is always a 16-bit number.
3822 r = (r & 0xFFFF) + (r >> 16);
3827 *dst16_ptr = (uint16_t)r;
3834 instr_alu_cksub_field_exec(struct rte_swx_pipeline *p)
3836 struct thread *t = &p->threads[p->thread_id];
3837 struct instruction *ip = t->ip;
3838 uint8_t *dst_struct, *src_struct;
3839 uint16_t *dst16_ptr, dst;
3840 uint64_t *src64_ptr, src64, src64_mask, src;
3843 TRACE("[Thread %2u] cksub (field)\n", p->thread_id);
3846 dst_struct = t->structs[ip->alu.dst.struct_id];
3847 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
3850 src_struct = t->structs[ip->alu.src.struct_id];
3851 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
3853 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
3854 src = src64 & src64_mask;
3859 /* Subtraction in 1's complement arithmetic (i.e. a '- b) is the same as
3860 * the following sequence of operations in 2's complement arithmetic:
3861 * a '- b = (a - b) % 0xFFFF.
3863 * In order to prevent an underflow for the below subtraction, in which
3864 * a 33-bit number (the subtrahend) is taken out of a 16-bit number (the
3865 * minuend), we first add a multiple of the 0xFFFF modulus to the
3866 * minuend. The number we add to the minuend needs to be a 34-bit number
3867 * or higher, so for readability reasons we picked the 36-bit multiple.
3868 * We are effectively turning the 16-bit minuend into a 36-bit number:
3869 * (a - b) % 0xFFFF = (a + 0xFFFF00000 - b) % 0xFFFF.
3871 r += 0xFFFF00000ULL; /* The output r is a 36-bit number. */
3873 /* A 33-bit number is subtracted from a 36-bit number (the input r). The
3874 * result (the output r) is a 36-bit number.
3876 r -= (src >> 32) + (src & 0xFFFFFFFF);
3878 /* The first input is a 16-bit number. The second input is a 20-bit
3879 * number. Their sum is a 21-bit number.
3881 r = (r & 0xFFFF) + (r >> 16);
3883 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
3884 * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1001E).
3886 r = (r & 0xFFFF) + (r >> 16);
3888 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
3889 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
3890 * 0x1001E), the output r is (0 .. 31). So no carry bit can be
3891 * generated, therefore the output r is always a 16-bit number.
3893 r = (r & 0xFFFF) + (r >> 16);
3898 *dst16_ptr = (uint16_t)r;
3905 instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline *p)
3907 struct thread *t = &p->threads[p->thread_id];
3908 struct instruction *ip = t->ip;
3909 uint8_t *dst_struct, *src_struct;
3910 uint16_t *dst16_ptr;
3911 uint32_t *src32_ptr;
3914 TRACE("[Thread %2u] ckadd (struct of 20 bytes)\n", p->thread_id);
3917 dst_struct = t->structs[ip->alu.dst.struct_id];
3918 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
3920 src_struct = t->structs[ip->alu.src.struct_id];
3921 src32_ptr = (uint32_t *)&src_struct[0];
3923 r0 = src32_ptr[0]; /* r0 is a 32-bit number. */
3924 r1 = src32_ptr[1]; /* r1 is a 32-bit number. */
3925 r0 += src32_ptr[2]; /* The output r0 is a 33-bit number. */
3926 r1 += src32_ptr[3]; /* The output r1 is a 33-bit number. */
3927 r0 += r1 + src32_ptr[4]; /* The output r0 is a 35-bit number. */
3929 /* The first input is a 16-bit number. The second input is a 19-bit
3930 * number. Their sum is a 20-bit number.
3932 r0 = (r0 & 0xFFFF) + (r0 >> 16);
3934 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
3935 * a 4-bit number (0 .. 15). The sum is a 17-bit number (0 .. 0x1000E).
3937 r0 = (r0 & 0xFFFF) + (r0 >> 16);
3939 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
3940 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
3941 * 0x1000E), the output r is (0 .. 15). So no carry bit can be
3942 * generated, therefore the output r is always a 16-bit number.
3944 r0 = (r0 & 0xFFFF) + (r0 >> 16);
3947 r0 = r0 ? r0 : 0xFFFF;
3949 *dst16_ptr = (uint16_t)r0;
3956 instr_alu_ckadd_struct_exec(struct rte_swx_pipeline *p)
3958 struct thread *t = &p->threads[p->thread_id];
3959 struct instruction *ip = t->ip;
3960 uint8_t *dst_struct, *src_struct;
3961 uint16_t *dst16_ptr;
3962 uint32_t *src32_ptr;
3966 TRACE("[Thread %2u] ckadd (struct)\n", p->thread_id);
3969 dst_struct = t->structs[ip->alu.dst.struct_id];
3970 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
3972 src_struct = t->structs[ip->alu.src.struct_id];
3973 src32_ptr = (uint32_t *)&src_struct[0];
3975 /* The max number of 32-bit words in a 256-byte header is 8 = 2^3.
3976 * Therefore, in the worst case scenario, a 35-bit number is added to a
3977 * 16-bit number (the input r), so the output r is 36-bit number.
3979 for (i = 0; i < ip->alu.src.n_bits / 32; i++, src32_ptr++)
3982 /* The first input is a 16-bit number. The second input is a 20-bit
3983 * number. Their sum is a 21-bit number.
3985 r = (r & 0xFFFF) + (r >> 16);
3987 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
3988 * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1000E).
3990 r = (r & 0xFFFF) + (r >> 16);
3992 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
3993 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
3994 * 0x1001E), the output r is (0 .. 31). So no carry bit can be
3995 * generated, therefore the output r is always a 16-bit number.
3997 r = (r & 0xFFFF) + (r >> 16);
4002 *dst16_ptr = (uint16_t)r;
4011 static struct regarray *
4012 regarray_find(struct rte_swx_pipeline *p, const char *name);
4015 instr_regprefetch_translate(struct rte_swx_pipeline *p,
4016 struct action *action,
4019 struct instruction *instr,
4020 struct instruction_data *data __rte_unused)
4022 char *regarray = tokens[1], *idx = tokens[2];
4025 uint32_t idx_struct_id, idx_val;
4027 CHECK(n_tokens == 3, EINVAL);
4029 r = regarray_find(p, regarray);
4032 /* REGPREFETCH_RH, REGPREFETCH_RM. */
4033 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4035 CHECK(!fidx->var_size, EINVAL);
4037 instr->type = INSTR_REGPREFETCH_RM;
4039 instr->type = INSTR_REGPREFETCH_RH;
4041 instr->regarray.regarray_id = r->id;
4042 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4043 instr->regarray.idx.n_bits = fidx->n_bits;
4044 instr->regarray.idx.offset = fidx->offset / 8;
4045 instr->regarray.dstsrc_val = 0; /* Unused. */
4049 /* REGPREFETCH_RI. */
4050 idx_val = strtoul(idx, &idx, 0);
4051 CHECK(!idx[0], EINVAL);
4053 instr->type = INSTR_REGPREFETCH_RI;
4054 instr->regarray.regarray_id = r->id;
4055 instr->regarray.idx_val = idx_val;
4056 instr->regarray.dstsrc_val = 0; /* Unused. */
4061 instr_regrd_translate(struct rte_swx_pipeline *p,
4062 struct action *action,
4065 struct instruction *instr,
4066 struct instruction_data *data __rte_unused)
4068 char *dst = tokens[1], *regarray = tokens[2], *idx = tokens[3];
4070 struct field *fdst, *fidx;
4071 uint32_t dst_struct_id, idx_struct_id, idx_val;
4073 CHECK(n_tokens == 4, EINVAL);
4075 r = regarray_find(p, regarray);
4078 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4079 CHECK(fdst, EINVAL);
4080 CHECK(!fdst->var_size, EINVAL);
4082 /* REGRD_HRH, REGRD_HRM, REGRD_MRH, REGRD_MRM. */
4083 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4085 CHECK(!fidx->var_size, EINVAL);
4087 instr->type = INSTR_REGRD_MRM;
4088 if (dst[0] == 'h' && idx[0] != 'h')
4089 instr->type = INSTR_REGRD_HRM;
4090 if (dst[0] != 'h' && idx[0] == 'h')
4091 instr->type = INSTR_REGRD_MRH;
4092 if (dst[0] == 'h' && idx[0] == 'h')
4093 instr->type = INSTR_REGRD_HRH;
4095 instr->regarray.regarray_id = r->id;
4096 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4097 instr->regarray.idx.n_bits = fidx->n_bits;
4098 instr->regarray.idx.offset = fidx->offset / 8;
4099 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
4100 instr->regarray.dstsrc.n_bits = fdst->n_bits;
4101 instr->regarray.dstsrc.offset = fdst->offset / 8;
4105 /* REGRD_MRI, REGRD_HRI. */
4106 idx_val = strtoul(idx, &idx, 0);
4107 CHECK(!idx[0], EINVAL);
4109 instr->type = INSTR_REGRD_MRI;
4111 instr->type = INSTR_REGRD_HRI;
4113 instr->regarray.regarray_id = r->id;
4114 instr->regarray.idx_val = idx_val;
4115 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
4116 instr->regarray.dstsrc.n_bits = fdst->n_bits;
4117 instr->regarray.dstsrc.offset = fdst->offset / 8;
4122 instr_regwr_translate(struct rte_swx_pipeline *p,
4123 struct action *action,
4126 struct instruction *instr,
4127 struct instruction_data *data __rte_unused)
4129 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
4131 struct field *fidx, *fsrc;
4133 uint32_t idx_struct_id, idx_val, src_struct_id;
4135 CHECK(n_tokens == 4, EINVAL);
4137 r = regarray_find(p, regarray);
4140 /* REGWR_RHH, REGWR_RHM, REGWR_RMH, REGWR_RMM. */
4141 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4142 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4144 CHECK(!fidx->var_size, EINVAL);
4145 CHECK(!fsrc->var_size, EINVAL);
4147 instr->type = INSTR_REGWR_RMM;
4148 if (idx[0] == 'h' && src[0] != 'h')
4149 instr->type = INSTR_REGWR_RHM;
4150 if (idx[0] != 'h' && src[0] == 'h')
4151 instr->type = INSTR_REGWR_RMH;
4152 if (idx[0] == 'h' && src[0] == 'h')
4153 instr->type = INSTR_REGWR_RHH;
4155 instr->regarray.regarray_id = r->id;
4156 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4157 instr->regarray.idx.n_bits = fidx->n_bits;
4158 instr->regarray.idx.offset = fidx->offset / 8;
4159 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4160 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4161 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4165 /* REGWR_RHI, REGWR_RMI. */
4166 if (fidx && !fsrc) {
4167 CHECK(!fidx->var_size, EINVAL);
4169 src_val = strtoull(src, &src, 0);
4170 CHECK(!src[0], EINVAL);
4172 instr->type = INSTR_REGWR_RMI;
4174 instr->type = INSTR_REGWR_RHI;
4176 instr->regarray.regarray_id = r->id;
4177 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4178 instr->regarray.idx.n_bits = fidx->n_bits;
4179 instr->regarray.idx.offset = fidx->offset / 8;
4180 instr->regarray.dstsrc_val = src_val;
4184 /* REGWR_RIH, REGWR_RIM. */
4185 if (!fidx && fsrc) {
4186 idx_val = strtoul(idx, &idx, 0);
4187 CHECK(!idx[0], EINVAL);
4189 CHECK(!fsrc->var_size, EINVAL);
4191 instr->type = INSTR_REGWR_RIM;
4193 instr->type = INSTR_REGWR_RIH;
4195 instr->regarray.regarray_id = r->id;
4196 instr->regarray.idx_val = idx_val;
4197 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4198 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4199 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4204 src_val = strtoull(src, &src, 0);
4205 CHECK(!src[0], EINVAL);
4207 idx_val = strtoul(idx, &idx, 0);
4208 CHECK(!idx[0], EINVAL);
4210 instr->type = INSTR_REGWR_RII;
4211 instr->regarray.idx_val = idx_val;
4212 instr->regarray.dstsrc_val = src_val;
4218 instr_regadd_translate(struct rte_swx_pipeline *p,
4219 struct action *action,
4222 struct instruction *instr,
4223 struct instruction_data *data __rte_unused)
4225 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
4227 struct field *fidx, *fsrc;
4229 uint32_t idx_struct_id, idx_val, src_struct_id;
4231 CHECK(n_tokens == 4, EINVAL);
4233 r = regarray_find(p, regarray);
4236 /* REGADD_RHH, REGADD_RHM, REGADD_RMH, REGADD_RMM. */
4237 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4238 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4240 CHECK(!fidx->var_size, EINVAL);
4241 CHECK(!fsrc->var_size, EINVAL);
4243 instr->type = INSTR_REGADD_RMM;
4244 if (idx[0] == 'h' && src[0] != 'h')
4245 instr->type = INSTR_REGADD_RHM;
4246 if (idx[0] != 'h' && src[0] == 'h')
4247 instr->type = INSTR_REGADD_RMH;
4248 if (idx[0] == 'h' && src[0] == 'h')
4249 instr->type = INSTR_REGADD_RHH;
4251 instr->regarray.regarray_id = r->id;
4252 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4253 instr->regarray.idx.n_bits = fidx->n_bits;
4254 instr->regarray.idx.offset = fidx->offset / 8;
4255 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4256 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4257 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4261 /* REGADD_RHI, REGADD_RMI. */
4262 if (fidx && !fsrc) {
4263 CHECK(!fidx->var_size, EINVAL);
4265 src_val = strtoull(src, &src, 0);
4266 CHECK(!src[0], EINVAL);
4268 instr->type = INSTR_REGADD_RMI;
4270 instr->type = INSTR_REGADD_RHI;
4272 instr->regarray.regarray_id = r->id;
4273 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4274 instr->regarray.idx.n_bits = fidx->n_bits;
4275 instr->regarray.idx.offset = fidx->offset / 8;
4276 instr->regarray.dstsrc_val = src_val;
4280 /* REGADD_RIH, REGADD_RIM. */
4281 if (!fidx && fsrc) {
4282 idx_val = strtoul(idx, &idx, 0);
4283 CHECK(!idx[0], EINVAL);
4285 CHECK(!fsrc->var_size, EINVAL);
4287 instr->type = INSTR_REGADD_RIM;
4289 instr->type = INSTR_REGADD_RIH;
4291 instr->regarray.regarray_id = r->id;
4292 instr->regarray.idx_val = idx_val;
4293 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4294 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4295 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4300 src_val = strtoull(src, &src, 0);
4301 CHECK(!src[0], EINVAL);
4303 idx_val = strtoul(idx, &idx, 0);
4304 CHECK(!idx[0], EINVAL);
4306 instr->type = INSTR_REGADD_RII;
4307 instr->regarray.idx_val = idx_val;
4308 instr->regarray.dstsrc_val = src_val;
4312 static inline uint64_t *
4313 instr_regarray_regarray(struct rte_swx_pipeline *p, struct instruction *ip)
4315 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4319 static inline uint64_t
4320 instr_regarray_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
4322 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4324 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
4325 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
4326 uint64_t idx64 = *idx64_ptr;
4327 uint64_t idx64_mask = UINT64_MAX >> (64 - ip->regarray.idx.n_bits);
4328 uint64_t idx = idx64 & idx64_mask & r->size_mask;
4333 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4335 static inline uint64_t
4336 instr_regarray_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
4338 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4340 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
4341 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
4342 uint64_t idx64 = *idx64_ptr;
4343 uint64_t idx = (ntoh64(idx64) >> (64 - ip->regarray.idx.n_bits)) & r->size_mask;
4350 #define instr_regarray_idx_nbo instr_regarray_idx_hbo
4354 static inline uint64_t
4355 instr_regarray_idx_imm(struct rte_swx_pipeline *p, struct instruction *ip)
4357 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4359 uint64_t idx = ip->regarray.idx_val & r->size_mask;
4364 static inline uint64_t
4365 instr_regarray_src_hbo(struct thread *t, struct instruction *ip)
4367 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
4368 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
4369 uint64_t src64 = *src64_ptr;
4370 uint64_t src64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
4371 uint64_t src = src64 & src64_mask;
4376 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4378 static inline uint64_t
4379 instr_regarray_src_nbo(struct thread *t, struct instruction *ip)
4381 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
4382 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
4383 uint64_t src64 = *src64_ptr;
4384 uint64_t src = ntoh64(src64) >> (64 - ip->regarray.dstsrc.n_bits);
4391 #define instr_regarray_src_nbo instr_regarray_src_hbo
4396 instr_regarray_dst_hbo_src_hbo_set(struct thread *t, struct instruction *ip, uint64_t src)
4398 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
4399 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
4400 uint64_t dst64 = *dst64_ptr;
4401 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
4403 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
4407 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4410 instr_regarray_dst_nbo_src_hbo_set(struct thread *t, struct instruction *ip, uint64_t src)
4412 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
4413 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
4414 uint64_t dst64 = *dst64_ptr;
4415 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
4417 src = hton64(src) >> (64 - ip->regarray.dstsrc.n_bits);
4418 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
4423 #define instr_regarray_dst_nbo_src_hbo_set instr_regarray_dst_hbo_src_hbo_set
4428 instr_regprefetch_rh_exec(struct rte_swx_pipeline *p)
4430 struct thread *t = &p->threads[p->thread_id];
4431 struct instruction *ip = t->ip;
4432 uint64_t *regarray, idx;
4434 TRACE("[Thread %2u] regprefetch (r[h])\n", p->thread_id);
4437 regarray = instr_regarray_regarray(p, ip);
4438 idx = instr_regarray_idx_nbo(p, t, ip);
4439 rte_prefetch0(®array[idx]);
4446 instr_regprefetch_rm_exec(struct rte_swx_pipeline *p)
4448 struct thread *t = &p->threads[p->thread_id];
4449 struct instruction *ip = t->ip;
4450 uint64_t *regarray, idx;
4452 TRACE("[Thread %2u] regprefetch (r[m])\n", p->thread_id);
4455 regarray = instr_regarray_regarray(p, ip);
4456 idx = instr_regarray_idx_hbo(p, t, ip);
4457 rte_prefetch0(®array[idx]);
4464 instr_regprefetch_ri_exec(struct rte_swx_pipeline *p)
4466 struct thread *t = &p->threads[p->thread_id];
4467 struct instruction *ip = t->ip;
4468 uint64_t *regarray, idx;
4470 TRACE("[Thread %2u] regprefetch (r[i])\n", p->thread_id);
4473 regarray = instr_regarray_regarray(p, ip);
4474 idx = instr_regarray_idx_imm(p, ip);
4475 rte_prefetch0(®array[idx]);
4482 instr_regrd_hrh_exec(struct rte_swx_pipeline *p)
4484 struct thread *t = &p->threads[p->thread_id];
4485 struct instruction *ip = t->ip;
4486 uint64_t *regarray, idx;
4488 TRACE("[Thread %2u] regrd (h = r[h])\n", p->thread_id);
4491 regarray = instr_regarray_regarray(p, ip);
4492 idx = instr_regarray_idx_nbo(p, t, ip);
4493 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
4500 instr_regrd_hrm_exec(struct rte_swx_pipeline *p)
4502 struct thread *t = &p->threads[p->thread_id];
4503 struct instruction *ip = t->ip;
4504 uint64_t *regarray, idx;
4506 TRACE("[Thread %2u] regrd (h = r[m])\n", p->thread_id);
4509 regarray = instr_regarray_regarray(p, ip);
4510 idx = instr_regarray_idx_hbo(p, t, ip);
4511 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
4518 instr_regrd_mrh_exec(struct rte_swx_pipeline *p)
4520 struct thread *t = &p->threads[p->thread_id];
4521 struct instruction *ip = t->ip;
4522 uint64_t *regarray, idx;
4524 TRACE("[Thread %2u] regrd (m = r[h])\n", p->thread_id);
4527 regarray = instr_regarray_regarray(p, ip);
4528 idx = instr_regarray_idx_nbo(p, t, ip);
4529 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
4536 instr_regrd_mrm_exec(struct rte_swx_pipeline *p)
4538 struct thread *t = &p->threads[p->thread_id];
4539 struct instruction *ip = t->ip;
4540 uint64_t *regarray, idx;
4543 regarray = instr_regarray_regarray(p, ip);
4544 idx = instr_regarray_idx_hbo(p, t, ip);
4545 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
4552 instr_regrd_hri_exec(struct rte_swx_pipeline *p)
4554 struct thread *t = &p->threads[p->thread_id];
4555 struct instruction *ip = t->ip;
4556 uint64_t *regarray, idx;
4558 TRACE("[Thread %2u] regrd (h = r[i])\n", p->thread_id);
4561 regarray = instr_regarray_regarray(p, ip);
4562 idx = instr_regarray_idx_imm(p, ip);
4563 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
4570 instr_regrd_mri_exec(struct rte_swx_pipeline *p)
4572 struct thread *t = &p->threads[p->thread_id];
4573 struct instruction *ip = t->ip;
4574 uint64_t *regarray, idx;
4576 TRACE("[Thread %2u] regrd (m = r[i])\n", p->thread_id);
4579 regarray = instr_regarray_regarray(p, ip);
4580 idx = instr_regarray_idx_imm(p, ip);
4581 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
4588 instr_regwr_rhh_exec(struct rte_swx_pipeline *p)
4590 struct thread *t = &p->threads[p->thread_id];
4591 struct instruction *ip = t->ip;
4592 uint64_t *regarray, idx, src;
4594 TRACE("[Thread %2u] regwr (r[h] = h)\n", p->thread_id);
4597 regarray = instr_regarray_regarray(p, ip);
4598 idx = instr_regarray_idx_nbo(p, t, ip);
4599 src = instr_regarray_src_nbo(t, ip);
4600 regarray[idx] = src;
4607 instr_regwr_rhm_exec(struct rte_swx_pipeline *p)
4609 struct thread *t = &p->threads[p->thread_id];
4610 struct instruction *ip = t->ip;
4611 uint64_t *regarray, idx, src;
4613 TRACE("[Thread %2u] regwr (r[h] = m)\n", p->thread_id);
4616 regarray = instr_regarray_regarray(p, ip);
4617 idx = instr_regarray_idx_nbo(p, t, ip);
4618 src = instr_regarray_src_hbo(t, ip);
4619 regarray[idx] = src;
4626 instr_regwr_rmh_exec(struct rte_swx_pipeline *p)
4628 struct thread *t = &p->threads[p->thread_id];
4629 struct instruction *ip = t->ip;
4630 uint64_t *regarray, idx, src;
4632 TRACE("[Thread %2u] regwr (r[m] = h)\n", p->thread_id);
4635 regarray = instr_regarray_regarray(p, ip);
4636 idx = instr_regarray_idx_hbo(p, t, ip);
4637 src = instr_regarray_src_nbo(t, ip);
4638 regarray[idx] = src;
4645 instr_regwr_rmm_exec(struct rte_swx_pipeline *p)
4647 struct thread *t = &p->threads[p->thread_id];
4648 struct instruction *ip = t->ip;
4649 uint64_t *regarray, idx, src;
4651 TRACE("[Thread %2u] regwr (r[m] = m)\n", p->thread_id);
4654 regarray = instr_regarray_regarray(p, ip);
4655 idx = instr_regarray_idx_hbo(p, t, ip);
4656 src = instr_regarray_src_hbo(t, ip);
4657 regarray[idx] = src;
4664 instr_regwr_rhi_exec(struct rte_swx_pipeline *p)
4666 struct thread *t = &p->threads[p->thread_id];
4667 struct instruction *ip = t->ip;
4668 uint64_t *regarray, idx, src;
4670 TRACE("[Thread %2u] regwr (r[h] = i)\n", p->thread_id);
4673 regarray = instr_regarray_regarray(p, ip);
4674 idx = instr_regarray_idx_nbo(p, t, ip);
4675 src = ip->regarray.dstsrc_val;
4676 regarray[idx] = src;
4683 instr_regwr_rmi_exec(struct rte_swx_pipeline *p)
4685 struct thread *t = &p->threads[p->thread_id];
4686 struct instruction *ip = t->ip;
4687 uint64_t *regarray, idx, src;
4689 TRACE("[Thread %2u] regwr (r[m] = i)\n", p->thread_id);
4692 regarray = instr_regarray_regarray(p, ip);
4693 idx = instr_regarray_idx_hbo(p, t, ip);
4694 src = ip->regarray.dstsrc_val;
4695 regarray[idx] = src;
4702 instr_regwr_rih_exec(struct rte_swx_pipeline *p)
4704 struct thread *t = &p->threads[p->thread_id];
4705 struct instruction *ip = t->ip;
4706 uint64_t *regarray, idx, src;
4708 TRACE("[Thread %2u] regwr (r[i] = h)\n", p->thread_id);
4711 regarray = instr_regarray_regarray(p, ip);
4712 idx = instr_regarray_idx_imm(p, ip);
4713 src = instr_regarray_src_nbo(t, ip);
4714 regarray[idx] = src;
4721 instr_regwr_rim_exec(struct rte_swx_pipeline *p)
4723 struct thread *t = &p->threads[p->thread_id];
4724 struct instruction *ip = t->ip;
4725 uint64_t *regarray, idx, src;
4727 TRACE("[Thread %2u] regwr (r[i] = m)\n", p->thread_id);
4730 regarray = instr_regarray_regarray(p, ip);
4731 idx = instr_regarray_idx_imm(p, ip);
4732 src = instr_regarray_src_hbo(t, ip);
4733 regarray[idx] = src;
4740 instr_regwr_rii_exec(struct rte_swx_pipeline *p)
4742 struct thread *t = &p->threads[p->thread_id];
4743 struct instruction *ip = t->ip;
4744 uint64_t *regarray, idx, src;
4746 TRACE("[Thread %2u] regwr (r[i] = i)\n", p->thread_id);
4749 regarray = instr_regarray_regarray(p, ip);
4750 idx = instr_regarray_idx_imm(p, ip);
4751 src = ip->regarray.dstsrc_val;
4752 regarray[idx] = src;
4759 instr_regadd_rhh_exec(struct rte_swx_pipeline *p)
4761 struct thread *t = &p->threads[p->thread_id];
4762 struct instruction *ip = t->ip;
4763 uint64_t *regarray, idx, src;
4765 TRACE("[Thread %2u] regadd (r[h] += h)\n", p->thread_id);
4768 regarray = instr_regarray_regarray(p, ip);
4769 idx = instr_regarray_idx_nbo(p, t, ip);
4770 src = instr_regarray_src_nbo(t, ip);
4771 regarray[idx] += src;
4778 instr_regadd_rhm_exec(struct rte_swx_pipeline *p)
4780 struct thread *t = &p->threads[p->thread_id];
4781 struct instruction *ip = t->ip;
4782 uint64_t *regarray, idx, src;
4784 TRACE("[Thread %2u] regadd (r[h] += m)\n", p->thread_id);
4787 regarray = instr_regarray_regarray(p, ip);
4788 idx = instr_regarray_idx_nbo(p, t, ip);
4789 src = instr_regarray_src_hbo(t, ip);
4790 regarray[idx] += src;
4797 instr_regadd_rmh_exec(struct rte_swx_pipeline *p)
4799 struct thread *t = &p->threads[p->thread_id];
4800 struct instruction *ip = t->ip;
4801 uint64_t *regarray, idx, src;
4803 TRACE("[Thread %2u] regadd (r[m] += h)\n", p->thread_id);
4806 regarray = instr_regarray_regarray(p, ip);
4807 idx = instr_regarray_idx_hbo(p, t, ip);
4808 src = instr_regarray_src_nbo(t, ip);
4809 regarray[idx] += src;
4816 instr_regadd_rmm_exec(struct rte_swx_pipeline *p)
4818 struct thread *t = &p->threads[p->thread_id];
4819 struct instruction *ip = t->ip;
4820 uint64_t *regarray, idx, src;
4822 TRACE("[Thread %2u] regadd (r[m] += m)\n", p->thread_id);
4825 regarray = instr_regarray_regarray(p, ip);
4826 idx = instr_regarray_idx_hbo(p, t, ip);
4827 src = instr_regarray_src_hbo(t, ip);
4828 regarray[idx] += src;
4835 instr_regadd_rhi_exec(struct rte_swx_pipeline *p)
4837 struct thread *t = &p->threads[p->thread_id];
4838 struct instruction *ip = t->ip;
4839 uint64_t *regarray, idx, src;
4841 TRACE("[Thread %2u] regadd (r[h] += i)\n", p->thread_id);
4844 regarray = instr_regarray_regarray(p, ip);
4845 idx = instr_regarray_idx_nbo(p, t, ip);
4846 src = ip->regarray.dstsrc_val;
4847 regarray[idx] += src;
4854 instr_regadd_rmi_exec(struct rte_swx_pipeline *p)
4856 struct thread *t = &p->threads[p->thread_id];
4857 struct instruction *ip = t->ip;
4858 uint64_t *regarray, idx, src;
4860 TRACE("[Thread %2u] regadd (r[m] += i)\n", p->thread_id);
4863 regarray = instr_regarray_regarray(p, ip);
4864 idx = instr_regarray_idx_hbo(p, t, ip);
4865 src = ip->regarray.dstsrc_val;
4866 regarray[idx] += src;
4873 instr_regadd_rih_exec(struct rte_swx_pipeline *p)
4875 struct thread *t = &p->threads[p->thread_id];
4876 struct instruction *ip = t->ip;
4877 uint64_t *regarray, idx, src;
4879 TRACE("[Thread %2u] regadd (r[i] += h)\n", p->thread_id);
4882 regarray = instr_regarray_regarray(p, ip);
4883 idx = instr_regarray_idx_imm(p, ip);
4884 src = instr_regarray_src_nbo(t, ip);
4885 regarray[idx] += src;
4892 instr_regadd_rim_exec(struct rte_swx_pipeline *p)
4894 struct thread *t = &p->threads[p->thread_id];
4895 struct instruction *ip = t->ip;
4896 uint64_t *regarray, idx, src;
4898 TRACE("[Thread %2u] regadd (r[i] += m)\n", p->thread_id);
4901 regarray = instr_regarray_regarray(p, ip);
4902 idx = instr_regarray_idx_imm(p, ip);
4903 src = instr_regarray_src_hbo(t, ip);
4904 regarray[idx] += src;
4911 instr_regadd_rii_exec(struct rte_swx_pipeline *p)
4913 struct thread *t = &p->threads[p->thread_id];
4914 struct instruction *ip = t->ip;
4915 uint64_t *regarray, idx, src;
4917 TRACE("[Thread %2u] regadd (r[i] += i)\n", p->thread_id);
4920 regarray = instr_regarray_regarray(p, ip);
4921 idx = instr_regarray_idx_imm(p, ip);
4922 src = ip->regarray.dstsrc_val;
4923 regarray[idx] += src;
4932 static struct metarray *
4933 metarray_find(struct rte_swx_pipeline *p, const char *name);
4936 instr_metprefetch_translate(struct rte_swx_pipeline *p,
4937 struct action *action,
4940 struct instruction *instr,
4941 struct instruction_data *data __rte_unused)
4943 char *metarray = tokens[1], *idx = tokens[2];
4946 uint32_t idx_struct_id, idx_val;
4948 CHECK(n_tokens == 3, EINVAL);
4950 m = metarray_find(p, metarray);
4953 /* METPREFETCH_H, METPREFETCH_M. */
4954 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4956 CHECK(!fidx->var_size, EINVAL);
4958 instr->type = INSTR_METPREFETCH_M;
4960 instr->type = INSTR_METPREFETCH_H;
4962 instr->meter.metarray_id = m->id;
4963 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4964 instr->meter.idx.n_bits = fidx->n_bits;
4965 instr->meter.idx.offset = fidx->offset / 8;
4969 /* METPREFETCH_I. */
4970 idx_val = strtoul(idx, &idx, 0);
4971 CHECK(!idx[0], EINVAL);
4973 instr->type = INSTR_METPREFETCH_I;
4974 instr->meter.metarray_id = m->id;
4975 instr->meter.idx_val = idx_val;
4980 instr_meter_translate(struct rte_swx_pipeline *p,
4981 struct action *action,
4984 struct instruction *instr,
4985 struct instruction_data *data __rte_unused)
4987 char *metarray = tokens[1], *idx = tokens[2], *length = tokens[3];
4988 char *color_in = tokens[4], *color_out = tokens[5];
4990 struct field *fidx, *flength, *fcin, *fcout;
4991 uint32_t idx_struct_id, length_struct_id;
4992 uint32_t color_in_struct_id, color_out_struct_id;
4994 CHECK(n_tokens == 6, EINVAL);
4996 m = metarray_find(p, metarray);
4999 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
5001 flength = struct_field_parse(p, action, length, &length_struct_id);
5002 CHECK(flength, EINVAL);
5003 CHECK(!flength->var_size, EINVAL);
5005 fcin = struct_field_parse(p, action, color_in, &color_in_struct_id);
5007 fcout = struct_field_parse(p, NULL, color_out, &color_out_struct_id);
5008 CHECK(fcout, EINVAL);
5009 CHECK(!fcout->var_size, EINVAL);
5011 /* index = HMEFT, length = HMEFT, color_in = MEFT, color_out = MEF. */
5013 CHECK(!fidx->var_size, EINVAL);
5014 CHECK(!fcin->var_size, EINVAL);
5016 instr->type = INSTR_METER_MMM;
5017 if (idx[0] == 'h' && length[0] == 'h')
5018 instr->type = INSTR_METER_HHM;
5019 if (idx[0] == 'h' && length[0] != 'h')
5020 instr->type = INSTR_METER_HMM;
5021 if (idx[0] != 'h' && length[0] == 'h')
5022 instr->type = INSTR_METER_MHM;
5024 instr->meter.metarray_id = m->id;
5026 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
5027 instr->meter.idx.n_bits = fidx->n_bits;
5028 instr->meter.idx.offset = fidx->offset / 8;
5030 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5031 instr->meter.length.n_bits = flength->n_bits;
5032 instr->meter.length.offset = flength->offset / 8;
5034 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
5035 instr->meter.color_in.n_bits = fcin->n_bits;
5036 instr->meter.color_in.offset = fcin->offset / 8;
5038 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5039 instr->meter.color_out.n_bits = fcout->n_bits;
5040 instr->meter.color_out.offset = fcout->offset / 8;
5045 /* index = HMEFT, length = HMEFT, color_in = I, color_out = MEF. */
5046 if (fidx && !fcin) {
5047 uint32_t color_in_val;
5049 CHECK(!fidx->var_size, EINVAL);
5051 color_in_val = strtoul(color_in, &color_in, 0);
5052 CHECK(!color_in[0], EINVAL);
5054 instr->type = INSTR_METER_MMI;
5055 if (idx[0] == 'h' && length[0] == 'h')
5056 instr->type = INSTR_METER_HHI;
5057 if (idx[0] == 'h' && length[0] != 'h')
5058 instr->type = INSTR_METER_HMI;
5059 if (idx[0] != 'h' && length[0] == 'h')
5060 instr->type = INSTR_METER_MHI;
5062 instr->meter.metarray_id = m->id;
5064 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
5065 instr->meter.idx.n_bits = fidx->n_bits;
5066 instr->meter.idx.offset = fidx->offset / 8;
5068 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5069 instr->meter.length.n_bits = flength->n_bits;
5070 instr->meter.length.offset = flength->offset / 8;
5072 instr->meter.color_in_val = color_in_val;
5074 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5075 instr->meter.color_out.n_bits = fcout->n_bits;
5076 instr->meter.color_out.offset = fcout->offset / 8;
5081 /* index = I, length = HMEFT, color_in = MEFT, color_out = MEF. */
5082 if (!fidx && fcin) {
5085 idx_val = strtoul(idx, &idx, 0);
5086 CHECK(!idx[0], EINVAL);
5088 CHECK(!fcin->var_size, EINVAL);
5090 instr->type = INSTR_METER_IMM;
5091 if (length[0] == 'h')
5092 instr->type = INSTR_METER_IHM;
5094 instr->meter.metarray_id = m->id;
5096 instr->meter.idx_val = idx_val;
5098 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5099 instr->meter.length.n_bits = flength->n_bits;
5100 instr->meter.length.offset = flength->offset / 8;
5102 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
5103 instr->meter.color_in.n_bits = fcin->n_bits;
5104 instr->meter.color_in.offset = fcin->offset / 8;
5106 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5107 instr->meter.color_out.n_bits = fcout->n_bits;
5108 instr->meter.color_out.offset = fcout->offset / 8;
5113 /* index = I, length = HMEFT, color_in = I, color_out = MEF. */
5114 if (!fidx && !fcin) {
5115 uint32_t idx_val, color_in_val;
5117 idx_val = strtoul(idx, &idx, 0);
5118 CHECK(!idx[0], EINVAL);
5120 color_in_val = strtoul(color_in, &color_in, 0);
5121 CHECK(!color_in[0], EINVAL);
5123 instr->type = INSTR_METER_IMI;
5124 if (length[0] == 'h')
5125 instr->type = INSTR_METER_IHI;
5127 instr->meter.metarray_id = m->id;
5129 instr->meter.idx_val = idx_val;
5131 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5132 instr->meter.length.n_bits = flength->n_bits;
5133 instr->meter.length.offset = flength->offset / 8;
5135 instr->meter.color_in_val = color_in_val;
5137 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5138 instr->meter.color_out.n_bits = fcout->n_bits;
5139 instr->meter.color_out.offset = fcout->offset / 8;
5147 static inline struct meter *
5148 instr_meter_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
5150 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
5152 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
5153 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
5154 uint64_t idx64 = *idx64_ptr;
5155 uint64_t idx64_mask = UINT64_MAX >> (64 - (ip)->meter.idx.n_bits);
5156 uint64_t idx = idx64 & idx64_mask & r->size_mask;
5158 return &r->metarray[idx];
5161 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5163 static inline struct meter *
5164 instr_meter_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
5166 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
5168 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
5169 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
5170 uint64_t idx64 = *idx64_ptr;
5171 uint64_t idx = (ntoh64(idx64) >> (64 - ip->meter.idx.n_bits)) & r->size_mask;
5173 return &r->metarray[idx];
5178 #define instr_meter_idx_nbo instr_meter_idx_hbo
5182 static inline struct meter *
5183 instr_meter_idx_imm(struct rte_swx_pipeline *p, struct instruction *ip)
5185 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
5187 uint64_t idx = ip->meter.idx_val & r->size_mask;
5189 return &r->metarray[idx];
5192 static inline uint32_t
5193 instr_meter_length_hbo(struct thread *t, struct instruction *ip)
5195 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
5196 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
5197 uint64_t src64 = *src64_ptr;
5198 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->meter.length.n_bits);
5199 uint64_t src = src64 & src64_mask;
5201 return (uint32_t)src;
5204 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5206 static inline uint32_t
5207 instr_meter_length_nbo(struct thread *t, struct instruction *ip)
5209 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
5210 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
5211 uint64_t src64 = *src64_ptr;
5212 uint64_t src = ntoh64(src64) >> (64 - ip->meter.length.n_bits);
5214 return (uint32_t)src;
5219 #define instr_meter_length_nbo instr_meter_length_hbo
5223 static inline enum rte_color
5224 instr_meter_color_in_hbo(struct thread *t, struct instruction *ip)
5226 uint8_t *src_struct = t->structs[ip->meter.color_in.struct_id];
5227 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.color_in.offset];
5228 uint64_t src64 = *src64_ptr;
5229 uint64_t src64_mask = UINT64_MAX >> (64 - ip->meter.color_in.n_bits);
5230 uint64_t src = src64 & src64_mask;
5232 return (enum rte_color)src;
5236 instr_meter_color_out_hbo_set(struct thread *t, struct instruction *ip, enum rte_color color_out)
5238 uint8_t *dst_struct = t->structs[ip->meter.color_out.struct_id];
5239 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->meter.color_out.offset];
5240 uint64_t dst64 = *dst64_ptr;
5241 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->meter.color_out.n_bits);
5243 uint64_t src = (uint64_t)color_out;
5245 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
5249 instr_metprefetch_h_exec(struct rte_swx_pipeline *p)
5251 struct thread *t = &p->threads[p->thread_id];
5252 struct instruction *ip = t->ip;
5255 TRACE("[Thread %2u] metprefetch (h)\n", p->thread_id);
5258 m = instr_meter_idx_nbo(p, t, ip);
5266 instr_metprefetch_m_exec(struct rte_swx_pipeline *p)
5268 struct thread *t = &p->threads[p->thread_id];
5269 struct instruction *ip = t->ip;
5272 TRACE("[Thread %2u] metprefetch (m)\n", p->thread_id);
5275 m = instr_meter_idx_hbo(p, t, ip);
5283 instr_metprefetch_i_exec(struct rte_swx_pipeline *p)
5285 struct thread *t = &p->threads[p->thread_id];
5286 struct instruction *ip = t->ip;
5289 TRACE("[Thread %2u] metprefetch (i)\n", p->thread_id);
5292 m = instr_meter_idx_imm(p, ip);
5300 instr_meter_hhm_exec(struct rte_swx_pipeline *p)
5302 struct thread *t = &p->threads[p->thread_id];
5303 struct instruction *ip = t->ip;
5305 uint64_t time, n_pkts, n_bytes;
5307 enum rte_color color_in, color_out;
5309 TRACE("[Thread %2u] meter (hhm)\n", p->thread_id);
5312 m = instr_meter_idx_nbo(p, t, ip);
5313 rte_prefetch0(m->n_pkts);
5314 time = rte_get_tsc_cycles();
5315 length = instr_meter_length_nbo(t, ip);
5316 color_in = instr_meter_color_in_hbo(t, ip);
5318 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5319 &m->profile->profile,
5324 color_out &= m->color_mask;
5326 n_pkts = m->n_pkts[color_out];
5327 n_bytes = m->n_bytes[color_out];
5329 instr_meter_color_out_hbo_set(t, ip, color_out);
5331 m->n_pkts[color_out] = n_pkts + 1;
5332 m->n_bytes[color_out] = n_bytes + length;
5339 instr_meter_hhi_exec(struct rte_swx_pipeline *p)
5341 struct thread *t = &p->threads[p->thread_id];
5342 struct instruction *ip = t->ip;
5344 uint64_t time, n_pkts, n_bytes;
5346 enum rte_color color_in, color_out;
5348 TRACE("[Thread %2u] meter (hhi)\n", p->thread_id);
5351 m = instr_meter_idx_nbo(p, t, ip);
5352 rte_prefetch0(m->n_pkts);
5353 time = rte_get_tsc_cycles();
5354 length = instr_meter_length_nbo(t, ip);
5355 color_in = (enum rte_color)ip->meter.color_in_val;
5357 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5358 &m->profile->profile,
5363 color_out &= m->color_mask;
5365 n_pkts = m->n_pkts[color_out];
5366 n_bytes = m->n_bytes[color_out];
5368 instr_meter_color_out_hbo_set(t, ip, color_out);
5370 m->n_pkts[color_out] = n_pkts + 1;
5371 m->n_bytes[color_out] = n_bytes + length;
5378 instr_meter_hmm_exec(struct rte_swx_pipeline *p)
5380 struct thread *t = &p->threads[p->thread_id];
5381 struct instruction *ip = t->ip;
5383 uint64_t time, n_pkts, n_bytes;
5385 enum rte_color color_in, color_out;
5387 TRACE("[Thread %2u] meter (hmm)\n", p->thread_id);
5390 m = instr_meter_idx_nbo(p, t, ip);
5391 rte_prefetch0(m->n_pkts);
5392 time = rte_get_tsc_cycles();
5393 length = instr_meter_length_hbo(t, ip);
5394 color_in = instr_meter_color_in_hbo(t, ip);
5396 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5397 &m->profile->profile,
5402 color_out &= m->color_mask;
5404 n_pkts = m->n_pkts[color_out];
5405 n_bytes = m->n_bytes[color_out];
5407 instr_meter_color_out_hbo_set(t, ip, color_out);
5409 m->n_pkts[color_out] = n_pkts + 1;
5410 m->n_bytes[color_out] = n_bytes + length;
5416 instr_meter_hmi_exec(struct rte_swx_pipeline *p)
5418 struct thread *t = &p->threads[p->thread_id];
5419 struct instruction *ip = t->ip;
5421 uint64_t time, n_pkts, n_bytes;
5423 enum rte_color color_in, color_out;
5425 TRACE("[Thread %2u] meter (hmi)\n", p->thread_id);
5428 m = instr_meter_idx_nbo(p, t, ip);
5429 rte_prefetch0(m->n_pkts);
5430 time = rte_get_tsc_cycles();
5431 length = instr_meter_length_hbo(t, ip);
5432 color_in = (enum rte_color)ip->meter.color_in_val;
5434 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5435 &m->profile->profile,
5440 color_out &= m->color_mask;
5442 n_pkts = m->n_pkts[color_out];
5443 n_bytes = m->n_bytes[color_out];
5445 instr_meter_color_out_hbo_set(t, ip, color_out);
5447 m->n_pkts[color_out] = n_pkts + 1;
5448 m->n_bytes[color_out] = n_bytes + length;
5455 instr_meter_mhm_exec(struct rte_swx_pipeline *p)
5457 struct thread *t = &p->threads[p->thread_id];
5458 struct instruction *ip = t->ip;
5460 uint64_t time, n_pkts, n_bytes;
5462 enum rte_color color_in, color_out;
5464 TRACE("[Thread %2u] meter (mhm)\n", p->thread_id);
5467 m = instr_meter_idx_hbo(p, t, ip);
5468 rte_prefetch0(m->n_pkts);
5469 time = rte_get_tsc_cycles();
5470 length = instr_meter_length_nbo(t, ip);
5471 color_in = instr_meter_color_in_hbo(t, ip);
5473 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5474 &m->profile->profile,
5479 color_out &= m->color_mask;
5481 n_pkts = m->n_pkts[color_out];
5482 n_bytes = m->n_bytes[color_out];
5484 instr_meter_color_out_hbo_set(t, ip, color_out);
5486 m->n_pkts[color_out] = n_pkts + 1;
5487 m->n_bytes[color_out] = n_bytes + length;
5494 instr_meter_mhi_exec(struct rte_swx_pipeline *p)
5496 struct thread *t = &p->threads[p->thread_id];
5497 struct instruction *ip = t->ip;
5499 uint64_t time, n_pkts, n_bytes;
5501 enum rte_color color_in, color_out;
5503 TRACE("[Thread %2u] meter (mhi)\n", p->thread_id);
5506 m = instr_meter_idx_hbo(p, t, ip);
5507 rte_prefetch0(m->n_pkts);
5508 time = rte_get_tsc_cycles();
5509 length = instr_meter_length_nbo(t, ip);
5510 color_in = (enum rte_color)ip->meter.color_in_val;
5512 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5513 &m->profile->profile,
5518 color_out &= m->color_mask;
5520 n_pkts = m->n_pkts[color_out];
5521 n_bytes = m->n_bytes[color_out];
5523 instr_meter_color_out_hbo_set(t, ip, color_out);
5525 m->n_pkts[color_out] = n_pkts + 1;
5526 m->n_bytes[color_out] = n_bytes + length;
5533 instr_meter_mmm_exec(struct rte_swx_pipeline *p)
5535 struct thread *t = &p->threads[p->thread_id];
5536 struct instruction *ip = t->ip;
5538 uint64_t time, n_pkts, n_bytes;
5540 enum rte_color color_in, color_out;
5542 TRACE("[Thread %2u] meter (mmm)\n", p->thread_id);
5545 m = instr_meter_idx_hbo(p, t, ip);
5546 rte_prefetch0(m->n_pkts);
5547 time = rte_get_tsc_cycles();
5548 length = instr_meter_length_hbo(t, ip);
5549 color_in = instr_meter_color_in_hbo(t, ip);
5551 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5552 &m->profile->profile,
5557 color_out &= m->color_mask;
5559 n_pkts = m->n_pkts[color_out];
5560 n_bytes = m->n_bytes[color_out];
5562 instr_meter_color_out_hbo_set(t, ip, color_out);
5564 m->n_pkts[color_out] = n_pkts + 1;
5565 m->n_bytes[color_out] = n_bytes + length;
5572 instr_meter_mmi_exec(struct rte_swx_pipeline *p)
5574 struct thread *t = &p->threads[p->thread_id];
5575 struct instruction *ip = t->ip;
5577 uint64_t time, n_pkts, n_bytes;
5579 enum rte_color color_in, color_out;
5581 TRACE("[Thread %2u] meter (mmi)\n", p->thread_id);
5584 m = instr_meter_idx_hbo(p, t, ip);
5585 rte_prefetch0(m->n_pkts);
5586 time = rte_get_tsc_cycles();
5587 length = instr_meter_length_hbo(t, ip);
5588 color_in = (enum rte_color)ip->meter.color_in_val;
5590 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5591 &m->profile->profile,
5596 color_out &= m->color_mask;
5598 n_pkts = m->n_pkts[color_out];
5599 n_bytes = m->n_bytes[color_out];
5601 instr_meter_color_out_hbo_set(t, ip, color_out);
5603 m->n_pkts[color_out] = n_pkts + 1;
5604 m->n_bytes[color_out] = n_bytes + length;
5611 instr_meter_ihm_exec(struct rte_swx_pipeline *p)
5613 struct thread *t = &p->threads[p->thread_id];
5614 struct instruction *ip = t->ip;
5616 uint64_t time, n_pkts, n_bytes;
5618 enum rte_color color_in, color_out;
5620 TRACE("[Thread %2u] meter (ihm)\n", p->thread_id);
5623 m = instr_meter_idx_imm(p, ip);
5624 rte_prefetch0(m->n_pkts);
5625 time = rte_get_tsc_cycles();
5626 length = instr_meter_length_nbo(t, ip);
5627 color_in = instr_meter_color_in_hbo(t, ip);
5629 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5630 &m->profile->profile,
5635 color_out &= m->color_mask;
5637 n_pkts = m->n_pkts[color_out];
5638 n_bytes = m->n_bytes[color_out];
5640 instr_meter_color_out_hbo_set(t, ip, color_out);
5642 m->n_pkts[color_out] = n_pkts + 1;
5643 m->n_bytes[color_out] = n_bytes + length;
5650 instr_meter_ihi_exec(struct rte_swx_pipeline *p)
5652 struct thread *t = &p->threads[p->thread_id];
5653 struct instruction *ip = t->ip;
5655 uint64_t time, n_pkts, n_bytes;
5657 enum rte_color color_in, color_out;
5659 TRACE("[Thread %2u] meter (ihi)\n", p->thread_id);
5662 m = instr_meter_idx_imm(p, ip);
5663 rte_prefetch0(m->n_pkts);
5664 time = rte_get_tsc_cycles();
5665 length = instr_meter_length_nbo(t, ip);
5666 color_in = (enum rte_color)ip->meter.color_in_val;
5668 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5669 &m->profile->profile,
5674 color_out &= m->color_mask;
5676 n_pkts = m->n_pkts[color_out];
5677 n_bytes = m->n_bytes[color_out];
5679 instr_meter_color_out_hbo_set(t, ip, color_out);
5681 m->n_pkts[color_out] = n_pkts + 1;
5682 m->n_bytes[color_out] = n_bytes + length;
5689 instr_meter_imm_exec(struct rte_swx_pipeline *p)
5691 struct thread *t = &p->threads[p->thread_id];
5692 struct instruction *ip = t->ip;
5694 uint64_t time, n_pkts, n_bytes;
5696 enum rte_color color_in, color_out;
5698 TRACE("[Thread %2u] meter (imm)\n", p->thread_id);
5701 m = instr_meter_idx_imm(p, ip);
5702 rte_prefetch0(m->n_pkts);
5703 time = rte_get_tsc_cycles();
5704 length = instr_meter_length_hbo(t, ip);
5705 color_in = instr_meter_color_in_hbo(t, ip);
5707 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5708 &m->profile->profile,
5713 color_out &= m->color_mask;
5715 n_pkts = m->n_pkts[color_out];
5716 n_bytes = m->n_bytes[color_out];
5718 instr_meter_color_out_hbo_set(t, ip, color_out);
5720 m->n_pkts[color_out] = n_pkts + 1;
5721 m->n_bytes[color_out] = n_bytes + length;
5727 instr_meter_imi_exec(struct rte_swx_pipeline *p)
5729 struct thread *t = &p->threads[p->thread_id];
5730 struct instruction *ip = t->ip;
5732 uint64_t time, n_pkts, n_bytes;
5734 enum rte_color color_in, color_out;
5736 TRACE("[Thread %2u] meter (imi)\n", p->thread_id);
5739 m = instr_meter_idx_imm(p, ip);
5740 rte_prefetch0(m->n_pkts);
5741 time = rte_get_tsc_cycles();
5742 length = instr_meter_length_hbo(t, ip);
5743 color_in = (enum rte_color)ip->meter.color_in_val;
5745 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5746 &m->profile->profile,
5751 color_out &= m->color_mask;
5753 n_pkts = m->n_pkts[color_out];
5754 n_bytes = m->n_bytes[color_out];
5756 instr_meter_color_out_hbo_set(t, ip, color_out);
5758 m->n_pkts[color_out] = n_pkts + 1;
5759 m->n_bytes[color_out] = n_bytes + length;
5769 instr_jmp_translate(struct rte_swx_pipeline *p __rte_unused,
5770 struct action *action __rte_unused,
5773 struct instruction *instr,
5774 struct instruction_data *data)
5776 CHECK(n_tokens == 2, EINVAL);
5778 strcpy(data->jmp_label, tokens[1]);
5780 instr->type = INSTR_JMP;
5781 instr->jmp.ip = NULL; /* Resolved later. */
5786 instr_jmp_valid_translate(struct rte_swx_pipeline *p,
5787 struct action *action __rte_unused,
5790 struct instruction *instr,
5791 struct instruction_data *data)
5795 CHECK(n_tokens == 3, EINVAL);
5797 strcpy(data->jmp_label, tokens[1]);
5799 h = header_parse(p, tokens[2]);
5802 instr->type = INSTR_JMP_VALID;
5803 instr->jmp.ip = NULL; /* Resolved later. */
5804 instr->jmp.header_id = h->id;
5809 instr_jmp_invalid_translate(struct rte_swx_pipeline *p,
5810 struct action *action __rte_unused,
5813 struct instruction *instr,
5814 struct instruction_data *data)
5818 CHECK(n_tokens == 3, EINVAL);
5820 strcpy(data->jmp_label, tokens[1]);
5822 h = header_parse(p, tokens[2]);
5825 instr->type = INSTR_JMP_INVALID;
5826 instr->jmp.ip = NULL; /* Resolved later. */
5827 instr->jmp.header_id = h->id;
5832 instr_jmp_hit_translate(struct rte_swx_pipeline *p __rte_unused,
5833 struct action *action,
5836 struct instruction *instr,
5837 struct instruction_data *data)
5839 CHECK(!action, EINVAL);
5840 CHECK(n_tokens == 2, EINVAL);
5842 strcpy(data->jmp_label, tokens[1]);
5844 instr->type = INSTR_JMP_HIT;
5845 instr->jmp.ip = NULL; /* Resolved later. */
5850 instr_jmp_miss_translate(struct rte_swx_pipeline *p __rte_unused,
5851 struct action *action,
5854 struct instruction *instr,
5855 struct instruction_data *data)
5857 CHECK(!action, EINVAL);
5858 CHECK(n_tokens == 2, EINVAL);
5860 strcpy(data->jmp_label, tokens[1]);
5862 instr->type = INSTR_JMP_MISS;
5863 instr->jmp.ip = NULL; /* Resolved later. */
5868 instr_jmp_action_hit_translate(struct rte_swx_pipeline *p,
5869 struct action *action,
5872 struct instruction *instr,
5873 struct instruction_data *data)
5877 CHECK(!action, EINVAL);
5878 CHECK(n_tokens == 3, EINVAL);
5880 strcpy(data->jmp_label, tokens[1]);
5882 a = action_find(p, tokens[2]);
5885 instr->type = INSTR_JMP_ACTION_HIT;
5886 instr->jmp.ip = NULL; /* Resolved later. */
5887 instr->jmp.action_id = a->id;
5892 instr_jmp_action_miss_translate(struct rte_swx_pipeline *p,
5893 struct action *action,
5896 struct instruction *instr,
5897 struct instruction_data *data)
5901 CHECK(!action, EINVAL);
5902 CHECK(n_tokens == 3, EINVAL);
5904 strcpy(data->jmp_label, tokens[1]);
5906 a = action_find(p, tokens[2]);
5909 instr->type = INSTR_JMP_ACTION_MISS;
5910 instr->jmp.ip = NULL; /* Resolved later. */
5911 instr->jmp.action_id = a->id;
5916 instr_jmp_eq_translate(struct rte_swx_pipeline *p,
5917 struct action *action,
5920 struct instruction *instr,
5921 struct instruction_data *data)
5923 char *a = tokens[2], *b = tokens[3];
5924 struct field *fa, *fb;
5926 uint32_t a_struct_id, b_struct_id;
5928 CHECK(n_tokens == 4, EINVAL);
5930 strcpy(data->jmp_label, tokens[1]);
5932 fa = struct_field_parse(p, action, a, &a_struct_id);
5934 CHECK(!fa->var_size, EINVAL);
5936 /* JMP_EQ, JMP_EQ_MH, JMP_EQ_HM, JMP_EQ_HH. */
5937 fb = struct_field_parse(p, action, b, &b_struct_id);
5939 CHECK(!fb->var_size, EINVAL);
5941 instr->type = INSTR_JMP_EQ;
5942 if (a[0] != 'h' && b[0] == 'h')
5943 instr->type = INSTR_JMP_EQ_MH;
5944 if (a[0] == 'h' && b[0] != 'h')
5945 instr->type = INSTR_JMP_EQ_HM;
5946 if (a[0] == 'h' && b[0] == 'h')
5947 instr->type = INSTR_JMP_EQ_HH;
5948 instr->jmp.ip = NULL; /* Resolved later. */
5950 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5951 instr->jmp.a.n_bits = fa->n_bits;
5952 instr->jmp.a.offset = fa->offset / 8;
5953 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5954 instr->jmp.b.n_bits = fb->n_bits;
5955 instr->jmp.b.offset = fb->offset / 8;
5960 b_val = strtoull(b, &b, 0);
5961 CHECK(!b[0], EINVAL);
5964 b_val = hton64(b_val) >> (64 - fa->n_bits);
5966 instr->type = INSTR_JMP_EQ_I;
5967 instr->jmp.ip = NULL; /* Resolved later. */
5968 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5969 instr->jmp.a.n_bits = fa->n_bits;
5970 instr->jmp.a.offset = fa->offset / 8;
5971 instr->jmp.b_val = b_val;
5976 instr_jmp_neq_translate(struct rte_swx_pipeline *p,
5977 struct action *action,
5980 struct instruction *instr,
5981 struct instruction_data *data)
5983 char *a = tokens[2], *b = tokens[3];
5984 struct field *fa, *fb;
5986 uint32_t a_struct_id, b_struct_id;
5988 CHECK(n_tokens == 4, EINVAL);
5990 strcpy(data->jmp_label, tokens[1]);
5992 fa = struct_field_parse(p, action, a, &a_struct_id);
5994 CHECK(!fa->var_size, EINVAL);
5996 /* JMP_NEQ, JMP_NEQ_MH, JMP_NEQ_HM, JMP_NEQ_HH. */
5997 fb = struct_field_parse(p, action, b, &b_struct_id);
5999 CHECK(!fb->var_size, EINVAL);
6001 instr->type = INSTR_JMP_NEQ;
6002 if (a[0] != 'h' && b[0] == 'h')
6003 instr->type = INSTR_JMP_NEQ_MH;
6004 if (a[0] == 'h' && b[0] != 'h')
6005 instr->type = INSTR_JMP_NEQ_HM;
6006 if (a[0] == 'h' && b[0] == 'h')
6007 instr->type = INSTR_JMP_NEQ_HH;
6008 instr->jmp.ip = NULL; /* Resolved later. */
6010 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6011 instr->jmp.a.n_bits = fa->n_bits;
6012 instr->jmp.a.offset = fa->offset / 8;
6013 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6014 instr->jmp.b.n_bits = fb->n_bits;
6015 instr->jmp.b.offset = fb->offset / 8;
6020 b_val = strtoull(b, &b, 0);
6021 CHECK(!b[0], EINVAL);
6024 b_val = hton64(b_val) >> (64 - fa->n_bits);
6026 instr->type = INSTR_JMP_NEQ_I;
6027 instr->jmp.ip = NULL; /* Resolved later. */
6028 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6029 instr->jmp.a.n_bits = fa->n_bits;
6030 instr->jmp.a.offset = fa->offset / 8;
6031 instr->jmp.b_val = b_val;
6036 instr_jmp_lt_translate(struct rte_swx_pipeline *p,
6037 struct action *action,
6040 struct instruction *instr,
6041 struct instruction_data *data)
6043 char *a = tokens[2], *b = tokens[3];
6044 struct field *fa, *fb;
6046 uint32_t a_struct_id, b_struct_id;
6048 CHECK(n_tokens == 4, EINVAL);
6050 strcpy(data->jmp_label, tokens[1]);
6052 fa = struct_field_parse(p, action, a, &a_struct_id);
6054 CHECK(!fa->var_size, EINVAL);
6056 /* JMP_LT, JMP_LT_MH, JMP_LT_HM, JMP_LT_HH. */
6057 fb = struct_field_parse(p, action, b, &b_struct_id);
6059 CHECK(!fb->var_size, EINVAL);
6061 instr->type = INSTR_JMP_LT;
6062 if (a[0] == 'h' && b[0] != 'h')
6063 instr->type = INSTR_JMP_LT_HM;
6064 if (a[0] != 'h' && b[0] == 'h')
6065 instr->type = INSTR_JMP_LT_MH;
6066 if (a[0] == 'h' && b[0] == 'h')
6067 instr->type = INSTR_JMP_LT_HH;
6068 instr->jmp.ip = NULL; /* Resolved later. */
6070 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6071 instr->jmp.a.n_bits = fa->n_bits;
6072 instr->jmp.a.offset = fa->offset / 8;
6073 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6074 instr->jmp.b.n_bits = fb->n_bits;
6075 instr->jmp.b.offset = fb->offset / 8;
6079 /* JMP_LT_MI, JMP_LT_HI. */
6080 b_val = strtoull(b, &b, 0);
6081 CHECK(!b[0], EINVAL);
6083 instr->type = INSTR_JMP_LT_MI;
6085 instr->type = INSTR_JMP_LT_HI;
6086 instr->jmp.ip = NULL; /* Resolved later. */
6088 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6089 instr->jmp.a.n_bits = fa->n_bits;
6090 instr->jmp.a.offset = fa->offset / 8;
6091 instr->jmp.b_val = b_val;
6096 instr_jmp_gt_translate(struct rte_swx_pipeline *p,
6097 struct action *action,
6100 struct instruction *instr,
6101 struct instruction_data *data)
6103 char *a = tokens[2], *b = tokens[3];
6104 struct field *fa, *fb;
6106 uint32_t a_struct_id, b_struct_id;
6108 CHECK(n_tokens == 4, EINVAL);
6110 strcpy(data->jmp_label, tokens[1]);
6112 fa = struct_field_parse(p, action, a, &a_struct_id);
6114 CHECK(!fa->var_size, EINVAL);
6116 /* JMP_GT, JMP_GT_MH, JMP_GT_HM, JMP_GT_HH. */
6117 fb = struct_field_parse(p, action, b, &b_struct_id);
6119 CHECK(!fb->var_size, EINVAL);
6121 instr->type = INSTR_JMP_GT;
6122 if (a[0] == 'h' && b[0] != 'h')
6123 instr->type = INSTR_JMP_GT_HM;
6124 if (a[0] != 'h' && b[0] == 'h')
6125 instr->type = INSTR_JMP_GT_MH;
6126 if (a[0] == 'h' && b[0] == 'h')
6127 instr->type = INSTR_JMP_GT_HH;
6128 instr->jmp.ip = NULL; /* Resolved later. */
6130 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6131 instr->jmp.a.n_bits = fa->n_bits;
6132 instr->jmp.a.offset = fa->offset / 8;
6133 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6134 instr->jmp.b.n_bits = fb->n_bits;
6135 instr->jmp.b.offset = fb->offset / 8;
6139 /* JMP_GT_MI, JMP_GT_HI. */
6140 b_val = strtoull(b, &b, 0);
6141 CHECK(!b[0], EINVAL);
6143 instr->type = INSTR_JMP_GT_MI;
6145 instr->type = INSTR_JMP_GT_HI;
6146 instr->jmp.ip = NULL; /* Resolved later. */
6148 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6149 instr->jmp.a.n_bits = fa->n_bits;
6150 instr->jmp.a.offset = fa->offset / 8;
6151 instr->jmp.b_val = b_val;
6156 instr_jmp_exec(struct rte_swx_pipeline *p)
6158 struct thread *t = &p->threads[p->thread_id];
6159 struct instruction *ip = t->ip;
6161 TRACE("[Thread %2u] jmp\n", p->thread_id);
6163 thread_ip_set(t, ip->jmp.ip);
6167 instr_jmp_valid_exec(struct rte_swx_pipeline *p)
6169 struct thread *t = &p->threads[p->thread_id];
6170 struct instruction *ip = t->ip;
6171 uint32_t header_id = ip->jmp.header_id;
6173 TRACE("[Thread %2u] jmpv\n", p->thread_id);
6175 t->ip = HEADER_VALID(t, header_id) ? ip->jmp.ip : (t->ip + 1);
6179 instr_jmp_invalid_exec(struct rte_swx_pipeline *p)
6181 struct thread *t = &p->threads[p->thread_id];
6182 struct instruction *ip = t->ip;
6183 uint32_t header_id = ip->jmp.header_id;
6185 TRACE("[Thread %2u] jmpnv\n", p->thread_id);
6187 t->ip = HEADER_VALID(t, header_id) ? (t->ip + 1) : ip->jmp.ip;
6191 instr_jmp_hit_exec(struct rte_swx_pipeline *p)
6193 struct thread *t = &p->threads[p->thread_id];
6194 struct instruction *ip = t->ip;
6195 struct instruction *ip_next[] = {t->ip + 1, ip->jmp.ip};
6197 TRACE("[Thread %2u] jmph\n", p->thread_id);
6199 t->ip = ip_next[t->hit];
6203 instr_jmp_miss_exec(struct rte_swx_pipeline *p)
6205 struct thread *t = &p->threads[p->thread_id];
6206 struct instruction *ip = t->ip;
6207 struct instruction *ip_next[] = {ip->jmp.ip, t->ip + 1};
6209 TRACE("[Thread %2u] jmpnh\n", p->thread_id);
6211 t->ip = ip_next[t->hit];
6215 instr_jmp_action_hit_exec(struct rte_swx_pipeline *p)
6217 struct thread *t = &p->threads[p->thread_id];
6218 struct instruction *ip = t->ip;
6220 TRACE("[Thread %2u] jmpa\n", p->thread_id);
6222 t->ip = (ip->jmp.action_id == t->action_id) ? ip->jmp.ip : (t->ip + 1);
6226 instr_jmp_action_miss_exec(struct rte_swx_pipeline *p)
6228 struct thread *t = &p->threads[p->thread_id];
6229 struct instruction *ip = t->ip;
6231 TRACE("[Thread %2u] jmpna\n", p->thread_id);
6233 t->ip = (ip->jmp.action_id == t->action_id) ? (t->ip + 1) : ip->jmp.ip;
6237 instr_jmp_eq_exec(struct rte_swx_pipeline *p)
6239 struct thread *t = &p->threads[p->thread_id];
6240 struct instruction *ip = t->ip;
6242 TRACE("[Thread %2u] jmpeq\n", p->thread_id);
6248 instr_jmp_eq_mh_exec(struct rte_swx_pipeline *p)
6250 struct thread *t = &p->threads[p->thread_id];
6251 struct instruction *ip = t->ip;
6253 TRACE("[Thread %2u] jmpeq (mh)\n", p->thread_id);
6255 JMP_CMP_MH(t, ip, ==);
6259 instr_jmp_eq_hm_exec(struct rte_swx_pipeline *p)
6261 struct thread *t = &p->threads[p->thread_id];
6262 struct instruction *ip = t->ip;
6264 TRACE("[Thread %2u] jmpeq (hm)\n", p->thread_id);
6266 JMP_CMP_HM(t, ip, ==);
6270 instr_jmp_eq_hh_exec(struct rte_swx_pipeline *p)
6272 struct thread *t = &p->threads[p->thread_id];
6273 struct instruction *ip = t->ip;
6275 TRACE("[Thread %2u] jmpeq (hh)\n", p->thread_id);
6277 JMP_CMP_HH_FAST(t, ip, ==);
6281 instr_jmp_eq_i_exec(struct rte_swx_pipeline *p)
6283 struct thread *t = &p->threads[p->thread_id];
6284 struct instruction *ip = t->ip;
6286 TRACE("[Thread %2u] jmpeq (i)\n", p->thread_id);
6288 JMP_CMP_I(t, ip, ==);
6292 instr_jmp_neq_exec(struct rte_swx_pipeline *p)
6294 struct thread *t = &p->threads[p->thread_id];
6295 struct instruction *ip = t->ip;
6297 TRACE("[Thread %2u] jmpneq\n", p->thread_id);
6303 instr_jmp_neq_mh_exec(struct rte_swx_pipeline *p)
6305 struct thread *t = &p->threads[p->thread_id];
6306 struct instruction *ip = t->ip;
6308 TRACE("[Thread %2u] jmpneq (mh)\n", p->thread_id);
6310 JMP_CMP_MH(t, ip, !=);
6314 instr_jmp_neq_hm_exec(struct rte_swx_pipeline *p)
6316 struct thread *t = &p->threads[p->thread_id];
6317 struct instruction *ip = t->ip;
6319 TRACE("[Thread %2u] jmpneq (hm)\n", p->thread_id);
6321 JMP_CMP_HM(t, ip, !=);
6325 instr_jmp_neq_hh_exec(struct rte_swx_pipeline *p)
6327 struct thread *t = &p->threads[p->thread_id];
6328 struct instruction *ip = t->ip;
6330 TRACE("[Thread %2u] jmpneq (hh)\n", p->thread_id);
6332 JMP_CMP_HH_FAST(t, ip, !=);
6336 instr_jmp_neq_i_exec(struct rte_swx_pipeline *p)
6338 struct thread *t = &p->threads[p->thread_id];
6339 struct instruction *ip = t->ip;
6341 TRACE("[Thread %2u] jmpneq (i)\n", p->thread_id);
6343 JMP_CMP_I(t, ip, !=);
6347 instr_jmp_lt_exec(struct rte_swx_pipeline *p)
6349 struct thread *t = &p->threads[p->thread_id];
6350 struct instruction *ip = t->ip;
6352 TRACE("[Thread %2u] jmplt\n", p->thread_id);
6358 instr_jmp_lt_mh_exec(struct rte_swx_pipeline *p)
6360 struct thread *t = &p->threads[p->thread_id];
6361 struct instruction *ip = t->ip;
6363 TRACE("[Thread %2u] jmplt (mh)\n", p->thread_id);
6365 JMP_CMP_MH(t, ip, <);
6369 instr_jmp_lt_hm_exec(struct rte_swx_pipeline *p)
6371 struct thread *t = &p->threads[p->thread_id];
6372 struct instruction *ip = t->ip;
6374 TRACE("[Thread %2u] jmplt (hm)\n", p->thread_id);
6376 JMP_CMP_HM(t, ip, <);
6380 instr_jmp_lt_hh_exec(struct rte_swx_pipeline *p)
6382 struct thread *t = &p->threads[p->thread_id];
6383 struct instruction *ip = t->ip;
6385 TRACE("[Thread %2u] jmplt (hh)\n", p->thread_id);
6387 JMP_CMP_HH(t, ip, <);
6391 instr_jmp_lt_mi_exec(struct rte_swx_pipeline *p)
6393 struct thread *t = &p->threads[p->thread_id];
6394 struct instruction *ip = t->ip;
6396 TRACE("[Thread %2u] jmplt (mi)\n", p->thread_id);
6398 JMP_CMP_MI(t, ip, <);
6402 instr_jmp_lt_hi_exec(struct rte_swx_pipeline *p)
6404 struct thread *t = &p->threads[p->thread_id];
6405 struct instruction *ip = t->ip;
6407 TRACE("[Thread %2u] jmplt (hi)\n", p->thread_id);
6409 JMP_CMP_HI(t, ip, <);
6413 instr_jmp_gt_exec(struct rte_swx_pipeline *p)
6415 struct thread *t = &p->threads[p->thread_id];
6416 struct instruction *ip = t->ip;
6418 TRACE("[Thread %2u] jmpgt\n", p->thread_id);
6424 instr_jmp_gt_mh_exec(struct rte_swx_pipeline *p)
6426 struct thread *t = &p->threads[p->thread_id];
6427 struct instruction *ip = t->ip;
6429 TRACE("[Thread %2u] jmpgt (mh)\n", p->thread_id);
6431 JMP_CMP_MH(t, ip, >);
6435 instr_jmp_gt_hm_exec(struct rte_swx_pipeline *p)
6437 struct thread *t = &p->threads[p->thread_id];
6438 struct instruction *ip = t->ip;
6440 TRACE("[Thread %2u] jmpgt (hm)\n", p->thread_id);
6442 JMP_CMP_HM(t, ip, >);
6446 instr_jmp_gt_hh_exec(struct rte_swx_pipeline *p)
6448 struct thread *t = &p->threads[p->thread_id];
6449 struct instruction *ip = t->ip;
6451 TRACE("[Thread %2u] jmpgt (hh)\n", p->thread_id);
6453 JMP_CMP_HH(t, ip, >);
6457 instr_jmp_gt_mi_exec(struct rte_swx_pipeline *p)
6459 struct thread *t = &p->threads[p->thread_id];
6460 struct instruction *ip = t->ip;
6462 TRACE("[Thread %2u] jmpgt (mi)\n", p->thread_id);
6464 JMP_CMP_MI(t, ip, >);
6468 instr_jmp_gt_hi_exec(struct rte_swx_pipeline *p)
6470 struct thread *t = &p->threads[p->thread_id];
6471 struct instruction *ip = t->ip;
6473 TRACE("[Thread %2u] jmpgt (hi)\n", p->thread_id);
6475 JMP_CMP_HI(t, ip, >);
6482 instr_return_translate(struct rte_swx_pipeline *p __rte_unused,
6483 struct action *action,
6484 char **tokens __rte_unused,
6486 struct instruction *instr,
6487 struct instruction_data *data __rte_unused)
6489 CHECK(action, EINVAL);
6490 CHECK(n_tokens == 1, EINVAL);
6492 instr->type = INSTR_RETURN;
6497 instr_return_exec(struct rte_swx_pipeline *p)
6499 struct thread *t = &p->threads[p->thread_id];
6501 TRACE("[Thread %2u] return\n", p->thread_id);
6507 instr_translate(struct rte_swx_pipeline *p,
6508 struct action *action,
6510 struct instruction *instr,
6511 struct instruction_data *data)
6513 char *tokens[RTE_SWX_INSTRUCTION_TOKENS_MAX];
6514 int n_tokens = 0, tpos = 0;
6516 /* Parse the instruction string into tokens. */
6520 token = strtok_r(string, " \t\v", &string);
6524 CHECK(n_tokens < RTE_SWX_INSTRUCTION_TOKENS_MAX, EINVAL);
6525 CHECK_NAME(token, EINVAL);
6527 tokens[n_tokens] = token;
6531 CHECK(n_tokens, EINVAL);
6533 /* Handle the optional instruction label. */
6534 if ((n_tokens >= 2) && !strcmp(tokens[1], ":")) {
6535 strcpy(data->label, tokens[0]);
6538 CHECK(n_tokens - tpos, EINVAL);
6541 /* Identify the instruction type. */
6542 if (!strcmp(tokens[tpos], "rx"))
6543 return instr_rx_translate(p,
6550 if (!strcmp(tokens[tpos], "tx"))
6551 return instr_tx_translate(p,
6558 if (!strcmp(tokens[tpos], "drop"))
6559 return instr_drop_translate(p,
6566 if (!strcmp(tokens[tpos], "extract"))
6567 return instr_hdr_extract_translate(p,
6574 if (!strcmp(tokens[tpos], "lookahead"))
6575 return instr_hdr_lookahead_translate(p,
6582 if (!strcmp(tokens[tpos], "emit"))
6583 return instr_hdr_emit_translate(p,
6590 if (!strcmp(tokens[tpos], "validate"))
6591 return instr_hdr_validate_translate(p,
6598 if (!strcmp(tokens[tpos], "invalidate"))
6599 return instr_hdr_invalidate_translate(p,
6606 if (!strcmp(tokens[tpos], "mov"))
6607 return instr_mov_translate(p,
6614 if (!strcmp(tokens[tpos], "add"))
6615 return instr_alu_add_translate(p,
6622 if (!strcmp(tokens[tpos], "sub"))
6623 return instr_alu_sub_translate(p,
6630 if (!strcmp(tokens[tpos], "ckadd"))
6631 return instr_alu_ckadd_translate(p,
6638 if (!strcmp(tokens[tpos], "cksub"))
6639 return instr_alu_cksub_translate(p,
6646 if (!strcmp(tokens[tpos], "and"))
6647 return instr_alu_and_translate(p,
6654 if (!strcmp(tokens[tpos], "or"))
6655 return instr_alu_or_translate(p,
6662 if (!strcmp(tokens[tpos], "xor"))
6663 return instr_alu_xor_translate(p,
6670 if (!strcmp(tokens[tpos], "shl"))
6671 return instr_alu_shl_translate(p,
6678 if (!strcmp(tokens[tpos], "shr"))
6679 return instr_alu_shr_translate(p,
6686 if (!strcmp(tokens[tpos], "regprefetch"))
6687 return instr_regprefetch_translate(p,
6694 if (!strcmp(tokens[tpos], "regrd"))
6695 return instr_regrd_translate(p,
6702 if (!strcmp(tokens[tpos], "regwr"))
6703 return instr_regwr_translate(p,
6710 if (!strcmp(tokens[tpos], "regadd"))
6711 return instr_regadd_translate(p,
6718 if (!strcmp(tokens[tpos], "metprefetch"))
6719 return instr_metprefetch_translate(p,
6726 if (!strcmp(tokens[tpos], "meter"))
6727 return instr_meter_translate(p,
6734 if (!strcmp(tokens[tpos], "table"))
6735 return instr_table_translate(p,
6742 if (!strcmp(tokens[tpos], "learn"))
6743 return instr_learn_translate(p,
6750 if (!strcmp(tokens[tpos], "forget"))
6751 return instr_forget_translate(p,
6758 if (!strcmp(tokens[tpos], "extern"))
6759 return instr_extern_translate(p,
6766 if (!strcmp(tokens[tpos], "jmp"))
6767 return instr_jmp_translate(p,
6774 if (!strcmp(tokens[tpos], "jmpv"))
6775 return instr_jmp_valid_translate(p,
6782 if (!strcmp(tokens[tpos], "jmpnv"))
6783 return instr_jmp_invalid_translate(p,
6790 if (!strcmp(tokens[tpos], "jmph"))
6791 return instr_jmp_hit_translate(p,
6798 if (!strcmp(tokens[tpos], "jmpnh"))
6799 return instr_jmp_miss_translate(p,
6806 if (!strcmp(tokens[tpos], "jmpa"))
6807 return instr_jmp_action_hit_translate(p,
6814 if (!strcmp(tokens[tpos], "jmpna"))
6815 return instr_jmp_action_miss_translate(p,
6822 if (!strcmp(tokens[tpos], "jmpeq"))
6823 return instr_jmp_eq_translate(p,
6830 if (!strcmp(tokens[tpos], "jmpneq"))
6831 return instr_jmp_neq_translate(p,
6838 if (!strcmp(tokens[tpos], "jmplt"))
6839 return instr_jmp_lt_translate(p,
6846 if (!strcmp(tokens[tpos], "jmpgt"))
6847 return instr_jmp_gt_translate(p,
6854 if (!strcmp(tokens[tpos], "return"))
6855 return instr_return_translate(p,
6865 static struct instruction_data *
6866 label_find(struct instruction_data *data, uint32_t n, const char *label)
6870 for (i = 0; i < n; i++)
6871 if (!strcmp(label, data[i].label))
6878 label_is_used(struct instruction_data *data, uint32_t n, const char *label)
6880 uint32_t count = 0, i;
6885 for (i = 0; i < n; i++)
6886 if (!strcmp(label, data[i].jmp_label))
6893 instr_label_check(struct instruction_data *instruction_data,
6894 uint32_t n_instructions)
6898 /* Check that all instruction labels are unique. */
6899 for (i = 0; i < n_instructions; i++) {
6900 struct instruction_data *data = &instruction_data[i];
6901 char *label = data->label;
6907 for (j = i + 1; j < n_instructions; j++)
6908 CHECK(strcmp(label, data[j].label), EINVAL);
6911 /* Get users for each instruction label. */
6912 for (i = 0; i < n_instructions; i++) {
6913 struct instruction_data *data = &instruction_data[i];
6914 char *label = data->label;
6916 data->n_users = label_is_used(instruction_data,
6925 instr_jmp_resolve(struct instruction *instructions,
6926 struct instruction_data *instruction_data,
6927 uint32_t n_instructions)
6931 for (i = 0; i < n_instructions; i++) {
6932 struct instruction *instr = &instructions[i];
6933 struct instruction_data *data = &instruction_data[i];
6934 struct instruction_data *found;
6936 if (!instruction_is_jmp(instr))
6939 found = label_find(instruction_data,
6942 CHECK(found, EINVAL);
6944 instr->jmp.ip = &instructions[found - instruction_data];
6951 instr_verify(struct rte_swx_pipeline *p __rte_unused,
6953 struct instruction *instr,
6954 struct instruction_data *data __rte_unused,
6955 uint32_t n_instructions)
6958 enum instruction_type type;
6961 /* Check that the first instruction is rx. */
6962 CHECK(instr[0].type == INSTR_RX, EINVAL);
6964 /* Check that there is at least one tx instruction. */
6965 for (i = 0; i < n_instructions; i++) {
6966 type = instr[i].type;
6968 if (instruction_is_tx(type))
6971 CHECK(i < n_instructions, EINVAL);
6973 /* Check that the last instruction is either tx or unconditional
6976 type = instr[n_instructions - 1].type;
6977 CHECK(instruction_is_tx(type) || (type == INSTR_JMP), EINVAL);
6981 enum instruction_type type;
6984 /* Check that there is at least one return or tx instruction. */
6985 for (i = 0; i < n_instructions; i++) {
6986 type = instr[i].type;
6988 if ((type == INSTR_RETURN) || instruction_is_tx(type))
6991 CHECK(i < n_instructions, EINVAL);
6998 instr_compact(struct instruction *instructions,
6999 struct instruction_data *instruction_data,
7000 uint32_t n_instructions)
7002 uint32_t i, pos = 0;
7004 /* Eliminate the invalid instructions that have been optimized out. */
7005 for (i = 0; i < n_instructions; i++) {
7006 struct instruction *instr = &instructions[i];
7007 struct instruction_data *data = &instruction_data[i];
7013 memcpy(&instructions[pos], instr, sizeof(*instr));
7014 memcpy(&instruction_data[pos], data, sizeof(*data));
7024 instr_pattern_extract_many_search(struct instruction *instr,
7025 struct instruction_data *data,
7027 uint32_t *n_pattern_instr)
7031 for (i = 0; i < n_instr; i++) {
7032 if (data[i].invalid)
7035 if (instr[i].type != INSTR_HDR_EXTRACT)
7038 if (i == RTE_DIM(instr->io.hdr.header_id))
7041 if (i && data[i].n_users)
7048 *n_pattern_instr = i;
7053 instr_pattern_extract_many_replace(struct instruction *instr,
7054 struct instruction_data *data,
7059 for (i = 1; i < n_instr; i++) {
7061 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
7062 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
7063 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
7065 data[i].invalid = 1;
7070 instr_pattern_extract_many_optimize(struct instruction *instructions,
7071 struct instruction_data *instruction_data,
7072 uint32_t n_instructions)
7076 for (i = 0; i < n_instructions; ) {
7077 struct instruction *instr = &instructions[i];
7078 struct instruction_data *data = &instruction_data[i];
7079 uint32_t n_instr = 0;
7083 detected = instr_pattern_extract_many_search(instr,
7088 instr_pattern_extract_many_replace(instr,
7095 /* No pattern starting at the current instruction. */
7099 /* Eliminate the invalid instructions that have been optimized out. */
7100 n_instructions = instr_compact(instructions,
7104 return n_instructions;
7108 instr_pattern_emit_many_tx_search(struct instruction *instr,
7109 struct instruction_data *data,
7111 uint32_t *n_pattern_instr)
7115 for (i = 0; i < n_instr; i++) {
7116 if (data[i].invalid)
7119 if (instr[i].type != INSTR_HDR_EMIT)
7122 if (i == RTE_DIM(instr->io.hdr.header_id))
7125 if (i && data[i].n_users)
7132 if (!instruction_is_tx(instr[i].type))
7135 if (data[i].n_users)
7140 *n_pattern_instr = i;
7145 instr_pattern_emit_many_tx_replace(struct instruction *instr,
7146 struct instruction_data *data,
7151 /* Any emit instruction in addition to the first one. */
7152 for (i = 1; i < n_instr - 1; i++) {
7154 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
7155 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
7156 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
7158 data[i].invalid = 1;
7161 /* The TX instruction is the last one in the pattern. */
7163 instr[0].io.io.offset = instr[i].io.io.offset;
7164 instr[0].io.io.n_bits = instr[i].io.io.n_bits;
7165 data[i].invalid = 1;
7169 instr_pattern_emit_many_tx_optimize(struct instruction *instructions,
7170 struct instruction_data *instruction_data,
7171 uint32_t n_instructions)
7175 for (i = 0; i < n_instructions; ) {
7176 struct instruction *instr = &instructions[i];
7177 struct instruction_data *data = &instruction_data[i];
7178 uint32_t n_instr = 0;
7181 /* Emit many + TX. */
7182 detected = instr_pattern_emit_many_tx_search(instr,
7187 instr_pattern_emit_many_tx_replace(instr,
7194 /* No pattern starting at the current instruction. */
7198 /* Eliminate the invalid instructions that have been optimized out. */
7199 n_instructions = instr_compact(instructions,
7203 return n_instructions;
7207 action_arg_src_mov_count(struct action *a,
7209 struct instruction *instructions,
7210 struct instruction_data *instruction_data,
7211 uint32_t n_instructions);
7214 instr_pattern_mov_all_validate_search(struct rte_swx_pipeline *p,
7216 struct instruction *instr,
7217 struct instruction_data *data,
7219 struct instruction *instructions,
7220 struct instruction_data *instruction_data,
7221 uint32_t n_instructions,
7222 uint32_t *n_pattern_instr)
7225 uint32_t src_field_id, i, j;
7227 /* Prerequisites. */
7231 /* First instruction: MOV_HM. */
7232 if (data[0].invalid || (instr[0].type != INSTR_MOV_HM))
7235 h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
7236 if (!h || h->st->var_size)
7239 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
7240 if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
7243 if (src_field_id == a->st->n_fields)
7246 if (instr[0].mov.dst.offset ||
7247 (instr[0].mov.dst.n_bits != h->st->fields[0].n_bits) ||
7248 instr[0].mov.src.struct_id ||
7249 (instr[0].mov.src.n_bits != a->st->fields[src_field_id].n_bits) ||
7250 (instr[0].mov.dst.n_bits != instr[0].mov.src.n_bits))
7253 if ((n_instr < h->st->n_fields + 1) ||
7254 (a->st->n_fields < src_field_id + h->st->n_fields + 1))
7257 /* Subsequent instructions: MOV_HM. */
7258 for (i = 1; i < h->st->n_fields; i++)
7259 if (data[i].invalid ||
7261 (instr[i].type != INSTR_MOV_HM) ||
7262 (instr[i].mov.dst.struct_id != h->struct_id) ||
7263 (instr[i].mov.dst.offset != h->st->fields[i].offset / 8) ||
7264 (instr[i].mov.dst.n_bits != h->st->fields[i].n_bits) ||
7265 instr[i].mov.src.struct_id ||
7266 (instr[i].mov.src.offset != a->st->fields[src_field_id + i].offset / 8) ||
7267 (instr[i].mov.src.n_bits != a->st->fields[src_field_id + i].n_bits) ||
7268 (instr[i].mov.dst.n_bits != instr[i].mov.src.n_bits))
7271 /* Last instruction: HDR_VALIDATE. */
7272 if ((instr[i].type != INSTR_HDR_VALIDATE) ||
7273 (instr[i].valid.header_id != h->id))
7276 /* Check that none of the action args that are used as source for this
7277 * DMA transfer are not used as source in any other mov instruction.
7279 for (j = src_field_id; j < src_field_id + h->st->n_fields; j++) {
7282 n_users = action_arg_src_mov_count(a,
7291 *n_pattern_instr = 1 + i;
7296 instr_pattern_mov_all_validate_replace(struct rte_swx_pipeline *p,
7298 struct instruction *instr,
7299 struct instruction_data *data,
7303 uint32_t src_field_id, src_offset, i;
7305 /* Read from the instructions before they are modified. */
7306 h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
7310 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
7311 if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
7314 if (src_field_id == a->st->n_fields)
7317 src_offset = instr[0].mov.src.offset;
7319 /* Modify the instructions. */
7320 instr[0].type = INSTR_DMA_HT;
7321 instr[0].dma.dst.header_id[0] = h->id;
7322 instr[0].dma.dst.struct_id[0] = h->struct_id;
7323 instr[0].dma.src.offset[0] = (uint8_t)src_offset;
7324 instr[0].dma.n_bytes[0] = h->st->n_bits / 8;
7326 for (i = 1; i < n_instr; i++)
7327 data[i].invalid = 1;
7329 /* Update the endianness of the action arguments to header endianness. */
7330 for (i = 0; i < h->st->n_fields; i++)
7331 a->args_endianness[src_field_id + i] = 1;
7335 instr_pattern_mov_all_validate_optimize(struct rte_swx_pipeline *p,
7337 struct instruction *instructions,
7338 struct instruction_data *instruction_data,
7339 uint32_t n_instructions)
7344 return n_instructions;
7346 for (i = 0; i < n_instructions; ) {
7347 struct instruction *instr = &instructions[i];
7348 struct instruction_data *data = &instruction_data[i];
7349 uint32_t n_instr = 0;
7352 /* Mov all + validate. */
7353 detected = instr_pattern_mov_all_validate_search(p,
7363 instr_pattern_mov_all_validate_replace(p, a, instr, data, n_instr);
7368 /* No pattern starting at the current instruction. */
7372 /* Eliminate the invalid instructions that have been optimized out. */
7373 n_instructions = instr_compact(instructions,
7377 return n_instructions;
7381 instr_pattern_dma_many_search(struct instruction *instr,
7382 struct instruction_data *data,
7384 uint32_t *n_pattern_instr)
7388 for (i = 0; i < n_instr; i++) {
7389 if (data[i].invalid)
7392 if (instr[i].type != INSTR_DMA_HT)
7395 if (i == RTE_DIM(instr->dma.dst.header_id))
7398 if (i && data[i].n_users)
7405 *n_pattern_instr = i;
7410 instr_pattern_dma_many_replace(struct instruction *instr,
7411 struct instruction_data *data,
7416 for (i = 1; i < n_instr; i++) {
7418 instr[0].dma.dst.header_id[i] = instr[i].dma.dst.header_id[0];
7419 instr[0].dma.dst.struct_id[i] = instr[i].dma.dst.struct_id[0];
7420 instr[0].dma.src.offset[i] = instr[i].dma.src.offset[0];
7421 instr[0].dma.n_bytes[i] = instr[i].dma.n_bytes[0];
7423 data[i].invalid = 1;
7428 instr_pattern_dma_many_optimize(struct instruction *instructions,
7429 struct instruction_data *instruction_data,
7430 uint32_t n_instructions)
7434 for (i = 0; i < n_instructions; ) {
7435 struct instruction *instr = &instructions[i];
7436 struct instruction_data *data = &instruction_data[i];
7437 uint32_t n_instr = 0;
7441 detected = instr_pattern_dma_many_search(instr,
7446 instr_pattern_dma_many_replace(instr, data, n_instr);
7451 /* No pattern starting at the current instruction. */
7455 /* Eliminate the invalid instructions that have been optimized out. */
7456 n_instructions = instr_compact(instructions,
7460 return n_instructions;
7464 instr_optimize(struct rte_swx_pipeline *p,
7466 struct instruction *instructions,
7467 struct instruction_data *instruction_data,
7468 uint32_t n_instructions)
7471 n_instructions = instr_pattern_extract_many_optimize(instructions,
7475 /* Emit many + TX. */
7476 n_instructions = instr_pattern_emit_many_tx_optimize(instructions,
7480 /* Mov all + validate. */
7481 n_instructions = instr_pattern_mov_all_validate_optimize(p,
7488 n_instructions = instr_pattern_dma_many_optimize(instructions,
7492 return n_instructions;
7496 instruction_config(struct rte_swx_pipeline *p,
7498 const char **instructions,
7499 uint32_t n_instructions)
7501 struct instruction *instr = NULL;
7502 struct instruction_data *data = NULL;
7506 CHECK(n_instructions, EINVAL);
7507 CHECK(instructions, EINVAL);
7508 for (i = 0; i < n_instructions; i++)
7509 CHECK_INSTRUCTION(instructions[i], EINVAL);
7511 /* Memory allocation. */
7512 instr = calloc(n_instructions, sizeof(struct instruction));
7518 data = calloc(n_instructions, sizeof(struct instruction_data));
7524 for (i = 0; i < n_instructions; i++) {
7525 char *string = strdup(instructions[i]);
7531 err = instr_translate(p, a, string, &instr[i], &data[i]);
7540 err = instr_label_check(data, n_instructions);
7544 err = instr_verify(p, a, instr, data, n_instructions);
7548 n_instructions = instr_optimize(p, a, instr, data, n_instructions);
7550 err = instr_jmp_resolve(instr, data, n_instructions);
7555 a->instructions = instr;
7556 a->n_instructions = n_instructions;
7558 p->instructions = instr;
7559 p->n_instructions = n_instructions;
7571 typedef void (*instr_exec_t)(struct rte_swx_pipeline *);
7573 static instr_exec_t instruction_table[] = {
7574 [INSTR_RX] = instr_rx_exec,
7575 [INSTR_TX] = instr_tx_exec,
7576 [INSTR_TX_I] = instr_tx_i_exec,
7578 [INSTR_HDR_EXTRACT] = instr_hdr_extract_exec,
7579 [INSTR_HDR_EXTRACT2] = instr_hdr_extract2_exec,
7580 [INSTR_HDR_EXTRACT3] = instr_hdr_extract3_exec,
7581 [INSTR_HDR_EXTRACT4] = instr_hdr_extract4_exec,
7582 [INSTR_HDR_EXTRACT5] = instr_hdr_extract5_exec,
7583 [INSTR_HDR_EXTRACT6] = instr_hdr_extract6_exec,
7584 [INSTR_HDR_EXTRACT7] = instr_hdr_extract7_exec,
7585 [INSTR_HDR_EXTRACT8] = instr_hdr_extract8_exec,
7586 [INSTR_HDR_EXTRACT_M] = instr_hdr_extract_m_exec,
7587 [INSTR_HDR_LOOKAHEAD] = instr_hdr_lookahead_exec,
7589 [INSTR_HDR_EMIT] = instr_hdr_emit_exec,
7590 [INSTR_HDR_EMIT_TX] = instr_hdr_emit_tx_exec,
7591 [INSTR_HDR_EMIT2_TX] = instr_hdr_emit2_tx_exec,
7592 [INSTR_HDR_EMIT3_TX] = instr_hdr_emit3_tx_exec,
7593 [INSTR_HDR_EMIT4_TX] = instr_hdr_emit4_tx_exec,
7594 [INSTR_HDR_EMIT5_TX] = instr_hdr_emit5_tx_exec,
7595 [INSTR_HDR_EMIT6_TX] = instr_hdr_emit6_tx_exec,
7596 [INSTR_HDR_EMIT7_TX] = instr_hdr_emit7_tx_exec,
7597 [INSTR_HDR_EMIT8_TX] = instr_hdr_emit8_tx_exec,
7599 [INSTR_HDR_VALIDATE] = instr_hdr_validate_exec,
7600 [INSTR_HDR_INVALIDATE] = instr_hdr_invalidate_exec,
7602 [INSTR_MOV] = instr_mov_exec,
7603 [INSTR_MOV_MH] = instr_mov_mh_exec,
7604 [INSTR_MOV_HM] = instr_mov_hm_exec,
7605 [INSTR_MOV_HH] = instr_mov_hh_exec,
7606 [INSTR_MOV_I] = instr_mov_i_exec,
7608 [INSTR_DMA_HT] = instr_dma_ht_exec,
7609 [INSTR_DMA_HT2] = instr_dma_ht2_exec,
7610 [INSTR_DMA_HT3] = instr_dma_ht3_exec,
7611 [INSTR_DMA_HT4] = instr_dma_ht4_exec,
7612 [INSTR_DMA_HT5] = instr_dma_ht5_exec,
7613 [INSTR_DMA_HT6] = instr_dma_ht6_exec,
7614 [INSTR_DMA_HT7] = instr_dma_ht7_exec,
7615 [INSTR_DMA_HT8] = instr_dma_ht8_exec,
7617 [INSTR_ALU_ADD] = instr_alu_add_exec,
7618 [INSTR_ALU_ADD_MH] = instr_alu_add_mh_exec,
7619 [INSTR_ALU_ADD_HM] = instr_alu_add_hm_exec,
7620 [INSTR_ALU_ADD_HH] = instr_alu_add_hh_exec,
7621 [INSTR_ALU_ADD_MI] = instr_alu_add_mi_exec,
7622 [INSTR_ALU_ADD_HI] = instr_alu_add_hi_exec,
7624 [INSTR_ALU_SUB] = instr_alu_sub_exec,
7625 [INSTR_ALU_SUB_MH] = instr_alu_sub_mh_exec,
7626 [INSTR_ALU_SUB_HM] = instr_alu_sub_hm_exec,
7627 [INSTR_ALU_SUB_HH] = instr_alu_sub_hh_exec,
7628 [INSTR_ALU_SUB_MI] = instr_alu_sub_mi_exec,
7629 [INSTR_ALU_SUB_HI] = instr_alu_sub_hi_exec,
7631 [INSTR_ALU_CKADD_FIELD] = instr_alu_ckadd_field_exec,
7632 [INSTR_ALU_CKADD_STRUCT] = instr_alu_ckadd_struct_exec,
7633 [INSTR_ALU_CKADD_STRUCT20] = instr_alu_ckadd_struct20_exec,
7634 [INSTR_ALU_CKSUB_FIELD] = instr_alu_cksub_field_exec,
7636 [INSTR_ALU_AND] = instr_alu_and_exec,
7637 [INSTR_ALU_AND_MH] = instr_alu_and_mh_exec,
7638 [INSTR_ALU_AND_HM] = instr_alu_and_hm_exec,
7639 [INSTR_ALU_AND_HH] = instr_alu_and_hh_exec,
7640 [INSTR_ALU_AND_I] = instr_alu_and_i_exec,
7642 [INSTR_ALU_OR] = instr_alu_or_exec,
7643 [INSTR_ALU_OR_MH] = instr_alu_or_mh_exec,
7644 [INSTR_ALU_OR_HM] = instr_alu_or_hm_exec,
7645 [INSTR_ALU_OR_HH] = instr_alu_or_hh_exec,
7646 [INSTR_ALU_OR_I] = instr_alu_or_i_exec,
7648 [INSTR_ALU_XOR] = instr_alu_xor_exec,
7649 [INSTR_ALU_XOR_MH] = instr_alu_xor_mh_exec,
7650 [INSTR_ALU_XOR_HM] = instr_alu_xor_hm_exec,
7651 [INSTR_ALU_XOR_HH] = instr_alu_xor_hh_exec,
7652 [INSTR_ALU_XOR_I] = instr_alu_xor_i_exec,
7654 [INSTR_ALU_SHL] = instr_alu_shl_exec,
7655 [INSTR_ALU_SHL_MH] = instr_alu_shl_mh_exec,
7656 [INSTR_ALU_SHL_HM] = instr_alu_shl_hm_exec,
7657 [INSTR_ALU_SHL_HH] = instr_alu_shl_hh_exec,
7658 [INSTR_ALU_SHL_MI] = instr_alu_shl_mi_exec,
7659 [INSTR_ALU_SHL_HI] = instr_alu_shl_hi_exec,
7661 [INSTR_ALU_SHR] = instr_alu_shr_exec,
7662 [INSTR_ALU_SHR_MH] = instr_alu_shr_mh_exec,
7663 [INSTR_ALU_SHR_HM] = instr_alu_shr_hm_exec,
7664 [INSTR_ALU_SHR_HH] = instr_alu_shr_hh_exec,
7665 [INSTR_ALU_SHR_MI] = instr_alu_shr_mi_exec,
7666 [INSTR_ALU_SHR_HI] = instr_alu_shr_hi_exec,
7668 [INSTR_REGPREFETCH_RH] = instr_regprefetch_rh_exec,
7669 [INSTR_REGPREFETCH_RM] = instr_regprefetch_rm_exec,
7670 [INSTR_REGPREFETCH_RI] = instr_regprefetch_ri_exec,
7672 [INSTR_REGRD_HRH] = instr_regrd_hrh_exec,
7673 [INSTR_REGRD_HRM] = instr_regrd_hrm_exec,
7674 [INSTR_REGRD_MRH] = instr_regrd_mrh_exec,
7675 [INSTR_REGRD_MRM] = instr_regrd_mrm_exec,
7676 [INSTR_REGRD_HRI] = instr_regrd_hri_exec,
7677 [INSTR_REGRD_MRI] = instr_regrd_mri_exec,
7679 [INSTR_REGWR_RHH] = instr_regwr_rhh_exec,
7680 [INSTR_REGWR_RHM] = instr_regwr_rhm_exec,
7681 [INSTR_REGWR_RMH] = instr_regwr_rmh_exec,
7682 [INSTR_REGWR_RMM] = instr_regwr_rmm_exec,
7683 [INSTR_REGWR_RHI] = instr_regwr_rhi_exec,
7684 [INSTR_REGWR_RMI] = instr_regwr_rmi_exec,
7685 [INSTR_REGWR_RIH] = instr_regwr_rih_exec,
7686 [INSTR_REGWR_RIM] = instr_regwr_rim_exec,
7687 [INSTR_REGWR_RII] = instr_regwr_rii_exec,
7689 [INSTR_REGADD_RHH] = instr_regadd_rhh_exec,
7690 [INSTR_REGADD_RHM] = instr_regadd_rhm_exec,
7691 [INSTR_REGADD_RMH] = instr_regadd_rmh_exec,
7692 [INSTR_REGADD_RMM] = instr_regadd_rmm_exec,
7693 [INSTR_REGADD_RHI] = instr_regadd_rhi_exec,
7694 [INSTR_REGADD_RMI] = instr_regadd_rmi_exec,
7695 [INSTR_REGADD_RIH] = instr_regadd_rih_exec,
7696 [INSTR_REGADD_RIM] = instr_regadd_rim_exec,
7697 [INSTR_REGADD_RII] = instr_regadd_rii_exec,
7699 [INSTR_METPREFETCH_H] = instr_metprefetch_h_exec,
7700 [INSTR_METPREFETCH_M] = instr_metprefetch_m_exec,
7701 [INSTR_METPREFETCH_I] = instr_metprefetch_i_exec,
7703 [INSTR_METER_HHM] = instr_meter_hhm_exec,
7704 [INSTR_METER_HHI] = instr_meter_hhi_exec,
7705 [INSTR_METER_HMM] = instr_meter_hmm_exec,
7706 [INSTR_METER_HMI] = instr_meter_hmi_exec,
7707 [INSTR_METER_MHM] = instr_meter_mhm_exec,
7708 [INSTR_METER_MHI] = instr_meter_mhi_exec,
7709 [INSTR_METER_MMM] = instr_meter_mmm_exec,
7710 [INSTR_METER_MMI] = instr_meter_mmi_exec,
7711 [INSTR_METER_IHM] = instr_meter_ihm_exec,
7712 [INSTR_METER_IHI] = instr_meter_ihi_exec,
7713 [INSTR_METER_IMM] = instr_meter_imm_exec,
7714 [INSTR_METER_IMI] = instr_meter_imi_exec,
7716 [INSTR_TABLE] = instr_table_exec,
7717 [INSTR_SELECTOR] = instr_selector_exec,
7718 [INSTR_LEARNER] = instr_learner_exec,
7719 [INSTR_LEARNER_LEARN] = instr_learn_exec,
7720 [INSTR_LEARNER_FORGET] = instr_forget_exec,
7721 [INSTR_EXTERN_OBJ] = instr_extern_obj_exec,
7722 [INSTR_EXTERN_FUNC] = instr_extern_func_exec,
7724 [INSTR_JMP] = instr_jmp_exec,
7725 [INSTR_JMP_VALID] = instr_jmp_valid_exec,
7726 [INSTR_JMP_INVALID] = instr_jmp_invalid_exec,
7727 [INSTR_JMP_HIT] = instr_jmp_hit_exec,
7728 [INSTR_JMP_MISS] = instr_jmp_miss_exec,
7729 [INSTR_JMP_ACTION_HIT] = instr_jmp_action_hit_exec,
7730 [INSTR_JMP_ACTION_MISS] = instr_jmp_action_miss_exec,
7732 [INSTR_JMP_EQ] = instr_jmp_eq_exec,
7733 [INSTR_JMP_EQ_MH] = instr_jmp_eq_mh_exec,
7734 [INSTR_JMP_EQ_HM] = instr_jmp_eq_hm_exec,
7735 [INSTR_JMP_EQ_HH] = instr_jmp_eq_hh_exec,
7736 [INSTR_JMP_EQ_I] = instr_jmp_eq_i_exec,
7738 [INSTR_JMP_NEQ] = instr_jmp_neq_exec,
7739 [INSTR_JMP_NEQ_MH] = instr_jmp_neq_mh_exec,
7740 [INSTR_JMP_NEQ_HM] = instr_jmp_neq_hm_exec,
7741 [INSTR_JMP_NEQ_HH] = instr_jmp_neq_hh_exec,
7742 [INSTR_JMP_NEQ_I] = instr_jmp_neq_i_exec,
7744 [INSTR_JMP_LT] = instr_jmp_lt_exec,
7745 [INSTR_JMP_LT_MH] = instr_jmp_lt_mh_exec,
7746 [INSTR_JMP_LT_HM] = instr_jmp_lt_hm_exec,
7747 [INSTR_JMP_LT_HH] = instr_jmp_lt_hh_exec,
7748 [INSTR_JMP_LT_MI] = instr_jmp_lt_mi_exec,
7749 [INSTR_JMP_LT_HI] = instr_jmp_lt_hi_exec,
7751 [INSTR_JMP_GT] = instr_jmp_gt_exec,
7752 [INSTR_JMP_GT_MH] = instr_jmp_gt_mh_exec,
7753 [INSTR_JMP_GT_HM] = instr_jmp_gt_hm_exec,
7754 [INSTR_JMP_GT_HH] = instr_jmp_gt_hh_exec,
7755 [INSTR_JMP_GT_MI] = instr_jmp_gt_mi_exec,
7756 [INSTR_JMP_GT_HI] = instr_jmp_gt_hi_exec,
7758 [INSTR_RETURN] = instr_return_exec,
7762 instr_exec(struct rte_swx_pipeline *p)
7764 struct thread *t = &p->threads[p->thread_id];
7765 struct instruction *ip = t->ip;
7766 instr_exec_t instr = instruction_table[ip->type];
7774 static struct action *
7775 action_find(struct rte_swx_pipeline *p, const char *name)
7777 struct action *elem;
7782 TAILQ_FOREACH(elem, &p->actions, node)
7783 if (strcmp(elem->name, name) == 0)
7789 static struct action *
7790 action_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7792 struct action *action = NULL;
7794 TAILQ_FOREACH(action, &p->actions, node)
7795 if (action->id == id)
7801 static struct field *
7802 action_field_find(struct action *a, const char *name)
7804 return a->st ? struct_type_field_find(a->st, name) : NULL;
7807 static struct field *
7808 action_field_parse(struct action *action, const char *name)
7810 if (name[0] != 't' || name[1] != '.')
7813 return action_field_find(action, &name[2]);
7817 action_has_nbo_args(struct action *a)
7821 /* Return if the action does not have any args. */
7823 return 0; /* FALSE */
7825 for (i = 0; i < a->st->n_fields; i++)
7826 if (a->args_endianness[i])
7827 return 1; /* TRUE */
7829 return 0; /* FALSE */
7833 action_does_learning(struct action *a)
7837 for (i = 0; i < a->n_instructions; i++)
7838 switch (a->instructions[i].type) {
7839 case INSTR_LEARNER_LEARN:
7840 return 1; /* TRUE */
7842 case INSTR_LEARNER_FORGET:
7843 return 1; /* TRUE */
7849 return 0; /* FALSE */
7853 rte_swx_pipeline_action_config(struct rte_swx_pipeline *p,
7855 const char *args_struct_type_name,
7856 const char **instructions,
7857 uint32_t n_instructions)
7859 struct struct_type *args_struct_type = NULL;
7865 CHECK_NAME(name, EINVAL);
7866 CHECK(!action_find(p, name), EEXIST);
7868 if (args_struct_type_name) {
7869 CHECK_NAME(args_struct_type_name, EINVAL);
7870 args_struct_type = struct_type_find(p, args_struct_type_name);
7871 CHECK(args_struct_type, EINVAL);
7872 CHECK(!args_struct_type->var_size, EINVAL);
7875 /* Node allocation. */
7876 a = calloc(1, sizeof(struct action));
7878 if (args_struct_type) {
7879 a->args_endianness = calloc(args_struct_type->n_fields, sizeof(int));
7880 if (!a->args_endianness) {
7886 /* Node initialization. */
7887 strcpy(a->name, name);
7888 a->st = args_struct_type;
7889 a->id = p->n_actions;
7891 /* Instruction translation. */
7892 err = instruction_config(p, a, instructions, n_instructions);
7894 free(a->args_endianness);
7899 /* Node add to tailq. */
7900 TAILQ_INSERT_TAIL(&p->actions, a, node);
7907 action_build(struct rte_swx_pipeline *p)
7909 struct action *action;
7911 p->action_instructions = calloc(p->n_actions,
7912 sizeof(struct instruction *));
7913 CHECK(p->action_instructions, ENOMEM);
7915 TAILQ_FOREACH(action, &p->actions, node)
7916 p->action_instructions[action->id] = action->instructions;
7922 action_build_free(struct rte_swx_pipeline *p)
7924 free(p->action_instructions);
7925 p->action_instructions = NULL;
7929 action_free(struct rte_swx_pipeline *p)
7931 action_build_free(p);
7934 struct action *action;
7936 action = TAILQ_FIRST(&p->actions);
7940 TAILQ_REMOVE(&p->actions, action, node);
7941 free(action->instructions);
7947 action_arg_src_mov_count(struct action *a,
7949 struct instruction *instructions,
7950 struct instruction_data *instruction_data,
7951 uint32_t n_instructions)
7953 uint32_t offset, n_users = 0, i;
7956 (arg_id >= a->st->n_fields) ||
7958 !instruction_data ||
7962 offset = a->st->fields[arg_id].offset / 8;
7964 for (i = 0; i < n_instructions; i++) {
7965 struct instruction *instr = &instructions[i];
7966 struct instruction_data *data = &instruction_data[i];
7968 if (data->invalid ||
7969 ((instr->type != INSTR_MOV) && (instr->type != INSTR_MOV_HM)) ||
7970 instr->mov.src.struct_id ||
7971 (instr->mov.src.offset != offset))
7983 static struct table_type *
7984 table_type_find(struct rte_swx_pipeline *p, const char *name)
7986 struct table_type *elem;
7988 TAILQ_FOREACH(elem, &p->table_types, node)
7989 if (strcmp(elem->name, name) == 0)
7995 static struct table_type *
7996 table_type_resolve(struct rte_swx_pipeline *p,
7997 const char *recommended_type_name,
7998 enum rte_swx_table_match_type match_type)
8000 struct table_type *elem;
8002 /* Only consider the recommended type if the match type is correct. */
8003 if (recommended_type_name)
8004 TAILQ_FOREACH(elem, &p->table_types, node)
8005 if (!strcmp(elem->name, recommended_type_name) &&
8006 (elem->match_type == match_type))
8009 /* Ignore the recommended type and get the first element with this match
8012 TAILQ_FOREACH(elem, &p->table_types, node)
8013 if (elem->match_type == match_type)
8019 static struct table *
8020 table_find(struct rte_swx_pipeline *p, const char *name)
8024 TAILQ_FOREACH(elem, &p->tables, node)
8025 if (strcmp(elem->name, name) == 0)
8031 static struct table *
8032 table_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8034 struct table *table = NULL;
8036 TAILQ_FOREACH(table, &p->tables, node)
8037 if (table->id == id)
8044 rte_swx_pipeline_table_type_register(struct rte_swx_pipeline *p,
8046 enum rte_swx_table_match_type match_type,
8047 struct rte_swx_table_ops *ops)
8049 struct table_type *elem;
8053 CHECK_NAME(name, EINVAL);
8054 CHECK(!table_type_find(p, name), EEXIST);
8057 CHECK(ops->create, EINVAL);
8058 CHECK(ops->lkp, EINVAL);
8059 CHECK(ops->free, EINVAL);
8061 /* Node allocation. */
8062 elem = calloc(1, sizeof(struct table_type));
8063 CHECK(elem, ENOMEM);
8065 /* Node initialization. */
8066 strcpy(elem->name, name);
8067 elem->match_type = match_type;
8068 memcpy(&elem->ops, ops, sizeof(*ops));
8070 /* Node add to tailq. */
8071 TAILQ_INSERT_TAIL(&p->table_types, elem, node);
8077 table_match_type_resolve(struct rte_swx_match_field_params *fields,
8079 enum rte_swx_table_match_type *match_type)
8081 uint32_t n_fields_em = 0, n_fields_lpm = 0, i;
8083 for (i = 0; i < n_fields; i++) {
8084 struct rte_swx_match_field_params *f = &fields[i];
8086 if (f->match_type == RTE_SWX_TABLE_MATCH_EXACT)
8089 if (f->match_type == RTE_SWX_TABLE_MATCH_LPM)
8093 if ((n_fields_lpm > 1) ||
8094 (n_fields_lpm && (n_fields_em != n_fields - 1)))
8097 *match_type = (n_fields_em == n_fields) ?
8098 RTE_SWX_TABLE_MATCH_EXACT :
8099 RTE_SWX_TABLE_MATCH_WILDCARD;
8105 table_match_fields_check(struct rte_swx_pipeline *p,
8106 struct rte_swx_pipeline_table_params *params,
8107 struct header **header)
8109 struct header *h0 = NULL;
8110 struct field *hf, *mf;
8111 uint32_t *offset = NULL, i;
8114 /* Return if no match fields. */
8115 if (!params->n_fields) {
8116 if (params->fields) {
8127 /* Memory allocation. */
8128 offset = calloc(params->n_fields, sizeof(uint32_t));
8134 /* Check that all the match fields belong to either the same header or
8137 hf = header_field_parse(p, params->fields[0].name, &h0);
8138 mf = metadata_field_parse(p, params->fields[0].name);
8139 if ((!hf && !mf) || (hf && hf->var_size)) {
8144 offset[0] = h0 ? hf->offset : mf->offset;
8146 for (i = 1; i < params->n_fields; i++)
8150 hf = header_field_parse(p, params->fields[i].name, &h);
8151 if (!hf || (h->id != h0->id) || hf->var_size) {
8156 offset[i] = hf->offset;
8158 mf = metadata_field_parse(p, params->fields[i].name);
8164 offset[i] = mf->offset;
8167 /* Check that there are no duplicated match fields. */
8168 for (i = 0; i < params->n_fields; i++) {
8171 for (j = 0; j < i; j++)
8172 if (offset[j] == offset[i]) {
8188 rte_swx_pipeline_table_config(struct rte_swx_pipeline *p,
8190 struct rte_swx_pipeline_table_params *params,
8191 const char *recommended_table_type_name,
8195 struct table_type *type;
8197 struct action *default_action;
8198 struct header *header = NULL;
8199 uint32_t action_data_size_max = 0, i;
8204 CHECK_NAME(name, EINVAL);
8205 CHECK(!table_find(p, name), EEXIST);
8206 CHECK(!selector_find(p, name), EEXIST);
8207 CHECK(!learner_find(p, name), EEXIST);
8209 CHECK(params, EINVAL);
8212 status = table_match_fields_check(p, params, &header);
8216 /* Action checks. */
8217 CHECK(params->n_actions, EINVAL);
8218 CHECK(params->action_names, EINVAL);
8219 for (i = 0; i < params->n_actions; i++) {
8220 const char *action_name = params->action_names[i];
8222 uint32_t action_data_size;
8224 CHECK_NAME(action_name, EINVAL);
8226 a = action_find(p, action_name);
8228 CHECK(!action_does_learning(a), EINVAL);
8230 action_data_size = a->st ? a->st->n_bits / 8 : 0;
8231 if (action_data_size > action_data_size_max)
8232 action_data_size_max = action_data_size;
8235 CHECK_NAME(params->default_action_name, EINVAL);
8236 for (i = 0; i < p->n_actions; i++)
8237 if (!strcmp(params->action_names[i],
8238 params->default_action_name))
8240 CHECK(i < params->n_actions, EINVAL);
8241 default_action = action_find(p, params->default_action_name);
8242 CHECK((default_action->st && params->default_action_data) ||
8243 !params->default_action_data, EINVAL);
8245 /* Table type checks. */
8246 if (recommended_table_type_name)
8247 CHECK_NAME(recommended_table_type_name, EINVAL);
8249 if (params->n_fields) {
8250 enum rte_swx_table_match_type match_type;
8252 status = table_match_type_resolve(params->fields, params->n_fields, &match_type);
8256 type = table_type_resolve(p, recommended_table_type_name, match_type);
8257 CHECK(type, EINVAL);
8262 /* Memory allocation. */
8263 t = calloc(1, sizeof(struct table));
8266 t->fields = calloc(params->n_fields, sizeof(struct match_field));
8272 t->actions = calloc(params->n_actions, sizeof(struct action *));
8279 if (action_data_size_max) {
8280 t->default_action_data = calloc(1, action_data_size_max);
8281 if (!t->default_action_data) {
8289 /* Node initialization. */
8290 strcpy(t->name, name);
8291 if (args && args[0])
8292 strcpy(t->args, args);
8295 for (i = 0; i < params->n_fields; i++) {
8296 struct rte_swx_match_field_params *field = ¶ms->fields[i];
8297 struct match_field *f = &t->fields[i];
8299 f->match_type = field->match_type;
8301 header_field_parse(p, field->name, NULL) :
8302 metadata_field_parse(p, field->name);
8304 t->n_fields = params->n_fields;
8307 for (i = 0; i < params->n_actions; i++)
8308 t->actions[i] = action_find(p, params->action_names[i]);
8309 t->default_action = default_action;
8310 if (default_action->st)
8311 memcpy(t->default_action_data,
8312 params->default_action_data,
8313 default_action->st->n_bits / 8);
8314 t->n_actions = params->n_actions;
8315 t->default_action_is_const = params->default_action_is_const;
8316 t->action_data_size_max = action_data_size_max;
8319 t->id = p->n_tables;
8321 /* Node add to tailq. */
8322 TAILQ_INSERT_TAIL(&p->tables, t, node);
8328 static struct rte_swx_table_params *
8329 table_params_get(struct table *table)
8331 struct rte_swx_table_params *params;
8332 struct field *first, *last;
8334 uint32_t key_size, key_offset, action_data_size, i;
8336 /* Memory allocation. */
8337 params = calloc(1, sizeof(struct rte_swx_table_params));
8341 /* Find first (smallest offset) and last (biggest offset) match fields. */
8342 first = table->fields[0].field;
8343 last = table->fields[0].field;
8345 for (i = 0; i < table->n_fields; i++) {
8346 struct field *f = table->fields[i].field;
8348 if (f->offset < first->offset)
8351 if (f->offset > last->offset)
8355 /* Key offset and size. */
8356 key_offset = first->offset / 8;
8357 key_size = (last->offset + last->n_bits - first->offset) / 8;
8359 /* Memory allocation. */
8360 key_mask = calloc(1, key_size);
8367 for (i = 0; i < table->n_fields; i++) {
8368 struct field *f = table->fields[i].field;
8369 uint32_t start = (f->offset - first->offset) / 8;
8370 size_t size = f->n_bits / 8;
8372 memset(&key_mask[start], 0xFF, size);
8375 /* Action data size. */
8376 action_data_size = 0;
8377 for (i = 0; i < table->n_actions; i++) {
8378 struct action *action = table->actions[i];
8379 uint32_t ads = action->st ? action->st->n_bits / 8 : 0;
8381 if (ads > action_data_size)
8382 action_data_size = ads;
8386 params->match_type = table->type->match_type;
8387 params->key_size = key_size;
8388 params->key_offset = key_offset;
8389 params->key_mask0 = key_mask;
8390 params->action_data_size = action_data_size;
8391 params->n_keys_max = table->size;
8397 table_params_free(struct rte_swx_table_params *params)
8402 free(params->key_mask0);
8407 table_stub_lkp(void *table __rte_unused,
8408 void *mailbox __rte_unused,
8409 uint8_t **key __rte_unused,
8410 uint64_t *action_id __rte_unused,
8411 uint8_t **action_data __rte_unused,
8415 return 1; /* DONE. */
8419 table_build(struct rte_swx_pipeline *p)
8423 /* Per pipeline: table statistics. */
8424 p->table_stats = calloc(p->n_tables, sizeof(struct table_statistics));
8425 CHECK(p->table_stats, ENOMEM);
8427 for (i = 0; i < p->n_tables; i++) {
8428 p->table_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
8429 CHECK(p->table_stats[i].n_pkts_action, ENOMEM);
8432 /* Per thread: table runt-time. */
8433 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8434 struct thread *t = &p->threads[i];
8435 struct table *table;
8437 t->tables = calloc(p->n_tables, sizeof(struct table_runtime));
8438 CHECK(t->tables, ENOMEM);
8440 TAILQ_FOREACH(table, &p->tables, node) {
8441 struct table_runtime *r = &t->tables[table->id];
8446 size = table->type->ops.mailbox_size_get();
8449 r->func = table->type->ops.lkp;
8453 r->mailbox = calloc(1, size);
8454 CHECK(r->mailbox, ENOMEM);
8458 r->key = table->header ?
8459 &t->structs[table->header->struct_id] :
8460 &t->structs[p->metadata_struct_id];
8462 r->func = table_stub_lkp;
8471 table_build_free(struct rte_swx_pipeline *p)
8475 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8476 struct thread *t = &p->threads[i];
8482 for (j = 0; j < p->n_tables; j++) {
8483 struct table_runtime *r = &t->tables[j];
8492 if (p->table_stats) {
8493 for (i = 0; i < p->n_tables; i++)
8494 free(p->table_stats[i].n_pkts_action);
8496 free(p->table_stats);
8501 table_free(struct rte_swx_pipeline *p)
8503 table_build_free(p);
8509 elem = TAILQ_FIRST(&p->tables);
8513 TAILQ_REMOVE(&p->tables, elem, node);
8515 free(elem->actions);
8516 free(elem->default_action_data);
8522 struct table_type *elem;
8524 elem = TAILQ_FIRST(&p->table_types);
8528 TAILQ_REMOVE(&p->table_types, elem, node);
8536 static struct selector *
8537 selector_find(struct rte_swx_pipeline *p, const char *name)
8541 TAILQ_FOREACH(s, &p->selectors, node)
8542 if (strcmp(s->name, name) == 0)
8548 static struct selector *
8549 selector_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8551 struct selector *s = NULL;
8553 TAILQ_FOREACH(s, &p->selectors, node)
8561 selector_fields_check(struct rte_swx_pipeline *p,
8562 struct rte_swx_pipeline_selector_params *params,
8563 struct header **header)
8565 struct header *h0 = NULL;
8566 struct field *hf, *mf;
8569 /* Return if no selector fields. */
8570 if (!params->n_selector_fields || !params->selector_field_names)
8573 /* Check that all the selector fields either belong to the same header
8574 * or are all meta-data fields.
8576 hf = header_field_parse(p, params->selector_field_names[0], &h0);
8577 mf = metadata_field_parse(p, params->selector_field_names[0]);
8581 for (i = 1; i < params->n_selector_fields; i++)
8585 hf = header_field_parse(p, params->selector_field_names[i], &h);
8586 if (!hf || (h->id != h0->id))
8589 mf = metadata_field_parse(p, params->selector_field_names[i]);
8594 /* Check that there are no duplicated match fields. */
8595 for (i = 0; i < params->n_selector_fields; i++) {
8596 const char *field_name = params->selector_field_names[i];
8599 for (j = i + 1; j < params->n_selector_fields; j++)
8600 if (!strcmp(params->selector_field_names[j], field_name))
8612 rte_swx_pipeline_selector_config(struct rte_swx_pipeline *p,
8614 struct rte_swx_pipeline_selector_params *params)
8617 struct header *selector_header = NULL;
8618 struct field *group_id_field, *member_id_field;
8624 CHECK_NAME(name, EINVAL);
8625 CHECK(!table_find(p, name), EEXIST);
8626 CHECK(!selector_find(p, name), EEXIST);
8627 CHECK(!learner_find(p, name), EEXIST);
8629 CHECK(params, EINVAL);
8631 CHECK_NAME(params->group_id_field_name, EINVAL);
8632 group_id_field = metadata_field_parse(p, params->group_id_field_name);
8633 CHECK(group_id_field, EINVAL);
8635 for (i = 0; i < params->n_selector_fields; i++) {
8636 const char *field_name = params->selector_field_names[i];
8638 CHECK_NAME(field_name, EINVAL);
8640 status = selector_fields_check(p, params, &selector_header);
8644 CHECK_NAME(params->member_id_field_name, EINVAL);
8645 member_id_field = metadata_field_parse(p, params->member_id_field_name);
8646 CHECK(member_id_field, EINVAL);
8648 CHECK(params->n_groups_max, EINVAL);
8650 CHECK(params->n_members_per_group_max, EINVAL);
8652 /* Memory allocation. */
8653 s = calloc(1, sizeof(struct selector));
8659 s->selector_fields = calloc(params->n_selector_fields, sizeof(struct field *));
8660 if (!s->selector_fields) {
8665 /* Node initialization. */
8666 strcpy(s->name, name);
8668 s->group_id_field = group_id_field;
8670 for (i = 0; i < params->n_selector_fields; i++) {
8671 const char *field_name = params->selector_field_names[i];
8673 s->selector_fields[i] = selector_header ?
8674 header_field_parse(p, field_name, NULL) :
8675 metadata_field_parse(p, field_name);
8678 s->n_selector_fields = params->n_selector_fields;
8680 s->selector_header = selector_header;
8682 s->member_id_field = member_id_field;
8684 s->n_groups_max = params->n_groups_max;
8686 s->n_members_per_group_max = params->n_members_per_group_max;
8688 s->id = p->n_selectors;
8690 /* Node add to tailq. */
8691 TAILQ_INSERT_TAIL(&p->selectors, s, node);
8700 free(s->selector_fields);
8708 selector_params_free(struct rte_swx_table_selector_params *params)
8713 free(params->selector_mask);
8718 static struct rte_swx_table_selector_params *
8719 selector_table_params_get(struct selector *s)
8721 struct rte_swx_table_selector_params *params = NULL;
8722 struct field *first, *last;
8725 /* Memory allocation. */
8726 params = calloc(1, sizeof(struct rte_swx_table_selector_params));
8731 params->group_id_offset = s->group_id_field->offset / 8;
8733 /* Find first (smallest offset) and last (biggest offset) selector fields. */
8734 first = s->selector_fields[0];
8735 last = s->selector_fields[0];
8737 for (i = 0; i < s->n_selector_fields; i++) {
8738 struct field *f = s->selector_fields[i];
8740 if (f->offset < first->offset)
8743 if (f->offset > last->offset)
8747 /* Selector offset and size. */
8748 params->selector_offset = first->offset / 8;
8749 params->selector_size = (last->offset + last->n_bits - first->offset) / 8;
8751 /* Memory allocation. */
8752 params->selector_mask = calloc(1, params->selector_size);
8753 if (!params->selector_mask)
8756 /* Selector mask. */
8757 for (i = 0; i < s->n_selector_fields; i++) {
8758 struct field *f = s->selector_fields[i];
8759 uint32_t start = (f->offset - first->offset) / 8;
8760 size_t size = f->n_bits / 8;
8762 memset(¶ms->selector_mask[start], 0xFF, size);
8766 params->member_id_offset = s->member_id_field->offset / 8;
8768 /* Maximum number of groups. */
8769 params->n_groups_max = s->n_groups_max;
8771 /* Maximum number of members per group. */
8772 params->n_members_per_group_max = s->n_members_per_group_max;
8777 selector_params_free(params);
8782 selector_build_free(struct rte_swx_pipeline *p)
8786 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8787 struct thread *t = &p->threads[i];
8793 for (j = 0; j < p->n_selectors; j++) {
8794 struct selector_runtime *r = &t->selectors[j];
8800 t->selectors = NULL;
8803 free(p->selector_stats);
8804 p->selector_stats = NULL;
8808 selector_build(struct rte_swx_pipeline *p)
8813 /* Per pipeline: selector statistics. */
8814 p->selector_stats = calloc(p->n_selectors, sizeof(struct selector_statistics));
8815 if (!p->selector_stats) {
8820 /* Per thread: selector run-time. */
8821 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8822 struct thread *t = &p->threads[i];
8825 t->selectors = calloc(p->n_selectors, sizeof(struct selector_runtime));
8826 if (!t->selectors) {
8831 TAILQ_FOREACH(s, &p->selectors, node) {
8832 struct selector_runtime *r = &t->selectors[s->id];
8836 size = rte_swx_table_selector_mailbox_size_get();
8838 r->mailbox = calloc(1, size);
8845 /* r->group_id_buffer. */
8846 r->group_id_buffer = &t->structs[p->metadata_struct_id];
8848 /* r->selector_buffer. */
8849 r->selector_buffer = s->selector_header ?
8850 &t->structs[s->selector_header->struct_id] :
8851 &t->structs[p->metadata_struct_id];
8853 /* r->member_id_buffer. */
8854 r->member_id_buffer = &t->structs[p->metadata_struct_id];
8861 selector_build_free(p);
8866 selector_free(struct rte_swx_pipeline *p)
8868 selector_build_free(p);
8870 /* Selector tables. */
8872 struct selector *elem;
8874 elem = TAILQ_FIRST(&p->selectors);
8878 TAILQ_REMOVE(&p->selectors, elem, node);
8879 free(elem->selector_fields);
8887 static struct learner *
8888 learner_find(struct rte_swx_pipeline *p, const char *name)
8892 TAILQ_FOREACH(l, &p->learners, node)
8893 if (!strcmp(l->name, name))
8899 static struct learner *
8900 learner_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8902 struct learner *l = NULL;
8904 TAILQ_FOREACH(l, &p->learners, node)
8912 learner_match_fields_check(struct rte_swx_pipeline *p,
8913 struct rte_swx_pipeline_learner_params *params,
8914 struct header **header)
8916 struct header *h0 = NULL;
8917 struct field *hf, *mf;
8920 /* Return if no match fields. */
8921 if (!params->n_fields || !params->field_names)
8924 /* Check that all the match fields either belong to the same header
8925 * or are all meta-data fields.
8927 hf = header_field_parse(p, params->field_names[0], &h0);
8928 mf = metadata_field_parse(p, params->field_names[0]);
8932 for (i = 1; i < params->n_fields; i++)
8936 hf = header_field_parse(p, params->field_names[i], &h);
8937 if (!hf || (h->id != h0->id))
8940 mf = metadata_field_parse(p, params->field_names[i]);
8945 /* Check that there are no duplicated match fields. */
8946 for (i = 0; i < params->n_fields; i++) {
8947 const char *field_name = params->field_names[i];
8950 for (j = i + 1; j < params->n_fields; j++)
8951 if (!strcmp(params->field_names[j], field_name))
8963 learner_action_args_check(struct rte_swx_pipeline *p, struct action *a, const char *mf_name)
8965 struct struct_type *mst = p->metadata_st, *ast = a->st;
8966 struct field *mf, *af;
8976 /* Check that mf_name is the name of a valid meta-data field. */
8977 CHECK_NAME(mf_name, EINVAL);
8978 mf = metadata_field_parse(p, mf_name);
8981 /* Check that there are enough meta-data fields, starting with the mf_name field, to cover
8982 * all the action arguments.
8984 mf_pos = mf - mst->fields;
8985 CHECK(mst->n_fields - mf_pos >= ast->n_fields, EINVAL);
8987 /* Check that the size of each of the identified meta-data fields matches exactly the size
8988 * of the corresponding action argument.
8990 for (i = 0; i < ast->n_fields; i++) {
8991 mf = &mst->fields[mf_pos + i];
8992 af = &ast->fields[i];
8994 CHECK(mf->n_bits == af->n_bits, EINVAL);
9001 learner_action_learning_check(struct rte_swx_pipeline *p,
9002 struct action *action,
9003 const char **action_names,
9008 /* For each "learn" instruction of the current action, check that the learned action (i.e.
9009 * the action passed as argument to the "learn" instruction) is also enabled for the
9010 * current learner table.
9012 for (i = 0; i < action->n_instructions; i++) {
9013 struct instruction *instr = &action->instructions[i];
9014 uint32_t found = 0, j;
9016 if (instr->type != INSTR_LEARNER_LEARN)
9019 for (j = 0; j < n_actions; j++) {
9022 a = action_find(p, action_names[j]);
9026 if (a->id == instr->learn.action_id)
9038 rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p,
9040 struct rte_swx_pipeline_learner_params *params,
9044 struct learner *l = NULL;
9045 struct action *default_action;
9046 struct header *header = NULL;
9047 uint32_t action_data_size_max = 0, i;
9052 CHECK_NAME(name, EINVAL);
9053 CHECK(!table_find(p, name), EEXIST);
9054 CHECK(!selector_find(p, name), EEXIST);
9055 CHECK(!learner_find(p, name), EEXIST);
9057 CHECK(params, EINVAL);
9060 status = learner_match_fields_check(p, params, &header);
9064 /* Action checks. */
9065 CHECK(params->n_actions, EINVAL);
9067 CHECK(params->action_names, EINVAL);
9068 for (i = 0; i < params->n_actions; i++) {
9069 const char *action_name = params->action_names[i];
9070 const char *action_field_name = params->action_field_names[i];
9072 uint32_t action_data_size;
9074 CHECK_NAME(action_name, EINVAL);
9076 a = action_find(p, action_name);
9079 status = learner_action_args_check(p, a, action_field_name);
9083 status = learner_action_learning_check(p,
9085 params->action_names,
9090 action_data_size = a->st ? a->st->n_bits / 8 : 0;
9091 if (action_data_size > action_data_size_max)
9092 action_data_size_max = action_data_size;
9095 CHECK_NAME(params->default_action_name, EINVAL);
9096 for (i = 0; i < p->n_actions; i++)
9097 if (!strcmp(params->action_names[i],
9098 params->default_action_name))
9100 CHECK(i < params->n_actions, EINVAL);
9102 default_action = action_find(p, params->default_action_name);
9103 CHECK((default_action->st && params->default_action_data) ||
9104 !params->default_action_data, EINVAL);
9106 /* Any other checks. */
9107 CHECK(size, EINVAL);
9108 CHECK(timeout, EINVAL);
9110 /* Memory allocation. */
9111 l = calloc(1, sizeof(struct learner));
9115 l->fields = calloc(params->n_fields, sizeof(struct field *));
9119 l->actions = calloc(params->n_actions, sizeof(struct action *));
9123 l->action_arg = calloc(params->n_actions, sizeof(struct field *));
9127 if (action_data_size_max) {
9128 l->default_action_data = calloc(1, action_data_size_max);
9129 if (!l->default_action_data)
9133 /* Node initialization. */
9134 strcpy(l->name, name);
9136 for (i = 0; i < params->n_fields; i++) {
9137 const char *field_name = params->field_names[i];
9139 l->fields[i] = header ?
9140 header_field_parse(p, field_name, NULL) :
9141 metadata_field_parse(p, field_name);
9144 l->n_fields = params->n_fields;
9148 for (i = 0; i < params->n_actions; i++) {
9149 const char *mf_name = params->action_field_names[i];
9151 l->actions[i] = action_find(p, params->action_names[i]);
9153 l->action_arg[i] = mf_name ? metadata_field_parse(p, mf_name) : NULL;
9156 l->default_action = default_action;
9158 if (default_action->st)
9159 memcpy(l->default_action_data,
9160 params->default_action_data,
9161 default_action->st->n_bits / 8);
9163 l->n_actions = params->n_actions;
9165 l->default_action_is_const = params->default_action_is_const;
9167 l->action_data_size_max = action_data_size_max;
9171 l->timeout = timeout;
9173 l->id = p->n_learners;
9175 /* Node add to tailq. */
9176 TAILQ_INSERT_TAIL(&p->learners, l, node);
9185 free(l->action_arg);
9194 learner_params_free(struct rte_swx_table_learner_params *params)
9199 free(params->key_mask0);
9204 static struct rte_swx_table_learner_params *
9205 learner_params_get(struct learner *l)
9207 struct rte_swx_table_learner_params *params = NULL;
9208 struct field *first, *last;
9211 /* Memory allocation. */
9212 params = calloc(1, sizeof(struct rte_swx_table_learner_params));
9216 /* Find first (smallest offset) and last (biggest offset) match fields. */
9217 first = l->fields[0];
9218 last = l->fields[0];
9220 for (i = 0; i < l->n_fields; i++) {
9221 struct field *f = l->fields[i];
9223 if (f->offset < first->offset)
9226 if (f->offset > last->offset)
9230 /* Key offset and size. */
9231 params->key_offset = first->offset / 8;
9232 params->key_size = (last->offset + last->n_bits - first->offset) / 8;
9234 /* Memory allocation. */
9235 params->key_mask0 = calloc(1, params->key_size);
9236 if (!params->key_mask0)
9240 for (i = 0; i < l->n_fields; i++) {
9241 struct field *f = l->fields[i];
9242 uint32_t start = (f->offset - first->offset) / 8;
9243 size_t size = f->n_bits / 8;
9245 memset(¶ms->key_mask0[start], 0xFF, size);
9248 /* Action data size. */
9249 params->action_data_size = l->action_data_size_max;
9251 /* Maximum number of keys. */
9252 params->n_keys_max = l->size;
9255 params->key_timeout = l->timeout;
9260 learner_params_free(params);
9265 learner_build_free(struct rte_swx_pipeline *p)
9269 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9270 struct thread *t = &p->threads[i];
9276 for (j = 0; j < p->n_learners; j++) {
9277 struct learner_runtime *r = &t->learners[j];
9280 free(r->action_data);
9287 if (p->learner_stats) {
9288 for (i = 0; i < p->n_learners; i++)
9289 free(p->learner_stats[i].n_pkts_action);
9291 free(p->learner_stats);
9296 learner_build(struct rte_swx_pipeline *p)
9301 /* Per pipeline: learner statistics. */
9302 p->learner_stats = calloc(p->n_learners, sizeof(struct learner_statistics));
9303 CHECK(p->learner_stats, ENOMEM);
9305 for (i = 0; i < p->n_learners; i++) {
9306 p->learner_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
9307 CHECK(p->learner_stats[i].n_pkts_action, ENOMEM);
9310 /* Per thread: learner run-time. */
9311 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9312 struct thread *t = &p->threads[i];
9315 t->learners = calloc(p->n_learners, sizeof(struct learner_runtime));
9321 TAILQ_FOREACH(l, &p->learners, node) {
9322 struct learner_runtime *r = &t->learners[l->id];
9327 size = rte_swx_table_learner_mailbox_size_get();
9329 r->mailbox = calloc(1, size);
9337 r->key = l->header ?
9338 &t->structs[l->header->struct_id] :
9339 &t->structs[p->metadata_struct_id];
9341 /* r->action_data. */
9342 r->action_data = calloc(p->n_actions, sizeof(uint8_t *));
9343 if (!r->action_data) {
9348 for (j = 0; j < l->n_actions; j++) {
9349 struct action *a = l->actions[j];
9350 struct field *mf = l->action_arg[j];
9351 uint8_t *m = t->structs[p->metadata_struct_id];
9353 r->action_data[a->id] = mf ? &m[mf->offset / 8] : NULL;
9361 learner_build_free(p);
9366 learner_free(struct rte_swx_pipeline *p)
9368 learner_build_free(p);
9370 /* Learner tables. */
9374 l = TAILQ_FIRST(&p->learners);
9378 TAILQ_REMOVE(&p->learners, l, node);
9381 free(l->action_arg);
9382 free(l->default_action_data);
9391 table_state_build(struct rte_swx_pipeline *p)
9393 struct table *table;
9397 p->table_state = calloc(p->n_tables + p->n_selectors,
9398 sizeof(struct rte_swx_table_state));
9399 CHECK(p->table_state, ENOMEM);
9401 TAILQ_FOREACH(table, &p->tables, node) {
9402 struct rte_swx_table_state *ts = &p->table_state[table->id];
9405 struct rte_swx_table_params *params;
9408 params = table_params_get(table);
9409 CHECK(params, ENOMEM);
9411 ts->obj = table->type->ops.create(params,
9416 table_params_free(params);
9417 CHECK(ts->obj, ENODEV);
9420 /* ts->default_action_data. */
9421 if (table->action_data_size_max) {
9422 ts->default_action_data =
9423 malloc(table->action_data_size_max);
9424 CHECK(ts->default_action_data, ENOMEM);
9426 memcpy(ts->default_action_data,
9427 table->default_action_data,
9428 table->action_data_size_max);
9431 /* ts->default_action_id. */
9432 ts->default_action_id = table->default_action->id;
9435 TAILQ_FOREACH(s, &p->selectors, node) {
9436 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + s->id];
9437 struct rte_swx_table_selector_params *params;
9440 params = selector_table_params_get(s);
9441 CHECK(params, ENOMEM);
9443 ts->obj = rte_swx_table_selector_create(params, NULL, p->numa_node);
9445 selector_params_free(params);
9446 CHECK(ts->obj, ENODEV);
9449 TAILQ_FOREACH(l, &p->learners, node) {
9450 struct rte_swx_table_state *ts = &p->table_state[p->n_tables +
9451 p->n_selectors + l->id];
9452 struct rte_swx_table_learner_params *params;
9455 params = learner_params_get(l);
9456 CHECK(params, ENOMEM);
9458 ts->obj = rte_swx_table_learner_create(params, p->numa_node);
9459 learner_params_free(params);
9460 CHECK(ts->obj, ENODEV);
9462 /* ts->default_action_data. */
9463 if (l->action_data_size_max) {
9464 ts->default_action_data = malloc(l->action_data_size_max);
9465 CHECK(ts->default_action_data, ENOMEM);
9467 memcpy(ts->default_action_data,
9468 l->default_action_data,
9469 l->action_data_size_max);
9472 /* ts->default_action_id. */
9473 ts->default_action_id = l->default_action->id;
9480 table_state_build_free(struct rte_swx_pipeline *p)
9484 if (!p->table_state)
9487 for (i = 0; i < p->n_tables; i++) {
9488 struct rte_swx_table_state *ts = &p->table_state[i];
9489 struct table *table = table_find_by_id(p, i);
9492 if (table->type && ts->obj)
9493 table->type->ops.free(ts->obj);
9495 /* ts->default_action_data. */
9496 free(ts->default_action_data);
9499 for (i = 0; i < p->n_selectors; i++) {
9500 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + i];
9504 rte_swx_table_selector_free(ts->obj);
9507 for (i = 0; i < p->n_learners; i++) {
9508 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + p->n_selectors + i];
9512 rte_swx_table_learner_free(ts->obj);
9514 /* ts->default_action_data. */
9515 free(ts->default_action_data);
9518 free(p->table_state);
9519 p->table_state = NULL;
9523 table_state_free(struct rte_swx_pipeline *p)
9525 table_state_build_free(p);
9531 static struct regarray *
9532 regarray_find(struct rte_swx_pipeline *p, const char *name)
9534 struct regarray *elem;
9536 TAILQ_FOREACH(elem, &p->regarrays, node)
9537 if (!strcmp(elem->name, name))
9543 static struct regarray *
9544 regarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9546 struct regarray *elem = NULL;
9548 TAILQ_FOREACH(elem, &p->regarrays, node)
9556 rte_swx_pipeline_regarray_config(struct rte_swx_pipeline *p,
9565 CHECK_NAME(name, EINVAL);
9566 CHECK(!regarray_find(p, name), EEXIST);
9568 CHECK(size, EINVAL);
9569 size = rte_align32pow2(size);
9571 /* Memory allocation. */
9572 r = calloc(1, sizeof(struct regarray));
9575 /* Node initialization. */
9576 strcpy(r->name, name);
9577 r->init_val = init_val;
9579 r->id = p->n_regarrays;
9581 /* Node add to tailq. */
9582 TAILQ_INSERT_TAIL(&p->regarrays, r, node);
9589 regarray_build(struct rte_swx_pipeline *p)
9591 struct regarray *regarray;
9593 if (!p->n_regarrays)
9596 p->regarray_runtime = calloc(p->n_regarrays, sizeof(struct regarray_runtime));
9597 CHECK(p->regarray_runtime, ENOMEM);
9599 TAILQ_FOREACH(regarray, &p->regarrays, node) {
9600 struct regarray_runtime *r = &p->regarray_runtime[regarray->id];
9603 r->regarray = env_malloc(regarray->size * sizeof(uint64_t),
9604 RTE_CACHE_LINE_SIZE,
9606 CHECK(r->regarray, ENOMEM);
9608 if (regarray->init_val)
9609 for (i = 0; i < regarray->size; i++)
9610 r->regarray[i] = regarray->init_val;
9612 r->size_mask = regarray->size - 1;
9619 regarray_build_free(struct rte_swx_pipeline *p)
9623 if (!p->regarray_runtime)
9626 for (i = 0; i < p->n_regarrays; i++) {
9627 struct regarray *regarray = regarray_find_by_id(p, i);
9628 struct regarray_runtime *r = &p->regarray_runtime[i];
9630 env_free(r->regarray, regarray->size * sizeof(uint64_t));
9633 free(p->regarray_runtime);
9634 p->regarray_runtime = NULL;
9638 regarray_free(struct rte_swx_pipeline *p)
9640 regarray_build_free(p);
9643 struct regarray *elem;
9645 elem = TAILQ_FIRST(&p->regarrays);
9649 TAILQ_REMOVE(&p->regarrays, elem, node);
9657 static struct meter_profile *
9658 meter_profile_find(struct rte_swx_pipeline *p, const char *name)
9660 struct meter_profile *elem;
9662 TAILQ_FOREACH(elem, &p->meter_profiles, node)
9663 if (!strcmp(elem->name, name))
9669 static struct metarray *
9670 metarray_find(struct rte_swx_pipeline *p, const char *name)
9672 struct metarray *elem;
9674 TAILQ_FOREACH(elem, &p->metarrays, node)
9675 if (!strcmp(elem->name, name))
9681 static struct metarray *
9682 metarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9684 struct metarray *elem = NULL;
9686 TAILQ_FOREACH(elem, &p->metarrays, node)
9694 rte_swx_pipeline_metarray_config(struct rte_swx_pipeline *p,
9702 CHECK_NAME(name, EINVAL);
9703 CHECK(!metarray_find(p, name), EEXIST);
9705 CHECK(size, EINVAL);
9706 size = rte_align32pow2(size);
9708 /* Memory allocation. */
9709 m = calloc(1, sizeof(struct metarray));
9712 /* Node initialization. */
9713 strcpy(m->name, name);
9715 m->id = p->n_metarrays;
9717 /* Node add to tailq. */
9718 TAILQ_INSERT_TAIL(&p->metarrays, m, node);
9724 struct meter_profile meter_profile_default = {
9733 .cir_bytes_per_period = 1,
9735 .pir_bytes_per_period = 1,
9742 meter_init(struct meter *m)
9744 memset(m, 0, sizeof(struct meter));
9745 rte_meter_trtcm_config(&m->m, &meter_profile_default.profile);
9746 m->profile = &meter_profile_default;
9747 m->color_mask = RTE_COLOR_GREEN;
9749 meter_profile_default.n_users++;
9753 metarray_build(struct rte_swx_pipeline *p)
9757 if (!p->n_metarrays)
9760 p->metarray_runtime = calloc(p->n_metarrays, sizeof(struct metarray_runtime));
9761 CHECK(p->metarray_runtime, ENOMEM);
9763 TAILQ_FOREACH(m, &p->metarrays, node) {
9764 struct metarray_runtime *r = &p->metarray_runtime[m->id];
9767 r->metarray = env_malloc(m->size * sizeof(struct meter),
9768 RTE_CACHE_LINE_SIZE,
9770 CHECK(r->metarray, ENOMEM);
9772 for (i = 0; i < m->size; i++)
9773 meter_init(&r->metarray[i]);
9775 r->size_mask = m->size - 1;
9782 metarray_build_free(struct rte_swx_pipeline *p)
9786 if (!p->metarray_runtime)
9789 for (i = 0; i < p->n_metarrays; i++) {
9790 struct metarray *m = metarray_find_by_id(p, i);
9791 struct metarray_runtime *r = &p->metarray_runtime[i];
9793 env_free(r->metarray, m->size * sizeof(struct meter));
9796 free(p->metarray_runtime);
9797 p->metarray_runtime = NULL;
9801 metarray_free(struct rte_swx_pipeline *p)
9803 metarray_build_free(p);
9807 struct metarray *elem;
9809 elem = TAILQ_FIRST(&p->metarrays);
9813 TAILQ_REMOVE(&p->metarrays, elem, node);
9817 /* Meter profiles. */
9819 struct meter_profile *elem;
9821 elem = TAILQ_FIRST(&p->meter_profiles);
9825 TAILQ_REMOVE(&p->meter_profiles, elem, node);
9834 rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
9836 struct rte_swx_pipeline *pipeline;
9838 /* Check input parameters. */
9841 /* Memory allocation. */
9842 pipeline = calloc(1, sizeof(struct rte_swx_pipeline));
9843 CHECK(pipeline, ENOMEM);
9845 /* Initialization. */
9846 TAILQ_INIT(&pipeline->struct_types);
9847 TAILQ_INIT(&pipeline->port_in_types);
9848 TAILQ_INIT(&pipeline->ports_in);
9849 TAILQ_INIT(&pipeline->port_out_types);
9850 TAILQ_INIT(&pipeline->ports_out);
9851 TAILQ_INIT(&pipeline->extern_types);
9852 TAILQ_INIT(&pipeline->extern_objs);
9853 TAILQ_INIT(&pipeline->extern_funcs);
9854 TAILQ_INIT(&pipeline->headers);
9855 TAILQ_INIT(&pipeline->actions);
9856 TAILQ_INIT(&pipeline->table_types);
9857 TAILQ_INIT(&pipeline->tables);
9858 TAILQ_INIT(&pipeline->selectors);
9859 TAILQ_INIT(&pipeline->learners);
9860 TAILQ_INIT(&pipeline->regarrays);
9861 TAILQ_INIT(&pipeline->meter_profiles);
9862 TAILQ_INIT(&pipeline->metarrays);
9864 pipeline->n_structs = 1; /* Struct 0 is reserved for action_data. */
9865 pipeline->numa_node = numa_node;
9872 rte_swx_pipeline_free(struct rte_swx_pipeline *p)
9877 free(p->instructions);
9881 table_state_free(p);
9888 extern_func_free(p);
9898 rte_swx_pipeline_instructions_config(struct rte_swx_pipeline *p,
9899 const char **instructions,
9900 uint32_t n_instructions)
9905 err = instruction_config(p, NULL, instructions, n_instructions);
9909 /* Thread instruction pointer reset. */
9910 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9911 struct thread *t = &p->threads[i];
9913 thread_ip_reset(p, t);
9920 rte_swx_pipeline_build(struct rte_swx_pipeline *p)
9925 CHECK(p->build_done == 0, EEXIST);
9927 status = port_in_build(p);
9931 status = port_out_build(p);
9935 status = struct_build(p);
9939 status = extern_obj_build(p);
9943 status = extern_func_build(p);
9947 status = header_build(p);
9951 status = metadata_build(p);
9955 status = action_build(p);
9959 status = table_build(p);
9963 status = selector_build(p);
9967 status = learner_build(p);
9971 status = table_state_build(p);
9975 status = regarray_build(p);
9979 status = metarray_build(p);
9987 metarray_build_free(p);
9988 regarray_build_free(p);
9989 table_state_build_free(p);
9990 learner_build_free(p);
9991 selector_build_free(p);
9992 table_build_free(p);
9993 action_build_free(p);
9994 metadata_build_free(p);
9995 header_build_free(p);
9996 extern_func_build_free(p);
9997 extern_obj_build_free(p);
9998 port_out_build_free(p);
9999 port_in_build_free(p);
10000 struct_build_free(p);
10006 rte_swx_pipeline_run(struct rte_swx_pipeline *p, uint32_t n_instructions)
10010 for (i = 0; i < n_instructions; i++)
10015 rte_swx_pipeline_flush(struct rte_swx_pipeline *p)
10019 for (i = 0; i < p->n_ports_out; i++) {
10020 struct port_out_runtime *port = &p->out[i];
10023 port->flush(port->obj);
10031 rte_swx_ctl_pipeline_info_get(struct rte_swx_pipeline *p,
10032 struct rte_swx_ctl_pipeline_info *pipeline)
10034 struct action *action;
10035 struct table *table;
10036 uint32_t n_actions = 0, n_tables = 0;
10038 if (!p || !pipeline)
10041 TAILQ_FOREACH(action, &p->actions, node)
10044 TAILQ_FOREACH(table, &p->tables, node)
10047 pipeline->n_ports_in = p->n_ports_in;
10048 pipeline->n_ports_out = p->n_ports_out;
10049 pipeline->n_actions = n_actions;
10050 pipeline->n_tables = n_tables;
10051 pipeline->n_selectors = p->n_selectors;
10052 pipeline->n_learners = p->n_learners;
10053 pipeline->n_regarrays = p->n_regarrays;
10054 pipeline->n_metarrays = p->n_metarrays;
10060 rte_swx_ctl_pipeline_numa_node_get(struct rte_swx_pipeline *p, int *numa_node)
10062 if (!p || !numa_node)
10065 *numa_node = p->numa_node;
10070 rte_swx_ctl_action_info_get(struct rte_swx_pipeline *p,
10071 uint32_t action_id,
10072 struct rte_swx_ctl_action_info *action)
10074 struct action *a = NULL;
10076 if (!p || (action_id >= p->n_actions) || !action)
10079 a = action_find_by_id(p, action_id);
10083 strcpy(action->name, a->name);
10084 action->n_args = a->st ? a->st->n_fields : 0;
10089 rte_swx_ctl_action_arg_info_get(struct rte_swx_pipeline *p,
10090 uint32_t action_id,
10091 uint32_t action_arg_id,
10092 struct rte_swx_ctl_action_arg_info *action_arg)
10094 struct action *a = NULL;
10095 struct field *arg = NULL;
10097 if (!p || (action_id >= p->n_actions) || !action_arg)
10100 a = action_find_by_id(p, action_id);
10101 if (!a || !a->st || (action_arg_id >= a->st->n_fields))
10104 arg = &a->st->fields[action_arg_id];
10105 strcpy(action_arg->name, arg->name);
10106 action_arg->n_bits = arg->n_bits;
10107 action_arg->is_network_byte_order = a->args_endianness[action_arg_id];
10113 rte_swx_ctl_table_info_get(struct rte_swx_pipeline *p,
10115 struct rte_swx_ctl_table_info *table)
10117 struct table *t = NULL;
10122 t = table_find_by_id(p, table_id);
10126 strcpy(table->name, t->name);
10127 strcpy(table->args, t->args);
10128 table->n_match_fields = t->n_fields;
10129 table->n_actions = t->n_actions;
10130 table->default_action_is_const = t->default_action_is_const;
10131 table->size = t->size;
10136 rte_swx_ctl_table_match_field_info_get(struct rte_swx_pipeline *p,
10138 uint32_t match_field_id,
10139 struct rte_swx_ctl_table_match_field_info *match_field)
10142 struct match_field *f;
10144 if (!p || (table_id >= p->n_tables) || !match_field)
10147 t = table_find_by_id(p, table_id);
10148 if (!t || (match_field_id >= t->n_fields))
10151 f = &t->fields[match_field_id];
10152 match_field->match_type = f->match_type;
10153 match_field->is_header = t->header ? 1 : 0;
10154 match_field->n_bits = f->field->n_bits;
10155 match_field->offset = f->field->offset;
10161 rte_swx_ctl_table_action_info_get(struct rte_swx_pipeline *p,
10163 uint32_t table_action_id,
10164 struct rte_swx_ctl_table_action_info *table_action)
10168 if (!p || (table_id >= p->n_tables) || !table_action)
10171 t = table_find_by_id(p, table_id);
10172 if (!t || (table_action_id >= t->n_actions))
10175 table_action->action_id = t->actions[table_action_id]->id;
10181 rte_swx_ctl_table_ops_get(struct rte_swx_pipeline *p,
10183 struct rte_swx_table_ops *table_ops,
10188 if (!p || (table_id >= p->n_tables))
10191 t = table_find_by_id(p, table_id);
10197 memcpy(table_ops, &t->type->ops, sizeof(*table_ops));
10207 rte_swx_ctl_selector_info_get(struct rte_swx_pipeline *p,
10208 uint32_t selector_id,
10209 struct rte_swx_ctl_selector_info *selector)
10211 struct selector *s = NULL;
10213 if (!p || !selector)
10216 s = selector_find_by_id(p, selector_id);
10220 strcpy(selector->name, s->name);
10222 selector->n_selector_fields = s->n_selector_fields;
10223 selector->n_groups_max = s->n_groups_max;
10224 selector->n_members_per_group_max = s->n_members_per_group_max;
10230 rte_swx_ctl_selector_group_id_field_info_get(struct rte_swx_pipeline *p,
10231 uint32_t selector_id,
10232 struct rte_swx_ctl_table_match_field_info *field)
10234 struct selector *s;
10236 if (!p || (selector_id >= p->n_selectors) || !field)
10239 s = selector_find_by_id(p, selector_id);
10243 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10244 field->is_header = 0;
10245 field->n_bits = s->group_id_field->n_bits;
10246 field->offset = s->group_id_field->offset;
10252 rte_swx_ctl_selector_field_info_get(struct rte_swx_pipeline *p,
10253 uint32_t selector_id,
10254 uint32_t selector_field_id,
10255 struct rte_swx_ctl_table_match_field_info *field)
10257 struct selector *s;
10260 if (!p || (selector_id >= p->n_selectors) || !field)
10263 s = selector_find_by_id(p, selector_id);
10264 if (!s || (selector_field_id >= s->n_selector_fields))
10267 f = s->selector_fields[selector_field_id];
10268 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10269 field->is_header = s->selector_header ? 1 : 0;
10270 field->n_bits = f->n_bits;
10271 field->offset = f->offset;
10277 rte_swx_ctl_selector_member_id_field_info_get(struct rte_swx_pipeline *p,
10278 uint32_t selector_id,
10279 struct rte_swx_ctl_table_match_field_info *field)
10281 struct selector *s;
10283 if (!p || (selector_id >= p->n_selectors) || !field)
10286 s = selector_find_by_id(p, selector_id);
10290 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10291 field->is_header = 0;
10292 field->n_bits = s->member_id_field->n_bits;
10293 field->offset = s->member_id_field->offset;
10299 rte_swx_ctl_learner_info_get(struct rte_swx_pipeline *p,
10300 uint32_t learner_id,
10301 struct rte_swx_ctl_learner_info *learner)
10303 struct learner *l = NULL;
10305 if (!p || !learner)
10308 l = learner_find_by_id(p, learner_id);
10312 strcpy(learner->name, l->name);
10314 learner->n_match_fields = l->n_fields;
10315 learner->n_actions = l->n_actions;
10316 learner->default_action_is_const = l->default_action_is_const;
10317 learner->size = l->size;
10323 rte_swx_ctl_learner_match_field_info_get(struct rte_swx_pipeline *p,
10324 uint32_t learner_id,
10325 uint32_t match_field_id,
10326 struct rte_swx_ctl_table_match_field_info *match_field)
10331 if (!p || (learner_id >= p->n_learners) || !match_field)
10334 l = learner_find_by_id(p, learner_id);
10335 if (!l || (match_field_id >= l->n_fields))
10338 f = l->fields[match_field_id];
10339 match_field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10340 match_field->is_header = l->header ? 1 : 0;
10341 match_field->n_bits = f->n_bits;
10342 match_field->offset = f->offset;
10348 rte_swx_ctl_learner_action_info_get(struct rte_swx_pipeline *p,
10349 uint32_t learner_id,
10350 uint32_t learner_action_id,
10351 struct rte_swx_ctl_table_action_info *learner_action)
10355 if (!p || (learner_id >= p->n_learners) || !learner_action)
10358 l = learner_find_by_id(p, learner_id);
10359 if (!l || (learner_action_id >= l->n_actions))
10362 learner_action->action_id = l->actions[learner_action_id]->id;
10368 rte_swx_pipeline_table_state_get(struct rte_swx_pipeline *p,
10369 struct rte_swx_table_state **table_state)
10371 if (!p || !table_state || !p->build_done)
10374 *table_state = p->table_state;
10379 rte_swx_pipeline_table_state_set(struct rte_swx_pipeline *p,
10380 struct rte_swx_table_state *table_state)
10382 if (!p || !table_state || !p->build_done)
10385 p->table_state = table_state;
10390 rte_swx_ctl_pipeline_port_in_stats_read(struct rte_swx_pipeline *p,
10392 struct rte_swx_port_in_stats *stats)
10394 struct port_in *port;
10399 port = port_in_find(p, port_id);
10403 port->type->ops.stats_read(port->obj, stats);
10408 rte_swx_ctl_pipeline_port_out_stats_read(struct rte_swx_pipeline *p,
10410 struct rte_swx_port_out_stats *stats)
10412 struct port_out *port;
10417 port = port_out_find(p, port_id);
10421 port->type->ops.stats_read(port->obj, stats);
10426 rte_swx_ctl_pipeline_table_stats_read(struct rte_swx_pipeline *p,
10427 const char *table_name,
10428 struct rte_swx_table_stats *stats)
10430 struct table *table;
10431 struct table_statistics *table_stats;
10433 if (!p || !table_name || !table_name[0] || !stats || !stats->n_pkts_action)
10436 table = table_find(p, table_name);
10440 table_stats = &p->table_stats[table->id];
10442 memcpy(stats->n_pkts_action,
10443 table_stats->n_pkts_action,
10444 p->n_actions * sizeof(uint64_t));
10446 stats->n_pkts_hit = table_stats->n_pkts_hit[1];
10447 stats->n_pkts_miss = table_stats->n_pkts_hit[0];
10453 rte_swx_ctl_pipeline_selector_stats_read(struct rte_swx_pipeline *p,
10454 const char *selector_name,
10455 struct rte_swx_pipeline_selector_stats *stats)
10457 struct selector *s;
10459 if (!p || !selector_name || !selector_name[0] || !stats)
10462 s = selector_find(p, selector_name);
10466 stats->n_pkts = p->selector_stats[s->id].n_pkts;
10472 rte_swx_ctl_pipeline_learner_stats_read(struct rte_swx_pipeline *p,
10473 const char *learner_name,
10474 struct rte_swx_learner_stats *stats)
10477 struct learner_statistics *learner_stats;
10479 if (!p || !learner_name || !learner_name[0] || !stats || !stats->n_pkts_action)
10482 l = learner_find(p, learner_name);
10486 learner_stats = &p->learner_stats[l->id];
10488 memcpy(stats->n_pkts_action,
10489 learner_stats->n_pkts_action,
10490 p->n_actions * sizeof(uint64_t));
10492 stats->n_pkts_hit = learner_stats->n_pkts_hit[1];
10493 stats->n_pkts_miss = learner_stats->n_pkts_hit[0];
10495 stats->n_pkts_learn_ok = learner_stats->n_pkts_learn[0];
10496 stats->n_pkts_learn_err = learner_stats->n_pkts_learn[1];
10498 stats->n_pkts_forget = learner_stats->n_pkts_forget;
10504 rte_swx_ctl_regarray_info_get(struct rte_swx_pipeline *p,
10505 uint32_t regarray_id,
10506 struct rte_swx_ctl_regarray_info *regarray)
10508 struct regarray *r;
10510 if (!p || !regarray)
10513 r = regarray_find_by_id(p, regarray_id);
10517 strcpy(regarray->name, r->name);
10518 regarray->size = r->size;
10523 rte_swx_ctl_pipeline_regarray_read(struct rte_swx_pipeline *p,
10524 const char *regarray_name,
10525 uint32_t regarray_index,
10528 struct regarray *regarray;
10529 struct regarray_runtime *r;
10531 if (!p || !regarray_name || !value)
10534 regarray = regarray_find(p, regarray_name);
10535 if (!regarray || (regarray_index >= regarray->size))
10538 r = &p->regarray_runtime[regarray->id];
10539 *value = r->regarray[regarray_index];
10544 rte_swx_ctl_pipeline_regarray_write(struct rte_swx_pipeline *p,
10545 const char *regarray_name,
10546 uint32_t regarray_index,
10549 struct regarray *regarray;
10550 struct regarray_runtime *r;
10552 if (!p || !regarray_name)
10555 regarray = regarray_find(p, regarray_name);
10556 if (!regarray || (regarray_index >= regarray->size))
10559 r = &p->regarray_runtime[regarray->id];
10560 r->regarray[regarray_index] = value;
10565 rte_swx_ctl_metarray_info_get(struct rte_swx_pipeline *p,
10566 uint32_t metarray_id,
10567 struct rte_swx_ctl_metarray_info *metarray)
10569 struct metarray *m;
10571 if (!p || !metarray)
10574 m = metarray_find_by_id(p, metarray_id);
10578 strcpy(metarray->name, m->name);
10579 metarray->size = m->size;
10584 rte_swx_ctl_meter_profile_add(struct rte_swx_pipeline *p,
10586 struct rte_meter_trtcm_params *params)
10588 struct meter_profile *mp;
10592 CHECK_NAME(name, EINVAL);
10593 CHECK(params, EINVAL);
10594 CHECK(!meter_profile_find(p, name), EEXIST);
10596 /* Node allocation. */
10597 mp = calloc(1, sizeof(struct meter_profile));
10600 /* Node initialization. */
10601 strcpy(mp->name, name);
10602 memcpy(&mp->params, params, sizeof(struct rte_meter_trtcm_params));
10603 status = rte_meter_trtcm_profile_config(&mp->profile, params);
10609 /* Node add to tailq. */
10610 TAILQ_INSERT_TAIL(&p->meter_profiles, mp, node);
10616 rte_swx_ctl_meter_profile_delete(struct rte_swx_pipeline *p,
10619 struct meter_profile *mp;
10622 CHECK_NAME(name, EINVAL);
10624 mp = meter_profile_find(p, name);
10626 CHECK(!mp->n_users, EBUSY);
10628 /* Remove node from tailq. */
10629 TAILQ_REMOVE(&p->meter_profiles, mp, node);
10636 rte_swx_ctl_meter_reset(struct rte_swx_pipeline *p,
10637 const char *metarray_name,
10638 uint32_t metarray_index)
10640 struct meter_profile *mp_old;
10641 struct metarray *metarray;
10642 struct metarray_runtime *metarray_runtime;
10646 CHECK_NAME(metarray_name, EINVAL);
10648 metarray = metarray_find(p, metarray_name);
10649 CHECK(metarray, EINVAL);
10650 CHECK(metarray_index < metarray->size, EINVAL);
10652 metarray_runtime = &p->metarray_runtime[metarray->id];
10653 m = &metarray_runtime->metarray[metarray_index];
10654 mp_old = m->profile;
10664 rte_swx_ctl_meter_set(struct rte_swx_pipeline *p,
10665 const char *metarray_name,
10666 uint32_t metarray_index,
10667 const char *profile_name)
10669 struct meter_profile *mp, *mp_old;
10670 struct metarray *metarray;
10671 struct metarray_runtime *metarray_runtime;
10675 CHECK_NAME(metarray_name, EINVAL);
10677 metarray = metarray_find(p, metarray_name);
10678 CHECK(metarray, EINVAL);
10679 CHECK(metarray_index < metarray->size, EINVAL);
10681 mp = meter_profile_find(p, profile_name);
10684 metarray_runtime = &p->metarray_runtime[metarray->id];
10685 m = &metarray_runtime->metarray[metarray_index];
10686 mp_old = m->profile;
10688 memset(m, 0, sizeof(struct meter));
10689 rte_meter_trtcm_config(&m->m, &mp->profile);
10691 m->color_mask = RTE_COLORS;
10700 rte_swx_ctl_meter_stats_read(struct rte_swx_pipeline *p,
10701 const char *metarray_name,
10702 uint32_t metarray_index,
10703 struct rte_swx_ctl_meter_stats *stats)
10705 struct metarray *metarray;
10706 struct metarray_runtime *metarray_runtime;
10710 CHECK_NAME(metarray_name, EINVAL);
10712 metarray = metarray_find(p, metarray_name);
10713 CHECK(metarray, EINVAL);
10714 CHECK(metarray_index < metarray->size, EINVAL);
10716 CHECK(stats, EINVAL);
10718 metarray_runtime = &p->metarray_runtime[metarray->id];
10719 m = &metarray_runtime->metarray[metarray_index];
10721 memcpy(stats->n_pkts, m->n_pkts, sizeof(m->n_pkts));
10722 memcpy(stats->n_bytes, m->n_bytes, sizeof(m->n_bytes));