1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2020 Intel Corporation
9 #include "rte_swx_pipeline_internal.h"
11 #define CHECK(condition, err_code) \
17 #define CHECK_NAME(name, err_code) \
20 (strnlen((name), RTE_SWX_NAME_SIZE) < RTE_SWX_NAME_SIZE), \
23 #define CHECK_INSTRUCTION(instr, err_code) \
26 (strnlen((instr), RTE_SWX_INSTRUCTION_SIZE) < \
27 RTE_SWX_INSTRUCTION_SIZE), \
33 #ifndef RTE_SWX_PIPELINE_HUGE_PAGES_DISABLE
35 #include <rte_malloc.h>
38 env_malloc(size_t size, size_t alignment, int numa_node)
40 return rte_zmalloc_socket(NULL, size, alignment, numa_node);
44 env_free(void *start, size_t size __rte_unused)
54 env_malloc(size_t size, size_t alignment __rte_unused, int numa_node)
58 if (numa_available() == -1)
61 start = numa_alloc_onnode(size, numa_node);
65 memset(start, 0, size);
70 env_free(void *start, size_t size)
72 if (numa_available() == -1)
75 numa_free(start, size);
83 static struct struct_type *
84 struct_type_find(struct rte_swx_pipeline *p, const char *name)
86 struct struct_type *elem;
88 TAILQ_FOREACH(elem, &p->struct_types, node)
89 if (strcmp(elem->name, name) == 0)
96 struct_type_field_find(struct struct_type *st, const char *name)
100 for (i = 0; i < st->n_fields; i++) {
101 struct field *f = &st->fields[i];
103 if (strcmp(f->name, name) == 0)
111 rte_swx_pipeline_struct_type_register(struct rte_swx_pipeline *p,
113 struct rte_swx_field_params *fields,
115 int last_field_has_variable_size)
117 struct struct_type *st;
121 CHECK_NAME(name, EINVAL);
122 CHECK(fields, EINVAL);
123 CHECK(n_fields, EINVAL);
125 for (i = 0; i < n_fields; i++) {
126 struct rte_swx_field_params *f = &fields[i];
127 int var_size = ((i == n_fields - 1) && last_field_has_variable_size) ? 1 : 0;
130 CHECK_NAME(f->name, EINVAL);
131 CHECK(f->n_bits, EINVAL);
132 CHECK((f->n_bits <= 64) || var_size, EINVAL);
133 CHECK((f->n_bits & 7) == 0, EINVAL);
135 for (j = 0; j < i; j++) {
136 struct rte_swx_field_params *f_prev = &fields[j];
138 CHECK(strcmp(f->name, f_prev->name), EINVAL);
142 CHECK(!struct_type_find(p, name), EEXIST);
144 /* Node allocation. */
145 st = calloc(1, sizeof(struct struct_type));
148 st->fields = calloc(n_fields, sizeof(struct field));
154 /* Node initialization. */
155 strcpy(st->name, name);
156 for (i = 0; i < n_fields; i++) {
157 struct field *dst = &st->fields[i];
158 struct rte_swx_field_params *src = &fields[i];
159 int var_size = ((i == n_fields - 1) && last_field_has_variable_size) ? 1 : 0;
161 strcpy(dst->name, src->name);
162 dst->n_bits = src->n_bits;
163 dst->offset = st->n_bits;
164 dst->var_size = var_size;
166 st->n_bits += src->n_bits;
167 st->n_bits_min += var_size ? 0 : src->n_bits;
169 st->n_fields = n_fields;
170 st->var_size = last_field_has_variable_size;
172 /* Node add to tailq. */
173 TAILQ_INSERT_TAIL(&p->struct_types, st, node);
179 struct_build(struct rte_swx_pipeline *p)
183 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
184 struct thread *t = &p->threads[i];
186 t->structs = calloc(p->n_structs, sizeof(uint8_t *));
187 CHECK(t->structs, ENOMEM);
194 struct_build_free(struct rte_swx_pipeline *p)
198 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
199 struct thread *t = &p->threads[i];
207 struct_free(struct rte_swx_pipeline *p)
209 struct_build_free(p);
213 struct struct_type *elem;
215 elem = TAILQ_FIRST(&p->struct_types);
219 TAILQ_REMOVE(&p->struct_types, elem, node);
228 static struct port_in_type *
229 port_in_type_find(struct rte_swx_pipeline *p, const char *name)
231 struct port_in_type *elem;
236 TAILQ_FOREACH(elem, &p->port_in_types, node)
237 if (strcmp(elem->name, name) == 0)
244 rte_swx_pipeline_port_in_type_register(struct rte_swx_pipeline *p,
246 struct rte_swx_port_in_ops *ops)
248 struct port_in_type *elem;
251 CHECK_NAME(name, EINVAL);
253 CHECK(ops->create, EINVAL);
254 CHECK(ops->free, EINVAL);
255 CHECK(ops->pkt_rx, EINVAL);
256 CHECK(ops->stats_read, EINVAL);
258 CHECK(!port_in_type_find(p, name), EEXIST);
260 /* Node allocation. */
261 elem = calloc(1, sizeof(struct port_in_type));
264 /* Node initialization. */
265 strcpy(elem->name, name);
266 memcpy(&elem->ops, ops, sizeof(*ops));
268 /* Node add to tailq. */
269 TAILQ_INSERT_TAIL(&p->port_in_types, elem, node);
274 static struct port_in *
275 port_in_find(struct rte_swx_pipeline *p, uint32_t port_id)
277 struct port_in *port;
279 TAILQ_FOREACH(port, &p->ports_in, node)
280 if (port->id == port_id)
287 rte_swx_pipeline_port_in_config(struct rte_swx_pipeline *p,
289 const char *port_type_name,
292 struct port_in_type *type = NULL;
293 struct port_in *port = NULL;
298 CHECK(!port_in_find(p, port_id), EINVAL);
300 CHECK_NAME(port_type_name, EINVAL);
301 type = port_in_type_find(p, port_type_name);
304 obj = type->ops.create(args);
307 /* Node allocation. */
308 port = calloc(1, sizeof(struct port_in));
311 /* Node initialization. */
316 /* Node add to tailq. */
317 TAILQ_INSERT_TAIL(&p->ports_in, port, node);
318 if (p->n_ports_in < port_id + 1)
319 p->n_ports_in = port_id + 1;
325 port_in_build(struct rte_swx_pipeline *p)
327 struct port_in *port;
330 CHECK(p->n_ports_in, EINVAL);
331 CHECK(rte_is_power_of_2(p->n_ports_in), EINVAL);
333 for (i = 0; i < p->n_ports_in; i++)
334 CHECK(port_in_find(p, i), EINVAL);
336 p->in = calloc(p->n_ports_in, sizeof(struct port_in_runtime));
337 CHECK(p->in, ENOMEM);
339 TAILQ_FOREACH(port, &p->ports_in, node) {
340 struct port_in_runtime *in = &p->in[port->id];
342 in->pkt_rx = port->type->ops.pkt_rx;
350 port_in_build_free(struct rte_swx_pipeline *p)
357 port_in_free(struct rte_swx_pipeline *p)
359 port_in_build_free(p);
363 struct port_in *port;
365 port = TAILQ_FIRST(&p->ports_in);
369 TAILQ_REMOVE(&p->ports_in, port, node);
370 port->type->ops.free(port->obj);
374 /* Input port types. */
376 struct port_in_type *elem;
378 elem = TAILQ_FIRST(&p->port_in_types);
382 TAILQ_REMOVE(&p->port_in_types, elem, node);
390 static struct port_out_type *
391 port_out_type_find(struct rte_swx_pipeline *p, const char *name)
393 struct port_out_type *elem;
398 TAILQ_FOREACH(elem, &p->port_out_types, node)
399 if (!strcmp(elem->name, name))
406 rte_swx_pipeline_port_out_type_register(struct rte_swx_pipeline *p,
408 struct rte_swx_port_out_ops *ops)
410 struct port_out_type *elem;
413 CHECK_NAME(name, EINVAL);
415 CHECK(ops->create, EINVAL);
416 CHECK(ops->free, EINVAL);
417 CHECK(ops->pkt_tx, EINVAL);
418 CHECK(ops->stats_read, EINVAL);
420 CHECK(!port_out_type_find(p, name), EEXIST);
422 /* Node allocation. */
423 elem = calloc(1, sizeof(struct port_out_type));
426 /* Node initialization. */
427 strcpy(elem->name, name);
428 memcpy(&elem->ops, ops, sizeof(*ops));
430 /* Node add to tailq. */
431 TAILQ_INSERT_TAIL(&p->port_out_types, elem, node);
436 static struct port_out *
437 port_out_find(struct rte_swx_pipeline *p, uint32_t port_id)
439 struct port_out *port;
441 TAILQ_FOREACH(port, &p->ports_out, node)
442 if (port->id == port_id)
449 rte_swx_pipeline_port_out_config(struct rte_swx_pipeline *p,
451 const char *port_type_name,
454 struct port_out_type *type = NULL;
455 struct port_out *port = NULL;
460 CHECK(!port_out_find(p, port_id), EINVAL);
462 CHECK_NAME(port_type_name, EINVAL);
463 type = port_out_type_find(p, port_type_name);
466 obj = type->ops.create(args);
469 /* Node allocation. */
470 port = calloc(1, sizeof(struct port_out));
473 /* Node initialization. */
478 /* Node add to tailq. */
479 TAILQ_INSERT_TAIL(&p->ports_out, port, node);
480 if (p->n_ports_out < port_id + 1)
481 p->n_ports_out = port_id + 1;
487 port_out_build(struct rte_swx_pipeline *p)
489 struct port_out *port;
492 CHECK(p->n_ports_out, EINVAL);
494 for (i = 0; i < p->n_ports_out; i++)
495 CHECK(port_out_find(p, i), EINVAL);
497 p->out = calloc(p->n_ports_out, sizeof(struct port_out_runtime));
498 CHECK(p->out, ENOMEM);
500 TAILQ_FOREACH(port, &p->ports_out, node) {
501 struct port_out_runtime *out = &p->out[port->id];
503 out->pkt_tx = port->type->ops.pkt_tx;
504 out->flush = port->type->ops.flush;
505 out->obj = port->obj;
512 port_out_build_free(struct rte_swx_pipeline *p)
519 port_out_free(struct rte_swx_pipeline *p)
521 port_out_build_free(p);
525 struct port_out *port;
527 port = TAILQ_FIRST(&p->ports_out);
531 TAILQ_REMOVE(&p->ports_out, port, node);
532 port->type->ops.free(port->obj);
536 /* Output port types. */
538 struct port_out_type *elem;
540 elem = TAILQ_FIRST(&p->port_out_types);
544 TAILQ_REMOVE(&p->port_out_types, elem, node);
552 static struct extern_type *
553 extern_type_find(struct rte_swx_pipeline *p, const char *name)
555 struct extern_type *elem;
557 TAILQ_FOREACH(elem, &p->extern_types, node)
558 if (strcmp(elem->name, name) == 0)
564 static struct extern_type_member_func *
565 extern_type_member_func_find(struct extern_type *type, const char *name)
567 struct extern_type_member_func *elem;
569 TAILQ_FOREACH(elem, &type->funcs, node)
570 if (strcmp(elem->name, name) == 0)
576 static struct extern_obj *
577 extern_obj_find(struct rte_swx_pipeline *p, const char *name)
579 struct extern_obj *elem;
581 TAILQ_FOREACH(elem, &p->extern_objs, node)
582 if (strcmp(elem->name, name) == 0)
588 static struct extern_type_member_func *
589 extern_obj_member_func_parse(struct rte_swx_pipeline *p,
591 struct extern_obj **obj)
593 struct extern_obj *object;
594 struct extern_type_member_func *func;
595 char *object_name, *func_name;
597 if (name[0] != 'e' || name[1] != '.')
600 object_name = strdup(&name[2]);
604 func_name = strchr(object_name, '.');
613 object = extern_obj_find(p, object_name);
619 func = extern_type_member_func_find(object->type, func_name);
632 static struct field *
633 extern_obj_mailbox_field_parse(struct rte_swx_pipeline *p,
635 struct extern_obj **object)
637 struct extern_obj *obj;
639 char *obj_name, *field_name;
641 if ((name[0] != 'e') || (name[1] != '.'))
644 obj_name = strdup(&name[2]);
648 field_name = strchr(obj_name, '.');
657 obj = extern_obj_find(p, obj_name);
663 f = struct_type_field_find(obj->type->mailbox_struct_type, field_name);
677 rte_swx_pipeline_extern_type_register(struct rte_swx_pipeline *p,
679 const char *mailbox_struct_type_name,
680 rte_swx_extern_type_constructor_t constructor,
681 rte_swx_extern_type_destructor_t destructor)
683 struct extern_type *elem;
684 struct struct_type *mailbox_struct_type;
688 CHECK_NAME(name, EINVAL);
689 CHECK(!extern_type_find(p, name), EEXIST);
691 CHECK_NAME(mailbox_struct_type_name, EINVAL);
692 mailbox_struct_type = struct_type_find(p, mailbox_struct_type_name);
693 CHECK(mailbox_struct_type, EINVAL);
694 CHECK(!mailbox_struct_type->var_size, EINVAL);
696 CHECK(constructor, EINVAL);
697 CHECK(destructor, EINVAL);
699 /* Node allocation. */
700 elem = calloc(1, sizeof(struct extern_type));
703 /* Node initialization. */
704 strcpy(elem->name, name);
705 elem->mailbox_struct_type = mailbox_struct_type;
706 elem->constructor = constructor;
707 elem->destructor = destructor;
708 TAILQ_INIT(&elem->funcs);
710 /* Node add to tailq. */
711 TAILQ_INSERT_TAIL(&p->extern_types, elem, node);
717 rte_swx_pipeline_extern_type_member_func_register(struct rte_swx_pipeline *p,
718 const char *extern_type_name,
720 rte_swx_extern_type_member_func_t member_func)
722 struct extern_type *type;
723 struct extern_type_member_func *type_member;
727 CHECK_NAME(extern_type_name, EINVAL);
728 type = extern_type_find(p, extern_type_name);
730 CHECK(type->n_funcs < RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX, ENOSPC);
732 CHECK_NAME(name, EINVAL);
733 CHECK(!extern_type_member_func_find(type, name), EEXIST);
735 CHECK(member_func, EINVAL);
737 /* Node allocation. */
738 type_member = calloc(1, sizeof(struct extern_type_member_func));
739 CHECK(type_member, ENOMEM);
741 /* Node initialization. */
742 strcpy(type_member->name, name);
743 type_member->func = member_func;
744 type_member->id = type->n_funcs;
746 /* Node add to tailq. */
747 TAILQ_INSERT_TAIL(&type->funcs, type_member, node);
754 rte_swx_pipeline_extern_object_config(struct rte_swx_pipeline *p,
755 const char *extern_type_name,
759 struct extern_type *type;
760 struct extern_obj *obj;
765 CHECK_NAME(extern_type_name, EINVAL);
766 type = extern_type_find(p, extern_type_name);
769 CHECK_NAME(name, EINVAL);
770 CHECK(!extern_obj_find(p, name), EEXIST);
772 /* Node allocation. */
773 obj = calloc(1, sizeof(struct extern_obj));
776 /* Object construction. */
777 obj_handle = type->constructor(args);
783 /* Node initialization. */
784 strcpy(obj->name, name);
786 obj->obj = obj_handle;
787 obj->struct_id = p->n_structs;
788 obj->id = p->n_extern_objs;
790 /* Node add to tailq. */
791 TAILQ_INSERT_TAIL(&p->extern_objs, obj, node);
799 extern_obj_build(struct rte_swx_pipeline *p)
803 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
804 struct thread *t = &p->threads[i];
805 struct extern_obj *obj;
807 t->extern_objs = calloc(p->n_extern_objs,
808 sizeof(struct extern_obj_runtime));
809 CHECK(t->extern_objs, ENOMEM);
811 TAILQ_FOREACH(obj, &p->extern_objs, node) {
812 struct extern_obj_runtime *r =
813 &t->extern_objs[obj->id];
814 struct extern_type_member_func *func;
815 uint32_t mailbox_size =
816 obj->type->mailbox_struct_type->n_bits / 8;
820 r->mailbox = calloc(1, mailbox_size);
821 CHECK(r->mailbox, ENOMEM);
823 TAILQ_FOREACH(func, &obj->type->funcs, node)
824 r->funcs[func->id] = func->func;
826 t->structs[obj->struct_id] = r->mailbox;
834 extern_obj_build_free(struct rte_swx_pipeline *p)
838 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
839 struct thread *t = &p->threads[i];
845 for (j = 0; j < p->n_extern_objs; j++) {
846 struct extern_obj_runtime *r = &t->extern_objs[j];
851 free(t->extern_objs);
852 t->extern_objs = NULL;
857 extern_obj_free(struct rte_swx_pipeline *p)
859 extern_obj_build_free(p);
861 /* Extern objects. */
863 struct extern_obj *elem;
865 elem = TAILQ_FIRST(&p->extern_objs);
869 TAILQ_REMOVE(&p->extern_objs, elem, node);
871 elem->type->destructor(elem->obj);
877 struct extern_type *elem;
879 elem = TAILQ_FIRST(&p->extern_types);
883 TAILQ_REMOVE(&p->extern_types, elem, node);
886 struct extern_type_member_func *func;
888 func = TAILQ_FIRST(&elem->funcs);
892 TAILQ_REMOVE(&elem->funcs, func, node);
903 static struct extern_func *
904 extern_func_find(struct rte_swx_pipeline *p, const char *name)
906 struct extern_func *elem;
908 TAILQ_FOREACH(elem, &p->extern_funcs, node)
909 if (strcmp(elem->name, name) == 0)
915 static struct extern_func *
916 extern_func_parse(struct rte_swx_pipeline *p,
919 if (name[0] != 'f' || name[1] != '.')
922 return extern_func_find(p, &name[2]);
925 static struct field *
926 extern_func_mailbox_field_parse(struct rte_swx_pipeline *p,
928 struct extern_func **function)
930 struct extern_func *func;
932 char *func_name, *field_name;
934 if ((name[0] != 'f') || (name[1] != '.'))
937 func_name = strdup(&name[2]);
941 field_name = strchr(func_name, '.');
950 func = extern_func_find(p, func_name);
956 f = struct_type_field_find(func->mailbox_struct_type, field_name);
970 rte_swx_pipeline_extern_func_register(struct rte_swx_pipeline *p,
972 const char *mailbox_struct_type_name,
973 rte_swx_extern_func_t func)
975 struct extern_func *f;
976 struct struct_type *mailbox_struct_type;
980 CHECK_NAME(name, EINVAL);
981 CHECK(!extern_func_find(p, name), EEXIST);
983 CHECK_NAME(mailbox_struct_type_name, EINVAL);
984 mailbox_struct_type = struct_type_find(p, mailbox_struct_type_name);
985 CHECK(mailbox_struct_type, EINVAL);
986 CHECK(!mailbox_struct_type->var_size, EINVAL);
990 /* Node allocation. */
991 f = calloc(1, sizeof(struct extern_func));
994 /* Node initialization. */
995 strcpy(f->name, name);
996 f->mailbox_struct_type = mailbox_struct_type;
998 f->struct_id = p->n_structs;
999 f->id = p->n_extern_funcs;
1001 /* Node add to tailq. */
1002 TAILQ_INSERT_TAIL(&p->extern_funcs, f, node);
1003 p->n_extern_funcs++;
1010 extern_func_build(struct rte_swx_pipeline *p)
1014 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1015 struct thread *t = &p->threads[i];
1016 struct extern_func *func;
1018 /* Memory allocation. */
1019 t->extern_funcs = calloc(p->n_extern_funcs,
1020 sizeof(struct extern_func_runtime));
1021 CHECK(t->extern_funcs, ENOMEM);
1023 /* Extern function. */
1024 TAILQ_FOREACH(func, &p->extern_funcs, node) {
1025 struct extern_func_runtime *r =
1026 &t->extern_funcs[func->id];
1027 uint32_t mailbox_size =
1028 func->mailbox_struct_type->n_bits / 8;
1030 r->func = func->func;
1032 r->mailbox = calloc(1, mailbox_size);
1033 CHECK(r->mailbox, ENOMEM);
1035 t->structs[func->struct_id] = r->mailbox;
1043 extern_func_build_free(struct rte_swx_pipeline *p)
1047 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1048 struct thread *t = &p->threads[i];
1051 if (!t->extern_funcs)
1054 for (j = 0; j < p->n_extern_funcs; j++) {
1055 struct extern_func_runtime *r = &t->extern_funcs[j];
1060 free(t->extern_funcs);
1061 t->extern_funcs = NULL;
1066 extern_func_free(struct rte_swx_pipeline *p)
1068 extern_func_build_free(p);
1071 struct extern_func *elem;
1073 elem = TAILQ_FIRST(&p->extern_funcs);
1077 TAILQ_REMOVE(&p->extern_funcs, elem, node);
1085 static struct header *
1086 header_find(struct rte_swx_pipeline *p, const char *name)
1088 struct header *elem;
1090 TAILQ_FOREACH(elem, &p->headers, node)
1091 if (strcmp(elem->name, name) == 0)
1097 static struct header *
1098 header_find_by_struct_id(struct rte_swx_pipeline *p, uint32_t struct_id)
1100 struct header *elem;
1102 TAILQ_FOREACH(elem, &p->headers, node)
1103 if (elem->struct_id == struct_id)
1109 static struct header *
1110 header_parse(struct rte_swx_pipeline *p,
1113 if (name[0] != 'h' || name[1] != '.')
1116 return header_find(p, &name[2]);
1119 static struct field *
1120 header_field_parse(struct rte_swx_pipeline *p,
1122 struct header **header)
1126 char *header_name, *field_name;
1128 if ((name[0] != 'h') || (name[1] != '.'))
1131 header_name = strdup(&name[2]);
1135 field_name = strchr(header_name, '.');
1144 h = header_find(p, header_name);
1150 f = struct_type_field_find(h->st, field_name);
1164 rte_swx_pipeline_packet_header_register(struct rte_swx_pipeline *p,
1166 const char *struct_type_name)
1168 struct struct_type *st;
1170 size_t n_headers_max;
1173 CHECK_NAME(name, EINVAL);
1174 CHECK_NAME(struct_type_name, EINVAL);
1176 CHECK(!header_find(p, name), EEXIST);
1178 st = struct_type_find(p, struct_type_name);
1181 n_headers_max = RTE_SIZEOF_FIELD(struct thread, valid_headers) * 8;
1182 CHECK(p->n_headers < n_headers_max, ENOSPC);
1184 /* Node allocation. */
1185 h = calloc(1, sizeof(struct header));
1188 /* Node initialization. */
1189 strcpy(h->name, name);
1191 h->struct_id = p->n_structs;
1192 h->id = p->n_headers;
1194 /* Node add to tailq. */
1195 TAILQ_INSERT_TAIL(&p->headers, h, node);
1203 header_build(struct rte_swx_pipeline *p)
1206 uint32_t n_bytes = 0, i;
1208 TAILQ_FOREACH(h, &p->headers, node) {
1209 n_bytes += h->st->n_bits / 8;
1212 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1213 struct thread *t = &p->threads[i];
1214 uint32_t offset = 0;
1216 t->headers = calloc(p->n_headers,
1217 sizeof(struct header_runtime));
1218 CHECK(t->headers, ENOMEM);
1220 t->headers_out = calloc(p->n_headers,
1221 sizeof(struct header_out_runtime));
1222 CHECK(t->headers_out, ENOMEM);
1224 t->header_storage = calloc(1, n_bytes);
1225 CHECK(t->header_storage, ENOMEM);
1227 t->header_out_storage = calloc(1, n_bytes);
1228 CHECK(t->header_out_storage, ENOMEM);
1230 TAILQ_FOREACH(h, &p->headers, node) {
1231 uint8_t *header_storage;
1232 uint32_t n_bytes = h->st->n_bits / 8;
1234 header_storage = &t->header_storage[offset];
1237 t->headers[h->id].ptr0 = header_storage;
1238 t->headers[h->id].n_bytes = n_bytes;
1240 t->structs[h->struct_id] = header_storage;
1248 header_build_free(struct rte_swx_pipeline *p)
1252 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1253 struct thread *t = &p->threads[i];
1255 free(t->headers_out);
1256 t->headers_out = NULL;
1261 free(t->header_out_storage);
1262 t->header_out_storage = NULL;
1264 free(t->header_storage);
1265 t->header_storage = NULL;
1270 header_free(struct rte_swx_pipeline *p)
1272 header_build_free(p);
1275 struct header *elem;
1277 elem = TAILQ_FIRST(&p->headers);
1281 TAILQ_REMOVE(&p->headers, elem, node);
1289 static struct field *
1290 metadata_field_parse(struct rte_swx_pipeline *p, const char *name)
1292 if (!p->metadata_st)
1295 if (name[0] != 'm' || name[1] != '.')
1298 return struct_type_field_find(p->metadata_st, &name[2]);
1302 rte_swx_pipeline_packet_metadata_register(struct rte_swx_pipeline *p,
1303 const char *struct_type_name)
1305 struct struct_type *st = NULL;
1309 CHECK_NAME(struct_type_name, EINVAL);
1310 st = struct_type_find(p, struct_type_name);
1312 CHECK(!st->var_size, EINVAL);
1313 CHECK(!p->metadata_st, EINVAL);
1315 p->metadata_st = st;
1316 p->metadata_struct_id = p->n_structs;
1324 metadata_build(struct rte_swx_pipeline *p)
1326 uint32_t n_bytes = p->metadata_st->n_bits / 8;
1329 /* Thread-level initialization. */
1330 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1331 struct thread *t = &p->threads[i];
1334 metadata = calloc(1, n_bytes);
1335 CHECK(metadata, ENOMEM);
1337 t->metadata = metadata;
1338 t->structs[p->metadata_struct_id] = metadata;
1345 metadata_build_free(struct rte_swx_pipeline *p)
1349 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1350 struct thread *t = &p->threads[i];
1358 metadata_free(struct rte_swx_pipeline *p)
1360 metadata_build_free(p);
1367 instruction_is_tx(enum instruction_type type)
1380 instruction_is_jmp(struct instruction *instr)
1382 switch (instr->type) {
1384 case INSTR_JMP_VALID:
1385 case INSTR_JMP_INVALID:
1387 case INSTR_JMP_MISS:
1388 case INSTR_JMP_ACTION_HIT:
1389 case INSTR_JMP_ACTION_MISS:
1391 case INSTR_JMP_EQ_MH:
1392 case INSTR_JMP_EQ_HM:
1393 case INSTR_JMP_EQ_HH:
1394 case INSTR_JMP_EQ_I:
1396 case INSTR_JMP_NEQ_MH:
1397 case INSTR_JMP_NEQ_HM:
1398 case INSTR_JMP_NEQ_HH:
1399 case INSTR_JMP_NEQ_I:
1401 case INSTR_JMP_LT_MH:
1402 case INSTR_JMP_LT_HM:
1403 case INSTR_JMP_LT_HH:
1404 case INSTR_JMP_LT_MI:
1405 case INSTR_JMP_LT_HI:
1407 case INSTR_JMP_GT_MH:
1408 case INSTR_JMP_GT_HM:
1409 case INSTR_JMP_GT_HH:
1410 case INSTR_JMP_GT_MI:
1411 case INSTR_JMP_GT_HI:
1419 static struct field *
1420 action_field_parse(struct action *action, const char *name);
1422 static struct field *
1423 struct_field_parse(struct rte_swx_pipeline *p,
1424 struct action *action,
1426 uint32_t *struct_id)
1433 struct header *header;
1435 f = header_field_parse(p, name, &header);
1439 *struct_id = header->struct_id;
1445 f = metadata_field_parse(p, name);
1449 *struct_id = p->metadata_struct_id;
1458 f = action_field_parse(action, name);
1468 struct extern_obj *obj;
1470 f = extern_obj_mailbox_field_parse(p, name, &obj);
1474 *struct_id = obj->struct_id;
1480 struct extern_func *func;
1482 f = extern_func_mailbox_field_parse(p, name, &func);
1486 *struct_id = func->struct_id;
1499 instr_rx_translate(struct rte_swx_pipeline *p,
1500 struct action *action,
1503 struct instruction *instr,
1504 struct instruction_data *data __rte_unused)
1508 CHECK(!action, EINVAL);
1509 CHECK(n_tokens == 2, EINVAL);
1511 f = metadata_field_parse(p, tokens[1]);
1514 instr->type = INSTR_RX;
1515 instr->io.io.offset = f->offset / 8;
1516 instr->io.io.n_bits = f->n_bits;
1524 instr_tx_translate(struct rte_swx_pipeline *p,
1525 struct action *action __rte_unused,
1528 struct instruction *instr,
1529 struct instruction_data *data __rte_unused)
1531 char *port = tokens[1];
1535 CHECK(n_tokens == 2, EINVAL);
1537 f = metadata_field_parse(p, port);
1539 instr->type = INSTR_TX;
1540 instr->io.io.offset = f->offset / 8;
1541 instr->io.io.n_bits = f->n_bits;
1546 port_val = strtoul(port, &port, 0);
1547 CHECK(!port[0], EINVAL);
1549 instr->type = INSTR_TX_I;
1550 instr->io.io.val = port_val;
1555 instr_drop_translate(struct rte_swx_pipeline *p,
1556 struct action *action __rte_unused,
1557 char **tokens __rte_unused,
1559 struct instruction *instr,
1560 struct instruction_data *data __rte_unused)
1562 CHECK(n_tokens == 1, EINVAL);
1565 instr->type = INSTR_TX_I;
1566 instr->io.io.val = p->n_ports_out - 1;
1571 instr_tx_exec(struct rte_swx_pipeline *p)
1573 struct thread *t = &p->threads[p->thread_id];
1574 struct instruction *ip = t->ip;
1576 __instr_tx_exec(p, t, ip);
1579 thread_ip_reset(p, t);
1584 instr_tx_i_exec(struct rte_swx_pipeline *p)
1586 struct thread *t = &p->threads[p->thread_id];
1587 struct instruction *ip = t->ip;
1589 __instr_tx_i_exec(p, t, ip);
1592 thread_ip_reset(p, t);
1600 instr_hdr_extract_translate(struct rte_swx_pipeline *p,
1601 struct action *action,
1604 struct instruction *instr,
1605 struct instruction_data *data __rte_unused)
1609 CHECK(!action, EINVAL);
1610 CHECK((n_tokens == 2) || (n_tokens == 3), EINVAL);
1612 h = header_parse(p, tokens[1]);
1615 if (n_tokens == 2) {
1616 CHECK(!h->st->var_size, EINVAL);
1618 instr->type = INSTR_HDR_EXTRACT;
1619 instr->io.hdr.header_id[0] = h->id;
1620 instr->io.hdr.struct_id[0] = h->struct_id;
1621 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
1625 CHECK(h->st->var_size, EINVAL);
1627 mf = metadata_field_parse(p, tokens[2]);
1629 CHECK(!mf->var_size, EINVAL);
1631 instr->type = INSTR_HDR_EXTRACT_M;
1632 instr->io.io.offset = mf->offset / 8;
1633 instr->io.io.n_bits = mf->n_bits;
1634 instr->io.hdr.header_id[0] = h->id;
1635 instr->io.hdr.struct_id[0] = h->struct_id;
1636 instr->io.hdr.n_bytes[0] = h->st->n_bits_min / 8;
1643 instr_hdr_lookahead_translate(struct rte_swx_pipeline *p,
1644 struct action *action,
1647 struct instruction *instr,
1648 struct instruction_data *data __rte_unused)
1652 CHECK(!action, EINVAL);
1653 CHECK(n_tokens == 2, EINVAL);
1655 h = header_parse(p, tokens[1]);
1657 CHECK(!h->st->var_size, EINVAL);
1659 instr->type = INSTR_HDR_LOOKAHEAD;
1660 instr->io.hdr.header_id[0] = h->id;
1661 instr->io.hdr.struct_id[0] = h->struct_id;
1662 instr->io.hdr.n_bytes[0] = 0; /* Unused. */
1668 instr_hdr_extract_exec(struct rte_swx_pipeline *p)
1670 struct thread *t = &p->threads[p->thread_id];
1671 struct instruction *ip = t->ip;
1673 __instr_hdr_extract_exec(p, t, ip);
1680 instr_hdr_extract2_exec(struct rte_swx_pipeline *p)
1682 struct thread *t = &p->threads[p->thread_id];
1683 struct instruction *ip = t->ip;
1685 __instr_hdr_extract2_exec(p, t, ip);
1692 instr_hdr_extract3_exec(struct rte_swx_pipeline *p)
1694 struct thread *t = &p->threads[p->thread_id];
1695 struct instruction *ip = t->ip;
1697 __instr_hdr_extract3_exec(p, t, ip);
1704 instr_hdr_extract4_exec(struct rte_swx_pipeline *p)
1706 struct thread *t = &p->threads[p->thread_id];
1707 struct instruction *ip = t->ip;
1709 __instr_hdr_extract4_exec(p, t, ip);
1716 instr_hdr_extract5_exec(struct rte_swx_pipeline *p)
1718 struct thread *t = &p->threads[p->thread_id];
1719 struct instruction *ip = t->ip;
1721 __instr_hdr_extract5_exec(p, t, ip);
1728 instr_hdr_extract6_exec(struct rte_swx_pipeline *p)
1730 struct thread *t = &p->threads[p->thread_id];
1731 struct instruction *ip = t->ip;
1733 __instr_hdr_extract6_exec(p, t, ip);
1740 instr_hdr_extract7_exec(struct rte_swx_pipeline *p)
1742 struct thread *t = &p->threads[p->thread_id];
1743 struct instruction *ip = t->ip;
1745 __instr_hdr_extract7_exec(p, t, ip);
1752 instr_hdr_extract8_exec(struct rte_swx_pipeline *p)
1754 struct thread *t = &p->threads[p->thread_id];
1755 struct instruction *ip = t->ip;
1757 __instr_hdr_extract8_exec(p, t, ip);
1764 instr_hdr_extract_m_exec(struct rte_swx_pipeline *p)
1766 struct thread *t = &p->threads[p->thread_id];
1767 struct instruction *ip = t->ip;
1769 __instr_hdr_extract_m_exec(p, t, ip);
1776 instr_hdr_lookahead_exec(struct rte_swx_pipeline *p)
1778 struct thread *t = &p->threads[p->thread_id];
1779 struct instruction *ip = t->ip;
1781 __instr_hdr_lookahead_exec(p, t, ip);
1791 instr_hdr_emit_translate(struct rte_swx_pipeline *p,
1792 struct action *action __rte_unused,
1795 struct instruction *instr,
1796 struct instruction_data *data __rte_unused)
1800 CHECK(n_tokens == 2, EINVAL);
1802 h = header_parse(p, tokens[1]);
1805 instr->type = INSTR_HDR_EMIT;
1806 instr->io.hdr.header_id[0] = h->id;
1807 instr->io.hdr.struct_id[0] = h->struct_id;
1808 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
1813 instr_hdr_emit_exec(struct rte_swx_pipeline *p)
1815 struct thread *t = &p->threads[p->thread_id];
1816 struct instruction *ip = t->ip;
1818 __instr_hdr_emit_exec(p, t, ip);
1825 instr_hdr_emit_tx_exec(struct rte_swx_pipeline *p)
1827 struct thread *t = &p->threads[p->thread_id];
1828 struct instruction *ip = t->ip;
1830 __instr_hdr_emit_tx_exec(p, t, ip);
1833 thread_ip_reset(p, t);
1838 instr_hdr_emit2_tx_exec(struct rte_swx_pipeline *p)
1840 struct thread *t = &p->threads[p->thread_id];
1841 struct instruction *ip = t->ip;
1843 __instr_hdr_emit2_tx_exec(p, t, ip);
1846 thread_ip_reset(p, t);
1851 instr_hdr_emit3_tx_exec(struct rte_swx_pipeline *p)
1853 struct thread *t = &p->threads[p->thread_id];
1854 struct instruction *ip = t->ip;
1856 __instr_hdr_emit3_tx_exec(p, t, ip);
1859 thread_ip_reset(p, t);
1864 instr_hdr_emit4_tx_exec(struct rte_swx_pipeline *p)
1866 struct thread *t = &p->threads[p->thread_id];
1867 struct instruction *ip = t->ip;
1869 __instr_hdr_emit4_tx_exec(p, t, ip);
1872 thread_ip_reset(p, t);
1877 instr_hdr_emit5_tx_exec(struct rte_swx_pipeline *p)
1879 struct thread *t = &p->threads[p->thread_id];
1880 struct instruction *ip = t->ip;
1882 __instr_hdr_emit5_tx_exec(p, t, ip);
1885 thread_ip_reset(p, t);
1890 instr_hdr_emit6_tx_exec(struct rte_swx_pipeline *p)
1892 struct thread *t = &p->threads[p->thread_id];
1893 struct instruction *ip = t->ip;
1895 __instr_hdr_emit6_tx_exec(p, t, ip);
1898 thread_ip_reset(p, t);
1903 instr_hdr_emit7_tx_exec(struct rte_swx_pipeline *p)
1905 struct thread *t = &p->threads[p->thread_id];
1906 struct instruction *ip = t->ip;
1908 __instr_hdr_emit7_tx_exec(p, t, ip);
1911 thread_ip_reset(p, t);
1916 instr_hdr_emit8_tx_exec(struct rte_swx_pipeline *p)
1918 struct thread *t = &p->threads[p->thread_id];
1919 struct instruction *ip = t->ip;
1921 __instr_hdr_emit8_tx_exec(p, t, ip);
1924 thread_ip_reset(p, t);
1932 instr_hdr_validate_translate(struct rte_swx_pipeline *p,
1933 struct action *action __rte_unused,
1936 struct instruction *instr,
1937 struct instruction_data *data __rte_unused)
1941 CHECK(n_tokens == 2, EINVAL);
1943 h = header_parse(p, tokens[1]);
1946 instr->type = INSTR_HDR_VALIDATE;
1947 instr->valid.header_id = h->id;
1952 instr_hdr_validate_exec(struct rte_swx_pipeline *p)
1954 struct thread *t = &p->threads[p->thread_id];
1955 struct instruction *ip = t->ip;
1957 __instr_hdr_validate_exec(p, t, ip);
1967 instr_hdr_invalidate_translate(struct rte_swx_pipeline *p,
1968 struct action *action __rte_unused,
1971 struct instruction *instr,
1972 struct instruction_data *data __rte_unused)
1976 CHECK(n_tokens == 2, EINVAL);
1978 h = header_parse(p, tokens[1]);
1981 instr->type = INSTR_HDR_INVALIDATE;
1982 instr->valid.header_id = h->id;
1987 instr_hdr_invalidate_exec(struct rte_swx_pipeline *p)
1989 struct thread *t = &p->threads[p->thread_id];
1990 struct instruction *ip = t->ip;
1992 __instr_hdr_invalidate_exec(p, t, ip);
2001 static struct table *
2002 table_find(struct rte_swx_pipeline *p, const char *name);
2004 static struct selector *
2005 selector_find(struct rte_swx_pipeline *p, const char *name);
2007 static struct learner *
2008 learner_find(struct rte_swx_pipeline *p, const char *name);
2011 instr_table_translate(struct rte_swx_pipeline *p,
2012 struct action *action,
2015 struct instruction *instr,
2016 struct instruction_data *data __rte_unused)
2022 CHECK(!action, EINVAL);
2023 CHECK(n_tokens == 2, EINVAL);
2025 t = table_find(p, tokens[1]);
2027 instr->type = INSTR_TABLE;
2028 instr->table.table_id = t->id;
2032 s = selector_find(p, tokens[1]);
2034 instr->type = INSTR_SELECTOR;
2035 instr->table.table_id = s->id;
2039 l = learner_find(p, tokens[1]);
2041 instr->type = INSTR_LEARNER;
2042 instr->table.table_id = l->id;
2050 instr_table_exec(struct rte_swx_pipeline *p)
2052 struct thread *t = &p->threads[p->thread_id];
2053 struct instruction *ip = t->ip;
2054 uint32_t table_id = ip->table.table_id;
2055 struct rte_swx_table_state *ts = &t->table_state[table_id];
2056 struct table_runtime *table = &t->tables[table_id];
2057 struct table_statistics *stats = &p->table_stats[table_id];
2058 uint64_t action_id, n_pkts_hit, n_pkts_action;
2059 uint8_t *action_data;
2063 done = table->func(ts->obj,
2071 TRACE("[Thread %2u] table %u (not finalized)\n",
2079 action_id = hit ? action_id : ts->default_action_id;
2080 action_data = hit ? action_data : ts->default_action_data;
2081 n_pkts_hit = stats->n_pkts_hit[hit];
2082 n_pkts_action = stats->n_pkts_action[action_id];
2084 TRACE("[Thread %2u] table %u (%s, action %u)\n",
2087 hit ? "hit" : "miss",
2088 (uint32_t)action_id);
2090 t->action_id = action_id;
2091 t->structs[0] = action_data;
2093 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2094 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2097 thread_ip_action_call(p, t, action_id);
2101 instr_selector_exec(struct rte_swx_pipeline *p)
2103 struct thread *t = &p->threads[p->thread_id];
2104 struct instruction *ip = t->ip;
2105 uint32_t selector_id = ip->table.table_id;
2106 struct rte_swx_table_state *ts = &t->table_state[p->n_tables + selector_id];
2107 struct selector_runtime *selector = &t->selectors[selector_id];
2108 struct selector_statistics *stats = &p->selector_stats[selector_id];
2109 uint64_t n_pkts = stats->n_pkts;
2113 done = rte_swx_table_selector_select(ts->obj,
2115 selector->group_id_buffer,
2116 selector->selector_buffer,
2117 selector->member_id_buffer);
2120 TRACE("[Thread %2u] selector %u (not finalized)\n",
2129 TRACE("[Thread %2u] selector %u\n",
2133 stats->n_pkts = n_pkts + 1;
2140 instr_learner_exec(struct rte_swx_pipeline *p)
2142 struct thread *t = &p->threads[p->thread_id];
2143 struct instruction *ip = t->ip;
2144 uint32_t learner_id = ip->table.table_id;
2145 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2146 p->n_selectors + learner_id];
2147 struct learner_runtime *l = &t->learners[learner_id];
2148 struct learner_statistics *stats = &p->learner_stats[learner_id];
2149 uint64_t action_id, n_pkts_hit, n_pkts_action, time;
2150 uint8_t *action_data;
2154 time = rte_get_tsc_cycles();
2156 done = rte_swx_table_learner_lookup(ts->obj,
2165 TRACE("[Thread %2u] learner %u (not finalized)\n",
2173 action_id = hit ? action_id : ts->default_action_id;
2174 action_data = hit ? action_data : ts->default_action_data;
2175 n_pkts_hit = stats->n_pkts_hit[hit];
2176 n_pkts_action = stats->n_pkts_action[action_id];
2178 TRACE("[Thread %2u] learner %u (%s, action %u)\n",
2181 hit ? "hit" : "miss",
2182 (uint32_t)action_id);
2184 t->action_id = action_id;
2185 t->structs[0] = action_data;
2187 t->learner_id = learner_id;
2189 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2190 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2193 thread_ip_action_call(p, t, action_id);
2199 static struct action *
2200 action_find(struct rte_swx_pipeline *p, const char *name);
2203 action_has_nbo_args(struct action *a);
2206 instr_learn_translate(struct rte_swx_pipeline *p,
2207 struct action *action,
2210 struct instruction *instr,
2211 struct instruction_data *data __rte_unused)
2215 CHECK(action, EINVAL);
2216 CHECK(n_tokens == 2, EINVAL);
2218 a = action_find(p, tokens[1]);
2220 CHECK(!action_has_nbo_args(a), EINVAL);
2222 instr->type = INSTR_LEARNER_LEARN;
2223 instr->learn.action_id = a->id;
2229 instr_learn_exec(struct rte_swx_pipeline *p)
2231 struct thread *t = &p->threads[p->thread_id];
2232 struct instruction *ip = t->ip;
2233 uint64_t action_id = ip->learn.action_id;
2234 uint32_t learner_id = t->learner_id;
2235 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2236 p->n_selectors + learner_id];
2237 struct learner_runtime *l = &t->learners[learner_id];
2238 struct learner_statistics *stats = &p->learner_stats[learner_id];
2242 status = rte_swx_table_learner_add(ts->obj,
2246 l->action_data[action_id]);
2248 TRACE("[Thread %2u] learner %u learn %s\n",
2251 status ? "ok" : "error");
2253 stats->n_pkts_learn[status] += 1;
2263 instr_forget_translate(struct rte_swx_pipeline *p __rte_unused,
2264 struct action *action,
2265 char **tokens __rte_unused,
2267 struct instruction *instr,
2268 struct instruction_data *data __rte_unused)
2270 CHECK(action, EINVAL);
2271 CHECK(n_tokens == 1, EINVAL);
2273 instr->type = INSTR_LEARNER_FORGET;
2279 instr_forget_exec(struct rte_swx_pipeline *p)
2281 struct thread *t = &p->threads[p->thread_id];
2282 uint32_t learner_id = t->learner_id;
2283 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2284 p->n_selectors + learner_id];
2285 struct learner_runtime *l = &t->learners[learner_id];
2286 struct learner_statistics *stats = &p->learner_stats[learner_id];
2289 rte_swx_table_learner_delete(ts->obj, l->mailbox);
2291 TRACE("[Thread %2u] learner %u forget\n",
2295 stats->n_pkts_forget += 1;
2305 instr_extern_translate(struct rte_swx_pipeline *p,
2306 struct action *action __rte_unused,
2309 struct instruction *instr,
2310 struct instruction_data *data __rte_unused)
2312 char *token = tokens[1];
2314 CHECK(n_tokens == 2, EINVAL);
2316 if (token[0] == 'e') {
2317 struct extern_obj *obj;
2318 struct extern_type_member_func *func;
2320 func = extern_obj_member_func_parse(p, token, &obj);
2321 CHECK(func, EINVAL);
2323 instr->type = INSTR_EXTERN_OBJ;
2324 instr->ext_obj.ext_obj_id = obj->id;
2325 instr->ext_obj.func_id = func->id;
2330 if (token[0] == 'f') {
2331 struct extern_func *func;
2333 func = extern_func_parse(p, token);
2334 CHECK(func, EINVAL);
2336 instr->type = INSTR_EXTERN_FUNC;
2337 instr->ext_func.ext_func_id = func->id;
2346 instr_extern_obj_exec(struct rte_swx_pipeline *p)
2348 struct thread *t = &p->threads[p->thread_id];
2349 struct instruction *ip = t->ip;
2350 uint32_t obj_id = ip->ext_obj.ext_obj_id;
2351 uint32_t func_id = ip->ext_obj.func_id;
2352 struct extern_obj_runtime *obj = &t->extern_objs[obj_id];
2353 rte_swx_extern_type_member_func_t func = obj->funcs[func_id];
2355 TRACE("[Thread %2u] extern obj %u member func %u\n",
2360 /* Extern object member function execute. */
2361 uint32_t done = func(obj->obj, obj->mailbox);
2364 thread_ip_inc_cond(t, done);
2365 thread_yield_cond(p, done ^ 1);
2369 instr_extern_func_exec(struct rte_swx_pipeline *p)
2371 struct thread *t = &p->threads[p->thread_id];
2372 struct instruction *ip = t->ip;
2373 uint32_t ext_func_id = ip->ext_func.ext_func_id;
2374 struct extern_func_runtime *ext_func = &t->extern_funcs[ext_func_id];
2375 rte_swx_extern_func_t func = ext_func->func;
2377 TRACE("[Thread %2u] extern func %u\n",
2381 /* Extern function execute. */
2382 uint32_t done = func(ext_func->mailbox);
2385 thread_ip_inc_cond(t, done);
2386 thread_yield_cond(p, done ^ 1);
2393 instr_mov_translate(struct rte_swx_pipeline *p,
2394 struct action *action,
2397 struct instruction *instr,
2398 struct instruction_data *data __rte_unused)
2400 char *dst = tokens[1], *src = tokens[2];
2401 struct field *fdst, *fsrc;
2403 uint32_t dst_struct_id = 0, src_struct_id = 0;
2405 CHECK(n_tokens == 3, EINVAL);
2407 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2408 CHECK(fdst, EINVAL);
2409 CHECK(!fdst->var_size, EINVAL);
2411 /* MOV, MOV_MH, MOV_HM or MOV_HH. */
2412 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2414 CHECK(!fsrc->var_size, EINVAL);
2416 instr->type = INSTR_MOV;
2417 if (dst[0] != 'h' && src[0] == 'h')
2418 instr->type = INSTR_MOV_MH;
2419 if (dst[0] == 'h' && src[0] != 'h')
2420 instr->type = INSTR_MOV_HM;
2421 if (dst[0] == 'h' && src[0] == 'h')
2422 instr->type = INSTR_MOV_HH;
2424 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
2425 instr->mov.dst.n_bits = fdst->n_bits;
2426 instr->mov.dst.offset = fdst->offset / 8;
2427 instr->mov.src.struct_id = (uint8_t)src_struct_id;
2428 instr->mov.src.n_bits = fsrc->n_bits;
2429 instr->mov.src.offset = fsrc->offset / 8;
2434 src_val = strtoull(src, &src, 0);
2435 CHECK(!src[0], EINVAL);
2438 src_val = hton64(src_val) >> (64 - fdst->n_bits);
2440 instr->type = INSTR_MOV_I;
2441 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
2442 instr->mov.dst.n_bits = fdst->n_bits;
2443 instr->mov.dst.offset = fdst->offset / 8;
2444 instr->mov.src_val = src_val;
2449 instr_mov_exec(struct rte_swx_pipeline *p)
2451 struct thread *t = &p->threads[p->thread_id];
2452 struct instruction *ip = t->ip;
2454 TRACE("[Thread %2u] mov\n",
2464 instr_mov_mh_exec(struct rte_swx_pipeline *p)
2466 struct thread *t = &p->threads[p->thread_id];
2467 struct instruction *ip = t->ip;
2469 TRACE("[Thread %2u] mov (mh)\n",
2479 instr_mov_hm_exec(struct rte_swx_pipeline *p)
2481 struct thread *t = &p->threads[p->thread_id];
2482 struct instruction *ip = t->ip;
2484 TRACE("[Thread %2u] mov (hm)\n",
2494 instr_mov_hh_exec(struct rte_swx_pipeline *p)
2496 struct thread *t = &p->threads[p->thread_id];
2497 struct instruction *ip = t->ip;
2499 TRACE("[Thread %2u] mov (hh)\n",
2509 instr_mov_i_exec(struct rte_swx_pipeline *p)
2511 struct thread *t = &p->threads[p->thread_id];
2512 struct instruction *ip = t->ip;
2514 TRACE("[Thread %2u] mov m.f %" PRIx64 "\n",
2528 __instr_dma_ht_exec(struct rte_swx_pipeline *p, uint32_t n_dma);
2531 __instr_dma_ht_exec(struct rte_swx_pipeline *p, uint32_t n_dma)
2533 struct thread *t = &p->threads[p->thread_id];
2534 struct instruction *ip = t->ip;
2535 uint8_t *action_data = t->structs[0];
2536 uint64_t valid_headers = t->valid_headers;
2539 for (i = 0; i < n_dma; i++) {
2540 uint32_t header_id = ip->dma.dst.header_id[i];
2541 uint32_t struct_id = ip->dma.dst.struct_id[i];
2542 uint32_t offset = ip->dma.src.offset[i];
2543 uint32_t n_bytes = ip->dma.n_bytes[i];
2545 struct header_runtime *h = &t->headers[header_id];
2546 uint8_t *h_ptr0 = h->ptr0;
2547 uint8_t *h_ptr = t->structs[struct_id];
2549 void *dst = MASK64_BIT_GET(valid_headers, header_id) ?
2551 void *src = &action_data[offset];
2553 TRACE("[Thread %2u] dma h.s t.f\n", p->thread_id);
2556 memcpy(dst, src, n_bytes);
2557 t->structs[struct_id] = dst;
2558 valid_headers = MASK64_BIT_SET(valid_headers, header_id);
2561 t->valid_headers = valid_headers;
2565 instr_dma_ht_exec(struct rte_swx_pipeline *p)
2567 __instr_dma_ht_exec(p, 1);
2574 instr_dma_ht2_exec(struct rte_swx_pipeline *p)
2576 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n",
2579 __instr_dma_ht_exec(p, 2);
2586 instr_dma_ht3_exec(struct rte_swx_pipeline *p)
2588 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n",
2591 __instr_dma_ht_exec(p, 3);
2598 instr_dma_ht4_exec(struct rte_swx_pipeline *p)
2600 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n",
2603 __instr_dma_ht_exec(p, 4);
2610 instr_dma_ht5_exec(struct rte_swx_pipeline *p)
2612 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n",
2615 __instr_dma_ht_exec(p, 5);
2622 instr_dma_ht6_exec(struct rte_swx_pipeline *p)
2624 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n",
2627 __instr_dma_ht_exec(p, 6);
2634 instr_dma_ht7_exec(struct rte_swx_pipeline *p)
2636 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n",
2639 __instr_dma_ht_exec(p, 7);
2646 instr_dma_ht8_exec(struct rte_swx_pipeline *p)
2648 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n",
2651 __instr_dma_ht_exec(p, 8);
2661 instr_alu_add_translate(struct rte_swx_pipeline *p,
2662 struct action *action,
2665 struct instruction *instr,
2666 struct instruction_data *data __rte_unused)
2668 char *dst = tokens[1], *src = tokens[2];
2669 struct field *fdst, *fsrc;
2671 uint32_t dst_struct_id = 0, src_struct_id = 0;
2673 CHECK(n_tokens == 3, EINVAL);
2675 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2676 CHECK(fdst, EINVAL);
2677 CHECK(!fdst->var_size, EINVAL);
2679 /* ADD, ADD_HM, ADD_MH, ADD_HH. */
2680 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2682 CHECK(!fsrc->var_size, EINVAL);
2684 instr->type = INSTR_ALU_ADD;
2685 if (dst[0] == 'h' && src[0] != 'h')
2686 instr->type = INSTR_ALU_ADD_HM;
2687 if (dst[0] != 'h' && src[0] == 'h')
2688 instr->type = INSTR_ALU_ADD_MH;
2689 if (dst[0] == 'h' && src[0] == 'h')
2690 instr->type = INSTR_ALU_ADD_HH;
2692 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2693 instr->alu.dst.n_bits = fdst->n_bits;
2694 instr->alu.dst.offset = fdst->offset / 8;
2695 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2696 instr->alu.src.n_bits = fsrc->n_bits;
2697 instr->alu.src.offset = fsrc->offset / 8;
2701 /* ADD_MI, ADD_HI. */
2702 src_val = strtoull(src, &src, 0);
2703 CHECK(!src[0], EINVAL);
2705 instr->type = INSTR_ALU_ADD_MI;
2707 instr->type = INSTR_ALU_ADD_HI;
2709 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2710 instr->alu.dst.n_bits = fdst->n_bits;
2711 instr->alu.dst.offset = fdst->offset / 8;
2712 instr->alu.src_val = src_val;
2717 instr_alu_sub_translate(struct rte_swx_pipeline *p,
2718 struct action *action,
2721 struct instruction *instr,
2722 struct instruction_data *data __rte_unused)
2724 char *dst = tokens[1], *src = tokens[2];
2725 struct field *fdst, *fsrc;
2727 uint32_t dst_struct_id = 0, src_struct_id = 0;
2729 CHECK(n_tokens == 3, EINVAL);
2731 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2732 CHECK(fdst, EINVAL);
2733 CHECK(!fdst->var_size, EINVAL);
2735 /* SUB, SUB_HM, SUB_MH, SUB_HH. */
2736 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2738 CHECK(!fsrc->var_size, EINVAL);
2740 instr->type = INSTR_ALU_SUB;
2741 if (dst[0] == 'h' && src[0] != 'h')
2742 instr->type = INSTR_ALU_SUB_HM;
2743 if (dst[0] != 'h' && src[0] == 'h')
2744 instr->type = INSTR_ALU_SUB_MH;
2745 if (dst[0] == 'h' && src[0] == 'h')
2746 instr->type = INSTR_ALU_SUB_HH;
2748 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2749 instr->alu.dst.n_bits = fdst->n_bits;
2750 instr->alu.dst.offset = fdst->offset / 8;
2751 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2752 instr->alu.src.n_bits = fsrc->n_bits;
2753 instr->alu.src.offset = fsrc->offset / 8;
2757 /* SUB_MI, SUB_HI. */
2758 src_val = strtoull(src, &src, 0);
2759 CHECK(!src[0], EINVAL);
2761 instr->type = INSTR_ALU_SUB_MI;
2763 instr->type = INSTR_ALU_SUB_HI;
2765 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2766 instr->alu.dst.n_bits = fdst->n_bits;
2767 instr->alu.dst.offset = fdst->offset / 8;
2768 instr->alu.src_val = src_val;
2773 instr_alu_ckadd_translate(struct rte_swx_pipeline *p,
2774 struct action *action __rte_unused,
2777 struct instruction *instr,
2778 struct instruction_data *data __rte_unused)
2780 char *dst = tokens[1], *src = tokens[2];
2781 struct header *hdst, *hsrc;
2782 struct field *fdst, *fsrc;
2784 CHECK(n_tokens == 3, EINVAL);
2786 fdst = header_field_parse(p, dst, &hdst);
2787 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
2788 CHECK(!fdst->var_size, EINVAL);
2791 fsrc = header_field_parse(p, src, &hsrc);
2793 CHECK(!fsrc->var_size, EINVAL);
2795 instr->type = INSTR_ALU_CKADD_FIELD;
2796 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2797 instr->alu.dst.n_bits = fdst->n_bits;
2798 instr->alu.dst.offset = fdst->offset / 8;
2799 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2800 instr->alu.src.n_bits = fsrc->n_bits;
2801 instr->alu.src.offset = fsrc->offset / 8;
2805 /* CKADD_STRUCT, CKADD_STRUCT20. */
2806 hsrc = header_parse(p, src);
2807 CHECK(hsrc, EINVAL);
2808 CHECK(!hsrc->st->var_size, EINVAL);
2810 instr->type = INSTR_ALU_CKADD_STRUCT;
2811 if ((hsrc->st->n_bits / 8) == 20)
2812 instr->type = INSTR_ALU_CKADD_STRUCT20;
2814 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2815 instr->alu.dst.n_bits = fdst->n_bits;
2816 instr->alu.dst.offset = fdst->offset / 8;
2817 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2818 instr->alu.src.n_bits = hsrc->st->n_bits;
2819 instr->alu.src.offset = 0; /* Unused. */
2824 instr_alu_cksub_translate(struct rte_swx_pipeline *p,
2825 struct action *action __rte_unused,
2828 struct instruction *instr,
2829 struct instruction_data *data __rte_unused)
2831 char *dst = tokens[1], *src = tokens[2];
2832 struct header *hdst, *hsrc;
2833 struct field *fdst, *fsrc;
2835 CHECK(n_tokens == 3, EINVAL);
2837 fdst = header_field_parse(p, dst, &hdst);
2838 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
2839 CHECK(!fdst->var_size, EINVAL);
2841 fsrc = header_field_parse(p, src, &hsrc);
2842 CHECK(fsrc, EINVAL);
2843 CHECK(!fsrc->var_size, EINVAL);
2845 instr->type = INSTR_ALU_CKSUB_FIELD;
2846 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2847 instr->alu.dst.n_bits = fdst->n_bits;
2848 instr->alu.dst.offset = fdst->offset / 8;
2849 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2850 instr->alu.src.n_bits = fsrc->n_bits;
2851 instr->alu.src.offset = fsrc->offset / 8;
2856 instr_alu_shl_translate(struct rte_swx_pipeline *p,
2857 struct action *action,
2860 struct instruction *instr,
2861 struct instruction_data *data __rte_unused)
2863 char *dst = tokens[1], *src = tokens[2];
2864 struct field *fdst, *fsrc;
2866 uint32_t dst_struct_id = 0, src_struct_id = 0;
2868 CHECK(n_tokens == 3, EINVAL);
2870 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2871 CHECK(fdst, EINVAL);
2872 CHECK(!fdst->var_size, EINVAL);
2874 /* SHL, SHL_HM, SHL_MH, SHL_HH. */
2875 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2877 CHECK(!fsrc->var_size, EINVAL);
2879 instr->type = INSTR_ALU_SHL;
2880 if (dst[0] == 'h' && src[0] != 'h')
2881 instr->type = INSTR_ALU_SHL_HM;
2882 if (dst[0] != 'h' && src[0] == 'h')
2883 instr->type = INSTR_ALU_SHL_MH;
2884 if (dst[0] == 'h' && src[0] == 'h')
2885 instr->type = INSTR_ALU_SHL_HH;
2887 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2888 instr->alu.dst.n_bits = fdst->n_bits;
2889 instr->alu.dst.offset = fdst->offset / 8;
2890 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2891 instr->alu.src.n_bits = fsrc->n_bits;
2892 instr->alu.src.offset = fsrc->offset / 8;
2896 /* SHL_MI, SHL_HI. */
2897 src_val = strtoull(src, &src, 0);
2898 CHECK(!src[0], EINVAL);
2900 instr->type = INSTR_ALU_SHL_MI;
2902 instr->type = INSTR_ALU_SHL_HI;
2904 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2905 instr->alu.dst.n_bits = fdst->n_bits;
2906 instr->alu.dst.offset = fdst->offset / 8;
2907 instr->alu.src_val = src_val;
2912 instr_alu_shr_translate(struct rte_swx_pipeline *p,
2913 struct action *action,
2916 struct instruction *instr,
2917 struct instruction_data *data __rte_unused)
2919 char *dst = tokens[1], *src = tokens[2];
2920 struct field *fdst, *fsrc;
2922 uint32_t dst_struct_id = 0, src_struct_id = 0;
2924 CHECK(n_tokens == 3, EINVAL);
2926 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2927 CHECK(fdst, EINVAL);
2928 CHECK(!fdst->var_size, EINVAL);
2930 /* SHR, SHR_HM, SHR_MH, SHR_HH. */
2931 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2933 CHECK(!fsrc->var_size, EINVAL);
2935 instr->type = INSTR_ALU_SHR;
2936 if (dst[0] == 'h' && src[0] != 'h')
2937 instr->type = INSTR_ALU_SHR_HM;
2938 if (dst[0] != 'h' && src[0] == 'h')
2939 instr->type = INSTR_ALU_SHR_MH;
2940 if (dst[0] == 'h' && src[0] == 'h')
2941 instr->type = INSTR_ALU_SHR_HH;
2943 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2944 instr->alu.dst.n_bits = fdst->n_bits;
2945 instr->alu.dst.offset = fdst->offset / 8;
2946 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2947 instr->alu.src.n_bits = fsrc->n_bits;
2948 instr->alu.src.offset = fsrc->offset / 8;
2952 /* SHR_MI, SHR_HI. */
2953 src_val = strtoull(src, &src, 0);
2954 CHECK(!src[0], EINVAL);
2956 instr->type = INSTR_ALU_SHR_MI;
2958 instr->type = INSTR_ALU_SHR_HI;
2960 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2961 instr->alu.dst.n_bits = fdst->n_bits;
2962 instr->alu.dst.offset = fdst->offset / 8;
2963 instr->alu.src_val = src_val;
2968 instr_alu_and_translate(struct rte_swx_pipeline *p,
2969 struct action *action,
2972 struct instruction *instr,
2973 struct instruction_data *data __rte_unused)
2975 char *dst = tokens[1], *src = tokens[2];
2976 struct field *fdst, *fsrc;
2978 uint32_t dst_struct_id = 0, src_struct_id = 0;
2980 CHECK(n_tokens == 3, EINVAL);
2982 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2983 CHECK(fdst, EINVAL);
2984 CHECK(!fdst->var_size, EINVAL);
2986 /* AND, AND_MH, AND_HM, AND_HH. */
2987 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2989 CHECK(!fsrc->var_size, EINVAL);
2991 instr->type = INSTR_ALU_AND;
2992 if (dst[0] != 'h' && src[0] == 'h')
2993 instr->type = INSTR_ALU_AND_MH;
2994 if (dst[0] == 'h' && src[0] != 'h')
2995 instr->type = INSTR_ALU_AND_HM;
2996 if (dst[0] == 'h' && src[0] == 'h')
2997 instr->type = INSTR_ALU_AND_HH;
2999 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3000 instr->alu.dst.n_bits = fdst->n_bits;
3001 instr->alu.dst.offset = fdst->offset / 8;
3002 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3003 instr->alu.src.n_bits = fsrc->n_bits;
3004 instr->alu.src.offset = fsrc->offset / 8;
3009 src_val = strtoull(src, &src, 0);
3010 CHECK(!src[0], EINVAL);
3013 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3015 instr->type = INSTR_ALU_AND_I;
3016 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3017 instr->alu.dst.n_bits = fdst->n_bits;
3018 instr->alu.dst.offset = fdst->offset / 8;
3019 instr->alu.src_val = src_val;
3024 instr_alu_or_translate(struct rte_swx_pipeline *p,
3025 struct action *action,
3028 struct instruction *instr,
3029 struct instruction_data *data __rte_unused)
3031 char *dst = tokens[1], *src = tokens[2];
3032 struct field *fdst, *fsrc;
3034 uint32_t dst_struct_id = 0, src_struct_id = 0;
3036 CHECK(n_tokens == 3, EINVAL);
3038 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3039 CHECK(fdst, EINVAL);
3040 CHECK(!fdst->var_size, EINVAL);
3042 /* OR, OR_MH, OR_HM, OR_HH. */
3043 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3045 CHECK(!fsrc->var_size, EINVAL);
3047 instr->type = INSTR_ALU_OR;
3048 if (dst[0] != 'h' && src[0] == 'h')
3049 instr->type = INSTR_ALU_OR_MH;
3050 if (dst[0] == 'h' && src[0] != 'h')
3051 instr->type = INSTR_ALU_OR_HM;
3052 if (dst[0] == 'h' && src[0] == 'h')
3053 instr->type = INSTR_ALU_OR_HH;
3055 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3056 instr->alu.dst.n_bits = fdst->n_bits;
3057 instr->alu.dst.offset = fdst->offset / 8;
3058 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3059 instr->alu.src.n_bits = fsrc->n_bits;
3060 instr->alu.src.offset = fsrc->offset / 8;
3065 src_val = strtoull(src, &src, 0);
3066 CHECK(!src[0], EINVAL);
3069 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3071 instr->type = INSTR_ALU_OR_I;
3072 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3073 instr->alu.dst.n_bits = fdst->n_bits;
3074 instr->alu.dst.offset = fdst->offset / 8;
3075 instr->alu.src_val = src_val;
3080 instr_alu_xor_translate(struct rte_swx_pipeline *p,
3081 struct action *action,
3084 struct instruction *instr,
3085 struct instruction_data *data __rte_unused)
3087 char *dst = tokens[1], *src = tokens[2];
3088 struct field *fdst, *fsrc;
3090 uint32_t dst_struct_id = 0, src_struct_id = 0;
3092 CHECK(n_tokens == 3, EINVAL);
3094 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3095 CHECK(fdst, EINVAL);
3096 CHECK(!fdst->var_size, EINVAL);
3098 /* XOR, XOR_MH, XOR_HM, XOR_HH. */
3099 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3101 CHECK(!fsrc->var_size, EINVAL);
3103 instr->type = INSTR_ALU_XOR;
3104 if (dst[0] != 'h' && src[0] == 'h')
3105 instr->type = INSTR_ALU_XOR_MH;
3106 if (dst[0] == 'h' && src[0] != 'h')
3107 instr->type = INSTR_ALU_XOR_HM;
3108 if (dst[0] == 'h' && src[0] == 'h')
3109 instr->type = INSTR_ALU_XOR_HH;
3111 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3112 instr->alu.dst.n_bits = fdst->n_bits;
3113 instr->alu.dst.offset = fdst->offset / 8;
3114 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3115 instr->alu.src.n_bits = fsrc->n_bits;
3116 instr->alu.src.offset = fsrc->offset / 8;
3121 src_val = strtoull(src, &src, 0);
3122 CHECK(!src[0], EINVAL);
3125 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3127 instr->type = INSTR_ALU_XOR_I;
3128 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3129 instr->alu.dst.n_bits = fdst->n_bits;
3130 instr->alu.dst.offset = fdst->offset / 8;
3131 instr->alu.src_val = src_val;
3136 instr_alu_add_exec(struct rte_swx_pipeline *p)
3138 struct thread *t = &p->threads[p->thread_id];
3139 struct instruction *ip = t->ip;
3141 TRACE("[Thread %2u] add\n", p->thread_id);
3151 instr_alu_add_mh_exec(struct rte_swx_pipeline *p)
3153 struct thread *t = &p->threads[p->thread_id];
3154 struct instruction *ip = t->ip;
3156 TRACE("[Thread %2u] add (mh)\n", p->thread_id);
3166 instr_alu_add_hm_exec(struct rte_swx_pipeline *p)
3168 struct thread *t = &p->threads[p->thread_id];
3169 struct instruction *ip = t->ip;
3171 TRACE("[Thread %2u] add (hm)\n", p->thread_id);
3181 instr_alu_add_hh_exec(struct rte_swx_pipeline *p)
3183 struct thread *t = &p->threads[p->thread_id];
3184 struct instruction *ip = t->ip;
3186 TRACE("[Thread %2u] add (hh)\n", p->thread_id);
3196 instr_alu_add_mi_exec(struct rte_swx_pipeline *p)
3198 struct thread *t = &p->threads[p->thread_id];
3199 struct instruction *ip = t->ip;
3201 TRACE("[Thread %2u] add (mi)\n", p->thread_id);
3211 instr_alu_add_hi_exec(struct rte_swx_pipeline *p)
3213 struct thread *t = &p->threads[p->thread_id];
3214 struct instruction *ip = t->ip;
3216 TRACE("[Thread %2u] add (hi)\n", p->thread_id);
3226 instr_alu_sub_exec(struct rte_swx_pipeline *p)
3228 struct thread *t = &p->threads[p->thread_id];
3229 struct instruction *ip = t->ip;
3231 TRACE("[Thread %2u] sub\n", p->thread_id);
3241 instr_alu_sub_mh_exec(struct rte_swx_pipeline *p)
3243 struct thread *t = &p->threads[p->thread_id];
3244 struct instruction *ip = t->ip;
3246 TRACE("[Thread %2u] sub (mh)\n", p->thread_id);
3256 instr_alu_sub_hm_exec(struct rte_swx_pipeline *p)
3258 struct thread *t = &p->threads[p->thread_id];
3259 struct instruction *ip = t->ip;
3261 TRACE("[Thread %2u] sub (hm)\n", p->thread_id);
3271 instr_alu_sub_hh_exec(struct rte_swx_pipeline *p)
3273 struct thread *t = &p->threads[p->thread_id];
3274 struct instruction *ip = t->ip;
3276 TRACE("[Thread %2u] sub (hh)\n", p->thread_id);
3286 instr_alu_sub_mi_exec(struct rte_swx_pipeline *p)
3288 struct thread *t = &p->threads[p->thread_id];
3289 struct instruction *ip = t->ip;
3291 TRACE("[Thread %2u] sub (mi)\n", p->thread_id);
3301 instr_alu_sub_hi_exec(struct rte_swx_pipeline *p)
3303 struct thread *t = &p->threads[p->thread_id];
3304 struct instruction *ip = t->ip;
3306 TRACE("[Thread %2u] sub (hi)\n", p->thread_id);
3316 instr_alu_shl_exec(struct rte_swx_pipeline *p)
3318 struct thread *t = &p->threads[p->thread_id];
3319 struct instruction *ip = t->ip;
3321 TRACE("[Thread %2u] shl\n", p->thread_id);
3331 instr_alu_shl_mh_exec(struct rte_swx_pipeline *p)
3333 struct thread *t = &p->threads[p->thread_id];
3334 struct instruction *ip = t->ip;
3336 TRACE("[Thread %2u] shl (mh)\n", p->thread_id);
3346 instr_alu_shl_hm_exec(struct rte_swx_pipeline *p)
3348 struct thread *t = &p->threads[p->thread_id];
3349 struct instruction *ip = t->ip;
3351 TRACE("[Thread %2u] shl (hm)\n", p->thread_id);
3361 instr_alu_shl_hh_exec(struct rte_swx_pipeline *p)
3363 struct thread *t = &p->threads[p->thread_id];
3364 struct instruction *ip = t->ip;
3366 TRACE("[Thread %2u] shl (hh)\n", p->thread_id);
3376 instr_alu_shl_mi_exec(struct rte_swx_pipeline *p)
3378 struct thread *t = &p->threads[p->thread_id];
3379 struct instruction *ip = t->ip;
3381 TRACE("[Thread %2u] shl (mi)\n", p->thread_id);
3391 instr_alu_shl_hi_exec(struct rte_swx_pipeline *p)
3393 struct thread *t = &p->threads[p->thread_id];
3394 struct instruction *ip = t->ip;
3396 TRACE("[Thread %2u] shl (hi)\n", p->thread_id);
3406 instr_alu_shr_exec(struct rte_swx_pipeline *p)
3408 struct thread *t = &p->threads[p->thread_id];
3409 struct instruction *ip = t->ip;
3411 TRACE("[Thread %2u] shr\n", p->thread_id);
3421 instr_alu_shr_mh_exec(struct rte_swx_pipeline *p)
3423 struct thread *t = &p->threads[p->thread_id];
3424 struct instruction *ip = t->ip;
3426 TRACE("[Thread %2u] shr (mh)\n", p->thread_id);
3436 instr_alu_shr_hm_exec(struct rte_swx_pipeline *p)
3438 struct thread *t = &p->threads[p->thread_id];
3439 struct instruction *ip = t->ip;
3441 TRACE("[Thread %2u] shr (hm)\n", p->thread_id);
3451 instr_alu_shr_hh_exec(struct rte_swx_pipeline *p)
3453 struct thread *t = &p->threads[p->thread_id];
3454 struct instruction *ip = t->ip;
3456 TRACE("[Thread %2u] shr (hh)\n", p->thread_id);
3466 instr_alu_shr_mi_exec(struct rte_swx_pipeline *p)
3468 struct thread *t = &p->threads[p->thread_id];
3469 struct instruction *ip = t->ip;
3471 TRACE("[Thread %2u] shr (mi)\n", p->thread_id);
3481 instr_alu_shr_hi_exec(struct rte_swx_pipeline *p)
3483 struct thread *t = &p->threads[p->thread_id];
3484 struct instruction *ip = t->ip;
3486 TRACE("[Thread %2u] shr (hi)\n", p->thread_id);
3496 instr_alu_and_exec(struct rte_swx_pipeline *p)
3498 struct thread *t = &p->threads[p->thread_id];
3499 struct instruction *ip = t->ip;
3501 TRACE("[Thread %2u] and\n", p->thread_id);
3511 instr_alu_and_mh_exec(struct rte_swx_pipeline *p)
3513 struct thread *t = &p->threads[p->thread_id];
3514 struct instruction *ip = t->ip;
3516 TRACE("[Thread %2u] and (mh)\n", p->thread_id);
3526 instr_alu_and_hm_exec(struct rte_swx_pipeline *p)
3528 struct thread *t = &p->threads[p->thread_id];
3529 struct instruction *ip = t->ip;
3531 TRACE("[Thread %2u] and (hm)\n", p->thread_id);
3534 ALU_HM_FAST(t, ip, &);
3541 instr_alu_and_hh_exec(struct rte_swx_pipeline *p)
3543 struct thread *t = &p->threads[p->thread_id];
3544 struct instruction *ip = t->ip;
3546 TRACE("[Thread %2u] and (hh)\n", p->thread_id);
3549 ALU_HH_FAST(t, ip, &);
3556 instr_alu_and_i_exec(struct rte_swx_pipeline *p)
3558 struct thread *t = &p->threads[p->thread_id];
3559 struct instruction *ip = t->ip;
3561 TRACE("[Thread %2u] and (i)\n", p->thread_id);
3571 instr_alu_or_exec(struct rte_swx_pipeline *p)
3573 struct thread *t = &p->threads[p->thread_id];
3574 struct instruction *ip = t->ip;
3576 TRACE("[Thread %2u] or\n", p->thread_id);
3586 instr_alu_or_mh_exec(struct rte_swx_pipeline *p)
3588 struct thread *t = &p->threads[p->thread_id];
3589 struct instruction *ip = t->ip;
3591 TRACE("[Thread %2u] or (mh)\n", p->thread_id);
3601 instr_alu_or_hm_exec(struct rte_swx_pipeline *p)
3603 struct thread *t = &p->threads[p->thread_id];
3604 struct instruction *ip = t->ip;
3606 TRACE("[Thread %2u] or (hm)\n", p->thread_id);
3609 ALU_HM_FAST(t, ip, |);
3616 instr_alu_or_hh_exec(struct rte_swx_pipeline *p)
3618 struct thread *t = &p->threads[p->thread_id];
3619 struct instruction *ip = t->ip;
3621 TRACE("[Thread %2u] or (hh)\n", p->thread_id);
3624 ALU_HH_FAST(t, ip, |);
3631 instr_alu_or_i_exec(struct rte_swx_pipeline *p)
3633 struct thread *t = &p->threads[p->thread_id];
3634 struct instruction *ip = t->ip;
3636 TRACE("[Thread %2u] or (i)\n", p->thread_id);
3646 instr_alu_xor_exec(struct rte_swx_pipeline *p)
3648 struct thread *t = &p->threads[p->thread_id];
3649 struct instruction *ip = t->ip;
3651 TRACE("[Thread %2u] xor\n", p->thread_id);
3661 instr_alu_xor_mh_exec(struct rte_swx_pipeline *p)
3663 struct thread *t = &p->threads[p->thread_id];
3664 struct instruction *ip = t->ip;
3666 TRACE("[Thread %2u] xor (mh)\n", p->thread_id);
3676 instr_alu_xor_hm_exec(struct rte_swx_pipeline *p)
3678 struct thread *t = &p->threads[p->thread_id];
3679 struct instruction *ip = t->ip;
3681 TRACE("[Thread %2u] xor (hm)\n", p->thread_id);
3684 ALU_HM_FAST(t, ip, ^);
3691 instr_alu_xor_hh_exec(struct rte_swx_pipeline *p)
3693 struct thread *t = &p->threads[p->thread_id];
3694 struct instruction *ip = t->ip;
3696 TRACE("[Thread %2u] xor (hh)\n", p->thread_id);
3699 ALU_HH_FAST(t, ip, ^);
3706 instr_alu_xor_i_exec(struct rte_swx_pipeline *p)
3708 struct thread *t = &p->threads[p->thread_id];
3709 struct instruction *ip = t->ip;
3711 TRACE("[Thread %2u] xor (i)\n", p->thread_id);
3721 instr_alu_ckadd_field_exec(struct rte_swx_pipeline *p)
3723 struct thread *t = &p->threads[p->thread_id];
3724 struct instruction *ip = t->ip;
3725 uint8_t *dst_struct, *src_struct;
3726 uint16_t *dst16_ptr, dst;
3727 uint64_t *src64_ptr, src64, src64_mask, src;
3730 TRACE("[Thread %2u] ckadd (field)\n", p->thread_id);
3733 dst_struct = t->structs[ip->alu.dst.struct_id];
3734 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
3737 src_struct = t->structs[ip->alu.src.struct_id];
3738 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
3740 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
3741 src = src64 & src64_mask;
3746 /* The first input (r) is a 16-bit number. The second and the third
3747 * inputs are 32-bit numbers. In the worst case scenario, the sum of the
3748 * three numbers (output r) is a 34-bit number.
3750 r += (src >> 32) + (src & 0xFFFFFFFF);
3752 /* The first input is a 16-bit number. The second input is an 18-bit
3753 * number. In the worst case scenario, the sum of the two numbers is a
3756 r = (r & 0xFFFF) + (r >> 16);
3758 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
3759 * a 3-bit number (0 .. 7). Their sum is a 17-bit number (0 .. 0x10006).
3761 r = (r & 0xFFFF) + (r >> 16);
3763 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
3764 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
3765 * 0x10006), the output r is (0 .. 7). So no carry bit can be generated,
3766 * therefore the output r is always a 16-bit number.
3768 r = (r & 0xFFFF) + (r >> 16);
3773 *dst16_ptr = (uint16_t)r;
3780 instr_alu_cksub_field_exec(struct rte_swx_pipeline *p)
3782 struct thread *t = &p->threads[p->thread_id];
3783 struct instruction *ip = t->ip;
3784 uint8_t *dst_struct, *src_struct;
3785 uint16_t *dst16_ptr, dst;
3786 uint64_t *src64_ptr, src64, src64_mask, src;
3789 TRACE("[Thread %2u] cksub (field)\n", p->thread_id);
3792 dst_struct = t->structs[ip->alu.dst.struct_id];
3793 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
3796 src_struct = t->structs[ip->alu.src.struct_id];
3797 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
3799 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
3800 src = src64 & src64_mask;
3805 /* Subtraction in 1's complement arithmetic (i.e. a '- b) is the same as
3806 * the following sequence of operations in 2's complement arithmetic:
3807 * a '- b = (a - b) % 0xFFFF.
3809 * In order to prevent an underflow for the below subtraction, in which
3810 * a 33-bit number (the subtrahend) is taken out of a 16-bit number (the
3811 * minuend), we first add a multiple of the 0xFFFF modulus to the
3812 * minuend. The number we add to the minuend needs to be a 34-bit number
3813 * or higher, so for readability reasons we picked the 36-bit multiple.
3814 * We are effectively turning the 16-bit minuend into a 36-bit number:
3815 * (a - b) % 0xFFFF = (a + 0xFFFF00000 - b) % 0xFFFF.
3817 r += 0xFFFF00000ULL; /* The output r is a 36-bit number. */
3819 /* A 33-bit number is subtracted from a 36-bit number (the input r). The
3820 * result (the output r) is a 36-bit number.
3822 r -= (src >> 32) + (src & 0xFFFFFFFF);
3824 /* The first input is a 16-bit number. The second input is a 20-bit
3825 * number. Their sum is a 21-bit number.
3827 r = (r & 0xFFFF) + (r >> 16);
3829 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
3830 * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1001E).
3832 r = (r & 0xFFFF) + (r >> 16);
3834 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
3835 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
3836 * 0x1001E), the output r is (0 .. 31). So no carry bit can be
3837 * generated, therefore the output r is always a 16-bit number.
3839 r = (r & 0xFFFF) + (r >> 16);
3844 *dst16_ptr = (uint16_t)r;
3851 instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline *p)
3853 struct thread *t = &p->threads[p->thread_id];
3854 struct instruction *ip = t->ip;
3855 uint8_t *dst_struct, *src_struct;
3856 uint16_t *dst16_ptr;
3857 uint32_t *src32_ptr;
3860 TRACE("[Thread %2u] ckadd (struct of 20 bytes)\n", p->thread_id);
3863 dst_struct = t->structs[ip->alu.dst.struct_id];
3864 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
3866 src_struct = t->structs[ip->alu.src.struct_id];
3867 src32_ptr = (uint32_t *)&src_struct[0];
3869 r0 = src32_ptr[0]; /* r0 is a 32-bit number. */
3870 r1 = src32_ptr[1]; /* r1 is a 32-bit number. */
3871 r0 += src32_ptr[2]; /* The output r0 is a 33-bit number. */
3872 r1 += src32_ptr[3]; /* The output r1 is a 33-bit number. */
3873 r0 += r1 + src32_ptr[4]; /* The output r0 is a 35-bit number. */
3875 /* The first input is a 16-bit number. The second input is a 19-bit
3876 * number. Their sum is a 20-bit number.
3878 r0 = (r0 & 0xFFFF) + (r0 >> 16);
3880 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
3881 * a 4-bit number (0 .. 15). The sum is a 17-bit number (0 .. 0x1000E).
3883 r0 = (r0 & 0xFFFF) + (r0 >> 16);
3885 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
3886 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
3887 * 0x1000E), the output r is (0 .. 15). So no carry bit can be
3888 * generated, therefore the output r is always a 16-bit number.
3890 r0 = (r0 & 0xFFFF) + (r0 >> 16);
3893 r0 = r0 ? r0 : 0xFFFF;
3895 *dst16_ptr = (uint16_t)r0;
3902 instr_alu_ckadd_struct_exec(struct rte_swx_pipeline *p)
3904 struct thread *t = &p->threads[p->thread_id];
3905 struct instruction *ip = t->ip;
3906 uint8_t *dst_struct, *src_struct;
3907 uint16_t *dst16_ptr;
3908 uint32_t *src32_ptr;
3912 TRACE("[Thread %2u] ckadd (struct)\n", p->thread_id);
3915 dst_struct = t->structs[ip->alu.dst.struct_id];
3916 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
3918 src_struct = t->structs[ip->alu.src.struct_id];
3919 src32_ptr = (uint32_t *)&src_struct[0];
3921 /* The max number of 32-bit words in a 256-byte header is 8 = 2^3.
3922 * Therefore, in the worst case scenario, a 35-bit number is added to a
3923 * 16-bit number (the input r), so the output r is 36-bit number.
3925 for (i = 0; i < ip->alu.src.n_bits / 32; i++, src32_ptr++)
3928 /* The first input is a 16-bit number. The second input is a 20-bit
3929 * number. Their sum is a 21-bit number.
3931 r = (r & 0xFFFF) + (r >> 16);
3933 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
3934 * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1000E).
3936 r = (r & 0xFFFF) + (r >> 16);
3938 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
3939 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
3940 * 0x1001E), the output r is (0 .. 31). So no carry bit can be
3941 * generated, therefore the output r is always a 16-bit number.
3943 r = (r & 0xFFFF) + (r >> 16);
3948 *dst16_ptr = (uint16_t)r;
3957 static struct regarray *
3958 regarray_find(struct rte_swx_pipeline *p, const char *name);
3961 instr_regprefetch_translate(struct rte_swx_pipeline *p,
3962 struct action *action,
3965 struct instruction *instr,
3966 struct instruction_data *data __rte_unused)
3968 char *regarray = tokens[1], *idx = tokens[2];
3971 uint32_t idx_struct_id, idx_val;
3973 CHECK(n_tokens == 3, EINVAL);
3975 r = regarray_find(p, regarray);
3978 /* REGPREFETCH_RH, REGPREFETCH_RM. */
3979 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
3981 CHECK(!fidx->var_size, EINVAL);
3983 instr->type = INSTR_REGPREFETCH_RM;
3985 instr->type = INSTR_REGPREFETCH_RH;
3987 instr->regarray.regarray_id = r->id;
3988 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
3989 instr->regarray.idx.n_bits = fidx->n_bits;
3990 instr->regarray.idx.offset = fidx->offset / 8;
3991 instr->regarray.dstsrc_val = 0; /* Unused. */
3995 /* REGPREFETCH_RI. */
3996 idx_val = strtoul(idx, &idx, 0);
3997 CHECK(!idx[0], EINVAL);
3999 instr->type = INSTR_REGPREFETCH_RI;
4000 instr->regarray.regarray_id = r->id;
4001 instr->regarray.idx_val = idx_val;
4002 instr->regarray.dstsrc_val = 0; /* Unused. */
4007 instr_regrd_translate(struct rte_swx_pipeline *p,
4008 struct action *action,
4011 struct instruction *instr,
4012 struct instruction_data *data __rte_unused)
4014 char *dst = tokens[1], *regarray = tokens[2], *idx = tokens[3];
4016 struct field *fdst, *fidx;
4017 uint32_t dst_struct_id, idx_struct_id, idx_val;
4019 CHECK(n_tokens == 4, EINVAL);
4021 r = regarray_find(p, regarray);
4024 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4025 CHECK(fdst, EINVAL);
4026 CHECK(!fdst->var_size, EINVAL);
4028 /* REGRD_HRH, REGRD_HRM, REGRD_MRH, REGRD_MRM. */
4029 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4031 CHECK(!fidx->var_size, EINVAL);
4033 instr->type = INSTR_REGRD_MRM;
4034 if (dst[0] == 'h' && idx[0] != 'h')
4035 instr->type = INSTR_REGRD_HRM;
4036 if (dst[0] != 'h' && idx[0] == 'h')
4037 instr->type = INSTR_REGRD_MRH;
4038 if (dst[0] == 'h' && idx[0] == 'h')
4039 instr->type = INSTR_REGRD_HRH;
4041 instr->regarray.regarray_id = r->id;
4042 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4043 instr->regarray.idx.n_bits = fidx->n_bits;
4044 instr->regarray.idx.offset = fidx->offset / 8;
4045 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
4046 instr->regarray.dstsrc.n_bits = fdst->n_bits;
4047 instr->regarray.dstsrc.offset = fdst->offset / 8;
4051 /* REGRD_MRI, REGRD_HRI. */
4052 idx_val = strtoul(idx, &idx, 0);
4053 CHECK(!idx[0], EINVAL);
4055 instr->type = INSTR_REGRD_MRI;
4057 instr->type = INSTR_REGRD_HRI;
4059 instr->regarray.regarray_id = r->id;
4060 instr->regarray.idx_val = idx_val;
4061 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
4062 instr->regarray.dstsrc.n_bits = fdst->n_bits;
4063 instr->regarray.dstsrc.offset = fdst->offset / 8;
4068 instr_regwr_translate(struct rte_swx_pipeline *p,
4069 struct action *action,
4072 struct instruction *instr,
4073 struct instruction_data *data __rte_unused)
4075 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
4077 struct field *fidx, *fsrc;
4079 uint32_t idx_struct_id, idx_val, src_struct_id;
4081 CHECK(n_tokens == 4, EINVAL);
4083 r = regarray_find(p, regarray);
4086 /* REGWR_RHH, REGWR_RHM, REGWR_RMH, REGWR_RMM. */
4087 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4088 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4090 CHECK(!fidx->var_size, EINVAL);
4091 CHECK(!fsrc->var_size, EINVAL);
4093 instr->type = INSTR_REGWR_RMM;
4094 if (idx[0] == 'h' && src[0] != 'h')
4095 instr->type = INSTR_REGWR_RHM;
4096 if (idx[0] != 'h' && src[0] == 'h')
4097 instr->type = INSTR_REGWR_RMH;
4098 if (idx[0] == 'h' && src[0] == 'h')
4099 instr->type = INSTR_REGWR_RHH;
4101 instr->regarray.regarray_id = r->id;
4102 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4103 instr->regarray.idx.n_bits = fidx->n_bits;
4104 instr->regarray.idx.offset = fidx->offset / 8;
4105 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4106 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4107 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4111 /* REGWR_RHI, REGWR_RMI. */
4112 if (fidx && !fsrc) {
4113 CHECK(!fidx->var_size, EINVAL);
4115 src_val = strtoull(src, &src, 0);
4116 CHECK(!src[0], EINVAL);
4118 instr->type = INSTR_REGWR_RMI;
4120 instr->type = INSTR_REGWR_RHI;
4122 instr->regarray.regarray_id = r->id;
4123 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4124 instr->regarray.idx.n_bits = fidx->n_bits;
4125 instr->regarray.idx.offset = fidx->offset / 8;
4126 instr->regarray.dstsrc_val = src_val;
4130 /* REGWR_RIH, REGWR_RIM. */
4131 if (!fidx && fsrc) {
4132 idx_val = strtoul(idx, &idx, 0);
4133 CHECK(!idx[0], EINVAL);
4135 CHECK(!fsrc->var_size, EINVAL);
4137 instr->type = INSTR_REGWR_RIM;
4139 instr->type = INSTR_REGWR_RIH;
4141 instr->regarray.regarray_id = r->id;
4142 instr->regarray.idx_val = idx_val;
4143 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4144 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4145 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4150 src_val = strtoull(src, &src, 0);
4151 CHECK(!src[0], EINVAL);
4153 idx_val = strtoul(idx, &idx, 0);
4154 CHECK(!idx[0], EINVAL);
4156 instr->type = INSTR_REGWR_RII;
4157 instr->regarray.idx_val = idx_val;
4158 instr->regarray.dstsrc_val = src_val;
4164 instr_regadd_translate(struct rte_swx_pipeline *p,
4165 struct action *action,
4168 struct instruction *instr,
4169 struct instruction_data *data __rte_unused)
4171 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
4173 struct field *fidx, *fsrc;
4175 uint32_t idx_struct_id, idx_val, src_struct_id;
4177 CHECK(n_tokens == 4, EINVAL);
4179 r = regarray_find(p, regarray);
4182 /* REGADD_RHH, REGADD_RHM, REGADD_RMH, REGADD_RMM. */
4183 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4184 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4186 CHECK(!fidx->var_size, EINVAL);
4187 CHECK(!fsrc->var_size, EINVAL);
4189 instr->type = INSTR_REGADD_RMM;
4190 if (idx[0] == 'h' && src[0] != 'h')
4191 instr->type = INSTR_REGADD_RHM;
4192 if (idx[0] != 'h' && src[0] == 'h')
4193 instr->type = INSTR_REGADD_RMH;
4194 if (idx[0] == 'h' && src[0] == 'h')
4195 instr->type = INSTR_REGADD_RHH;
4197 instr->regarray.regarray_id = r->id;
4198 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4199 instr->regarray.idx.n_bits = fidx->n_bits;
4200 instr->regarray.idx.offset = fidx->offset / 8;
4201 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4202 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4203 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4207 /* REGADD_RHI, REGADD_RMI. */
4208 if (fidx && !fsrc) {
4209 CHECK(!fidx->var_size, EINVAL);
4211 src_val = strtoull(src, &src, 0);
4212 CHECK(!src[0], EINVAL);
4214 instr->type = INSTR_REGADD_RMI;
4216 instr->type = INSTR_REGADD_RHI;
4218 instr->regarray.regarray_id = r->id;
4219 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4220 instr->regarray.idx.n_bits = fidx->n_bits;
4221 instr->regarray.idx.offset = fidx->offset / 8;
4222 instr->regarray.dstsrc_val = src_val;
4226 /* REGADD_RIH, REGADD_RIM. */
4227 if (!fidx && fsrc) {
4228 idx_val = strtoul(idx, &idx, 0);
4229 CHECK(!idx[0], EINVAL);
4231 CHECK(!fsrc->var_size, EINVAL);
4233 instr->type = INSTR_REGADD_RIM;
4235 instr->type = INSTR_REGADD_RIH;
4237 instr->regarray.regarray_id = r->id;
4238 instr->regarray.idx_val = idx_val;
4239 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4240 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4241 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4246 src_val = strtoull(src, &src, 0);
4247 CHECK(!src[0], EINVAL);
4249 idx_val = strtoul(idx, &idx, 0);
4250 CHECK(!idx[0], EINVAL);
4252 instr->type = INSTR_REGADD_RII;
4253 instr->regarray.idx_val = idx_val;
4254 instr->regarray.dstsrc_val = src_val;
4258 static inline uint64_t *
4259 instr_regarray_regarray(struct rte_swx_pipeline *p, struct instruction *ip)
4261 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4265 static inline uint64_t
4266 instr_regarray_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
4268 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4270 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
4271 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
4272 uint64_t idx64 = *idx64_ptr;
4273 uint64_t idx64_mask = UINT64_MAX >> (64 - ip->regarray.idx.n_bits);
4274 uint64_t idx = idx64 & idx64_mask & r->size_mask;
4279 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4281 static inline uint64_t
4282 instr_regarray_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
4284 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4286 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
4287 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
4288 uint64_t idx64 = *idx64_ptr;
4289 uint64_t idx = (ntoh64(idx64) >> (64 - ip->regarray.idx.n_bits)) & r->size_mask;
4296 #define instr_regarray_idx_nbo instr_regarray_idx_hbo
4300 static inline uint64_t
4301 instr_regarray_idx_imm(struct rte_swx_pipeline *p, struct instruction *ip)
4303 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4305 uint64_t idx = ip->regarray.idx_val & r->size_mask;
4310 static inline uint64_t
4311 instr_regarray_src_hbo(struct thread *t, struct instruction *ip)
4313 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
4314 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
4315 uint64_t src64 = *src64_ptr;
4316 uint64_t src64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
4317 uint64_t src = src64 & src64_mask;
4322 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4324 static inline uint64_t
4325 instr_regarray_src_nbo(struct thread *t, struct instruction *ip)
4327 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
4328 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
4329 uint64_t src64 = *src64_ptr;
4330 uint64_t src = ntoh64(src64) >> (64 - ip->regarray.dstsrc.n_bits);
4337 #define instr_regarray_src_nbo instr_regarray_src_hbo
4342 instr_regarray_dst_hbo_src_hbo_set(struct thread *t, struct instruction *ip, uint64_t src)
4344 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
4345 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
4346 uint64_t dst64 = *dst64_ptr;
4347 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
4349 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
4353 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4356 instr_regarray_dst_nbo_src_hbo_set(struct thread *t, struct instruction *ip, uint64_t src)
4358 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
4359 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
4360 uint64_t dst64 = *dst64_ptr;
4361 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
4363 src = hton64(src) >> (64 - ip->regarray.dstsrc.n_bits);
4364 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
4369 #define instr_regarray_dst_nbo_src_hbo_set instr_regarray_dst_hbo_src_hbo_set
4374 instr_regprefetch_rh_exec(struct rte_swx_pipeline *p)
4376 struct thread *t = &p->threads[p->thread_id];
4377 struct instruction *ip = t->ip;
4378 uint64_t *regarray, idx;
4380 TRACE("[Thread %2u] regprefetch (r[h])\n", p->thread_id);
4383 regarray = instr_regarray_regarray(p, ip);
4384 idx = instr_regarray_idx_nbo(p, t, ip);
4385 rte_prefetch0(®array[idx]);
4392 instr_regprefetch_rm_exec(struct rte_swx_pipeline *p)
4394 struct thread *t = &p->threads[p->thread_id];
4395 struct instruction *ip = t->ip;
4396 uint64_t *regarray, idx;
4398 TRACE("[Thread %2u] regprefetch (r[m])\n", p->thread_id);
4401 regarray = instr_regarray_regarray(p, ip);
4402 idx = instr_regarray_idx_hbo(p, t, ip);
4403 rte_prefetch0(®array[idx]);
4410 instr_regprefetch_ri_exec(struct rte_swx_pipeline *p)
4412 struct thread *t = &p->threads[p->thread_id];
4413 struct instruction *ip = t->ip;
4414 uint64_t *regarray, idx;
4416 TRACE("[Thread %2u] regprefetch (r[i])\n", p->thread_id);
4419 regarray = instr_regarray_regarray(p, ip);
4420 idx = instr_regarray_idx_imm(p, ip);
4421 rte_prefetch0(®array[idx]);
4428 instr_regrd_hrh_exec(struct rte_swx_pipeline *p)
4430 struct thread *t = &p->threads[p->thread_id];
4431 struct instruction *ip = t->ip;
4432 uint64_t *regarray, idx;
4434 TRACE("[Thread %2u] regrd (h = r[h])\n", p->thread_id);
4437 regarray = instr_regarray_regarray(p, ip);
4438 idx = instr_regarray_idx_nbo(p, t, ip);
4439 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
4446 instr_regrd_hrm_exec(struct rte_swx_pipeline *p)
4448 struct thread *t = &p->threads[p->thread_id];
4449 struct instruction *ip = t->ip;
4450 uint64_t *regarray, idx;
4452 TRACE("[Thread %2u] regrd (h = r[m])\n", p->thread_id);
4455 regarray = instr_regarray_regarray(p, ip);
4456 idx = instr_regarray_idx_hbo(p, t, ip);
4457 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
4464 instr_regrd_mrh_exec(struct rte_swx_pipeline *p)
4466 struct thread *t = &p->threads[p->thread_id];
4467 struct instruction *ip = t->ip;
4468 uint64_t *regarray, idx;
4470 TRACE("[Thread %2u] regrd (m = r[h])\n", p->thread_id);
4473 regarray = instr_regarray_regarray(p, ip);
4474 idx = instr_regarray_idx_nbo(p, t, ip);
4475 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
4482 instr_regrd_mrm_exec(struct rte_swx_pipeline *p)
4484 struct thread *t = &p->threads[p->thread_id];
4485 struct instruction *ip = t->ip;
4486 uint64_t *regarray, idx;
4489 regarray = instr_regarray_regarray(p, ip);
4490 idx = instr_regarray_idx_hbo(p, t, ip);
4491 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
4498 instr_regrd_hri_exec(struct rte_swx_pipeline *p)
4500 struct thread *t = &p->threads[p->thread_id];
4501 struct instruction *ip = t->ip;
4502 uint64_t *regarray, idx;
4504 TRACE("[Thread %2u] regrd (h = r[i])\n", p->thread_id);
4507 regarray = instr_regarray_regarray(p, ip);
4508 idx = instr_regarray_idx_imm(p, ip);
4509 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
4516 instr_regrd_mri_exec(struct rte_swx_pipeline *p)
4518 struct thread *t = &p->threads[p->thread_id];
4519 struct instruction *ip = t->ip;
4520 uint64_t *regarray, idx;
4522 TRACE("[Thread %2u] regrd (m = r[i])\n", p->thread_id);
4525 regarray = instr_regarray_regarray(p, ip);
4526 idx = instr_regarray_idx_imm(p, ip);
4527 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
4534 instr_regwr_rhh_exec(struct rte_swx_pipeline *p)
4536 struct thread *t = &p->threads[p->thread_id];
4537 struct instruction *ip = t->ip;
4538 uint64_t *regarray, idx, src;
4540 TRACE("[Thread %2u] regwr (r[h] = h)\n", p->thread_id);
4543 regarray = instr_regarray_regarray(p, ip);
4544 idx = instr_regarray_idx_nbo(p, t, ip);
4545 src = instr_regarray_src_nbo(t, ip);
4546 regarray[idx] = src;
4553 instr_regwr_rhm_exec(struct rte_swx_pipeline *p)
4555 struct thread *t = &p->threads[p->thread_id];
4556 struct instruction *ip = t->ip;
4557 uint64_t *regarray, idx, src;
4559 TRACE("[Thread %2u] regwr (r[h] = m)\n", p->thread_id);
4562 regarray = instr_regarray_regarray(p, ip);
4563 idx = instr_regarray_idx_nbo(p, t, ip);
4564 src = instr_regarray_src_hbo(t, ip);
4565 regarray[idx] = src;
4572 instr_regwr_rmh_exec(struct rte_swx_pipeline *p)
4574 struct thread *t = &p->threads[p->thread_id];
4575 struct instruction *ip = t->ip;
4576 uint64_t *regarray, idx, src;
4578 TRACE("[Thread %2u] regwr (r[m] = h)\n", p->thread_id);
4581 regarray = instr_regarray_regarray(p, ip);
4582 idx = instr_regarray_idx_hbo(p, t, ip);
4583 src = instr_regarray_src_nbo(t, ip);
4584 regarray[idx] = src;
4591 instr_regwr_rmm_exec(struct rte_swx_pipeline *p)
4593 struct thread *t = &p->threads[p->thread_id];
4594 struct instruction *ip = t->ip;
4595 uint64_t *regarray, idx, src;
4597 TRACE("[Thread %2u] regwr (r[m] = m)\n", p->thread_id);
4600 regarray = instr_regarray_regarray(p, ip);
4601 idx = instr_regarray_idx_hbo(p, t, ip);
4602 src = instr_regarray_src_hbo(t, ip);
4603 regarray[idx] = src;
4610 instr_regwr_rhi_exec(struct rte_swx_pipeline *p)
4612 struct thread *t = &p->threads[p->thread_id];
4613 struct instruction *ip = t->ip;
4614 uint64_t *regarray, idx, src;
4616 TRACE("[Thread %2u] regwr (r[h] = i)\n", p->thread_id);
4619 regarray = instr_regarray_regarray(p, ip);
4620 idx = instr_regarray_idx_nbo(p, t, ip);
4621 src = ip->regarray.dstsrc_val;
4622 regarray[idx] = src;
4629 instr_regwr_rmi_exec(struct rte_swx_pipeline *p)
4631 struct thread *t = &p->threads[p->thread_id];
4632 struct instruction *ip = t->ip;
4633 uint64_t *regarray, idx, src;
4635 TRACE("[Thread %2u] regwr (r[m] = i)\n", p->thread_id);
4638 regarray = instr_regarray_regarray(p, ip);
4639 idx = instr_regarray_idx_hbo(p, t, ip);
4640 src = ip->regarray.dstsrc_val;
4641 regarray[idx] = src;
4648 instr_regwr_rih_exec(struct rte_swx_pipeline *p)
4650 struct thread *t = &p->threads[p->thread_id];
4651 struct instruction *ip = t->ip;
4652 uint64_t *regarray, idx, src;
4654 TRACE("[Thread %2u] regwr (r[i] = h)\n", p->thread_id);
4657 regarray = instr_regarray_regarray(p, ip);
4658 idx = instr_regarray_idx_imm(p, ip);
4659 src = instr_regarray_src_nbo(t, ip);
4660 regarray[idx] = src;
4667 instr_regwr_rim_exec(struct rte_swx_pipeline *p)
4669 struct thread *t = &p->threads[p->thread_id];
4670 struct instruction *ip = t->ip;
4671 uint64_t *regarray, idx, src;
4673 TRACE("[Thread %2u] regwr (r[i] = m)\n", p->thread_id);
4676 regarray = instr_regarray_regarray(p, ip);
4677 idx = instr_regarray_idx_imm(p, ip);
4678 src = instr_regarray_src_hbo(t, ip);
4679 regarray[idx] = src;
4686 instr_regwr_rii_exec(struct rte_swx_pipeline *p)
4688 struct thread *t = &p->threads[p->thread_id];
4689 struct instruction *ip = t->ip;
4690 uint64_t *regarray, idx, src;
4692 TRACE("[Thread %2u] regwr (r[i] = i)\n", p->thread_id);
4695 regarray = instr_regarray_regarray(p, ip);
4696 idx = instr_regarray_idx_imm(p, ip);
4697 src = ip->regarray.dstsrc_val;
4698 regarray[idx] = src;
4705 instr_regadd_rhh_exec(struct rte_swx_pipeline *p)
4707 struct thread *t = &p->threads[p->thread_id];
4708 struct instruction *ip = t->ip;
4709 uint64_t *regarray, idx, src;
4711 TRACE("[Thread %2u] regadd (r[h] += h)\n", p->thread_id);
4714 regarray = instr_regarray_regarray(p, ip);
4715 idx = instr_regarray_idx_nbo(p, t, ip);
4716 src = instr_regarray_src_nbo(t, ip);
4717 regarray[idx] += src;
4724 instr_regadd_rhm_exec(struct rte_swx_pipeline *p)
4726 struct thread *t = &p->threads[p->thread_id];
4727 struct instruction *ip = t->ip;
4728 uint64_t *regarray, idx, src;
4730 TRACE("[Thread %2u] regadd (r[h] += m)\n", p->thread_id);
4733 regarray = instr_regarray_regarray(p, ip);
4734 idx = instr_regarray_idx_nbo(p, t, ip);
4735 src = instr_regarray_src_hbo(t, ip);
4736 regarray[idx] += src;
4743 instr_regadd_rmh_exec(struct rte_swx_pipeline *p)
4745 struct thread *t = &p->threads[p->thread_id];
4746 struct instruction *ip = t->ip;
4747 uint64_t *regarray, idx, src;
4749 TRACE("[Thread %2u] regadd (r[m] += h)\n", p->thread_id);
4752 regarray = instr_regarray_regarray(p, ip);
4753 idx = instr_regarray_idx_hbo(p, t, ip);
4754 src = instr_regarray_src_nbo(t, ip);
4755 regarray[idx] += src;
4762 instr_regadd_rmm_exec(struct rte_swx_pipeline *p)
4764 struct thread *t = &p->threads[p->thread_id];
4765 struct instruction *ip = t->ip;
4766 uint64_t *regarray, idx, src;
4768 TRACE("[Thread %2u] regadd (r[m] += m)\n", p->thread_id);
4771 regarray = instr_regarray_regarray(p, ip);
4772 idx = instr_regarray_idx_hbo(p, t, ip);
4773 src = instr_regarray_src_hbo(t, ip);
4774 regarray[idx] += src;
4781 instr_regadd_rhi_exec(struct rte_swx_pipeline *p)
4783 struct thread *t = &p->threads[p->thread_id];
4784 struct instruction *ip = t->ip;
4785 uint64_t *regarray, idx, src;
4787 TRACE("[Thread %2u] regadd (r[h] += i)\n", p->thread_id);
4790 regarray = instr_regarray_regarray(p, ip);
4791 idx = instr_regarray_idx_nbo(p, t, ip);
4792 src = ip->regarray.dstsrc_val;
4793 regarray[idx] += src;
4800 instr_regadd_rmi_exec(struct rte_swx_pipeline *p)
4802 struct thread *t = &p->threads[p->thread_id];
4803 struct instruction *ip = t->ip;
4804 uint64_t *regarray, idx, src;
4806 TRACE("[Thread %2u] regadd (r[m] += i)\n", p->thread_id);
4809 regarray = instr_regarray_regarray(p, ip);
4810 idx = instr_regarray_idx_hbo(p, t, ip);
4811 src = ip->regarray.dstsrc_val;
4812 regarray[idx] += src;
4819 instr_regadd_rih_exec(struct rte_swx_pipeline *p)
4821 struct thread *t = &p->threads[p->thread_id];
4822 struct instruction *ip = t->ip;
4823 uint64_t *regarray, idx, src;
4825 TRACE("[Thread %2u] regadd (r[i] += h)\n", p->thread_id);
4828 regarray = instr_regarray_regarray(p, ip);
4829 idx = instr_regarray_idx_imm(p, ip);
4830 src = instr_regarray_src_nbo(t, ip);
4831 regarray[idx] += src;
4838 instr_regadd_rim_exec(struct rte_swx_pipeline *p)
4840 struct thread *t = &p->threads[p->thread_id];
4841 struct instruction *ip = t->ip;
4842 uint64_t *regarray, idx, src;
4844 TRACE("[Thread %2u] regadd (r[i] += m)\n", p->thread_id);
4847 regarray = instr_regarray_regarray(p, ip);
4848 idx = instr_regarray_idx_imm(p, ip);
4849 src = instr_regarray_src_hbo(t, ip);
4850 regarray[idx] += src;
4857 instr_regadd_rii_exec(struct rte_swx_pipeline *p)
4859 struct thread *t = &p->threads[p->thread_id];
4860 struct instruction *ip = t->ip;
4861 uint64_t *regarray, idx, src;
4863 TRACE("[Thread %2u] regadd (r[i] += i)\n", p->thread_id);
4866 regarray = instr_regarray_regarray(p, ip);
4867 idx = instr_regarray_idx_imm(p, ip);
4868 src = ip->regarray.dstsrc_val;
4869 regarray[idx] += src;
4878 static struct metarray *
4879 metarray_find(struct rte_swx_pipeline *p, const char *name);
4882 instr_metprefetch_translate(struct rte_swx_pipeline *p,
4883 struct action *action,
4886 struct instruction *instr,
4887 struct instruction_data *data __rte_unused)
4889 char *metarray = tokens[1], *idx = tokens[2];
4892 uint32_t idx_struct_id, idx_val;
4894 CHECK(n_tokens == 3, EINVAL);
4896 m = metarray_find(p, metarray);
4899 /* METPREFETCH_H, METPREFETCH_M. */
4900 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4902 CHECK(!fidx->var_size, EINVAL);
4904 instr->type = INSTR_METPREFETCH_M;
4906 instr->type = INSTR_METPREFETCH_H;
4908 instr->meter.metarray_id = m->id;
4909 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4910 instr->meter.idx.n_bits = fidx->n_bits;
4911 instr->meter.idx.offset = fidx->offset / 8;
4915 /* METPREFETCH_I. */
4916 idx_val = strtoul(idx, &idx, 0);
4917 CHECK(!idx[0], EINVAL);
4919 instr->type = INSTR_METPREFETCH_I;
4920 instr->meter.metarray_id = m->id;
4921 instr->meter.idx_val = idx_val;
4926 instr_meter_translate(struct rte_swx_pipeline *p,
4927 struct action *action,
4930 struct instruction *instr,
4931 struct instruction_data *data __rte_unused)
4933 char *metarray = tokens[1], *idx = tokens[2], *length = tokens[3];
4934 char *color_in = tokens[4], *color_out = tokens[5];
4936 struct field *fidx, *flength, *fcin, *fcout;
4937 uint32_t idx_struct_id, length_struct_id;
4938 uint32_t color_in_struct_id, color_out_struct_id;
4940 CHECK(n_tokens == 6, EINVAL);
4942 m = metarray_find(p, metarray);
4945 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4947 flength = struct_field_parse(p, action, length, &length_struct_id);
4948 CHECK(flength, EINVAL);
4949 CHECK(!flength->var_size, EINVAL);
4951 fcin = struct_field_parse(p, action, color_in, &color_in_struct_id);
4953 fcout = struct_field_parse(p, NULL, color_out, &color_out_struct_id);
4954 CHECK(fcout, EINVAL);
4955 CHECK(!fcout->var_size, EINVAL);
4957 /* index = HMEFT, length = HMEFT, color_in = MEFT, color_out = MEF. */
4959 CHECK(!fidx->var_size, EINVAL);
4960 CHECK(!fcin->var_size, EINVAL);
4962 instr->type = INSTR_METER_MMM;
4963 if (idx[0] == 'h' && length[0] == 'h')
4964 instr->type = INSTR_METER_HHM;
4965 if (idx[0] == 'h' && length[0] != 'h')
4966 instr->type = INSTR_METER_HMM;
4967 if (idx[0] != 'h' && length[0] == 'h')
4968 instr->type = INSTR_METER_MHM;
4970 instr->meter.metarray_id = m->id;
4972 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4973 instr->meter.idx.n_bits = fidx->n_bits;
4974 instr->meter.idx.offset = fidx->offset / 8;
4976 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4977 instr->meter.length.n_bits = flength->n_bits;
4978 instr->meter.length.offset = flength->offset / 8;
4980 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
4981 instr->meter.color_in.n_bits = fcin->n_bits;
4982 instr->meter.color_in.offset = fcin->offset / 8;
4984 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4985 instr->meter.color_out.n_bits = fcout->n_bits;
4986 instr->meter.color_out.offset = fcout->offset / 8;
4991 /* index = HMEFT, length = HMEFT, color_in = I, color_out = MEF. */
4992 if (fidx && !fcin) {
4993 uint32_t color_in_val;
4995 CHECK(!fidx->var_size, EINVAL);
4997 color_in_val = strtoul(color_in, &color_in, 0);
4998 CHECK(!color_in[0], EINVAL);
5000 instr->type = INSTR_METER_MMI;
5001 if (idx[0] == 'h' && length[0] == 'h')
5002 instr->type = INSTR_METER_HHI;
5003 if (idx[0] == 'h' && length[0] != 'h')
5004 instr->type = INSTR_METER_HMI;
5005 if (idx[0] != 'h' && length[0] == 'h')
5006 instr->type = INSTR_METER_MHI;
5008 instr->meter.metarray_id = m->id;
5010 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
5011 instr->meter.idx.n_bits = fidx->n_bits;
5012 instr->meter.idx.offset = fidx->offset / 8;
5014 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5015 instr->meter.length.n_bits = flength->n_bits;
5016 instr->meter.length.offset = flength->offset / 8;
5018 instr->meter.color_in_val = color_in_val;
5020 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5021 instr->meter.color_out.n_bits = fcout->n_bits;
5022 instr->meter.color_out.offset = fcout->offset / 8;
5027 /* index = I, length = HMEFT, color_in = MEFT, color_out = MEF. */
5028 if (!fidx && fcin) {
5031 idx_val = strtoul(idx, &idx, 0);
5032 CHECK(!idx[0], EINVAL);
5034 CHECK(!fcin->var_size, EINVAL);
5036 instr->type = INSTR_METER_IMM;
5037 if (length[0] == 'h')
5038 instr->type = INSTR_METER_IHM;
5040 instr->meter.metarray_id = m->id;
5042 instr->meter.idx_val = idx_val;
5044 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5045 instr->meter.length.n_bits = flength->n_bits;
5046 instr->meter.length.offset = flength->offset / 8;
5048 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
5049 instr->meter.color_in.n_bits = fcin->n_bits;
5050 instr->meter.color_in.offset = fcin->offset / 8;
5052 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5053 instr->meter.color_out.n_bits = fcout->n_bits;
5054 instr->meter.color_out.offset = fcout->offset / 8;
5059 /* index = I, length = HMEFT, color_in = I, color_out = MEF. */
5060 if (!fidx && !fcin) {
5061 uint32_t idx_val, color_in_val;
5063 idx_val = strtoul(idx, &idx, 0);
5064 CHECK(!idx[0], EINVAL);
5066 color_in_val = strtoul(color_in, &color_in, 0);
5067 CHECK(!color_in[0], EINVAL);
5069 instr->type = INSTR_METER_IMI;
5070 if (length[0] == 'h')
5071 instr->type = INSTR_METER_IHI;
5073 instr->meter.metarray_id = m->id;
5075 instr->meter.idx_val = idx_val;
5077 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5078 instr->meter.length.n_bits = flength->n_bits;
5079 instr->meter.length.offset = flength->offset / 8;
5081 instr->meter.color_in_val = color_in_val;
5083 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5084 instr->meter.color_out.n_bits = fcout->n_bits;
5085 instr->meter.color_out.offset = fcout->offset / 8;
5093 static inline struct meter *
5094 instr_meter_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
5096 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
5098 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
5099 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
5100 uint64_t idx64 = *idx64_ptr;
5101 uint64_t idx64_mask = UINT64_MAX >> (64 - (ip)->meter.idx.n_bits);
5102 uint64_t idx = idx64 & idx64_mask & r->size_mask;
5104 return &r->metarray[idx];
5107 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5109 static inline struct meter *
5110 instr_meter_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
5112 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
5114 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
5115 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
5116 uint64_t idx64 = *idx64_ptr;
5117 uint64_t idx = (ntoh64(idx64) >> (64 - ip->meter.idx.n_bits)) & r->size_mask;
5119 return &r->metarray[idx];
5124 #define instr_meter_idx_nbo instr_meter_idx_hbo
5128 static inline struct meter *
5129 instr_meter_idx_imm(struct rte_swx_pipeline *p, struct instruction *ip)
5131 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
5133 uint64_t idx = ip->meter.idx_val & r->size_mask;
5135 return &r->metarray[idx];
5138 static inline uint32_t
5139 instr_meter_length_hbo(struct thread *t, struct instruction *ip)
5141 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
5142 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
5143 uint64_t src64 = *src64_ptr;
5144 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->meter.length.n_bits);
5145 uint64_t src = src64 & src64_mask;
5147 return (uint32_t)src;
5150 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5152 static inline uint32_t
5153 instr_meter_length_nbo(struct thread *t, struct instruction *ip)
5155 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
5156 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
5157 uint64_t src64 = *src64_ptr;
5158 uint64_t src = ntoh64(src64) >> (64 - ip->meter.length.n_bits);
5160 return (uint32_t)src;
5165 #define instr_meter_length_nbo instr_meter_length_hbo
5169 static inline enum rte_color
5170 instr_meter_color_in_hbo(struct thread *t, struct instruction *ip)
5172 uint8_t *src_struct = t->structs[ip->meter.color_in.struct_id];
5173 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.color_in.offset];
5174 uint64_t src64 = *src64_ptr;
5175 uint64_t src64_mask = UINT64_MAX >> (64 - ip->meter.color_in.n_bits);
5176 uint64_t src = src64 & src64_mask;
5178 return (enum rte_color)src;
5182 instr_meter_color_out_hbo_set(struct thread *t, struct instruction *ip, enum rte_color color_out)
5184 uint8_t *dst_struct = t->structs[ip->meter.color_out.struct_id];
5185 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->meter.color_out.offset];
5186 uint64_t dst64 = *dst64_ptr;
5187 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->meter.color_out.n_bits);
5189 uint64_t src = (uint64_t)color_out;
5191 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
5195 instr_metprefetch_h_exec(struct rte_swx_pipeline *p)
5197 struct thread *t = &p->threads[p->thread_id];
5198 struct instruction *ip = t->ip;
5201 TRACE("[Thread %2u] metprefetch (h)\n", p->thread_id);
5204 m = instr_meter_idx_nbo(p, t, ip);
5212 instr_metprefetch_m_exec(struct rte_swx_pipeline *p)
5214 struct thread *t = &p->threads[p->thread_id];
5215 struct instruction *ip = t->ip;
5218 TRACE("[Thread %2u] metprefetch (m)\n", p->thread_id);
5221 m = instr_meter_idx_hbo(p, t, ip);
5229 instr_metprefetch_i_exec(struct rte_swx_pipeline *p)
5231 struct thread *t = &p->threads[p->thread_id];
5232 struct instruction *ip = t->ip;
5235 TRACE("[Thread %2u] metprefetch (i)\n", p->thread_id);
5238 m = instr_meter_idx_imm(p, ip);
5246 instr_meter_hhm_exec(struct rte_swx_pipeline *p)
5248 struct thread *t = &p->threads[p->thread_id];
5249 struct instruction *ip = t->ip;
5251 uint64_t time, n_pkts, n_bytes;
5253 enum rte_color color_in, color_out;
5255 TRACE("[Thread %2u] meter (hhm)\n", p->thread_id);
5258 m = instr_meter_idx_nbo(p, t, ip);
5259 rte_prefetch0(m->n_pkts);
5260 time = rte_get_tsc_cycles();
5261 length = instr_meter_length_nbo(t, ip);
5262 color_in = instr_meter_color_in_hbo(t, ip);
5264 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5265 &m->profile->profile,
5270 color_out &= m->color_mask;
5272 n_pkts = m->n_pkts[color_out];
5273 n_bytes = m->n_bytes[color_out];
5275 instr_meter_color_out_hbo_set(t, ip, color_out);
5277 m->n_pkts[color_out] = n_pkts + 1;
5278 m->n_bytes[color_out] = n_bytes + length;
5285 instr_meter_hhi_exec(struct rte_swx_pipeline *p)
5287 struct thread *t = &p->threads[p->thread_id];
5288 struct instruction *ip = t->ip;
5290 uint64_t time, n_pkts, n_bytes;
5292 enum rte_color color_in, color_out;
5294 TRACE("[Thread %2u] meter (hhi)\n", p->thread_id);
5297 m = instr_meter_idx_nbo(p, t, ip);
5298 rte_prefetch0(m->n_pkts);
5299 time = rte_get_tsc_cycles();
5300 length = instr_meter_length_nbo(t, ip);
5301 color_in = (enum rte_color)ip->meter.color_in_val;
5303 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5304 &m->profile->profile,
5309 color_out &= m->color_mask;
5311 n_pkts = m->n_pkts[color_out];
5312 n_bytes = m->n_bytes[color_out];
5314 instr_meter_color_out_hbo_set(t, ip, color_out);
5316 m->n_pkts[color_out] = n_pkts + 1;
5317 m->n_bytes[color_out] = n_bytes + length;
5324 instr_meter_hmm_exec(struct rte_swx_pipeline *p)
5326 struct thread *t = &p->threads[p->thread_id];
5327 struct instruction *ip = t->ip;
5329 uint64_t time, n_pkts, n_bytes;
5331 enum rte_color color_in, color_out;
5333 TRACE("[Thread %2u] meter (hmm)\n", p->thread_id);
5336 m = instr_meter_idx_nbo(p, t, ip);
5337 rte_prefetch0(m->n_pkts);
5338 time = rte_get_tsc_cycles();
5339 length = instr_meter_length_hbo(t, ip);
5340 color_in = instr_meter_color_in_hbo(t, ip);
5342 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5343 &m->profile->profile,
5348 color_out &= m->color_mask;
5350 n_pkts = m->n_pkts[color_out];
5351 n_bytes = m->n_bytes[color_out];
5353 instr_meter_color_out_hbo_set(t, ip, color_out);
5355 m->n_pkts[color_out] = n_pkts + 1;
5356 m->n_bytes[color_out] = n_bytes + length;
5362 instr_meter_hmi_exec(struct rte_swx_pipeline *p)
5364 struct thread *t = &p->threads[p->thread_id];
5365 struct instruction *ip = t->ip;
5367 uint64_t time, n_pkts, n_bytes;
5369 enum rte_color color_in, color_out;
5371 TRACE("[Thread %2u] meter (hmi)\n", p->thread_id);
5374 m = instr_meter_idx_nbo(p, t, ip);
5375 rte_prefetch0(m->n_pkts);
5376 time = rte_get_tsc_cycles();
5377 length = instr_meter_length_hbo(t, ip);
5378 color_in = (enum rte_color)ip->meter.color_in_val;
5380 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5381 &m->profile->profile,
5386 color_out &= m->color_mask;
5388 n_pkts = m->n_pkts[color_out];
5389 n_bytes = m->n_bytes[color_out];
5391 instr_meter_color_out_hbo_set(t, ip, color_out);
5393 m->n_pkts[color_out] = n_pkts + 1;
5394 m->n_bytes[color_out] = n_bytes + length;
5401 instr_meter_mhm_exec(struct rte_swx_pipeline *p)
5403 struct thread *t = &p->threads[p->thread_id];
5404 struct instruction *ip = t->ip;
5406 uint64_t time, n_pkts, n_bytes;
5408 enum rte_color color_in, color_out;
5410 TRACE("[Thread %2u] meter (mhm)\n", p->thread_id);
5413 m = instr_meter_idx_hbo(p, t, ip);
5414 rte_prefetch0(m->n_pkts);
5415 time = rte_get_tsc_cycles();
5416 length = instr_meter_length_nbo(t, ip);
5417 color_in = instr_meter_color_in_hbo(t, ip);
5419 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5420 &m->profile->profile,
5425 color_out &= m->color_mask;
5427 n_pkts = m->n_pkts[color_out];
5428 n_bytes = m->n_bytes[color_out];
5430 instr_meter_color_out_hbo_set(t, ip, color_out);
5432 m->n_pkts[color_out] = n_pkts + 1;
5433 m->n_bytes[color_out] = n_bytes + length;
5440 instr_meter_mhi_exec(struct rte_swx_pipeline *p)
5442 struct thread *t = &p->threads[p->thread_id];
5443 struct instruction *ip = t->ip;
5445 uint64_t time, n_pkts, n_bytes;
5447 enum rte_color color_in, color_out;
5449 TRACE("[Thread %2u] meter (mhi)\n", p->thread_id);
5452 m = instr_meter_idx_hbo(p, t, ip);
5453 rte_prefetch0(m->n_pkts);
5454 time = rte_get_tsc_cycles();
5455 length = instr_meter_length_nbo(t, ip);
5456 color_in = (enum rte_color)ip->meter.color_in_val;
5458 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5459 &m->profile->profile,
5464 color_out &= m->color_mask;
5466 n_pkts = m->n_pkts[color_out];
5467 n_bytes = m->n_bytes[color_out];
5469 instr_meter_color_out_hbo_set(t, ip, color_out);
5471 m->n_pkts[color_out] = n_pkts + 1;
5472 m->n_bytes[color_out] = n_bytes + length;
5479 instr_meter_mmm_exec(struct rte_swx_pipeline *p)
5481 struct thread *t = &p->threads[p->thread_id];
5482 struct instruction *ip = t->ip;
5484 uint64_t time, n_pkts, n_bytes;
5486 enum rte_color color_in, color_out;
5488 TRACE("[Thread %2u] meter (mmm)\n", p->thread_id);
5491 m = instr_meter_idx_hbo(p, t, ip);
5492 rte_prefetch0(m->n_pkts);
5493 time = rte_get_tsc_cycles();
5494 length = instr_meter_length_hbo(t, ip);
5495 color_in = instr_meter_color_in_hbo(t, ip);
5497 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5498 &m->profile->profile,
5503 color_out &= m->color_mask;
5505 n_pkts = m->n_pkts[color_out];
5506 n_bytes = m->n_bytes[color_out];
5508 instr_meter_color_out_hbo_set(t, ip, color_out);
5510 m->n_pkts[color_out] = n_pkts + 1;
5511 m->n_bytes[color_out] = n_bytes + length;
5518 instr_meter_mmi_exec(struct rte_swx_pipeline *p)
5520 struct thread *t = &p->threads[p->thread_id];
5521 struct instruction *ip = t->ip;
5523 uint64_t time, n_pkts, n_bytes;
5525 enum rte_color color_in, color_out;
5527 TRACE("[Thread %2u] meter (mmi)\n", p->thread_id);
5530 m = instr_meter_idx_hbo(p, t, ip);
5531 rte_prefetch0(m->n_pkts);
5532 time = rte_get_tsc_cycles();
5533 length = instr_meter_length_hbo(t, ip);
5534 color_in = (enum rte_color)ip->meter.color_in_val;
5536 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5537 &m->profile->profile,
5542 color_out &= m->color_mask;
5544 n_pkts = m->n_pkts[color_out];
5545 n_bytes = m->n_bytes[color_out];
5547 instr_meter_color_out_hbo_set(t, ip, color_out);
5549 m->n_pkts[color_out] = n_pkts + 1;
5550 m->n_bytes[color_out] = n_bytes + length;
5557 instr_meter_ihm_exec(struct rte_swx_pipeline *p)
5559 struct thread *t = &p->threads[p->thread_id];
5560 struct instruction *ip = t->ip;
5562 uint64_t time, n_pkts, n_bytes;
5564 enum rte_color color_in, color_out;
5566 TRACE("[Thread %2u] meter (ihm)\n", p->thread_id);
5569 m = instr_meter_idx_imm(p, ip);
5570 rte_prefetch0(m->n_pkts);
5571 time = rte_get_tsc_cycles();
5572 length = instr_meter_length_nbo(t, ip);
5573 color_in = instr_meter_color_in_hbo(t, ip);
5575 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5576 &m->profile->profile,
5581 color_out &= m->color_mask;
5583 n_pkts = m->n_pkts[color_out];
5584 n_bytes = m->n_bytes[color_out];
5586 instr_meter_color_out_hbo_set(t, ip, color_out);
5588 m->n_pkts[color_out] = n_pkts + 1;
5589 m->n_bytes[color_out] = n_bytes + length;
5596 instr_meter_ihi_exec(struct rte_swx_pipeline *p)
5598 struct thread *t = &p->threads[p->thread_id];
5599 struct instruction *ip = t->ip;
5601 uint64_t time, n_pkts, n_bytes;
5603 enum rte_color color_in, color_out;
5605 TRACE("[Thread %2u] meter (ihi)\n", p->thread_id);
5608 m = instr_meter_idx_imm(p, ip);
5609 rte_prefetch0(m->n_pkts);
5610 time = rte_get_tsc_cycles();
5611 length = instr_meter_length_nbo(t, ip);
5612 color_in = (enum rte_color)ip->meter.color_in_val;
5614 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5615 &m->profile->profile,
5620 color_out &= m->color_mask;
5622 n_pkts = m->n_pkts[color_out];
5623 n_bytes = m->n_bytes[color_out];
5625 instr_meter_color_out_hbo_set(t, ip, color_out);
5627 m->n_pkts[color_out] = n_pkts + 1;
5628 m->n_bytes[color_out] = n_bytes + length;
5635 instr_meter_imm_exec(struct rte_swx_pipeline *p)
5637 struct thread *t = &p->threads[p->thread_id];
5638 struct instruction *ip = t->ip;
5640 uint64_t time, n_pkts, n_bytes;
5642 enum rte_color color_in, color_out;
5644 TRACE("[Thread %2u] meter (imm)\n", p->thread_id);
5647 m = instr_meter_idx_imm(p, ip);
5648 rte_prefetch0(m->n_pkts);
5649 time = rte_get_tsc_cycles();
5650 length = instr_meter_length_hbo(t, ip);
5651 color_in = instr_meter_color_in_hbo(t, ip);
5653 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5654 &m->profile->profile,
5659 color_out &= m->color_mask;
5661 n_pkts = m->n_pkts[color_out];
5662 n_bytes = m->n_bytes[color_out];
5664 instr_meter_color_out_hbo_set(t, ip, color_out);
5666 m->n_pkts[color_out] = n_pkts + 1;
5667 m->n_bytes[color_out] = n_bytes + length;
5673 instr_meter_imi_exec(struct rte_swx_pipeline *p)
5675 struct thread *t = &p->threads[p->thread_id];
5676 struct instruction *ip = t->ip;
5678 uint64_t time, n_pkts, n_bytes;
5680 enum rte_color color_in, color_out;
5682 TRACE("[Thread %2u] meter (imi)\n", p->thread_id);
5685 m = instr_meter_idx_imm(p, ip);
5686 rte_prefetch0(m->n_pkts);
5687 time = rte_get_tsc_cycles();
5688 length = instr_meter_length_hbo(t, ip);
5689 color_in = (enum rte_color)ip->meter.color_in_val;
5691 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5692 &m->profile->profile,
5697 color_out &= m->color_mask;
5699 n_pkts = m->n_pkts[color_out];
5700 n_bytes = m->n_bytes[color_out];
5702 instr_meter_color_out_hbo_set(t, ip, color_out);
5704 m->n_pkts[color_out] = n_pkts + 1;
5705 m->n_bytes[color_out] = n_bytes + length;
5715 instr_jmp_translate(struct rte_swx_pipeline *p __rte_unused,
5716 struct action *action __rte_unused,
5719 struct instruction *instr,
5720 struct instruction_data *data)
5722 CHECK(n_tokens == 2, EINVAL);
5724 strcpy(data->jmp_label, tokens[1]);
5726 instr->type = INSTR_JMP;
5727 instr->jmp.ip = NULL; /* Resolved later. */
5732 instr_jmp_valid_translate(struct rte_swx_pipeline *p,
5733 struct action *action __rte_unused,
5736 struct instruction *instr,
5737 struct instruction_data *data)
5741 CHECK(n_tokens == 3, EINVAL);
5743 strcpy(data->jmp_label, tokens[1]);
5745 h = header_parse(p, tokens[2]);
5748 instr->type = INSTR_JMP_VALID;
5749 instr->jmp.ip = NULL; /* Resolved later. */
5750 instr->jmp.header_id = h->id;
5755 instr_jmp_invalid_translate(struct rte_swx_pipeline *p,
5756 struct action *action __rte_unused,
5759 struct instruction *instr,
5760 struct instruction_data *data)
5764 CHECK(n_tokens == 3, EINVAL);
5766 strcpy(data->jmp_label, tokens[1]);
5768 h = header_parse(p, tokens[2]);
5771 instr->type = INSTR_JMP_INVALID;
5772 instr->jmp.ip = NULL; /* Resolved later. */
5773 instr->jmp.header_id = h->id;
5778 instr_jmp_hit_translate(struct rte_swx_pipeline *p __rte_unused,
5779 struct action *action,
5782 struct instruction *instr,
5783 struct instruction_data *data)
5785 CHECK(!action, EINVAL);
5786 CHECK(n_tokens == 2, EINVAL);
5788 strcpy(data->jmp_label, tokens[1]);
5790 instr->type = INSTR_JMP_HIT;
5791 instr->jmp.ip = NULL; /* Resolved later. */
5796 instr_jmp_miss_translate(struct rte_swx_pipeline *p __rte_unused,
5797 struct action *action,
5800 struct instruction *instr,
5801 struct instruction_data *data)
5803 CHECK(!action, EINVAL);
5804 CHECK(n_tokens == 2, EINVAL);
5806 strcpy(data->jmp_label, tokens[1]);
5808 instr->type = INSTR_JMP_MISS;
5809 instr->jmp.ip = NULL; /* Resolved later. */
5814 instr_jmp_action_hit_translate(struct rte_swx_pipeline *p,
5815 struct action *action,
5818 struct instruction *instr,
5819 struct instruction_data *data)
5823 CHECK(!action, EINVAL);
5824 CHECK(n_tokens == 3, EINVAL);
5826 strcpy(data->jmp_label, tokens[1]);
5828 a = action_find(p, tokens[2]);
5831 instr->type = INSTR_JMP_ACTION_HIT;
5832 instr->jmp.ip = NULL; /* Resolved later. */
5833 instr->jmp.action_id = a->id;
5838 instr_jmp_action_miss_translate(struct rte_swx_pipeline *p,
5839 struct action *action,
5842 struct instruction *instr,
5843 struct instruction_data *data)
5847 CHECK(!action, EINVAL);
5848 CHECK(n_tokens == 3, EINVAL);
5850 strcpy(data->jmp_label, tokens[1]);
5852 a = action_find(p, tokens[2]);
5855 instr->type = INSTR_JMP_ACTION_MISS;
5856 instr->jmp.ip = NULL; /* Resolved later. */
5857 instr->jmp.action_id = a->id;
5862 instr_jmp_eq_translate(struct rte_swx_pipeline *p,
5863 struct action *action,
5866 struct instruction *instr,
5867 struct instruction_data *data)
5869 char *a = tokens[2], *b = tokens[3];
5870 struct field *fa, *fb;
5872 uint32_t a_struct_id, b_struct_id;
5874 CHECK(n_tokens == 4, EINVAL);
5876 strcpy(data->jmp_label, tokens[1]);
5878 fa = struct_field_parse(p, action, a, &a_struct_id);
5880 CHECK(!fa->var_size, EINVAL);
5882 /* JMP_EQ, JMP_EQ_MH, JMP_EQ_HM, JMP_EQ_HH. */
5883 fb = struct_field_parse(p, action, b, &b_struct_id);
5885 CHECK(!fb->var_size, EINVAL);
5887 instr->type = INSTR_JMP_EQ;
5888 if (a[0] != 'h' && b[0] == 'h')
5889 instr->type = INSTR_JMP_EQ_MH;
5890 if (a[0] == 'h' && b[0] != 'h')
5891 instr->type = INSTR_JMP_EQ_HM;
5892 if (a[0] == 'h' && b[0] == 'h')
5893 instr->type = INSTR_JMP_EQ_HH;
5894 instr->jmp.ip = NULL; /* Resolved later. */
5896 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5897 instr->jmp.a.n_bits = fa->n_bits;
5898 instr->jmp.a.offset = fa->offset / 8;
5899 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5900 instr->jmp.b.n_bits = fb->n_bits;
5901 instr->jmp.b.offset = fb->offset / 8;
5906 b_val = strtoull(b, &b, 0);
5907 CHECK(!b[0], EINVAL);
5910 b_val = hton64(b_val) >> (64 - fa->n_bits);
5912 instr->type = INSTR_JMP_EQ_I;
5913 instr->jmp.ip = NULL; /* Resolved later. */
5914 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5915 instr->jmp.a.n_bits = fa->n_bits;
5916 instr->jmp.a.offset = fa->offset / 8;
5917 instr->jmp.b_val = b_val;
5922 instr_jmp_neq_translate(struct rte_swx_pipeline *p,
5923 struct action *action,
5926 struct instruction *instr,
5927 struct instruction_data *data)
5929 char *a = tokens[2], *b = tokens[3];
5930 struct field *fa, *fb;
5932 uint32_t a_struct_id, b_struct_id;
5934 CHECK(n_tokens == 4, EINVAL);
5936 strcpy(data->jmp_label, tokens[1]);
5938 fa = struct_field_parse(p, action, a, &a_struct_id);
5940 CHECK(!fa->var_size, EINVAL);
5942 /* JMP_NEQ, JMP_NEQ_MH, JMP_NEQ_HM, JMP_NEQ_HH. */
5943 fb = struct_field_parse(p, action, b, &b_struct_id);
5945 CHECK(!fb->var_size, EINVAL);
5947 instr->type = INSTR_JMP_NEQ;
5948 if (a[0] != 'h' && b[0] == 'h')
5949 instr->type = INSTR_JMP_NEQ_MH;
5950 if (a[0] == 'h' && b[0] != 'h')
5951 instr->type = INSTR_JMP_NEQ_HM;
5952 if (a[0] == 'h' && b[0] == 'h')
5953 instr->type = INSTR_JMP_NEQ_HH;
5954 instr->jmp.ip = NULL; /* Resolved later. */
5956 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5957 instr->jmp.a.n_bits = fa->n_bits;
5958 instr->jmp.a.offset = fa->offset / 8;
5959 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5960 instr->jmp.b.n_bits = fb->n_bits;
5961 instr->jmp.b.offset = fb->offset / 8;
5966 b_val = strtoull(b, &b, 0);
5967 CHECK(!b[0], EINVAL);
5970 b_val = hton64(b_val) >> (64 - fa->n_bits);
5972 instr->type = INSTR_JMP_NEQ_I;
5973 instr->jmp.ip = NULL; /* Resolved later. */
5974 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5975 instr->jmp.a.n_bits = fa->n_bits;
5976 instr->jmp.a.offset = fa->offset / 8;
5977 instr->jmp.b_val = b_val;
5982 instr_jmp_lt_translate(struct rte_swx_pipeline *p,
5983 struct action *action,
5986 struct instruction *instr,
5987 struct instruction_data *data)
5989 char *a = tokens[2], *b = tokens[3];
5990 struct field *fa, *fb;
5992 uint32_t a_struct_id, b_struct_id;
5994 CHECK(n_tokens == 4, EINVAL);
5996 strcpy(data->jmp_label, tokens[1]);
5998 fa = struct_field_parse(p, action, a, &a_struct_id);
6000 CHECK(!fa->var_size, EINVAL);
6002 /* JMP_LT, JMP_LT_MH, JMP_LT_HM, JMP_LT_HH. */
6003 fb = struct_field_parse(p, action, b, &b_struct_id);
6005 CHECK(!fb->var_size, EINVAL);
6007 instr->type = INSTR_JMP_LT;
6008 if (a[0] == 'h' && b[0] != 'h')
6009 instr->type = INSTR_JMP_LT_HM;
6010 if (a[0] != 'h' && b[0] == 'h')
6011 instr->type = INSTR_JMP_LT_MH;
6012 if (a[0] == 'h' && b[0] == 'h')
6013 instr->type = INSTR_JMP_LT_HH;
6014 instr->jmp.ip = NULL; /* Resolved later. */
6016 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6017 instr->jmp.a.n_bits = fa->n_bits;
6018 instr->jmp.a.offset = fa->offset / 8;
6019 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6020 instr->jmp.b.n_bits = fb->n_bits;
6021 instr->jmp.b.offset = fb->offset / 8;
6025 /* JMP_LT_MI, JMP_LT_HI. */
6026 b_val = strtoull(b, &b, 0);
6027 CHECK(!b[0], EINVAL);
6029 instr->type = INSTR_JMP_LT_MI;
6031 instr->type = INSTR_JMP_LT_HI;
6032 instr->jmp.ip = NULL; /* Resolved later. */
6034 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6035 instr->jmp.a.n_bits = fa->n_bits;
6036 instr->jmp.a.offset = fa->offset / 8;
6037 instr->jmp.b_val = b_val;
6042 instr_jmp_gt_translate(struct rte_swx_pipeline *p,
6043 struct action *action,
6046 struct instruction *instr,
6047 struct instruction_data *data)
6049 char *a = tokens[2], *b = tokens[3];
6050 struct field *fa, *fb;
6052 uint32_t a_struct_id, b_struct_id;
6054 CHECK(n_tokens == 4, EINVAL);
6056 strcpy(data->jmp_label, tokens[1]);
6058 fa = struct_field_parse(p, action, a, &a_struct_id);
6060 CHECK(!fa->var_size, EINVAL);
6062 /* JMP_GT, JMP_GT_MH, JMP_GT_HM, JMP_GT_HH. */
6063 fb = struct_field_parse(p, action, b, &b_struct_id);
6065 CHECK(!fb->var_size, EINVAL);
6067 instr->type = INSTR_JMP_GT;
6068 if (a[0] == 'h' && b[0] != 'h')
6069 instr->type = INSTR_JMP_GT_HM;
6070 if (a[0] != 'h' && b[0] == 'h')
6071 instr->type = INSTR_JMP_GT_MH;
6072 if (a[0] == 'h' && b[0] == 'h')
6073 instr->type = INSTR_JMP_GT_HH;
6074 instr->jmp.ip = NULL; /* Resolved later. */
6076 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6077 instr->jmp.a.n_bits = fa->n_bits;
6078 instr->jmp.a.offset = fa->offset / 8;
6079 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6080 instr->jmp.b.n_bits = fb->n_bits;
6081 instr->jmp.b.offset = fb->offset / 8;
6085 /* JMP_GT_MI, JMP_GT_HI. */
6086 b_val = strtoull(b, &b, 0);
6087 CHECK(!b[0], EINVAL);
6089 instr->type = INSTR_JMP_GT_MI;
6091 instr->type = INSTR_JMP_GT_HI;
6092 instr->jmp.ip = NULL; /* Resolved later. */
6094 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6095 instr->jmp.a.n_bits = fa->n_bits;
6096 instr->jmp.a.offset = fa->offset / 8;
6097 instr->jmp.b_val = b_val;
6102 instr_jmp_exec(struct rte_swx_pipeline *p)
6104 struct thread *t = &p->threads[p->thread_id];
6105 struct instruction *ip = t->ip;
6107 TRACE("[Thread %2u] jmp\n", p->thread_id);
6109 thread_ip_set(t, ip->jmp.ip);
6113 instr_jmp_valid_exec(struct rte_swx_pipeline *p)
6115 struct thread *t = &p->threads[p->thread_id];
6116 struct instruction *ip = t->ip;
6117 uint32_t header_id = ip->jmp.header_id;
6119 TRACE("[Thread %2u] jmpv\n", p->thread_id);
6121 t->ip = HEADER_VALID(t, header_id) ? ip->jmp.ip : (t->ip + 1);
6125 instr_jmp_invalid_exec(struct rte_swx_pipeline *p)
6127 struct thread *t = &p->threads[p->thread_id];
6128 struct instruction *ip = t->ip;
6129 uint32_t header_id = ip->jmp.header_id;
6131 TRACE("[Thread %2u] jmpnv\n", p->thread_id);
6133 t->ip = HEADER_VALID(t, header_id) ? (t->ip + 1) : ip->jmp.ip;
6137 instr_jmp_hit_exec(struct rte_swx_pipeline *p)
6139 struct thread *t = &p->threads[p->thread_id];
6140 struct instruction *ip = t->ip;
6141 struct instruction *ip_next[] = {t->ip + 1, ip->jmp.ip};
6143 TRACE("[Thread %2u] jmph\n", p->thread_id);
6145 t->ip = ip_next[t->hit];
6149 instr_jmp_miss_exec(struct rte_swx_pipeline *p)
6151 struct thread *t = &p->threads[p->thread_id];
6152 struct instruction *ip = t->ip;
6153 struct instruction *ip_next[] = {ip->jmp.ip, t->ip + 1};
6155 TRACE("[Thread %2u] jmpnh\n", p->thread_id);
6157 t->ip = ip_next[t->hit];
6161 instr_jmp_action_hit_exec(struct rte_swx_pipeline *p)
6163 struct thread *t = &p->threads[p->thread_id];
6164 struct instruction *ip = t->ip;
6166 TRACE("[Thread %2u] jmpa\n", p->thread_id);
6168 t->ip = (ip->jmp.action_id == t->action_id) ? ip->jmp.ip : (t->ip + 1);
6172 instr_jmp_action_miss_exec(struct rte_swx_pipeline *p)
6174 struct thread *t = &p->threads[p->thread_id];
6175 struct instruction *ip = t->ip;
6177 TRACE("[Thread %2u] jmpna\n", p->thread_id);
6179 t->ip = (ip->jmp.action_id == t->action_id) ? (t->ip + 1) : ip->jmp.ip;
6183 instr_jmp_eq_exec(struct rte_swx_pipeline *p)
6185 struct thread *t = &p->threads[p->thread_id];
6186 struct instruction *ip = t->ip;
6188 TRACE("[Thread %2u] jmpeq\n", p->thread_id);
6194 instr_jmp_eq_mh_exec(struct rte_swx_pipeline *p)
6196 struct thread *t = &p->threads[p->thread_id];
6197 struct instruction *ip = t->ip;
6199 TRACE("[Thread %2u] jmpeq (mh)\n", p->thread_id);
6201 JMP_CMP_MH(t, ip, ==);
6205 instr_jmp_eq_hm_exec(struct rte_swx_pipeline *p)
6207 struct thread *t = &p->threads[p->thread_id];
6208 struct instruction *ip = t->ip;
6210 TRACE("[Thread %2u] jmpeq (hm)\n", p->thread_id);
6212 JMP_CMP_HM(t, ip, ==);
6216 instr_jmp_eq_hh_exec(struct rte_swx_pipeline *p)
6218 struct thread *t = &p->threads[p->thread_id];
6219 struct instruction *ip = t->ip;
6221 TRACE("[Thread %2u] jmpeq (hh)\n", p->thread_id);
6223 JMP_CMP_HH_FAST(t, ip, ==);
6227 instr_jmp_eq_i_exec(struct rte_swx_pipeline *p)
6229 struct thread *t = &p->threads[p->thread_id];
6230 struct instruction *ip = t->ip;
6232 TRACE("[Thread %2u] jmpeq (i)\n", p->thread_id);
6234 JMP_CMP_I(t, ip, ==);
6238 instr_jmp_neq_exec(struct rte_swx_pipeline *p)
6240 struct thread *t = &p->threads[p->thread_id];
6241 struct instruction *ip = t->ip;
6243 TRACE("[Thread %2u] jmpneq\n", p->thread_id);
6249 instr_jmp_neq_mh_exec(struct rte_swx_pipeline *p)
6251 struct thread *t = &p->threads[p->thread_id];
6252 struct instruction *ip = t->ip;
6254 TRACE("[Thread %2u] jmpneq (mh)\n", p->thread_id);
6256 JMP_CMP_MH(t, ip, !=);
6260 instr_jmp_neq_hm_exec(struct rte_swx_pipeline *p)
6262 struct thread *t = &p->threads[p->thread_id];
6263 struct instruction *ip = t->ip;
6265 TRACE("[Thread %2u] jmpneq (hm)\n", p->thread_id);
6267 JMP_CMP_HM(t, ip, !=);
6271 instr_jmp_neq_hh_exec(struct rte_swx_pipeline *p)
6273 struct thread *t = &p->threads[p->thread_id];
6274 struct instruction *ip = t->ip;
6276 TRACE("[Thread %2u] jmpneq (hh)\n", p->thread_id);
6278 JMP_CMP_HH_FAST(t, ip, !=);
6282 instr_jmp_neq_i_exec(struct rte_swx_pipeline *p)
6284 struct thread *t = &p->threads[p->thread_id];
6285 struct instruction *ip = t->ip;
6287 TRACE("[Thread %2u] jmpneq (i)\n", p->thread_id);
6289 JMP_CMP_I(t, ip, !=);
6293 instr_jmp_lt_exec(struct rte_swx_pipeline *p)
6295 struct thread *t = &p->threads[p->thread_id];
6296 struct instruction *ip = t->ip;
6298 TRACE("[Thread %2u] jmplt\n", p->thread_id);
6304 instr_jmp_lt_mh_exec(struct rte_swx_pipeline *p)
6306 struct thread *t = &p->threads[p->thread_id];
6307 struct instruction *ip = t->ip;
6309 TRACE("[Thread %2u] jmplt (mh)\n", p->thread_id);
6311 JMP_CMP_MH(t, ip, <);
6315 instr_jmp_lt_hm_exec(struct rte_swx_pipeline *p)
6317 struct thread *t = &p->threads[p->thread_id];
6318 struct instruction *ip = t->ip;
6320 TRACE("[Thread %2u] jmplt (hm)\n", p->thread_id);
6322 JMP_CMP_HM(t, ip, <);
6326 instr_jmp_lt_hh_exec(struct rte_swx_pipeline *p)
6328 struct thread *t = &p->threads[p->thread_id];
6329 struct instruction *ip = t->ip;
6331 TRACE("[Thread %2u] jmplt (hh)\n", p->thread_id);
6333 JMP_CMP_HH(t, ip, <);
6337 instr_jmp_lt_mi_exec(struct rte_swx_pipeline *p)
6339 struct thread *t = &p->threads[p->thread_id];
6340 struct instruction *ip = t->ip;
6342 TRACE("[Thread %2u] jmplt (mi)\n", p->thread_id);
6344 JMP_CMP_MI(t, ip, <);
6348 instr_jmp_lt_hi_exec(struct rte_swx_pipeline *p)
6350 struct thread *t = &p->threads[p->thread_id];
6351 struct instruction *ip = t->ip;
6353 TRACE("[Thread %2u] jmplt (hi)\n", p->thread_id);
6355 JMP_CMP_HI(t, ip, <);
6359 instr_jmp_gt_exec(struct rte_swx_pipeline *p)
6361 struct thread *t = &p->threads[p->thread_id];
6362 struct instruction *ip = t->ip;
6364 TRACE("[Thread %2u] jmpgt\n", p->thread_id);
6370 instr_jmp_gt_mh_exec(struct rte_swx_pipeline *p)
6372 struct thread *t = &p->threads[p->thread_id];
6373 struct instruction *ip = t->ip;
6375 TRACE("[Thread %2u] jmpgt (mh)\n", p->thread_id);
6377 JMP_CMP_MH(t, ip, >);
6381 instr_jmp_gt_hm_exec(struct rte_swx_pipeline *p)
6383 struct thread *t = &p->threads[p->thread_id];
6384 struct instruction *ip = t->ip;
6386 TRACE("[Thread %2u] jmpgt (hm)\n", p->thread_id);
6388 JMP_CMP_HM(t, ip, >);
6392 instr_jmp_gt_hh_exec(struct rte_swx_pipeline *p)
6394 struct thread *t = &p->threads[p->thread_id];
6395 struct instruction *ip = t->ip;
6397 TRACE("[Thread %2u] jmpgt (hh)\n", p->thread_id);
6399 JMP_CMP_HH(t, ip, >);
6403 instr_jmp_gt_mi_exec(struct rte_swx_pipeline *p)
6405 struct thread *t = &p->threads[p->thread_id];
6406 struct instruction *ip = t->ip;
6408 TRACE("[Thread %2u] jmpgt (mi)\n", p->thread_id);
6410 JMP_CMP_MI(t, ip, >);
6414 instr_jmp_gt_hi_exec(struct rte_swx_pipeline *p)
6416 struct thread *t = &p->threads[p->thread_id];
6417 struct instruction *ip = t->ip;
6419 TRACE("[Thread %2u] jmpgt (hi)\n", p->thread_id);
6421 JMP_CMP_HI(t, ip, >);
6428 instr_return_translate(struct rte_swx_pipeline *p __rte_unused,
6429 struct action *action,
6430 char **tokens __rte_unused,
6432 struct instruction *instr,
6433 struct instruction_data *data __rte_unused)
6435 CHECK(action, EINVAL);
6436 CHECK(n_tokens == 1, EINVAL);
6438 instr->type = INSTR_RETURN;
6443 instr_return_exec(struct rte_swx_pipeline *p)
6445 struct thread *t = &p->threads[p->thread_id];
6447 TRACE("[Thread %2u] return\n", p->thread_id);
6453 instr_translate(struct rte_swx_pipeline *p,
6454 struct action *action,
6456 struct instruction *instr,
6457 struct instruction_data *data)
6459 char *tokens[RTE_SWX_INSTRUCTION_TOKENS_MAX];
6460 int n_tokens = 0, tpos = 0;
6462 /* Parse the instruction string into tokens. */
6466 token = strtok_r(string, " \t\v", &string);
6470 CHECK(n_tokens < RTE_SWX_INSTRUCTION_TOKENS_MAX, EINVAL);
6471 CHECK_NAME(token, EINVAL);
6473 tokens[n_tokens] = token;
6477 CHECK(n_tokens, EINVAL);
6479 /* Handle the optional instruction label. */
6480 if ((n_tokens >= 2) && !strcmp(tokens[1], ":")) {
6481 strcpy(data->label, tokens[0]);
6484 CHECK(n_tokens - tpos, EINVAL);
6487 /* Identify the instruction type. */
6488 if (!strcmp(tokens[tpos], "rx"))
6489 return instr_rx_translate(p,
6496 if (!strcmp(tokens[tpos], "tx"))
6497 return instr_tx_translate(p,
6504 if (!strcmp(tokens[tpos], "drop"))
6505 return instr_drop_translate(p,
6512 if (!strcmp(tokens[tpos], "extract"))
6513 return instr_hdr_extract_translate(p,
6520 if (!strcmp(tokens[tpos], "lookahead"))
6521 return instr_hdr_lookahead_translate(p,
6528 if (!strcmp(tokens[tpos], "emit"))
6529 return instr_hdr_emit_translate(p,
6536 if (!strcmp(tokens[tpos], "validate"))
6537 return instr_hdr_validate_translate(p,
6544 if (!strcmp(tokens[tpos], "invalidate"))
6545 return instr_hdr_invalidate_translate(p,
6552 if (!strcmp(tokens[tpos], "mov"))
6553 return instr_mov_translate(p,
6560 if (!strcmp(tokens[tpos], "add"))
6561 return instr_alu_add_translate(p,
6568 if (!strcmp(tokens[tpos], "sub"))
6569 return instr_alu_sub_translate(p,
6576 if (!strcmp(tokens[tpos], "ckadd"))
6577 return instr_alu_ckadd_translate(p,
6584 if (!strcmp(tokens[tpos], "cksub"))
6585 return instr_alu_cksub_translate(p,
6592 if (!strcmp(tokens[tpos], "and"))
6593 return instr_alu_and_translate(p,
6600 if (!strcmp(tokens[tpos], "or"))
6601 return instr_alu_or_translate(p,
6608 if (!strcmp(tokens[tpos], "xor"))
6609 return instr_alu_xor_translate(p,
6616 if (!strcmp(tokens[tpos], "shl"))
6617 return instr_alu_shl_translate(p,
6624 if (!strcmp(tokens[tpos], "shr"))
6625 return instr_alu_shr_translate(p,
6632 if (!strcmp(tokens[tpos], "regprefetch"))
6633 return instr_regprefetch_translate(p,
6640 if (!strcmp(tokens[tpos], "regrd"))
6641 return instr_regrd_translate(p,
6648 if (!strcmp(tokens[tpos], "regwr"))
6649 return instr_regwr_translate(p,
6656 if (!strcmp(tokens[tpos], "regadd"))
6657 return instr_regadd_translate(p,
6664 if (!strcmp(tokens[tpos], "metprefetch"))
6665 return instr_metprefetch_translate(p,
6672 if (!strcmp(tokens[tpos], "meter"))
6673 return instr_meter_translate(p,
6680 if (!strcmp(tokens[tpos], "table"))
6681 return instr_table_translate(p,
6688 if (!strcmp(tokens[tpos], "learn"))
6689 return instr_learn_translate(p,
6696 if (!strcmp(tokens[tpos], "forget"))
6697 return instr_forget_translate(p,
6704 if (!strcmp(tokens[tpos], "extern"))
6705 return instr_extern_translate(p,
6712 if (!strcmp(tokens[tpos], "jmp"))
6713 return instr_jmp_translate(p,
6720 if (!strcmp(tokens[tpos], "jmpv"))
6721 return instr_jmp_valid_translate(p,
6728 if (!strcmp(tokens[tpos], "jmpnv"))
6729 return instr_jmp_invalid_translate(p,
6736 if (!strcmp(tokens[tpos], "jmph"))
6737 return instr_jmp_hit_translate(p,
6744 if (!strcmp(tokens[tpos], "jmpnh"))
6745 return instr_jmp_miss_translate(p,
6752 if (!strcmp(tokens[tpos], "jmpa"))
6753 return instr_jmp_action_hit_translate(p,
6760 if (!strcmp(tokens[tpos], "jmpna"))
6761 return instr_jmp_action_miss_translate(p,
6768 if (!strcmp(tokens[tpos], "jmpeq"))
6769 return instr_jmp_eq_translate(p,
6776 if (!strcmp(tokens[tpos], "jmpneq"))
6777 return instr_jmp_neq_translate(p,
6784 if (!strcmp(tokens[tpos], "jmplt"))
6785 return instr_jmp_lt_translate(p,
6792 if (!strcmp(tokens[tpos], "jmpgt"))
6793 return instr_jmp_gt_translate(p,
6800 if (!strcmp(tokens[tpos], "return"))
6801 return instr_return_translate(p,
6811 static struct instruction_data *
6812 label_find(struct instruction_data *data, uint32_t n, const char *label)
6816 for (i = 0; i < n; i++)
6817 if (!strcmp(label, data[i].label))
6824 label_is_used(struct instruction_data *data, uint32_t n, const char *label)
6826 uint32_t count = 0, i;
6831 for (i = 0; i < n; i++)
6832 if (!strcmp(label, data[i].jmp_label))
6839 instr_label_check(struct instruction_data *instruction_data,
6840 uint32_t n_instructions)
6844 /* Check that all instruction labels are unique. */
6845 for (i = 0; i < n_instructions; i++) {
6846 struct instruction_data *data = &instruction_data[i];
6847 char *label = data->label;
6853 for (j = i + 1; j < n_instructions; j++)
6854 CHECK(strcmp(label, data[j].label), EINVAL);
6857 /* Get users for each instruction label. */
6858 for (i = 0; i < n_instructions; i++) {
6859 struct instruction_data *data = &instruction_data[i];
6860 char *label = data->label;
6862 data->n_users = label_is_used(instruction_data,
6871 instr_jmp_resolve(struct instruction *instructions,
6872 struct instruction_data *instruction_data,
6873 uint32_t n_instructions)
6877 for (i = 0; i < n_instructions; i++) {
6878 struct instruction *instr = &instructions[i];
6879 struct instruction_data *data = &instruction_data[i];
6880 struct instruction_data *found;
6882 if (!instruction_is_jmp(instr))
6885 found = label_find(instruction_data,
6888 CHECK(found, EINVAL);
6890 instr->jmp.ip = &instructions[found - instruction_data];
6897 instr_verify(struct rte_swx_pipeline *p __rte_unused,
6899 struct instruction *instr,
6900 struct instruction_data *data __rte_unused,
6901 uint32_t n_instructions)
6904 enum instruction_type type;
6907 /* Check that the first instruction is rx. */
6908 CHECK(instr[0].type == INSTR_RX, EINVAL);
6910 /* Check that there is at least one tx instruction. */
6911 for (i = 0; i < n_instructions; i++) {
6912 type = instr[i].type;
6914 if (instruction_is_tx(type))
6917 CHECK(i < n_instructions, EINVAL);
6919 /* Check that the last instruction is either tx or unconditional
6922 type = instr[n_instructions - 1].type;
6923 CHECK(instruction_is_tx(type) || (type == INSTR_JMP), EINVAL);
6927 enum instruction_type type;
6930 /* Check that there is at least one return or tx instruction. */
6931 for (i = 0; i < n_instructions; i++) {
6932 type = instr[i].type;
6934 if ((type == INSTR_RETURN) || instruction_is_tx(type))
6937 CHECK(i < n_instructions, EINVAL);
6944 instr_compact(struct instruction *instructions,
6945 struct instruction_data *instruction_data,
6946 uint32_t n_instructions)
6948 uint32_t i, pos = 0;
6950 /* Eliminate the invalid instructions that have been optimized out. */
6951 for (i = 0; i < n_instructions; i++) {
6952 struct instruction *instr = &instructions[i];
6953 struct instruction_data *data = &instruction_data[i];
6959 memcpy(&instructions[pos], instr, sizeof(*instr));
6960 memcpy(&instruction_data[pos], data, sizeof(*data));
6970 instr_pattern_extract_many_search(struct instruction *instr,
6971 struct instruction_data *data,
6973 uint32_t *n_pattern_instr)
6977 for (i = 0; i < n_instr; i++) {
6978 if (data[i].invalid)
6981 if (instr[i].type != INSTR_HDR_EXTRACT)
6984 if (i == RTE_DIM(instr->io.hdr.header_id))
6987 if (i && data[i].n_users)
6994 *n_pattern_instr = i;
6999 instr_pattern_extract_many_replace(struct instruction *instr,
7000 struct instruction_data *data,
7005 for (i = 1; i < n_instr; i++) {
7007 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
7008 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
7009 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
7011 data[i].invalid = 1;
7016 instr_pattern_extract_many_optimize(struct instruction *instructions,
7017 struct instruction_data *instruction_data,
7018 uint32_t n_instructions)
7022 for (i = 0; i < n_instructions; ) {
7023 struct instruction *instr = &instructions[i];
7024 struct instruction_data *data = &instruction_data[i];
7025 uint32_t n_instr = 0;
7029 detected = instr_pattern_extract_many_search(instr,
7034 instr_pattern_extract_many_replace(instr,
7041 /* No pattern starting at the current instruction. */
7045 /* Eliminate the invalid instructions that have been optimized out. */
7046 n_instructions = instr_compact(instructions,
7050 return n_instructions;
7054 instr_pattern_emit_many_tx_search(struct instruction *instr,
7055 struct instruction_data *data,
7057 uint32_t *n_pattern_instr)
7061 for (i = 0; i < n_instr; i++) {
7062 if (data[i].invalid)
7065 if (instr[i].type != INSTR_HDR_EMIT)
7068 if (i == RTE_DIM(instr->io.hdr.header_id))
7071 if (i && data[i].n_users)
7078 if (!instruction_is_tx(instr[i].type))
7081 if (data[i].n_users)
7086 *n_pattern_instr = i;
7091 instr_pattern_emit_many_tx_replace(struct instruction *instr,
7092 struct instruction_data *data,
7097 /* Any emit instruction in addition to the first one. */
7098 for (i = 1; i < n_instr - 1; i++) {
7100 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
7101 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
7102 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
7104 data[i].invalid = 1;
7107 /* The TX instruction is the last one in the pattern. */
7109 instr[0].io.io.offset = instr[i].io.io.offset;
7110 instr[0].io.io.n_bits = instr[i].io.io.n_bits;
7111 data[i].invalid = 1;
7115 instr_pattern_emit_many_tx_optimize(struct instruction *instructions,
7116 struct instruction_data *instruction_data,
7117 uint32_t n_instructions)
7121 for (i = 0; i < n_instructions; ) {
7122 struct instruction *instr = &instructions[i];
7123 struct instruction_data *data = &instruction_data[i];
7124 uint32_t n_instr = 0;
7127 /* Emit many + TX. */
7128 detected = instr_pattern_emit_many_tx_search(instr,
7133 instr_pattern_emit_many_tx_replace(instr,
7140 /* No pattern starting at the current instruction. */
7144 /* Eliminate the invalid instructions that have been optimized out. */
7145 n_instructions = instr_compact(instructions,
7149 return n_instructions;
7153 action_arg_src_mov_count(struct action *a,
7155 struct instruction *instructions,
7156 struct instruction_data *instruction_data,
7157 uint32_t n_instructions);
7160 instr_pattern_mov_all_validate_search(struct rte_swx_pipeline *p,
7162 struct instruction *instr,
7163 struct instruction_data *data,
7165 struct instruction *instructions,
7166 struct instruction_data *instruction_data,
7167 uint32_t n_instructions,
7168 uint32_t *n_pattern_instr)
7171 uint32_t src_field_id, i, j;
7173 /* Prerequisites. */
7177 /* First instruction: MOV_HM. */
7178 if (data[0].invalid || (instr[0].type != INSTR_MOV_HM))
7181 h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
7182 if (!h || h->st->var_size)
7185 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
7186 if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
7189 if (src_field_id == a->st->n_fields)
7192 if (instr[0].mov.dst.offset ||
7193 (instr[0].mov.dst.n_bits != h->st->fields[0].n_bits) ||
7194 instr[0].mov.src.struct_id ||
7195 (instr[0].mov.src.n_bits != a->st->fields[src_field_id].n_bits) ||
7196 (instr[0].mov.dst.n_bits != instr[0].mov.src.n_bits))
7199 if ((n_instr < h->st->n_fields + 1) ||
7200 (a->st->n_fields < src_field_id + h->st->n_fields + 1))
7203 /* Subsequent instructions: MOV_HM. */
7204 for (i = 1; i < h->st->n_fields; i++)
7205 if (data[i].invalid ||
7207 (instr[i].type != INSTR_MOV_HM) ||
7208 (instr[i].mov.dst.struct_id != h->struct_id) ||
7209 (instr[i].mov.dst.offset != h->st->fields[i].offset / 8) ||
7210 (instr[i].mov.dst.n_bits != h->st->fields[i].n_bits) ||
7211 instr[i].mov.src.struct_id ||
7212 (instr[i].mov.src.offset != a->st->fields[src_field_id + i].offset / 8) ||
7213 (instr[i].mov.src.n_bits != a->st->fields[src_field_id + i].n_bits) ||
7214 (instr[i].mov.dst.n_bits != instr[i].mov.src.n_bits))
7217 /* Last instruction: HDR_VALIDATE. */
7218 if ((instr[i].type != INSTR_HDR_VALIDATE) ||
7219 (instr[i].valid.header_id != h->id))
7222 /* Check that none of the action args that are used as source for this
7223 * DMA transfer are not used as source in any other mov instruction.
7225 for (j = src_field_id; j < src_field_id + h->st->n_fields; j++) {
7228 n_users = action_arg_src_mov_count(a,
7237 *n_pattern_instr = 1 + i;
7242 instr_pattern_mov_all_validate_replace(struct rte_swx_pipeline *p,
7244 struct instruction *instr,
7245 struct instruction_data *data,
7249 uint32_t src_field_id, src_offset, i;
7251 /* Read from the instructions before they are modified. */
7252 h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
7256 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
7257 if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
7260 if (src_field_id == a->st->n_fields)
7263 src_offset = instr[0].mov.src.offset;
7265 /* Modify the instructions. */
7266 instr[0].type = INSTR_DMA_HT;
7267 instr[0].dma.dst.header_id[0] = h->id;
7268 instr[0].dma.dst.struct_id[0] = h->struct_id;
7269 instr[0].dma.src.offset[0] = (uint8_t)src_offset;
7270 instr[0].dma.n_bytes[0] = h->st->n_bits / 8;
7272 for (i = 1; i < n_instr; i++)
7273 data[i].invalid = 1;
7275 /* Update the endianness of the action arguments to header endianness. */
7276 for (i = 0; i < h->st->n_fields; i++)
7277 a->args_endianness[src_field_id + i] = 1;
7281 instr_pattern_mov_all_validate_optimize(struct rte_swx_pipeline *p,
7283 struct instruction *instructions,
7284 struct instruction_data *instruction_data,
7285 uint32_t n_instructions)
7290 return n_instructions;
7292 for (i = 0; i < n_instructions; ) {
7293 struct instruction *instr = &instructions[i];
7294 struct instruction_data *data = &instruction_data[i];
7295 uint32_t n_instr = 0;
7298 /* Mov all + validate. */
7299 detected = instr_pattern_mov_all_validate_search(p,
7309 instr_pattern_mov_all_validate_replace(p, a, instr, data, n_instr);
7314 /* No pattern starting at the current instruction. */
7318 /* Eliminate the invalid instructions that have been optimized out. */
7319 n_instructions = instr_compact(instructions,
7323 return n_instructions;
7327 instr_pattern_dma_many_search(struct instruction *instr,
7328 struct instruction_data *data,
7330 uint32_t *n_pattern_instr)
7334 for (i = 0; i < n_instr; i++) {
7335 if (data[i].invalid)
7338 if (instr[i].type != INSTR_DMA_HT)
7341 if (i == RTE_DIM(instr->dma.dst.header_id))
7344 if (i && data[i].n_users)
7351 *n_pattern_instr = i;
7356 instr_pattern_dma_many_replace(struct instruction *instr,
7357 struct instruction_data *data,
7362 for (i = 1; i < n_instr; i++) {
7364 instr[0].dma.dst.header_id[i] = instr[i].dma.dst.header_id[0];
7365 instr[0].dma.dst.struct_id[i] = instr[i].dma.dst.struct_id[0];
7366 instr[0].dma.src.offset[i] = instr[i].dma.src.offset[0];
7367 instr[0].dma.n_bytes[i] = instr[i].dma.n_bytes[0];
7369 data[i].invalid = 1;
7374 instr_pattern_dma_many_optimize(struct instruction *instructions,
7375 struct instruction_data *instruction_data,
7376 uint32_t n_instructions)
7380 for (i = 0; i < n_instructions; ) {
7381 struct instruction *instr = &instructions[i];
7382 struct instruction_data *data = &instruction_data[i];
7383 uint32_t n_instr = 0;
7387 detected = instr_pattern_dma_many_search(instr,
7392 instr_pattern_dma_many_replace(instr, data, n_instr);
7397 /* No pattern starting at the current instruction. */
7401 /* Eliminate the invalid instructions that have been optimized out. */
7402 n_instructions = instr_compact(instructions,
7406 return n_instructions;
7410 instr_optimize(struct rte_swx_pipeline *p,
7412 struct instruction *instructions,
7413 struct instruction_data *instruction_data,
7414 uint32_t n_instructions)
7417 n_instructions = instr_pattern_extract_many_optimize(instructions,
7421 /* Emit many + TX. */
7422 n_instructions = instr_pattern_emit_many_tx_optimize(instructions,
7426 /* Mov all + validate. */
7427 n_instructions = instr_pattern_mov_all_validate_optimize(p,
7434 n_instructions = instr_pattern_dma_many_optimize(instructions,
7438 return n_instructions;
7442 instruction_config(struct rte_swx_pipeline *p,
7444 const char **instructions,
7445 uint32_t n_instructions)
7447 struct instruction *instr = NULL;
7448 struct instruction_data *data = NULL;
7452 CHECK(n_instructions, EINVAL);
7453 CHECK(instructions, EINVAL);
7454 for (i = 0; i < n_instructions; i++)
7455 CHECK_INSTRUCTION(instructions[i], EINVAL);
7457 /* Memory allocation. */
7458 instr = calloc(n_instructions, sizeof(struct instruction));
7464 data = calloc(n_instructions, sizeof(struct instruction_data));
7470 for (i = 0; i < n_instructions; i++) {
7471 char *string = strdup(instructions[i]);
7477 err = instr_translate(p, a, string, &instr[i], &data[i]);
7486 err = instr_label_check(data, n_instructions);
7490 err = instr_verify(p, a, instr, data, n_instructions);
7494 n_instructions = instr_optimize(p, a, instr, data, n_instructions);
7496 err = instr_jmp_resolve(instr, data, n_instructions);
7501 a->instructions = instr;
7502 a->n_instructions = n_instructions;
7504 p->instructions = instr;
7505 p->n_instructions = n_instructions;
7517 typedef void (*instr_exec_t)(struct rte_swx_pipeline *);
7519 static instr_exec_t instruction_table[] = {
7520 [INSTR_RX] = instr_rx_exec,
7521 [INSTR_TX] = instr_tx_exec,
7522 [INSTR_TX_I] = instr_tx_i_exec,
7524 [INSTR_HDR_EXTRACT] = instr_hdr_extract_exec,
7525 [INSTR_HDR_EXTRACT2] = instr_hdr_extract2_exec,
7526 [INSTR_HDR_EXTRACT3] = instr_hdr_extract3_exec,
7527 [INSTR_HDR_EXTRACT4] = instr_hdr_extract4_exec,
7528 [INSTR_HDR_EXTRACT5] = instr_hdr_extract5_exec,
7529 [INSTR_HDR_EXTRACT6] = instr_hdr_extract6_exec,
7530 [INSTR_HDR_EXTRACT7] = instr_hdr_extract7_exec,
7531 [INSTR_HDR_EXTRACT8] = instr_hdr_extract8_exec,
7532 [INSTR_HDR_EXTRACT_M] = instr_hdr_extract_m_exec,
7533 [INSTR_HDR_LOOKAHEAD] = instr_hdr_lookahead_exec,
7535 [INSTR_HDR_EMIT] = instr_hdr_emit_exec,
7536 [INSTR_HDR_EMIT_TX] = instr_hdr_emit_tx_exec,
7537 [INSTR_HDR_EMIT2_TX] = instr_hdr_emit2_tx_exec,
7538 [INSTR_HDR_EMIT3_TX] = instr_hdr_emit3_tx_exec,
7539 [INSTR_HDR_EMIT4_TX] = instr_hdr_emit4_tx_exec,
7540 [INSTR_HDR_EMIT5_TX] = instr_hdr_emit5_tx_exec,
7541 [INSTR_HDR_EMIT6_TX] = instr_hdr_emit6_tx_exec,
7542 [INSTR_HDR_EMIT7_TX] = instr_hdr_emit7_tx_exec,
7543 [INSTR_HDR_EMIT8_TX] = instr_hdr_emit8_tx_exec,
7545 [INSTR_HDR_VALIDATE] = instr_hdr_validate_exec,
7546 [INSTR_HDR_INVALIDATE] = instr_hdr_invalidate_exec,
7548 [INSTR_MOV] = instr_mov_exec,
7549 [INSTR_MOV_MH] = instr_mov_mh_exec,
7550 [INSTR_MOV_HM] = instr_mov_hm_exec,
7551 [INSTR_MOV_HH] = instr_mov_hh_exec,
7552 [INSTR_MOV_I] = instr_mov_i_exec,
7554 [INSTR_DMA_HT] = instr_dma_ht_exec,
7555 [INSTR_DMA_HT2] = instr_dma_ht2_exec,
7556 [INSTR_DMA_HT3] = instr_dma_ht3_exec,
7557 [INSTR_DMA_HT4] = instr_dma_ht4_exec,
7558 [INSTR_DMA_HT5] = instr_dma_ht5_exec,
7559 [INSTR_DMA_HT6] = instr_dma_ht6_exec,
7560 [INSTR_DMA_HT7] = instr_dma_ht7_exec,
7561 [INSTR_DMA_HT8] = instr_dma_ht8_exec,
7563 [INSTR_ALU_ADD] = instr_alu_add_exec,
7564 [INSTR_ALU_ADD_MH] = instr_alu_add_mh_exec,
7565 [INSTR_ALU_ADD_HM] = instr_alu_add_hm_exec,
7566 [INSTR_ALU_ADD_HH] = instr_alu_add_hh_exec,
7567 [INSTR_ALU_ADD_MI] = instr_alu_add_mi_exec,
7568 [INSTR_ALU_ADD_HI] = instr_alu_add_hi_exec,
7570 [INSTR_ALU_SUB] = instr_alu_sub_exec,
7571 [INSTR_ALU_SUB_MH] = instr_alu_sub_mh_exec,
7572 [INSTR_ALU_SUB_HM] = instr_alu_sub_hm_exec,
7573 [INSTR_ALU_SUB_HH] = instr_alu_sub_hh_exec,
7574 [INSTR_ALU_SUB_MI] = instr_alu_sub_mi_exec,
7575 [INSTR_ALU_SUB_HI] = instr_alu_sub_hi_exec,
7577 [INSTR_ALU_CKADD_FIELD] = instr_alu_ckadd_field_exec,
7578 [INSTR_ALU_CKADD_STRUCT] = instr_alu_ckadd_struct_exec,
7579 [INSTR_ALU_CKADD_STRUCT20] = instr_alu_ckadd_struct20_exec,
7580 [INSTR_ALU_CKSUB_FIELD] = instr_alu_cksub_field_exec,
7582 [INSTR_ALU_AND] = instr_alu_and_exec,
7583 [INSTR_ALU_AND_MH] = instr_alu_and_mh_exec,
7584 [INSTR_ALU_AND_HM] = instr_alu_and_hm_exec,
7585 [INSTR_ALU_AND_HH] = instr_alu_and_hh_exec,
7586 [INSTR_ALU_AND_I] = instr_alu_and_i_exec,
7588 [INSTR_ALU_OR] = instr_alu_or_exec,
7589 [INSTR_ALU_OR_MH] = instr_alu_or_mh_exec,
7590 [INSTR_ALU_OR_HM] = instr_alu_or_hm_exec,
7591 [INSTR_ALU_OR_HH] = instr_alu_or_hh_exec,
7592 [INSTR_ALU_OR_I] = instr_alu_or_i_exec,
7594 [INSTR_ALU_XOR] = instr_alu_xor_exec,
7595 [INSTR_ALU_XOR_MH] = instr_alu_xor_mh_exec,
7596 [INSTR_ALU_XOR_HM] = instr_alu_xor_hm_exec,
7597 [INSTR_ALU_XOR_HH] = instr_alu_xor_hh_exec,
7598 [INSTR_ALU_XOR_I] = instr_alu_xor_i_exec,
7600 [INSTR_ALU_SHL] = instr_alu_shl_exec,
7601 [INSTR_ALU_SHL_MH] = instr_alu_shl_mh_exec,
7602 [INSTR_ALU_SHL_HM] = instr_alu_shl_hm_exec,
7603 [INSTR_ALU_SHL_HH] = instr_alu_shl_hh_exec,
7604 [INSTR_ALU_SHL_MI] = instr_alu_shl_mi_exec,
7605 [INSTR_ALU_SHL_HI] = instr_alu_shl_hi_exec,
7607 [INSTR_ALU_SHR] = instr_alu_shr_exec,
7608 [INSTR_ALU_SHR_MH] = instr_alu_shr_mh_exec,
7609 [INSTR_ALU_SHR_HM] = instr_alu_shr_hm_exec,
7610 [INSTR_ALU_SHR_HH] = instr_alu_shr_hh_exec,
7611 [INSTR_ALU_SHR_MI] = instr_alu_shr_mi_exec,
7612 [INSTR_ALU_SHR_HI] = instr_alu_shr_hi_exec,
7614 [INSTR_REGPREFETCH_RH] = instr_regprefetch_rh_exec,
7615 [INSTR_REGPREFETCH_RM] = instr_regprefetch_rm_exec,
7616 [INSTR_REGPREFETCH_RI] = instr_regprefetch_ri_exec,
7618 [INSTR_REGRD_HRH] = instr_regrd_hrh_exec,
7619 [INSTR_REGRD_HRM] = instr_regrd_hrm_exec,
7620 [INSTR_REGRD_MRH] = instr_regrd_mrh_exec,
7621 [INSTR_REGRD_MRM] = instr_regrd_mrm_exec,
7622 [INSTR_REGRD_HRI] = instr_regrd_hri_exec,
7623 [INSTR_REGRD_MRI] = instr_regrd_mri_exec,
7625 [INSTR_REGWR_RHH] = instr_regwr_rhh_exec,
7626 [INSTR_REGWR_RHM] = instr_regwr_rhm_exec,
7627 [INSTR_REGWR_RMH] = instr_regwr_rmh_exec,
7628 [INSTR_REGWR_RMM] = instr_regwr_rmm_exec,
7629 [INSTR_REGWR_RHI] = instr_regwr_rhi_exec,
7630 [INSTR_REGWR_RMI] = instr_regwr_rmi_exec,
7631 [INSTR_REGWR_RIH] = instr_regwr_rih_exec,
7632 [INSTR_REGWR_RIM] = instr_regwr_rim_exec,
7633 [INSTR_REGWR_RII] = instr_regwr_rii_exec,
7635 [INSTR_REGADD_RHH] = instr_regadd_rhh_exec,
7636 [INSTR_REGADD_RHM] = instr_regadd_rhm_exec,
7637 [INSTR_REGADD_RMH] = instr_regadd_rmh_exec,
7638 [INSTR_REGADD_RMM] = instr_regadd_rmm_exec,
7639 [INSTR_REGADD_RHI] = instr_regadd_rhi_exec,
7640 [INSTR_REGADD_RMI] = instr_regadd_rmi_exec,
7641 [INSTR_REGADD_RIH] = instr_regadd_rih_exec,
7642 [INSTR_REGADD_RIM] = instr_regadd_rim_exec,
7643 [INSTR_REGADD_RII] = instr_regadd_rii_exec,
7645 [INSTR_METPREFETCH_H] = instr_metprefetch_h_exec,
7646 [INSTR_METPREFETCH_M] = instr_metprefetch_m_exec,
7647 [INSTR_METPREFETCH_I] = instr_metprefetch_i_exec,
7649 [INSTR_METER_HHM] = instr_meter_hhm_exec,
7650 [INSTR_METER_HHI] = instr_meter_hhi_exec,
7651 [INSTR_METER_HMM] = instr_meter_hmm_exec,
7652 [INSTR_METER_HMI] = instr_meter_hmi_exec,
7653 [INSTR_METER_MHM] = instr_meter_mhm_exec,
7654 [INSTR_METER_MHI] = instr_meter_mhi_exec,
7655 [INSTR_METER_MMM] = instr_meter_mmm_exec,
7656 [INSTR_METER_MMI] = instr_meter_mmi_exec,
7657 [INSTR_METER_IHM] = instr_meter_ihm_exec,
7658 [INSTR_METER_IHI] = instr_meter_ihi_exec,
7659 [INSTR_METER_IMM] = instr_meter_imm_exec,
7660 [INSTR_METER_IMI] = instr_meter_imi_exec,
7662 [INSTR_TABLE] = instr_table_exec,
7663 [INSTR_SELECTOR] = instr_selector_exec,
7664 [INSTR_LEARNER] = instr_learner_exec,
7665 [INSTR_LEARNER_LEARN] = instr_learn_exec,
7666 [INSTR_LEARNER_FORGET] = instr_forget_exec,
7667 [INSTR_EXTERN_OBJ] = instr_extern_obj_exec,
7668 [INSTR_EXTERN_FUNC] = instr_extern_func_exec,
7670 [INSTR_JMP] = instr_jmp_exec,
7671 [INSTR_JMP_VALID] = instr_jmp_valid_exec,
7672 [INSTR_JMP_INVALID] = instr_jmp_invalid_exec,
7673 [INSTR_JMP_HIT] = instr_jmp_hit_exec,
7674 [INSTR_JMP_MISS] = instr_jmp_miss_exec,
7675 [INSTR_JMP_ACTION_HIT] = instr_jmp_action_hit_exec,
7676 [INSTR_JMP_ACTION_MISS] = instr_jmp_action_miss_exec,
7678 [INSTR_JMP_EQ] = instr_jmp_eq_exec,
7679 [INSTR_JMP_EQ_MH] = instr_jmp_eq_mh_exec,
7680 [INSTR_JMP_EQ_HM] = instr_jmp_eq_hm_exec,
7681 [INSTR_JMP_EQ_HH] = instr_jmp_eq_hh_exec,
7682 [INSTR_JMP_EQ_I] = instr_jmp_eq_i_exec,
7684 [INSTR_JMP_NEQ] = instr_jmp_neq_exec,
7685 [INSTR_JMP_NEQ_MH] = instr_jmp_neq_mh_exec,
7686 [INSTR_JMP_NEQ_HM] = instr_jmp_neq_hm_exec,
7687 [INSTR_JMP_NEQ_HH] = instr_jmp_neq_hh_exec,
7688 [INSTR_JMP_NEQ_I] = instr_jmp_neq_i_exec,
7690 [INSTR_JMP_LT] = instr_jmp_lt_exec,
7691 [INSTR_JMP_LT_MH] = instr_jmp_lt_mh_exec,
7692 [INSTR_JMP_LT_HM] = instr_jmp_lt_hm_exec,
7693 [INSTR_JMP_LT_HH] = instr_jmp_lt_hh_exec,
7694 [INSTR_JMP_LT_MI] = instr_jmp_lt_mi_exec,
7695 [INSTR_JMP_LT_HI] = instr_jmp_lt_hi_exec,
7697 [INSTR_JMP_GT] = instr_jmp_gt_exec,
7698 [INSTR_JMP_GT_MH] = instr_jmp_gt_mh_exec,
7699 [INSTR_JMP_GT_HM] = instr_jmp_gt_hm_exec,
7700 [INSTR_JMP_GT_HH] = instr_jmp_gt_hh_exec,
7701 [INSTR_JMP_GT_MI] = instr_jmp_gt_mi_exec,
7702 [INSTR_JMP_GT_HI] = instr_jmp_gt_hi_exec,
7704 [INSTR_RETURN] = instr_return_exec,
7708 instr_exec(struct rte_swx_pipeline *p)
7710 struct thread *t = &p->threads[p->thread_id];
7711 struct instruction *ip = t->ip;
7712 instr_exec_t instr = instruction_table[ip->type];
7720 static struct action *
7721 action_find(struct rte_swx_pipeline *p, const char *name)
7723 struct action *elem;
7728 TAILQ_FOREACH(elem, &p->actions, node)
7729 if (strcmp(elem->name, name) == 0)
7735 static struct action *
7736 action_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7738 struct action *action = NULL;
7740 TAILQ_FOREACH(action, &p->actions, node)
7741 if (action->id == id)
7747 static struct field *
7748 action_field_find(struct action *a, const char *name)
7750 return a->st ? struct_type_field_find(a->st, name) : NULL;
7753 static struct field *
7754 action_field_parse(struct action *action, const char *name)
7756 if (name[0] != 't' || name[1] != '.')
7759 return action_field_find(action, &name[2]);
7763 action_has_nbo_args(struct action *a)
7767 /* Return if the action does not have any args. */
7769 return 0; /* FALSE */
7771 for (i = 0; i < a->st->n_fields; i++)
7772 if (a->args_endianness[i])
7773 return 1; /* TRUE */
7775 return 0; /* FALSE */
7779 action_does_learning(struct action *a)
7783 for (i = 0; i < a->n_instructions; i++)
7784 switch (a->instructions[i].type) {
7785 case INSTR_LEARNER_LEARN:
7786 return 1; /* TRUE */
7788 case INSTR_LEARNER_FORGET:
7789 return 1; /* TRUE */
7795 return 0; /* FALSE */
7799 rte_swx_pipeline_action_config(struct rte_swx_pipeline *p,
7801 const char *args_struct_type_name,
7802 const char **instructions,
7803 uint32_t n_instructions)
7805 struct struct_type *args_struct_type = NULL;
7811 CHECK_NAME(name, EINVAL);
7812 CHECK(!action_find(p, name), EEXIST);
7814 if (args_struct_type_name) {
7815 CHECK_NAME(args_struct_type_name, EINVAL);
7816 args_struct_type = struct_type_find(p, args_struct_type_name);
7817 CHECK(args_struct_type, EINVAL);
7818 CHECK(!args_struct_type->var_size, EINVAL);
7821 /* Node allocation. */
7822 a = calloc(1, sizeof(struct action));
7824 if (args_struct_type) {
7825 a->args_endianness = calloc(args_struct_type->n_fields, sizeof(int));
7826 if (!a->args_endianness) {
7832 /* Node initialization. */
7833 strcpy(a->name, name);
7834 a->st = args_struct_type;
7835 a->id = p->n_actions;
7837 /* Instruction translation. */
7838 err = instruction_config(p, a, instructions, n_instructions);
7840 free(a->args_endianness);
7845 /* Node add to tailq. */
7846 TAILQ_INSERT_TAIL(&p->actions, a, node);
7853 action_build(struct rte_swx_pipeline *p)
7855 struct action *action;
7857 p->action_instructions = calloc(p->n_actions,
7858 sizeof(struct instruction *));
7859 CHECK(p->action_instructions, ENOMEM);
7861 TAILQ_FOREACH(action, &p->actions, node)
7862 p->action_instructions[action->id] = action->instructions;
7868 action_build_free(struct rte_swx_pipeline *p)
7870 free(p->action_instructions);
7871 p->action_instructions = NULL;
7875 action_free(struct rte_swx_pipeline *p)
7877 action_build_free(p);
7880 struct action *action;
7882 action = TAILQ_FIRST(&p->actions);
7886 TAILQ_REMOVE(&p->actions, action, node);
7887 free(action->instructions);
7893 action_arg_src_mov_count(struct action *a,
7895 struct instruction *instructions,
7896 struct instruction_data *instruction_data,
7897 uint32_t n_instructions)
7899 uint32_t offset, n_users = 0, i;
7902 (arg_id >= a->st->n_fields) ||
7904 !instruction_data ||
7908 offset = a->st->fields[arg_id].offset / 8;
7910 for (i = 0; i < n_instructions; i++) {
7911 struct instruction *instr = &instructions[i];
7912 struct instruction_data *data = &instruction_data[i];
7914 if (data->invalid ||
7915 ((instr->type != INSTR_MOV) && (instr->type != INSTR_MOV_HM)) ||
7916 instr->mov.src.struct_id ||
7917 (instr->mov.src.offset != offset))
7929 static struct table_type *
7930 table_type_find(struct rte_swx_pipeline *p, const char *name)
7932 struct table_type *elem;
7934 TAILQ_FOREACH(elem, &p->table_types, node)
7935 if (strcmp(elem->name, name) == 0)
7941 static struct table_type *
7942 table_type_resolve(struct rte_swx_pipeline *p,
7943 const char *recommended_type_name,
7944 enum rte_swx_table_match_type match_type)
7946 struct table_type *elem;
7948 /* Only consider the recommended type if the match type is correct. */
7949 if (recommended_type_name)
7950 TAILQ_FOREACH(elem, &p->table_types, node)
7951 if (!strcmp(elem->name, recommended_type_name) &&
7952 (elem->match_type == match_type))
7955 /* Ignore the recommended type and get the first element with this match
7958 TAILQ_FOREACH(elem, &p->table_types, node)
7959 if (elem->match_type == match_type)
7965 static struct table *
7966 table_find(struct rte_swx_pipeline *p, const char *name)
7970 TAILQ_FOREACH(elem, &p->tables, node)
7971 if (strcmp(elem->name, name) == 0)
7977 static struct table *
7978 table_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7980 struct table *table = NULL;
7982 TAILQ_FOREACH(table, &p->tables, node)
7983 if (table->id == id)
7990 rte_swx_pipeline_table_type_register(struct rte_swx_pipeline *p,
7992 enum rte_swx_table_match_type match_type,
7993 struct rte_swx_table_ops *ops)
7995 struct table_type *elem;
7999 CHECK_NAME(name, EINVAL);
8000 CHECK(!table_type_find(p, name), EEXIST);
8003 CHECK(ops->create, EINVAL);
8004 CHECK(ops->lkp, EINVAL);
8005 CHECK(ops->free, EINVAL);
8007 /* Node allocation. */
8008 elem = calloc(1, sizeof(struct table_type));
8009 CHECK(elem, ENOMEM);
8011 /* Node initialization. */
8012 strcpy(elem->name, name);
8013 elem->match_type = match_type;
8014 memcpy(&elem->ops, ops, sizeof(*ops));
8016 /* Node add to tailq. */
8017 TAILQ_INSERT_TAIL(&p->table_types, elem, node);
8023 table_match_type_resolve(struct rte_swx_match_field_params *fields,
8025 enum rte_swx_table_match_type *match_type)
8027 uint32_t n_fields_em = 0, n_fields_lpm = 0, i;
8029 for (i = 0; i < n_fields; i++) {
8030 struct rte_swx_match_field_params *f = &fields[i];
8032 if (f->match_type == RTE_SWX_TABLE_MATCH_EXACT)
8035 if (f->match_type == RTE_SWX_TABLE_MATCH_LPM)
8039 if ((n_fields_lpm > 1) ||
8040 (n_fields_lpm && (n_fields_em != n_fields - 1)))
8043 *match_type = (n_fields_em == n_fields) ?
8044 RTE_SWX_TABLE_MATCH_EXACT :
8045 RTE_SWX_TABLE_MATCH_WILDCARD;
8051 table_match_fields_check(struct rte_swx_pipeline *p,
8052 struct rte_swx_pipeline_table_params *params,
8053 struct header **header)
8055 struct header *h0 = NULL;
8056 struct field *hf, *mf;
8057 uint32_t *offset = NULL, i;
8060 /* Return if no match fields. */
8061 if (!params->n_fields) {
8062 if (params->fields) {
8073 /* Memory allocation. */
8074 offset = calloc(params->n_fields, sizeof(uint32_t));
8080 /* Check that all the match fields belong to either the same header or
8083 hf = header_field_parse(p, params->fields[0].name, &h0);
8084 mf = metadata_field_parse(p, params->fields[0].name);
8085 if ((!hf && !mf) || (hf && hf->var_size)) {
8090 offset[0] = h0 ? hf->offset : mf->offset;
8092 for (i = 1; i < params->n_fields; i++)
8096 hf = header_field_parse(p, params->fields[i].name, &h);
8097 if (!hf || (h->id != h0->id) || hf->var_size) {
8102 offset[i] = hf->offset;
8104 mf = metadata_field_parse(p, params->fields[i].name);
8110 offset[i] = mf->offset;
8113 /* Check that there are no duplicated match fields. */
8114 for (i = 0; i < params->n_fields; i++) {
8117 for (j = 0; j < i; j++)
8118 if (offset[j] == offset[i]) {
8134 rte_swx_pipeline_table_config(struct rte_swx_pipeline *p,
8136 struct rte_swx_pipeline_table_params *params,
8137 const char *recommended_table_type_name,
8141 struct table_type *type;
8143 struct action *default_action;
8144 struct header *header = NULL;
8145 uint32_t action_data_size_max = 0, i;
8150 CHECK_NAME(name, EINVAL);
8151 CHECK(!table_find(p, name), EEXIST);
8152 CHECK(!selector_find(p, name), EEXIST);
8153 CHECK(!learner_find(p, name), EEXIST);
8155 CHECK(params, EINVAL);
8158 status = table_match_fields_check(p, params, &header);
8162 /* Action checks. */
8163 CHECK(params->n_actions, EINVAL);
8164 CHECK(params->action_names, EINVAL);
8165 for (i = 0; i < params->n_actions; i++) {
8166 const char *action_name = params->action_names[i];
8168 uint32_t action_data_size;
8170 CHECK_NAME(action_name, EINVAL);
8172 a = action_find(p, action_name);
8174 CHECK(!action_does_learning(a), EINVAL);
8176 action_data_size = a->st ? a->st->n_bits / 8 : 0;
8177 if (action_data_size > action_data_size_max)
8178 action_data_size_max = action_data_size;
8181 CHECK_NAME(params->default_action_name, EINVAL);
8182 for (i = 0; i < p->n_actions; i++)
8183 if (!strcmp(params->action_names[i],
8184 params->default_action_name))
8186 CHECK(i < params->n_actions, EINVAL);
8187 default_action = action_find(p, params->default_action_name);
8188 CHECK((default_action->st && params->default_action_data) ||
8189 !params->default_action_data, EINVAL);
8191 /* Table type checks. */
8192 if (recommended_table_type_name)
8193 CHECK_NAME(recommended_table_type_name, EINVAL);
8195 if (params->n_fields) {
8196 enum rte_swx_table_match_type match_type;
8198 status = table_match_type_resolve(params->fields, params->n_fields, &match_type);
8202 type = table_type_resolve(p, recommended_table_type_name, match_type);
8203 CHECK(type, EINVAL);
8208 /* Memory allocation. */
8209 t = calloc(1, sizeof(struct table));
8212 t->fields = calloc(params->n_fields, sizeof(struct match_field));
8218 t->actions = calloc(params->n_actions, sizeof(struct action *));
8225 if (action_data_size_max) {
8226 t->default_action_data = calloc(1, action_data_size_max);
8227 if (!t->default_action_data) {
8235 /* Node initialization. */
8236 strcpy(t->name, name);
8237 if (args && args[0])
8238 strcpy(t->args, args);
8241 for (i = 0; i < params->n_fields; i++) {
8242 struct rte_swx_match_field_params *field = ¶ms->fields[i];
8243 struct match_field *f = &t->fields[i];
8245 f->match_type = field->match_type;
8247 header_field_parse(p, field->name, NULL) :
8248 metadata_field_parse(p, field->name);
8250 t->n_fields = params->n_fields;
8253 for (i = 0; i < params->n_actions; i++)
8254 t->actions[i] = action_find(p, params->action_names[i]);
8255 t->default_action = default_action;
8256 if (default_action->st)
8257 memcpy(t->default_action_data,
8258 params->default_action_data,
8259 default_action->st->n_bits / 8);
8260 t->n_actions = params->n_actions;
8261 t->default_action_is_const = params->default_action_is_const;
8262 t->action_data_size_max = action_data_size_max;
8265 t->id = p->n_tables;
8267 /* Node add to tailq. */
8268 TAILQ_INSERT_TAIL(&p->tables, t, node);
8274 static struct rte_swx_table_params *
8275 table_params_get(struct table *table)
8277 struct rte_swx_table_params *params;
8278 struct field *first, *last;
8280 uint32_t key_size, key_offset, action_data_size, i;
8282 /* Memory allocation. */
8283 params = calloc(1, sizeof(struct rte_swx_table_params));
8287 /* Find first (smallest offset) and last (biggest offset) match fields. */
8288 first = table->fields[0].field;
8289 last = table->fields[0].field;
8291 for (i = 0; i < table->n_fields; i++) {
8292 struct field *f = table->fields[i].field;
8294 if (f->offset < first->offset)
8297 if (f->offset > last->offset)
8301 /* Key offset and size. */
8302 key_offset = first->offset / 8;
8303 key_size = (last->offset + last->n_bits - first->offset) / 8;
8305 /* Memory allocation. */
8306 key_mask = calloc(1, key_size);
8313 for (i = 0; i < table->n_fields; i++) {
8314 struct field *f = table->fields[i].field;
8315 uint32_t start = (f->offset - first->offset) / 8;
8316 size_t size = f->n_bits / 8;
8318 memset(&key_mask[start], 0xFF, size);
8321 /* Action data size. */
8322 action_data_size = 0;
8323 for (i = 0; i < table->n_actions; i++) {
8324 struct action *action = table->actions[i];
8325 uint32_t ads = action->st ? action->st->n_bits / 8 : 0;
8327 if (ads > action_data_size)
8328 action_data_size = ads;
8332 params->match_type = table->type->match_type;
8333 params->key_size = key_size;
8334 params->key_offset = key_offset;
8335 params->key_mask0 = key_mask;
8336 params->action_data_size = action_data_size;
8337 params->n_keys_max = table->size;
8343 table_params_free(struct rte_swx_table_params *params)
8348 free(params->key_mask0);
8353 table_stub_lkp(void *table __rte_unused,
8354 void *mailbox __rte_unused,
8355 uint8_t **key __rte_unused,
8356 uint64_t *action_id __rte_unused,
8357 uint8_t **action_data __rte_unused,
8361 return 1; /* DONE. */
8365 table_build(struct rte_swx_pipeline *p)
8369 /* Per pipeline: table statistics. */
8370 p->table_stats = calloc(p->n_tables, sizeof(struct table_statistics));
8371 CHECK(p->table_stats, ENOMEM);
8373 for (i = 0; i < p->n_tables; i++) {
8374 p->table_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
8375 CHECK(p->table_stats[i].n_pkts_action, ENOMEM);
8378 /* Per thread: table runt-time. */
8379 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8380 struct thread *t = &p->threads[i];
8381 struct table *table;
8383 t->tables = calloc(p->n_tables, sizeof(struct table_runtime));
8384 CHECK(t->tables, ENOMEM);
8386 TAILQ_FOREACH(table, &p->tables, node) {
8387 struct table_runtime *r = &t->tables[table->id];
8392 size = table->type->ops.mailbox_size_get();
8395 r->func = table->type->ops.lkp;
8399 r->mailbox = calloc(1, size);
8400 CHECK(r->mailbox, ENOMEM);
8404 r->key = table->header ?
8405 &t->structs[table->header->struct_id] :
8406 &t->structs[p->metadata_struct_id];
8408 r->func = table_stub_lkp;
8417 table_build_free(struct rte_swx_pipeline *p)
8421 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8422 struct thread *t = &p->threads[i];
8428 for (j = 0; j < p->n_tables; j++) {
8429 struct table_runtime *r = &t->tables[j];
8438 if (p->table_stats) {
8439 for (i = 0; i < p->n_tables; i++)
8440 free(p->table_stats[i].n_pkts_action);
8442 free(p->table_stats);
8447 table_free(struct rte_swx_pipeline *p)
8449 table_build_free(p);
8455 elem = TAILQ_FIRST(&p->tables);
8459 TAILQ_REMOVE(&p->tables, elem, node);
8461 free(elem->actions);
8462 free(elem->default_action_data);
8468 struct table_type *elem;
8470 elem = TAILQ_FIRST(&p->table_types);
8474 TAILQ_REMOVE(&p->table_types, elem, node);
8482 static struct selector *
8483 selector_find(struct rte_swx_pipeline *p, const char *name)
8487 TAILQ_FOREACH(s, &p->selectors, node)
8488 if (strcmp(s->name, name) == 0)
8494 static struct selector *
8495 selector_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8497 struct selector *s = NULL;
8499 TAILQ_FOREACH(s, &p->selectors, node)
8507 selector_fields_check(struct rte_swx_pipeline *p,
8508 struct rte_swx_pipeline_selector_params *params,
8509 struct header **header)
8511 struct header *h0 = NULL;
8512 struct field *hf, *mf;
8515 /* Return if no selector fields. */
8516 if (!params->n_selector_fields || !params->selector_field_names)
8519 /* Check that all the selector fields either belong to the same header
8520 * or are all meta-data fields.
8522 hf = header_field_parse(p, params->selector_field_names[0], &h0);
8523 mf = metadata_field_parse(p, params->selector_field_names[0]);
8527 for (i = 1; i < params->n_selector_fields; i++)
8531 hf = header_field_parse(p, params->selector_field_names[i], &h);
8532 if (!hf || (h->id != h0->id))
8535 mf = metadata_field_parse(p, params->selector_field_names[i]);
8540 /* Check that there are no duplicated match fields. */
8541 for (i = 0; i < params->n_selector_fields; i++) {
8542 const char *field_name = params->selector_field_names[i];
8545 for (j = i + 1; j < params->n_selector_fields; j++)
8546 if (!strcmp(params->selector_field_names[j], field_name))
8558 rte_swx_pipeline_selector_config(struct rte_swx_pipeline *p,
8560 struct rte_swx_pipeline_selector_params *params)
8563 struct header *selector_header = NULL;
8564 struct field *group_id_field, *member_id_field;
8570 CHECK_NAME(name, EINVAL);
8571 CHECK(!table_find(p, name), EEXIST);
8572 CHECK(!selector_find(p, name), EEXIST);
8573 CHECK(!learner_find(p, name), EEXIST);
8575 CHECK(params, EINVAL);
8577 CHECK_NAME(params->group_id_field_name, EINVAL);
8578 group_id_field = metadata_field_parse(p, params->group_id_field_name);
8579 CHECK(group_id_field, EINVAL);
8581 for (i = 0; i < params->n_selector_fields; i++) {
8582 const char *field_name = params->selector_field_names[i];
8584 CHECK_NAME(field_name, EINVAL);
8586 status = selector_fields_check(p, params, &selector_header);
8590 CHECK_NAME(params->member_id_field_name, EINVAL);
8591 member_id_field = metadata_field_parse(p, params->member_id_field_name);
8592 CHECK(member_id_field, EINVAL);
8594 CHECK(params->n_groups_max, EINVAL);
8596 CHECK(params->n_members_per_group_max, EINVAL);
8598 /* Memory allocation. */
8599 s = calloc(1, sizeof(struct selector));
8605 s->selector_fields = calloc(params->n_selector_fields, sizeof(struct field *));
8606 if (!s->selector_fields) {
8611 /* Node initialization. */
8612 strcpy(s->name, name);
8614 s->group_id_field = group_id_field;
8616 for (i = 0; i < params->n_selector_fields; i++) {
8617 const char *field_name = params->selector_field_names[i];
8619 s->selector_fields[i] = selector_header ?
8620 header_field_parse(p, field_name, NULL) :
8621 metadata_field_parse(p, field_name);
8624 s->n_selector_fields = params->n_selector_fields;
8626 s->selector_header = selector_header;
8628 s->member_id_field = member_id_field;
8630 s->n_groups_max = params->n_groups_max;
8632 s->n_members_per_group_max = params->n_members_per_group_max;
8634 s->id = p->n_selectors;
8636 /* Node add to tailq. */
8637 TAILQ_INSERT_TAIL(&p->selectors, s, node);
8646 free(s->selector_fields);
8654 selector_params_free(struct rte_swx_table_selector_params *params)
8659 free(params->selector_mask);
8664 static struct rte_swx_table_selector_params *
8665 selector_table_params_get(struct selector *s)
8667 struct rte_swx_table_selector_params *params = NULL;
8668 struct field *first, *last;
8671 /* Memory allocation. */
8672 params = calloc(1, sizeof(struct rte_swx_table_selector_params));
8677 params->group_id_offset = s->group_id_field->offset / 8;
8679 /* Find first (smallest offset) and last (biggest offset) selector fields. */
8680 first = s->selector_fields[0];
8681 last = s->selector_fields[0];
8683 for (i = 0; i < s->n_selector_fields; i++) {
8684 struct field *f = s->selector_fields[i];
8686 if (f->offset < first->offset)
8689 if (f->offset > last->offset)
8693 /* Selector offset and size. */
8694 params->selector_offset = first->offset / 8;
8695 params->selector_size = (last->offset + last->n_bits - first->offset) / 8;
8697 /* Memory allocation. */
8698 params->selector_mask = calloc(1, params->selector_size);
8699 if (!params->selector_mask)
8702 /* Selector mask. */
8703 for (i = 0; i < s->n_selector_fields; i++) {
8704 struct field *f = s->selector_fields[i];
8705 uint32_t start = (f->offset - first->offset) / 8;
8706 size_t size = f->n_bits / 8;
8708 memset(¶ms->selector_mask[start], 0xFF, size);
8712 params->member_id_offset = s->member_id_field->offset / 8;
8714 /* Maximum number of groups. */
8715 params->n_groups_max = s->n_groups_max;
8717 /* Maximum number of members per group. */
8718 params->n_members_per_group_max = s->n_members_per_group_max;
8723 selector_params_free(params);
8728 selector_build_free(struct rte_swx_pipeline *p)
8732 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8733 struct thread *t = &p->threads[i];
8739 for (j = 0; j < p->n_selectors; j++) {
8740 struct selector_runtime *r = &t->selectors[j];
8746 t->selectors = NULL;
8749 free(p->selector_stats);
8750 p->selector_stats = NULL;
8754 selector_build(struct rte_swx_pipeline *p)
8759 /* Per pipeline: selector statistics. */
8760 p->selector_stats = calloc(p->n_selectors, sizeof(struct selector_statistics));
8761 if (!p->selector_stats) {
8766 /* Per thread: selector run-time. */
8767 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8768 struct thread *t = &p->threads[i];
8771 t->selectors = calloc(p->n_selectors, sizeof(struct selector_runtime));
8772 if (!t->selectors) {
8777 TAILQ_FOREACH(s, &p->selectors, node) {
8778 struct selector_runtime *r = &t->selectors[s->id];
8782 size = rte_swx_table_selector_mailbox_size_get();
8784 r->mailbox = calloc(1, size);
8791 /* r->group_id_buffer. */
8792 r->group_id_buffer = &t->structs[p->metadata_struct_id];
8794 /* r->selector_buffer. */
8795 r->selector_buffer = s->selector_header ?
8796 &t->structs[s->selector_header->struct_id] :
8797 &t->structs[p->metadata_struct_id];
8799 /* r->member_id_buffer. */
8800 r->member_id_buffer = &t->structs[p->metadata_struct_id];
8807 selector_build_free(p);
8812 selector_free(struct rte_swx_pipeline *p)
8814 selector_build_free(p);
8816 /* Selector tables. */
8818 struct selector *elem;
8820 elem = TAILQ_FIRST(&p->selectors);
8824 TAILQ_REMOVE(&p->selectors, elem, node);
8825 free(elem->selector_fields);
8833 static struct learner *
8834 learner_find(struct rte_swx_pipeline *p, const char *name)
8838 TAILQ_FOREACH(l, &p->learners, node)
8839 if (!strcmp(l->name, name))
8845 static struct learner *
8846 learner_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8848 struct learner *l = NULL;
8850 TAILQ_FOREACH(l, &p->learners, node)
8858 learner_match_fields_check(struct rte_swx_pipeline *p,
8859 struct rte_swx_pipeline_learner_params *params,
8860 struct header **header)
8862 struct header *h0 = NULL;
8863 struct field *hf, *mf;
8866 /* Return if no match fields. */
8867 if (!params->n_fields || !params->field_names)
8870 /* Check that all the match fields either belong to the same header
8871 * or are all meta-data fields.
8873 hf = header_field_parse(p, params->field_names[0], &h0);
8874 mf = metadata_field_parse(p, params->field_names[0]);
8878 for (i = 1; i < params->n_fields; i++)
8882 hf = header_field_parse(p, params->field_names[i], &h);
8883 if (!hf || (h->id != h0->id))
8886 mf = metadata_field_parse(p, params->field_names[i]);
8891 /* Check that there are no duplicated match fields. */
8892 for (i = 0; i < params->n_fields; i++) {
8893 const char *field_name = params->field_names[i];
8896 for (j = i + 1; j < params->n_fields; j++)
8897 if (!strcmp(params->field_names[j], field_name))
8909 learner_action_args_check(struct rte_swx_pipeline *p, struct action *a, const char *mf_name)
8911 struct struct_type *mst = p->metadata_st, *ast = a->st;
8912 struct field *mf, *af;
8922 /* Check that mf_name is the name of a valid meta-data field. */
8923 CHECK_NAME(mf_name, EINVAL);
8924 mf = metadata_field_parse(p, mf_name);
8927 /* Check that there are enough meta-data fields, starting with the mf_name field, to cover
8928 * all the action arguments.
8930 mf_pos = mf - mst->fields;
8931 CHECK(mst->n_fields - mf_pos >= ast->n_fields, EINVAL);
8933 /* Check that the size of each of the identified meta-data fields matches exactly the size
8934 * of the corresponding action argument.
8936 for (i = 0; i < ast->n_fields; i++) {
8937 mf = &mst->fields[mf_pos + i];
8938 af = &ast->fields[i];
8940 CHECK(mf->n_bits == af->n_bits, EINVAL);
8947 learner_action_learning_check(struct rte_swx_pipeline *p,
8948 struct action *action,
8949 const char **action_names,
8954 /* For each "learn" instruction of the current action, check that the learned action (i.e.
8955 * the action passed as argument to the "learn" instruction) is also enabled for the
8956 * current learner table.
8958 for (i = 0; i < action->n_instructions; i++) {
8959 struct instruction *instr = &action->instructions[i];
8960 uint32_t found = 0, j;
8962 if (instr->type != INSTR_LEARNER_LEARN)
8965 for (j = 0; j < n_actions; j++) {
8968 a = action_find(p, action_names[j]);
8972 if (a->id == instr->learn.action_id)
8984 rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p,
8986 struct rte_swx_pipeline_learner_params *params,
8990 struct learner *l = NULL;
8991 struct action *default_action;
8992 struct header *header = NULL;
8993 uint32_t action_data_size_max = 0, i;
8998 CHECK_NAME(name, EINVAL);
8999 CHECK(!table_find(p, name), EEXIST);
9000 CHECK(!selector_find(p, name), EEXIST);
9001 CHECK(!learner_find(p, name), EEXIST);
9003 CHECK(params, EINVAL);
9006 status = learner_match_fields_check(p, params, &header);
9010 /* Action checks. */
9011 CHECK(params->n_actions, EINVAL);
9013 CHECK(params->action_names, EINVAL);
9014 for (i = 0; i < params->n_actions; i++) {
9015 const char *action_name = params->action_names[i];
9016 const char *action_field_name = params->action_field_names[i];
9018 uint32_t action_data_size;
9020 CHECK_NAME(action_name, EINVAL);
9022 a = action_find(p, action_name);
9025 status = learner_action_args_check(p, a, action_field_name);
9029 status = learner_action_learning_check(p,
9031 params->action_names,
9036 action_data_size = a->st ? a->st->n_bits / 8 : 0;
9037 if (action_data_size > action_data_size_max)
9038 action_data_size_max = action_data_size;
9041 CHECK_NAME(params->default_action_name, EINVAL);
9042 for (i = 0; i < p->n_actions; i++)
9043 if (!strcmp(params->action_names[i],
9044 params->default_action_name))
9046 CHECK(i < params->n_actions, EINVAL);
9048 default_action = action_find(p, params->default_action_name);
9049 CHECK((default_action->st && params->default_action_data) ||
9050 !params->default_action_data, EINVAL);
9052 /* Any other checks. */
9053 CHECK(size, EINVAL);
9054 CHECK(timeout, EINVAL);
9056 /* Memory allocation. */
9057 l = calloc(1, sizeof(struct learner));
9061 l->fields = calloc(params->n_fields, sizeof(struct field *));
9065 l->actions = calloc(params->n_actions, sizeof(struct action *));
9069 l->action_arg = calloc(params->n_actions, sizeof(struct field *));
9073 if (action_data_size_max) {
9074 l->default_action_data = calloc(1, action_data_size_max);
9075 if (!l->default_action_data)
9079 /* Node initialization. */
9080 strcpy(l->name, name);
9082 for (i = 0; i < params->n_fields; i++) {
9083 const char *field_name = params->field_names[i];
9085 l->fields[i] = header ?
9086 header_field_parse(p, field_name, NULL) :
9087 metadata_field_parse(p, field_name);
9090 l->n_fields = params->n_fields;
9094 for (i = 0; i < params->n_actions; i++) {
9095 const char *mf_name = params->action_field_names[i];
9097 l->actions[i] = action_find(p, params->action_names[i]);
9099 l->action_arg[i] = mf_name ? metadata_field_parse(p, mf_name) : NULL;
9102 l->default_action = default_action;
9104 if (default_action->st)
9105 memcpy(l->default_action_data,
9106 params->default_action_data,
9107 default_action->st->n_bits / 8);
9109 l->n_actions = params->n_actions;
9111 l->default_action_is_const = params->default_action_is_const;
9113 l->action_data_size_max = action_data_size_max;
9117 l->timeout = timeout;
9119 l->id = p->n_learners;
9121 /* Node add to tailq. */
9122 TAILQ_INSERT_TAIL(&p->learners, l, node);
9131 free(l->action_arg);
9140 learner_params_free(struct rte_swx_table_learner_params *params)
9145 free(params->key_mask0);
9150 static struct rte_swx_table_learner_params *
9151 learner_params_get(struct learner *l)
9153 struct rte_swx_table_learner_params *params = NULL;
9154 struct field *first, *last;
9157 /* Memory allocation. */
9158 params = calloc(1, sizeof(struct rte_swx_table_learner_params));
9162 /* Find first (smallest offset) and last (biggest offset) match fields. */
9163 first = l->fields[0];
9164 last = l->fields[0];
9166 for (i = 0; i < l->n_fields; i++) {
9167 struct field *f = l->fields[i];
9169 if (f->offset < first->offset)
9172 if (f->offset > last->offset)
9176 /* Key offset and size. */
9177 params->key_offset = first->offset / 8;
9178 params->key_size = (last->offset + last->n_bits - first->offset) / 8;
9180 /* Memory allocation. */
9181 params->key_mask0 = calloc(1, params->key_size);
9182 if (!params->key_mask0)
9186 for (i = 0; i < l->n_fields; i++) {
9187 struct field *f = l->fields[i];
9188 uint32_t start = (f->offset - first->offset) / 8;
9189 size_t size = f->n_bits / 8;
9191 memset(¶ms->key_mask0[start], 0xFF, size);
9194 /* Action data size. */
9195 params->action_data_size = l->action_data_size_max;
9197 /* Maximum number of keys. */
9198 params->n_keys_max = l->size;
9201 params->key_timeout = l->timeout;
9206 learner_params_free(params);
9211 learner_build_free(struct rte_swx_pipeline *p)
9215 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9216 struct thread *t = &p->threads[i];
9222 for (j = 0; j < p->n_learners; j++) {
9223 struct learner_runtime *r = &t->learners[j];
9226 free(r->action_data);
9233 if (p->learner_stats) {
9234 for (i = 0; i < p->n_learners; i++)
9235 free(p->learner_stats[i].n_pkts_action);
9237 free(p->learner_stats);
9242 learner_build(struct rte_swx_pipeline *p)
9247 /* Per pipeline: learner statistics. */
9248 p->learner_stats = calloc(p->n_learners, sizeof(struct learner_statistics));
9249 CHECK(p->learner_stats, ENOMEM);
9251 for (i = 0; i < p->n_learners; i++) {
9252 p->learner_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
9253 CHECK(p->learner_stats[i].n_pkts_action, ENOMEM);
9256 /* Per thread: learner run-time. */
9257 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9258 struct thread *t = &p->threads[i];
9261 t->learners = calloc(p->n_learners, sizeof(struct learner_runtime));
9267 TAILQ_FOREACH(l, &p->learners, node) {
9268 struct learner_runtime *r = &t->learners[l->id];
9273 size = rte_swx_table_learner_mailbox_size_get();
9275 r->mailbox = calloc(1, size);
9283 r->key = l->header ?
9284 &t->structs[l->header->struct_id] :
9285 &t->structs[p->metadata_struct_id];
9287 /* r->action_data. */
9288 r->action_data = calloc(p->n_actions, sizeof(uint8_t *));
9289 if (!r->action_data) {
9294 for (j = 0; j < l->n_actions; j++) {
9295 struct action *a = l->actions[j];
9296 struct field *mf = l->action_arg[j];
9297 uint8_t *m = t->structs[p->metadata_struct_id];
9299 r->action_data[a->id] = mf ? &m[mf->offset / 8] : NULL;
9307 learner_build_free(p);
9312 learner_free(struct rte_swx_pipeline *p)
9314 learner_build_free(p);
9316 /* Learner tables. */
9320 l = TAILQ_FIRST(&p->learners);
9324 TAILQ_REMOVE(&p->learners, l, node);
9327 free(l->action_arg);
9328 free(l->default_action_data);
9337 table_state_build(struct rte_swx_pipeline *p)
9339 struct table *table;
9343 p->table_state = calloc(p->n_tables + p->n_selectors,
9344 sizeof(struct rte_swx_table_state));
9345 CHECK(p->table_state, ENOMEM);
9347 TAILQ_FOREACH(table, &p->tables, node) {
9348 struct rte_swx_table_state *ts = &p->table_state[table->id];
9351 struct rte_swx_table_params *params;
9354 params = table_params_get(table);
9355 CHECK(params, ENOMEM);
9357 ts->obj = table->type->ops.create(params,
9362 table_params_free(params);
9363 CHECK(ts->obj, ENODEV);
9366 /* ts->default_action_data. */
9367 if (table->action_data_size_max) {
9368 ts->default_action_data =
9369 malloc(table->action_data_size_max);
9370 CHECK(ts->default_action_data, ENOMEM);
9372 memcpy(ts->default_action_data,
9373 table->default_action_data,
9374 table->action_data_size_max);
9377 /* ts->default_action_id. */
9378 ts->default_action_id = table->default_action->id;
9381 TAILQ_FOREACH(s, &p->selectors, node) {
9382 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + s->id];
9383 struct rte_swx_table_selector_params *params;
9386 params = selector_table_params_get(s);
9387 CHECK(params, ENOMEM);
9389 ts->obj = rte_swx_table_selector_create(params, NULL, p->numa_node);
9391 selector_params_free(params);
9392 CHECK(ts->obj, ENODEV);
9395 TAILQ_FOREACH(l, &p->learners, node) {
9396 struct rte_swx_table_state *ts = &p->table_state[p->n_tables +
9397 p->n_selectors + l->id];
9398 struct rte_swx_table_learner_params *params;
9401 params = learner_params_get(l);
9402 CHECK(params, ENOMEM);
9404 ts->obj = rte_swx_table_learner_create(params, p->numa_node);
9405 learner_params_free(params);
9406 CHECK(ts->obj, ENODEV);
9408 /* ts->default_action_data. */
9409 if (l->action_data_size_max) {
9410 ts->default_action_data = malloc(l->action_data_size_max);
9411 CHECK(ts->default_action_data, ENOMEM);
9413 memcpy(ts->default_action_data,
9414 l->default_action_data,
9415 l->action_data_size_max);
9418 /* ts->default_action_id. */
9419 ts->default_action_id = l->default_action->id;
9426 table_state_build_free(struct rte_swx_pipeline *p)
9430 if (!p->table_state)
9433 for (i = 0; i < p->n_tables; i++) {
9434 struct rte_swx_table_state *ts = &p->table_state[i];
9435 struct table *table = table_find_by_id(p, i);
9438 if (table->type && ts->obj)
9439 table->type->ops.free(ts->obj);
9441 /* ts->default_action_data. */
9442 free(ts->default_action_data);
9445 for (i = 0; i < p->n_selectors; i++) {
9446 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + i];
9450 rte_swx_table_selector_free(ts->obj);
9453 for (i = 0; i < p->n_learners; i++) {
9454 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + p->n_selectors + i];
9458 rte_swx_table_learner_free(ts->obj);
9460 /* ts->default_action_data. */
9461 free(ts->default_action_data);
9464 free(p->table_state);
9465 p->table_state = NULL;
9469 table_state_free(struct rte_swx_pipeline *p)
9471 table_state_build_free(p);
9477 static struct regarray *
9478 regarray_find(struct rte_swx_pipeline *p, const char *name)
9480 struct regarray *elem;
9482 TAILQ_FOREACH(elem, &p->regarrays, node)
9483 if (!strcmp(elem->name, name))
9489 static struct regarray *
9490 regarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9492 struct regarray *elem = NULL;
9494 TAILQ_FOREACH(elem, &p->regarrays, node)
9502 rte_swx_pipeline_regarray_config(struct rte_swx_pipeline *p,
9511 CHECK_NAME(name, EINVAL);
9512 CHECK(!regarray_find(p, name), EEXIST);
9514 CHECK(size, EINVAL);
9515 size = rte_align32pow2(size);
9517 /* Memory allocation. */
9518 r = calloc(1, sizeof(struct regarray));
9521 /* Node initialization. */
9522 strcpy(r->name, name);
9523 r->init_val = init_val;
9525 r->id = p->n_regarrays;
9527 /* Node add to tailq. */
9528 TAILQ_INSERT_TAIL(&p->regarrays, r, node);
9535 regarray_build(struct rte_swx_pipeline *p)
9537 struct regarray *regarray;
9539 if (!p->n_regarrays)
9542 p->regarray_runtime = calloc(p->n_regarrays, sizeof(struct regarray_runtime));
9543 CHECK(p->regarray_runtime, ENOMEM);
9545 TAILQ_FOREACH(regarray, &p->regarrays, node) {
9546 struct regarray_runtime *r = &p->regarray_runtime[regarray->id];
9549 r->regarray = env_malloc(regarray->size * sizeof(uint64_t),
9550 RTE_CACHE_LINE_SIZE,
9552 CHECK(r->regarray, ENOMEM);
9554 if (regarray->init_val)
9555 for (i = 0; i < regarray->size; i++)
9556 r->regarray[i] = regarray->init_val;
9558 r->size_mask = regarray->size - 1;
9565 regarray_build_free(struct rte_swx_pipeline *p)
9569 if (!p->regarray_runtime)
9572 for (i = 0; i < p->n_regarrays; i++) {
9573 struct regarray *regarray = regarray_find_by_id(p, i);
9574 struct regarray_runtime *r = &p->regarray_runtime[i];
9576 env_free(r->regarray, regarray->size * sizeof(uint64_t));
9579 free(p->regarray_runtime);
9580 p->regarray_runtime = NULL;
9584 regarray_free(struct rte_swx_pipeline *p)
9586 regarray_build_free(p);
9589 struct regarray *elem;
9591 elem = TAILQ_FIRST(&p->regarrays);
9595 TAILQ_REMOVE(&p->regarrays, elem, node);
9603 static struct meter_profile *
9604 meter_profile_find(struct rte_swx_pipeline *p, const char *name)
9606 struct meter_profile *elem;
9608 TAILQ_FOREACH(elem, &p->meter_profiles, node)
9609 if (!strcmp(elem->name, name))
9615 static struct metarray *
9616 metarray_find(struct rte_swx_pipeline *p, const char *name)
9618 struct metarray *elem;
9620 TAILQ_FOREACH(elem, &p->metarrays, node)
9621 if (!strcmp(elem->name, name))
9627 static struct metarray *
9628 metarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9630 struct metarray *elem = NULL;
9632 TAILQ_FOREACH(elem, &p->metarrays, node)
9640 rte_swx_pipeline_metarray_config(struct rte_swx_pipeline *p,
9648 CHECK_NAME(name, EINVAL);
9649 CHECK(!metarray_find(p, name), EEXIST);
9651 CHECK(size, EINVAL);
9652 size = rte_align32pow2(size);
9654 /* Memory allocation. */
9655 m = calloc(1, sizeof(struct metarray));
9658 /* Node initialization. */
9659 strcpy(m->name, name);
9661 m->id = p->n_metarrays;
9663 /* Node add to tailq. */
9664 TAILQ_INSERT_TAIL(&p->metarrays, m, node);
9670 struct meter_profile meter_profile_default = {
9679 .cir_bytes_per_period = 1,
9681 .pir_bytes_per_period = 1,
9688 meter_init(struct meter *m)
9690 memset(m, 0, sizeof(struct meter));
9691 rte_meter_trtcm_config(&m->m, &meter_profile_default.profile);
9692 m->profile = &meter_profile_default;
9693 m->color_mask = RTE_COLOR_GREEN;
9695 meter_profile_default.n_users++;
9699 metarray_build(struct rte_swx_pipeline *p)
9703 if (!p->n_metarrays)
9706 p->metarray_runtime = calloc(p->n_metarrays, sizeof(struct metarray_runtime));
9707 CHECK(p->metarray_runtime, ENOMEM);
9709 TAILQ_FOREACH(m, &p->metarrays, node) {
9710 struct metarray_runtime *r = &p->metarray_runtime[m->id];
9713 r->metarray = env_malloc(m->size * sizeof(struct meter),
9714 RTE_CACHE_LINE_SIZE,
9716 CHECK(r->metarray, ENOMEM);
9718 for (i = 0; i < m->size; i++)
9719 meter_init(&r->metarray[i]);
9721 r->size_mask = m->size - 1;
9728 metarray_build_free(struct rte_swx_pipeline *p)
9732 if (!p->metarray_runtime)
9735 for (i = 0; i < p->n_metarrays; i++) {
9736 struct metarray *m = metarray_find_by_id(p, i);
9737 struct metarray_runtime *r = &p->metarray_runtime[i];
9739 env_free(r->metarray, m->size * sizeof(struct meter));
9742 free(p->metarray_runtime);
9743 p->metarray_runtime = NULL;
9747 metarray_free(struct rte_swx_pipeline *p)
9749 metarray_build_free(p);
9753 struct metarray *elem;
9755 elem = TAILQ_FIRST(&p->metarrays);
9759 TAILQ_REMOVE(&p->metarrays, elem, node);
9763 /* Meter profiles. */
9765 struct meter_profile *elem;
9767 elem = TAILQ_FIRST(&p->meter_profiles);
9771 TAILQ_REMOVE(&p->meter_profiles, elem, node);
9780 rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
9782 struct rte_swx_pipeline *pipeline;
9784 /* Check input parameters. */
9787 /* Memory allocation. */
9788 pipeline = calloc(1, sizeof(struct rte_swx_pipeline));
9789 CHECK(pipeline, ENOMEM);
9791 /* Initialization. */
9792 TAILQ_INIT(&pipeline->struct_types);
9793 TAILQ_INIT(&pipeline->port_in_types);
9794 TAILQ_INIT(&pipeline->ports_in);
9795 TAILQ_INIT(&pipeline->port_out_types);
9796 TAILQ_INIT(&pipeline->ports_out);
9797 TAILQ_INIT(&pipeline->extern_types);
9798 TAILQ_INIT(&pipeline->extern_objs);
9799 TAILQ_INIT(&pipeline->extern_funcs);
9800 TAILQ_INIT(&pipeline->headers);
9801 TAILQ_INIT(&pipeline->actions);
9802 TAILQ_INIT(&pipeline->table_types);
9803 TAILQ_INIT(&pipeline->tables);
9804 TAILQ_INIT(&pipeline->selectors);
9805 TAILQ_INIT(&pipeline->learners);
9806 TAILQ_INIT(&pipeline->regarrays);
9807 TAILQ_INIT(&pipeline->meter_profiles);
9808 TAILQ_INIT(&pipeline->metarrays);
9810 pipeline->n_structs = 1; /* Struct 0 is reserved for action_data. */
9811 pipeline->numa_node = numa_node;
9818 rte_swx_pipeline_free(struct rte_swx_pipeline *p)
9823 free(p->instructions);
9827 table_state_free(p);
9834 extern_func_free(p);
9844 rte_swx_pipeline_instructions_config(struct rte_swx_pipeline *p,
9845 const char **instructions,
9846 uint32_t n_instructions)
9851 err = instruction_config(p, NULL, instructions, n_instructions);
9855 /* Thread instruction pointer reset. */
9856 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9857 struct thread *t = &p->threads[i];
9859 thread_ip_reset(p, t);
9866 rte_swx_pipeline_build(struct rte_swx_pipeline *p)
9871 CHECK(p->build_done == 0, EEXIST);
9873 status = port_in_build(p);
9877 status = port_out_build(p);
9881 status = struct_build(p);
9885 status = extern_obj_build(p);
9889 status = extern_func_build(p);
9893 status = header_build(p);
9897 status = metadata_build(p);
9901 status = action_build(p);
9905 status = table_build(p);
9909 status = selector_build(p);
9913 status = learner_build(p);
9917 status = table_state_build(p);
9921 status = regarray_build(p);
9925 status = metarray_build(p);
9933 metarray_build_free(p);
9934 regarray_build_free(p);
9935 table_state_build_free(p);
9936 learner_build_free(p);
9937 selector_build_free(p);
9938 table_build_free(p);
9939 action_build_free(p);
9940 metadata_build_free(p);
9941 header_build_free(p);
9942 extern_func_build_free(p);
9943 extern_obj_build_free(p);
9944 port_out_build_free(p);
9945 port_in_build_free(p);
9946 struct_build_free(p);
9952 rte_swx_pipeline_run(struct rte_swx_pipeline *p, uint32_t n_instructions)
9956 for (i = 0; i < n_instructions; i++)
9961 rte_swx_pipeline_flush(struct rte_swx_pipeline *p)
9965 for (i = 0; i < p->n_ports_out; i++) {
9966 struct port_out_runtime *port = &p->out[i];
9969 port->flush(port->obj);
9977 rte_swx_ctl_pipeline_info_get(struct rte_swx_pipeline *p,
9978 struct rte_swx_ctl_pipeline_info *pipeline)
9980 struct action *action;
9981 struct table *table;
9982 uint32_t n_actions = 0, n_tables = 0;
9984 if (!p || !pipeline)
9987 TAILQ_FOREACH(action, &p->actions, node)
9990 TAILQ_FOREACH(table, &p->tables, node)
9993 pipeline->n_ports_in = p->n_ports_in;
9994 pipeline->n_ports_out = p->n_ports_out;
9995 pipeline->n_actions = n_actions;
9996 pipeline->n_tables = n_tables;
9997 pipeline->n_selectors = p->n_selectors;
9998 pipeline->n_learners = p->n_learners;
9999 pipeline->n_regarrays = p->n_regarrays;
10000 pipeline->n_metarrays = p->n_metarrays;
10006 rte_swx_ctl_pipeline_numa_node_get(struct rte_swx_pipeline *p, int *numa_node)
10008 if (!p || !numa_node)
10011 *numa_node = p->numa_node;
10016 rte_swx_ctl_action_info_get(struct rte_swx_pipeline *p,
10017 uint32_t action_id,
10018 struct rte_swx_ctl_action_info *action)
10020 struct action *a = NULL;
10022 if (!p || (action_id >= p->n_actions) || !action)
10025 a = action_find_by_id(p, action_id);
10029 strcpy(action->name, a->name);
10030 action->n_args = a->st ? a->st->n_fields : 0;
10035 rte_swx_ctl_action_arg_info_get(struct rte_swx_pipeline *p,
10036 uint32_t action_id,
10037 uint32_t action_arg_id,
10038 struct rte_swx_ctl_action_arg_info *action_arg)
10040 struct action *a = NULL;
10041 struct field *arg = NULL;
10043 if (!p || (action_id >= p->n_actions) || !action_arg)
10046 a = action_find_by_id(p, action_id);
10047 if (!a || !a->st || (action_arg_id >= a->st->n_fields))
10050 arg = &a->st->fields[action_arg_id];
10051 strcpy(action_arg->name, arg->name);
10052 action_arg->n_bits = arg->n_bits;
10053 action_arg->is_network_byte_order = a->args_endianness[action_arg_id];
10059 rte_swx_ctl_table_info_get(struct rte_swx_pipeline *p,
10061 struct rte_swx_ctl_table_info *table)
10063 struct table *t = NULL;
10068 t = table_find_by_id(p, table_id);
10072 strcpy(table->name, t->name);
10073 strcpy(table->args, t->args);
10074 table->n_match_fields = t->n_fields;
10075 table->n_actions = t->n_actions;
10076 table->default_action_is_const = t->default_action_is_const;
10077 table->size = t->size;
10082 rte_swx_ctl_table_match_field_info_get(struct rte_swx_pipeline *p,
10084 uint32_t match_field_id,
10085 struct rte_swx_ctl_table_match_field_info *match_field)
10088 struct match_field *f;
10090 if (!p || (table_id >= p->n_tables) || !match_field)
10093 t = table_find_by_id(p, table_id);
10094 if (!t || (match_field_id >= t->n_fields))
10097 f = &t->fields[match_field_id];
10098 match_field->match_type = f->match_type;
10099 match_field->is_header = t->header ? 1 : 0;
10100 match_field->n_bits = f->field->n_bits;
10101 match_field->offset = f->field->offset;
10107 rte_swx_ctl_table_action_info_get(struct rte_swx_pipeline *p,
10109 uint32_t table_action_id,
10110 struct rte_swx_ctl_table_action_info *table_action)
10114 if (!p || (table_id >= p->n_tables) || !table_action)
10117 t = table_find_by_id(p, table_id);
10118 if (!t || (table_action_id >= t->n_actions))
10121 table_action->action_id = t->actions[table_action_id]->id;
10127 rte_swx_ctl_table_ops_get(struct rte_swx_pipeline *p,
10129 struct rte_swx_table_ops *table_ops,
10134 if (!p || (table_id >= p->n_tables))
10137 t = table_find_by_id(p, table_id);
10143 memcpy(table_ops, &t->type->ops, sizeof(*table_ops));
10153 rte_swx_ctl_selector_info_get(struct rte_swx_pipeline *p,
10154 uint32_t selector_id,
10155 struct rte_swx_ctl_selector_info *selector)
10157 struct selector *s = NULL;
10159 if (!p || !selector)
10162 s = selector_find_by_id(p, selector_id);
10166 strcpy(selector->name, s->name);
10168 selector->n_selector_fields = s->n_selector_fields;
10169 selector->n_groups_max = s->n_groups_max;
10170 selector->n_members_per_group_max = s->n_members_per_group_max;
10176 rte_swx_ctl_selector_group_id_field_info_get(struct rte_swx_pipeline *p,
10177 uint32_t selector_id,
10178 struct rte_swx_ctl_table_match_field_info *field)
10180 struct selector *s;
10182 if (!p || (selector_id >= p->n_selectors) || !field)
10185 s = selector_find_by_id(p, selector_id);
10189 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10190 field->is_header = 0;
10191 field->n_bits = s->group_id_field->n_bits;
10192 field->offset = s->group_id_field->offset;
10198 rte_swx_ctl_selector_field_info_get(struct rte_swx_pipeline *p,
10199 uint32_t selector_id,
10200 uint32_t selector_field_id,
10201 struct rte_swx_ctl_table_match_field_info *field)
10203 struct selector *s;
10206 if (!p || (selector_id >= p->n_selectors) || !field)
10209 s = selector_find_by_id(p, selector_id);
10210 if (!s || (selector_field_id >= s->n_selector_fields))
10213 f = s->selector_fields[selector_field_id];
10214 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10215 field->is_header = s->selector_header ? 1 : 0;
10216 field->n_bits = f->n_bits;
10217 field->offset = f->offset;
10223 rte_swx_ctl_selector_member_id_field_info_get(struct rte_swx_pipeline *p,
10224 uint32_t selector_id,
10225 struct rte_swx_ctl_table_match_field_info *field)
10227 struct selector *s;
10229 if (!p || (selector_id >= p->n_selectors) || !field)
10232 s = selector_find_by_id(p, selector_id);
10236 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10237 field->is_header = 0;
10238 field->n_bits = s->member_id_field->n_bits;
10239 field->offset = s->member_id_field->offset;
10245 rte_swx_ctl_learner_info_get(struct rte_swx_pipeline *p,
10246 uint32_t learner_id,
10247 struct rte_swx_ctl_learner_info *learner)
10249 struct learner *l = NULL;
10251 if (!p || !learner)
10254 l = learner_find_by_id(p, learner_id);
10258 strcpy(learner->name, l->name);
10260 learner->n_match_fields = l->n_fields;
10261 learner->n_actions = l->n_actions;
10262 learner->default_action_is_const = l->default_action_is_const;
10263 learner->size = l->size;
10269 rte_swx_ctl_learner_match_field_info_get(struct rte_swx_pipeline *p,
10270 uint32_t learner_id,
10271 uint32_t match_field_id,
10272 struct rte_swx_ctl_table_match_field_info *match_field)
10277 if (!p || (learner_id >= p->n_learners) || !match_field)
10280 l = learner_find_by_id(p, learner_id);
10281 if (!l || (match_field_id >= l->n_fields))
10284 f = l->fields[match_field_id];
10285 match_field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10286 match_field->is_header = l->header ? 1 : 0;
10287 match_field->n_bits = f->n_bits;
10288 match_field->offset = f->offset;
10294 rte_swx_ctl_learner_action_info_get(struct rte_swx_pipeline *p,
10295 uint32_t learner_id,
10296 uint32_t learner_action_id,
10297 struct rte_swx_ctl_table_action_info *learner_action)
10301 if (!p || (learner_id >= p->n_learners) || !learner_action)
10304 l = learner_find_by_id(p, learner_id);
10305 if (!l || (learner_action_id >= l->n_actions))
10308 learner_action->action_id = l->actions[learner_action_id]->id;
10314 rte_swx_pipeline_table_state_get(struct rte_swx_pipeline *p,
10315 struct rte_swx_table_state **table_state)
10317 if (!p || !table_state || !p->build_done)
10320 *table_state = p->table_state;
10325 rte_swx_pipeline_table_state_set(struct rte_swx_pipeline *p,
10326 struct rte_swx_table_state *table_state)
10328 if (!p || !table_state || !p->build_done)
10331 p->table_state = table_state;
10336 rte_swx_ctl_pipeline_port_in_stats_read(struct rte_swx_pipeline *p,
10338 struct rte_swx_port_in_stats *stats)
10340 struct port_in *port;
10345 port = port_in_find(p, port_id);
10349 port->type->ops.stats_read(port->obj, stats);
10354 rte_swx_ctl_pipeline_port_out_stats_read(struct rte_swx_pipeline *p,
10356 struct rte_swx_port_out_stats *stats)
10358 struct port_out *port;
10363 port = port_out_find(p, port_id);
10367 port->type->ops.stats_read(port->obj, stats);
10372 rte_swx_ctl_pipeline_table_stats_read(struct rte_swx_pipeline *p,
10373 const char *table_name,
10374 struct rte_swx_table_stats *stats)
10376 struct table *table;
10377 struct table_statistics *table_stats;
10379 if (!p || !table_name || !table_name[0] || !stats || !stats->n_pkts_action)
10382 table = table_find(p, table_name);
10386 table_stats = &p->table_stats[table->id];
10388 memcpy(stats->n_pkts_action,
10389 table_stats->n_pkts_action,
10390 p->n_actions * sizeof(uint64_t));
10392 stats->n_pkts_hit = table_stats->n_pkts_hit[1];
10393 stats->n_pkts_miss = table_stats->n_pkts_hit[0];
10399 rte_swx_ctl_pipeline_selector_stats_read(struct rte_swx_pipeline *p,
10400 const char *selector_name,
10401 struct rte_swx_pipeline_selector_stats *stats)
10403 struct selector *s;
10405 if (!p || !selector_name || !selector_name[0] || !stats)
10408 s = selector_find(p, selector_name);
10412 stats->n_pkts = p->selector_stats[s->id].n_pkts;
10418 rte_swx_ctl_pipeline_learner_stats_read(struct rte_swx_pipeline *p,
10419 const char *learner_name,
10420 struct rte_swx_learner_stats *stats)
10423 struct learner_statistics *learner_stats;
10425 if (!p || !learner_name || !learner_name[0] || !stats || !stats->n_pkts_action)
10428 l = learner_find(p, learner_name);
10432 learner_stats = &p->learner_stats[l->id];
10434 memcpy(stats->n_pkts_action,
10435 learner_stats->n_pkts_action,
10436 p->n_actions * sizeof(uint64_t));
10438 stats->n_pkts_hit = learner_stats->n_pkts_hit[1];
10439 stats->n_pkts_miss = learner_stats->n_pkts_hit[0];
10441 stats->n_pkts_learn_ok = learner_stats->n_pkts_learn[0];
10442 stats->n_pkts_learn_err = learner_stats->n_pkts_learn[1];
10444 stats->n_pkts_forget = learner_stats->n_pkts_forget;
10450 rte_swx_ctl_regarray_info_get(struct rte_swx_pipeline *p,
10451 uint32_t regarray_id,
10452 struct rte_swx_ctl_regarray_info *regarray)
10454 struct regarray *r;
10456 if (!p || !regarray)
10459 r = regarray_find_by_id(p, regarray_id);
10463 strcpy(regarray->name, r->name);
10464 regarray->size = r->size;
10469 rte_swx_ctl_pipeline_regarray_read(struct rte_swx_pipeline *p,
10470 const char *regarray_name,
10471 uint32_t regarray_index,
10474 struct regarray *regarray;
10475 struct regarray_runtime *r;
10477 if (!p || !regarray_name || !value)
10480 regarray = regarray_find(p, regarray_name);
10481 if (!regarray || (regarray_index >= regarray->size))
10484 r = &p->regarray_runtime[regarray->id];
10485 *value = r->regarray[regarray_index];
10490 rte_swx_ctl_pipeline_regarray_write(struct rte_swx_pipeline *p,
10491 const char *regarray_name,
10492 uint32_t regarray_index,
10495 struct regarray *regarray;
10496 struct regarray_runtime *r;
10498 if (!p || !regarray_name)
10501 regarray = regarray_find(p, regarray_name);
10502 if (!regarray || (regarray_index >= regarray->size))
10505 r = &p->regarray_runtime[regarray->id];
10506 r->regarray[regarray_index] = value;
10511 rte_swx_ctl_metarray_info_get(struct rte_swx_pipeline *p,
10512 uint32_t metarray_id,
10513 struct rte_swx_ctl_metarray_info *metarray)
10515 struct metarray *m;
10517 if (!p || !metarray)
10520 m = metarray_find_by_id(p, metarray_id);
10524 strcpy(metarray->name, m->name);
10525 metarray->size = m->size;
10530 rte_swx_ctl_meter_profile_add(struct rte_swx_pipeline *p,
10532 struct rte_meter_trtcm_params *params)
10534 struct meter_profile *mp;
10538 CHECK_NAME(name, EINVAL);
10539 CHECK(params, EINVAL);
10540 CHECK(!meter_profile_find(p, name), EEXIST);
10542 /* Node allocation. */
10543 mp = calloc(1, sizeof(struct meter_profile));
10546 /* Node initialization. */
10547 strcpy(mp->name, name);
10548 memcpy(&mp->params, params, sizeof(struct rte_meter_trtcm_params));
10549 status = rte_meter_trtcm_profile_config(&mp->profile, params);
10555 /* Node add to tailq. */
10556 TAILQ_INSERT_TAIL(&p->meter_profiles, mp, node);
10562 rte_swx_ctl_meter_profile_delete(struct rte_swx_pipeline *p,
10565 struct meter_profile *mp;
10568 CHECK_NAME(name, EINVAL);
10570 mp = meter_profile_find(p, name);
10572 CHECK(!mp->n_users, EBUSY);
10574 /* Remove node from tailq. */
10575 TAILQ_REMOVE(&p->meter_profiles, mp, node);
10582 rte_swx_ctl_meter_reset(struct rte_swx_pipeline *p,
10583 const char *metarray_name,
10584 uint32_t metarray_index)
10586 struct meter_profile *mp_old;
10587 struct metarray *metarray;
10588 struct metarray_runtime *metarray_runtime;
10592 CHECK_NAME(metarray_name, EINVAL);
10594 metarray = metarray_find(p, metarray_name);
10595 CHECK(metarray, EINVAL);
10596 CHECK(metarray_index < metarray->size, EINVAL);
10598 metarray_runtime = &p->metarray_runtime[metarray->id];
10599 m = &metarray_runtime->metarray[metarray_index];
10600 mp_old = m->profile;
10610 rte_swx_ctl_meter_set(struct rte_swx_pipeline *p,
10611 const char *metarray_name,
10612 uint32_t metarray_index,
10613 const char *profile_name)
10615 struct meter_profile *mp, *mp_old;
10616 struct metarray *metarray;
10617 struct metarray_runtime *metarray_runtime;
10621 CHECK_NAME(metarray_name, EINVAL);
10623 metarray = metarray_find(p, metarray_name);
10624 CHECK(metarray, EINVAL);
10625 CHECK(metarray_index < metarray->size, EINVAL);
10627 mp = meter_profile_find(p, profile_name);
10630 metarray_runtime = &p->metarray_runtime[metarray->id];
10631 m = &metarray_runtime->metarray[metarray_index];
10632 mp_old = m->profile;
10634 memset(m, 0, sizeof(struct meter));
10635 rte_meter_trtcm_config(&m->m, &mp->profile);
10637 m->color_mask = RTE_COLORS;
10646 rte_swx_ctl_meter_stats_read(struct rte_swx_pipeline *p,
10647 const char *metarray_name,
10648 uint32_t metarray_index,
10649 struct rte_swx_ctl_meter_stats *stats)
10651 struct metarray *metarray;
10652 struct metarray_runtime *metarray_runtime;
10656 CHECK_NAME(metarray_name, EINVAL);
10658 metarray = metarray_find(p, metarray_name);
10659 CHECK(metarray, EINVAL);
10660 CHECK(metarray_index < metarray->size, EINVAL);
10662 CHECK(stats, EINVAL);
10664 metarray_runtime = &p->metarray_runtime[metarray->id];
10665 m = &metarray_runtime->metarray[metarray_index];
10667 memcpy(stats->n_pkts, m->n_pkts, sizeof(m->n_pkts));
10668 memcpy(stats->n_bytes, m->n_bytes, sizeof(m->n_bytes));