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, uint32_t n_extract);
1671 __instr_hdr_extract_exec(struct rte_swx_pipeline *p, uint32_t n_extract)
1673 struct thread *t = &p->threads[p->thread_id];
1674 struct instruction *ip = t->ip;
1675 uint64_t valid_headers = t->valid_headers;
1676 uint8_t *ptr = t->ptr;
1677 uint32_t offset = t->pkt.offset;
1678 uint32_t length = t->pkt.length;
1681 for (i = 0; i < n_extract; i++) {
1682 uint32_t header_id = ip->io.hdr.header_id[i];
1683 uint32_t struct_id = ip->io.hdr.struct_id[i];
1684 uint32_t n_bytes = ip->io.hdr.n_bytes[i];
1686 TRACE("[Thread %2u]: extract header %u (%u bytes)\n",
1692 t->structs[struct_id] = ptr;
1693 valid_headers = MASK64_BIT_SET(valid_headers, header_id);
1702 t->valid_headers = valid_headers;
1705 t->pkt.offset = offset;
1706 t->pkt.length = length;
1711 instr_hdr_extract_exec(struct rte_swx_pipeline *p)
1713 __instr_hdr_extract_exec(p, 1);
1720 instr_hdr_extract2_exec(struct rte_swx_pipeline *p)
1722 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n",
1725 __instr_hdr_extract_exec(p, 2);
1732 instr_hdr_extract3_exec(struct rte_swx_pipeline *p)
1734 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n",
1737 __instr_hdr_extract_exec(p, 3);
1744 instr_hdr_extract4_exec(struct rte_swx_pipeline *p)
1746 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n",
1749 __instr_hdr_extract_exec(p, 4);
1756 instr_hdr_extract5_exec(struct rte_swx_pipeline *p)
1758 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n",
1761 __instr_hdr_extract_exec(p, 5);
1768 instr_hdr_extract6_exec(struct rte_swx_pipeline *p)
1770 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n",
1773 __instr_hdr_extract_exec(p, 6);
1780 instr_hdr_extract7_exec(struct rte_swx_pipeline *p)
1782 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n",
1785 __instr_hdr_extract_exec(p, 7);
1792 instr_hdr_extract8_exec(struct rte_swx_pipeline *p)
1794 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n",
1797 __instr_hdr_extract_exec(p, 8);
1804 instr_hdr_extract_m_exec(struct rte_swx_pipeline *p)
1806 struct thread *t = &p->threads[p->thread_id];
1807 struct instruction *ip = t->ip;
1809 uint64_t valid_headers = t->valid_headers;
1810 uint8_t *ptr = t->ptr;
1811 uint32_t offset = t->pkt.offset;
1812 uint32_t length = t->pkt.length;
1814 uint32_t n_bytes_last = METADATA_READ(t, ip->io.io.offset, ip->io.io.n_bits);
1815 uint32_t header_id = ip->io.hdr.header_id[0];
1816 uint32_t struct_id = ip->io.hdr.struct_id[0];
1817 uint32_t n_bytes = ip->io.hdr.n_bytes[0];
1819 struct header_runtime *h = &t->headers[header_id];
1821 TRACE("[Thread %2u]: extract header %u (%u + %u bytes)\n",
1827 n_bytes += n_bytes_last;
1830 t->structs[struct_id] = ptr;
1831 t->valid_headers = MASK64_BIT_SET(valid_headers, header_id);
1832 h->n_bytes = n_bytes;
1835 t->pkt.offset = offset + n_bytes;
1836 t->pkt.length = length - n_bytes;
1837 t->ptr = ptr + n_bytes;
1844 instr_hdr_lookahead_exec(struct rte_swx_pipeline *p)
1846 struct thread *t = &p->threads[p->thread_id];
1847 struct instruction *ip = t->ip;
1849 uint64_t valid_headers = t->valid_headers;
1850 uint8_t *ptr = t->ptr;
1852 uint32_t header_id = ip->io.hdr.header_id[0];
1853 uint32_t struct_id = ip->io.hdr.struct_id[0];
1855 TRACE("[Thread %2u]: lookahead header %u\n",
1860 t->structs[struct_id] = ptr;
1861 t->valid_headers = MASK64_BIT_SET(valid_headers, header_id);
1871 instr_hdr_emit_translate(struct rte_swx_pipeline *p,
1872 struct action *action __rte_unused,
1875 struct instruction *instr,
1876 struct instruction_data *data __rte_unused)
1880 CHECK(n_tokens == 2, EINVAL);
1882 h = header_parse(p, tokens[1]);
1885 instr->type = INSTR_HDR_EMIT;
1886 instr->io.hdr.header_id[0] = h->id;
1887 instr->io.hdr.struct_id[0] = h->struct_id;
1888 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
1893 __instr_hdr_emit_exec(struct rte_swx_pipeline *p, uint32_t n_emit);
1896 __instr_hdr_emit_exec(struct rte_swx_pipeline *p, uint32_t n_emit)
1898 struct thread *t = &p->threads[p->thread_id];
1899 struct instruction *ip = t->ip;
1900 uint64_t valid_headers = t->valid_headers;
1901 uint32_t n_headers_out = t->n_headers_out;
1902 struct header_out_runtime *ho = &t->headers_out[n_headers_out - 1];
1903 uint8_t *ho_ptr = NULL;
1904 uint32_t ho_nbytes = 0, first = 1, i;
1906 for (i = 0; i < n_emit; i++) {
1907 uint32_t header_id = ip->io.hdr.header_id[i];
1908 uint32_t struct_id = ip->io.hdr.struct_id[i];
1910 struct header_runtime *hi = &t->headers[header_id];
1911 uint8_t *hi_ptr0 = hi->ptr0;
1912 uint32_t n_bytes = hi->n_bytes;
1914 uint8_t *hi_ptr = t->structs[struct_id];
1916 if (!MASK64_BIT_GET(valid_headers, header_id))
1919 TRACE("[Thread %2u]: emit header %u\n",
1927 if (!t->n_headers_out) {
1928 ho = &t->headers_out[0];
1934 ho_nbytes = n_bytes;
1941 ho_nbytes = ho->n_bytes;
1945 if (ho_ptr + ho_nbytes == hi_ptr) {
1946 ho_nbytes += n_bytes;
1948 ho->n_bytes = ho_nbytes;
1955 ho_nbytes = n_bytes;
1961 ho->n_bytes = ho_nbytes;
1962 t->n_headers_out = n_headers_out;
1966 instr_hdr_emit_exec(struct rte_swx_pipeline *p)
1968 __instr_hdr_emit_exec(p, 1);
1975 instr_hdr_emit_tx_exec(struct rte_swx_pipeline *p)
1977 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n",
1980 __instr_hdr_emit_exec(p, 1);
1985 instr_hdr_emit2_tx_exec(struct rte_swx_pipeline *p)
1987 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n",
1990 __instr_hdr_emit_exec(p, 2);
1995 instr_hdr_emit3_tx_exec(struct rte_swx_pipeline *p)
1997 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n",
2000 __instr_hdr_emit_exec(p, 3);
2005 instr_hdr_emit4_tx_exec(struct rte_swx_pipeline *p)
2007 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n",
2010 __instr_hdr_emit_exec(p, 4);
2015 instr_hdr_emit5_tx_exec(struct rte_swx_pipeline *p)
2017 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n",
2020 __instr_hdr_emit_exec(p, 5);
2025 instr_hdr_emit6_tx_exec(struct rte_swx_pipeline *p)
2027 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n",
2030 __instr_hdr_emit_exec(p, 6);
2035 instr_hdr_emit7_tx_exec(struct rte_swx_pipeline *p)
2037 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n",
2040 __instr_hdr_emit_exec(p, 7);
2045 instr_hdr_emit8_tx_exec(struct rte_swx_pipeline *p)
2047 TRACE("[Thread %2u] *** The next 9 instructions are fused. ***\n",
2050 __instr_hdr_emit_exec(p, 8);
2058 instr_hdr_validate_translate(struct rte_swx_pipeline *p,
2059 struct action *action __rte_unused,
2062 struct instruction *instr,
2063 struct instruction_data *data __rte_unused)
2067 CHECK(n_tokens == 2, EINVAL);
2069 h = header_parse(p, tokens[1]);
2072 instr->type = INSTR_HDR_VALIDATE;
2073 instr->valid.header_id = h->id;
2078 instr_hdr_validate_exec(struct rte_swx_pipeline *p)
2080 struct thread *t = &p->threads[p->thread_id];
2081 struct instruction *ip = t->ip;
2082 uint32_t header_id = ip->valid.header_id;
2084 TRACE("[Thread %2u] validate header %u\n", p->thread_id, header_id);
2087 t->valid_headers = MASK64_BIT_SET(t->valid_headers, header_id);
2097 instr_hdr_invalidate_translate(struct rte_swx_pipeline *p,
2098 struct action *action __rte_unused,
2101 struct instruction *instr,
2102 struct instruction_data *data __rte_unused)
2106 CHECK(n_tokens == 2, EINVAL);
2108 h = header_parse(p, tokens[1]);
2111 instr->type = INSTR_HDR_INVALIDATE;
2112 instr->valid.header_id = h->id;
2117 instr_hdr_invalidate_exec(struct rte_swx_pipeline *p)
2119 struct thread *t = &p->threads[p->thread_id];
2120 struct instruction *ip = t->ip;
2121 uint32_t header_id = ip->valid.header_id;
2123 TRACE("[Thread %2u] invalidate header %u\n", p->thread_id, header_id);
2126 t->valid_headers = MASK64_BIT_CLR(t->valid_headers, header_id);
2135 static struct table *
2136 table_find(struct rte_swx_pipeline *p, const char *name);
2138 static struct selector *
2139 selector_find(struct rte_swx_pipeline *p, const char *name);
2141 static struct learner *
2142 learner_find(struct rte_swx_pipeline *p, const char *name);
2145 instr_table_translate(struct rte_swx_pipeline *p,
2146 struct action *action,
2149 struct instruction *instr,
2150 struct instruction_data *data __rte_unused)
2156 CHECK(!action, EINVAL);
2157 CHECK(n_tokens == 2, EINVAL);
2159 t = table_find(p, tokens[1]);
2161 instr->type = INSTR_TABLE;
2162 instr->table.table_id = t->id;
2166 s = selector_find(p, tokens[1]);
2168 instr->type = INSTR_SELECTOR;
2169 instr->table.table_id = s->id;
2173 l = learner_find(p, tokens[1]);
2175 instr->type = INSTR_LEARNER;
2176 instr->table.table_id = l->id;
2184 instr_table_exec(struct rte_swx_pipeline *p)
2186 struct thread *t = &p->threads[p->thread_id];
2187 struct instruction *ip = t->ip;
2188 uint32_t table_id = ip->table.table_id;
2189 struct rte_swx_table_state *ts = &t->table_state[table_id];
2190 struct table_runtime *table = &t->tables[table_id];
2191 struct table_statistics *stats = &p->table_stats[table_id];
2192 uint64_t action_id, n_pkts_hit, n_pkts_action;
2193 uint8_t *action_data;
2197 done = table->func(ts->obj,
2205 TRACE("[Thread %2u] table %u (not finalized)\n",
2213 action_id = hit ? action_id : ts->default_action_id;
2214 action_data = hit ? action_data : ts->default_action_data;
2215 n_pkts_hit = stats->n_pkts_hit[hit];
2216 n_pkts_action = stats->n_pkts_action[action_id];
2218 TRACE("[Thread %2u] table %u (%s, action %u)\n",
2221 hit ? "hit" : "miss",
2222 (uint32_t)action_id);
2224 t->action_id = action_id;
2225 t->structs[0] = action_data;
2227 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2228 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2231 thread_ip_action_call(p, t, action_id);
2235 instr_selector_exec(struct rte_swx_pipeline *p)
2237 struct thread *t = &p->threads[p->thread_id];
2238 struct instruction *ip = t->ip;
2239 uint32_t selector_id = ip->table.table_id;
2240 struct rte_swx_table_state *ts = &t->table_state[p->n_tables + selector_id];
2241 struct selector_runtime *selector = &t->selectors[selector_id];
2242 struct selector_statistics *stats = &p->selector_stats[selector_id];
2243 uint64_t n_pkts = stats->n_pkts;
2247 done = rte_swx_table_selector_select(ts->obj,
2249 selector->group_id_buffer,
2250 selector->selector_buffer,
2251 selector->member_id_buffer);
2254 TRACE("[Thread %2u] selector %u (not finalized)\n",
2263 TRACE("[Thread %2u] selector %u\n",
2267 stats->n_pkts = n_pkts + 1;
2274 instr_learner_exec(struct rte_swx_pipeline *p)
2276 struct thread *t = &p->threads[p->thread_id];
2277 struct instruction *ip = t->ip;
2278 uint32_t learner_id = ip->table.table_id;
2279 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2280 p->n_selectors + learner_id];
2281 struct learner_runtime *l = &t->learners[learner_id];
2282 struct learner_statistics *stats = &p->learner_stats[learner_id];
2283 uint64_t action_id, n_pkts_hit, n_pkts_action, time;
2284 uint8_t *action_data;
2288 time = rte_get_tsc_cycles();
2290 done = rte_swx_table_learner_lookup(ts->obj,
2299 TRACE("[Thread %2u] learner %u (not finalized)\n",
2307 action_id = hit ? action_id : ts->default_action_id;
2308 action_data = hit ? action_data : ts->default_action_data;
2309 n_pkts_hit = stats->n_pkts_hit[hit];
2310 n_pkts_action = stats->n_pkts_action[action_id];
2312 TRACE("[Thread %2u] learner %u (%s, action %u)\n",
2315 hit ? "hit" : "miss",
2316 (uint32_t)action_id);
2318 t->action_id = action_id;
2319 t->structs[0] = action_data;
2321 t->learner_id = learner_id;
2323 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2324 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2327 thread_ip_action_call(p, t, action_id);
2333 static struct action *
2334 action_find(struct rte_swx_pipeline *p, const char *name);
2337 action_has_nbo_args(struct action *a);
2340 instr_learn_translate(struct rte_swx_pipeline *p,
2341 struct action *action,
2344 struct instruction *instr,
2345 struct instruction_data *data __rte_unused)
2349 CHECK(action, EINVAL);
2350 CHECK(n_tokens == 2, EINVAL);
2352 a = action_find(p, tokens[1]);
2354 CHECK(!action_has_nbo_args(a), EINVAL);
2356 instr->type = INSTR_LEARNER_LEARN;
2357 instr->learn.action_id = a->id;
2363 instr_learn_exec(struct rte_swx_pipeline *p)
2365 struct thread *t = &p->threads[p->thread_id];
2366 struct instruction *ip = t->ip;
2367 uint64_t action_id = ip->learn.action_id;
2368 uint32_t learner_id = t->learner_id;
2369 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2370 p->n_selectors + learner_id];
2371 struct learner_runtime *l = &t->learners[learner_id];
2372 struct learner_statistics *stats = &p->learner_stats[learner_id];
2376 status = rte_swx_table_learner_add(ts->obj,
2380 l->action_data[action_id]);
2382 TRACE("[Thread %2u] learner %u learn %s\n",
2385 status ? "ok" : "error");
2387 stats->n_pkts_learn[status] += 1;
2397 instr_forget_translate(struct rte_swx_pipeline *p __rte_unused,
2398 struct action *action,
2399 char **tokens __rte_unused,
2401 struct instruction *instr,
2402 struct instruction_data *data __rte_unused)
2404 CHECK(action, EINVAL);
2405 CHECK(n_tokens == 1, EINVAL);
2407 instr->type = INSTR_LEARNER_FORGET;
2413 instr_forget_exec(struct rte_swx_pipeline *p)
2415 struct thread *t = &p->threads[p->thread_id];
2416 uint32_t learner_id = t->learner_id;
2417 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2418 p->n_selectors + learner_id];
2419 struct learner_runtime *l = &t->learners[learner_id];
2420 struct learner_statistics *stats = &p->learner_stats[learner_id];
2423 rte_swx_table_learner_delete(ts->obj, l->mailbox);
2425 TRACE("[Thread %2u] learner %u forget\n",
2429 stats->n_pkts_forget += 1;
2439 instr_extern_translate(struct rte_swx_pipeline *p,
2440 struct action *action __rte_unused,
2443 struct instruction *instr,
2444 struct instruction_data *data __rte_unused)
2446 char *token = tokens[1];
2448 CHECK(n_tokens == 2, EINVAL);
2450 if (token[0] == 'e') {
2451 struct extern_obj *obj;
2452 struct extern_type_member_func *func;
2454 func = extern_obj_member_func_parse(p, token, &obj);
2455 CHECK(func, EINVAL);
2457 instr->type = INSTR_EXTERN_OBJ;
2458 instr->ext_obj.ext_obj_id = obj->id;
2459 instr->ext_obj.func_id = func->id;
2464 if (token[0] == 'f') {
2465 struct extern_func *func;
2467 func = extern_func_parse(p, token);
2468 CHECK(func, EINVAL);
2470 instr->type = INSTR_EXTERN_FUNC;
2471 instr->ext_func.ext_func_id = func->id;
2480 instr_extern_obj_exec(struct rte_swx_pipeline *p)
2482 struct thread *t = &p->threads[p->thread_id];
2483 struct instruction *ip = t->ip;
2484 uint32_t obj_id = ip->ext_obj.ext_obj_id;
2485 uint32_t func_id = ip->ext_obj.func_id;
2486 struct extern_obj_runtime *obj = &t->extern_objs[obj_id];
2487 rte_swx_extern_type_member_func_t func = obj->funcs[func_id];
2489 TRACE("[Thread %2u] extern obj %u member func %u\n",
2494 /* Extern object member function execute. */
2495 uint32_t done = func(obj->obj, obj->mailbox);
2498 thread_ip_inc_cond(t, done);
2499 thread_yield_cond(p, done ^ 1);
2503 instr_extern_func_exec(struct rte_swx_pipeline *p)
2505 struct thread *t = &p->threads[p->thread_id];
2506 struct instruction *ip = t->ip;
2507 uint32_t ext_func_id = ip->ext_func.ext_func_id;
2508 struct extern_func_runtime *ext_func = &t->extern_funcs[ext_func_id];
2509 rte_swx_extern_func_t func = ext_func->func;
2511 TRACE("[Thread %2u] extern func %u\n",
2515 /* Extern function execute. */
2516 uint32_t done = func(ext_func->mailbox);
2519 thread_ip_inc_cond(t, done);
2520 thread_yield_cond(p, done ^ 1);
2527 instr_mov_translate(struct rte_swx_pipeline *p,
2528 struct action *action,
2531 struct instruction *instr,
2532 struct instruction_data *data __rte_unused)
2534 char *dst = tokens[1], *src = tokens[2];
2535 struct field *fdst, *fsrc;
2537 uint32_t dst_struct_id = 0, src_struct_id = 0;
2539 CHECK(n_tokens == 3, EINVAL);
2541 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2542 CHECK(fdst, EINVAL);
2543 CHECK(!fdst->var_size, EINVAL);
2545 /* MOV, MOV_MH, MOV_HM or MOV_HH. */
2546 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2548 CHECK(!fsrc->var_size, EINVAL);
2550 instr->type = INSTR_MOV;
2551 if (dst[0] != 'h' && src[0] == 'h')
2552 instr->type = INSTR_MOV_MH;
2553 if (dst[0] == 'h' && src[0] != 'h')
2554 instr->type = INSTR_MOV_HM;
2555 if (dst[0] == 'h' && src[0] == 'h')
2556 instr->type = INSTR_MOV_HH;
2558 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
2559 instr->mov.dst.n_bits = fdst->n_bits;
2560 instr->mov.dst.offset = fdst->offset / 8;
2561 instr->mov.src.struct_id = (uint8_t)src_struct_id;
2562 instr->mov.src.n_bits = fsrc->n_bits;
2563 instr->mov.src.offset = fsrc->offset / 8;
2568 src_val = strtoull(src, &src, 0);
2569 CHECK(!src[0], EINVAL);
2572 src_val = hton64(src_val) >> (64 - fdst->n_bits);
2574 instr->type = INSTR_MOV_I;
2575 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
2576 instr->mov.dst.n_bits = fdst->n_bits;
2577 instr->mov.dst.offset = fdst->offset / 8;
2578 instr->mov.src_val = src_val;
2583 instr_mov_exec(struct rte_swx_pipeline *p)
2585 struct thread *t = &p->threads[p->thread_id];
2586 struct instruction *ip = t->ip;
2588 TRACE("[Thread %2u] mov\n",
2598 instr_mov_mh_exec(struct rte_swx_pipeline *p)
2600 struct thread *t = &p->threads[p->thread_id];
2601 struct instruction *ip = t->ip;
2603 TRACE("[Thread %2u] mov (mh)\n",
2613 instr_mov_hm_exec(struct rte_swx_pipeline *p)
2615 struct thread *t = &p->threads[p->thread_id];
2616 struct instruction *ip = t->ip;
2618 TRACE("[Thread %2u] mov (hm)\n",
2628 instr_mov_hh_exec(struct rte_swx_pipeline *p)
2630 struct thread *t = &p->threads[p->thread_id];
2631 struct instruction *ip = t->ip;
2633 TRACE("[Thread %2u] mov (hh)\n",
2643 instr_mov_i_exec(struct rte_swx_pipeline *p)
2645 struct thread *t = &p->threads[p->thread_id];
2646 struct instruction *ip = t->ip;
2648 TRACE("[Thread %2u] mov m.f %" PRIx64 "\n",
2662 __instr_dma_ht_exec(struct rte_swx_pipeline *p, uint32_t n_dma);
2665 __instr_dma_ht_exec(struct rte_swx_pipeline *p, uint32_t n_dma)
2667 struct thread *t = &p->threads[p->thread_id];
2668 struct instruction *ip = t->ip;
2669 uint8_t *action_data = t->structs[0];
2670 uint64_t valid_headers = t->valid_headers;
2673 for (i = 0; i < n_dma; i++) {
2674 uint32_t header_id = ip->dma.dst.header_id[i];
2675 uint32_t struct_id = ip->dma.dst.struct_id[i];
2676 uint32_t offset = ip->dma.src.offset[i];
2677 uint32_t n_bytes = ip->dma.n_bytes[i];
2679 struct header_runtime *h = &t->headers[header_id];
2680 uint8_t *h_ptr0 = h->ptr0;
2681 uint8_t *h_ptr = t->structs[struct_id];
2683 void *dst = MASK64_BIT_GET(valid_headers, header_id) ?
2685 void *src = &action_data[offset];
2687 TRACE("[Thread %2u] dma h.s t.f\n", p->thread_id);
2690 memcpy(dst, src, n_bytes);
2691 t->structs[struct_id] = dst;
2692 valid_headers = MASK64_BIT_SET(valid_headers, header_id);
2695 t->valid_headers = valid_headers;
2699 instr_dma_ht_exec(struct rte_swx_pipeline *p)
2701 __instr_dma_ht_exec(p, 1);
2708 instr_dma_ht2_exec(struct rte_swx_pipeline *p)
2710 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n",
2713 __instr_dma_ht_exec(p, 2);
2720 instr_dma_ht3_exec(struct rte_swx_pipeline *p)
2722 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n",
2725 __instr_dma_ht_exec(p, 3);
2732 instr_dma_ht4_exec(struct rte_swx_pipeline *p)
2734 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n",
2737 __instr_dma_ht_exec(p, 4);
2744 instr_dma_ht5_exec(struct rte_swx_pipeline *p)
2746 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n",
2749 __instr_dma_ht_exec(p, 5);
2756 instr_dma_ht6_exec(struct rte_swx_pipeline *p)
2758 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n",
2761 __instr_dma_ht_exec(p, 6);
2768 instr_dma_ht7_exec(struct rte_swx_pipeline *p)
2770 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n",
2773 __instr_dma_ht_exec(p, 7);
2780 instr_dma_ht8_exec(struct rte_swx_pipeline *p)
2782 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n",
2785 __instr_dma_ht_exec(p, 8);
2795 instr_alu_add_translate(struct rte_swx_pipeline *p,
2796 struct action *action,
2799 struct instruction *instr,
2800 struct instruction_data *data __rte_unused)
2802 char *dst = tokens[1], *src = tokens[2];
2803 struct field *fdst, *fsrc;
2805 uint32_t dst_struct_id = 0, src_struct_id = 0;
2807 CHECK(n_tokens == 3, EINVAL);
2809 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2810 CHECK(fdst, EINVAL);
2811 CHECK(!fdst->var_size, EINVAL);
2813 /* ADD, ADD_HM, ADD_MH, ADD_HH. */
2814 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2816 CHECK(!fsrc->var_size, EINVAL);
2818 instr->type = INSTR_ALU_ADD;
2819 if (dst[0] == 'h' && src[0] != 'h')
2820 instr->type = INSTR_ALU_ADD_HM;
2821 if (dst[0] != 'h' && src[0] == 'h')
2822 instr->type = INSTR_ALU_ADD_MH;
2823 if (dst[0] == 'h' && src[0] == 'h')
2824 instr->type = INSTR_ALU_ADD_HH;
2826 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2827 instr->alu.dst.n_bits = fdst->n_bits;
2828 instr->alu.dst.offset = fdst->offset / 8;
2829 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2830 instr->alu.src.n_bits = fsrc->n_bits;
2831 instr->alu.src.offset = fsrc->offset / 8;
2835 /* ADD_MI, ADD_HI. */
2836 src_val = strtoull(src, &src, 0);
2837 CHECK(!src[0], EINVAL);
2839 instr->type = INSTR_ALU_ADD_MI;
2841 instr->type = INSTR_ALU_ADD_HI;
2843 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2844 instr->alu.dst.n_bits = fdst->n_bits;
2845 instr->alu.dst.offset = fdst->offset / 8;
2846 instr->alu.src_val = src_val;
2851 instr_alu_sub_translate(struct rte_swx_pipeline *p,
2852 struct action *action,
2855 struct instruction *instr,
2856 struct instruction_data *data __rte_unused)
2858 char *dst = tokens[1], *src = tokens[2];
2859 struct field *fdst, *fsrc;
2861 uint32_t dst_struct_id = 0, src_struct_id = 0;
2863 CHECK(n_tokens == 3, EINVAL);
2865 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2866 CHECK(fdst, EINVAL);
2867 CHECK(!fdst->var_size, EINVAL);
2869 /* SUB, SUB_HM, SUB_MH, SUB_HH. */
2870 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2872 CHECK(!fsrc->var_size, EINVAL);
2874 instr->type = INSTR_ALU_SUB;
2875 if (dst[0] == 'h' && src[0] != 'h')
2876 instr->type = INSTR_ALU_SUB_HM;
2877 if (dst[0] != 'h' && src[0] == 'h')
2878 instr->type = INSTR_ALU_SUB_MH;
2879 if (dst[0] == 'h' && src[0] == 'h')
2880 instr->type = INSTR_ALU_SUB_HH;
2882 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2883 instr->alu.dst.n_bits = fdst->n_bits;
2884 instr->alu.dst.offset = fdst->offset / 8;
2885 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2886 instr->alu.src.n_bits = fsrc->n_bits;
2887 instr->alu.src.offset = fsrc->offset / 8;
2891 /* SUB_MI, SUB_HI. */
2892 src_val = strtoull(src, &src, 0);
2893 CHECK(!src[0], EINVAL);
2895 instr->type = INSTR_ALU_SUB_MI;
2897 instr->type = INSTR_ALU_SUB_HI;
2899 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2900 instr->alu.dst.n_bits = fdst->n_bits;
2901 instr->alu.dst.offset = fdst->offset / 8;
2902 instr->alu.src_val = src_val;
2907 instr_alu_ckadd_translate(struct rte_swx_pipeline *p,
2908 struct action *action __rte_unused,
2911 struct instruction *instr,
2912 struct instruction_data *data __rte_unused)
2914 char *dst = tokens[1], *src = tokens[2];
2915 struct header *hdst, *hsrc;
2916 struct field *fdst, *fsrc;
2918 CHECK(n_tokens == 3, EINVAL);
2920 fdst = header_field_parse(p, dst, &hdst);
2921 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
2922 CHECK(!fdst->var_size, EINVAL);
2925 fsrc = header_field_parse(p, src, &hsrc);
2927 CHECK(!fsrc->var_size, EINVAL);
2929 instr->type = INSTR_ALU_CKADD_FIELD;
2930 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2931 instr->alu.dst.n_bits = fdst->n_bits;
2932 instr->alu.dst.offset = fdst->offset / 8;
2933 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2934 instr->alu.src.n_bits = fsrc->n_bits;
2935 instr->alu.src.offset = fsrc->offset / 8;
2939 /* CKADD_STRUCT, CKADD_STRUCT20. */
2940 hsrc = header_parse(p, src);
2941 CHECK(hsrc, EINVAL);
2942 CHECK(!hsrc->st->var_size, EINVAL);
2944 instr->type = INSTR_ALU_CKADD_STRUCT;
2945 if ((hsrc->st->n_bits / 8) == 20)
2946 instr->type = INSTR_ALU_CKADD_STRUCT20;
2948 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2949 instr->alu.dst.n_bits = fdst->n_bits;
2950 instr->alu.dst.offset = fdst->offset / 8;
2951 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2952 instr->alu.src.n_bits = hsrc->st->n_bits;
2953 instr->alu.src.offset = 0; /* Unused. */
2958 instr_alu_cksub_translate(struct rte_swx_pipeline *p,
2959 struct action *action __rte_unused,
2962 struct instruction *instr,
2963 struct instruction_data *data __rte_unused)
2965 char *dst = tokens[1], *src = tokens[2];
2966 struct header *hdst, *hsrc;
2967 struct field *fdst, *fsrc;
2969 CHECK(n_tokens == 3, EINVAL);
2971 fdst = header_field_parse(p, dst, &hdst);
2972 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
2973 CHECK(!fdst->var_size, EINVAL);
2975 fsrc = header_field_parse(p, src, &hsrc);
2976 CHECK(fsrc, EINVAL);
2977 CHECK(!fsrc->var_size, EINVAL);
2979 instr->type = INSTR_ALU_CKSUB_FIELD;
2980 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2981 instr->alu.dst.n_bits = fdst->n_bits;
2982 instr->alu.dst.offset = fdst->offset / 8;
2983 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2984 instr->alu.src.n_bits = fsrc->n_bits;
2985 instr->alu.src.offset = fsrc->offset / 8;
2990 instr_alu_shl_translate(struct rte_swx_pipeline *p,
2991 struct action *action,
2994 struct instruction *instr,
2995 struct instruction_data *data __rte_unused)
2997 char *dst = tokens[1], *src = tokens[2];
2998 struct field *fdst, *fsrc;
3000 uint32_t dst_struct_id = 0, src_struct_id = 0;
3002 CHECK(n_tokens == 3, EINVAL);
3004 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3005 CHECK(fdst, EINVAL);
3006 CHECK(!fdst->var_size, EINVAL);
3008 /* SHL, SHL_HM, SHL_MH, SHL_HH. */
3009 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3011 CHECK(!fsrc->var_size, EINVAL);
3013 instr->type = INSTR_ALU_SHL;
3014 if (dst[0] == 'h' && src[0] != 'h')
3015 instr->type = INSTR_ALU_SHL_HM;
3016 if (dst[0] != 'h' && src[0] == 'h')
3017 instr->type = INSTR_ALU_SHL_MH;
3018 if (dst[0] == 'h' && src[0] == 'h')
3019 instr->type = INSTR_ALU_SHL_HH;
3021 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3022 instr->alu.dst.n_bits = fdst->n_bits;
3023 instr->alu.dst.offset = fdst->offset / 8;
3024 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3025 instr->alu.src.n_bits = fsrc->n_bits;
3026 instr->alu.src.offset = fsrc->offset / 8;
3030 /* SHL_MI, SHL_HI. */
3031 src_val = strtoull(src, &src, 0);
3032 CHECK(!src[0], EINVAL);
3034 instr->type = INSTR_ALU_SHL_MI;
3036 instr->type = INSTR_ALU_SHL_HI;
3038 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3039 instr->alu.dst.n_bits = fdst->n_bits;
3040 instr->alu.dst.offset = fdst->offset / 8;
3041 instr->alu.src_val = src_val;
3046 instr_alu_shr_translate(struct rte_swx_pipeline *p,
3047 struct action *action,
3050 struct instruction *instr,
3051 struct instruction_data *data __rte_unused)
3053 char *dst = tokens[1], *src = tokens[2];
3054 struct field *fdst, *fsrc;
3056 uint32_t dst_struct_id = 0, src_struct_id = 0;
3058 CHECK(n_tokens == 3, EINVAL);
3060 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3061 CHECK(fdst, EINVAL);
3062 CHECK(!fdst->var_size, EINVAL);
3064 /* SHR, SHR_HM, SHR_MH, SHR_HH. */
3065 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3067 CHECK(!fsrc->var_size, EINVAL);
3069 instr->type = INSTR_ALU_SHR;
3070 if (dst[0] == 'h' && src[0] != 'h')
3071 instr->type = INSTR_ALU_SHR_HM;
3072 if (dst[0] != 'h' && src[0] == 'h')
3073 instr->type = INSTR_ALU_SHR_MH;
3074 if (dst[0] == 'h' && src[0] == 'h')
3075 instr->type = INSTR_ALU_SHR_HH;
3077 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3078 instr->alu.dst.n_bits = fdst->n_bits;
3079 instr->alu.dst.offset = fdst->offset / 8;
3080 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3081 instr->alu.src.n_bits = fsrc->n_bits;
3082 instr->alu.src.offset = fsrc->offset / 8;
3086 /* SHR_MI, SHR_HI. */
3087 src_val = strtoull(src, &src, 0);
3088 CHECK(!src[0], EINVAL);
3090 instr->type = INSTR_ALU_SHR_MI;
3092 instr->type = INSTR_ALU_SHR_HI;
3094 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3095 instr->alu.dst.n_bits = fdst->n_bits;
3096 instr->alu.dst.offset = fdst->offset / 8;
3097 instr->alu.src_val = src_val;
3102 instr_alu_and_translate(struct rte_swx_pipeline *p,
3103 struct action *action,
3106 struct instruction *instr,
3107 struct instruction_data *data __rte_unused)
3109 char *dst = tokens[1], *src = tokens[2];
3110 struct field *fdst, *fsrc;
3112 uint32_t dst_struct_id = 0, src_struct_id = 0;
3114 CHECK(n_tokens == 3, EINVAL);
3116 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3117 CHECK(fdst, EINVAL);
3118 CHECK(!fdst->var_size, EINVAL);
3120 /* AND, AND_MH, AND_HM, AND_HH. */
3121 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3123 CHECK(!fsrc->var_size, EINVAL);
3125 instr->type = INSTR_ALU_AND;
3126 if (dst[0] != 'h' && src[0] == 'h')
3127 instr->type = INSTR_ALU_AND_MH;
3128 if (dst[0] == 'h' && src[0] != 'h')
3129 instr->type = INSTR_ALU_AND_HM;
3130 if (dst[0] == 'h' && src[0] == 'h')
3131 instr->type = INSTR_ALU_AND_HH;
3133 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3134 instr->alu.dst.n_bits = fdst->n_bits;
3135 instr->alu.dst.offset = fdst->offset / 8;
3136 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3137 instr->alu.src.n_bits = fsrc->n_bits;
3138 instr->alu.src.offset = fsrc->offset / 8;
3143 src_val = strtoull(src, &src, 0);
3144 CHECK(!src[0], EINVAL);
3147 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3149 instr->type = INSTR_ALU_AND_I;
3150 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3151 instr->alu.dst.n_bits = fdst->n_bits;
3152 instr->alu.dst.offset = fdst->offset / 8;
3153 instr->alu.src_val = src_val;
3158 instr_alu_or_translate(struct rte_swx_pipeline *p,
3159 struct action *action,
3162 struct instruction *instr,
3163 struct instruction_data *data __rte_unused)
3165 char *dst = tokens[1], *src = tokens[2];
3166 struct field *fdst, *fsrc;
3168 uint32_t dst_struct_id = 0, src_struct_id = 0;
3170 CHECK(n_tokens == 3, EINVAL);
3172 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3173 CHECK(fdst, EINVAL);
3174 CHECK(!fdst->var_size, EINVAL);
3176 /* OR, OR_MH, OR_HM, OR_HH. */
3177 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3179 CHECK(!fsrc->var_size, EINVAL);
3181 instr->type = INSTR_ALU_OR;
3182 if (dst[0] != 'h' && src[0] == 'h')
3183 instr->type = INSTR_ALU_OR_MH;
3184 if (dst[0] == 'h' && src[0] != 'h')
3185 instr->type = INSTR_ALU_OR_HM;
3186 if (dst[0] == 'h' && src[0] == 'h')
3187 instr->type = INSTR_ALU_OR_HH;
3189 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3190 instr->alu.dst.n_bits = fdst->n_bits;
3191 instr->alu.dst.offset = fdst->offset / 8;
3192 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3193 instr->alu.src.n_bits = fsrc->n_bits;
3194 instr->alu.src.offset = fsrc->offset / 8;
3199 src_val = strtoull(src, &src, 0);
3200 CHECK(!src[0], EINVAL);
3203 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3205 instr->type = INSTR_ALU_OR_I;
3206 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3207 instr->alu.dst.n_bits = fdst->n_bits;
3208 instr->alu.dst.offset = fdst->offset / 8;
3209 instr->alu.src_val = src_val;
3214 instr_alu_xor_translate(struct rte_swx_pipeline *p,
3215 struct action *action,
3218 struct instruction *instr,
3219 struct instruction_data *data __rte_unused)
3221 char *dst = tokens[1], *src = tokens[2];
3222 struct field *fdst, *fsrc;
3224 uint32_t dst_struct_id = 0, src_struct_id = 0;
3226 CHECK(n_tokens == 3, EINVAL);
3228 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3229 CHECK(fdst, EINVAL);
3230 CHECK(!fdst->var_size, EINVAL);
3232 /* XOR, XOR_MH, XOR_HM, XOR_HH. */
3233 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3235 CHECK(!fsrc->var_size, EINVAL);
3237 instr->type = INSTR_ALU_XOR;
3238 if (dst[0] != 'h' && src[0] == 'h')
3239 instr->type = INSTR_ALU_XOR_MH;
3240 if (dst[0] == 'h' && src[0] != 'h')
3241 instr->type = INSTR_ALU_XOR_HM;
3242 if (dst[0] == 'h' && src[0] == 'h')
3243 instr->type = INSTR_ALU_XOR_HH;
3245 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3246 instr->alu.dst.n_bits = fdst->n_bits;
3247 instr->alu.dst.offset = fdst->offset / 8;
3248 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3249 instr->alu.src.n_bits = fsrc->n_bits;
3250 instr->alu.src.offset = fsrc->offset / 8;
3255 src_val = strtoull(src, &src, 0);
3256 CHECK(!src[0], EINVAL);
3259 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3261 instr->type = INSTR_ALU_XOR_I;
3262 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3263 instr->alu.dst.n_bits = fdst->n_bits;
3264 instr->alu.dst.offset = fdst->offset / 8;
3265 instr->alu.src_val = src_val;
3270 instr_alu_add_exec(struct rte_swx_pipeline *p)
3272 struct thread *t = &p->threads[p->thread_id];
3273 struct instruction *ip = t->ip;
3275 TRACE("[Thread %2u] add\n", p->thread_id);
3285 instr_alu_add_mh_exec(struct rte_swx_pipeline *p)
3287 struct thread *t = &p->threads[p->thread_id];
3288 struct instruction *ip = t->ip;
3290 TRACE("[Thread %2u] add (mh)\n", p->thread_id);
3300 instr_alu_add_hm_exec(struct rte_swx_pipeline *p)
3302 struct thread *t = &p->threads[p->thread_id];
3303 struct instruction *ip = t->ip;
3305 TRACE("[Thread %2u] add (hm)\n", p->thread_id);
3315 instr_alu_add_hh_exec(struct rte_swx_pipeline *p)
3317 struct thread *t = &p->threads[p->thread_id];
3318 struct instruction *ip = t->ip;
3320 TRACE("[Thread %2u] add (hh)\n", p->thread_id);
3330 instr_alu_add_mi_exec(struct rte_swx_pipeline *p)
3332 struct thread *t = &p->threads[p->thread_id];
3333 struct instruction *ip = t->ip;
3335 TRACE("[Thread %2u] add (mi)\n", p->thread_id);
3345 instr_alu_add_hi_exec(struct rte_swx_pipeline *p)
3347 struct thread *t = &p->threads[p->thread_id];
3348 struct instruction *ip = t->ip;
3350 TRACE("[Thread %2u] add (hi)\n", p->thread_id);
3360 instr_alu_sub_exec(struct rte_swx_pipeline *p)
3362 struct thread *t = &p->threads[p->thread_id];
3363 struct instruction *ip = t->ip;
3365 TRACE("[Thread %2u] sub\n", p->thread_id);
3375 instr_alu_sub_mh_exec(struct rte_swx_pipeline *p)
3377 struct thread *t = &p->threads[p->thread_id];
3378 struct instruction *ip = t->ip;
3380 TRACE("[Thread %2u] sub (mh)\n", p->thread_id);
3390 instr_alu_sub_hm_exec(struct rte_swx_pipeline *p)
3392 struct thread *t = &p->threads[p->thread_id];
3393 struct instruction *ip = t->ip;
3395 TRACE("[Thread %2u] sub (hm)\n", p->thread_id);
3405 instr_alu_sub_hh_exec(struct rte_swx_pipeline *p)
3407 struct thread *t = &p->threads[p->thread_id];
3408 struct instruction *ip = t->ip;
3410 TRACE("[Thread %2u] sub (hh)\n", p->thread_id);
3420 instr_alu_sub_mi_exec(struct rte_swx_pipeline *p)
3422 struct thread *t = &p->threads[p->thread_id];
3423 struct instruction *ip = t->ip;
3425 TRACE("[Thread %2u] sub (mi)\n", p->thread_id);
3435 instr_alu_sub_hi_exec(struct rte_swx_pipeline *p)
3437 struct thread *t = &p->threads[p->thread_id];
3438 struct instruction *ip = t->ip;
3440 TRACE("[Thread %2u] sub (hi)\n", p->thread_id);
3450 instr_alu_shl_exec(struct rte_swx_pipeline *p)
3452 struct thread *t = &p->threads[p->thread_id];
3453 struct instruction *ip = t->ip;
3455 TRACE("[Thread %2u] shl\n", p->thread_id);
3465 instr_alu_shl_mh_exec(struct rte_swx_pipeline *p)
3467 struct thread *t = &p->threads[p->thread_id];
3468 struct instruction *ip = t->ip;
3470 TRACE("[Thread %2u] shl (mh)\n", p->thread_id);
3480 instr_alu_shl_hm_exec(struct rte_swx_pipeline *p)
3482 struct thread *t = &p->threads[p->thread_id];
3483 struct instruction *ip = t->ip;
3485 TRACE("[Thread %2u] shl (hm)\n", p->thread_id);
3495 instr_alu_shl_hh_exec(struct rte_swx_pipeline *p)
3497 struct thread *t = &p->threads[p->thread_id];
3498 struct instruction *ip = t->ip;
3500 TRACE("[Thread %2u] shl (hh)\n", p->thread_id);
3510 instr_alu_shl_mi_exec(struct rte_swx_pipeline *p)
3512 struct thread *t = &p->threads[p->thread_id];
3513 struct instruction *ip = t->ip;
3515 TRACE("[Thread %2u] shl (mi)\n", p->thread_id);
3525 instr_alu_shl_hi_exec(struct rte_swx_pipeline *p)
3527 struct thread *t = &p->threads[p->thread_id];
3528 struct instruction *ip = t->ip;
3530 TRACE("[Thread %2u] shl (hi)\n", p->thread_id);
3540 instr_alu_shr_exec(struct rte_swx_pipeline *p)
3542 struct thread *t = &p->threads[p->thread_id];
3543 struct instruction *ip = t->ip;
3545 TRACE("[Thread %2u] shr\n", p->thread_id);
3555 instr_alu_shr_mh_exec(struct rte_swx_pipeline *p)
3557 struct thread *t = &p->threads[p->thread_id];
3558 struct instruction *ip = t->ip;
3560 TRACE("[Thread %2u] shr (mh)\n", p->thread_id);
3570 instr_alu_shr_hm_exec(struct rte_swx_pipeline *p)
3572 struct thread *t = &p->threads[p->thread_id];
3573 struct instruction *ip = t->ip;
3575 TRACE("[Thread %2u] shr (hm)\n", p->thread_id);
3585 instr_alu_shr_hh_exec(struct rte_swx_pipeline *p)
3587 struct thread *t = &p->threads[p->thread_id];
3588 struct instruction *ip = t->ip;
3590 TRACE("[Thread %2u] shr (hh)\n", p->thread_id);
3600 instr_alu_shr_mi_exec(struct rte_swx_pipeline *p)
3602 struct thread *t = &p->threads[p->thread_id];
3603 struct instruction *ip = t->ip;
3605 TRACE("[Thread %2u] shr (mi)\n", p->thread_id);
3615 instr_alu_shr_hi_exec(struct rte_swx_pipeline *p)
3617 struct thread *t = &p->threads[p->thread_id];
3618 struct instruction *ip = t->ip;
3620 TRACE("[Thread %2u] shr (hi)\n", p->thread_id);
3630 instr_alu_and_exec(struct rte_swx_pipeline *p)
3632 struct thread *t = &p->threads[p->thread_id];
3633 struct instruction *ip = t->ip;
3635 TRACE("[Thread %2u] and\n", p->thread_id);
3645 instr_alu_and_mh_exec(struct rte_swx_pipeline *p)
3647 struct thread *t = &p->threads[p->thread_id];
3648 struct instruction *ip = t->ip;
3650 TRACE("[Thread %2u] and (mh)\n", p->thread_id);
3660 instr_alu_and_hm_exec(struct rte_swx_pipeline *p)
3662 struct thread *t = &p->threads[p->thread_id];
3663 struct instruction *ip = t->ip;
3665 TRACE("[Thread %2u] and (hm)\n", p->thread_id);
3668 ALU_HM_FAST(t, ip, &);
3675 instr_alu_and_hh_exec(struct rte_swx_pipeline *p)
3677 struct thread *t = &p->threads[p->thread_id];
3678 struct instruction *ip = t->ip;
3680 TRACE("[Thread %2u] and (hh)\n", p->thread_id);
3683 ALU_HH_FAST(t, ip, &);
3690 instr_alu_and_i_exec(struct rte_swx_pipeline *p)
3692 struct thread *t = &p->threads[p->thread_id];
3693 struct instruction *ip = t->ip;
3695 TRACE("[Thread %2u] and (i)\n", p->thread_id);
3705 instr_alu_or_exec(struct rte_swx_pipeline *p)
3707 struct thread *t = &p->threads[p->thread_id];
3708 struct instruction *ip = t->ip;
3710 TRACE("[Thread %2u] or\n", p->thread_id);
3720 instr_alu_or_mh_exec(struct rte_swx_pipeline *p)
3722 struct thread *t = &p->threads[p->thread_id];
3723 struct instruction *ip = t->ip;
3725 TRACE("[Thread %2u] or (mh)\n", p->thread_id);
3735 instr_alu_or_hm_exec(struct rte_swx_pipeline *p)
3737 struct thread *t = &p->threads[p->thread_id];
3738 struct instruction *ip = t->ip;
3740 TRACE("[Thread %2u] or (hm)\n", p->thread_id);
3743 ALU_HM_FAST(t, ip, |);
3750 instr_alu_or_hh_exec(struct rte_swx_pipeline *p)
3752 struct thread *t = &p->threads[p->thread_id];
3753 struct instruction *ip = t->ip;
3755 TRACE("[Thread %2u] or (hh)\n", p->thread_id);
3758 ALU_HH_FAST(t, ip, |);
3765 instr_alu_or_i_exec(struct rte_swx_pipeline *p)
3767 struct thread *t = &p->threads[p->thread_id];
3768 struct instruction *ip = t->ip;
3770 TRACE("[Thread %2u] or (i)\n", p->thread_id);
3780 instr_alu_xor_exec(struct rte_swx_pipeline *p)
3782 struct thread *t = &p->threads[p->thread_id];
3783 struct instruction *ip = t->ip;
3785 TRACE("[Thread %2u] xor\n", p->thread_id);
3795 instr_alu_xor_mh_exec(struct rte_swx_pipeline *p)
3797 struct thread *t = &p->threads[p->thread_id];
3798 struct instruction *ip = t->ip;
3800 TRACE("[Thread %2u] xor (mh)\n", p->thread_id);
3810 instr_alu_xor_hm_exec(struct rte_swx_pipeline *p)
3812 struct thread *t = &p->threads[p->thread_id];
3813 struct instruction *ip = t->ip;
3815 TRACE("[Thread %2u] xor (hm)\n", p->thread_id);
3818 ALU_HM_FAST(t, ip, ^);
3825 instr_alu_xor_hh_exec(struct rte_swx_pipeline *p)
3827 struct thread *t = &p->threads[p->thread_id];
3828 struct instruction *ip = t->ip;
3830 TRACE("[Thread %2u] xor (hh)\n", p->thread_id);
3833 ALU_HH_FAST(t, ip, ^);
3840 instr_alu_xor_i_exec(struct rte_swx_pipeline *p)
3842 struct thread *t = &p->threads[p->thread_id];
3843 struct instruction *ip = t->ip;
3845 TRACE("[Thread %2u] xor (i)\n", p->thread_id);
3855 instr_alu_ckadd_field_exec(struct rte_swx_pipeline *p)
3857 struct thread *t = &p->threads[p->thread_id];
3858 struct instruction *ip = t->ip;
3859 uint8_t *dst_struct, *src_struct;
3860 uint16_t *dst16_ptr, dst;
3861 uint64_t *src64_ptr, src64, src64_mask, src;
3864 TRACE("[Thread %2u] ckadd (field)\n", p->thread_id);
3867 dst_struct = t->structs[ip->alu.dst.struct_id];
3868 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
3871 src_struct = t->structs[ip->alu.src.struct_id];
3872 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
3874 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
3875 src = src64 & src64_mask;
3880 /* The first input (r) is a 16-bit number. The second and the third
3881 * inputs are 32-bit numbers. In the worst case scenario, the sum of the
3882 * three numbers (output r) is a 34-bit number.
3884 r += (src >> 32) + (src & 0xFFFFFFFF);
3886 /* The first input is a 16-bit number. The second input is an 18-bit
3887 * number. In the worst case scenario, the sum of the two numbers is a
3890 r = (r & 0xFFFF) + (r >> 16);
3892 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
3893 * a 3-bit number (0 .. 7). Their sum is a 17-bit number (0 .. 0x10006).
3895 r = (r & 0xFFFF) + (r >> 16);
3897 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
3898 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
3899 * 0x10006), the output r is (0 .. 7). So no carry bit can be generated,
3900 * therefore the output r is always a 16-bit number.
3902 r = (r & 0xFFFF) + (r >> 16);
3907 *dst16_ptr = (uint16_t)r;
3914 instr_alu_cksub_field_exec(struct rte_swx_pipeline *p)
3916 struct thread *t = &p->threads[p->thread_id];
3917 struct instruction *ip = t->ip;
3918 uint8_t *dst_struct, *src_struct;
3919 uint16_t *dst16_ptr, dst;
3920 uint64_t *src64_ptr, src64, src64_mask, src;
3923 TRACE("[Thread %2u] cksub (field)\n", p->thread_id);
3926 dst_struct = t->structs[ip->alu.dst.struct_id];
3927 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
3930 src_struct = t->structs[ip->alu.src.struct_id];
3931 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
3933 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
3934 src = src64 & src64_mask;
3939 /* Subtraction in 1's complement arithmetic (i.e. a '- b) is the same as
3940 * the following sequence of operations in 2's complement arithmetic:
3941 * a '- b = (a - b) % 0xFFFF.
3943 * In order to prevent an underflow for the below subtraction, in which
3944 * a 33-bit number (the subtrahend) is taken out of a 16-bit number (the
3945 * minuend), we first add a multiple of the 0xFFFF modulus to the
3946 * minuend. The number we add to the minuend needs to be a 34-bit number
3947 * or higher, so for readability reasons we picked the 36-bit multiple.
3948 * We are effectively turning the 16-bit minuend into a 36-bit number:
3949 * (a - b) % 0xFFFF = (a + 0xFFFF00000 - b) % 0xFFFF.
3951 r += 0xFFFF00000ULL; /* The output r is a 36-bit number. */
3953 /* A 33-bit number is subtracted from a 36-bit number (the input r). The
3954 * result (the output r) is a 36-bit number.
3956 r -= (src >> 32) + (src & 0xFFFFFFFF);
3958 /* The first input is a 16-bit number. The second input is a 20-bit
3959 * number. Their sum is a 21-bit number.
3961 r = (r & 0xFFFF) + (r >> 16);
3963 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
3964 * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1001E).
3966 r = (r & 0xFFFF) + (r >> 16);
3968 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
3969 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
3970 * 0x1001E), the output r is (0 .. 31). So no carry bit can be
3971 * generated, therefore the output r is always a 16-bit number.
3973 r = (r & 0xFFFF) + (r >> 16);
3978 *dst16_ptr = (uint16_t)r;
3985 instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline *p)
3987 struct thread *t = &p->threads[p->thread_id];
3988 struct instruction *ip = t->ip;
3989 uint8_t *dst_struct, *src_struct;
3990 uint16_t *dst16_ptr;
3991 uint32_t *src32_ptr;
3994 TRACE("[Thread %2u] ckadd (struct of 20 bytes)\n", p->thread_id);
3997 dst_struct = t->structs[ip->alu.dst.struct_id];
3998 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
4000 src_struct = t->structs[ip->alu.src.struct_id];
4001 src32_ptr = (uint32_t *)&src_struct[0];
4003 r0 = src32_ptr[0]; /* r0 is a 32-bit number. */
4004 r1 = src32_ptr[1]; /* r1 is a 32-bit number. */
4005 r0 += src32_ptr[2]; /* The output r0 is a 33-bit number. */
4006 r1 += src32_ptr[3]; /* The output r1 is a 33-bit number. */
4007 r0 += r1 + src32_ptr[4]; /* The output r0 is a 35-bit number. */
4009 /* The first input is a 16-bit number. The second input is a 19-bit
4010 * number. Their sum is a 20-bit number.
4012 r0 = (r0 & 0xFFFF) + (r0 >> 16);
4014 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
4015 * a 4-bit number (0 .. 15). The sum is a 17-bit number (0 .. 0x1000E).
4017 r0 = (r0 & 0xFFFF) + (r0 >> 16);
4019 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
4020 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
4021 * 0x1000E), the output r is (0 .. 15). So no carry bit can be
4022 * generated, therefore the output r is always a 16-bit number.
4024 r0 = (r0 & 0xFFFF) + (r0 >> 16);
4027 r0 = r0 ? r0 : 0xFFFF;
4029 *dst16_ptr = (uint16_t)r0;
4036 instr_alu_ckadd_struct_exec(struct rte_swx_pipeline *p)
4038 struct thread *t = &p->threads[p->thread_id];
4039 struct instruction *ip = t->ip;
4040 uint8_t *dst_struct, *src_struct;
4041 uint16_t *dst16_ptr;
4042 uint32_t *src32_ptr;
4046 TRACE("[Thread %2u] ckadd (struct)\n", p->thread_id);
4049 dst_struct = t->structs[ip->alu.dst.struct_id];
4050 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
4052 src_struct = t->structs[ip->alu.src.struct_id];
4053 src32_ptr = (uint32_t *)&src_struct[0];
4055 /* The max number of 32-bit words in a 256-byte header is 8 = 2^3.
4056 * Therefore, in the worst case scenario, a 35-bit number is added to a
4057 * 16-bit number (the input r), so the output r is 36-bit number.
4059 for (i = 0; i < ip->alu.src.n_bits / 32; i++, src32_ptr++)
4062 /* The first input is a 16-bit number. The second input is a 20-bit
4063 * number. Their sum is a 21-bit number.
4065 r = (r & 0xFFFF) + (r >> 16);
4067 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
4068 * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1000E).
4070 r = (r & 0xFFFF) + (r >> 16);
4072 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
4073 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
4074 * 0x1001E), the output r is (0 .. 31). So no carry bit can be
4075 * generated, therefore the output r is always a 16-bit number.
4077 r = (r & 0xFFFF) + (r >> 16);
4082 *dst16_ptr = (uint16_t)r;
4091 static struct regarray *
4092 regarray_find(struct rte_swx_pipeline *p, const char *name);
4095 instr_regprefetch_translate(struct rte_swx_pipeline *p,
4096 struct action *action,
4099 struct instruction *instr,
4100 struct instruction_data *data __rte_unused)
4102 char *regarray = tokens[1], *idx = tokens[2];
4105 uint32_t idx_struct_id, idx_val;
4107 CHECK(n_tokens == 3, EINVAL);
4109 r = regarray_find(p, regarray);
4112 /* REGPREFETCH_RH, REGPREFETCH_RM. */
4113 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4115 CHECK(!fidx->var_size, EINVAL);
4117 instr->type = INSTR_REGPREFETCH_RM;
4119 instr->type = INSTR_REGPREFETCH_RH;
4121 instr->regarray.regarray_id = r->id;
4122 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4123 instr->regarray.idx.n_bits = fidx->n_bits;
4124 instr->regarray.idx.offset = fidx->offset / 8;
4125 instr->regarray.dstsrc_val = 0; /* Unused. */
4129 /* REGPREFETCH_RI. */
4130 idx_val = strtoul(idx, &idx, 0);
4131 CHECK(!idx[0], EINVAL);
4133 instr->type = INSTR_REGPREFETCH_RI;
4134 instr->regarray.regarray_id = r->id;
4135 instr->regarray.idx_val = idx_val;
4136 instr->regarray.dstsrc_val = 0; /* Unused. */
4141 instr_regrd_translate(struct rte_swx_pipeline *p,
4142 struct action *action,
4145 struct instruction *instr,
4146 struct instruction_data *data __rte_unused)
4148 char *dst = tokens[1], *regarray = tokens[2], *idx = tokens[3];
4150 struct field *fdst, *fidx;
4151 uint32_t dst_struct_id, idx_struct_id, idx_val;
4153 CHECK(n_tokens == 4, EINVAL);
4155 r = regarray_find(p, regarray);
4158 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4159 CHECK(fdst, EINVAL);
4160 CHECK(!fdst->var_size, EINVAL);
4162 /* REGRD_HRH, REGRD_HRM, REGRD_MRH, REGRD_MRM. */
4163 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4165 CHECK(!fidx->var_size, EINVAL);
4167 instr->type = INSTR_REGRD_MRM;
4168 if (dst[0] == 'h' && idx[0] != 'h')
4169 instr->type = INSTR_REGRD_HRM;
4170 if (dst[0] != 'h' && idx[0] == 'h')
4171 instr->type = INSTR_REGRD_MRH;
4172 if (dst[0] == 'h' && idx[0] == 'h')
4173 instr->type = INSTR_REGRD_HRH;
4175 instr->regarray.regarray_id = r->id;
4176 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4177 instr->regarray.idx.n_bits = fidx->n_bits;
4178 instr->regarray.idx.offset = fidx->offset / 8;
4179 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
4180 instr->regarray.dstsrc.n_bits = fdst->n_bits;
4181 instr->regarray.dstsrc.offset = fdst->offset / 8;
4185 /* REGRD_MRI, REGRD_HRI. */
4186 idx_val = strtoul(idx, &idx, 0);
4187 CHECK(!idx[0], EINVAL);
4189 instr->type = INSTR_REGRD_MRI;
4191 instr->type = INSTR_REGRD_HRI;
4193 instr->regarray.regarray_id = r->id;
4194 instr->regarray.idx_val = idx_val;
4195 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
4196 instr->regarray.dstsrc.n_bits = fdst->n_bits;
4197 instr->regarray.dstsrc.offset = fdst->offset / 8;
4202 instr_regwr_translate(struct rte_swx_pipeline *p,
4203 struct action *action,
4206 struct instruction *instr,
4207 struct instruction_data *data __rte_unused)
4209 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
4211 struct field *fidx, *fsrc;
4213 uint32_t idx_struct_id, idx_val, src_struct_id;
4215 CHECK(n_tokens == 4, EINVAL);
4217 r = regarray_find(p, regarray);
4220 /* REGWR_RHH, REGWR_RHM, REGWR_RMH, REGWR_RMM. */
4221 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4222 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4224 CHECK(!fidx->var_size, EINVAL);
4225 CHECK(!fsrc->var_size, EINVAL);
4227 instr->type = INSTR_REGWR_RMM;
4228 if (idx[0] == 'h' && src[0] != 'h')
4229 instr->type = INSTR_REGWR_RHM;
4230 if (idx[0] != 'h' && src[0] == 'h')
4231 instr->type = INSTR_REGWR_RMH;
4232 if (idx[0] == 'h' && src[0] == 'h')
4233 instr->type = INSTR_REGWR_RHH;
4235 instr->regarray.regarray_id = r->id;
4236 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4237 instr->regarray.idx.n_bits = fidx->n_bits;
4238 instr->regarray.idx.offset = fidx->offset / 8;
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;
4245 /* REGWR_RHI, REGWR_RMI. */
4246 if (fidx && !fsrc) {
4247 CHECK(!fidx->var_size, EINVAL);
4249 src_val = strtoull(src, &src, 0);
4250 CHECK(!src[0], EINVAL);
4252 instr->type = INSTR_REGWR_RMI;
4254 instr->type = INSTR_REGWR_RHI;
4256 instr->regarray.regarray_id = r->id;
4257 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4258 instr->regarray.idx.n_bits = fidx->n_bits;
4259 instr->regarray.idx.offset = fidx->offset / 8;
4260 instr->regarray.dstsrc_val = src_val;
4264 /* REGWR_RIH, REGWR_RIM. */
4265 if (!fidx && fsrc) {
4266 idx_val = strtoul(idx, &idx, 0);
4267 CHECK(!idx[0], EINVAL);
4269 CHECK(!fsrc->var_size, EINVAL);
4271 instr->type = INSTR_REGWR_RIM;
4273 instr->type = INSTR_REGWR_RIH;
4275 instr->regarray.regarray_id = r->id;
4276 instr->regarray.idx_val = idx_val;
4277 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4278 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4279 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4284 src_val = strtoull(src, &src, 0);
4285 CHECK(!src[0], EINVAL);
4287 idx_val = strtoul(idx, &idx, 0);
4288 CHECK(!idx[0], EINVAL);
4290 instr->type = INSTR_REGWR_RII;
4291 instr->regarray.idx_val = idx_val;
4292 instr->regarray.dstsrc_val = src_val;
4298 instr_regadd_translate(struct rte_swx_pipeline *p,
4299 struct action *action,
4302 struct instruction *instr,
4303 struct instruction_data *data __rte_unused)
4305 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
4307 struct field *fidx, *fsrc;
4309 uint32_t idx_struct_id, idx_val, src_struct_id;
4311 CHECK(n_tokens == 4, EINVAL);
4313 r = regarray_find(p, regarray);
4316 /* REGADD_RHH, REGADD_RHM, REGADD_RMH, REGADD_RMM. */
4317 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4318 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4320 CHECK(!fidx->var_size, EINVAL);
4321 CHECK(!fsrc->var_size, EINVAL);
4323 instr->type = INSTR_REGADD_RMM;
4324 if (idx[0] == 'h' && src[0] != 'h')
4325 instr->type = INSTR_REGADD_RHM;
4326 if (idx[0] != 'h' && src[0] == 'h')
4327 instr->type = INSTR_REGADD_RMH;
4328 if (idx[0] == 'h' && src[0] == 'h')
4329 instr->type = INSTR_REGADD_RHH;
4331 instr->regarray.regarray_id = r->id;
4332 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4333 instr->regarray.idx.n_bits = fidx->n_bits;
4334 instr->regarray.idx.offset = fidx->offset / 8;
4335 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4336 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4337 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4341 /* REGADD_RHI, REGADD_RMI. */
4342 if (fidx && !fsrc) {
4343 CHECK(!fidx->var_size, EINVAL);
4345 src_val = strtoull(src, &src, 0);
4346 CHECK(!src[0], EINVAL);
4348 instr->type = INSTR_REGADD_RMI;
4350 instr->type = INSTR_REGADD_RHI;
4352 instr->regarray.regarray_id = r->id;
4353 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4354 instr->regarray.idx.n_bits = fidx->n_bits;
4355 instr->regarray.idx.offset = fidx->offset / 8;
4356 instr->regarray.dstsrc_val = src_val;
4360 /* REGADD_RIH, REGADD_RIM. */
4361 if (!fidx && fsrc) {
4362 idx_val = strtoul(idx, &idx, 0);
4363 CHECK(!idx[0], EINVAL);
4365 CHECK(!fsrc->var_size, EINVAL);
4367 instr->type = INSTR_REGADD_RIM;
4369 instr->type = INSTR_REGADD_RIH;
4371 instr->regarray.regarray_id = r->id;
4372 instr->regarray.idx_val = idx_val;
4373 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4374 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4375 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4380 src_val = strtoull(src, &src, 0);
4381 CHECK(!src[0], EINVAL);
4383 idx_val = strtoul(idx, &idx, 0);
4384 CHECK(!idx[0], EINVAL);
4386 instr->type = INSTR_REGADD_RII;
4387 instr->regarray.idx_val = idx_val;
4388 instr->regarray.dstsrc_val = src_val;
4392 static inline uint64_t *
4393 instr_regarray_regarray(struct rte_swx_pipeline *p, struct instruction *ip)
4395 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4399 static inline uint64_t
4400 instr_regarray_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
4402 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4404 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
4405 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
4406 uint64_t idx64 = *idx64_ptr;
4407 uint64_t idx64_mask = UINT64_MAX >> (64 - ip->regarray.idx.n_bits);
4408 uint64_t idx = idx64 & idx64_mask & r->size_mask;
4413 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4415 static inline uint64_t
4416 instr_regarray_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
4418 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4420 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
4421 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
4422 uint64_t idx64 = *idx64_ptr;
4423 uint64_t idx = (ntoh64(idx64) >> (64 - ip->regarray.idx.n_bits)) & r->size_mask;
4430 #define instr_regarray_idx_nbo instr_regarray_idx_hbo
4434 static inline uint64_t
4435 instr_regarray_idx_imm(struct rte_swx_pipeline *p, struct instruction *ip)
4437 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4439 uint64_t idx = ip->regarray.idx_val & r->size_mask;
4444 static inline uint64_t
4445 instr_regarray_src_hbo(struct thread *t, struct instruction *ip)
4447 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
4448 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
4449 uint64_t src64 = *src64_ptr;
4450 uint64_t src64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
4451 uint64_t src = src64 & src64_mask;
4456 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4458 static inline uint64_t
4459 instr_regarray_src_nbo(struct thread *t, struct instruction *ip)
4461 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
4462 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
4463 uint64_t src64 = *src64_ptr;
4464 uint64_t src = ntoh64(src64) >> (64 - ip->regarray.dstsrc.n_bits);
4471 #define instr_regarray_src_nbo instr_regarray_src_hbo
4476 instr_regarray_dst_hbo_src_hbo_set(struct thread *t, struct instruction *ip, uint64_t src)
4478 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
4479 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
4480 uint64_t dst64 = *dst64_ptr;
4481 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
4483 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
4487 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4490 instr_regarray_dst_nbo_src_hbo_set(struct thread *t, struct instruction *ip, uint64_t src)
4492 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
4493 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
4494 uint64_t dst64 = *dst64_ptr;
4495 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
4497 src = hton64(src) >> (64 - ip->regarray.dstsrc.n_bits);
4498 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
4503 #define instr_regarray_dst_nbo_src_hbo_set instr_regarray_dst_hbo_src_hbo_set
4508 instr_regprefetch_rh_exec(struct rte_swx_pipeline *p)
4510 struct thread *t = &p->threads[p->thread_id];
4511 struct instruction *ip = t->ip;
4512 uint64_t *regarray, idx;
4514 TRACE("[Thread %2u] regprefetch (r[h])\n", p->thread_id);
4517 regarray = instr_regarray_regarray(p, ip);
4518 idx = instr_regarray_idx_nbo(p, t, ip);
4519 rte_prefetch0(®array[idx]);
4526 instr_regprefetch_rm_exec(struct rte_swx_pipeline *p)
4528 struct thread *t = &p->threads[p->thread_id];
4529 struct instruction *ip = t->ip;
4530 uint64_t *regarray, idx;
4532 TRACE("[Thread %2u] regprefetch (r[m])\n", p->thread_id);
4535 regarray = instr_regarray_regarray(p, ip);
4536 idx = instr_regarray_idx_hbo(p, t, ip);
4537 rte_prefetch0(®array[idx]);
4544 instr_regprefetch_ri_exec(struct rte_swx_pipeline *p)
4546 struct thread *t = &p->threads[p->thread_id];
4547 struct instruction *ip = t->ip;
4548 uint64_t *regarray, idx;
4550 TRACE("[Thread %2u] regprefetch (r[i])\n", p->thread_id);
4553 regarray = instr_regarray_regarray(p, ip);
4554 idx = instr_regarray_idx_imm(p, ip);
4555 rte_prefetch0(®array[idx]);
4562 instr_regrd_hrh_exec(struct rte_swx_pipeline *p)
4564 struct thread *t = &p->threads[p->thread_id];
4565 struct instruction *ip = t->ip;
4566 uint64_t *regarray, idx;
4568 TRACE("[Thread %2u] regrd (h = r[h])\n", p->thread_id);
4571 regarray = instr_regarray_regarray(p, ip);
4572 idx = instr_regarray_idx_nbo(p, t, ip);
4573 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
4580 instr_regrd_hrm_exec(struct rte_swx_pipeline *p)
4582 struct thread *t = &p->threads[p->thread_id];
4583 struct instruction *ip = t->ip;
4584 uint64_t *regarray, idx;
4586 TRACE("[Thread %2u] regrd (h = r[m])\n", p->thread_id);
4589 regarray = instr_regarray_regarray(p, ip);
4590 idx = instr_regarray_idx_hbo(p, t, ip);
4591 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
4598 instr_regrd_mrh_exec(struct rte_swx_pipeline *p)
4600 struct thread *t = &p->threads[p->thread_id];
4601 struct instruction *ip = t->ip;
4602 uint64_t *regarray, idx;
4604 TRACE("[Thread %2u] regrd (m = r[h])\n", p->thread_id);
4607 regarray = instr_regarray_regarray(p, ip);
4608 idx = instr_regarray_idx_nbo(p, t, ip);
4609 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
4616 instr_regrd_mrm_exec(struct rte_swx_pipeline *p)
4618 struct thread *t = &p->threads[p->thread_id];
4619 struct instruction *ip = t->ip;
4620 uint64_t *regarray, idx;
4623 regarray = instr_regarray_regarray(p, ip);
4624 idx = instr_regarray_idx_hbo(p, t, ip);
4625 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
4632 instr_regrd_hri_exec(struct rte_swx_pipeline *p)
4634 struct thread *t = &p->threads[p->thread_id];
4635 struct instruction *ip = t->ip;
4636 uint64_t *regarray, idx;
4638 TRACE("[Thread %2u] regrd (h = r[i])\n", p->thread_id);
4641 regarray = instr_regarray_regarray(p, ip);
4642 idx = instr_regarray_idx_imm(p, ip);
4643 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
4650 instr_regrd_mri_exec(struct rte_swx_pipeline *p)
4652 struct thread *t = &p->threads[p->thread_id];
4653 struct instruction *ip = t->ip;
4654 uint64_t *regarray, idx;
4656 TRACE("[Thread %2u] regrd (m = r[i])\n", p->thread_id);
4659 regarray = instr_regarray_regarray(p, ip);
4660 idx = instr_regarray_idx_imm(p, ip);
4661 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
4668 instr_regwr_rhh_exec(struct rte_swx_pipeline *p)
4670 struct thread *t = &p->threads[p->thread_id];
4671 struct instruction *ip = t->ip;
4672 uint64_t *regarray, idx, src;
4674 TRACE("[Thread %2u] regwr (r[h] = h)\n", p->thread_id);
4677 regarray = instr_regarray_regarray(p, ip);
4678 idx = instr_regarray_idx_nbo(p, t, ip);
4679 src = instr_regarray_src_nbo(t, ip);
4680 regarray[idx] = src;
4687 instr_regwr_rhm_exec(struct rte_swx_pipeline *p)
4689 struct thread *t = &p->threads[p->thread_id];
4690 struct instruction *ip = t->ip;
4691 uint64_t *regarray, idx, src;
4693 TRACE("[Thread %2u] regwr (r[h] = m)\n", p->thread_id);
4696 regarray = instr_regarray_regarray(p, ip);
4697 idx = instr_regarray_idx_nbo(p, t, ip);
4698 src = instr_regarray_src_hbo(t, ip);
4699 regarray[idx] = src;
4706 instr_regwr_rmh_exec(struct rte_swx_pipeline *p)
4708 struct thread *t = &p->threads[p->thread_id];
4709 struct instruction *ip = t->ip;
4710 uint64_t *regarray, idx, src;
4712 TRACE("[Thread %2u] regwr (r[m] = h)\n", p->thread_id);
4715 regarray = instr_regarray_regarray(p, ip);
4716 idx = instr_regarray_idx_hbo(p, t, ip);
4717 src = instr_regarray_src_nbo(t, ip);
4718 regarray[idx] = src;
4725 instr_regwr_rmm_exec(struct rte_swx_pipeline *p)
4727 struct thread *t = &p->threads[p->thread_id];
4728 struct instruction *ip = t->ip;
4729 uint64_t *regarray, idx, src;
4731 TRACE("[Thread %2u] regwr (r[m] = m)\n", p->thread_id);
4734 regarray = instr_regarray_regarray(p, ip);
4735 idx = instr_regarray_idx_hbo(p, t, ip);
4736 src = instr_regarray_src_hbo(t, ip);
4737 regarray[idx] = src;
4744 instr_regwr_rhi_exec(struct rte_swx_pipeline *p)
4746 struct thread *t = &p->threads[p->thread_id];
4747 struct instruction *ip = t->ip;
4748 uint64_t *regarray, idx, src;
4750 TRACE("[Thread %2u] regwr (r[h] = i)\n", p->thread_id);
4753 regarray = instr_regarray_regarray(p, ip);
4754 idx = instr_regarray_idx_nbo(p, t, ip);
4755 src = ip->regarray.dstsrc_val;
4756 regarray[idx] = src;
4763 instr_regwr_rmi_exec(struct rte_swx_pipeline *p)
4765 struct thread *t = &p->threads[p->thread_id];
4766 struct instruction *ip = t->ip;
4767 uint64_t *regarray, idx, src;
4769 TRACE("[Thread %2u] regwr (r[m] = i)\n", p->thread_id);
4772 regarray = instr_regarray_regarray(p, ip);
4773 idx = instr_regarray_idx_hbo(p, t, ip);
4774 src = ip->regarray.dstsrc_val;
4775 regarray[idx] = src;
4782 instr_regwr_rih_exec(struct rte_swx_pipeline *p)
4784 struct thread *t = &p->threads[p->thread_id];
4785 struct instruction *ip = t->ip;
4786 uint64_t *regarray, idx, src;
4788 TRACE("[Thread %2u] regwr (r[i] = h)\n", p->thread_id);
4791 regarray = instr_regarray_regarray(p, ip);
4792 idx = instr_regarray_idx_imm(p, ip);
4793 src = instr_regarray_src_nbo(t, ip);
4794 regarray[idx] = src;
4801 instr_regwr_rim_exec(struct rte_swx_pipeline *p)
4803 struct thread *t = &p->threads[p->thread_id];
4804 struct instruction *ip = t->ip;
4805 uint64_t *regarray, idx, src;
4807 TRACE("[Thread %2u] regwr (r[i] = m)\n", p->thread_id);
4810 regarray = instr_regarray_regarray(p, ip);
4811 idx = instr_regarray_idx_imm(p, ip);
4812 src = instr_regarray_src_hbo(t, ip);
4813 regarray[idx] = src;
4820 instr_regwr_rii_exec(struct rte_swx_pipeline *p)
4822 struct thread *t = &p->threads[p->thread_id];
4823 struct instruction *ip = t->ip;
4824 uint64_t *regarray, idx, src;
4826 TRACE("[Thread %2u] regwr (r[i] = i)\n", p->thread_id);
4829 regarray = instr_regarray_regarray(p, ip);
4830 idx = instr_regarray_idx_imm(p, ip);
4831 src = ip->regarray.dstsrc_val;
4832 regarray[idx] = src;
4839 instr_regadd_rhh_exec(struct rte_swx_pipeline *p)
4841 struct thread *t = &p->threads[p->thread_id];
4842 struct instruction *ip = t->ip;
4843 uint64_t *regarray, idx, src;
4845 TRACE("[Thread %2u] regadd (r[h] += h)\n", p->thread_id);
4848 regarray = instr_regarray_regarray(p, ip);
4849 idx = instr_regarray_idx_nbo(p, t, ip);
4850 src = instr_regarray_src_nbo(t, ip);
4851 regarray[idx] += src;
4858 instr_regadd_rhm_exec(struct rte_swx_pipeline *p)
4860 struct thread *t = &p->threads[p->thread_id];
4861 struct instruction *ip = t->ip;
4862 uint64_t *regarray, idx, src;
4864 TRACE("[Thread %2u] regadd (r[h] += m)\n", p->thread_id);
4867 regarray = instr_regarray_regarray(p, ip);
4868 idx = instr_regarray_idx_nbo(p, t, ip);
4869 src = instr_regarray_src_hbo(t, ip);
4870 regarray[idx] += src;
4877 instr_regadd_rmh_exec(struct rte_swx_pipeline *p)
4879 struct thread *t = &p->threads[p->thread_id];
4880 struct instruction *ip = t->ip;
4881 uint64_t *regarray, idx, src;
4883 TRACE("[Thread %2u] regadd (r[m] += h)\n", p->thread_id);
4886 regarray = instr_regarray_regarray(p, ip);
4887 idx = instr_regarray_idx_hbo(p, t, ip);
4888 src = instr_regarray_src_nbo(t, ip);
4889 regarray[idx] += src;
4896 instr_regadd_rmm_exec(struct rte_swx_pipeline *p)
4898 struct thread *t = &p->threads[p->thread_id];
4899 struct instruction *ip = t->ip;
4900 uint64_t *regarray, idx, src;
4902 TRACE("[Thread %2u] regadd (r[m] += m)\n", p->thread_id);
4905 regarray = instr_regarray_regarray(p, ip);
4906 idx = instr_regarray_idx_hbo(p, t, ip);
4907 src = instr_regarray_src_hbo(t, ip);
4908 regarray[idx] += src;
4915 instr_regadd_rhi_exec(struct rte_swx_pipeline *p)
4917 struct thread *t = &p->threads[p->thread_id];
4918 struct instruction *ip = t->ip;
4919 uint64_t *regarray, idx, src;
4921 TRACE("[Thread %2u] regadd (r[h] += i)\n", p->thread_id);
4924 regarray = instr_regarray_regarray(p, ip);
4925 idx = instr_regarray_idx_nbo(p, t, ip);
4926 src = ip->regarray.dstsrc_val;
4927 regarray[idx] += src;
4934 instr_regadd_rmi_exec(struct rte_swx_pipeline *p)
4936 struct thread *t = &p->threads[p->thread_id];
4937 struct instruction *ip = t->ip;
4938 uint64_t *regarray, idx, src;
4940 TRACE("[Thread %2u] regadd (r[m] += i)\n", p->thread_id);
4943 regarray = instr_regarray_regarray(p, ip);
4944 idx = instr_regarray_idx_hbo(p, t, ip);
4945 src = ip->regarray.dstsrc_val;
4946 regarray[idx] += src;
4953 instr_regadd_rih_exec(struct rte_swx_pipeline *p)
4955 struct thread *t = &p->threads[p->thread_id];
4956 struct instruction *ip = t->ip;
4957 uint64_t *regarray, idx, src;
4959 TRACE("[Thread %2u] regadd (r[i] += h)\n", p->thread_id);
4962 regarray = instr_regarray_regarray(p, ip);
4963 idx = instr_regarray_idx_imm(p, ip);
4964 src = instr_regarray_src_nbo(t, ip);
4965 regarray[idx] += src;
4972 instr_regadd_rim_exec(struct rte_swx_pipeline *p)
4974 struct thread *t = &p->threads[p->thread_id];
4975 struct instruction *ip = t->ip;
4976 uint64_t *regarray, idx, src;
4978 TRACE("[Thread %2u] regadd (r[i] += m)\n", p->thread_id);
4981 regarray = instr_regarray_regarray(p, ip);
4982 idx = instr_regarray_idx_imm(p, ip);
4983 src = instr_regarray_src_hbo(t, ip);
4984 regarray[idx] += src;
4991 instr_regadd_rii_exec(struct rte_swx_pipeline *p)
4993 struct thread *t = &p->threads[p->thread_id];
4994 struct instruction *ip = t->ip;
4995 uint64_t *regarray, idx, src;
4997 TRACE("[Thread %2u] regadd (r[i] += i)\n", p->thread_id);
5000 regarray = instr_regarray_regarray(p, ip);
5001 idx = instr_regarray_idx_imm(p, ip);
5002 src = ip->regarray.dstsrc_val;
5003 regarray[idx] += src;
5012 static struct metarray *
5013 metarray_find(struct rte_swx_pipeline *p, const char *name);
5016 instr_metprefetch_translate(struct rte_swx_pipeline *p,
5017 struct action *action,
5020 struct instruction *instr,
5021 struct instruction_data *data __rte_unused)
5023 char *metarray = tokens[1], *idx = tokens[2];
5026 uint32_t idx_struct_id, idx_val;
5028 CHECK(n_tokens == 3, EINVAL);
5030 m = metarray_find(p, metarray);
5033 /* METPREFETCH_H, METPREFETCH_M. */
5034 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
5036 CHECK(!fidx->var_size, EINVAL);
5038 instr->type = INSTR_METPREFETCH_M;
5040 instr->type = INSTR_METPREFETCH_H;
5042 instr->meter.metarray_id = m->id;
5043 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
5044 instr->meter.idx.n_bits = fidx->n_bits;
5045 instr->meter.idx.offset = fidx->offset / 8;
5049 /* METPREFETCH_I. */
5050 idx_val = strtoul(idx, &idx, 0);
5051 CHECK(!idx[0], EINVAL);
5053 instr->type = INSTR_METPREFETCH_I;
5054 instr->meter.metarray_id = m->id;
5055 instr->meter.idx_val = idx_val;
5060 instr_meter_translate(struct rte_swx_pipeline *p,
5061 struct action *action,
5064 struct instruction *instr,
5065 struct instruction_data *data __rte_unused)
5067 char *metarray = tokens[1], *idx = tokens[2], *length = tokens[3];
5068 char *color_in = tokens[4], *color_out = tokens[5];
5070 struct field *fidx, *flength, *fcin, *fcout;
5071 uint32_t idx_struct_id, length_struct_id;
5072 uint32_t color_in_struct_id, color_out_struct_id;
5074 CHECK(n_tokens == 6, EINVAL);
5076 m = metarray_find(p, metarray);
5079 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
5081 flength = struct_field_parse(p, action, length, &length_struct_id);
5082 CHECK(flength, EINVAL);
5083 CHECK(!flength->var_size, EINVAL);
5085 fcin = struct_field_parse(p, action, color_in, &color_in_struct_id);
5087 fcout = struct_field_parse(p, NULL, color_out, &color_out_struct_id);
5088 CHECK(fcout, EINVAL);
5089 CHECK(!fcout->var_size, EINVAL);
5091 /* index = HMEFT, length = HMEFT, color_in = MEFT, color_out = MEF. */
5093 CHECK(!fidx->var_size, EINVAL);
5094 CHECK(!fcin->var_size, EINVAL);
5096 instr->type = INSTR_METER_MMM;
5097 if (idx[0] == 'h' && length[0] == 'h')
5098 instr->type = INSTR_METER_HHM;
5099 if (idx[0] == 'h' && length[0] != 'h')
5100 instr->type = INSTR_METER_HMM;
5101 if (idx[0] != 'h' && length[0] == 'h')
5102 instr->type = INSTR_METER_MHM;
5104 instr->meter.metarray_id = m->id;
5106 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
5107 instr->meter.idx.n_bits = fidx->n_bits;
5108 instr->meter.idx.offset = fidx->offset / 8;
5110 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5111 instr->meter.length.n_bits = flength->n_bits;
5112 instr->meter.length.offset = flength->offset / 8;
5114 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
5115 instr->meter.color_in.n_bits = fcin->n_bits;
5116 instr->meter.color_in.offset = fcin->offset / 8;
5118 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5119 instr->meter.color_out.n_bits = fcout->n_bits;
5120 instr->meter.color_out.offset = fcout->offset / 8;
5125 /* index = HMEFT, length = HMEFT, color_in = I, color_out = MEF. */
5126 if (fidx && !fcin) {
5127 uint32_t color_in_val;
5129 CHECK(!fidx->var_size, EINVAL);
5131 color_in_val = strtoul(color_in, &color_in, 0);
5132 CHECK(!color_in[0], EINVAL);
5134 instr->type = INSTR_METER_MMI;
5135 if (idx[0] == 'h' && length[0] == 'h')
5136 instr->type = INSTR_METER_HHI;
5137 if (idx[0] == 'h' && length[0] != 'h')
5138 instr->type = INSTR_METER_HMI;
5139 if (idx[0] != 'h' && length[0] == 'h')
5140 instr->type = INSTR_METER_MHI;
5142 instr->meter.metarray_id = m->id;
5144 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
5145 instr->meter.idx.n_bits = fidx->n_bits;
5146 instr->meter.idx.offset = fidx->offset / 8;
5148 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5149 instr->meter.length.n_bits = flength->n_bits;
5150 instr->meter.length.offset = flength->offset / 8;
5152 instr->meter.color_in_val = color_in_val;
5154 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5155 instr->meter.color_out.n_bits = fcout->n_bits;
5156 instr->meter.color_out.offset = fcout->offset / 8;
5161 /* index = I, length = HMEFT, color_in = MEFT, color_out = MEF. */
5162 if (!fidx && fcin) {
5165 idx_val = strtoul(idx, &idx, 0);
5166 CHECK(!idx[0], EINVAL);
5168 CHECK(!fcin->var_size, EINVAL);
5170 instr->type = INSTR_METER_IMM;
5171 if (length[0] == 'h')
5172 instr->type = INSTR_METER_IHM;
5174 instr->meter.metarray_id = m->id;
5176 instr->meter.idx_val = idx_val;
5178 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5179 instr->meter.length.n_bits = flength->n_bits;
5180 instr->meter.length.offset = flength->offset / 8;
5182 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
5183 instr->meter.color_in.n_bits = fcin->n_bits;
5184 instr->meter.color_in.offset = fcin->offset / 8;
5186 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5187 instr->meter.color_out.n_bits = fcout->n_bits;
5188 instr->meter.color_out.offset = fcout->offset / 8;
5193 /* index = I, length = HMEFT, color_in = I, color_out = MEF. */
5194 if (!fidx && !fcin) {
5195 uint32_t idx_val, color_in_val;
5197 idx_val = strtoul(idx, &idx, 0);
5198 CHECK(!idx[0], EINVAL);
5200 color_in_val = strtoul(color_in, &color_in, 0);
5201 CHECK(!color_in[0], EINVAL);
5203 instr->type = INSTR_METER_IMI;
5204 if (length[0] == 'h')
5205 instr->type = INSTR_METER_IHI;
5207 instr->meter.metarray_id = m->id;
5209 instr->meter.idx_val = idx_val;
5211 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5212 instr->meter.length.n_bits = flength->n_bits;
5213 instr->meter.length.offset = flength->offset / 8;
5215 instr->meter.color_in_val = color_in_val;
5217 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5218 instr->meter.color_out.n_bits = fcout->n_bits;
5219 instr->meter.color_out.offset = fcout->offset / 8;
5227 static inline struct meter *
5228 instr_meter_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
5230 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
5232 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
5233 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
5234 uint64_t idx64 = *idx64_ptr;
5235 uint64_t idx64_mask = UINT64_MAX >> (64 - (ip)->meter.idx.n_bits);
5236 uint64_t idx = idx64 & idx64_mask & r->size_mask;
5238 return &r->metarray[idx];
5241 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5243 static inline struct meter *
5244 instr_meter_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
5246 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
5248 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
5249 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
5250 uint64_t idx64 = *idx64_ptr;
5251 uint64_t idx = (ntoh64(idx64) >> (64 - ip->meter.idx.n_bits)) & r->size_mask;
5253 return &r->metarray[idx];
5258 #define instr_meter_idx_nbo instr_meter_idx_hbo
5262 static inline struct meter *
5263 instr_meter_idx_imm(struct rte_swx_pipeline *p, struct instruction *ip)
5265 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
5267 uint64_t idx = ip->meter.idx_val & r->size_mask;
5269 return &r->metarray[idx];
5272 static inline uint32_t
5273 instr_meter_length_hbo(struct thread *t, struct instruction *ip)
5275 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
5276 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
5277 uint64_t src64 = *src64_ptr;
5278 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->meter.length.n_bits);
5279 uint64_t src = src64 & src64_mask;
5281 return (uint32_t)src;
5284 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5286 static inline uint32_t
5287 instr_meter_length_nbo(struct thread *t, struct instruction *ip)
5289 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
5290 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
5291 uint64_t src64 = *src64_ptr;
5292 uint64_t src = ntoh64(src64) >> (64 - ip->meter.length.n_bits);
5294 return (uint32_t)src;
5299 #define instr_meter_length_nbo instr_meter_length_hbo
5303 static inline enum rte_color
5304 instr_meter_color_in_hbo(struct thread *t, struct instruction *ip)
5306 uint8_t *src_struct = t->structs[ip->meter.color_in.struct_id];
5307 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.color_in.offset];
5308 uint64_t src64 = *src64_ptr;
5309 uint64_t src64_mask = UINT64_MAX >> (64 - ip->meter.color_in.n_bits);
5310 uint64_t src = src64 & src64_mask;
5312 return (enum rte_color)src;
5316 instr_meter_color_out_hbo_set(struct thread *t, struct instruction *ip, enum rte_color color_out)
5318 uint8_t *dst_struct = t->structs[ip->meter.color_out.struct_id];
5319 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->meter.color_out.offset];
5320 uint64_t dst64 = *dst64_ptr;
5321 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->meter.color_out.n_bits);
5323 uint64_t src = (uint64_t)color_out;
5325 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
5329 instr_metprefetch_h_exec(struct rte_swx_pipeline *p)
5331 struct thread *t = &p->threads[p->thread_id];
5332 struct instruction *ip = t->ip;
5335 TRACE("[Thread %2u] metprefetch (h)\n", p->thread_id);
5338 m = instr_meter_idx_nbo(p, t, ip);
5346 instr_metprefetch_m_exec(struct rte_swx_pipeline *p)
5348 struct thread *t = &p->threads[p->thread_id];
5349 struct instruction *ip = t->ip;
5352 TRACE("[Thread %2u] metprefetch (m)\n", p->thread_id);
5355 m = instr_meter_idx_hbo(p, t, ip);
5363 instr_metprefetch_i_exec(struct rte_swx_pipeline *p)
5365 struct thread *t = &p->threads[p->thread_id];
5366 struct instruction *ip = t->ip;
5369 TRACE("[Thread %2u] metprefetch (i)\n", p->thread_id);
5372 m = instr_meter_idx_imm(p, ip);
5380 instr_meter_hhm_exec(struct rte_swx_pipeline *p)
5382 struct thread *t = &p->threads[p->thread_id];
5383 struct instruction *ip = t->ip;
5385 uint64_t time, n_pkts, n_bytes;
5387 enum rte_color color_in, color_out;
5389 TRACE("[Thread %2u] meter (hhm)\n", p->thread_id);
5392 m = instr_meter_idx_nbo(p, t, ip);
5393 rte_prefetch0(m->n_pkts);
5394 time = rte_get_tsc_cycles();
5395 length = instr_meter_length_nbo(t, ip);
5396 color_in = instr_meter_color_in_hbo(t, ip);
5398 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5399 &m->profile->profile,
5404 color_out &= m->color_mask;
5406 n_pkts = m->n_pkts[color_out];
5407 n_bytes = m->n_bytes[color_out];
5409 instr_meter_color_out_hbo_set(t, ip, color_out);
5411 m->n_pkts[color_out] = n_pkts + 1;
5412 m->n_bytes[color_out] = n_bytes + length;
5419 instr_meter_hhi_exec(struct rte_swx_pipeline *p)
5421 struct thread *t = &p->threads[p->thread_id];
5422 struct instruction *ip = t->ip;
5424 uint64_t time, n_pkts, n_bytes;
5426 enum rte_color color_in, color_out;
5428 TRACE("[Thread %2u] meter (hhi)\n", p->thread_id);
5431 m = instr_meter_idx_nbo(p, t, ip);
5432 rte_prefetch0(m->n_pkts);
5433 time = rte_get_tsc_cycles();
5434 length = instr_meter_length_nbo(t, ip);
5435 color_in = (enum rte_color)ip->meter.color_in_val;
5437 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5438 &m->profile->profile,
5443 color_out &= m->color_mask;
5445 n_pkts = m->n_pkts[color_out];
5446 n_bytes = m->n_bytes[color_out];
5448 instr_meter_color_out_hbo_set(t, ip, color_out);
5450 m->n_pkts[color_out] = n_pkts + 1;
5451 m->n_bytes[color_out] = n_bytes + length;
5458 instr_meter_hmm_exec(struct rte_swx_pipeline *p)
5460 struct thread *t = &p->threads[p->thread_id];
5461 struct instruction *ip = t->ip;
5463 uint64_t time, n_pkts, n_bytes;
5465 enum rte_color color_in, color_out;
5467 TRACE("[Thread %2u] meter (hmm)\n", p->thread_id);
5470 m = instr_meter_idx_nbo(p, t, ip);
5471 rte_prefetch0(m->n_pkts);
5472 time = rte_get_tsc_cycles();
5473 length = instr_meter_length_hbo(t, ip);
5474 color_in = instr_meter_color_in_hbo(t, ip);
5476 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5477 &m->profile->profile,
5482 color_out &= m->color_mask;
5484 n_pkts = m->n_pkts[color_out];
5485 n_bytes = m->n_bytes[color_out];
5487 instr_meter_color_out_hbo_set(t, ip, color_out);
5489 m->n_pkts[color_out] = n_pkts + 1;
5490 m->n_bytes[color_out] = n_bytes + length;
5496 instr_meter_hmi_exec(struct rte_swx_pipeline *p)
5498 struct thread *t = &p->threads[p->thread_id];
5499 struct instruction *ip = t->ip;
5501 uint64_t time, n_pkts, n_bytes;
5503 enum rte_color color_in, color_out;
5505 TRACE("[Thread %2u] meter (hmi)\n", p->thread_id);
5508 m = instr_meter_idx_nbo(p, t, ip);
5509 rte_prefetch0(m->n_pkts);
5510 time = rte_get_tsc_cycles();
5511 length = instr_meter_length_hbo(t, ip);
5512 color_in = (enum rte_color)ip->meter.color_in_val;
5514 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5515 &m->profile->profile,
5520 color_out &= m->color_mask;
5522 n_pkts = m->n_pkts[color_out];
5523 n_bytes = m->n_bytes[color_out];
5525 instr_meter_color_out_hbo_set(t, ip, color_out);
5527 m->n_pkts[color_out] = n_pkts + 1;
5528 m->n_bytes[color_out] = n_bytes + length;
5535 instr_meter_mhm_exec(struct rte_swx_pipeline *p)
5537 struct thread *t = &p->threads[p->thread_id];
5538 struct instruction *ip = t->ip;
5540 uint64_t time, n_pkts, n_bytes;
5542 enum rte_color color_in, color_out;
5544 TRACE("[Thread %2u] meter (mhm)\n", p->thread_id);
5547 m = instr_meter_idx_hbo(p, t, ip);
5548 rte_prefetch0(m->n_pkts);
5549 time = rte_get_tsc_cycles();
5550 length = instr_meter_length_nbo(t, ip);
5551 color_in = instr_meter_color_in_hbo(t, ip);
5553 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5554 &m->profile->profile,
5559 color_out &= m->color_mask;
5561 n_pkts = m->n_pkts[color_out];
5562 n_bytes = m->n_bytes[color_out];
5564 instr_meter_color_out_hbo_set(t, ip, color_out);
5566 m->n_pkts[color_out] = n_pkts + 1;
5567 m->n_bytes[color_out] = n_bytes + length;
5574 instr_meter_mhi_exec(struct rte_swx_pipeline *p)
5576 struct thread *t = &p->threads[p->thread_id];
5577 struct instruction *ip = t->ip;
5579 uint64_t time, n_pkts, n_bytes;
5581 enum rte_color color_in, color_out;
5583 TRACE("[Thread %2u] meter (mhi)\n", p->thread_id);
5586 m = instr_meter_idx_hbo(p, t, ip);
5587 rte_prefetch0(m->n_pkts);
5588 time = rte_get_tsc_cycles();
5589 length = instr_meter_length_nbo(t, ip);
5590 color_in = (enum rte_color)ip->meter.color_in_val;
5592 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5593 &m->profile->profile,
5598 color_out &= m->color_mask;
5600 n_pkts = m->n_pkts[color_out];
5601 n_bytes = m->n_bytes[color_out];
5603 instr_meter_color_out_hbo_set(t, ip, color_out);
5605 m->n_pkts[color_out] = n_pkts + 1;
5606 m->n_bytes[color_out] = n_bytes + length;
5613 instr_meter_mmm_exec(struct rte_swx_pipeline *p)
5615 struct thread *t = &p->threads[p->thread_id];
5616 struct instruction *ip = t->ip;
5618 uint64_t time, n_pkts, n_bytes;
5620 enum rte_color color_in, color_out;
5622 TRACE("[Thread %2u] meter (mmm)\n", p->thread_id);
5625 m = instr_meter_idx_hbo(p, t, ip);
5626 rte_prefetch0(m->n_pkts);
5627 time = rte_get_tsc_cycles();
5628 length = instr_meter_length_hbo(t, ip);
5629 color_in = instr_meter_color_in_hbo(t, ip);
5631 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5632 &m->profile->profile,
5637 color_out &= m->color_mask;
5639 n_pkts = m->n_pkts[color_out];
5640 n_bytes = m->n_bytes[color_out];
5642 instr_meter_color_out_hbo_set(t, ip, color_out);
5644 m->n_pkts[color_out] = n_pkts + 1;
5645 m->n_bytes[color_out] = n_bytes + length;
5652 instr_meter_mmi_exec(struct rte_swx_pipeline *p)
5654 struct thread *t = &p->threads[p->thread_id];
5655 struct instruction *ip = t->ip;
5657 uint64_t time, n_pkts, n_bytes;
5659 enum rte_color color_in, color_out;
5661 TRACE("[Thread %2u] meter (mmi)\n", p->thread_id);
5664 m = instr_meter_idx_hbo(p, t, ip);
5665 rte_prefetch0(m->n_pkts);
5666 time = rte_get_tsc_cycles();
5667 length = instr_meter_length_hbo(t, ip);
5668 color_in = (enum rte_color)ip->meter.color_in_val;
5670 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5671 &m->profile->profile,
5676 color_out &= m->color_mask;
5678 n_pkts = m->n_pkts[color_out];
5679 n_bytes = m->n_bytes[color_out];
5681 instr_meter_color_out_hbo_set(t, ip, color_out);
5683 m->n_pkts[color_out] = n_pkts + 1;
5684 m->n_bytes[color_out] = n_bytes + length;
5691 instr_meter_ihm_exec(struct rte_swx_pipeline *p)
5693 struct thread *t = &p->threads[p->thread_id];
5694 struct instruction *ip = t->ip;
5696 uint64_t time, n_pkts, n_bytes;
5698 enum rte_color color_in, color_out;
5700 TRACE("[Thread %2u] meter (ihm)\n", p->thread_id);
5703 m = instr_meter_idx_imm(p, ip);
5704 rte_prefetch0(m->n_pkts);
5705 time = rte_get_tsc_cycles();
5706 length = instr_meter_length_nbo(t, ip);
5707 color_in = instr_meter_color_in_hbo(t, ip);
5709 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5710 &m->profile->profile,
5715 color_out &= m->color_mask;
5717 n_pkts = m->n_pkts[color_out];
5718 n_bytes = m->n_bytes[color_out];
5720 instr_meter_color_out_hbo_set(t, ip, color_out);
5722 m->n_pkts[color_out] = n_pkts + 1;
5723 m->n_bytes[color_out] = n_bytes + length;
5730 instr_meter_ihi_exec(struct rte_swx_pipeline *p)
5732 struct thread *t = &p->threads[p->thread_id];
5733 struct instruction *ip = t->ip;
5735 uint64_t time, n_pkts, n_bytes;
5737 enum rte_color color_in, color_out;
5739 TRACE("[Thread %2u] meter (ihi)\n", p->thread_id);
5742 m = instr_meter_idx_imm(p, ip);
5743 rte_prefetch0(m->n_pkts);
5744 time = rte_get_tsc_cycles();
5745 length = instr_meter_length_nbo(t, ip);
5746 color_in = (enum rte_color)ip->meter.color_in_val;
5748 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5749 &m->profile->profile,
5754 color_out &= m->color_mask;
5756 n_pkts = m->n_pkts[color_out];
5757 n_bytes = m->n_bytes[color_out];
5759 instr_meter_color_out_hbo_set(t, ip, color_out);
5761 m->n_pkts[color_out] = n_pkts + 1;
5762 m->n_bytes[color_out] = n_bytes + length;
5769 instr_meter_imm_exec(struct rte_swx_pipeline *p)
5771 struct thread *t = &p->threads[p->thread_id];
5772 struct instruction *ip = t->ip;
5774 uint64_t time, n_pkts, n_bytes;
5776 enum rte_color color_in, color_out;
5778 TRACE("[Thread %2u] meter (imm)\n", p->thread_id);
5781 m = instr_meter_idx_imm(p, ip);
5782 rte_prefetch0(m->n_pkts);
5783 time = rte_get_tsc_cycles();
5784 length = instr_meter_length_hbo(t, ip);
5785 color_in = instr_meter_color_in_hbo(t, ip);
5787 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5788 &m->profile->profile,
5793 color_out &= m->color_mask;
5795 n_pkts = m->n_pkts[color_out];
5796 n_bytes = m->n_bytes[color_out];
5798 instr_meter_color_out_hbo_set(t, ip, color_out);
5800 m->n_pkts[color_out] = n_pkts + 1;
5801 m->n_bytes[color_out] = n_bytes + length;
5807 instr_meter_imi_exec(struct rte_swx_pipeline *p)
5809 struct thread *t = &p->threads[p->thread_id];
5810 struct instruction *ip = t->ip;
5812 uint64_t time, n_pkts, n_bytes;
5814 enum rte_color color_in, color_out;
5816 TRACE("[Thread %2u] meter (imi)\n", p->thread_id);
5819 m = instr_meter_idx_imm(p, ip);
5820 rte_prefetch0(m->n_pkts);
5821 time = rte_get_tsc_cycles();
5822 length = instr_meter_length_hbo(t, ip);
5823 color_in = (enum rte_color)ip->meter.color_in_val;
5825 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5826 &m->profile->profile,
5831 color_out &= m->color_mask;
5833 n_pkts = m->n_pkts[color_out];
5834 n_bytes = m->n_bytes[color_out];
5836 instr_meter_color_out_hbo_set(t, ip, color_out);
5838 m->n_pkts[color_out] = n_pkts + 1;
5839 m->n_bytes[color_out] = n_bytes + length;
5849 instr_jmp_translate(struct rte_swx_pipeline *p __rte_unused,
5850 struct action *action __rte_unused,
5853 struct instruction *instr,
5854 struct instruction_data *data)
5856 CHECK(n_tokens == 2, EINVAL);
5858 strcpy(data->jmp_label, tokens[1]);
5860 instr->type = INSTR_JMP;
5861 instr->jmp.ip = NULL; /* Resolved later. */
5866 instr_jmp_valid_translate(struct rte_swx_pipeline *p,
5867 struct action *action __rte_unused,
5870 struct instruction *instr,
5871 struct instruction_data *data)
5875 CHECK(n_tokens == 3, EINVAL);
5877 strcpy(data->jmp_label, tokens[1]);
5879 h = header_parse(p, tokens[2]);
5882 instr->type = INSTR_JMP_VALID;
5883 instr->jmp.ip = NULL; /* Resolved later. */
5884 instr->jmp.header_id = h->id;
5889 instr_jmp_invalid_translate(struct rte_swx_pipeline *p,
5890 struct action *action __rte_unused,
5893 struct instruction *instr,
5894 struct instruction_data *data)
5898 CHECK(n_tokens == 3, EINVAL);
5900 strcpy(data->jmp_label, tokens[1]);
5902 h = header_parse(p, tokens[2]);
5905 instr->type = INSTR_JMP_INVALID;
5906 instr->jmp.ip = NULL; /* Resolved later. */
5907 instr->jmp.header_id = h->id;
5912 instr_jmp_hit_translate(struct rte_swx_pipeline *p __rte_unused,
5913 struct action *action,
5916 struct instruction *instr,
5917 struct instruction_data *data)
5919 CHECK(!action, EINVAL);
5920 CHECK(n_tokens == 2, EINVAL);
5922 strcpy(data->jmp_label, tokens[1]);
5924 instr->type = INSTR_JMP_HIT;
5925 instr->jmp.ip = NULL; /* Resolved later. */
5930 instr_jmp_miss_translate(struct rte_swx_pipeline *p __rte_unused,
5931 struct action *action,
5934 struct instruction *instr,
5935 struct instruction_data *data)
5937 CHECK(!action, EINVAL);
5938 CHECK(n_tokens == 2, EINVAL);
5940 strcpy(data->jmp_label, tokens[1]);
5942 instr->type = INSTR_JMP_MISS;
5943 instr->jmp.ip = NULL; /* Resolved later. */
5948 instr_jmp_action_hit_translate(struct rte_swx_pipeline *p,
5949 struct action *action,
5952 struct instruction *instr,
5953 struct instruction_data *data)
5957 CHECK(!action, EINVAL);
5958 CHECK(n_tokens == 3, EINVAL);
5960 strcpy(data->jmp_label, tokens[1]);
5962 a = action_find(p, tokens[2]);
5965 instr->type = INSTR_JMP_ACTION_HIT;
5966 instr->jmp.ip = NULL; /* Resolved later. */
5967 instr->jmp.action_id = a->id;
5972 instr_jmp_action_miss_translate(struct rte_swx_pipeline *p,
5973 struct action *action,
5976 struct instruction *instr,
5977 struct instruction_data *data)
5981 CHECK(!action, EINVAL);
5982 CHECK(n_tokens == 3, EINVAL);
5984 strcpy(data->jmp_label, tokens[1]);
5986 a = action_find(p, tokens[2]);
5989 instr->type = INSTR_JMP_ACTION_MISS;
5990 instr->jmp.ip = NULL; /* Resolved later. */
5991 instr->jmp.action_id = a->id;
5996 instr_jmp_eq_translate(struct rte_swx_pipeline *p,
5997 struct action *action,
6000 struct instruction *instr,
6001 struct instruction_data *data)
6003 char *a = tokens[2], *b = tokens[3];
6004 struct field *fa, *fb;
6006 uint32_t a_struct_id, b_struct_id;
6008 CHECK(n_tokens == 4, EINVAL);
6010 strcpy(data->jmp_label, tokens[1]);
6012 fa = struct_field_parse(p, action, a, &a_struct_id);
6014 CHECK(!fa->var_size, EINVAL);
6016 /* JMP_EQ, JMP_EQ_MH, JMP_EQ_HM, JMP_EQ_HH. */
6017 fb = struct_field_parse(p, action, b, &b_struct_id);
6019 CHECK(!fb->var_size, EINVAL);
6021 instr->type = INSTR_JMP_EQ;
6022 if (a[0] != 'h' && b[0] == 'h')
6023 instr->type = INSTR_JMP_EQ_MH;
6024 if (a[0] == 'h' && b[0] != 'h')
6025 instr->type = INSTR_JMP_EQ_HM;
6026 if (a[0] == 'h' && b[0] == 'h')
6027 instr->type = INSTR_JMP_EQ_HH;
6028 instr->jmp.ip = NULL; /* Resolved later. */
6030 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6031 instr->jmp.a.n_bits = fa->n_bits;
6032 instr->jmp.a.offset = fa->offset / 8;
6033 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6034 instr->jmp.b.n_bits = fb->n_bits;
6035 instr->jmp.b.offset = fb->offset / 8;
6040 b_val = strtoull(b, &b, 0);
6041 CHECK(!b[0], EINVAL);
6044 b_val = hton64(b_val) >> (64 - fa->n_bits);
6046 instr->type = INSTR_JMP_EQ_I;
6047 instr->jmp.ip = NULL; /* Resolved later. */
6048 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6049 instr->jmp.a.n_bits = fa->n_bits;
6050 instr->jmp.a.offset = fa->offset / 8;
6051 instr->jmp.b_val = b_val;
6056 instr_jmp_neq_translate(struct rte_swx_pipeline *p,
6057 struct action *action,
6060 struct instruction *instr,
6061 struct instruction_data *data)
6063 char *a = tokens[2], *b = tokens[3];
6064 struct field *fa, *fb;
6066 uint32_t a_struct_id, b_struct_id;
6068 CHECK(n_tokens == 4, EINVAL);
6070 strcpy(data->jmp_label, tokens[1]);
6072 fa = struct_field_parse(p, action, a, &a_struct_id);
6074 CHECK(!fa->var_size, EINVAL);
6076 /* JMP_NEQ, JMP_NEQ_MH, JMP_NEQ_HM, JMP_NEQ_HH. */
6077 fb = struct_field_parse(p, action, b, &b_struct_id);
6079 CHECK(!fb->var_size, EINVAL);
6081 instr->type = INSTR_JMP_NEQ;
6082 if (a[0] != 'h' && b[0] == 'h')
6083 instr->type = INSTR_JMP_NEQ_MH;
6084 if (a[0] == 'h' && b[0] != 'h')
6085 instr->type = INSTR_JMP_NEQ_HM;
6086 if (a[0] == 'h' && b[0] == 'h')
6087 instr->type = INSTR_JMP_NEQ_HH;
6088 instr->jmp.ip = NULL; /* Resolved later. */
6090 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6091 instr->jmp.a.n_bits = fa->n_bits;
6092 instr->jmp.a.offset = fa->offset / 8;
6093 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6094 instr->jmp.b.n_bits = fb->n_bits;
6095 instr->jmp.b.offset = fb->offset / 8;
6100 b_val = strtoull(b, &b, 0);
6101 CHECK(!b[0], EINVAL);
6104 b_val = hton64(b_val) >> (64 - fa->n_bits);
6106 instr->type = INSTR_JMP_NEQ_I;
6107 instr->jmp.ip = NULL; /* Resolved later. */
6108 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6109 instr->jmp.a.n_bits = fa->n_bits;
6110 instr->jmp.a.offset = fa->offset / 8;
6111 instr->jmp.b_val = b_val;
6116 instr_jmp_lt_translate(struct rte_swx_pipeline *p,
6117 struct action *action,
6120 struct instruction *instr,
6121 struct instruction_data *data)
6123 char *a = tokens[2], *b = tokens[3];
6124 struct field *fa, *fb;
6126 uint32_t a_struct_id, b_struct_id;
6128 CHECK(n_tokens == 4, EINVAL);
6130 strcpy(data->jmp_label, tokens[1]);
6132 fa = struct_field_parse(p, action, a, &a_struct_id);
6134 CHECK(!fa->var_size, EINVAL);
6136 /* JMP_LT, JMP_LT_MH, JMP_LT_HM, JMP_LT_HH. */
6137 fb = struct_field_parse(p, action, b, &b_struct_id);
6139 CHECK(!fb->var_size, EINVAL);
6141 instr->type = INSTR_JMP_LT;
6142 if (a[0] == 'h' && b[0] != 'h')
6143 instr->type = INSTR_JMP_LT_HM;
6144 if (a[0] != 'h' && b[0] == 'h')
6145 instr->type = INSTR_JMP_LT_MH;
6146 if (a[0] == 'h' && b[0] == 'h')
6147 instr->type = INSTR_JMP_LT_HH;
6148 instr->jmp.ip = NULL; /* Resolved later. */
6150 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6151 instr->jmp.a.n_bits = fa->n_bits;
6152 instr->jmp.a.offset = fa->offset / 8;
6153 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6154 instr->jmp.b.n_bits = fb->n_bits;
6155 instr->jmp.b.offset = fb->offset / 8;
6159 /* JMP_LT_MI, JMP_LT_HI. */
6160 b_val = strtoull(b, &b, 0);
6161 CHECK(!b[0], EINVAL);
6163 instr->type = INSTR_JMP_LT_MI;
6165 instr->type = INSTR_JMP_LT_HI;
6166 instr->jmp.ip = NULL; /* Resolved later. */
6168 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6169 instr->jmp.a.n_bits = fa->n_bits;
6170 instr->jmp.a.offset = fa->offset / 8;
6171 instr->jmp.b_val = b_val;
6176 instr_jmp_gt_translate(struct rte_swx_pipeline *p,
6177 struct action *action,
6180 struct instruction *instr,
6181 struct instruction_data *data)
6183 char *a = tokens[2], *b = tokens[3];
6184 struct field *fa, *fb;
6186 uint32_t a_struct_id, b_struct_id;
6188 CHECK(n_tokens == 4, EINVAL);
6190 strcpy(data->jmp_label, tokens[1]);
6192 fa = struct_field_parse(p, action, a, &a_struct_id);
6194 CHECK(!fa->var_size, EINVAL);
6196 /* JMP_GT, JMP_GT_MH, JMP_GT_HM, JMP_GT_HH. */
6197 fb = struct_field_parse(p, action, b, &b_struct_id);
6199 CHECK(!fb->var_size, EINVAL);
6201 instr->type = INSTR_JMP_GT;
6202 if (a[0] == 'h' && b[0] != 'h')
6203 instr->type = INSTR_JMP_GT_HM;
6204 if (a[0] != 'h' && b[0] == 'h')
6205 instr->type = INSTR_JMP_GT_MH;
6206 if (a[0] == 'h' && b[0] == 'h')
6207 instr->type = INSTR_JMP_GT_HH;
6208 instr->jmp.ip = NULL; /* Resolved later. */
6210 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6211 instr->jmp.a.n_bits = fa->n_bits;
6212 instr->jmp.a.offset = fa->offset / 8;
6213 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6214 instr->jmp.b.n_bits = fb->n_bits;
6215 instr->jmp.b.offset = fb->offset / 8;
6219 /* JMP_GT_MI, JMP_GT_HI. */
6220 b_val = strtoull(b, &b, 0);
6221 CHECK(!b[0], EINVAL);
6223 instr->type = INSTR_JMP_GT_MI;
6225 instr->type = INSTR_JMP_GT_HI;
6226 instr->jmp.ip = NULL; /* Resolved later. */
6228 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6229 instr->jmp.a.n_bits = fa->n_bits;
6230 instr->jmp.a.offset = fa->offset / 8;
6231 instr->jmp.b_val = b_val;
6236 instr_jmp_exec(struct rte_swx_pipeline *p)
6238 struct thread *t = &p->threads[p->thread_id];
6239 struct instruction *ip = t->ip;
6241 TRACE("[Thread %2u] jmp\n", p->thread_id);
6243 thread_ip_set(t, ip->jmp.ip);
6247 instr_jmp_valid_exec(struct rte_swx_pipeline *p)
6249 struct thread *t = &p->threads[p->thread_id];
6250 struct instruction *ip = t->ip;
6251 uint32_t header_id = ip->jmp.header_id;
6253 TRACE("[Thread %2u] jmpv\n", p->thread_id);
6255 t->ip = HEADER_VALID(t, header_id) ? ip->jmp.ip : (t->ip + 1);
6259 instr_jmp_invalid_exec(struct rte_swx_pipeline *p)
6261 struct thread *t = &p->threads[p->thread_id];
6262 struct instruction *ip = t->ip;
6263 uint32_t header_id = ip->jmp.header_id;
6265 TRACE("[Thread %2u] jmpnv\n", p->thread_id);
6267 t->ip = HEADER_VALID(t, header_id) ? (t->ip + 1) : ip->jmp.ip;
6271 instr_jmp_hit_exec(struct rte_swx_pipeline *p)
6273 struct thread *t = &p->threads[p->thread_id];
6274 struct instruction *ip = t->ip;
6275 struct instruction *ip_next[] = {t->ip + 1, ip->jmp.ip};
6277 TRACE("[Thread %2u] jmph\n", p->thread_id);
6279 t->ip = ip_next[t->hit];
6283 instr_jmp_miss_exec(struct rte_swx_pipeline *p)
6285 struct thread *t = &p->threads[p->thread_id];
6286 struct instruction *ip = t->ip;
6287 struct instruction *ip_next[] = {ip->jmp.ip, t->ip + 1};
6289 TRACE("[Thread %2u] jmpnh\n", p->thread_id);
6291 t->ip = ip_next[t->hit];
6295 instr_jmp_action_hit_exec(struct rte_swx_pipeline *p)
6297 struct thread *t = &p->threads[p->thread_id];
6298 struct instruction *ip = t->ip;
6300 TRACE("[Thread %2u] jmpa\n", p->thread_id);
6302 t->ip = (ip->jmp.action_id == t->action_id) ? ip->jmp.ip : (t->ip + 1);
6306 instr_jmp_action_miss_exec(struct rte_swx_pipeline *p)
6308 struct thread *t = &p->threads[p->thread_id];
6309 struct instruction *ip = t->ip;
6311 TRACE("[Thread %2u] jmpna\n", p->thread_id);
6313 t->ip = (ip->jmp.action_id == t->action_id) ? (t->ip + 1) : ip->jmp.ip;
6317 instr_jmp_eq_exec(struct rte_swx_pipeline *p)
6319 struct thread *t = &p->threads[p->thread_id];
6320 struct instruction *ip = t->ip;
6322 TRACE("[Thread %2u] jmpeq\n", p->thread_id);
6328 instr_jmp_eq_mh_exec(struct rte_swx_pipeline *p)
6330 struct thread *t = &p->threads[p->thread_id];
6331 struct instruction *ip = t->ip;
6333 TRACE("[Thread %2u] jmpeq (mh)\n", p->thread_id);
6335 JMP_CMP_MH(t, ip, ==);
6339 instr_jmp_eq_hm_exec(struct rte_swx_pipeline *p)
6341 struct thread *t = &p->threads[p->thread_id];
6342 struct instruction *ip = t->ip;
6344 TRACE("[Thread %2u] jmpeq (hm)\n", p->thread_id);
6346 JMP_CMP_HM(t, ip, ==);
6350 instr_jmp_eq_hh_exec(struct rte_swx_pipeline *p)
6352 struct thread *t = &p->threads[p->thread_id];
6353 struct instruction *ip = t->ip;
6355 TRACE("[Thread %2u] jmpeq (hh)\n", p->thread_id);
6357 JMP_CMP_HH_FAST(t, ip, ==);
6361 instr_jmp_eq_i_exec(struct rte_swx_pipeline *p)
6363 struct thread *t = &p->threads[p->thread_id];
6364 struct instruction *ip = t->ip;
6366 TRACE("[Thread %2u] jmpeq (i)\n", p->thread_id);
6368 JMP_CMP_I(t, ip, ==);
6372 instr_jmp_neq_exec(struct rte_swx_pipeline *p)
6374 struct thread *t = &p->threads[p->thread_id];
6375 struct instruction *ip = t->ip;
6377 TRACE("[Thread %2u] jmpneq\n", p->thread_id);
6383 instr_jmp_neq_mh_exec(struct rte_swx_pipeline *p)
6385 struct thread *t = &p->threads[p->thread_id];
6386 struct instruction *ip = t->ip;
6388 TRACE("[Thread %2u] jmpneq (mh)\n", p->thread_id);
6390 JMP_CMP_MH(t, ip, !=);
6394 instr_jmp_neq_hm_exec(struct rte_swx_pipeline *p)
6396 struct thread *t = &p->threads[p->thread_id];
6397 struct instruction *ip = t->ip;
6399 TRACE("[Thread %2u] jmpneq (hm)\n", p->thread_id);
6401 JMP_CMP_HM(t, ip, !=);
6405 instr_jmp_neq_hh_exec(struct rte_swx_pipeline *p)
6407 struct thread *t = &p->threads[p->thread_id];
6408 struct instruction *ip = t->ip;
6410 TRACE("[Thread %2u] jmpneq (hh)\n", p->thread_id);
6412 JMP_CMP_HH_FAST(t, ip, !=);
6416 instr_jmp_neq_i_exec(struct rte_swx_pipeline *p)
6418 struct thread *t = &p->threads[p->thread_id];
6419 struct instruction *ip = t->ip;
6421 TRACE("[Thread %2u] jmpneq (i)\n", p->thread_id);
6423 JMP_CMP_I(t, ip, !=);
6427 instr_jmp_lt_exec(struct rte_swx_pipeline *p)
6429 struct thread *t = &p->threads[p->thread_id];
6430 struct instruction *ip = t->ip;
6432 TRACE("[Thread %2u] jmplt\n", p->thread_id);
6438 instr_jmp_lt_mh_exec(struct rte_swx_pipeline *p)
6440 struct thread *t = &p->threads[p->thread_id];
6441 struct instruction *ip = t->ip;
6443 TRACE("[Thread %2u] jmplt (mh)\n", p->thread_id);
6445 JMP_CMP_MH(t, ip, <);
6449 instr_jmp_lt_hm_exec(struct rte_swx_pipeline *p)
6451 struct thread *t = &p->threads[p->thread_id];
6452 struct instruction *ip = t->ip;
6454 TRACE("[Thread %2u] jmplt (hm)\n", p->thread_id);
6456 JMP_CMP_HM(t, ip, <);
6460 instr_jmp_lt_hh_exec(struct rte_swx_pipeline *p)
6462 struct thread *t = &p->threads[p->thread_id];
6463 struct instruction *ip = t->ip;
6465 TRACE("[Thread %2u] jmplt (hh)\n", p->thread_id);
6467 JMP_CMP_HH(t, ip, <);
6471 instr_jmp_lt_mi_exec(struct rte_swx_pipeline *p)
6473 struct thread *t = &p->threads[p->thread_id];
6474 struct instruction *ip = t->ip;
6476 TRACE("[Thread %2u] jmplt (mi)\n", p->thread_id);
6478 JMP_CMP_MI(t, ip, <);
6482 instr_jmp_lt_hi_exec(struct rte_swx_pipeline *p)
6484 struct thread *t = &p->threads[p->thread_id];
6485 struct instruction *ip = t->ip;
6487 TRACE("[Thread %2u] jmplt (hi)\n", p->thread_id);
6489 JMP_CMP_HI(t, ip, <);
6493 instr_jmp_gt_exec(struct rte_swx_pipeline *p)
6495 struct thread *t = &p->threads[p->thread_id];
6496 struct instruction *ip = t->ip;
6498 TRACE("[Thread %2u] jmpgt\n", p->thread_id);
6504 instr_jmp_gt_mh_exec(struct rte_swx_pipeline *p)
6506 struct thread *t = &p->threads[p->thread_id];
6507 struct instruction *ip = t->ip;
6509 TRACE("[Thread %2u] jmpgt (mh)\n", p->thread_id);
6511 JMP_CMP_MH(t, ip, >);
6515 instr_jmp_gt_hm_exec(struct rte_swx_pipeline *p)
6517 struct thread *t = &p->threads[p->thread_id];
6518 struct instruction *ip = t->ip;
6520 TRACE("[Thread %2u] jmpgt (hm)\n", p->thread_id);
6522 JMP_CMP_HM(t, ip, >);
6526 instr_jmp_gt_hh_exec(struct rte_swx_pipeline *p)
6528 struct thread *t = &p->threads[p->thread_id];
6529 struct instruction *ip = t->ip;
6531 TRACE("[Thread %2u] jmpgt (hh)\n", p->thread_id);
6533 JMP_CMP_HH(t, ip, >);
6537 instr_jmp_gt_mi_exec(struct rte_swx_pipeline *p)
6539 struct thread *t = &p->threads[p->thread_id];
6540 struct instruction *ip = t->ip;
6542 TRACE("[Thread %2u] jmpgt (mi)\n", p->thread_id);
6544 JMP_CMP_MI(t, ip, >);
6548 instr_jmp_gt_hi_exec(struct rte_swx_pipeline *p)
6550 struct thread *t = &p->threads[p->thread_id];
6551 struct instruction *ip = t->ip;
6553 TRACE("[Thread %2u] jmpgt (hi)\n", p->thread_id);
6555 JMP_CMP_HI(t, ip, >);
6562 instr_return_translate(struct rte_swx_pipeline *p __rte_unused,
6563 struct action *action,
6564 char **tokens __rte_unused,
6566 struct instruction *instr,
6567 struct instruction_data *data __rte_unused)
6569 CHECK(action, EINVAL);
6570 CHECK(n_tokens == 1, EINVAL);
6572 instr->type = INSTR_RETURN;
6577 instr_return_exec(struct rte_swx_pipeline *p)
6579 struct thread *t = &p->threads[p->thread_id];
6581 TRACE("[Thread %2u] return\n", p->thread_id);
6587 instr_translate(struct rte_swx_pipeline *p,
6588 struct action *action,
6590 struct instruction *instr,
6591 struct instruction_data *data)
6593 char *tokens[RTE_SWX_INSTRUCTION_TOKENS_MAX];
6594 int n_tokens = 0, tpos = 0;
6596 /* Parse the instruction string into tokens. */
6600 token = strtok_r(string, " \t\v", &string);
6604 CHECK(n_tokens < RTE_SWX_INSTRUCTION_TOKENS_MAX, EINVAL);
6605 CHECK_NAME(token, EINVAL);
6607 tokens[n_tokens] = token;
6611 CHECK(n_tokens, EINVAL);
6613 /* Handle the optional instruction label. */
6614 if ((n_tokens >= 2) && !strcmp(tokens[1], ":")) {
6615 strcpy(data->label, tokens[0]);
6618 CHECK(n_tokens - tpos, EINVAL);
6621 /* Identify the instruction type. */
6622 if (!strcmp(tokens[tpos], "rx"))
6623 return instr_rx_translate(p,
6630 if (!strcmp(tokens[tpos], "tx"))
6631 return instr_tx_translate(p,
6638 if (!strcmp(tokens[tpos], "drop"))
6639 return instr_drop_translate(p,
6646 if (!strcmp(tokens[tpos], "extract"))
6647 return instr_hdr_extract_translate(p,
6654 if (!strcmp(tokens[tpos], "lookahead"))
6655 return instr_hdr_lookahead_translate(p,
6662 if (!strcmp(tokens[tpos], "emit"))
6663 return instr_hdr_emit_translate(p,
6670 if (!strcmp(tokens[tpos], "validate"))
6671 return instr_hdr_validate_translate(p,
6678 if (!strcmp(tokens[tpos], "invalidate"))
6679 return instr_hdr_invalidate_translate(p,
6686 if (!strcmp(tokens[tpos], "mov"))
6687 return instr_mov_translate(p,
6694 if (!strcmp(tokens[tpos], "add"))
6695 return instr_alu_add_translate(p,
6702 if (!strcmp(tokens[tpos], "sub"))
6703 return instr_alu_sub_translate(p,
6710 if (!strcmp(tokens[tpos], "ckadd"))
6711 return instr_alu_ckadd_translate(p,
6718 if (!strcmp(tokens[tpos], "cksub"))
6719 return instr_alu_cksub_translate(p,
6726 if (!strcmp(tokens[tpos], "and"))
6727 return instr_alu_and_translate(p,
6734 if (!strcmp(tokens[tpos], "or"))
6735 return instr_alu_or_translate(p,
6742 if (!strcmp(tokens[tpos], "xor"))
6743 return instr_alu_xor_translate(p,
6750 if (!strcmp(tokens[tpos], "shl"))
6751 return instr_alu_shl_translate(p,
6758 if (!strcmp(tokens[tpos], "shr"))
6759 return instr_alu_shr_translate(p,
6766 if (!strcmp(tokens[tpos], "regprefetch"))
6767 return instr_regprefetch_translate(p,
6774 if (!strcmp(tokens[tpos], "regrd"))
6775 return instr_regrd_translate(p,
6782 if (!strcmp(tokens[tpos], "regwr"))
6783 return instr_regwr_translate(p,
6790 if (!strcmp(tokens[tpos], "regadd"))
6791 return instr_regadd_translate(p,
6798 if (!strcmp(tokens[tpos], "metprefetch"))
6799 return instr_metprefetch_translate(p,
6806 if (!strcmp(tokens[tpos], "meter"))
6807 return instr_meter_translate(p,
6814 if (!strcmp(tokens[tpos], "table"))
6815 return instr_table_translate(p,
6822 if (!strcmp(tokens[tpos], "learn"))
6823 return instr_learn_translate(p,
6830 if (!strcmp(tokens[tpos], "forget"))
6831 return instr_forget_translate(p,
6838 if (!strcmp(tokens[tpos], "extern"))
6839 return instr_extern_translate(p,
6846 if (!strcmp(tokens[tpos], "jmp"))
6847 return instr_jmp_translate(p,
6854 if (!strcmp(tokens[tpos], "jmpv"))
6855 return instr_jmp_valid_translate(p,
6862 if (!strcmp(tokens[tpos], "jmpnv"))
6863 return instr_jmp_invalid_translate(p,
6870 if (!strcmp(tokens[tpos], "jmph"))
6871 return instr_jmp_hit_translate(p,
6878 if (!strcmp(tokens[tpos], "jmpnh"))
6879 return instr_jmp_miss_translate(p,
6886 if (!strcmp(tokens[tpos], "jmpa"))
6887 return instr_jmp_action_hit_translate(p,
6894 if (!strcmp(tokens[tpos], "jmpna"))
6895 return instr_jmp_action_miss_translate(p,
6902 if (!strcmp(tokens[tpos], "jmpeq"))
6903 return instr_jmp_eq_translate(p,
6910 if (!strcmp(tokens[tpos], "jmpneq"))
6911 return instr_jmp_neq_translate(p,
6918 if (!strcmp(tokens[tpos], "jmplt"))
6919 return instr_jmp_lt_translate(p,
6926 if (!strcmp(tokens[tpos], "jmpgt"))
6927 return instr_jmp_gt_translate(p,
6934 if (!strcmp(tokens[tpos], "return"))
6935 return instr_return_translate(p,
6945 static struct instruction_data *
6946 label_find(struct instruction_data *data, uint32_t n, const char *label)
6950 for (i = 0; i < n; i++)
6951 if (!strcmp(label, data[i].label))
6958 label_is_used(struct instruction_data *data, uint32_t n, const char *label)
6960 uint32_t count = 0, i;
6965 for (i = 0; i < n; i++)
6966 if (!strcmp(label, data[i].jmp_label))
6973 instr_label_check(struct instruction_data *instruction_data,
6974 uint32_t n_instructions)
6978 /* Check that all instruction labels are unique. */
6979 for (i = 0; i < n_instructions; i++) {
6980 struct instruction_data *data = &instruction_data[i];
6981 char *label = data->label;
6987 for (j = i + 1; j < n_instructions; j++)
6988 CHECK(strcmp(label, data[j].label), EINVAL);
6991 /* Get users for each instruction label. */
6992 for (i = 0; i < n_instructions; i++) {
6993 struct instruction_data *data = &instruction_data[i];
6994 char *label = data->label;
6996 data->n_users = label_is_used(instruction_data,
7005 instr_jmp_resolve(struct instruction *instructions,
7006 struct instruction_data *instruction_data,
7007 uint32_t n_instructions)
7011 for (i = 0; i < n_instructions; i++) {
7012 struct instruction *instr = &instructions[i];
7013 struct instruction_data *data = &instruction_data[i];
7014 struct instruction_data *found;
7016 if (!instruction_is_jmp(instr))
7019 found = label_find(instruction_data,
7022 CHECK(found, EINVAL);
7024 instr->jmp.ip = &instructions[found - instruction_data];
7031 instr_verify(struct rte_swx_pipeline *p __rte_unused,
7033 struct instruction *instr,
7034 struct instruction_data *data __rte_unused,
7035 uint32_t n_instructions)
7038 enum instruction_type type;
7041 /* Check that the first instruction is rx. */
7042 CHECK(instr[0].type == INSTR_RX, EINVAL);
7044 /* Check that there is at least one tx instruction. */
7045 for (i = 0; i < n_instructions; i++) {
7046 type = instr[i].type;
7048 if (instruction_is_tx(type))
7051 CHECK(i < n_instructions, EINVAL);
7053 /* Check that the last instruction is either tx or unconditional
7056 type = instr[n_instructions - 1].type;
7057 CHECK(instruction_is_tx(type) || (type == INSTR_JMP), EINVAL);
7061 enum instruction_type type;
7064 /* Check that there is at least one return or tx instruction. */
7065 for (i = 0; i < n_instructions; i++) {
7066 type = instr[i].type;
7068 if ((type == INSTR_RETURN) || instruction_is_tx(type))
7071 CHECK(i < n_instructions, EINVAL);
7078 instr_compact(struct instruction *instructions,
7079 struct instruction_data *instruction_data,
7080 uint32_t n_instructions)
7082 uint32_t i, pos = 0;
7084 /* Eliminate the invalid instructions that have been optimized out. */
7085 for (i = 0; i < n_instructions; i++) {
7086 struct instruction *instr = &instructions[i];
7087 struct instruction_data *data = &instruction_data[i];
7093 memcpy(&instructions[pos], instr, sizeof(*instr));
7094 memcpy(&instruction_data[pos], data, sizeof(*data));
7104 instr_pattern_extract_many_search(struct instruction *instr,
7105 struct instruction_data *data,
7107 uint32_t *n_pattern_instr)
7111 for (i = 0; i < n_instr; i++) {
7112 if (data[i].invalid)
7115 if (instr[i].type != INSTR_HDR_EXTRACT)
7118 if (i == RTE_DIM(instr->io.hdr.header_id))
7121 if (i && data[i].n_users)
7128 *n_pattern_instr = i;
7133 instr_pattern_extract_many_replace(struct instruction *instr,
7134 struct instruction_data *data,
7139 for (i = 1; i < n_instr; i++) {
7141 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
7142 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
7143 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
7145 data[i].invalid = 1;
7150 instr_pattern_extract_many_optimize(struct instruction *instructions,
7151 struct instruction_data *instruction_data,
7152 uint32_t n_instructions)
7156 for (i = 0; i < n_instructions; ) {
7157 struct instruction *instr = &instructions[i];
7158 struct instruction_data *data = &instruction_data[i];
7159 uint32_t n_instr = 0;
7163 detected = instr_pattern_extract_many_search(instr,
7168 instr_pattern_extract_many_replace(instr,
7175 /* No pattern starting at the current instruction. */
7179 /* Eliminate the invalid instructions that have been optimized out. */
7180 n_instructions = instr_compact(instructions,
7184 return n_instructions;
7188 instr_pattern_emit_many_tx_search(struct instruction *instr,
7189 struct instruction_data *data,
7191 uint32_t *n_pattern_instr)
7195 for (i = 0; i < n_instr; i++) {
7196 if (data[i].invalid)
7199 if (instr[i].type != INSTR_HDR_EMIT)
7202 if (i == RTE_DIM(instr->io.hdr.header_id))
7205 if (i && data[i].n_users)
7212 if (!instruction_is_tx(instr[i].type))
7215 if (data[i].n_users)
7220 *n_pattern_instr = i;
7225 instr_pattern_emit_many_tx_replace(struct instruction *instr,
7226 struct instruction_data *data,
7231 /* Any emit instruction in addition to the first one. */
7232 for (i = 1; i < n_instr - 1; i++) {
7234 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
7235 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
7236 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
7238 data[i].invalid = 1;
7241 /* The TX instruction is the last one in the pattern. */
7243 instr[0].io.io.offset = instr[i].io.io.offset;
7244 instr[0].io.io.n_bits = instr[i].io.io.n_bits;
7245 data[i].invalid = 1;
7249 instr_pattern_emit_many_tx_optimize(struct instruction *instructions,
7250 struct instruction_data *instruction_data,
7251 uint32_t n_instructions)
7255 for (i = 0; i < n_instructions; ) {
7256 struct instruction *instr = &instructions[i];
7257 struct instruction_data *data = &instruction_data[i];
7258 uint32_t n_instr = 0;
7261 /* Emit many + TX. */
7262 detected = instr_pattern_emit_many_tx_search(instr,
7267 instr_pattern_emit_many_tx_replace(instr,
7274 /* No pattern starting at the current instruction. */
7278 /* Eliminate the invalid instructions that have been optimized out. */
7279 n_instructions = instr_compact(instructions,
7283 return n_instructions;
7287 action_arg_src_mov_count(struct action *a,
7289 struct instruction *instructions,
7290 struct instruction_data *instruction_data,
7291 uint32_t n_instructions);
7294 instr_pattern_mov_all_validate_search(struct rte_swx_pipeline *p,
7296 struct instruction *instr,
7297 struct instruction_data *data,
7299 struct instruction *instructions,
7300 struct instruction_data *instruction_data,
7301 uint32_t n_instructions,
7302 uint32_t *n_pattern_instr)
7305 uint32_t src_field_id, i, j;
7307 /* Prerequisites. */
7311 /* First instruction: MOV_HM. */
7312 if (data[0].invalid || (instr[0].type != INSTR_MOV_HM))
7315 h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
7316 if (!h || h->st->var_size)
7319 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
7320 if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
7323 if (src_field_id == a->st->n_fields)
7326 if (instr[0].mov.dst.offset ||
7327 (instr[0].mov.dst.n_bits != h->st->fields[0].n_bits) ||
7328 instr[0].mov.src.struct_id ||
7329 (instr[0].mov.src.n_bits != a->st->fields[src_field_id].n_bits) ||
7330 (instr[0].mov.dst.n_bits != instr[0].mov.src.n_bits))
7333 if ((n_instr < h->st->n_fields + 1) ||
7334 (a->st->n_fields < src_field_id + h->st->n_fields + 1))
7337 /* Subsequent instructions: MOV_HM. */
7338 for (i = 1; i < h->st->n_fields; i++)
7339 if (data[i].invalid ||
7341 (instr[i].type != INSTR_MOV_HM) ||
7342 (instr[i].mov.dst.struct_id != h->struct_id) ||
7343 (instr[i].mov.dst.offset != h->st->fields[i].offset / 8) ||
7344 (instr[i].mov.dst.n_bits != h->st->fields[i].n_bits) ||
7345 instr[i].mov.src.struct_id ||
7346 (instr[i].mov.src.offset != a->st->fields[src_field_id + i].offset / 8) ||
7347 (instr[i].mov.src.n_bits != a->st->fields[src_field_id + i].n_bits) ||
7348 (instr[i].mov.dst.n_bits != instr[i].mov.src.n_bits))
7351 /* Last instruction: HDR_VALIDATE. */
7352 if ((instr[i].type != INSTR_HDR_VALIDATE) ||
7353 (instr[i].valid.header_id != h->id))
7356 /* Check that none of the action args that are used as source for this
7357 * DMA transfer are not used as source in any other mov instruction.
7359 for (j = src_field_id; j < src_field_id + h->st->n_fields; j++) {
7362 n_users = action_arg_src_mov_count(a,
7371 *n_pattern_instr = 1 + i;
7376 instr_pattern_mov_all_validate_replace(struct rte_swx_pipeline *p,
7378 struct instruction *instr,
7379 struct instruction_data *data,
7383 uint32_t src_field_id, src_offset, i;
7385 /* Read from the instructions before they are modified. */
7386 h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
7390 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
7391 if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
7394 if (src_field_id == a->st->n_fields)
7397 src_offset = instr[0].mov.src.offset;
7399 /* Modify the instructions. */
7400 instr[0].type = INSTR_DMA_HT;
7401 instr[0].dma.dst.header_id[0] = h->id;
7402 instr[0].dma.dst.struct_id[0] = h->struct_id;
7403 instr[0].dma.src.offset[0] = (uint8_t)src_offset;
7404 instr[0].dma.n_bytes[0] = h->st->n_bits / 8;
7406 for (i = 1; i < n_instr; i++)
7407 data[i].invalid = 1;
7409 /* Update the endianness of the action arguments to header endianness. */
7410 for (i = 0; i < h->st->n_fields; i++)
7411 a->args_endianness[src_field_id + i] = 1;
7415 instr_pattern_mov_all_validate_optimize(struct rte_swx_pipeline *p,
7417 struct instruction *instructions,
7418 struct instruction_data *instruction_data,
7419 uint32_t n_instructions)
7424 return n_instructions;
7426 for (i = 0; i < n_instructions; ) {
7427 struct instruction *instr = &instructions[i];
7428 struct instruction_data *data = &instruction_data[i];
7429 uint32_t n_instr = 0;
7432 /* Mov all + validate. */
7433 detected = instr_pattern_mov_all_validate_search(p,
7443 instr_pattern_mov_all_validate_replace(p, a, instr, data, n_instr);
7448 /* No pattern starting at the current instruction. */
7452 /* Eliminate the invalid instructions that have been optimized out. */
7453 n_instructions = instr_compact(instructions,
7457 return n_instructions;
7461 instr_pattern_dma_many_search(struct instruction *instr,
7462 struct instruction_data *data,
7464 uint32_t *n_pattern_instr)
7468 for (i = 0; i < n_instr; i++) {
7469 if (data[i].invalid)
7472 if (instr[i].type != INSTR_DMA_HT)
7475 if (i == RTE_DIM(instr->dma.dst.header_id))
7478 if (i && data[i].n_users)
7485 *n_pattern_instr = i;
7490 instr_pattern_dma_many_replace(struct instruction *instr,
7491 struct instruction_data *data,
7496 for (i = 1; i < n_instr; i++) {
7498 instr[0].dma.dst.header_id[i] = instr[i].dma.dst.header_id[0];
7499 instr[0].dma.dst.struct_id[i] = instr[i].dma.dst.struct_id[0];
7500 instr[0].dma.src.offset[i] = instr[i].dma.src.offset[0];
7501 instr[0].dma.n_bytes[i] = instr[i].dma.n_bytes[0];
7503 data[i].invalid = 1;
7508 instr_pattern_dma_many_optimize(struct instruction *instructions,
7509 struct instruction_data *instruction_data,
7510 uint32_t n_instructions)
7514 for (i = 0; i < n_instructions; ) {
7515 struct instruction *instr = &instructions[i];
7516 struct instruction_data *data = &instruction_data[i];
7517 uint32_t n_instr = 0;
7521 detected = instr_pattern_dma_many_search(instr,
7526 instr_pattern_dma_many_replace(instr, data, n_instr);
7531 /* No pattern starting at the current instruction. */
7535 /* Eliminate the invalid instructions that have been optimized out. */
7536 n_instructions = instr_compact(instructions,
7540 return n_instructions;
7544 instr_optimize(struct rte_swx_pipeline *p,
7546 struct instruction *instructions,
7547 struct instruction_data *instruction_data,
7548 uint32_t n_instructions)
7551 n_instructions = instr_pattern_extract_many_optimize(instructions,
7555 /* Emit many + TX. */
7556 n_instructions = instr_pattern_emit_many_tx_optimize(instructions,
7560 /* Mov all + validate. */
7561 n_instructions = instr_pattern_mov_all_validate_optimize(p,
7568 n_instructions = instr_pattern_dma_many_optimize(instructions,
7572 return n_instructions;
7576 instruction_config(struct rte_swx_pipeline *p,
7578 const char **instructions,
7579 uint32_t n_instructions)
7581 struct instruction *instr = NULL;
7582 struct instruction_data *data = NULL;
7586 CHECK(n_instructions, EINVAL);
7587 CHECK(instructions, EINVAL);
7588 for (i = 0; i < n_instructions; i++)
7589 CHECK_INSTRUCTION(instructions[i], EINVAL);
7591 /* Memory allocation. */
7592 instr = calloc(n_instructions, sizeof(struct instruction));
7598 data = calloc(n_instructions, sizeof(struct instruction_data));
7604 for (i = 0; i < n_instructions; i++) {
7605 char *string = strdup(instructions[i]);
7611 err = instr_translate(p, a, string, &instr[i], &data[i]);
7620 err = instr_label_check(data, n_instructions);
7624 err = instr_verify(p, a, instr, data, n_instructions);
7628 n_instructions = instr_optimize(p, a, instr, data, n_instructions);
7630 err = instr_jmp_resolve(instr, data, n_instructions);
7635 a->instructions = instr;
7636 a->n_instructions = n_instructions;
7638 p->instructions = instr;
7639 p->n_instructions = n_instructions;
7651 typedef void (*instr_exec_t)(struct rte_swx_pipeline *);
7653 static instr_exec_t instruction_table[] = {
7654 [INSTR_RX] = instr_rx_exec,
7655 [INSTR_TX] = instr_tx_exec,
7656 [INSTR_TX_I] = instr_tx_i_exec,
7658 [INSTR_HDR_EXTRACT] = instr_hdr_extract_exec,
7659 [INSTR_HDR_EXTRACT2] = instr_hdr_extract2_exec,
7660 [INSTR_HDR_EXTRACT3] = instr_hdr_extract3_exec,
7661 [INSTR_HDR_EXTRACT4] = instr_hdr_extract4_exec,
7662 [INSTR_HDR_EXTRACT5] = instr_hdr_extract5_exec,
7663 [INSTR_HDR_EXTRACT6] = instr_hdr_extract6_exec,
7664 [INSTR_HDR_EXTRACT7] = instr_hdr_extract7_exec,
7665 [INSTR_HDR_EXTRACT8] = instr_hdr_extract8_exec,
7666 [INSTR_HDR_EXTRACT_M] = instr_hdr_extract_m_exec,
7667 [INSTR_HDR_LOOKAHEAD] = instr_hdr_lookahead_exec,
7669 [INSTR_HDR_EMIT] = instr_hdr_emit_exec,
7670 [INSTR_HDR_EMIT_TX] = instr_hdr_emit_tx_exec,
7671 [INSTR_HDR_EMIT2_TX] = instr_hdr_emit2_tx_exec,
7672 [INSTR_HDR_EMIT3_TX] = instr_hdr_emit3_tx_exec,
7673 [INSTR_HDR_EMIT4_TX] = instr_hdr_emit4_tx_exec,
7674 [INSTR_HDR_EMIT5_TX] = instr_hdr_emit5_tx_exec,
7675 [INSTR_HDR_EMIT6_TX] = instr_hdr_emit6_tx_exec,
7676 [INSTR_HDR_EMIT7_TX] = instr_hdr_emit7_tx_exec,
7677 [INSTR_HDR_EMIT8_TX] = instr_hdr_emit8_tx_exec,
7679 [INSTR_HDR_VALIDATE] = instr_hdr_validate_exec,
7680 [INSTR_HDR_INVALIDATE] = instr_hdr_invalidate_exec,
7682 [INSTR_MOV] = instr_mov_exec,
7683 [INSTR_MOV_MH] = instr_mov_mh_exec,
7684 [INSTR_MOV_HM] = instr_mov_hm_exec,
7685 [INSTR_MOV_HH] = instr_mov_hh_exec,
7686 [INSTR_MOV_I] = instr_mov_i_exec,
7688 [INSTR_DMA_HT] = instr_dma_ht_exec,
7689 [INSTR_DMA_HT2] = instr_dma_ht2_exec,
7690 [INSTR_DMA_HT3] = instr_dma_ht3_exec,
7691 [INSTR_DMA_HT4] = instr_dma_ht4_exec,
7692 [INSTR_DMA_HT5] = instr_dma_ht5_exec,
7693 [INSTR_DMA_HT6] = instr_dma_ht6_exec,
7694 [INSTR_DMA_HT7] = instr_dma_ht7_exec,
7695 [INSTR_DMA_HT8] = instr_dma_ht8_exec,
7697 [INSTR_ALU_ADD] = instr_alu_add_exec,
7698 [INSTR_ALU_ADD_MH] = instr_alu_add_mh_exec,
7699 [INSTR_ALU_ADD_HM] = instr_alu_add_hm_exec,
7700 [INSTR_ALU_ADD_HH] = instr_alu_add_hh_exec,
7701 [INSTR_ALU_ADD_MI] = instr_alu_add_mi_exec,
7702 [INSTR_ALU_ADD_HI] = instr_alu_add_hi_exec,
7704 [INSTR_ALU_SUB] = instr_alu_sub_exec,
7705 [INSTR_ALU_SUB_MH] = instr_alu_sub_mh_exec,
7706 [INSTR_ALU_SUB_HM] = instr_alu_sub_hm_exec,
7707 [INSTR_ALU_SUB_HH] = instr_alu_sub_hh_exec,
7708 [INSTR_ALU_SUB_MI] = instr_alu_sub_mi_exec,
7709 [INSTR_ALU_SUB_HI] = instr_alu_sub_hi_exec,
7711 [INSTR_ALU_CKADD_FIELD] = instr_alu_ckadd_field_exec,
7712 [INSTR_ALU_CKADD_STRUCT] = instr_alu_ckadd_struct_exec,
7713 [INSTR_ALU_CKADD_STRUCT20] = instr_alu_ckadd_struct20_exec,
7714 [INSTR_ALU_CKSUB_FIELD] = instr_alu_cksub_field_exec,
7716 [INSTR_ALU_AND] = instr_alu_and_exec,
7717 [INSTR_ALU_AND_MH] = instr_alu_and_mh_exec,
7718 [INSTR_ALU_AND_HM] = instr_alu_and_hm_exec,
7719 [INSTR_ALU_AND_HH] = instr_alu_and_hh_exec,
7720 [INSTR_ALU_AND_I] = instr_alu_and_i_exec,
7722 [INSTR_ALU_OR] = instr_alu_or_exec,
7723 [INSTR_ALU_OR_MH] = instr_alu_or_mh_exec,
7724 [INSTR_ALU_OR_HM] = instr_alu_or_hm_exec,
7725 [INSTR_ALU_OR_HH] = instr_alu_or_hh_exec,
7726 [INSTR_ALU_OR_I] = instr_alu_or_i_exec,
7728 [INSTR_ALU_XOR] = instr_alu_xor_exec,
7729 [INSTR_ALU_XOR_MH] = instr_alu_xor_mh_exec,
7730 [INSTR_ALU_XOR_HM] = instr_alu_xor_hm_exec,
7731 [INSTR_ALU_XOR_HH] = instr_alu_xor_hh_exec,
7732 [INSTR_ALU_XOR_I] = instr_alu_xor_i_exec,
7734 [INSTR_ALU_SHL] = instr_alu_shl_exec,
7735 [INSTR_ALU_SHL_MH] = instr_alu_shl_mh_exec,
7736 [INSTR_ALU_SHL_HM] = instr_alu_shl_hm_exec,
7737 [INSTR_ALU_SHL_HH] = instr_alu_shl_hh_exec,
7738 [INSTR_ALU_SHL_MI] = instr_alu_shl_mi_exec,
7739 [INSTR_ALU_SHL_HI] = instr_alu_shl_hi_exec,
7741 [INSTR_ALU_SHR] = instr_alu_shr_exec,
7742 [INSTR_ALU_SHR_MH] = instr_alu_shr_mh_exec,
7743 [INSTR_ALU_SHR_HM] = instr_alu_shr_hm_exec,
7744 [INSTR_ALU_SHR_HH] = instr_alu_shr_hh_exec,
7745 [INSTR_ALU_SHR_MI] = instr_alu_shr_mi_exec,
7746 [INSTR_ALU_SHR_HI] = instr_alu_shr_hi_exec,
7748 [INSTR_REGPREFETCH_RH] = instr_regprefetch_rh_exec,
7749 [INSTR_REGPREFETCH_RM] = instr_regprefetch_rm_exec,
7750 [INSTR_REGPREFETCH_RI] = instr_regprefetch_ri_exec,
7752 [INSTR_REGRD_HRH] = instr_regrd_hrh_exec,
7753 [INSTR_REGRD_HRM] = instr_regrd_hrm_exec,
7754 [INSTR_REGRD_MRH] = instr_regrd_mrh_exec,
7755 [INSTR_REGRD_MRM] = instr_regrd_mrm_exec,
7756 [INSTR_REGRD_HRI] = instr_regrd_hri_exec,
7757 [INSTR_REGRD_MRI] = instr_regrd_mri_exec,
7759 [INSTR_REGWR_RHH] = instr_regwr_rhh_exec,
7760 [INSTR_REGWR_RHM] = instr_regwr_rhm_exec,
7761 [INSTR_REGWR_RMH] = instr_regwr_rmh_exec,
7762 [INSTR_REGWR_RMM] = instr_regwr_rmm_exec,
7763 [INSTR_REGWR_RHI] = instr_regwr_rhi_exec,
7764 [INSTR_REGWR_RMI] = instr_regwr_rmi_exec,
7765 [INSTR_REGWR_RIH] = instr_regwr_rih_exec,
7766 [INSTR_REGWR_RIM] = instr_regwr_rim_exec,
7767 [INSTR_REGWR_RII] = instr_regwr_rii_exec,
7769 [INSTR_REGADD_RHH] = instr_regadd_rhh_exec,
7770 [INSTR_REGADD_RHM] = instr_regadd_rhm_exec,
7771 [INSTR_REGADD_RMH] = instr_regadd_rmh_exec,
7772 [INSTR_REGADD_RMM] = instr_regadd_rmm_exec,
7773 [INSTR_REGADD_RHI] = instr_regadd_rhi_exec,
7774 [INSTR_REGADD_RMI] = instr_regadd_rmi_exec,
7775 [INSTR_REGADD_RIH] = instr_regadd_rih_exec,
7776 [INSTR_REGADD_RIM] = instr_regadd_rim_exec,
7777 [INSTR_REGADD_RII] = instr_regadd_rii_exec,
7779 [INSTR_METPREFETCH_H] = instr_metprefetch_h_exec,
7780 [INSTR_METPREFETCH_M] = instr_metprefetch_m_exec,
7781 [INSTR_METPREFETCH_I] = instr_metprefetch_i_exec,
7783 [INSTR_METER_HHM] = instr_meter_hhm_exec,
7784 [INSTR_METER_HHI] = instr_meter_hhi_exec,
7785 [INSTR_METER_HMM] = instr_meter_hmm_exec,
7786 [INSTR_METER_HMI] = instr_meter_hmi_exec,
7787 [INSTR_METER_MHM] = instr_meter_mhm_exec,
7788 [INSTR_METER_MHI] = instr_meter_mhi_exec,
7789 [INSTR_METER_MMM] = instr_meter_mmm_exec,
7790 [INSTR_METER_MMI] = instr_meter_mmi_exec,
7791 [INSTR_METER_IHM] = instr_meter_ihm_exec,
7792 [INSTR_METER_IHI] = instr_meter_ihi_exec,
7793 [INSTR_METER_IMM] = instr_meter_imm_exec,
7794 [INSTR_METER_IMI] = instr_meter_imi_exec,
7796 [INSTR_TABLE] = instr_table_exec,
7797 [INSTR_SELECTOR] = instr_selector_exec,
7798 [INSTR_LEARNER] = instr_learner_exec,
7799 [INSTR_LEARNER_LEARN] = instr_learn_exec,
7800 [INSTR_LEARNER_FORGET] = instr_forget_exec,
7801 [INSTR_EXTERN_OBJ] = instr_extern_obj_exec,
7802 [INSTR_EXTERN_FUNC] = instr_extern_func_exec,
7804 [INSTR_JMP] = instr_jmp_exec,
7805 [INSTR_JMP_VALID] = instr_jmp_valid_exec,
7806 [INSTR_JMP_INVALID] = instr_jmp_invalid_exec,
7807 [INSTR_JMP_HIT] = instr_jmp_hit_exec,
7808 [INSTR_JMP_MISS] = instr_jmp_miss_exec,
7809 [INSTR_JMP_ACTION_HIT] = instr_jmp_action_hit_exec,
7810 [INSTR_JMP_ACTION_MISS] = instr_jmp_action_miss_exec,
7812 [INSTR_JMP_EQ] = instr_jmp_eq_exec,
7813 [INSTR_JMP_EQ_MH] = instr_jmp_eq_mh_exec,
7814 [INSTR_JMP_EQ_HM] = instr_jmp_eq_hm_exec,
7815 [INSTR_JMP_EQ_HH] = instr_jmp_eq_hh_exec,
7816 [INSTR_JMP_EQ_I] = instr_jmp_eq_i_exec,
7818 [INSTR_JMP_NEQ] = instr_jmp_neq_exec,
7819 [INSTR_JMP_NEQ_MH] = instr_jmp_neq_mh_exec,
7820 [INSTR_JMP_NEQ_HM] = instr_jmp_neq_hm_exec,
7821 [INSTR_JMP_NEQ_HH] = instr_jmp_neq_hh_exec,
7822 [INSTR_JMP_NEQ_I] = instr_jmp_neq_i_exec,
7824 [INSTR_JMP_LT] = instr_jmp_lt_exec,
7825 [INSTR_JMP_LT_MH] = instr_jmp_lt_mh_exec,
7826 [INSTR_JMP_LT_HM] = instr_jmp_lt_hm_exec,
7827 [INSTR_JMP_LT_HH] = instr_jmp_lt_hh_exec,
7828 [INSTR_JMP_LT_MI] = instr_jmp_lt_mi_exec,
7829 [INSTR_JMP_LT_HI] = instr_jmp_lt_hi_exec,
7831 [INSTR_JMP_GT] = instr_jmp_gt_exec,
7832 [INSTR_JMP_GT_MH] = instr_jmp_gt_mh_exec,
7833 [INSTR_JMP_GT_HM] = instr_jmp_gt_hm_exec,
7834 [INSTR_JMP_GT_HH] = instr_jmp_gt_hh_exec,
7835 [INSTR_JMP_GT_MI] = instr_jmp_gt_mi_exec,
7836 [INSTR_JMP_GT_HI] = instr_jmp_gt_hi_exec,
7838 [INSTR_RETURN] = instr_return_exec,
7842 instr_exec(struct rte_swx_pipeline *p)
7844 struct thread *t = &p->threads[p->thread_id];
7845 struct instruction *ip = t->ip;
7846 instr_exec_t instr = instruction_table[ip->type];
7854 static struct action *
7855 action_find(struct rte_swx_pipeline *p, const char *name)
7857 struct action *elem;
7862 TAILQ_FOREACH(elem, &p->actions, node)
7863 if (strcmp(elem->name, name) == 0)
7869 static struct action *
7870 action_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7872 struct action *action = NULL;
7874 TAILQ_FOREACH(action, &p->actions, node)
7875 if (action->id == id)
7881 static struct field *
7882 action_field_find(struct action *a, const char *name)
7884 return a->st ? struct_type_field_find(a->st, name) : NULL;
7887 static struct field *
7888 action_field_parse(struct action *action, const char *name)
7890 if (name[0] != 't' || name[1] != '.')
7893 return action_field_find(action, &name[2]);
7897 action_has_nbo_args(struct action *a)
7901 /* Return if the action does not have any args. */
7903 return 0; /* FALSE */
7905 for (i = 0; i < a->st->n_fields; i++)
7906 if (a->args_endianness[i])
7907 return 1; /* TRUE */
7909 return 0; /* FALSE */
7913 action_does_learning(struct action *a)
7917 for (i = 0; i < a->n_instructions; i++)
7918 switch (a->instructions[i].type) {
7919 case INSTR_LEARNER_LEARN:
7920 return 1; /* TRUE */
7922 case INSTR_LEARNER_FORGET:
7923 return 1; /* TRUE */
7929 return 0; /* FALSE */
7933 rte_swx_pipeline_action_config(struct rte_swx_pipeline *p,
7935 const char *args_struct_type_name,
7936 const char **instructions,
7937 uint32_t n_instructions)
7939 struct struct_type *args_struct_type = NULL;
7945 CHECK_NAME(name, EINVAL);
7946 CHECK(!action_find(p, name), EEXIST);
7948 if (args_struct_type_name) {
7949 CHECK_NAME(args_struct_type_name, EINVAL);
7950 args_struct_type = struct_type_find(p, args_struct_type_name);
7951 CHECK(args_struct_type, EINVAL);
7952 CHECK(!args_struct_type->var_size, EINVAL);
7955 /* Node allocation. */
7956 a = calloc(1, sizeof(struct action));
7958 if (args_struct_type) {
7959 a->args_endianness = calloc(args_struct_type->n_fields, sizeof(int));
7960 if (!a->args_endianness) {
7966 /* Node initialization. */
7967 strcpy(a->name, name);
7968 a->st = args_struct_type;
7969 a->id = p->n_actions;
7971 /* Instruction translation. */
7972 err = instruction_config(p, a, instructions, n_instructions);
7974 free(a->args_endianness);
7979 /* Node add to tailq. */
7980 TAILQ_INSERT_TAIL(&p->actions, a, node);
7987 action_build(struct rte_swx_pipeline *p)
7989 struct action *action;
7991 p->action_instructions = calloc(p->n_actions,
7992 sizeof(struct instruction *));
7993 CHECK(p->action_instructions, ENOMEM);
7995 TAILQ_FOREACH(action, &p->actions, node)
7996 p->action_instructions[action->id] = action->instructions;
8002 action_build_free(struct rte_swx_pipeline *p)
8004 free(p->action_instructions);
8005 p->action_instructions = NULL;
8009 action_free(struct rte_swx_pipeline *p)
8011 action_build_free(p);
8014 struct action *action;
8016 action = TAILQ_FIRST(&p->actions);
8020 TAILQ_REMOVE(&p->actions, action, node);
8021 free(action->instructions);
8027 action_arg_src_mov_count(struct action *a,
8029 struct instruction *instructions,
8030 struct instruction_data *instruction_data,
8031 uint32_t n_instructions)
8033 uint32_t offset, n_users = 0, i;
8036 (arg_id >= a->st->n_fields) ||
8038 !instruction_data ||
8042 offset = a->st->fields[arg_id].offset / 8;
8044 for (i = 0; i < n_instructions; i++) {
8045 struct instruction *instr = &instructions[i];
8046 struct instruction_data *data = &instruction_data[i];
8048 if (data->invalid ||
8049 ((instr->type != INSTR_MOV) && (instr->type != INSTR_MOV_HM)) ||
8050 instr->mov.src.struct_id ||
8051 (instr->mov.src.offset != offset))
8063 static struct table_type *
8064 table_type_find(struct rte_swx_pipeline *p, const char *name)
8066 struct table_type *elem;
8068 TAILQ_FOREACH(elem, &p->table_types, node)
8069 if (strcmp(elem->name, name) == 0)
8075 static struct table_type *
8076 table_type_resolve(struct rte_swx_pipeline *p,
8077 const char *recommended_type_name,
8078 enum rte_swx_table_match_type match_type)
8080 struct table_type *elem;
8082 /* Only consider the recommended type if the match type is correct. */
8083 if (recommended_type_name)
8084 TAILQ_FOREACH(elem, &p->table_types, node)
8085 if (!strcmp(elem->name, recommended_type_name) &&
8086 (elem->match_type == match_type))
8089 /* Ignore the recommended type and get the first element with this match
8092 TAILQ_FOREACH(elem, &p->table_types, node)
8093 if (elem->match_type == match_type)
8099 static struct table *
8100 table_find(struct rte_swx_pipeline *p, const char *name)
8104 TAILQ_FOREACH(elem, &p->tables, node)
8105 if (strcmp(elem->name, name) == 0)
8111 static struct table *
8112 table_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8114 struct table *table = NULL;
8116 TAILQ_FOREACH(table, &p->tables, node)
8117 if (table->id == id)
8124 rte_swx_pipeline_table_type_register(struct rte_swx_pipeline *p,
8126 enum rte_swx_table_match_type match_type,
8127 struct rte_swx_table_ops *ops)
8129 struct table_type *elem;
8133 CHECK_NAME(name, EINVAL);
8134 CHECK(!table_type_find(p, name), EEXIST);
8137 CHECK(ops->create, EINVAL);
8138 CHECK(ops->lkp, EINVAL);
8139 CHECK(ops->free, EINVAL);
8141 /* Node allocation. */
8142 elem = calloc(1, sizeof(struct table_type));
8143 CHECK(elem, ENOMEM);
8145 /* Node initialization. */
8146 strcpy(elem->name, name);
8147 elem->match_type = match_type;
8148 memcpy(&elem->ops, ops, sizeof(*ops));
8150 /* Node add to tailq. */
8151 TAILQ_INSERT_TAIL(&p->table_types, elem, node);
8157 table_match_type_resolve(struct rte_swx_match_field_params *fields,
8159 enum rte_swx_table_match_type *match_type)
8161 uint32_t n_fields_em = 0, n_fields_lpm = 0, i;
8163 for (i = 0; i < n_fields; i++) {
8164 struct rte_swx_match_field_params *f = &fields[i];
8166 if (f->match_type == RTE_SWX_TABLE_MATCH_EXACT)
8169 if (f->match_type == RTE_SWX_TABLE_MATCH_LPM)
8173 if ((n_fields_lpm > 1) ||
8174 (n_fields_lpm && (n_fields_em != n_fields - 1)))
8177 *match_type = (n_fields_em == n_fields) ?
8178 RTE_SWX_TABLE_MATCH_EXACT :
8179 RTE_SWX_TABLE_MATCH_WILDCARD;
8185 table_match_fields_check(struct rte_swx_pipeline *p,
8186 struct rte_swx_pipeline_table_params *params,
8187 struct header **header)
8189 struct header *h0 = NULL;
8190 struct field *hf, *mf;
8191 uint32_t *offset = NULL, i;
8194 /* Return if no match fields. */
8195 if (!params->n_fields) {
8196 if (params->fields) {
8207 /* Memory allocation. */
8208 offset = calloc(params->n_fields, sizeof(uint32_t));
8214 /* Check that all the match fields belong to either the same header or
8217 hf = header_field_parse(p, params->fields[0].name, &h0);
8218 mf = metadata_field_parse(p, params->fields[0].name);
8219 if ((!hf && !mf) || (hf && hf->var_size)) {
8224 offset[0] = h0 ? hf->offset : mf->offset;
8226 for (i = 1; i < params->n_fields; i++)
8230 hf = header_field_parse(p, params->fields[i].name, &h);
8231 if (!hf || (h->id != h0->id) || hf->var_size) {
8236 offset[i] = hf->offset;
8238 mf = metadata_field_parse(p, params->fields[i].name);
8244 offset[i] = mf->offset;
8247 /* Check that there are no duplicated match fields. */
8248 for (i = 0; i < params->n_fields; i++) {
8251 for (j = 0; j < i; j++)
8252 if (offset[j] == offset[i]) {
8268 rte_swx_pipeline_table_config(struct rte_swx_pipeline *p,
8270 struct rte_swx_pipeline_table_params *params,
8271 const char *recommended_table_type_name,
8275 struct table_type *type;
8277 struct action *default_action;
8278 struct header *header = NULL;
8279 uint32_t action_data_size_max = 0, i;
8284 CHECK_NAME(name, EINVAL);
8285 CHECK(!table_find(p, name), EEXIST);
8286 CHECK(!selector_find(p, name), EEXIST);
8287 CHECK(!learner_find(p, name), EEXIST);
8289 CHECK(params, EINVAL);
8292 status = table_match_fields_check(p, params, &header);
8296 /* Action checks. */
8297 CHECK(params->n_actions, EINVAL);
8298 CHECK(params->action_names, EINVAL);
8299 for (i = 0; i < params->n_actions; i++) {
8300 const char *action_name = params->action_names[i];
8302 uint32_t action_data_size;
8304 CHECK_NAME(action_name, EINVAL);
8306 a = action_find(p, action_name);
8308 CHECK(!action_does_learning(a), EINVAL);
8310 action_data_size = a->st ? a->st->n_bits / 8 : 0;
8311 if (action_data_size > action_data_size_max)
8312 action_data_size_max = action_data_size;
8315 CHECK_NAME(params->default_action_name, EINVAL);
8316 for (i = 0; i < p->n_actions; i++)
8317 if (!strcmp(params->action_names[i],
8318 params->default_action_name))
8320 CHECK(i < params->n_actions, EINVAL);
8321 default_action = action_find(p, params->default_action_name);
8322 CHECK((default_action->st && params->default_action_data) ||
8323 !params->default_action_data, EINVAL);
8325 /* Table type checks. */
8326 if (recommended_table_type_name)
8327 CHECK_NAME(recommended_table_type_name, EINVAL);
8329 if (params->n_fields) {
8330 enum rte_swx_table_match_type match_type;
8332 status = table_match_type_resolve(params->fields, params->n_fields, &match_type);
8336 type = table_type_resolve(p, recommended_table_type_name, match_type);
8337 CHECK(type, EINVAL);
8342 /* Memory allocation. */
8343 t = calloc(1, sizeof(struct table));
8346 t->fields = calloc(params->n_fields, sizeof(struct match_field));
8352 t->actions = calloc(params->n_actions, sizeof(struct action *));
8359 if (action_data_size_max) {
8360 t->default_action_data = calloc(1, action_data_size_max);
8361 if (!t->default_action_data) {
8369 /* Node initialization. */
8370 strcpy(t->name, name);
8371 if (args && args[0])
8372 strcpy(t->args, args);
8375 for (i = 0; i < params->n_fields; i++) {
8376 struct rte_swx_match_field_params *field = ¶ms->fields[i];
8377 struct match_field *f = &t->fields[i];
8379 f->match_type = field->match_type;
8381 header_field_parse(p, field->name, NULL) :
8382 metadata_field_parse(p, field->name);
8384 t->n_fields = params->n_fields;
8387 for (i = 0; i < params->n_actions; i++)
8388 t->actions[i] = action_find(p, params->action_names[i]);
8389 t->default_action = default_action;
8390 if (default_action->st)
8391 memcpy(t->default_action_data,
8392 params->default_action_data,
8393 default_action->st->n_bits / 8);
8394 t->n_actions = params->n_actions;
8395 t->default_action_is_const = params->default_action_is_const;
8396 t->action_data_size_max = action_data_size_max;
8399 t->id = p->n_tables;
8401 /* Node add to tailq. */
8402 TAILQ_INSERT_TAIL(&p->tables, t, node);
8408 static struct rte_swx_table_params *
8409 table_params_get(struct table *table)
8411 struct rte_swx_table_params *params;
8412 struct field *first, *last;
8414 uint32_t key_size, key_offset, action_data_size, i;
8416 /* Memory allocation. */
8417 params = calloc(1, sizeof(struct rte_swx_table_params));
8421 /* Find first (smallest offset) and last (biggest offset) match fields. */
8422 first = table->fields[0].field;
8423 last = table->fields[0].field;
8425 for (i = 0; i < table->n_fields; i++) {
8426 struct field *f = table->fields[i].field;
8428 if (f->offset < first->offset)
8431 if (f->offset > last->offset)
8435 /* Key offset and size. */
8436 key_offset = first->offset / 8;
8437 key_size = (last->offset + last->n_bits - first->offset) / 8;
8439 /* Memory allocation. */
8440 key_mask = calloc(1, key_size);
8447 for (i = 0; i < table->n_fields; i++) {
8448 struct field *f = table->fields[i].field;
8449 uint32_t start = (f->offset - first->offset) / 8;
8450 size_t size = f->n_bits / 8;
8452 memset(&key_mask[start], 0xFF, size);
8455 /* Action data size. */
8456 action_data_size = 0;
8457 for (i = 0; i < table->n_actions; i++) {
8458 struct action *action = table->actions[i];
8459 uint32_t ads = action->st ? action->st->n_bits / 8 : 0;
8461 if (ads > action_data_size)
8462 action_data_size = ads;
8466 params->match_type = table->type->match_type;
8467 params->key_size = key_size;
8468 params->key_offset = key_offset;
8469 params->key_mask0 = key_mask;
8470 params->action_data_size = action_data_size;
8471 params->n_keys_max = table->size;
8477 table_params_free(struct rte_swx_table_params *params)
8482 free(params->key_mask0);
8487 table_stub_lkp(void *table __rte_unused,
8488 void *mailbox __rte_unused,
8489 uint8_t **key __rte_unused,
8490 uint64_t *action_id __rte_unused,
8491 uint8_t **action_data __rte_unused,
8495 return 1; /* DONE. */
8499 table_build(struct rte_swx_pipeline *p)
8503 /* Per pipeline: table statistics. */
8504 p->table_stats = calloc(p->n_tables, sizeof(struct table_statistics));
8505 CHECK(p->table_stats, ENOMEM);
8507 for (i = 0; i < p->n_tables; i++) {
8508 p->table_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
8509 CHECK(p->table_stats[i].n_pkts_action, ENOMEM);
8512 /* Per thread: table runt-time. */
8513 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8514 struct thread *t = &p->threads[i];
8515 struct table *table;
8517 t->tables = calloc(p->n_tables, sizeof(struct table_runtime));
8518 CHECK(t->tables, ENOMEM);
8520 TAILQ_FOREACH(table, &p->tables, node) {
8521 struct table_runtime *r = &t->tables[table->id];
8526 size = table->type->ops.mailbox_size_get();
8529 r->func = table->type->ops.lkp;
8533 r->mailbox = calloc(1, size);
8534 CHECK(r->mailbox, ENOMEM);
8538 r->key = table->header ?
8539 &t->structs[table->header->struct_id] :
8540 &t->structs[p->metadata_struct_id];
8542 r->func = table_stub_lkp;
8551 table_build_free(struct rte_swx_pipeline *p)
8555 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8556 struct thread *t = &p->threads[i];
8562 for (j = 0; j < p->n_tables; j++) {
8563 struct table_runtime *r = &t->tables[j];
8572 if (p->table_stats) {
8573 for (i = 0; i < p->n_tables; i++)
8574 free(p->table_stats[i].n_pkts_action);
8576 free(p->table_stats);
8581 table_free(struct rte_swx_pipeline *p)
8583 table_build_free(p);
8589 elem = TAILQ_FIRST(&p->tables);
8593 TAILQ_REMOVE(&p->tables, elem, node);
8595 free(elem->actions);
8596 free(elem->default_action_data);
8602 struct table_type *elem;
8604 elem = TAILQ_FIRST(&p->table_types);
8608 TAILQ_REMOVE(&p->table_types, elem, node);
8616 static struct selector *
8617 selector_find(struct rte_swx_pipeline *p, const char *name)
8621 TAILQ_FOREACH(s, &p->selectors, node)
8622 if (strcmp(s->name, name) == 0)
8628 static struct selector *
8629 selector_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8631 struct selector *s = NULL;
8633 TAILQ_FOREACH(s, &p->selectors, node)
8641 selector_fields_check(struct rte_swx_pipeline *p,
8642 struct rte_swx_pipeline_selector_params *params,
8643 struct header **header)
8645 struct header *h0 = NULL;
8646 struct field *hf, *mf;
8649 /* Return if no selector fields. */
8650 if (!params->n_selector_fields || !params->selector_field_names)
8653 /* Check that all the selector fields either belong to the same header
8654 * or are all meta-data fields.
8656 hf = header_field_parse(p, params->selector_field_names[0], &h0);
8657 mf = metadata_field_parse(p, params->selector_field_names[0]);
8661 for (i = 1; i < params->n_selector_fields; i++)
8665 hf = header_field_parse(p, params->selector_field_names[i], &h);
8666 if (!hf || (h->id != h0->id))
8669 mf = metadata_field_parse(p, params->selector_field_names[i]);
8674 /* Check that there are no duplicated match fields. */
8675 for (i = 0; i < params->n_selector_fields; i++) {
8676 const char *field_name = params->selector_field_names[i];
8679 for (j = i + 1; j < params->n_selector_fields; j++)
8680 if (!strcmp(params->selector_field_names[j], field_name))
8692 rte_swx_pipeline_selector_config(struct rte_swx_pipeline *p,
8694 struct rte_swx_pipeline_selector_params *params)
8697 struct header *selector_header = NULL;
8698 struct field *group_id_field, *member_id_field;
8704 CHECK_NAME(name, EINVAL);
8705 CHECK(!table_find(p, name), EEXIST);
8706 CHECK(!selector_find(p, name), EEXIST);
8707 CHECK(!learner_find(p, name), EEXIST);
8709 CHECK(params, EINVAL);
8711 CHECK_NAME(params->group_id_field_name, EINVAL);
8712 group_id_field = metadata_field_parse(p, params->group_id_field_name);
8713 CHECK(group_id_field, EINVAL);
8715 for (i = 0; i < params->n_selector_fields; i++) {
8716 const char *field_name = params->selector_field_names[i];
8718 CHECK_NAME(field_name, EINVAL);
8720 status = selector_fields_check(p, params, &selector_header);
8724 CHECK_NAME(params->member_id_field_name, EINVAL);
8725 member_id_field = metadata_field_parse(p, params->member_id_field_name);
8726 CHECK(member_id_field, EINVAL);
8728 CHECK(params->n_groups_max, EINVAL);
8730 CHECK(params->n_members_per_group_max, EINVAL);
8732 /* Memory allocation. */
8733 s = calloc(1, sizeof(struct selector));
8739 s->selector_fields = calloc(params->n_selector_fields, sizeof(struct field *));
8740 if (!s->selector_fields) {
8745 /* Node initialization. */
8746 strcpy(s->name, name);
8748 s->group_id_field = group_id_field;
8750 for (i = 0; i < params->n_selector_fields; i++) {
8751 const char *field_name = params->selector_field_names[i];
8753 s->selector_fields[i] = selector_header ?
8754 header_field_parse(p, field_name, NULL) :
8755 metadata_field_parse(p, field_name);
8758 s->n_selector_fields = params->n_selector_fields;
8760 s->selector_header = selector_header;
8762 s->member_id_field = member_id_field;
8764 s->n_groups_max = params->n_groups_max;
8766 s->n_members_per_group_max = params->n_members_per_group_max;
8768 s->id = p->n_selectors;
8770 /* Node add to tailq. */
8771 TAILQ_INSERT_TAIL(&p->selectors, s, node);
8780 free(s->selector_fields);
8788 selector_params_free(struct rte_swx_table_selector_params *params)
8793 free(params->selector_mask);
8798 static struct rte_swx_table_selector_params *
8799 selector_table_params_get(struct selector *s)
8801 struct rte_swx_table_selector_params *params = NULL;
8802 struct field *first, *last;
8805 /* Memory allocation. */
8806 params = calloc(1, sizeof(struct rte_swx_table_selector_params));
8811 params->group_id_offset = s->group_id_field->offset / 8;
8813 /* Find first (smallest offset) and last (biggest offset) selector fields. */
8814 first = s->selector_fields[0];
8815 last = s->selector_fields[0];
8817 for (i = 0; i < s->n_selector_fields; i++) {
8818 struct field *f = s->selector_fields[i];
8820 if (f->offset < first->offset)
8823 if (f->offset > last->offset)
8827 /* Selector offset and size. */
8828 params->selector_offset = first->offset / 8;
8829 params->selector_size = (last->offset + last->n_bits - first->offset) / 8;
8831 /* Memory allocation. */
8832 params->selector_mask = calloc(1, params->selector_size);
8833 if (!params->selector_mask)
8836 /* Selector mask. */
8837 for (i = 0; i < s->n_selector_fields; i++) {
8838 struct field *f = s->selector_fields[i];
8839 uint32_t start = (f->offset - first->offset) / 8;
8840 size_t size = f->n_bits / 8;
8842 memset(¶ms->selector_mask[start], 0xFF, size);
8846 params->member_id_offset = s->member_id_field->offset / 8;
8848 /* Maximum number of groups. */
8849 params->n_groups_max = s->n_groups_max;
8851 /* Maximum number of members per group. */
8852 params->n_members_per_group_max = s->n_members_per_group_max;
8857 selector_params_free(params);
8862 selector_build_free(struct rte_swx_pipeline *p)
8866 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8867 struct thread *t = &p->threads[i];
8873 for (j = 0; j < p->n_selectors; j++) {
8874 struct selector_runtime *r = &t->selectors[j];
8880 t->selectors = NULL;
8883 free(p->selector_stats);
8884 p->selector_stats = NULL;
8888 selector_build(struct rte_swx_pipeline *p)
8893 /* Per pipeline: selector statistics. */
8894 p->selector_stats = calloc(p->n_selectors, sizeof(struct selector_statistics));
8895 if (!p->selector_stats) {
8900 /* Per thread: selector run-time. */
8901 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8902 struct thread *t = &p->threads[i];
8905 t->selectors = calloc(p->n_selectors, sizeof(struct selector_runtime));
8906 if (!t->selectors) {
8911 TAILQ_FOREACH(s, &p->selectors, node) {
8912 struct selector_runtime *r = &t->selectors[s->id];
8916 size = rte_swx_table_selector_mailbox_size_get();
8918 r->mailbox = calloc(1, size);
8925 /* r->group_id_buffer. */
8926 r->group_id_buffer = &t->structs[p->metadata_struct_id];
8928 /* r->selector_buffer. */
8929 r->selector_buffer = s->selector_header ?
8930 &t->structs[s->selector_header->struct_id] :
8931 &t->structs[p->metadata_struct_id];
8933 /* r->member_id_buffer. */
8934 r->member_id_buffer = &t->structs[p->metadata_struct_id];
8941 selector_build_free(p);
8946 selector_free(struct rte_swx_pipeline *p)
8948 selector_build_free(p);
8950 /* Selector tables. */
8952 struct selector *elem;
8954 elem = TAILQ_FIRST(&p->selectors);
8958 TAILQ_REMOVE(&p->selectors, elem, node);
8959 free(elem->selector_fields);
8967 static struct learner *
8968 learner_find(struct rte_swx_pipeline *p, const char *name)
8972 TAILQ_FOREACH(l, &p->learners, node)
8973 if (!strcmp(l->name, name))
8979 static struct learner *
8980 learner_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8982 struct learner *l = NULL;
8984 TAILQ_FOREACH(l, &p->learners, node)
8992 learner_match_fields_check(struct rte_swx_pipeline *p,
8993 struct rte_swx_pipeline_learner_params *params,
8994 struct header **header)
8996 struct header *h0 = NULL;
8997 struct field *hf, *mf;
9000 /* Return if no match fields. */
9001 if (!params->n_fields || !params->field_names)
9004 /* Check that all the match fields either belong to the same header
9005 * or are all meta-data fields.
9007 hf = header_field_parse(p, params->field_names[0], &h0);
9008 mf = metadata_field_parse(p, params->field_names[0]);
9012 for (i = 1; i < params->n_fields; i++)
9016 hf = header_field_parse(p, params->field_names[i], &h);
9017 if (!hf || (h->id != h0->id))
9020 mf = metadata_field_parse(p, params->field_names[i]);
9025 /* Check that there are no duplicated match fields. */
9026 for (i = 0; i < params->n_fields; i++) {
9027 const char *field_name = params->field_names[i];
9030 for (j = i + 1; j < params->n_fields; j++)
9031 if (!strcmp(params->field_names[j], field_name))
9043 learner_action_args_check(struct rte_swx_pipeline *p, struct action *a, const char *mf_name)
9045 struct struct_type *mst = p->metadata_st, *ast = a->st;
9046 struct field *mf, *af;
9056 /* Check that mf_name is the name of a valid meta-data field. */
9057 CHECK_NAME(mf_name, EINVAL);
9058 mf = metadata_field_parse(p, mf_name);
9061 /* Check that there are enough meta-data fields, starting with the mf_name field, to cover
9062 * all the action arguments.
9064 mf_pos = mf - mst->fields;
9065 CHECK(mst->n_fields - mf_pos >= ast->n_fields, EINVAL);
9067 /* Check that the size of each of the identified meta-data fields matches exactly the size
9068 * of the corresponding action argument.
9070 for (i = 0; i < ast->n_fields; i++) {
9071 mf = &mst->fields[mf_pos + i];
9072 af = &ast->fields[i];
9074 CHECK(mf->n_bits == af->n_bits, EINVAL);
9081 learner_action_learning_check(struct rte_swx_pipeline *p,
9082 struct action *action,
9083 const char **action_names,
9088 /* For each "learn" instruction of the current action, check that the learned action (i.e.
9089 * the action passed as argument to the "learn" instruction) is also enabled for the
9090 * current learner table.
9092 for (i = 0; i < action->n_instructions; i++) {
9093 struct instruction *instr = &action->instructions[i];
9094 uint32_t found = 0, j;
9096 if (instr->type != INSTR_LEARNER_LEARN)
9099 for (j = 0; j < n_actions; j++) {
9102 a = action_find(p, action_names[j]);
9106 if (a->id == instr->learn.action_id)
9118 rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p,
9120 struct rte_swx_pipeline_learner_params *params,
9124 struct learner *l = NULL;
9125 struct action *default_action;
9126 struct header *header = NULL;
9127 uint32_t action_data_size_max = 0, i;
9132 CHECK_NAME(name, EINVAL);
9133 CHECK(!table_find(p, name), EEXIST);
9134 CHECK(!selector_find(p, name), EEXIST);
9135 CHECK(!learner_find(p, name), EEXIST);
9137 CHECK(params, EINVAL);
9140 status = learner_match_fields_check(p, params, &header);
9144 /* Action checks. */
9145 CHECK(params->n_actions, EINVAL);
9147 CHECK(params->action_names, EINVAL);
9148 for (i = 0; i < params->n_actions; i++) {
9149 const char *action_name = params->action_names[i];
9150 const char *action_field_name = params->action_field_names[i];
9152 uint32_t action_data_size;
9154 CHECK_NAME(action_name, EINVAL);
9156 a = action_find(p, action_name);
9159 status = learner_action_args_check(p, a, action_field_name);
9163 status = learner_action_learning_check(p,
9165 params->action_names,
9170 action_data_size = a->st ? a->st->n_bits / 8 : 0;
9171 if (action_data_size > action_data_size_max)
9172 action_data_size_max = action_data_size;
9175 CHECK_NAME(params->default_action_name, EINVAL);
9176 for (i = 0; i < p->n_actions; i++)
9177 if (!strcmp(params->action_names[i],
9178 params->default_action_name))
9180 CHECK(i < params->n_actions, EINVAL);
9182 default_action = action_find(p, params->default_action_name);
9183 CHECK((default_action->st && params->default_action_data) ||
9184 !params->default_action_data, EINVAL);
9186 /* Any other checks. */
9187 CHECK(size, EINVAL);
9188 CHECK(timeout, EINVAL);
9190 /* Memory allocation. */
9191 l = calloc(1, sizeof(struct learner));
9195 l->fields = calloc(params->n_fields, sizeof(struct field *));
9199 l->actions = calloc(params->n_actions, sizeof(struct action *));
9203 l->action_arg = calloc(params->n_actions, sizeof(struct field *));
9207 if (action_data_size_max) {
9208 l->default_action_data = calloc(1, action_data_size_max);
9209 if (!l->default_action_data)
9213 /* Node initialization. */
9214 strcpy(l->name, name);
9216 for (i = 0; i < params->n_fields; i++) {
9217 const char *field_name = params->field_names[i];
9219 l->fields[i] = header ?
9220 header_field_parse(p, field_name, NULL) :
9221 metadata_field_parse(p, field_name);
9224 l->n_fields = params->n_fields;
9228 for (i = 0; i < params->n_actions; i++) {
9229 const char *mf_name = params->action_field_names[i];
9231 l->actions[i] = action_find(p, params->action_names[i]);
9233 l->action_arg[i] = mf_name ? metadata_field_parse(p, mf_name) : NULL;
9236 l->default_action = default_action;
9238 if (default_action->st)
9239 memcpy(l->default_action_data,
9240 params->default_action_data,
9241 default_action->st->n_bits / 8);
9243 l->n_actions = params->n_actions;
9245 l->default_action_is_const = params->default_action_is_const;
9247 l->action_data_size_max = action_data_size_max;
9251 l->timeout = timeout;
9253 l->id = p->n_learners;
9255 /* Node add to tailq. */
9256 TAILQ_INSERT_TAIL(&p->learners, l, node);
9265 free(l->action_arg);
9274 learner_params_free(struct rte_swx_table_learner_params *params)
9279 free(params->key_mask0);
9284 static struct rte_swx_table_learner_params *
9285 learner_params_get(struct learner *l)
9287 struct rte_swx_table_learner_params *params = NULL;
9288 struct field *first, *last;
9291 /* Memory allocation. */
9292 params = calloc(1, sizeof(struct rte_swx_table_learner_params));
9296 /* Find first (smallest offset) and last (biggest offset) match fields. */
9297 first = l->fields[0];
9298 last = l->fields[0];
9300 for (i = 0; i < l->n_fields; i++) {
9301 struct field *f = l->fields[i];
9303 if (f->offset < first->offset)
9306 if (f->offset > last->offset)
9310 /* Key offset and size. */
9311 params->key_offset = first->offset / 8;
9312 params->key_size = (last->offset + last->n_bits - first->offset) / 8;
9314 /* Memory allocation. */
9315 params->key_mask0 = calloc(1, params->key_size);
9316 if (!params->key_mask0)
9320 for (i = 0; i < l->n_fields; i++) {
9321 struct field *f = l->fields[i];
9322 uint32_t start = (f->offset - first->offset) / 8;
9323 size_t size = f->n_bits / 8;
9325 memset(¶ms->key_mask0[start], 0xFF, size);
9328 /* Action data size. */
9329 params->action_data_size = l->action_data_size_max;
9331 /* Maximum number of keys. */
9332 params->n_keys_max = l->size;
9335 params->key_timeout = l->timeout;
9340 learner_params_free(params);
9345 learner_build_free(struct rte_swx_pipeline *p)
9349 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9350 struct thread *t = &p->threads[i];
9356 for (j = 0; j < p->n_learners; j++) {
9357 struct learner_runtime *r = &t->learners[j];
9360 free(r->action_data);
9367 if (p->learner_stats) {
9368 for (i = 0; i < p->n_learners; i++)
9369 free(p->learner_stats[i].n_pkts_action);
9371 free(p->learner_stats);
9376 learner_build(struct rte_swx_pipeline *p)
9381 /* Per pipeline: learner statistics. */
9382 p->learner_stats = calloc(p->n_learners, sizeof(struct learner_statistics));
9383 CHECK(p->learner_stats, ENOMEM);
9385 for (i = 0; i < p->n_learners; i++) {
9386 p->learner_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
9387 CHECK(p->learner_stats[i].n_pkts_action, ENOMEM);
9390 /* Per thread: learner run-time. */
9391 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9392 struct thread *t = &p->threads[i];
9395 t->learners = calloc(p->n_learners, sizeof(struct learner_runtime));
9401 TAILQ_FOREACH(l, &p->learners, node) {
9402 struct learner_runtime *r = &t->learners[l->id];
9407 size = rte_swx_table_learner_mailbox_size_get();
9409 r->mailbox = calloc(1, size);
9417 r->key = l->header ?
9418 &t->structs[l->header->struct_id] :
9419 &t->structs[p->metadata_struct_id];
9421 /* r->action_data. */
9422 r->action_data = calloc(p->n_actions, sizeof(uint8_t *));
9423 if (!r->action_data) {
9428 for (j = 0; j < l->n_actions; j++) {
9429 struct action *a = l->actions[j];
9430 struct field *mf = l->action_arg[j];
9431 uint8_t *m = t->structs[p->metadata_struct_id];
9433 r->action_data[a->id] = mf ? &m[mf->offset / 8] : NULL;
9441 learner_build_free(p);
9446 learner_free(struct rte_swx_pipeline *p)
9448 learner_build_free(p);
9450 /* Learner tables. */
9454 l = TAILQ_FIRST(&p->learners);
9458 TAILQ_REMOVE(&p->learners, l, node);
9461 free(l->action_arg);
9462 free(l->default_action_data);
9471 table_state_build(struct rte_swx_pipeline *p)
9473 struct table *table;
9477 p->table_state = calloc(p->n_tables + p->n_selectors,
9478 sizeof(struct rte_swx_table_state));
9479 CHECK(p->table_state, ENOMEM);
9481 TAILQ_FOREACH(table, &p->tables, node) {
9482 struct rte_swx_table_state *ts = &p->table_state[table->id];
9485 struct rte_swx_table_params *params;
9488 params = table_params_get(table);
9489 CHECK(params, ENOMEM);
9491 ts->obj = table->type->ops.create(params,
9496 table_params_free(params);
9497 CHECK(ts->obj, ENODEV);
9500 /* ts->default_action_data. */
9501 if (table->action_data_size_max) {
9502 ts->default_action_data =
9503 malloc(table->action_data_size_max);
9504 CHECK(ts->default_action_data, ENOMEM);
9506 memcpy(ts->default_action_data,
9507 table->default_action_data,
9508 table->action_data_size_max);
9511 /* ts->default_action_id. */
9512 ts->default_action_id = table->default_action->id;
9515 TAILQ_FOREACH(s, &p->selectors, node) {
9516 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + s->id];
9517 struct rte_swx_table_selector_params *params;
9520 params = selector_table_params_get(s);
9521 CHECK(params, ENOMEM);
9523 ts->obj = rte_swx_table_selector_create(params, NULL, p->numa_node);
9525 selector_params_free(params);
9526 CHECK(ts->obj, ENODEV);
9529 TAILQ_FOREACH(l, &p->learners, node) {
9530 struct rte_swx_table_state *ts = &p->table_state[p->n_tables +
9531 p->n_selectors + l->id];
9532 struct rte_swx_table_learner_params *params;
9535 params = learner_params_get(l);
9536 CHECK(params, ENOMEM);
9538 ts->obj = rte_swx_table_learner_create(params, p->numa_node);
9539 learner_params_free(params);
9540 CHECK(ts->obj, ENODEV);
9542 /* ts->default_action_data. */
9543 if (l->action_data_size_max) {
9544 ts->default_action_data = malloc(l->action_data_size_max);
9545 CHECK(ts->default_action_data, ENOMEM);
9547 memcpy(ts->default_action_data,
9548 l->default_action_data,
9549 l->action_data_size_max);
9552 /* ts->default_action_id. */
9553 ts->default_action_id = l->default_action->id;
9560 table_state_build_free(struct rte_swx_pipeline *p)
9564 if (!p->table_state)
9567 for (i = 0; i < p->n_tables; i++) {
9568 struct rte_swx_table_state *ts = &p->table_state[i];
9569 struct table *table = table_find_by_id(p, i);
9572 if (table->type && ts->obj)
9573 table->type->ops.free(ts->obj);
9575 /* ts->default_action_data. */
9576 free(ts->default_action_data);
9579 for (i = 0; i < p->n_selectors; i++) {
9580 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + i];
9584 rte_swx_table_selector_free(ts->obj);
9587 for (i = 0; i < p->n_learners; i++) {
9588 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + p->n_selectors + i];
9592 rte_swx_table_learner_free(ts->obj);
9594 /* ts->default_action_data. */
9595 free(ts->default_action_data);
9598 free(p->table_state);
9599 p->table_state = NULL;
9603 table_state_free(struct rte_swx_pipeline *p)
9605 table_state_build_free(p);
9611 static struct regarray *
9612 regarray_find(struct rte_swx_pipeline *p, const char *name)
9614 struct regarray *elem;
9616 TAILQ_FOREACH(elem, &p->regarrays, node)
9617 if (!strcmp(elem->name, name))
9623 static struct regarray *
9624 regarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9626 struct regarray *elem = NULL;
9628 TAILQ_FOREACH(elem, &p->regarrays, node)
9636 rte_swx_pipeline_regarray_config(struct rte_swx_pipeline *p,
9645 CHECK_NAME(name, EINVAL);
9646 CHECK(!regarray_find(p, name), EEXIST);
9648 CHECK(size, EINVAL);
9649 size = rte_align32pow2(size);
9651 /* Memory allocation. */
9652 r = calloc(1, sizeof(struct regarray));
9655 /* Node initialization. */
9656 strcpy(r->name, name);
9657 r->init_val = init_val;
9659 r->id = p->n_regarrays;
9661 /* Node add to tailq. */
9662 TAILQ_INSERT_TAIL(&p->regarrays, r, node);
9669 regarray_build(struct rte_swx_pipeline *p)
9671 struct regarray *regarray;
9673 if (!p->n_regarrays)
9676 p->regarray_runtime = calloc(p->n_regarrays, sizeof(struct regarray_runtime));
9677 CHECK(p->regarray_runtime, ENOMEM);
9679 TAILQ_FOREACH(regarray, &p->regarrays, node) {
9680 struct regarray_runtime *r = &p->regarray_runtime[regarray->id];
9683 r->regarray = env_malloc(regarray->size * sizeof(uint64_t),
9684 RTE_CACHE_LINE_SIZE,
9686 CHECK(r->regarray, ENOMEM);
9688 if (regarray->init_val)
9689 for (i = 0; i < regarray->size; i++)
9690 r->regarray[i] = regarray->init_val;
9692 r->size_mask = regarray->size - 1;
9699 regarray_build_free(struct rte_swx_pipeline *p)
9703 if (!p->regarray_runtime)
9706 for (i = 0; i < p->n_regarrays; i++) {
9707 struct regarray *regarray = regarray_find_by_id(p, i);
9708 struct regarray_runtime *r = &p->regarray_runtime[i];
9710 env_free(r->regarray, regarray->size * sizeof(uint64_t));
9713 free(p->regarray_runtime);
9714 p->regarray_runtime = NULL;
9718 regarray_free(struct rte_swx_pipeline *p)
9720 regarray_build_free(p);
9723 struct regarray *elem;
9725 elem = TAILQ_FIRST(&p->regarrays);
9729 TAILQ_REMOVE(&p->regarrays, elem, node);
9737 static struct meter_profile *
9738 meter_profile_find(struct rte_swx_pipeline *p, const char *name)
9740 struct meter_profile *elem;
9742 TAILQ_FOREACH(elem, &p->meter_profiles, node)
9743 if (!strcmp(elem->name, name))
9749 static struct metarray *
9750 metarray_find(struct rte_swx_pipeline *p, const char *name)
9752 struct metarray *elem;
9754 TAILQ_FOREACH(elem, &p->metarrays, node)
9755 if (!strcmp(elem->name, name))
9761 static struct metarray *
9762 metarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9764 struct metarray *elem = NULL;
9766 TAILQ_FOREACH(elem, &p->metarrays, node)
9774 rte_swx_pipeline_metarray_config(struct rte_swx_pipeline *p,
9782 CHECK_NAME(name, EINVAL);
9783 CHECK(!metarray_find(p, name), EEXIST);
9785 CHECK(size, EINVAL);
9786 size = rte_align32pow2(size);
9788 /* Memory allocation. */
9789 m = calloc(1, sizeof(struct metarray));
9792 /* Node initialization. */
9793 strcpy(m->name, name);
9795 m->id = p->n_metarrays;
9797 /* Node add to tailq. */
9798 TAILQ_INSERT_TAIL(&p->metarrays, m, node);
9804 struct meter_profile meter_profile_default = {
9813 .cir_bytes_per_period = 1,
9815 .pir_bytes_per_period = 1,
9822 meter_init(struct meter *m)
9824 memset(m, 0, sizeof(struct meter));
9825 rte_meter_trtcm_config(&m->m, &meter_profile_default.profile);
9826 m->profile = &meter_profile_default;
9827 m->color_mask = RTE_COLOR_GREEN;
9829 meter_profile_default.n_users++;
9833 metarray_build(struct rte_swx_pipeline *p)
9837 if (!p->n_metarrays)
9840 p->metarray_runtime = calloc(p->n_metarrays, sizeof(struct metarray_runtime));
9841 CHECK(p->metarray_runtime, ENOMEM);
9843 TAILQ_FOREACH(m, &p->metarrays, node) {
9844 struct metarray_runtime *r = &p->metarray_runtime[m->id];
9847 r->metarray = env_malloc(m->size * sizeof(struct meter),
9848 RTE_CACHE_LINE_SIZE,
9850 CHECK(r->metarray, ENOMEM);
9852 for (i = 0; i < m->size; i++)
9853 meter_init(&r->metarray[i]);
9855 r->size_mask = m->size - 1;
9862 metarray_build_free(struct rte_swx_pipeline *p)
9866 if (!p->metarray_runtime)
9869 for (i = 0; i < p->n_metarrays; i++) {
9870 struct metarray *m = metarray_find_by_id(p, i);
9871 struct metarray_runtime *r = &p->metarray_runtime[i];
9873 env_free(r->metarray, m->size * sizeof(struct meter));
9876 free(p->metarray_runtime);
9877 p->metarray_runtime = NULL;
9881 metarray_free(struct rte_swx_pipeline *p)
9883 metarray_build_free(p);
9887 struct metarray *elem;
9889 elem = TAILQ_FIRST(&p->metarrays);
9893 TAILQ_REMOVE(&p->metarrays, elem, node);
9897 /* Meter profiles. */
9899 struct meter_profile *elem;
9901 elem = TAILQ_FIRST(&p->meter_profiles);
9905 TAILQ_REMOVE(&p->meter_profiles, elem, node);
9914 rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
9916 struct rte_swx_pipeline *pipeline;
9918 /* Check input parameters. */
9921 /* Memory allocation. */
9922 pipeline = calloc(1, sizeof(struct rte_swx_pipeline));
9923 CHECK(pipeline, ENOMEM);
9925 /* Initialization. */
9926 TAILQ_INIT(&pipeline->struct_types);
9927 TAILQ_INIT(&pipeline->port_in_types);
9928 TAILQ_INIT(&pipeline->ports_in);
9929 TAILQ_INIT(&pipeline->port_out_types);
9930 TAILQ_INIT(&pipeline->ports_out);
9931 TAILQ_INIT(&pipeline->extern_types);
9932 TAILQ_INIT(&pipeline->extern_objs);
9933 TAILQ_INIT(&pipeline->extern_funcs);
9934 TAILQ_INIT(&pipeline->headers);
9935 TAILQ_INIT(&pipeline->actions);
9936 TAILQ_INIT(&pipeline->table_types);
9937 TAILQ_INIT(&pipeline->tables);
9938 TAILQ_INIT(&pipeline->selectors);
9939 TAILQ_INIT(&pipeline->learners);
9940 TAILQ_INIT(&pipeline->regarrays);
9941 TAILQ_INIT(&pipeline->meter_profiles);
9942 TAILQ_INIT(&pipeline->metarrays);
9944 pipeline->n_structs = 1; /* Struct 0 is reserved for action_data. */
9945 pipeline->numa_node = numa_node;
9952 rte_swx_pipeline_free(struct rte_swx_pipeline *p)
9957 free(p->instructions);
9961 table_state_free(p);
9968 extern_func_free(p);
9978 rte_swx_pipeline_instructions_config(struct rte_swx_pipeline *p,
9979 const char **instructions,
9980 uint32_t n_instructions)
9985 err = instruction_config(p, NULL, instructions, n_instructions);
9989 /* Thread instruction pointer reset. */
9990 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9991 struct thread *t = &p->threads[i];
9993 thread_ip_reset(p, t);
10000 rte_swx_pipeline_build(struct rte_swx_pipeline *p)
10005 CHECK(p->build_done == 0, EEXIST);
10007 status = port_in_build(p);
10011 status = port_out_build(p);
10015 status = struct_build(p);
10019 status = extern_obj_build(p);
10023 status = extern_func_build(p);
10027 status = header_build(p);
10031 status = metadata_build(p);
10035 status = action_build(p);
10039 status = table_build(p);
10043 status = selector_build(p);
10047 status = learner_build(p);
10051 status = table_state_build(p);
10055 status = regarray_build(p);
10059 status = metarray_build(p);
10067 metarray_build_free(p);
10068 regarray_build_free(p);
10069 table_state_build_free(p);
10070 learner_build_free(p);
10071 selector_build_free(p);
10072 table_build_free(p);
10073 action_build_free(p);
10074 metadata_build_free(p);
10075 header_build_free(p);
10076 extern_func_build_free(p);
10077 extern_obj_build_free(p);
10078 port_out_build_free(p);
10079 port_in_build_free(p);
10080 struct_build_free(p);
10086 rte_swx_pipeline_run(struct rte_swx_pipeline *p, uint32_t n_instructions)
10090 for (i = 0; i < n_instructions; i++)
10095 rte_swx_pipeline_flush(struct rte_swx_pipeline *p)
10099 for (i = 0; i < p->n_ports_out; i++) {
10100 struct port_out_runtime *port = &p->out[i];
10103 port->flush(port->obj);
10111 rte_swx_ctl_pipeline_info_get(struct rte_swx_pipeline *p,
10112 struct rte_swx_ctl_pipeline_info *pipeline)
10114 struct action *action;
10115 struct table *table;
10116 uint32_t n_actions = 0, n_tables = 0;
10118 if (!p || !pipeline)
10121 TAILQ_FOREACH(action, &p->actions, node)
10124 TAILQ_FOREACH(table, &p->tables, node)
10127 pipeline->n_ports_in = p->n_ports_in;
10128 pipeline->n_ports_out = p->n_ports_out;
10129 pipeline->n_actions = n_actions;
10130 pipeline->n_tables = n_tables;
10131 pipeline->n_selectors = p->n_selectors;
10132 pipeline->n_learners = p->n_learners;
10133 pipeline->n_regarrays = p->n_regarrays;
10134 pipeline->n_metarrays = p->n_metarrays;
10140 rte_swx_ctl_pipeline_numa_node_get(struct rte_swx_pipeline *p, int *numa_node)
10142 if (!p || !numa_node)
10145 *numa_node = p->numa_node;
10150 rte_swx_ctl_action_info_get(struct rte_swx_pipeline *p,
10151 uint32_t action_id,
10152 struct rte_swx_ctl_action_info *action)
10154 struct action *a = NULL;
10156 if (!p || (action_id >= p->n_actions) || !action)
10159 a = action_find_by_id(p, action_id);
10163 strcpy(action->name, a->name);
10164 action->n_args = a->st ? a->st->n_fields : 0;
10169 rte_swx_ctl_action_arg_info_get(struct rte_swx_pipeline *p,
10170 uint32_t action_id,
10171 uint32_t action_arg_id,
10172 struct rte_swx_ctl_action_arg_info *action_arg)
10174 struct action *a = NULL;
10175 struct field *arg = NULL;
10177 if (!p || (action_id >= p->n_actions) || !action_arg)
10180 a = action_find_by_id(p, action_id);
10181 if (!a || !a->st || (action_arg_id >= a->st->n_fields))
10184 arg = &a->st->fields[action_arg_id];
10185 strcpy(action_arg->name, arg->name);
10186 action_arg->n_bits = arg->n_bits;
10187 action_arg->is_network_byte_order = a->args_endianness[action_arg_id];
10193 rte_swx_ctl_table_info_get(struct rte_swx_pipeline *p,
10195 struct rte_swx_ctl_table_info *table)
10197 struct table *t = NULL;
10202 t = table_find_by_id(p, table_id);
10206 strcpy(table->name, t->name);
10207 strcpy(table->args, t->args);
10208 table->n_match_fields = t->n_fields;
10209 table->n_actions = t->n_actions;
10210 table->default_action_is_const = t->default_action_is_const;
10211 table->size = t->size;
10216 rte_swx_ctl_table_match_field_info_get(struct rte_swx_pipeline *p,
10218 uint32_t match_field_id,
10219 struct rte_swx_ctl_table_match_field_info *match_field)
10222 struct match_field *f;
10224 if (!p || (table_id >= p->n_tables) || !match_field)
10227 t = table_find_by_id(p, table_id);
10228 if (!t || (match_field_id >= t->n_fields))
10231 f = &t->fields[match_field_id];
10232 match_field->match_type = f->match_type;
10233 match_field->is_header = t->header ? 1 : 0;
10234 match_field->n_bits = f->field->n_bits;
10235 match_field->offset = f->field->offset;
10241 rte_swx_ctl_table_action_info_get(struct rte_swx_pipeline *p,
10243 uint32_t table_action_id,
10244 struct rte_swx_ctl_table_action_info *table_action)
10248 if (!p || (table_id >= p->n_tables) || !table_action)
10251 t = table_find_by_id(p, table_id);
10252 if (!t || (table_action_id >= t->n_actions))
10255 table_action->action_id = t->actions[table_action_id]->id;
10261 rte_swx_ctl_table_ops_get(struct rte_swx_pipeline *p,
10263 struct rte_swx_table_ops *table_ops,
10268 if (!p || (table_id >= p->n_tables))
10271 t = table_find_by_id(p, table_id);
10277 memcpy(table_ops, &t->type->ops, sizeof(*table_ops));
10287 rte_swx_ctl_selector_info_get(struct rte_swx_pipeline *p,
10288 uint32_t selector_id,
10289 struct rte_swx_ctl_selector_info *selector)
10291 struct selector *s = NULL;
10293 if (!p || !selector)
10296 s = selector_find_by_id(p, selector_id);
10300 strcpy(selector->name, s->name);
10302 selector->n_selector_fields = s->n_selector_fields;
10303 selector->n_groups_max = s->n_groups_max;
10304 selector->n_members_per_group_max = s->n_members_per_group_max;
10310 rte_swx_ctl_selector_group_id_field_info_get(struct rte_swx_pipeline *p,
10311 uint32_t selector_id,
10312 struct rte_swx_ctl_table_match_field_info *field)
10314 struct selector *s;
10316 if (!p || (selector_id >= p->n_selectors) || !field)
10319 s = selector_find_by_id(p, selector_id);
10323 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10324 field->is_header = 0;
10325 field->n_bits = s->group_id_field->n_bits;
10326 field->offset = s->group_id_field->offset;
10332 rte_swx_ctl_selector_field_info_get(struct rte_swx_pipeline *p,
10333 uint32_t selector_id,
10334 uint32_t selector_field_id,
10335 struct rte_swx_ctl_table_match_field_info *field)
10337 struct selector *s;
10340 if (!p || (selector_id >= p->n_selectors) || !field)
10343 s = selector_find_by_id(p, selector_id);
10344 if (!s || (selector_field_id >= s->n_selector_fields))
10347 f = s->selector_fields[selector_field_id];
10348 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10349 field->is_header = s->selector_header ? 1 : 0;
10350 field->n_bits = f->n_bits;
10351 field->offset = f->offset;
10357 rte_swx_ctl_selector_member_id_field_info_get(struct rte_swx_pipeline *p,
10358 uint32_t selector_id,
10359 struct rte_swx_ctl_table_match_field_info *field)
10361 struct selector *s;
10363 if (!p || (selector_id >= p->n_selectors) || !field)
10366 s = selector_find_by_id(p, selector_id);
10370 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10371 field->is_header = 0;
10372 field->n_bits = s->member_id_field->n_bits;
10373 field->offset = s->member_id_field->offset;
10379 rte_swx_ctl_learner_info_get(struct rte_swx_pipeline *p,
10380 uint32_t learner_id,
10381 struct rte_swx_ctl_learner_info *learner)
10383 struct learner *l = NULL;
10385 if (!p || !learner)
10388 l = learner_find_by_id(p, learner_id);
10392 strcpy(learner->name, l->name);
10394 learner->n_match_fields = l->n_fields;
10395 learner->n_actions = l->n_actions;
10396 learner->default_action_is_const = l->default_action_is_const;
10397 learner->size = l->size;
10403 rte_swx_ctl_learner_match_field_info_get(struct rte_swx_pipeline *p,
10404 uint32_t learner_id,
10405 uint32_t match_field_id,
10406 struct rte_swx_ctl_table_match_field_info *match_field)
10411 if (!p || (learner_id >= p->n_learners) || !match_field)
10414 l = learner_find_by_id(p, learner_id);
10415 if (!l || (match_field_id >= l->n_fields))
10418 f = l->fields[match_field_id];
10419 match_field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10420 match_field->is_header = l->header ? 1 : 0;
10421 match_field->n_bits = f->n_bits;
10422 match_field->offset = f->offset;
10428 rte_swx_ctl_learner_action_info_get(struct rte_swx_pipeline *p,
10429 uint32_t learner_id,
10430 uint32_t learner_action_id,
10431 struct rte_swx_ctl_table_action_info *learner_action)
10435 if (!p || (learner_id >= p->n_learners) || !learner_action)
10438 l = learner_find_by_id(p, learner_id);
10439 if (!l || (learner_action_id >= l->n_actions))
10442 learner_action->action_id = l->actions[learner_action_id]->id;
10448 rte_swx_pipeline_table_state_get(struct rte_swx_pipeline *p,
10449 struct rte_swx_table_state **table_state)
10451 if (!p || !table_state || !p->build_done)
10454 *table_state = p->table_state;
10459 rte_swx_pipeline_table_state_set(struct rte_swx_pipeline *p,
10460 struct rte_swx_table_state *table_state)
10462 if (!p || !table_state || !p->build_done)
10465 p->table_state = table_state;
10470 rte_swx_ctl_pipeline_port_in_stats_read(struct rte_swx_pipeline *p,
10472 struct rte_swx_port_in_stats *stats)
10474 struct port_in *port;
10479 port = port_in_find(p, port_id);
10483 port->type->ops.stats_read(port->obj, stats);
10488 rte_swx_ctl_pipeline_port_out_stats_read(struct rte_swx_pipeline *p,
10490 struct rte_swx_port_out_stats *stats)
10492 struct port_out *port;
10497 port = port_out_find(p, port_id);
10501 port->type->ops.stats_read(port->obj, stats);
10506 rte_swx_ctl_pipeline_table_stats_read(struct rte_swx_pipeline *p,
10507 const char *table_name,
10508 struct rte_swx_table_stats *stats)
10510 struct table *table;
10511 struct table_statistics *table_stats;
10513 if (!p || !table_name || !table_name[0] || !stats || !stats->n_pkts_action)
10516 table = table_find(p, table_name);
10520 table_stats = &p->table_stats[table->id];
10522 memcpy(stats->n_pkts_action,
10523 table_stats->n_pkts_action,
10524 p->n_actions * sizeof(uint64_t));
10526 stats->n_pkts_hit = table_stats->n_pkts_hit[1];
10527 stats->n_pkts_miss = table_stats->n_pkts_hit[0];
10533 rte_swx_ctl_pipeline_selector_stats_read(struct rte_swx_pipeline *p,
10534 const char *selector_name,
10535 struct rte_swx_pipeline_selector_stats *stats)
10537 struct selector *s;
10539 if (!p || !selector_name || !selector_name[0] || !stats)
10542 s = selector_find(p, selector_name);
10546 stats->n_pkts = p->selector_stats[s->id].n_pkts;
10552 rte_swx_ctl_pipeline_learner_stats_read(struct rte_swx_pipeline *p,
10553 const char *learner_name,
10554 struct rte_swx_learner_stats *stats)
10557 struct learner_statistics *learner_stats;
10559 if (!p || !learner_name || !learner_name[0] || !stats || !stats->n_pkts_action)
10562 l = learner_find(p, learner_name);
10566 learner_stats = &p->learner_stats[l->id];
10568 memcpy(stats->n_pkts_action,
10569 learner_stats->n_pkts_action,
10570 p->n_actions * sizeof(uint64_t));
10572 stats->n_pkts_hit = learner_stats->n_pkts_hit[1];
10573 stats->n_pkts_miss = learner_stats->n_pkts_hit[0];
10575 stats->n_pkts_learn_ok = learner_stats->n_pkts_learn[0];
10576 stats->n_pkts_learn_err = learner_stats->n_pkts_learn[1];
10578 stats->n_pkts_forget = learner_stats->n_pkts_forget;
10584 rte_swx_ctl_regarray_info_get(struct rte_swx_pipeline *p,
10585 uint32_t regarray_id,
10586 struct rte_swx_ctl_regarray_info *regarray)
10588 struct regarray *r;
10590 if (!p || !regarray)
10593 r = regarray_find_by_id(p, regarray_id);
10597 strcpy(regarray->name, r->name);
10598 regarray->size = r->size;
10603 rte_swx_ctl_pipeline_regarray_read(struct rte_swx_pipeline *p,
10604 const char *regarray_name,
10605 uint32_t regarray_index,
10608 struct regarray *regarray;
10609 struct regarray_runtime *r;
10611 if (!p || !regarray_name || !value)
10614 regarray = regarray_find(p, regarray_name);
10615 if (!regarray || (regarray_index >= regarray->size))
10618 r = &p->regarray_runtime[regarray->id];
10619 *value = r->regarray[regarray_index];
10624 rte_swx_ctl_pipeline_regarray_write(struct rte_swx_pipeline *p,
10625 const char *regarray_name,
10626 uint32_t regarray_index,
10629 struct regarray *regarray;
10630 struct regarray_runtime *r;
10632 if (!p || !regarray_name)
10635 regarray = regarray_find(p, regarray_name);
10636 if (!regarray || (regarray_index >= regarray->size))
10639 r = &p->regarray_runtime[regarray->id];
10640 r->regarray[regarray_index] = value;
10645 rte_swx_ctl_metarray_info_get(struct rte_swx_pipeline *p,
10646 uint32_t metarray_id,
10647 struct rte_swx_ctl_metarray_info *metarray)
10649 struct metarray *m;
10651 if (!p || !metarray)
10654 m = metarray_find_by_id(p, metarray_id);
10658 strcpy(metarray->name, m->name);
10659 metarray->size = m->size;
10664 rte_swx_ctl_meter_profile_add(struct rte_swx_pipeline *p,
10666 struct rte_meter_trtcm_params *params)
10668 struct meter_profile *mp;
10672 CHECK_NAME(name, EINVAL);
10673 CHECK(params, EINVAL);
10674 CHECK(!meter_profile_find(p, name), EEXIST);
10676 /* Node allocation. */
10677 mp = calloc(1, sizeof(struct meter_profile));
10680 /* Node initialization. */
10681 strcpy(mp->name, name);
10682 memcpy(&mp->params, params, sizeof(struct rte_meter_trtcm_params));
10683 status = rte_meter_trtcm_profile_config(&mp->profile, params);
10689 /* Node add to tailq. */
10690 TAILQ_INSERT_TAIL(&p->meter_profiles, mp, node);
10696 rte_swx_ctl_meter_profile_delete(struct rte_swx_pipeline *p,
10699 struct meter_profile *mp;
10702 CHECK_NAME(name, EINVAL);
10704 mp = meter_profile_find(p, name);
10706 CHECK(!mp->n_users, EBUSY);
10708 /* Remove node from tailq. */
10709 TAILQ_REMOVE(&p->meter_profiles, mp, node);
10716 rte_swx_ctl_meter_reset(struct rte_swx_pipeline *p,
10717 const char *metarray_name,
10718 uint32_t metarray_index)
10720 struct meter_profile *mp_old;
10721 struct metarray *metarray;
10722 struct metarray_runtime *metarray_runtime;
10726 CHECK_NAME(metarray_name, EINVAL);
10728 metarray = metarray_find(p, metarray_name);
10729 CHECK(metarray, EINVAL);
10730 CHECK(metarray_index < metarray->size, EINVAL);
10732 metarray_runtime = &p->metarray_runtime[metarray->id];
10733 m = &metarray_runtime->metarray[metarray_index];
10734 mp_old = m->profile;
10744 rte_swx_ctl_meter_set(struct rte_swx_pipeline *p,
10745 const char *metarray_name,
10746 uint32_t metarray_index,
10747 const char *profile_name)
10749 struct meter_profile *mp, *mp_old;
10750 struct metarray *metarray;
10751 struct metarray_runtime *metarray_runtime;
10755 CHECK_NAME(metarray_name, EINVAL);
10757 metarray = metarray_find(p, metarray_name);
10758 CHECK(metarray, EINVAL);
10759 CHECK(metarray_index < metarray->size, EINVAL);
10761 mp = meter_profile_find(p, profile_name);
10764 metarray_runtime = &p->metarray_runtime[metarray->id];
10765 m = &metarray_runtime->metarray[metarray_index];
10766 mp_old = m->profile;
10768 memset(m, 0, sizeof(struct meter));
10769 rte_meter_trtcm_config(&m->m, &mp->profile);
10771 m->color_mask = RTE_COLORS;
10780 rte_swx_ctl_meter_stats_read(struct rte_swx_pipeline *p,
10781 const char *metarray_name,
10782 uint32_t metarray_index,
10783 struct rte_swx_ctl_meter_stats *stats)
10785 struct metarray *metarray;
10786 struct metarray_runtime *metarray_runtime;
10790 CHECK_NAME(metarray_name, EINVAL);
10792 metarray = metarray_find(p, metarray_name);
10793 CHECK(metarray, EINVAL);
10794 CHECK(metarray_index < metarray->size, EINVAL);
10796 CHECK(stats, EINVAL);
10798 metarray_runtime = &p->metarray_runtime[metarray->id];
10799 m = &metarray_runtime->metarray[metarray_index];
10801 memcpy(stats->n_pkts, m->n_pkts, sizeof(m->n_pkts));
10802 memcpy(stats->n_bytes, m->n_bytes, sizeof(m->n_bytes));