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;
1956 uint32_t header_id = ip->valid.header_id;
1958 TRACE("[Thread %2u] validate header %u\n", p->thread_id, header_id);
1961 t->valid_headers = MASK64_BIT_SET(t->valid_headers, header_id);
1971 instr_hdr_invalidate_translate(struct rte_swx_pipeline *p,
1972 struct action *action __rte_unused,
1975 struct instruction *instr,
1976 struct instruction_data *data __rte_unused)
1980 CHECK(n_tokens == 2, EINVAL);
1982 h = header_parse(p, tokens[1]);
1985 instr->type = INSTR_HDR_INVALIDATE;
1986 instr->valid.header_id = h->id;
1991 instr_hdr_invalidate_exec(struct rte_swx_pipeline *p)
1993 struct thread *t = &p->threads[p->thread_id];
1994 struct instruction *ip = t->ip;
1995 uint32_t header_id = ip->valid.header_id;
1997 TRACE("[Thread %2u] invalidate header %u\n", p->thread_id, header_id);
2000 t->valid_headers = MASK64_BIT_CLR(t->valid_headers, header_id);
2009 static struct table *
2010 table_find(struct rte_swx_pipeline *p, const char *name);
2012 static struct selector *
2013 selector_find(struct rte_swx_pipeline *p, const char *name);
2015 static struct learner *
2016 learner_find(struct rte_swx_pipeline *p, const char *name);
2019 instr_table_translate(struct rte_swx_pipeline *p,
2020 struct action *action,
2023 struct instruction *instr,
2024 struct instruction_data *data __rte_unused)
2030 CHECK(!action, EINVAL);
2031 CHECK(n_tokens == 2, EINVAL);
2033 t = table_find(p, tokens[1]);
2035 instr->type = INSTR_TABLE;
2036 instr->table.table_id = t->id;
2040 s = selector_find(p, tokens[1]);
2042 instr->type = INSTR_SELECTOR;
2043 instr->table.table_id = s->id;
2047 l = learner_find(p, tokens[1]);
2049 instr->type = INSTR_LEARNER;
2050 instr->table.table_id = l->id;
2058 instr_table_exec(struct rte_swx_pipeline *p)
2060 struct thread *t = &p->threads[p->thread_id];
2061 struct instruction *ip = t->ip;
2062 uint32_t table_id = ip->table.table_id;
2063 struct rte_swx_table_state *ts = &t->table_state[table_id];
2064 struct table_runtime *table = &t->tables[table_id];
2065 struct table_statistics *stats = &p->table_stats[table_id];
2066 uint64_t action_id, n_pkts_hit, n_pkts_action;
2067 uint8_t *action_data;
2071 done = table->func(ts->obj,
2079 TRACE("[Thread %2u] table %u (not finalized)\n",
2087 action_id = hit ? action_id : ts->default_action_id;
2088 action_data = hit ? action_data : ts->default_action_data;
2089 n_pkts_hit = stats->n_pkts_hit[hit];
2090 n_pkts_action = stats->n_pkts_action[action_id];
2092 TRACE("[Thread %2u] table %u (%s, action %u)\n",
2095 hit ? "hit" : "miss",
2096 (uint32_t)action_id);
2098 t->action_id = action_id;
2099 t->structs[0] = action_data;
2101 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2102 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2105 thread_ip_action_call(p, t, action_id);
2109 instr_selector_exec(struct rte_swx_pipeline *p)
2111 struct thread *t = &p->threads[p->thread_id];
2112 struct instruction *ip = t->ip;
2113 uint32_t selector_id = ip->table.table_id;
2114 struct rte_swx_table_state *ts = &t->table_state[p->n_tables + selector_id];
2115 struct selector_runtime *selector = &t->selectors[selector_id];
2116 struct selector_statistics *stats = &p->selector_stats[selector_id];
2117 uint64_t n_pkts = stats->n_pkts;
2121 done = rte_swx_table_selector_select(ts->obj,
2123 selector->group_id_buffer,
2124 selector->selector_buffer,
2125 selector->member_id_buffer);
2128 TRACE("[Thread %2u] selector %u (not finalized)\n",
2137 TRACE("[Thread %2u] selector %u\n",
2141 stats->n_pkts = n_pkts + 1;
2148 instr_learner_exec(struct rte_swx_pipeline *p)
2150 struct thread *t = &p->threads[p->thread_id];
2151 struct instruction *ip = t->ip;
2152 uint32_t learner_id = ip->table.table_id;
2153 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2154 p->n_selectors + learner_id];
2155 struct learner_runtime *l = &t->learners[learner_id];
2156 struct learner_statistics *stats = &p->learner_stats[learner_id];
2157 uint64_t action_id, n_pkts_hit, n_pkts_action, time;
2158 uint8_t *action_data;
2162 time = rte_get_tsc_cycles();
2164 done = rte_swx_table_learner_lookup(ts->obj,
2173 TRACE("[Thread %2u] learner %u (not finalized)\n",
2181 action_id = hit ? action_id : ts->default_action_id;
2182 action_data = hit ? action_data : ts->default_action_data;
2183 n_pkts_hit = stats->n_pkts_hit[hit];
2184 n_pkts_action = stats->n_pkts_action[action_id];
2186 TRACE("[Thread %2u] learner %u (%s, action %u)\n",
2189 hit ? "hit" : "miss",
2190 (uint32_t)action_id);
2192 t->action_id = action_id;
2193 t->structs[0] = action_data;
2195 t->learner_id = learner_id;
2197 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2198 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2201 thread_ip_action_call(p, t, action_id);
2207 static struct action *
2208 action_find(struct rte_swx_pipeline *p, const char *name);
2211 action_has_nbo_args(struct action *a);
2214 instr_learn_translate(struct rte_swx_pipeline *p,
2215 struct action *action,
2218 struct instruction *instr,
2219 struct instruction_data *data __rte_unused)
2223 CHECK(action, EINVAL);
2224 CHECK(n_tokens == 2, EINVAL);
2226 a = action_find(p, tokens[1]);
2228 CHECK(!action_has_nbo_args(a), EINVAL);
2230 instr->type = INSTR_LEARNER_LEARN;
2231 instr->learn.action_id = a->id;
2237 instr_learn_exec(struct rte_swx_pipeline *p)
2239 struct thread *t = &p->threads[p->thread_id];
2240 struct instruction *ip = t->ip;
2241 uint64_t action_id = ip->learn.action_id;
2242 uint32_t learner_id = t->learner_id;
2243 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2244 p->n_selectors + learner_id];
2245 struct learner_runtime *l = &t->learners[learner_id];
2246 struct learner_statistics *stats = &p->learner_stats[learner_id];
2250 status = rte_swx_table_learner_add(ts->obj,
2254 l->action_data[action_id]);
2256 TRACE("[Thread %2u] learner %u learn %s\n",
2259 status ? "ok" : "error");
2261 stats->n_pkts_learn[status] += 1;
2271 instr_forget_translate(struct rte_swx_pipeline *p __rte_unused,
2272 struct action *action,
2273 char **tokens __rte_unused,
2275 struct instruction *instr,
2276 struct instruction_data *data __rte_unused)
2278 CHECK(action, EINVAL);
2279 CHECK(n_tokens == 1, EINVAL);
2281 instr->type = INSTR_LEARNER_FORGET;
2287 instr_forget_exec(struct rte_swx_pipeline *p)
2289 struct thread *t = &p->threads[p->thread_id];
2290 uint32_t learner_id = t->learner_id;
2291 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2292 p->n_selectors + learner_id];
2293 struct learner_runtime *l = &t->learners[learner_id];
2294 struct learner_statistics *stats = &p->learner_stats[learner_id];
2297 rte_swx_table_learner_delete(ts->obj, l->mailbox);
2299 TRACE("[Thread %2u] learner %u forget\n",
2303 stats->n_pkts_forget += 1;
2313 instr_extern_translate(struct rte_swx_pipeline *p,
2314 struct action *action __rte_unused,
2317 struct instruction *instr,
2318 struct instruction_data *data __rte_unused)
2320 char *token = tokens[1];
2322 CHECK(n_tokens == 2, EINVAL);
2324 if (token[0] == 'e') {
2325 struct extern_obj *obj;
2326 struct extern_type_member_func *func;
2328 func = extern_obj_member_func_parse(p, token, &obj);
2329 CHECK(func, EINVAL);
2331 instr->type = INSTR_EXTERN_OBJ;
2332 instr->ext_obj.ext_obj_id = obj->id;
2333 instr->ext_obj.func_id = func->id;
2338 if (token[0] == 'f') {
2339 struct extern_func *func;
2341 func = extern_func_parse(p, token);
2342 CHECK(func, EINVAL);
2344 instr->type = INSTR_EXTERN_FUNC;
2345 instr->ext_func.ext_func_id = func->id;
2354 instr_extern_obj_exec(struct rte_swx_pipeline *p)
2356 struct thread *t = &p->threads[p->thread_id];
2357 struct instruction *ip = t->ip;
2358 uint32_t obj_id = ip->ext_obj.ext_obj_id;
2359 uint32_t func_id = ip->ext_obj.func_id;
2360 struct extern_obj_runtime *obj = &t->extern_objs[obj_id];
2361 rte_swx_extern_type_member_func_t func = obj->funcs[func_id];
2363 TRACE("[Thread %2u] extern obj %u member func %u\n",
2368 /* Extern object member function execute. */
2369 uint32_t done = func(obj->obj, obj->mailbox);
2372 thread_ip_inc_cond(t, done);
2373 thread_yield_cond(p, done ^ 1);
2377 instr_extern_func_exec(struct rte_swx_pipeline *p)
2379 struct thread *t = &p->threads[p->thread_id];
2380 struct instruction *ip = t->ip;
2381 uint32_t ext_func_id = ip->ext_func.ext_func_id;
2382 struct extern_func_runtime *ext_func = &t->extern_funcs[ext_func_id];
2383 rte_swx_extern_func_t func = ext_func->func;
2385 TRACE("[Thread %2u] extern func %u\n",
2389 /* Extern function execute. */
2390 uint32_t done = func(ext_func->mailbox);
2393 thread_ip_inc_cond(t, done);
2394 thread_yield_cond(p, done ^ 1);
2401 instr_mov_translate(struct rte_swx_pipeline *p,
2402 struct action *action,
2405 struct instruction *instr,
2406 struct instruction_data *data __rte_unused)
2408 char *dst = tokens[1], *src = tokens[2];
2409 struct field *fdst, *fsrc;
2411 uint32_t dst_struct_id = 0, src_struct_id = 0;
2413 CHECK(n_tokens == 3, EINVAL);
2415 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2416 CHECK(fdst, EINVAL);
2417 CHECK(!fdst->var_size, EINVAL);
2419 /* MOV, MOV_MH, MOV_HM or MOV_HH. */
2420 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2422 CHECK(!fsrc->var_size, EINVAL);
2424 instr->type = INSTR_MOV;
2425 if (dst[0] != 'h' && src[0] == 'h')
2426 instr->type = INSTR_MOV_MH;
2427 if (dst[0] == 'h' && src[0] != 'h')
2428 instr->type = INSTR_MOV_HM;
2429 if (dst[0] == 'h' && src[0] == 'h')
2430 instr->type = INSTR_MOV_HH;
2432 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
2433 instr->mov.dst.n_bits = fdst->n_bits;
2434 instr->mov.dst.offset = fdst->offset / 8;
2435 instr->mov.src.struct_id = (uint8_t)src_struct_id;
2436 instr->mov.src.n_bits = fsrc->n_bits;
2437 instr->mov.src.offset = fsrc->offset / 8;
2442 src_val = strtoull(src, &src, 0);
2443 CHECK(!src[0], EINVAL);
2446 src_val = hton64(src_val) >> (64 - fdst->n_bits);
2448 instr->type = INSTR_MOV_I;
2449 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
2450 instr->mov.dst.n_bits = fdst->n_bits;
2451 instr->mov.dst.offset = fdst->offset / 8;
2452 instr->mov.src_val = src_val;
2457 instr_mov_exec(struct rte_swx_pipeline *p)
2459 struct thread *t = &p->threads[p->thread_id];
2460 struct instruction *ip = t->ip;
2462 TRACE("[Thread %2u] mov\n",
2472 instr_mov_mh_exec(struct rte_swx_pipeline *p)
2474 struct thread *t = &p->threads[p->thread_id];
2475 struct instruction *ip = t->ip;
2477 TRACE("[Thread %2u] mov (mh)\n",
2487 instr_mov_hm_exec(struct rte_swx_pipeline *p)
2489 struct thread *t = &p->threads[p->thread_id];
2490 struct instruction *ip = t->ip;
2492 TRACE("[Thread %2u] mov (hm)\n",
2502 instr_mov_hh_exec(struct rte_swx_pipeline *p)
2504 struct thread *t = &p->threads[p->thread_id];
2505 struct instruction *ip = t->ip;
2507 TRACE("[Thread %2u] mov (hh)\n",
2517 instr_mov_i_exec(struct rte_swx_pipeline *p)
2519 struct thread *t = &p->threads[p->thread_id];
2520 struct instruction *ip = t->ip;
2522 TRACE("[Thread %2u] mov m.f %" PRIx64 "\n",
2536 __instr_dma_ht_exec(struct rte_swx_pipeline *p, uint32_t n_dma);
2539 __instr_dma_ht_exec(struct rte_swx_pipeline *p, uint32_t n_dma)
2541 struct thread *t = &p->threads[p->thread_id];
2542 struct instruction *ip = t->ip;
2543 uint8_t *action_data = t->structs[0];
2544 uint64_t valid_headers = t->valid_headers;
2547 for (i = 0; i < n_dma; i++) {
2548 uint32_t header_id = ip->dma.dst.header_id[i];
2549 uint32_t struct_id = ip->dma.dst.struct_id[i];
2550 uint32_t offset = ip->dma.src.offset[i];
2551 uint32_t n_bytes = ip->dma.n_bytes[i];
2553 struct header_runtime *h = &t->headers[header_id];
2554 uint8_t *h_ptr0 = h->ptr0;
2555 uint8_t *h_ptr = t->structs[struct_id];
2557 void *dst = MASK64_BIT_GET(valid_headers, header_id) ?
2559 void *src = &action_data[offset];
2561 TRACE("[Thread %2u] dma h.s t.f\n", p->thread_id);
2564 memcpy(dst, src, n_bytes);
2565 t->structs[struct_id] = dst;
2566 valid_headers = MASK64_BIT_SET(valid_headers, header_id);
2569 t->valid_headers = valid_headers;
2573 instr_dma_ht_exec(struct rte_swx_pipeline *p)
2575 __instr_dma_ht_exec(p, 1);
2582 instr_dma_ht2_exec(struct rte_swx_pipeline *p)
2584 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n",
2587 __instr_dma_ht_exec(p, 2);
2594 instr_dma_ht3_exec(struct rte_swx_pipeline *p)
2596 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n",
2599 __instr_dma_ht_exec(p, 3);
2606 instr_dma_ht4_exec(struct rte_swx_pipeline *p)
2608 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n",
2611 __instr_dma_ht_exec(p, 4);
2618 instr_dma_ht5_exec(struct rte_swx_pipeline *p)
2620 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n",
2623 __instr_dma_ht_exec(p, 5);
2630 instr_dma_ht6_exec(struct rte_swx_pipeline *p)
2632 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n",
2635 __instr_dma_ht_exec(p, 6);
2642 instr_dma_ht7_exec(struct rte_swx_pipeline *p)
2644 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n",
2647 __instr_dma_ht_exec(p, 7);
2654 instr_dma_ht8_exec(struct rte_swx_pipeline *p)
2656 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n",
2659 __instr_dma_ht_exec(p, 8);
2669 instr_alu_add_translate(struct rte_swx_pipeline *p,
2670 struct action *action,
2673 struct instruction *instr,
2674 struct instruction_data *data __rte_unused)
2676 char *dst = tokens[1], *src = tokens[2];
2677 struct field *fdst, *fsrc;
2679 uint32_t dst_struct_id = 0, src_struct_id = 0;
2681 CHECK(n_tokens == 3, EINVAL);
2683 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2684 CHECK(fdst, EINVAL);
2685 CHECK(!fdst->var_size, EINVAL);
2687 /* ADD, ADD_HM, ADD_MH, ADD_HH. */
2688 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2690 CHECK(!fsrc->var_size, EINVAL);
2692 instr->type = INSTR_ALU_ADD;
2693 if (dst[0] == 'h' && src[0] != 'h')
2694 instr->type = INSTR_ALU_ADD_HM;
2695 if (dst[0] != 'h' && src[0] == 'h')
2696 instr->type = INSTR_ALU_ADD_MH;
2697 if (dst[0] == 'h' && src[0] == 'h')
2698 instr->type = INSTR_ALU_ADD_HH;
2700 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2701 instr->alu.dst.n_bits = fdst->n_bits;
2702 instr->alu.dst.offset = fdst->offset / 8;
2703 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2704 instr->alu.src.n_bits = fsrc->n_bits;
2705 instr->alu.src.offset = fsrc->offset / 8;
2709 /* ADD_MI, ADD_HI. */
2710 src_val = strtoull(src, &src, 0);
2711 CHECK(!src[0], EINVAL);
2713 instr->type = INSTR_ALU_ADD_MI;
2715 instr->type = INSTR_ALU_ADD_HI;
2717 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2718 instr->alu.dst.n_bits = fdst->n_bits;
2719 instr->alu.dst.offset = fdst->offset / 8;
2720 instr->alu.src_val = src_val;
2725 instr_alu_sub_translate(struct rte_swx_pipeline *p,
2726 struct action *action,
2729 struct instruction *instr,
2730 struct instruction_data *data __rte_unused)
2732 char *dst = tokens[1], *src = tokens[2];
2733 struct field *fdst, *fsrc;
2735 uint32_t dst_struct_id = 0, src_struct_id = 0;
2737 CHECK(n_tokens == 3, EINVAL);
2739 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2740 CHECK(fdst, EINVAL);
2741 CHECK(!fdst->var_size, EINVAL);
2743 /* SUB, SUB_HM, SUB_MH, SUB_HH. */
2744 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2746 CHECK(!fsrc->var_size, EINVAL);
2748 instr->type = INSTR_ALU_SUB;
2749 if (dst[0] == 'h' && src[0] != 'h')
2750 instr->type = INSTR_ALU_SUB_HM;
2751 if (dst[0] != 'h' && src[0] == 'h')
2752 instr->type = INSTR_ALU_SUB_MH;
2753 if (dst[0] == 'h' && src[0] == 'h')
2754 instr->type = INSTR_ALU_SUB_HH;
2756 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2757 instr->alu.dst.n_bits = fdst->n_bits;
2758 instr->alu.dst.offset = fdst->offset / 8;
2759 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2760 instr->alu.src.n_bits = fsrc->n_bits;
2761 instr->alu.src.offset = fsrc->offset / 8;
2765 /* SUB_MI, SUB_HI. */
2766 src_val = strtoull(src, &src, 0);
2767 CHECK(!src[0], EINVAL);
2769 instr->type = INSTR_ALU_SUB_MI;
2771 instr->type = INSTR_ALU_SUB_HI;
2773 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2774 instr->alu.dst.n_bits = fdst->n_bits;
2775 instr->alu.dst.offset = fdst->offset / 8;
2776 instr->alu.src_val = src_val;
2781 instr_alu_ckadd_translate(struct rte_swx_pipeline *p,
2782 struct action *action __rte_unused,
2785 struct instruction *instr,
2786 struct instruction_data *data __rte_unused)
2788 char *dst = tokens[1], *src = tokens[2];
2789 struct header *hdst, *hsrc;
2790 struct field *fdst, *fsrc;
2792 CHECK(n_tokens == 3, EINVAL);
2794 fdst = header_field_parse(p, dst, &hdst);
2795 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
2796 CHECK(!fdst->var_size, EINVAL);
2799 fsrc = header_field_parse(p, src, &hsrc);
2801 CHECK(!fsrc->var_size, EINVAL);
2803 instr->type = INSTR_ALU_CKADD_FIELD;
2804 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2805 instr->alu.dst.n_bits = fdst->n_bits;
2806 instr->alu.dst.offset = fdst->offset / 8;
2807 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2808 instr->alu.src.n_bits = fsrc->n_bits;
2809 instr->alu.src.offset = fsrc->offset / 8;
2813 /* CKADD_STRUCT, CKADD_STRUCT20. */
2814 hsrc = header_parse(p, src);
2815 CHECK(hsrc, EINVAL);
2816 CHECK(!hsrc->st->var_size, EINVAL);
2818 instr->type = INSTR_ALU_CKADD_STRUCT;
2819 if ((hsrc->st->n_bits / 8) == 20)
2820 instr->type = INSTR_ALU_CKADD_STRUCT20;
2822 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2823 instr->alu.dst.n_bits = fdst->n_bits;
2824 instr->alu.dst.offset = fdst->offset / 8;
2825 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2826 instr->alu.src.n_bits = hsrc->st->n_bits;
2827 instr->alu.src.offset = 0; /* Unused. */
2832 instr_alu_cksub_translate(struct rte_swx_pipeline *p,
2833 struct action *action __rte_unused,
2836 struct instruction *instr,
2837 struct instruction_data *data __rte_unused)
2839 char *dst = tokens[1], *src = tokens[2];
2840 struct header *hdst, *hsrc;
2841 struct field *fdst, *fsrc;
2843 CHECK(n_tokens == 3, EINVAL);
2845 fdst = header_field_parse(p, dst, &hdst);
2846 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
2847 CHECK(!fdst->var_size, EINVAL);
2849 fsrc = header_field_parse(p, src, &hsrc);
2850 CHECK(fsrc, EINVAL);
2851 CHECK(!fsrc->var_size, EINVAL);
2853 instr->type = INSTR_ALU_CKSUB_FIELD;
2854 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2855 instr->alu.dst.n_bits = fdst->n_bits;
2856 instr->alu.dst.offset = fdst->offset / 8;
2857 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2858 instr->alu.src.n_bits = fsrc->n_bits;
2859 instr->alu.src.offset = fsrc->offset / 8;
2864 instr_alu_shl_translate(struct rte_swx_pipeline *p,
2865 struct action *action,
2868 struct instruction *instr,
2869 struct instruction_data *data __rte_unused)
2871 char *dst = tokens[1], *src = tokens[2];
2872 struct field *fdst, *fsrc;
2874 uint32_t dst_struct_id = 0, src_struct_id = 0;
2876 CHECK(n_tokens == 3, EINVAL);
2878 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2879 CHECK(fdst, EINVAL);
2880 CHECK(!fdst->var_size, EINVAL);
2882 /* SHL, SHL_HM, SHL_MH, SHL_HH. */
2883 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2885 CHECK(!fsrc->var_size, EINVAL);
2887 instr->type = INSTR_ALU_SHL;
2888 if (dst[0] == 'h' && src[0] != 'h')
2889 instr->type = INSTR_ALU_SHL_HM;
2890 if (dst[0] != 'h' && src[0] == 'h')
2891 instr->type = INSTR_ALU_SHL_MH;
2892 if (dst[0] == 'h' && src[0] == 'h')
2893 instr->type = INSTR_ALU_SHL_HH;
2895 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2896 instr->alu.dst.n_bits = fdst->n_bits;
2897 instr->alu.dst.offset = fdst->offset / 8;
2898 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2899 instr->alu.src.n_bits = fsrc->n_bits;
2900 instr->alu.src.offset = fsrc->offset / 8;
2904 /* SHL_MI, SHL_HI. */
2905 src_val = strtoull(src, &src, 0);
2906 CHECK(!src[0], EINVAL);
2908 instr->type = INSTR_ALU_SHL_MI;
2910 instr->type = INSTR_ALU_SHL_HI;
2912 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2913 instr->alu.dst.n_bits = fdst->n_bits;
2914 instr->alu.dst.offset = fdst->offset / 8;
2915 instr->alu.src_val = src_val;
2920 instr_alu_shr_translate(struct rte_swx_pipeline *p,
2921 struct action *action,
2924 struct instruction *instr,
2925 struct instruction_data *data __rte_unused)
2927 char *dst = tokens[1], *src = tokens[2];
2928 struct field *fdst, *fsrc;
2930 uint32_t dst_struct_id = 0, src_struct_id = 0;
2932 CHECK(n_tokens == 3, EINVAL);
2934 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2935 CHECK(fdst, EINVAL);
2936 CHECK(!fdst->var_size, EINVAL);
2938 /* SHR, SHR_HM, SHR_MH, SHR_HH. */
2939 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2941 CHECK(!fsrc->var_size, EINVAL);
2943 instr->type = INSTR_ALU_SHR;
2944 if (dst[0] == 'h' && src[0] != 'h')
2945 instr->type = INSTR_ALU_SHR_HM;
2946 if (dst[0] != 'h' && src[0] == 'h')
2947 instr->type = INSTR_ALU_SHR_MH;
2948 if (dst[0] == 'h' && src[0] == 'h')
2949 instr->type = INSTR_ALU_SHR_HH;
2951 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2952 instr->alu.dst.n_bits = fdst->n_bits;
2953 instr->alu.dst.offset = fdst->offset / 8;
2954 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2955 instr->alu.src.n_bits = fsrc->n_bits;
2956 instr->alu.src.offset = fsrc->offset / 8;
2960 /* SHR_MI, SHR_HI. */
2961 src_val = strtoull(src, &src, 0);
2962 CHECK(!src[0], EINVAL);
2964 instr->type = INSTR_ALU_SHR_MI;
2966 instr->type = INSTR_ALU_SHR_HI;
2968 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2969 instr->alu.dst.n_bits = fdst->n_bits;
2970 instr->alu.dst.offset = fdst->offset / 8;
2971 instr->alu.src_val = src_val;
2976 instr_alu_and_translate(struct rte_swx_pipeline *p,
2977 struct action *action,
2980 struct instruction *instr,
2981 struct instruction_data *data __rte_unused)
2983 char *dst = tokens[1], *src = tokens[2];
2984 struct field *fdst, *fsrc;
2986 uint32_t dst_struct_id = 0, src_struct_id = 0;
2988 CHECK(n_tokens == 3, EINVAL);
2990 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2991 CHECK(fdst, EINVAL);
2992 CHECK(!fdst->var_size, EINVAL);
2994 /* AND, AND_MH, AND_HM, AND_HH. */
2995 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2997 CHECK(!fsrc->var_size, EINVAL);
2999 instr->type = INSTR_ALU_AND;
3000 if (dst[0] != 'h' && src[0] == 'h')
3001 instr->type = INSTR_ALU_AND_MH;
3002 if (dst[0] == 'h' && src[0] != 'h')
3003 instr->type = INSTR_ALU_AND_HM;
3004 if (dst[0] == 'h' && src[0] == 'h')
3005 instr->type = INSTR_ALU_AND_HH;
3007 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3008 instr->alu.dst.n_bits = fdst->n_bits;
3009 instr->alu.dst.offset = fdst->offset / 8;
3010 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3011 instr->alu.src.n_bits = fsrc->n_bits;
3012 instr->alu.src.offset = fsrc->offset / 8;
3017 src_val = strtoull(src, &src, 0);
3018 CHECK(!src[0], EINVAL);
3021 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3023 instr->type = INSTR_ALU_AND_I;
3024 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3025 instr->alu.dst.n_bits = fdst->n_bits;
3026 instr->alu.dst.offset = fdst->offset / 8;
3027 instr->alu.src_val = src_val;
3032 instr_alu_or_translate(struct rte_swx_pipeline *p,
3033 struct action *action,
3036 struct instruction *instr,
3037 struct instruction_data *data __rte_unused)
3039 char *dst = tokens[1], *src = tokens[2];
3040 struct field *fdst, *fsrc;
3042 uint32_t dst_struct_id = 0, src_struct_id = 0;
3044 CHECK(n_tokens == 3, EINVAL);
3046 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3047 CHECK(fdst, EINVAL);
3048 CHECK(!fdst->var_size, EINVAL);
3050 /* OR, OR_MH, OR_HM, OR_HH. */
3051 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3053 CHECK(!fsrc->var_size, EINVAL);
3055 instr->type = INSTR_ALU_OR;
3056 if (dst[0] != 'h' && src[0] == 'h')
3057 instr->type = INSTR_ALU_OR_MH;
3058 if (dst[0] == 'h' && src[0] != 'h')
3059 instr->type = INSTR_ALU_OR_HM;
3060 if (dst[0] == 'h' && src[0] == 'h')
3061 instr->type = INSTR_ALU_OR_HH;
3063 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3064 instr->alu.dst.n_bits = fdst->n_bits;
3065 instr->alu.dst.offset = fdst->offset / 8;
3066 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3067 instr->alu.src.n_bits = fsrc->n_bits;
3068 instr->alu.src.offset = fsrc->offset / 8;
3073 src_val = strtoull(src, &src, 0);
3074 CHECK(!src[0], EINVAL);
3077 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3079 instr->type = INSTR_ALU_OR_I;
3080 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3081 instr->alu.dst.n_bits = fdst->n_bits;
3082 instr->alu.dst.offset = fdst->offset / 8;
3083 instr->alu.src_val = src_val;
3088 instr_alu_xor_translate(struct rte_swx_pipeline *p,
3089 struct action *action,
3092 struct instruction *instr,
3093 struct instruction_data *data __rte_unused)
3095 char *dst = tokens[1], *src = tokens[2];
3096 struct field *fdst, *fsrc;
3098 uint32_t dst_struct_id = 0, src_struct_id = 0;
3100 CHECK(n_tokens == 3, EINVAL);
3102 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3103 CHECK(fdst, EINVAL);
3104 CHECK(!fdst->var_size, EINVAL);
3106 /* XOR, XOR_MH, XOR_HM, XOR_HH. */
3107 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3109 CHECK(!fsrc->var_size, EINVAL);
3111 instr->type = INSTR_ALU_XOR;
3112 if (dst[0] != 'h' && src[0] == 'h')
3113 instr->type = INSTR_ALU_XOR_MH;
3114 if (dst[0] == 'h' && src[0] != 'h')
3115 instr->type = INSTR_ALU_XOR_HM;
3116 if (dst[0] == 'h' && src[0] == 'h')
3117 instr->type = INSTR_ALU_XOR_HH;
3119 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3120 instr->alu.dst.n_bits = fdst->n_bits;
3121 instr->alu.dst.offset = fdst->offset / 8;
3122 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3123 instr->alu.src.n_bits = fsrc->n_bits;
3124 instr->alu.src.offset = fsrc->offset / 8;
3129 src_val = strtoull(src, &src, 0);
3130 CHECK(!src[0], EINVAL);
3133 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3135 instr->type = INSTR_ALU_XOR_I;
3136 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3137 instr->alu.dst.n_bits = fdst->n_bits;
3138 instr->alu.dst.offset = fdst->offset / 8;
3139 instr->alu.src_val = src_val;
3144 instr_alu_add_exec(struct rte_swx_pipeline *p)
3146 struct thread *t = &p->threads[p->thread_id];
3147 struct instruction *ip = t->ip;
3149 TRACE("[Thread %2u] add\n", p->thread_id);
3159 instr_alu_add_mh_exec(struct rte_swx_pipeline *p)
3161 struct thread *t = &p->threads[p->thread_id];
3162 struct instruction *ip = t->ip;
3164 TRACE("[Thread %2u] add (mh)\n", p->thread_id);
3174 instr_alu_add_hm_exec(struct rte_swx_pipeline *p)
3176 struct thread *t = &p->threads[p->thread_id];
3177 struct instruction *ip = t->ip;
3179 TRACE("[Thread %2u] add (hm)\n", p->thread_id);
3189 instr_alu_add_hh_exec(struct rte_swx_pipeline *p)
3191 struct thread *t = &p->threads[p->thread_id];
3192 struct instruction *ip = t->ip;
3194 TRACE("[Thread %2u] add (hh)\n", p->thread_id);
3204 instr_alu_add_mi_exec(struct rte_swx_pipeline *p)
3206 struct thread *t = &p->threads[p->thread_id];
3207 struct instruction *ip = t->ip;
3209 TRACE("[Thread %2u] add (mi)\n", p->thread_id);
3219 instr_alu_add_hi_exec(struct rte_swx_pipeline *p)
3221 struct thread *t = &p->threads[p->thread_id];
3222 struct instruction *ip = t->ip;
3224 TRACE("[Thread %2u] add (hi)\n", p->thread_id);
3234 instr_alu_sub_exec(struct rte_swx_pipeline *p)
3236 struct thread *t = &p->threads[p->thread_id];
3237 struct instruction *ip = t->ip;
3239 TRACE("[Thread %2u] sub\n", p->thread_id);
3249 instr_alu_sub_mh_exec(struct rte_swx_pipeline *p)
3251 struct thread *t = &p->threads[p->thread_id];
3252 struct instruction *ip = t->ip;
3254 TRACE("[Thread %2u] sub (mh)\n", p->thread_id);
3264 instr_alu_sub_hm_exec(struct rte_swx_pipeline *p)
3266 struct thread *t = &p->threads[p->thread_id];
3267 struct instruction *ip = t->ip;
3269 TRACE("[Thread %2u] sub (hm)\n", p->thread_id);
3279 instr_alu_sub_hh_exec(struct rte_swx_pipeline *p)
3281 struct thread *t = &p->threads[p->thread_id];
3282 struct instruction *ip = t->ip;
3284 TRACE("[Thread %2u] sub (hh)\n", p->thread_id);
3294 instr_alu_sub_mi_exec(struct rte_swx_pipeline *p)
3296 struct thread *t = &p->threads[p->thread_id];
3297 struct instruction *ip = t->ip;
3299 TRACE("[Thread %2u] sub (mi)\n", p->thread_id);
3309 instr_alu_sub_hi_exec(struct rte_swx_pipeline *p)
3311 struct thread *t = &p->threads[p->thread_id];
3312 struct instruction *ip = t->ip;
3314 TRACE("[Thread %2u] sub (hi)\n", p->thread_id);
3324 instr_alu_shl_exec(struct rte_swx_pipeline *p)
3326 struct thread *t = &p->threads[p->thread_id];
3327 struct instruction *ip = t->ip;
3329 TRACE("[Thread %2u] shl\n", p->thread_id);
3339 instr_alu_shl_mh_exec(struct rte_swx_pipeline *p)
3341 struct thread *t = &p->threads[p->thread_id];
3342 struct instruction *ip = t->ip;
3344 TRACE("[Thread %2u] shl (mh)\n", p->thread_id);
3354 instr_alu_shl_hm_exec(struct rte_swx_pipeline *p)
3356 struct thread *t = &p->threads[p->thread_id];
3357 struct instruction *ip = t->ip;
3359 TRACE("[Thread %2u] shl (hm)\n", p->thread_id);
3369 instr_alu_shl_hh_exec(struct rte_swx_pipeline *p)
3371 struct thread *t = &p->threads[p->thread_id];
3372 struct instruction *ip = t->ip;
3374 TRACE("[Thread %2u] shl (hh)\n", p->thread_id);
3384 instr_alu_shl_mi_exec(struct rte_swx_pipeline *p)
3386 struct thread *t = &p->threads[p->thread_id];
3387 struct instruction *ip = t->ip;
3389 TRACE("[Thread %2u] shl (mi)\n", p->thread_id);
3399 instr_alu_shl_hi_exec(struct rte_swx_pipeline *p)
3401 struct thread *t = &p->threads[p->thread_id];
3402 struct instruction *ip = t->ip;
3404 TRACE("[Thread %2u] shl (hi)\n", p->thread_id);
3414 instr_alu_shr_exec(struct rte_swx_pipeline *p)
3416 struct thread *t = &p->threads[p->thread_id];
3417 struct instruction *ip = t->ip;
3419 TRACE("[Thread %2u] shr\n", p->thread_id);
3429 instr_alu_shr_mh_exec(struct rte_swx_pipeline *p)
3431 struct thread *t = &p->threads[p->thread_id];
3432 struct instruction *ip = t->ip;
3434 TRACE("[Thread %2u] shr (mh)\n", p->thread_id);
3444 instr_alu_shr_hm_exec(struct rte_swx_pipeline *p)
3446 struct thread *t = &p->threads[p->thread_id];
3447 struct instruction *ip = t->ip;
3449 TRACE("[Thread %2u] shr (hm)\n", p->thread_id);
3459 instr_alu_shr_hh_exec(struct rte_swx_pipeline *p)
3461 struct thread *t = &p->threads[p->thread_id];
3462 struct instruction *ip = t->ip;
3464 TRACE("[Thread %2u] shr (hh)\n", p->thread_id);
3474 instr_alu_shr_mi_exec(struct rte_swx_pipeline *p)
3476 struct thread *t = &p->threads[p->thread_id];
3477 struct instruction *ip = t->ip;
3479 TRACE("[Thread %2u] shr (mi)\n", p->thread_id);
3489 instr_alu_shr_hi_exec(struct rte_swx_pipeline *p)
3491 struct thread *t = &p->threads[p->thread_id];
3492 struct instruction *ip = t->ip;
3494 TRACE("[Thread %2u] shr (hi)\n", p->thread_id);
3504 instr_alu_and_exec(struct rte_swx_pipeline *p)
3506 struct thread *t = &p->threads[p->thread_id];
3507 struct instruction *ip = t->ip;
3509 TRACE("[Thread %2u] and\n", p->thread_id);
3519 instr_alu_and_mh_exec(struct rte_swx_pipeline *p)
3521 struct thread *t = &p->threads[p->thread_id];
3522 struct instruction *ip = t->ip;
3524 TRACE("[Thread %2u] and (mh)\n", p->thread_id);
3534 instr_alu_and_hm_exec(struct rte_swx_pipeline *p)
3536 struct thread *t = &p->threads[p->thread_id];
3537 struct instruction *ip = t->ip;
3539 TRACE("[Thread %2u] and (hm)\n", p->thread_id);
3542 ALU_HM_FAST(t, ip, &);
3549 instr_alu_and_hh_exec(struct rte_swx_pipeline *p)
3551 struct thread *t = &p->threads[p->thread_id];
3552 struct instruction *ip = t->ip;
3554 TRACE("[Thread %2u] and (hh)\n", p->thread_id);
3557 ALU_HH_FAST(t, ip, &);
3564 instr_alu_and_i_exec(struct rte_swx_pipeline *p)
3566 struct thread *t = &p->threads[p->thread_id];
3567 struct instruction *ip = t->ip;
3569 TRACE("[Thread %2u] and (i)\n", p->thread_id);
3579 instr_alu_or_exec(struct rte_swx_pipeline *p)
3581 struct thread *t = &p->threads[p->thread_id];
3582 struct instruction *ip = t->ip;
3584 TRACE("[Thread %2u] or\n", p->thread_id);
3594 instr_alu_or_mh_exec(struct rte_swx_pipeline *p)
3596 struct thread *t = &p->threads[p->thread_id];
3597 struct instruction *ip = t->ip;
3599 TRACE("[Thread %2u] or (mh)\n", p->thread_id);
3609 instr_alu_or_hm_exec(struct rte_swx_pipeline *p)
3611 struct thread *t = &p->threads[p->thread_id];
3612 struct instruction *ip = t->ip;
3614 TRACE("[Thread %2u] or (hm)\n", p->thread_id);
3617 ALU_HM_FAST(t, ip, |);
3624 instr_alu_or_hh_exec(struct rte_swx_pipeline *p)
3626 struct thread *t = &p->threads[p->thread_id];
3627 struct instruction *ip = t->ip;
3629 TRACE("[Thread %2u] or (hh)\n", p->thread_id);
3632 ALU_HH_FAST(t, ip, |);
3639 instr_alu_or_i_exec(struct rte_swx_pipeline *p)
3641 struct thread *t = &p->threads[p->thread_id];
3642 struct instruction *ip = t->ip;
3644 TRACE("[Thread %2u] or (i)\n", p->thread_id);
3654 instr_alu_xor_exec(struct rte_swx_pipeline *p)
3656 struct thread *t = &p->threads[p->thread_id];
3657 struct instruction *ip = t->ip;
3659 TRACE("[Thread %2u] xor\n", p->thread_id);
3669 instr_alu_xor_mh_exec(struct rte_swx_pipeline *p)
3671 struct thread *t = &p->threads[p->thread_id];
3672 struct instruction *ip = t->ip;
3674 TRACE("[Thread %2u] xor (mh)\n", p->thread_id);
3684 instr_alu_xor_hm_exec(struct rte_swx_pipeline *p)
3686 struct thread *t = &p->threads[p->thread_id];
3687 struct instruction *ip = t->ip;
3689 TRACE("[Thread %2u] xor (hm)\n", p->thread_id);
3692 ALU_HM_FAST(t, ip, ^);
3699 instr_alu_xor_hh_exec(struct rte_swx_pipeline *p)
3701 struct thread *t = &p->threads[p->thread_id];
3702 struct instruction *ip = t->ip;
3704 TRACE("[Thread %2u] xor (hh)\n", p->thread_id);
3707 ALU_HH_FAST(t, ip, ^);
3714 instr_alu_xor_i_exec(struct rte_swx_pipeline *p)
3716 struct thread *t = &p->threads[p->thread_id];
3717 struct instruction *ip = t->ip;
3719 TRACE("[Thread %2u] xor (i)\n", p->thread_id);
3729 instr_alu_ckadd_field_exec(struct rte_swx_pipeline *p)
3731 struct thread *t = &p->threads[p->thread_id];
3732 struct instruction *ip = t->ip;
3733 uint8_t *dst_struct, *src_struct;
3734 uint16_t *dst16_ptr, dst;
3735 uint64_t *src64_ptr, src64, src64_mask, src;
3738 TRACE("[Thread %2u] ckadd (field)\n", p->thread_id);
3741 dst_struct = t->structs[ip->alu.dst.struct_id];
3742 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
3745 src_struct = t->structs[ip->alu.src.struct_id];
3746 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
3748 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
3749 src = src64 & src64_mask;
3754 /* The first input (r) is a 16-bit number. The second and the third
3755 * inputs are 32-bit numbers. In the worst case scenario, the sum of the
3756 * three numbers (output r) is a 34-bit number.
3758 r += (src >> 32) + (src & 0xFFFFFFFF);
3760 /* The first input is a 16-bit number. The second input is an 18-bit
3761 * number. In the worst case scenario, the sum of the two numbers is a
3764 r = (r & 0xFFFF) + (r >> 16);
3766 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
3767 * a 3-bit number (0 .. 7). Their sum is a 17-bit number (0 .. 0x10006).
3769 r = (r & 0xFFFF) + (r >> 16);
3771 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
3772 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
3773 * 0x10006), the output r is (0 .. 7). So no carry bit can be generated,
3774 * therefore the output r is always a 16-bit number.
3776 r = (r & 0xFFFF) + (r >> 16);
3781 *dst16_ptr = (uint16_t)r;
3788 instr_alu_cksub_field_exec(struct rte_swx_pipeline *p)
3790 struct thread *t = &p->threads[p->thread_id];
3791 struct instruction *ip = t->ip;
3792 uint8_t *dst_struct, *src_struct;
3793 uint16_t *dst16_ptr, dst;
3794 uint64_t *src64_ptr, src64, src64_mask, src;
3797 TRACE("[Thread %2u] cksub (field)\n", p->thread_id);
3800 dst_struct = t->structs[ip->alu.dst.struct_id];
3801 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
3804 src_struct = t->structs[ip->alu.src.struct_id];
3805 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
3807 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
3808 src = src64 & src64_mask;
3813 /* Subtraction in 1's complement arithmetic (i.e. a '- b) is the same as
3814 * the following sequence of operations in 2's complement arithmetic:
3815 * a '- b = (a - b) % 0xFFFF.
3817 * In order to prevent an underflow for the below subtraction, in which
3818 * a 33-bit number (the subtrahend) is taken out of a 16-bit number (the
3819 * minuend), we first add a multiple of the 0xFFFF modulus to the
3820 * minuend. The number we add to the minuend needs to be a 34-bit number
3821 * or higher, so for readability reasons we picked the 36-bit multiple.
3822 * We are effectively turning the 16-bit minuend into a 36-bit number:
3823 * (a - b) % 0xFFFF = (a + 0xFFFF00000 - b) % 0xFFFF.
3825 r += 0xFFFF00000ULL; /* The output r is a 36-bit number. */
3827 /* A 33-bit number is subtracted from a 36-bit number (the input r). The
3828 * result (the output r) is a 36-bit number.
3830 r -= (src >> 32) + (src & 0xFFFFFFFF);
3832 /* The first input is a 16-bit number. The second input is a 20-bit
3833 * number. Their sum is a 21-bit number.
3835 r = (r & 0xFFFF) + (r >> 16);
3837 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
3838 * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1001E).
3840 r = (r & 0xFFFF) + (r >> 16);
3842 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
3843 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
3844 * 0x1001E), the output r is (0 .. 31). So no carry bit can be
3845 * generated, therefore the output r is always a 16-bit number.
3847 r = (r & 0xFFFF) + (r >> 16);
3852 *dst16_ptr = (uint16_t)r;
3859 instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline *p)
3861 struct thread *t = &p->threads[p->thread_id];
3862 struct instruction *ip = t->ip;
3863 uint8_t *dst_struct, *src_struct;
3864 uint16_t *dst16_ptr;
3865 uint32_t *src32_ptr;
3868 TRACE("[Thread %2u] ckadd (struct of 20 bytes)\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 r0 = src32_ptr[0]; /* r0 is a 32-bit number. */
3878 r1 = src32_ptr[1]; /* r1 is a 32-bit number. */
3879 r0 += src32_ptr[2]; /* The output r0 is a 33-bit number. */
3880 r1 += src32_ptr[3]; /* The output r1 is a 33-bit number. */
3881 r0 += r1 + src32_ptr[4]; /* The output r0 is a 35-bit number. */
3883 /* The first input is a 16-bit number. The second input is a 19-bit
3884 * number. Their sum is a 20-bit number.
3886 r0 = (r0 & 0xFFFF) + (r0 >> 16);
3888 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
3889 * a 4-bit number (0 .. 15). The sum is a 17-bit number (0 .. 0x1000E).
3891 r0 = (r0 & 0xFFFF) + (r0 >> 16);
3893 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
3894 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
3895 * 0x1000E), the output r is (0 .. 15). So no carry bit can be
3896 * generated, therefore the output r is always a 16-bit number.
3898 r0 = (r0 & 0xFFFF) + (r0 >> 16);
3901 r0 = r0 ? r0 : 0xFFFF;
3903 *dst16_ptr = (uint16_t)r0;
3910 instr_alu_ckadd_struct_exec(struct rte_swx_pipeline *p)
3912 struct thread *t = &p->threads[p->thread_id];
3913 struct instruction *ip = t->ip;
3914 uint8_t *dst_struct, *src_struct;
3915 uint16_t *dst16_ptr;
3916 uint32_t *src32_ptr;
3920 TRACE("[Thread %2u] ckadd (struct)\n", p->thread_id);
3923 dst_struct = t->structs[ip->alu.dst.struct_id];
3924 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
3926 src_struct = t->structs[ip->alu.src.struct_id];
3927 src32_ptr = (uint32_t *)&src_struct[0];
3929 /* The max number of 32-bit words in a 256-byte header is 8 = 2^3.
3930 * Therefore, in the worst case scenario, a 35-bit number is added to a
3931 * 16-bit number (the input r), so the output r is 36-bit number.
3933 for (i = 0; i < ip->alu.src.n_bits / 32; i++, src32_ptr++)
3936 /* The first input is a 16-bit number. The second input is a 20-bit
3937 * number. Their sum is a 21-bit number.
3939 r = (r & 0xFFFF) + (r >> 16);
3941 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
3942 * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1000E).
3944 r = (r & 0xFFFF) + (r >> 16);
3946 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
3947 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
3948 * 0x1001E), the output r is (0 .. 31). So no carry bit can be
3949 * generated, therefore the output r is always a 16-bit number.
3951 r = (r & 0xFFFF) + (r >> 16);
3956 *dst16_ptr = (uint16_t)r;
3965 static struct regarray *
3966 regarray_find(struct rte_swx_pipeline *p, const char *name);
3969 instr_regprefetch_translate(struct rte_swx_pipeline *p,
3970 struct action *action,
3973 struct instruction *instr,
3974 struct instruction_data *data __rte_unused)
3976 char *regarray = tokens[1], *idx = tokens[2];
3979 uint32_t idx_struct_id, idx_val;
3981 CHECK(n_tokens == 3, EINVAL);
3983 r = regarray_find(p, regarray);
3986 /* REGPREFETCH_RH, REGPREFETCH_RM. */
3987 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
3989 CHECK(!fidx->var_size, EINVAL);
3991 instr->type = INSTR_REGPREFETCH_RM;
3993 instr->type = INSTR_REGPREFETCH_RH;
3995 instr->regarray.regarray_id = r->id;
3996 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
3997 instr->regarray.idx.n_bits = fidx->n_bits;
3998 instr->regarray.idx.offset = fidx->offset / 8;
3999 instr->regarray.dstsrc_val = 0; /* Unused. */
4003 /* REGPREFETCH_RI. */
4004 idx_val = strtoul(idx, &idx, 0);
4005 CHECK(!idx[0], EINVAL);
4007 instr->type = INSTR_REGPREFETCH_RI;
4008 instr->regarray.regarray_id = r->id;
4009 instr->regarray.idx_val = idx_val;
4010 instr->regarray.dstsrc_val = 0; /* Unused. */
4015 instr_regrd_translate(struct rte_swx_pipeline *p,
4016 struct action *action,
4019 struct instruction *instr,
4020 struct instruction_data *data __rte_unused)
4022 char *dst = tokens[1], *regarray = tokens[2], *idx = tokens[3];
4024 struct field *fdst, *fidx;
4025 uint32_t dst_struct_id, idx_struct_id, idx_val;
4027 CHECK(n_tokens == 4, EINVAL);
4029 r = regarray_find(p, regarray);
4032 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4033 CHECK(fdst, EINVAL);
4034 CHECK(!fdst->var_size, EINVAL);
4036 /* REGRD_HRH, REGRD_HRM, REGRD_MRH, REGRD_MRM. */
4037 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4039 CHECK(!fidx->var_size, EINVAL);
4041 instr->type = INSTR_REGRD_MRM;
4042 if (dst[0] == 'h' && idx[0] != 'h')
4043 instr->type = INSTR_REGRD_HRM;
4044 if (dst[0] != 'h' && idx[0] == 'h')
4045 instr->type = INSTR_REGRD_MRH;
4046 if (dst[0] == 'h' && idx[0] == 'h')
4047 instr->type = INSTR_REGRD_HRH;
4049 instr->regarray.regarray_id = r->id;
4050 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4051 instr->regarray.idx.n_bits = fidx->n_bits;
4052 instr->regarray.idx.offset = fidx->offset / 8;
4053 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
4054 instr->regarray.dstsrc.n_bits = fdst->n_bits;
4055 instr->regarray.dstsrc.offset = fdst->offset / 8;
4059 /* REGRD_MRI, REGRD_HRI. */
4060 idx_val = strtoul(idx, &idx, 0);
4061 CHECK(!idx[0], EINVAL);
4063 instr->type = INSTR_REGRD_MRI;
4065 instr->type = INSTR_REGRD_HRI;
4067 instr->regarray.regarray_id = r->id;
4068 instr->regarray.idx_val = idx_val;
4069 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
4070 instr->regarray.dstsrc.n_bits = fdst->n_bits;
4071 instr->regarray.dstsrc.offset = fdst->offset / 8;
4076 instr_regwr_translate(struct rte_swx_pipeline *p,
4077 struct action *action,
4080 struct instruction *instr,
4081 struct instruction_data *data __rte_unused)
4083 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
4085 struct field *fidx, *fsrc;
4087 uint32_t idx_struct_id, idx_val, src_struct_id;
4089 CHECK(n_tokens == 4, EINVAL);
4091 r = regarray_find(p, regarray);
4094 /* REGWR_RHH, REGWR_RHM, REGWR_RMH, REGWR_RMM. */
4095 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4096 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4098 CHECK(!fidx->var_size, EINVAL);
4099 CHECK(!fsrc->var_size, EINVAL);
4101 instr->type = INSTR_REGWR_RMM;
4102 if (idx[0] == 'h' && src[0] != 'h')
4103 instr->type = INSTR_REGWR_RHM;
4104 if (idx[0] != 'h' && src[0] == 'h')
4105 instr->type = INSTR_REGWR_RMH;
4106 if (idx[0] == 'h' && src[0] == 'h')
4107 instr->type = INSTR_REGWR_RHH;
4109 instr->regarray.regarray_id = r->id;
4110 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4111 instr->regarray.idx.n_bits = fidx->n_bits;
4112 instr->regarray.idx.offset = fidx->offset / 8;
4113 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4114 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4115 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4119 /* REGWR_RHI, REGWR_RMI. */
4120 if (fidx && !fsrc) {
4121 CHECK(!fidx->var_size, EINVAL);
4123 src_val = strtoull(src, &src, 0);
4124 CHECK(!src[0], EINVAL);
4126 instr->type = INSTR_REGWR_RMI;
4128 instr->type = INSTR_REGWR_RHI;
4130 instr->regarray.regarray_id = r->id;
4131 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4132 instr->regarray.idx.n_bits = fidx->n_bits;
4133 instr->regarray.idx.offset = fidx->offset / 8;
4134 instr->regarray.dstsrc_val = src_val;
4138 /* REGWR_RIH, REGWR_RIM. */
4139 if (!fidx && fsrc) {
4140 idx_val = strtoul(idx, &idx, 0);
4141 CHECK(!idx[0], EINVAL);
4143 CHECK(!fsrc->var_size, EINVAL);
4145 instr->type = INSTR_REGWR_RIM;
4147 instr->type = INSTR_REGWR_RIH;
4149 instr->regarray.regarray_id = r->id;
4150 instr->regarray.idx_val = idx_val;
4151 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4152 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4153 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4158 src_val = strtoull(src, &src, 0);
4159 CHECK(!src[0], EINVAL);
4161 idx_val = strtoul(idx, &idx, 0);
4162 CHECK(!idx[0], EINVAL);
4164 instr->type = INSTR_REGWR_RII;
4165 instr->regarray.idx_val = idx_val;
4166 instr->regarray.dstsrc_val = src_val;
4172 instr_regadd_translate(struct rte_swx_pipeline *p,
4173 struct action *action,
4176 struct instruction *instr,
4177 struct instruction_data *data __rte_unused)
4179 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
4181 struct field *fidx, *fsrc;
4183 uint32_t idx_struct_id, idx_val, src_struct_id;
4185 CHECK(n_tokens == 4, EINVAL);
4187 r = regarray_find(p, regarray);
4190 /* REGADD_RHH, REGADD_RHM, REGADD_RMH, REGADD_RMM. */
4191 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4192 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4194 CHECK(!fidx->var_size, EINVAL);
4195 CHECK(!fsrc->var_size, EINVAL);
4197 instr->type = INSTR_REGADD_RMM;
4198 if (idx[0] == 'h' && src[0] != 'h')
4199 instr->type = INSTR_REGADD_RHM;
4200 if (idx[0] != 'h' && src[0] == 'h')
4201 instr->type = INSTR_REGADD_RMH;
4202 if (idx[0] == 'h' && src[0] == 'h')
4203 instr->type = INSTR_REGADD_RHH;
4205 instr->regarray.regarray_id = r->id;
4206 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4207 instr->regarray.idx.n_bits = fidx->n_bits;
4208 instr->regarray.idx.offset = fidx->offset / 8;
4209 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4210 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4211 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4215 /* REGADD_RHI, REGADD_RMI. */
4216 if (fidx && !fsrc) {
4217 CHECK(!fidx->var_size, EINVAL);
4219 src_val = strtoull(src, &src, 0);
4220 CHECK(!src[0], EINVAL);
4222 instr->type = INSTR_REGADD_RMI;
4224 instr->type = INSTR_REGADD_RHI;
4226 instr->regarray.regarray_id = r->id;
4227 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4228 instr->regarray.idx.n_bits = fidx->n_bits;
4229 instr->regarray.idx.offset = fidx->offset / 8;
4230 instr->regarray.dstsrc_val = src_val;
4234 /* REGADD_RIH, REGADD_RIM. */
4235 if (!fidx && fsrc) {
4236 idx_val = strtoul(idx, &idx, 0);
4237 CHECK(!idx[0], EINVAL);
4239 CHECK(!fsrc->var_size, EINVAL);
4241 instr->type = INSTR_REGADD_RIM;
4243 instr->type = INSTR_REGADD_RIH;
4245 instr->regarray.regarray_id = r->id;
4246 instr->regarray.idx_val = idx_val;
4247 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4248 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4249 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4254 src_val = strtoull(src, &src, 0);
4255 CHECK(!src[0], EINVAL);
4257 idx_val = strtoul(idx, &idx, 0);
4258 CHECK(!idx[0], EINVAL);
4260 instr->type = INSTR_REGADD_RII;
4261 instr->regarray.idx_val = idx_val;
4262 instr->regarray.dstsrc_val = src_val;
4266 static inline uint64_t *
4267 instr_regarray_regarray(struct rte_swx_pipeline *p, struct instruction *ip)
4269 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4273 static inline uint64_t
4274 instr_regarray_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
4276 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4278 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
4279 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
4280 uint64_t idx64 = *idx64_ptr;
4281 uint64_t idx64_mask = UINT64_MAX >> (64 - ip->regarray.idx.n_bits);
4282 uint64_t idx = idx64 & idx64_mask & r->size_mask;
4287 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4289 static inline uint64_t
4290 instr_regarray_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
4292 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4294 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
4295 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
4296 uint64_t idx64 = *idx64_ptr;
4297 uint64_t idx = (ntoh64(idx64) >> (64 - ip->regarray.idx.n_bits)) & r->size_mask;
4304 #define instr_regarray_idx_nbo instr_regarray_idx_hbo
4308 static inline uint64_t
4309 instr_regarray_idx_imm(struct rte_swx_pipeline *p, struct instruction *ip)
4311 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4313 uint64_t idx = ip->regarray.idx_val & r->size_mask;
4318 static inline uint64_t
4319 instr_regarray_src_hbo(struct thread *t, struct instruction *ip)
4321 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
4322 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
4323 uint64_t src64 = *src64_ptr;
4324 uint64_t src64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
4325 uint64_t src = src64 & src64_mask;
4330 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4332 static inline uint64_t
4333 instr_regarray_src_nbo(struct thread *t, struct instruction *ip)
4335 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
4336 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
4337 uint64_t src64 = *src64_ptr;
4338 uint64_t src = ntoh64(src64) >> (64 - ip->regarray.dstsrc.n_bits);
4345 #define instr_regarray_src_nbo instr_regarray_src_hbo
4350 instr_regarray_dst_hbo_src_hbo_set(struct thread *t, struct instruction *ip, uint64_t src)
4352 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
4353 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
4354 uint64_t dst64 = *dst64_ptr;
4355 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
4357 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
4361 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4364 instr_regarray_dst_nbo_src_hbo_set(struct thread *t, struct instruction *ip, uint64_t src)
4366 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
4367 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
4368 uint64_t dst64 = *dst64_ptr;
4369 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
4371 src = hton64(src) >> (64 - ip->regarray.dstsrc.n_bits);
4372 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
4377 #define instr_regarray_dst_nbo_src_hbo_set instr_regarray_dst_hbo_src_hbo_set
4382 instr_regprefetch_rh_exec(struct rte_swx_pipeline *p)
4384 struct thread *t = &p->threads[p->thread_id];
4385 struct instruction *ip = t->ip;
4386 uint64_t *regarray, idx;
4388 TRACE("[Thread %2u] regprefetch (r[h])\n", p->thread_id);
4391 regarray = instr_regarray_regarray(p, ip);
4392 idx = instr_regarray_idx_nbo(p, t, ip);
4393 rte_prefetch0(®array[idx]);
4400 instr_regprefetch_rm_exec(struct rte_swx_pipeline *p)
4402 struct thread *t = &p->threads[p->thread_id];
4403 struct instruction *ip = t->ip;
4404 uint64_t *regarray, idx;
4406 TRACE("[Thread %2u] regprefetch (r[m])\n", p->thread_id);
4409 regarray = instr_regarray_regarray(p, ip);
4410 idx = instr_regarray_idx_hbo(p, t, ip);
4411 rte_prefetch0(®array[idx]);
4418 instr_regprefetch_ri_exec(struct rte_swx_pipeline *p)
4420 struct thread *t = &p->threads[p->thread_id];
4421 struct instruction *ip = t->ip;
4422 uint64_t *regarray, idx;
4424 TRACE("[Thread %2u] regprefetch (r[i])\n", p->thread_id);
4427 regarray = instr_regarray_regarray(p, ip);
4428 idx = instr_regarray_idx_imm(p, ip);
4429 rte_prefetch0(®array[idx]);
4436 instr_regrd_hrh_exec(struct rte_swx_pipeline *p)
4438 struct thread *t = &p->threads[p->thread_id];
4439 struct instruction *ip = t->ip;
4440 uint64_t *regarray, idx;
4442 TRACE("[Thread %2u] regrd (h = r[h])\n", p->thread_id);
4445 regarray = instr_regarray_regarray(p, ip);
4446 idx = instr_regarray_idx_nbo(p, t, ip);
4447 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
4454 instr_regrd_hrm_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[m])\n", p->thread_id);
4463 regarray = instr_regarray_regarray(p, ip);
4464 idx = instr_regarray_idx_hbo(p, t, ip);
4465 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
4472 instr_regrd_mrh_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[h])\n", p->thread_id);
4481 regarray = instr_regarray_regarray(p, ip);
4482 idx = instr_regarray_idx_nbo(p, t, ip);
4483 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
4490 instr_regrd_mrm_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;
4497 regarray = instr_regarray_regarray(p, ip);
4498 idx = instr_regarray_idx_hbo(p, t, ip);
4499 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
4506 instr_regrd_hri_exec(struct rte_swx_pipeline *p)
4508 struct thread *t = &p->threads[p->thread_id];
4509 struct instruction *ip = t->ip;
4510 uint64_t *regarray, idx;
4512 TRACE("[Thread %2u] regrd (h = r[i])\n", p->thread_id);
4515 regarray = instr_regarray_regarray(p, ip);
4516 idx = instr_regarray_idx_imm(p, ip);
4517 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
4524 instr_regrd_mri_exec(struct rte_swx_pipeline *p)
4526 struct thread *t = &p->threads[p->thread_id];
4527 struct instruction *ip = t->ip;
4528 uint64_t *regarray, idx;
4530 TRACE("[Thread %2u] regrd (m = r[i])\n", p->thread_id);
4533 regarray = instr_regarray_regarray(p, ip);
4534 idx = instr_regarray_idx_imm(p, ip);
4535 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
4542 instr_regwr_rhh_exec(struct rte_swx_pipeline *p)
4544 struct thread *t = &p->threads[p->thread_id];
4545 struct instruction *ip = t->ip;
4546 uint64_t *regarray, idx, src;
4548 TRACE("[Thread %2u] regwr (r[h] = h)\n", p->thread_id);
4551 regarray = instr_regarray_regarray(p, ip);
4552 idx = instr_regarray_idx_nbo(p, t, ip);
4553 src = instr_regarray_src_nbo(t, ip);
4554 regarray[idx] = src;
4561 instr_regwr_rhm_exec(struct rte_swx_pipeline *p)
4563 struct thread *t = &p->threads[p->thread_id];
4564 struct instruction *ip = t->ip;
4565 uint64_t *regarray, idx, src;
4567 TRACE("[Thread %2u] regwr (r[h] = m)\n", p->thread_id);
4570 regarray = instr_regarray_regarray(p, ip);
4571 idx = instr_regarray_idx_nbo(p, t, ip);
4572 src = instr_regarray_src_hbo(t, ip);
4573 regarray[idx] = src;
4580 instr_regwr_rmh_exec(struct rte_swx_pipeline *p)
4582 struct thread *t = &p->threads[p->thread_id];
4583 struct instruction *ip = t->ip;
4584 uint64_t *regarray, idx, src;
4586 TRACE("[Thread %2u] regwr (r[m] = h)\n", p->thread_id);
4589 regarray = instr_regarray_regarray(p, ip);
4590 idx = instr_regarray_idx_hbo(p, t, ip);
4591 src = instr_regarray_src_nbo(t, ip);
4592 regarray[idx] = src;
4599 instr_regwr_rmm_exec(struct rte_swx_pipeline *p)
4601 struct thread *t = &p->threads[p->thread_id];
4602 struct instruction *ip = t->ip;
4603 uint64_t *regarray, idx, src;
4605 TRACE("[Thread %2u] regwr (r[m] = m)\n", p->thread_id);
4608 regarray = instr_regarray_regarray(p, ip);
4609 idx = instr_regarray_idx_hbo(p, t, ip);
4610 src = instr_regarray_src_hbo(t, ip);
4611 regarray[idx] = src;
4618 instr_regwr_rhi_exec(struct rte_swx_pipeline *p)
4620 struct thread *t = &p->threads[p->thread_id];
4621 struct instruction *ip = t->ip;
4622 uint64_t *regarray, idx, src;
4624 TRACE("[Thread %2u] regwr (r[h] = i)\n", p->thread_id);
4627 regarray = instr_regarray_regarray(p, ip);
4628 idx = instr_regarray_idx_nbo(p, t, ip);
4629 src = ip->regarray.dstsrc_val;
4630 regarray[idx] = src;
4637 instr_regwr_rmi_exec(struct rte_swx_pipeline *p)
4639 struct thread *t = &p->threads[p->thread_id];
4640 struct instruction *ip = t->ip;
4641 uint64_t *regarray, idx, src;
4643 TRACE("[Thread %2u] regwr (r[m] = i)\n", p->thread_id);
4646 regarray = instr_regarray_regarray(p, ip);
4647 idx = instr_regarray_idx_hbo(p, t, ip);
4648 src = ip->regarray.dstsrc_val;
4649 regarray[idx] = src;
4656 instr_regwr_rih_exec(struct rte_swx_pipeline *p)
4658 struct thread *t = &p->threads[p->thread_id];
4659 struct instruction *ip = t->ip;
4660 uint64_t *regarray, idx, src;
4662 TRACE("[Thread %2u] regwr (r[i] = h)\n", p->thread_id);
4665 regarray = instr_regarray_regarray(p, ip);
4666 idx = instr_regarray_idx_imm(p, ip);
4667 src = instr_regarray_src_nbo(t, ip);
4668 regarray[idx] = src;
4675 instr_regwr_rim_exec(struct rte_swx_pipeline *p)
4677 struct thread *t = &p->threads[p->thread_id];
4678 struct instruction *ip = t->ip;
4679 uint64_t *regarray, idx, src;
4681 TRACE("[Thread %2u] regwr (r[i] = m)\n", p->thread_id);
4684 regarray = instr_regarray_regarray(p, ip);
4685 idx = instr_regarray_idx_imm(p, ip);
4686 src = instr_regarray_src_hbo(t, ip);
4687 regarray[idx] = src;
4694 instr_regwr_rii_exec(struct rte_swx_pipeline *p)
4696 struct thread *t = &p->threads[p->thread_id];
4697 struct instruction *ip = t->ip;
4698 uint64_t *regarray, idx, src;
4700 TRACE("[Thread %2u] regwr (r[i] = i)\n", p->thread_id);
4703 regarray = instr_regarray_regarray(p, ip);
4704 idx = instr_regarray_idx_imm(p, ip);
4705 src = ip->regarray.dstsrc_val;
4706 regarray[idx] = src;
4713 instr_regadd_rhh_exec(struct rte_swx_pipeline *p)
4715 struct thread *t = &p->threads[p->thread_id];
4716 struct instruction *ip = t->ip;
4717 uint64_t *regarray, idx, src;
4719 TRACE("[Thread %2u] regadd (r[h] += h)\n", p->thread_id);
4722 regarray = instr_regarray_regarray(p, ip);
4723 idx = instr_regarray_idx_nbo(p, t, ip);
4724 src = instr_regarray_src_nbo(t, ip);
4725 regarray[idx] += src;
4732 instr_regadd_rhm_exec(struct rte_swx_pipeline *p)
4734 struct thread *t = &p->threads[p->thread_id];
4735 struct instruction *ip = t->ip;
4736 uint64_t *regarray, idx, src;
4738 TRACE("[Thread %2u] regadd (r[h] += m)\n", p->thread_id);
4741 regarray = instr_regarray_regarray(p, ip);
4742 idx = instr_regarray_idx_nbo(p, t, ip);
4743 src = instr_regarray_src_hbo(t, ip);
4744 regarray[idx] += src;
4751 instr_regadd_rmh_exec(struct rte_swx_pipeline *p)
4753 struct thread *t = &p->threads[p->thread_id];
4754 struct instruction *ip = t->ip;
4755 uint64_t *regarray, idx, src;
4757 TRACE("[Thread %2u] regadd (r[m] += h)\n", p->thread_id);
4760 regarray = instr_regarray_regarray(p, ip);
4761 idx = instr_regarray_idx_hbo(p, t, ip);
4762 src = instr_regarray_src_nbo(t, ip);
4763 regarray[idx] += src;
4770 instr_regadd_rmm_exec(struct rte_swx_pipeline *p)
4772 struct thread *t = &p->threads[p->thread_id];
4773 struct instruction *ip = t->ip;
4774 uint64_t *regarray, idx, src;
4776 TRACE("[Thread %2u] regadd (r[m] += m)\n", p->thread_id);
4779 regarray = instr_regarray_regarray(p, ip);
4780 idx = instr_regarray_idx_hbo(p, t, ip);
4781 src = instr_regarray_src_hbo(t, ip);
4782 regarray[idx] += src;
4789 instr_regadd_rhi_exec(struct rte_swx_pipeline *p)
4791 struct thread *t = &p->threads[p->thread_id];
4792 struct instruction *ip = t->ip;
4793 uint64_t *regarray, idx, src;
4795 TRACE("[Thread %2u] regadd (r[h] += i)\n", p->thread_id);
4798 regarray = instr_regarray_regarray(p, ip);
4799 idx = instr_regarray_idx_nbo(p, t, ip);
4800 src = ip->regarray.dstsrc_val;
4801 regarray[idx] += src;
4808 instr_regadd_rmi_exec(struct rte_swx_pipeline *p)
4810 struct thread *t = &p->threads[p->thread_id];
4811 struct instruction *ip = t->ip;
4812 uint64_t *regarray, idx, src;
4814 TRACE("[Thread %2u] regadd (r[m] += i)\n", p->thread_id);
4817 regarray = instr_regarray_regarray(p, ip);
4818 idx = instr_regarray_idx_hbo(p, t, ip);
4819 src = ip->regarray.dstsrc_val;
4820 regarray[idx] += src;
4827 instr_regadd_rih_exec(struct rte_swx_pipeline *p)
4829 struct thread *t = &p->threads[p->thread_id];
4830 struct instruction *ip = t->ip;
4831 uint64_t *regarray, idx, src;
4833 TRACE("[Thread %2u] regadd (r[i] += h)\n", p->thread_id);
4836 regarray = instr_regarray_regarray(p, ip);
4837 idx = instr_regarray_idx_imm(p, ip);
4838 src = instr_regarray_src_nbo(t, ip);
4839 regarray[idx] += src;
4846 instr_regadd_rim_exec(struct rte_swx_pipeline *p)
4848 struct thread *t = &p->threads[p->thread_id];
4849 struct instruction *ip = t->ip;
4850 uint64_t *regarray, idx, src;
4852 TRACE("[Thread %2u] regadd (r[i] += m)\n", p->thread_id);
4855 regarray = instr_regarray_regarray(p, ip);
4856 idx = instr_regarray_idx_imm(p, ip);
4857 src = instr_regarray_src_hbo(t, ip);
4858 regarray[idx] += src;
4865 instr_regadd_rii_exec(struct rte_swx_pipeline *p)
4867 struct thread *t = &p->threads[p->thread_id];
4868 struct instruction *ip = t->ip;
4869 uint64_t *regarray, idx, src;
4871 TRACE("[Thread %2u] regadd (r[i] += i)\n", p->thread_id);
4874 regarray = instr_regarray_regarray(p, ip);
4875 idx = instr_regarray_idx_imm(p, ip);
4876 src = ip->regarray.dstsrc_val;
4877 regarray[idx] += src;
4886 static struct metarray *
4887 metarray_find(struct rte_swx_pipeline *p, const char *name);
4890 instr_metprefetch_translate(struct rte_swx_pipeline *p,
4891 struct action *action,
4894 struct instruction *instr,
4895 struct instruction_data *data __rte_unused)
4897 char *metarray = tokens[1], *idx = tokens[2];
4900 uint32_t idx_struct_id, idx_val;
4902 CHECK(n_tokens == 3, EINVAL);
4904 m = metarray_find(p, metarray);
4907 /* METPREFETCH_H, METPREFETCH_M. */
4908 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4910 CHECK(!fidx->var_size, EINVAL);
4912 instr->type = INSTR_METPREFETCH_M;
4914 instr->type = INSTR_METPREFETCH_H;
4916 instr->meter.metarray_id = m->id;
4917 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4918 instr->meter.idx.n_bits = fidx->n_bits;
4919 instr->meter.idx.offset = fidx->offset / 8;
4923 /* METPREFETCH_I. */
4924 idx_val = strtoul(idx, &idx, 0);
4925 CHECK(!idx[0], EINVAL);
4927 instr->type = INSTR_METPREFETCH_I;
4928 instr->meter.metarray_id = m->id;
4929 instr->meter.idx_val = idx_val;
4934 instr_meter_translate(struct rte_swx_pipeline *p,
4935 struct action *action,
4938 struct instruction *instr,
4939 struct instruction_data *data __rte_unused)
4941 char *metarray = tokens[1], *idx = tokens[2], *length = tokens[3];
4942 char *color_in = tokens[4], *color_out = tokens[5];
4944 struct field *fidx, *flength, *fcin, *fcout;
4945 uint32_t idx_struct_id, length_struct_id;
4946 uint32_t color_in_struct_id, color_out_struct_id;
4948 CHECK(n_tokens == 6, EINVAL);
4950 m = metarray_find(p, metarray);
4953 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4955 flength = struct_field_parse(p, action, length, &length_struct_id);
4956 CHECK(flength, EINVAL);
4957 CHECK(!flength->var_size, EINVAL);
4959 fcin = struct_field_parse(p, action, color_in, &color_in_struct_id);
4961 fcout = struct_field_parse(p, NULL, color_out, &color_out_struct_id);
4962 CHECK(fcout, EINVAL);
4963 CHECK(!fcout->var_size, EINVAL);
4965 /* index = HMEFT, length = HMEFT, color_in = MEFT, color_out = MEF. */
4967 CHECK(!fidx->var_size, EINVAL);
4968 CHECK(!fcin->var_size, EINVAL);
4970 instr->type = INSTR_METER_MMM;
4971 if (idx[0] == 'h' && length[0] == 'h')
4972 instr->type = INSTR_METER_HHM;
4973 if (idx[0] == 'h' && length[0] != 'h')
4974 instr->type = INSTR_METER_HMM;
4975 if (idx[0] != 'h' && length[0] == 'h')
4976 instr->type = INSTR_METER_MHM;
4978 instr->meter.metarray_id = m->id;
4980 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4981 instr->meter.idx.n_bits = fidx->n_bits;
4982 instr->meter.idx.offset = fidx->offset / 8;
4984 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4985 instr->meter.length.n_bits = flength->n_bits;
4986 instr->meter.length.offset = flength->offset / 8;
4988 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
4989 instr->meter.color_in.n_bits = fcin->n_bits;
4990 instr->meter.color_in.offset = fcin->offset / 8;
4992 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4993 instr->meter.color_out.n_bits = fcout->n_bits;
4994 instr->meter.color_out.offset = fcout->offset / 8;
4999 /* index = HMEFT, length = HMEFT, color_in = I, color_out = MEF. */
5000 if (fidx && !fcin) {
5001 uint32_t color_in_val;
5003 CHECK(!fidx->var_size, EINVAL);
5005 color_in_val = strtoul(color_in, &color_in, 0);
5006 CHECK(!color_in[0], EINVAL);
5008 instr->type = INSTR_METER_MMI;
5009 if (idx[0] == 'h' && length[0] == 'h')
5010 instr->type = INSTR_METER_HHI;
5011 if (idx[0] == 'h' && length[0] != 'h')
5012 instr->type = INSTR_METER_HMI;
5013 if (idx[0] != 'h' && length[0] == 'h')
5014 instr->type = INSTR_METER_MHI;
5016 instr->meter.metarray_id = m->id;
5018 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
5019 instr->meter.idx.n_bits = fidx->n_bits;
5020 instr->meter.idx.offset = fidx->offset / 8;
5022 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5023 instr->meter.length.n_bits = flength->n_bits;
5024 instr->meter.length.offset = flength->offset / 8;
5026 instr->meter.color_in_val = color_in_val;
5028 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5029 instr->meter.color_out.n_bits = fcout->n_bits;
5030 instr->meter.color_out.offset = fcout->offset / 8;
5035 /* index = I, length = HMEFT, color_in = MEFT, color_out = MEF. */
5036 if (!fidx && fcin) {
5039 idx_val = strtoul(idx, &idx, 0);
5040 CHECK(!idx[0], EINVAL);
5042 CHECK(!fcin->var_size, EINVAL);
5044 instr->type = INSTR_METER_IMM;
5045 if (length[0] == 'h')
5046 instr->type = INSTR_METER_IHM;
5048 instr->meter.metarray_id = m->id;
5050 instr->meter.idx_val = idx_val;
5052 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5053 instr->meter.length.n_bits = flength->n_bits;
5054 instr->meter.length.offset = flength->offset / 8;
5056 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
5057 instr->meter.color_in.n_bits = fcin->n_bits;
5058 instr->meter.color_in.offset = fcin->offset / 8;
5060 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5061 instr->meter.color_out.n_bits = fcout->n_bits;
5062 instr->meter.color_out.offset = fcout->offset / 8;
5067 /* index = I, length = HMEFT, color_in = I, color_out = MEF. */
5068 if (!fidx && !fcin) {
5069 uint32_t idx_val, color_in_val;
5071 idx_val = strtoul(idx, &idx, 0);
5072 CHECK(!idx[0], EINVAL);
5074 color_in_val = strtoul(color_in, &color_in, 0);
5075 CHECK(!color_in[0], EINVAL);
5077 instr->type = INSTR_METER_IMI;
5078 if (length[0] == 'h')
5079 instr->type = INSTR_METER_IHI;
5081 instr->meter.metarray_id = m->id;
5083 instr->meter.idx_val = idx_val;
5085 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5086 instr->meter.length.n_bits = flength->n_bits;
5087 instr->meter.length.offset = flength->offset / 8;
5089 instr->meter.color_in_val = color_in_val;
5091 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5092 instr->meter.color_out.n_bits = fcout->n_bits;
5093 instr->meter.color_out.offset = fcout->offset / 8;
5101 static inline struct meter *
5102 instr_meter_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
5104 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
5106 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
5107 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
5108 uint64_t idx64 = *idx64_ptr;
5109 uint64_t idx64_mask = UINT64_MAX >> (64 - (ip)->meter.idx.n_bits);
5110 uint64_t idx = idx64 & idx64_mask & r->size_mask;
5112 return &r->metarray[idx];
5115 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5117 static inline struct meter *
5118 instr_meter_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
5120 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
5122 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
5123 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
5124 uint64_t idx64 = *idx64_ptr;
5125 uint64_t idx = (ntoh64(idx64) >> (64 - ip->meter.idx.n_bits)) & r->size_mask;
5127 return &r->metarray[idx];
5132 #define instr_meter_idx_nbo instr_meter_idx_hbo
5136 static inline struct meter *
5137 instr_meter_idx_imm(struct rte_swx_pipeline *p, struct instruction *ip)
5139 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
5141 uint64_t idx = ip->meter.idx_val & r->size_mask;
5143 return &r->metarray[idx];
5146 static inline uint32_t
5147 instr_meter_length_hbo(struct thread *t, struct instruction *ip)
5149 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
5150 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
5151 uint64_t src64 = *src64_ptr;
5152 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->meter.length.n_bits);
5153 uint64_t src = src64 & src64_mask;
5155 return (uint32_t)src;
5158 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5160 static inline uint32_t
5161 instr_meter_length_nbo(struct thread *t, struct instruction *ip)
5163 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
5164 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
5165 uint64_t src64 = *src64_ptr;
5166 uint64_t src = ntoh64(src64) >> (64 - ip->meter.length.n_bits);
5168 return (uint32_t)src;
5173 #define instr_meter_length_nbo instr_meter_length_hbo
5177 static inline enum rte_color
5178 instr_meter_color_in_hbo(struct thread *t, struct instruction *ip)
5180 uint8_t *src_struct = t->structs[ip->meter.color_in.struct_id];
5181 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.color_in.offset];
5182 uint64_t src64 = *src64_ptr;
5183 uint64_t src64_mask = UINT64_MAX >> (64 - ip->meter.color_in.n_bits);
5184 uint64_t src = src64 & src64_mask;
5186 return (enum rte_color)src;
5190 instr_meter_color_out_hbo_set(struct thread *t, struct instruction *ip, enum rte_color color_out)
5192 uint8_t *dst_struct = t->structs[ip->meter.color_out.struct_id];
5193 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->meter.color_out.offset];
5194 uint64_t dst64 = *dst64_ptr;
5195 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->meter.color_out.n_bits);
5197 uint64_t src = (uint64_t)color_out;
5199 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
5203 instr_metprefetch_h_exec(struct rte_swx_pipeline *p)
5205 struct thread *t = &p->threads[p->thread_id];
5206 struct instruction *ip = t->ip;
5209 TRACE("[Thread %2u] metprefetch (h)\n", p->thread_id);
5212 m = instr_meter_idx_nbo(p, t, ip);
5220 instr_metprefetch_m_exec(struct rte_swx_pipeline *p)
5222 struct thread *t = &p->threads[p->thread_id];
5223 struct instruction *ip = t->ip;
5226 TRACE("[Thread %2u] metprefetch (m)\n", p->thread_id);
5229 m = instr_meter_idx_hbo(p, t, ip);
5237 instr_metprefetch_i_exec(struct rte_swx_pipeline *p)
5239 struct thread *t = &p->threads[p->thread_id];
5240 struct instruction *ip = t->ip;
5243 TRACE("[Thread %2u] metprefetch (i)\n", p->thread_id);
5246 m = instr_meter_idx_imm(p, ip);
5254 instr_meter_hhm_exec(struct rte_swx_pipeline *p)
5256 struct thread *t = &p->threads[p->thread_id];
5257 struct instruction *ip = t->ip;
5259 uint64_t time, n_pkts, n_bytes;
5261 enum rte_color color_in, color_out;
5263 TRACE("[Thread %2u] meter (hhm)\n", p->thread_id);
5266 m = instr_meter_idx_nbo(p, t, ip);
5267 rte_prefetch0(m->n_pkts);
5268 time = rte_get_tsc_cycles();
5269 length = instr_meter_length_nbo(t, ip);
5270 color_in = instr_meter_color_in_hbo(t, ip);
5272 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5273 &m->profile->profile,
5278 color_out &= m->color_mask;
5280 n_pkts = m->n_pkts[color_out];
5281 n_bytes = m->n_bytes[color_out];
5283 instr_meter_color_out_hbo_set(t, ip, color_out);
5285 m->n_pkts[color_out] = n_pkts + 1;
5286 m->n_bytes[color_out] = n_bytes + length;
5293 instr_meter_hhi_exec(struct rte_swx_pipeline *p)
5295 struct thread *t = &p->threads[p->thread_id];
5296 struct instruction *ip = t->ip;
5298 uint64_t time, n_pkts, n_bytes;
5300 enum rte_color color_in, color_out;
5302 TRACE("[Thread %2u] meter (hhi)\n", p->thread_id);
5305 m = instr_meter_idx_nbo(p, t, ip);
5306 rte_prefetch0(m->n_pkts);
5307 time = rte_get_tsc_cycles();
5308 length = instr_meter_length_nbo(t, ip);
5309 color_in = (enum rte_color)ip->meter.color_in_val;
5311 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5312 &m->profile->profile,
5317 color_out &= m->color_mask;
5319 n_pkts = m->n_pkts[color_out];
5320 n_bytes = m->n_bytes[color_out];
5322 instr_meter_color_out_hbo_set(t, ip, color_out);
5324 m->n_pkts[color_out] = n_pkts + 1;
5325 m->n_bytes[color_out] = n_bytes + length;
5332 instr_meter_hmm_exec(struct rte_swx_pipeline *p)
5334 struct thread *t = &p->threads[p->thread_id];
5335 struct instruction *ip = t->ip;
5337 uint64_t time, n_pkts, n_bytes;
5339 enum rte_color color_in, color_out;
5341 TRACE("[Thread %2u] meter (hmm)\n", p->thread_id);
5344 m = instr_meter_idx_nbo(p, t, ip);
5345 rte_prefetch0(m->n_pkts);
5346 time = rte_get_tsc_cycles();
5347 length = instr_meter_length_hbo(t, ip);
5348 color_in = instr_meter_color_in_hbo(t, ip);
5350 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5351 &m->profile->profile,
5356 color_out &= m->color_mask;
5358 n_pkts = m->n_pkts[color_out];
5359 n_bytes = m->n_bytes[color_out];
5361 instr_meter_color_out_hbo_set(t, ip, color_out);
5363 m->n_pkts[color_out] = n_pkts + 1;
5364 m->n_bytes[color_out] = n_bytes + length;
5370 instr_meter_hmi_exec(struct rte_swx_pipeline *p)
5372 struct thread *t = &p->threads[p->thread_id];
5373 struct instruction *ip = t->ip;
5375 uint64_t time, n_pkts, n_bytes;
5377 enum rte_color color_in, color_out;
5379 TRACE("[Thread %2u] meter (hmi)\n", p->thread_id);
5382 m = instr_meter_idx_nbo(p, t, ip);
5383 rte_prefetch0(m->n_pkts);
5384 time = rte_get_tsc_cycles();
5385 length = instr_meter_length_hbo(t, ip);
5386 color_in = (enum rte_color)ip->meter.color_in_val;
5388 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5389 &m->profile->profile,
5394 color_out &= m->color_mask;
5396 n_pkts = m->n_pkts[color_out];
5397 n_bytes = m->n_bytes[color_out];
5399 instr_meter_color_out_hbo_set(t, ip, color_out);
5401 m->n_pkts[color_out] = n_pkts + 1;
5402 m->n_bytes[color_out] = n_bytes + length;
5409 instr_meter_mhm_exec(struct rte_swx_pipeline *p)
5411 struct thread *t = &p->threads[p->thread_id];
5412 struct instruction *ip = t->ip;
5414 uint64_t time, n_pkts, n_bytes;
5416 enum rte_color color_in, color_out;
5418 TRACE("[Thread %2u] meter (mhm)\n", p->thread_id);
5421 m = instr_meter_idx_hbo(p, t, ip);
5422 rte_prefetch0(m->n_pkts);
5423 time = rte_get_tsc_cycles();
5424 length = instr_meter_length_nbo(t, ip);
5425 color_in = instr_meter_color_in_hbo(t, ip);
5427 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5428 &m->profile->profile,
5433 color_out &= m->color_mask;
5435 n_pkts = m->n_pkts[color_out];
5436 n_bytes = m->n_bytes[color_out];
5438 instr_meter_color_out_hbo_set(t, ip, color_out);
5440 m->n_pkts[color_out] = n_pkts + 1;
5441 m->n_bytes[color_out] = n_bytes + length;
5448 instr_meter_mhi_exec(struct rte_swx_pipeline *p)
5450 struct thread *t = &p->threads[p->thread_id];
5451 struct instruction *ip = t->ip;
5453 uint64_t time, n_pkts, n_bytes;
5455 enum rte_color color_in, color_out;
5457 TRACE("[Thread %2u] meter (mhi)\n", p->thread_id);
5460 m = instr_meter_idx_hbo(p, t, ip);
5461 rte_prefetch0(m->n_pkts);
5462 time = rte_get_tsc_cycles();
5463 length = instr_meter_length_nbo(t, ip);
5464 color_in = (enum rte_color)ip->meter.color_in_val;
5466 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5467 &m->profile->profile,
5472 color_out &= m->color_mask;
5474 n_pkts = m->n_pkts[color_out];
5475 n_bytes = m->n_bytes[color_out];
5477 instr_meter_color_out_hbo_set(t, ip, color_out);
5479 m->n_pkts[color_out] = n_pkts + 1;
5480 m->n_bytes[color_out] = n_bytes + length;
5487 instr_meter_mmm_exec(struct rte_swx_pipeline *p)
5489 struct thread *t = &p->threads[p->thread_id];
5490 struct instruction *ip = t->ip;
5492 uint64_t time, n_pkts, n_bytes;
5494 enum rte_color color_in, color_out;
5496 TRACE("[Thread %2u] meter (mmm)\n", p->thread_id);
5499 m = instr_meter_idx_hbo(p, t, ip);
5500 rte_prefetch0(m->n_pkts);
5501 time = rte_get_tsc_cycles();
5502 length = instr_meter_length_hbo(t, ip);
5503 color_in = instr_meter_color_in_hbo(t, ip);
5505 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5506 &m->profile->profile,
5511 color_out &= m->color_mask;
5513 n_pkts = m->n_pkts[color_out];
5514 n_bytes = m->n_bytes[color_out];
5516 instr_meter_color_out_hbo_set(t, ip, color_out);
5518 m->n_pkts[color_out] = n_pkts + 1;
5519 m->n_bytes[color_out] = n_bytes + length;
5526 instr_meter_mmi_exec(struct rte_swx_pipeline *p)
5528 struct thread *t = &p->threads[p->thread_id];
5529 struct instruction *ip = t->ip;
5531 uint64_t time, n_pkts, n_bytes;
5533 enum rte_color color_in, color_out;
5535 TRACE("[Thread %2u] meter (mmi)\n", p->thread_id);
5538 m = instr_meter_idx_hbo(p, t, ip);
5539 rte_prefetch0(m->n_pkts);
5540 time = rte_get_tsc_cycles();
5541 length = instr_meter_length_hbo(t, ip);
5542 color_in = (enum rte_color)ip->meter.color_in_val;
5544 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5545 &m->profile->profile,
5550 color_out &= m->color_mask;
5552 n_pkts = m->n_pkts[color_out];
5553 n_bytes = m->n_bytes[color_out];
5555 instr_meter_color_out_hbo_set(t, ip, color_out);
5557 m->n_pkts[color_out] = n_pkts + 1;
5558 m->n_bytes[color_out] = n_bytes + length;
5565 instr_meter_ihm_exec(struct rte_swx_pipeline *p)
5567 struct thread *t = &p->threads[p->thread_id];
5568 struct instruction *ip = t->ip;
5570 uint64_t time, n_pkts, n_bytes;
5572 enum rte_color color_in, color_out;
5574 TRACE("[Thread %2u] meter (ihm)\n", p->thread_id);
5577 m = instr_meter_idx_imm(p, ip);
5578 rte_prefetch0(m->n_pkts);
5579 time = rte_get_tsc_cycles();
5580 length = instr_meter_length_nbo(t, ip);
5581 color_in = instr_meter_color_in_hbo(t, ip);
5583 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5584 &m->profile->profile,
5589 color_out &= m->color_mask;
5591 n_pkts = m->n_pkts[color_out];
5592 n_bytes = m->n_bytes[color_out];
5594 instr_meter_color_out_hbo_set(t, ip, color_out);
5596 m->n_pkts[color_out] = n_pkts + 1;
5597 m->n_bytes[color_out] = n_bytes + length;
5604 instr_meter_ihi_exec(struct rte_swx_pipeline *p)
5606 struct thread *t = &p->threads[p->thread_id];
5607 struct instruction *ip = t->ip;
5609 uint64_t time, n_pkts, n_bytes;
5611 enum rte_color color_in, color_out;
5613 TRACE("[Thread %2u] meter (ihi)\n", p->thread_id);
5616 m = instr_meter_idx_imm(p, ip);
5617 rte_prefetch0(m->n_pkts);
5618 time = rte_get_tsc_cycles();
5619 length = instr_meter_length_nbo(t, ip);
5620 color_in = (enum rte_color)ip->meter.color_in_val;
5622 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5623 &m->profile->profile,
5628 color_out &= m->color_mask;
5630 n_pkts = m->n_pkts[color_out];
5631 n_bytes = m->n_bytes[color_out];
5633 instr_meter_color_out_hbo_set(t, ip, color_out);
5635 m->n_pkts[color_out] = n_pkts + 1;
5636 m->n_bytes[color_out] = n_bytes + length;
5643 instr_meter_imm_exec(struct rte_swx_pipeline *p)
5645 struct thread *t = &p->threads[p->thread_id];
5646 struct instruction *ip = t->ip;
5648 uint64_t time, n_pkts, n_bytes;
5650 enum rte_color color_in, color_out;
5652 TRACE("[Thread %2u] meter (imm)\n", p->thread_id);
5655 m = instr_meter_idx_imm(p, ip);
5656 rte_prefetch0(m->n_pkts);
5657 time = rte_get_tsc_cycles();
5658 length = instr_meter_length_hbo(t, ip);
5659 color_in = instr_meter_color_in_hbo(t, ip);
5661 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5662 &m->profile->profile,
5667 color_out &= m->color_mask;
5669 n_pkts = m->n_pkts[color_out];
5670 n_bytes = m->n_bytes[color_out];
5672 instr_meter_color_out_hbo_set(t, ip, color_out);
5674 m->n_pkts[color_out] = n_pkts + 1;
5675 m->n_bytes[color_out] = n_bytes + length;
5681 instr_meter_imi_exec(struct rte_swx_pipeline *p)
5683 struct thread *t = &p->threads[p->thread_id];
5684 struct instruction *ip = t->ip;
5686 uint64_t time, n_pkts, n_bytes;
5688 enum rte_color color_in, color_out;
5690 TRACE("[Thread %2u] meter (imi)\n", p->thread_id);
5693 m = instr_meter_idx_imm(p, ip);
5694 rte_prefetch0(m->n_pkts);
5695 time = rte_get_tsc_cycles();
5696 length = instr_meter_length_hbo(t, ip);
5697 color_in = (enum rte_color)ip->meter.color_in_val;
5699 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5700 &m->profile->profile,
5705 color_out &= m->color_mask;
5707 n_pkts = m->n_pkts[color_out];
5708 n_bytes = m->n_bytes[color_out];
5710 instr_meter_color_out_hbo_set(t, ip, color_out);
5712 m->n_pkts[color_out] = n_pkts + 1;
5713 m->n_bytes[color_out] = n_bytes + length;
5723 instr_jmp_translate(struct rte_swx_pipeline *p __rte_unused,
5724 struct action *action __rte_unused,
5727 struct instruction *instr,
5728 struct instruction_data *data)
5730 CHECK(n_tokens == 2, EINVAL);
5732 strcpy(data->jmp_label, tokens[1]);
5734 instr->type = INSTR_JMP;
5735 instr->jmp.ip = NULL; /* Resolved later. */
5740 instr_jmp_valid_translate(struct rte_swx_pipeline *p,
5741 struct action *action __rte_unused,
5744 struct instruction *instr,
5745 struct instruction_data *data)
5749 CHECK(n_tokens == 3, EINVAL);
5751 strcpy(data->jmp_label, tokens[1]);
5753 h = header_parse(p, tokens[2]);
5756 instr->type = INSTR_JMP_VALID;
5757 instr->jmp.ip = NULL; /* Resolved later. */
5758 instr->jmp.header_id = h->id;
5763 instr_jmp_invalid_translate(struct rte_swx_pipeline *p,
5764 struct action *action __rte_unused,
5767 struct instruction *instr,
5768 struct instruction_data *data)
5772 CHECK(n_tokens == 3, EINVAL);
5774 strcpy(data->jmp_label, tokens[1]);
5776 h = header_parse(p, tokens[2]);
5779 instr->type = INSTR_JMP_INVALID;
5780 instr->jmp.ip = NULL; /* Resolved later. */
5781 instr->jmp.header_id = h->id;
5786 instr_jmp_hit_translate(struct rte_swx_pipeline *p __rte_unused,
5787 struct action *action,
5790 struct instruction *instr,
5791 struct instruction_data *data)
5793 CHECK(!action, EINVAL);
5794 CHECK(n_tokens == 2, EINVAL);
5796 strcpy(data->jmp_label, tokens[1]);
5798 instr->type = INSTR_JMP_HIT;
5799 instr->jmp.ip = NULL; /* Resolved later. */
5804 instr_jmp_miss_translate(struct rte_swx_pipeline *p __rte_unused,
5805 struct action *action,
5808 struct instruction *instr,
5809 struct instruction_data *data)
5811 CHECK(!action, EINVAL);
5812 CHECK(n_tokens == 2, EINVAL);
5814 strcpy(data->jmp_label, tokens[1]);
5816 instr->type = INSTR_JMP_MISS;
5817 instr->jmp.ip = NULL; /* Resolved later. */
5822 instr_jmp_action_hit_translate(struct rte_swx_pipeline *p,
5823 struct action *action,
5826 struct instruction *instr,
5827 struct instruction_data *data)
5831 CHECK(!action, EINVAL);
5832 CHECK(n_tokens == 3, EINVAL);
5834 strcpy(data->jmp_label, tokens[1]);
5836 a = action_find(p, tokens[2]);
5839 instr->type = INSTR_JMP_ACTION_HIT;
5840 instr->jmp.ip = NULL; /* Resolved later. */
5841 instr->jmp.action_id = a->id;
5846 instr_jmp_action_miss_translate(struct rte_swx_pipeline *p,
5847 struct action *action,
5850 struct instruction *instr,
5851 struct instruction_data *data)
5855 CHECK(!action, EINVAL);
5856 CHECK(n_tokens == 3, EINVAL);
5858 strcpy(data->jmp_label, tokens[1]);
5860 a = action_find(p, tokens[2]);
5863 instr->type = INSTR_JMP_ACTION_MISS;
5864 instr->jmp.ip = NULL; /* Resolved later. */
5865 instr->jmp.action_id = a->id;
5870 instr_jmp_eq_translate(struct rte_swx_pipeline *p,
5871 struct action *action,
5874 struct instruction *instr,
5875 struct instruction_data *data)
5877 char *a = tokens[2], *b = tokens[3];
5878 struct field *fa, *fb;
5880 uint32_t a_struct_id, b_struct_id;
5882 CHECK(n_tokens == 4, EINVAL);
5884 strcpy(data->jmp_label, tokens[1]);
5886 fa = struct_field_parse(p, action, a, &a_struct_id);
5888 CHECK(!fa->var_size, EINVAL);
5890 /* JMP_EQ, JMP_EQ_MH, JMP_EQ_HM, JMP_EQ_HH. */
5891 fb = struct_field_parse(p, action, b, &b_struct_id);
5893 CHECK(!fb->var_size, EINVAL);
5895 instr->type = INSTR_JMP_EQ;
5896 if (a[0] != 'h' && b[0] == 'h')
5897 instr->type = INSTR_JMP_EQ_MH;
5898 if (a[0] == 'h' && b[0] != 'h')
5899 instr->type = INSTR_JMP_EQ_HM;
5900 if (a[0] == 'h' && b[0] == 'h')
5901 instr->type = INSTR_JMP_EQ_HH;
5902 instr->jmp.ip = NULL; /* Resolved later. */
5904 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5905 instr->jmp.a.n_bits = fa->n_bits;
5906 instr->jmp.a.offset = fa->offset / 8;
5907 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5908 instr->jmp.b.n_bits = fb->n_bits;
5909 instr->jmp.b.offset = fb->offset / 8;
5914 b_val = strtoull(b, &b, 0);
5915 CHECK(!b[0], EINVAL);
5918 b_val = hton64(b_val) >> (64 - fa->n_bits);
5920 instr->type = INSTR_JMP_EQ_I;
5921 instr->jmp.ip = NULL; /* Resolved later. */
5922 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5923 instr->jmp.a.n_bits = fa->n_bits;
5924 instr->jmp.a.offset = fa->offset / 8;
5925 instr->jmp.b_val = b_val;
5930 instr_jmp_neq_translate(struct rte_swx_pipeline *p,
5931 struct action *action,
5934 struct instruction *instr,
5935 struct instruction_data *data)
5937 char *a = tokens[2], *b = tokens[3];
5938 struct field *fa, *fb;
5940 uint32_t a_struct_id, b_struct_id;
5942 CHECK(n_tokens == 4, EINVAL);
5944 strcpy(data->jmp_label, tokens[1]);
5946 fa = struct_field_parse(p, action, a, &a_struct_id);
5948 CHECK(!fa->var_size, EINVAL);
5950 /* JMP_NEQ, JMP_NEQ_MH, JMP_NEQ_HM, JMP_NEQ_HH. */
5951 fb = struct_field_parse(p, action, b, &b_struct_id);
5953 CHECK(!fb->var_size, EINVAL);
5955 instr->type = INSTR_JMP_NEQ;
5956 if (a[0] != 'h' && b[0] == 'h')
5957 instr->type = INSTR_JMP_NEQ_MH;
5958 if (a[0] == 'h' && b[0] != 'h')
5959 instr->type = INSTR_JMP_NEQ_HM;
5960 if (a[0] == 'h' && b[0] == 'h')
5961 instr->type = INSTR_JMP_NEQ_HH;
5962 instr->jmp.ip = NULL; /* Resolved later. */
5964 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5965 instr->jmp.a.n_bits = fa->n_bits;
5966 instr->jmp.a.offset = fa->offset / 8;
5967 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5968 instr->jmp.b.n_bits = fb->n_bits;
5969 instr->jmp.b.offset = fb->offset / 8;
5974 b_val = strtoull(b, &b, 0);
5975 CHECK(!b[0], EINVAL);
5978 b_val = hton64(b_val) >> (64 - fa->n_bits);
5980 instr->type = INSTR_JMP_NEQ_I;
5981 instr->jmp.ip = NULL; /* Resolved later. */
5982 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5983 instr->jmp.a.n_bits = fa->n_bits;
5984 instr->jmp.a.offset = fa->offset / 8;
5985 instr->jmp.b_val = b_val;
5990 instr_jmp_lt_translate(struct rte_swx_pipeline *p,
5991 struct action *action,
5994 struct instruction *instr,
5995 struct instruction_data *data)
5997 char *a = tokens[2], *b = tokens[3];
5998 struct field *fa, *fb;
6000 uint32_t a_struct_id, b_struct_id;
6002 CHECK(n_tokens == 4, EINVAL);
6004 strcpy(data->jmp_label, tokens[1]);
6006 fa = struct_field_parse(p, action, a, &a_struct_id);
6008 CHECK(!fa->var_size, EINVAL);
6010 /* JMP_LT, JMP_LT_MH, JMP_LT_HM, JMP_LT_HH. */
6011 fb = struct_field_parse(p, action, b, &b_struct_id);
6013 CHECK(!fb->var_size, EINVAL);
6015 instr->type = INSTR_JMP_LT;
6016 if (a[0] == 'h' && b[0] != 'h')
6017 instr->type = INSTR_JMP_LT_HM;
6018 if (a[0] != 'h' && b[0] == 'h')
6019 instr->type = INSTR_JMP_LT_MH;
6020 if (a[0] == 'h' && b[0] == 'h')
6021 instr->type = INSTR_JMP_LT_HH;
6022 instr->jmp.ip = NULL; /* Resolved later. */
6024 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6025 instr->jmp.a.n_bits = fa->n_bits;
6026 instr->jmp.a.offset = fa->offset / 8;
6027 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6028 instr->jmp.b.n_bits = fb->n_bits;
6029 instr->jmp.b.offset = fb->offset / 8;
6033 /* JMP_LT_MI, JMP_LT_HI. */
6034 b_val = strtoull(b, &b, 0);
6035 CHECK(!b[0], EINVAL);
6037 instr->type = INSTR_JMP_LT_MI;
6039 instr->type = INSTR_JMP_LT_HI;
6040 instr->jmp.ip = NULL; /* Resolved later. */
6042 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6043 instr->jmp.a.n_bits = fa->n_bits;
6044 instr->jmp.a.offset = fa->offset / 8;
6045 instr->jmp.b_val = b_val;
6050 instr_jmp_gt_translate(struct rte_swx_pipeline *p,
6051 struct action *action,
6054 struct instruction *instr,
6055 struct instruction_data *data)
6057 char *a = tokens[2], *b = tokens[3];
6058 struct field *fa, *fb;
6060 uint32_t a_struct_id, b_struct_id;
6062 CHECK(n_tokens == 4, EINVAL);
6064 strcpy(data->jmp_label, tokens[1]);
6066 fa = struct_field_parse(p, action, a, &a_struct_id);
6068 CHECK(!fa->var_size, EINVAL);
6070 /* JMP_GT, JMP_GT_MH, JMP_GT_HM, JMP_GT_HH. */
6071 fb = struct_field_parse(p, action, b, &b_struct_id);
6073 CHECK(!fb->var_size, EINVAL);
6075 instr->type = INSTR_JMP_GT;
6076 if (a[0] == 'h' && b[0] != 'h')
6077 instr->type = INSTR_JMP_GT_HM;
6078 if (a[0] != 'h' && b[0] == 'h')
6079 instr->type = INSTR_JMP_GT_MH;
6080 if (a[0] == 'h' && b[0] == 'h')
6081 instr->type = INSTR_JMP_GT_HH;
6082 instr->jmp.ip = NULL; /* Resolved later. */
6084 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6085 instr->jmp.a.n_bits = fa->n_bits;
6086 instr->jmp.a.offset = fa->offset / 8;
6087 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6088 instr->jmp.b.n_bits = fb->n_bits;
6089 instr->jmp.b.offset = fb->offset / 8;
6093 /* JMP_GT_MI, JMP_GT_HI. */
6094 b_val = strtoull(b, &b, 0);
6095 CHECK(!b[0], EINVAL);
6097 instr->type = INSTR_JMP_GT_MI;
6099 instr->type = INSTR_JMP_GT_HI;
6100 instr->jmp.ip = NULL; /* Resolved later. */
6102 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6103 instr->jmp.a.n_bits = fa->n_bits;
6104 instr->jmp.a.offset = fa->offset / 8;
6105 instr->jmp.b_val = b_val;
6110 instr_jmp_exec(struct rte_swx_pipeline *p)
6112 struct thread *t = &p->threads[p->thread_id];
6113 struct instruction *ip = t->ip;
6115 TRACE("[Thread %2u] jmp\n", p->thread_id);
6117 thread_ip_set(t, ip->jmp.ip);
6121 instr_jmp_valid_exec(struct rte_swx_pipeline *p)
6123 struct thread *t = &p->threads[p->thread_id];
6124 struct instruction *ip = t->ip;
6125 uint32_t header_id = ip->jmp.header_id;
6127 TRACE("[Thread %2u] jmpv\n", p->thread_id);
6129 t->ip = HEADER_VALID(t, header_id) ? ip->jmp.ip : (t->ip + 1);
6133 instr_jmp_invalid_exec(struct rte_swx_pipeline *p)
6135 struct thread *t = &p->threads[p->thread_id];
6136 struct instruction *ip = t->ip;
6137 uint32_t header_id = ip->jmp.header_id;
6139 TRACE("[Thread %2u] jmpnv\n", p->thread_id);
6141 t->ip = HEADER_VALID(t, header_id) ? (t->ip + 1) : ip->jmp.ip;
6145 instr_jmp_hit_exec(struct rte_swx_pipeline *p)
6147 struct thread *t = &p->threads[p->thread_id];
6148 struct instruction *ip = t->ip;
6149 struct instruction *ip_next[] = {t->ip + 1, ip->jmp.ip};
6151 TRACE("[Thread %2u] jmph\n", p->thread_id);
6153 t->ip = ip_next[t->hit];
6157 instr_jmp_miss_exec(struct rte_swx_pipeline *p)
6159 struct thread *t = &p->threads[p->thread_id];
6160 struct instruction *ip = t->ip;
6161 struct instruction *ip_next[] = {ip->jmp.ip, t->ip + 1};
6163 TRACE("[Thread %2u] jmpnh\n", p->thread_id);
6165 t->ip = ip_next[t->hit];
6169 instr_jmp_action_hit_exec(struct rte_swx_pipeline *p)
6171 struct thread *t = &p->threads[p->thread_id];
6172 struct instruction *ip = t->ip;
6174 TRACE("[Thread %2u] jmpa\n", p->thread_id);
6176 t->ip = (ip->jmp.action_id == t->action_id) ? ip->jmp.ip : (t->ip + 1);
6180 instr_jmp_action_miss_exec(struct rte_swx_pipeline *p)
6182 struct thread *t = &p->threads[p->thread_id];
6183 struct instruction *ip = t->ip;
6185 TRACE("[Thread %2u] jmpna\n", p->thread_id);
6187 t->ip = (ip->jmp.action_id == t->action_id) ? (t->ip + 1) : ip->jmp.ip;
6191 instr_jmp_eq_exec(struct rte_swx_pipeline *p)
6193 struct thread *t = &p->threads[p->thread_id];
6194 struct instruction *ip = t->ip;
6196 TRACE("[Thread %2u] jmpeq\n", p->thread_id);
6202 instr_jmp_eq_mh_exec(struct rte_swx_pipeline *p)
6204 struct thread *t = &p->threads[p->thread_id];
6205 struct instruction *ip = t->ip;
6207 TRACE("[Thread %2u] jmpeq (mh)\n", p->thread_id);
6209 JMP_CMP_MH(t, ip, ==);
6213 instr_jmp_eq_hm_exec(struct rte_swx_pipeline *p)
6215 struct thread *t = &p->threads[p->thread_id];
6216 struct instruction *ip = t->ip;
6218 TRACE("[Thread %2u] jmpeq (hm)\n", p->thread_id);
6220 JMP_CMP_HM(t, ip, ==);
6224 instr_jmp_eq_hh_exec(struct rte_swx_pipeline *p)
6226 struct thread *t = &p->threads[p->thread_id];
6227 struct instruction *ip = t->ip;
6229 TRACE("[Thread %2u] jmpeq (hh)\n", p->thread_id);
6231 JMP_CMP_HH_FAST(t, ip, ==);
6235 instr_jmp_eq_i_exec(struct rte_swx_pipeline *p)
6237 struct thread *t = &p->threads[p->thread_id];
6238 struct instruction *ip = t->ip;
6240 TRACE("[Thread %2u] jmpeq (i)\n", p->thread_id);
6242 JMP_CMP_I(t, ip, ==);
6246 instr_jmp_neq_exec(struct rte_swx_pipeline *p)
6248 struct thread *t = &p->threads[p->thread_id];
6249 struct instruction *ip = t->ip;
6251 TRACE("[Thread %2u] jmpneq\n", p->thread_id);
6257 instr_jmp_neq_mh_exec(struct rte_swx_pipeline *p)
6259 struct thread *t = &p->threads[p->thread_id];
6260 struct instruction *ip = t->ip;
6262 TRACE("[Thread %2u] jmpneq (mh)\n", p->thread_id);
6264 JMP_CMP_MH(t, ip, !=);
6268 instr_jmp_neq_hm_exec(struct rte_swx_pipeline *p)
6270 struct thread *t = &p->threads[p->thread_id];
6271 struct instruction *ip = t->ip;
6273 TRACE("[Thread %2u] jmpneq (hm)\n", p->thread_id);
6275 JMP_CMP_HM(t, ip, !=);
6279 instr_jmp_neq_hh_exec(struct rte_swx_pipeline *p)
6281 struct thread *t = &p->threads[p->thread_id];
6282 struct instruction *ip = t->ip;
6284 TRACE("[Thread %2u] jmpneq (hh)\n", p->thread_id);
6286 JMP_CMP_HH_FAST(t, ip, !=);
6290 instr_jmp_neq_i_exec(struct rte_swx_pipeline *p)
6292 struct thread *t = &p->threads[p->thread_id];
6293 struct instruction *ip = t->ip;
6295 TRACE("[Thread %2u] jmpneq (i)\n", p->thread_id);
6297 JMP_CMP_I(t, ip, !=);
6301 instr_jmp_lt_exec(struct rte_swx_pipeline *p)
6303 struct thread *t = &p->threads[p->thread_id];
6304 struct instruction *ip = t->ip;
6306 TRACE("[Thread %2u] jmplt\n", p->thread_id);
6312 instr_jmp_lt_mh_exec(struct rte_swx_pipeline *p)
6314 struct thread *t = &p->threads[p->thread_id];
6315 struct instruction *ip = t->ip;
6317 TRACE("[Thread %2u] jmplt (mh)\n", p->thread_id);
6319 JMP_CMP_MH(t, ip, <);
6323 instr_jmp_lt_hm_exec(struct rte_swx_pipeline *p)
6325 struct thread *t = &p->threads[p->thread_id];
6326 struct instruction *ip = t->ip;
6328 TRACE("[Thread %2u] jmplt (hm)\n", p->thread_id);
6330 JMP_CMP_HM(t, ip, <);
6334 instr_jmp_lt_hh_exec(struct rte_swx_pipeline *p)
6336 struct thread *t = &p->threads[p->thread_id];
6337 struct instruction *ip = t->ip;
6339 TRACE("[Thread %2u] jmplt (hh)\n", p->thread_id);
6341 JMP_CMP_HH(t, ip, <);
6345 instr_jmp_lt_mi_exec(struct rte_swx_pipeline *p)
6347 struct thread *t = &p->threads[p->thread_id];
6348 struct instruction *ip = t->ip;
6350 TRACE("[Thread %2u] jmplt (mi)\n", p->thread_id);
6352 JMP_CMP_MI(t, ip, <);
6356 instr_jmp_lt_hi_exec(struct rte_swx_pipeline *p)
6358 struct thread *t = &p->threads[p->thread_id];
6359 struct instruction *ip = t->ip;
6361 TRACE("[Thread %2u] jmplt (hi)\n", p->thread_id);
6363 JMP_CMP_HI(t, ip, <);
6367 instr_jmp_gt_exec(struct rte_swx_pipeline *p)
6369 struct thread *t = &p->threads[p->thread_id];
6370 struct instruction *ip = t->ip;
6372 TRACE("[Thread %2u] jmpgt\n", p->thread_id);
6378 instr_jmp_gt_mh_exec(struct rte_swx_pipeline *p)
6380 struct thread *t = &p->threads[p->thread_id];
6381 struct instruction *ip = t->ip;
6383 TRACE("[Thread %2u] jmpgt (mh)\n", p->thread_id);
6385 JMP_CMP_MH(t, ip, >);
6389 instr_jmp_gt_hm_exec(struct rte_swx_pipeline *p)
6391 struct thread *t = &p->threads[p->thread_id];
6392 struct instruction *ip = t->ip;
6394 TRACE("[Thread %2u] jmpgt (hm)\n", p->thread_id);
6396 JMP_CMP_HM(t, ip, >);
6400 instr_jmp_gt_hh_exec(struct rte_swx_pipeline *p)
6402 struct thread *t = &p->threads[p->thread_id];
6403 struct instruction *ip = t->ip;
6405 TRACE("[Thread %2u] jmpgt (hh)\n", p->thread_id);
6407 JMP_CMP_HH(t, ip, >);
6411 instr_jmp_gt_mi_exec(struct rte_swx_pipeline *p)
6413 struct thread *t = &p->threads[p->thread_id];
6414 struct instruction *ip = t->ip;
6416 TRACE("[Thread %2u] jmpgt (mi)\n", p->thread_id);
6418 JMP_CMP_MI(t, ip, >);
6422 instr_jmp_gt_hi_exec(struct rte_swx_pipeline *p)
6424 struct thread *t = &p->threads[p->thread_id];
6425 struct instruction *ip = t->ip;
6427 TRACE("[Thread %2u] jmpgt (hi)\n", p->thread_id);
6429 JMP_CMP_HI(t, ip, >);
6436 instr_return_translate(struct rte_swx_pipeline *p __rte_unused,
6437 struct action *action,
6438 char **tokens __rte_unused,
6440 struct instruction *instr,
6441 struct instruction_data *data __rte_unused)
6443 CHECK(action, EINVAL);
6444 CHECK(n_tokens == 1, EINVAL);
6446 instr->type = INSTR_RETURN;
6451 instr_return_exec(struct rte_swx_pipeline *p)
6453 struct thread *t = &p->threads[p->thread_id];
6455 TRACE("[Thread %2u] return\n", p->thread_id);
6461 instr_translate(struct rte_swx_pipeline *p,
6462 struct action *action,
6464 struct instruction *instr,
6465 struct instruction_data *data)
6467 char *tokens[RTE_SWX_INSTRUCTION_TOKENS_MAX];
6468 int n_tokens = 0, tpos = 0;
6470 /* Parse the instruction string into tokens. */
6474 token = strtok_r(string, " \t\v", &string);
6478 CHECK(n_tokens < RTE_SWX_INSTRUCTION_TOKENS_MAX, EINVAL);
6479 CHECK_NAME(token, EINVAL);
6481 tokens[n_tokens] = token;
6485 CHECK(n_tokens, EINVAL);
6487 /* Handle the optional instruction label. */
6488 if ((n_tokens >= 2) && !strcmp(tokens[1], ":")) {
6489 strcpy(data->label, tokens[0]);
6492 CHECK(n_tokens - tpos, EINVAL);
6495 /* Identify the instruction type. */
6496 if (!strcmp(tokens[tpos], "rx"))
6497 return instr_rx_translate(p,
6504 if (!strcmp(tokens[tpos], "tx"))
6505 return instr_tx_translate(p,
6512 if (!strcmp(tokens[tpos], "drop"))
6513 return instr_drop_translate(p,
6520 if (!strcmp(tokens[tpos], "extract"))
6521 return instr_hdr_extract_translate(p,
6528 if (!strcmp(tokens[tpos], "lookahead"))
6529 return instr_hdr_lookahead_translate(p,
6536 if (!strcmp(tokens[tpos], "emit"))
6537 return instr_hdr_emit_translate(p,
6544 if (!strcmp(tokens[tpos], "validate"))
6545 return instr_hdr_validate_translate(p,
6552 if (!strcmp(tokens[tpos], "invalidate"))
6553 return instr_hdr_invalidate_translate(p,
6560 if (!strcmp(tokens[tpos], "mov"))
6561 return instr_mov_translate(p,
6568 if (!strcmp(tokens[tpos], "add"))
6569 return instr_alu_add_translate(p,
6576 if (!strcmp(tokens[tpos], "sub"))
6577 return instr_alu_sub_translate(p,
6584 if (!strcmp(tokens[tpos], "ckadd"))
6585 return instr_alu_ckadd_translate(p,
6592 if (!strcmp(tokens[tpos], "cksub"))
6593 return instr_alu_cksub_translate(p,
6600 if (!strcmp(tokens[tpos], "and"))
6601 return instr_alu_and_translate(p,
6608 if (!strcmp(tokens[tpos], "or"))
6609 return instr_alu_or_translate(p,
6616 if (!strcmp(tokens[tpos], "xor"))
6617 return instr_alu_xor_translate(p,
6624 if (!strcmp(tokens[tpos], "shl"))
6625 return instr_alu_shl_translate(p,
6632 if (!strcmp(tokens[tpos], "shr"))
6633 return instr_alu_shr_translate(p,
6640 if (!strcmp(tokens[tpos], "regprefetch"))
6641 return instr_regprefetch_translate(p,
6648 if (!strcmp(tokens[tpos], "regrd"))
6649 return instr_regrd_translate(p,
6656 if (!strcmp(tokens[tpos], "regwr"))
6657 return instr_regwr_translate(p,
6664 if (!strcmp(tokens[tpos], "regadd"))
6665 return instr_regadd_translate(p,
6672 if (!strcmp(tokens[tpos], "metprefetch"))
6673 return instr_metprefetch_translate(p,
6680 if (!strcmp(tokens[tpos], "meter"))
6681 return instr_meter_translate(p,
6688 if (!strcmp(tokens[tpos], "table"))
6689 return instr_table_translate(p,
6696 if (!strcmp(tokens[tpos], "learn"))
6697 return instr_learn_translate(p,
6704 if (!strcmp(tokens[tpos], "forget"))
6705 return instr_forget_translate(p,
6712 if (!strcmp(tokens[tpos], "extern"))
6713 return instr_extern_translate(p,
6720 if (!strcmp(tokens[tpos], "jmp"))
6721 return instr_jmp_translate(p,
6728 if (!strcmp(tokens[tpos], "jmpv"))
6729 return instr_jmp_valid_translate(p,
6736 if (!strcmp(tokens[tpos], "jmpnv"))
6737 return instr_jmp_invalid_translate(p,
6744 if (!strcmp(tokens[tpos], "jmph"))
6745 return instr_jmp_hit_translate(p,
6752 if (!strcmp(tokens[tpos], "jmpnh"))
6753 return instr_jmp_miss_translate(p,
6760 if (!strcmp(tokens[tpos], "jmpa"))
6761 return instr_jmp_action_hit_translate(p,
6768 if (!strcmp(tokens[tpos], "jmpna"))
6769 return instr_jmp_action_miss_translate(p,
6776 if (!strcmp(tokens[tpos], "jmpeq"))
6777 return instr_jmp_eq_translate(p,
6784 if (!strcmp(tokens[tpos], "jmpneq"))
6785 return instr_jmp_neq_translate(p,
6792 if (!strcmp(tokens[tpos], "jmplt"))
6793 return instr_jmp_lt_translate(p,
6800 if (!strcmp(tokens[tpos], "jmpgt"))
6801 return instr_jmp_gt_translate(p,
6808 if (!strcmp(tokens[tpos], "return"))
6809 return instr_return_translate(p,
6819 static struct instruction_data *
6820 label_find(struct instruction_data *data, uint32_t n, const char *label)
6824 for (i = 0; i < n; i++)
6825 if (!strcmp(label, data[i].label))
6832 label_is_used(struct instruction_data *data, uint32_t n, const char *label)
6834 uint32_t count = 0, i;
6839 for (i = 0; i < n; i++)
6840 if (!strcmp(label, data[i].jmp_label))
6847 instr_label_check(struct instruction_data *instruction_data,
6848 uint32_t n_instructions)
6852 /* Check that all instruction labels are unique. */
6853 for (i = 0; i < n_instructions; i++) {
6854 struct instruction_data *data = &instruction_data[i];
6855 char *label = data->label;
6861 for (j = i + 1; j < n_instructions; j++)
6862 CHECK(strcmp(label, data[j].label), EINVAL);
6865 /* Get users for each instruction label. */
6866 for (i = 0; i < n_instructions; i++) {
6867 struct instruction_data *data = &instruction_data[i];
6868 char *label = data->label;
6870 data->n_users = label_is_used(instruction_data,
6879 instr_jmp_resolve(struct instruction *instructions,
6880 struct instruction_data *instruction_data,
6881 uint32_t n_instructions)
6885 for (i = 0; i < n_instructions; i++) {
6886 struct instruction *instr = &instructions[i];
6887 struct instruction_data *data = &instruction_data[i];
6888 struct instruction_data *found;
6890 if (!instruction_is_jmp(instr))
6893 found = label_find(instruction_data,
6896 CHECK(found, EINVAL);
6898 instr->jmp.ip = &instructions[found - instruction_data];
6905 instr_verify(struct rte_swx_pipeline *p __rte_unused,
6907 struct instruction *instr,
6908 struct instruction_data *data __rte_unused,
6909 uint32_t n_instructions)
6912 enum instruction_type type;
6915 /* Check that the first instruction is rx. */
6916 CHECK(instr[0].type == INSTR_RX, EINVAL);
6918 /* Check that there is at least one tx instruction. */
6919 for (i = 0; i < n_instructions; i++) {
6920 type = instr[i].type;
6922 if (instruction_is_tx(type))
6925 CHECK(i < n_instructions, EINVAL);
6927 /* Check that the last instruction is either tx or unconditional
6930 type = instr[n_instructions - 1].type;
6931 CHECK(instruction_is_tx(type) || (type == INSTR_JMP), EINVAL);
6935 enum instruction_type type;
6938 /* Check that there is at least one return or tx instruction. */
6939 for (i = 0; i < n_instructions; i++) {
6940 type = instr[i].type;
6942 if ((type == INSTR_RETURN) || instruction_is_tx(type))
6945 CHECK(i < n_instructions, EINVAL);
6952 instr_compact(struct instruction *instructions,
6953 struct instruction_data *instruction_data,
6954 uint32_t n_instructions)
6956 uint32_t i, pos = 0;
6958 /* Eliminate the invalid instructions that have been optimized out. */
6959 for (i = 0; i < n_instructions; i++) {
6960 struct instruction *instr = &instructions[i];
6961 struct instruction_data *data = &instruction_data[i];
6967 memcpy(&instructions[pos], instr, sizeof(*instr));
6968 memcpy(&instruction_data[pos], data, sizeof(*data));
6978 instr_pattern_extract_many_search(struct instruction *instr,
6979 struct instruction_data *data,
6981 uint32_t *n_pattern_instr)
6985 for (i = 0; i < n_instr; i++) {
6986 if (data[i].invalid)
6989 if (instr[i].type != INSTR_HDR_EXTRACT)
6992 if (i == RTE_DIM(instr->io.hdr.header_id))
6995 if (i && data[i].n_users)
7002 *n_pattern_instr = i;
7007 instr_pattern_extract_many_replace(struct instruction *instr,
7008 struct instruction_data *data,
7013 for (i = 1; i < n_instr; i++) {
7015 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
7016 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
7017 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
7019 data[i].invalid = 1;
7024 instr_pattern_extract_many_optimize(struct instruction *instructions,
7025 struct instruction_data *instruction_data,
7026 uint32_t n_instructions)
7030 for (i = 0; i < n_instructions; ) {
7031 struct instruction *instr = &instructions[i];
7032 struct instruction_data *data = &instruction_data[i];
7033 uint32_t n_instr = 0;
7037 detected = instr_pattern_extract_many_search(instr,
7042 instr_pattern_extract_many_replace(instr,
7049 /* No pattern starting at the current instruction. */
7053 /* Eliminate the invalid instructions that have been optimized out. */
7054 n_instructions = instr_compact(instructions,
7058 return n_instructions;
7062 instr_pattern_emit_many_tx_search(struct instruction *instr,
7063 struct instruction_data *data,
7065 uint32_t *n_pattern_instr)
7069 for (i = 0; i < n_instr; i++) {
7070 if (data[i].invalid)
7073 if (instr[i].type != INSTR_HDR_EMIT)
7076 if (i == RTE_DIM(instr->io.hdr.header_id))
7079 if (i && data[i].n_users)
7086 if (!instruction_is_tx(instr[i].type))
7089 if (data[i].n_users)
7094 *n_pattern_instr = i;
7099 instr_pattern_emit_many_tx_replace(struct instruction *instr,
7100 struct instruction_data *data,
7105 /* Any emit instruction in addition to the first one. */
7106 for (i = 1; i < n_instr - 1; i++) {
7108 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
7109 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
7110 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
7112 data[i].invalid = 1;
7115 /* The TX instruction is the last one in the pattern. */
7117 instr[0].io.io.offset = instr[i].io.io.offset;
7118 instr[0].io.io.n_bits = instr[i].io.io.n_bits;
7119 data[i].invalid = 1;
7123 instr_pattern_emit_many_tx_optimize(struct instruction *instructions,
7124 struct instruction_data *instruction_data,
7125 uint32_t n_instructions)
7129 for (i = 0; i < n_instructions; ) {
7130 struct instruction *instr = &instructions[i];
7131 struct instruction_data *data = &instruction_data[i];
7132 uint32_t n_instr = 0;
7135 /* Emit many + TX. */
7136 detected = instr_pattern_emit_many_tx_search(instr,
7141 instr_pattern_emit_many_tx_replace(instr,
7148 /* No pattern starting at the current instruction. */
7152 /* Eliminate the invalid instructions that have been optimized out. */
7153 n_instructions = instr_compact(instructions,
7157 return n_instructions;
7161 action_arg_src_mov_count(struct action *a,
7163 struct instruction *instructions,
7164 struct instruction_data *instruction_data,
7165 uint32_t n_instructions);
7168 instr_pattern_mov_all_validate_search(struct rte_swx_pipeline *p,
7170 struct instruction *instr,
7171 struct instruction_data *data,
7173 struct instruction *instructions,
7174 struct instruction_data *instruction_data,
7175 uint32_t n_instructions,
7176 uint32_t *n_pattern_instr)
7179 uint32_t src_field_id, i, j;
7181 /* Prerequisites. */
7185 /* First instruction: MOV_HM. */
7186 if (data[0].invalid || (instr[0].type != INSTR_MOV_HM))
7189 h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
7190 if (!h || h->st->var_size)
7193 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
7194 if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
7197 if (src_field_id == a->st->n_fields)
7200 if (instr[0].mov.dst.offset ||
7201 (instr[0].mov.dst.n_bits != h->st->fields[0].n_bits) ||
7202 instr[0].mov.src.struct_id ||
7203 (instr[0].mov.src.n_bits != a->st->fields[src_field_id].n_bits) ||
7204 (instr[0].mov.dst.n_bits != instr[0].mov.src.n_bits))
7207 if ((n_instr < h->st->n_fields + 1) ||
7208 (a->st->n_fields < src_field_id + h->st->n_fields + 1))
7211 /* Subsequent instructions: MOV_HM. */
7212 for (i = 1; i < h->st->n_fields; i++)
7213 if (data[i].invalid ||
7215 (instr[i].type != INSTR_MOV_HM) ||
7216 (instr[i].mov.dst.struct_id != h->struct_id) ||
7217 (instr[i].mov.dst.offset != h->st->fields[i].offset / 8) ||
7218 (instr[i].mov.dst.n_bits != h->st->fields[i].n_bits) ||
7219 instr[i].mov.src.struct_id ||
7220 (instr[i].mov.src.offset != a->st->fields[src_field_id + i].offset / 8) ||
7221 (instr[i].mov.src.n_bits != a->st->fields[src_field_id + i].n_bits) ||
7222 (instr[i].mov.dst.n_bits != instr[i].mov.src.n_bits))
7225 /* Last instruction: HDR_VALIDATE. */
7226 if ((instr[i].type != INSTR_HDR_VALIDATE) ||
7227 (instr[i].valid.header_id != h->id))
7230 /* Check that none of the action args that are used as source for this
7231 * DMA transfer are not used as source in any other mov instruction.
7233 for (j = src_field_id; j < src_field_id + h->st->n_fields; j++) {
7236 n_users = action_arg_src_mov_count(a,
7245 *n_pattern_instr = 1 + i;
7250 instr_pattern_mov_all_validate_replace(struct rte_swx_pipeline *p,
7252 struct instruction *instr,
7253 struct instruction_data *data,
7257 uint32_t src_field_id, src_offset, i;
7259 /* Read from the instructions before they are modified. */
7260 h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
7264 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
7265 if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
7268 if (src_field_id == a->st->n_fields)
7271 src_offset = instr[0].mov.src.offset;
7273 /* Modify the instructions. */
7274 instr[0].type = INSTR_DMA_HT;
7275 instr[0].dma.dst.header_id[0] = h->id;
7276 instr[0].dma.dst.struct_id[0] = h->struct_id;
7277 instr[0].dma.src.offset[0] = (uint8_t)src_offset;
7278 instr[0].dma.n_bytes[0] = h->st->n_bits / 8;
7280 for (i = 1; i < n_instr; i++)
7281 data[i].invalid = 1;
7283 /* Update the endianness of the action arguments to header endianness. */
7284 for (i = 0; i < h->st->n_fields; i++)
7285 a->args_endianness[src_field_id + i] = 1;
7289 instr_pattern_mov_all_validate_optimize(struct rte_swx_pipeline *p,
7291 struct instruction *instructions,
7292 struct instruction_data *instruction_data,
7293 uint32_t n_instructions)
7298 return n_instructions;
7300 for (i = 0; i < n_instructions; ) {
7301 struct instruction *instr = &instructions[i];
7302 struct instruction_data *data = &instruction_data[i];
7303 uint32_t n_instr = 0;
7306 /* Mov all + validate. */
7307 detected = instr_pattern_mov_all_validate_search(p,
7317 instr_pattern_mov_all_validate_replace(p, a, instr, data, n_instr);
7322 /* No pattern starting at the current instruction. */
7326 /* Eliminate the invalid instructions that have been optimized out. */
7327 n_instructions = instr_compact(instructions,
7331 return n_instructions;
7335 instr_pattern_dma_many_search(struct instruction *instr,
7336 struct instruction_data *data,
7338 uint32_t *n_pattern_instr)
7342 for (i = 0; i < n_instr; i++) {
7343 if (data[i].invalid)
7346 if (instr[i].type != INSTR_DMA_HT)
7349 if (i == RTE_DIM(instr->dma.dst.header_id))
7352 if (i && data[i].n_users)
7359 *n_pattern_instr = i;
7364 instr_pattern_dma_many_replace(struct instruction *instr,
7365 struct instruction_data *data,
7370 for (i = 1; i < n_instr; i++) {
7372 instr[0].dma.dst.header_id[i] = instr[i].dma.dst.header_id[0];
7373 instr[0].dma.dst.struct_id[i] = instr[i].dma.dst.struct_id[0];
7374 instr[0].dma.src.offset[i] = instr[i].dma.src.offset[0];
7375 instr[0].dma.n_bytes[i] = instr[i].dma.n_bytes[0];
7377 data[i].invalid = 1;
7382 instr_pattern_dma_many_optimize(struct instruction *instructions,
7383 struct instruction_data *instruction_data,
7384 uint32_t n_instructions)
7388 for (i = 0; i < n_instructions; ) {
7389 struct instruction *instr = &instructions[i];
7390 struct instruction_data *data = &instruction_data[i];
7391 uint32_t n_instr = 0;
7395 detected = instr_pattern_dma_many_search(instr,
7400 instr_pattern_dma_many_replace(instr, data, n_instr);
7405 /* No pattern starting at the current instruction. */
7409 /* Eliminate the invalid instructions that have been optimized out. */
7410 n_instructions = instr_compact(instructions,
7414 return n_instructions;
7418 instr_optimize(struct rte_swx_pipeline *p,
7420 struct instruction *instructions,
7421 struct instruction_data *instruction_data,
7422 uint32_t n_instructions)
7425 n_instructions = instr_pattern_extract_many_optimize(instructions,
7429 /* Emit many + TX. */
7430 n_instructions = instr_pattern_emit_many_tx_optimize(instructions,
7434 /* Mov all + validate. */
7435 n_instructions = instr_pattern_mov_all_validate_optimize(p,
7442 n_instructions = instr_pattern_dma_many_optimize(instructions,
7446 return n_instructions;
7450 instruction_config(struct rte_swx_pipeline *p,
7452 const char **instructions,
7453 uint32_t n_instructions)
7455 struct instruction *instr = NULL;
7456 struct instruction_data *data = NULL;
7460 CHECK(n_instructions, EINVAL);
7461 CHECK(instructions, EINVAL);
7462 for (i = 0; i < n_instructions; i++)
7463 CHECK_INSTRUCTION(instructions[i], EINVAL);
7465 /* Memory allocation. */
7466 instr = calloc(n_instructions, sizeof(struct instruction));
7472 data = calloc(n_instructions, sizeof(struct instruction_data));
7478 for (i = 0; i < n_instructions; i++) {
7479 char *string = strdup(instructions[i]);
7485 err = instr_translate(p, a, string, &instr[i], &data[i]);
7494 err = instr_label_check(data, n_instructions);
7498 err = instr_verify(p, a, instr, data, n_instructions);
7502 n_instructions = instr_optimize(p, a, instr, data, n_instructions);
7504 err = instr_jmp_resolve(instr, data, n_instructions);
7509 a->instructions = instr;
7510 a->n_instructions = n_instructions;
7512 p->instructions = instr;
7513 p->n_instructions = n_instructions;
7525 typedef void (*instr_exec_t)(struct rte_swx_pipeline *);
7527 static instr_exec_t instruction_table[] = {
7528 [INSTR_RX] = instr_rx_exec,
7529 [INSTR_TX] = instr_tx_exec,
7530 [INSTR_TX_I] = instr_tx_i_exec,
7532 [INSTR_HDR_EXTRACT] = instr_hdr_extract_exec,
7533 [INSTR_HDR_EXTRACT2] = instr_hdr_extract2_exec,
7534 [INSTR_HDR_EXTRACT3] = instr_hdr_extract3_exec,
7535 [INSTR_HDR_EXTRACT4] = instr_hdr_extract4_exec,
7536 [INSTR_HDR_EXTRACT5] = instr_hdr_extract5_exec,
7537 [INSTR_HDR_EXTRACT6] = instr_hdr_extract6_exec,
7538 [INSTR_HDR_EXTRACT7] = instr_hdr_extract7_exec,
7539 [INSTR_HDR_EXTRACT8] = instr_hdr_extract8_exec,
7540 [INSTR_HDR_EXTRACT_M] = instr_hdr_extract_m_exec,
7541 [INSTR_HDR_LOOKAHEAD] = instr_hdr_lookahead_exec,
7543 [INSTR_HDR_EMIT] = instr_hdr_emit_exec,
7544 [INSTR_HDR_EMIT_TX] = instr_hdr_emit_tx_exec,
7545 [INSTR_HDR_EMIT2_TX] = instr_hdr_emit2_tx_exec,
7546 [INSTR_HDR_EMIT3_TX] = instr_hdr_emit3_tx_exec,
7547 [INSTR_HDR_EMIT4_TX] = instr_hdr_emit4_tx_exec,
7548 [INSTR_HDR_EMIT5_TX] = instr_hdr_emit5_tx_exec,
7549 [INSTR_HDR_EMIT6_TX] = instr_hdr_emit6_tx_exec,
7550 [INSTR_HDR_EMIT7_TX] = instr_hdr_emit7_tx_exec,
7551 [INSTR_HDR_EMIT8_TX] = instr_hdr_emit8_tx_exec,
7553 [INSTR_HDR_VALIDATE] = instr_hdr_validate_exec,
7554 [INSTR_HDR_INVALIDATE] = instr_hdr_invalidate_exec,
7556 [INSTR_MOV] = instr_mov_exec,
7557 [INSTR_MOV_MH] = instr_mov_mh_exec,
7558 [INSTR_MOV_HM] = instr_mov_hm_exec,
7559 [INSTR_MOV_HH] = instr_mov_hh_exec,
7560 [INSTR_MOV_I] = instr_mov_i_exec,
7562 [INSTR_DMA_HT] = instr_dma_ht_exec,
7563 [INSTR_DMA_HT2] = instr_dma_ht2_exec,
7564 [INSTR_DMA_HT3] = instr_dma_ht3_exec,
7565 [INSTR_DMA_HT4] = instr_dma_ht4_exec,
7566 [INSTR_DMA_HT5] = instr_dma_ht5_exec,
7567 [INSTR_DMA_HT6] = instr_dma_ht6_exec,
7568 [INSTR_DMA_HT7] = instr_dma_ht7_exec,
7569 [INSTR_DMA_HT8] = instr_dma_ht8_exec,
7571 [INSTR_ALU_ADD] = instr_alu_add_exec,
7572 [INSTR_ALU_ADD_MH] = instr_alu_add_mh_exec,
7573 [INSTR_ALU_ADD_HM] = instr_alu_add_hm_exec,
7574 [INSTR_ALU_ADD_HH] = instr_alu_add_hh_exec,
7575 [INSTR_ALU_ADD_MI] = instr_alu_add_mi_exec,
7576 [INSTR_ALU_ADD_HI] = instr_alu_add_hi_exec,
7578 [INSTR_ALU_SUB] = instr_alu_sub_exec,
7579 [INSTR_ALU_SUB_MH] = instr_alu_sub_mh_exec,
7580 [INSTR_ALU_SUB_HM] = instr_alu_sub_hm_exec,
7581 [INSTR_ALU_SUB_HH] = instr_alu_sub_hh_exec,
7582 [INSTR_ALU_SUB_MI] = instr_alu_sub_mi_exec,
7583 [INSTR_ALU_SUB_HI] = instr_alu_sub_hi_exec,
7585 [INSTR_ALU_CKADD_FIELD] = instr_alu_ckadd_field_exec,
7586 [INSTR_ALU_CKADD_STRUCT] = instr_alu_ckadd_struct_exec,
7587 [INSTR_ALU_CKADD_STRUCT20] = instr_alu_ckadd_struct20_exec,
7588 [INSTR_ALU_CKSUB_FIELD] = instr_alu_cksub_field_exec,
7590 [INSTR_ALU_AND] = instr_alu_and_exec,
7591 [INSTR_ALU_AND_MH] = instr_alu_and_mh_exec,
7592 [INSTR_ALU_AND_HM] = instr_alu_and_hm_exec,
7593 [INSTR_ALU_AND_HH] = instr_alu_and_hh_exec,
7594 [INSTR_ALU_AND_I] = instr_alu_and_i_exec,
7596 [INSTR_ALU_OR] = instr_alu_or_exec,
7597 [INSTR_ALU_OR_MH] = instr_alu_or_mh_exec,
7598 [INSTR_ALU_OR_HM] = instr_alu_or_hm_exec,
7599 [INSTR_ALU_OR_HH] = instr_alu_or_hh_exec,
7600 [INSTR_ALU_OR_I] = instr_alu_or_i_exec,
7602 [INSTR_ALU_XOR] = instr_alu_xor_exec,
7603 [INSTR_ALU_XOR_MH] = instr_alu_xor_mh_exec,
7604 [INSTR_ALU_XOR_HM] = instr_alu_xor_hm_exec,
7605 [INSTR_ALU_XOR_HH] = instr_alu_xor_hh_exec,
7606 [INSTR_ALU_XOR_I] = instr_alu_xor_i_exec,
7608 [INSTR_ALU_SHL] = instr_alu_shl_exec,
7609 [INSTR_ALU_SHL_MH] = instr_alu_shl_mh_exec,
7610 [INSTR_ALU_SHL_HM] = instr_alu_shl_hm_exec,
7611 [INSTR_ALU_SHL_HH] = instr_alu_shl_hh_exec,
7612 [INSTR_ALU_SHL_MI] = instr_alu_shl_mi_exec,
7613 [INSTR_ALU_SHL_HI] = instr_alu_shl_hi_exec,
7615 [INSTR_ALU_SHR] = instr_alu_shr_exec,
7616 [INSTR_ALU_SHR_MH] = instr_alu_shr_mh_exec,
7617 [INSTR_ALU_SHR_HM] = instr_alu_shr_hm_exec,
7618 [INSTR_ALU_SHR_HH] = instr_alu_shr_hh_exec,
7619 [INSTR_ALU_SHR_MI] = instr_alu_shr_mi_exec,
7620 [INSTR_ALU_SHR_HI] = instr_alu_shr_hi_exec,
7622 [INSTR_REGPREFETCH_RH] = instr_regprefetch_rh_exec,
7623 [INSTR_REGPREFETCH_RM] = instr_regprefetch_rm_exec,
7624 [INSTR_REGPREFETCH_RI] = instr_regprefetch_ri_exec,
7626 [INSTR_REGRD_HRH] = instr_regrd_hrh_exec,
7627 [INSTR_REGRD_HRM] = instr_regrd_hrm_exec,
7628 [INSTR_REGRD_MRH] = instr_regrd_mrh_exec,
7629 [INSTR_REGRD_MRM] = instr_regrd_mrm_exec,
7630 [INSTR_REGRD_HRI] = instr_regrd_hri_exec,
7631 [INSTR_REGRD_MRI] = instr_regrd_mri_exec,
7633 [INSTR_REGWR_RHH] = instr_regwr_rhh_exec,
7634 [INSTR_REGWR_RHM] = instr_regwr_rhm_exec,
7635 [INSTR_REGWR_RMH] = instr_regwr_rmh_exec,
7636 [INSTR_REGWR_RMM] = instr_regwr_rmm_exec,
7637 [INSTR_REGWR_RHI] = instr_regwr_rhi_exec,
7638 [INSTR_REGWR_RMI] = instr_regwr_rmi_exec,
7639 [INSTR_REGWR_RIH] = instr_regwr_rih_exec,
7640 [INSTR_REGWR_RIM] = instr_regwr_rim_exec,
7641 [INSTR_REGWR_RII] = instr_regwr_rii_exec,
7643 [INSTR_REGADD_RHH] = instr_regadd_rhh_exec,
7644 [INSTR_REGADD_RHM] = instr_regadd_rhm_exec,
7645 [INSTR_REGADD_RMH] = instr_regadd_rmh_exec,
7646 [INSTR_REGADD_RMM] = instr_regadd_rmm_exec,
7647 [INSTR_REGADD_RHI] = instr_regadd_rhi_exec,
7648 [INSTR_REGADD_RMI] = instr_regadd_rmi_exec,
7649 [INSTR_REGADD_RIH] = instr_regadd_rih_exec,
7650 [INSTR_REGADD_RIM] = instr_regadd_rim_exec,
7651 [INSTR_REGADD_RII] = instr_regadd_rii_exec,
7653 [INSTR_METPREFETCH_H] = instr_metprefetch_h_exec,
7654 [INSTR_METPREFETCH_M] = instr_metprefetch_m_exec,
7655 [INSTR_METPREFETCH_I] = instr_metprefetch_i_exec,
7657 [INSTR_METER_HHM] = instr_meter_hhm_exec,
7658 [INSTR_METER_HHI] = instr_meter_hhi_exec,
7659 [INSTR_METER_HMM] = instr_meter_hmm_exec,
7660 [INSTR_METER_HMI] = instr_meter_hmi_exec,
7661 [INSTR_METER_MHM] = instr_meter_mhm_exec,
7662 [INSTR_METER_MHI] = instr_meter_mhi_exec,
7663 [INSTR_METER_MMM] = instr_meter_mmm_exec,
7664 [INSTR_METER_MMI] = instr_meter_mmi_exec,
7665 [INSTR_METER_IHM] = instr_meter_ihm_exec,
7666 [INSTR_METER_IHI] = instr_meter_ihi_exec,
7667 [INSTR_METER_IMM] = instr_meter_imm_exec,
7668 [INSTR_METER_IMI] = instr_meter_imi_exec,
7670 [INSTR_TABLE] = instr_table_exec,
7671 [INSTR_SELECTOR] = instr_selector_exec,
7672 [INSTR_LEARNER] = instr_learner_exec,
7673 [INSTR_LEARNER_LEARN] = instr_learn_exec,
7674 [INSTR_LEARNER_FORGET] = instr_forget_exec,
7675 [INSTR_EXTERN_OBJ] = instr_extern_obj_exec,
7676 [INSTR_EXTERN_FUNC] = instr_extern_func_exec,
7678 [INSTR_JMP] = instr_jmp_exec,
7679 [INSTR_JMP_VALID] = instr_jmp_valid_exec,
7680 [INSTR_JMP_INVALID] = instr_jmp_invalid_exec,
7681 [INSTR_JMP_HIT] = instr_jmp_hit_exec,
7682 [INSTR_JMP_MISS] = instr_jmp_miss_exec,
7683 [INSTR_JMP_ACTION_HIT] = instr_jmp_action_hit_exec,
7684 [INSTR_JMP_ACTION_MISS] = instr_jmp_action_miss_exec,
7686 [INSTR_JMP_EQ] = instr_jmp_eq_exec,
7687 [INSTR_JMP_EQ_MH] = instr_jmp_eq_mh_exec,
7688 [INSTR_JMP_EQ_HM] = instr_jmp_eq_hm_exec,
7689 [INSTR_JMP_EQ_HH] = instr_jmp_eq_hh_exec,
7690 [INSTR_JMP_EQ_I] = instr_jmp_eq_i_exec,
7692 [INSTR_JMP_NEQ] = instr_jmp_neq_exec,
7693 [INSTR_JMP_NEQ_MH] = instr_jmp_neq_mh_exec,
7694 [INSTR_JMP_NEQ_HM] = instr_jmp_neq_hm_exec,
7695 [INSTR_JMP_NEQ_HH] = instr_jmp_neq_hh_exec,
7696 [INSTR_JMP_NEQ_I] = instr_jmp_neq_i_exec,
7698 [INSTR_JMP_LT] = instr_jmp_lt_exec,
7699 [INSTR_JMP_LT_MH] = instr_jmp_lt_mh_exec,
7700 [INSTR_JMP_LT_HM] = instr_jmp_lt_hm_exec,
7701 [INSTR_JMP_LT_HH] = instr_jmp_lt_hh_exec,
7702 [INSTR_JMP_LT_MI] = instr_jmp_lt_mi_exec,
7703 [INSTR_JMP_LT_HI] = instr_jmp_lt_hi_exec,
7705 [INSTR_JMP_GT] = instr_jmp_gt_exec,
7706 [INSTR_JMP_GT_MH] = instr_jmp_gt_mh_exec,
7707 [INSTR_JMP_GT_HM] = instr_jmp_gt_hm_exec,
7708 [INSTR_JMP_GT_HH] = instr_jmp_gt_hh_exec,
7709 [INSTR_JMP_GT_MI] = instr_jmp_gt_mi_exec,
7710 [INSTR_JMP_GT_HI] = instr_jmp_gt_hi_exec,
7712 [INSTR_RETURN] = instr_return_exec,
7716 instr_exec(struct rte_swx_pipeline *p)
7718 struct thread *t = &p->threads[p->thread_id];
7719 struct instruction *ip = t->ip;
7720 instr_exec_t instr = instruction_table[ip->type];
7728 static struct action *
7729 action_find(struct rte_swx_pipeline *p, const char *name)
7731 struct action *elem;
7736 TAILQ_FOREACH(elem, &p->actions, node)
7737 if (strcmp(elem->name, name) == 0)
7743 static struct action *
7744 action_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7746 struct action *action = NULL;
7748 TAILQ_FOREACH(action, &p->actions, node)
7749 if (action->id == id)
7755 static struct field *
7756 action_field_find(struct action *a, const char *name)
7758 return a->st ? struct_type_field_find(a->st, name) : NULL;
7761 static struct field *
7762 action_field_parse(struct action *action, const char *name)
7764 if (name[0] != 't' || name[1] != '.')
7767 return action_field_find(action, &name[2]);
7771 action_has_nbo_args(struct action *a)
7775 /* Return if the action does not have any args. */
7777 return 0; /* FALSE */
7779 for (i = 0; i < a->st->n_fields; i++)
7780 if (a->args_endianness[i])
7781 return 1; /* TRUE */
7783 return 0; /* FALSE */
7787 action_does_learning(struct action *a)
7791 for (i = 0; i < a->n_instructions; i++)
7792 switch (a->instructions[i].type) {
7793 case INSTR_LEARNER_LEARN:
7794 return 1; /* TRUE */
7796 case INSTR_LEARNER_FORGET:
7797 return 1; /* TRUE */
7803 return 0; /* FALSE */
7807 rte_swx_pipeline_action_config(struct rte_swx_pipeline *p,
7809 const char *args_struct_type_name,
7810 const char **instructions,
7811 uint32_t n_instructions)
7813 struct struct_type *args_struct_type = NULL;
7819 CHECK_NAME(name, EINVAL);
7820 CHECK(!action_find(p, name), EEXIST);
7822 if (args_struct_type_name) {
7823 CHECK_NAME(args_struct_type_name, EINVAL);
7824 args_struct_type = struct_type_find(p, args_struct_type_name);
7825 CHECK(args_struct_type, EINVAL);
7826 CHECK(!args_struct_type->var_size, EINVAL);
7829 /* Node allocation. */
7830 a = calloc(1, sizeof(struct action));
7832 if (args_struct_type) {
7833 a->args_endianness = calloc(args_struct_type->n_fields, sizeof(int));
7834 if (!a->args_endianness) {
7840 /* Node initialization. */
7841 strcpy(a->name, name);
7842 a->st = args_struct_type;
7843 a->id = p->n_actions;
7845 /* Instruction translation. */
7846 err = instruction_config(p, a, instructions, n_instructions);
7848 free(a->args_endianness);
7853 /* Node add to tailq. */
7854 TAILQ_INSERT_TAIL(&p->actions, a, node);
7861 action_build(struct rte_swx_pipeline *p)
7863 struct action *action;
7865 p->action_instructions = calloc(p->n_actions,
7866 sizeof(struct instruction *));
7867 CHECK(p->action_instructions, ENOMEM);
7869 TAILQ_FOREACH(action, &p->actions, node)
7870 p->action_instructions[action->id] = action->instructions;
7876 action_build_free(struct rte_swx_pipeline *p)
7878 free(p->action_instructions);
7879 p->action_instructions = NULL;
7883 action_free(struct rte_swx_pipeline *p)
7885 action_build_free(p);
7888 struct action *action;
7890 action = TAILQ_FIRST(&p->actions);
7894 TAILQ_REMOVE(&p->actions, action, node);
7895 free(action->instructions);
7901 action_arg_src_mov_count(struct action *a,
7903 struct instruction *instructions,
7904 struct instruction_data *instruction_data,
7905 uint32_t n_instructions)
7907 uint32_t offset, n_users = 0, i;
7910 (arg_id >= a->st->n_fields) ||
7912 !instruction_data ||
7916 offset = a->st->fields[arg_id].offset / 8;
7918 for (i = 0; i < n_instructions; i++) {
7919 struct instruction *instr = &instructions[i];
7920 struct instruction_data *data = &instruction_data[i];
7922 if (data->invalid ||
7923 ((instr->type != INSTR_MOV) && (instr->type != INSTR_MOV_HM)) ||
7924 instr->mov.src.struct_id ||
7925 (instr->mov.src.offset != offset))
7937 static struct table_type *
7938 table_type_find(struct rte_swx_pipeline *p, const char *name)
7940 struct table_type *elem;
7942 TAILQ_FOREACH(elem, &p->table_types, node)
7943 if (strcmp(elem->name, name) == 0)
7949 static struct table_type *
7950 table_type_resolve(struct rte_swx_pipeline *p,
7951 const char *recommended_type_name,
7952 enum rte_swx_table_match_type match_type)
7954 struct table_type *elem;
7956 /* Only consider the recommended type if the match type is correct. */
7957 if (recommended_type_name)
7958 TAILQ_FOREACH(elem, &p->table_types, node)
7959 if (!strcmp(elem->name, recommended_type_name) &&
7960 (elem->match_type == match_type))
7963 /* Ignore the recommended type and get the first element with this match
7966 TAILQ_FOREACH(elem, &p->table_types, node)
7967 if (elem->match_type == match_type)
7973 static struct table *
7974 table_find(struct rte_swx_pipeline *p, const char *name)
7978 TAILQ_FOREACH(elem, &p->tables, node)
7979 if (strcmp(elem->name, name) == 0)
7985 static struct table *
7986 table_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7988 struct table *table = NULL;
7990 TAILQ_FOREACH(table, &p->tables, node)
7991 if (table->id == id)
7998 rte_swx_pipeline_table_type_register(struct rte_swx_pipeline *p,
8000 enum rte_swx_table_match_type match_type,
8001 struct rte_swx_table_ops *ops)
8003 struct table_type *elem;
8007 CHECK_NAME(name, EINVAL);
8008 CHECK(!table_type_find(p, name), EEXIST);
8011 CHECK(ops->create, EINVAL);
8012 CHECK(ops->lkp, EINVAL);
8013 CHECK(ops->free, EINVAL);
8015 /* Node allocation. */
8016 elem = calloc(1, sizeof(struct table_type));
8017 CHECK(elem, ENOMEM);
8019 /* Node initialization. */
8020 strcpy(elem->name, name);
8021 elem->match_type = match_type;
8022 memcpy(&elem->ops, ops, sizeof(*ops));
8024 /* Node add to tailq. */
8025 TAILQ_INSERT_TAIL(&p->table_types, elem, node);
8031 table_match_type_resolve(struct rte_swx_match_field_params *fields,
8033 enum rte_swx_table_match_type *match_type)
8035 uint32_t n_fields_em = 0, n_fields_lpm = 0, i;
8037 for (i = 0; i < n_fields; i++) {
8038 struct rte_swx_match_field_params *f = &fields[i];
8040 if (f->match_type == RTE_SWX_TABLE_MATCH_EXACT)
8043 if (f->match_type == RTE_SWX_TABLE_MATCH_LPM)
8047 if ((n_fields_lpm > 1) ||
8048 (n_fields_lpm && (n_fields_em != n_fields - 1)))
8051 *match_type = (n_fields_em == n_fields) ?
8052 RTE_SWX_TABLE_MATCH_EXACT :
8053 RTE_SWX_TABLE_MATCH_WILDCARD;
8059 table_match_fields_check(struct rte_swx_pipeline *p,
8060 struct rte_swx_pipeline_table_params *params,
8061 struct header **header)
8063 struct header *h0 = NULL;
8064 struct field *hf, *mf;
8065 uint32_t *offset = NULL, i;
8068 /* Return if no match fields. */
8069 if (!params->n_fields) {
8070 if (params->fields) {
8081 /* Memory allocation. */
8082 offset = calloc(params->n_fields, sizeof(uint32_t));
8088 /* Check that all the match fields belong to either the same header or
8091 hf = header_field_parse(p, params->fields[0].name, &h0);
8092 mf = metadata_field_parse(p, params->fields[0].name);
8093 if ((!hf && !mf) || (hf && hf->var_size)) {
8098 offset[0] = h0 ? hf->offset : mf->offset;
8100 for (i = 1; i < params->n_fields; i++)
8104 hf = header_field_parse(p, params->fields[i].name, &h);
8105 if (!hf || (h->id != h0->id) || hf->var_size) {
8110 offset[i] = hf->offset;
8112 mf = metadata_field_parse(p, params->fields[i].name);
8118 offset[i] = mf->offset;
8121 /* Check that there are no duplicated match fields. */
8122 for (i = 0; i < params->n_fields; i++) {
8125 for (j = 0; j < i; j++)
8126 if (offset[j] == offset[i]) {
8142 rte_swx_pipeline_table_config(struct rte_swx_pipeline *p,
8144 struct rte_swx_pipeline_table_params *params,
8145 const char *recommended_table_type_name,
8149 struct table_type *type;
8151 struct action *default_action;
8152 struct header *header = NULL;
8153 uint32_t action_data_size_max = 0, i;
8158 CHECK_NAME(name, EINVAL);
8159 CHECK(!table_find(p, name), EEXIST);
8160 CHECK(!selector_find(p, name), EEXIST);
8161 CHECK(!learner_find(p, name), EEXIST);
8163 CHECK(params, EINVAL);
8166 status = table_match_fields_check(p, params, &header);
8170 /* Action checks. */
8171 CHECK(params->n_actions, EINVAL);
8172 CHECK(params->action_names, EINVAL);
8173 for (i = 0; i < params->n_actions; i++) {
8174 const char *action_name = params->action_names[i];
8176 uint32_t action_data_size;
8178 CHECK_NAME(action_name, EINVAL);
8180 a = action_find(p, action_name);
8182 CHECK(!action_does_learning(a), EINVAL);
8184 action_data_size = a->st ? a->st->n_bits / 8 : 0;
8185 if (action_data_size > action_data_size_max)
8186 action_data_size_max = action_data_size;
8189 CHECK_NAME(params->default_action_name, EINVAL);
8190 for (i = 0; i < p->n_actions; i++)
8191 if (!strcmp(params->action_names[i],
8192 params->default_action_name))
8194 CHECK(i < params->n_actions, EINVAL);
8195 default_action = action_find(p, params->default_action_name);
8196 CHECK((default_action->st && params->default_action_data) ||
8197 !params->default_action_data, EINVAL);
8199 /* Table type checks. */
8200 if (recommended_table_type_name)
8201 CHECK_NAME(recommended_table_type_name, EINVAL);
8203 if (params->n_fields) {
8204 enum rte_swx_table_match_type match_type;
8206 status = table_match_type_resolve(params->fields, params->n_fields, &match_type);
8210 type = table_type_resolve(p, recommended_table_type_name, match_type);
8211 CHECK(type, EINVAL);
8216 /* Memory allocation. */
8217 t = calloc(1, sizeof(struct table));
8220 t->fields = calloc(params->n_fields, sizeof(struct match_field));
8226 t->actions = calloc(params->n_actions, sizeof(struct action *));
8233 if (action_data_size_max) {
8234 t->default_action_data = calloc(1, action_data_size_max);
8235 if (!t->default_action_data) {
8243 /* Node initialization. */
8244 strcpy(t->name, name);
8245 if (args && args[0])
8246 strcpy(t->args, args);
8249 for (i = 0; i < params->n_fields; i++) {
8250 struct rte_swx_match_field_params *field = ¶ms->fields[i];
8251 struct match_field *f = &t->fields[i];
8253 f->match_type = field->match_type;
8255 header_field_parse(p, field->name, NULL) :
8256 metadata_field_parse(p, field->name);
8258 t->n_fields = params->n_fields;
8261 for (i = 0; i < params->n_actions; i++)
8262 t->actions[i] = action_find(p, params->action_names[i]);
8263 t->default_action = default_action;
8264 if (default_action->st)
8265 memcpy(t->default_action_data,
8266 params->default_action_data,
8267 default_action->st->n_bits / 8);
8268 t->n_actions = params->n_actions;
8269 t->default_action_is_const = params->default_action_is_const;
8270 t->action_data_size_max = action_data_size_max;
8273 t->id = p->n_tables;
8275 /* Node add to tailq. */
8276 TAILQ_INSERT_TAIL(&p->tables, t, node);
8282 static struct rte_swx_table_params *
8283 table_params_get(struct table *table)
8285 struct rte_swx_table_params *params;
8286 struct field *first, *last;
8288 uint32_t key_size, key_offset, action_data_size, i;
8290 /* Memory allocation. */
8291 params = calloc(1, sizeof(struct rte_swx_table_params));
8295 /* Find first (smallest offset) and last (biggest offset) match fields. */
8296 first = table->fields[0].field;
8297 last = table->fields[0].field;
8299 for (i = 0; i < table->n_fields; i++) {
8300 struct field *f = table->fields[i].field;
8302 if (f->offset < first->offset)
8305 if (f->offset > last->offset)
8309 /* Key offset and size. */
8310 key_offset = first->offset / 8;
8311 key_size = (last->offset + last->n_bits - first->offset) / 8;
8313 /* Memory allocation. */
8314 key_mask = calloc(1, key_size);
8321 for (i = 0; i < table->n_fields; i++) {
8322 struct field *f = table->fields[i].field;
8323 uint32_t start = (f->offset - first->offset) / 8;
8324 size_t size = f->n_bits / 8;
8326 memset(&key_mask[start], 0xFF, size);
8329 /* Action data size. */
8330 action_data_size = 0;
8331 for (i = 0; i < table->n_actions; i++) {
8332 struct action *action = table->actions[i];
8333 uint32_t ads = action->st ? action->st->n_bits / 8 : 0;
8335 if (ads > action_data_size)
8336 action_data_size = ads;
8340 params->match_type = table->type->match_type;
8341 params->key_size = key_size;
8342 params->key_offset = key_offset;
8343 params->key_mask0 = key_mask;
8344 params->action_data_size = action_data_size;
8345 params->n_keys_max = table->size;
8351 table_params_free(struct rte_swx_table_params *params)
8356 free(params->key_mask0);
8361 table_stub_lkp(void *table __rte_unused,
8362 void *mailbox __rte_unused,
8363 uint8_t **key __rte_unused,
8364 uint64_t *action_id __rte_unused,
8365 uint8_t **action_data __rte_unused,
8369 return 1; /* DONE. */
8373 table_build(struct rte_swx_pipeline *p)
8377 /* Per pipeline: table statistics. */
8378 p->table_stats = calloc(p->n_tables, sizeof(struct table_statistics));
8379 CHECK(p->table_stats, ENOMEM);
8381 for (i = 0; i < p->n_tables; i++) {
8382 p->table_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
8383 CHECK(p->table_stats[i].n_pkts_action, ENOMEM);
8386 /* Per thread: table runt-time. */
8387 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8388 struct thread *t = &p->threads[i];
8389 struct table *table;
8391 t->tables = calloc(p->n_tables, sizeof(struct table_runtime));
8392 CHECK(t->tables, ENOMEM);
8394 TAILQ_FOREACH(table, &p->tables, node) {
8395 struct table_runtime *r = &t->tables[table->id];
8400 size = table->type->ops.mailbox_size_get();
8403 r->func = table->type->ops.lkp;
8407 r->mailbox = calloc(1, size);
8408 CHECK(r->mailbox, ENOMEM);
8412 r->key = table->header ?
8413 &t->structs[table->header->struct_id] :
8414 &t->structs[p->metadata_struct_id];
8416 r->func = table_stub_lkp;
8425 table_build_free(struct rte_swx_pipeline *p)
8429 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8430 struct thread *t = &p->threads[i];
8436 for (j = 0; j < p->n_tables; j++) {
8437 struct table_runtime *r = &t->tables[j];
8446 if (p->table_stats) {
8447 for (i = 0; i < p->n_tables; i++)
8448 free(p->table_stats[i].n_pkts_action);
8450 free(p->table_stats);
8455 table_free(struct rte_swx_pipeline *p)
8457 table_build_free(p);
8463 elem = TAILQ_FIRST(&p->tables);
8467 TAILQ_REMOVE(&p->tables, elem, node);
8469 free(elem->actions);
8470 free(elem->default_action_data);
8476 struct table_type *elem;
8478 elem = TAILQ_FIRST(&p->table_types);
8482 TAILQ_REMOVE(&p->table_types, elem, node);
8490 static struct selector *
8491 selector_find(struct rte_swx_pipeline *p, const char *name)
8495 TAILQ_FOREACH(s, &p->selectors, node)
8496 if (strcmp(s->name, name) == 0)
8502 static struct selector *
8503 selector_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8505 struct selector *s = NULL;
8507 TAILQ_FOREACH(s, &p->selectors, node)
8515 selector_fields_check(struct rte_swx_pipeline *p,
8516 struct rte_swx_pipeline_selector_params *params,
8517 struct header **header)
8519 struct header *h0 = NULL;
8520 struct field *hf, *mf;
8523 /* Return if no selector fields. */
8524 if (!params->n_selector_fields || !params->selector_field_names)
8527 /* Check that all the selector fields either belong to the same header
8528 * or are all meta-data fields.
8530 hf = header_field_parse(p, params->selector_field_names[0], &h0);
8531 mf = metadata_field_parse(p, params->selector_field_names[0]);
8535 for (i = 1; i < params->n_selector_fields; i++)
8539 hf = header_field_parse(p, params->selector_field_names[i], &h);
8540 if (!hf || (h->id != h0->id))
8543 mf = metadata_field_parse(p, params->selector_field_names[i]);
8548 /* Check that there are no duplicated match fields. */
8549 for (i = 0; i < params->n_selector_fields; i++) {
8550 const char *field_name = params->selector_field_names[i];
8553 for (j = i + 1; j < params->n_selector_fields; j++)
8554 if (!strcmp(params->selector_field_names[j], field_name))
8566 rte_swx_pipeline_selector_config(struct rte_swx_pipeline *p,
8568 struct rte_swx_pipeline_selector_params *params)
8571 struct header *selector_header = NULL;
8572 struct field *group_id_field, *member_id_field;
8578 CHECK_NAME(name, EINVAL);
8579 CHECK(!table_find(p, name), EEXIST);
8580 CHECK(!selector_find(p, name), EEXIST);
8581 CHECK(!learner_find(p, name), EEXIST);
8583 CHECK(params, EINVAL);
8585 CHECK_NAME(params->group_id_field_name, EINVAL);
8586 group_id_field = metadata_field_parse(p, params->group_id_field_name);
8587 CHECK(group_id_field, EINVAL);
8589 for (i = 0; i < params->n_selector_fields; i++) {
8590 const char *field_name = params->selector_field_names[i];
8592 CHECK_NAME(field_name, EINVAL);
8594 status = selector_fields_check(p, params, &selector_header);
8598 CHECK_NAME(params->member_id_field_name, EINVAL);
8599 member_id_field = metadata_field_parse(p, params->member_id_field_name);
8600 CHECK(member_id_field, EINVAL);
8602 CHECK(params->n_groups_max, EINVAL);
8604 CHECK(params->n_members_per_group_max, EINVAL);
8606 /* Memory allocation. */
8607 s = calloc(1, sizeof(struct selector));
8613 s->selector_fields = calloc(params->n_selector_fields, sizeof(struct field *));
8614 if (!s->selector_fields) {
8619 /* Node initialization. */
8620 strcpy(s->name, name);
8622 s->group_id_field = group_id_field;
8624 for (i = 0; i < params->n_selector_fields; i++) {
8625 const char *field_name = params->selector_field_names[i];
8627 s->selector_fields[i] = selector_header ?
8628 header_field_parse(p, field_name, NULL) :
8629 metadata_field_parse(p, field_name);
8632 s->n_selector_fields = params->n_selector_fields;
8634 s->selector_header = selector_header;
8636 s->member_id_field = member_id_field;
8638 s->n_groups_max = params->n_groups_max;
8640 s->n_members_per_group_max = params->n_members_per_group_max;
8642 s->id = p->n_selectors;
8644 /* Node add to tailq. */
8645 TAILQ_INSERT_TAIL(&p->selectors, s, node);
8654 free(s->selector_fields);
8662 selector_params_free(struct rte_swx_table_selector_params *params)
8667 free(params->selector_mask);
8672 static struct rte_swx_table_selector_params *
8673 selector_table_params_get(struct selector *s)
8675 struct rte_swx_table_selector_params *params = NULL;
8676 struct field *first, *last;
8679 /* Memory allocation. */
8680 params = calloc(1, sizeof(struct rte_swx_table_selector_params));
8685 params->group_id_offset = s->group_id_field->offset / 8;
8687 /* Find first (smallest offset) and last (biggest offset) selector fields. */
8688 first = s->selector_fields[0];
8689 last = s->selector_fields[0];
8691 for (i = 0; i < s->n_selector_fields; i++) {
8692 struct field *f = s->selector_fields[i];
8694 if (f->offset < first->offset)
8697 if (f->offset > last->offset)
8701 /* Selector offset and size. */
8702 params->selector_offset = first->offset / 8;
8703 params->selector_size = (last->offset + last->n_bits - first->offset) / 8;
8705 /* Memory allocation. */
8706 params->selector_mask = calloc(1, params->selector_size);
8707 if (!params->selector_mask)
8710 /* Selector mask. */
8711 for (i = 0; i < s->n_selector_fields; i++) {
8712 struct field *f = s->selector_fields[i];
8713 uint32_t start = (f->offset - first->offset) / 8;
8714 size_t size = f->n_bits / 8;
8716 memset(¶ms->selector_mask[start], 0xFF, size);
8720 params->member_id_offset = s->member_id_field->offset / 8;
8722 /* Maximum number of groups. */
8723 params->n_groups_max = s->n_groups_max;
8725 /* Maximum number of members per group. */
8726 params->n_members_per_group_max = s->n_members_per_group_max;
8731 selector_params_free(params);
8736 selector_build_free(struct rte_swx_pipeline *p)
8740 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8741 struct thread *t = &p->threads[i];
8747 for (j = 0; j < p->n_selectors; j++) {
8748 struct selector_runtime *r = &t->selectors[j];
8754 t->selectors = NULL;
8757 free(p->selector_stats);
8758 p->selector_stats = NULL;
8762 selector_build(struct rte_swx_pipeline *p)
8767 /* Per pipeline: selector statistics. */
8768 p->selector_stats = calloc(p->n_selectors, sizeof(struct selector_statistics));
8769 if (!p->selector_stats) {
8774 /* Per thread: selector run-time. */
8775 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8776 struct thread *t = &p->threads[i];
8779 t->selectors = calloc(p->n_selectors, sizeof(struct selector_runtime));
8780 if (!t->selectors) {
8785 TAILQ_FOREACH(s, &p->selectors, node) {
8786 struct selector_runtime *r = &t->selectors[s->id];
8790 size = rte_swx_table_selector_mailbox_size_get();
8792 r->mailbox = calloc(1, size);
8799 /* r->group_id_buffer. */
8800 r->group_id_buffer = &t->structs[p->metadata_struct_id];
8802 /* r->selector_buffer. */
8803 r->selector_buffer = s->selector_header ?
8804 &t->structs[s->selector_header->struct_id] :
8805 &t->structs[p->metadata_struct_id];
8807 /* r->member_id_buffer. */
8808 r->member_id_buffer = &t->structs[p->metadata_struct_id];
8815 selector_build_free(p);
8820 selector_free(struct rte_swx_pipeline *p)
8822 selector_build_free(p);
8824 /* Selector tables. */
8826 struct selector *elem;
8828 elem = TAILQ_FIRST(&p->selectors);
8832 TAILQ_REMOVE(&p->selectors, elem, node);
8833 free(elem->selector_fields);
8841 static struct learner *
8842 learner_find(struct rte_swx_pipeline *p, const char *name)
8846 TAILQ_FOREACH(l, &p->learners, node)
8847 if (!strcmp(l->name, name))
8853 static struct learner *
8854 learner_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8856 struct learner *l = NULL;
8858 TAILQ_FOREACH(l, &p->learners, node)
8866 learner_match_fields_check(struct rte_swx_pipeline *p,
8867 struct rte_swx_pipeline_learner_params *params,
8868 struct header **header)
8870 struct header *h0 = NULL;
8871 struct field *hf, *mf;
8874 /* Return if no match fields. */
8875 if (!params->n_fields || !params->field_names)
8878 /* Check that all the match fields either belong to the same header
8879 * or are all meta-data fields.
8881 hf = header_field_parse(p, params->field_names[0], &h0);
8882 mf = metadata_field_parse(p, params->field_names[0]);
8886 for (i = 1; i < params->n_fields; i++)
8890 hf = header_field_parse(p, params->field_names[i], &h);
8891 if (!hf || (h->id != h0->id))
8894 mf = metadata_field_parse(p, params->field_names[i]);
8899 /* Check that there are no duplicated match fields. */
8900 for (i = 0; i < params->n_fields; i++) {
8901 const char *field_name = params->field_names[i];
8904 for (j = i + 1; j < params->n_fields; j++)
8905 if (!strcmp(params->field_names[j], field_name))
8917 learner_action_args_check(struct rte_swx_pipeline *p, struct action *a, const char *mf_name)
8919 struct struct_type *mst = p->metadata_st, *ast = a->st;
8920 struct field *mf, *af;
8930 /* Check that mf_name is the name of a valid meta-data field. */
8931 CHECK_NAME(mf_name, EINVAL);
8932 mf = metadata_field_parse(p, mf_name);
8935 /* Check that there are enough meta-data fields, starting with the mf_name field, to cover
8936 * all the action arguments.
8938 mf_pos = mf - mst->fields;
8939 CHECK(mst->n_fields - mf_pos >= ast->n_fields, EINVAL);
8941 /* Check that the size of each of the identified meta-data fields matches exactly the size
8942 * of the corresponding action argument.
8944 for (i = 0; i < ast->n_fields; i++) {
8945 mf = &mst->fields[mf_pos + i];
8946 af = &ast->fields[i];
8948 CHECK(mf->n_bits == af->n_bits, EINVAL);
8955 learner_action_learning_check(struct rte_swx_pipeline *p,
8956 struct action *action,
8957 const char **action_names,
8962 /* For each "learn" instruction of the current action, check that the learned action (i.e.
8963 * the action passed as argument to the "learn" instruction) is also enabled for the
8964 * current learner table.
8966 for (i = 0; i < action->n_instructions; i++) {
8967 struct instruction *instr = &action->instructions[i];
8968 uint32_t found = 0, j;
8970 if (instr->type != INSTR_LEARNER_LEARN)
8973 for (j = 0; j < n_actions; j++) {
8976 a = action_find(p, action_names[j]);
8980 if (a->id == instr->learn.action_id)
8992 rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p,
8994 struct rte_swx_pipeline_learner_params *params,
8998 struct learner *l = NULL;
8999 struct action *default_action;
9000 struct header *header = NULL;
9001 uint32_t action_data_size_max = 0, i;
9006 CHECK_NAME(name, EINVAL);
9007 CHECK(!table_find(p, name), EEXIST);
9008 CHECK(!selector_find(p, name), EEXIST);
9009 CHECK(!learner_find(p, name), EEXIST);
9011 CHECK(params, EINVAL);
9014 status = learner_match_fields_check(p, params, &header);
9018 /* Action checks. */
9019 CHECK(params->n_actions, EINVAL);
9021 CHECK(params->action_names, EINVAL);
9022 for (i = 0; i < params->n_actions; i++) {
9023 const char *action_name = params->action_names[i];
9024 const char *action_field_name = params->action_field_names[i];
9026 uint32_t action_data_size;
9028 CHECK_NAME(action_name, EINVAL);
9030 a = action_find(p, action_name);
9033 status = learner_action_args_check(p, a, action_field_name);
9037 status = learner_action_learning_check(p,
9039 params->action_names,
9044 action_data_size = a->st ? a->st->n_bits / 8 : 0;
9045 if (action_data_size > action_data_size_max)
9046 action_data_size_max = action_data_size;
9049 CHECK_NAME(params->default_action_name, EINVAL);
9050 for (i = 0; i < p->n_actions; i++)
9051 if (!strcmp(params->action_names[i],
9052 params->default_action_name))
9054 CHECK(i < params->n_actions, EINVAL);
9056 default_action = action_find(p, params->default_action_name);
9057 CHECK((default_action->st && params->default_action_data) ||
9058 !params->default_action_data, EINVAL);
9060 /* Any other checks. */
9061 CHECK(size, EINVAL);
9062 CHECK(timeout, EINVAL);
9064 /* Memory allocation. */
9065 l = calloc(1, sizeof(struct learner));
9069 l->fields = calloc(params->n_fields, sizeof(struct field *));
9073 l->actions = calloc(params->n_actions, sizeof(struct action *));
9077 l->action_arg = calloc(params->n_actions, sizeof(struct field *));
9081 if (action_data_size_max) {
9082 l->default_action_data = calloc(1, action_data_size_max);
9083 if (!l->default_action_data)
9087 /* Node initialization. */
9088 strcpy(l->name, name);
9090 for (i = 0; i < params->n_fields; i++) {
9091 const char *field_name = params->field_names[i];
9093 l->fields[i] = header ?
9094 header_field_parse(p, field_name, NULL) :
9095 metadata_field_parse(p, field_name);
9098 l->n_fields = params->n_fields;
9102 for (i = 0; i < params->n_actions; i++) {
9103 const char *mf_name = params->action_field_names[i];
9105 l->actions[i] = action_find(p, params->action_names[i]);
9107 l->action_arg[i] = mf_name ? metadata_field_parse(p, mf_name) : NULL;
9110 l->default_action = default_action;
9112 if (default_action->st)
9113 memcpy(l->default_action_data,
9114 params->default_action_data,
9115 default_action->st->n_bits / 8);
9117 l->n_actions = params->n_actions;
9119 l->default_action_is_const = params->default_action_is_const;
9121 l->action_data_size_max = action_data_size_max;
9125 l->timeout = timeout;
9127 l->id = p->n_learners;
9129 /* Node add to tailq. */
9130 TAILQ_INSERT_TAIL(&p->learners, l, node);
9139 free(l->action_arg);
9148 learner_params_free(struct rte_swx_table_learner_params *params)
9153 free(params->key_mask0);
9158 static struct rte_swx_table_learner_params *
9159 learner_params_get(struct learner *l)
9161 struct rte_swx_table_learner_params *params = NULL;
9162 struct field *first, *last;
9165 /* Memory allocation. */
9166 params = calloc(1, sizeof(struct rte_swx_table_learner_params));
9170 /* Find first (smallest offset) and last (biggest offset) match fields. */
9171 first = l->fields[0];
9172 last = l->fields[0];
9174 for (i = 0; i < l->n_fields; i++) {
9175 struct field *f = l->fields[i];
9177 if (f->offset < first->offset)
9180 if (f->offset > last->offset)
9184 /* Key offset and size. */
9185 params->key_offset = first->offset / 8;
9186 params->key_size = (last->offset + last->n_bits - first->offset) / 8;
9188 /* Memory allocation. */
9189 params->key_mask0 = calloc(1, params->key_size);
9190 if (!params->key_mask0)
9194 for (i = 0; i < l->n_fields; i++) {
9195 struct field *f = l->fields[i];
9196 uint32_t start = (f->offset - first->offset) / 8;
9197 size_t size = f->n_bits / 8;
9199 memset(¶ms->key_mask0[start], 0xFF, size);
9202 /* Action data size. */
9203 params->action_data_size = l->action_data_size_max;
9205 /* Maximum number of keys. */
9206 params->n_keys_max = l->size;
9209 params->key_timeout = l->timeout;
9214 learner_params_free(params);
9219 learner_build_free(struct rte_swx_pipeline *p)
9223 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9224 struct thread *t = &p->threads[i];
9230 for (j = 0; j < p->n_learners; j++) {
9231 struct learner_runtime *r = &t->learners[j];
9234 free(r->action_data);
9241 if (p->learner_stats) {
9242 for (i = 0; i < p->n_learners; i++)
9243 free(p->learner_stats[i].n_pkts_action);
9245 free(p->learner_stats);
9250 learner_build(struct rte_swx_pipeline *p)
9255 /* Per pipeline: learner statistics. */
9256 p->learner_stats = calloc(p->n_learners, sizeof(struct learner_statistics));
9257 CHECK(p->learner_stats, ENOMEM);
9259 for (i = 0; i < p->n_learners; i++) {
9260 p->learner_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
9261 CHECK(p->learner_stats[i].n_pkts_action, ENOMEM);
9264 /* Per thread: learner run-time. */
9265 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9266 struct thread *t = &p->threads[i];
9269 t->learners = calloc(p->n_learners, sizeof(struct learner_runtime));
9275 TAILQ_FOREACH(l, &p->learners, node) {
9276 struct learner_runtime *r = &t->learners[l->id];
9281 size = rte_swx_table_learner_mailbox_size_get();
9283 r->mailbox = calloc(1, size);
9291 r->key = l->header ?
9292 &t->structs[l->header->struct_id] :
9293 &t->structs[p->metadata_struct_id];
9295 /* r->action_data. */
9296 r->action_data = calloc(p->n_actions, sizeof(uint8_t *));
9297 if (!r->action_data) {
9302 for (j = 0; j < l->n_actions; j++) {
9303 struct action *a = l->actions[j];
9304 struct field *mf = l->action_arg[j];
9305 uint8_t *m = t->structs[p->metadata_struct_id];
9307 r->action_data[a->id] = mf ? &m[mf->offset / 8] : NULL;
9315 learner_build_free(p);
9320 learner_free(struct rte_swx_pipeline *p)
9322 learner_build_free(p);
9324 /* Learner tables. */
9328 l = TAILQ_FIRST(&p->learners);
9332 TAILQ_REMOVE(&p->learners, l, node);
9335 free(l->action_arg);
9336 free(l->default_action_data);
9345 table_state_build(struct rte_swx_pipeline *p)
9347 struct table *table;
9351 p->table_state = calloc(p->n_tables + p->n_selectors,
9352 sizeof(struct rte_swx_table_state));
9353 CHECK(p->table_state, ENOMEM);
9355 TAILQ_FOREACH(table, &p->tables, node) {
9356 struct rte_swx_table_state *ts = &p->table_state[table->id];
9359 struct rte_swx_table_params *params;
9362 params = table_params_get(table);
9363 CHECK(params, ENOMEM);
9365 ts->obj = table->type->ops.create(params,
9370 table_params_free(params);
9371 CHECK(ts->obj, ENODEV);
9374 /* ts->default_action_data. */
9375 if (table->action_data_size_max) {
9376 ts->default_action_data =
9377 malloc(table->action_data_size_max);
9378 CHECK(ts->default_action_data, ENOMEM);
9380 memcpy(ts->default_action_data,
9381 table->default_action_data,
9382 table->action_data_size_max);
9385 /* ts->default_action_id. */
9386 ts->default_action_id = table->default_action->id;
9389 TAILQ_FOREACH(s, &p->selectors, node) {
9390 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + s->id];
9391 struct rte_swx_table_selector_params *params;
9394 params = selector_table_params_get(s);
9395 CHECK(params, ENOMEM);
9397 ts->obj = rte_swx_table_selector_create(params, NULL, p->numa_node);
9399 selector_params_free(params);
9400 CHECK(ts->obj, ENODEV);
9403 TAILQ_FOREACH(l, &p->learners, node) {
9404 struct rte_swx_table_state *ts = &p->table_state[p->n_tables +
9405 p->n_selectors + l->id];
9406 struct rte_swx_table_learner_params *params;
9409 params = learner_params_get(l);
9410 CHECK(params, ENOMEM);
9412 ts->obj = rte_swx_table_learner_create(params, p->numa_node);
9413 learner_params_free(params);
9414 CHECK(ts->obj, ENODEV);
9416 /* ts->default_action_data. */
9417 if (l->action_data_size_max) {
9418 ts->default_action_data = malloc(l->action_data_size_max);
9419 CHECK(ts->default_action_data, ENOMEM);
9421 memcpy(ts->default_action_data,
9422 l->default_action_data,
9423 l->action_data_size_max);
9426 /* ts->default_action_id. */
9427 ts->default_action_id = l->default_action->id;
9434 table_state_build_free(struct rte_swx_pipeline *p)
9438 if (!p->table_state)
9441 for (i = 0; i < p->n_tables; i++) {
9442 struct rte_swx_table_state *ts = &p->table_state[i];
9443 struct table *table = table_find_by_id(p, i);
9446 if (table->type && ts->obj)
9447 table->type->ops.free(ts->obj);
9449 /* ts->default_action_data. */
9450 free(ts->default_action_data);
9453 for (i = 0; i < p->n_selectors; i++) {
9454 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + i];
9458 rte_swx_table_selector_free(ts->obj);
9461 for (i = 0; i < p->n_learners; i++) {
9462 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + p->n_selectors + i];
9466 rte_swx_table_learner_free(ts->obj);
9468 /* ts->default_action_data. */
9469 free(ts->default_action_data);
9472 free(p->table_state);
9473 p->table_state = NULL;
9477 table_state_free(struct rte_swx_pipeline *p)
9479 table_state_build_free(p);
9485 static struct regarray *
9486 regarray_find(struct rte_swx_pipeline *p, const char *name)
9488 struct regarray *elem;
9490 TAILQ_FOREACH(elem, &p->regarrays, node)
9491 if (!strcmp(elem->name, name))
9497 static struct regarray *
9498 regarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9500 struct regarray *elem = NULL;
9502 TAILQ_FOREACH(elem, &p->regarrays, node)
9510 rte_swx_pipeline_regarray_config(struct rte_swx_pipeline *p,
9519 CHECK_NAME(name, EINVAL);
9520 CHECK(!regarray_find(p, name), EEXIST);
9522 CHECK(size, EINVAL);
9523 size = rte_align32pow2(size);
9525 /* Memory allocation. */
9526 r = calloc(1, sizeof(struct regarray));
9529 /* Node initialization. */
9530 strcpy(r->name, name);
9531 r->init_val = init_val;
9533 r->id = p->n_regarrays;
9535 /* Node add to tailq. */
9536 TAILQ_INSERT_TAIL(&p->regarrays, r, node);
9543 regarray_build(struct rte_swx_pipeline *p)
9545 struct regarray *regarray;
9547 if (!p->n_regarrays)
9550 p->regarray_runtime = calloc(p->n_regarrays, sizeof(struct regarray_runtime));
9551 CHECK(p->regarray_runtime, ENOMEM);
9553 TAILQ_FOREACH(regarray, &p->regarrays, node) {
9554 struct regarray_runtime *r = &p->regarray_runtime[regarray->id];
9557 r->regarray = env_malloc(regarray->size * sizeof(uint64_t),
9558 RTE_CACHE_LINE_SIZE,
9560 CHECK(r->regarray, ENOMEM);
9562 if (regarray->init_val)
9563 for (i = 0; i < regarray->size; i++)
9564 r->regarray[i] = regarray->init_val;
9566 r->size_mask = regarray->size - 1;
9573 regarray_build_free(struct rte_swx_pipeline *p)
9577 if (!p->regarray_runtime)
9580 for (i = 0; i < p->n_regarrays; i++) {
9581 struct regarray *regarray = regarray_find_by_id(p, i);
9582 struct regarray_runtime *r = &p->regarray_runtime[i];
9584 env_free(r->regarray, regarray->size * sizeof(uint64_t));
9587 free(p->regarray_runtime);
9588 p->regarray_runtime = NULL;
9592 regarray_free(struct rte_swx_pipeline *p)
9594 regarray_build_free(p);
9597 struct regarray *elem;
9599 elem = TAILQ_FIRST(&p->regarrays);
9603 TAILQ_REMOVE(&p->regarrays, elem, node);
9611 static struct meter_profile *
9612 meter_profile_find(struct rte_swx_pipeline *p, const char *name)
9614 struct meter_profile *elem;
9616 TAILQ_FOREACH(elem, &p->meter_profiles, node)
9617 if (!strcmp(elem->name, name))
9623 static struct metarray *
9624 metarray_find(struct rte_swx_pipeline *p, const char *name)
9626 struct metarray *elem;
9628 TAILQ_FOREACH(elem, &p->metarrays, node)
9629 if (!strcmp(elem->name, name))
9635 static struct metarray *
9636 metarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9638 struct metarray *elem = NULL;
9640 TAILQ_FOREACH(elem, &p->metarrays, node)
9648 rte_swx_pipeline_metarray_config(struct rte_swx_pipeline *p,
9656 CHECK_NAME(name, EINVAL);
9657 CHECK(!metarray_find(p, name), EEXIST);
9659 CHECK(size, EINVAL);
9660 size = rte_align32pow2(size);
9662 /* Memory allocation. */
9663 m = calloc(1, sizeof(struct metarray));
9666 /* Node initialization. */
9667 strcpy(m->name, name);
9669 m->id = p->n_metarrays;
9671 /* Node add to tailq. */
9672 TAILQ_INSERT_TAIL(&p->metarrays, m, node);
9678 struct meter_profile meter_profile_default = {
9687 .cir_bytes_per_period = 1,
9689 .pir_bytes_per_period = 1,
9696 meter_init(struct meter *m)
9698 memset(m, 0, sizeof(struct meter));
9699 rte_meter_trtcm_config(&m->m, &meter_profile_default.profile);
9700 m->profile = &meter_profile_default;
9701 m->color_mask = RTE_COLOR_GREEN;
9703 meter_profile_default.n_users++;
9707 metarray_build(struct rte_swx_pipeline *p)
9711 if (!p->n_metarrays)
9714 p->metarray_runtime = calloc(p->n_metarrays, sizeof(struct metarray_runtime));
9715 CHECK(p->metarray_runtime, ENOMEM);
9717 TAILQ_FOREACH(m, &p->metarrays, node) {
9718 struct metarray_runtime *r = &p->metarray_runtime[m->id];
9721 r->metarray = env_malloc(m->size * sizeof(struct meter),
9722 RTE_CACHE_LINE_SIZE,
9724 CHECK(r->metarray, ENOMEM);
9726 for (i = 0; i < m->size; i++)
9727 meter_init(&r->metarray[i]);
9729 r->size_mask = m->size - 1;
9736 metarray_build_free(struct rte_swx_pipeline *p)
9740 if (!p->metarray_runtime)
9743 for (i = 0; i < p->n_metarrays; i++) {
9744 struct metarray *m = metarray_find_by_id(p, i);
9745 struct metarray_runtime *r = &p->metarray_runtime[i];
9747 env_free(r->metarray, m->size * sizeof(struct meter));
9750 free(p->metarray_runtime);
9751 p->metarray_runtime = NULL;
9755 metarray_free(struct rte_swx_pipeline *p)
9757 metarray_build_free(p);
9761 struct metarray *elem;
9763 elem = TAILQ_FIRST(&p->metarrays);
9767 TAILQ_REMOVE(&p->metarrays, elem, node);
9771 /* Meter profiles. */
9773 struct meter_profile *elem;
9775 elem = TAILQ_FIRST(&p->meter_profiles);
9779 TAILQ_REMOVE(&p->meter_profiles, elem, node);
9788 rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
9790 struct rte_swx_pipeline *pipeline;
9792 /* Check input parameters. */
9795 /* Memory allocation. */
9796 pipeline = calloc(1, sizeof(struct rte_swx_pipeline));
9797 CHECK(pipeline, ENOMEM);
9799 /* Initialization. */
9800 TAILQ_INIT(&pipeline->struct_types);
9801 TAILQ_INIT(&pipeline->port_in_types);
9802 TAILQ_INIT(&pipeline->ports_in);
9803 TAILQ_INIT(&pipeline->port_out_types);
9804 TAILQ_INIT(&pipeline->ports_out);
9805 TAILQ_INIT(&pipeline->extern_types);
9806 TAILQ_INIT(&pipeline->extern_objs);
9807 TAILQ_INIT(&pipeline->extern_funcs);
9808 TAILQ_INIT(&pipeline->headers);
9809 TAILQ_INIT(&pipeline->actions);
9810 TAILQ_INIT(&pipeline->table_types);
9811 TAILQ_INIT(&pipeline->tables);
9812 TAILQ_INIT(&pipeline->selectors);
9813 TAILQ_INIT(&pipeline->learners);
9814 TAILQ_INIT(&pipeline->regarrays);
9815 TAILQ_INIT(&pipeline->meter_profiles);
9816 TAILQ_INIT(&pipeline->metarrays);
9818 pipeline->n_structs = 1; /* Struct 0 is reserved for action_data. */
9819 pipeline->numa_node = numa_node;
9826 rte_swx_pipeline_free(struct rte_swx_pipeline *p)
9831 free(p->instructions);
9835 table_state_free(p);
9842 extern_func_free(p);
9852 rte_swx_pipeline_instructions_config(struct rte_swx_pipeline *p,
9853 const char **instructions,
9854 uint32_t n_instructions)
9859 err = instruction_config(p, NULL, instructions, n_instructions);
9863 /* Thread instruction pointer reset. */
9864 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9865 struct thread *t = &p->threads[i];
9867 thread_ip_reset(p, t);
9874 rte_swx_pipeline_build(struct rte_swx_pipeline *p)
9879 CHECK(p->build_done == 0, EEXIST);
9881 status = port_in_build(p);
9885 status = port_out_build(p);
9889 status = struct_build(p);
9893 status = extern_obj_build(p);
9897 status = extern_func_build(p);
9901 status = header_build(p);
9905 status = metadata_build(p);
9909 status = action_build(p);
9913 status = table_build(p);
9917 status = selector_build(p);
9921 status = learner_build(p);
9925 status = table_state_build(p);
9929 status = regarray_build(p);
9933 status = metarray_build(p);
9941 metarray_build_free(p);
9942 regarray_build_free(p);
9943 table_state_build_free(p);
9944 learner_build_free(p);
9945 selector_build_free(p);
9946 table_build_free(p);
9947 action_build_free(p);
9948 metadata_build_free(p);
9949 header_build_free(p);
9950 extern_func_build_free(p);
9951 extern_obj_build_free(p);
9952 port_out_build_free(p);
9953 port_in_build_free(p);
9954 struct_build_free(p);
9960 rte_swx_pipeline_run(struct rte_swx_pipeline *p, uint32_t n_instructions)
9964 for (i = 0; i < n_instructions; i++)
9969 rte_swx_pipeline_flush(struct rte_swx_pipeline *p)
9973 for (i = 0; i < p->n_ports_out; i++) {
9974 struct port_out_runtime *port = &p->out[i];
9977 port->flush(port->obj);
9985 rte_swx_ctl_pipeline_info_get(struct rte_swx_pipeline *p,
9986 struct rte_swx_ctl_pipeline_info *pipeline)
9988 struct action *action;
9989 struct table *table;
9990 uint32_t n_actions = 0, n_tables = 0;
9992 if (!p || !pipeline)
9995 TAILQ_FOREACH(action, &p->actions, node)
9998 TAILQ_FOREACH(table, &p->tables, node)
10001 pipeline->n_ports_in = p->n_ports_in;
10002 pipeline->n_ports_out = p->n_ports_out;
10003 pipeline->n_actions = n_actions;
10004 pipeline->n_tables = n_tables;
10005 pipeline->n_selectors = p->n_selectors;
10006 pipeline->n_learners = p->n_learners;
10007 pipeline->n_regarrays = p->n_regarrays;
10008 pipeline->n_metarrays = p->n_metarrays;
10014 rte_swx_ctl_pipeline_numa_node_get(struct rte_swx_pipeline *p, int *numa_node)
10016 if (!p || !numa_node)
10019 *numa_node = p->numa_node;
10024 rte_swx_ctl_action_info_get(struct rte_swx_pipeline *p,
10025 uint32_t action_id,
10026 struct rte_swx_ctl_action_info *action)
10028 struct action *a = NULL;
10030 if (!p || (action_id >= p->n_actions) || !action)
10033 a = action_find_by_id(p, action_id);
10037 strcpy(action->name, a->name);
10038 action->n_args = a->st ? a->st->n_fields : 0;
10043 rte_swx_ctl_action_arg_info_get(struct rte_swx_pipeline *p,
10044 uint32_t action_id,
10045 uint32_t action_arg_id,
10046 struct rte_swx_ctl_action_arg_info *action_arg)
10048 struct action *a = NULL;
10049 struct field *arg = NULL;
10051 if (!p || (action_id >= p->n_actions) || !action_arg)
10054 a = action_find_by_id(p, action_id);
10055 if (!a || !a->st || (action_arg_id >= a->st->n_fields))
10058 arg = &a->st->fields[action_arg_id];
10059 strcpy(action_arg->name, arg->name);
10060 action_arg->n_bits = arg->n_bits;
10061 action_arg->is_network_byte_order = a->args_endianness[action_arg_id];
10067 rte_swx_ctl_table_info_get(struct rte_swx_pipeline *p,
10069 struct rte_swx_ctl_table_info *table)
10071 struct table *t = NULL;
10076 t = table_find_by_id(p, table_id);
10080 strcpy(table->name, t->name);
10081 strcpy(table->args, t->args);
10082 table->n_match_fields = t->n_fields;
10083 table->n_actions = t->n_actions;
10084 table->default_action_is_const = t->default_action_is_const;
10085 table->size = t->size;
10090 rte_swx_ctl_table_match_field_info_get(struct rte_swx_pipeline *p,
10092 uint32_t match_field_id,
10093 struct rte_swx_ctl_table_match_field_info *match_field)
10096 struct match_field *f;
10098 if (!p || (table_id >= p->n_tables) || !match_field)
10101 t = table_find_by_id(p, table_id);
10102 if (!t || (match_field_id >= t->n_fields))
10105 f = &t->fields[match_field_id];
10106 match_field->match_type = f->match_type;
10107 match_field->is_header = t->header ? 1 : 0;
10108 match_field->n_bits = f->field->n_bits;
10109 match_field->offset = f->field->offset;
10115 rte_swx_ctl_table_action_info_get(struct rte_swx_pipeline *p,
10117 uint32_t table_action_id,
10118 struct rte_swx_ctl_table_action_info *table_action)
10122 if (!p || (table_id >= p->n_tables) || !table_action)
10125 t = table_find_by_id(p, table_id);
10126 if (!t || (table_action_id >= t->n_actions))
10129 table_action->action_id = t->actions[table_action_id]->id;
10135 rte_swx_ctl_table_ops_get(struct rte_swx_pipeline *p,
10137 struct rte_swx_table_ops *table_ops,
10142 if (!p || (table_id >= p->n_tables))
10145 t = table_find_by_id(p, table_id);
10151 memcpy(table_ops, &t->type->ops, sizeof(*table_ops));
10161 rte_swx_ctl_selector_info_get(struct rte_swx_pipeline *p,
10162 uint32_t selector_id,
10163 struct rte_swx_ctl_selector_info *selector)
10165 struct selector *s = NULL;
10167 if (!p || !selector)
10170 s = selector_find_by_id(p, selector_id);
10174 strcpy(selector->name, s->name);
10176 selector->n_selector_fields = s->n_selector_fields;
10177 selector->n_groups_max = s->n_groups_max;
10178 selector->n_members_per_group_max = s->n_members_per_group_max;
10184 rte_swx_ctl_selector_group_id_field_info_get(struct rte_swx_pipeline *p,
10185 uint32_t selector_id,
10186 struct rte_swx_ctl_table_match_field_info *field)
10188 struct selector *s;
10190 if (!p || (selector_id >= p->n_selectors) || !field)
10193 s = selector_find_by_id(p, selector_id);
10197 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10198 field->is_header = 0;
10199 field->n_bits = s->group_id_field->n_bits;
10200 field->offset = s->group_id_field->offset;
10206 rte_swx_ctl_selector_field_info_get(struct rte_swx_pipeline *p,
10207 uint32_t selector_id,
10208 uint32_t selector_field_id,
10209 struct rte_swx_ctl_table_match_field_info *field)
10211 struct selector *s;
10214 if (!p || (selector_id >= p->n_selectors) || !field)
10217 s = selector_find_by_id(p, selector_id);
10218 if (!s || (selector_field_id >= s->n_selector_fields))
10221 f = s->selector_fields[selector_field_id];
10222 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10223 field->is_header = s->selector_header ? 1 : 0;
10224 field->n_bits = f->n_bits;
10225 field->offset = f->offset;
10231 rte_swx_ctl_selector_member_id_field_info_get(struct rte_swx_pipeline *p,
10232 uint32_t selector_id,
10233 struct rte_swx_ctl_table_match_field_info *field)
10235 struct selector *s;
10237 if (!p || (selector_id >= p->n_selectors) || !field)
10240 s = selector_find_by_id(p, selector_id);
10244 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10245 field->is_header = 0;
10246 field->n_bits = s->member_id_field->n_bits;
10247 field->offset = s->member_id_field->offset;
10253 rte_swx_ctl_learner_info_get(struct rte_swx_pipeline *p,
10254 uint32_t learner_id,
10255 struct rte_swx_ctl_learner_info *learner)
10257 struct learner *l = NULL;
10259 if (!p || !learner)
10262 l = learner_find_by_id(p, learner_id);
10266 strcpy(learner->name, l->name);
10268 learner->n_match_fields = l->n_fields;
10269 learner->n_actions = l->n_actions;
10270 learner->default_action_is_const = l->default_action_is_const;
10271 learner->size = l->size;
10277 rte_swx_ctl_learner_match_field_info_get(struct rte_swx_pipeline *p,
10278 uint32_t learner_id,
10279 uint32_t match_field_id,
10280 struct rte_swx_ctl_table_match_field_info *match_field)
10285 if (!p || (learner_id >= p->n_learners) || !match_field)
10288 l = learner_find_by_id(p, learner_id);
10289 if (!l || (match_field_id >= l->n_fields))
10292 f = l->fields[match_field_id];
10293 match_field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10294 match_field->is_header = l->header ? 1 : 0;
10295 match_field->n_bits = f->n_bits;
10296 match_field->offset = f->offset;
10302 rte_swx_ctl_learner_action_info_get(struct rte_swx_pipeline *p,
10303 uint32_t learner_id,
10304 uint32_t learner_action_id,
10305 struct rte_swx_ctl_table_action_info *learner_action)
10309 if (!p || (learner_id >= p->n_learners) || !learner_action)
10312 l = learner_find_by_id(p, learner_id);
10313 if (!l || (learner_action_id >= l->n_actions))
10316 learner_action->action_id = l->actions[learner_action_id]->id;
10322 rte_swx_pipeline_table_state_get(struct rte_swx_pipeline *p,
10323 struct rte_swx_table_state **table_state)
10325 if (!p || !table_state || !p->build_done)
10328 *table_state = p->table_state;
10333 rte_swx_pipeline_table_state_set(struct rte_swx_pipeline *p,
10334 struct rte_swx_table_state *table_state)
10336 if (!p || !table_state || !p->build_done)
10339 p->table_state = table_state;
10344 rte_swx_ctl_pipeline_port_in_stats_read(struct rte_swx_pipeline *p,
10346 struct rte_swx_port_in_stats *stats)
10348 struct port_in *port;
10353 port = port_in_find(p, port_id);
10357 port->type->ops.stats_read(port->obj, stats);
10362 rte_swx_ctl_pipeline_port_out_stats_read(struct rte_swx_pipeline *p,
10364 struct rte_swx_port_out_stats *stats)
10366 struct port_out *port;
10371 port = port_out_find(p, port_id);
10375 port->type->ops.stats_read(port->obj, stats);
10380 rte_swx_ctl_pipeline_table_stats_read(struct rte_swx_pipeline *p,
10381 const char *table_name,
10382 struct rte_swx_table_stats *stats)
10384 struct table *table;
10385 struct table_statistics *table_stats;
10387 if (!p || !table_name || !table_name[0] || !stats || !stats->n_pkts_action)
10390 table = table_find(p, table_name);
10394 table_stats = &p->table_stats[table->id];
10396 memcpy(stats->n_pkts_action,
10397 table_stats->n_pkts_action,
10398 p->n_actions * sizeof(uint64_t));
10400 stats->n_pkts_hit = table_stats->n_pkts_hit[1];
10401 stats->n_pkts_miss = table_stats->n_pkts_hit[0];
10407 rte_swx_ctl_pipeline_selector_stats_read(struct rte_swx_pipeline *p,
10408 const char *selector_name,
10409 struct rte_swx_pipeline_selector_stats *stats)
10411 struct selector *s;
10413 if (!p || !selector_name || !selector_name[0] || !stats)
10416 s = selector_find(p, selector_name);
10420 stats->n_pkts = p->selector_stats[s->id].n_pkts;
10426 rte_swx_ctl_pipeline_learner_stats_read(struct rte_swx_pipeline *p,
10427 const char *learner_name,
10428 struct rte_swx_learner_stats *stats)
10431 struct learner_statistics *learner_stats;
10433 if (!p || !learner_name || !learner_name[0] || !stats || !stats->n_pkts_action)
10436 l = learner_find(p, learner_name);
10440 learner_stats = &p->learner_stats[l->id];
10442 memcpy(stats->n_pkts_action,
10443 learner_stats->n_pkts_action,
10444 p->n_actions * sizeof(uint64_t));
10446 stats->n_pkts_hit = learner_stats->n_pkts_hit[1];
10447 stats->n_pkts_miss = learner_stats->n_pkts_hit[0];
10449 stats->n_pkts_learn_ok = learner_stats->n_pkts_learn[0];
10450 stats->n_pkts_learn_err = learner_stats->n_pkts_learn[1];
10452 stats->n_pkts_forget = learner_stats->n_pkts_forget;
10458 rte_swx_ctl_regarray_info_get(struct rte_swx_pipeline *p,
10459 uint32_t regarray_id,
10460 struct rte_swx_ctl_regarray_info *regarray)
10462 struct regarray *r;
10464 if (!p || !regarray)
10467 r = regarray_find_by_id(p, regarray_id);
10471 strcpy(regarray->name, r->name);
10472 regarray->size = r->size;
10477 rte_swx_ctl_pipeline_regarray_read(struct rte_swx_pipeline *p,
10478 const char *regarray_name,
10479 uint32_t regarray_index,
10482 struct regarray *regarray;
10483 struct regarray_runtime *r;
10485 if (!p || !regarray_name || !value)
10488 regarray = regarray_find(p, regarray_name);
10489 if (!regarray || (regarray_index >= regarray->size))
10492 r = &p->regarray_runtime[regarray->id];
10493 *value = r->regarray[regarray_index];
10498 rte_swx_ctl_pipeline_regarray_write(struct rte_swx_pipeline *p,
10499 const char *regarray_name,
10500 uint32_t regarray_index,
10503 struct regarray *regarray;
10504 struct regarray_runtime *r;
10506 if (!p || !regarray_name)
10509 regarray = regarray_find(p, regarray_name);
10510 if (!regarray || (regarray_index >= regarray->size))
10513 r = &p->regarray_runtime[regarray->id];
10514 r->regarray[regarray_index] = value;
10519 rte_swx_ctl_metarray_info_get(struct rte_swx_pipeline *p,
10520 uint32_t metarray_id,
10521 struct rte_swx_ctl_metarray_info *metarray)
10523 struct metarray *m;
10525 if (!p || !metarray)
10528 m = metarray_find_by_id(p, metarray_id);
10532 strcpy(metarray->name, m->name);
10533 metarray->size = m->size;
10538 rte_swx_ctl_meter_profile_add(struct rte_swx_pipeline *p,
10540 struct rte_meter_trtcm_params *params)
10542 struct meter_profile *mp;
10546 CHECK_NAME(name, EINVAL);
10547 CHECK(params, EINVAL);
10548 CHECK(!meter_profile_find(p, name), EEXIST);
10550 /* Node allocation. */
10551 mp = calloc(1, sizeof(struct meter_profile));
10554 /* Node initialization. */
10555 strcpy(mp->name, name);
10556 memcpy(&mp->params, params, sizeof(struct rte_meter_trtcm_params));
10557 status = rte_meter_trtcm_profile_config(&mp->profile, params);
10563 /* Node add to tailq. */
10564 TAILQ_INSERT_TAIL(&p->meter_profiles, mp, node);
10570 rte_swx_ctl_meter_profile_delete(struct rte_swx_pipeline *p,
10573 struct meter_profile *mp;
10576 CHECK_NAME(name, EINVAL);
10578 mp = meter_profile_find(p, name);
10580 CHECK(!mp->n_users, EBUSY);
10582 /* Remove node from tailq. */
10583 TAILQ_REMOVE(&p->meter_profiles, mp, node);
10590 rte_swx_ctl_meter_reset(struct rte_swx_pipeline *p,
10591 const char *metarray_name,
10592 uint32_t metarray_index)
10594 struct meter_profile *mp_old;
10595 struct metarray *metarray;
10596 struct metarray_runtime *metarray_runtime;
10600 CHECK_NAME(metarray_name, EINVAL);
10602 metarray = metarray_find(p, metarray_name);
10603 CHECK(metarray, EINVAL);
10604 CHECK(metarray_index < metarray->size, EINVAL);
10606 metarray_runtime = &p->metarray_runtime[metarray->id];
10607 m = &metarray_runtime->metarray[metarray_index];
10608 mp_old = m->profile;
10618 rte_swx_ctl_meter_set(struct rte_swx_pipeline *p,
10619 const char *metarray_name,
10620 uint32_t metarray_index,
10621 const char *profile_name)
10623 struct meter_profile *mp, *mp_old;
10624 struct metarray *metarray;
10625 struct metarray_runtime *metarray_runtime;
10629 CHECK_NAME(metarray_name, EINVAL);
10631 metarray = metarray_find(p, metarray_name);
10632 CHECK(metarray, EINVAL);
10633 CHECK(metarray_index < metarray->size, EINVAL);
10635 mp = meter_profile_find(p, profile_name);
10638 metarray_runtime = &p->metarray_runtime[metarray->id];
10639 m = &metarray_runtime->metarray[metarray_index];
10640 mp_old = m->profile;
10642 memset(m, 0, sizeof(struct meter));
10643 rte_meter_trtcm_config(&m->m, &mp->profile);
10645 m->color_mask = RTE_COLORS;
10654 rte_swx_ctl_meter_stats_read(struct rte_swx_pipeline *p,
10655 const char *metarray_name,
10656 uint32_t metarray_index,
10657 struct rte_swx_ctl_meter_stats *stats)
10659 struct metarray *metarray;
10660 struct metarray_runtime *metarray_runtime;
10664 CHECK_NAME(metarray_name, EINVAL);
10666 metarray = metarray_find(p, metarray_name);
10667 CHECK(metarray, EINVAL);
10668 CHECK(metarray_index < metarray->size, EINVAL);
10670 CHECK(stats, EINVAL);
10672 metarray_runtime = &p->metarray_runtime[metarray->id];
10673 m = &metarray_runtime->metarray[metarray_index];
10675 memcpy(stats->n_pkts, m->n_pkts, sizeof(m->n_pkts));
10676 memcpy(stats->n_bytes, m->n_bytes, sizeof(m->n_bytes));