1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2020 Intel Corporation
9 #include "rte_swx_pipeline_internal.h"
11 #define CHECK(condition, err_code) \
17 #define CHECK_NAME(name, err_code) \
20 (strnlen((name), RTE_SWX_NAME_SIZE) < RTE_SWX_NAME_SIZE), \
23 #define CHECK_INSTRUCTION(instr, err_code) \
26 (strnlen((instr), RTE_SWX_INSTRUCTION_SIZE) < \
27 RTE_SWX_INSTRUCTION_SIZE), \
33 #ifndef RTE_SWX_PIPELINE_HUGE_PAGES_DISABLE
35 #include <rte_malloc.h>
38 env_malloc(size_t size, size_t alignment, int numa_node)
40 return rte_zmalloc_socket(NULL, size, alignment, numa_node);
44 env_free(void *start, size_t size __rte_unused)
54 env_malloc(size_t size, size_t alignment __rte_unused, int numa_node)
58 if (numa_available() == -1)
61 start = numa_alloc_onnode(size, numa_node);
65 memset(start, 0, size);
70 env_free(void *start, size_t size)
72 if (numa_available() == -1)
75 numa_free(start, size);
83 static struct struct_type *
84 struct_type_find(struct rte_swx_pipeline *p, const char *name)
86 struct struct_type *elem;
88 TAILQ_FOREACH(elem, &p->struct_types, node)
89 if (strcmp(elem->name, name) == 0)
96 struct_type_field_find(struct struct_type *st, const char *name)
100 for (i = 0; i < st->n_fields; i++) {
101 struct field *f = &st->fields[i];
103 if (strcmp(f->name, name) == 0)
111 rte_swx_pipeline_struct_type_register(struct rte_swx_pipeline *p,
113 struct rte_swx_field_params *fields,
115 int last_field_has_variable_size)
117 struct struct_type *st;
121 CHECK_NAME(name, EINVAL);
122 CHECK(fields, EINVAL);
123 CHECK(n_fields, EINVAL);
125 for (i = 0; i < n_fields; i++) {
126 struct rte_swx_field_params *f = &fields[i];
127 int var_size = ((i == n_fields - 1) && last_field_has_variable_size) ? 1 : 0;
130 CHECK_NAME(f->name, EINVAL);
131 CHECK(f->n_bits, EINVAL);
132 CHECK((f->n_bits <= 64) || var_size, EINVAL);
133 CHECK((f->n_bits & 7) == 0, EINVAL);
135 for (j = 0; j < i; j++) {
136 struct rte_swx_field_params *f_prev = &fields[j];
138 CHECK(strcmp(f->name, f_prev->name), EINVAL);
142 CHECK(!struct_type_find(p, name), EEXIST);
144 /* Node allocation. */
145 st = calloc(1, sizeof(struct struct_type));
148 st->fields = calloc(n_fields, sizeof(struct field));
154 /* Node initialization. */
155 strcpy(st->name, name);
156 for (i = 0; i < n_fields; i++) {
157 struct field *dst = &st->fields[i];
158 struct rte_swx_field_params *src = &fields[i];
159 int var_size = ((i == n_fields - 1) && last_field_has_variable_size) ? 1 : 0;
161 strcpy(dst->name, src->name);
162 dst->n_bits = src->n_bits;
163 dst->offset = st->n_bits;
164 dst->var_size = var_size;
166 st->n_bits += src->n_bits;
167 st->n_bits_min += var_size ? 0 : src->n_bits;
169 st->n_fields = n_fields;
170 st->var_size = last_field_has_variable_size;
172 /* Node add to tailq. */
173 TAILQ_INSERT_TAIL(&p->struct_types, st, node);
179 struct_build(struct rte_swx_pipeline *p)
183 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
184 struct thread *t = &p->threads[i];
186 t->structs = calloc(p->n_structs, sizeof(uint8_t *));
187 CHECK(t->structs, ENOMEM);
194 struct_build_free(struct rte_swx_pipeline *p)
198 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
199 struct thread *t = &p->threads[i];
207 struct_free(struct rte_swx_pipeline *p)
209 struct_build_free(p);
213 struct struct_type *elem;
215 elem = TAILQ_FIRST(&p->struct_types);
219 TAILQ_REMOVE(&p->struct_types, elem, node);
228 static struct port_in_type *
229 port_in_type_find(struct rte_swx_pipeline *p, const char *name)
231 struct port_in_type *elem;
236 TAILQ_FOREACH(elem, &p->port_in_types, node)
237 if (strcmp(elem->name, name) == 0)
244 rte_swx_pipeline_port_in_type_register(struct rte_swx_pipeline *p,
246 struct rte_swx_port_in_ops *ops)
248 struct port_in_type *elem;
251 CHECK_NAME(name, EINVAL);
253 CHECK(ops->create, EINVAL);
254 CHECK(ops->free, EINVAL);
255 CHECK(ops->pkt_rx, EINVAL);
256 CHECK(ops->stats_read, EINVAL);
258 CHECK(!port_in_type_find(p, name), EEXIST);
260 /* Node allocation. */
261 elem = calloc(1, sizeof(struct port_in_type));
264 /* Node initialization. */
265 strcpy(elem->name, name);
266 memcpy(&elem->ops, ops, sizeof(*ops));
268 /* Node add to tailq. */
269 TAILQ_INSERT_TAIL(&p->port_in_types, elem, node);
274 static struct port_in *
275 port_in_find(struct rte_swx_pipeline *p, uint32_t port_id)
277 struct port_in *port;
279 TAILQ_FOREACH(port, &p->ports_in, node)
280 if (port->id == port_id)
287 rte_swx_pipeline_port_in_config(struct rte_swx_pipeline *p,
289 const char *port_type_name,
292 struct port_in_type *type = NULL;
293 struct port_in *port = NULL;
298 CHECK(!port_in_find(p, port_id), EINVAL);
300 CHECK_NAME(port_type_name, EINVAL);
301 type = port_in_type_find(p, port_type_name);
304 obj = type->ops.create(args);
307 /* Node allocation. */
308 port = calloc(1, sizeof(struct port_in));
311 /* Node initialization. */
316 /* Node add to tailq. */
317 TAILQ_INSERT_TAIL(&p->ports_in, port, node);
318 if (p->n_ports_in < port_id + 1)
319 p->n_ports_in = port_id + 1;
325 port_in_build(struct rte_swx_pipeline *p)
327 struct port_in *port;
330 CHECK(p->n_ports_in, EINVAL);
331 CHECK(rte_is_power_of_2(p->n_ports_in), EINVAL);
333 for (i = 0; i < p->n_ports_in; i++)
334 CHECK(port_in_find(p, i), EINVAL);
336 p->in = calloc(p->n_ports_in, sizeof(struct port_in_runtime));
337 CHECK(p->in, ENOMEM);
339 TAILQ_FOREACH(port, &p->ports_in, node) {
340 struct port_in_runtime *in = &p->in[port->id];
342 in->pkt_rx = port->type->ops.pkt_rx;
350 port_in_build_free(struct rte_swx_pipeline *p)
357 port_in_free(struct rte_swx_pipeline *p)
359 port_in_build_free(p);
363 struct port_in *port;
365 port = TAILQ_FIRST(&p->ports_in);
369 TAILQ_REMOVE(&p->ports_in, port, node);
370 port->type->ops.free(port->obj);
374 /* Input port types. */
376 struct port_in_type *elem;
378 elem = TAILQ_FIRST(&p->port_in_types);
382 TAILQ_REMOVE(&p->port_in_types, elem, node);
390 static struct port_out_type *
391 port_out_type_find(struct rte_swx_pipeline *p, const char *name)
393 struct port_out_type *elem;
398 TAILQ_FOREACH(elem, &p->port_out_types, node)
399 if (!strcmp(elem->name, name))
406 rte_swx_pipeline_port_out_type_register(struct rte_swx_pipeline *p,
408 struct rte_swx_port_out_ops *ops)
410 struct port_out_type *elem;
413 CHECK_NAME(name, EINVAL);
415 CHECK(ops->create, EINVAL);
416 CHECK(ops->free, EINVAL);
417 CHECK(ops->pkt_tx, EINVAL);
418 CHECK(ops->stats_read, EINVAL);
420 CHECK(!port_out_type_find(p, name), EEXIST);
422 /* Node allocation. */
423 elem = calloc(1, sizeof(struct port_out_type));
426 /* Node initialization. */
427 strcpy(elem->name, name);
428 memcpy(&elem->ops, ops, sizeof(*ops));
430 /* Node add to tailq. */
431 TAILQ_INSERT_TAIL(&p->port_out_types, elem, node);
436 static struct port_out *
437 port_out_find(struct rte_swx_pipeline *p, uint32_t port_id)
439 struct port_out *port;
441 TAILQ_FOREACH(port, &p->ports_out, node)
442 if (port->id == port_id)
449 rte_swx_pipeline_port_out_config(struct rte_swx_pipeline *p,
451 const char *port_type_name,
454 struct port_out_type *type = NULL;
455 struct port_out *port = NULL;
460 CHECK(!port_out_find(p, port_id), EINVAL);
462 CHECK_NAME(port_type_name, EINVAL);
463 type = port_out_type_find(p, port_type_name);
466 obj = type->ops.create(args);
469 /* Node allocation. */
470 port = calloc(1, sizeof(struct port_out));
473 /* Node initialization. */
478 /* Node add to tailq. */
479 TAILQ_INSERT_TAIL(&p->ports_out, port, node);
480 if (p->n_ports_out < port_id + 1)
481 p->n_ports_out = port_id + 1;
487 port_out_build(struct rte_swx_pipeline *p)
489 struct port_out *port;
492 CHECK(p->n_ports_out, EINVAL);
494 for (i = 0; i < p->n_ports_out; i++)
495 CHECK(port_out_find(p, i), EINVAL);
497 p->out = calloc(p->n_ports_out, sizeof(struct port_out_runtime));
498 CHECK(p->out, ENOMEM);
500 TAILQ_FOREACH(port, &p->ports_out, node) {
501 struct port_out_runtime *out = &p->out[port->id];
503 out->pkt_tx = port->type->ops.pkt_tx;
504 out->flush = port->type->ops.flush;
505 out->obj = port->obj;
512 port_out_build_free(struct rte_swx_pipeline *p)
519 port_out_free(struct rte_swx_pipeline *p)
521 port_out_build_free(p);
525 struct port_out *port;
527 port = TAILQ_FIRST(&p->ports_out);
531 TAILQ_REMOVE(&p->ports_out, port, node);
532 port->type->ops.free(port->obj);
536 /* Output port types. */
538 struct port_out_type *elem;
540 elem = TAILQ_FIRST(&p->port_out_types);
544 TAILQ_REMOVE(&p->port_out_types, elem, node);
552 static struct extern_type *
553 extern_type_find(struct rte_swx_pipeline *p, const char *name)
555 struct extern_type *elem;
557 TAILQ_FOREACH(elem, &p->extern_types, node)
558 if (strcmp(elem->name, name) == 0)
564 static struct extern_type_member_func *
565 extern_type_member_func_find(struct extern_type *type, const char *name)
567 struct extern_type_member_func *elem;
569 TAILQ_FOREACH(elem, &type->funcs, node)
570 if (strcmp(elem->name, name) == 0)
576 static struct extern_obj *
577 extern_obj_find(struct rte_swx_pipeline *p, const char *name)
579 struct extern_obj *elem;
581 TAILQ_FOREACH(elem, &p->extern_objs, node)
582 if (strcmp(elem->name, name) == 0)
588 static struct extern_type_member_func *
589 extern_obj_member_func_parse(struct rte_swx_pipeline *p,
591 struct extern_obj **obj)
593 struct extern_obj *object;
594 struct extern_type_member_func *func;
595 char *object_name, *func_name;
597 if (name[0] != 'e' || name[1] != '.')
600 object_name = strdup(&name[2]);
604 func_name = strchr(object_name, '.');
613 object = extern_obj_find(p, object_name);
619 func = extern_type_member_func_find(object->type, func_name);
632 static struct field *
633 extern_obj_mailbox_field_parse(struct rte_swx_pipeline *p,
635 struct extern_obj **object)
637 struct extern_obj *obj;
639 char *obj_name, *field_name;
641 if ((name[0] != 'e') || (name[1] != '.'))
644 obj_name = strdup(&name[2]);
648 field_name = strchr(obj_name, '.');
657 obj = extern_obj_find(p, obj_name);
663 f = struct_type_field_find(obj->type->mailbox_struct_type, field_name);
677 rte_swx_pipeline_extern_type_register(struct rte_swx_pipeline *p,
679 const char *mailbox_struct_type_name,
680 rte_swx_extern_type_constructor_t constructor,
681 rte_swx_extern_type_destructor_t destructor)
683 struct extern_type *elem;
684 struct struct_type *mailbox_struct_type;
688 CHECK_NAME(name, EINVAL);
689 CHECK(!extern_type_find(p, name), EEXIST);
691 CHECK_NAME(mailbox_struct_type_name, EINVAL);
692 mailbox_struct_type = struct_type_find(p, mailbox_struct_type_name);
693 CHECK(mailbox_struct_type, EINVAL);
694 CHECK(!mailbox_struct_type->var_size, EINVAL);
696 CHECK(constructor, EINVAL);
697 CHECK(destructor, EINVAL);
699 /* Node allocation. */
700 elem = calloc(1, sizeof(struct extern_type));
703 /* Node initialization. */
704 strcpy(elem->name, name);
705 elem->mailbox_struct_type = mailbox_struct_type;
706 elem->constructor = constructor;
707 elem->destructor = destructor;
708 TAILQ_INIT(&elem->funcs);
710 /* Node add to tailq. */
711 TAILQ_INSERT_TAIL(&p->extern_types, elem, node);
717 rte_swx_pipeline_extern_type_member_func_register(struct rte_swx_pipeline *p,
718 const char *extern_type_name,
720 rte_swx_extern_type_member_func_t member_func)
722 struct extern_type *type;
723 struct extern_type_member_func *type_member;
727 CHECK_NAME(extern_type_name, EINVAL);
728 type = extern_type_find(p, extern_type_name);
730 CHECK(type->n_funcs < RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX, ENOSPC);
732 CHECK_NAME(name, EINVAL);
733 CHECK(!extern_type_member_func_find(type, name), EEXIST);
735 CHECK(member_func, EINVAL);
737 /* Node allocation. */
738 type_member = calloc(1, sizeof(struct extern_type_member_func));
739 CHECK(type_member, ENOMEM);
741 /* Node initialization. */
742 strcpy(type_member->name, name);
743 type_member->func = member_func;
744 type_member->id = type->n_funcs;
746 /* Node add to tailq. */
747 TAILQ_INSERT_TAIL(&type->funcs, type_member, node);
754 rte_swx_pipeline_extern_object_config(struct rte_swx_pipeline *p,
755 const char *extern_type_name,
759 struct extern_type *type;
760 struct extern_obj *obj;
765 CHECK_NAME(extern_type_name, EINVAL);
766 type = extern_type_find(p, extern_type_name);
769 CHECK_NAME(name, EINVAL);
770 CHECK(!extern_obj_find(p, name), EEXIST);
772 /* Node allocation. */
773 obj = calloc(1, sizeof(struct extern_obj));
776 /* Object construction. */
777 obj_handle = type->constructor(args);
783 /* Node initialization. */
784 strcpy(obj->name, name);
786 obj->obj = obj_handle;
787 obj->struct_id = p->n_structs;
788 obj->id = p->n_extern_objs;
790 /* Node add to tailq. */
791 TAILQ_INSERT_TAIL(&p->extern_objs, obj, node);
799 extern_obj_build(struct rte_swx_pipeline *p)
803 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
804 struct thread *t = &p->threads[i];
805 struct extern_obj *obj;
807 t->extern_objs = calloc(p->n_extern_objs,
808 sizeof(struct extern_obj_runtime));
809 CHECK(t->extern_objs, ENOMEM);
811 TAILQ_FOREACH(obj, &p->extern_objs, node) {
812 struct extern_obj_runtime *r =
813 &t->extern_objs[obj->id];
814 struct extern_type_member_func *func;
815 uint32_t mailbox_size =
816 obj->type->mailbox_struct_type->n_bits / 8;
820 r->mailbox = calloc(1, mailbox_size);
821 CHECK(r->mailbox, ENOMEM);
823 TAILQ_FOREACH(func, &obj->type->funcs, node)
824 r->funcs[func->id] = func->func;
826 t->structs[obj->struct_id] = r->mailbox;
834 extern_obj_build_free(struct rte_swx_pipeline *p)
838 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
839 struct thread *t = &p->threads[i];
845 for (j = 0; j < p->n_extern_objs; j++) {
846 struct extern_obj_runtime *r = &t->extern_objs[j];
851 free(t->extern_objs);
852 t->extern_objs = NULL;
857 extern_obj_free(struct rte_swx_pipeline *p)
859 extern_obj_build_free(p);
861 /* Extern objects. */
863 struct extern_obj *elem;
865 elem = TAILQ_FIRST(&p->extern_objs);
869 TAILQ_REMOVE(&p->extern_objs, elem, node);
871 elem->type->destructor(elem->obj);
877 struct extern_type *elem;
879 elem = TAILQ_FIRST(&p->extern_types);
883 TAILQ_REMOVE(&p->extern_types, elem, node);
886 struct extern_type_member_func *func;
888 func = TAILQ_FIRST(&elem->funcs);
892 TAILQ_REMOVE(&elem->funcs, func, node);
903 static struct extern_func *
904 extern_func_find(struct rte_swx_pipeline *p, const char *name)
906 struct extern_func *elem;
908 TAILQ_FOREACH(elem, &p->extern_funcs, node)
909 if (strcmp(elem->name, name) == 0)
915 static struct extern_func *
916 extern_func_parse(struct rte_swx_pipeline *p,
919 if (name[0] != 'f' || name[1] != '.')
922 return extern_func_find(p, &name[2]);
925 static struct field *
926 extern_func_mailbox_field_parse(struct rte_swx_pipeline *p,
928 struct extern_func **function)
930 struct extern_func *func;
932 char *func_name, *field_name;
934 if ((name[0] != 'f') || (name[1] != '.'))
937 func_name = strdup(&name[2]);
941 field_name = strchr(func_name, '.');
950 func = extern_func_find(p, func_name);
956 f = struct_type_field_find(func->mailbox_struct_type, field_name);
970 rte_swx_pipeline_extern_func_register(struct rte_swx_pipeline *p,
972 const char *mailbox_struct_type_name,
973 rte_swx_extern_func_t func)
975 struct extern_func *f;
976 struct struct_type *mailbox_struct_type;
980 CHECK_NAME(name, EINVAL);
981 CHECK(!extern_func_find(p, name), EEXIST);
983 CHECK_NAME(mailbox_struct_type_name, EINVAL);
984 mailbox_struct_type = struct_type_find(p, mailbox_struct_type_name);
985 CHECK(mailbox_struct_type, EINVAL);
986 CHECK(!mailbox_struct_type->var_size, EINVAL);
990 /* Node allocation. */
991 f = calloc(1, sizeof(struct extern_func));
994 /* Node initialization. */
995 strcpy(f->name, name);
996 f->mailbox_struct_type = mailbox_struct_type;
998 f->struct_id = p->n_structs;
999 f->id = p->n_extern_funcs;
1001 /* Node add to tailq. */
1002 TAILQ_INSERT_TAIL(&p->extern_funcs, f, node);
1003 p->n_extern_funcs++;
1010 extern_func_build(struct rte_swx_pipeline *p)
1014 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1015 struct thread *t = &p->threads[i];
1016 struct extern_func *func;
1018 /* Memory allocation. */
1019 t->extern_funcs = calloc(p->n_extern_funcs,
1020 sizeof(struct extern_func_runtime));
1021 CHECK(t->extern_funcs, ENOMEM);
1023 /* Extern function. */
1024 TAILQ_FOREACH(func, &p->extern_funcs, node) {
1025 struct extern_func_runtime *r =
1026 &t->extern_funcs[func->id];
1027 uint32_t mailbox_size =
1028 func->mailbox_struct_type->n_bits / 8;
1030 r->func = func->func;
1032 r->mailbox = calloc(1, mailbox_size);
1033 CHECK(r->mailbox, ENOMEM);
1035 t->structs[func->struct_id] = r->mailbox;
1043 extern_func_build_free(struct rte_swx_pipeline *p)
1047 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1048 struct thread *t = &p->threads[i];
1051 if (!t->extern_funcs)
1054 for (j = 0; j < p->n_extern_funcs; j++) {
1055 struct extern_func_runtime *r = &t->extern_funcs[j];
1060 free(t->extern_funcs);
1061 t->extern_funcs = NULL;
1066 extern_func_free(struct rte_swx_pipeline *p)
1068 extern_func_build_free(p);
1071 struct extern_func *elem;
1073 elem = TAILQ_FIRST(&p->extern_funcs);
1077 TAILQ_REMOVE(&p->extern_funcs, elem, node);
1085 static struct header *
1086 header_find(struct rte_swx_pipeline *p, const char *name)
1088 struct header *elem;
1090 TAILQ_FOREACH(elem, &p->headers, node)
1091 if (strcmp(elem->name, name) == 0)
1097 static struct header *
1098 header_find_by_struct_id(struct rte_swx_pipeline *p, uint32_t struct_id)
1100 struct header *elem;
1102 TAILQ_FOREACH(elem, &p->headers, node)
1103 if (elem->struct_id == struct_id)
1109 static struct header *
1110 header_parse(struct rte_swx_pipeline *p,
1113 if (name[0] != 'h' || name[1] != '.')
1116 return header_find(p, &name[2]);
1119 static struct field *
1120 header_field_parse(struct rte_swx_pipeline *p,
1122 struct header **header)
1126 char *header_name, *field_name;
1128 if ((name[0] != 'h') || (name[1] != '.'))
1131 header_name = strdup(&name[2]);
1135 field_name = strchr(header_name, '.');
1144 h = header_find(p, header_name);
1150 f = struct_type_field_find(h->st, field_name);
1164 rte_swx_pipeline_packet_header_register(struct rte_swx_pipeline *p,
1166 const char *struct_type_name)
1168 struct struct_type *st;
1170 size_t n_headers_max;
1173 CHECK_NAME(name, EINVAL);
1174 CHECK_NAME(struct_type_name, EINVAL);
1176 CHECK(!header_find(p, name), EEXIST);
1178 st = struct_type_find(p, struct_type_name);
1181 n_headers_max = RTE_SIZEOF_FIELD(struct thread, valid_headers) * 8;
1182 CHECK(p->n_headers < n_headers_max, ENOSPC);
1184 /* Node allocation. */
1185 h = calloc(1, sizeof(struct header));
1188 /* Node initialization. */
1189 strcpy(h->name, name);
1191 h->struct_id = p->n_structs;
1192 h->id = p->n_headers;
1194 /* Node add to tailq. */
1195 TAILQ_INSERT_TAIL(&p->headers, h, node);
1203 header_build(struct rte_swx_pipeline *p)
1206 uint32_t n_bytes = 0, i;
1208 TAILQ_FOREACH(h, &p->headers, node) {
1209 n_bytes += h->st->n_bits / 8;
1212 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1213 struct thread *t = &p->threads[i];
1214 uint32_t offset = 0;
1216 t->headers = calloc(p->n_headers,
1217 sizeof(struct header_runtime));
1218 CHECK(t->headers, ENOMEM);
1220 t->headers_out = calloc(p->n_headers,
1221 sizeof(struct header_out_runtime));
1222 CHECK(t->headers_out, ENOMEM);
1224 t->header_storage = calloc(1, n_bytes);
1225 CHECK(t->header_storage, ENOMEM);
1227 t->header_out_storage = calloc(1, n_bytes);
1228 CHECK(t->header_out_storage, ENOMEM);
1230 TAILQ_FOREACH(h, &p->headers, node) {
1231 uint8_t *header_storage;
1232 uint32_t n_bytes = h->st->n_bits / 8;
1234 header_storage = &t->header_storage[offset];
1237 t->headers[h->id].ptr0 = header_storage;
1238 t->headers[h->id].n_bytes = n_bytes;
1240 t->structs[h->struct_id] = header_storage;
1248 header_build_free(struct rte_swx_pipeline *p)
1252 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1253 struct thread *t = &p->threads[i];
1255 free(t->headers_out);
1256 t->headers_out = NULL;
1261 free(t->header_out_storage);
1262 t->header_out_storage = NULL;
1264 free(t->header_storage);
1265 t->header_storage = NULL;
1270 header_free(struct rte_swx_pipeline *p)
1272 header_build_free(p);
1275 struct header *elem;
1277 elem = TAILQ_FIRST(&p->headers);
1281 TAILQ_REMOVE(&p->headers, elem, node);
1289 static struct field *
1290 metadata_field_parse(struct rte_swx_pipeline *p, const char *name)
1292 if (!p->metadata_st)
1295 if (name[0] != 'm' || name[1] != '.')
1298 return struct_type_field_find(p->metadata_st, &name[2]);
1302 rte_swx_pipeline_packet_metadata_register(struct rte_swx_pipeline *p,
1303 const char *struct_type_name)
1305 struct struct_type *st = NULL;
1309 CHECK_NAME(struct_type_name, EINVAL);
1310 st = struct_type_find(p, struct_type_name);
1312 CHECK(!st->var_size, EINVAL);
1313 CHECK(!p->metadata_st, EINVAL);
1315 p->metadata_st = st;
1316 p->metadata_struct_id = p->n_structs;
1324 metadata_build(struct rte_swx_pipeline *p)
1326 uint32_t n_bytes = p->metadata_st->n_bits / 8;
1329 /* Thread-level initialization. */
1330 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1331 struct thread *t = &p->threads[i];
1334 metadata = calloc(1, n_bytes);
1335 CHECK(metadata, ENOMEM);
1337 t->metadata = metadata;
1338 t->structs[p->metadata_struct_id] = metadata;
1345 metadata_build_free(struct rte_swx_pipeline *p)
1349 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1350 struct thread *t = &p->threads[i];
1358 metadata_free(struct rte_swx_pipeline *p)
1360 metadata_build_free(p);
1367 instruction_is_tx(enum instruction_type type)
1380 instruction_is_jmp(struct instruction *instr)
1382 switch (instr->type) {
1384 case INSTR_JMP_VALID:
1385 case INSTR_JMP_INVALID:
1387 case INSTR_JMP_MISS:
1388 case INSTR_JMP_ACTION_HIT:
1389 case INSTR_JMP_ACTION_MISS:
1391 case INSTR_JMP_EQ_MH:
1392 case INSTR_JMP_EQ_HM:
1393 case INSTR_JMP_EQ_HH:
1394 case INSTR_JMP_EQ_I:
1396 case INSTR_JMP_NEQ_MH:
1397 case INSTR_JMP_NEQ_HM:
1398 case INSTR_JMP_NEQ_HH:
1399 case INSTR_JMP_NEQ_I:
1401 case INSTR_JMP_LT_MH:
1402 case INSTR_JMP_LT_HM:
1403 case INSTR_JMP_LT_HH:
1404 case INSTR_JMP_LT_MI:
1405 case INSTR_JMP_LT_HI:
1407 case INSTR_JMP_GT_MH:
1408 case INSTR_JMP_GT_HM:
1409 case INSTR_JMP_GT_HH:
1410 case INSTR_JMP_GT_MI:
1411 case INSTR_JMP_GT_HI:
1419 static struct field *
1420 action_field_parse(struct action *action, const char *name);
1422 static struct field *
1423 struct_field_parse(struct rte_swx_pipeline *p,
1424 struct action *action,
1426 uint32_t *struct_id)
1433 struct header *header;
1435 f = header_field_parse(p, name, &header);
1439 *struct_id = header->struct_id;
1445 f = metadata_field_parse(p, name);
1449 *struct_id = p->metadata_struct_id;
1458 f = action_field_parse(action, name);
1468 struct extern_obj *obj;
1470 f = extern_obj_mailbox_field_parse(p, name, &obj);
1474 *struct_id = obj->struct_id;
1480 struct extern_func *func;
1482 f = extern_func_mailbox_field_parse(p, name, &func);
1486 *struct_id = func->struct_id;
1499 instr_rx_translate(struct rte_swx_pipeline *p,
1500 struct action *action,
1503 struct instruction *instr,
1504 struct instruction_data *data __rte_unused)
1508 CHECK(!action, EINVAL);
1509 CHECK(n_tokens == 2, EINVAL);
1511 f = metadata_field_parse(p, tokens[1]);
1514 instr->type = INSTR_RX;
1515 instr->io.io.offset = f->offset / 8;
1516 instr->io.io.n_bits = f->n_bits;
1524 instr_tx_translate(struct rte_swx_pipeline *p,
1525 struct action *action __rte_unused,
1528 struct instruction *instr,
1529 struct instruction_data *data __rte_unused)
1531 char *port = tokens[1];
1535 CHECK(n_tokens == 2, EINVAL);
1537 f = metadata_field_parse(p, port);
1539 instr->type = INSTR_TX;
1540 instr->io.io.offset = f->offset / 8;
1541 instr->io.io.n_bits = f->n_bits;
1546 port_val = strtoul(port, &port, 0);
1547 CHECK(!port[0], EINVAL);
1549 instr->type = INSTR_TX_I;
1550 instr->io.io.val = port_val;
1555 instr_drop_translate(struct rte_swx_pipeline *p,
1556 struct action *action __rte_unused,
1557 char **tokens __rte_unused,
1559 struct instruction *instr,
1560 struct instruction_data *data __rte_unused)
1562 CHECK(n_tokens == 1, EINVAL);
1565 instr->type = INSTR_TX_I;
1566 instr->io.io.val = p->n_ports_out - 1;
1571 instr_tx_exec(struct rte_swx_pipeline *p)
1573 struct thread *t = &p->threads[p->thread_id];
1574 struct instruction *ip = t->ip;
1576 __instr_tx_exec(p, t, ip);
1579 thread_ip_reset(p, t);
1584 instr_tx_i_exec(struct rte_swx_pipeline *p)
1586 struct thread *t = &p->threads[p->thread_id];
1587 struct instruction *ip = t->ip;
1589 __instr_tx_i_exec(p, t, ip);
1592 thread_ip_reset(p, t);
1600 instr_hdr_extract_translate(struct rte_swx_pipeline *p,
1601 struct action *action,
1604 struct instruction *instr,
1605 struct instruction_data *data __rte_unused)
1609 CHECK(!action, EINVAL);
1610 CHECK((n_tokens == 2) || (n_tokens == 3), EINVAL);
1612 h = header_parse(p, tokens[1]);
1615 if (n_tokens == 2) {
1616 CHECK(!h->st->var_size, EINVAL);
1618 instr->type = INSTR_HDR_EXTRACT;
1619 instr->io.hdr.header_id[0] = h->id;
1620 instr->io.hdr.struct_id[0] = h->struct_id;
1621 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
1625 CHECK(h->st->var_size, EINVAL);
1627 mf = metadata_field_parse(p, tokens[2]);
1629 CHECK(!mf->var_size, EINVAL);
1631 instr->type = INSTR_HDR_EXTRACT_M;
1632 instr->io.io.offset = mf->offset / 8;
1633 instr->io.io.n_bits = mf->n_bits;
1634 instr->io.hdr.header_id[0] = h->id;
1635 instr->io.hdr.struct_id[0] = h->struct_id;
1636 instr->io.hdr.n_bytes[0] = h->st->n_bits_min / 8;
1643 instr_hdr_lookahead_translate(struct rte_swx_pipeline *p,
1644 struct action *action,
1647 struct instruction *instr,
1648 struct instruction_data *data __rte_unused)
1652 CHECK(!action, EINVAL);
1653 CHECK(n_tokens == 2, EINVAL);
1655 h = header_parse(p, tokens[1]);
1657 CHECK(!h->st->var_size, EINVAL);
1659 instr->type = INSTR_HDR_LOOKAHEAD;
1660 instr->io.hdr.header_id[0] = h->id;
1661 instr->io.hdr.struct_id[0] = h->struct_id;
1662 instr->io.hdr.n_bytes[0] = 0; /* Unused. */
1668 instr_hdr_extract_exec(struct rte_swx_pipeline *p)
1670 struct thread *t = &p->threads[p->thread_id];
1671 struct instruction *ip = t->ip;
1673 __instr_hdr_extract_exec(p, t, ip);
1680 instr_hdr_extract2_exec(struct rte_swx_pipeline *p)
1682 struct thread *t = &p->threads[p->thread_id];
1683 struct instruction *ip = t->ip;
1685 __instr_hdr_extract2_exec(p, t, ip);
1692 instr_hdr_extract3_exec(struct rte_swx_pipeline *p)
1694 struct thread *t = &p->threads[p->thread_id];
1695 struct instruction *ip = t->ip;
1697 __instr_hdr_extract3_exec(p, t, ip);
1704 instr_hdr_extract4_exec(struct rte_swx_pipeline *p)
1706 struct thread *t = &p->threads[p->thread_id];
1707 struct instruction *ip = t->ip;
1709 __instr_hdr_extract4_exec(p, t, ip);
1716 instr_hdr_extract5_exec(struct rte_swx_pipeline *p)
1718 struct thread *t = &p->threads[p->thread_id];
1719 struct instruction *ip = t->ip;
1721 __instr_hdr_extract5_exec(p, t, ip);
1728 instr_hdr_extract6_exec(struct rte_swx_pipeline *p)
1730 struct thread *t = &p->threads[p->thread_id];
1731 struct instruction *ip = t->ip;
1733 __instr_hdr_extract6_exec(p, t, ip);
1740 instr_hdr_extract7_exec(struct rte_swx_pipeline *p)
1742 struct thread *t = &p->threads[p->thread_id];
1743 struct instruction *ip = t->ip;
1745 __instr_hdr_extract7_exec(p, t, ip);
1752 instr_hdr_extract8_exec(struct rte_swx_pipeline *p)
1754 struct thread *t = &p->threads[p->thread_id];
1755 struct instruction *ip = t->ip;
1757 __instr_hdr_extract8_exec(p, t, ip);
1764 instr_hdr_extract_m_exec(struct rte_swx_pipeline *p)
1766 struct thread *t = &p->threads[p->thread_id];
1767 struct instruction *ip = t->ip;
1769 __instr_hdr_extract_m_exec(p, t, ip);
1776 instr_hdr_lookahead_exec(struct rte_swx_pipeline *p)
1778 struct thread *t = &p->threads[p->thread_id];
1779 struct instruction *ip = t->ip;
1781 __instr_hdr_lookahead_exec(p, t, ip);
1791 instr_hdr_emit_translate(struct rte_swx_pipeline *p,
1792 struct action *action __rte_unused,
1795 struct instruction *instr,
1796 struct instruction_data *data __rte_unused)
1800 CHECK(n_tokens == 2, EINVAL);
1802 h = header_parse(p, tokens[1]);
1805 instr->type = INSTR_HDR_EMIT;
1806 instr->io.hdr.header_id[0] = h->id;
1807 instr->io.hdr.struct_id[0] = h->struct_id;
1808 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
1813 instr_hdr_emit_exec(struct rte_swx_pipeline *p)
1815 struct thread *t = &p->threads[p->thread_id];
1816 struct instruction *ip = t->ip;
1818 __instr_hdr_emit_exec(p, t, ip);
1825 instr_hdr_emit_tx_exec(struct rte_swx_pipeline *p)
1827 struct thread *t = &p->threads[p->thread_id];
1828 struct instruction *ip = t->ip;
1830 __instr_hdr_emit_tx_exec(p, t, ip);
1833 thread_ip_reset(p, t);
1838 instr_hdr_emit2_tx_exec(struct rte_swx_pipeline *p)
1840 struct thread *t = &p->threads[p->thread_id];
1841 struct instruction *ip = t->ip;
1843 __instr_hdr_emit2_tx_exec(p, t, ip);
1846 thread_ip_reset(p, t);
1851 instr_hdr_emit3_tx_exec(struct rte_swx_pipeline *p)
1853 struct thread *t = &p->threads[p->thread_id];
1854 struct instruction *ip = t->ip;
1856 __instr_hdr_emit3_tx_exec(p, t, ip);
1859 thread_ip_reset(p, t);
1864 instr_hdr_emit4_tx_exec(struct rte_swx_pipeline *p)
1866 struct thread *t = &p->threads[p->thread_id];
1867 struct instruction *ip = t->ip;
1869 __instr_hdr_emit4_tx_exec(p, t, ip);
1872 thread_ip_reset(p, t);
1877 instr_hdr_emit5_tx_exec(struct rte_swx_pipeline *p)
1879 struct thread *t = &p->threads[p->thread_id];
1880 struct instruction *ip = t->ip;
1882 __instr_hdr_emit5_tx_exec(p, t, ip);
1885 thread_ip_reset(p, t);
1890 instr_hdr_emit6_tx_exec(struct rte_swx_pipeline *p)
1892 struct thread *t = &p->threads[p->thread_id];
1893 struct instruction *ip = t->ip;
1895 __instr_hdr_emit6_tx_exec(p, t, ip);
1898 thread_ip_reset(p, t);
1903 instr_hdr_emit7_tx_exec(struct rte_swx_pipeline *p)
1905 struct thread *t = &p->threads[p->thread_id];
1906 struct instruction *ip = t->ip;
1908 __instr_hdr_emit7_tx_exec(p, t, ip);
1911 thread_ip_reset(p, t);
1916 instr_hdr_emit8_tx_exec(struct rte_swx_pipeline *p)
1918 struct thread *t = &p->threads[p->thread_id];
1919 struct instruction *ip = t->ip;
1921 __instr_hdr_emit8_tx_exec(p, t, ip);
1924 thread_ip_reset(p, t);
1932 instr_hdr_validate_translate(struct rte_swx_pipeline *p,
1933 struct action *action __rte_unused,
1936 struct instruction *instr,
1937 struct instruction_data *data __rte_unused)
1941 CHECK(n_tokens == 2, EINVAL);
1943 h = header_parse(p, tokens[1]);
1946 instr->type = INSTR_HDR_VALIDATE;
1947 instr->valid.header_id = h->id;
1952 instr_hdr_validate_exec(struct rte_swx_pipeline *p)
1954 struct thread *t = &p->threads[p->thread_id];
1955 struct instruction *ip = t->ip;
1957 __instr_hdr_validate_exec(p, t, ip);
1967 instr_hdr_invalidate_translate(struct rte_swx_pipeline *p,
1968 struct action *action __rte_unused,
1971 struct instruction *instr,
1972 struct instruction_data *data __rte_unused)
1976 CHECK(n_tokens == 2, EINVAL);
1978 h = header_parse(p, tokens[1]);
1981 instr->type = INSTR_HDR_INVALIDATE;
1982 instr->valid.header_id = h->id;
1987 instr_hdr_invalidate_exec(struct rte_swx_pipeline *p)
1989 struct thread *t = &p->threads[p->thread_id];
1990 struct instruction *ip = t->ip;
1992 __instr_hdr_invalidate_exec(p, t, ip);
2001 static struct table *
2002 table_find(struct rte_swx_pipeline *p, const char *name);
2004 static struct selector *
2005 selector_find(struct rte_swx_pipeline *p, const char *name);
2007 static struct learner *
2008 learner_find(struct rte_swx_pipeline *p, const char *name);
2011 instr_table_translate(struct rte_swx_pipeline *p,
2012 struct action *action,
2015 struct instruction *instr,
2016 struct instruction_data *data __rte_unused)
2022 CHECK(!action, EINVAL);
2023 CHECK(n_tokens == 2, EINVAL);
2025 t = table_find(p, tokens[1]);
2027 instr->type = INSTR_TABLE;
2028 instr->table.table_id = t->id;
2032 s = selector_find(p, tokens[1]);
2034 instr->type = INSTR_SELECTOR;
2035 instr->table.table_id = s->id;
2039 l = learner_find(p, tokens[1]);
2041 instr->type = INSTR_LEARNER;
2042 instr->table.table_id = l->id;
2050 instr_table_exec(struct rte_swx_pipeline *p)
2052 struct thread *t = &p->threads[p->thread_id];
2053 struct instruction *ip = t->ip;
2054 uint32_t table_id = ip->table.table_id;
2055 struct rte_swx_table_state *ts = &t->table_state[table_id];
2056 struct table_runtime *table = &t->tables[table_id];
2057 struct table_statistics *stats = &p->table_stats[table_id];
2058 uint64_t action_id, n_pkts_hit, n_pkts_action;
2059 uint8_t *action_data;
2063 done = table->func(ts->obj,
2071 TRACE("[Thread %2u] table %u (not finalized)\n",
2079 action_id = hit ? action_id : ts->default_action_id;
2080 action_data = hit ? action_data : ts->default_action_data;
2081 n_pkts_hit = stats->n_pkts_hit[hit];
2082 n_pkts_action = stats->n_pkts_action[action_id];
2084 TRACE("[Thread %2u] table %u (%s, action %u)\n",
2087 hit ? "hit" : "miss",
2088 (uint32_t)action_id);
2090 t->action_id = action_id;
2091 t->structs[0] = action_data;
2093 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2094 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2097 thread_ip_action_call(p, t, action_id);
2101 instr_selector_exec(struct rte_swx_pipeline *p)
2103 struct thread *t = &p->threads[p->thread_id];
2104 struct instruction *ip = t->ip;
2105 uint32_t selector_id = ip->table.table_id;
2106 struct rte_swx_table_state *ts = &t->table_state[p->n_tables + selector_id];
2107 struct selector_runtime *selector = &t->selectors[selector_id];
2108 struct selector_statistics *stats = &p->selector_stats[selector_id];
2109 uint64_t n_pkts = stats->n_pkts;
2113 done = rte_swx_table_selector_select(ts->obj,
2115 selector->group_id_buffer,
2116 selector->selector_buffer,
2117 selector->member_id_buffer);
2120 TRACE("[Thread %2u] selector %u (not finalized)\n",
2129 TRACE("[Thread %2u] selector %u\n",
2133 stats->n_pkts = n_pkts + 1;
2140 instr_learner_exec(struct rte_swx_pipeline *p)
2142 struct thread *t = &p->threads[p->thread_id];
2143 struct instruction *ip = t->ip;
2144 uint32_t learner_id = ip->table.table_id;
2145 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2146 p->n_selectors + learner_id];
2147 struct learner_runtime *l = &t->learners[learner_id];
2148 struct learner_statistics *stats = &p->learner_stats[learner_id];
2149 uint64_t action_id, n_pkts_hit, n_pkts_action, time;
2150 uint8_t *action_data;
2154 time = rte_get_tsc_cycles();
2156 done = rte_swx_table_learner_lookup(ts->obj,
2165 TRACE("[Thread %2u] learner %u (not finalized)\n",
2173 action_id = hit ? action_id : ts->default_action_id;
2174 action_data = hit ? action_data : ts->default_action_data;
2175 n_pkts_hit = stats->n_pkts_hit[hit];
2176 n_pkts_action = stats->n_pkts_action[action_id];
2178 TRACE("[Thread %2u] learner %u (%s, action %u)\n",
2181 hit ? "hit" : "miss",
2182 (uint32_t)action_id);
2184 t->action_id = action_id;
2185 t->structs[0] = action_data;
2187 t->learner_id = learner_id;
2189 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2190 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2193 thread_ip_action_call(p, t, action_id);
2199 static struct action *
2200 action_find(struct rte_swx_pipeline *p, const char *name);
2203 action_has_nbo_args(struct action *a);
2206 instr_learn_translate(struct rte_swx_pipeline *p,
2207 struct action *action,
2210 struct instruction *instr,
2211 struct instruction_data *data __rte_unused)
2215 CHECK(action, EINVAL);
2216 CHECK(n_tokens == 2, EINVAL);
2218 a = action_find(p, tokens[1]);
2220 CHECK(!action_has_nbo_args(a), EINVAL);
2222 instr->type = INSTR_LEARNER_LEARN;
2223 instr->learn.action_id = a->id;
2229 instr_learn_exec(struct rte_swx_pipeline *p)
2231 struct thread *t = &p->threads[p->thread_id];
2232 struct instruction *ip = t->ip;
2234 __instr_learn_exec(p, t, ip);
2244 instr_forget_translate(struct rte_swx_pipeline *p __rte_unused,
2245 struct action *action,
2246 char **tokens __rte_unused,
2248 struct instruction *instr,
2249 struct instruction_data *data __rte_unused)
2251 CHECK(action, EINVAL);
2252 CHECK(n_tokens == 1, EINVAL);
2254 instr->type = INSTR_LEARNER_FORGET;
2260 instr_forget_exec(struct rte_swx_pipeline *p)
2262 struct thread *t = &p->threads[p->thread_id];
2263 struct instruction *ip = t->ip;
2265 __instr_forget_exec(p, t, ip);
2275 instr_extern_translate(struct rte_swx_pipeline *p,
2276 struct action *action __rte_unused,
2279 struct instruction *instr,
2280 struct instruction_data *data __rte_unused)
2282 char *token = tokens[1];
2284 CHECK(n_tokens == 2, EINVAL);
2286 if (token[0] == 'e') {
2287 struct extern_obj *obj;
2288 struct extern_type_member_func *func;
2290 func = extern_obj_member_func_parse(p, token, &obj);
2291 CHECK(func, EINVAL);
2293 instr->type = INSTR_EXTERN_OBJ;
2294 instr->ext_obj.ext_obj_id = obj->id;
2295 instr->ext_obj.func_id = func->id;
2300 if (token[0] == 'f') {
2301 struct extern_func *func;
2303 func = extern_func_parse(p, token);
2304 CHECK(func, EINVAL);
2306 instr->type = INSTR_EXTERN_FUNC;
2307 instr->ext_func.ext_func_id = func->id;
2316 instr_extern_obj_exec(struct rte_swx_pipeline *p)
2318 struct thread *t = &p->threads[p->thread_id];
2319 struct instruction *ip = t->ip;
2322 /* Extern object member function execute. */
2323 done = __instr_extern_obj_exec(p, t, ip);
2326 thread_ip_inc_cond(t, done);
2327 thread_yield_cond(p, done ^ 1);
2331 instr_extern_func_exec(struct rte_swx_pipeline *p)
2333 struct thread *t = &p->threads[p->thread_id];
2334 struct instruction *ip = t->ip;
2337 /* Extern function execute. */
2338 done = __instr_extern_func_exec(p, t, ip);
2341 thread_ip_inc_cond(t, done);
2342 thread_yield_cond(p, done ^ 1);
2349 instr_mov_translate(struct rte_swx_pipeline *p,
2350 struct action *action,
2353 struct instruction *instr,
2354 struct instruction_data *data __rte_unused)
2356 char *dst = tokens[1], *src = tokens[2];
2357 struct field *fdst, *fsrc;
2359 uint32_t dst_struct_id = 0, src_struct_id = 0;
2361 CHECK(n_tokens == 3, EINVAL);
2363 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2364 CHECK(fdst, EINVAL);
2365 CHECK(!fdst->var_size, EINVAL);
2367 /* MOV, MOV_MH, MOV_HM or MOV_HH. */
2368 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2370 CHECK(!fsrc->var_size, EINVAL);
2372 instr->type = INSTR_MOV;
2373 if (dst[0] != 'h' && src[0] == 'h')
2374 instr->type = INSTR_MOV_MH;
2375 if (dst[0] == 'h' && src[0] != 'h')
2376 instr->type = INSTR_MOV_HM;
2377 if (dst[0] == 'h' && src[0] == 'h')
2378 instr->type = INSTR_MOV_HH;
2380 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
2381 instr->mov.dst.n_bits = fdst->n_bits;
2382 instr->mov.dst.offset = fdst->offset / 8;
2383 instr->mov.src.struct_id = (uint8_t)src_struct_id;
2384 instr->mov.src.n_bits = fsrc->n_bits;
2385 instr->mov.src.offset = fsrc->offset / 8;
2390 src_val = strtoull(src, &src, 0);
2391 CHECK(!src[0], EINVAL);
2394 src_val = hton64(src_val) >> (64 - fdst->n_bits);
2396 instr->type = INSTR_MOV_I;
2397 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
2398 instr->mov.dst.n_bits = fdst->n_bits;
2399 instr->mov.dst.offset = fdst->offset / 8;
2400 instr->mov.src_val = src_val;
2405 instr_mov_exec(struct rte_swx_pipeline *p)
2407 struct thread *t = &p->threads[p->thread_id];
2408 struct instruction *ip = t->ip;
2410 __instr_mov_exec(p, t, ip);
2417 instr_mov_mh_exec(struct rte_swx_pipeline *p)
2419 struct thread *t = &p->threads[p->thread_id];
2420 struct instruction *ip = t->ip;
2422 __instr_mov_mh_exec(p, t, ip);
2429 instr_mov_hm_exec(struct rte_swx_pipeline *p)
2431 struct thread *t = &p->threads[p->thread_id];
2432 struct instruction *ip = t->ip;
2434 __instr_mov_hm_exec(p, t, ip);
2441 instr_mov_hh_exec(struct rte_swx_pipeline *p)
2443 struct thread *t = &p->threads[p->thread_id];
2444 struct instruction *ip = t->ip;
2446 __instr_mov_hh_exec(p, t, ip);
2453 instr_mov_i_exec(struct rte_swx_pipeline *p)
2455 struct thread *t = &p->threads[p->thread_id];
2456 struct instruction *ip = t->ip;
2458 __instr_mov_i_exec(p, t, ip);
2468 instr_dma_ht_exec(struct rte_swx_pipeline *p)
2470 struct thread *t = &p->threads[p->thread_id];
2471 struct instruction *ip = t->ip;
2473 __instr_dma_ht_exec(p, t, ip);
2480 instr_dma_ht2_exec(struct rte_swx_pipeline *p)
2482 struct thread *t = &p->threads[p->thread_id];
2483 struct instruction *ip = t->ip;
2485 __instr_dma_ht2_exec(p, t, ip);
2492 instr_dma_ht3_exec(struct rte_swx_pipeline *p)
2494 struct thread *t = &p->threads[p->thread_id];
2495 struct instruction *ip = t->ip;
2497 __instr_dma_ht3_exec(p, t, ip);
2504 instr_dma_ht4_exec(struct rte_swx_pipeline *p)
2506 struct thread *t = &p->threads[p->thread_id];
2507 struct instruction *ip = t->ip;
2509 __instr_dma_ht4_exec(p, t, ip);
2516 instr_dma_ht5_exec(struct rte_swx_pipeline *p)
2518 struct thread *t = &p->threads[p->thread_id];
2519 struct instruction *ip = t->ip;
2521 __instr_dma_ht5_exec(p, t, ip);
2528 instr_dma_ht6_exec(struct rte_swx_pipeline *p)
2530 struct thread *t = &p->threads[p->thread_id];
2531 struct instruction *ip = t->ip;
2533 __instr_dma_ht6_exec(p, t, ip);
2540 instr_dma_ht7_exec(struct rte_swx_pipeline *p)
2542 struct thread *t = &p->threads[p->thread_id];
2543 struct instruction *ip = t->ip;
2545 __instr_dma_ht7_exec(p, t, ip);
2552 instr_dma_ht8_exec(struct rte_swx_pipeline *p)
2554 struct thread *t = &p->threads[p->thread_id];
2555 struct instruction *ip = t->ip;
2557 __instr_dma_ht8_exec(p, t, ip);
2567 instr_alu_add_translate(struct rte_swx_pipeline *p,
2568 struct action *action,
2571 struct instruction *instr,
2572 struct instruction_data *data __rte_unused)
2574 char *dst = tokens[1], *src = tokens[2];
2575 struct field *fdst, *fsrc;
2577 uint32_t dst_struct_id = 0, src_struct_id = 0;
2579 CHECK(n_tokens == 3, EINVAL);
2581 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2582 CHECK(fdst, EINVAL);
2583 CHECK(!fdst->var_size, EINVAL);
2585 /* ADD, ADD_HM, ADD_MH, ADD_HH. */
2586 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2588 CHECK(!fsrc->var_size, EINVAL);
2590 instr->type = INSTR_ALU_ADD;
2591 if (dst[0] == 'h' && src[0] != 'h')
2592 instr->type = INSTR_ALU_ADD_HM;
2593 if (dst[0] != 'h' && src[0] == 'h')
2594 instr->type = INSTR_ALU_ADD_MH;
2595 if (dst[0] == 'h' && src[0] == 'h')
2596 instr->type = INSTR_ALU_ADD_HH;
2598 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2599 instr->alu.dst.n_bits = fdst->n_bits;
2600 instr->alu.dst.offset = fdst->offset / 8;
2601 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2602 instr->alu.src.n_bits = fsrc->n_bits;
2603 instr->alu.src.offset = fsrc->offset / 8;
2607 /* ADD_MI, ADD_HI. */
2608 src_val = strtoull(src, &src, 0);
2609 CHECK(!src[0], EINVAL);
2611 instr->type = INSTR_ALU_ADD_MI;
2613 instr->type = INSTR_ALU_ADD_HI;
2615 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2616 instr->alu.dst.n_bits = fdst->n_bits;
2617 instr->alu.dst.offset = fdst->offset / 8;
2618 instr->alu.src_val = src_val;
2623 instr_alu_sub_translate(struct rte_swx_pipeline *p,
2624 struct action *action,
2627 struct instruction *instr,
2628 struct instruction_data *data __rte_unused)
2630 char *dst = tokens[1], *src = tokens[2];
2631 struct field *fdst, *fsrc;
2633 uint32_t dst_struct_id = 0, src_struct_id = 0;
2635 CHECK(n_tokens == 3, EINVAL);
2637 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2638 CHECK(fdst, EINVAL);
2639 CHECK(!fdst->var_size, EINVAL);
2641 /* SUB, SUB_HM, SUB_MH, SUB_HH. */
2642 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2644 CHECK(!fsrc->var_size, EINVAL);
2646 instr->type = INSTR_ALU_SUB;
2647 if (dst[0] == 'h' && src[0] != 'h')
2648 instr->type = INSTR_ALU_SUB_HM;
2649 if (dst[0] != 'h' && src[0] == 'h')
2650 instr->type = INSTR_ALU_SUB_MH;
2651 if (dst[0] == 'h' && src[0] == 'h')
2652 instr->type = INSTR_ALU_SUB_HH;
2654 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2655 instr->alu.dst.n_bits = fdst->n_bits;
2656 instr->alu.dst.offset = fdst->offset / 8;
2657 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2658 instr->alu.src.n_bits = fsrc->n_bits;
2659 instr->alu.src.offset = fsrc->offset / 8;
2663 /* SUB_MI, SUB_HI. */
2664 src_val = strtoull(src, &src, 0);
2665 CHECK(!src[0], EINVAL);
2667 instr->type = INSTR_ALU_SUB_MI;
2669 instr->type = INSTR_ALU_SUB_HI;
2671 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2672 instr->alu.dst.n_bits = fdst->n_bits;
2673 instr->alu.dst.offset = fdst->offset / 8;
2674 instr->alu.src_val = src_val;
2679 instr_alu_ckadd_translate(struct rte_swx_pipeline *p,
2680 struct action *action __rte_unused,
2683 struct instruction *instr,
2684 struct instruction_data *data __rte_unused)
2686 char *dst = tokens[1], *src = tokens[2];
2687 struct header *hdst, *hsrc;
2688 struct field *fdst, *fsrc;
2690 CHECK(n_tokens == 3, EINVAL);
2692 fdst = header_field_parse(p, dst, &hdst);
2693 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
2694 CHECK(!fdst->var_size, EINVAL);
2697 fsrc = header_field_parse(p, src, &hsrc);
2699 CHECK(!fsrc->var_size, EINVAL);
2701 instr->type = INSTR_ALU_CKADD_FIELD;
2702 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2703 instr->alu.dst.n_bits = fdst->n_bits;
2704 instr->alu.dst.offset = fdst->offset / 8;
2705 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2706 instr->alu.src.n_bits = fsrc->n_bits;
2707 instr->alu.src.offset = fsrc->offset / 8;
2711 /* CKADD_STRUCT, CKADD_STRUCT20. */
2712 hsrc = header_parse(p, src);
2713 CHECK(hsrc, EINVAL);
2714 CHECK(!hsrc->st->var_size, EINVAL);
2716 instr->type = INSTR_ALU_CKADD_STRUCT;
2717 if ((hsrc->st->n_bits / 8) == 20)
2718 instr->type = INSTR_ALU_CKADD_STRUCT20;
2720 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2721 instr->alu.dst.n_bits = fdst->n_bits;
2722 instr->alu.dst.offset = fdst->offset / 8;
2723 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2724 instr->alu.src.n_bits = hsrc->st->n_bits;
2725 instr->alu.src.offset = 0; /* Unused. */
2730 instr_alu_cksub_translate(struct rte_swx_pipeline *p,
2731 struct action *action __rte_unused,
2734 struct instruction *instr,
2735 struct instruction_data *data __rte_unused)
2737 char *dst = tokens[1], *src = tokens[2];
2738 struct header *hdst, *hsrc;
2739 struct field *fdst, *fsrc;
2741 CHECK(n_tokens == 3, EINVAL);
2743 fdst = header_field_parse(p, dst, &hdst);
2744 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
2745 CHECK(!fdst->var_size, EINVAL);
2747 fsrc = header_field_parse(p, src, &hsrc);
2748 CHECK(fsrc, EINVAL);
2749 CHECK(!fsrc->var_size, EINVAL);
2751 instr->type = INSTR_ALU_CKSUB_FIELD;
2752 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2753 instr->alu.dst.n_bits = fdst->n_bits;
2754 instr->alu.dst.offset = fdst->offset / 8;
2755 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2756 instr->alu.src.n_bits = fsrc->n_bits;
2757 instr->alu.src.offset = fsrc->offset / 8;
2762 instr_alu_shl_translate(struct rte_swx_pipeline *p,
2763 struct action *action,
2766 struct instruction *instr,
2767 struct instruction_data *data __rte_unused)
2769 char *dst = tokens[1], *src = tokens[2];
2770 struct field *fdst, *fsrc;
2772 uint32_t dst_struct_id = 0, src_struct_id = 0;
2774 CHECK(n_tokens == 3, EINVAL);
2776 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2777 CHECK(fdst, EINVAL);
2778 CHECK(!fdst->var_size, EINVAL);
2780 /* SHL, SHL_HM, SHL_MH, SHL_HH. */
2781 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2783 CHECK(!fsrc->var_size, EINVAL);
2785 instr->type = INSTR_ALU_SHL;
2786 if (dst[0] == 'h' && src[0] != 'h')
2787 instr->type = INSTR_ALU_SHL_HM;
2788 if (dst[0] != 'h' && src[0] == 'h')
2789 instr->type = INSTR_ALU_SHL_MH;
2790 if (dst[0] == 'h' && src[0] == 'h')
2791 instr->type = INSTR_ALU_SHL_HH;
2793 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2794 instr->alu.dst.n_bits = fdst->n_bits;
2795 instr->alu.dst.offset = fdst->offset / 8;
2796 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2797 instr->alu.src.n_bits = fsrc->n_bits;
2798 instr->alu.src.offset = fsrc->offset / 8;
2802 /* SHL_MI, SHL_HI. */
2803 src_val = strtoull(src, &src, 0);
2804 CHECK(!src[0], EINVAL);
2806 instr->type = INSTR_ALU_SHL_MI;
2808 instr->type = INSTR_ALU_SHL_HI;
2810 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2811 instr->alu.dst.n_bits = fdst->n_bits;
2812 instr->alu.dst.offset = fdst->offset / 8;
2813 instr->alu.src_val = src_val;
2818 instr_alu_shr_translate(struct rte_swx_pipeline *p,
2819 struct action *action,
2822 struct instruction *instr,
2823 struct instruction_data *data __rte_unused)
2825 char *dst = tokens[1], *src = tokens[2];
2826 struct field *fdst, *fsrc;
2828 uint32_t dst_struct_id = 0, src_struct_id = 0;
2830 CHECK(n_tokens == 3, EINVAL);
2832 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2833 CHECK(fdst, EINVAL);
2834 CHECK(!fdst->var_size, EINVAL);
2836 /* SHR, SHR_HM, SHR_MH, SHR_HH. */
2837 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2839 CHECK(!fsrc->var_size, EINVAL);
2841 instr->type = INSTR_ALU_SHR;
2842 if (dst[0] == 'h' && src[0] != 'h')
2843 instr->type = INSTR_ALU_SHR_HM;
2844 if (dst[0] != 'h' && src[0] == 'h')
2845 instr->type = INSTR_ALU_SHR_MH;
2846 if (dst[0] == 'h' && src[0] == 'h')
2847 instr->type = INSTR_ALU_SHR_HH;
2849 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2850 instr->alu.dst.n_bits = fdst->n_bits;
2851 instr->alu.dst.offset = fdst->offset / 8;
2852 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2853 instr->alu.src.n_bits = fsrc->n_bits;
2854 instr->alu.src.offset = fsrc->offset / 8;
2858 /* SHR_MI, SHR_HI. */
2859 src_val = strtoull(src, &src, 0);
2860 CHECK(!src[0], EINVAL);
2862 instr->type = INSTR_ALU_SHR_MI;
2864 instr->type = INSTR_ALU_SHR_HI;
2866 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2867 instr->alu.dst.n_bits = fdst->n_bits;
2868 instr->alu.dst.offset = fdst->offset / 8;
2869 instr->alu.src_val = src_val;
2874 instr_alu_and_translate(struct rte_swx_pipeline *p,
2875 struct action *action,
2878 struct instruction *instr,
2879 struct instruction_data *data __rte_unused)
2881 char *dst = tokens[1], *src = tokens[2];
2882 struct field *fdst, *fsrc;
2884 uint32_t dst_struct_id = 0, src_struct_id = 0;
2886 CHECK(n_tokens == 3, EINVAL);
2888 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2889 CHECK(fdst, EINVAL);
2890 CHECK(!fdst->var_size, EINVAL);
2892 /* AND, AND_MH, AND_HM, AND_HH. */
2893 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2895 CHECK(!fsrc->var_size, EINVAL);
2897 instr->type = INSTR_ALU_AND;
2898 if (dst[0] != 'h' && src[0] == 'h')
2899 instr->type = INSTR_ALU_AND_MH;
2900 if (dst[0] == 'h' && src[0] != 'h')
2901 instr->type = INSTR_ALU_AND_HM;
2902 if (dst[0] == 'h' && src[0] == 'h')
2903 instr->type = INSTR_ALU_AND_HH;
2905 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2906 instr->alu.dst.n_bits = fdst->n_bits;
2907 instr->alu.dst.offset = fdst->offset / 8;
2908 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2909 instr->alu.src.n_bits = fsrc->n_bits;
2910 instr->alu.src.offset = fsrc->offset / 8;
2915 src_val = strtoull(src, &src, 0);
2916 CHECK(!src[0], EINVAL);
2919 src_val = hton64(src_val) >> (64 - fdst->n_bits);
2921 instr->type = INSTR_ALU_AND_I;
2922 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2923 instr->alu.dst.n_bits = fdst->n_bits;
2924 instr->alu.dst.offset = fdst->offset / 8;
2925 instr->alu.src_val = src_val;
2930 instr_alu_or_translate(struct rte_swx_pipeline *p,
2931 struct action *action,
2934 struct instruction *instr,
2935 struct instruction_data *data __rte_unused)
2937 char *dst = tokens[1], *src = tokens[2];
2938 struct field *fdst, *fsrc;
2940 uint32_t dst_struct_id = 0, src_struct_id = 0;
2942 CHECK(n_tokens == 3, EINVAL);
2944 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2945 CHECK(fdst, EINVAL);
2946 CHECK(!fdst->var_size, EINVAL);
2948 /* OR, OR_MH, OR_HM, OR_HH. */
2949 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2951 CHECK(!fsrc->var_size, EINVAL);
2953 instr->type = INSTR_ALU_OR;
2954 if (dst[0] != 'h' && src[0] == 'h')
2955 instr->type = INSTR_ALU_OR_MH;
2956 if (dst[0] == 'h' && src[0] != 'h')
2957 instr->type = INSTR_ALU_OR_HM;
2958 if (dst[0] == 'h' && src[0] == 'h')
2959 instr->type = INSTR_ALU_OR_HH;
2961 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2962 instr->alu.dst.n_bits = fdst->n_bits;
2963 instr->alu.dst.offset = fdst->offset / 8;
2964 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2965 instr->alu.src.n_bits = fsrc->n_bits;
2966 instr->alu.src.offset = fsrc->offset / 8;
2971 src_val = strtoull(src, &src, 0);
2972 CHECK(!src[0], EINVAL);
2975 src_val = hton64(src_val) >> (64 - fdst->n_bits);
2977 instr->type = INSTR_ALU_OR_I;
2978 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2979 instr->alu.dst.n_bits = fdst->n_bits;
2980 instr->alu.dst.offset = fdst->offset / 8;
2981 instr->alu.src_val = src_val;
2986 instr_alu_xor_translate(struct rte_swx_pipeline *p,
2987 struct action *action,
2990 struct instruction *instr,
2991 struct instruction_data *data __rte_unused)
2993 char *dst = tokens[1], *src = tokens[2];
2994 struct field *fdst, *fsrc;
2996 uint32_t dst_struct_id = 0, src_struct_id = 0;
2998 CHECK(n_tokens == 3, EINVAL);
3000 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3001 CHECK(fdst, EINVAL);
3002 CHECK(!fdst->var_size, EINVAL);
3004 /* XOR, XOR_MH, XOR_HM, XOR_HH. */
3005 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3007 CHECK(!fsrc->var_size, EINVAL);
3009 instr->type = INSTR_ALU_XOR;
3010 if (dst[0] != 'h' && src[0] == 'h')
3011 instr->type = INSTR_ALU_XOR_MH;
3012 if (dst[0] == 'h' && src[0] != 'h')
3013 instr->type = INSTR_ALU_XOR_HM;
3014 if (dst[0] == 'h' && src[0] == 'h')
3015 instr->type = INSTR_ALU_XOR_HH;
3017 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3018 instr->alu.dst.n_bits = fdst->n_bits;
3019 instr->alu.dst.offset = fdst->offset / 8;
3020 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3021 instr->alu.src.n_bits = fsrc->n_bits;
3022 instr->alu.src.offset = fsrc->offset / 8;
3027 src_val = strtoull(src, &src, 0);
3028 CHECK(!src[0], EINVAL);
3031 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3033 instr->type = INSTR_ALU_XOR_I;
3034 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3035 instr->alu.dst.n_bits = fdst->n_bits;
3036 instr->alu.dst.offset = fdst->offset / 8;
3037 instr->alu.src_val = src_val;
3042 instr_alu_add_exec(struct rte_swx_pipeline *p)
3044 struct thread *t = &p->threads[p->thread_id];
3045 struct instruction *ip = t->ip;
3048 __instr_alu_add_exec(p, t, ip);
3055 instr_alu_add_mh_exec(struct rte_swx_pipeline *p)
3057 struct thread *t = &p->threads[p->thread_id];
3058 struct instruction *ip = t->ip;
3061 __instr_alu_add_mh_exec(p, t, ip);
3068 instr_alu_add_hm_exec(struct rte_swx_pipeline *p)
3070 struct thread *t = &p->threads[p->thread_id];
3071 struct instruction *ip = t->ip;
3074 __instr_alu_add_hm_exec(p, t, ip);
3081 instr_alu_add_hh_exec(struct rte_swx_pipeline *p)
3083 struct thread *t = &p->threads[p->thread_id];
3084 struct instruction *ip = t->ip;
3087 __instr_alu_add_hh_exec(p, t, ip);
3094 instr_alu_add_mi_exec(struct rte_swx_pipeline *p)
3096 struct thread *t = &p->threads[p->thread_id];
3097 struct instruction *ip = t->ip;
3100 __instr_alu_add_mi_exec(p, t, ip);
3107 instr_alu_add_hi_exec(struct rte_swx_pipeline *p)
3109 struct thread *t = &p->threads[p->thread_id];
3110 struct instruction *ip = t->ip;
3113 __instr_alu_add_hi_exec(p, t, ip);
3120 instr_alu_sub_exec(struct rte_swx_pipeline *p)
3122 struct thread *t = &p->threads[p->thread_id];
3123 struct instruction *ip = t->ip;
3126 __instr_alu_sub_exec(p, t, ip);
3133 instr_alu_sub_mh_exec(struct rte_swx_pipeline *p)
3135 struct thread *t = &p->threads[p->thread_id];
3136 struct instruction *ip = t->ip;
3139 __instr_alu_sub_mh_exec(p, t, ip);
3146 instr_alu_sub_hm_exec(struct rte_swx_pipeline *p)
3148 struct thread *t = &p->threads[p->thread_id];
3149 struct instruction *ip = t->ip;
3152 __instr_alu_sub_hm_exec(p, t, ip);
3159 instr_alu_sub_hh_exec(struct rte_swx_pipeline *p)
3161 struct thread *t = &p->threads[p->thread_id];
3162 struct instruction *ip = t->ip;
3165 __instr_alu_sub_hh_exec(p, t, ip);
3172 instr_alu_sub_mi_exec(struct rte_swx_pipeline *p)
3174 struct thread *t = &p->threads[p->thread_id];
3175 struct instruction *ip = t->ip;
3178 __instr_alu_sub_mi_exec(p, t, ip);
3185 instr_alu_sub_hi_exec(struct rte_swx_pipeline *p)
3187 struct thread *t = &p->threads[p->thread_id];
3188 struct instruction *ip = t->ip;
3191 __instr_alu_sub_hi_exec(p, t, ip);
3198 instr_alu_shl_exec(struct rte_swx_pipeline *p)
3200 struct thread *t = &p->threads[p->thread_id];
3201 struct instruction *ip = t->ip;
3204 __instr_alu_shl_exec(p, t, ip);
3211 instr_alu_shl_mh_exec(struct rte_swx_pipeline *p)
3213 struct thread *t = &p->threads[p->thread_id];
3214 struct instruction *ip = t->ip;
3217 __instr_alu_shl_mh_exec(p, t, ip);
3224 instr_alu_shl_hm_exec(struct rte_swx_pipeline *p)
3226 struct thread *t = &p->threads[p->thread_id];
3227 struct instruction *ip = t->ip;
3230 __instr_alu_shl_hm_exec(p, t, ip);
3237 instr_alu_shl_hh_exec(struct rte_swx_pipeline *p)
3239 struct thread *t = &p->threads[p->thread_id];
3240 struct instruction *ip = t->ip;
3243 __instr_alu_shl_hh_exec(p, t, ip);
3250 instr_alu_shl_mi_exec(struct rte_swx_pipeline *p)
3252 struct thread *t = &p->threads[p->thread_id];
3253 struct instruction *ip = t->ip;
3256 __instr_alu_shl_mi_exec(p, t, ip);
3263 instr_alu_shl_hi_exec(struct rte_swx_pipeline *p)
3265 struct thread *t = &p->threads[p->thread_id];
3266 struct instruction *ip = t->ip;
3269 __instr_alu_shl_hi_exec(p, t, ip);
3276 instr_alu_shr_exec(struct rte_swx_pipeline *p)
3278 struct thread *t = &p->threads[p->thread_id];
3279 struct instruction *ip = t->ip;
3282 __instr_alu_shr_exec(p, t, ip);
3289 instr_alu_shr_mh_exec(struct rte_swx_pipeline *p)
3291 struct thread *t = &p->threads[p->thread_id];
3292 struct instruction *ip = t->ip;
3295 __instr_alu_shr_mh_exec(p, t, ip);
3302 instr_alu_shr_hm_exec(struct rte_swx_pipeline *p)
3304 struct thread *t = &p->threads[p->thread_id];
3305 struct instruction *ip = t->ip;
3308 __instr_alu_shr_hm_exec(p, t, ip);
3315 instr_alu_shr_hh_exec(struct rte_swx_pipeline *p)
3317 struct thread *t = &p->threads[p->thread_id];
3318 struct instruction *ip = t->ip;
3321 __instr_alu_shr_hh_exec(p, t, ip);
3328 instr_alu_shr_mi_exec(struct rte_swx_pipeline *p)
3330 struct thread *t = &p->threads[p->thread_id];
3331 struct instruction *ip = t->ip;
3334 __instr_alu_shr_mi_exec(p, t, ip);
3341 instr_alu_shr_hi_exec(struct rte_swx_pipeline *p)
3343 struct thread *t = &p->threads[p->thread_id];
3344 struct instruction *ip = t->ip;
3347 __instr_alu_shr_hi_exec(p, t, ip);
3354 instr_alu_and_exec(struct rte_swx_pipeline *p)
3356 struct thread *t = &p->threads[p->thread_id];
3357 struct instruction *ip = t->ip;
3360 __instr_alu_and_exec(p, t, ip);
3367 instr_alu_and_mh_exec(struct rte_swx_pipeline *p)
3369 struct thread *t = &p->threads[p->thread_id];
3370 struct instruction *ip = t->ip;
3373 __instr_alu_and_mh_exec(p, t, ip);
3380 instr_alu_and_hm_exec(struct rte_swx_pipeline *p)
3382 struct thread *t = &p->threads[p->thread_id];
3383 struct instruction *ip = t->ip;
3386 __instr_alu_and_hm_exec(p, t, ip);
3393 instr_alu_and_hh_exec(struct rte_swx_pipeline *p)
3395 struct thread *t = &p->threads[p->thread_id];
3396 struct instruction *ip = t->ip;
3399 __instr_alu_and_hh_exec(p, t, ip);
3406 instr_alu_and_i_exec(struct rte_swx_pipeline *p)
3408 struct thread *t = &p->threads[p->thread_id];
3409 struct instruction *ip = t->ip;
3412 __instr_alu_and_i_exec(p, t, ip);
3419 instr_alu_or_exec(struct rte_swx_pipeline *p)
3421 struct thread *t = &p->threads[p->thread_id];
3422 struct instruction *ip = t->ip;
3425 __instr_alu_or_exec(p, t, ip);
3432 instr_alu_or_mh_exec(struct rte_swx_pipeline *p)
3434 struct thread *t = &p->threads[p->thread_id];
3435 struct instruction *ip = t->ip;
3438 __instr_alu_or_mh_exec(p, t, ip);
3445 instr_alu_or_hm_exec(struct rte_swx_pipeline *p)
3447 struct thread *t = &p->threads[p->thread_id];
3448 struct instruction *ip = t->ip;
3451 __instr_alu_or_hm_exec(p, t, ip);
3458 instr_alu_or_hh_exec(struct rte_swx_pipeline *p)
3460 struct thread *t = &p->threads[p->thread_id];
3461 struct instruction *ip = t->ip;
3464 __instr_alu_or_hh_exec(p, t, ip);
3471 instr_alu_or_i_exec(struct rte_swx_pipeline *p)
3473 struct thread *t = &p->threads[p->thread_id];
3474 struct instruction *ip = t->ip;
3477 __instr_alu_or_i_exec(p, t, ip);
3484 instr_alu_xor_exec(struct rte_swx_pipeline *p)
3486 struct thread *t = &p->threads[p->thread_id];
3487 struct instruction *ip = t->ip;
3490 __instr_alu_xor_exec(p, t, ip);
3497 instr_alu_xor_mh_exec(struct rte_swx_pipeline *p)
3499 struct thread *t = &p->threads[p->thread_id];
3500 struct instruction *ip = t->ip;
3503 __instr_alu_xor_mh_exec(p, t, ip);
3510 instr_alu_xor_hm_exec(struct rte_swx_pipeline *p)
3512 struct thread *t = &p->threads[p->thread_id];
3513 struct instruction *ip = t->ip;
3516 __instr_alu_xor_hm_exec(p, t, ip);
3523 instr_alu_xor_hh_exec(struct rte_swx_pipeline *p)
3525 struct thread *t = &p->threads[p->thread_id];
3526 struct instruction *ip = t->ip;
3529 __instr_alu_xor_hh_exec(p, t, ip);
3536 instr_alu_xor_i_exec(struct rte_swx_pipeline *p)
3538 struct thread *t = &p->threads[p->thread_id];
3539 struct instruction *ip = t->ip;
3542 __instr_alu_xor_i_exec(p, t, ip);
3549 instr_alu_ckadd_field_exec(struct rte_swx_pipeline *p)
3551 struct thread *t = &p->threads[p->thread_id];
3552 struct instruction *ip = t->ip;
3555 __instr_alu_ckadd_field_exec(p, t, ip);
3562 instr_alu_cksub_field_exec(struct rte_swx_pipeline *p)
3564 struct thread *t = &p->threads[p->thread_id];
3565 struct instruction *ip = t->ip;
3568 __instr_alu_cksub_field_exec(p, t, ip);
3575 instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline *p)
3577 struct thread *t = &p->threads[p->thread_id];
3578 struct instruction *ip = t->ip;
3581 __instr_alu_ckadd_struct20_exec(p, t, ip);
3588 instr_alu_ckadd_struct_exec(struct rte_swx_pipeline *p)
3590 struct thread *t = &p->threads[p->thread_id];
3591 struct instruction *ip = t->ip;
3594 __instr_alu_ckadd_struct_exec(p, t, ip);
3603 static struct regarray *
3604 regarray_find(struct rte_swx_pipeline *p, const char *name);
3607 instr_regprefetch_translate(struct rte_swx_pipeline *p,
3608 struct action *action,
3611 struct instruction *instr,
3612 struct instruction_data *data __rte_unused)
3614 char *regarray = tokens[1], *idx = tokens[2];
3617 uint32_t idx_struct_id, idx_val;
3619 CHECK(n_tokens == 3, EINVAL);
3621 r = regarray_find(p, regarray);
3624 /* REGPREFETCH_RH, REGPREFETCH_RM. */
3625 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
3627 CHECK(!fidx->var_size, EINVAL);
3629 instr->type = INSTR_REGPREFETCH_RM;
3631 instr->type = INSTR_REGPREFETCH_RH;
3633 instr->regarray.regarray_id = r->id;
3634 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
3635 instr->regarray.idx.n_bits = fidx->n_bits;
3636 instr->regarray.idx.offset = fidx->offset / 8;
3637 instr->regarray.dstsrc_val = 0; /* Unused. */
3641 /* REGPREFETCH_RI. */
3642 idx_val = strtoul(idx, &idx, 0);
3643 CHECK(!idx[0], EINVAL);
3645 instr->type = INSTR_REGPREFETCH_RI;
3646 instr->regarray.regarray_id = r->id;
3647 instr->regarray.idx_val = idx_val;
3648 instr->regarray.dstsrc_val = 0; /* Unused. */
3653 instr_regrd_translate(struct rte_swx_pipeline *p,
3654 struct action *action,
3657 struct instruction *instr,
3658 struct instruction_data *data __rte_unused)
3660 char *dst = tokens[1], *regarray = tokens[2], *idx = tokens[3];
3662 struct field *fdst, *fidx;
3663 uint32_t dst_struct_id, idx_struct_id, idx_val;
3665 CHECK(n_tokens == 4, EINVAL);
3667 r = regarray_find(p, regarray);
3670 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3671 CHECK(fdst, EINVAL);
3672 CHECK(!fdst->var_size, EINVAL);
3674 /* REGRD_HRH, REGRD_HRM, REGRD_MRH, REGRD_MRM. */
3675 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
3677 CHECK(!fidx->var_size, EINVAL);
3679 instr->type = INSTR_REGRD_MRM;
3680 if (dst[0] == 'h' && idx[0] != 'h')
3681 instr->type = INSTR_REGRD_HRM;
3682 if (dst[0] != 'h' && idx[0] == 'h')
3683 instr->type = INSTR_REGRD_MRH;
3684 if (dst[0] == 'h' && idx[0] == 'h')
3685 instr->type = INSTR_REGRD_HRH;
3687 instr->regarray.regarray_id = r->id;
3688 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
3689 instr->regarray.idx.n_bits = fidx->n_bits;
3690 instr->regarray.idx.offset = fidx->offset / 8;
3691 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
3692 instr->regarray.dstsrc.n_bits = fdst->n_bits;
3693 instr->regarray.dstsrc.offset = fdst->offset / 8;
3697 /* REGRD_MRI, REGRD_HRI. */
3698 idx_val = strtoul(idx, &idx, 0);
3699 CHECK(!idx[0], EINVAL);
3701 instr->type = INSTR_REGRD_MRI;
3703 instr->type = INSTR_REGRD_HRI;
3705 instr->regarray.regarray_id = r->id;
3706 instr->regarray.idx_val = idx_val;
3707 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
3708 instr->regarray.dstsrc.n_bits = fdst->n_bits;
3709 instr->regarray.dstsrc.offset = fdst->offset / 8;
3714 instr_regwr_translate(struct rte_swx_pipeline *p,
3715 struct action *action,
3718 struct instruction *instr,
3719 struct instruction_data *data __rte_unused)
3721 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
3723 struct field *fidx, *fsrc;
3725 uint32_t idx_struct_id, idx_val, src_struct_id;
3727 CHECK(n_tokens == 4, EINVAL);
3729 r = regarray_find(p, regarray);
3732 /* REGWR_RHH, REGWR_RHM, REGWR_RMH, REGWR_RMM. */
3733 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
3734 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3736 CHECK(!fidx->var_size, EINVAL);
3737 CHECK(!fsrc->var_size, EINVAL);
3739 instr->type = INSTR_REGWR_RMM;
3740 if (idx[0] == 'h' && src[0] != 'h')
3741 instr->type = INSTR_REGWR_RHM;
3742 if (idx[0] != 'h' && src[0] == 'h')
3743 instr->type = INSTR_REGWR_RMH;
3744 if (idx[0] == 'h' && src[0] == 'h')
3745 instr->type = INSTR_REGWR_RHH;
3747 instr->regarray.regarray_id = r->id;
3748 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
3749 instr->regarray.idx.n_bits = fidx->n_bits;
3750 instr->regarray.idx.offset = fidx->offset / 8;
3751 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
3752 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
3753 instr->regarray.dstsrc.offset = fsrc->offset / 8;
3757 /* REGWR_RHI, REGWR_RMI. */
3758 if (fidx && !fsrc) {
3759 CHECK(!fidx->var_size, EINVAL);
3761 src_val = strtoull(src, &src, 0);
3762 CHECK(!src[0], EINVAL);
3764 instr->type = INSTR_REGWR_RMI;
3766 instr->type = INSTR_REGWR_RHI;
3768 instr->regarray.regarray_id = r->id;
3769 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
3770 instr->regarray.idx.n_bits = fidx->n_bits;
3771 instr->regarray.idx.offset = fidx->offset / 8;
3772 instr->regarray.dstsrc_val = src_val;
3776 /* REGWR_RIH, REGWR_RIM. */
3777 if (!fidx && fsrc) {
3778 idx_val = strtoul(idx, &idx, 0);
3779 CHECK(!idx[0], EINVAL);
3781 CHECK(!fsrc->var_size, EINVAL);
3783 instr->type = INSTR_REGWR_RIM;
3785 instr->type = INSTR_REGWR_RIH;
3787 instr->regarray.regarray_id = r->id;
3788 instr->regarray.idx_val = idx_val;
3789 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
3790 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
3791 instr->regarray.dstsrc.offset = fsrc->offset / 8;
3796 src_val = strtoull(src, &src, 0);
3797 CHECK(!src[0], EINVAL);
3799 idx_val = strtoul(idx, &idx, 0);
3800 CHECK(!idx[0], EINVAL);
3802 instr->type = INSTR_REGWR_RII;
3803 instr->regarray.idx_val = idx_val;
3804 instr->regarray.dstsrc_val = src_val;
3810 instr_regadd_translate(struct rte_swx_pipeline *p,
3811 struct action *action,
3814 struct instruction *instr,
3815 struct instruction_data *data __rte_unused)
3817 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
3819 struct field *fidx, *fsrc;
3821 uint32_t idx_struct_id, idx_val, src_struct_id;
3823 CHECK(n_tokens == 4, EINVAL);
3825 r = regarray_find(p, regarray);
3828 /* REGADD_RHH, REGADD_RHM, REGADD_RMH, REGADD_RMM. */
3829 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
3830 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3832 CHECK(!fidx->var_size, EINVAL);
3833 CHECK(!fsrc->var_size, EINVAL);
3835 instr->type = INSTR_REGADD_RMM;
3836 if (idx[0] == 'h' && src[0] != 'h')
3837 instr->type = INSTR_REGADD_RHM;
3838 if (idx[0] != 'h' && src[0] == 'h')
3839 instr->type = INSTR_REGADD_RMH;
3840 if (idx[0] == 'h' && src[0] == 'h')
3841 instr->type = INSTR_REGADD_RHH;
3843 instr->regarray.regarray_id = r->id;
3844 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
3845 instr->regarray.idx.n_bits = fidx->n_bits;
3846 instr->regarray.idx.offset = fidx->offset / 8;
3847 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
3848 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
3849 instr->regarray.dstsrc.offset = fsrc->offset / 8;
3853 /* REGADD_RHI, REGADD_RMI. */
3854 if (fidx && !fsrc) {
3855 CHECK(!fidx->var_size, EINVAL);
3857 src_val = strtoull(src, &src, 0);
3858 CHECK(!src[0], EINVAL);
3860 instr->type = INSTR_REGADD_RMI;
3862 instr->type = INSTR_REGADD_RHI;
3864 instr->regarray.regarray_id = r->id;
3865 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
3866 instr->regarray.idx.n_bits = fidx->n_bits;
3867 instr->regarray.idx.offset = fidx->offset / 8;
3868 instr->regarray.dstsrc_val = src_val;
3872 /* REGADD_RIH, REGADD_RIM. */
3873 if (!fidx && fsrc) {
3874 idx_val = strtoul(idx, &idx, 0);
3875 CHECK(!idx[0], EINVAL);
3877 CHECK(!fsrc->var_size, EINVAL);
3879 instr->type = INSTR_REGADD_RIM;
3881 instr->type = INSTR_REGADD_RIH;
3883 instr->regarray.regarray_id = r->id;
3884 instr->regarray.idx_val = idx_val;
3885 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
3886 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
3887 instr->regarray.dstsrc.offset = fsrc->offset / 8;
3892 src_val = strtoull(src, &src, 0);
3893 CHECK(!src[0], EINVAL);
3895 idx_val = strtoul(idx, &idx, 0);
3896 CHECK(!idx[0], EINVAL);
3898 instr->type = INSTR_REGADD_RII;
3899 instr->regarray.idx_val = idx_val;
3900 instr->regarray.dstsrc_val = src_val;
3904 static inline uint64_t *
3905 instr_regarray_regarray(struct rte_swx_pipeline *p, struct instruction *ip)
3907 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
3911 static inline uint64_t
3912 instr_regarray_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
3914 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
3916 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
3917 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
3918 uint64_t idx64 = *idx64_ptr;
3919 uint64_t idx64_mask = UINT64_MAX >> (64 - ip->regarray.idx.n_bits);
3920 uint64_t idx = idx64 & idx64_mask & r->size_mask;
3925 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
3927 static inline uint64_t
3928 instr_regarray_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
3930 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
3932 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
3933 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
3934 uint64_t idx64 = *idx64_ptr;
3935 uint64_t idx = (ntoh64(idx64) >> (64 - ip->regarray.idx.n_bits)) & r->size_mask;
3942 #define instr_regarray_idx_nbo instr_regarray_idx_hbo
3946 static inline uint64_t
3947 instr_regarray_idx_imm(struct rte_swx_pipeline *p, struct instruction *ip)
3949 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
3951 uint64_t idx = ip->regarray.idx_val & r->size_mask;
3956 static inline uint64_t
3957 instr_regarray_src_hbo(struct thread *t, struct instruction *ip)
3959 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
3960 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
3961 uint64_t src64 = *src64_ptr;
3962 uint64_t src64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
3963 uint64_t src = src64 & src64_mask;
3968 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
3970 static inline uint64_t
3971 instr_regarray_src_nbo(struct thread *t, struct instruction *ip)
3973 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
3974 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
3975 uint64_t src64 = *src64_ptr;
3976 uint64_t src = ntoh64(src64) >> (64 - ip->regarray.dstsrc.n_bits);
3983 #define instr_regarray_src_nbo instr_regarray_src_hbo
3988 instr_regarray_dst_hbo_src_hbo_set(struct thread *t, struct instruction *ip, uint64_t src)
3990 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
3991 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
3992 uint64_t dst64 = *dst64_ptr;
3993 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
3995 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
3999 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4002 instr_regarray_dst_nbo_src_hbo_set(struct thread *t, struct instruction *ip, uint64_t src)
4004 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
4005 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
4006 uint64_t dst64 = *dst64_ptr;
4007 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
4009 src = hton64(src) >> (64 - ip->regarray.dstsrc.n_bits);
4010 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
4015 #define instr_regarray_dst_nbo_src_hbo_set instr_regarray_dst_hbo_src_hbo_set
4020 instr_regprefetch_rh_exec(struct rte_swx_pipeline *p)
4022 struct thread *t = &p->threads[p->thread_id];
4023 struct instruction *ip = t->ip;
4024 uint64_t *regarray, idx;
4026 TRACE("[Thread %2u] regprefetch (r[h])\n", p->thread_id);
4029 regarray = instr_regarray_regarray(p, ip);
4030 idx = instr_regarray_idx_nbo(p, t, ip);
4031 rte_prefetch0(®array[idx]);
4038 instr_regprefetch_rm_exec(struct rte_swx_pipeline *p)
4040 struct thread *t = &p->threads[p->thread_id];
4041 struct instruction *ip = t->ip;
4042 uint64_t *regarray, idx;
4044 TRACE("[Thread %2u] regprefetch (r[m])\n", p->thread_id);
4047 regarray = instr_regarray_regarray(p, ip);
4048 idx = instr_regarray_idx_hbo(p, t, ip);
4049 rte_prefetch0(®array[idx]);
4056 instr_regprefetch_ri_exec(struct rte_swx_pipeline *p)
4058 struct thread *t = &p->threads[p->thread_id];
4059 struct instruction *ip = t->ip;
4060 uint64_t *regarray, idx;
4062 TRACE("[Thread %2u] regprefetch (r[i])\n", p->thread_id);
4065 regarray = instr_regarray_regarray(p, ip);
4066 idx = instr_regarray_idx_imm(p, ip);
4067 rte_prefetch0(®array[idx]);
4074 instr_regrd_hrh_exec(struct rte_swx_pipeline *p)
4076 struct thread *t = &p->threads[p->thread_id];
4077 struct instruction *ip = t->ip;
4078 uint64_t *regarray, idx;
4080 TRACE("[Thread %2u] regrd (h = r[h])\n", p->thread_id);
4083 regarray = instr_regarray_regarray(p, ip);
4084 idx = instr_regarray_idx_nbo(p, t, ip);
4085 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
4092 instr_regrd_hrm_exec(struct rte_swx_pipeline *p)
4094 struct thread *t = &p->threads[p->thread_id];
4095 struct instruction *ip = t->ip;
4096 uint64_t *regarray, idx;
4098 TRACE("[Thread %2u] regrd (h = r[m])\n", p->thread_id);
4101 regarray = instr_regarray_regarray(p, ip);
4102 idx = instr_regarray_idx_hbo(p, t, ip);
4103 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
4110 instr_regrd_mrh_exec(struct rte_swx_pipeline *p)
4112 struct thread *t = &p->threads[p->thread_id];
4113 struct instruction *ip = t->ip;
4114 uint64_t *regarray, idx;
4116 TRACE("[Thread %2u] regrd (m = r[h])\n", p->thread_id);
4119 regarray = instr_regarray_regarray(p, ip);
4120 idx = instr_regarray_idx_nbo(p, t, ip);
4121 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
4128 instr_regrd_mrm_exec(struct rte_swx_pipeline *p)
4130 struct thread *t = &p->threads[p->thread_id];
4131 struct instruction *ip = t->ip;
4132 uint64_t *regarray, idx;
4135 regarray = instr_regarray_regarray(p, ip);
4136 idx = instr_regarray_idx_hbo(p, t, ip);
4137 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
4144 instr_regrd_hri_exec(struct rte_swx_pipeline *p)
4146 struct thread *t = &p->threads[p->thread_id];
4147 struct instruction *ip = t->ip;
4148 uint64_t *regarray, idx;
4150 TRACE("[Thread %2u] regrd (h = r[i])\n", p->thread_id);
4153 regarray = instr_regarray_regarray(p, ip);
4154 idx = instr_regarray_idx_imm(p, ip);
4155 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
4162 instr_regrd_mri_exec(struct rte_swx_pipeline *p)
4164 struct thread *t = &p->threads[p->thread_id];
4165 struct instruction *ip = t->ip;
4166 uint64_t *regarray, idx;
4168 TRACE("[Thread %2u] regrd (m = r[i])\n", p->thread_id);
4171 regarray = instr_regarray_regarray(p, ip);
4172 idx = instr_regarray_idx_imm(p, ip);
4173 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
4180 instr_regwr_rhh_exec(struct rte_swx_pipeline *p)
4182 struct thread *t = &p->threads[p->thread_id];
4183 struct instruction *ip = t->ip;
4184 uint64_t *regarray, idx, src;
4186 TRACE("[Thread %2u] regwr (r[h] = h)\n", p->thread_id);
4189 regarray = instr_regarray_regarray(p, ip);
4190 idx = instr_regarray_idx_nbo(p, t, ip);
4191 src = instr_regarray_src_nbo(t, ip);
4192 regarray[idx] = src;
4199 instr_regwr_rhm_exec(struct rte_swx_pipeline *p)
4201 struct thread *t = &p->threads[p->thread_id];
4202 struct instruction *ip = t->ip;
4203 uint64_t *regarray, idx, src;
4205 TRACE("[Thread %2u] regwr (r[h] = m)\n", p->thread_id);
4208 regarray = instr_regarray_regarray(p, ip);
4209 idx = instr_regarray_idx_nbo(p, t, ip);
4210 src = instr_regarray_src_hbo(t, ip);
4211 regarray[idx] = src;
4218 instr_regwr_rmh_exec(struct rte_swx_pipeline *p)
4220 struct thread *t = &p->threads[p->thread_id];
4221 struct instruction *ip = t->ip;
4222 uint64_t *regarray, idx, src;
4224 TRACE("[Thread %2u] regwr (r[m] = h)\n", p->thread_id);
4227 regarray = instr_regarray_regarray(p, ip);
4228 idx = instr_regarray_idx_hbo(p, t, ip);
4229 src = instr_regarray_src_nbo(t, ip);
4230 regarray[idx] = src;
4237 instr_regwr_rmm_exec(struct rte_swx_pipeline *p)
4239 struct thread *t = &p->threads[p->thread_id];
4240 struct instruction *ip = t->ip;
4241 uint64_t *regarray, idx, src;
4243 TRACE("[Thread %2u] regwr (r[m] = m)\n", p->thread_id);
4246 regarray = instr_regarray_regarray(p, ip);
4247 idx = instr_regarray_idx_hbo(p, t, ip);
4248 src = instr_regarray_src_hbo(t, ip);
4249 regarray[idx] = src;
4256 instr_regwr_rhi_exec(struct rte_swx_pipeline *p)
4258 struct thread *t = &p->threads[p->thread_id];
4259 struct instruction *ip = t->ip;
4260 uint64_t *regarray, idx, src;
4262 TRACE("[Thread %2u] regwr (r[h] = i)\n", p->thread_id);
4265 regarray = instr_regarray_regarray(p, ip);
4266 idx = instr_regarray_idx_nbo(p, t, ip);
4267 src = ip->regarray.dstsrc_val;
4268 regarray[idx] = src;
4275 instr_regwr_rmi_exec(struct rte_swx_pipeline *p)
4277 struct thread *t = &p->threads[p->thread_id];
4278 struct instruction *ip = t->ip;
4279 uint64_t *regarray, idx, src;
4281 TRACE("[Thread %2u] regwr (r[m] = i)\n", p->thread_id);
4284 regarray = instr_regarray_regarray(p, ip);
4285 idx = instr_regarray_idx_hbo(p, t, ip);
4286 src = ip->regarray.dstsrc_val;
4287 regarray[idx] = src;
4294 instr_regwr_rih_exec(struct rte_swx_pipeline *p)
4296 struct thread *t = &p->threads[p->thread_id];
4297 struct instruction *ip = t->ip;
4298 uint64_t *regarray, idx, src;
4300 TRACE("[Thread %2u] regwr (r[i] = h)\n", p->thread_id);
4303 regarray = instr_regarray_regarray(p, ip);
4304 idx = instr_regarray_idx_imm(p, ip);
4305 src = instr_regarray_src_nbo(t, ip);
4306 regarray[idx] = src;
4313 instr_regwr_rim_exec(struct rte_swx_pipeline *p)
4315 struct thread *t = &p->threads[p->thread_id];
4316 struct instruction *ip = t->ip;
4317 uint64_t *regarray, idx, src;
4319 TRACE("[Thread %2u] regwr (r[i] = m)\n", p->thread_id);
4322 regarray = instr_regarray_regarray(p, ip);
4323 idx = instr_regarray_idx_imm(p, ip);
4324 src = instr_regarray_src_hbo(t, ip);
4325 regarray[idx] = src;
4332 instr_regwr_rii_exec(struct rte_swx_pipeline *p)
4334 struct thread *t = &p->threads[p->thread_id];
4335 struct instruction *ip = t->ip;
4336 uint64_t *regarray, idx, src;
4338 TRACE("[Thread %2u] regwr (r[i] = i)\n", p->thread_id);
4341 regarray = instr_regarray_regarray(p, ip);
4342 idx = instr_regarray_idx_imm(p, ip);
4343 src = ip->regarray.dstsrc_val;
4344 regarray[idx] = src;
4351 instr_regadd_rhh_exec(struct rte_swx_pipeline *p)
4353 struct thread *t = &p->threads[p->thread_id];
4354 struct instruction *ip = t->ip;
4355 uint64_t *regarray, idx, src;
4357 TRACE("[Thread %2u] regadd (r[h] += h)\n", p->thread_id);
4360 regarray = instr_regarray_regarray(p, ip);
4361 idx = instr_regarray_idx_nbo(p, t, ip);
4362 src = instr_regarray_src_nbo(t, ip);
4363 regarray[idx] += src;
4370 instr_regadd_rhm_exec(struct rte_swx_pipeline *p)
4372 struct thread *t = &p->threads[p->thread_id];
4373 struct instruction *ip = t->ip;
4374 uint64_t *regarray, idx, src;
4376 TRACE("[Thread %2u] regadd (r[h] += m)\n", p->thread_id);
4379 regarray = instr_regarray_regarray(p, ip);
4380 idx = instr_regarray_idx_nbo(p, t, ip);
4381 src = instr_regarray_src_hbo(t, ip);
4382 regarray[idx] += src;
4389 instr_regadd_rmh_exec(struct rte_swx_pipeline *p)
4391 struct thread *t = &p->threads[p->thread_id];
4392 struct instruction *ip = t->ip;
4393 uint64_t *regarray, idx, src;
4395 TRACE("[Thread %2u] regadd (r[m] += h)\n", p->thread_id);
4398 regarray = instr_regarray_regarray(p, ip);
4399 idx = instr_regarray_idx_hbo(p, t, ip);
4400 src = instr_regarray_src_nbo(t, ip);
4401 regarray[idx] += src;
4408 instr_regadd_rmm_exec(struct rte_swx_pipeline *p)
4410 struct thread *t = &p->threads[p->thread_id];
4411 struct instruction *ip = t->ip;
4412 uint64_t *regarray, idx, src;
4414 TRACE("[Thread %2u] regadd (r[m] += m)\n", p->thread_id);
4417 regarray = instr_regarray_regarray(p, ip);
4418 idx = instr_regarray_idx_hbo(p, t, ip);
4419 src = instr_regarray_src_hbo(t, ip);
4420 regarray[idx] += src;
4427 instr_regadd_rhi_exec(struct rte_swx_pipeline *p)
4429 struct thread *t = &p->threads[p->thread_id];
4430 struct instruction *ip = t->ip;
4431 uint64_t *regarray, idx, src;
4433 TRACE("[Thread %2u] regadd (r[h] += i)\n", p->thread_id);
4436 regarray = instr_regarray_regarray(p, ip);
4437 idx = instr_regarray_idx_nbo(p, t, ip);
4438 src = ip->regarray.dstsrc_val;
4439 regarray[idx] += src;
4446 instr_regadd_rmi_exec(struct rte_swx_pipeline *p)
4448 struct thread *t = &p->threads[p->thread_id];
4449 struct instruction *ip = t->ip;
4450 uint64_t *regarray, idx, src;
4452 TRACE("[Thread %2u] regadd (r[m] += i)\n", p->thread_id);
4455 regarray = instr_regarray_regarray(p, ip);
4456 idx = instr_regarray_idx_hbo(p, t, ip);
4457 src = ip->regarray.dstsrc_val;
4458 regarray[idx] += src;
4465 instr_regadd_rih_exec(struct rte_swx_pipeline *p)
4467 struct thread *t = &p->threads[p->thread_id];
4468 struct instruction *ip = t->ip;
4469 uint64_t *regarray, idx, src;
4471 TRACE("[Thread %2u] regadd (r[i] += h)\n", p->thread_id);
4474 regarray = instr_regarray_regarray(p, ip);
4475 idx = instr_regarray_idx_imm(p, ip);
4476 src = instr_regarray_src_nbo(t, ip);
4477 regarray[idx] += src;
4484 instr_regadd_rim_exec(struct rte_swx_pipeline *p)
4486 struct thread *t = &p->threads[p->thread_id];
4487 struct instruction *ip = t->ip;
4488 uint64_t *regarray, idx, src;
4490 TRACE("[Thread %2u] regadd (r[i] += m)\n", p->thread_id);
4493 regarray = instr_regarray_regarray(p, ip);
4494 idx = instr_regarray_idx_imm(p, ip);
4495 src = instr_regarray_src_hbo(t, ip);
4496 regarray[idx] += src;
4503 instr_regadd_rii_exec(struct rte_swx_pipeline *p)
4505 struct thread *t = &p->threads[p->thread_id];
4506 struct instruction *ip = t->ip;
4507 uint64_t *regarray, idx, src;
4509 TRACE("[Thread %2u] regadd (r[i] += i)\n", p->thread_id);
4512 regarray = instr_regarray_regarray(p, ip);
4513 idx = instr_regarray_idx_imm(p, ip);
4514 src = ip->regarray.dstsrc_val;
4515 regarray[idx] += src;
4524 static struct metarray *
4525 metarray_find(struct rte_swx_pipeline *p, const char *name);
4528 instr_metprefetch_translate(struct rte_swx_pipeline *p,
4529 struct action *action,
4532 struct instruction *instr,
4533 struct instruction_data *data __rte_unused)
4535 char *metarray = tokens[1], *idx = tokens[2];
4538 uint32_t idx_struct_id, idx_val;
4540 CHECK(n_tokens == 3, EINVAL);
4542 m = metarray_find(p, metarray);
4545 /* METPREFETCH_H, METPREFETCH_M. */
4546 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4548 CHECK(!fidx->var_size, EINVAL);
4550 instr->type = INSTR_METPREFETCH_M;
4552 instr->type = INSTR_METPREFETCH_H;
4554 instr->meter.metarray_id = m->id;
4555 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4556 instr->meter.idx.n_bits = fidx->n_bits;
4557 instr->meter.idx.offset = fidx->offset / 8;
4561 /* METPREFETCH_I. */
4562 idx_val = strtoul(idx, &idx, 0);
4563 CHECK(!idx[0], EINVAL);
4565 instr->type = INSTR_METPREFETCH_I;
4566 instr->meter.metarray_id = m->id;
4567 instr->meter.idx_val = idx_val;
4572 instr_meter_translate(struct rte_swx_pipeline *p,
4573 struct action *action,
4576 struct instruction *instr,
4577 struct instruction_data *data __rte_unused)
4579 char *metarray = tokens[1], *idx = tokens[2], *length = tokens[3];
4580 char *color_in = tokens[4], *color_out = tokens[5];
4582 struct field *fidx, *flength, *fcin, *fcout;
4583 uint32_t idx_struct_id, length_struct_id;
4584 uint32_t color_in_struct_id, color_out_struct_id;
4586 CHECK(n_tokens == 6, EINVAL);
4588 m = metarray_find(p, metarray);
4591 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4593 flength = struct_field_parse(p, action, length, &length_struct_id);
4594 CHECK(flength, EINVAL);
4595 CHECK(!flength->var_size, EINVAL);
4597 fcin = struct_field_parse(p, action, color_in, &color_in_struct_id);
4599 fcout = struct_field_parse(p, NULL, color_out, &color_out_struct_id);
4600 CHECK(fcout, EINVAL);
4601 CHECK(!fcout->var_size, EINVAL);
4603 /* index = HMEFT, length = HMEFT, color_in = MEFT, color_out = MEF. */
4605 CHECK(!fidx->var_size, EINVAL);
4606 CHECK(!fcin->var_size, EINVAL);
4608 instr->type = INSTR_METER_MMM;
4609 if (idx[0] == 'h' && length[0] == 'h')
4610 instr->type = INSTR_METER_HHM;
4611 if (idx[0] == 'h' && length[0] != 'h')
4612 instr->type = INSTR_METER_HMM;
4613 if (idx[0] != 'h' && length[0] == 'h')
4614 instr->type = INSTR_METER_MHM;
4616 instr->meter.metarray_id = m->id;
4618 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4619 instr->meter.idx.n_bits = fidx->n_bits;
4620 instr->meter.idx.offset = fidx->offset / 8;
4622 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4623 instr->meter.length.n_bits = flength->n_bits;
4624 instr->meter.length.offset = flength->offset / 8;
4626 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
4627 instr->meter.color_in.n_bits = fcin->n_bits;
4628 instr->meter.color_in.offset = fcin->offset / 8;
4630 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4631 instr->meter.color_out.n_bits = fcout->n_bits;
4632 instr->meter.color_out.offset = fcout->offset / 8;
4637 /* index = HMEFT, length = HMEFT, color_in = I, color_out = MEF. */
4638 if (fidx && !fcin) {
4639 uint32_t color_in_val;
4641 CHECK(!fidx->var_size, EINVAL);
4643 color_in_val = strtoul(color_in, &color_in, 0);
4644 CHECK(!color_in[0], EINVAL);
4646 instr->type = INSTR_METER_MMI;
4647 if (idx[0] == 'h' && length[0] == 'h')
4648 instr->type = INSTR_METER_HHI;
4649 if (idx[0] == 'h' && length[0] != 'h')
4650 instr->type = INSTR_METER_HMI;
4651 if (idx[0] != 'h' && length[0] == 'h')
4652 instr->type = INSTR_METER_MHI;
4654 instr->meter.metarray_id = m->id;
4656 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4657 instr->meter.idx.n_bits = fidx->n_bits;
4658 instr->meter.idx.offset = fidx->offset / 8;
4660 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4661 instr->meter.length.n_bits = flength->n_bits;
4662 instr->meter.length.offset = flength->offset / 8;
4664 instr->meter.color_in_val = color_in_val;
4666 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4667 instr->meter.color_out.n_bits = fcout->n_bits;
4668 instr->meter.color_out.offset = fcout->offset / 8;
4673 /* index = I, length = HMEFT, color_in = MEFT, color_out = MEF. */
4674 if (!fidx && fcin) {
4677 idx_val = strtoul(idx, &idx, 0);
4678 CHECK(!idx[0], EINVAL);
4680 CHECK(!fcin->var_size, EINVAL);
4682 instr->type = INSTR_METER_IMM;
4683 if (length[0] == 'h')
4684 instr->type = INSTR_METER_IHM;
4686 instr->meter.metarray_id = m->id;
4688 instr->meter.idx_val = idx_val;
4690 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4691 instr->meter.length.n_bits = flength->n_bits;
4692 instr->meter.length.offset = flength->offset / 8;
4694 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
4695 instr->meter.color_in.n_bits = fcin->n_bits;
4696 instr->meter.color_in.offset = fcin->offset / 8;
4698 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4699 instr->meter.color_out.n_bits = fcout->n_bits;
4700 instr->meter.color_out.offset = fcout->offset / 8;
4705 /* index = I, length = HMEFT, color_in = I, color_out = MEF. */
4706 if (!fidx && !fcin) {
4707 uint32_t idx_val, color_in_val;
4709 idx_val = strtoul(idx, &idx, 0);
4710 CHECK(!idx[0], EINVAL);
4712 color_in_val = strtoul(color_in, &color_in, 0);
4713 CHECK(!color_in[0], EINVAL);
4715 instr->type = INSTR_METER_IMI;
4716 if (length[0] == 'h')
4717 instr->type = INSTR_METER_IHI;
4719 instr->meter.metarray_id = m->id;
4721 instr->meter.idx_val = idx_val;
4723 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4724 instr->meter.length.n_bits = flength->n_bits;
4725 instr->meter.length.offset = flength->offset / 8;
4727 instr->meter.color_in_val = color_in_val;
4729 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4730 instr->meter.color_out.n_bits = fcout->n_bits;
4731 instr->meter.color_out.offset = fcout->offset / 8;
4739 static inline struct meter *
4740 instr_meter_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
4742 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
4744 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
4745 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
4746 uint64_t idx64 = *idx64_ptr;
4747 uint64_t idx64_mask = UINT64_MAX >> (64 - (ip)->meter.idx.n_bits);
4748 uint64_t idx = idx64 & idx64_mask & r->size_mask;
4750 return &r->metarray[idx];
4753 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4755 static inline struct meter *
4756 instr_meter_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
4758 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
4760 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
4761 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
4762 uint64_t idx64 = *idx64_ptr;
4763 uint64_t idx = (ntoh64(idx64) >> (64 - ip->meter.idx.n_bits)) & r->size_mask;
4765 return &r->metarray[idx];
4770 #define instr_meter_idx_nbo instr_meter_idx_hbo
4774 static inline struct meter *
4775 instr_meter_idx_imm(struct rte_swx_pipeline *p, struct instruction *ip)
4777 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
4779 uint64_t idx = ip->meter.idx_val & r->size_mask;
4781 return &r->metarray[idx];
4784 static inline uint32_t
4785 instr_meter_length_hbo(struct thread *t, struct instruction *ip)
4787 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
4788 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
4789 uint64_t src64 = *src64_ptr;
4790 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->meter.length.n_bits);
4791 uint64_t src = src64 & src64_mask;
4793 return (uint32_t)src;
4796 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4798 static inline uint32_t
4799 instr_meter_length_nbo(struct thread *t, struct instruction *ip)
4801 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
4802 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
4803 uint64_t src64 = *src64_ptr;
4804 uint64_t src = ntoh64(src64) >> (64 - ip->meter.length.n_bits);
4806 return (uint32_t)src;
4811 #define instr_meter_length_nbo instr_meter_length_hbo
4815 static inline enum rte_color
4816 instr_meter_color_in_hbo(struct thread *t, struct instruction *ip)
4818 uint8_t *src_struct = t->structs[ip->meter.color_in.struct_id];
4819 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.color_in.offset];
4820 uint64_t src64 = *src64_ptr;
4821 uint64_t src64_mask = UINT64_MAX >> (64 - ip->meter.color_in.n_bits);
4822 uint64_t src = src64 & src64_mask;
4824 return (enum rte_color)src;
4828 instr_meter_color_out_hbo_set(struct thread *t, struct instruction *ip, enum rte_color color_out)
4830 uint8_t *dst_struct = t->structs[ip->meter.color_out.struct_id];
4831 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->meter.color_out.offset];
4832 uint64_t dst64 = *dst64_ptr;
4833 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->meter.color_out.n_bits);
4835 uint64_t src = (uint64_t)color_out;
4837 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
4841 instr_metprefetch_h_exec(struct rte_swx_pipeline *p)
4843 struct thread *t = &p->threads[p->thread_id];
4844 struct instruction *ip = t->ip;
4847 TRACE("[Thread %2u] metprefetch (h)\n", p->thread_id);
4850 m = instr_meter_idx_nbo(p, t, ip);
4858 instr_metprefetch_m_exec(struct rte_swx_pipeline *p)
4860 struct thread *t = &p->threads[p->thread_id];
4861 struct instruction *ip = t->ip;
4864 TRACE("[Thread %2u] metprefetch (m)\n", p->thread_id);
4867 m = instr_meter_idx_hbo(p, t, ip);
4875 instr_metprefetch_i_exec(struct rte_swx_pipeline *p)
4877 struct thread *t = &p->threads[p->thread_id];
4878 struct instruction *ip = t->ip;
4881 TRACE("[Thread %2u] metprefetch (i)\n", p->thread_id);
4884 m = instr_meter_idx_imm(p, ip);
4892 instr_meter_hhm_exec(struct rte_swx_pipeline *p)
4894 struct thread *t = &p->threads[p->thread_id];
4895 struct instruction *ip = t->ip;
4897 uint64_t time, n_pkts, n_bytes;
4899 enum rte_color color_in, color_out;
4901 TRACE("[Thread %2u] meter (hhm)\n", p->thread_id);
4904 m = instr_meter_idx_nbo(p, t, ip);
4905 rte_prefetch0(m->n_pkts);
4906 time = rte_get_tsc_cycles();
4907 length = instr_meter_length_nbo(t, ip);
4908 color_in = instr_meter_color_in_hbo(t, ip);
4910 color_out = rte_meter_trtcm_color_aware_check(&m->m,
4911 &m->profile->profile,
4916 color_out &= m->color_mask;
4918 n_pkts = m->n_pkts[color_out];
4919 n_bytes = m->n_bytes[color_out];
4921 instr_meter_color_out_hbo_set(t, ip, color_out);
4923 m->n_pkts[color_out] = n_pkts + 1;
4924 m->n_bytes[color_out] = n_bytes + length;
4931 instr_meter_hhi_exec(struct rte_swx_pipeline *p)
4933 struct thread *t = &p->threads[p->thread_id];
4934 struct instruction *ip = t->ip;
4936 uint64_t time, n_pkts, n_bytes;
4938 enum rte_color color_in, color_out;
4940 TRACE("[Thread %2u] meter (hhi)\n", p->thread_id);
4943 m = instr_meter_idx_nbo(p, t, ip);
4944 rte_prefetch0(m->n_pkts);
4945 time = rte_get_tsc_cycles();
4946 length = instr_meter_length_nbo(t, ip);
4947 color_in = (enum rte_color)ip->meter.color_in_val;
4949 color_out = rte_meter_trtcm_color_aware_check(&m->m,
4950 &m->profile->profile,
4955 color_out &= m->color_mask;
4957 n_pkts = m->n_pkts[color_out];
4958 n_bytes = m->n_bytes[color_out];
4960 instr_meter_color_out_hbo_set(t, ip, color_out);
4962 m->n_pkts[color_out] = n_pkts + 1;
4963 m->n_bytes[color_out] = n_bytes + length;
4970 instr_meter_hmm_exec(struct rte_swx_pipeline *p)
4972 struct thread *t = &p->threads[p->thread_id];
4973 struct instruction *ip = t->ip;
4975 uint64_t time, n_pkts, n_bytes;
4977 enum rte_color color_in, color_out;
4979 TRACE("[Thread %2u] meter (hmm)\n", p->thread_id);
4982 m = instr_meter_idx_nbo(p, t, ip);
4983 rte_prefetch0(m->n_pkts);
4984 time = rte_get_tsc_cycles();
4985 length = instr_meter_length_hbo(t, ip);
4986 color_in = instr_meter_color_in_hbo(t, ip);
4988 color_out = rte_meter_trtcm_color_aware_check(&m->m,
4989 &m->profile->profile,
4994 color_out &= m->color_mask;
4996 n_pkts = m->n_pkts[color_out];
4997 n_bytes = m->n_bytes[color_out];
4999 instr_meter_color_out_hbo_set(t, ip, color_out);
5001 m->n_pkts[color_out] = n_pkts + 1;
5002 m->n_bytes[color_out] = n_bytes + length;
5008 instr_meter_hmi_exec(struct rte_swx_pipeline *p)
5010 struct thread *t = &p->threads[p->thread_id];
5011 struct instruction *ip = t->ip;
5013 uint64_t time, n_pkts, n_bytes;
5015 enum rte_color color_in, color_out;
5017 TRACE("[Thread %2u] meter (hmi)\n", p->thread_id);
5020 m = instr_meter_idx_nbo(p, t, ip);
5021 rte_prefetch0(m->n_pkts);
5022 time = rte_get_tsc_cycles();
5023 length = instr_meter_length_hbo(t, ip);
5024 color_in = (enum rte_color)ip->meter.color_in_val;
5026 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5027 &m->profile->profile,
5032 color_out &= m->color_mask;
5034 n_pkts = m->n_pkts[color_out];
5035 n_bytes = m->n_bytes[color_out];
5037 instr_meter_color_out_hbo_set(t, ip, color_out);
5039 m->n_pkts[color_out] = n_pkts + 1;
5040 m->n_bytes[color_out] = n_bytes + length;
5047 instr_meter_mhm_exec(struct rte_swx_pipeline *p)
5049 struct thread *t = &p->threads[p->thread_id];
5050 struct instruction *ip = t->ip;
5052 uint64_t time, n_pkts, n_bytes;
5054 enum rte_color color_in, color_out;
5056 TRACE("[Thread %2u] meter (mhm)\n", p->thread_id);
5059 m = instr_meter_idx_hbo(p, t, ip);
5060 rte_prefetch0(m->n_pkts);
5061 time = rte_get_tsc_cycles();
5062 length = instr_meter_length_nbo(t, ip);
5063 color_in = instr_meter_color_in_hbo(t, ip);
5065 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5066 &m->profile->profile,
5071 color_out &= m->color_mask;
5073 n_pkts = m->n_pkts[color_out];
5074 n_bytes = m->n_bytes[color_out];
5076 instr_meter_color_out_hbo_set(t, ip, color_out);
5078 m->n_pkts[color_out] = n_pkts + 1;
5079 m->n_bytes[color_out] = n_bytes + length;
5086 instr_meter_mhi_exec(struct rte_swx_pipeline *p)
5088 struct thread *t = &p->threads[p->thread_id];
5089 struct instruction *ip = t->ip;
5091 uint64_t time, n_pkts, n_bytes;
5093 enum rte_color color_in, color_out;
5095 TRACE("[Thread %2u] meter (mhi)\n", p->thread_id);
5098 m = instr_meter_idx_hbo(p, t, ip);
5099 rte_prefetch0(m->n_pkts);
5100 time = rte_get_tsc_cycles();
5101 length = instr_meter_length_nbo(t, ip);
5102 color_in = (enum rte_color)ip->meter.color_in_val;
5104 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5105 &m->profile->profile,
5110 color_out &= m->color_mask;
5112 n_pkts = m->n_pkts[color_out];
5113 n_bytes = m->n_bytes[color_out];
5115 instr_meter_color_out_hbo_set(t, ip, color_out);
5117 m->n_pkts[color_out] = n_pkts + 1;
5118 m->n_bytes[color_out] = n_bytes + length;
5125 instr_meter_mmm_exec(struct rte_swx_pipeline *p)
5127 struct thread *t = &p->threads[p->thread_id];
5128 struct instruction *ip = t->ip;
5130 uint64_t time, n_pkts, n_bytes;
5132 enum rte_color color_in, color_out;
5134 TRACE("[Thread %2u] meter (mmm)\n", p->thread_id);
5137 m = instr_meter_idx_hbo(p, t, ip);
5138 rte_prefetch0(m->n_pkts);
5139 time = rte_get_tsc_cycles();
5140 length = instr_meter_length_hbo(t, ip);
5141 color_in = instr_meter_color_in_hbo(t, ip);
5143 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5144 &m->profile->profile,
5149 color_out &= m->color_mask;
5151 n_pkts = m->n_pkts[color_out];
5152 n_bytes = m->n_bytes[color_out];
5154 instr_meter_color_out_hbo_set(t, ip, color_out);
5156 m->n_pkts[color_out] = n_pkts + 1;
5157 m->n_bytes[color_out] = n_bytes + length;
5164 instr_meter_mmi_exec(struct rte_swx_pipeline *p)
5166 struct thread *t = &p->threads[p->thread_id];
5167 struct instruction *ip = t->ip;
5169 uint64_t time, n_pkts, n_bytes;
5171 enum rte_color color_in, color_out;
5173 TRACE("[Thread %2u] meter (mmi)\n", p->thread_id);
5176 m = instr_meter_idx_hbo(p, t, ip);
5177 rte_prefetch0(m->n_pkts);
5178 time = rte_get_tsc_cycles();
5179 length = instr_meter_length_hbo(t, ip);
5180 color_in = (enum rte_color)ip->meter.color_in_val;
5182 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5183 &m->profile->profile,
5188 color_out &= m->color_mask;
5190 n_pkts = m->n_pkts[color_out];
5191 n_bytes = m->n_bytes[color_out];
5193 instr_meter_color_out_hbo_set(t, ip, color_out);
5195 m->n_pkts[color_out] = n_pkts + 1;
5196 m->n_bytes[color_out] = n_bytes + length;
5203 instr_meter_ihm_exec(struct rte_swx_pipeline *p)
5205 struct thread *t = &p->threads[p->thread_id];
5206 struct instruction *ip = t->ip;
5208 uint64_t time, n_pkts, n_bytes;
5210 enum rte_color color_in, color_out;
5212 TRACE("[Thread %2u] meter (ihm)\n", p->thread_id);
5215 m = instr_meter_idx_imm(p, ip);
5216 rte_prefetch0(m->n_pkts);
5217 time = rte_get_tsc_cycles();
5218 length = instr_meter_length_nbo(t, ip);
5219 color_in = instr_meter_color_in_hbo(t, ip);
5221 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5222 &m->profile->profile,
5227 color_out &= m->color_mask;
5229 n_pkts = m->n_pkts[color_out];
5230 n_bytes = m->n_bytes[color_out];
5232 instr_meter_color_out_hbo_set(t, ip, color_out);
5234 m->n_pkts[color_out] = n_pkts + 1;
5235 m->n_bytes[color_out] = n_bytes + length;
5242 instr_meter_ihi_exec(struct rte_swx_pipeline *p)
5244 struct thread *t = &p->threads[p->thread_id];
5245 struct instruction *ip = t->ip;
5247 uint64_t time, n_pkts, n_bytes;
5249 enum rte_color color_in, color_out;
5251 TRACE("[Thread %2u] meter (ihi)\n", p->thread_id);
5254 m = instr_meter_idx_imm(p, ip);
5255 rte_prefetch0(m->n_pkts);
5256 time = rte_get_tsc_cycles();
5257 length = instr_meter_length_nbo(t, ip);
5258 color_in = (enum rte_color)ip->meter.color_in_val;
5260 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5261 &m->profile->profile,
5266 color_out &= m->color_mask;
5268 n_pkts = m->n_pkts[color_out];
5269 n_bytes = m->n_bytes[color_out];
5271 instr_meter_color_out_hbo_set(t, ip, color_out);
5273 m->n_pkts[color_out] = n_pkts + 1;
5274 m->n_bytes[color_out] = n_bytes + length;
5281 instr_meter_imm_exec(struct rte_swx_pipeline *p)
5283 struct thread *t = &p->threads[p->thread_id];
5284 struct instruction *ip = t->ip;
5286 uint64_t time, n_pkts, n_bytes;
5288 enum rte_color color_in, color_out;
5290 TRACE("[Thread %2u] meter (imm)\n", p->thread_id);
5293 m = instr_meter_idx_imm(p, ip);
5294 rte_prefetch0(m->n_pkts);
5295 time = rte_get_tsc_cycles();
5296 length = instr_meter_length_hbo(t, ip);
5297 color_in = instr_meter_color_in_hbo(t, ip);
5299 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5300 &m->profile->profile,
5305 color_out &= m->color_mask;
5307 n_pkts = m->n_pkts[color_out];
5308 n_bytes = m->n_bytes[color_out];
5310 instr_meter_color_out_hbo_set(t, ip, color_out);
5312 m->n_pkts[color_out] = n_pkts + 1;
5313 m->n_bytes[color_out] = n_bytes + length;
5319 instr_meter_imi_exec(struct rte_swx_pipeline *p)
5321 struct thread *t = &p->threads[p->thread_id];
5322 struct instruction *ip = t->ip;
5324 uint64_t time, n_pkts, n_bytes;
5326 enum rte_color color_in, color_out;
5328 TRACE("[Thread %2u] meter (imi)\n", p->thread_id);
5331 m = instr_meter_idx_imm(p, ip);
5332 rte_prefetch0(m->n_pkts);
5333 time = rte_get_tsc_cycles();
5334 length = instr_meter_length_hbo(t, ip);
5335 color_in = (enum rte_color)ip->meter.color_in_val;
5337 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5338 &m->profile->profile,
5343 color_out &= m->color_mask;
5345 n_pkts = m->n_pkts[color_out];
5346 n_bytes = m->n_bytes[color_out];
5348 instr_meter_color_out_hbo_set(t, ip, color_out);
5350 m->n_pkts[color_out] = n_pkts + 1;
5351 m->n_bytes[color_out] = n_bytes + length;
5361 instr_jmp_translate(struct rte_swx_pipeline *p __rte_unused,
5362 struct action *action __rte_unused,
5365 struct instruction *instr,
5366 struct instruction_data *data)
5368 CHECK(n_tokens == 2, EINVAL);
5370 strcpy(data->jmp_label, tokens[1]);
5372 instr->type = INSTR_JMP;
5373 instr->jmp.ip = NULL; /* Resolved later. */
5378 instr_jmp_valid_translate(struct rte_swx_pipeline *p,
5379 struct action *action __rte_unused,
5382 struct instruction *instr,
5383 struct instruction_data *data)
5387 CHECK(n_tokens == 3, EINVAL);
5389 strcpy(data->jmp_label, tokens[1]);
5391 h = header_parse(p, tokens[2]);
5394 instr->type = INSTR_JMP_VALID;
5395 instr->jmp.ip = NULL; /* Resolved later. */
5396 instr->jmp.header_id = h->id;
5401 instr_jmp_invalid_translate(struct rte_swx_pipeline *p,
5402 struct action *action __rte_unused,
5405 struct instruction *instr,
5406 struct instruction_data *data)
5410 CHECK(n_tokens == 3, EINVAL);
5412 strcpy(data->jmp_label, tokens[1]);
5414 h = header_parse(p, tokens[2]);
5417 instr->type = INSTR_JMP_INVALID;
5418 instr->jmp.ip = NULL; /* Resolved later. */
5419 instr->jmp.header_id = h->id;
5424 instr_jmp_hit_translate(struct rte_swx_pipeline *p __rte_unused,
5425 struct action *action,
5428 struct instruction *instr,
5429 struct instruction_data *data)
5431 CHECK(!action, EINVAL);
5432 CHECK(n_tokens == 2, EINVAL);
5434 strcpy(data->jmp_label, tokens[1]);
5436 instr->type = INSTR_JMP_HIT;
5437 instr->jmp.ip = NULL; /* Resolved later. */
5442 instr_jmp_miss_translate(struct rte_swx_pipeline *p __rte_unused,
5443 struct action *action,
5446 struct instruction *instr,
5447 struct instruction_data *data)
5449 CHECK(!action, EINVAL);
5450 CHECK(n_tokens == 2, EINVAL);
5452 strcpy(data->jmp_label, tokens[1]);
5454 instr->type = INSTR_JMP_MISS;
5455 instr->jmp.ip = NULL; /* Resolved later. */
5460 instr_jmp_action_hit_translate(struct rte_swx_pipeline *p,
5461 struct action *action,
5464 struct instruction *instr,
5465 struct instruction_data *data)
5469 CHECK(!action, EINVAL);
5470 CHECK(n_tokens == 3, EINVAL);
5472 strcpy(data->jmp_label, tokens[1]);
5474 a = action_find(p, tokens[2]);
5477 instr->type = INSTR_JMP_ACTION_HIT;
5478 instr->jmp.ip = NULL; /* Resolved later. */
5479 instr->jmp.action_id = a->id;
5484 instr_jmp_action_miss_translate(struct rte_swx_pipeline *p,
5485 struct action *action,
5488 struct instruction *instr,
5489 struct instruction_data *data)
5493 CHECK(!action, EINVAL);
5494 CHECK(n_tokens == 3, EINVAL);
5496 strcpy(data->jmp_label, tokens[1]);
5498 a = action_find(p, tokens[2]);
5501 instr->type = INSTR_JMP_ACTION_MISS;
5502 instr->jmp.ip = NULL; /* Resolved later. */
5503 instr->jmp.action_id = a->id;
5508 instr_jmp_eq_translate(struct rte_swx_pipeline *p,
5509 struct action *action,
5512 struct instruction *instr,
5513 struct instruction_data *data)
5515 char *a = tokens[2], *b = tokens[3];
5516 struct field *fa, *fb;
5518 uint32_t a_struct_id, b_struct_id;
5520 CHECK(n_tokens == 4, EINVAL);
5522 strcpy(data->jmp_label, tokens[1]);
5524 fa = struct_field_parse(p, action, a, &a_struct_id);
5526 CHECK(!fa->var_size, EINVAL);
5528 /* JMP_EQ, JMP_EQ_MH, JMP_EQ_HM, JMP_EQ_HH. */
5529 fb = struct_field_parse(p, action, b, &b_struct_id);
5531 CHECK(!fb->var_size, EINVAL);
5533 instr->type = INSTR_JMP_EQ;
5534 if (a[0] != 'h' && b[0] == 'h')
5535 instr->type = INSTR_JMP_EQ_MH;
5536 if (a[0] == 'h' && b[0] != 'h')
5537 instr->type = INSTR_JMP_EQ_HM;
5538 if (a[0] == 'h' && b[0] == 'h')
5539 instr->type = INSTR_JMP_EQ_HH;
5540 instr->jmp.ip = NULL; /* Resolved later. */
5542 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5543 instr->jmp.a.n_bits = fa->n_bits;
5544 instr->jmp.a.offset = fa->offset / 8;
5545 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5546 instr->jmp.b.n_bits = fb->n_bits;
5547 instr->jmp.b.offset = fb->offset / 8;
5552 b_val = strtoull(b, &b, 0);
5553 CHECK(!b[0], EINVAL);
5556 b_val = hton64(b_val) >> (64 - fa->n_bits);
5558 instr->type = INSTR_JMP_EQ_I;
5559 instr->jmp.ip = NULL; /* Resolved later. */
5560 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5561 instr->jmp.a.n_bits = fa->n_bits;
5562 instr->jmp.a.offset = fa->offset / 8;
5563 instr->jmp.b_val = b_val;
5568 instr_jmp_neq_translate(struct rte_swx_pipeline *p,
5569 struct action *action,
5572 struct instruction *instr,
5573 struct instruction_data *data)
5575 char *a = tokens[2], *b = tokens[3];
5576 struct field *fa, *fb;
5578 uint32_t a_struct_id, b_struct_id;
5580 CHECK(n_tokens == 4, EINVAL);
5582 strcpy(data->jmp_label, tokens[1]);
5584 fa = struct_field_parse(p, action, a, &a_struct_id);
5586 CHECK(!fa->var_size, EINVAL);
5588 /* JMP_NEQ, JMP_NEQ_MH, JMP_NEQ_HM, JMP_NEQ_HH. */
5589 fb = struct_field_parse(p, action, b, &b_struct_id);
5591 CHECK(!fb->var_size, EINVAL);
5593 instr->type = INSTR_JMP_NEQ;
5594 if (a[0] != 'h' && b[0] == 'h')
5595 instr->type = INSTR_JMP_NEQ_MH;
5596 if (a[0] == 'h' && b[0] != 'h')
5597 instr->type = INSTR_JMP_NEQ_HM;
5598 if (a[0] == 'h' && b[0] == 'h')
5599 instr->type = INSTR_JMP_NEQ_HH;
5600 instr->jmp.ip = NULL; /* Resolved later. */
5602 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5603 instr->jmp.a.n_bits = fa->n_bits;
5604 instr->jmp.a.offset = fa->offset / 8;
5605 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5606 instr->jmp.b.n_bits = fb->n_bits;
5607 instr->jmp.b.offset = fb->offset / 8;
5612 b_val = strtoull(b, &b, 0);
5613 CHECK(!b[0], EINVAL);
5616 b_val = hton64(b_val) >> (64 - fa->n_bits);
5618 instr->type = INSTR_JMP_NEQ_I;
5619 instr->jmp.ip = NULL; /* Resolved later. */
5620 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5621 instr->jmp.a.n_bits = fa->n_bits;
5622 instr->jmp.a.offset = fa->offset / 8;
5623 instr->jmp.b_val = b_val;
5628 instr_jmp_lt_translate(struct rte_swx_pipeline *p,
5629 struct action *action,
5632 struct instruction *instr,
5633 struct instruction_data *data)
5635 char *a = tokens[2], *b = tokens[3];
5636 struct field *fa, *fb;
5638 uint32_t a_struct_id, b_struct_id;
5640 CHECK(n_tokens == 4, EINVAL);
5642 strcpy(data->jmp_label, tokens[1]);
5644 fa = struct_field_parse(p, action, a, &a_struct_id);
5646 CHECK(!fa->var_size, EINVAL);
5648 /* JMP_LT, JMP_LT_MH, JMP_LT_HM, JMP_LT_HH. */
5649 fb = struct_field_parse(p, action, b, &b_struct_id);
5651 CHECK(!fb->var_size, EINVAL);
5653 instr->type = INSTR_JMP_LT;
5654 if (a[0] == 'h' && b[0] != 'h')
5655 instr->type = INSTR_JMP_LT_HM;
5656 if (a[0] != 'h' && b[0] == 'h')
5657 instr->type = INSTR_JMP_LT_MH;
5658 if (a[0] == 'h' && b[0] == 'h')
5659 instr->type = INSTR_JMP_LT_HH;
5660 instr->jmp.ip = NULL; /* Resolved later. */
5662 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5663 instr->jmp.a.n_bits = fa->n_bits;
5664 instr->jmp.a.offset = fa->offset / 8;
5665 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5666 instr->jmp.b.n_bits = fb->n_bits;
5667 instr->jmp.b.offset = fb->offset / 8;
5671 /* JMP_LT_MI, JMP_LT_HI. */
5672 b_val = strtoull(b, &b, 0);
5673 CHECK(!b[0], EINVAL);
5675 instr->type = INSTR_JMP_LT_MI;
5677 instr->type = INSTR_JMP_LT_HI;
5678 instr->jmp.ip = NULL; /* Resolved later. */
5680 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5681 instr->jmp.a.n_bits = fa->n_bits;
5682 instr->jmp.a.offset = fa->offset / 8;
5683 instr->jmp.b_val = b_val;
5688 instr_jmp_gt_translate(struct rte_swx_pipeline *p,
5689 struct action *action,
5692 struct instruction *instr,
5693 struct instruction_data *data)
5695 char *a = tokens[2], *b = tokens[3];
5696 struct field *fa, *fb;
5698 uint32_t a_struct_id, b_struct_id;
5700 CHECK(n_tokens == 4, EINVAL);
5702 strcpy(data->jmp_label, tokens[1]);
5704 fa = struct_field_parse(p, action, a, &a_struct_id);
5706 CHECK(!fa->var_size, EINVAL);
5708 /* JMP_GT, JMP_GT_MH, JMP_GT_HM, JMP_GT_HH. */
5709 fb = struct_field_parse(p, action, b, &b_struct_id);
5711 CHECK(!fb->var_size, EINVAL);
5713 instr->type = INSTR_JMP_GT;
5714 if (a[0] == 'h' && b[0] != 'h')
5715 instr->type = INSTR_JMP_GT_HM;
5716 if (a[0] != 'h' && b[0] == 'h')
5717 instr->type = INSTR_JMP_GT_MH;
5718 if (a[0] == 'h' && b[0] == 'h')
5719 instr->type = INSTR_JMP_GT_HH;
5720 instr->jmp.ip = NULL; /* Resolved later. */
5722 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5723 instr->jmp.a.n_bits = fa->n_bits;
5724 instr->jmp.a.offset = fa->offset / 8;
5725 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5726 instr->jmp.b.n_bits = fb->n_bits;
5727 instr->jmp.b.offset = fb->offset / 8;
5731 /* JMP_GT_MI, JMP_GT_HI. */
5732 b_val = strtoull(b, &b, 0);
5733 CHECK(!b[0], EINVAL);
5735 instr->type = INSTR_JMP_GT_MI;
5737 instr->type = INSTR_JMP_GT_HI;
5738 instr->jmp.ip = NULL; /* Resolved later. */
5740 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5741 instr->jmp.a.n_bits = fa->n_bits;
5742 instr->jmp.a.offset = fa->offset / 8;
5743 instr->jmp.b_val = b_val;
5748 instr_jmp_exec(struct rte_swx_pipeline *p)
5750 struct thread *t = &p->threads[p->thread_id];
5751 struct instruction *ip = t->ip;
5753 TRACE("[Thread %2u] jmp\n", p->thread_id);
5755 thread_ip_set(t, ip->jmp.ip);
5759 instr_jmp_valid_exec(struct rte_swx_pipeline *p)
5761 struct thread *t = &p->threads[p->thread_id];
5762 struct instruction *ip = t->ip;
5763 uint32_t header_id = ip->jmp.header_id;
5765 TRACE("[Thread %2u] jmpv\n", p->thread_id);
5767 t->ip = HEADER_VALID(t, header_id) ? ip->jmp.ip : (t->ip + 1);
5771 instr_jmp_invalid_exec(struct rte_swx_pipeline *p)
5773 struct thread *t = &p->threads[p->thread_id];
5774 struct instruction *ip = t->ip;
5775 uint32_t header_id = ip->jmp.header_id;
5777 TRACE("[Thread %2u] jmpnv\n", p->thread_id);
5779 t->ip = HEADER_VALID(t, header_id) ? (t->ip + 1) : ip->jmp.ip;
5783 instr_jmp_hit_exec(struct rte_swx_pipeline *p)
5785 struct thread *t = &p->threads[p->thread_id];
5786 struct instruction *ip = t->ip;
5787 struct instruction *ip_next[] = {t->ip + 1, ip->jmp.ip};
5789 TRACE("[Thread %2u] jmph\n", p->thread_id);
5791 t->ip = ip_next[t->hit];
5795 instr_jmp_miss_exec(struct rte_swx_pipeline *p)
5797 struct thread *t = &p->threads[p->thread_id];
5798 struct instruction *ip = t->ip;
5799 struct instruction *ip_next[] = {ip->jmp.ip, t->ip + 1};
5801 TRACE("[Thread %2u] jmpnh\n", p->thread_id);
5803 t->ip = ip_next[t->hit];
5807 instr_jmp_action_hit_exec(struct rte_swx_pipeline *p)
5809 struct thread *t = &p->threads[p->thread_id];
5810 struct instruction *ip = t->ip;
5812 TRACE("[Thread %2u] jmpa\n", p->thread_id);
5814 t->ip = (ip->jmp.action_id == t->action_id) ? ip->jmp.ip : (t->ip + 1);
5818 instr_jmp_action_miss_exec(struct rte_swx_pipeline *p)
5820 struct thread *t = &p->threads[p->thread_id];
5821 struct instruction *ip = t->ip;
5823 TRACE("[Thread %2u] jmpna\n", p->thread_id);
5825 t->ip = (ip->jmp.action_id == t->action_id) ? (t->ip + 1) : ip->jmp.ip;
5829 instr_jmp_eq_exec(struct rte_swx_pipeline *p)
5831 struct thread *t = &p->threads[p->thread_id];
5832 struct instruction *ip = t->ip;
5834 TRACE("[Thread %2u] jmpeq\n", p->thread_id);
5840 instr_jmp_eq_mh_exec(struct rte_swx_pipeline *p)
5842 struct thread *t = &p->threads[p->thread_id];
5843 struct instruction *ip = t->ip;
5845 TRACE("[Thread %2u] jmpeq (mh)\n", p->thread_id);
5847 JMP_CMP_MH(t, ip, ==);
5851 instr_jmp_eq_hm_exec(struct rte_swx_pipeline *p)
5853 struct thread *t = &p->threads[p->thread_id];
5854 struct instruction *ip = t->ip;
5856 TRACE("[Thread %2u] jmpeq (hm)\n", p->thread_id);
5858 JMP_CMP_HM(t, ip, ==);
5862 instr_jmp_eq_hh_exec(struct rte_swx_pipeline *p)
5864 struct thread *t = &p->threads[p->thread_id];
5865 struct instruction *ip = t->ip;
5867 TRACE("[Thread %2u] jmpeq (hh)\n", p->thread_id);
5869 JMP_CMP_HH_FAST(t, ip, ==);
5873 instr_jmp_eq_i_exec(struct rte_swx_pipeline *p)
5875 struct thread *t = &p->threads[p->thread_id];
5876 struct instruction *ip = t->ip;
5878 TRACE("[Thread %2u] jmpeq (i)\n", p->thread_id);
5880 JMP_CMP_I(t, ip, ==);
5884 instr_jmp_neq_exec(struct rte_swx_pipeline *p)
5886 struct thread *t = &p->threads[p->thread_id];
5887 struct instruction *ip = t->ip;
5889 TRACE("[Thread %2u] jmpneq\n", p->thread_id);
5895 instr_jmp_neq_mh_exec(struct rte_swx_pipeline *p)
5897 struct thread *t = &p->threads[p->thread_id];
5898 struct instruction *ip = t->ip;
5900 TRACE("[Thread %2u] jmpneq (mh)\n", p->thread_id);
5902 JMP_CMP_MH(t, ip, !=);
5906 instr_jmp_neq_hm_exec(struct rte_swx_pipeline *p)
5908 struct thread *t = &p->threads[p->thread_id];
5909 struct instruction *ip = t->ip;
5911 TRACE("[Thread %2u] jmpneq (hm)\n", p->thread_id);
5913 JMP_CMP_HM(t, ip, !=);
5917 instr_jmp_neq_hh_exec(struct rte_swx_pipeline *p)
5919 struct thread *t = &p->threads[p->thread_id];
5920 struct instruction *ip = t->ip;
5922 TRACE("[Thread %2u] jmpneq (hh)\n", p->thread_id);
5924 JMP_CMP_HH_FAST(t, ip, !=);
5928 instr_jmp_neq_i_exec(struct rte_swx_pipeline *p)
5930 struct thread *t = &p->threads[p->thread_id];
5931 struct instruction *ip = t->ip;
5933 TRACE("[Thread %2u] jmpneq (i)\n", p->thread_id);
5935 JMP_CMP_I(t, ip, !=);
5939 instr_jmp_lt_exec(struct rte_swx_pipeline *p)
5941 struct thread *t = &p->threads[p->thread_id];
5942 struct instruction *ip = t->ip;
5944 TRACE("[Thread %2u] jmplt\n", p->thread_id);
5950 instr_jmp_lt_mh_exec(struct rte_swx_pipeline *p)
5952 struct thread *t = &p->threads[p->thread_id];
5953 struct instruction *ip = t->ip;
5955 TRACE("[Thread %2u] jmplt (mh)\n", p->thread_id);
5957 JMP_CMP_MH(t, ip, <);
5961 instr_jmp_lt_hm_exec(struct rte_swx_pipeline *p)
5963 struct thread *t = &p->threads[p->thread_id];
5964 struct instruction *ip = t->ip;
5966 TRACE("[Thread %2u] jmplt (hm)\n", p->thread_id);
5968 JMP_CMP_HM(t, ip, <);
5972 instr_jmp_lt_hh_exec(struct rte_swx_pipeline *p)
5974 struct thread *t = &p->threads[p->thread_id];
5975 struct instruction *ip = t->ip;
5977 TRACE("[Thread %2u] jmplt (hh)\n", p->thread_id);
5979 JMP_CMP_HH(t, ip, <);
5983 instr_jmp_lt_mi_exec(struct rte_swx_pipeline *p)
5985 struct thread *t = &p->threads[p->thread_id];
5986 struct instruction *ip = t->ip;
5988 TRACE("[Thread %2u] jmplt (mi)\n", p->thread_id);
5990 JMP_CMP_MI(t, ip, <);
5994 instr_jmp_lt_hi_exec(struct rte_swx_pipeline *p)
5996 struct thread *t = &p->threads[p->thread_id];
5997 struct instruction *ip = t->ip;
5999 TRACE("[Thread %2u] jmplt (hi)\n", p->thread_id);
6001 JMP_CMP_HI(t, ip, <);
6005 instr_jmp_gt_exec(struct rte_swx_pipeline *p)
6007 struct thread *t = &p->threads[p->thread_id];
6008 struct instruction *ip = t->ip;
6010 TRACE("[Thread %2u] jmpgt\n", p->thread_id);
6016 instr_jmp_gt_mh_exec(struct rte_swx_pipeline *p)
6018 struct thread *t = &p->threads[p->thread_id];
6019 struct instruction *ip = t->ip;
6021 TRACE("[Thread %2u] jmpgt (mh)\n", p->thread_id);
6023 JMP_CMP_MH(t, ip, >);
6027 instr_jmp_gt_hm_exec(struct rte_swx_pipeline *p)
6029 struct thread *t = &p->threads[p->thread_id];
6030 struct instruction *ip = t->ip;
6032 TRACE("[Thread %2u] jmpgt (hm)\n", p->thread_id);
6034 JMP_CMP_HM(t, ip, >);
6038 instr_jmp_gt_hh_exec(struct rte_swx_pipeline *p)
6040 struct thread *t = &p->threads[p->thread_id];
6041 struct instruction *ip = t->ip;
6043 TRACE("[Thread %2u] jmpgt (hh)\n", p->thread_id);
6045 JMP_CMP_HH(t, ip, >);
6049 instr_jmp_gt_mi_exec(struct rte_swx_pipeline *p)
6051 struct thread *t = &p->threads[p->thread_id];
6052 struct instruction *ip = t->ip;
6054 TRACE("[Thread %2u] jmpgt (mi)\n", p->thread_id);
6056 JMP_CMP_MI(t, ip, >);
6060 instr_jmp_gt_hi_exec(struct rte_swx_pipeline *p)
6062 struct thread *t = &p->threads[p->thread_id];
6063 struct instruction *ip = t->ip;
6065 TRACE("[Thread %2u] jmpgt (hi)\n", p->thread_id);
6067 JMP_CMP_HI(t, ip, >);
6074 instr_return_translate(struct rte_swx_pipeline *p __rte_unused,
6075 struct action *action,
6076 char **tokens __rte_unused,
6078 struct instruction *instr,
6079 struct instruction_data *data __rte_unused)
6081 CHECK(action, EINVAL);
6082 CHECK(n_tokens == 1, EINVAL);
6084 instr->type = INSTR_RETURN;
6089 instr_return_exec(struct rte_swx_pipeline *p)
6091 struct thread *t = &p->threads[p->thread_id];
6093 TRACE("[Thread %2u] return\n", p->thread_id);
6099 instr_translate(struct rte_swx_pipeline *p,
6100 struct action *action,
6102 struct instruction *instr,
6103 struct instruction_data *data)
6105 char *tokens[RTE_SWX_INSTRUCTION_TOKENS_MAX];
6106 int n_tokens = 0, tpos = 0;
6108 /* Parse the instruction string into tokens. */
6112 token = strtok_r(string, " \t\v", &string);
6116 CHECK(n_tokens < RTE_SWX_INSTRUCTION_TOKENS_MAX, EINVAL);
6117 CHECK_NAME(token, EINVAL);
6119 tokens[n_tokens] = token;
6123 CHECK(n_tokens, EINVAL);
6125 /* Handle the optional instruction label. */
6126 if ((n_tokens >= 2) && !strcmp(tokens[1], ":")) {
6127 strcpy(data->label, tokens[0]);
6130 CHECK(n_tokens - tpos, EINVAL);
6133 /* Identify the instruction type. */
6134 if (!strcmp(tokens[tpos], "rx"))
6135 return instr_rx_translate(p,
6142 if (!strcmp(tokens[tpos], "tx"))
6143 return instr_tx_translate(p,
6150 if (!strcmp(tokens[tpos], "drop"))
6151 return instr_drop_translate(p,
6158 if (!strcmp(tokens[tpos], "extract"))
6159 return instr_hdr_extract_translate(p,
6166 if (!strcmp(tokens[tpos], "lookahead"))
6167 return instr_hdr_lookahead_translate(p,
6174 if (!strcmp(tokens[tpos], "emit"))
6175 return instr_hdr_emit_translate(p,
6182 if (!strcmp(tokens[tpos], "validate"))
6183 return instr_hdr_validate_translate(p,
6190 if (!strcmp(tokens[tpos], "invalidate"))
6191 return instr_hdr_invalidate_translate(p,
6198 if (!strcmp(tokens[tpos], "mov"))
6199 return instr_mov_translate(p,
6206 if (!strcmp(tokens[tpos], "add"))
6207 return instr_alu_add_translate(p,
6214 if (!strcmp(tokens[tpos], "sub"))
6215 return instr_alu_sub_translate(p,
6222 if (!strcmp(tokens[tpos], "ckadd"))
6223 return instr_alu_ckadd_translate(p,
6230 if (!strcmp(tokens[tpos], "cksub"))
6231 return instr_alu_cksub_translate(p,
6238 if (!strcmp(tokens[tpos], "and"))
6239 return instr_alu_and_translate(p,
6246 if (!strcmp(tokens[tpos], "or"))
6247 return instr_alu_or_translate(p,
6254 if (!strcmp(tokens[tpos], "xor"))
6255 return instr_alu_xor_translate(p,
6262 if (!strcmp(tokens[tpos], "shl"))
6263 return instr_alu_shl_translate(p,
6270 if (!strcmp(tokens[tpos], "shr"))
6271 return instr_alu_shr_translate(p,
6278 if (!strcmp(tokens[tpos], "regprefetch"))
6279 return instr_regprefetch_translate(p,
6286 if (!strcmp(tokens[tpos], "regrd"))
6287 return instr_regrd_translate(p,
6294 if (!strcmp(tokens[tpos], "regwr"))
6295 return instr_regwr_translate(p,
6302 if (!strcmp(tokens[tpos], "regadd"))
6303 return instr_regadd_translate(p,
6310 if (!strcmp(tokens[tpos], "metprefetch"))
6311 return instr_metprefetch_translate(p,
6318 if (!strcmp(tokens[tpos], "meter"))
6319 return instr_meter_translate(p,
6326 if (!strcmp(tokens[tpos], "table"))
6327 return instr_table_translate(p,
6334 if (!strcmp(tokens[tpos], "learn"))
6335 return instr_learn_translate(p,
6342 if (!strcmp(tokens[tpos], "forget"))
6343 return instr_forget_translate(p,
6350 if (!strcmp(tokens[tpos], "extern"))
6351 return instr_extern_translate(p,
6358 if (!strcmp(tokens[tpos], "jmp"))
6359 return instr_jmp_translate(p,
6366 if (!strcmp(tokens[tpos], "jmpv"))
6367 return instr_jmp_valid_translate(p,
6374 if (!strcmp(tokens[tpos], "jmpnv"))
6375 return instr_jmp_invalid_translate(p,
6382 if (!strcmp(tokens[tpos], "jmph"))
6383 return instr_jmp_hit_translate(p,
6390 if (!strcmp(tokens[tpos], "jmpnh"))
6391 return instr_jmp_miss_translate(p,
6398 if (!strcmp(tokens[tpos], "jmpa"))
6399 return instr_jmp_action_hit_translate(p,
6406 if (!strcmp(tokens[tpos], "jmpna"))
6407 return instr_jmp_action_miss_translate(p,
6414 if (!strcmp(tokens[tpos], "jmpeq"))
6415 return instr_jmp_eq_translate(p,
6422 if (!strcmp(tokens[tpos], "jmpneq"))
6423 return instr_jmp_neq_translate(p,
6430 if (!strcmp(tokens[tpos], "jmplt"))
6431 return instr_jmp_lt_translate(p,
6438 if (!strcmp(tokens[tpos], "jmpgt"))
6439 return instr_jmp_gt_translate(p,
6446 if (!strcmp(tokens[tpos], "return"))
6447 return instr_return_translate(p,
6457 static struct instruction_data *
6458 label_find(struct instruction_data *data, uint32_t n, const char *label)
6462 for (i = 0; i < n; i++)
6463 if (!strcmp(label, data[i].label))
6470 label_is_used(struct instruction_data *data, uint32_t n, const char *label)
6472 uint32_t count = 0, i;
6477 for (i = 0; i < n; i++)
6478 if (!strcmp(label, data[i].jmp_label))
6485 instr_label_check(struct instruction_data *instruction_data,
6486 uint32_t n_instructions)
6490 /* Check that all instruction labels are unique. */
6491 for (i = 0; i < n_instructions; i++) {
6492 struct instruction_data *data = &instruction_data[i];
6493 char *label = data->label;
6499 for (j = i + 1; j < n_instructions; j++)
6500 CHECK(strcmp(label, data[j].label), EINVAL);
6503 /* Get users for each instruction label. */
6504 for (i = 0; i < n_instructions; i++) {
6505 struct instruction_data *data = &instruction_data[i];
6506 char *label = data->label;
6508 data->n_users = label_is_used(instruction_data,
6517 instr_jmp_resolve(struct instruction *instructions,
6518 struct instruction_data *instruction_data,
6519 uint32_t n_instructions)
6523 for (i = 0; i < n_instructions; i++) {
6524 struct instruction *instr = &instructions[i];
6525 struct instruction_data *data = &instruction_data[i];
6526 struct instruction_data *found;
6528 if (!instruction_is_jmp(instr))
6531 found = label_find(instruction_data,
6534 CHECK(found, EINVAL);
6536 instr->jmp.ip = &instructions[found - instruction_data];
6543 instr_verify(struct rte_swx_pipeline *p __rte_unused,
6545 struct instruction *instr,
6546 struct instruction_data *data __rte_unused,
6547 uint32_t n_instructions)
6550 enum instruction_type type;
6553 /* Check that the first instruction is rx. */
6554 CHECK(instr[0].type == INSTR_RX, EINVAL);
6556 /* Check that there is at least one tx instruction. */
6557 for (i = 0; i < n_instructions; i++) {
6558 type = instr[i].type;
6560 if (instruction_is_tx(type))
6563 CHECK(i < n_instructions, EINVAL);
6565 /* Check that the last instruction is either tx or unconditional
6568 type = instr[n_instructions - 1].type;
6569 CHECK(instruction_is_tx(type) || (type == INSTR_JMP), EINVAL);
6573 enum instruction_type type;
6576 /* Check that there is at least one return or tx instruction. */
6577 for (i = 0; i < n_instructions; i++) {
6578 type = instr[i].type;
6580 if ((type == INSTR_RETURN) || instruction_is_tx(type))
6583 CHECK(i < n_instructions, EINVAL);
6590 instr_compact(struct instruction *instructions,
6591 struct instruction_data *instruction_data,
6592 uint32_t n_instructions)
6594 uint32_t i, pos = 0;
6596 /* Eliminate the invalid instructions that have been optimized out. */
6597 for (i = 0; i < n_instructions; i++) {
6598 struct instruction *instr = &instructions[i];
6599 struct instruction_data *data = &instruction_data[i];
6605 memcpy(&instructions[pos], instr, sizeof(*instr));
6606 memcpy(&instruction_data[pos], data, sizeof(*data));
6616 instr_pattern_extract_many_search(struct instruction *instr,
6617 struct instruction_data *data,
6619 uint32_t *n_pattern_instr)
6623 for (i = 0; i < n_instr; i++) {
6624 if (data[i].invalid)
6627 if (instr[i].type != INSTR_HDR_EXTRACT)
6630 if (i == RTE_DIM(instr->io.hdr.header_id))
6633 if (i && data[i].n_users)
6640 *n_pattern_instr = i;
6645 instr_pattern_extract_many_replace(struct instruction *instr,
6646 struct instruction_data *data,
6651 for (i = 1; i < n_instr; i++) {
6653 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
6654 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
6655 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
6657 data[i].invalid = 1;
6662 instr_pattern_extract_many_optimize(struct instruction *instructions,
6663 struct instruction_data *instruction_data,
6664 uint32_t n_instructions)
6668 for (i = 0; i < n_instructions; ) {
6669 struct instruction *instr = &instructions[i];
6670 struct instruction_data *data = &instruction_data[i];
6671 uint32_t n_instr = 0;
6675 detected = instr_pattern_extract_many_search(instr,
6680 instr_pattern_extract_many_replace(instr,
6687 /* No pattern starting at the current instruction. */
6691 /* Eliminate the invalid instructions that have been optimized out. */
6692 n_instructions = instr_compact(instructions,
6696 return n_instructions;
6700 instr_pattern_emit_many_tx_search(struct instruction *instr,
6701 struct instruction_data *data,
6703 uint32_t *n_pattern_instr)
6707 for (i = 0; i < n_instr; i++) {
6708 if (data[i].invalid)
6711 if (instr[i].type != INSTR_HDR_EMIT)
6714 if (i == RTE_DIM(instr->io.hdr.header_id))
6717 if (i && data[i].n_users)
6724 if (!instruction_is_tx(instr[i].type))
6727 if (data[i].n_users)
6732 *n_pattern_instr = i;
6737 instr_pattern_emit_many_tx_replace(struct instruction *instr,
6738 struct instruction_data *data,
6743 /* Any emit instruction in addition to the first one. */
6744 for (i = 1; i < n_instr - 1; i++) {
6746 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
6747 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
6748 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
6750 data[i].invalid = 1;
6753 /* The TX instruction is the last one in the pattern. */
6755 instr[0].io.io.offset = instr[i].io.io.offset;
6756 instr[0].io.io.n_bits = instr[i].io.io.n_bits;
6757 data[i].invalid = 1;
6761 instr_pattern_emit_many_tx_optimize(struct instruction *instructions,
6762 struct instruction_data *instruction_data,
6763 uint32_t n_instructions)
6767 for (i = 0; i < n_instructions; ) {
6768 struct instruction *instr = &instructions[i];
6769 struct instruction_data *data = &instruction_data[i];
6770 uint32_t n_instr = 0;
6773 /* Emit many + TX. */
6774 detected = instr_pattern_emit_many_tx_search(instr,
6779 instr_pattern_emit_many_tx_replace(instr,
6786 /* No pattern starting at the current instruction. */
6790 /* Eliminate the invalid instructions that have been optimized out. */
6791 n_instructions = instr_compact(instructions,
6795 return n_instructions;
6799 action_arg_src_mov_count(struct action *a,
6801 struct instruction *instructions,
6802 struct instruction_data *instruction_data,
6803 uint32_t n_instructions);
6806 instr_pattern_mov_all_validate_search(struct rte_swx_pipeline *p,
6808 struct instruction *instr,
6809 struct instruction_data *data,
6811 struct instruction *instructions,
6812 struct instruction_data *instruction_data,
6813 uint32_t n_instructions,
6814 uint32_t *n_pattern_instr)
6817 uint32_t src_field_id, i, j;
6819 /* Prerequisites. */
6823 /* First instruction: MOV_HM. */
6824 if (data[0].invalid || (instr[0].type != INSTR_MOV_HM))
6827 h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
6828 if (!h || h->st->var_size)
6831 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
6832 if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
6835 if (src_field_id == a->st->n_fields)
6838 if (instr[0].mov.dst.offset ||
6839 (instr[0].mov.dst.n_bits != h->st->fields[0].n_bits) ||
6840 instr[0].mov.src.struct_id ||
6841 (instr[0].mov.src.n_bits != a->st->fields[src_field_id].n_bits) ||
6842 (instr[0].mov.dst.n_bits != instr[0].mov.src.n_bits))
6845 if ((n_instr < h->st->n_fields + 1) ||
6846 (a->st->n_fields < src_field_id + h->st->n_fields + 1))
6849 /* Subsequent instructions: MOV_HM. */
6850 for (i = 1; i < h->st->n_fields; i++)
6851 if (data[i].invalid ||
6853 (instr[i].type != INSTR_MOV_HM) ||
6854 (instr[i].mov.dst.struct_id != h->struct_id) ||
6855 (instr[i].mov.dst.offset != h->st->fields[i].offset / 8) ||
6856 (instr[i].mov.dst.n_bits != h->st->fields[i].n_bits) ||
6857 instr[i].mov.src.struct_id ||
6858 (instr[i].mov.src.offset != a->st->fields[src_field_id + i].offset / 8) ||
6859 (instr[i].mov.src.n_bits != a->st->fields[src_field_id + i].n_bits) ||
6860 (instr[i].mov.dst.n_bits != instr[i].mov.src.n_bits))
6863 /* Last instruction: HDR_VALIDATE. */
6864 if ((instr[i].type != INSTR_HDR_VALIDATE) ||
6865 (instr[i].valid.header_id != h->id))
6868 /* Check that none of the action args that are used as source for this
6869 * DMA transfer are not used as source in any other mov instruction.
6871 for (j = src_field_id; j < src_field_id + h->st->n_fields; j++) {
6874 n_users = action_arg_src_mov_count(a,
6883 *n_pattern_instr = 1 + i;
6888 instr_pattern_mov_all_validate_replace(struct rte_swx_pipeline *p,
6890 struct instruction *instr,
6891 struct instruction_data *data,
6895 uint32_t src_field_id, src_offset, i;
6897 /* Read from the instructions before they are modified. */
6898 h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
6902 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
6903 if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
6906 if (src_field_id == a->st->n_fields)
6909 src_offset = instr[0].mov.src.offset;
6911 /* Modify the instructions. */
6912 instr[0].type = INSTR_DMA_HT;
6913 instr[0].dma.dst.header_id[0] = h->id;
6914 instr[0].dma.dst.struct_id[0] = h->struct_id;
6915 instr[0].dma.src.offset[0] = (uint8_t)src_offset;
6916 instr[0].dma.n_bytes[0] = h->st->n_bits / 8;
6918 for (i = 1; i < n_instr; i++)
6919 data[i].invalid = 1;
6921 /* Update the endianness of the action arguments to header endianness. */
6922 for (i = 0; i < h->st->n_fields; i++)
6923 a->args_endianness[src_field_id + i] = 1;
6927 instr_pattern_mov_all_validate_optimize(struct rte_swx_pipeline *p,
6929 struct instruction *instructions,
6930 struct instruction_data *instruction_data,
6931 uint32_t n_instructions)
6936 return n_instructions;
6938 for (i = 0; i < n_instructions; ) {
6939 struct instruction *instr = &instructions[i];
6940 struct instruction_data *data = &instruction_data[i];
6941 uint32_t n_instr = 0;
6944 /* Mov all + validate. */
6945 detected = instr_pattern_mov_all_validate_search(p,
6955 instr_pattern_mov_all_validate_replace(p, a, instr, data, n_instr);
6960 /* No pattern starting at the current instruction. */
6964 /* Eliminate the invalid instructions that have been optimized out. */
6965 n_instructions = instr_compact(instructions,
6969 return n_instructions;
6973 instr_pattern_dma_many_search(struct instruction *instr,
6974 struct instruction_data *data,
6976 uint32_t *n_pattern_instr)
6980 for (i = 0; i < n_instr; i++) {
6981 if (data[i].invalid)
6984 if (instr[i].type != INSTR_DMA_HT)
6987 if (i == RTE_DIM(instr->dma.dst.header_id))
6990 if (i && data[i].n_users)
6997 *n_pattern_instr = i;
7002 instr_pattern_dma_many_replace(struct instruction *instr,
7003 struct instruction_data *data,
7008 for (i = 1; i < n_instr; i++) {
7010 instr[0].dma.dst.header_id[i] = instr[i].dma.dst.header_id[0];
7011 instr[0].dma.dst.struct_id[i] = instr[i].dma.dst.struct_id[0];
7012 instr[0].dma.src.offset[i] = instr[i].dma.src.offset[0];
7013 instr[0].dma.n_bytes[i] = instr[i].dma.n_bytes[0];
7015 data[i].invalid = 1;
7020 instr_pattern_dma_many_optimize(struct instruction *instructions,
7021 struct instruction_data *instruction_data,
7022 uint32_t n_instructions)
7026 for (i = 0; i < n_instructions; ) {
7027 struct instruction *instr = &instructions[i];
7028 struct instruction_data *data = &instruction_data[i];
7029 uint32_t n_instr = 0;
7033 detected = instr_pattern_dma_many_search(instr,
7038 instr_pattern_dma_many_replace(instr, data, n_instr);
7043 /* No pattern starting at the current instruction. */
7047 /* Eliminate the invalid instructions that have been optimized out. */
7048 n_instructions = instr_compact(instructions,
7052 return n_instructions;
7056 instr_optimize(struct rte_swx_pipeline *p,
7058 struct instruction *instructions,
7059 struct instruction_data *instruction_data,
7060 uint32_t n_instructions)
7063 n_instructions = instr_pattern_extract_many_optimize(instructions,
7067 /* Emit many + TX. */
7068 n_instructions = instr_pattern_emit_many_tx_optimize(instructions,
7072 /* Mov all + validate. */
7073 n_instructions = instr_pattern_mov_all_validate_optimize(p,
7080 n_instructions = instr_pattern_dma_many_optimize(instructions,
7084 return n_instructions;
7088 instruction_config(struct rte_swx_pipeline *p,
7090 const char **instructions,
7091 uint32_t n_instructions)
7093 struct instruction *instr = NULL;
7094 struct instruction_data *data = NULL;
7098 CHECK(n_instructions, EINVAL);
7099 CHECK(instructions, EINVAL);
7100 for (i = 0; i < n_instructions; i++)
7101 CHECK_INSTRUCTION(instructions[i], EINVAL);
7103 /* Memory allocation. */
7104 instr = calloc(n_instructions, sizeof(struct instruction));
7110 data = calloc(n_instructions, sizeof(struct instruction_data));
7116 for (i = 0; i < n_instructions; i++) {
7117 char *string = strdup(instructions[i]);
7123 err = instr_translate(p, a, string, &instr[i], &data[i]);
7132 err = instr_label_check(data, n_instructions);
7136 err = instr_verify(p, a, instr, data, n_instructions);
7140 n_instructions = instr_optimize(p, a, instr, data, n_instructions);
7142 err = instr_jmp_resolve(instr, data, n_instructions);
7147 a->instructions = instr;
7148 a->n_instructions = n_instructions;
7150 p->instructions = instr;
7151 p->n_instructions = n_instructions;
7163 typedef void (*instr_exec_t)(struct rte_swx_pipeline *);
7165 static instr_exec_t instruction_table[] = {
7166 [INSTR_RX] = instr_rx_exec,
7167 [INSTR_TX] = instr_tx_exec,
7168 [INSTR_TX_I] = instr_tx_i_exec,
7170 [INSTR_HDR_EXTRACT] = instr_hdr_extract_exec,
7171 [INSTR_HDR_EXTRACT2] = instr_hdr_extract2_exec,
7172 [INSTR_HDR_EXTRACT3] = instr_hdr_extract3_exec,
7173 [INSTR_HDR_EXTRACT4] = instr_hdr_extract4_exec,
7174 [INSTR_HDR_EXTRACT5] = instr_hdr_extract5_exec,
7175 [INSTR_HDR_EXTRACT6] = instr_hdr_extract6_exec,
7176 [INSTR_HDR_EXTRACT7] = instr_hdr_extract7_exec,
7177 [INSTR_HDR_EXTRACT8] = instr_hdr_extract8_exec,
7178 [INSTR_HDR_EXTRACT_M] = instr_hdr_extract_m_exec,
7179 [INSTR_HDR_LOOKAHEAD] = instr_hdr_lookahead_exec,
7181 [INSTR_HDR_EMIT] = instr_hdr_emit_exec,
7182 [INSTR_HDR_EMIT_TX] = instr_hdr_emit_tx_exec,
7183 [INSTR_HDR_EMIT2_TX] = instr_hdr_emit2_tx_exec,
7184 [INSTR_HDR_EMIT3_TX] = instr_hdr_emit3_tx_exec,
7185 [INSTR_HDR_EMIT4_TX] = instr_hdr_emit4_tx_exec,
7186 [INSTR_HDR_EMIT5_TX] = instr_hdr_emit5_tx_exec,
7187 [INSTR_HDR_EMIT6_TX] = instr_hdr_emit6_tx_exec,
7188 [INSTR_HDR_EMIT7_TX] = instr_hdr_emit7_tx_exec,
7189 [INSTR_HDR_EMIT8_TX] = instr_hdr_emit8_tx_exec,
7191 [INSTR_HDR_VALIDATE] = instr_hdr_validate_exec,
7192 [INSTR_HDR_INVALIDATE] = instr_hdr_invalidate_exec,
7194 [INSTR_MOV] = instr_mov_exec,
7195 [INSTR_MOV_MH] = instr_mov_mh_exec,
7196 [INSTR_MOV_HM] = instr_mov_hm_exec,
7197 [INSTR_MOV_HH] = instr_mov_hh_exec,
7198 [INSTR_MOV_I] = instr_mov_i_exec,
7200 [INSTR_DMA_HT] = instr_dma_ht_exec,
7201 [INSTR_DMA_HT2] = instr_dma_ht2_exec,
7202 [INSTR_DMA_HT3] = instr_dma_ht3_exec,
7203 [INSTR_DMA_HT4] = instr_dma_ht4_exec,
7204 [INSTR_DMA_HT5] = instr_dma_ht5_exec,
7205 [INSTR_DMA_HT6] = instr_dma_ht6_exec,
7206 [INSTR_DMA_HT7] = instr_dma_ht7_exec,
7207 [INSTR_DMA_HT8] = instr_dma_ht8_exec,
7209 [INSTR_ALU_ADD] = instr_alu_add_exec,
7210 [INSTR_ALU_ADD_MH] = instr_alu_add_mh_exec,
7211 [INSTR_ALU_ADD_HM] = instr_alu_add_hm_exec,
7212 [INSTR_ALU_ADD_HH] = instr_alu_add_hh_exec,
7213 [INSTR_ALU_ADD_MI] = instr_alu_add_mi_exec,
7214 [INSTR_ALU_ADD_HI] = instr_alu_add_hi_exec,
7216 [INSTR_ALU_SUB] = instr_alu_sub_exec,
7217 [INSTR_ALU_SUB_MH] = instr_alu_sub_mh_exec,
7218 [INSTR_ALU_SUB_HM] = instr_alu_sub_hm_exec,
7219 [INSTR_ALU_SUB_HH] = instr_alu_sub_hh_exec,
7220 [INSTR_ALU_SUB_MI] = instr_alu_sub_mi_exec,
7221 [INSTR_ALU_SUB_HI] = instr_alu_sub_hi_exec,
7223 [INSTR_ALU_CKADD_FIELD] = instr_alu_ckadd_field_exec,
7224 [INSTR_ALU_CKADD_STRUCT] = instr_alu_ckadd_struct_exec,
7225 [INSTR_ALU_CKADD_STRUCT20] = instr_alu_ckadd_struct20_exec,
7226 [INSTR_ALU_CKSUB_FIELD] = instr_alu_cksub_field_exec,
7228 [INSTR_ALU_AND] = instr_alu_and_exec,
7229 [INSTR_ALU_AND_MH] = instr_alu_and_mh_exec,
7230 [INSTR_ALU_AND_HM] = instr_alu_and_hm_exec,
7231 [INSTR_ALU_AND_HH] = instr_alu_and_hh_exec,
7232 [INSTR_ALU_AND_I] = instr_alu_and_i_exec,
7234 [INSTR_ALU_OR] = instr_alu_or_exec,
7235 [INSTR_ALU_OR_MH] = instr_alu_or_mh_exec,
7236 [INSTR_ALU_OR_HM] = instr_alu_or_hm_exec,
7237 [INSTR_ALU_OR_HH] = instr_alu_or_hh_exec,
7238 [INSTR_ALU_OR_I] = instr_alu_or_i_exec,
7240 [INSTR_ALU_XOR] = instr_alu_xor_exec,
7241 [INSTR_ALU_XOR_MH] = instr_alu_xor_mh_exec,
7242 [INSTR_ALU_XOR_HM] = instr_alu_xor_hm_exec,
7243 [INSTR_ALU_XOR_HH] = instr_alu_xor_hh_exec,
7244 [INSTR_ALU_XOR_I] = instr_alu_xor_i_exec,
7246 [INSTR_ALU_SHL] = instr_alu_shl_exec,
7247 [INSTR_ALU_SHL_MH] = instr_alu_shl_mh_exec,
7248 [INSTR_ALU_SHL_HM] = instr_alu_shl_hm_exec,
7249 [INSTR_ALU_SHL_HH] = instr_alu_shl_hh_exec,
7250 [INSTR_ALU_SHL_MI] = instr_alu_shl_mi_exec,
7251 [INSTR_ALU_SHL_HI] = instr_alu_shl_hi_exec,
7253 [INSTR_ALU_SHR] = instr_alu_shr_exec,
7254 [INSTR_ALU_SHR_MH] = instr_alu_shr_mh_exec,
7255 [INSTR_ALU_SHR_HM] = instr_alu_shr_hm_exec,
7256 [INSTR_ALU_SHR_HH] = instr_alu_shr_hh_exec,
7257 [INSTR_ALU_SHR_MI] = instr_alu_shr_mi_exec,
7258 [INSTR_ALU_SHR_HI] = instr_alu_shr_hi_exec,
7260 [INSTR_REGPREFETCH_RH] = instr_regprefetch_rh_exec,
7261 [INSTR_REGPREFETCH_RM] = instr_regprefetch_rm_exec,
7262 [INSTR_REGPREFETCH_RI] = instr_regprefetch_ri_exec,
7264 [INSTR_REGRD_HRH] = instr_regrd_hrh_exec,
7265 [INSTR_REGRD_HRM] = instr_regrd_hrm_exec,
7266 [INSTR_REGRD_MRH] = instr_regrd_mrh_exec,
7267 [INSTR_REGRD_MRM] = instr_regrd_mrm_exec,
7268 [INSTR_REGRD_HRI] = instr_regrd_hri_exec,
7269 [INSTR_REGRD_MRI] = instr_regrd_mri_exec,
7271 [INSTR_REGWR_RHH] = instr_regwr_rhh_exec,
7272 [INSTR_REGWR_RHM] = instr_regwr_rhm_exec,
7273 [INSTR_REGWR_RMH] = instr_regwr_rmh_exec,
7274 [INSTR_REGWR_RMM] = instr_regwr_rmm_exec,
7275 [INSTR_REGWR_RHI] = instr_regwr_rhi_exec,
7276 [INSTR_REGWR_RMI] = instr_regwr_rmi_exec,
7277 [INSTR_REGWR_RIH] = instr_regwr_rih_exec,
7278 [INSTR_REGWR_RIM] = instr_regwr_rim_exec,
7279 [INSTR_REGWR_RII] = instr_regwr_rii_exec,
7281 [INSTR_REGADD_RHH] = instr_regadd_rhh_exec,
7282 [INSTR_REGADD_RHM] = instr_regadd_rhm_exec,
7283 [INSTR_REGADD_RMH] = instr_regadd_rmh_exec,
7284 [INSTR_REGADD_RMM] = instr_regadd_rmm_exec,
7285 [INSTR_REGADD_RHI] = instr_regadd_rhi_exec,
7286 [INSTR_REGADD_RMI] = instr_regadd_rmi_exec,
7287 [INSTR_REGADD_RIH] = instr_regadd_rih_exec,
7288 [INSTR_REGADD_RIM] = instr_regadd_rim_exec,
7289 [INSTR_REGADD_RII] = instr_regadd_rii_exec,
7291 [INSTR_METPREFETCH_H] = instr_metprefetch_h_exec,
7292 [INSTR_METPREFETCH_M] = instr_metprefetch_m_exec,
7293 [INSTR_METPREFETCH_I] = instr_metprefetch_i_exec,
7295 [INSTR_METER_HHM] = instr_meter_hhm_exec,
7296 [INSTR_METER_HHI] = instr_meter_hhi_exec,
7297 [INSTR_METER_HMM] = instr_meter_hmm_exec,
7298 [INSTR_METER_HMI] = instr_meter_hmi_exec,
7299 [INSTR_METER_MHM] = instr_meter_mhm_exec,
7300 [INSTR_METER_MHI] = instr_meter_mhi_exec,
7301 [INSTR_METER_MMM] = instr_meter_mmm_exec,
7302 [INSTR_METER_MMI] = instr_meter_mmi_exec,
7303 [INSTR_METER_IHM] = instr_meter_ihm_exec,
7304 [INSTR_METER_IHI] = instr_meter_ihi_exec,
7305 [INSTR_METER_IMM] = instr_meter_imm_exec,
7306 [INSTR_METER_IMI] = instr_meter_imi_exec,
7308 [INSTR_TABLE] = instr_table_exec,
7309 [INSTR_SELECTOR] = instr_selector_exec,
7310 [INSTR_LEARNER] = instr_learner_exec,
7311 [INSTR_LEARNER_LEARN] = instr_learn_exec,
7312 [INSTR_LEARNER_FORGET] = instr_forget_exec,
7313 [INSTR_EXTERN_OBJ] = instr_extern_obj_exec,
7314 [INSTR_EXTERN_FUNC] = instr_extern_func_exec,
7316 [INSTR_JMP] = instr_jmp_exec,
7317 [INSTR_JMP_VALID] = instr_jmp_valid_exec,
7318 [INSTR_JMP_INVALID] = instr_jmp_invalid_exec,
7319 [INSTR_JMP_HIT] = instr_jmp_hit_exec,
7320 [INSTR_JMP_MISS] = instr_jmp_miss_exec,
7321 [INSTR_JMP_ACTION_HIT] = instr_jmp_action_hit_exec,
7322 [INSTR_JMP_ACTION_MISS] = instr_jmp_action_miss_exec,
7324 [INSTR_JMP_EQ] = instr_jmp_eq_exec,
7325 [INSTR_JMP_EQ_MH] = instr_jmp_eq_mh_exec,
7326 [INSTR_JMP_EQ_HM] = instr_jmp_eq_hm_exec,
7327 [INSTR_JMP_EQ_HH] = instr_jmp_eq_hh_exec,
7328 [INSTR_JMP_EQ_I] = instr_jmp_eq_i_exec,
7330 [INSTR_JMP_NEQ] = instr_jmp_neq_exec,
7331 [INSTR_JMP_NEQ_MH] = instr_jmp_neq_mh_exec,
7332 [INSTR_JMP_NEQ_HM] = instr_jmp_neq_hm_exec,
7333 [INSTR_JMP_NEQ_HH] = instr_jmp_neq_hh_exec,
7334 [INSTR_JMP_NEQ_I] = instr_jmp_neq_i_exec,
7336 [INSTR_JMP_LT] = instr_jmp_lt_exec,
7337 [INSTR_JMP_LT_MH] = instr_jmp_lt_mh_exec,
7338 [INSTR_JMP_LT_HM] = instr_jmp_lt_hm_exec,
7339 [INSTR_JMP_LT_HH] = instr_jmp_lt_hh_exec,
7340 [INSTR_JMP_LT_MI] = instr_jmp_lt_mi_exec,
7341 [INSTR_JMP_LT_HI] = instr_jmp_lt_hi_exec,
7343 [INSTR_JMP_GT] = instr_jmp_gt_exec,
7344 [INSTR_JMP_GT_MH] = instr_jmp_gt_mh_exec,
7345 [INSTR_JMP_GT_HM] = instr_jmp_gt_hm_exec,
7346 [INSTR_JMP_GT_HH] = instr_jmp_gt_hh_exec,
7347 [INSTR_JMP_GT_MI] = instr_jmp_gt_mi_exec,
7348 [INSTR_JMP_GT_HI] = instr_jmp_gt_hi_exec,
7350 [INSTR_RETURN] = instr_return_exec,
7354 instr_exec(struct rte_swx_pipeline *p)
7356 struct thread *t = &p->threads[p->thread_id];
7357 struct instruction *ip = t->ip;
7358 instr_exec_t instr = instruction_table[ip->type];
7366 static struct action *
7367 action_find(struct rte_swx_pipeline *p, const char *name)
7369 struct action *elem;
7374 TAILQ_FOREACH(elem, &p->actions, node)
7375 if (strcmp(elem->name, name) == 0)
7381 static struct action *
7382 action_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7384 struct action *action = NULL;
7386 TAILQ_FOREACH(action, &p->actions, node)
7387 if (action->id == id)
7393 static struct field *
7394 action_field_find(struct action *a, const char *name)
7396 return a->st ? struct_type_field_find(a->st, name) : NULL;
7399 static struct field *
7400 action_field_parse(struct action *action, const char *name)
7402 if (name[0] != 't' || name[1] != '.')
7405 return action_field_find(action, &name[2]);
7409 action_has_nbo_args(struct action *a)
7413 /* Return if the action does not have any args. */
7415 return 0; /* FALSE */
7417 for (i = 0; i < a->st->n_fields; i++)
7418 if (a->args_endianness[i])
7419 return 1; /* TRUE */
7421 return 0; /* FALSE */
7425 action_does_learning(struct action *a)
7429 for (i = 0; i < a->n_instructions; i++)
7430 switch (a->instructions[i].type) {
7431 case INSTR_LEARNER_LEARN:
7432 return 1; /* TRUE */
7434 case INSTR_LEARNER_FORGET:
7435 return 1; /* TRUE */
7441 return 0; /* FALSE */
7445 rte_swx_pipeline_action_config(struct rte_swx_pipeline *p,
7447 const char *args_struct_type_name,
7448 const char **instructions,
7449 uint32_t n_instructions)
7451 struct struct_type *args_struct_type = NULL;
7457 CHECK_NAME(name, EINVAL);
7458 CHECK(!action_find(p, name), EEXIST);
7460 if (args_struct_type_name) {
7461 CHECK_NAME(args_struct_type_name, EINVAL);
7462 args_struct_type = struct_type_find(p, args_struct_type_name);
7463 CHECK(args_struct_type, EINVAL);
7464 CHECK(!args_struct_type->var_size, EINVAL);
7467 /* Node allocation. */
7468 a = calloc(1, sizeof(struct action));
7470 if (args_struct_type) {
7471 a->args_endianness = calloc(args_struct_type->n_fields, sizeof(int));
7472 if (!a->args_endianness) {
7478 /* Node initialization. */
7479 strcpy(a->name, name);
7480 a->st = args_struct_type;
7481 a->id = p->n_actions;
7483 /* Instruction translation. */
7484 err = instruction_config(p, a, instructions, n_instructions);
7486 free(a->args_endianness);
7491 /* Node add to tailq. */
7492 TAILQ_INSERT_TAIL(&p->actions, a, node);
7499 action_build(struct rte_swx_pipeline *p)
7501 struct action *action;
7503 p->action_instructions = calloc(p->n_actions,
7504 sizeof(struct instruction *));
7505 CHECK(p->action_instructions, ENOMEM);
7507 TAILQ_FOREACH(action, &p->actions, node)
7508 p->action_instructions[action->id] = action->instructions;
7514 action_build_free(struct rte_swx_pipeline *p)
7516 free(p->action_instructions);
7517 p->action_instructions = NULL;
7521 action_free(struct rte_swx_pipeline *p)
7523 action_build_free(p);
7526 struct action *action;
7528 action = TAILQ_FIRST(&p->actions);
7532 TAILQ_REMOVE(&p->actions, action, node);
7533 free(action->instructions);
7539 action_arg_src_mov_count(struct action *a,
7541 struct instruction *instructions,
7542 struct instruction_data *instruction_data,
7543 uint32_t n_instructions)
7545 uint32_t offset, n_users = 0, i;
7548 (arg_id >= a->st->n_fields) ||
7550 !instruction_data ||
7554 offset = a->st->fields[arg_id].offset / 8;
7556 for (i = 0; i < n_instructions; i++) {
7557 struct instruction *instr = &instructions[i];
7558 struct instruction_data *data = &instruction_data[i];
7560 if (data->invalid ||
7561 ((instr->type != INSTR_MOV) && (instr->type != INSTR_MOV_HM)) ||
7562 instr->mov.src.struct_id ||
7563 (instr->mov.src.offset != offset))
7575 static struct table_type *
7576 table_type_find(struct rte_swx_pipeline *p, const char *name)
7578 struct table_type *elem;
7580 TAILQ_FOREACH(elem, &p->table_types, node)
7581 if (strcmp(elem->name, name) == 0)
7587 static struct table_type *
7588 table_type_resolve(struct rte_swx_pipeline *p,
7589 const char *recommended_type_name,
7590 enum rte_swx_table_match_type match_type)
7592 struct table_type *elem;
7594 /* Only consider the recommended type if the match type is correct. */
7595 if (recommended_type_name)
7596 TAILQ_FOREACH(elem, &p->table_types, node)
7597 if (!strcmp(elem->name, recommended_type_name) &&
7598 (elem->match_type == match_type))
7601 /* Ignore the recommended type and get the first element with this match
7604 TAILQ_FOREACH(elem, &p->table_types, node)
7605 if (elem->match_type == match_type)
7611 static struct table *
7612 table_find(struct rte_swx_pipeline *p, const char *name)
7616 TAILQ_FOREACH(elem, &p->tables, node)
7617 if (strcmp(elem->name, name) == 0)
7623 static struct table *
7624 table_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7626 struct table *table = NULL;
7628 TAILQ_FOREACH(table, &p->tables, node)
7629 if (table->id == id)
7636 rte_swx_pipeline_table_type_register(struct rte_swx_pipeline *p,
7638 enum rte_swx_table_match_type match_type,
7639 struct rte_swx_table_ops *ops)
7641 struct table_type *elem;
7645 CHECK_NAME(name, EINVAL);
7646 CHECK(!table_type_find(p, name), EEXIST);
7649 CHECK(ops->create, EINVAL);
7650 CHECK(ops->lkp, EINVAL);
7651 CHECK(ops->free, EINVAL);
7653 /* Node allocation. */
7654 elem = calloc(1, sizeof(struct table_type));
7655 CHECK(elem, ENOMEM);
7657 /* Node initialization. */
7658 strcpy(elem->name, name);
7659 elem->match_type = match_type;
7660 memcpy(&elem->ops, ops, sizeof(*ops));
7662 /* Node add to tailq. */
7663 TAILQ_INSERT_TAIL(&p->table_types, elem, node);
7669 table_match_type_resolve(struct rte_swx_match_field_params *fields,
7671 enum rte_swx_table_match_type *match_type)
7673 uint32_t n_fields_em = 0, n_fields_lpm = 0, i;
7675 for (i = 0; i < n_fields; i++) {
7676 struct rte_swx_match_field_params *f = &fields[i];
7678 if (f->match_type == RTE_SWX_TABLE_MATCH_EXACT)
7681 if (f->match_type == RTE_SWX_TABLE_MATCH_LPM)
7685 if ((n_fields_lpm > 1) ||
7686 (n_fields_lpm && (n_fields_em != n_fields - 1)))
7689 *match_type = (n_fields_em == n_fields) ?
7690 RTE_SWX_TABLE_MATCH_EXACT :
7691 RTE_SWX_TABLE_MATCH_WILDCARD;
7697 table_match_fields_check(struct rte_swx_pipeline *p,
7698 struct rte_swx_pipeline_table_params *params,
7699 struct header **header)
7701 struct header *h0 = NULL;
7702 struct field *hf, *mf;
7703 uint32_t *offset = NULL, i;
7706 /* Return if no match fields. */
7707 if (!params->n_fields) {
7708 if (params->fields) {
7719 /* Memory allocation. */
7720 offset = calloc(params->n_fields, sizeof(uint32_t));
7726 /* Check that all the match fields belong to either the same header or
7729 hf = header_field_parse(p, params->fields[0].name, &h0);
7730 mf = metadata_field_parse(p, params->fields[0].name);
7731 if ((!hf && !mf) || (hf && hf->var_size)) {
7736 offset[0] = h0 ? hf->offset : mf->offset;
7738 for (i = 1; i < params->n_fields; i++)
7742 hf = header_field_parse(p, params->fields[i].name, &h);
7743 if (!hf || (h->id != h0->id) || hf->var_size) {
7748 offset[i] = hf->offset;
7750 mf = metadata_field_parse(p, params->fields[i].name);
7756 offset[i] = mf->offset;
7759 /* Check that there are no duplicated match fields. */
7760 for (i = 0; i < params->n_fields; i++) {
7763 for (j = 0; j < i; j++)
7764 if (offset[j] == offset[i]) {
7780 rte_swx_pipeline_table_config(struct rte_swx_pipeline *p,
7782 struct rte_swx_pipeline_table_params *params,
7783 const char *recommended_table_type_name,
7787 struct table_type *type;
7789 struct action *default_action;
7790 struct header *header = NULL;
7791 uint32_t action_data_size_max = 0, i;
7796 CHECK_NAME(name, EINVAL);
7797 CHECK(!table_find(p, name), EEXIST);
7798 CHECK(!selector_find(p, name), EEXIST);
7799 CHECK(!learner_find(p, name), EEXIST);
7801 CHECK(params, EINVAL);
7804 status = table_match_fields_check(p, params, &header);
7808 /* Action checks. */
7809 CHECK(params->n_actions, EINVAL);
7810 CHECK(params->action_names, EINVAL);
7811 for (i = 0; i < params->n_actions; i++) {
7812 const char *action_name = params->action_names[i];
7814 uint32_t action_data_size;
7816 CHECK_NAME(action_name, EINVAL);
7818 a = action_find(p, action_name);
7820 CHECK(!action_does_learning(a), EINVAL);
7822 action_data_size = a->st ? a->st->n_bits / 8 : 0;
7823 if (action_data_size > action_data_size_max)
7824 action_data_size_max = action_data_size;
7827 CHECK_NAME(params->default_action_name, EINVAL);
7828 for (i = 0; i < p->n_actions; i++)
7829 if (!strcmp(params->action_names[i],
7830 params->default_action_name))
7832 CHECK(i < params->n_actions, EINVAL);
7833 default_action = action_find(p, params->default_action_name);
7834 CHECK((default_action->st && params->default_action_data) ||
7835 !params->default_action_data, EINVAL);
7837 /* Table type checks. */
7838 if (recommended_table_type_name)
7839 CHECK_NAME(recommended_table_type_name, EINVAL);
7841 if (params->n_fields) {
7842 enum rte_swx_table_match_type match_type;
7844 status = table_match_type_resolve(params->fields, params->n_fields, &match_type);
7848 type = table_type_resolve(p, recommended_table_type_name, match_type);
7849 CHECK(type, EINVAL);
7854 /* Memory allocation. */
7855 t = calloc(1, sizeof(struct table));
7858 t->fields = calloc(params->n_fields, sizeof(struct match_field));
7864 t->actions = calloc(params->n_actions, sizeof(struct action *));
7871 if (action_data_size_max) {
7872 t->default_action_data = calloc(1, action_data_size_max);
7873 if (!t->default_action_data) {
7881 /* Node initialization. */
7882 strcpy(t->name, name);
7883 if (args && args[0])
7884 strcpy(t->args, args);
7887 for (i = 0; i < params->n_fields; i++) {
7888 struct rte_swx_match_field_params *field = ¶ms->fields[i];
7889 struct match_field *f = &t->fields[i];
7891 f->match_type = field->match_type;
7893 header_field_parse(p, field->name, NULL) :
7894 metadata_field_parse(p, field->name);
7896 t->n_fields = params->n_fields;
7899 for (i = 0; i < params->n_actions; i++)
7900 t->actions[i] = action_find(p, params->action_names[i]);
7901 t->default_action = default_action;
7902 if (default_action->st)
7903 memcpy(t->default_action_data,
7904 params->default_action_data,
7905 default_action->st->n_bits / 8);
7906 t->n_actions = params->n_actions;
7907 t->default_action_is_const = params->default_action_is_const;
7908 t->action_data_size_max = action_data_size_max;
7911 t->id = p->n_tables;
7913 /* Node add to tailq. */
7914 TAILQ_INSERT_TAIL(&p->tables, t, node);
7920 static struct rte_swx_table_params *
7921 table_params_get(struct table *table)
7923 struct rte_swx_table_params *params;
7924 struct field *first, *last;
7926 uint32_t key_size, key_offset, action_data_size, i;
7928 /* Memory allocation. */
7929 params = calloc(1, sizeof(struct rte_swx_table_params));
7933 /* Find first (smallest offset) and last (biggest offset) match fields. */
7934 first = table->fields[0].field;
7935 last = table->fields[0].field;
7937 for (i = 0; i < table->n_fields; i++) {
7938 struct field *f = table->fields[i].field;
7940 if (f->offset < first->offset)
7943 if (f->offset > last->offset)
7947 /* Key offset and size. */
7948 key_offset = first->offset / 8;
7949 key_size = (last->offset + last->n_bits - first->offset) / 8;
7951 /* Memory allocation. */
7952 key_mask = calloc(1, key_size);
7959 for (i = 0; i < table->n_fields; i++) {
7960 struct field *f = table->fields[i].field;
7961 uint32_t start = (f->offset - first->offset) / 8;
7962 size_t size = f->n_bits / 8;
7964 memset(&key_mask[start], 0xFF, size);
7967 /* Action data size. */
7968 action_data_size = 0;
7969 for (i = 0; i < table->n_actions; i++) {
7970 struct action *action = table->actions[i];
7971 uint32_t ads = action->st ? action->st->n_bits / 8 : 0;
7973 if (ads > action_data_size)
7974 action_data_size = ads;
7978 params->match_type = table->type->match_type;
7979 params->key_size = key_size;
7980 params->key_offset = key_offset;
7981 params->key_mask0 = key_mask;
7982 params->action_data_size = action_data_size;
7983 params->n_keys_max = table->size;
7989 table_params_free(struct rte_swx_table_params *params)
7994 free(params->key_mask0);
7999 table_stub_lkp(void *table __rte_unused,
8000 void *mailbox __rte_unused,
8001 uint8_t **key __rte_unused,
8002 uint64_t *action_id __rte_unused,
8003 uint8_t **action_data __rte_unused,
8007 return 1; /* DONE. */
8011 table_build(struct rte_swx_pipeline *p)
8015 /* Per pipeline: table statistics. */
8016 p->table_stats = calloc(p->n_tables, sizeof(struct table_statistics));
8017 CHECK(p->table_stats, ENOMEM);
8019 for (i = 0; i < p->n_tables; i++) {
8020 p->table_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
8021 CHECK(p->table_stats[i].n_pkts_action, ENOMEM);
8024 /* Per thread: table runt-time. */
8025 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8026 struct thread *t = &p->threads[i];
8027 struct table *table;
8029 t->tables = calloc(p->n_tables, sizeof(struct table_runtime));
8030 CHECK(t->tables, ENOMEM);
8032 TAILQ_FOREACH(table, &p->tables, node) {
8033 struct table_runtime *r = &t->tables[table->id];
8038 size = table->type->ops.mailbox_size_get();
8041 r->func = table->type->ops.lkp;
8045 r->mailbox = calloc(1, size);
8046 CHECK(r->mailbox, ENOMEM);
8050 r->key = table->header ?
8051 &t->structs[table->header->struct_id] :
8052 &t->structs[p->metadata_struct_id];
8054 r->func = table_stub_lkp;
8063 table_build_free(struct rte_swx_pipeline *p)
8067 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8068 struct thread *t = &p->threads[i];
8074 for (j = 0; j < p->n_tables; j++) {
8075 struct table_runtime *r = &t->tables[j];
8084 if (p->table_stats) {
8085 for (i = 0; i < p->n_tables; i++)
8086 free(p->table_stats[i].n_pkts_action);
8088 free(p->table_stats);
8093 table_free(struct rte_swx_pipeline *p)
8095 table_build_free(p);
8101 elem = TAILQ_FIRST(&p->tables);
8105 TAILQ_REMOVE(&p->tables, elem, node);
8107 free(elem->actions);
8108 free(elem->default_action_data);
8114 struct table_type *elem;
8116 elem = TAILQ_FIRST(&p->table_types);
8120 TAILQ_REMOVE(&p->table_types, elem, node);
8128 static struct selector *
8129 selector_find(struct rte_swx_pipeline *p, const char *name)
8133 TAILQ_FOREACH(s, &p->selectors, node)
8134 if (strcmp(s->name, name) == 0)
8140 static struct selector *
8141 selector_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8143 struct selector *s = NULL;
8145 TAILQ_FOREACH(s, &p->selectors, node)
8153 selector_fields_check(struct rte_swx_pipeline *p,
8154 struct rte_swx_pipeline_selector_params *params,
8155 struct header **header)
8157 struct header *h0 = NULL;
8158 struct field *hf, *mf;
8161 /* Return if no selector fields. */
8162 if (!params->n_selector_fields || !params->selector_field_names)
8165 /* Check that all the selector fields either belong to the same header
8166 * or are all meta-data fields.
8168 hf = header_field_parse(p, params->selector_field_names[0], &h0);
8169 mf = metadata_field_parse(p, params->selector_field_names[0]);
8173 for (i = 1; i < params->n_selector_fields; i++)
8177 hf = header_field_parse(p, params->selector_field_names[i], &h);
8178 if (!hf || (h->id != h0->id))
8181 mf = metadata_field_parse(p, params->selector_field_names[i]);
8186 /* Check that there are no duplicated match fields. */
8187 for (i = 0; i < params->n_selector_fields; i++) {
8188 const char *field_name = params->selector_field_names[i];
8191 for (j = i + 1; j < params->n_selector_fields; j++)
8192 if (!strcmp(params->selector_field_names[j], field_name))
8204 rte_swx_pipeline_selector_config(struct rte_swx_pipeline *p,
8206 struct rte_swx_pipeline_selector_params *params)
8209 struct header *selector_header = NULL;
8210 struct field *group_id_field, *member_id_field;
8216 CHECK_NAME(name, EINVAL);
8217 CHECK(!table_find(p, name), EEXIST);
8218 CHECK(!selector_find(p, name), EEXIST);
8219 CHECK(!learner_find(p, name), EEXIST);
8221 CHECK(params, EINVAL);
8223 CHECK_NAME(params->group_id_field_name, EINVAL);
8224 group_id_field = metadata_field_parse(p, params->group_id_field_name);
8225 CHECK(group_id_field, EINVAL);
8227 for (i = 0; i < params->n_selector_fields; i++) {
8228 const char *field_name = params->selector_field_names[i];
8230 CHECK_NAME(field_name, EINVAL);
8232 status = selector_fields_check(p, params, &selector_header);
8236 CHECK_NAME(params->member_id_field_name, EINVAL);
8237 member_id_field = metadata_field_parse(p, params->member_id_field_name);
8238 CHECK(member_id_field, EINVAL);
8240 CHECK(params->n_groups_max, EINVAL);
8242 CHECK(params->n_members_per_group_max, EINVAL);
8244 /* Memory allocation. */
8245 s = calloc(1, sizeof(struct selector));
8251 s->selector_fields = calloc(params->n_selector_fields, sizeof(struct field *));
8252 if (!s->selector_fields) {
8257 /* Node initialization. */
8258 strcpy(s->name, name);
8260 s->group_id_field = group_id_field;
8262 for (i = 0; i < params->n_selector_fields; i++) {
8263 const char *field_name = params->selector_field_names[i];
8265 s->selector_fields[i] = selector_header ?
8266 header_field_parse(p, field_name, NULL) :
8267 metadata_field_parse(p, field_name);
8270 s->n_selector_fields = params->n_selector_fields;
8272 s->selector_header = selector_header;
8274 s->member_id_field = member_id_field;
8276 s->n_groups_max = params->n_groups_max;
8278 s->n_members_per_group_max = params->n_members_per_group_max;
8280 s->id = p->n_selectors;
8282 /* Node add to tailq. */
8283 TAILQ_INSERT_TAIL(&p->selectors, s, node);
8292 free(s->selector_fields);
8300 selector_params_free(struct rte_swx_table_selector_params *params)
8305 free(params->selector_mask);
8310 static struct rte_swx_table_selector_params *
8311 selector_table_params_get(struct selector *s)
8313 struct rte_swx_table_selector_params *params = NULL;
8314 struct field *first, *last;
8317 /* Memory allocation. */
8318 params = calloc(1, sizeof(struct rte_swx_table_selector_params));
8323 params->group_id_offset = s->group_id_field->offset / 8;
8325 /* Find first (smallest offset) and last (biggest offset) selector fields. */
8326 first = s->selector_fields[0];
8327 last = s->selector_fields[0];
8329 for (i = 0; i < s->n_selector_fields; i++) {
8330 struct field *f = s->selector_fields[i];
8332 if (f->offset < first->offset)
8335 if (f->offset > last->offset)
8339 /* Selector offset and size. */
8340 params->selector_offset = first->offset / 8;
8341 params->selector_size = (last->offset + last->n_bits - first->offset) / 8;
8343 /* Memory allocation. */
8344 params->selector_mask = calloc(1, params->selector_size);
8345 if (!params->selector_mask)
8348 /* Selector mask. */
8349 for (i = 0; i < s->n_selector_fields; i++) {
8350 struct field *f = s->selector_fields[i];
8351 uint32_t start = (f->offset - first->offset) / 8;
8352 size_t size = f->n_bits / 8;
8354 memset(¶ms->selector_mask[start], 0xFF, size);
8358 params->member_id_offset = s->member_id_field->offset / 8;
8360 /* Maximum number of groups. */
8361 params->n_groups_max = s->n_groups_max;
8363 /* Maximum number of members per group. */
8364 params->n_members_per_group_max = s->n_members_per_group_max;
8369 selector_params_free(params);
8374 selector_build_free(struct rte_swx_pipeline *p)
8378 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8379 struct thread *t = &p->threads[i];
8385 for (j = 0; j < p->n_selectors; j++) {
8386 struct selector_runtime *r = &t->selectors[j];
8392 t->selectors = NULL;
8395 free(p->selector_stats);
8396 p->selector_stats = NULL;
8400 selector_build(struct rte_swx_pipeline *p)
8405 /* Per pipeline: selector statistics. */
8406 p->selector_stats = calloc(p->n_selectors, sizeof(struct selector_statistics));
8407 if (!p->selector_stats) {
8412 /* Per thread: selector run-time. */
8413 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8414 struct thread *t = &p->threads[i];
8417 t->selectors = calloc(p->n_selectors, sizeof(struct selector_runtime));
8418 if (!t->selectors) {
8423 TAILQ_FOREACH(s, &p->selectors, node) {
8424 struct selector_runtime *r = &t->selectors[s->id];
8428 size = rte_swx_table_selector_mailbox_size_get();
8430 r->mailbox = calloc(1, size);
8437 /* r->group_id_buffer. */
8438 r->group_id_buffer = &t->structs[p->metadata_struct_id];
8440 /* r->selector_buffer. */
8441 r->selector_buffer = s->selector_header ?
8442 &t->structs[s->selector_header->struct_id] :
8443 &t->structs[p->metadata_struct_id];
8445 /* r->member_id_buffer. */
8446 r->member_id_buffer = &t->structs[p->metadata_struct_id];
8453 selector_build_free(p);
8458 selector_free(struct rte_swx_pipeline *p)
8460 selector_build_free(p);
8462 /* Selector tables. */
8464 struct selector *elem;
8466 elem = TAILQ_FIRST(&p->selectors);
8470 TAILQ_REMOVE(&p->selectors, elem, node);
8471 free(elem->selector_fields);
8479 static struct learner *
8480 learner_find(struct rte_swx_pipeline *p, const char *name)
8484 TAILQ_FOREACH(l, &p->learners, node)
8485 if (!strcmp(l->name, name))
8491 static struct learner *
8492 learner_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8494 struct learner *l = NULL;
8496 TAILQ_FOREACH(l, &p->learners, node)
8504 learner_match_fields_check(struct rte_swx_pipeline *p,
8505 struct rte_swx_pipeline_learner_params *params,
8506 struct header **header)
8508 struct header *h0 = NULL;
8509 struct field *hf, *mf;
8512 /* Return if no match fields. */
8513 if (!params->n_fields || !params->field_names)
8516 /* Check that all the match fields either belong to the same header
8517 * or are all meta-data fields.
8519 hf = header_field_parse(p, params->field_names[0], &h0);
8520 mf = metadata_field_parse(p, params->field_names[0]);
8524 for (i = 1; i < params->n_fields; i++)
8528 hf = header_field_parse(p, params->field_names[i], &h);
8529 if (!hf || (h->id != h0->id))
8532 mf = metadata_field_parse(p, params->field_names[i]);
8537 /* Check that there are no duplicated match fields. */
8538 for (i = 0; i < params->n_fields; i++) {
8539 const char *field_name = params->field_names[i];
8542 for (j = i + 1; j < params->n_fields; j++)
8543 if (!strcmp(params->field_names[j], field_name))
8555 learner_action_args_check(struct rte_swx_pipeline *p, struct action *a, const char *mf_name)
8557 struct struct_type *mst = p->metadata_st, *ast = a->st;
8558 struct field *mf, *af;
8568 /* Check that mf_name is the name of a valid meta-data field. */
8569 CHECK_NAME(mf_name, EINVAL);
8570 mf = metadata_field_parse(p, mf_name);
8573 /* Check that there are enough meta-data fields, starting with the mf_name field, to cover
8574 * all the action arguments.
8576 mf_pos = mf - mst->fields;
8577 CHECK(mst->n_fields - mf_pos >= ast->n_fields, EINVAL);
8579 /* Check that the size of each of the identified meta-data fields matches exactly the size
8580 * of the corresponding action argument.
8582 for (i = 0; i < ast->n_fields; i++) {
8583 mf = &mst->fields[mf_pos + i];
8584 af = &ast->fields[i];
8586 CHECK(mf->n_bits == af->n_bits, EINVAL);
8593 learner_action_learning_check(struct rte_swx_pipeline *p,
8594 struct action *action,
8595 const char **action_names,
8600 /* For each "learn" instruction of the current action, check that the learned action (i.e.
8601 * the action passed as argument to the "learn" instruction) is also enabled for the
8602 * current learner table.
8604 for (i = 0; i < action->n_instructions; i++) {
8605 struct instruction *instr = &action->instructions[i];
8606 uint32_t found = 0, j;
8608 if (instr->type != INSTR_LEARNER_LEARN)
8611 for (j = 0; j < n_actions; j++) {
8614 a = action_find(p, action_names[j]);
8618 if (a->id == instr->learn.action_id)
8630 rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p,
8632 struct rte_swx_pipeline_learner_params *params,
8636 struct learner *l = NULL;
8637 struct action *default_action;
8638 struct header *header = NULL;
8639 uint32_t action_data_size_max = 0, i;
8644 CHECK_NAME(name, EINVAL);
8645 CHECK(!table_find(p, name), EEXIST);
8646 CHECK(!selector_find(p, name), EEXIST);
8647 CHECK(!learner_find(p, name), EEXIST);
8649 CHECK(params, EINVAL);
8652 status = learner_match_fields_check(p, params, &header);
8656 /* Action checks. */
8657 CHECK(params->n_actions, EINVAL);
8659 CHECK(params->action_names, EINVAL);
8660 for (i = 0; i < params->n_actions; i++) {
8661 const char *action_name = params->action_names[i];
8662 const char *action_field_name = params->action_field_names[i];
8664 uint32_t action_data_size;
8666 CHECK_NAME(action_name, EINVAL);
8668 a = action_find(p, action_name);
8671 status = learner_action_args_check(p, a, action_field_name);
8675 status = learner_action_learning_check(p,
8677 params->action_names,
8682 action_data_size = a->st ? a->st->n_bits / 8 : 0;
8683 if (action_data_size > action_data_size_max)
8684 action_data_size_max = action_data_size;
8687 CHECK_NAME(params->default_action_name, EINVAL);
8688 for (i = 0; i < p->n_actions; i++)
8689 if (!strcmp(params->action_names[i],
8690 params->default_action_name))
8692 CHECK(i < params->n_actions, EINVAL);
8694 default_action = action_find(p, params->default_action_name);
8695 CHECK((default_action->st && params->default_action_data) ||
8696 !params->default_action_data, EINVAL);
8698 /* Any other checks. */
8699 CHECK(size, EINVAL);
8700 CHECK(timeout, EINVAL);
8702 /* Memory allocation. */
8703 l = calloc(1, sizeof(struct learner));
8707 l->fields = calloc(params->n_fields, sizeof(struct field *));
8711 l->actions = calloc(params->n_actions, sizeof(struct action *));
8715 l->action_arg = calloc(params->n_actions, sizeof(struct field *));
8719 if (action_data_size_max) {
8720 l->default_action_data = calloc(1, action_data_size_max);
8721 if (!l->default_action_data)
8725 /* Node initialization. */
8726 strcpy(l->name, name);
8728 for (i = 0; i < params->n_fields; i++) {
8729 const char *field_name = params->field_names[i];
8731 l->fields[i] = header ?
8732 header_field_parse(p, field_name, NULL) :
8733 metadata_field_parse(p, field_name);
8736 l->n_fields = params->n_fields;
8740 for (i = 0; i < params->n_actions; i++) {
8741 const char *mf_name = params->action_field_names[i];
8743 l->actions[i] = action_find(p, params->action_names[i]);
8745 l->action_arg[i] = mf_name ? metadata_field_parse(p, mf_name) : NULL;
8748 l->default_action = default_action;
8750 if (default_action->st)
8751 memcpy(l->default_action_data,
8752 params->default_action_data,
8753 default_action->st->n_bits / 8);
8755 l->n_actions = params->n_actions;
8757 l->default_action_is_const = params->default_action_is_const;
8759 l->action_data_size_max = action_data_size_max;
8763 l->timeout = timeout;
8765 l->id = p->n_learners;
8767 /* Node add to tailq. */
8768 TAILQ_INSERT_TAIL(&p->learners, l, node);
8777 free(l->action_arg);
8786 learner_params_free(struct rte_swx_table_learner_params *params)
8791 free(params->key_mask0);
8796 static struct rte_swx_table_learner_params *
8797 learner_params_get(struct learner *l)
8799 struct rte_swx_table_learner_params *params = NULL;
8800 struct field *first, *last;
8803 /* Memory allocation. */
8804 params = calloc(1, sizeof(struct rte_swx_table_learner_params));
8808 /* Find first (smallest offset) and last (biggest offset) match fields. */
8809 first = l->fields[0];
8810 last = l->fields[0];
8812 for (i = 0; i < l->n_fields; i++) {
8813 struct field *f = l->fields[i];
8815 if (f->offset < first->offset)
8818 if (f->offset > last->offset)
8822 /* Key offset and size. */
8823 params->key_offset = first->offset / 8;
8824 params->key_size = (last->offset + last->n_bits - first->offset) / 8;
8826 /* Memory allocation. */
8827 params->key_mask0 = calloc(1, params->key_size);
8828 if (!params->key_mask0)
8832 for (i = 0; i < l->n_fields; i++) {
8833 struct field *f = l->fields[i];
8834 uint32_t start = (f->offset - first->offset) / 8;
8835 size_t size = f->n_bits / 8;
8837 memset(¶ms->key_mask0[start], 0xFF, size);
8840 /* Action data size. */
8841 params->action_data_size = l->action_data_size_max;
8843 /* Maximum number of keys. */
8844 params->n_keys_max = l->size;
8847 params->key_timeout = l->timeout;
8852 learner_params_free(params);
8857 learner_build_free(struct rte_swx_pipeline *p)
8861 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8862 struct thread *t = &p->threads[i];
8868 for (j = 0; j < p->n_learners; j++) {
8869 struct learner_runtime *r = &t->learners[j];
8872 free(r->action_data);
8879 if (p->learner_stats) {
8880 for (i = 0; i < p->n_learners; i++)
8881 free(p->learner_stats[i].n_pkts_action);
8883 free(p->learner_stats);
8888 learner_build(struct rte_swx_pipeline *p)
8893 /* Per pipeline: learner statistics. */
8894 p->learner_stats = calloc(p->n_learners, sizeof(struct learner_statistics));
8895 CHECK(p->learner_stats, ENOMEM);
8897 for (i = 0; i < p->n_learners; i++) {
8898 p->learner_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
8899 CHECK(p->learner_stats[i].n_pkts_action, ENOMEM);
8902 /* Per thread: learner run-time. */
8903 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8904 struct thread *t = &p->threads[i];
8907 t->learners = calloc(p->n_learners, sizeof(struct learner_runtime));
8913 TAILQ_FOREACH(l, &p->learners, node) {
8914 struct learner_runtime *r = &t->learners[l->id];
8919 size = rte_swx_table_learner_mailbox_size_get();
8921 r->mailbox = calloc(1, size);
8929 r->key = l->header ?
8930 &t->structs[l->header->struct_id] :
8931 &t->structs[p->metadata_struct_id];
8933 /* r->action_data. */
8934 r->action_data = calloc(p->n_actions, sizeof(uint8_t *));
8935 if (!r->action_data) {
8940 for (j = 0; j < l->n_actions; j++) {
8941 struct action *a = l->actions[j];
8942 struct field *mf = l->action_arg[j];
8943 uint8_t *m = t->structs[p->metadata_struct_id];
8945 r->action_data[a->id] = mf ? &m[mf->offset / 8] : NULL;
8953 learner_build_free(p);
8958 learner_free(struct rte_swx_pipeline *p)
8960 learner_build_free(p);
8962 /* Learner tables. */
8966 l = TAILQ_FIRST(&p->learners);
8970 TAILQ_REMOVE(&p->learners, l, node);
8973 free(l->action_arg);
8974 free(l->default_action_data);
8983 table_state_build(struct rte_swx_pipeline *p)
8985 struct table *table;
8989 p->table_state = calloc(p->n_tables + p->n_selectors,
8990 sizeof(struct rte_swx_table_state));
8991 CHECK(p->table_state, ENOMEM);
8993 TAILQ_FOREACH(table, &p->tables, node) {
8994 struct rte_swx_table_state *ts = &p->table_state[table->id];
8997 struct rte_swx_table_params *params;
9000 params = table_params_get(table);
9001 CHECK(params, ENOMEM);
9003 ts->obj = table->type->ops.create(params,
9008 table_params_free(params);
9009 CHECK(ts->obj, ENODEV);
9012 /* ts->default_action_data. */
9013 if (table->action_data_size_max) {
9014 ts->default_action_data =
9015 malloc(table->action_data_size_max);
9016 CHECK(ts->default_action_data, ENOMEM);
9018 memcpy(ts->default_action_data,
9019 table->default_action_data,
9020 table->action_data_size_max);
9023 /* ts->default_action_id. */
9024 ts->default_action_id = table->default_action->id;
9027 TAILQ_FOREACH(s, &p->selectors, node) {
9028 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + s->id];
9029 struct rte_swx_table_selector_params *params;
9032 params = selector_table_params_get(s);
9033 CHECK(params, ENOMEM);
9035 ts->obj = rte_swx_table_selector_create(params, NULL, p->numa_node);
9037 selector_params_free(params);
9038 CHECK(ts->obj, ENODEV);
9041 TAILQ_FOREACH(l, &p->learners, node) {
9042 struct rte_swx_table_state *ts = &p->table_state[p->n_tables +
9043 p->n_selectors + l->id];
9044 struct rte_swx_table_learner_params *params;
9047 params = learner_params_get(l);
9048 CHECK(params, ENOMEM);
9050 ts->obj = rte_swx_table_learner_create(params, p->numa_node);
9051 learner_params_free(params);
9052 CHECK(ts->obj, ENODEV);
9054 /* ts->default_action_data. */
9055 if (l->action_data_size_max) {
9056 ts->default_action_data = malloc(l->action_data_size_max);
9057 CHECK(ts->default_action_data, ENOMEM);
9059 memcpy(ts->default_action_data,
9060 l->default_action_data,
9061 l->action_data_size_max);
9064 /* ts->default_action_id. */
9065 ts->default_action_id = l->default_action->id;
9072 table_state_build_free(struct rte_swx_pipeline *p)
9076 if (!p->table_state)
9079 for (i = 0; i < p->n_tables; i++) {
9080 struct rte_swx_table_state *ts = &p->table_state[i];
9081 struct table *table = table_find_by_id(p, i);
9084 if (table->type && ts->obj)
9085 table->type->ops.free(ts->obj);
9087 /* ts->default_action_data. */
9088 free(ts->default_action_data);
9091 for (i = 0; i < p->n_selectors; i++) {
9092 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + i];
9096 rte_swx_table_selector_free(ts->obj);
9099 for (i = 0; i < p->n_learners; i++) {
9100 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + p->n_selectors + i];
9104 rte_swx_table_learner_free(ts->obj);
9106 /* ts->default_action_data. */
9107 free(ts->default_action_data);
9110 free(p->table_state);
9111 p->table_state = NULL;
9115 table_state_free(struct rte_swx_pipeline *p)
9117 table_state_build_free(p);
9123 static struct regarray *
9124 regarray_find(struct rte_swx_pipeline *p, const char *name)
9126 struct regarray *elem;
9128 TAILQ_FOREACH(elem, &p->regarrays, node)
9129 if (!strcmp(elem->name, name))
9135 static struct regarray *
9136 regarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9138 struct regarray *elem = NULL;
9140 TAILQ_FOREACH(elem, &p->regarrays, node)
9148 rte_swx_pipeline_regarray_config(struct rte_swx_pipeline *p,
9157 CHECK_NAME(name, EINVAL);
9158 CHECK(!regarray_find(p, name), EEXIST);
9160 CHECK(size, EINVAL);
9161 size = rte_align32pow2(size);
9163 /* Memory allocation. */
9164 r = calloc(1, sizeof(struct regarray));
9167 /* Node initialization. */
9168 strcpy(r->name, name);
9169 r->init_val = init_val;
9171 r->id = p->n_regarrays;
9173 /* Node add to tailq. */
9174 TAILQ_INSERT_TAIL(&p->regarrays, r, node);
9181 regarray_build(struct rte_swx_pipeline *p)
9183 struct regarray *regarray;
9185 if (!p->n_regarrays)
9188 p->regarray_runtime = calloc(p->n_regarrays, sizeof(struct regarray_runtime));
9189 CHECK(p->regarray_runtime, ENOMEM);
9191 TAILQ_FOREACH(regarray, &p->regarrays, node) {
9192 struct regarray_runtime *r = &p->regarray_runtime[regarray->id];
9195 r->regarray = env_malloc(regarray->size * sizeof(uint64_t),
9196 RTE_CACHE_LINE_SIZE,
9198 CHECK(r->regarray, ENOMEM);
9200 if (regarray->init_val)
9201 for (i = 0; i < regarray->size; i++)
9202 r->regarray[i] = regarray->init_val;
9204 r->size_mask = regarray->size - 1;
9211 regarray_build_free(struct rte_swx_pipeline *p)
9215 if (!p->regarray_runtime)
9218 for (i = 0; i < p->n_regarrays; i++) {
9219 struct regarray *regarray = regarray_find_by_id(p, i);
9220 struct regarray_runtime *r = &p->regarray_runtime[i];
9222 env_free(r->regarray, regarray->size * sizeof(uint64_t));
9225 free(p->regarray_runtime);
9226 p->regarray_runtime = NULL;
9230 regarray_free(struct rte_swx_pipeline *p)
9232 regarray_build_free(p);
9235 struct regarray *elem;
9237 elem = TAILQ_FIRST(&p->regarrays);
9241 TAILQ_REMOVE(&p->regarrays, elem, node);
9249 static struct meter_profile *
9250 meter_profile_find(struct rte_swx_pipeline *p, const char *name)
9252 struct meter_profile *elem;
9254 TAILQ_FOREACH(elem, &p->meter_profiles, node)
9255 if (!strcmp(elem->name, name))
9261 static struct metarray *
9262 metarray_find(struct rte_swx_pipeline *p, const char *name)
9264 struct metarray *elem;
9266 TAILQ_FOREACH(elem, &p->metarrays, node)
9267 if (!strcmp(elem->name, name))
9273 static struct metarray *
9274 metarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9276 struct metarray *elem = NULL;
9278 TAILQ_FOREACH(elem, &p->metarrays, node)
9286 rte_swx_pipeline_metarray_config(struct rte_swx_pipeline *p,
9294 CHECK_NAME(name, EINVAL);
9295 CHECK(!metarray_find(p, name), EEXIST);
9297 CHECK(size, EINVAL);
9298 size = rte_align32pow2(size);
9300 /* Memory allocation. */
9301 m = calloc(1, sizeof(struct metarray));
9304 /* Node initialization. */
9305 strcpy(m->name, name);
9307 m->id = p->n_metarrays;
9309 /* Node add to tailq. */
9310 TAILQ_INSERT_TAIL(&p->metarrays, m, node);
9316 struct meter_profile meter_profile_default = {
9325 .cir_bytes_per_period = 1,
9327 .pir_bytes_per_period = 1,
9334 meter_init(struct meter *m)
9336 memset(m, 0, sizeof(struct meter));
9337 rte_meter_trtcm_config(&m->m, &meter_profile_default.profile);
9338 m->profile = &meter_profile_default;
9339 m->color_mask = RTE_COLOR_GREEN;
9341 meter_profile_default.n_users++;
9345 metarray_build(struct rte_swx_pipeline *p)
9349 if (!p->n_metarrays)
9352 p->metarray_runtime = calloc(p->n_metarrays, sizeof(struct metarray_runtime));
9353 CHECK(p->metarray_runtime, ENOMEM);
9355 TAILQ_FOREACH(m, &p->metarrays, node) {
9356 struct metarray_runtime *r = &p->metarray_runtime[m->id];
9359 r->metarray = env_malloc(m->size * sizeof(struct meter),
9360 RTE_CACHE_LINE_SIZE,
9362 CHECK(r->metarray, ENOMEM);
9364 for (i = 0; i < m->size; i++)
9365 meter_init(&r->metarray[i]);
9367 r->size_mask = m->size - 1;
9374 metarray_build_free(struct rte_swx_pipeline *p)
9378 if (!p->metarray_runtime)
9381 for (i = 0; i < p->n_metarrays; i++) {
9382 struct metarray *m = metarray_find_by_id(p, i);
9383 struct metarray_runtime *r = &p->metarray_runtime[i];
9385 env_free(r->metarray, m->size * sizeof(struct meter));
9388 free(p->metarray_runtime);
9389 p->metarray_runtime = NULL;
9393 metarray_free(struct rte_swx_pipeline *p)
9395 metarray_build_free(p);
9399 struct metarray *elem;
9401 elem = TAILQ_FIRST(&p->metarrays);
9405 TAILQ_REMOVE(&p->metarrays, elem, node);
9409 /* Meter profiles. */
9411 struct meter_profile *elem;
9413 elem = TAILQ_FIRST(&p->meter_profiles);
9417 TAILQ_REMOVE(&p->meter_profiles, elem, node);
9426 rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
9428 struct rte_swx_pipeline *pipeline;
9430 /* Check input parameters. */
9433 /* Memory allocation. */
9434 pipeline = calloc(1, sizeof(struct rte_swx_pipeline));
9435 CHECK(pipeline, ENOMEM);
9437 /* Initialization. */
9438 TAILQ_INIT(&pipeline->struct_types);
9439 TAILQ_INIT(&pipeline->port_in_types);
9440 TAILQ_INIT(&pipeline->ports_in);
9441 TAILQ_INIT(&pipeline->port_out_types);
9442 TAILQ_INIT(&pipeline->ports_out);
9443 TAILQ_INIT(&pipeline->extern_types);
9444 TAILQ_INIT(&pipeline->extern_objs);
9445 TAILQ_INIT(&pipeline->extern_funcs);
9446 TAILQ_INIT(&pipeline->headers);
9447 TAILQ_INIT(&pipeline->actions);
9448 TAILQ_INIT(&pipeline->table_types);
9449 TAILQ_INIT(&pipeline->tables);
9450 TAILQ_INIT(&pipeline->selectors);
9451 TAILQ_INIT(&pipeline->learners);
9452 TAILQ_INIT(&pipeline->regarrays);
9453 TAILQ_INIT(&pipeline->meter_profiles);
9454 TAILQ_INIT(&pipeline->metarrays);
9456 pipeline->n_structs = 1; /* Struct 0 is reserved for action_data. */
9457 pipeline->numa_node = numa_node;
9464 rte_swx_pipeline_free(struct rte_swx_pipeline *p)
9469 free(p->instructions);
9473 table_state_free(p);
9480 extern_func_free(p);
9490 rte_swx_pipeline_instructions_config(struct rte_swx_pipeline *p,
9491 const char **instructions,
9492 uint32_t n_instructions)
9497 err = instruction_config(p, NULL, instructions, n_instructions);
9501 /* Thread instruction pointer reset. */
9502 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9503 struct thread *t = &p->threads[i];
9505 thread_ip_reset(p, t);
9512 rte_swx_pipeline_build(struct rte_swx_pipeline *p)
9517 CHECK(p->build_done == 0, EEXIST);
9519 status = port_in_build(p);
9523 status = port_out_build(p);
9527 status = struct_build(p);
9531 status = extern_obj_build(p);
9535 status = extern_func_build(p);
9539 status = header_build(p);
9543 status = metadata_build(p);
9547 status = action_build(p);
9551 status = table_build(p);
9555 status = selector_build(p);
9559 status = learner_build(p);
9563 status = table_state_build(p);
9567 status = regarray_build(p);
9571 status = metarray_build(p);
9579 metarray_build_free(p);
9580 regarray_build_free(p);
9581 table_state_build_free(p);
9582 learner_build_free(p);
9583 selector_build_free(p);
9584 table_build_free(p);
9585 action_build_free(p);
9586 metadata_build_free(p);
9587 header_build_free(p);
9588 extern_func_build_free(p);
9589 extern_obj_build_free(p);
9590 port_out_build_free(p);
9591 port_in_build_free(p);
9592 struct_build_free(p);
9598 rte_swx_pipeline_run(struct rte_swx_pipeline *p, uint32_t n_instructions)
9602 for (i = 0; i < n_instructions; i++)
9607 rte_swx_pipeline_flush(struct rte_swx_pipeline *p)
9611 for (i = 0; i < p->n_ports_out; i++) {
9612 struct port_out_runtime *port = &p->out[i];
9615 port->flush(port->obj);
9623 rte_swx_ctl_pipeline_info_get(struct rte_swx_pipeline *p,
9624 struct rte_swx_ctl_pipeline_info *pipeline)
9626 struct action *action;
9627 struct table *table;
9628 uint32_t n_actions = 0, n_tables = 0;
9630 if (!p || !pipeline)
9633 TAILQ_FOREACH(action, &p->actions, node)
9636 TAILQ_FOREACH(table, &p->tables, node)
9639 pipeline->n_ports_in = p->n_ports_in;
9640 pipeline->n_ports_out = p->n_ports_out;
9641 pipeline->n_actions = n_actions;
9642 pipeline->n_tables = n_tables;
9643 pipeline->n_selectors = p->n_selectors;
9644 pipeline->n_learners = p->n_learners;
9645 pipeline->n_regarrays = p->n_regarrays;
9646 pipeline->n_metarrays = p->n_metarrays;
9652 rte_swx_ctl_pipeline_numa_node_get(struct rte_swx_pipeline *p, int *numa_node)
9654 if (!p || !numa_node)
9657 *numa_node = p->numa_node;
9662 rte_swx_ctl_action_info_get(struct rte_swx_pipeline *p,
9664 struct rte_swx_ctl_action_info *action)
9666 struct action *a = NULL;
9668 if (!p || (action_id >= p->n_actions) || !action)
9671 a = action_find_by_id(p, action_id);
9675 strcpy(action->name, a->name);
9676 action->n_args = a->st ? a->st->n_fields : 0;
9681 rte_swx_ctl_action_arg_info_get(struct rte_swx_pipeline *p,
9683 uint32_t action_arg_id,
9684 struct rte_swx_ctl_action_arg_info *action_arg)
9686 struct action *a = NULL;
9687 struct field *arg = NULL;
9689 if (!p || (action_id >= p->n_actions) || !action_arg)
9692 a = action_find_by_id(p, action_id);
9693 if (!a || !a->st || (action_arg_id >= a->st->n_fields))
9696 arg = &a->st->fields[action_arg_id];
9697 strcpy(action_arg->name, arg->name);
9698 action_arg->n_bits = arg->n_bits;
9699 action_arg->is_network_byte_order = a->args_endianness[action_arg_id];
9705 rte_swx_ctl_table_info_get(struct rte_swx_pipeline *p,
9707 struct rte_swx_ctl_table_info *table)
9709 struct table *t = NULL;
9714 t = table_find_by_id(p, table_id);
9718 strcpy(table->name, t->name);
9719 strcpy(table->args, t->args);
9720 table->n_match_fields = t->n_fields;
9721 table->n_actions = t->n_actions;
9722 table->default_action_is_const = t->default_action_is_const;
9723 table->size = t->size;
9728 rte_swx_ctl_table_match_field_info_get(struct rte_swx_pipeline *p,
9730 uint32_t match_field_id,
9731 struct rte_swx_ctl_table_match_field_info *match_field)
9734 struct match_field *f;
9736 if (!p || (table_id >= p->n_tables) || !match_field)
9739 t = table_find_by_id(p, table_id);
9740 if (!t || (match_field_id >= t->n_fields))
9743 f = &t->fields[match_field_id];
9744 match_field->match_type = f->match_type;
9745 match_field->is_header = t->header ? 1 : 0;
9746 match_field->n_bits = f->field->n_bits;
9747 match_field->offset = f->field->offset;
9753 rte_swx_ctl_table_action_info_get(struct rte_swx_pipeline *p,
9755 uint32_t table_action_id,
9756 struct rte_swx_ctl_table_action_info *table_action)
9760 if (!p || (table_id >= p->n_tables) || !table_action)
9763 t = table_find_by_id(p, table_id);
9764 if (!t || (table_action_id >= t->n_actions))
9767 table_action->action_id = t->actions[table_action_id]->id;
9773 rte_swx_ctl_table_ops_get(struct rte_swx_pipeline *p,
9775 struct rte_swx_table_ops *table_ops,
9780 if (!p || (table_id >= p->n_tables))
9783 t = table_find_by_id(p, table_id);
9789 memcpy(table_ops, &t->type->ops, sizeof(*table_ops));
9799 rte_swx_ctl_selector_info_get(struct rte_swx_pipeline *p,
9800 uint32_t selector_id,
9801 struct rte_swx_ctl_selector_info *selector)
9803 struct selector *s = NULL;
9805 if (!p || !selector)
9808 s = selector_find_by_id(p, selector_id);
9812 strcpy(selector->name, s->name);
9814 selector->n_selector_fields = s->n_selector_fields;
9815 selector->n_groups_max = s->n_groups_max;
9816 selector->n_members_per_group_max = s->n_members_per_group_max;
9822 rte_swx_ctl_selector_group_id_field_info_get(struct rte_swx_pipeline *p,
9823 uint32_t selector_id,
9824 struct rte_swx_ctl_table_match_field_info *field)
9828 if (!p || (selector_id >= p->n_selectors) || !field)
9831 s = selector_find_by_id(p, selector_id);
9835 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
9836 field->is_header = 0;
9837 field->n_bits = s->group_id_field->n_bits;
9838 field->offset = s->group_id_field->offset;
9844 rte_swx_ctl_selector_field_info_get(struct rte_swx_pipeline *p,
9845 uint32_t selector_id,
9846 uint32_t selector_field_id,
9847 struct rte_swx_ctl_table_match_field_info *field)
9852 if (!p || (selector_id >= p->n_selectors) || !field)
9855 s = selector_find_by_id(p, selector_id);
9856 if (!s || (selector_field_id >= s->n_selector_fields))
9859 f = s->selector_fields[selector_field_id];
9860 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
9861 field->is_header = s->selector_header ? 1 : 0;
9862 field->n_bits = f->n_bits;
9863 field->offset = f->offset;
9869 rte_swx_ctl_selector_member_id_field_info_get(struct rte_swx_pipeline *p,
9870 uint32_t selector_id,
9871 struct rte_swx_ctl_table_match_field_info *field)
9875 if (!p || (selector_id >= p->n_selectors) || !field)
9878 s = selector_find_by_id(p, selector_id);
9882 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
9883 field->is_header = 0;
9884 field->n_bits = s->member_id_field->n_bits;
9885 field->offset = s->member_id_field->offset;
9891 rte_swx_ctl_learner_info_get(struct rte_swx_pipeline *p,
9892 uint32_t learner_id,
9893 struct rte_swx_ctl_learner_info *learner)
9895 struct learner *l = NULL;
9900 l = learner_find_by_id(p, learner_id);
9904 strcpy(learner->name, l->name);
9906 learner->n_match_fields = l->n_fields;
9907 learner->n_actions = l->n_actions;
9908 learner->default_action_is_const = l->default_action_is_const;
9909 learner->size = l->size;
9915 rte_swx_ctl_learner_match_field_info_get(struct rte_swx_pipeline *p,
9916 uint32_t learner_id,
9917 uint32_t match_field_id,
9918 struct rte_swx_ctl_table_match_field_info *match_field)
9923 if (!p || (learner_id >= p->n_learners) || !match_field)
9926 l = learner_find_by_id(p, learner_id);
9927 if (!l || (match_field_id >= l->n_fields))
9930 f = l->fields[match_field_id];
9931 match_field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
9932 match_field->is_header = l->header ? 1 : 0;
9933 match_field->n_bits = f->n_bits;
9934 match_field->offset = f->offset;
9940 rte_swx_ctl_learner_action_info_get(struct rte_swx_pipeline *p,
9941 uint32_t learner_id,
9942 uint32_t learner_action_id,
9943 struct rte_swx_ctl_table_action_info *learner_action)
9947 if (!p || (learner_id >= p->n_learners) || !learner_action)
9950 l = learner_find_by_id(p, learner_id);
9951 if (!l || (learner_action_id >= l->n_actions))
9954 learner_action->action_id = l->actions[learner_action_id]->id;
9960 rte_swx_pipeline_table_state_get(struct rte_swx_pipeline *p,
9961 struct rte_swx_table_state **table_state)
9963 if (!p || !table_state || !p->build_done)
9966 *table_state = p->table_state;
9971 rte_swx_pipeline_table_state_set(struct rte_swx_pipeline *p,
9972 struct rte_swx_table_state *table_state)
9974 if (!p || !table_state || !p->build_done)
9977 p->table_state = table_state;
9982 rte_swx_ctl_pipeline_port_in_stats_read(struct rte_swx_pipeline *p,
9984 struct rte_swx_port_in_stats *stats)
9986 struct port_in *port;
9991 port = port_in_find(p, port_id);
9995 port->type->ops.stats_read(port->obj, stats);
10000 rte_swx_ctl_pipeline_port_out_stats_read(struct rte_swx_pipeline *p,
10002 struct rte_swx_port_out_stats *stats)
10004 struct port_out *port;
10009 port = port_out_find(p, port_id);
10013 port->type->ops.stats_read(port->obj, stats);
10018 rte_swx_ctl_pipeline_table_stats_read(struct rte_swx_pipeline *p,
10019 const char *table_name,
10020 struct rte_swx_table_stats *stats)
10022 struct table *table;
10023 struct table_statistics *table_stats;
10025 if (!p || !table_name || !table_name[0] || !stats || !stats->n_pkts_action)
10028 table = table_find(p, table_name);
10032 table_stats = &p->table_stats[table->id];
10034 memcpy(stats->n_pkts_action,
10035 table_stats->n_pkts_action,
10036 p->n_actions * sizeof(uint64_t));
10038 stats->n_pkts_hit = table_stats->n_pkts_hit[1];
10039 stats->n_pkts_miss = table_stats->n_pkts_hit[0];
10045 rte_swx_ctl_pipeline_selector_stats_read(struct rte_swx_pipeline *p,
10046 const char *selector_name,
10047 struct rte_swx_pipeline_selector_stats *stats)
10049 struct selector *s;
10051 if (!p || !selector_name || !selector_name[0] || !stats)
10054 s = selector_find(p, selector_name);
10058 stats->n_pkts = p->selector_stats[s->id].n_pkts;
10064 rte_swx_ctl_pipeline_learner_stats_read(struct rte_swx_pipeline *p,
10065 const char *learner_name,
10066 struct rte_swx_learner_stats *stats)
10069 struct learner_statistics *learner_stats;
10071 if (!p || !learner_name || !learner_name[0] || !stats || !stats->n_pkts_action)
10074 l = learner_find(p, learner_name);
10078 learner_stats = &p->learner_stats[l->id];
10080 memcpy(stats->n_pkts_action,
10081 learner_stats->n_pkts_action,
10082 p->n_actions * sizeof(uint64_t));
10084 stats->n_pkts_hit = learner_stats->n_pkts_hit[1];
10085 stats->n_pkts_miss = learner_stats->n_pkts_hit[0];
10087 stats->n_pkts_learn_ok = learner_stats->n_pkts_learn[0];
10088 stats->n_pkts_learn_err = learner_stats->n_pkts_learn[1];
10090 stats->n_pkts_forget = learner_stats->n_pkts_forget;
10096 rte_swx_ctl_regarray_info_get(struct rte_swx_pipeline *p,
10097 uint32_t regarray_id,
10098 struct rte_swx_ctl_regarray_info *regarray)
10100 struct regarray *r;
10102 if (!p || !regarray)
10105 r = regarray_find_by_id(p, regarray_id);
10109 strcpy(regarray->name, r->name);
10110 regarray->size = r->size;
10115 rte_swx_ctl_pipeline_regarray_read(struct rte_swx_pipeline *p,
10116 const char *regarray_name,
10117 uint32_t regarray_index,
10120 struct regarray *regarray;
10121 struct regarray_runtime *r;
10123 if (!p || !regarray_name || !value)
10126 regarray = regarray_find(p, regarray_name);
10127 if (!regarray || (regarray_index >= regarray->size))
10130 r = &p->regarray_runtime[regarray->id];
10131 *value = r->regarray[regarray_index];
10136 rte_swx_ctl_pipeline_regarray_write(struct rte_swx_pipeline *p,
10137 const char *regarray_name,
10138 uint32_t regarray_index,
10141 struct regarray *regarray;
10142 struct regarray_runtime *r;
10144 if (!p || !regarray_name)
10147 regarray = regarray_find(p, regarray_name);
10148 if (!regarray || (regarray_index >= regarray->size))
10151 r = &p->regarray_runtime[regarray->id];
10152 r->regarray[regarray_index] = value;
10157 rte_swx_ctl_metarray_info_get(struct rte_swx_pipeline *p,
10158 uint32_t metarray_id,
10159 struct rte_swx_ctl_metarray_info *metarray)
10161 struct metarray *m;
10163 if (!p || !metarray)
10166 m = metarray_find_by_id(p, metarray_id);
10170 strcpy(metarray->name, m->name);
10171 metarray->size = m->size;
10176 rte_swx_ctl_meter_profile_add(struct rte_swx_pipeline *p,
10178 struct rte_meter_trtcm_params *params)
10180 struct meter_profile *mp;
10184 CHECK_NAME(name, EINVAL);
10185 CHECK(params, EINVAL);
10186 CHECK(!meter_profile_find(p, name), EEXIST);
10188 /* Node allocation. */
10189 mp = calloc(1, sizeof(struct meter_profile));
10192 /* Node initialization. */
10193 strcpy(mp->name, name);
10194 memcpy(&mp->params, params, sizeof(struct rte_meter_trtcm_params));
10195 status = rte_meter_trtcm_profile_config(&mp->profile, params);
10201 /* Node add to tailq. */
10202 TAILQ_INSERT_TAIL(&p->meter_profiles, mp, node);
10208 rte_swx_ctl_meter_profile_delete(struct rte_swx_pipeline *p,
10211 struct meter_profile *mp;
10214 CHECK_NAME(name, EINVAL);
10216 mp = meter_profile_find(p, name);
10218 CHECK(!mp->n_users, EBUSY);
10220 /* Remove node from tailq. */
10221 TAILQ_REMOVE(&p->meter_profiles, mp, node);
10228 rte_swx_ctl_meter_reset(struct rte_swx_pipeline *p,
10229 const char *metarray_name,
10230 uint32_t metarray_index)
10232 struct meter_profile *mp_old;
10233 struct metarray *metarray;
10234 struct metarray_runtime *metarray_runtime;
10238 CHECK_NAME(metarray_name, EINVAL);
10240 metarray = metarray_find(p, metarray_name);
10241 CHECK(metarray, EINVAL);
10242 CHECK(metarray_index < metarray->size, EINVAL);
10244 metarray_runtime = &p->metarray_runtime[metarray->id];
10245 m = &metarray_runtime->metarray[metarray_index];
10246 mp_old = m->profile;
10256 rte_swx_ctl_meter_set(struct rte_swx_pipeline *p,
10257 const char *metarray_name,
10258 uint32_t metarray_index,
10259 const char *profile_name)
10261 struct meter_profile *mp, *mp_old;
10262 struct metarray *metarray;
10263 struct metarray_runtime *metarray_runtime;
10267 CHECK_NAME(metarray_name, EINVAL);
10269 metarray = metarray_find(p, metarray_name);
10270 CHECK(metarray, EINVAL);
10271 CHECK(metarray_index < metarray->size, EINVAL);
10273 mp = meter_profile_find(p, profile_name);
10276 metarray_runtime = &p->metarray_runtime[metarray->id];
10277 m = &metarray_runtime->metarray[metarray_index];
10278 mp_old = m->profile;
10280 memset(m, 0, sizeof(struct meter));
10281 rte_meter_trtcm_config(&m->m, &mp->profile);
10283 m->color_mask = RTE_COLORS;
10292 rte_swx_ctl_meter_stats_read(struct rte_swx_pipeline *p,
10293 const char *metarray_name,
10294 uint32_t metarray_index,
10295 struct rte_swx_ctl_meter_stats *stats)
10297 struct metarray *metarray;
10298 struct metarray_runtime *metarray_runtime;
10302 CHECK_NAME(metarray_name, EINVAL);
10304 metarray = metarray_find(p, metarray_name);
10305 CHECK(metarray, EINVAL);
10306 CHECK(metarray_index < metarray->size, EINVAL);
10308 CHECK(stats, EINVAL);
10310 metarray_runtime = &p->metarray_runtime[metarray->id];
10311 m = &metarray_runtime->metarray[metarray_index];
10313 memcpy(stats->n_pkts, m->n_pkts, sizeof(m->n_pkts));
10314 memcpy(stats->n_bytes, m->n_bytes, sizeof(m->n_bytes));