1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2020 Intel Corporation
9 #include "rte_swx_pipeline_internal.h"
11 #define CHECK(condition, err_code) \
17 #define CHECK_NAME(name, err_code) \
20 (strnlen((name), RTE_SWX_NAME_SIZE) < RTE_SWX_NAME_SIZE), \
23 #define CHECK_INSTRUCTION(instr, err_code) \
26 (strnlen((instr), RTE_SWX_INSTRUCTION_SIZE) < \
27 RTE_SWX_INSTRUCTION_SIZE), \
33 #ifndef RTE_SWX_PIPELINE_HUGE_PAGES_DISABLE
35 #include <rte_malloc.h>
38 env_malloc(size_t size, size_t alignment, int numa_node)
40 return rte_zmalloc_socket(NULL, size, alignment, numa_node);
44 env_free(void *start, size_t size __rte_unused)
54 env_malloc(size_t size, size_t alignment __rte_unused, int numa_node)
58 if (numa_available() == -1)
61 start = numa_alloc_onnode(size, numa_node);
65 memset(start, 0, size);
70 env_free(void *start, size_t size)
72 if (numa_available() == -1)
75 numa_free(start, size);
83 static struct struct_type *
84 struct_type_find(struct rte_swx_pipeline *p, const char *name)
86 struct struct_type *elem;
88 TAILQ_FOREACH(elem, &p->struct_types, node)
89 if (strcmp(elem->name, name) == 0)
96 struct_type_field_find(struct struct_type *st, const char *name)
100 for (i = 0; i < st->n_fields; i++) {
101 struct field *f = &st->fields[i];
103 if (strcmp(f->name, name) == 0)
111 rte_swx_pipeline_struct_type_register(struct rte_swx_pipeline *p,
113 struct rte_swx_field_params *fields,
115 int last_field_has_variable_size)
117 struct struct_type *st;
121 CHECK_NAME(name, EINVAL);
122 CHECK(fields, EINVAL);
123 CHECK(n_fields, EINVAL);
125 for (i = 0; i < n_fields; i++) {
126 struct rte_swx_field_params *f = &fields[i];
127 int var_size = ((i == n_fields - 1) && last_field_has_variable_size) ? 1 : 0;
130 CHECK_NAME(f->name, EINVAL);
131 CHECK(f->n_bits, EINVAL);
132 CHECK((f->n_bits <= 64) || var_size, EINVAL);
133 CHECK((f->n_bits & 7) == 0, EINVAL);
135 for (j = 0; j < i; j++) {
136 struct rte_swx_field_params *f_prev = &fields[j];
138 CHECK(strcmp(f->name, f_prev->name), EINVAL);
142 CHECK(!struct_type_find(p, name), EEXIST);
144 /* Node allocation. */
145 st = calloc(1, sizeof(struct struct_type));
148 st->fields = calloc(n_fields, sizeof(struct field));
154 /* Node initialization. */
155 strcpy(st->name, name);
156 for (i = 0; i < n_fields; i++) {
157 struct field *dst = &st->fields[i];
158 struct rte_swx_field_params *src = &fields[i];
159 int var_size = ((i == n_fields - 1) && last_field_has_variable_size) ? 1 : 0;
161 strcpy(dst->name, src->name);
162 dst->n_bits = src->n_bits;
163 dst->offset = st->n_bits;
164 dst->var_size = var_size;
166 st->n_bits += src->n_bits;
167 st->n_bits_min += var_size ? 0 : src->n_bits;
169 st->n_fields = n_fields;
170 st->var_size = last_field_has_variable_size;
172 /* Node add to tailq. */
173 TAILQ_INSERT_TAIL(&p->struct_types, st, node);
179 struct_build(struct rte_swx_pipeline *p)
183 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
184 struct thread *t = &p->threads[i];
186 t->structs = calloc(p->n_structs, sizeof(uint8_t *));
187 CHECK(t->structs, ENOMEM);
194 struct_build_free(struct rte_swx_pipeline *p)
198 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
199 struct thread *t = &p->threads[i];
207 struct_free(struct rte_swx_pipeline *p)
209 struct_build_free(p);
213 struct struct_type *elem;
215 elem = TAILQ_FIRST(&p->struct_types);
219 TAILQ_REMOVE(&p->struct_types, elem, node);
228 static struct port_in_type *
229 port_in_type_find(struct rte_swx_pipeline *p, const char *name)
231 struct port_in_type *elem;
236 TAILQ_FOREACH(elem, &p->port_in_types, node)
237 if (strcmp(elem->name, name) == 0)
244 rte_swx_pipeline_port_in_type_register(struct rte_swx_pipeline *p,
246 struct rte_swx_port_in_ops *ops)
248 struct port_in_type *elem;
251 CHECK_NAME(name, EINVAL);
253 CHECK(ops->create, EINVAL);
254 CHECK(ops->free, EINVAL);
255 CHECK(ops->pkt_rx, EINVAL);
256 CHECK(ops->stats_read, EINVAL);
258 CHECK(!port_in_type_find(p, name), EEXIST);
260 /* Node allocation. */
261 elem = calloc(1, sizeof(struct port_in_type));
264 /* Node initialization. */
265 strcpy(elem->name, name);
266 memcpy(&elem->ops, ops, sizeof(*ops));
268 /* Node add to tailq. */
269 TAILQ_INSERT_TAIL(&p->port_in_types, elem, node);
274 static struct port_in *
275 port_in_find(struct rte_swx_pipeline *p, uint32_t port_id)
277 struct port_in *port;
279 TAILQ_FOREACH(port, &p->ports_in, node)
280 if (port->id == port_id)
287 rte_swx_pipeline_port_in_config(struct rte_swx_pipeline *p,
289 const char *port_type_name,
292 struct port_in_type *type = NULL;
293 struct port_in *port = NULL;
298 CHECK(!port_in_find(p, port_id), EINVAL);
300 CHECK_NAME(port_type_name, EINVAL);
301 type = port_in_type_find(p, port_type_name);
304 obj = type->ops.create(args);
307 /* Node allocation. */
308 port = calloc(1, sizeof(struct port_in));
311 /* Node initialization. */
316 /* Node add to tailq. */
317 TAILQ_INSERT_TAIL(&p->ports_in, port, node);
318 if (p->n_ports_in < port_id + 1)
319 p->n_ports_in = port_id + 1;
325 port_in_build(struct rte_swx_pipeline *p)
327 struct port_in *port;
330 CHECK(p->n_ports_in, EINVAL);
331 CHECK(rte_is_power_of_2(p->n_ports_in), EINVAL);
333 for (i = 0; i < p->n_ports_in; i++)
334 CHECK(port_in_find(p, i), EINVAL);
336 p->in = calloc(p->n_ports_in, sizeof(struct port_in_runtime));
337 CHECK(p->in, ENOMEM);
339 TAILQ_FOREACH(port, &p->ports_in, node) {
340 struct port_in_runtime *in = &p->in[port->id];
342 in->pkt_rx = port->type->ops.pkt_rx;
350 port_in_build_free(struct rte_swx_pipeline *p)
357 port_in_free(struct rte_swx_pipeline *p)
359 port_in_build_free(p);
363 struct port_in *port;
365 port = TAILQ_FIRST(&p->ports_in);
369 TAILQ_REMOVE(&p->ports_in, port, node);
370 port->type->ops.free(port->obj);
374 /* Input port types. */
376 struct port_in_type *elem;
378 elem = TAILQ_FIRST(&p->port_in_types);
382 TAILQ_REMOVE(&p->port_in_types, elem, node);
390 static struct port_out_type *
391 port_out_type_find(struct rte_swx_pipeline *p, const char *name)
393 struct port_out_type *elem;
398 TAILQ_FOREACH(elem, &p->port_out_types, node)
399 if (!strcmp(elem->name, name))
406 rte_swx_pipeline_port_out_type_register(struct rte_swx_pipeline *p,
408 struct rte_swx_port_out_ops *ops)
410 struct port_out_type *elem;
413 CHECK_NAME(name, EINVAL);
415 CHECK(ops->create, EINVAL);
416 CHECK(ops->free, EINVAL);
417 CHECK(ops->pkt_tx, EINVAL);
418 CHECK(ops->stats_read, EINVAL);
420 CHECK(!port_out_type_find(p, name), EEXIST);
422 /* Node allocation. */
423 elem = calloc(1, sizeof(struct port_out_type));
426 /* Node initialization. */
427 strcpy(elem->name, name);
428 memcpy(&elem->ops, ops, sizeof(*ops));
430 /* Node add to tailq. */
431 TAILQ_INSERT_TAIL(&p->port_out_types, elem, node);
436 static struct port_out *
437 port_out_find(struct rte_swx_pipeline *p, uint32_t port_id)
439 struct port_out *port;
441 TAILQ_FOREACH(port, &p->ports_out, node)
442 if (port->id == port_id)
449 rte_swx_pipeline_port_out_config(struct rte_swx_pipeline *p,
451 const char *port_type_name,
454 struct port_out_type *type = NULL;
455 struct port_out *port = NULL;
460 CHECK(!port_out_find(p, port_id), EINVAL);
462 CHECK_NAME(port_type_name, EINVAL);
463 type = port_out_type_find(p, port_type_name);
466 obj = type->ops.create(args);
469 /* Node allocation. */
470 port = calloc(1, sizeof(struct port_out));
473 /* Node initialization. */
478 /* Node add to tailq. */
479 TAILQ_INSERT_TAIL(&p->ports_out, port, node);
480 if (p->n_ports_out < port_id + 1)
481 p->n_ports_out = port_id + 1;
487 port_out_build(struct rte_swx_pipeline *p)
489 struct port_out *port;
492 CHECK(p->n_ports_out, EINVAL);
494 for (i = 0; i < p->n_ports_out; i++)
495 CHECK(port_out_find(p, i), EINVAL);
497 p->out = calloc(p->n_ports_out, sizeof(struct port_out_runtime));
498 CHECK(p->out, ENOMEM);
500 TAILQ_FOREACH(port, &p->ports_out, node) {
501 struct port_out_runtime *out = &p->out[port->id];
503 out->pkt_tx = port->type->ops.pkt_tx;
504 out->flush = port->type->ops.flush;
505 out->obj = port->obj;
512 port_out_build_free(struct rte_swx_pipeline *p)
519 port_out_free(struct rte_swx_pipeline *p)
521 port_out_build_free(p);
525 struct port_out *port;
527 port = TAILQ_FIRST(&p->ports_out);
531 TAILQ_REMOVE(&p->ports_out, port, node);
532 port->type->ops.free(port->obj);
536 /* Output port types. */
538 struct port_out_type *elem;
540 elem = TAILQ_FIRST(&p->port_out_types);
544 TAILQ_REMOVE(&p->port_out_types, elem, node);
552 static struct extern_type *
553 extern_type_find(struct rte_swx_pipeline *p, const char *name)
555 struct extern_type *elem;
557 TAILQ_FOREACH(elem, &p->extern_types, node)
558 if (strcmp(elem->name, name) == 0)
564 static struct extern_type_member_func *
565 extern_type_member_func_find(struct extern_type *type, const char *name)
567 struct extern_type_member_func *elem;
569 TAILQ_FOREACH(elem, &type->funcs, node)
570 if (strcmp(elem->name, name) == 0)
576 static struct extern_obj *
577 extern_obj_find(struct rte_swx_pipeline *p, const char *name)
579 struct extern_obj *elem;
581 TAILQ_FOREACH(elem, &p->extern_objs, node)
582 if (strcmp(elem->name, name) == 0)
588 static struct extern_type_member_func *
589 extern_obj_member_func_parse(struct rte_swx_pipeline *p,
591 struct extern_obj **obj)
593 struct extern_obj *object;
594 struct extern_type_member_func *func;
595 char *object_name, *func_name;
597 if (name[0] != 'e' || name[1] != '.')
600 object_name = strdup(&name[2]);
604 func_name = strchr(object_name, '.');
613 object = extern_obj_find(p, object_name);
619 func = extern_type_member_func_find(object->type, func_name);
632 static struct field *
633 extern_obj_mailbox_field_parse(struct rte_swx_pipeline *p,
635 struct extern_obj **object)
637 struct extern_obj *obj;
639 char *obj_name, *field_name;
641 if ((name[0] != 'e') || (name[1] != '.'))
644 obj_name = strdup(&name[2]);
648 field_name = strchr(obj_name, '.');
657 obj = extern_obj_find(p, obj_name);
663 f = struct_type_field_find(obj->type->mailbox_struct_type, field_name);
677 rte_swx_pipeline_extern_type_register(struct rte_swx_pipeline *p,
679 const char *mailbox_struct_type_name,
680 rte_swx_extern_type_constructor_t constructor,
681 rte_swx_extern_type_destructor_t destructor)
683 struct extern_type *elem;
684 struct struct_type *mailbox_struct_type;
688 CHECK_NAME(name, EINVAL);
689 CHECK(!extern_type_find(p, name), EEXIST);
691 CHECK_NAME(mailbox_struct_type_name, EINVAL);
692 mailbox_struct_type = struct_type_find(p, mailbox_struct_type_name);
693 CHECK(mailbox_struct_type, EINVAL);
694 CHECK(!mailbox_struct_type->var_size, EINVAL);
696 CHECK(constructor, EINVAL);
697 CHECK(destructor, EINVAL);
699 /* Node allocation. */
700 elem = calloc(1, sizeof(struct extern_type));
703 /* Node initialization. */
704 strcpy(elem->name, name);
705 elem->mailbox_struct_type = mailbox_struct_type;
706 elem->constructor = constructor;
707 elem->destructor = destructor;
708 TAILQ_INIT(&elem->funcs);
710 /* Node add to tailq. */
711 TAILQ_INSERT_TAIL(&p->extern_types, elem, node);
717 rte_swx_pipeline_extern_type_member_func_register(struct rte_swx_pipeline *p,
718 const char *extern_type_name,
720 rte_swx_extern_type_member_func_t member_func)
722 struct extern_type *type;
723 struct extern_type_member_func *type_member;
727 CHECK_NAME(extern_type_name, EINVAL);
728 type = extern_type_find(p, extern_type_name);
730 CHECK(type->n_funcs < RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX, ENOSPC);
732 CHECK_NAME(name, EINVAL);
733 CHECK(!extern_type_member_func_find(type, name), EEXIST);
735 CHECK(member_func, EINVAL);
737 /* Node allocation. */
738 type_member = calloc(1, sizeof(struct extern_type_member_func));
739 CHECK(type_member, ENOMEM);
741 /* Node initialization. */
742 strcpy(type_member->name, name);
743 type_member->func = member_func;
744 type_member->id = type->n_funcs;
746 /* Node add to tailq. */
747 TAILQ_INSERT_TAIL(&type->funcs, type_member, node);
754 rte_swx_pipeline_extern_object_config(struct rte_swx_pipeline *p,
755 const char *extern_type_name,
759 struct extern_type *type;
760 struct extern_obj *obj;
765 CHECK_NAME(extern_type_name, EINVAL);
766 type = extern_type_find(p, extern_type_name);
769 CHECK_NAME(name, EINVAL);
770 CHECK(!extern_obj_find(p, name), EEXIST);
772 /* Node allocation. */
773 obj = calloc(1, sizeof(struct extern_obj));
776 /* Object construction. */
777 obj_handle = type->constructor(args);
783 /* Node initialization. */
784 strcpy(obj->name, name);
786 obj->obj = obj_handle;
787 obj->struct_id = p->n_structs;
788 obj->id = p->n_extern_objs;
790 /* Node add to tailq. */
791 TAILQ_INSERT_TAIL(&p->extern_objs, obj, node);
799 extern_obj_build(struct rte_swx_pipeline *p)
803 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
804 struct thread *t = &p->threads[i];
805 struct extern_obj *obj;
807 t->extern_objs = calloc(p->n_extern_objs,
808 sizeof(struct extern_obj_runtime));
809 CHECK(t->extern_objs, ENOMEM);
811 TAILQ_FOREACH(obj, &p->extern_objs, node) {
812 struct extern_obj_runtime *r =
813 &t->extern_objs[obj->id];
814 struct extern_type_member_func *func;
815 uint32_t mailbox_size =
816 obj->type->mailbox_struct_type->n_bits / 8;
820 r->mailbox = calloc(1, mailbox_size);
821 CHECK(r->mailbox, ENOMEM);
823 TAILQ_FOREACH(func, &obj->type->funcs, node)
824 r->funcs[func->id] = func->func;
826 t->structs[obj->struct_id] = r->mailbox;
834 extern_obj_build_free(struct rte_swx_pipeline *p)
838 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
839 struct thread *t = &p->threads[i];
845 for (j = 0; j < p->n_extern_objs; j++) {
846 struct extern_obj_runtime *r = &t->extern_objs[j];
851 free(t->extern_objs);
852 t->extern_objs = NULL;
857 extern_obj_free(struct rte_swx_pipeline *p)
859 extern_obj_build_free(p);
861 /* Extern objects. */
863 struct extern_obj *elem;
865 elem = TAILQ_FIRST(&p->extern_objs);
869 TAILQ_REMOVE(&p->extern_objs, elem, node);
871 elem->type->destructor(elem->obj);
877 struct extern_type *elem;
879 elem = TAILQ_FIRST(&p->extern_types);
883 TAILQ_REMOVE(&p->extern_types, elem, node);
886 struct extern_type_member_func *func;
888 func = TAILQ_FIRST(&elem->funcs);
892 TAILQ_REMOVE(&elem->funcs, func, node);
903 static struct extern_func *
904 extern_func_find(struct rte_swx_pipeline *p, const char *name)
906 struct extern_func *elem;
908 TAILQ_FOREACH(elem, &p->extern_funcs, node)
909 if (strcmp(elem->name, name) == 0)
915 static struct extern_func *
916 extern_func_parse(struct rte_swx_pipeline *p,
919 if (name[0] != 'f' || name[1] != '.')
922 return extern_func_find(p, &name[2]);
925 static struct field *
926 extern_func_mailbox_field_parse(struct rte_swx_pipeline *p,
928 struct extern_func **function)
930 struct extern_func *func;
932 char *func_name, *field_name;
934 if ((name[0] != 'f') || (name[1] != '.'))
937 func_name = strdup(&name[2]);
941 field_name = strchr(func_name, '.');
950 func = extern_func_find(p, func_name);
956 f = struct_type_field_find(func->mailbox_struct_type, field_name);
970 rte_swx_pipeline_extern_func_register(struct rte_swx_pipeline *p,
972 const char *mailbox_struct_type_name,
973 rte_swx_extern_func_t func)
975 struct extern_func *f;
976 struct struct_type *mailbox_struct_type;
980 CHECK_NAME(name, EINVAL);
981 CHECK(!extern_func_find(p, name), EEXIST);
983 CHECK_NAME(mailbox_struct_type_name, EINVAL);
984 mailbox_struct_type = struct_type_find(p, mailbox_struct_type_name);
985 CHECK(mailbox_struct_type, EINVAL);
986 CHECK(!mailbox_struct_type->var_size, EINVAL);
990 /* Node allocation. */
991 f = calloc(1, sizeof(struct extern_func));
994 /* Node initialization. */
995 strcpy(f->name, name);
996 f->mailbox_struct_type = mailbox_struct_type;
998 f->struct_id = p->n_structs;
999 f->id = p->n_extern_funcs;
1001 /* Node add to tailq. */
1002 TAILQ_INSERT_TAIL(&p->extern_funcs, f, node);
1003 p->n_extern_funcs++;
1010 extern_func_build(struct rte_swx_pipeline *p)
1014 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1015 struct thread *t = &p->threads[i];
1016 struct extern_func *func;
1018 /* Memory allocation. */
1019 t->extern_funcs = calloc(p->n_extern_funcs,
1020 sizeof(struct extern_func_runtime));
1021 CHECK(t->extern_funcs, ENOMEM);
1023 /* Extern function. */
1024 TAILQ_FOREACH(func, &p->extern_funcs, node) {
1025 struct extern_func_runtime *r =
1026 &t->extern_funcs[func->id];
1027 uint32_t mailbox_size =
1028 func->mailbox_struct_type->n_bits / 8;
1030 r->func = func->func;
1032 r->mailbox = calloc(1, mailbox_size);
1033 CHECK(r->mailbox, ENOMEM);
1035 t->structs[func->struct_id] = r->mailbox;
1043 extern_func_build_free(struct rte_swx_pipeline *p)
1047 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1048 struct thread *t = &p->threads[i];
1051 if (!t->extern_funcs)
1054 for (j = 0; j < p->n_extern_funcs; j++) {
1055 struct extern_func_runtime *r = &t->extern_funcs[j];
1060 free(t->extern_funcs);
1061 t->extern_funcs = NULL;
1066 extern_func_free(struct rte_swx_pipeline *p)
1068 extern_func_build_free(p);
1071 struct extern_func *elem;
1073 elem = TAILQ_FIRST(&p->extern_funcs);
1077 TAILQ_REMOVE(&p->extern_funcs, elem, node);
1085 static struct header *
1086 header_find(struct rte_swx_pipeline *p, const char *name)
1088 struct header *elem;
1090 TAILQ_FOREACH(elem, &p->headers, node)
1091 if (strcmp(elem->name, name) == 0)
1097 static struct header *
1098 header_find_by_struct_id(struct rte_swx_pipeline *p, uint32_t struct_id)
1100 struct header *elem;
1102 TAILQ_FOREACH(elem, &p->headers, node)
1103 if (elem->struct_id == struct_id)
1109 static struct header *
1110 header_parse(struct rte_swx_pipeline *p,
1113 if (name[0] != 'h' || name[1] != '.')
1116 return header_find(p, &name[2]);
1119 static struct field *
1120 header_field_parse(struct rte_swx_pipeline *p,
1122 struct header **header)
1126 char *header_name, *field_name;
1128 if ((name[0] != 'h') || (name[1] != '.'))
1131 header_name = strdup(&name[2]);
1135 field_name = strchr(header_name, '.');
1144 h = header_find(p, header_name);
1150 f = struct_type_field_find(h->st, field_name);
1164 rte_swx_pipeline_packet_header_register(struct rte_swx_pipeline *p,
1166 const char *struct_type_name)
1168 struct struct_type *st;
1170 size_t n_headers_max;
1173 CHECK_NAME(name, EINVAL);
1174 CHECK_NAME(struct_type_name, EINVAL);
1176 CHECK(!header_find(p, name), EEXIST);
1178 st = struct_type_find(p, struct_type_name);
1181 n_headers_max = RTE_SIZEOF_FIELD(struct thread, valid_headers) * 8;
1182 CHECK(p->n_headers < n_headers_max, ENOSPC);
1184 /* Node allocation. */
1185 h = calloc(1, sizeof(struct header));
1188 /* Node initialization. */
1189 strcpy(h->name, name);
1191 h->struct_id = p->n_structs;
1192 h->id = p->n_headers;
1194 /* Node add to tailq. */
1195 TAILQ_INSERT_TAIL(&p->headers, h, node);
1203 header_build(struct rte_swx_pipeline *p)
1206 uint32_t n_bytes = 0, i;
1208 TAILQ_FOREACH(h, &p->headers, node) {
1209 n_bytes += h->st->n_bits / 8;
1212 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1213 struct thread *t = &p->threads[i];
1214 uint32_t offset = 0;
1216 t->headers = calloc(p->n_headers,
1217 sizeof(struct header_runtime));
1218 CHECK(t->headers, ENOMEM);
1220 t->headers_out = calloc(p->n_headers,
1221 sizeof(struct header_out_runtime));
1222 CHECK(t->headers_out, ENOMEM);
1224 t->header_storage = calloc(1, n_bytes);
1225 CHECK(t->header_storage, ENOMEM);
1227 t->header_out_storage = calloc(1, n_bytes);
1228 CHECK(t->header_out_storage, ENOMEM);
1230 TAILQ_FOREACH(h, &p->headers, node) {
1231 uint8_t *header_storage;
1232 uint32_t n_bytes = h->st->n_bits / 8;
1234 header_storage = &t->header_storage[offset];
1237 t->headers[h->id].ptr0 = header_storage;
1238 t->headers[h->id].n_bytes = n_bytes;
1240 t->structs[h->struct_id] = header_storage;
1248 header_build_free(struct rte_swx_pipeline *p)
1252 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1253 struct thread *t = &p->threads[i];
1255 free(t->headers_out);
1256 t->headers_out = NULL;
1261 free(t->header_out_storage);
1262 t->header_out_storage = NULL;
1264 free(t->header_storage);
1265 t->header_storage = NULL;
1270 header_free(struct rte_swx_pipeline *p)
1272 header_build_free(p);
1275 struct header *elem;
1277 elem = TAILQ_FIRST(&p->headers);
1281 TAILQ_REMOVE(&p->headers, elem, node);
1289 static struct field *
1290 metadata_field_parse(struct rte_swx_pipeline *p, const char *name)
1292 if (!p->metadata_st)
1295 if (name[0] != 'm' || name[1] != '.')
1298 return struct_type_field_find(p->metadata_st, &name[2]);
1302 rte_swx_pipeline_packet_metadata_register(struct rte_swx_pipeline *p,
1303 const char *struct_type_name)
1305 struct struct_type *st = NULL;
1309 CHECK_NAME(struct_type_name, EINVAL);
1310 st = struct_type_find(p, struct_type_name);
1312 CHECK(!st->var_size, EINVAL);
1313 CHECK(!p->metadata_st, EINVAL);
1315 p->metadata_st = st;
1316 p->metadata_struct_id = p->n_structs;
1324 metadata_build(struct rte_swx_pipeline *p)
1326 uint32_t n_bytes = p->metadata_st->n_bits / 8;
1329 /* Thread-level initialization. */
1330 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1331 struct thread *t = &p->threads[i];
1334 metadata = calloc(1, n_bytes);
1335 CHECK(metadata, ENOMEM);
1337 t->metadata = metadata;
1338 t->structs[p->metadata_struct_id] = metadata;
1345 metadata_build_free(struct rte_swx_pipeline *p)
1349 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1350 struct thread *t = &p->threads[i];
1358 metadata_free(struct rte_swx_pipeline *p)
1360 metadata_build_free(p);
1367 instruction_is_tx(enum instruction_type type)
1380 instruction_is_jmp(struct instruction *instr)
1382 switch (instr->type) {
1384 case INSTR_JMP_VALID:
1385 case INSTR_JMP_INVALID:
1387 case INSTR_JMP_MISS:
1388 case INSTR_JMP_ACTION_HIT:
1389 case INSTR_JMP_ACTION_MISS:
1391 case INSTR_JMP_EQ_MH:
1392 case INSTR_JMP_EQ_HM:
1393 case INSTR_JMP_EQ_HH:
1394 case INSTR_JMP_EQ_I:
1396 case INSTR_JMP_NEQ_MH:
1397 case INSTR_JMP_NEQ_HM:
1398 case INSTR_JMP_NEQ_HH:
1399 case INSTR_JMP_NEQ_I:
1401 case INSTR_JMP_LT_MH:
1402 case INSTR_JMP_LT_HM:
1403 case INSTR_JMP_LT_HH:
1404 case INSTR_JMP_LT_MI:
1405 case INSTR_JMP_LT_HI:
1407 case INSTR_JMP_GT_MH:
1408 case INSTR_JMP_GT_HM:
1409 case INSTR_JMP_GT_HH:
1410 case INSTR_JMP_GT_MI:
1411 case INSTR_JMP_GT_HI:
1419 static struct field *
1420 action_field_parse(struct action *action, const char *name);
1422 static struct field *
1423 struct_field_parse(struct rte_swx_pipeline *p,
1424 struct action *action,
1426 uint32_t *struct_id)
1433 struct header *header;
1435 f = header_field_parse(p, name, &header);
1439 *struct_id = header->struct_id;
1445 f = metadata_field_parse(p, name);
1449 *struct_id = p->metadata_struct_id;
1458 f = action_field_parse(action, name);
1468 struct extern_obj *obj;
1470 f = extern_obj_mailbox_field_parse(p, name, &obj);
1474 *struct_id = obj->struct_id;
1480 struct extern_func *func;
1482 f = extern_func_mailbox_field_parse(p, name, &func);
1486 *struct_id = func->struct_id;
1499 instr_rx_translate(struct rte_swx_pipeline *p,
1500 struct action *action,
1503 struct instruction *instr,
1504 struct instruction_data *data __rte_unused)
1508 CHECK(!action, EINVAL);
1509 CHECK(n_tokens == 2, EINVAL);
1511 f = metadata_field_parse(p, tokens[1]);
1514 instr->type = INSTR_RX;
1515 instr->io.io.offset = f->offset / 8;
1516 instr->io.io.n_bits = f->n_bits;
1524 instr_tx_translate(struct rte_swx_pipeline *p,
1525 struct action *action __rte_unused,
1528 struct instruction *instr,
1529 struct instruction_data *data __rte_unused)
1531 char *port = tokens[1];
1535 CHECK(n_tokens == 2, EINVAL);
1537 f = metadata_field_parse(p, port);
1539 instr->type = INSTR_TX;
1540 instr->io.io.offset = f->offset / 8;
1541 instr->io.io.n_bits = f->n_bits;
1546 port_val = strtoul(port, &port, 0);
1547 CHECK(!port[0], EINVAL);
1549 instr->type = INSTR_TX_I;
1550 instr->io.io.val = port_val;
1555 instr_drop_translate(struct rte_swx_pipeline *p,
1556 struct action *action __rte_unused,
1557 char **tokens __rte_unused,
1559 struct instruction *instr,
1560 struct instruction_data *data __rte_unused)
1562 CHECK(n_tokens == 1, EINVAL);
1565 instr->type = INSTR_TX_I;
1566 instr->io.io.val = p->n_ports_out - 1;
1571 instr_tx_exec(struct rte_swx_pipeline *p)
1573 struct thread *t = &p->threads[p->thread_id];
1574 struct instruction *ip = t->ip;
1576 __instr_tx_exec(p, t, ip);
1579 thread_ip_reset(p, t);
1584 instr_tx_i_exec(struct rte_swx_pipeline *p)
1586 struct thread *t = &p->threads[p->thread_id];
1587 struct instruction *ip = t->ip;
1589 __instr_tx_i_exec(p, t, ip);
1592 thread_ip_reset(p, t);
1600 instr_hdr_extract_translate(struct rte_swx_pipeline *p,
1601 struct action *action,
1604 struct instruction *instr,
1605 struct instruction_data *data __rte_unused)
1609 CHECK(!action, EINVAL);
1610 CHECK((n_tokens == 2) || (n_tokens == 3), EINVAL);
1612 h = header_parse(p, tokens[1]);
1615 if (n_tokens == 2) {
1616 CHECK(!h->st->var_size, EINVAL);
1618 instr->type = INSTR_HDR_EXTRACT;
1619 instr->io.hdr.header_id[0] = h->id;
1620 instr->io.hdr.struct_id[0] = h->struct_id;
1621 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
1625 CHECK(h->st->var_size, EINVAL);
1627 mf = metadata_field_parse(p, tokens[2]);
1629 CHECK(!mf->var_size, EINVAL);
1631 instr->type = INSTR_HDR_EXTRACT_M;
1632 instr->io.io.offset = mf->offset / 8;
1633 instr->io.io.n_bits = mf->n_bits;
1634 instr->io.hdr.header_id[0] = h->id;
1635 instr->io.hdr.struct_id[0] = h->struct_id;
1636 instr->io.hdr.n_bytes[0] = h->st->n_bits_min / 8;
1643 instr_hdr_lookahead_translate(struct rte_swx_pipeline *p,
1644 struct action *action,
1647 struct instruction *instr,
1648 struct instruction_data *data __rte_unused)
1652 CHECK(!action, EINVAL);
1653 CHECK(n_tokens == 2, EINVAL);
1655 h = header_parse(p, tokens[1]);
1657 CHECK(!h->st->var_size, EINVAL);
1659 instr->type = INSTR_HDR_LOOKAHEAD;
1660 instr->io.hdr.header_id[0] = h->id;
1661 instr->io.hdr.struct_id[0] = h->struct_id;
1662 instr->io.hdr.n_bytes[0] = 0; /* Unused. */
1668 instr_hdr_extract_exec(struct rte_swx_pipeline *p)
1670 struct thread *t = &p->threads[p->thread_id];
1671 struct instruction *ip = t->ip;
1673 __instr_hdr_extract_exec(p, t, ip);
1680 instr_hdr_extract2_exec(struct rte_swx_pipeline *p)
1682 struct thread *t = &p->threads[p->thread_id];
1683 struct instruction *ip = t->ip;
1685 __instr_hdr_extract2_exec(p, t, ip);
1692 instr_hdr_extract3_exec(struct rte_swx_pipeline *p)
1694 struct thread *t = &p->threads[p->thread_id];
1695 struct instruction *ip = t->ip;
1697 __instr_hdr_extract3_exec(p, t, ip);
1704 instr_hdr_extract4_exec(struct rte_swx_pipeline *p)
1706 struct thread *t = &p->threads[p->thread_id];
1707 struct instruction *ip = t->ip;
1709 __instr_hdr_extract4_exec(p, t, ip);
1716 instr_hdr_extract5_exec(struct rte_swx_pipeline *p)
1718 struct thread *t = &p->threads[p->thread_id];
1719 struct instruction *ip = t->ip;
1721 __instr_hdr_extract5_exec(p, t, ip);
1728 instr_hdr_extract6_exec(struct rte_swx_pipeline *p)
1730 struct thread *t = &p->threads[p->thread_id];
1731 struct instruction *ip = t->ip;
1733 __instr_hdr_extract6_exec(p, t, ip);
1740 instr_hdr_extract7_exec(struct rte_swx_pipeline *p)
1742 struct thread *t = &p->threads[p->thread_id];
1743 struct instruction *ip = t->ip;
1745 __instr_hdr_extract7_exec(p, t, ip);
1752 instr_hdr_extract8_exec(struct rte_swx_pipeline *p)
1754 struct thread *t = &p->threads[p->thread_id];
1755 struct instruction *ip = t->ip;
1757 __instr_hdr_extract8_exec(p, t, ip);
1764 instr_hdr_extract_m_exec(struct rte_swx_pipeline *p)
1766 struct thread *t = &p->threads[p->thread_id];
1767 struct instruction *ip = t->ip;
1769 __instr_hdr_extract_m_exec(p, t, ip);
1776 instr_hdr_lookahead_exec(struct rte_swx_pipeline *p)
1778 struct thread *t = &p->threads[p->thread_id];
1779 struct instruction *ip = t->ip;
1781 __instr_hdr_lookahead_exec(p, t, ip);
1791 instr_hdr_emit_translate(struct rte_swx_pipeline *p,
1792 struct action *action __rte_unused,
1795 struct instruction *instr,
1796 struct instruction_data *data __rte_unused)
1800 CHECK(n_tokens == 2, EINVAL);
1802 h = header_parse(p, tokens[1]);
1805 instr->type = INSTR_HDR_EMIT;
1806 instr->io.hdr.header_id[0] = h->id;
1807 instr->io.hdr.struct_id[0] = h->struct_id;
1808 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
1813 instr_hdr_emit_exec(struct rte_swx_pipeline *p)
1815 struct thread *t = &p->threads[p->thread_id];
1816 struct instruction *ip = t->ip;
1818 __instr_hdr_emit_exec(p, t, ip);
1825 instr_hdr_emit_tx_exec(struct rte_swx_pipeline *p)
1827 struct thread *t = &p->threads[p->thread_id];
1828 struct instruction *ip = t->ip;
1830 __instr_hdr_emit_tx_exec(p, t, ip);
1833 thread_ip_reset(p, t);
1838 instr_hdr_emit2_tx_exec(struct rte_swx_pipeline *p)
1840 struct thread *t = &p->threads[p->thread_id];
1841 struct instruction *ip = t->ip;
1843 __instr_hdr_emit2_tx_exec(p, t, ip);
1846 thread_ip_reset(p, t);
1851 instr_hdr_emit3_tx_exec(struct rte_swx_pipeline *p)
1853 struct thread *t = &p->threads[p->thread_id];
1854 struct instruction *ip = t->ip;
1856 __instr_hdr_emit3_tx_exec(p, t, ip);
1859 thread_ip_reset(p, t);
1864 instr_hdr_emit4_tx_exec(struct rte_swx_pipeline *p)
1866 struct thread *t = &p->threads[p->thread_id];
1867 struct instruction *ip = t->ip;
1869 __instr_hdr_emit4_tx_exec(p, t, ip);
1872 thread_ip_reset(p, t);
1877 instr_hdr_emit5_tx_exec(struct rte_swx_pipeline *p)
1879 struct thread *t = &p->threads[p->thread_id];
1880 struct instruction *ip = t->ip;
1882 __instr_hdr_emit5_tx_exec(p, t, ip);
1885 thread_ip_reset(p, t);
1890 instr_hdr_emit6_tx_exec(struct rte_swx_pipeline *p)
1892 struct thread *t = &p->threads[p->thread_id];
1893 struct instruction *ip = t->ip;
1895 __instr_hdr_emit6_tx_exec(p, t, ip);
1898 thread_ip_reset(p, t);
1903 instr_hdr_emit7_tx_exec(struct rte_swx_pipeline *p)
1905 struct thread *t = &p->threads[p->thread_id];
1906 struct instruction *ip = t->ip;
1908 __instr_hdr_emit7_tx_exec(p, t, ip);
1911 thread_ip_reset(p, t);
1916 instr_hdr_emit8_tx_exec(struct rte_swx_pipeline *p)
1918 struct thread *t = &p->threads[p->thread_id];
1919 struct instruction *ip = t->ip;
1921 __instr_hdr_emit8_tx_exec(p, t, ip);
1924 thread_ip_reset(p, t);
1932 instr_hdr_validate_translate(struct rte_swx_pipeline *p,
1933 struct action *action __rte_unused,
1936 struct instruction *instr,
1937 struct instruction_data *data __rte_unused)
1941 CHECK(n_tokens == 2, EINVAL);
1943 h = header_parse(p, tokens[1]);
1946 instr->type = INSTR_HDR_VALIDATE;
1947 instr->valid.header_id = h->id;
1952 instr_hdr_validate_exec(struct rte_swx_pipeline *p)
1954 struct thread *t = &p->threads[p->thread_id];
1955 struct instruction *ip = t->ip;
1957 __instr_hdr_validate_exec(p, t, ip);
1967 instr_hdr_invalidate_translate(struct rte_swx_pipeline *p,
1968 struct action *action __rte_unused,
1971 struct instruction *instr,
1972 struct instruction_data *data __rte_unused)
1976 CHECK(n_tokens == 2, EINVAL);
1978 h = header_parse(p, tokens[1]);
1981 instr->type = INSTR_HDR_INVALIDATE;
1982 instr->valid.header_id = h->id;
1987 instr_hdr_invalidate_exec(struct rte_swx_pipeline *p)
1989 struct thread *t = &p->threads[p->thread_id];
1990 struct instruction *ip = t->ip;
1992 __instr_hdr_invalidate_exec(p, t, ip);
2001 static struct table *
2002 table_find(struct rte_swx_pipeline *p, const char *name);
2004 static struct selector *
2005 selector_find(struct rte_swx_pipeline *p, const char *name);
2007 static struct learner *
2008 learner_find(struct rte_swx_pipeline *p, const char *name);
2011 instr_table_translate(struct rte_swx_pipeline *p,
2012 struct action *action,
2015 struct instruction *instr,
2016 struct instruction_data *data __rte_unused)
2022 CHECK(!action, EINVAL);
2023 CHECK(n_tokens == 2, EINVAL);
2025 t = table_find(p, tokens[1]);
2027 instr->type = INSTR_TABLE;
2028 instr->table.table_id = t->id;
2032 s = selector_find(p, tokens[1]);
2034 instr->type = INSTR_SELECTOR;
2035 instr->table.table_id = s->id;
2039 l = learner_find(p, tokens[1]);
2041 instr->type = INSTR_LEARNER;
2042 instr->table.table_id = l->id;
2050 instr_table_exec(struct rte_swx_pipeline *p)
2052 struct thread *t = &p->threads[p->thread_id];
2053 struct instruction *ip = t->ip;
2054 uint32_t table_id = ip->table.table_id;
2055 struct rte_swx_table_state *ts = &t->table_state[table_id];
2056 struct table_runtime *table = &t->tables[table_id];
2057 struct table_statistics *stats = &p->table_stats[table_id];
2058 uint64_t action_id, n_pkts_hit, n_pkts_action;
2059 uint8_t *action_data;
2063 done = table->func(ts->obj,
2071 TRACE("[Thread %2u] table %u (not finalized)\n",
2079 action_id = hit ? action_id : ts->default_action_id;
2080 action_data = hit ? action_data : ts->default_action_data;
2081 n_pkts_hit = stats->n_pkts_hit[hit];
2082 n_pkts_action = stats->n_pkts_action[action_id];
2084 TRACE("[Thread %2u] table %u (%s, action %u)\n",
2087 hit ? "hit" : "miss",
2088 (uint32_t)action_id);
2090 t->action_id = action_id;
2091 t->structs[0] = action_data;
2093 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2094 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2097 thread_ip_action_call(p, t, action_id);
2101 instr_selector_exec(struct rte_swx_pipeline *p)
2103 struct thread *t = &p->threads[p->thread_id];
2104 struct instruction *ip = t->ip;
2105 uint32_t selector_id = ip->table.table_id;
2106 struct rte_swx_table_state *ts = &t->table_state[p->n_tables + selector_id];
2107 struct selector_runtime *selector = &t->selectors[selector_id];
2108 struct selector_statistics *stats = &p->selector_stats[selector_id];
2109 uint64_t n_pkts = stats->n_pkts;
2113 done = rte_swx_table_selector_select(ts->obj,
2115 selector->group_id_buffer,
2116 selector->selector_buffer,
2117 selector->member_id_buffer);
2120 TRACE("[Thread %2u] selector %u (not finalized)\n",
2129 TRACE("[Thread %2u] selector %u\n",
2133 stats->n_pkts = n_pkts + 1;
2140 instr_learner_exec(struct rte_swx_pipeline *p)
2142 struct thread *t = &p->threads[p->thread_id];
2143 struct instruction *ip = t->ip;
2144 uint32_t learner_id = ip->table.table_id;
2145 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2146 p->n_selectors + learner_id];
2147 struct learner_runtime *l = &t->learners[learner_id];
2148 struct learner_statistics *stats = &p->learner_stats[learner_id];
2149 uint64_t action_id, n_pkts_hit, n_pkts_action, time;
2150 uint8_t *action_data;
2154 time = rte_get_tsc_cycles();
2156 done = rte_swx_table_learner_lookup(ts->obj,
2165 TRACE("[Thread %2u] learner %u (not finalized)\n",
2173 action_id = hit ? action_id : ts->default_action_id;
2174 action_data = hit ? action_data : ts->default_action_data;
2175 n_pkts_hit = stats->n_pkts_hit[hit];
2176 n_pkts_action = stats->n_pkts_action[action_id];
2178 TRACE("[Thread %2u] learner %u (%s, action %u)\n",
2181 hit ? "hit" : "miss",
2182 (uint32_t)action_id);
2184 t->action_id = action_id;
2185 t->structs[0] = action_data;
2187 t->learner_id = learner_id;
2189 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2190 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2193 thread_ip_action_call(p, t, action_id);
2199 static struct action *
2200 action_find(struct rte_swx_pipeline *p, const char *name);
2203 action_has_nbo_args(struct action *a);
2206 instr_learn_translate(struct rte_swx_pipeline *p,
2207 struct action *action,
2210 struct instruction *instr,
2211 struct instruction_data *data __rte_unused)
2215 CHECK(action, EINVAL);
2216 CHECK(n_tokens == 2, EINVAL);
2218 a = action_find(p, tokens[1]);
2220 CHECK(!action_has_nbo_args(a), EINVAL);
2222 instr->type = INSTR_LEARNER_LEARN;
2223 instr->learn.action_id = a->id;
2229 instr_learn_exec(struct rte_swx_pipeline *p)
2231 struct thread *t = &p->threads[p->thread_id];
2232 struct instruction *ip = t->ip;
2234 __instr_learn_exec(p, t, ip);
2244 instr_forget_translate(struct rte_swx_pipeline *p __rte_unused,
2245 struct action *action,
2246 char **tokens __rte_unused,
2248 struct instruction *instr,
2249 struct instruction_data *data __rte_unused)
2251 CHECK(action, EINVAL);
2252 CHECK(n_tokens == 1, EINVAL);
2254 instr->type = INSTR_LEARNER_FORGET;
2260 instr_forget_exec(struct rte_swx_pipeline *p)
2262 struct thread *t = &p->threads[p->thread_id];
2263 struct instruction *ip = t->ip;
2265 __instr_forget_exec(p, t, ip);
2275 instr_extern_translate(struct rte_swx_pipeline *p,
2276 struct action *action __rte_unused,
2279 struct instruction *instr,
2280 struct instruction_data *data __rte_unused)
2282 char *token = tokens[1];
2284 CHECK(n_tokens == 2, EINVAL);
2286 if (token[0] == 'e') {
2287 struct extern_obj *obj;
2288 struct extern_type_member_func *func;
2290 func = extern_obj_member_func_parse(p, token, &obj);
2291 CHECK(func, EINVAL);
2293 instr->type = INSTR_EXTERN_OBJ;
2294 instr->ext_obj.ext_obj_id = obj->id;
2295 instr->ext_obj.func_id = func->id;
2300 if (token[0] == 'f') {
2301 struct extern_func *func;
2303 func = extern_func_parse(p, token);
2304 CHECK(func, EINVAL);
2306 instr->type = INSTR_EXTERN_FUNC;
2307 instr->ext_func.ext_func_id = func->id;
2316 instr_extern_obj_exec(struct rte_swx_pipeline *p)
2318 struct thread *t = &p->threads[p->thread_id];
2319 struct instruction *ip = t->ip;
2322 /* Extern object member function execute. */
2323 done = __instr_extern_obj_exec(p, t, ip);
2326 thread_ip_inc_cond(t, done);
2327 thread_yield_cond(p, done ^ 1);
2331 instr_extern_func_exec(struct rte_swx_pipeline *p)
2333 struct thread *t = &p->threads[p->thread_id];
2334 struct instruction *ip = t->ip;
2337 /* Extern function execute. */
2338 done = __instr_extern_func_exec(p, t, ip);
2341 thread_ip_inc_cond(t, done);
2342 thread_yield_cond(p, done ^ 1);
2349 instr_mov_translate(struct rte_swx_pipeline *p,
2350 struct action *action,
2353 struct instruction *instr,
2354 struct instruction_data *data __rte_unused)
2356 char *dst = tokens[1], *src = tokens[2];
2357 struct field *fdst, *fsrc;
2359 uint32_t dst_struct_id = 0, src_struct_id = 0;
2361 CHECK(n_tokens == 3, EINVAL);
2363 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2364 CHECK(fdst, EINVAL);
2365 CHECK(!fdst->var_size, EINVAL);
2367 /* MOV, MOV_MH, MOV_HM or MOV_HH. */
2368 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2370 CHECK(!fsrc->var_size, EINVAL);
2372 instr->type = INSTR_MOV;
2373 if (dst[0] != 'h' && src[0] == 'h')
2374 instr->type = INSTR_MOV_MH;
2375 if (dst[0] == 'h' && src[0] != 'h')
2376 instr->type = INSTR_MOV_HM;
2377 if (dst[0] == 'h' && src[0] == 'h')
2378 instr->type = INSTR_MOV_HH;
2380 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
2381 instr->mov.dst.n_bits = fdst->n_bits;
2382 instr->mov.dst.offset = fdst->offset / 8;
2383 instr->mov.src.struct_id = (uint8_t)src_struct_id;
2384 instr->mov.src.n_bits = fsrc->n_bits;
2385 instr->mov.src.offset = fsrc->offset / 8;
2390 src_val = strtoull(src, &src, 0);
2391 CHECK(!src[0], EINVAL);
2394 src_val = hton64(src_val) >> (64 - fdst->n_bits);
2396 instr->type = INSTR_MOV_I;
2397 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
2398 instr->mov.dst.n_bits = fdst->n_bits;
2399 instr->mov.dst.offset = fdst->offset / 8;
2400 instr->mov.src_val = src_val;
2405 instr_mov_exec(struct rte_swx_pipeline *p)
2407 struct thread *t = &p->threads[p->thread_id];
2408 struct instruction *ip = t->ip;
2410 TRACE("[Thread %2u] mov\n",
2420 instr_mov_mh_exec(struct rte_swx_pipeline *p)
2422 struct thread *t = &p->threads[p->thread_id];
2423 struct instruction *ip = t->ip;
2425 TRACE("[Thread %2u] mov (mh)\n",
2435 instr_mov_hm_exec(struct rte_swx_pipeline *p)
2437 struct thread *t = &p->threads[p->thread_id];
2438 struct instruction *ip = t->ip;
2440 TRACE("[Thread %2u] mov (hm)\n",
2450 instr_mov_hh_exec(struct rte_swx_pipeline *p)
2452 struct thread *t = &p->threads[p->thread_id];
2453 struct instruction *ip = t->ip;
2455 TRACE("[Thread %2u] mov (hh)\n",
2465 instr_mov_i_exec(struct rte_swx_pipeline *p)
2467 struct thread *t = &p->threads[p->thread_id];
2468 struct instruction *ip = t->ip;
2470 TRACE("[Thread %2u] mov m.f %" PRIx64 "\n",
2484 __instr_dma_ht_exec(struct rte_swx_pipeline *p, uint32_t n_dma);
2487 __instr_dma_ht_exec(struct rte_swx_pipeline *p, uint32_t n_dma)
2489 struct thread *t = &p->threads[p->thread_id];
2490 struct instruction *ip = t->ip;
2491 uint8_t *action_data = t->structs[0];
2492 uint64_t valid_headers = t->valid_headers;
2495 for (i = 0; i < n_dma; i++) {
2496 uint32_t header_id = ip->dma.dst.header_id[i];
2497 uint32_t struct_id = ip->dma.dst.struct_id[i];
2498 uint32_t offset = ip->dma.src.offset[i];
2499 uint32_t n_bytes = ip->dma.n_bytes[i];
2501 struct header_runtime *h = &t->headers[header_id];
2502 uint8_t *h_ptr0 = h->ptr0;
2503 uint8_t *h_ptr = t->structs[struct_id];
2505 void *dst = MASK64_BIT_GET(valid_headers, header_id) ?
2507 void *src = &action_data[offset];
2509 TRACE("[Thread %2u] dma h.s t.f\n", p->thread_id);
2512 memcpy(dst, src, n_bytes);
2513 t->structs[struct_id] = dst;
2514 valid_headers = MASK64_BIT_SET(valid_headers, header_id);
2517 t->valid_headers = valid_headers;
2521 instr_dma_ht_exec(struct rte_swx_pipeline *p)
2523 __instr_dma_ht_exec(p, 1);
2530 instr_dma_ht2_exec(struct rte_swx_pipeline *p)
2532 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n",
2535 __instr_dma_ht_exec(p, 2);
2542 instr_dma_ht3_exec(struct rte_swx_pipeline *p)
2544 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n",
2547 __instr_dma_ht_exec(p, 3);
2554 instr_dma_ht4_exec(struct rte_swx_pipeline *p)
2556 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n",
2559 __instr_dma_ht_exec(p, 4);
2566 instr_dma_ht5_exec(struct rte_swx_pipeline *p)
2568 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n",
2571 __instr_dma_ht_exec(p, 5);
2578 instr_dma_ht6_exec(struct rte_swx_pipeline *p)
2580 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n",
2583 __instr_dma_ht_exec(p, 6);
2590 instr_dma_ht7_exec(struct rte_swx_pipeline *p)
2592 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n",
2595 __instr_dma_ht_exec(p, 7);
2602 instr_dma_ht8_exec(struct rte_swx_pipeline *p)
2604 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n",
2607 __instr_dma_ht_exec(p, 8);
2617 instr_alu_add_translate(struct rte_swx_pipeline *p,
2618 struct action *action,
2621 struct instruction *instr,
2622 struct instruction_data *data __rte_unused)
2624 char *dst = tokens[1], *src = tokens[2];
2625 struct field *fdst, *fsrc;
2627 uint32_t dst_struct_id = 0, src_struct_id = 0;
2629 CHECK(n_tokens == 3, EINVAL);
2631 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2632 CHECK(fdst, EINVAL);
2633 CHECK(!fdst->var_size, EINVAL);
2635 /* ADD, ADD_HM, ADD_MH, ADD_HH. */
2636 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2638 CHECK(!fsrc->var_size, EINVAL);
2640 instr->type = INSTR_ALU_ADD;
2641 if (dst[0] == 'h' && src[0] != 'h')
2642 instr->type = INSTR_ALU_ADD_HM;
2643 if (dst[0] != 'h' && src[0] == 'h')
2644 instr->type = INSTR_ALU_ADD_MH;
2645 if (dst[0] == 'h' && src[0] == 'h')
2646 instr->type = INSTR_ALU_ADD_HH;
2648 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2649 instr->alu.dst.n_bits = fdst->n_bits;
2650 instr->alu.dst.offset = fdst->offset / 8;
2651 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2652 instr->alu.src.n_bits = fsrc->n_bits;
2653 instr->alu.src.offset = fsrc->offset / 8;
2657 /* ADD_MI, ADD_HI. */
2658 src_val = strtoull(src, &src, 0);
2659 CHECK(!src[0], EINVAL);
2661 instr->type = INSTR_ALU_ADD_MI;
2663 instr->type = INSTR_ALU_ADD_HI;
2665 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2666 instr->alu.dst.n_bits = fdst->n_bits;
2667 instr->alu.dst.offset = fdst->offset / 8;
2668 instr->alu.src_val = src_val;
2673 instr_alu_sub_translate(struct rte_swx_pipeline *p,
2674 struct action *action,
2677 struct instruction *instr,
2678 struct instruction_data *data __rte_unused)
2680 char *dst = tokens[1], *src = tokens[2];
2681 struct field *fdst, *fsrc;
2683 uint32_t dst_struct_id = 0, src_struct_id = 0;
2685 CHECK(n_tokens == 3, EINVAL);
2687 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2688 CHECK(fdst, EINVAL);
2689 CHECK(!fdst->var_size, EINVAL);
2691 /* SUB, SUB_HM, SUB_MH, SUB_HH. */
2692 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2694 CHECK(!fsrc->var_size, EINVAL);
2696 instr->type = INSTR_ALU_SUB;
2697 if (dst[0] == 'h' && src[0] != 'h')
2698 instr->type = INSTR_ALU_SUB_HM;
2699 if (dst[0] != 'h' && src[0] == 'h')
2700 instr->type = INSTR_ALU_SUB_MH;
2701 if (dst[0] == 'h' && src[0] == 'h')
2702 instr->type = INSTR_ALU_SUB_HH;
2704 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2705 instr->alu.dst.n_bits = fdst->n_bits;
2706 instr->alu.dst.offset = fdst->offset / 8;
2707 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2708 instr->alu.src.n_bits = fsrc->n_bits;
2709 instr->alu.src.offset = fsrc->offset / 8;
2713 /* SUB_MI, SUB_HI. */
2714 src_val = strtoull(src, &src, 0);
2715 CHECK(!src[0], EINVAL);
2717 instr->type = INSTR_ALU_SUB_MI;
2719 instr->type = INSTR_ALU_SUB_HI;
2721 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2722 instr->alu.dst.n_bits = fdst->n_bits;
2723 instr->alu.dst.offset = fdst->offset / 8;
2724 instr->alu.src_val = src_val;
2729 instr_alu_ckadd_translate(struct rte_swx_pipeline *p,
2730 struct action *action __rte_unused,
2733 struct instruction *instr,
2734 struct instruction_data *data __rte_unused)
2736 char *dst = tokens[1], *src = tokens[2];
2737 struct header *hdst, *hsrc;
2738 struct field *fdst, *fsrc;
2740 CHECK(n_tokens == 3, EINVAL);
2742 fdst = header_field_parse(p, dst, &hdst);
2743 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
2744 CHECK(!fdst->var_size, EINVAL);
2747 fsrc = header_field_parse(p, src, &hsrc);
2749 CHECK(!fsrc->var_size, EINVAL);
2751 instr->type = INSTR_ALU_CKADD_FIELD;
2752 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2753 instr->alu.dst.n_bits = fdst->n_bits;
2754 instr->alu.dst.offset = fdst->offset / 8;
2755 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2756 instr->alu.src.n_bits = fsrc->n_bits;
2757 instr->alu.src.offset = fsrc->offset / 8;
2761 /* CKADD_STRUCT, CKADD_STRUCT20. */
2762 hsrc = header_parse(p, src);
2763 CHECK(hsrc, EINVAL);
2764 CHECK(!hsrc->st->var_size, EINVAL);
2766 instr->type = INSTR_ALU_CKADD_STRUCT;
2767 if ((hsrc->st->n_bits / 8) == 20)
2768 instr->type = INSTR_ALU_CKADD_STRUCT20;
2770 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2771 instr->alu.dst.n_bits = fdst->n_bits;
2772 instr->alu.dst.offset = fdst->offset / 8;
2773 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2774 instr->alu.src.n_bits = hsrc->st->n_bits;
2775 instr->alu.src.offset = 0; /* Unused. */
2780 instr_alu_cksub_translate(struct rte_swx_pipeline *p,
2781 struct action *action __rte_unused,
2784 struct instruction *instr,
2785 struct instruction_data *data __rte_unused)
2787 char *dst = tokens[1], *src = tokens[2];
2788 struct header *hdst, *hsrc;
2789 struct field *fdst, *fsrc;
2791 CHECK(n_tokens == 3, EINVAL);
2793 fdst = header_field_parse(p, dst, &hdst);
2794 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
2795 CHECK(!fdst->var_size, EINVAL);
2797 fsrc = header_field_parse(p, src, &hsrc);
2798 CHECK(fsrc, EINVAL);
2799 CHECK(!fsrc->var_size, EINVAL);
2801 instr->type = INSTR_ALU_CKSUB_FIELD;
2802 instr->alu.dst.struct_id = (uint8_t)hdst->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)hsrc->struct_id;
2806 instr->alu.src.n_bits = fsrc->n_bits;
2807 instr->alu.src.offset = fsrc->offset / 8;
2812 instr_alu_shl_translate(struct rte_swx_pipeline *p,
2813 struct action *action,
2816 struct instruction *instr,
2817 struct instruction_data *data __rte_unused)
2819 char *dst = tokens[1], *src = tokens[2];
2820 struct field *fdst, *fsrc;
2822 uint32_t dst_struct_id = 0, src_struct_id = 0;
2824 CHECK(n_tokens == 3, EINVAL);
2826 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2827 CHECK(fdst, EINVAL);
2828 CHECK(!fdst->var_size, EINVAL);
2830 /* SHL, SHL_HM, SHL_MH, SHL_HH. */
2831 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2833 CHECK(!fsrc->var_size, EINVAL);
2835 instr->type = INSTR_ALU_SHL;
2836 if (dst[0] == 'h' && src[0] != 'h')
2837 instr->type = INSTR_ALU_SHL_HM;
2838 if (dst[0] != 'h' && src[0] == 'h')
2839 instr->type = INSTR_ALU_SHL_MH;
2840 if (dst[0] == 'h' && src[0] == 'h')
2841 instr->type = INSTR_ALU_SHL_HH;
2843 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2844 instr->alu.dst.n_bits = fdst->n_bits;
2845 instr->alu.dst.offset = fdst->offset / 8;
2846 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2847 instr->alu.src.n_bits = fsrc->n_bits;
2848 instr->alu.src.offset = fsrc->offset / 8;
2852 /* SHL_MI, SHL_HI. */
2853 src_val = strtoull(src, &src, 0);
2854 CHECK(!src[0], EINVAL);
2856 instr->type = INSTR_ALU_SHL_MI;
2858 instr->type = INSTR_ALU_SHL_HI;
2860 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2861 instr->alu.dst.n_bits = fdst->n_bits;
2862 instr->alu.dst.offset = fdst->offset / 8;
2863 instr->alu.src_val = src_val;
2868 instr_alu_shr_translate(struct rte_swx_pipeline *p,
2869 struct action *action,
2872 struct instruction *instr,
2873 struct instruction_data *data __rte_unused)
2875 char *dst = tokens[1], *src = tokens[2];
2876 struct field *fdst, *fsrc;
2878 uint32_t dst_struct_id = 0, src_struct_id = 0;
2880 CHECK(n_tokens == 3, EINVAL);
2882 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2883 CHECK(fdst, EINVAL);
2884 CHECK(!fdst->var_size, EINVAL);
2886 /* SHR, SHR_HM, SHR_MH, SHR_HH. */
2887 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2889 CHECK(!fsrc->var_size, EINVAL);
2891 instr->type = INSTR_ALU_SHR;
2892 if (dst[0] == 'h' && src[0] != 'h')
2893 instr->type = INSTR_ALU_SHR_HM;
2894 if (dst[0] != 'h' && src[0] == 'h')
2895 instr->type = INSTR_ALU_SHR_MH;
2896 if (dst[0] == 'h' && src[0] == 'h')
2897 instr->type = INSTR_ALU_SHR_HH;
2899 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2900 instr->alu.dst.n_bits = fdst->n_bits;
2901 instr->alu.dst.offset = fdst->offset / 8;
2902 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2903 instr->alu.src.n_bits = fsrc->n_bits;
2904 instr->alu.src.offset = fsrc->offset / 8;
2908 /* SHR_MI, SHR_HI. */
2909 src_val = strtoull(src, &src, 0);
2910 CHECK(!src[0], EINVAL);
2912 instr->type = INSTR_ALU_SHR_MI;
2914 instr->type = INSTR_ALU_SHR_HI;
2916 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2917 instr->alu.dst.n_bits = fdst->n_bits;
2918 instr->alu.dst.offset = fdst->offset / 8;
2919 instr->alu.src_val = src_val;
2924 instr_alu_and_translate(struct rte_swx_pipeline *p,
2925 struct action *action,
2928 struct instruction *instr,
2929 struct instruction_data *data __rte_unused)
2931 char *dst = tokens[1], *src = tokens[2];
2932 struct field *fdst, *fsrc;
2934 uint32_t dst_struct_id = 0, src_struct_id = 0;
2936 CHECK(n_tokens == 3, EINVAL);
2938 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2939 CHECK(fdst, EINVAL);
2940 CHECK(!fdst->var_size, EINVAL);
2942 /* AND, AND_MH, AND_HM, AND_HH. */
2943 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2945 CHECK(!fsrc->var_size, EINVAL);
2947 instr->type = INSTR_ALU_AND;
2948 if (dst[0] != 'h' && src[0] == 'h')
2949 instr->type = INSTR_ALU_AND_MH;
2950 if (dst[0] == 'h' && src[0] != 'h')
2951 instr->type = INSTR_ALU_AND_HM;
2952 if (dst[0] == 'h' && src[0] == 'h')
2953 instr->type = INSTR_ALU_AND_HH;
2955 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2956 instr->alu.dst.n_bits = fdst->n_bits;
2957 instr->alu.dst.offset = fdst->offset / 8;
2958 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2959 instr->alu.src.n_bits = fsrc->n_bits;
2960 instr->alu.src.offset = fsrc->offset / 8;
2965 src_val = strtoull(src, &src, 0);
2966 CHECK(!src[0], EINVAL);
2969 src_val = hton64(src_val) >> (64 - fdst->n_bits);
2971 instr->type = INSTR_ALU_AND_I;
2972 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2973 instr->alu.dst.n_bits = fdst->n_bits;
2974 instr->alu.dst.offset = fdst->offset / 8;
2975 instr->alu.src_val = src_val;
2980 instr_alu_or_translate(struct rte_swx_pipeline *p,
2981 struct action *action,
2984 struct instruction *instr,
2985 struct instruction_data *data __rte_unused)
2987 char *dst = tokens[1], *src = tokens[2];
2988 struct field *fdst, *fsrc;
2990 uint32_t dst_struct_id = 0, src_struct_id = 0;
2992 CHECK(n_tokens == 3, EINVAL);
2994 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2995 CHECK(fdst, EINVAL);
2996 CHECK(!fdst->var_size, EINVAL);
2998 /* OR, OR_MH, OR_HM, OR_HH. */
2999 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3001 CHECK(!fsrc->var_size, EINVAL);
3003 instr->type = INSTR_ALU_OR;
3004 if (dst[0] != 'h' && src[0] == 'h')
3005 instr->type = INSTR_ALU_OR_MH;
3006 if (dst[0] == 'h' && src[0] != 'h')
3007 instr->type = INSTR_ALU_OR_HM;
3008 if (dst[0] == 'h' && src[0] == 'h')
3009 instr->type = INSTR_ALU_OR_HH;
3011 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3012 instr->alu.dst.n_bits = fdst->n_bits;
3013 instr->alu.dst.offset = fdst->offset / 8;
3014 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3015 instr->alu.src.n_bits = fsrc->n_bits;
3016 instr->alu.src.offset = fsrc->offset / 8;
3021 src_val = strtoull(src, &src, 0);
3022 CHECK(!src[0], EINVAL);
3025 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3027 instr->type = INSTR_ALU_OR_I;
3028 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3029 instr->alu.dst.n_bits = fdst->n_bits;
3030 instr->alu.dst.offset = fdst->offset / 8;
3031 instr->alu.src_val = src_val;
3036 instr_alu_xor_translate(struct rte_swx_pipeline *p,
3037 struct action *action,
3040 struct instruction *instr,
3041 struct instruction_data *data __rte_unused)
3043 char *dst = tokens[1], *src = tokens[2];
3044 struct field *fdst, *fsrc;
3046 uint32_t dst_struct_id = 0, src_struct_id = 0;
3048 CHECK(n_tokens == 3, EINVAL);
3050 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3051 CHECK(fdst, EINVAL);
3052 CHECK(!fdst->var_size, EINVAL);
3054 /* XOR, XOR_MH, XOR_HM, XOR_HH. */
3055 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3057 CHECK(!fsrc->var_size, EINVAL);
3059 instr->type = INSTR_ALU_XOR;
3060 if (dst[0] != 'h' && src[0] == 'h')
3061 instr->type = INSTR_ALU_XOR_MH;
3062 if (dst[0] == 'h' && src[0] != 'h')
3063 instr->type = INSTR_ALU_XOR_HM;
3064 if (dst[0] == 'h' && src[0] == 'h')
3065 instr->type = INSTR_ALU_XOR_HH;
3067 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3068 instr->alu.dst.n_bits = fdst->n_bits;
3069 instr->alu.dst.offset = fdst->offset / 8;
3070 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3071 instr->alu.src.n_bits = fsrc->n_bits;
3072 instr->alu.src.offset = fsrc->offset / 8;
3077 src_val = strtoull(src, &src, 0);
3078 CHECK(!src[0], EINVAL);
3081 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3083 instr->type = INSTR_ALU_XOR_I;
3084 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3085 instr->alu.dst.n_bits = fdst->n_bits;
3086 instr->alu.dst.offset = fdst->offset / 8;
3087 instr->alu.src_val = src_val;
3092 instr_alu_add_exec(struct rte_swx_pipeline *p)
3094 struct thread *t = &p->threads[p->thread_id];
3095 struct instruction *ip = t->ip;
3097 TRACE("[Thread %2u] add\n", p->thread_id);
3107 instr_alu_add_mh_exec(struct rte_swx_pipeline *p)
3109 struct thread *t = &p->threads[p->thread_id];
3110 struct instruction *ip = t->ip;
3112 TRACE("[Thread %2u] add (mh)\n", p->thread_id);
3122 instr_alu_add_hm_exec(struct rte_swx_pipeline *p)
3124 struct thread *t = &p->threads[p->thread_id];
3125 struct instruction *ip = t->ip;
3127 TRACE("[Thread %2u] add (hm)\n", p->thread_id);
3137 instr_alu_add_hh_exec(struct rte_swx_pipeline *p)
3139 struct thread *t = &p->threads[p->thread_id];
3140 struct instruction *ip = t->ip;
3142 TRACE("[Thread %2u] add (hh)\n", p->thread_id);
3152 instr_alu_add_mi_exec(struct rte_swx_pipeline *p)
3154 struct thread *t = &p->threads[p->thread_id];
3155 struct instruction *ip = t->ip;
3157 TRACE("[Thread %2u] add (mi)\n", p->thread_id);
3167 instr_alu_add_hi_exec(struct rte_swx_pipeline *p)
3169 struct thread *t = &p->threads[p->thread_id];
3170 struct instruction *ip = t->ip;
3172 TRACE("[Thread %2u] add (hi)\n", p->thread_id);
3182 instr_alu_sub_exec(struct rte_swx_pipeline *p)
3184 struct thread *t = &p->threads[p->thread_id];
3185 struct instruction *ip = t->ip;
3187 TRACE("[Thread %2u] sub\n", p->thread_id);
3197 instr_alu_sub_mh_exec(struct rte_swx_pipeline *p)
3199 struct thread *t = &p->threads[p->thread_id];
3200 struct instruction *ip = t->ip;
3202 TRACE("[Thread %2u] sub (mh)\n", p->thread_id);
3212 instr_alu_sub_hm_exec(struct rte_swx_pipeline *p)
3214 struct thread *t = &p->threads[p->thread_id];
3215 struct instruction *ip = t->ip;
3217 TRACE("[Thread %2u] sub (hm)\n", p->thread_id);
3227 instr_alu_sub_hh_exec(struct rte_swx_pipeline *p)
3229 struct thread *t = &p->threads[p->thread_id];
3230 struct instruction *ip = t->ip;
3232 TRACE("[Thread %2u] sub (hh)\n", p->thread_id);
3242 instr_alu_sub_mi_exec(struct rte_swx_pipeline *p)
3244 struct thread *t = &p->threads[p->thread_id];
3245 struct instruction *ip = t->ip;
3247 TRACE("[Thread %2u] sub (mi)\n", p->thread_id);
3257 instr_alu_sub_hi_exec(struct rte_swx_pipeline *p)
3259 struct thread *t = &p->threads[p->thread_id];
3260 struct instruction *ip = t->ip;
3262 TRACE("[Thread %2u] sub (hi)\n", p->thread_id);
3272 instr_alu_shl_exec(struct rte_swx_pipeline *p)
3274 struct thread *t = &p->threads[p->thread_id];
3275 struct instruction *ip = t->ip;
3277 TRACE("[Thread %2u] shl\n", p->thread_id);
3287 instr_alu_shl_mh_exec(struct rte_swx_pipeline *p)
3289 struct thread *t = &p->threads[p->thread_id];
3290 struct instruction *ip = t->ip;
3292 TRACE("[Thread %2u] shl (mh)\n", p->thread_id);
3302 instr_alu_shl_hm_exec(struct rte_swx_pipeline *p)
3304 struct thread *t = &p->threads[p->thread_id];
3305 struct instruction *ip = t->ip;
3307 TRACE("[Thread %2u] shl (hm)\n", p->thread_id);
3317 instr_alu_shl_hh_exec(struct rte_swx_pipeline *p)
3319 struct thread *t = &p->threads[p->thread_id];
3320 struct instruction *ip = t->ip;
3322 TRACE("[Thread %2u] shl (hh)\n", p->thread_id);
3332 instr_alu_shl_mi_exec(struct rte_swx_pipeline *p)
3334 struct thread *t = &p->threads[p->thread_id];
3335 struct instruction *ip = t->ip;
3337 TRACE("[Thread %2u] shl (mi)\n", p->thread_id);
3347 instr_alu_shl_hi_exec(struct rte_swx_pipeline *p)
3349 struct thread *t = &p->threads[p->thread_id];
3350 struct instruction *ip = t->ip;
3352 TRACE("[Thread %2u] shl (hi)\n", p->thread_id);
3362 instr_alu_shr_exec(struct rte_swx_pipeline *p)
3364 struct thread *t = &p->threads[p->thread_id];
3365 struct instruction *ip = t->ip;
3367 TRACE("[Thread %2u] shr\n", p->thread_id);
3377 instr_alu_shr_mh_exec(struct rte_swx_pipeline *p)
3379 struct thread *t = &p->threads[p->thread_id];
3380 struct instruction *ip = t->ip;
3382 TRACE("[Thread %2u] shr (mh)\n", p->thread_id);
3392 instr_alu_shr_hm_exec(struct rte_swx_pipeline *p)
3394 struct thread *t = &p->threads[p->thread_id];
3395 struct instruction *ip = t->ip;
3397 TRACE("[Thread %2u] shr (hm)\n", p->thread_id);
3407 instr_alu_shr_hh_exec(struct rte_swx_pipeline *p)
3409 struct thread *t = &p->threads[p->thread_id];
3410 struct instruction *ip = t->ip;
3412 TRACE("[Thread %2u] shr (hh)\n", p->thread_id);
3422 instr_alu_shr_mi_exec(struct rte_swx_pipeline *p)
3424 struct thread *t = &p->threads[p->thread_id];
3425 struct instruction *ip = t->ip;
3427 TRACE("[Thread %2u] shr (mi)\n", p->thread_id);
3437 instr_alu_shr_hi_exec(struct rte_swx_pipeline *p)
3439 struct thread *t = &p->threads[p->thread_id];
3440 struct instruction *ip = t->ip;
3442 TRACE("[Thread %2u] shr (hi)\n", p->thread_id);
3452 instr_alu_and_exec(struct rte_swx_pipeline *p)
3454 struct thread *t = &p->threads[p->thread_id];
3455 struct instruction *ip = t->ip;
3457 TRACE("[Thread %2u] and\n", p->thread_id);
3467 instr_alu_and_mh_exec(struct rte_swx_pipeline *p)
3469 struct thread *t = &p->threads[p->thread_id];
3470 struct instruction *ip = t->ip;
3472 TRACE("[Thread %2u] and (mh)\n", p->thread_id);
3482 instr_alu_and_hm_exec(struct rte_swx_pipeline *p)
3484 struct thread *t = &p->threads[p->thread_id];
3485 struct instruction *ip = t->ip;
3487 TRACE("[Thread %2u] and (hm)\n", p->thread_id);
3490 ALU_HM_FAST(t, ip, &);
3497 instr_alu_and_hh_exec(struct rte_swx_pipeline *p)
3499 struct thread *t = &p->threads[p->thread_id];
3500 struct instruction *ip = t->ip;
3502 TRACE("[Thread %2u] and (hh)\n", p->thread_id);
3505 ALU_HH_FAST(t, ip, &);
3512 instr_alu_and_i_exec(struct rte_swx_pipeline *p)
3514 struct thread *t = &p->threads[p->thread_id];
3515 struct instruction *ip = t->ip;
3517 TRACE("[Thread %2u] and (i)\n", p->thread_id);
3527 instr_alu_or_exec(struct rte_swx_pipeline *p)
3529 struct thread *t = &p->threads[p->thread_id];
3530 struct instruction *ip = t->ip;
3532 TRACE("[Thread %2u] or\n", p->thread_id);
3542 instr_alu_or_mh_exec(struct rte_swx_pipeline *p)
3544 struct thread *t = &p->threads[p->thread_id];
3545 struct instruction *ip = t->ip;
3547 TRACE("[Thread %2u] or (mh)\n", p->thread_id);
3557 instr_alu_or_hm_exec(struct rte_swx_pipeline *p)
3559 struct thread *t = &p->threads[p->thread_id];
3560 struct instruction *ip = t->ip;
3562 TRACE("[Thread %2u] or (hm)\n", p->thread_id);
3565 ALU_HM_FAST(t, ip, |);
3572 instr_alu_or_hh_exec(struct rte_swx_pipeline *p)
3574 struct thread *t = &p->threads[p->thread_id];
3575 struct instruction *ip = t->ip;
3577 TRACE("[Thread %2u] or (hh)\n", p->thread_id);
3580 ALU_HH_FAST(t, ip, |);
3587 instr_alu_or_i_exec(struct rte_swx_pipeline *p)
3589 struct thread *t = &p->threads[p->thread_id];
3590 struct instruction *ip = t->ip;
3592 TRACE("[Thread %2u] or (i)\n", p->thread_id);
3602 instr_alu_xor_exec(struct rte_swx_pipeline *p)
3604 struct thread *t = &p->threads[p->thread_id];
3605 struct instruction *ip = t->ip;
3607 TRACE("[Thread %2u] xor\n", p->thread_id);
3617 instr_alu_xor_mh_exec(struct rte_swx_pipeline *p)
3619 struct thread *t = &p->threads[p->thread_id];
3620 struct instruction *ip = t->ip;
3622 TRACE("[Thread %2u] xor (mh)\n", p->thread_id);
3632 instr_alu_xor_hm_exec(struct rte_swx_pipeline *p)
3634 struct thread *t = &p->threads[p->thread_id];
3635 struct instruction *ip = t->ip;
3637 TRACE("[Thread %2u] xor (hm)\n", p->thread_id);
3640 ALU_HM_FAST(t, ip, ^);
3647 instr_alu_xor_hh_exec(struct rte_swx_pipeline *p)
3649 struct thread *t = &p->threads[p->thread_id];
3650 struct instruction *ip = t->ip;
3652 TRACE("[Thread %2u] xor (hh)\n", p->thread_id);
3655 ALU_HH_FAST(t, ip, ^);
3662 instr_alu_xor_i_exec(struct rte_swx_pipeline *p)
3664 struct thread *t = &p->threads[p->thread_id];
3665 struct instruction *ip = t->ip;
3667 TRACE("[Thread %2u] xor (i)\n", p->thread_id);
3677 instr_alu_ckadd_field_exec(struct rte_swx_pipeline *p)
3679 struct thread *t = &p->threads[p->thread_id];
3680 struct instruction *ip = t->ip;
3681 uint8_t *dst_struct, *src_struct;
3682 uint16_t *dst16_ptr, dst;
3683 uint64_t *src64_ptr, src64, src64_mask, src;
3686 TRACE("[Thread %2u] ckadd (field)\n", p->thread_id);
3689 dst_struct = t->structs[ip->alu.dst.struct_id];
3690 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
3693 src_struct = t->structs[ip->alu.src.struct_id];
3694 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
3696 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
3697 src = src64 & src64_mask;
3702 /* The first input (r) is a 16-bit number. The second and the third
3703 * inputs are 32-bit numbers. In the worst case scenario, the sum of the
3704 * three numbers (output r) is a 34-bit number.
3706 r += (src >> 32) + (src & 0xFFFFFFFF);
3708 /* The first input is a 16-bit number. The second input is an 18-bit
3709 * number. In the worst case scenario, the sum of the two numbers is a
3712 r = (r & 0xFFFF) + (r >> 16);
3714 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
3715 * a 3-bit number (0 .. 7). Their sum is a 17-bit number (0 .. 0x10006).
3717 r = (r & 0xFFFF) + (r >> 16);
3719 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
3720 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
3721 * 0x10006), the output r is (0 .. 7). So no carry bit can be generated,
3722 * therefore the output r is always a 16-bit number.
3724 r = (r & 0xFFFF) + (r >> 16);
3729 *dst16_ptr = (uint16_t)r;
3736 instr_alu_cksub_field_exec(struct rte_swx_pipeline *p)
3738 struct thread *t = &p->threads[p->thread_id];
3739 struct instruction *ip = t->ip;
3740 uint8_t *dst_struct, *src_struct;
3741 uint16_t *dst16_ptr, dst;
3742 uint64_t *src64_ptr, src64, src64_mask, src;
3745 TRACE("[Thread %2u] cksub (field)\n", p->thread_id);
3748 dst_struct = t->structs[ip->alu.dst.struct_id];
3749 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
3752 src_struct = t->structs[ip->alu.src.struct_id];
3753 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
3755 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
3756 src = src64 & src64_mask;
3761 /* Subtraction in 1's complement arithmetic (i.e. a '- b) is the same as
3762 * the following sequence of operations in 2's complement arithmetic:
3763 * a '- b = (a - b) % 0xFFFF.
3765 * In order to prevent an underflow for the below subtraction, in which
3766 * a 33-bit number (the subtrahend) is taken out of a 16-bit number (the
3767 * minuend), we first add a multiple of the 0xFFFF modulus to the
3768 * minuend. The number we add to the minuend needs to be a 34-bit number
3769 * or higher, so for readability reasons we picked the 36-bit multiple.
3770 * We are effectively turning the 16-bit minuend into a 36-bit number:
3771 * (a - b) % 0xFFFF = (a + 0xFFFF00000 - b) % 0xFFFF.
3773 r += 0xFFFF00000ULL; /* The output r is a 36-bit number. */
3775 /* A 33-bit number is subtracted from a 36-bit number (the input r). The
3776 * result (the output r) is a 36-bit number.
3778 r -= (src >> 32) + (src & 0xFFFFFFFF);
3780 /* The first input is a 16-bit number. The second input is a 20-bit
3781 * number. Their sum is a 21-bit number.
3783 r = (r & 0xFFFF) + (r >> 16);
3785 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
3786 * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1001E).
3788 r = (r & 0xFFFF) + (r >> 16);
3790 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
3791 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
3792 * 0x1001E), the output r is (0 .. 31). So no carry bit can be
3793 * generated, therefore the output r is always a 16-bit number.
3795 r = (r & 0xFFFF) + (r >> 16);
3800 *dst16_ptr = (uint16_t)r;
3807 instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline *p)
3809 struct thread *t = &p->threads[p->thread_id];
3810 struct instruction *ip = t->ip;
3811 uint8_t *dst_struct, *src_struct;
3812 uint16_t *dst16_ptr;
3813 uint32_t *src32_ptr;
3816 TRACE("[Thread %2u] ckadd (struct of 20 bytes)\n", p->thread_id);
3819 dst_struct = t->structs[ip->alu.dst.struct_id];
3820 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
3822 src_struct = t->structs[ip->alu.src.struct_id];
3823 src32_ptr = (uint32_t *)&src_struct[0];
3825 r0 = src32_ptr[0]; /* r0 is a 32-bit number. */
3826 r1 = src32_ptr[1]; /* r1 is a 32-bit number. */
3827 r0 += src32_ptr[2]; /* The output r0 is a 33-bit number. */
3828 r1 += src32_ptr[3]; /* The output r1 is a 33-bit number. */
3829 r0 += r1 + src32_ptr[4]; /* The output r0 is a 35-bit number. */
3831 /* The first input is a 16-bit number. The second input is a 19-bit
3832 * number. Their sum is a 20-bit number.
3834 r0 = (r0 & 0xFFFF) + (r0 >> 16);
3836 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
3837 * a 4-bit number (0 .. 15). The sum is a 17-bit number (0 .. 0x1000E).
3839 r0 = (r0 & 0xFFFF) + (r0 >> 16);
3841 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
3842 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
3843 * 0x1000E), the output r is (0 .. 15). So no carry bit can be
3844 * generated, therefore the output r is always a 16-bit number.
3846 r0 = (r0 & 0xFFFF) + (r0 >> 16);
3849 r0 = r0 ? r0 : 0xFFFF;
3851 *dst16_ptr = (uint16_t)r0;
3858 instr_alu_ckadd_struct_exec(struct rte_swx_pipeline *p)
3860 struct thread *t = &p->threads[p->thread_id];
3861 struct instruction *ip = t->ip;
3862 uint8_t *dst_struct, *src_struct;
3863 uint16_t *dst16_ptr;
3864 uint32_t *src32_ptr;
3868 TRACE("[Thread %2u] ckadd (struct)\n", p->thread_id);
3871 dst_struct = t->structs[ip->alu.dst.struct_id];
3872 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
3874 src_struct = t->structs[ip->alu.src.struct_id];
3875 src32_ptr = (uint32_t *)&src_struct[0];
3877 /* The max number of 32-bit words in a 256-byte header is 8 = 2^3.
3878 * Therefore, in the worst case scenario, a 35-bit number is added to a
3879 * 16-bit number (the input r), so the output r is 36-bit number.
3881 for (i = 0; i < ip->alu.src.n_bits / 32; i++, src32_ptr++)
3884 /* The first input is a 16-bit number. The second input is a 20-bit
3885 * number. Their sum is a 21-bit number.
3887 r = (r & 0xFFFF) + (r >> 16);
3889 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
3890 * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1000E).
3892 r = (r & 0xFFFF) + (r >> 16);
3894 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
3895 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
3896 * 0x1001E), the output r is (0 .. 31). So no carry bit can be
3897 * generated, therefore the output r is always a 16-bit number.
3899 r = (r & 0xFFFF) + (r >> 16);
3904 *dst16_ptr = (uint16_t)r;
3913 static struct regarray *
3914 regarray_find(struct rte_swx_pipeline *p, const char *name);
3917 instr_regprefetch_translate(struct rte_swx_pipeline *p,
3918 struct action *action,
3921 struct instruction *instr,
3922 struct instruction_data *data __rte_unused)
3924 char *regarray = tokens[1], *idx = tokens[2];
3927 uint32_t idx_struct_id, idx_val;
3929 CHECK(n_tokens == 3, EINVAL);
3931 r = regarray_find(p, regarray);
3934 /* REGPREFETCH_RH, REGPREFETCH_RM. */
3935 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
3937 CHECK(!fidx->var_size, EINVAL);
3939 instr->type = INSTR_REGPREFETCH_RM;
3941 instr->type = INSTR_REGPREFETCH_RH;
3943 instr->regarray.regarray_id = r->id;
3944 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
3945 instr->regarray.idx.n_bits = fidx->n_bits;
3946 instr->regarray.idx.offset = fidx->offset / 8;
3947 instr->regarray.dstsrc_val = 0; /* Unused. */
3951 /* REGPREFETCH_RI. */
3952 idx_val = strtoul(idx, &idx, 0);
3953 CHECK(!idx[0], EINVAL);
3955 instr->type = INSTR_REGPREFETCH_RI;
3956 instr->regarray.regarray_id = r->id;
3957 instr->regarray.idx_val = idx_val;
3958 instr->regarray.dstsrc_val = 0; /* Unused. */
3963 instr_regrd_translate(struct rte_swx_pipeline *p,
3964 struct action *action,
3967 struct instruction *instr,
3968 struct instruction_data *data __rte_unused)
3970 char *dst = tokens[1], *regarray = tokens[2], *idx = tokens[3];
3972 struct field *fdst, *fidx;
3973 uint32_t dst_struct_id, idx_struct_id, idx_val;
3975 CHECK(n_tokens == 4, EINVAL);
3977 r = regarray_find(p, regarray);
3980 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3981 CHECK(fdst, EINVAL);
3982 CHECK(!fdst->var_size, EINVAL);
3984 /* REGRD_HRH, REGRD_HRM, REGRD_MRH, REGRD_MRM. */
3985 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
3987 CHECK(!fidx->var_size, EINVAL);
3989 instr->type = INSTR_REGRD_MRM;
3990 if (dst[0] == 'h' && idx[0] != 'h')
3991 instr->type = INSTR_REGRD_HRM;
3992 if (dst[0] != 'h' && idx[0] == 'h')
3993 instr->type = INSTR_REGRD_MRH;
3994 if (dst[0] == 'h' && idx[0] == 'h')
3995 instr->type = INSTR_REGRD_HRH;
3997 instr->regarray.regarray_id = r->id;
3998 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
3999 instr->regarray.idx.n_bits = fidx->n_bits;
4000 instr->regarray.idx.offset = fidx->offset / 8;
4001 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
4002 instr->regarray.dstsrc.n_bits = fdst->n_bits;
4003 instr->regarray.dstsrc.offset = fdst->offset / 8;
4007 /* REGRD_MRI, REGRD_HRI. */
4008 idx_val = strtoul(idx, &idx, 0);
4009 CHECK(!idx[0], EINVAL);
4011 instr->type = INSTR_REGRD_MRI;
4013 instr->type = INSTR_REGRD_HRI;
4015 instr->regarray.regarray_id = r->id;
4016 instr->regarray.idx_val = idx_val;
4017 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
4018 instr->regarray.dstsrc.n_bits = fdst->n_bits;
4019 instr->regarray.dstsrc.offset = fdst->offset / 8;
4024 instr_regwr_translate(struct rte_swx_pipeline *p,
4025 struct action *action,
4028 struct instruction *instr,
4029 struct instruction_data *data __rte_unused)
4031 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
4033 struct field *fidx, *fsrc;
4035 uint32_t idx_struct_id, idx_val, src_struct_id;
4037 CHECK(n_tokens == 4, EINVAL);
4039 r = regarray_find(p, regarray);
4042 /* REGWR_RHH, REGWR_RHM, REGWR_RMH, REGWR_RMM. */
4043 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4044 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4046 CHECK(!fidx->var_size, EINVAL);
4047 CHECK(!fsrc->var_size, EINVAL);
4049 instr->type = INSTR_REGWR_RMM;
4050 if (idx[0] == 'h' && src[0] != 'h')
4051 instr->type = INSTR_REGWR_RHM;
4052 if (idx[0] != 'h' && src[0] == 'h')
4053 instr->type = INSTR_REGWR_RMH;
4054 if (idx[0] == 'h' && src[0] == 'h')
4055 instr->type = INSTR_REGWR_RHH;
4057 instr->regarray.regarray_id = r->id;
4058 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4059 instr->regarray.idx.n_bits = fidx->n_bits;
4060 instr->regarray.idx.offset = fidx->offset / 8;
4061 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4062 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4063 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4067 /* REGWR_RHI, REGWR_RMI. */
4068 if (fidx && !fsrc) {
4069 CHECK(!fidx->var_size, EINVAL);
4071 src_val = strtoull(src, &src, 0);
4072 CHECK(!src[0], EINVAL);
4074 instr->type = INSTR_REGWR_RMI;
4076 instr->type = INSTR_REGWR_RHI;
4078 instr->regarray.regarray_id = r->id;
4079 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4080 instr->regarray.idx.n_bits = fidx->n_bits;
4081 instr->regarray.idx.offset = fidx->offset / 8;
4082 instr->regarray.dstsrc_val = src_val;
4086 /* REGWR_RIH, REGWR_RIM. */
4087 if (!fidx && fsrc) {
4088 idx_val = strtoul(idx, &idx, 0);
4089 CHECK(!idx[0], EINVAL);
4091 CHECK(!fsrc->var_size, EINVAL);
4093 instr->type = INSTR_REGWR_RIM;
4095 instr->type = INSTR_REGWR_RIH;
4097 instr->regarray.regarray_id = r->id;
4098 instr->regarray.idx_val = idx_val;
4099 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4100 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4101 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4106 src_val = strtoull(src, &src, 0);
4107 CHECK(!src[0], EINVAL);
4109 idx_val = strtoul(idx, &idx, 0);
4110 CHECK(!idx[0], EINVAL);
4112 instr->type = INSTR_REGWR_RII;
4113 instr->regarray.idx_val = idx_val;
4114 instr->regarray.dstsrc_val = src_val;
4120 instr_regadd_translate(struct rte_swx_pipeline *p,
4121 struct action *action,
4124 struct instruction *instr,
4125 struct instruction_data *data __rte_unused)
4127 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
4129 struct field *fidx, *fsrc;
4131 uint32_t idx_struct_id, idx_val, src_struct_id;
4133 CHECK(n_tokens == 4, EINVAL);
4135 r = regarray_find(p, regarray);
4138 /* REGADD_RHH, REGADD_RHM, REGADD_RMH, REGADD_RMM. */
4139 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4140 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4142 CHECK(!fidx->var_size, EINVAL);
4143 CHECK(!fsrc->var_size, EINVAL);
4145 instr->type = INSTR_REGADD_RMM;
4146 if (idx[0] == 'h' && src[0] != 'h')
4147 instr->type = INSTR_REGADD_RHM;
4148 if (idx[0] != 'h' && src[0] == 'h')
4149 instr->type = INSTR_REGADD_RMH;
4150 if (idx[0] == 'h' && src[0] == 'h')
4151 instr->type = INSTR_REGADD_RHH;
4153 instr->regarray.regarray_id = r->id;
4154 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4155 instr->regarray.idx.n_bits = fidx->n_bits;
4156 instr->regarray.idx.offset = fidx->offset / 8;
4157 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4158 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4159 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4163 /* REGADD_RHI, REGADD_RMI. */
4164 if (fidx && !fsrc) {
4165 CHECK(!fidx->var_size, EINVAL);
4167 src_val = strtoull(src, &src, 0);
4168 CHECK(!src[0], EINVAL);
4170 instr->type = INSTR_REGADD_RMI;
4172 instr->type = INSTR_REGADD_RHI;
4174 instr->regarray.regarray_id = r->id;
4175 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4176 instr->regarray.idx.n_bits = fidx->n_bits;
4177 instr->regarray.idx.offset = fidx->offset / 8;
4178 instr->regarray.dstsrc_val = src_val;
4182 /* REGADD_RIH, REGADD_RIM. */
4183 if (!fidx && fsrc) {
4184 idx_val = strtoul(idx, &idx, 0);
4185 CHECK(!idx[0], EINVAL);
4187 CHECK(!fsrc->var_size, EINVAL);
4189 instr->type = INSTR_REGADD_RIM;
4191 instr->type = INSTR_REGADD_RIH;
4193 instr->regarray.regarray_id = r->id;
4194 instr->regarray.idx_val = idx_val;
4195 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4196 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4197 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4202 src_val = strtoull(src, &src, 0);
4203 CHECK(!src[0], EINVAL);
4205 idx_val = strtoul(idx, &idx, 0);
4206 CHECK(!idx[0], EINVAL);
4208 instr->type = INSTR_REGADD_RII;
4209 instr->regarray.idx_val = idx_val;
4210 instr->regarray.dstsrc_val = src_val;
4214 static inline uint64_t *
4215 instr_regarray_regarray(struct rte_swx_pipeline *p, struct instruction *ip)
4217 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4221 static inline uint64_t
4222 instr_regarray_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
4224 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4226 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
4227 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
4228 uint64_t idx64 = *idx64_ptr;
4229 uint64_t idx64_mask = UINT64_MAX >> (64 - ip->regarray.idx.n_bits);
4230 uint64_t idx = idx64 & idx64_mask & r->size_mask;
4235 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4237 static inline uint64_t
4238 instr_regarray_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
4240 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4242 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
4243 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
4244 uint64_t idx64 = *idx64_ptr;
4245 uint64_t idx = (ntoh64(idx64) >> (64 - ip->regarray.idx.n_bits)) & r->size_mask;
4252 #define instr_regarray_idx_nbo instr_regarray_idx_hbo
4256 static inline uint64_t
4257 instr_regarray_idx_imm(struct rte_swx_pipeline *p, struct instruction *ip)
4259 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4261 uint64_t idx = ip->regarray.idx_val & r->size_mask;
4266 static inline uint64_t
4267 instr_regarray_src_hbo(struct thread *t, struct instruction *ip)
4269 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
4270 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
4271 uint64_t src64 = *src64_ptr;
4272 uint64_t src64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
4273 uint64_t src = src64 & src64_mask;
4278 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4280 static inline uint64_t
4281 instr_regarray_src_nbo(struct thread *t, struct instruction *ip)
4283 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
4284 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
4285 uint64_t src64 = *src64_ptr;
4286 uint64_t src = ntoh64(src64) >> (64 - ip->regarray.dstsrc.n_bits);
4293 #define instr_regarray_src_nbo instr_regarray_src_hbo
4298 instr_regarray_dst_hbo_src_hbo_set(struct thread *t, struct instruction *ip, uint64_t src)
4300 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
4301 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
4302 uint64_t dst64 = *dst64_ptr;
4303 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
4305 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
4309 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4312 instr_regarray_dst_nbo_src_hbo_set(struct thread *t, struct instruction *ip, uint64_t src)
4314 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
4315 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
4316 uint64_t dst64 = *dst64_ptr;
4317 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
4319 src = hton64(src) >> (64 - ip->regarray.dstsrc.n_bits);
4320 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
4325 #define instr_regarray_dst_nbo_src_hbo_set instr_regarray_dst_hbo_src_hbo_set
4330 instr_regprefetch_rh_exec(struct rte_swx_pipeline *p)
4332 struct thread *t = &p->threads[p->thread_id];
4333 struct instruction *ip = t->ip;
4334 uint64_t *regarray, idx;
4336 TRACE("[Thread %2u] regprefetch (r[h])\n", p->thread_id);
4339 regarray = instr_regarray_regarray(p, ip);
4340 idx = instr_regarray_idx_nbo(p, t, ip);
4341 rte_prefetch0(®array[idx]);
4348 instr_regprefetch_rm_exec(struct rte_swx_pipeline *p)
4350 struct thread *t = &p->threads[p->thread_id];
4351 struct instruction *ip = t->ip;
4352 uint64_t *regarray, idx;
4354 TRACE("[Thread %2u] regprefetch (r[m])\n", p->thread_id);
4357 regarray = instr_regarray_regarray(p, ip);
4358 idx = instr_regarray_idx_hbo(p, t, ip);
4359 rte_prefetch0(®array[idx]);
4366 instr_regprefetch_ri_exec(struct rte_swx_pipeline *p)
4368 struct thread *t = &p->threads[p->thread_id];
4369 struct instruction *ip = t->ip;
4370 uint64_t *regarray, idx;
4372 TRACE("[Thread %2u] regprefetch (r[i])\n", p->thread_id);
4375 regarray = instr_regarray_regarray(p, ip);
4376 idx = instr_regarray_idx_imm(p, ip);
4377 rte_prefetch0(®array[idx]);
4384 instr_regrd_hrh_exec(struct rte_swx_pipeline *p)
4386 struct thread *t = &p->threads[p->thread_id];
4387 struct instruction *ip = t->ip;
4388 uint64_t *regarray, idx;
4390 TRACE("[Thread %2u] regrd (h = r[h])\n", p->thread_id);
4393 regarray = instr_regarray_regarray(p, ip);
4394 idx = instr_regarray_idx_nbo(p, t, ip);
4395 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
4402 instr_regrd_hrm_exec(struct rte_swx_pipeline *p)
4404 struct thread *t = &p->threads[p->thread_id];
4405 struct instruction *ip = t->ip;
4406 uint64_t *regarray, idx;
4408 TRACE("[Thread %2u] regrd (h = r[m])\n", p->thread_id);
4411 regarray = instr_regarray_regarray(p, ip);
4412 idx = instr_regarray_idx_hbo(p, t, ip);
4413 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
4420 instr_regrd_mrh_exec(struct rte_swx_pipeline *p)
4422 struct thread *t = &p->threads[p->thread_id];
4423 struct instruction *ip = t->ip;
4424 uint64_t *regarray, idx;
4426 TRACE("[Thread %2u] regrd (m = r[h])\n", p->thread_id);
4429 regarray = instr_regarray_regarray(p, ip);
4430 idx = instr_regarray_idx_nbo(p, t, ip);
4431 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
4438 instr_regrd_mrm_exec(struct rte_swx_pipeline *p)
4440 struct thread *t = &p->threads[p->thread_id];
4441 struct instruction *ip = t->ip;
4442 uint64_t *regarray, idx;
4445 regarray = instr_regarray_regarray(p, ip);
4446 idx = instr_regarray_idx_hbo(p, t, ip);
4447 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
4454 instr_regrd_hri_exec(struct rte_swx_pipeline *p)
4456 struct thread *t = &p->threads[p->thread_id];
4457 struct instruction *ip = t->ip;
4458 uint64_t *regarray, idx;
4460 TRACE("[Thread %2u] regrd (h = r[i])\n", p->thread_id);
4463 regarray = instr_regarray_regarray(p, ip);
4464 idx = instr_regarray_idx_imm(p, ip);
4465 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
4472 instr_regrd_mri_exec(struct rte_swx_pipeline *p)
4474 struct thread *t = &p->threads[p->thread_id];
4475 struct instruction *ip = t->ip;
4476 uint64_t *regarray, idx;
4478 TRACE("[Thread %2u] regrd (m = r[i])\n", p->thread_id);
4481 regarray = instr_regarray_regarray(p, ip);
4482 idx = instr_regarray_idx_imm(p, ip);
4483 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
4490 instr_regwr_rhh_exec(struct rte_swx_pipeline *p)
4492 struct thread *t = &p->threads[p->thread_id];
4493 struct instruction *ip = t->ip;
4494 uint64_t *regarray, idx, src;
4496 TRACE("[Thread %2u] regwr (r[h] = h)\n", p->thread_id);
4499 regarray = instr_regarray_regarray(p, ip);
4500 idx = instr_regarray_idx_nbo(p, t, ip);
4501 src = instr_regarray_src_nbo(t, ip);
4502 regarray[idx] = src;
4509 instr_regwr_rhm_exec(struct rte_swx_pipeline *p)
4511 struct thread *t = &p->threads[p->thread_id];
4512 struct instruction *ip = t->ip;
4513 uint64_t *regarray, idx, src;
4515 TRACE("[Thread %2u] regwr (r[h] = m)\n", p->thread_id);
4518 regarray = instr_regarray_regarray(p, ip);
4519 idx = instr_regarray_idx_nbo(p, t, ip);
4520 src = instr_regarray_src_hbo(t, ip);
4521 regarray[idx] = src;
4528 instr_regwr_rmh_exec(struct rte_swx_pipeline *p)
4530 struct thread *t = &p->threads[p->thread_id];
4531 struct instruction *ip = t->ip;
4532 uint64_t *regarray, idx, src;
4534 TRACE("[Thread %2u] regwr (r[m] = h)\n", p->thread_id);
4537 regarray = instr_regarray_regarray(p, ip);
4538 idx = instr_regarray_idx_hbo(p, t, ip);
4539 src = instr_regarray_src_nbo(t, ip);
4540 regarray[idx] = src;
4547 instr_regwr_rmm_exec(struct rte_swx_pipeline *p)
4549 struct thread *t = &p->threads[p->thread_id];
4550 struct instruction *ip = t->ip;
4551 uint64_t *regarray, idx, src;
4553 TRACE("[Thread %2u] regwr (r[m] = m)\n", p->thread_id);
4556 regarray = instr_regarray_regarray(p, ip);
4557 idx = instr_regarray_idx_hbo(p, t, ip);
4558 src = instr_regarray_src_hbo(t, ip);
4559 regarray[idx] = src;
4566 instr_regwr_rhi_exec(struct rte_swx_pipeline *p)
4568 struct thread *t = &p->threads[p->thread_id];
4569 struct instruction *ip = t->ip;
4570 uint64_t *regarray, idx, src;
4572 TRACE("[Thread %2u] regwr (r[h] = i)\n", p->thread_id);
4575 regarray = instr_regarray_regarray(p, ip);
4576 idx = instr_regarray_idx_nbo(p, t, ip);
4577 src = ip->regarray.dstsrc_val;
4578 regarray[idx] = src;
4585 instr_regwr_rmi_exec(struct rte_swx_pipeline *p)
4587 struct thread *t = &p->threads[p->thread_id];
4588 struct instruction *ip = t->ip;
4589 uint64_t *regarray, idx, src;
4591 TRACE("[Thread %2u] regwr (r[m] = i)\n", p->thread_id);
4594 regarray = instr_regarray_regarray(p, ip);
4595 idx = instr_regarray_idx_hbo(p, t, ip);
4596 src = ip->regarray.dstsrc_val;
4597 regarray[idx] = src;
4604 instr_regwr_rih_exec(struct rte_swx_pipeline *p)
4606 struct thread *t = &p->threads[p->thread_id];
4607 struct instruction *ip = t->ip;
4608 uint64_t *regarray, idx, src;
4610 TRACE("[Thread %2u] regwr (r[i] = h)\n", p->thread_id);
4613 regarray = instr_regarray_regarray(p, ip);
4614 idx = instr_regarray_idx_imm(p, ip);
4615 src = instr_regarray_src_nbo(t, ip);
4616 regarray[idx] = src;
4623 instr_regwr_rim_exec(struct rte_swx_pipeline *p)
4625 struct thread *t = &p->threads[p->thread_id];
4626 struct instruction *ip = t->ip;
4627 uint64_t *regarray, idx, src;
4629 TRACE("[Thread %2u] regwr (r[i] = m)\n", p->thread_id);
4632 regarray = instr_regarray_regarray(p, ip);
4633 idx = instr_regarray_idx_imm(p, ip);
4634 src = instr_regarray_src_hbo(t, ip);
4635 regarray[idx] = src;
4642 instr_regwr_rii_exec(struct rte_swx_pipeline *p)
4644 struct thread *t = &p->threads[p->thread_id];
4645 struct instruction *ip = t->ip;
4646 uint64_t *regarray, idx, src;
4648 TRACE("[Thread %2u] regwr (r[i] = i)\n", p->thread_id);
4651 regarray = instr_regarray_regarray(p, ip);
4652 idx = instr_regarray_idx_imm(p, ip);
4653 src = ip->regarray.dstsrc_val;
4654 regarray[idx] = src;
4661 instr_regadd_rhh_exec(struct rte_swx_pipeline *p)
4663 struct thread *t = &p->threads[p->thread_id];
4664 struct instruction *ip = t->ip;
4665 uint64_t *regarray, idx, src;
4667 TRACE("[Thread %2u] regadd (r[h] += h)\n", p->thread_id);
4670 regarray = instr_regarray_regarray(p, ip);
4671 idx = instr_regarray_idx_nbo(p, t, ip);
4672 src = instr_regarray_src_nbo(t, ip);
4673 regarray[idx] += src;
4680 instr_regadd_rhm_exec(struct rte_swx_pipeline *p)
4682 struct thread *t = &p->threads[p->thread_id];
4683 struct instruction *ip = t->ip;
4684 uint64_t *regarray, idx, src;
4686 TRACE("[Thread %2u] regadd (r[h] += m)\n", p->thread_id);
4689 regarray = instr_regarray_regarray(p, ip);
4690 idx = instr_regarray_idx_nbo(p, t, ip);
4691 src = instr_regarray_src_hbo(t, ip);
4692 regarray[idx] += src;
4699 instr_regadd_rmh_exec(struct rte_swx_pipeline *p)
4701 struct thread *t = &p->threads[p->thread_id];
4702 struct instruction *ip = t->ip;
4703 uint64_t *regarray, idx, src;
4705 TRACE("[Thread %2u] regadd (r[m] += h)\n", p->thread_id);
4708 regarray = instr_regarray_regarray(p, ip);
4709 idx = instr_regarray_idx_hbo(p, t, ip);
4710 src = instr_regarray_src_nbo(t, ip);
4711 regarray[idx] += src;
4718 instr_regadd_rmm_exec(struct rte_swx_pipeline *p)
4720 struct thread *t = &p->threads[p->thread_id];
4721 struct instruction *ip = t->ip;
4722 uint64_t *regarray, idx, src;
4724 TRACE("[Thread %2u] regadd (r[m] += m)\n", p->thread_id);
4727 regarray = instr_regarray_regarray(p, ip);
4728 idx = instr_regarray_idx_hbo(p, t, ip);
4729 src = instr_regarray_src_hbo(t, ip);
4730 regarray[idx] += src;
4737 instr_regadd_rhi_exec(struct rte_swx_pipeline *p)
4739 struct thread *t = &p->threads[p->thread_id];
4740 struct instruction *ip = t->ip;
4741 uint64_t *regarray, idx, src;
4743 TRACE("[Thread %2u] regadd (r[h] += i)\n", p->thread_id);
4746 regarray = instr_regarray_regarray(p, ip);
4747 idx = instr_regarray_idx_nbo(p, t, ip);
4748 src = ip->regarray.dstsrc_val;
4749 regarray[idx] += src;
4756 instr_regadd_rmi_exec(struct rte_swx_pipeline *p)
4758 struct thread *t = &p->threads[p->thread_id];
4759 struct instruction *ip = t->ip;
4760 uint64_t *regarray, idx, src;
4762 TRACE("[Thread %2u] regadd (r[m] += i)\n", p->thread_id);
4765 regarray = instr_regarray_regarray(p, ip);
4766 idx = instr_regarray_idx_hbo(p, t, ip);
4767 src = ip->regarray.dstsrc_val;
4768 regarray[idx] += src;
4775 instr_regadd_rih_exec(struct rte_swx_pipeline *p)
4777 struct thread *t = &p->threads[p->thread_id];
4778 struct instruction *ip = t->ip;
4779 uint64_t *regarray, idx, src;
4781 TRACE("[Thread %2u] regadd (r[i] += h)\n", p->thread_id);
4784 regarray = instr_regarray_regarray(p, ip);
4785 idx = instr_regarray_idx_imm(p, ip);
4786 src = instr_regarray_src_nbo(t, ip);
4787 regarray[idx] += src;
4794 instr_regadd_rim_exec(struct rte_swx_pipeline *p)
4796 struct thread *t = &p->threads[p->thread_id];
4797 struct instruction *ip = t->ip;
4798 uint64_t *regarray, idx, src;
4800 TRACE("[Thread %2u] regadd (r[i] += m)\n", p->thread_id);
4803 regarray = instr_regarray_regarray(p, ip);
4804 idx = instr_regarray_idx_imm(p, ip);
4805 src = instr_regarray_src_hbo(t, ip);
4806 regarray[idx] += src;
4813 instr_regadd_rii_exec(struct rte_swx_pipeline *p)
4815 struct thread *t = &p->threads[p->thread_id];
4816 struct instruction *ip = t->ip;
4817 uint64_t *regarray, idx, src;
4819 TRACE("[Thread %2u] regadd (r[i] += i)\n", p->thread_id);
4822 regarray = instr_regarray_regarray(p, ip);
4823 idx = instr_regarray_idx_imm(p, ip);
4824 src = ip->regarray.dstsrc_val;
4825 regarray[idx] += src;
4834 static struct metarray *
4835 metarray_find(struct rte_swx_pipeline *p, const char *name);
4838 instr_metprefetch_translate(struct rte_swx_pipeline *p,
4839 struct action *action,
4842 struct instruction *instr,
4843 struct instruction_data *data __rte_unused)
4845 char *metarray = tokens[1], *idx = tokens[2];
4848 uint32_t idx_struct_id, idx_val;
4850 CHECK(n_tokens == 3, EINVAL);
4852 m = metarray_find(p, metarray);
4855 /* METPREFETCH_H, METPREFETCH_M. */
4856 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4858 CHECK(!fidx->var_size, EINVAL);
4860 instr->type = INSTR_METPREFETCH_M;
4862 instr->type = INSTR_METPREFETCH_H;
4864 instr->meter.metarray_id = m->id;
4865 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4866 instr->meter.idx.n_bits = fidx->n_bits;
4867 instr->meter.idx.offset = fidx->offset / 8;
4871 /* METPREFETCH_I. */
4872 idx_val = strtoul(idx, &idx, 0);
4873 CHECK(!idx[0], EINVAL);
4875 instr->type = INSTR_METPREFETCH_I;
4876 instr->meter.metarray_id = m->id;
4877 instr->meter.idx_val = idx_val;
4882 instr_meter_translate(struct rte_swx_pipeline *p,
4883 struct action *action,
4886 struct instruction *instr,
4887 struct instruction_data *data __rte_unused)
4889 char *metarray = tokens[1], *idx = tokens[2], *length = tokens[3];
4890 char *color_in = tokens[4], *color_out = tokens[5];
4892 struct field *fidx, *flength, *fcin, *fcout;
4893 uint32_t idx_struct_id, length_struct_id;
4894 uint32_t color_in_struct_id, color_out_struct_id;
4896 CHECK(n_tokens == 6, EINVAL);
4898 m = metarray_find(p, metarray);
4901 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4903 flength = struct_field_parse(p, action, length, &length_struct_id);
4904 CHECK(flength, EINVAL);
4905 CHECK(!flength->var_size, EINVAL);
4907 fcin = struct_field_parse(p, action, color_in, &color_in_struct_id);
4909 fcout = struct_field_parse(p, NULL, color_out, &color_out_struct_id);
4910 CHECK(fcout, EINVAL);
4911 CHECK(!fcout->var_size, EINVAL);
4913 /* index = HMEFT, length = HMEFT, color_in = MEFT, color_out = MEF. */
4915 CHECK(!fidx->var_size, EINVAL);
4916 CHECK(!fcin->var_size, EINVAL);
4918 instr->type = INSTR_METER_MMM;
4919 if (idx[0] == 'h' && length[0] == 'h')
4920 instr->type = INSTR_METER_HHM;
4921 if (idx[0] == 'h' && length[0] != 'h')
4922 instr->type = INSTR_METER_HMM;
4923 if (idx[0] != 'h' && length[0] == 'h')
4924 instr->type = INSTR_METER_MHM;
4926 instr->meter.metarray_id = m->id;
4928 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4929 instr->meter.idx.n_bits = fidx->n_bits;
4930 instr->meter.idx.offset = fidx->offset / 8;
4932 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4933 instr->meter.length.n_bits = flength->n_bits;
4934 instr->meter.length.offset = flength->offset / 8;
4936 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
4937 instr->meter.color_in.n_bits = fcin->n_bits;
4938 instr->meter.color_in.offset = fcin->offset / 8;
4940 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4941 instr->meter.color_out.n_bits = fcout->n_bits;
4942 instr->meter.color_out.offset = fcout->offset / 8;
4947 /* index = HMEFT, length = HMEFT, color_in = I, color_out = MEF. */
4948 if (fidx && !fcin) {
4949 uint32_t color_in_val;
4951 CHECK(!fidx->var_size, EINVAL);
4953 color_in_val = strtoul(color_in, &color_in, 0);
4954 CHECK(!color_in[0], EINVAL);
4956 instr->type = INSTR_METER_MMI;
4957 if (idx[0] == 'h' && length[0] == 'h')
4958 instr->type = INSTR_METER_HHI;
4959 if (idx[0] == 'h' && length[0] != 'h')
4960 instr->type = INSTR_METER_HMI;
4961 if (idx[0] != 'h' && length[0] == 'h')
4962 instr->type = INSTR_METER_MHI;
4964 instr->meter.metarray_id = m->id;
4966 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4967 instr->meter.idx.n_bits = fidx->n_bits;
4968 instr->meter.idx.offset = fidx->offset / 8;
4970 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4971 instr->meter.length.n_bits = flength->n_bits;
4972 instr->meter.length.offset = flength->offset / 8;
4974 instr->meter.color_in_val = color_in_val;
4976 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4977 instr->meter.color_out.n_bits = fcout->n_bits;
4978 instr->meter.color_out.offset = fcout->offset / 8;
4983 /* index = I, length = HMEFT, color_in = MEFT, color_out = MEF. */
4984 if (!fidx && fcin) {
4987 idx_val = strtoul(idx, &idx, 0);
4988 CHECK(!idx[0], EINVAL);
4990 CHECK(!fcin->var_size, EINVAL);
4992 instr->type = INSTR_METER_IMM;
4993 if (length[0] == 'h')
4994 instr->type = INSTR_METER_IHM;
4996 instr->meter.metarray_id = m->id;
4998 instr->meter.idx_val = idx_val;
5000 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5001 instr->meter.length.n_bits = flength->n_bits;
5002 instr->meter.length.offset = flength->offset / 8;
5004 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
5005 instr->meter.color_in.n_bits = fcin->n_bits;
5006 instr->meter.color_in.offset = fcin->offset / 8;
5008 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5009 instr->meter.color_out.n_bits = fcout->n_bits;
5010 instr->meter.color_out.offset = fcout->offset / 8;
5015 /* index = I, length = HMEFT, color_in = I, color_out = MEF. */
5016 if (!fidx && !fcin) {
5017 uint32_t idx_val, color_in_val;
5019 idx_val = strtoul(idx, &idx, 0);
5020 CHECK(!idx[0], EINVAL);
5022 color_in_val = strtoul(color_in, &color_in, 0);
5023 CHECK(!color_in[0], EINVAL);
5025 instr->type = INSTR_METER_IMI;
5026 if (length[0] == 'h')
5027 instr->type = INSTR_METER_IHI;
5029 instr->meter.metarray_id = m->id;
5031 instr->meter.idx_val = idx_val;
5033 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5034 instr->meter.length.n_bits = flength->n_bits;
5035 instr->meter.length.offset = flength->offset / 8;
5037 instr->meter.color_in_val = color_in_val;
5039 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5040 instr->meter.color_out.n_bits = fcout->n_bits;
5041 instr->meter.color_out.offset = fcout->offset / 8;
5049 static inline struct meter *
5050 instr_meter_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
5052 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
5054 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
5055 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
5056 uint64_t idx64 = *idx64_ptr;
5057 uint64_t idx64_mask = UINT64_MAX >> (64 - (ip)->meter.idx.n_bits);
5058 uint64_t idx = idx64 & idx64_mask & r->size_mask;
5060 return &r->metarray[idx];
5063 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5065 static inline struct meter *
5066 instr_meter_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
5068 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
5070 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
5071 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
5072 uint64_t idx64 = *idx64_ptr;
5073 uint64_t idx = (ntoh64(idx64) >> (64 - ip->meter.idx.n_bits)) & r->size_mask;
5075 return &r->metarray[idx];
5080 #define instr_meter_idx_nbo instr_meter_idx_hbo
5084 static inline struct meter *
5085 instr_meter_idx_imm(struct rte_swx_pipeline *p, struct instruction *ip)
5087 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
5089 uint64_t idx = ip->meter.idx_val & r->size_mask;
5091 return &r->metarray[idx];
5094 static inline uint32_t
5095 instr_meter_length_hbo(struct thread *t, struct instruction *ip)
5097 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
5098 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
5099 uint64_t src64 = *src64_ptr;
5100 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->meter.length.n_bits);
5101 uint64_t src = src64 & src64_mask;
5103 return (uint32_t)src;
5106 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5108 static inline uint32_t
5109 instr_meter_length_nbo(struct thread *t, struct instruction *ip)
5111 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
5112 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
5113 uint64_t src64 = *src64_ptr;
5114 uint64_t src = ntoh64(src64) >> (64 - ip->meter.length.n_bits);
5116 return (uint32_t)src;
5121 #define instr_meter_length_nbo instr_meter_length_hbo
5125 static inline enum rte_color
5126 instr_meter_color_in_hbo(struct thread *t, struct instruction *ip)
5128 uint8_t *src_struct = t->structs[ip->meter.color_in.struct_id];
5129 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.color_in.offset];
5130 uint64_t src64 = *src64_ptr;
5131 uint64_t src64_mask = UINT64_MAX >> (64 - ip->meter.color_in.n_bits);
5132 uint64_t src = src64 & src64_mask;
5134 return (enum rte_color)src;
5138 instr_meter_color_out_hbo_set(struct thread *t, struct instruction *ip, enum rte_color color_out)
5140 uint8_t *dst_struct = t->structs[ip->meter.color_out.struct_id];
5141 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->meter.color_out.offset];
5142 uint64_t dst64 = *dst64_ptr;
5143 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->meter.color_out.n_bits);
5145 uint64_t src = (uint64_t)color_out;
5147 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
5151 instr_metprefetch_h_exec(struct rte_swx_pipeline *p)
5153 struct thread *t = &p->threads[p->thread_id];
5154 struct instruction *ip = t->ip;
5157 TRACE("[Thread %2u] metprefetch (h)\n", p->thread_id);
5160 m = instr_meter_idx_nbo(p, t, ip);
5168 instr_metprefetch_m_exec(struct rte_swx_pipeline *p)
5170 struct thread *t = &p->threads[p->thread_id];
5171 struct instruction *ip = t->ip;
5174 TRACE("[Thread %2u] metprefetch (m)\n", p->thread_id);
5177 m = instr_meter_idx_hbo(p, t, ip);
5185 instr_metprefetch_i_exec(struct rte_swx_pipeline *p)
5187 struct thread *t = &p->threads[p->thread_id];
5188 struct instruction *ip = t->ip;
5191 TRACE("[Thread %2u] metprefetch (i)\n", p->thread_id);
5194 m = instr_meter_idx_imm(p, ip);
5202 instr_meter_hhm_exec(struct rte_swx_pipeline *p)
5204 struct thread *t = &p->threads[p->thread_id];
5205 struct instruction *ip = t->ip;
5207 uint64_t time, n_pkts, n_bytes;
5209 enum rte_color color_in, color_out;
5211 TRACE("[Thread %2u] meter (hhm)\n", p->thread_id);
5214 m = instr_meter_idx_nbo(p, t, ip);
5215 rte_prefetch0(m->n_pkts);
5216 time = rte_get_tsc_cycles();
5217 length = instr_meter_length_nbo(t, ip);
5218 color_in = instr_meter_color_in_hbo(t, ip);
5220 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5221 &m->profile->profile,
5226 color_out &= m->color_mask;
5228 n_pkts = m->n_pkts[color_out];
5229 n_bytes = m->n_bytes[color_out];
5231 instr_meter_color_out_hbo_set(t, ip, color_out);
5233 m->n_pkts[color_out] = n_pkts + 1;
5234 m->n_bytes[color_out] = n_bytes + length;
5241 instr_meter_hhi_exec(struct rte_swx_pipeline *p)
5243 struct thread *t = &p->threads[p->thread_id];
5244 struct instruction *ip = t->ip;
5246 uint64_t time, n_pkts, n_bytes;
5248 enum rte_color color_in, color_out;
5250 TRACE("[Thread %2u] meter (hhi)\n", p->thread_id);
5253 m = instr_meter_idx_nbo(p, t, ip);
5254 rte_prefetch0(m->n_pkts);
5255 time = rte_get_tsc_cycles();
5256 length = instr_meter_length_nbo(t, ip);
5257 color_in = (enum rte_color)ip->meter.color_in_val;
5259 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5260 &m->profile->profile,
5265 color_out &= m->color_mask;
5267 n_pkts = m->n_pkts[color_out];
5268 n_bytes = m->n_bytes[color_out];
5270 instr_meter_color_out_hbo_set(t, ip, color_out);
5272 m->n_pkts[color_out] = n_pkts + 1;
5273 m->n_bytes[color_out] = n_bytes + length;
5280 instr_meter_hmm_exec(struct rte_swx_pipeline *p)
5282 struct thread *t = &p->threads[p->thread_id];
5283 struct instruction *ip = t->ip;
5285 uint64_t time, n_pkts, n_bytes;
5287 enum rte_color color_in, color_out;
5289 TRACE("[Thread %2u] meter (hmm)\n", p->thread_id);
5292 m = instr_meter_idx_nbo(p, t, ip);
5293 rte_prefetch0(m->n_pkts);
5294 time = rte_get_tsc_cycles();
5295 length = instr_meter_length_hbo(t, ip);
5296 color_in = instr_meter_color_in_hbo(t, ip);
5298 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5299 &m->profile->profile,
5304 color_out &= m->color_mask;
5306 n_pkts = m->n_pkts[color_out];
5307 n_bytes = m->n_bytes[color_out];
5309 instr_meter_color_out_hbo_set(t, ip, color_out);
5311 m->n_pkts[color_out] = n_pkts + 1;
5312 m->n_bytes[color_out] = n_bytes + length;
5318 instr_meter_hmi_exec(struct rte_swx_pipeline *p)
5320 struct thread *t = &p->threads[p->thread_id];
5321 struct instruction *ip = t->ip;
5323 uint64_t time, n_pkts, n_bytes;
5325 enum rte_color color_in, color_out;
5327 TRACE("[Thread %2u] meter (hmi)\n", p->thread_id);
5330 m = instr_meter_idx_nbo(p, t, ip);
5331 rte_prefetch0(m->n_pkts);
5332 time = rte_get_tsc_cycles();
5333 length = instr_meter_length_hbo(t, ip);
5334 color_in = (enum rte_color)ip->meter.color_in_val;
5336 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5337 &m->profile->profile,
5342 color_out &= m->color_mask;
5344 n_pkts = m->n_pkts[color_out];
5345 n_bytes = m->n_bytes[color_out];
5347 instr_meter_color_out_hbo_set(t, ip, color_out);
5349 m->n_pkts[color_out] = n_pkts + 1;
5350 m->n_bytes[color_out] = n_bytes + length;
5357 instr_meter_mhm_exec(struct rte_swx_pipeline *p)
5359 struct thread *t = &p->threads[p->thread_id];
5360 struct instruction *ip = t->ip;
5362 uint64_t time, n_pkts, n_bytes;
5364 enum rte_color color_in, color_out;
5366 TRACE("[Thread %2u] meter (mhm)\n", p->thread_id);
5369 m = instr_meter_idx_hbo(p, t, ip);
5370 rte_prefetch0(m->n_pkts);
5371 time = rte_get_tsc_cycles();
5372 length = instr_meter_length_nbo(t, ip);
5373 color_in = instr_meter_color_in_hbo(t, ip);
5375 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5376 &m->profile->profile,
5381 color_out &= m->color_mask;
5383 n_pkts = m->n_pkts[color_out];
5384 n_bytes = m->n_bytes[color_out];
5386 instr_meter_color_out_hbo_set(t, ip, color_out);
5388 m->n_pkts[color_out] = n_pkts + 1;
5389 m->n_bytes[color_out] = n_bytes + length;
5396 instr_meter_mhi_exec(struct rte_swx_pipeline *p)
5398 struct thread *t = &p->threads[p->thread_id];
5399 struct instruction *ip = t->ip;
5401 uint64_t time, n_pkts, n_bytes;
5403 enum rte_color color_in, color_out;
5405 TRACE("[Thread %2u] meter (mhi)\n", p->thread_id);
5408 m = instr_meter_idx_hbo(p, t, ip);
5409 rte_prefetch0(m->n_pkts);
5410 time = rte_get_tsc_cycles();
5411 length = instr_meter_length_nbo(t, ip);
5412 color_in = (enum rte_color)ip->meter.color_in_val;
5414 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5415 &m->profile->profile,
5420 color_out &= m->color_mask;
5422 n_pkts = m->n_pkts[color_out];
5423 n_bytes = m->n_bytes[color_out];
5425 instr_meter_color_out_hbo_set(t, ip, color_out);
5427 m->n_pkts[color_out] = n_pkts + 1;
5428 m->n_bytes[color_out] = n_bytes + length;
5435 instr_meter_mmm_exec(struct rte_swx_pipeline *p)
5437 struct thread *t = &p->threads[p->thread_id];
5438 struct instruction *ip = t->ip;
5440 uint64_t time, n_pkts, n_bytes;
5442 enum rte_color color_in, color_out;
5444 TRACE("[Thread %2u] meter (mmm)\n", p->thread_id);
5447 m = instr_meter_idx_hbo(p, t, ip);
5448 rte_prefetch0(m->n_pkts);
5449 time = rte_get_tsc_cycles();
5450 length = instr_meter_length_hbo(t, ip);
5451 color_in = instr_meter_color_in_hbo(t, ip);
5453 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5454 &m->profile->profile,
5459 color_out &= m->color_mask;
5461 n_pkts = m->n_pkts[color_out];
5462 n_bytes = m->n_bytes[color_out];
5464 instr_meter_color_out_hbo_set(t, ip, color_out);
5466 m->n_pkts[color_out] = n_pkts + 1;
5467 m->n_bytes[color_out] = n_bytes + length;
5474 instr_meter_mmi_exec(struct rte_swx_pipeline *p)
5476 struct thread *t = &p->threads[p->thread_id];
5477 struct instruction *ip = t->ip;
5479 uint64_t time, n_pkts, n_bytes;
5481 enum rte_color color_in, color_out;
5483 TRACE("[Thread %2u] meter (mmi)\n", p->thread_id);
5486 m = instr_meter_idx_hbo(p, t, ip);
5487 rte_prefetch0(m->n_pkts);
5488 time = rte_get_tsc_cycles();
5489 length = instr_meter_length_hbo(t, ip);
5490 color_in = (enum rte_color)ip->meter.color_in_val;
5492 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5493 &m->profile->profile,
5498 color_out &= m->color_mask;
5500 n_pkts = m->n_pkts[color_out];
5501 n_bytes = m->n_bytes[color_out];
5503 instr_meter_color_out_hbo_set(t, ip, color_out);
5505 m->n_pkts[color_out] = n_pkts + 1;
5506 m->n_bytes[color_out] = n_bytes + length;
5513 instr_meter_ihm_exec(struct rte_swx_pipeline *p)
5515 struct thread *t = &p->threads[p->thread_id];
5516 struct instruction *ip = t->ip;
5518 uint64_t time, n_pkts, n_bytes;
5520 enum rte_color color_in, color_out;
5522 TRACE("[Thread %2u] meter (ihm)\n", p->thread_id);
5525 m = instr_meter_idx_imm(p, ip);
5526 rte_prefetch0(m->n_pkts);
5527 time = rte_get_tsc_cycles();
5528 length = instr_meter_length_nbo(t, ip);
5529 color_in = instr_meter_color_in_hbo(t, ip);
5531 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5532 &m->profile->profile,
5537 color_out &= m->color_mask;
5539 n_pkts = m->n_pkts[color_out];
5540 n_bytes = m->n_bytes[color_out];
5542 instr_meter_color_out_hbo_set(t, ip, color_out);
5544 m->n_pkts[color_out] = n_pkts + 1;
5545 m->n_bytes[color_out] = n_bytes + length;
5552 instr_meter_ihi_exec(struct rte_swx_pipeline *p)
5554 struct thread *t = &p->threads[p->thread_id];
5555 struct instruction *ip = t->ip;
5557 uint64_t time, n_pkts, n_bytes;
5559 enum rte_color color_in, color_out;
5561 TRACE("[Thread %2u] meter (ihi)\n", p->thread_id);
5564 m = instr_meter_idx_imm(p, ip);
5565 rte_prefetch0(m->n_pkts);
5566 time = rte_get_tsc_cycles();
5567 length = instr_meter_length_nbo(t, ip);
5568 color_in = (enum rte_color)ip->meter.color_in_val;
5570 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5571 &m->profile->profile,
5576 color_out &= m->color_mask;
5578 n_pkts = m->n_pkts[color_out];
5579 n_bytes = m->n_bytes[color_out];
5581 instr_meter_color_out_hbo_set(t, ip, color_out);
5583 m->n_pkts[color_out] = n_pkts + 1;
5584 m->n_bytes[color_out] = n_bytes + length;
5591 instr_meter_imm_exec(struct rte_swx_pipeline *p)
5593 struct thread *t = &p->threads[p->thread_id];
5594 struct instruction *ip = t->ip;
5596 uint64_t time, n_pkts, n_bytes;
5598 enum rte_color color_in, color_out;
5600 TRACE("[Thread %2u] meter (imm)\n", p->thread_id);
5603 m = instr_meter_idx_imm(p, ip);
5604 rte_prefetch0(m->n_pkts);
5605 time = rte_get_tsc_cycles();
5606 length = instr_meter_length_hbo(t, ip);
5607 color_in = instr_meter_color_in_hbo(t, ip);
5609 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5610 &m->profile->profile,
5615 color_out &= m->color_mask;
5617 n_pkts = m->n_pkts[color_out];
5618 n_bytes = m->n_bytes[color_out];
5620 instr_meter_color_out_hbo_set(t, ip, color_out);
5622 m->n_pkts[color_out] = n_pkts + 1;
5623 m->n_bytes[color_out] = n_bytes + length;
5629 instr_meter_imi_exec(struct rte_swx_pipeline *p)
5631 struct thread *t = &p->threads[p->thread_id];
5632 struct instruction *ip = t->ip;
5634 uint64_t time, n_pkts, n_bytes;
5636 enum rte_color color_in, color_out;
5638 TRACE("[Thread %2u] meter (imi)\n", p->thread_id);
5641 m = instr_meter_idx_imm(p, ip);
5642 rte_prefetch0(m->n_pkts);
5643 time = rte_get_tsc_cycles();
5644 length = instr_meter_length_hbo(t, ip);
5645 color_in = (enum rte_color)ip->meter.color_in_val;
5647 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5648 &m->profile->profile,
5653 color_out &= m->color_mask;
5655 n_pkts = m->n_pkts[color_out];
5656 n_bytes = m->n_bytes[color_out];
5658 instr_meter_color_out_hbo_set(t, ip, color_out);
5660 m->n_pkts[color_out] = n_pkts + 1;
5661 m->n_bytes[color_out] = n_bytes + length;
5671 instr_jmp_translate(struct rte_swx_pipeline *p __rte_unused,
5672 struct action *action __rte_unused,
5675 struct instruction *instr,
5676 struct instruction_data *data)
5678 CHECK(n_tokens == 2, EINVAL);
5680 strcpy(data->jmp_label, tokens[1]);
5682 instr->type = INSTR_JMP;
5683 instr->jmp.ip = NULL; /* Resolved later. */
5688 instr_jmp_valid_translate(struct rte_swx_pipeline *p,
5689 struct action *action __rte_unused,
5692 struct instruction *instr,
5693 struct instruction_data *data)
5697 CHECK(n_tokens == 3, EINVAL);
5699 strcpy(data->jmp_label, tokens[1]);
5701 h = header_parse(p, tokens[2]);
5704 instr->type = INSTR_JMP_VALID;
5705 instr->jmp.ip = NULL; /* Resolved later. */
5706 instr->jmp.header_id = h->id;
5711 instr_jmp_invalid_translate(struct rte_swx_pipeline *p,
5712 struct action *action __rte_unused,
5715 struct instruction *instr,
5716 struct instruction_data *data)
5720 CHECK(n_tokens == 3, EINVAL);
5722 strcpy(data->jmp_label, tokens[1]);
5724 h = header_parse(p, tokens[2]);
5727 instr->type = INSTR_JMP_INVALID;
5728 instr->jmp.ip = NULL; /* Resolved later. */
5729 instr->jmp.header_id = h->id;
5734 instr_jmp_hit_translate(struct rte_swx_pipeline *p __rte_unused,
5735 struct action *action,
5738 struct instruction *instr,
5739 struct instruction_data *data)
5741 CHECK(!action, EINVAL);
5742 CHECK(n_tokens == 2, EINVAL);
5744 strcpy(data->jmp_label, tokens[1]);
5746 instr->type = INSTR_JMP_HIT;
5747 instr->jmp.ip = NULL; /* Resolved later. */
5752 instr_jmp_miss_translate(struct rte_swx_pipeline *p __rte_unused,
5753 struct action *action,
5756 struct instruction *instr,
5757 struct instruction_data *data)
5759 CHECK(!action, EINVAL);
5760 CHECK(n_tokens == 2, EINVAL);
5762 strcpy(data->jmp_label, tokens[1]);
5764 instr->type = INSTR_JMP_MISS;
5765 instr->jmp.ip = NULL; /* Resolved later. */
5770 instr_jmp_action_hit_translate(struct rte_swx_pipeline *p,
5771 struct action *action,
5774 struct instruction *instr,
5775 struct instruction_data *data)
5779 CHECK(!action, EINVAL);
5780 CHECK(n_tokens == 3, EINVAL);
5782 strcpy(data->jmp_label, tokens[1]);
5784 a = action_find(p, tokens[2]);
5787 instr->type = INSTR_JMP_ACTION_HIT;
5788 instr->jmp.ip = NULL; /* Resolved later. */
5789 instr->jmp.action_id = a->id;
5794 instr_jmp_action_miss_translate(struct rte_swx_pipeline *p,
5795 struct action *action,
5798 struct instruction *instr,
5799 struct instruction_data *data)
5803 CHECK(!action, EINVAL);
5804 CHECK(n_tokens == 3, EINVAL);
5806 strcpy(data->jmp_label, tokens[1]);
5808 a = action_find(p, tokens[2]);
5811 instr->type = INSTR_JMP_ACTION_MISS;
5812 instr->jmp.ip = NULL; /* Resolved later. */
5813 instr->jmp.action_id = a->id;
5818 instr_jmp_eq_translate(struct rte_swx_pipeline *p,
5819 struct action *action,
5822 struct instruction *instr,
5823 struct instruction_data *data)
5825 char *a = tokens[2], *b = tokens[3];
5826 struct field *fa, *fb;
5828 uint32_t a_struct_id, b_struct_id;
5830 CHECK(n_tokens == 4, EINVAL);
5832 strcpy(data->jmp_label, tokens[1]);
5834 fa = struct_field_parse(p, action, a, &a_struct_id);
5836 CHECK(!fa->var_size, EINVAL);
5838 /* JMP_EQ, JMP_EQ_MH, JMP_EQ_HM, JMP_EQ_HH. */
5839 fb = struct_field_parse(p, action, b, &b_struct_id);
5841 CHECK(!fb->var_size, EINVAL);
5843 instr->type = INSTR_JMP_EQ;
5844 if (a[0] != 'h' && b[0] == 'h')
5845 instr->type = INSTR_JMP_EQ_MH;
5846 if (a[0] == 'h' && b[0] != 'h')
5847 instr->type = INSTR_JMP_EQ_HM;
5848 if (a[0] == 'h' && b[0] == 'h')
5849 instr->type = INSTR_JMP_EQ_HH;
5850 instr->jmp.ip = NULL; /* Resolved later. */
5852 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5853 instr->jmp.a.n_bits = fa->n_bits;
5854 instr->jmp.a.offset = fa->offset / 8;
5855 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5856 instr->jmp.b.n_bits = fb->n_bits;
5857 instr->jmp.b.offset = fb->offset / 8;
5862 b_val = strtoull(b, &b, 0);
5863 CHECK(!b[0], EINVAL);
5866 b_val = hton64(b_val) >> (64 - fa->n_bits);
5868 instr->type = INSTR_JMP_EQ_I;
5869 instr->jmp.ip = NULL; /* Resolved later. */
5870 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5871 instr->jmp.a.n_bits = fa->n_bits;
5872 instr->jmp.a.offset = fa->offset / 8;
5873 instr->jmp.b_val = b_val;
5878 instr_jmp_neq_translate(struct rte_swx_pipeline *p,
5879 struct action *action,
5882 struct instruction *instr,
5883 struct instruction_data *data)
5885 char *a = tokens[2], *b = tokens[3];
5886 struct field *fa, *fb;
5888 uint32_t a_struct_id, b_struct_id;
5890 CHECK(n_tokens == 4, EINVAL);
5892 strcpy(data->jmp_label, tokens[1]);
5894 fa = struct_field_parse(p, action, a, &a_struct_id);
5896 CHECK(!fa->var_size, EINVAL);
5898 /* JMP_NEQ, JMP_NEQ_MH, JMP_NEQ_HM, JMP_NEQ_HH. */
5899 fb = struct_field_parse(p, action, b, &b_struct_id);
5901 CHECK(!fb->var_size, EINVAL);
5903 instr->type = INSTR_JMP_NEQ;
5904 if (a[0] != 'h' && b[0] == 'h')
5905 instr->type = INSTR_JMP_NEQ_MH;
5906 if (a[0] == 'h' && b[0] != 'h')
5907 instr->type = INSTR_JMP_NEQ_HM;
5908 if (a[0] == 'h' && b[0] == 'h')
5909 instr->type = INSTR_JMP_NEQ_HH;
5910 instr->jmp.ip = NULL; /* Resolved later. */
5912 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5913 instr->jmp.a.n_bits = fa->n_bits;
5914 instr->jmp.a.offset = fa->offset / 8;
5915 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5916 instr->jmp.b.n_bits = fb->n_bits;
5917 instr->jmp.b.offset = fb->offset / 8;
5922 b_val = strtoull(b, &b, 0);
5923 CHECK(!b[0], EINVAL);
5926 b_val = hton64(b_val) >> (64 - fa->n_bits);
5928 instr->type = INSTR_JMP_NEQ_I;
5929 instr->jmp.ip = NULL; /* Resolved later. */
5930 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5931 instr->jmp.a.n_bits = fa->n_bits;
5932 instr->jmp.a.offset = fa->offset / 8;
5933 instr->jmp.b_val = b_val;
5938 instr_jmp_lt_translate(struct rte_swx_pipeline *p,
5939 struct action *action,
5942 struct instruction *instr,
5943 struct instruction_data *data)
5945 char *a = tokens[2], *b = tokens[3];
5946 struct field *fa, *fb;
5948 uint32_t a_struct_id, b_struct_id;
5950 CHECK(n_tokens == 4, EINVAL);
5952 strcpy(data->jmp_label, tokens[1]);
5954 fa = struct_field_parse(p, action, a, &a_struct_id);
5956 CHECK(!fa->var_size, EINVAL);
5958 /* JMP_LT, JMP_LT_MH, JMP_LT_HM, JMP_LT_HH. */
5959 fb = struct_field_parse(p, action, b, &b_struct_id);
5961 CHECK(!fb->var_size, EINVAL);
5963 instr->type = INSTR_JMP_LT;
5964 if (a[0] == 'h' && b[0] != 'h')
5965 instr->type = INSTR_JMP_LT_HM;
5966 if (a[0] != 'h' && b[0] == 'h')
5967 instr->type = INSTR_JMP_LT_MH;
5968 if (a[0] == 'h' && b[0] == 'h')
5969 instr->type = INSTR_JMP_LT_HH;
5970 instr->jmp.ip = NULL; /* Resolved later. */
5972 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5973 instr->jmp.a.n_bits = fa->n_bits;
5974 instr->jmp.a.offset = fa->offset / 8;
5975 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5976 instr->jmp.b.n_bits = fb->n_bits;
5977 instr->jmp.b.offset = fb->offset / 8;
5981 /* JMP_LT_MI, JMP_LT_HI. */
5982 b_val = strtoull(b, &b, 0);
5983 CHECK(!b[0], EINVAL);
5985 instr->type = INSTR_JMP_LT_MI;
5987 instr->type = INSTR_JMP_LT_HI;
5988 instr->jmp.ip = NULL; /* Resolved later. */
5990 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5991 instr->jmp.a.n_bits = fa->n_bits;
5992 instr->jmp.a.offset = fa->offset / 8;
5993 instr->jmp.b_val = b_val;
5998 instr_jmp_gt_translate(struct rte_swx_pipeline *p,
5999 struct action *action,
6002 struct instruction *instr,
6003 struct instruction_data *data)
6005 char *a = tokens[2], *b = tokens[3];
6006 struct field *fa, *fb;
6008 uint32_t a_struct_id, b_struct_id;
6010 CHECK(n_tokens == 4, EINVAL);
6012 strcpy(data->jmp_label, tokens[1]);
6014 fa = struct_field_parse(p, action, a, &a_struct_id);
6016 CHECK(!fa->var_size, EINVAL);
6018 /* JMP_GT, JMP_GT_MH, JMP_GT_HM, JMP_GT_HH. */
6019 fb = struct_field_parse(p, action, b, &b_struct_id);
6021 CHECK(!fb->var_size, EINVAL);
6023 instr->type = INSTR_JMP_GT;
6024 if (a[0] == 'h' && b[0] != 'h')
6025 instr->type = INSTR_JMP_GT_HM;
6026 if (a[0] != 'h' && b[0] == 'h')
6027 instr->type = INSTR_JMP_GT_MH;
6028 if (a[0] == 'h' && b[0] == 'h')
6029 instr->type = INSTR_JMP_GT_HH;
6030 instr->jmp.ip = NULL; /* Resolved later. */
6032 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6033 instr->jmp.a.n_bits = fa->n_bits;
6034 instr->jmp.a.offset = fa->offset / 8;
6035 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6036 instr->jmp.b.n_bits = fb->n_bits;
6037 instr->jmp.b.offset = fb->offset / 8;
6041 /* JMP_GT_MI, JMP_GT_HI. */
6042 b_val = strtoull(b, &b, 0);
6043 CHECK(!b[0], EINVAL);
6045 instr->type = INSTR_JMP_GT_MI;
6047 instr->type = INSTR_JMP_GT_HI;
6048 instr->jmp.ip = NULL; /* Resolved later. */
6050 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6051 instr->jmp.a.n_bits = fa->n_bits;
6052 instr->jmp.a.offset = fa->offset / 8;
6053 instr->jmp.b_val = b_val;
6058 instr_jmp_exec(struct rte_swx_pipeline *p)
6060 struct thread *t = &p->threads[p->thread_id];
6061 struct instruction *ip = t->ip;
6063 TRACE("[Thread %2u] jmp\n", p->thread_id);
6065 thread_ip_set(t, ip->jmp.ip);
6069 instr_jmp_valid_exec(struct rte_swx_pipeline *p)
6071 struct thread *t = &p->threads[p->thread_id];
6072 struct instruction *ip = t->ip;
6073 uint32_t header_id = ip->jmp.header_id;
6075 TRACE("[Thread %2u] jmpv\n", p->thread_id);
6077 t->ip = HEADER_VALID(t, header_id) ? ip->jmp.ip : (t->ip + 1);
6081 instr_jmp_invalid_exec(struct rte_swx_pipeline *p)
6083 struct thread *t = &p->threads[p->thread_id];
6084 struct instruction *ip = t->ip;
6085 uint32_t header_id = ip->jmp.header_id;
6087 TRACE("[Thread %2u] jmpnv\n", p->thread_id);
6089 t->ip = HEADER_VALID(t, header_id) ? (t->ip + 1) : ip->jmp.ip;
6093 instr_jmp_hit_exec(struct rte_swx_pipeline *p)
6095 struct thread *t = &p->threads[p->thread_id];
6096 struct instruction *ip = t->ip;
6097 struct instruction *ip_next[] = {t->ip + 1, ip->jmp.ip};
6099 TRACE("[Thread %2u] jmph\n", p->thread_id);
6101 t->ip = ip_next[t->hit];
6105 instr_jmp_miss_exec(struct rte_swx_pipeline *p)
6107 struct thread *t = &p->threads[p->thread_id];
6108 struct instruction *ip = t->ip;
6109 struct instruction *ip_next[] = {ip->jmp.ip, t->ip + 1};
6111 TRACE("[Thread %2u] jmpnh\n", p->thread_id);
6113 t->ip = ip_next[t->hit];
6117 instr_jmp_action_hit_exec(struct rte_swx_pipeline *p)
6119 struct thread *t = &p->threads[p->thread_id];
6120 struct instruction *ip = t->ip;
6122 TRACE("[Thread %2u] jmpa\n", p->thread_id);
6124 t->ip = (ip->jmp.action_id == t->action_id) ? ip->jmp.ip : (t->ip + 1);
6128 instr_jmp_action_miss_exec(struct rte_swx_pipeline *p)
6130 struct thread *t = &p->threads[p->thread_id];
6131 struct instruction *ip = t->ip;
6133 TRACE("[Thread %2u] jmpna\n", p->thread_id);
6135 t->ip = (ip->jmp.action_id == t->action_id) ? (t->ip + 1) : ip->jmp.ip;
6139 instr_jmp_eq_exec(struct rte_swx_pipeline *p)
6141 struct thread *t = &p->threads[p->thread_id];
6142 struct instruction *ip = t->ip;
6144 TRACE("[Thread %2u] jmpeq\n", p->thread_id);
6150 instr_jmp_eq_mh_exec(struct rte_swx_pipeline *p)
6152 struct thread *t = &p->threads[p->thread_id];
6153 struct instruction *ip = t->ip;
6155 TRACE("[Thread %2u] jmpeq (mh)\n", p->thread_id);
6157 JMP_CMP_MH(t, ip, ==);
6161 instr_jmp_eq_hm_exec(struct rte_swx_pipeline *p)
6163 struct thread *t = &p->threads[p->thread_id];
6164 struct instruction *ip = t->ip;
6166 TRACE("[Thread %2u] jmpeq (hm)\n", p->thread_id);
6168 JMP_CMP_HM(t, ip, ==);
6172 instr_jmp_eq_hh_exec(struct rte_swx_pipeline *p)
6174 struct thread *t = &p->threads[p->thread_id];
6175 struct instruction *ip = t->ip;
6177 TRACE("[Thread %2u] jmpeq (hh)\n", p->thread_id);
6179 JMP_CMP_HH_FAST(t, ip, ==);
6183 instr_jmp_eq_i_exec(struct rte_swx_pipeline *p)
6185 struct thread *t = &p->threads[p->thread_id];
6186 struct instruction *ip = t->ip;
6188 TRACE("[Thread %2u] jmpeq (i)\n", p->thread_id);
6190 JMP_CMP_I(t, ip, ==);
6194 instr_jmp_neq_exec(struct rte_swx_pipeline *p)
6196 struct thread *t = &p->threads[p->thread_id];
6197 struct instruction *ip = t->ip;
6199 TRACE("[Thread %2u] jmpneq\n", p->thread_id);
6205 instr_jmp_neq_mh_exec(struct rte_swx_pipeline *p)
6207 struct thread *t = &p->threads[p->thread_id];
6208 struct instruction *ip = t->ip;
6210 TRACE("[Thread %2u] jmpneq (mh)\n", p->thread_id);
6212 JMP_CMP_MH(t, ip, !=);
6216 instr_jmp_neq_hm_exec(struct rte_swx_pipeline *p)
6218 struct thread *t = &p->threads[p->thread_id];
6219 struct instruction *ip = t->ip;
6221 TRACE("[Thread %2u] jmpneq (hm)\n", p->thread_id);
6223 JMP_CMP_HM(t, ip, !=);
6227 instr_jmp_neq_hh_exec(struct rte_swx_pipeline *p)
6229 struct thread *t = &p->threads[p->thread_id];
6230 struct instruction *ip = t->ip;
6232 TRACE("[Thread %2u] jmpneq (hh)\n", p->thread_id);
6234 JMP_CMP_HH_FAST(t, ip, !=);
6238 instr_jmp_neq_i_exec(struct rte_swx_pipeline *p)
6240 struct thread *t = &p->threads[p->thread_id];
6241 struct instruction *ip = t->ip;
6243 TRACE("[Thread %2u] jmpneq (i)\n", p->thread_id);
6245 JMP_CMP_I(t, ip, !=);
6249 instr_jmp_lt_exec(struct rte_swx_pipeline *p)
6251 struct thread *t = &p->threads[p->thread_id];
6252 struct instruction *ip = t->ip;
6254 TRACE("[Thread %2u] jmplt\n", p->thread_id);
6260 instr_jmp_lt_mh_exec(struct rte_swx_pipeline *p)
6262 struct thread *t = &p->threads[p->thread_id];
6263 struct instruction *ip = t->ip;
6265 TRACE("[Thread %2u] jmplt (mh)\n", p->thread_id);
6267 JMP_CMP_MH(t, ip, <);
6271 instr_jmp_lt_hm_exec(struct rte_swx_pipeline *p)
6273 struct thread *t = &p->threads[p->thread_id];
6274 struct instruction *ip = t->ip;
6276 TRACE("[Thread %2u] jmplt (hm)\n", p->thread_id);
6278 JMP_CMP_HM(t, ip, <);
6282 instr_jmp_lt_hh_exec(struct rte_swx_pipeline *p)
6284 struct thread *t = &p->threads[p->thread_id];
6285 struct instruction *ip = t->ip;
6287 TRACE("[Thread %2u] jmplt (hh)\n", p->thread_id);
6289 JMP_CMP_HH(t, ip, <);
6293 instr_jmp_lt_mi_exec(struct rte_swx_pipeline *p)
6295 struct thread *t = &p->threads[p->thread_id];
6296 struct instruction *ip = t->ip;
6298 TRACE("[Thread %2u] jmplt (mi)\n", p->thread_id);
6300 JMP_CMP_MI(t, ip, <);
6304 instr_jmp_lt_hi_exec(struct rte_swx_pipeline *p)
6306 struct thread *t = &p->threads[p->thread_id];
6307 struct instruction *ip = t->ip;
6309 TRACE("[Thread %2u] jmplt (hi)\n", p->thread_id);
6311 JMP_CMP_HI(t, ip, <);
6315 instr_jmp_gt_exec(struct rte_swx_pipeline *p)
6317 struct thread *t = &p->threads[p->thread_id];
6318 struct instruction *ip = t->ip;
6320 TRACE("[Thread %2u] jmpgt\n", p->thread_id);
6326 instr_jmp_gt_mh_exec(struct rte_swx_pipeline *p)
6328 struct thread *t = &p->threads[p->thread_id];
6329 struct instruction *ip = t->ip;
6331 TRACE("[Thread %2u] jmpgt (mh)\n", p->thread_id);
6333 JMP_CMP_MH(t, ip, >);
6337 instr_jmp_gt_hm_exec(struct rte_swx_pipeline *p)
6339 struct thread *t = &p->threads[p->thread_id];
6340 struct instruction *ip = t->ip;
6342 TRACE("[Thread %2u] jmpgt (hm)\n", p->thread_id);
6344 JMP_CMP_HM(t, ip, >);
6348 instr_jmp_gt_hh_exec(struct rte_swx_pipeline *p)
6350 struct thread *t = &p->threads[p->thread_id];
6351 struct instruction *ip = t->ip;
6353 TRACE("[Thread %2u] jmpgt (hh)\n", p->thread_id);
6355 JMP_CMP_HH(t, ip, >);
6359 instr_jmp_gt_mi_exec(struct rte_swx_pipeline *p)
6361 struct thread *t = &p->threads[p->thread_id];
6362 struct instruction *ip = t->ip;
6364 TRACE("[Thread %2u] jmpgt (mi)\n", p->thread_id);
6366 JMP_CMP_MI(t, ip, >);
6370 instr_jmp_gt_hi_exec(struct rte_swx_pipeline *p)
6372 struct thread *t = &p->threads[p->thread_id];
6373 struct instruction *ip = t->ip;
6375 TRACE("[Thread %2u] jmpgt (hi)\n", p->thread_id);
6377 JMP_CMP_HI(t, ip, >);
6384 instr_return_translate(struct rte_swx_pipeline *p __rte_unused,
6385 struct action *action,
6386 char **tokens __rte_unused,
6388 struct instruction *instr,
6389 struct instruction_data *data __rte_unused)
6391 CHECK(action, EINVAL);
6392 CHECK(n_tokens == 1, EINVAL);
6394 instr->type = INSTR_RETURN;
6399 instr_return_exec(struct rte_swx_pipeline *p)
6401 struct thread *t = &p->threads[p->thread_id];
6403 TRACE("[Thread %2u] return\n", p->thread_id);
6409 instr_translate(struct rte_swx_pipeline *p,
6410 struct action *action,
6412 struct instruction *instr,
6413 struct instruction_data *data)
6415 char *tokens[RTE_SWX_INSTRUCTION_TOKENS_MAX];
6416 int n_tokens = 0, tpos = 0;
6418 /* Parse the instruction string into tokens. */
6422 token = strtok_r(string, " \t\v", &string);
6426 CHECK(n_tokens < RTE_SWX_INSTRUCTION_TOKENS_MAX, EINVAL);
6427 CHECK_NAME(token, EINVAL);
6429 tokens[n_tokens] = token;
6433 CHECK(n_tokens, EINVAL);
6435 /* Handle the optional instruction label. */
6436 if ((n_tokens >= 2) && !strcmp(tokens[1], ":")) {
6437 strcpy(data->label, tokens[0]);
6440 CHECK(n_tokens - tpos, EINVAL);
6443 /* Identify the instruction type. */
6444 if (!strcmp(tokens[tpos], "rx"))
6445 return instr_rx_translate(p,
6452 if (!strcmp(tokens[tpos], "tx"))
6453 return instr_tx_translate(p,
6460 if (!strcmp(tokens[tpos], "drop"))
6461 return instr_drop_translate(p,
6468 if (!strcmp(tokens[tpos], "extract"))
6469 return instr_hdr_extract_translate(p,
6476 if (!strcmp(tokens[tpos], "lookahead"))
6477 return instr_hdr_lookahead_translate(p,
6484 if (!strcmp(tokens[tpos], "emit"))
6485 return instr_hdr_emit_translate(p,
6492 if (!strcmp(tokens[tpos], "validate"))
6493 return instr_hdr_validate_translate(p,
6500 if (!strcmp(tokens[tpos], "invalidate"))
6501 return instr_hdr_invalidate_translate(p,
6508 if (!strcmp(tokens[tpos], "mov"))
6509 return instr_mov_translate(p,
6516 if (!strcmp(tokens[tpos], "add"))
6517 return instr_alu_add_translate(p,
6524 if (!strcmp(tokens[tpos], "sub"))
6525 return instr_alu_sub_translate(p,
6532 if (!strcmp(tokens[tpos], "ckadd"))
6533 return instr_alu_ckadd_translate(p,
6540 if (!strcmp(tokens[tpos], "cksub"))
6541 return instr_alu_cksub_translate(p,
6548 if (!strcmp(tokens[tpos], "and"))
6549 return instr_alu_and_translate(p,
6556 if (!strcmp(tokens[tpos], "or"))
6557 return instr_alu_or_translate(p,
6564 if (!strcmp(tokens[tpos], "xor"))
6565 return instr_alu_xor_translate(p,
6572 if (!strcmp(tokens[tpos], "shl"))
6573 return instr_alu_shl_translate(p,
6580 if (!strcmp(tokens[tpos], "shr"))
6581 return instr_alu_shr_translate(p,
6588 if (!strcmp(tokens[tpos], "regprefetch"))
6589 return instr_regprefetch_translate(p,
6596 if (!strcmp(tokens[tpos], "regrd"))
6597 return instr_regrd_translate(p,
6604 if (!strcmp(tokens[tpos], "regwr"))
6605 return instr_regwr_translate(p,
6612 if (!strcmp(tokens[tpos], "regadd"))
6613 return instr_regadd_translate(p,
6620 if (!strcmp(tokens[tpos], "metprefetch"))
6621 return instr_metprefetch_translate(p,
6628 if (!strcmp(tokens[tpos], "meter"))
6629 return instr_meter_translate(p,
6636 if (!strcmp(tokens[tpos], "table"))
6637 return instr_table_translate(p,
6644 if (!strcmp(tokens[tpos], "learn"))
6645 return instr_learn_translate(p,
6652 if (!strcmp(tokens[tpos], "forget"))
6653 return instr_forget_translate(p,
6660 if (!strcmp(tokens[tpos], "extern"))
6661 return instr_extern_translate(p,
6668 if (!strcmp(tokens[tpos], "jmp"))
6669 return instr_jmp_translate(p,
6676 if (!strcmp(tokens[tpos], "jmpv"))
6677 return instr_jmp_valid_translate(p,
6684 if (!strcmp(tokens[tpos], "jmpnv"))
6685 return instr_jmp_invalid_translate(p,
6692 if (!strcmp(tokens[tpos], "jmph"))
6693 return instr_jmp_hit_translate(p,
6700 if (!strcmp(tokens[tpos], "jmpnh"))
6701 return instr_jmp_miss_translate(p,
6708 if (!strcmp(tokens[tpos], "jmpa"))
6709 return instr_jmp_action_hit_translate(p,
6716 if (!strcmp(tokens[tpos], "jmpna"))
6717 return instr_jmp_action_miss_translate(p,
6724 if (!strcmp(tokens[tpos], "jmpeq"))
6725 return instr_jmp_eq_translate(p,
6732 if (!strcmp(tokens[tpos], "jmpneq"))
6733 return instr_jmp_neq_translate(p,
6740 if (!strcmp(tokens[tpos], "jmplt"))
6741 return instr_jmp_lt_translate(p,
6748 if (!strcmp(tokens[tpos], "jmpgt"))
6749 return instr_jmp_gt_translate(p,
6756 if (!strcmp(tokens[tpos], "return"))
6757 return instr_return_translate(p,
6767 static struct instruction_data *
6768 label_find(struct instruction_data *data, uint32_t n, const char *label)
6772 for (i = 0; i < n; i++)
6773 if (!strcmp(label, data[i].label))
6780 label_is_used(struct instruction_data *data, uint32_t n, const char *label)
6782 uint32_t count = 0, i;
6787 for (i = 0; i < n; i++)
6788 if (!strcmp(label, data[i].jmp_label))
6795 instr_label_check(struct instruction_data *instruction_data,
6796 uint32_t n_instructions)
6800 /* Check that all instruction labels are unique. */
6801 for (i = 0; i < n_instructions; i++) {
6802 struct instruction_data *data = &instruction_data[i];
6803 char *label = data->label;
6809 for (j = i + 1; j < n_instructions; j++)
6810 CHECK(strcmp(label, data[j].label), EINVAL);
6813 /* Get users for each instruction label. */
6814 for (i = 0; i < n_instructions; i++) {
6815 struct instruction_data *data = &instruction_data[i];
6816 char *label = data->label;
6818 data->n_users = label_is_used(instruction_data,
6827 instr_jmp_resolve(struct instruction *instructions,
6828 struct instruction_data *instruction_data,
6829 uint32_t n_instructions)
6833 for (i = 0; i < n_instructions; i++) {
6834 struct instruction *instr = &instructions[i];
6835 struct instruction_data *data = &instruction_data[i];
6836 struct instruction_data *found;
6838 if (!instruction_is_jmp(instr))
6841 found = label_find(instruction_data,
6844 CHECK(found, EINVAL);
6846 instr->jmp.ip = &instructions[found - instruction_data];
6853 instr_verify(struct rte_swx_pipeline *p __rte_unused,
6855 struct instruction *instr,
6856 struct instruction_data *data __rte_unused,
6857 uint32_t n_instructions)
6860 enum instruction_type type;
6863 /* Check that the first instruction is rx. */
6864 CHECK(instr[0].type == INSTR_RX, EINVAL);
6866 /* Check that there is at least one tx instruction. */
6867 for (i = 0; i < n_instructions; i++) {
6868 type = instr[i].type;
6870 if (instruction_is_tx(type))
6873 CHECK(i < n_instructions, EINVAL);
6875 /* Check that the last instruction is either tx or unconditional
6878 type = instr[n_instructions - 1].type;
6879 CHECK(instruction_is_tx(type) || (type == INSTR_JMP), EINVAL);
6883 enum instruction_type type;
6886 /* Check that there is at least one return or tx instruction. */
6887 for (i = 0; i < n_instructions; i++) {
6888 type = instr[i].type;
6890 if ((type == INSTR_RETURN) || instruction_is_tx(type))
6893 CHECK(i < n_instructions, EINVAL);
6900 instr_compact(struct instruction *instructions,
6901 struct instruction_data *instruction_data,
6902 uint32_t n_instructions)
6904 uint32_t i, pos = 0;
6906 /* Eliminate the invalid instructions that have been optimized out. */
6907 for (i = 0; i < n_instructions; i++) {
6908 struct instruction *instr = &instructions[i];
6909 struct instruction_data *data = &instruction_data[i];
6915 memcpy(&instructions[pos], instr, sizeof(*instr));
6916 memcpy(&instruction_data[pos], data, sizeof(*data));
6926 instr_pattern_extract_many_search(struct instruction *instr,
6927 struct instruction_data *data,
6929 uint32_t *n_pattern_instr)
6933 for (i = 0; i < n_instr; i++) {
6934 if (data[i].invalid)
6937 if (instr[i].type != INSTR_HDR_EXTRACT)
6940 if (i == RTE_DIM(instr->io.hdr.header_id))
6943 if (i && data[i].n_users)
6950 *n_pattern_instr = i;
6955 instr_pattern_extract_many_replace(struct instruction *instr,
6956 struct instruction_data *data,
6961 for (i = 1; i < n_instr; i++) {
6963 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
6964 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
6965 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
6967 data[i].invalid = 1;
6972 instr_pattern_extract_many_optimize(struct instruction *instructions,
6973 struct instruction_data *instruction_data,
6974 uint32_t n_instructions)
6978 for (i = 0; i < n_instructions; ) {
6979 struct instruction *instr = &instructions[i];
6980 struct instruction_data *data = &instruction_data[i];
6981 uint32_t n_instr = 0;
6985 detected = instr_pattern_extract_many_search(instr,
6990 instr_pattern_extract_many_replace(instr,
6997 /* No pattern starting at the current instruction. */
7001 /* Eliminate the invalid instructions that have been optimized out. */
7002 n_instructions = instr_compact(instructions,
7006 return n_instructions;
7010 instr_pattern_emit_many_tx_search(struct instruction *instr,
7011 struct instruction_data *data,
7013 uint32_t *n_pattern_instr)
7017 for (i = 0; i < n_instr; i++) {
7018 if (data[i].invalid)
7021 if (instr[i].type != INSTR_HDR_EMIT)
7024 if (i == RTE_DIM(instr->io.hdr.header_id))
7027 if (i && data[i].n_users)
7034 if (!instruction_is_tx(instr[i].type))
7037 if (data[i].n_users)
7042 *n_pattern_instr = i;
7047 instr_pattern_emit_many_tx_replace(struct instruction *instr,
7048 struct instruction_data *data,
7053 /* Any emit instruction in addition to the first one. */
7054 for (i = 1; i < n_instr - 1; i++) {
7056 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
7057 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
7058 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
7060 data[i].invalid = 1;
7063 /* The TX instruction is the last one in the pattern. */
7065 instr[0].io.io.offset = instr[i].io.io.offset;
7066 instr[0].io.io.n_bits = instr[i].io.io.n_bits;
7067 data[i].invalid = 1;
7071 instr_pattern_emit_many_tx_optimize(struct instruction *instructions,
7072 struct instruction_data *instruction_data,
7073 uint32_t n_instructions)
7077 for (i = 0; i < n_instructions; ) {
7078 struct instruction *instr = &instructions[i];
7079 struct instruction_data *data = &instruction_data[i];
7080 uint32_t n_instr = 0;
7083 /* Emit many + TX. */
7084 detected = instr_pattern_emit_many_tx_search(instr,
7089 instr_pattern_emit_many_tx_replace(instr,
7096 /* No pattern starting at the current instruction. */
7100 /* Eliminate the invalid instructions that have been optimized out. */
7101 n_instructions = instr_compact(instructions,
7105 return n_instructions;
7109 action_arg_src_mov_count(struct action *a,
7111 struct instruction *instructions,
7112 struct instruction_data *instruction_data,
7113 uint32_t n_instructions);
7116 instr_pattern_mov_all_validate_search(struct rte_swx_pipeline *p,
7118 struct instruction *instr,
7119 struct instruction_data *data,
7121 struct instruction *instructions,
7122 struct instruction_data *instruction_data,
7123 uint32_t n_instructions,
7124 uint32_t *n_pattern_instr)
7127 uint32_t src_field_id, i, j;
7129 /* Prerequisites. */
7133 /* First instruction: MOV_HM. */
7134 if (data[0].invalid || (instr[0].type != INSTR_MOV_HM))
7137 h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
7138 if (!h || h->st->var_size)
7141 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
7142 if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
7145 if (src_field_id == a->st->n_fields)
7148 if (instr[0].mov.dst.offset ||
7149 (instr[0].mov.dst.n_bits != h->st->fields[0].n_bits) ||
7150 instr[0].mov.src.struct_id ||
7151 (instr[0].mov.src.n_bits != a->st->fields[src_field_id].n_bits) ||
7152 (instr[0].mov.dst.n_bits != instr[0].mov.src.n_bits))
7155 if ((n_instr < h->st->n_fields + 1) ||
7156 (a->st->n_fields < src_field_id + h->st->n_fields + 1))
7159 /* Subsequent instructions: MOV_HM. */
7160 for (i = 1; i < h->st->n_fields; i++)
7161 if (data[i].invalid ||
7163 (instr[i].type != INSTR_MOV_HM) ||
7164 (instr[i].mov.dst.struct_id != h->struct_id) ||
7165 (instr[i].mov.dst.offset != h->st->fields[i].offset / 8) ||
7166 (instr[i].mov.dst.n_bits != h->st->fields[i].n_bits) ||
7167 instr[i].mov.src.struct_id ||
7168 (instr[i].mov.src.offset != a->st->fields[src_field_id + i].offset / 8) ||
7169 (instr[i].mov.src.n_bits != a->st->fields[src_field_id + i].n_bits) ||
7170 (instr[i].mov.dst.n_bits != instr[i].mov.src.n_bits))
7173 /* Last instruction: HDR_VALIDATE. */
7174 if ((instr[i].type != INSTR_HDR_VALIDATE) ||
7175 (instr[i].valid.header_id != h->id))
7178 /* Check that none of the action args that are used as source for this
7179 * DMA transfer are not used as source in any other mov instruction.
7181 for (j = src_field_id; j < src_field_id + h->st->n_fields; j++) {
7184 n_users = action_arg_src_mov_count(a,
7193 *n_pattern_instr = 1 + i;
7198 instr_pattern_mov_all_validate_replace(struct rte_swx_pipeline *p,
7200 struct instruction *instr,
7201 struct instruction_data *data,
7205 uint32_t src_field_id, src_offset, i;
7207 /* Read from the instructions before they are modified. */
7208 h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
7212 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
7213 if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
7216 if (src_field_id == a->st->n_fields)
7219 src_offset = instr[0].mov.src.offset;
7221 /* Modify the instructions. */
7222 instr[0].type = INSTR_DMA_HT;
7223 instr[0].dma.dst.header_id[0] = h->id;
7224 instr[0].dma.dst.struct_id[0] = h->struct_id;
7225 instr[0].dma.src.offset[0] = (uint8_t)src_offset;
7226 instr[0].dma.n_bytes[0] = h->st->n_bits / 8;
7228 for (i = 1; i < n_instr; i++)
7229 data[i].invalid = 1;
7231 /* Update the endianness of the action arguments to header endianness. */
7232 for (i = 0; i < h->st->n_fields; i++)
7233 a->args_endianness[src_field_id + i] = 1;
7237 instr_pattern_mov_all_validate_optimize(struct rte_swx_pipeline *p,
7239 struct instruction *instructions,
7240 struct instruction_data *instruction_data,
7241 uint32_t n_instructions)
7246 return n_instructions;
7248 for (i = 0; i < n_instructions; ) {
7249 struct instruction *instr = &instructions[i];
7250 struct instruction_data *data = &instruction_data[i];
7251 uint32_t n_instr = 0;
7254 /* Mov all + validate. */
7255 detected = instr_pattern_mov_all_validate_search(p,
7265 instr_pattern_mov_all_validate_replace(p, a, instr, data, n_instr);
7270 /* No pattern starting at the current instruction. */
7274 /* Eliminate the invalid instructions that have been optimized out. */
7275 n_instructions = instr_compact(instructions,
7279 return n_instructions;
7283 instr_pattern_dma_many_search(struct instruction *instr,
7284 struct instruction_data *data,
7286 uint32_t *n_pattern_instr)
7290 for (i = 0; i < n_instr; i++) {
7291 if (data[i].invalid)
7294 if (instr[i].type != INSTR_DMA_HT)
7297 if (i == RTE_DIM(instr->dma.dst.header_id))
7300 if (i && data[i].n_users)
7307 *n_pattern_instr = i;
7312 instr_pattern_dma_many_replace(struct instruction *instr,
7313 struct instruction_data *data,
7318 for (i = 1; i < n_instr; i++) {
7320 instr[0].dma.dst.header_id[i] = instr[i].dma.dst.header_id[0];
7321 instr[0].dma.dst.struct_id[i] = instr[i].dma.dst.struct_id[0];
7322 instr[0].dma.src.offset[i] = instr[i].dma.src.offset[0];
7323 instr[0].dma.n_bytes[i] = instr[i].dma.n_bytes[0];
7325 data[i].invalid = 1;
7330 instr_pattern_dma_many_optimize(struct instruction *instructions,
7331 struct instruction_data *instruction_data,
7332 uint32_t n_instructions)
7336 for (i = 0; i < n_instructions; ) {
7337 struct instruction *instr = &instructions[i];
7338 struct instruction_data *data = &instruction_data[i];
7339 uint32_t n_instr = 0;
7343 detected = instr_pattern_dma_many_search(instr,
7348 instr_pattern_dma_many_replace(instr, data, n_instr);
7353 /* No pattern starting at the current instruction. */
7357 /* Eliminate the invalid instructions that have been optimized out. */
7358 n_instructions = instr_compact(instructions,
7362 return n_instructions;
7366 instr_optimize(struct rte_swx_pipeline *p,
7368 struct instruction *instructions,
7369 struct instruction_data *instruction_data,
7370 uint32_t n_instructions)
7373 n_instructions = instr_pattern_extract_many_optimize(instructions,
7377 /* Emit many + TX. */
7378 n_instructions = instr_pattern_emit_many_tx_optimize(instructions,
7382 /* Mov all + validate. */
7383 n_instructions = instr_pattern_mov_all_validate_optimize(p,
7390 n_instructions = instr_pattern_dma_many_optimize(instructions,
7394 return n_instructions;
7398 instruction_config(struct rte_swx_pipeline *p,
7400 const char **instructions,
7401 uint32_t n_instructions)
7403 struct instruction *instr = NULL;
7404 struct instruction_data *data = NULL;
7408 CHECK(n_instructions, EINVAL);
7409 CHECK(instructions, EINVAL);
7410 for (i = 0; i < n_instructions; i++)
7411 CHECK_INSTRUCTION(instructions[i], EINVAL);
7413 /* Memory allocation. */
7414 instr = calloc(n_instructions, sizeof(struct instruction));
7420 data = calloc(n_instructions, sizeof(struct instruction_data));
7426 for (i = 0; i < n_instructions; i++) {
7427 char *string = strdup(instructions[i]);
7433 err = instr_translate(p, a, string, &instr[i], &data[i]);
7442 err = instr_label_check(data, n_instructions);
7446 err = instr_verify(p, a, instr, data, n_instructions);
7450 n_instructions = instr_optimize(p, a, instr, data, n_instructions);
7452 err = instr_jmp_resolve(instr, data, n_instructions);
7457 a->instructions = instr;
7458 a->n_instructions = n_instructions;
7460 p->instructions = instr;
7461 p->n_instructions = n_instructions;
7473 typedef void (*instr_exec_t)(struct rte_swx_pipeline *);
7475 static instr_exec_t instruction_table[] = {
7476 [INSTR_RX] = instr_rx_exec,
7477 [INSTR_TX] = instr_tx_exec,
7478 [INSTR_TX_I] = instr_tx_i_exec,
7480 [INSTR_HDR_EXTRACT] = instr_hdr_extract_exec,
7481 [INSTR_HDR_EXTRACT2] = instr_hdr_extract2_exec,
7482 [INSTR_HDR_EXTRACT3] = instr_hdr_extract3_exec,
7483 [INSTR_HDR_EXTRACT4] = instr_hdr_extract4_exec,
7484 [INSTR_HDR_EXTRACT5] = instr_hdr_extract5_exec,
7485 [INSTR_HDR_EXTRACT6] = instr_hdr_extract6_exec,
7486 [INSTR_HDR_EXTRACT7] = instr_hdr_extract7_exec,
7487 [INSTR_HDR_EXTRACT8] = instr_hdr_extract8_exec,
7488 [INSTR_HDR_EXTRACT_M] = instr_hdr_extract_m_exec,
7489 [INSTR_HDR_LOOKAHEAD] = instr_hdr_lookahead_exec,
7491 [INSTR_HDR_EMIT] = instr_hdr_emit_exec,
7492 [INSTR_HDR_EMIT_TX] = instr_hdr_emit_tx_exec,
7493 [INSTR_HDR_EMIT2_TX] = instr_hdr_emit2_tx_exec,
7494 [INSTR_HDR_EMIT3_TX] = instr_hdr_emit3_tx_exec,
7495 [INSTR_HDR_EMIT4_TX] = instr_hdr_emit4_tx_exec,
7496 [INSTR_HDR_EMIT5_TX] = instr_hdr_emit5_tx_exec,
7497 [INSTR_HDR_EMIT6_TX] = instr_hdr_emit6_tx_exec,
7498 [INSTR_HDR_EMIT7_TX] = instr_hdr_emit7_tx_exec,
7499 [INSTR_HDR_EMIT8_TX] = instr_hdr_emit8_tx_exec,
7501 [INSTR_HDR_VALIDATE] = instr_hdr_validate_exec,
7502 [INSTR_HDR_INVALIDATE] = instr_hdr_invalidate_exec,
7504 [INSTR_MOV] = instr_mov_exec,
7505 [INSTR_MOV_MH] = instr_mov_mh_exec,
7506 [INSTR_MOV_HM] = instr_mov_hm_exec,
7507 [INSTR_MOV_HH] = instr_mov_hh_exec,
7508 [INSTR_MOV_I] = instr_mov_i_exec,
7510 [INSTR_DMA_HT] = instr_dma_ht_exec,
7511 [INSTR_DMA_HT2] = instr_dma_ht2_exec,
7512 [INSTR_DMA_HT3] = instr_dma_ht3_exec,
7513 [INSTR_DMA_HT4] = instr_dma_ht4_exec,
7514 [INSTR_DMA_HT5] = instr_dma_ht5_exec,
7515 [INSTR_DMA_HT6] = instr_dma_ht6_exec,
7516 [INSTR_DMA_HT7] = instr_dma_ht7_exec,
7517 [INSTR_DMA_HT8] = instr_dma_ht8_exec,
7519 [INSTR_ALU_ADD] = instr_alu_add_exec,
7520 [INSTR_ALU_ADD_MH] = instr_alu_add_mh_exec,
7521 [INSTR_ALU_ADD_HM] = instr_alu_add_hm_exec,
7522 [INSTR_ALU_ADD_HH] = instr_alu_add_hh_exec,
7523 [INSTR_ALU_ADD_MI] = instr_alu_add_mi_exec,
7524 [INSTR_ALU_ADD_HI] = instr_alu_add_hi_exec,
7526 [INSTR_ALU_SUB] = instr_alu_sub_exec,
7527 [INSTR_ALU_SUB_MH] = instr_alu_sub_mh_exec,
7528 [INSTR_ALU_SUB_HM] = instr_alu_sub_hm_exec,
7529 [INSTR_ALU_SUB_HH] = instr_alu_sub_hh_exec,
7530 [INSTR_ALU_SUB_MI] = instr_alu_sub_mi_exec,
7531 [INSTR_ALU_SUB_HI] = instr_alu_sub_hi_exec,
7533 [INSTR_ALU_CKADD_FIELD] = instr_alu_ckadd_field_exec,
7534 [INSTR_ALU_CKADD_STRUCT] = instr_alu_ckadd_struct_exec,
7535 [INSTR_ALU_CKADD_STRUCT20] = instr_alu_ckadd_struct20_exec,
7536 [INSTR_ALU_CKSUB_FIELD] = instr_alu_cksub_field_exec,
7538 [INSTR_ALU_AND] = instr_alu_and_exec,
7539 [INSTR_ALU_AND_MH] = instr_alu_and_mh_exec,
7540 [INSTR_ALU_AND_HM] = instr_alu_and_hm_exec,
7541 [INSTR_ALU_AND_HH] = instr_alu_and_hh_exec,
7542 [INSTR_ALU_AND_I] = instr_alu_and_i_exec,
7544 [INSTR_ALU_OR] = instr_alu_or_exec,
7545 [INSTR_ALU_OR_MH] = instr_alu_or_mh_exec,
7546 [INSTR_ALU_OR_HM] = instr_alu_or_hm_exec,
7547 [INSTR_ALU_OR_HH] = instr_alu_or_hh_exec,
7548 [INSTR_ALU_OR_I] = instr_alu_or_i_exec,
7550 [INSTR_ALU_XOR] = instr_alu_xor_exec,
7551 [INSTR_ALU_XOR_MH] = instr_alu_xor_mh_exec,
7552 [INSTR_ALU_XOR_HM] = instr_alu_xor_hm_exec,
7553 [INSTR_ALU_XOR_HH] = instr_alu_xor_hh_exec,
7554 [INSTR_ALU_XOR_I] = instr_alu_xor_i_exec,
7556 [INSTR_ALU_SHL] = instr_alu_shl_exec,
7557 [INSTR_ALU_SHL_MH] = instr_alu_shl_mh_exec,
7558 [INSTR_ALU_SHL_HM] = instr_alu_shl_hm_exec,
7559 [INSTR_ALU_SHL_HH] = instr_alu_shl_hh_exec,
7560 [INSTR_ALU_SHL_MI] = instr_alu_shl_mi_exec,
7561 [INSTR_ALU_SHL_HI] = instr_alu_shl_hi_exec,
7563 [INSTR_ALU_SHR] = instr_alu_shr_exec,
7564 [INSTR_ALU_SHR_MH] = instr_alu_shr_mh_exec,
7565 [INSTR_ALU_SHR_HM] = instr_alu_shr_hm_exec,
7566 [INSTR_ALU_SHR_HH] = instr_alu_shr_hh_exec,
7567 [INSTR_ALU_SHR_MI] = instr_alu_shr_mi_exec,
7568 [INSTR_ALU_SHR_HI] = instr_alu_shr_hi_exec,
7570 [INSTR_REGPREFETCH_RH] = instr_regprefetch_rh_exec,
7571 [INSTR_REGPREFETCH_RM] = instr_regprefetch_rm_exec,
7572 [INSTR_REGPREFETCH_RI] = instr_regprefetch_ri_exec,
7574 [INSTR_REGRD_HRH] = instr_regrd_hrh_exec,
7575 [INSTR_REGRD_HRM] = instr_regrd_hrm_exec,
7576 [INSTR_REGRD_MRH] = instr_regrd_mrh_exec,
7577 [INSTR_REGRD_MRM] = instr_regrd_mrm_exec,
7578 [INSTR_REGRD_HRI] = instr_regrd_hri_exec,
7579 [INSTR_REGRD_MRI] = instr_regrd_mri_exec,
7581 [INSTR_REGWR_RHH] = instr_regwr_rhh_exec,
7582 [INSTR_REGWR_RHM] = instr_regwr_rhm_exec,
7583 [INSTR_REGWR_RMH] = instr_regwr_rmh_exec,
7584 [INSTR_REGWR_RMM] = instr_regwr_rmm_exec,
7585 [INSTR_REGWR_RHI] = instr_regwr_rhi_exec,
7586 [INSTR_REGWR_RMI] = instr_regwr_rmi_exec,
7587 [INSTR_REGWR_RIH] = instr_regwr_rih_exec,
7588 [INSTR_REGWR_RIM] = instr_regwr_rim_exec,
7589 [INSTR_REGWR_RII] = instr_regwr_rii_exec,
7591 [INSTR_REGADD_RHH] = instr_regadd_rhh_exec,
7592 [INSTR_REGADD_RHM] = instr_regadd_rhm_exec,
7593 [INSTR_REGADD_RMH] = instr_regadd_rmh_exec,
7594 [INSTR_REGADD_RMM] = instr_regadd_rmm_exec,
7595 [INSTR_REGADD_RHI] = instr_regadd_rhi_exec,
7596 [INSTR_REGADD_RMI] = instr_regadd_rmi_exec,
7597 [INSTR_REGADD_RIH] = instr_regadd_rih_exec,
7598 [INSTR_REGADD_RIM] = instr_regadd_rim_exec,
7599 [INSTR_REGADD_RII] = instr_regadd_rii_exec,
7601 [INSTR_METPREFETCH_H] = instr_metprefetch_h_exec,
7602 [INSTR_METPREFETCH_M] = instr_metprefetch_m_exec,
7603 [INSTR_METPREFETCH_I] = instr_metprefetch_i_exec,
7605 [INSTR_METER_HHM] = instr_meter_hhm_exec,
7606 [INSTR_METER_HHI] = instr_meter_hhi_exec,
7607 [INSTR_METER_HMM] = instr_meter_hmm_exec,
7608 [INSTR_METER_HMI] = instr_meter_hmi_exec,
7609 [INSTR_METER_MHM] = instr_meter_mhm_exec,
7610 [INSTR_METER_MHI] = instr_meter_mhi_exec,
7611 [INSTR_METER_MMM] = instr_meter_mmm_exec,
7612 [INSTR_METER_MMI] = instr_meter_mmi_exec,
7613 [INSTR_METER_IHM] = instr_meter_ihm_exec,
7614 [INSTR_METER_IHI] = instr_meter_ihi_exec,
7615 [INSTR_METER_IMM] = instr_meter_imm_exec,
7616 [INSTR_METER_IMI] = instr_meter_imi_exec,
7618 [INSTR_TABLE] = instr_table_exec,
7619 [INSTR_SELECTOR] = instr_selector_exec,
7620 [INSTR_LEARNER] = instr_learner_exec,
7621 [INSTR_LEARNER_LEARN] = instr_learn_exec,
7622 [INSTR_LEARNER_FORGET] = instr_forget_exec,
7623 [INSTR_EXTERN_OBJ] = instr_extern_obj_exec,
7624 [INSTR_EXTERN_FUNC] = instr_extern_func_exec,
7626 [INSTR_JMP] = instr_jmp_exec,
7627 [INSTR_JMP_VALID] = instr_jmp_valid_exec,
7628 [INSTR_JMP_INVALID] = instr_jmp_invalid_exec,
7629 [INSTR_JMP_HIT] = instr_jmp_hit_exec,
7630 [INSTR_JMP_MISS] = instr_jmp_miss_exec,
7631 [INSTR_JMP_ACTION_HIT] = instr_jmp_action_hit_exec,
7632 [INSTR_JMP_ACTION_MISS] = instr_jmp_action_miss_exec,
7634 [INSTR_JMP_EQ] = instr_jmp_eq_exec,
7635 [INSTR_JMP_EQ_MH] = instr_jmp_eq_mh_exec,
7636 [INSTR_JMP_EQ_HM] = instr_jmp_eq_hm_exec,
7637 [INSTR_JMP_EQ_HH] = instr_jmp_eq_hh_exec,
7638 [INSTR_JMP_EQ_I] = instr_jmp_eq_i_exec,
7640 [INSTR_JMP_NEQ] = instr_jmp_neq_exec,
7641 [INSTR_JMP_NEQ_MH] = instr_jmp_neq_mh_exec,
7642 [INSTR_JMP_NEQ_HM] = instr_jmp_neq_hm_exec,
7643 [INSTR_JMP_NEQ_HH] = instr_jmp_neq_hh_exec,
7644 [INSTR_JMP_NEQ_I] = instr_jmp_neq_i_exec,
7646 [INSTR_JMP_LT] = instr_jmp_lt_exec,
7647 [INSTR_JMP_LT_MH] = instr_jmp_lt_mh_exec,
7648 [INSTR_JMP_LT_HM] = instr_jmp_lt_hm_exec,
7649 [INSTR_JMP_LT_HH] = instr_jmp_lt_hh_exec,
7650 [INSTR_JMP_LT_MI] = instr_jmp_lt_mi_exec,
7651 [INSTR_JMP_LT_HI] = instr_jmp_lt_hi_exec,
7653 [INSTR_JMP_GT] = instr_jmp_gt_exec,
7654 [INSTR_JMP_GT_MH] = instr_jmp_gt_mh_exec,
7655 [INSTR_JMP_GT_HM] = instr_jmp_gt_hm_exec,
7656 [INSTR_JMP_GT_HH] = instr_jmp_gt_hh_exec,
7657 [INSTR_JMP_GT_MI] = instr_jmp_gt_mi_exec,
7658 [INSTR_JMP_GT_HI] = instr_jmp_gt_hi_exec,
7660 [INSTR_RETURN] = instr_return_exec,
7664 instr_exec(struct rte_swx_pipeline *p)
7666 struct thread *t = &p->threads[p->thread_id];
7667 struct instruction *ip = t->ip;
7668 instr_exec_t instr = instruction_table[ip->type];
7676 static struct action *
7677 action_find(struct rte_swx_pipeline *p, const char *name)
7679 struct action *elem;
7684 TAILQ_FOREACH(elem, &p->actions, node)
7685 if (strcmp(elem->name, name) == 0)
7691 static struct action *
7692 action_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7694 struct action *action = NULL;
7696 TAILQ_FOREACH(action, &p->actions, node)
7697 if (action->id == id)
7703 static struct field *
7704 action_field_find(struct action *a, const char *name)
7706 return a->st ? struct_type_field_find(a->st, name) : NULL;
7709 static struct field *
7710 action_field_parse(struct action *action, const char *name)
7712 if (name[0] != 't' || name[1] != '.')
7715 return action_field_find(action, &name[2]);
7719 action_has_nbo_args(struct action *a)
7723 /* Return if the action does not have any args. */
7725 return 0; /* FALSE */
7727 for (i = 0; i < a->st->n_fields; i++)
7728 if (a->args_endianness[i])
7729 return 1; /* TRUE */
7731 return 0; /* FALSE */
7735 action_does_learning(struct action *a)
7739 for (i = 0; i < a->n_instructions; i++)
7740 switch (a->instructions[i].type) {
7741 case INSTR_LEARNER_LEARN:
7742 return 1; /* TRUE */
7744 case INSTR_LEARNER_FORGET:
7745 return 1; /* TRUE */
7751 return 0; /* FALSE */
7755 rte_swx_pipeline_action_config(struct rte_swx_pipeline *p,
7757 const char *args_struct_type_name,
7758 const char **instructions,
7759 uint32_t n_instructions)
7761 struct struct_type *args_struct_type = NULL;
7767 CHECK_NAME(name, EINVAL);
7768 CHECK(!action_find(p, name), EEXIST);
7770 if (args_struct_type_name) {
7771 CHECK_NAME(args_struct_type_name, EINVAL);
7772 args_struct_type = struct_type_find(p, args_struct_type_name);
7773 CHECK(args_struct_type, EINVAL);
7774 CHECK(!args_struct_type->var_size, EINVAL);
7777 /* Node allocation. */
7778 a = calloc(1, sizeof(struct action));
7780 if (args_struct_type) {
7781 a->args_endianness = calloc(args_struct_type->n_fields, sizeof(int));
7782 if (!a->args_endianness) {
7788 /* Node initialization. */
7789 strcpy(a->name, name);
7790 a->st = args_struct_type;
7791 a->id = p->n_actions;
7793 /* Instruction translation. */
7794 err = instruction_config(p, a, instructions, n_instructions);
7796 free(a->args_endianness);
7801 /* Node add to tailq. */
7802 TAILQ_INSERT_TAIL(&p->actions, a, node);
7809 action_build(struct rte_swx_pipeline *p)
7811 struct action *action;
7813 p->action_instructions = calloc(p->n_actions,
7814 sizeof(struct instruction *));
7815 CHECK(p->action_instructions, ENOMEM);
7817 TAILQ_FOREACH(action, &p->actions, node)
7818 p->action_instructions[action->id] = action->instructions;
7824 action_build_free(struct rte_swx_pipeline *p)
7826 free(p->action_instructions);
7827 p->action_instructions = NULL;
7831 action_free(struct rte_swx_pipeline *p)
7833 action_build_free(p);
7836 struct action *action;
7838 action = TAILQ_FIRST(&p->actions);
7842 TAILQ_REMOVE(&p->actions, action, node);
7843 free(action->instructions);
7849 action_arg_src_mov_count(struct action *a,
7851 struct instruction *instructions,
7852 struct instruction_data *instruction_data,
7853 uint32_t n_instructions)
7855 uint32_t offset, n_users = 0, i;
7858 (arg_id >= a->st->n_fields) ||
7860 !instruction_data ||
7864 offset = a->st->fields[arg_id].offset / 8;
7866 for (i = 0; i < n_instructions; i++) {
7867 struct instruction *instr = &instructions[i];
7868 struct instruction_data *data = &instruction_data[i];
7870 if (data->invalid ||
7871 ((instr->type != INSTR_MOV) && (instr->type != INSTR_MOV_HM)) ||
7872 instr->mov.src.struct_id ||
7873 (instr->mov.src.offset != offset))
7885 static struct table_type *
7886 table_type_find(struct rte_swx_pipeline *p, const char *name)
7888 struct table_type *elem;
7890 TAILQ_FOREACH(elem, &p->table_types, node)
7891 if (strcmp(elem->name, name) == 0)
7897 static struct table_type *
7898 table_type_resolve(struct rte_swx_pipeline *p,
7899 const char *recommended_type_name,
7900 enum rte_swx_table_match_type match_type)
7902 struct table_type *elem;
7904 /* Only consider the recommended type if the match type is correct. */
7905 if (recommended_type_name)
7906 TAILQ_FOREACH(elem, &p->table_types, node)
7907 if (!strcmp(elem->name, recommended_type_name) &&
7908 (elem->match_type == match_type))
7911 /* Ignore the recommended type and get the first element with this match
7914 TAILQ_FOREACH(elem, &p->table_types, node)
7915 if (elem->match_type == match_type)
7921 static struct table *
7922 table_find(struct rte_swx_pipeline *p, const char *name)
7926 TAILQ_FOREACH(elem, &p->tables, node)
7927 if (strcmp(elem->name, name) == 0)
7933 static struct table *
7934 table_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7936 struct table *table = NULL;
7938 TAILQ_FOREACH(table, &p->tables, node)
7939 if (table->id == id)
7946 rte_swx_pipeline_table_type_register(struct rte_swx_pipeline *p,
7948 enum rte_swx_table_match_type match_type,
7949 struct rte_swx_table_ops *ops)
7951 struct table_type *elem;
7955 CHECK_NAME(name, EINVAL);
7956 CHECK(!table_type_find(p, name), EEXIST);
7959 CHECK(ops->create, EINVAL);
7960 CHECK(ops->lkp, EINVAL);
7961 CHECK(ops->free, EINVAL);
7963 /* Node allocation. */
7964 elem = calloc(1, sizeof(struct table_type));
7965 CHECK(elem, ENOMEM);
7967 /* Node initialization. */
7968 strcpy(elem->name, name);
7969 elem->match_type = match_type;
7970 memcpy(&elem->ops, ops, sizeof(*ops));
7972 /* Node add to tailq. */
7973 TAILQ_INSERT_TAIL(&p->table_types, elem, node);
7979 table_match_type_resolve(struct rte_swx_match_field_params *fields,
7981 enum rte_swx_table_match_type *match_type)
7983 uint32_t n_fields_em = 0, n_fields_lpm = 0, i;
7985 for (i = 0; i < n_fields; i++) {
7986 struct rte_swx_match_field_params *f = &fields[i];
7988 if (f->match_type == RTE_SWX_TABLE_MATCH_EXACT)
7991 if (f->match_type == RTE_SWX_TABLE_MATCH_LPM)
7995 if ((n_fields_lpm > 1) ||
7996 (n_fields_lpm && (n_fields_em != n_fields - 1)))
7999 *match_type = (n_fields_em == n_fields) ?
8000 RTE_SWX_TABLE_MATCH_EXACT :
8001 RTE_SWX_TABLE_MATCH_WILDCARD;
8007 table_match_fields_check(struct rte_swx_pipeline *p,
8008 struct rte_swx_pipeline_table_params *params,
8009 struct header **header)
8011 struct header *h0 = NULL;
8012 struct field *hf, *mf;
8013 uint32_t *offset = NULL, i;
8016 /* Return if no match fields. */
8017 if (!params->n_fields) {
8018 if (params->fields) {
8029 /* Memory allocation. */
8030 offset = calloc(params->n_fields, sizeof(uint32_t));
8036 /* Check that all the match fields belong to either the same header or
8039 hf = header_field_parse(p, params->fields[0].name, &h0);
8040 mf = metadata_field_parse(p, params->fields[0].name);
8041 if ((!hf && !mf) || (hf && hf->var_size)) {
8046 offset[0] = h0 ? hf->offset : mf->offset;
8048 for (i = 1; i < params->n_fields; i++)
8052 hf = header_field_parse(p, params->fields[i].name, &h);
8053 if (!hf || (h->id != h0->id) || hf->var_size) {
8058 offset[i] = hf->offset;
8060 mf = metadata_field_parse(p, params->fields[i].name);
8066 offset[i] = mf->offset;
8069 /* Check that there are no duplicated match fields. */
8070 for (i = 0; i < params->n_fields; i++) {
8073 for (j = 0; j < i; j++)
8074 if (offset[j] == offset[i]) {
8090 rte_swx_pipeline_table_config(struct rte_swx_pipeline *p,
8092 struct rte_swx_pipeline_table_params *params,
8093 const char *recommended_table_type_name,
8097 struct table_type *type;
8099 struct action *default_action;
8100 struct header *header = NULL;
8101 uint32_t action_data_size_max = 0, i;
8106 CHECK_NAME(name, EINVAL);
8107 CHECK(!table_find(p, name), EEXIST);
8108 CHECK(!selector_find(p, name), EEXIST);
8109 CHECK(!learner_find(p, name), EEXIST);
8111 CHECK(params, EINVAL);
8114 status = table_match_fields_check(p, params, &header);
8118 /* Action checks. */
8119 CHECK(params->n_actions, EINVAL);
8120 CHECK(params->action_names, EINVAL);
8121 for (i = 0; i < params->n_actions; i++) {
8122 const char *action_name = params->action_names[i];
8124 uint32_t action_data_size;
8126 CHECK_NAME(action_name, EINVAL);
8128 a = action_find(p, action_name);
8130 CHECK(!action_does_learning(a), EINVAL);
8132 action_data_size = a->st ? a->st->n_bits / 8 : 0;
8133 if (action_data_size > action_data_size_max)
8134 action_data_size_max = action_data_size;
8137 CHECK_NAME(params->default_action_name, EINVAL);
8138 for (i = 0; i < p->n_actions; i++)
8139 if (!strcmp(params->action_names[i],
8140 params->default_action_name))
8142 CHECK(i < params->n_actions, EINVAL);
8143 default_action = action_find(p, params->default_action_name);
8144 CHECK((default_action->st && params->default_action_data) ||
8145 !params->default_action_data, EINVAL);
8147 /* Table type checks. */
8148 if (recommended_table_type_name)
8149 CHECK_NAME(recommended_table_type_name, EINVAL);
8151 if (params->n_fields) {
8152 enum rte_swx_table_match_type match_type;
8154 status = table_match_type_resolve(params->fields, params->n_fields, &match_type);
8158 type = table_type_resolve(p, recommended_table_type_name, match_type);
8159 CHECK(type, EINVAL);
8164 /* Memory allocation. */
8165 t = calloc(1, sizeof(struct table));
8168 t->fields = calloc(params->n_fields, sizeof(struct match_field));
8174 t->actions = calloc(params->n_actions, sizeof(struct action *));
8181 if (action_data_size_max) {
8182 t->default_action_data = calloc(1, action_data_size_max);
8183 if (!t->default_action_data) {
8191 /* Node initialization. */
8192 strcpy(t->name, name);
8193 if (args && args[0])
8194 strcpy(t->args, args);
8197 for (i = 0; i < params->n_fields; i++) {
8198 struct rte_swx_match_field_params *field = ¶ms->fields[i];
8199 struct match_field *f = &t->fields[i];
8201 f->match_type = field->match_type;
8203 header_field_parse(p, field->name, NULL) :
8204 metadata_field_parse(p, field->name);
8206 t->n_fields = params->n_fields;
8209 for (i = 0; i < params->n_actions; i++)
8210 t->actions[i] = action_find(p, params->action_names[i]);
8211 t->default_action = default_action;
8212 if (default_action->st)
8213 memcpy(t->default_action_data,
8214 params->default_action_data,
8215 default_action->st->n_bits / 8);
8216 t->n_actions = params->n_actions;
8217 t->default_action_is_const = params->default_action_is_const;
8218 t->action_data_size_max = action_data_size_max;
8221 t->id = p->n_tables;
8223 /* Node add to tailq. */
8224 TAILQ_INSERT_TAIL(&p->tables, t, node);
8230 static struct rte_swx_table_params *
8231 table_params_get(struct table *table)
8233 struct rte_swx_table_params *params;
8234 struct field *first, *last;
8236 uint32_t key_size, key_offset, action_data_size, i;
8238 /* Memory allocation. */
8239 params = calloc(1, sizeof(struct rte_swx_table_params));
8243 /* Find first (smallest offset) and last (biggest offset) match fields. */
8244 first = table->fields[0].field;
8245 last = table->fields[0].field;
8247 for (i = 0; i < table->n_fields; i++) {
8248 struct field *f = table->fields[i].field;
8250 if (f->offset < first->offset)
8253 if (f->offset > last->offset)
8257 /* Key offset and size. */
8258 key_offset = first->offset / 8;
8259 key_size = (last->offset + last->n_bits - first->offset) / 8;
8261 /* Memory allocation. */
8262 key_mask = calloc(1, key_size);
8269 for (i = 0; i < table->n_fields; i++) {
8270 struct field *f = table->fields[i].field;
8271 uint32_t start = (f->offset - first->offset) / 8;
8272 size_t size = f->n_bits / 8;
8274 memset(&key_mask[start], 0xFF, size);
8277 /* Action data size. */
8278 action_data_size = 0;
8279 for (i = 0; i < table->n_actions; i++) {
8280 struct action *action = table->actions[i];
8281 uint32_t ads = action->st ? action->st->n_bits / 8 : 0;
8283 if (ads > action_data_size)
8284 action_data_size = ads;
8288 params->match_type = table->type->match_type;
8289 params->key_size = key_size;
8290 params->key_offset = key_offset;
8291 params->key_mask0 = key_mask;
8292 params->action_data_size = action_data_size;
8293 params->n_keys_max = table->size;
8299 table_params_free(struct rte_swx_table_params *params)
8304 free(params->key_mask0);
8309 table_stub_lkp(void *table __rte_unused,
8310 void *mailbox __rte_unused,
8311 uint8_t **key __rte_unused,
8312 uint64_t *action_id __rte_unused,
8313 uint8_t **action_data __rte_unused,
8317 return 1; /* DONE. */
8321 table_build(struct rte_swx_pipeline *p)
8325 /* Per pipeline: table statistics. */
8326 p->table_stats = calloc(p->n_tables, sizeof(struct table_statistics));
8327 CHECK(p->table_stats, ENOMEM);
8329 for (i = 0; i < p->n_tables; i++) {
8330 p->table_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
8331 CHECK(p->table_stats[i].n_pkts_action, ENOMEM);
8334 /* Per thread: table runt-time. */
8335 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8336 struct thread *t = &p->threads[i];
8337 struct table *table;
8339 t->tables = calloc(p->n_tables, sizeof(struct table_runtime));
8340 CHECK(t->tables, ENOMEM);
8342 TAILQ_FOREACH(table, &p->tables, node) {
8343 struct table_runtime *r = &t->tables[table->id];
8348 size = table->type->ops.mailbox_size_get();
8351 r->func = table->type->ops.lkp;
8355 r->mailbox = calloc(1, size);
8356 CHECK(r->mailbox, ENOMEM);
8360 r->key = table->header ?
8361 &t->structs[table->header->struct_id] :
8362 &t->structs[p->metadata_struct_id];
8364 r->func = table_stub_lkp;
8373 table_build_free(struct rte_swx_pipeline *p)
8377 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8378 struct thread *t = &p->threads[i];
8384 for (j = 0; j < p->n_tables; j++) {
8385 struct table_runtime *r = &t->tables[j];
8394 if (p->table_stats) {
8395 for (i = 0; i < p->n_tables; i++)
8396 free(p->table_stats[i].n_pkts_action);
8398 free(p->table_stats);
8403 table_free(struct rte_swx_pipeline *p)
8405 table_build_free(p);
8411 elem = TAILQ_FIRST(&p->tables);
8415 TAILQ_REMOVE(&p->tables, elem, node);
8417 free(elem->actions);
8418 free(elem->default_action_data);
8424 struct table_type *elem;
8426 elem = TAILQ_FIRST(&p->table_types);
8430 TAILQ_REMOVE(&p->table_types, elem, node);
8438 static struct selector *
8439 selector_find(struct rte_swx_pipeline *p, const char *name)
8443 TAILQ_FOREACH(s, &p->selectors, node)
8444 if (strcmp(s->name, name) == 0)
8450 static struct selector *
8451 selector_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8453 struct selector *s = NULL;
8455 TAILQ_FOREACH(s, &p->selectors, node)
8463 selector_fields_check(struct rte_swx_pipeline *p,
8464 struct rte_swx_pipeline_selector_params *params,
8465 struct header **header)
8467 struct header *h0 = NULL;
8468 struct field *hf, *mf;
8471 /* Return if no selector fields. */
8472 if (!params->n_selector_fields || !params->selector_field_names)
8475 /* Check that all the selector fields either belong to the same header
8476 * or are all meta-data fields.
8478 hf = header_field_parse(p, params->selector_field_names[0], &h0);
8479 mf = metadata_field_parse(p, params->selector_field_names[0]);
8483 for (i = 1; i < params->n_selector_fields; i++)
8487 hf = header_field_parse(p, params->selector_field_names[i], &h);
8488 if (!hf || (h->id != h0->id))
8491 mf = metadata_field_parse(p, params->selector_field_names[i]);
8496 /* Check that there are no duplicated match fields. */
8497 for (i = 0; i < params->n_selector_fields; i++) {
8498 const char *field_name = params->selector_field_names[i];
8501 for (j = i + 1; j < params->n_selector_fields; j++)
8502 if (!strcmp(params->selector_field_names[j], field_name))
8514 rte_swx_pipeline_selector_config(struct rte_swx_pipeline *p,
8516 struct rte_swx_pipeline_selector_params *params)
8519 struct header *selector_header = NULL;
8520 struct field *group_id_field, *member_id_field;
8526 CHECK_NAME(name, EINVAL);
8527 CHECK(!table_find(p, name), EEXIST);
8528 CHECK(!selector_find(p, name), EEXIST);
8529 CHECK(!learner_find(p, name), EEXIST);
8531 CHECK(params, EINVAL);
8533 CHECK_NAME(params->group_id_field_name, EINVAL);
8534 group_id_field = metadata_field_parse(p, params->group_id_field_name);
8535 CHECK(group_id_field, EINVAL);
8537 for (i = 0; i < params->n_selector_fields; i++) {
8538 const char *field_name = params->selector_field_names[i];
8540 CHECK_NAME(field_name, EINVAL);
8542 status = selector_fields_check(p, params, &selector_header);
8546 CHECK_NAME(params->member_id_field_name, EINVAL);
8547 member_id_field = metadata_field_parse(p, params->member_id_field_name);
8548 CHECK(member_id_field, EINVAL);
8550 CHECK(params->n_groups_max, EINVAL);
8552 CHECK(params->n_members_per_group_max, EINVAL);
8554 /* Memory allocation. */
8555 s = calloc(1, sizeof(struct selector));
8561 s->selector_fields = calloc(params->n_selector_fields, sizeof(struct field *));
8562 if (!s->selector_fields) {
8567 /* Node initialization. */
8568 strcpy(s->name, name);
8570 s->group_id_field = group_id_field;
8572 for (i = 0; i < params->n_selector_fields; i++) {
8573 const char *field_name = params->selector_field_names[i];
8575 s->selector_fields[i] = selector_header ?
8576 header_field_parse(p, field_name, NULL) :
8577 metadata_field_parse(p, field_name);
8580 s->n_selector_fields = params->n_selector_fields;
8582 s->selector_header = selector_header;
8584 s->member_id_field = member_id_field;
8586 s->n_groups_max = params->n_groups_max;
8588 s->n_members_per_group_max = params->n_members_per_group_max;
8590 s->id = p->n_selectors;
8592 /* Node add to tailq. */
8593 TAILQ_INSERT_TAIL(&p->selectors, s, node);
8602 free(s->selector_fields);
8610 selector_params_free(struct rte_swx_table_selector_params *params)
8615 free(params->selector_mask);
8620 static struct rte_swx_table_selector_params *
8621 selector_table_params_get(struct selector *s)
8623 struct rte_swx_table_selector_params *params = NULL;
8624 struct field *first, *last;
8627 /* Memory allocation. */
8628 params = calloc(1, sizeof(struct rte_swx_table_selector_params));
8633 params->group_id_offset = s->group_id_field->offset / 8;
8635 /* Find first (smallest offset) and last (biggest offset) selector fields. */
8636 first = s->selector_fields[0];
8637 last = s->selector_fields[0];
8639 for (i = 0; i < s->n_selector_fields; i++) {
8640 struct field *f = s->selector_fields[i];
8642 if (f->offset < first->offset)
8645 if (f->offset > last->offset)
8649 /* Selector offset and size. */
8650 params->selector_offset = first->offset / 8;
8651 params->selector_size = (last->offset + last->n_bits - first->offset) / 8;
8653 /* Memory allocation. */
8654 params->selector_mask = calloc(1, params->selector_size);
8655 if (!params->selector_mask)
8658 /* Selector mask. */
8659 for (i = 0; i < s->n_selector_fields; i++) {
8660 struct field *f = s->selector_fields[i];
8661 uint32_t start = (f->offset - first->offset) / 8;
8662 size_t size = f->n_bits / 8;
8664 memset(¶ms->selector_mask[start], 0xFF, size);
8668 params->member_id_offset = s->member_id_field->offset / 8;
8670 /* Maximum number of groups. */
8671 params->n_groups_max = s->n_groups_max;
8673 /* Maximum number of members per group. */
8674 params->n_members_per_group_max = s->n_members_per_group_max;
8679 selector_params_free(params);
8684 selector_build_free(struct rte_swx_pipeline *p)
8688 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8689 struct thread *t = &p->threads[i];
8695 for (j = 0; j < p->n_selectors; j++) {
8696 struct selector_runtime *r = &t->selectors[j];
8702 t->selectors = NULL;
8705 free(p->selector_stats);
8706 p->selector_stats = NULL;
8710 selector_build(struct rte_swx_pipeline *p)
8715 /* Per pipeline: selector statistics. */
8716 p->selector_stats = calloc(p->n_selectors, sizeof(struct selector_statistics));
8717 if (!p->selector_stats) {
8722 /* Per thread: selector run-time. */
8723 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8724 struct thread *t = &p->threads[i];
8727 t->selectors = calloc(p->n_selectors, sizeof(struct selector_runtime));
8728 if (!t->selectors) {
8733 TAILQ_FOREACH(s, &p->selectors, node) {
8734 struct selector_runtime *r = &t->selectors[s->id];
8738 size = rte_swx_table_selector_mailbox_size_get();
8740 r->mailbox = calloc(1, size);
8747 /* r->group_id_buffer. */
8748 r->group_id_buffer = &t->structs[p->metadata_struct_id];
8750 /* r->selector_buffer. */
8751 r->selector_buffer = s->selector_header ?
8752 &t->structs[s->selector_header->struct_id] :
8753 &t->structs[p->metadata_struct_id];
8755 /* r->member_id_buffer. */
8756 r->member_id_buffer = &t->structs[p->metadata_struct_id];
8763 selector_build_free(p);
8768 selector_free(struct rte_swx_pipeline *p)
8770 selector_build_free(p);
8772 /* Selector tables. */
8774 struct selector *elem;
8776 elem = TAILQ_FIRST(&p->selectors);
8780 TAILQ_REMOVE(&p->selectors, elem, node);
8781 free(elem->selector_fields);
8789 static struct learner *
8790 learner_find(struct rte_swx_pipeline *p, const char *name)
8794 TAILQ_FOREACH(l, &p->learners, node)
8795 if (!strcmp(l->name, name))
8801 static struct learner *
8802 learner_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8804 struct learner *l = NULL;
8806 TAILQ_FOREACH(l, &p->learners, node)
8814 learner_match_fields_check(struct rte_swx_pipeline *p,
8815 struct rte_swx_pipeline_learner_params *params,
8816 struct header **header)
8818 struct header *h0 = NULL;
8819 struct field *hf, *mf;
8822 /* Return if no match fields. */
8823 if (!params->n_fields || !params->field_names)
8826 /* Check that all the match fields either belong to the same header
8827 * or are all meta-data fields.
8829 hf = header_field_parse(p, params->field_names[0], &h0);
8830 mf = metadata_field_parse(p, params->field_names[0]);
8834 for (i = 1; i < params->n_fields; i++)
8838 hf = header_field_parse(p, params->field_names[i], &h);
8839 if (!hf || (h->id != h0->id))
8842 mf = metadata_field_parse(p, params->field_names[i]);
8847 /* Check that there are no duplicated match fields. */
8848 for (i = 0; i < params->n_fields; i++) {
8849 const char *field_name = params->field_names[i];
8852 for (j = i + 1; j < params->n_fields; j++)
8853 if (!strcmp(params->field_names[j], field_name))
8865 learner_action_args_check(struct rte_swx_pipeline *p, struct action *a, const char *mf_name)
8867 struct struct_type *mst = p->metadata_st, *ast = a->st;
8868 struct field *mf, *af;
8878 /* Check that mf_name is the name of a valid meta-data field. */
8879 CHECK_NAME(mf_name, EINVAL);
8880 mf = metadata_field_parse(p, mf_name);
8883 /* Check that there are enough meta-data fields, starting with the mf_name field, to cover
8884 * all the action arguments.
8886 mf_pos = mf - mst->fields;
8887 CHECK(mst->n_fields - mf_pos >= ast->n_fields, EINVAL);
8889 /* Check that the size of each of the identified meta-data fields matches exactly the size
8890 * of the corresponding action argument.
8892 for (i = 0; i < ast->n_fields; i++) {
8893 mf = &mst->fields[mf_pos + i];
8894 af = &ast->fields[i];
8896 CHECK(mf->n_bits == af->n_bits, EINVAL);
8903 learner_action_learning_check(struct rte_swx_pipeline *p,
8904 struct action *action,
8905 const char **action_names,
8910 /* For each "learn" instruction of the current action, check that the learned action (i.e.
8911 * the action passed as argument to the "learn" instruction) is also enabled for the
8912 * current learner table.
8914 for (i = 0; i < action->n_instructions; i++) {
8915 struct instruction *instr = &action->instructions[i];
8916 uint32_t found = 0, j;
8918 if (instr->type != INSTR_LEARNER_LEARN)
8921 for (j = 0; j < n_actions; j++) {
8924 a = action_find(p, action_names[j]);
8928 if (a->id == instr->learn.action_id)
8940 rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p,
8942 struct rte_swx_pipeline_learner_params *params,
8946 struct learner *l = NULL;
8947 struct action *default_action;
8948 struct header *header = NULL;
8949 uint32_t action_data_size_max = 0, i;
8954 CHECK_NAME(name, EINVAL);
8955 CHECK(!table_find(p, name), EEXIST);
8956 CHECK(!selector_find(p, name), EEXIST);
8957 CHECK(!learner_find(p, name), EEXIST);
8959 CHECK(params, EINVAL);
8962 status = learner_match_fields_check(p, params, &header);
8966 /* Action checks. */
8967 CHECK(params->n_actions, EINVAL);
8969 CHECK(params->action_names, EINVAL);
8970 for (i = 0; i < params->n_actions; i++) {
8971 const char *action_name = params->action_names[i];
8972 const char *action_field_name = params->action_field_names[i];
8974 uint32_t action_data_size;
8976 CHECK_NAME(action_name, EINVAL);
8978 a = action_find(p, action_name);
8981 status = learner_action_args_check(p, a, action_field_name);
8985 status = learner_action_learning_check(p,
8987 params->action_names,
8992 action_data_size = a->st ? a->st->n_bits / 8 : 0;
8993 if (action_data_size > action_data_size_max)
8994 action_data_size_max = action_data_size;
8997 CHECK_NAME(params->default_action_name, EINVAL);
8998 for (i = 0; i < p->n_actions; i++)
8999 if (!strcmp(params->action_names[i],
9000 params->default_action_name))
9002 CHECK(i < params->n_actions, EINVAL);
9004 default_action = action_find(p, params->default_action_name);
9005 CHECK((default_action->st && params->default_action_data) ||
9006 !params->default_action_data, EINVAL);
9008 /* Any other checks. */
9009 CHECK(size, EINVAL);
9010 CHECK(timeout, EINVAL);
9012 /* Memory allocation. */
9013 l = calloc(1, sizeof(struct learner));
9017 l->fields = calloc(params->n_fields, sizeof(struct field *));
9021 l->actions = calloc(params->n_actions, sizeof(struct action *));
9025 l->action_arg = calloc(params->n_actions, sizeof(struct field *));
9029 if (action_data_size_max) {
9030 l->default_action_data = calloc(1, action_data_size_max);
9031 if (!l->default_action_data)
9035 /* Node initialization. */
9036 strcpy(l->name, name);
9038 for (i = 0; i < params->n_fields; i++) {
9039 const char *field_name = params->field_names[i];
9041 l->fields[i] = header ?
9042 header_field_parse(p, field_name, NULL) :
9043 metadata_field_parse(p, field_name);
9046 l->n_fields = params->n_fields;
9050 for (i = 0; i < params->n_actions; i++) {
9051 const char *mf_name = params->action_field_names[i];
9053 l->actions[i] = action_find(p, params->action_names[i]);
9055 l->action_arg[i] = mf_name ? metadata_field_parse(p, mf_name) : NULL;
9058 l->default_action = default_action;
9060 if (default_action->st)
9061 memcpy(l->default_action_data,
9062 params->default_action_data,
9063 default_action->st->n_bits / 8);
9065 l->n_actions = params->n_actions;
9067 l->default_action_is_const = params->default_action_is_const;
9069 l->action_data_size_max = action_data_size_max;
9073 l->timeout = timeout;
9075 l->id = p->n_learners;
9077 /* Node add to tailq. */
9078 TAILQ_INSERT_TAIL(&p->learners, l, node);
9087 free(l->action_arg);
9096 learner_params_free(struct rte_swx_table_learner_params *params)
9101 free(params->key_mask0);
9106 static struct rte_swx_table_learner_params *
9107 learner_params_get(struct learner *l)
9109 struct rte_swx_table_learner_params *params = NULL;
9110 struct field *first, *last;
9113 /* Memory allocation. */
9114 params = calloc(1, sizeof(struct rte_swx_table_learner_params));
9118 /* Find first (smallest offset) and last (biggest offset) match fields. */
9119 first = l->fields[0];
9120 last = l->fields[0];
9122 for (i = 0; i < l->n_fields; i++) {
9123 struct field *f = l->fields[i];
9125 if (f->offset < first->offset)
9128 if (f->offset > last->offset)
9132 /* Key offset and size. */
9133 params->key_offset = first->offset / 8;
9134 params->key_size = (last->offset + last->n_bits - first->offset) / 8;
9136 /* Memory allocation. */
9137 params->key_mask0 = calloc(1, params->key_size);
9138 if (!params->key_mask0)
9142 for (i = 0; i < l->n_fields; i++) {
9143 struct field *f = l->fields[i];
9144 uint32_t start = (f->offset - first->offset) / 8;
9145 size_t size = f->n_bits / 8;
9147 memset(¶ms->key_mask0[start], 0xFF, size);
9150 /* Action data size. */
9151 params->action_data_size = l->action_data_size_max;
9153 /* Maximum number of keys. */
9154 params->n_keys_max = l->size;
9157 params->key_timeout = l->timeout;
9162 learner_params_free(params);
9167 learner_build_free(struct rte_swx_pipeline *p)
9171 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9172 struct thread *t = &p->threads[i];
9178 for (j = 0; j < p->n_learners; j++) {
9179 struct learner_runtime *r = &t->learners[j];
9182 free(r->action_data);
9189 if (p->learner_stats) {
9190 for (i = 0; i < p->n_learners; i++)
9191 free(p->learner_stats[i].n_pkts_action);
9193 free(p->learner_stats);
9198 learner_build(struct rte_swx_pipeline *p)
9203 /* Per pipeline: learner statistics. */
9204 p->learner_stats = calloc(p->n_learners, sizeof(struct learner_statistics));
9205 CHECK(p->learner_stats, ENOMEM);
9207 for (i = 0; i < p->n_learners; i++) {
9208 p->learner_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
9209 CHECK(p->learner_stats[i].n_pkts_action, ENOMEM);
9212 /* Per thread: learner run-time. */
9213 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9214 struct thread *t = &p->threads[i];
9217 t->learners = calloc(p->n_learners, sizeof(struct learner_runtime));
9223 TAILQ_FOREACH(l, &p->learners, node) {
9224 struct learner_runtime *r = &t->learners[l->id];
9229 size = rte_swx_table_learner_mailbox_size_get();
9231 r->mailbox = calloc(1, size);
9239 r->key = l->header ?
9240 &t->structs[l->header->struct_id] :
9241 &t->structs[p->metadata_struct_id];
9243 /* r->action_data. */
9244 r->action_data = calloc(p->n_actions, sizeof(uint8_t *));
9245 if (!r->action_data) {
9250 for (j = 0; j < l->n_actions; j++) {
9251 struct action *a = l->actions[j];
9252 struct field *mf = l->action_arg[j];
9253 uint8_t *m = t->structs[p->metadata_struct_id];
9255 r->action_data[a->id] = mf ? &m[mf->offset / 8] : NULL;
9263 learner_build_free(p);
9268 learner_free(struct rte_swx_pipeline *p)
9270 learner_build_free(p);
9272 /* Learner tables. */
9276 l = TAILQ_FIRST(&p->learners);
9280 TAILQ_REMOVE(&p->learners, l, node);
9283 free(l->action_arg);
9284 free(l->default_action_data);
9293 table_state_build(struct rte_swx_pipeline *p)
9295 struct table *table;
9299 p->table_state = calloc(p->n_tables + p->n_selectors,
9300 sizeof(struct rte_swx_table_state));
9301 CHECK(p->table_state, ENOMEM);
9303 TAILQ_FOREACH(table, &p->tables, node) {
9304 struct rte_swx_table_state *ts = &p->table_state[table->id];
9307 struct rte_swx_table_params *params;
9310 params = table_params_get(table);
9311 CHECK(params, ENOMEM);
9313 ts->obj = table->type->ops.create(params,
9318 table_params_free(params);
9319 CHECK(ts->obj, ENODEV);
9322 /* ts->default_action_data. */
9323 if (table->action_data_size_max) {
9324 ts->default_action_data =
9325 malloc(table->action_data_size_max);
9326 CHECK(ts->default_action_data, ENOMEM);
9328 memcpy(ts->default_action_data,
9329 table->default_action_data,
9330 table->action_data_size_max);
9333 /* ts->default_action_id. */
9334 ts->default_action_id = table->default_action->id;
9337 TAILQ_FOREACH(s, &p->selectors, node) {
9338 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + s->id];
9339 struct rte_swx_table_selector_params *params;
9342 params = selector_table_params_get(s);
9343 CHECK(params, ENOMEM);
9345 ts->obj = rte_swx_table_selector_create(params, NULL, p->numa_node);
9347 selector_params_free(params);
9348 CHECK(ts->obj, ENODEV);
9351 TAILQ_FOREACH(l, &p->learners, node) {
9352 struct rte_swx_table_state *ts = &p->table_state[p->n_tables +
9353 p->n_selectors + l->id];
9354 struct rte_swx_table_learner_params *params;
9357 params = learner_params_get(l);
9358 CHECK(params, ENOMEM);
9360 ts->obj = rte_swx_table_learner_create(params, p->numa_node);
9361 learner_params_free(params);
9362 CHECK(ts->obj, ENODEV);
9364 /* ts->default_action_data. */
9365 if (l->action_data_size_max) {
9366 ts->default_action_data = malloc(l->action_data_size_max);
9367 CHECK(ts->default_action_data, ENOMEM);
9369 memcpy(ts->default_action_data,
9370 l->default_action_data,
9371 l->action_data_size_max);
9374 /* ts->default_action_id. */
9375 ts->default_action_id = l->default_action->id;
9382 table_state_build_free(struct rte_swx_pipeline *p)
9386 if (!p->table_state)
9389 for (i = 0; i < p->n_tables; i++) {
9390 struct rte_swx_table_state *ts = &p->table_state[i];
9391 struct table *table = table_find_by_id(p, i);
9394 if (table->type && ts->obj)
9395 table->type->ops.free(ts->obj);
9397 /* ts->default_action_data. */
9398 free(ts->default_action_data);
9401 for (i = 0; i < p->n_selectors; i++) {
9402 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + i];
9406 rte_swx_table_selector_free(ts->obj);
9409 for (i = 0; i < p->n_learners; i++) {
9410 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + p->n_selectors + i];
9414 rte_swx_table_learner_free(ts->obj);
9416 /* ts->default_action_data. */
9417 free(ts->default_action_data);
9420 free(p->table_state);
9421 p->table_state = NULL;
9425 table_state_free(struct rte_swx_pipeline *p)
9427 table_state_build_free(p);
9433 static struct regarray *
9434 regarray_find(struct rte_swx_pipeline *p, const char *name)
9436 struct regarray *elem;
9438 TAILQ_FOREACH(elem, &p->regarrays, node)
9439 if (!strcmp(elem->name, name))
9445 static struct regarray *
9446 regarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9448 struct regarray *elem = NULL;
9450 TAILQ_FOREACH(elem, &p->regarrays, node)
9458 rte_swx_pipeline_regarray_config(struct rte_swx_pipeline *p,
9467 CHECK_NAME(name, EINVAL);
9468 CHECK(!regarray_find(p, name), EEXIST);
9470 CHECK(size, EINVAL);
9471 size = rte_align32pow2(size);
9473 /* Memory allocation. */
9474 r = calloc(1, sizeof(struct regarray));
9477 /* Node initialization. */
9478 strcpy(r->name, name);
9479 r->init_val = init_val;
9481 r->id = p->n_regarrays;
9483 /* Node add to tailq. */
9484 TAILQ_INSERT_TAIL(&p->regarrays, r, node);
9491 regarray_build(struct rte_swx_pipeline *p)
9493 struct regarray *regarray;
9495 if (!p->n_regarrays)
9498 p->regarray_runtime = calloc(p->n_regarrays, sizeof(struct regarray_runtime));
9499 CHECK(p->regarray_runtime, ENOMEM);
9501 TAILQ_FOREACH(regarray, &p->regarrays, node) {
9502 struct regarray_runtime *r = &p->regarray_runtime[regarray->id];
9505 r->regarray = env_malloc(regarray->size * sizeof(uint64_t),
9506 RTE_CACHE_LINE_SIZE,
9508 CHECK(r->regarray, ENOMEM);
9510 if (regarray->init_val)
9511 for (i = 0; i < regarray->size; i++)
9512 r->regarray[i] = regarray->init_val;
9514 r->size_mask = regarray->size - 1;
9521 regarray_build_free(struct rte_swx_pipeline *p)
9525 if (!p->regarray_runtime)
9528 for (i = 0; i < p->n_regarrays; i++) {
9529 struct regarray *regarray = regarray_find_by_id(p, i);
9530 struct regarray_runtime *r = &p->regarray_runtime[i];
9532 env_free(r->regarray, regarray->size * sizeof(uint64_t));
9535 free(p->regarray_runtime);
9536 p->regarray_runtime = NULL;
9540 regarray_free(struct rte_swx_pipeline *p)
9542 regarray_build_free(p);
9545 struct regarray *elem;
9547 elem = TAILQ_FIRST(&p->regarrays);
9551 TAILQ_REMOVE(&p->regarrays, elem, node);
9559 static struct meter_profile *
9560 meter_profile_find(struct rte_swx_pipeline *p, const char *name)
9562 struct meter_profile *elem;
9564 TAILQ_FOREACH(elem, &p->meter_profiles, node)
9565 if (!strcmp(elem->name, name))
9571 static struct metarray *
9572 metarray_find(struct rte_swx_pipeline *p, const char *name)
9574 struct metarray *elem;
9576 TAILQ_FOREACH(elem, &p->metarrays, node)
9577 if (!strcmp(elem->name, name))
9583 static struct metarray *
9584 metarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9586 struct metarray *elem = NULL;
9588 TAILQ_FOREACH(elem, &p->metarrays, node)
9596 rte_swx_pipeline_metarray_config(struct rte_swx_pipeline *p,
9604 CHECK_NAME(name, EINVAL);
9605 CHECK(!metarray_find(p, name), EEXIST);
9607 CHECK(size, EINVAL);
9608 size = rte_align32pow2(size);
9610 /* Memory allocation. */
9611 m = calloc(1, sizeof(struct metarray));
9614 /* Node initialization. */
9615 strcpy(m->name, name);
9617 m->id = p->n_metarrays;
9619 /* Node add to tailq. */
9620 TAILQ_INSERT_TAIL(&p->metarrays, m, node);
9626 struct meter_profile meter_profile_default = {
9635 .cir_bytes_per_period = 1,
9637 .pir_bytes_per_period = 1,
9644 meter_init(struct meter *m)
9646 memset(m, 0, sizeof(struct meter));
9647 rte_meter_trtcm_config(&m->m, &meter_profile_default.profile);
9648 m->profile = &meter_profile_default;
9649 m->color_mask = RTE_COLOR_GREEN;
9651 meter_profile_default.n_users++;
9655 metarray_build(struct rte_swx_pipeline *p)
9659 if (!p->n_metarrays)
9662 p->metarray_runtime = calloc(p->n_metarrays, sizeof(struct metarray_runtime));
9663 CHECK(p->metarray_runtime, ENOMEM);
9665 TAILQ_FOREACH(m, &p->metarrays, node) {
9666 struct metarray_runtime *r = &p->metarray_runtime[m->id];
9669 r->metarray = env_malloc(m->size * sizeof(struct meter),
9670 RTE_CACHE_LINE_SIZE,
9672 CHECK(r->metarray, ENOMEM);
9674 for (i = 0; i < m->size; i++)
9675 meter_init(&r->metarray[i]);
9677 r->size_mask = m->size - 1;
9684 metarray_build_free(struct rte_swx_pipeline *p)
9688 if (!p->metarray_runtime)
9691 for (i = 0; i < p->n_metarrays; i++) {
9692 struct metarray *m = metarray_find_by_id(p, i);
9693 struct metarray_runtime *r = &p->metarray_runtime[i];
9695 env_free(r->metarray, m->size * sizeof(struct meter));
9698 free(p->metarray_runtime);
9699 p->metarray_runtime = NULL;
9703 metarray_free(struct rte_swx_pipeline *p)
9705 metarray_build_free(p);
9709 struct metarray *elem;
9711 elem = TAILQ_FIRST(&p->metarrays);
9715 TAILQ_REMOVE(&p->metarrays, elem, node);
9719 /* Meter profiles. */
9721 struct meter_profile *elem;
9723 elem = TAILQ_FIRST(&p->meter_profiles);
9727 TAILQ_REMOVE(&p->meter_profiles, elem, node);
9736 rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
9738 struct rte_swx_pipeline *pipeline;
9740 /* Check input parameters. */
9743 /* Memory allocation. */
9744 pipeline = calloc(1, sizeof(struct rte_swx_pipeline));
9745 CHECK(pipeline, ENOMEM);
9747 /* Initialization. */
9748 TAILQ_INIT(&pipeline->struct_types);
9749 TAILQ_INIT(&pipeline->port_in_types);
9750 TAILQ_INIT(&pipeline->ports_in);
9751 TAILQ_INIT(&pipeline->port_out_types);
9752 TAILQ_INIT(&pipeline->ports_out);
9753 TAILQ_INIT(&pipeline->extern_types);
9754 TAILQ_INIT(&pipeline->extern_objs);
9755 TAILQ_INIT(&pipeline->extern_funcs);
9756 TAILQ_INIT(&pipeline->headers);
9757 TAILQ_INIT(&pipeline->actions);
9758 TAILQ_INIT(&pipeline->table_types);
9759 TAILQ_INIT(&pipeline->tables);
9760 TAILQ_INIT(&pipeline->selectors);
9761 TAILQ_INIT(&pipeline->learners);
9762 TAILQ_INIT(&pipeline->regarrays);
9763 TAILQ_INIT(&pipeline->meter_profiles);
9764 TAILQ_INIT(&pipeline->metarrays);
9766 pipeline->n_structs = 1; /* Struct 0 is reserved for action_data. */
9767 pipeline->numa_node = numa_node;
9774 rte_swx_pipeline_free(struct rte_swx_pipeline *p)
9779 free(p->instructions);
9783 table_state_free(p);
9790 extern_func_free(p);
9800 rte_swx_pipeline_instructions_config(struct rte_swx_pipeline *p,
9801 const char **instructions,
9802 uint32_t n_instructions)
9807 err = instruction_config(p, NULL, instructions, n_instructions);
9811 /* Thread instruction pointer reset. */
9812 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9813 struct thread *t = &p->threads[i];
9815 thread_ip_reset(p, t);
9822 rte_swx_pipeline_build(struct rte_swx_pipeline *p)
9827 CHECK(p->build_done == 0, EEXIST);
9829 status = port_in_build(p);
9833 status = port_out_build(p);
9837 status = struct_build(p);
9841 status = extern_obj_build(p);
9845 status = extern_func_build(p);
9849 status = header_build(p);
9853 status = metadata_build(p);
9857 status = action_build(p);
9861 status = table_build(p);
9865 status = selector_build(p);
9869 status = learner_build(p);
9873 status = table_state_build(p);
9877 status = regarray_build(p);
9881 status = metarray_build(p);
9889 metarray_build_free(p);
9890 regarray_build_free(p);
9891 table_state_build_free(p);
9892 learner_build_free(p);
9893 selector_build_free(p);
9894 table_build_free(p);
9895 action_build_free(p);
9896 metadata_build_free(p);
9897 header_build_free(p);
9898 extern_func_build_free(p);
9899 extern_obj_build_free(p);
9900 port_out_build_free(p);
9901 port_in_build_free(p);
9902 struct_build_free(p);
9908 rte_swx_pipeline_run(struct rte_swx_pipeline *p, uint32_t n_instructions)
9912 for (i = 0; i < n_instructions; i++)
9917 rte_swx_pipeline_flush(struct rte_swx_pipeline *p)
9921 for (i = 0; i < p->n_ports_out; i++) {
9922 struct port_out_runtime *port = &p->out[i];
9925 port->flush(port->obj);
9933 rte_swx_ctl_pipeline_info_get(struct rte_swx_pipeline *p,
9934 struct rte_swx_ctl_pipeline_info *pipeline)
9936 struct action *action;
9937 struct table *table;
9938 uint32_t n_actions = 0, n_tables = 0;
9940 if (!p || !pipeline)
9943 TAILQ_FOREACH(action, &p->actions, node)
9946 TAILQ_FOREACH(table, &p->tables, node)
9949 pipeline->n_ports_in = p->n_ports_in;
9950 pipeline->n_ports_out = p->n_ports_out;
9951 pipeline->n_actions = n_actions;
9952 pipeline->n_tables = n_tables;
9953 pipeline->n_selectors = p->n_selectors;
9954 pipeline->n_learners = p->n_learners;
9955 pipeline->n_regarrays = p->n_regarrays;
9956 pipeline->n_metarrays = p->n_metarrays;
9962 rte_swx_ctl_pipeline_numa_node_get(struct rte_swx_pipeline *p, int *numa_node)
9964 if (!p || !numa_node)
9967 *numa_node = p->numa_node;
9972 rte_swx_ctl_action_info_get(struct rte_swx_pipeline *p,
9974 struct rte_swx_ctl_action_info *action)
9976 struct action *a = NULL;
9978 if (!p || (action_id >= p->n_actions) || !action)
9981 a = action_find_by_id(p, action_id);
9985 strcpy(action->name, a->name);
9986 action->n_args = a->st ? a->st->n_fields : 0;
9991 rte_swx_ctl_action_arg_info_get(struct rte_swx_pipeline *p,
9993 uint32_t action_arg_id,
9994 struct rte_swx_ctl_action_arg_info *action_arg)
9996 struct action *a = NULL;
9997 struct field *arg = NULL;
9999 if (!p || (action_id >= p->n_actions) || !action_arg)
10002 a = action_find_by_id(p, action_id);
10003 if (!a || !a->st || (action_arg_id >= a->st->n_fields))
10006 arg = &a->st->fields[action_arg_id];
10007 strcpy(action_arg->name, arg->name);
10008 action_arg->n_bits = arg->n_bits;
10009 action_arg->is_network_byte_order = a->args_endianness[action_arg_id];
10015 rte_swx_ctl_table_info_get(struct rte_swx_pipeline *p,
10017 struct rte_swx_ctl_table_info *table)
10019 struct table *t = NULL;
10024 t = table_find_by_id(p, table_id);
10028 strcpy(table->name, t->name);
10029 strcpy(table->args, t->args);
10030 table->n_match_fields = t->n_fields;
10031 table->n_actions = t->n_actions;
10032 table->default_action_is_const = t->default_action_is_const;
10033 table->size = t->size;
10038 rte_swx_ctl_table_match_field_info_get(struct rte_swx_pipeline *p,
10040 uint32_t match_field_id,
10041 struct rte_swx_ctl_table_match_field_info *match_field)
10044 struct match_field *f;
10046 if (!p || (table_id >= p->n_tables) || !match_field)
10049 t = table_find_by_id(p, table_id);
10050 if (!t || (match_field_id >= t->n_fields))
10053 f = &t->fields[match_field_id];
10054 match_field->match_type = f->match_type;
10055 match_field->is_header = t->header ? 1 : 0;
10056 match_field->n_bits = f->field->n_bits;
10057 match_field->offset = f->field->offset;
10063 rte_swx_ctl_table_action_info_get(struct rte_swx_pipeline *p,
10065 uint32_t table_action_id,
10066 struct rte_swx_ctl_table_action_info *table_action)
10070 if (!p || (table_id >= p->n_tables) || !table_action)
10073 t = table_find_by_id(p, table_id);
10074 if (!t || (table_action_id >= t->n_actions))
10077 table_action->action_id = t->actions[table_action_id]->id;
10083 rte_swx_ctl_table_ops_get(struct rte_swx_pipeline *p,
10085 struct rte_swx_table_ops *table_ops,
10090 if (!p || (table_id >= p->n_tables))
10093 t = table_find_by_id(p, table_id);
10099 memcpy(table_ops, &t->type->ops, sizeof(*table_ops));
10109 rte_swx_ctl_selector_info_get(struct rte_swx_pipeline *p,
10110 uint32_t selector_id,
10111 struct rte_swx_ctl_selector_info *selector)
10113 struct selector *s = NULL;
10115 if (!p || !selector)
10118 s = selector_find_by_id(p, selector_id);
10122 strcpy(selector->name, s->name);
10124 selector->n_selector_fields = s->n_selector_fields;
10125 selector->n_groups_max = s->n_groups_max;
10126 selector->n_members_per_group_max = s->n_members_per_group_max;
10132 rte_swx_ctl_selector_group_id_field_info_get(struct rte_swx_pipeline *p,
10133 uint32_t selector_id,
10134 struct rte_swx_ctl_table_match_field_info *field)
10136 struct selector *s;
10138 if (!p || (selector_id >= p->n_selectors) || !field)
10141 s = selector_find_by_id(p, selector_id);
10145 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10146 field->is_header = 0;
10147 field->n_bits = s->group_id_field->n_bits;
10148 field->offset = s->group_id_field->offset;
10154 rte_swx_ctl_selector_field_info_get(struct rte_swx_pipeline *p,
10155 uint32_t selector_id,
10156 uint32_t selector_field_id,
10157 struct rte_swx_ctl_table_match_field_info *field)
10159 struct selector *s;
10162 if (!p || (selector_id >= p->n_selectors) || !field)
10165 s = selector_find_by_id(p, selector_id);
10166 if (!s || (selector_field_id >= s->n_selector_fields))
10169 f = s->selector_fields[selector_field_id];
10170 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10171 field->is_header = s->selector_header ? 1 : 0;
10172 field->n_bits = f->n_bits;
10173 field->offset = f->offset;
10179 rte_swx_ctl_selector_member_id_field_info_get(struct rte_swx_pipeline *p,
10180 uint32_t selector_id,
10181 struct rte_swx_ctl_table_match_field_info *field)
10183 struct selector *s;
10185 if (!p || (selector_id >= p->n_selectors) || !field)
10188 s = selector_find_by_id(p, selector_id);
10192 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10193 field->is_header = 0;
10194 field->n_bits = s->member_id_field->n_bits;
10195 field->offset = s->member_id_field->offset;
10201 rte_swx_ctl_learner_info_get(struct rte_swx_pipeline *p,
10202 uint32_t learner_id,
10203 struct rte_swx_ctl_learner_info *learner)
10205 struct learner *l = NULL;
10207 if (!p || !learner)
10210 l = learner_find_by_id(p, learner_id);
10214 strcpy(learner->name, l->name);
10216 learner->n_match_fields = l->n_fields;
10217 learner->n_actions = l->n_actions;
10218 learner->default_action_is_const = l->default_action_is_const;
10219 learner->size = l->size;
10225 rte_swx_ctl_learner_match_field_info_get(struct rte_swx_pipeline *p,
10226 uint32_t learner_id,
10227 uint32_t match_field_id,
10228 struct rte_swx_ctl_table_match_field_info *match_field)
10233 if (!p || (learner_id >= p->n_learners) || !match_field)
10236 l = learner_find_by_id(p, learner_id);
10237 if (!l || (match_field_id >= l->n_fields))
10240 f = l->fields[match_field_id];
10241 match_field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10242 match_field->is_header = l->header ? 1 : 0;
10243 match_field->n_bits = f->n_bits;
10244 match_field->offset = f->offset;
10250 rte_swx_ctl_learner_action_info_get(struct rte_swx_pipeline *p,
10251 uint32_t learner_id,
10252 uint32_t learner_action_id,
10253 struct rte_swx_ctl_table_action_info *learner_action)
10257 if (!p || (learner_id >= p->n_learners) || !learner_action)
10260 l = learner_find_by_id(p, learner_id);
10261 if (!l || (learner_action_id >= l->n_actions))
10264 learner_action->action_id = l->actions[learner_action_id]->id;
10270 rte_swx_pipeline_table_state_get(struct rte_swx_pipeline *p,
10271 struct rte_swx_table_state **table_state)
10273 if (!p || !table_state || !p->build_done)
10276 *table_state = p->table_state;
10281 rte_swx_pipeline_table_state_set(struct rte_swx_pipeline *p,
10282 struct rte_swx_table_state *table_state)
10284 if (!p || !table_state || !p->build_done)
10287 p->table_state = table_state;
10292 rte_swx_ctl_pipeline_port_in_stats_read(struct rte_swx_pipeline *p,
10294 struct rte_swx_port_in_stats *stats)
10296 struct port_in *port;
10301 port = port_in_find(p, port_id);
10305 port->type->ops.stats_read(port->obj, stats);
10310 rte_swx_ctl_pipeline_port_out_stats_read(struct rte_swx_pipeline *p,
10312 struct rte_swx_port_out_stats *stats)
10314 struct port_out *port;
10319 port = port_out_find(p, port_id);
10323 port->type->ops.stats_read(port->obj, stats);
10328 rte_swx_ctl_pipeline_table_stats_read(struct rte_swx_pipeline *p,
10329 const char *table_name,
10330 struct rte_swx_table_stats *stats)
10332 struct table *table;
10333 struct table_statistics *table_stats;
10335 if (!p || !table_name || !table_name[0] || !stats || !stats->n_pkts_action)
10338 table = table_find(p, table_name);
10342 table_stats = &p->table_stats[table->id];
10344 memcpy(stats->n_pkts_action,
10345 table_stats->n_pkts_action,
10346 p->n_actions * sizeof(uint64_t));
10348 stats->n_pkts_hit = table_stats->n_pkts_hit[1];
10349 stats->n_pkts_miss = table_stats->n_pkts_hit[0];
10355 rte_swx_ctl_pipeline_selector_stats_read(struct rte_swx_pipeline *p,
10356 const char *selector_name,
10357 struct rte_swx_pipeline_selector_stats *stats)
10359 struct selector *s;
10361 if (!p || !selector_name || !selector_name[0] || !stats)
10364 s = selector_find(p, selector_name);
10368 stats->n_pkts = p->selector_stats[s->id].n_pkts;
10374 rte_swx_ctl_pipeline_learner_stats_read(struct rte_swx_pipeline *p,
10375 const char *learner_name,
10376 struct rte_swx_learner_stats *stats)
10379 struct learner_statistics *learner_stats;
10381 if (!p || !learner_name || !learner_name[0] || !stats || !stats->n_pkts_action)
10384 l = learner_find(p, learner_name);
10388 learner_stats = &p->learner_stats[l->id];
10390 memcpy(stats->n_pkts_action,
10391 learner_stats->n_pkts_action,
10392 p->n_actions * sizeof(uint64_t));
10394 stats->n_pkts_hit = learner_stats->n_pkts_hit[1];
10395 stats->n_pkts_miss = learner_stats->n_pkts_hit[0];
10397 stats->n_pkts_learn_ok = learner_stats->n_pkts_learn[0];
10398 stats->n_pkts_learn_err = learner_stats->n_pkts_learn[1];
10400 stats->n_pkts_forget = learner_stats->n_pkts_forget;
10406 rte_swx_ctl_regarray_info_get(struct rte_swx_pipeline *p,
10407 uint32_t regarray_id,
10408 struct rte_swx_ctl_regarray_info *regarray)
10410 struct regarray *r;
10412 if (!p || !regarray)
10415 r = regarray_find_by_id(p, regarray_id);
10419 strcpy(regarray->name, r->name);
10420 regarray->size = r->size;
10425 rte_swx_ctl_pipeline_regarray_read(struct rte_swx_pipeline *p,
10426 const char *regarray_name,
10427 uint32_t regarray_index,
10430 struct regarray *regarray;
10431 struct regarray_runtime *r;
10433 if (!p || !regarray_name || !value)
10436 regarray = regarray_find(p, regarray_name);
10437 if (!regarray || (regarray_index >= regarray->size))
10440 r = &p->regarray_runtime[regarray->id];
10441 *value = r->regarray[regarray_index];
10446 rte_swx_ctl_pipeline_regarray_write(struct rte_swx_pipeline *p,
10447 const char *regarray_name,
10448 uint32_t regarray_index,
10451 struct regarray *regarray;
10452 struct regarray_runtime *r;
10454 if (!p || !regarray_name)
10457 regarray = regarray_find(p, regarray_name);
10458 if (!regarray || (regarray_index >= regarray->size))
10461 r = &p->regarray_runtime[regarray->id];
10462 r->regarray[regarray_index] = value;
10467 rte_swx_ctl_metarray_info_get(struct rte_swx_pipeline *p,
10468 uint32_t metarray_id,
10469 struct rte_swx_ctl_metarray_info *metarray)
10471 struct metarray *m;
10473 if (!p || !metarray)
10476 m = metarray_find_by_id(p, metarray_id);
10480 strcpy(metarray->name, m->name);
10481 metarray->size = m->size;
10486 rte_swx_ctl_meter_profile_add(struct rte_swx_pipeline *p,
10488 struct rte_meter_trtcm_params *params)
10490 struct meter_profile *mp;
10494 CHECK_NAME(name, EINVAL);
10495 CHECK(params, EINVAL);
10496 CHECK(!meter_profile_find(p, name), EEXIST);
10498 /* Node allocation. */
10499 mp = calloc(1, sizeof(struct meter_profile));
10502 /* Node initialization. */
10503 strcpy(mp->name, name);
10504 memcpy(&mp->params, params, sizeof(struct rte_meter_trtcm_params));
10505 status = rte_meter_trtcm_profile_config(&mp->profile, params);
10511 /* Node add to tailq. */
10512 TAILQ_INSERT_TAIL(&p->meter_profiles, mp, node);
10518 rte_swx_ctl_meter_profile_delete(struct rte_swx_pipeline *p,
10521 struct meter_profile *mp;
10524 CHECK_NAME(name, EINVAL);
10526 mp = meter_profile_find(p, name);
10528 CHECK(!mp->n_users, EBUSY);
10530 /* Remove node from tailq. */
10531 TAILQ_REMOVE(&p->meter_profiles, mp, node);
10538 rte_swx_ctl_meter_reset(struct rte_swx_pipeline *p,
10539 const char *metarray_name,
10540 uint32_t metarray_index)
10542 struct meter_profile *mp_old;
10543 struct metarray *metarray;
10544 struct metarray_runtime *metarray_runtime;
10548 CHECK_NAME(metarray_name, EINVAL);
10550 metarray = metarray_find(p, metarray_name);
10551 CHECK(metarray, EINVAL);
10552 CHECK(metarray_index < metarray->size, EINVAL);
10554 metarray_runtime = &p->metarray_runtime[metarray->id];
10555 m = &metarray_runtime->metarray[metarray_index];
10556 mp_old = m->profile;
10566 rte_swx_ctl_meter_set(struct rte_swx_pipeline *p,
10567 const char *metarray_name,
10568 uint32_t metarray_index,
10569 const char *profile_name)
10571 struct meter_profile *mp, *mp_old;
10572 struct metarray *metarray;
10573 struct metarray_runtime *metarray_runtime;
10577 CHECK_NAME(metarray_name, EINVAL);
10579 metarray = metarray_find(p, metarray_name);
10580 CHECK(metarray, EINVAL);
10581 CHECK(metarray_index < metarray->size, EINVAL);
10583 mp = meter_profile_find(p, profile_name);
10586 metarray_runtime = &p->metarray_runtime[metarray->id];
10587 m = &metarray_runtime->metarray[metarray_index];
10588 mp_old = m->profile;
10590 memset(m, 0, sizeof(struct meter));
10591 rte_meter_trtcm_config(&m->m, &mp->profile);
10593 m->color_mask = RTE_COLORS;
10602 rte_swx_ctl_meter_stats_read(struct rte_swx_pipeline *p,
10603 const char *metarray_name,
10604 uint32_t metarray_index,
10605 struct rte_swx_ctl_meter_stats *stats)
10607 struct metarray *metarray;
10608 struct metarray_runtime *metarray_runtime;
10612 CHECK_NAME(metarray_name, EINVAL);
10614 metarray = metarray_find(p, metarray_name);
10615 CHECK(metarray, EINVAL);
10616 CHECK(metarray_index < metarray->size, EINVAL);
10618 CHECK(stats, EINVAL);
10620 metarray_runtime = &p->metarray_runtime[metarray->id];
10621 m = &metarray_runtime->metarray[metarray_index];
10623 memcpy(stats->n_pkts, m->n_pkts, sizeof(m->n_pkts));
10624 memcpy(stats->n_bytes, m->n_bytes, sizeof(m->n_bytes));