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;
2320 uint32_t obj_id = ip->ext_obj.ext_obj_id;
2321 uint32_t func_id = ip->ext_obj.func_id;
2322 struct extern_obj_runtime *obj = &t->extern_objs[obj_id];
2323 rte_swx_extern_type_member_func_t func = obj->funcs[func_id];
2325 TRACE("[Thread %2u] extern obj %u member func %u\n",
2330 /* Extern object member function execute. */
2331 uint32_t done = func(obj->obj, obj->mailbox);
2334 thread_ip_inc_cond(t, done);
2335 thread_yield_cond(p, done ^ 1);
2339 instr_extern_func_exec(struct rte_swx_pipeline *p)
2341 struct thread *t = &p->threads[p->thread_id];
2342 struct instruction *ip = t->ip;
2343 uint32_t ext_func_id = ip->ext_func.ext_func_id;
2344 struct extern_func_runtime *ext_func = &t->extern_funcs[ext_func_id];
2345 rte_swx_extern_func_t func = ext_func->func;
2347 TRACE("[Thread %2u] extern func %u\n",
2351 /* Extern function execute. */
2352 uint32_t done = func(ext_func->mailbox);
2355 thread_ip_inc_cond(t, done);
2356 thread_yield_cond(p, done ^ 1);
2363 instr_mov_translate(struct rte_swx_pipeline *p,
2364 struct action *action,
2367 struct instruction *instr,
2368 struct instruction_data *data __rte_unused)
2370 char *dst = tokens[1], *src = tokens[2];
2371 struct field *fdst, *fsrc;
2373 uint32_t dst_struct_id = 0, src_struct_id = 0;
2375 CHECK(n_tokens == 3, EINVAL);
2377 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2378 CHECK(fdst, EINVAL);
2379 CHECK(!fdst->var_size, EINVAL);
2381 /* MOV, MOV_MH, MOV_HM or MOV_HH. */
2382 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2384 CHECK(!fsrc->var_size, EINVAL);
2386 instr->type = INSTR_MOV;
2387 if (dst[0] != 'h' && src[0] == 'h')
2388 instr->type = INSTR_MOV_MH;
2389 if (dst[0] == 'h' && src[0] != 'h')
2390 instr->type = INSTR_MOV_HM;
2391 if (dst[0] == 'h' && src[0] == 'h')
2392 instr->type = INSTR_MOV_HH;
2394 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
2395 instr->mov.dst.n_bits = fdst->n_bits;
2396 instr->mov.dst.offset = fdst->offset / 8;
2397 instr->mov.src.struct_id = (uint8_t)src_struct_id;
2398 instr->mov.src.n_bits = fsrc->n_bits;
2399 instr->mov.src.offset = fsrc->offset / 8;
2404 src_val = strtoull(src, &src, 0);
2405 CHECK(!src[0], EINVAL);
2408 src_val = hton64(src_val) >> (64 - fdst->n_bits);
2410 instr->type = INSTR_MOV_I;
2411 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
2412 instr->mov.dst.n_bits = fdst->n_bits;
2413 instr->mov.dst.offset = fdst->offset / 8;
2414 instr->mov.src_val = src_val;
2419 instr_mov_exec(struct rte_swx_pipeline *p)
2421 struct thread *t = &p->threads[p->thread_id];
2422 struct instruction *ip = t->ip;
2424 TRACE("[Thread %2u] mov\n",
2434 instr_mov_mh_exec(struct rte_swx_pipeline *p)
2436 struct thread *t = &p->threads[p->thread_id];
2437 struct instruction *ip = t->ip;
2439 TRACE("[Thread %2u] mov (mh)\n",
2449 instr_mov_hm_exec(struct rte_swx_pipeline *p)
2451 struct thread *t = &p->threads[p->thread_id];
2452 struct instruction *ip = t->ip;
2454 TRACE("[Thread %2u] mov (hm)\n",
2464 instr_mov_hh_exec(struct rte_swx_pipeline *p)
2466 struct thread *t = &p->threads[p->thread_id];
2467 struct instruction *ip = t->ip;
2469 TRACE("[Thread %2u] mov (hh)\n",
2479 instr_mov_i_exec(struct rte_swx_pipeline *p)
2481 struct thread *t = &p->threads[p->thread_id];
2482 struct instruction *ip = t->ip;
2484 TRACE("[Thread %2u] mov m.f %" PRIx64 "\n",
2498 __instr_dma_ht_exec(struct rte_swx_pipeline *p, uint32_t n_dma);
2501 __instr_dma_ht_exec(struct rte_swx_pipeline *p, uint32_t n_dma)
2503 struct thread *t = &p->threads[p->thread_id];
2504 struct instruction *ip = t->ip;
2505 uint8_t *action_data = t->structs[0];
2506 uint64_t valid_headers = t->valid_headers;
2509 for (i = 0; i < n_dma; i++) {
2510 uint32_t header_id = ip->dma.dst.header_id[i];
2511 uint32_t struct_id = ip->dma.dst.struct_id[i];
2512 uint32_t offset = ip->dma.src.offset[i];
2513 uint32_t n_bytes = ip->dma.n_bytes[i];
2515 struct header_runtime *h = &t->headers[header_id];
2516 uint8_t *h_ptr0 = h->ptr0;
2517 uint8_t *h_ptr = t->structs[struct_id];
2519 void *dst = MASK64_BIT_GET(valid_headers, header_id) ?
2521 void *src = &action_data[offset];
2523 TRACE("[Thread %2u] dma h.s t.f\n", p->thread_id);
2526 memcpy(dst, src, n_bytes);
2527 t->structs[struct_id] = dst;
2528 valid_headers = MASK64_BIT_SET(valid_headers, header_id);
2531 t->valid_headers = valid_headers;
2535 instr_dma_ht_exec(struct rte_swx_pipeline *p)
2537 __instr_dma_ht_exec(p, 1);
2544 instr_dma_ht2_exec(struct rte_swx_pipeline *p)
2546 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n",
2549 __instr_dma_ht_exec(p, 2);
2556 instr_dma_ht3_exec(struct rte_swx_pipeline *p)
2558 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n",
2561 __instr_dma_ht_exec(p, 3);
2568 instr_dma_ht4_exec(struct rte_swx_pipeline *p)
2570 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n",
2573 __instr_dma_ht_exec(p, 4);
2580 instr_dma_ht5_exec(struct rte_swx_pipeline *p)
2582 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n",
2585 __instr_dma_ht_exec(p, 5);
2592 instr_dma_ht6_exec(struct rte_swx_pipeline *p)
2594 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n",
2597 __instr_dma_ht_exec(p, 6);
2604 instr_dma_ht7_exec(struct rte_swx_pipeline *p)
2606 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n",
2609 __instr_dma_ht_exec(p, 7);
2616 instr_dma_ht8_exec(struct rte_swx_pipeline *p)
2618 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n",
2621 __instr_dma_ht_exec(p, 8);
2631 instr_alu_add_translate(struct rte_swx_pipeline *p,
2632 struct action *action,
2635 struct instruction *instr,
2636 struct instruction_data *data __rte_unused)
2638 char *dst = tokens[1], *src = tokens[2];
2639 struct field *fdst, *fsrc;
2641 uint32_t dst_struct_id = 0, src_struct_id = 0;
2643 CHECK(n_tokens == 3, EINVAL);
2645 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2646 CHECK(fdst, EINVAL);
2647 CHECK(!fdst->var_size, EINVAL);
2649 /* ADD, ADD_HM, ADD_MH, ADD_HH. */
2650 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2652 CHECK(!fsrc->var_size, EINVAL);
2654 instr->type = INSTR_ALU_ADD;
2655 if (dst[0] == 'h' && src[0] != 'h')
2656 instr->type = INSTR_ALU_ADD_HM;
2657 if (dst[0] != 'h' && src[0] == 'h')
2658 instr->type = INSTR_ALU_ADD_MH;
2659 if (dst[0] == 'h' && src[0] == 'h')
2660 instr->type = INSTR_ALU_ADD_HH;
2662 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2663 instr->alu.dst.n_bits = fdst->n_bits;
2664 instr->alu.dst.offset = fdst->offset / 8;
2665 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2666 instr->alu.src.n_bits = fsrc->n_bits;
2667 instr->alu.src.offset = fsrc->offset / 8;
2671 /* ADD_MI, ADD_HI. */
2672 src_val = strtoull(src, &src, 0);
2673 CHECK(!src[0], EINVAL);
2675 instr->type = INSTR_ALU_ADD_MI;
2677 instr->type = INSTR_ALU_ADD_HI;
2679 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2680 instr->alu.dst.n_bits = fdst->n_bits;
2681 instr->alu.dst.offset = fdst->offset / 8;
2682 instr->alu.src_val = src_val;
2687 instr_alu_sub_translate(struct rte_swx_pipeline *p,
2688 struct action *action,
2691 struct instruction *instr,
2692 struct instruction_data *data __rte_unused)
2694 char *dst = tokens[1], *src = tokens[2];
2695 struct field *fdst, *fsrc;
2697 uint32_t dst_struct_id = 0, src_struct_id = 0;
2699 CHECK(n_tokens == 3, EINVAL);
2701 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2702 CHECK(fdst, EINVAL);
2703 CHECK(!fdst->var_size, EINVAL);
2705 /* SUB, SUB_HM, SUB_MH, SUB_HH. */
2706 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2708 CHECK(!fsrc->var_size, EINVAL);
2710 instr->type = INSTR_ALU_SUB;
2711 if (dst[0] == 'h' && src[0] != 'h')
2712 instr->type = INSTR_ALU_SUB_HM;
2713 if (dst[0] != 'h' && src[0] == 'h')
2714 instr->type = INSTR_ALU_SUB_MH;
2715 if (dst[0] == 'h' && src[0] == 'h')
2716 instr->type = INSTR_ALU_SUB_HH;
2718 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2719 instr->alu.dst.n_bits = fdst->n_bits;
2720 instr->alu.dst.offset = fdst->offset / 8;
2721 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2722 instr->alu.src.n_bits = fsrc->n_bits;
2723 instr->alu.src.offset = fsrc->offset / 8;
2727 /* SUB_MI, SUB_HI. */
2728 src_val = strtoull(src, &src, 0);
2729 CHECK(!src[0], EINVAL);
2731 instr->type = INSTR_ALU_SUB_MI;
2733 instr->type = INSTR_ALU_SUB_HI;
2735 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2736 instr->alu.dst.n_bits = fdst->n_bits;
2737 instr->alu.dst.offset = fdst->offset / 8;
2738 instr->alu.src_val = src_val;
2743 instr_alu_ckadd_translate(struct rte_swx_pipeline *p,
2744 struct action *action __rte_unused,
2747 struct instruction *instr,
2748 struct instruction_data *data __rte_unused)
2750 char *dst = tokens[1], *src = tokens[2];
2751 struct header *hdst, *hsrc;
2752 struct field *fdst, *fsrc;
2754 CHECK(n_tokens == 3, EINVAL);
2756 fdst = header_field_parse(p, dst, &hdst);
2757 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
2758 CHECK(!fdst->var_size, EINVAL);
2761 fsrc = header_field_parse(p, src, &hsrc);
2763 CHECK(!fsrc->var_size, EINVAL);
2765 instr->type = INSTR_ALU_CKADD_FIELD;
2766 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2767 instr->alu.dst.n_bits = fdst->n_bits;
2768 instr->alu.dst.offset = fdst->offset / 8;
2769 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2770 instr->alu.src.n_bits = fsrc->n_bits;
2771 instr->alu.src.offset = fsrc->offset / 8;
2775 /* CKADD_STRUCT, CKADD_STRUCT20. */
2776 hsrc = header_parse(p, src);
2777 CHECK(hsrc, EINVAL);
2778 CHECK(!hsrc->st->var_size, EINVAL);
2780 instr->type = INSTR_ALU_CKADD_STRUCT;
2781 if ((hsrc->st->n_bits / 8) == 20)
2782 instr->type = INSTR_ALU_CKADD_STRUCT20;
2784 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2785 instr->alu.dst.n_bits = fdst->n_bits;
2786 instr->alu.dst.offset = fdst->offset / 8;
2787 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2788 instr->alu.src.n_bits = hsrc->st->n_bits;
2789 instr->alu.src.offset = 0; /* Unused. */
2794 instr_alu_cksub_translate(struct rte_swx_pipeline *p,
2795 struct action *action __rte_unused,
2798 struct instruction *instr,
2799 struct instruction_data *data __rte_unused)
2801 char *dst = tokens[1], *src = tokens[2];
2802 struct header *hdst, *hsrc;
2803 struct field *fdst, *fsrc;
2805 CHECK(n_tokens == 3, EINVAL);
2807 fdst = header_field_parse(p, dst, &hdst);
2808 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
2809 CHECK(!fdst->var_size, EINVAL);
2811 fsrc = header_field_parse(p, src, &hsrc);
2812 CHECK(fsrc, EINVAL);
2813 CHECK(!fsrc->var_size, EINVAL);
2815 instr->type = INSTR_ALU_CKSUB_FIELD;
2816 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2817 instr->alu.dst.n_bits = fdst->n_bits;
2818 instr->alu.dst.offset = fdst->offset / 8;
2819 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2820 instr->alu.src.n_bits = fsrc->n_bits;
2821 instr->alu.src.offset = fsrc->offset / 8;
2826 instr_alu_shl_translate(struct rte_swx_pipeline *p,
2827 struct action *action,
2830 struct instruction *instr,
2831 struct instruction_data *data __rte_unused)
2833 char *dst = tokens[1], *src = tokens[2];
2834 struct field *fdst, *fsrc;
2836 uint32_t dst_struct_id = 0, src_struct_id = 0;
2838 CHECK(n_tokens == 3, EINVAL);
2840 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2841 CHECK(fdst, EINVAL);
2842 CHECK(!fdst->var_size, EINVAL);
2844 /* SHL, SHL_HM, SHL_MH, SHL_HH. */
2845 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2847 CHECK(!fsrc->var_size, EINVAL);
2849 instr->type = INSTR_ALU_SHL;
2850 if (dst[0] == 'h' && src[0] != 'h')
2851 instr->type = INSTR_ALU_SHL_HM;
2852 if (dst[0] != 'h' && src[0] == 'h')
2853 instr->type = INSTR_ALU_SHL_MH;
2854 if (dst[0] == 'h' && src[0] == 'h')
2855 instr->type = INSTR_ALU_SHL_HH;
2857 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2858 instr->alu.dst.n_bits = fdst->n_bits;
2859 instr->alu.dst.offset = fdst->offset / 8;
2860 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2861 instr->alu.src.n_bits = fsrc->n_bits;
2862 instr->alu.src.offset = fsrc->offset / 8;
2866 /* SHL_MI, SHL_HI. */
2867 src_val = strtoull(src, &src, 0);
2868 CHECK(!src[0], EINVAL);
2870 instr->type = INSTR_ALU_SHL_MI;
2872 instr->type = INSTR_ALU_SHL_HI;
2874 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2875 instr->alu.dst.n_bits = fdst->n_bits;
2876 instr->alu.dst.offset = fdst->offset / 8;
2877 instr->alu.src_val = src_val;
2882 instr_alu_shr_translate(struct rte_swx_pipeline *p,
2883 struct action *action,
2886 struct instruction *instr,
2887 struct instruction_data *data __rte_unused)
2889 char *dst = tokens[1], *src = tokens[2];
2890 struct field *fdst, *fsrc;
2892 uint32_t dst_struct_id = 0, src_struct_id = 0;
2894 CHECK(n_tokens == 3, EINVAL);
2896 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2897 CHECK(fdst, EINVAL);
2898 CHECK(!fdst->var_size, EINVAL);
2900 /* SHR, SHR_HM, SHR_MH, SHR_HH. */
2901 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2903 CHECK(!fsrc->var_size, EINVAL);
2905 instr->type = INSTR_ALU_SHR;
2906 if (dst[0] == 'h' && src[0] != 'h')
2907 instr->type = INSTR_ALU_SHR_HM;
2908 if (dst[0] != 'h' && src[0] == 'h')
2909 instr->type = INSTR_ALU_SHR_MH;
2910 if (dst[0] == 'h' && src[0] == 'h')
2911 instr->type = INSTR_ALU_SHR_HH;
2913 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2914 instr->alu.dst.n_bits = fdst->n_bits;
2915 instr->alu.dst.offset = fdst->offset / 8;
2916 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2917 instr->alu.src.n_bits = fsrc->n_bits;
2918 instr->alu.src.offset = fsrc->offset / 8;
2922 /* SHR_MI, SHR_HI. */
2923 src_val = strtoull(src, &src, 0);
2924 CHECK(!src[0], EINVAL);
2926 instr->type = INSTR_ALU_SHR_MI;
2928 instr->type = INSTR_ALU_SHR_HI;
2930 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2931 instr->alu.dst.n_bits = fdst->n_bits;
2932 instr->alu.dst.offset = fdst->offset / 8;
2933 instr->alu.src_val = src_val;
2938 instr_alu_and_translate(struct rte_swx_pipeline *p,
2939 struct action *action,
2942 struct instruction *instr,
2943 struct instruction_data *data __rte_unused)
2945 char *dst = tokens[1], *src = tokens[2];
2946 struct field *fdst, *fsrc;
2948 uint32_t dst_struct_id = 0, src_struct_id = 0;
2950 CHECK(n_tokens == 3, EINVAL);
2952 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2953 CHECK(fdst, EINVAL);
2954 CHECK(!fdst->var_size, EINVAL);
2956 /* AND, AND_MH, AND_HM, AND_HH. */
2957 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2959 CHECK(!fsrc->var_size, EINVAL);
2961 instr->type = INSTR_ALU_AND;
2962 if (dst[0] != 'h' && src[0] == 'h')
2963 instr->type = INSTR_ALU_AND_MH;
2964 if (dst[0] == 'h' && src[0] != 'h')
2965 instr->type = INSTR_ALU_AND_HM;
2966 if (dst[0] == 'h' && src[0] == 'h')
2967 instr->type = INSTR_ALU_AND_HH;
2969 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2970 instr->alu.dst.n_bits = fdst->n_bits;
2971 instr->alu.dst.offset = fdst->offset / 8;
2972 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2973 instr->alu.src.n_bits = fsrc->n_bits;
2974 instr->alu.src.offset = fsrc->offset / 8;
2979 src_val = strtoull(src, &src, 0);
2980 CHECK(!src[0], EINVAL);
2983 src_val = hton64(src_val) >> (64 - fdst->n_bits);
2985 instr->type = INSTR_ALU_AND_I;
2986 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2987 instr->alu.dst.n_bits = fdst->n_bits;
2988 instr->alu.dst.offset = fdst->offset / 8;
2989 instr->alu.src_val = src_val;
2994 instr_alu_or_translate(struct rte_swx_pipeline *p,
2995 struct action *action,
2998 struct instruction *instr,
2999 struct instruction_data *data __rte_unused)
3001 char *dst = tokens[1], *src = tokens[2];
3002 struct field *fdst, *fsrc;
3004 uint32_t dst_struct_id = 0, src_struct_id = 0;
3006 CHECK(n_tokens == 3, EINVAL);
3008 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3009 CHECK(fdst, EINVAL);
3010 CHECK(!fdst->var_size, EINVAL);
3012 /* OR, OR_MH, OR_HM, OR_HH. */
3013 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3015 CHECK(!fsrc->var_size, EINVAL);
3017 instr->type = INSTR_ALU_OR;
3018 if (dst[0] != 'h' && src[0] == 'h')
3019 instr->type = INSTR_ALU_OR_MH;
3020 if (dst[0] == 'h' && src[0] != 'h')
3021 instr->type = INSTR_ALU_OR_HM;
3022 if (dst[0] == 'h' && src[0] == 'h')
3023 instr->type = INSTR_ALU_OR_HH;
3025 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3026 instr->alu.dst.n_bits = fdst->n_bits;
3027 instr->alu.dst.offset = fdst->offset / 8;
3028 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3029 instr->alu.src.n_bits = fsrc->n_bits;
3030 instr->alu.src.offset = fsrc->offset / 8;
3035 src_val = strtoull(src, &src, 0);
3036 CHECK(!src[0], EINVAL);
3039 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3041 instr->type = INSTR_ALU_OR_I;
3042 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3043 instr->alu.dst.n_bits = fdst->n_bits;
3044 instr->alu.dst.offset = fdst->offset / 8;
3045 instr->alu.src_val = src_val;
3050 instr_alu_xor_translate(struct rte_swx_pipeline *p,
3051 struct action *action,
3054 struct instruction *instr,
3055 struct instruction_data *data __rte_unused)
3057 char *dst = tokens[1], *src = tokens[2];
3058 struct field *fdst, *fsrc;
3060 uint32_t dst_struct_id = 0, src_struct_id = 0;
3062 CHECK(n_tokens == 3, EINVAL);
3064 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3065 CHECK(fdst, EINVAL);
3066 CHECK(!fdst->var_size, EINVAL);
3068 /* XOR, XOR_MH, XOR_HM, XOR_HH. */
3069 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3071 CHECK(!fsrc->var_size, EINVAL);
3073 instr->type = INSTR_ALU_XOR;
3074 if (dst[0] != 'h' && src[0] == 'h')
3075 instr->type = INSTR_ALU_XOR_MH;
3076 if (dst[0] == 'h' && src[0] != 'h')
3077 instr->type = INSTR_ALU_XOR_HM;
3078 if (dst[0] == 'h' && src[0] == 'h')
3079 instr->type = INSTR_ALU_XOR_HH;
3081 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3082 instr->alu.dst.n_bits = fdst->n_bits;
3083 instr->alu.dst.offset = fdst->offset / 8;
3084 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3085 instr->alu.src.n_bits = fsrc->n_bits;
3086 instr->alu.src.offset = fsrc->offset / 8;
3091 src_val = strtoull(src, &src, 0);
3092 CHECK(!src[0], EINVAL);
3095 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3097 instr->type = INSTR_ALU_XOR_I;
3098 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3099 instr->alu.dst.n_bits = fdst->n_bits;
3100 instr->alu.dst.offset = fdst->offset / 8;
3101 instr->alu.src_val = src_val;
3106 instr_alu_add_exec(struct rte_swx_pipeline *p)
3108 struct thread *t = &p->threads[p->thread_id];
3109 struct instruction *ip = t->ip;
3111 TRACE("[Thread %2u] add\n", p->thread_id);
3121 instr_alu_add_mh_exec(struct rte_swx_pipeline *p)
3123 struct thread *t = &p->threads[p->thread_id];
3124 struct instruction *ip = t->ip;
3126 TRACE("[Thread %2u] add (mh)\n", p->thread_id);
3136 instr_alu_add_hm_exec(struct rte_swx_pipeline *p)
3138 struct thread *t = &p->threads[p->thread_id];
3139 struct instruction *ip = t->ip;
3141 TRACE("[Thread %2u] add (hm)\n", p->thread_id);
3151 instr_alu_add_hh_exec(struct rte_swx_pipeline *p)
3153 struct thread *t = &p->threads[p->thread_id];
3154 struct instruction *ip = t->ip;
3156 TRACE("[Thread %2u] add (hh)\n", p->thread_id);
3166 instr_alu_add_mi_exec(struct rte_swx_pipeline *p)
3168 struct thread *t = &p->threads[p->thread_id];
3169 struct instruction *ip = t->ip;
3171 TRACE("[Thread %2u] add (mi)\n", p->thread_id);
3181 instr_alu_add_hi_exec(struct rte_swx_pipeline *p)
3183 struct thread *t = &p->threads[p->thread_id];
3184 struct instruction *ip = t->ip;
3186 TRACE("[Thread %2u] add (hi)\n", p->thread_id);
3196 instr_alu_sub_exec(struct rte_swx_pipeline *p)
3198 struct thread *t = &p->threads[p->thread_id];
3199 struct instruction *ip = t->ip;
3201 TRACE("[Thread %2u] sub\n", p->thread_id);
3211 instr_alu_sub_mh_exec(struct rte_swx_pipeline *p)
3213 struct thread *t = &p->threads[p->thread_id];
3214 struct instruction *ip = t->ip;
3216 TRACE("[Thread %2u] sub (mh)\n", p->thread_id);
3226 instr_alu_sub_hm_exec(struct rte_swx_pipeline *p)
3228 struct thread *t = &p->threads[p->thread_id];
3229 struct instruction *ip = t->ip;
3231 TRACE("[Thread %2u] sub (hm)\n", p->thread_id);
3241 instr_alu_sub_hh_exec(struct rte_swx_pipeline *p)
3243 struct thread *t = &p->threads[p->thread_id];
3244 struct instruction *ip = t->ip;
3246 TRACE("[Thread %2u] sub (hh)\n", p->thread_id);
3256 instr_alu_sub_mi_exec(struct rte_swx_pipeline *p)
3258 struct thread *t = &p->threads[p->thread_id];
3259 struct instruction *ip = t->ip;
3261 TRACE("[Thread %2u] sub (mi)\n", p->thread_id);
3271 instr_alu_sub_hi_exec(struct rte_swx_pipeline *p)
3273 struct thread *t = &p->threads[p->thread_id];
3274 struct instruction *ip = t->ip;
3276 TRACE("[Thread %2u] sub (hi)\n", p->thread_id);
3286 instr_alu_shl_exec(struct rte_swx_pipeline *p)
3288 struct thread *t = &p->threads[p->thread_id];
3289 struct instruction *ip = t->ip;
3291 TRACE("[Thread %2u] shl\n", p->thread_id);
3301 instr_alu_shl_mh_exec(struct rte_swx_pipeline *p)
3303 struct thread *t = &p->threads[p->thread_id];
3304 struct instruction *ip = t->ip;
3306 TRACE("[Thread %2u] shl (mh)\n", p->thread_id);
3316 instr_alu_shl_hm_exec(struct rte_swx_pipeline *p)
3318 struct thread *t = &p->threads[p->thread_id];
3319 struct instruction *ip = t->ip;
3321 TRACE("[Thread %2u] shl (hm)\n", p->thread_id);
3331 instr_alu_shl_hh_exec(struct rte_swx_pipeline *p)
3333 struct thread *t = &p->threads[p->thread_id];
3334 struct instruction *ip = t->ip;
3336 TRACE("[Thread %2u] shl (hh)\n", p->thread_id);
3346 instr_alu_shl_mi_exec(struct rte_swx_pipeline *p)
3348 struct thread *t = &p->threads[p->thread_id];
3349 struct instruction *ip = t->ip;
3351 TRACE("[Thread %2u] shl (mi)\n", p->thread_id);
3361 instr_alu_shl_hi_exec(struct rte_swx_pipeline *p)
3363 struct thread *t = &p->threads[p->thread_id];
3364 struct instruction *ip = t->ip;
3366 TRACE("[Thread %2u] shl (hi)\n", p->thread_id);
3376 instr_alu_shr_exec(struct rte_swx_pipeline *p)
3378 struct thread *t = &p->threads[p->thread_id];
3379 struct instruction *ip = t->ip;
3381 TRACE("[Thread %2u] shr\n", p->thread_id);
3391 instr_alu_shr_mh_exec(struct rte_swx_pipeline *p)
3393 struct thread *t = &p->threads[p->thread_id];
3394 struct instruction *ip = t->ip;
3396 TRACE("[Thread %2u] shr (mh)\n", p->thread_id);
3406 instr_alu_shr_hm_exec(struct rte_swx_pipeline *p)
3408 struct thread *t = &p->threads[p->thread_id];
3409 struct instruction *ip = t->ip;
3411 TRACE("[Thread %2u] shr (hm)\n", p->thread_id);
3421 instr_alu_shr_hh_exec(struct rte_swx_pipeline *p)
3423 struct thread *t = &p->threads[p->thread_id];
3424 struct instruction *ip = t->ip;
3426 TRACE("[Thread %2u] shr (hh)\n", p->thread_id);
3436 instr_alu_shr_mi_exec(struct rte_swx_pipeline *p)
3438 struct thread *t = &p->threads[p->thread_id];
3439 struct instruction *ip = t->ip;
3441 TRACE("[Thread %2u] shr (mi)\n", p->thread_id);
3451 instr_alu_shr_hi_exec(struct rte_swx_pipeline *p)
3453 struct thread *t = &p->threads[p->thread_id];
3454 struct instruction *ip = t->ip;
3456 TRACE("[Thread %2u] shr (hi)\n", p->thread_id);
3466 instr_alu_and_exec(struct rte_swx_pipeline *p)
3468 struct thread *t = &p->threads[p->thread_id];
3469 struct instruction *ip = t->ip;
3471 TRACE("[Thread %2u] and\n", p->thread_id);
3481 instr_alu_and_mh_exec(struct rte_swx_pipeline *p)
3483 struct thread *t = &p->threads[p->thread_id];
3484 struct instruction *ip = t->ip;
3486 TRACE("[Thread %2u] and (mh)\n", p->thread_id);
3496 instr_alu_and_hm_exec(struct rte_swx_pipeline *p)
3498 struct thread *t = &p->threads[p->thread_id];
3499 struct instruction *ip = t->ip;
3501 TRACE("[Thread %2u] and (hm)\n", p->thread_id);
3504 ALU_HM_FAST(t, ip, &);
3511 instr_alu_and_hh_exec(struct rte_swx_pipeline *p)
3513 struct thread *t = &p->threads[p->thread_id];
3514 struct instruction *ip = t->ip;
3516 TRACE("[Thread %2u] and (hh)\n", p->thread_id);
3519 ALU_HH_FAST(t, ip, &);
3526 instr_alu_and_i_exec(struct rte_swx_pipeline *p)
3528 struct thread *t = &p->threads[p->thread_id];
3529 struct instruction *ip = t->ip;
3531 TRACE("[Thread %2u] and (i)\n", p->thread_id);
3541 instr_alu_or_exec(struct rte_swx_pipeline *p)
3543 struct thread *t = &p->threads[p->thread_id];
3544 struct instruction *ip = t->ip;
3546 TRACE("[Thread %2u] or\n", p->thread_id);
3556 instr_alu_or_mh_exec(struct rte_swx_pipeline *p)
3558 struct thread *t = &p->threads[p->thread_id];
3559 struct instruction *ip = t->ip;
3561 TRACE("[Thread %2u] or (mh)\n", p->thread_id);
3571 instr_alu_or_hm_exec(struct rte_swx_pipeline *p)
3573 struct thread *t = &p->threads[p->thread_id];
3574 struct instruction *ip = t->ip;
3576 TRACE("[Thread %2u] or (hm)\n", p->thread_id);
3579 ALU_HM_FAST(t, ip, |);
3586 instr_alu_or_hh_exec(struct rte_swx_pipeline *p)
3588 struct thread *t = &p->threads[p->thread_id];
3589 struct instruction *ip = t->ip;
3591 TRACE("[Thread %2u] or (hh)\n", p->thread_id);
3594 ALU_HH_FAST(t, ip, |);
3601 instr_alu_or_i_exec(struct rte_swx_pipeline *p)
3603 struct thread *t = &p->threads[p->thread_id];
3604 struct instruction *ip = t->ip;
3606 TRACE("[Thread %2u] or (i)\n", p->thread_id);
3616 instr_alu_xor_exec(struct rte_swx_pipeline *p)
3618 struct thread *t = &p->threads[p->thread_id];
3619 struct instruction *ip = t->ip;
3621 TRACE("[Thread %2u] xor\n", p->thread_id);
3631 instr_alu_xor_mh_exec(struct rte_swx_pipeline *p)
3633 struct thread *t = &p->threads[p->thread_id];
3634 struct instruction *ip = t->ip;
3636 TRACE("[Thread %2u] xor (mh)\n", p->thread_id);
3646 instr_alu_xor_hm_exec(struct rte_swx_pipeline *p)
3648 struct thread *t = &p->threads[p->thread_id];
3649 struct instruction *ip = t->ip;
3651 TRACE("[Thread %2u] xor (hm)\n", p->thread_id);
3654 ALU_HM_FAST(t, ip, ^);
3661 instr_alu_xor_hh_exec(struct rte_swx_pipeline *p)
3663 struct thread *t = &p->threads[p->thread_id];
3664 struct instruction *ip = t->ip;
3666 TRACE("[Thread %2u] xor (hh)\n", p->thread_id);
3669 ALU_HH_FAST(t, ip, ^);
3676 instr_alu_xor_i_exec(struct rte_swx_pipeline *p)
3678 struct thread *t = &p->threads[p->thread_id];
3679 struct instruction *ip = t->ip;
3681 TRACE("[Thread %2u] xor (i)\n", p->thread_id);
3691 instr_alu_ckadd_field_exec(struct rte_swx_pipeline *p)
3693 struct thread *t = &p->threads[p->thread_id];
3694 struct instruction *ip = t->ip;
3695 uint8_t *dst_struct, *src_struct;
3696 uint16_t *dst16_ptr, dst;
3697 uint64_t *src64_ptr, src64, src64_mask, src;
3700 TRACE("[Thread %2u] ckadd (field)\n", p->thread_id);
3703 dst_struct = t->structs[ip->alu.dst.struct_id];
3704 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
3707 src_struct = t->structs[ip->alu.src.struct_id];
3708 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
3710 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
3711 src = src64 & src64_mask;
3716 /* The first input (r) is a 16-bit number. The second and the third
3717 * inputs are 32-bit numbers. In the worst case scenario, the sum of the
3718 * three numbers (output r) is a 34-bit number.
3720 r += (src >> 32) + (src & 0xFFFFFFFF);
3722 /* The first input is a 16-bit number. The second input is an 18-bit
3723 * number. In the worst case scenario, the sum of the two numbers is a
3726 r = (r & 0xFFFF) + (r >> 16);
3728 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
3729 * a 3-bit number (0 .. 7). Their sum is a 17-bit number (0 .. 0x10006).
3731 r = (r & 0xFFFF) + (r >> 16);
3733 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
3734 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
3735 * 0x10006), the output r is (0 .. 7). So no carry bit can be generated,
3736 * therefore the output r is always a 16-bit number.
3738 r = (r & 0xFFFF) + (r >> 16);
3743 *dst16_ptr = (uint16_t)r;
3750 instr_alu_cksub_field_exec(struct rte_swx_pipeline *p)
3752 struct thread *t = &p->threads[p->thread_id];
3753 struct instruction *ip = t->ip;
3754 uint8_t *dst_struct, *src_struct;
3755 uint16_t *dst16_ptr, dst;
3756 uint64_t *src64_ptr, src64, src64_mask, src;
3759 TRACE("[Thread %2u] cksub (field)\n", p->thread_id);
3762 dst_struct = t->structs[ip->alu.dst.struct_id];
3763 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
3766 src_struct = t->structs[ip->alu.src.struct_id];
3767 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
3769 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
3770 src = src64 & src64_mask;
3775 /* Subtraction in 1's complement arithmetic (i.e. a '- b) is the same as
3776 * the following sequence of operations in 2's complement arithmetic:
3777 * a '- b = (a - b) % 0xFFFF.
3779 * In order to prevent an underflow for the below subtraction, in which
3780 * a 33-bit number (the subtrahend) is taken out of a 16-bit number (the
3781 * minuend), we first add a multiple of the 0xFFFF modulus to the
3782 * minuend. The number we add to the minuend needs to be a 34-bit number
3783 * or higher, so for readability reasons we picked the 36-bit multiple.
3784 * We are effectively turning the 16-bit minuend into a 36-bit number:
3785 * (a - b) % 0xFFFF = (a + 0xFFFF00000 - b) % 0xFFFF.
3787 r += 0xFFFF00000ULL; /* The output r is a 36-bit number. */
3789 /* A 33-bit number is subtracted from a 36-bit number (the input r). The
3790 * result (the output r) is a 36-bit number.
3792 r -= (src >> 32) + (src & 0xFFFFFFFF);
3794 /* The first input is a 16-bit number. The second input is a 20-bit
3795 * number. Their sum is a 21-bit number.
3797 r = (r & 0xFFFF) + (r >> 16);
3799 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
3800 * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1001E).
3802 r = (r & 0xFFFF) + (r >> 16);
3804 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
3805 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
3806 * 0x1001E), the output r is (0 .. 31). So no carry bit can be
3807 * generated, therefore the output r is always a 16-bit number.
3809 r = (r & 0xFFFF) + (r >> 16);
3814 *dst16_ptr = (uint16_t)r;
3821 instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline *p)
3823 struct thread *t = &p->threads[p->thread_id];
3824 struct instruction *ip = t->ip;
3825 uint8_t *dst_struct, *src_struct;
3826 uint16_t *dst16_ptr;
3827 uint32_t *src32_ptr;
3830 TRACE("[Thread %2u] ckadd (struct of 20 bytes)\n", p->thread_id);
3833 dst_struct = t->structs[ip->alu.dst.struct_id];
3834 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
3836 src_struct = t->structs[ip->alu.src.struct_id];
3837 src32_ptr = (uint32_t *)&src_struct[0];
3839 r0 = src32_ptr[0]; /* r0 is a 32-bit number. */
3840 r1 = src32_ptr[1]; /* r1 is a 32-bit number. */
3841 r0 += src32_ptr[2]; /* The output r0 is a 33-bit number. */
3842 r1 += src32_ptr[3]; /* The output r1 is a 33-bit number. */
3843 r0 += r1 + src32_ptr[4]; /* The output r0 is a 35-bit number. */
3845 /* The first input is a 16-bit number. The second input is a 19-bit
3846 * number. Their sum is a 20-bit number.
3848 r0 = (r0 & 0xFFFF) + (r0 >> 16);
3850 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
3851 * a 4-bit number (0 .. 15). The sum is a 17-bit number (0 .. 0x1000E).
3853 r0 = (r0 & 0xFFFF) + (r0 >> 16);
3855 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
3856 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
3857 * 0x1000E), the output r is (0 .. 15). So no carry bit can be
3858 * generated, therefore the output r is always a 16-bit number.
3860 r0 = (r0 & 0xFFFF) + (r0 >> 16);
3863 r0 = r0 ? r0 : 0xFFFF;
3865 *dst16_ptr = (uint16_t)r0;
3872 instr_alu_ckadd_struct_exec(struct rte_swx_pipeline *p)
3874 struct thread *t = &p->threads[p->thread_id];
3875 struct instruction *ip = t->ip;
3876 uint8_t *dst_struct, *src_struct;
3877 uint16_t *dst16_ptr;
3878 uint32_t *src32_ptr;
3882 TRACE("[Thread %2u] ckadd (struct)\n", p->thread_id);
3885 dst_struct = t->structs[ip->alu.dst.struct_id];
3886 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
3888 src_struct = t->structs[ip->alu.src.struct_id];
3889 src32_ptr = (uint32_t *)&src_struct[0];
3891 /* The max number of 32-bit words in a 256-byte header is 8 = 2^3.
3892 * Therefore, in the worst case scenario, a 35-bit number is added to a
3893 * 16-bit number (the input r), so the output r is 36-bit number.
3895 for (i = 0; i < ip->alu.src.n_bits / 32; i++, src32_ptr++)
3898 /* The first input is a 16-bit number. The second input is a 20-bit
3899 * number. Their sum is a 21-bit number.
3901 r = (r & 0xFFFF) + (r >> 16);
3903 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
3904 * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1000E).
3906 r = (r & 0xFFFF) + (r >> 16);
3908 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
3909 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
3910 * 0x1001E), the output r is (0 .. 31). So no carry bit can be
3911 * generated, therefore the output r is always a 16-bit number.
3913 r = (r & 0xFFFF) + (r >> 16);
3918 *dst16_ptr = (uint16_t)r;
3927 static struct regarray *
3928 regarray_find(struct rte_swx_pipeline *p, const char *name);
3931 instr_regprefetch_translate(struct rte_swx_pipeline *p,
3932 struct action *action,
3935 struct instruction *instr,
3936 struct instruction_data *data __rte_unused)
3938 char *regarray = tokens[1], *idx = tokens[2];
3941 uint32_t idx_struct_id, idx_val;
3943 CHECK(n_tokens == 3, EINVAL);
3945 r = regarray_find(p, regarray);
3948 /* REGPREFETCH_RH, REGPREFETCH_RM. */
3949 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
3951 CHECK(!fidx->var_size, EINVAL);
3953 instr->type = INSTR_REGPREFETCH_RM;
3955 instr->type = INSTR_REGPREFETCH_RH;
3957 instr->regarray.regarray_id = r->id;
3958 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
3959 instr->regarray.idx.n_bits = fidx->n_bits;
3960 instr->regarray.idx.offset = fidx->offset / 8;
3961 instr->regarray.dstsrc_val = 0; /* Unused. */
3965 /* REGPREFETCH_RI. */
3966 idx_val = strtoul(idx, &idx, 0);
3967 CHECK(!idx[0], EINVAL);
3969 instr->type = INSTR_REGPREFETCH_RI;
3970 instr->regarray.regarray_id = r->id;
3971 instr->regarray.idx_val = idx_val;
3972 instr->regarray.dstsrc_val = 0; /* Unused. */
3977 instr_regrd_translate(struct rte_swx_pipeline *p,
3978 struct action *action,
3981 struct instruction *instr,
3982 struct instruction_data *data __rte_unused)
3984 char *dst = tokens[1], *regarray = tokens[2], *idx = tokens[3];
3986 struct field *fdst, *fidx;
3987 uint32_t dst_struct_id, idx_struct_id, idx_val;
3989 CHECK(n_tokens == 4, EINVAL);
3991 r = regarray_find(p, regarray);
3994 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3995 CHECK(fdst, EINVAL);
3996 CHECK(!fdst->var_size, EINVAL);
3998 /* REGRD_HRH, REGRD_HRM, REGRD_MRH, REGRD_MRM. */
3999 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4001 CHECK(!fidx->var_size, EINVAL);
4003 instr->type = INSTR_REGRD_MRM;
4004 if (dst[0] == 'h' && idx[0] != 'h')
4005 instr->type = INSTR_REGRD_HRM;
4006 if (dst[0] != 'h' && idx[0] == 'h')
4007 instr->type = INSTR_REGRD_MRH;
4008 if (dst[0] == 'h' && idx[0] == 'h')
4009 instr->type = INSTR_REGRD_HRH;
4011 instr->regarray.regarray_id = r->id;
4012 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4013 instr->regarray.idx.n_bits = fidx->n_bits;
4014 instr->regarray.idx.offset = fidx->offset / 8;
4015 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
4016 instr->regarray.dstsrc.n_bits = fdst->n_bits;
4017 instr->regarray.dstsrc.offset = fdst->offset / 8;
4021 /* REGRD_MRI, REGRD_HRI. */
4022 idx_val = strtoul(idx, &idx, 0);
4023 CHECK(!idx[0], EINVAL);
4025 instr->type = INSTR_REGRD_MRI;
4027 instr->type = INSTR_REGRD_HRI;
4029 instr->regarray.regarray_id = r->id;
4030 instr->regarray.idx_val = idx_val;
4031 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
4032 instr->regarray.dstsrc.n_bits = fdst->n_bits;
4033 instr->regarray.dstsrc.offset = fdst->offset / 8;
4038 instr_regwr_translate(struct rte_swx_pipeline *p,
4039 struct action *action,
4042 struct instruction *instr,
4043 struct instruction_data *data __rte_unused)
4045 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
4047 struct field *fidx, *fsrc;
4049 uint32_t idx_struct_id, idx_val, src_struct_id;
4051 CHECK(n_tokens == 4, EINVAL);
4053 r = regarray_find(p, regarray);
4056 /* REGWR_RHH, REGWR_RHM, REGWR_RMH, REGWR_RMM. */
4057 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4058 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4060 CHECK(!fidx->var_size, EINVAL);
4061 CHECK(!fsrc->var_size, EINVAL);
4063 instr->type = INSTR_REGWR_RMM;
4064 if (idx[0] == 'h' && src[0] != 'h')
4065 instr->type = INSTR_REGWR_RHM;
4066 if (idx[0] != 'h' && src[0] == 'h')
4067 instr->type = INSTR_REGWR_RMH;
4068 if (idx[0] == 'h' && src[0] == 'h')
4069 instr->type = INSTR_REGWR_RHH;
4071 instr->regarray.regarray_id = r->id;
4072 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4073 instr->regarray.idx.n_bits = fidx->n_bits;
4074 instr->regarray.idx.offset = fidx->offset / 8;
4075 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4076 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4077 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4081 /* REGWR_RHI, REGWR_RMI. */
4082 if (fidx && !fsrc) {
4083 CHECK(!fidx->var_size, EINVAL);
4085 src_val = strtoull(src, &src, 0);
4086 CHECK(!src[0], EINVAL);
4088 instr->type = INSTR_REGWR_RMI;
4090 instr->type = INSTR_REGWR_RHI;
4092 instr->regarray.regarray_id = r->id;
4093 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4094 instr->regarray.idx.n_bits = fidx->n_bits;
4095 instr->regarray.idx.offset = fidx->offset / 8;
4096 instr->regarray.dstsrc_val = src_val;
4100 /* REGWR_RIH, REGWR_RIM. */
4101 if (!fidx && fsrc) {
4102 idx_val = strtoul(idx, &idx, 0);
4103 CHECK(!idx[0], EINVAL);
4105 CHECK(!fsrc->var_size, EINVAL);
4107 instr->type = INSTR_REGWR_RIM;
4109 instr->type = INSTR_REGWR_RIH;
4111 instr->regarray.regarray_id = r->id;
4112 instr->regarray.idx_val = idx_val;
4113 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4114 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4115 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4120 src_val = strtoull(src, &src, 0);
4121 CHECK(!src[0], EINVAL);
4123 idx_val = strtoul(idx, &idx, 0);
4124 CHECK(!idx[0], EINVAL);
4126 instr->type = INSTR_REGWR_RII;
4127 instr->regarray.idx_val = idx_val;
4128 instr->regarray.dstsrc_val = src_val;
4134 instr_regadd_translate(struct rte_swx_pipeline *p,
4135 struct action *action,
4138 struct instruction *instr,
4139 struct instruction_data *data __rte_unused)
4141 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
4143 struct field *fidx, *fsrc;
4145 uint32_t idx_struct_id, idx_val, src_struct_id;
4147 CHECK(n_tokens == 4, EINVAL);
4149 r = regarray_find(p, regarray);
4152 /* REGADD_RHH, REGADD_RHM, REGADD_RMH, REGADD_RMM. */
4153 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4154 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4156 CHECK(!fidx->var_size, EINVAL);
4157 CHECK(!fsrc->var_size, EINVAL);
4159 instr->type = INSTR_REGADD_RMM;
4160 if (idx[0] == 'h' && src[0] != 'h')
4161 instr->type = INSTR_REGADD_RHM;
4162 if (idx[0] != 'h' && src[0] == 'h')
4163 instr->type = INSTR_REGADD_RMH;
4164 if (idx[0] == 'h' && src[0] == 'h')
4165 instr->type = INSTR_REGADD_RHH;
4167 instr->regarray.regarray_id = r->id;
4168 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4169 instr->regarray.idx.n_bits = fidx->n_bits;
4170 instr->regarray.idx.offset = fidx->offset / 8;
4171 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4172 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4173 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4177 /* REGADD_RHI, REGADD_RMI. */
4178 if (fidx && !fsrc) {
4179 CHECK(!fidx->var_size, EINVAL);
4181 src_val = strtoull(src, &src, 0);
4182 CHECK(!src[0], EINVAL);
4184 instr->type = INSTR_REGADD_RMI;
4186 instr->type = INSTR_REGADD_RHI;
4188 instr->regarray.regarray_id = r->id;
4189 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4190 instr->regarray.idx.n_bits = fidx->n_bits;
4191 instr->regarray.idx.offset = fidx->offset / 8;
4192 instr->regarray.dstsrc_val = src_val;
4196 /* REGADD_RIH, REGADD_RIM. */
4197 if (!fidx && fsrc) {
4198 idx_val = strtoul(idx, &idx, 0);
4199 CHECK(!idx[0], EINVAL);
4201 CHECK(!fsrc->var_size, EINVAL);
4203 instr->type = INSTR_REGADD_RIM;
4205 instr->type = INSTR_REGADD_RIH;
4207 instr->regarray.regarray_id = r->id;
4208 instr->regarray.idx_val = idx_val;
4209 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4210 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4211 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4216 src_val = strtoull(src, &src, 0);
4217 CHECK(!src[0], EINVAL);
4219 idx_val = strtoul(idx, &idx, 0);
4220 CHECK(!idx[0], EINVAL);
4222 instr->type = INSTR_REGADD_RII;
4223 instr->regarray.idx_val = idx_val;
4224 instr->regarray.dstsrc_val = src_val;
4228 static inline uint64_t *
4229 instr_regarray_regarray(struct rte_swx_pipeline *p, struct instruction *ip)
4231 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4235 static inline uint64_t
4236 instr_regarray_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
4238 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4240 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
4241 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
4242 uint64_t idx64 = *idx64_ptr;
4243 uint64_t idx64_mask = UINT64_MAX >> (64 - ip->regarray.idx.n_bits);
4244 uint64_t idx = idx64 & idx64_mask & r->size_mask;
4249 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4251 static inline uint64_t
4252 instr_regarray_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
4254 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4256 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
4257 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
4258 uint64_t idx64 = *idx64_ptr;
4259 uint64_t idx = (ntoh64(idx64) >> (64 - ip->regarray.idx.n_bits)) & r->size_mask;
4266 #define instr_regarray_idx_nbo instr_regarray_idx_hbo
4270 static inline uint64_t
4271 instr_regarray_idx_imm(struct rte_swx_pipeline *p, struct instruction *ip)
4273 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4275 uint64_t idx = ip->regarray.idx_val & r->size_mask;
4280 static inline uint64_t
4281 instr_regarray_src_hbo(struct thread *t, struct instruction *ip)
4283 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
4284 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
4285 uint64_t src64 = *src64_ptr;
4286 uint64_t src64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
4287 uint64_t src = src64 & src64_mask;
4292 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4294 static inline uint64_t
4295 instr_regarray_src_nbo(struct thread *t, struct instruction *ip)
4297 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
4298 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
4299 uint64_t src64 = *src64_ptr;
4300 uint64_t src = ntoh64(src64) >> (64 - ip->regarray.dstsrc.n_bits);
4307 #define instr_regarray_src_nbo instr_regarray_src_hbo
4312 instr_regarray_dst_hbo_src_hbo_set(struct thread *t, struct instruction *ip, uint64_t src)
4314 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
4315 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
4316 uint64_t dst64 = *dst64_ptr;
4317 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
4319 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
4323 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4326 instr_regarray_dst_nbo_src_hbo_set(struct thread *t, struct instruction *ip, uint64_t src)
4328 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
4329 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
4330 uint64_t dst64 = *dst64_ptr;
4331 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
4333 src = hton64(src) >> (64 - ip->regarray.dstsrc.n_bits);
4334 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
4339 #define instr_regarray_dst_nbo_src_hbo_set instr_regarray_dst_hbo_src_hbo_set
4344 instr_regprefetch_rh_exec(struct rte_swx_pipeline *p)
4346 struct thread *t = &p->threads[p->thread_id];
4347 struct instruction *ip = t->ip;
4348 uint64_t *regarray, idx;
4350 TRACE("[Thread %2u] regprefetch (r[h])\n", p->thread_id);
4353 regarray = instr_regarray_regarray(p, ip);
4354 idx = instr_regarray_idx_nbo(p, t, ip);
4355 rte_prefetch0(®array[idx]);
4362 instr_regprefetch_rm_exec(struct rte_swx_pipeline *p)
4364 struct thread *t = &p->threads[p->thread_id];
4365 struct instruction *ip = t->ip;
4366 uint64_t *regarray, idx;
4368 TRACE("[Thread %2u] regprefetch (r[m])\n", p->thread_id);
4371 regarray = instr_regarray_regarray(p, ip);
4372 idx = instr_regarray_idx_hbo(p, t, ip);
4373 rte_prefetch0(®array[idx]);
4380 instr_regprefetch_ri_exec(struct rte_swx_pipeline *p)
4382 struct thread *t = &p->threads[p->thread_id];
4383 struct instruction *ip = t->ip;
4384 uint64_t *regarray, idx;
4386 TRACE("[Thread %2u] regprefetch (r[i])\n", p->thread_id);
4389 regarray = instr_regarray_regarray(p, ip);
4390 idx = instr_regarray_idx_imm(p, ip);
4391 rte_prefetch0(®array[idx]);
4398 instr_regrd_hrh_exec(struct rte_swx_pipeline *p)
4400 struct thread *t = &p->threads[p->thread_id];
4401 struct instruction *ip = t->ip;
4402 uint64_t *regarray, idx;
4404 TRACE("[Thread %2u] regrd (h = r[h])\n", p->thread_id);
4407 regarray = instr_regarray_regarray(p, ip);
4408 idx = instr_regarray_idx_nbo(p, t, ip);
4409 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
4416 instr_regrd_hrm_exec(struct rte_swx_pipeline *p)
4418 struct thread *t = &p->threads[p->thread_id];
4419 struct instruction *ip = t->ip;
4420 uint64_t *regarray, idx;
4422 TRACE("[Thread %2u] regrd (h = r[m])\n", p->thread_id);
4425 regarray = instr_regarray_regarray(p, ip);
4426 idx = instr_regarray_idx_hbo(p, t, ip);
4427 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
4434 instr_regrd_mrh_exec(struct rte_swx_pipeline *p)
4436 struct thread *t = &p->threads[p->thread_id];
4437 struct instruction *ip = t->ip;
4438 uint64_t *regarray, idx;
4440 TRACE("[Thread %2u] regrd (m = r[h])\n", p->thread_id);
4443 regarray = instr_regarray_regarray(p, ip);
4444 idx = instr_regarray_idx_nbo(p, t, ip);
4445 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
4452 instr_regrd_mrm_exec(struct rte_swx_pipeline *p)
4454 struct thread *t = &p->threads[p->thread_id];
4455 struct instruction *ip = t->ip;
4456 uint64_t *regarray, idx;
4459 regarray = instr_regarray_regarray(p, ip);
4460 idx = instr_regarray_idx_hbo(p, t, ip);
4461 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
4468 instr_regrd_hri_exec(struct rte_swx_pipeline *p)
4470 struct thread *t = &p->threads[p->thread_id];
4471 struct instruction *ip = t->ip;
4472 uint64_t *regarray, idx;
4474 TRACE("[Thread %2u] regrd (h = r[i])\n", p->thread_id);
4477 regarray = instr_regarray_regarray(p, ip);
4478 idx = instr_regarray_idx_imm(p, ip);
4479 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
4486 instr_regrd_mri_exec(struct rte_swx_pipeline *p)
4488 struct thread *t = &p->threads[p->thread_id];
4489 struct instruction *ip = t->ip;
4490 uint64_t *regarray, idx;
4492 TRACE("[Thread %2u] regrd (m = r[i])\n", p->thread_id);
4495 regarray = instr_regarray_regarray(p, ip);
4496 idx = instr_regarray_idx_imm(p, ip);
4497 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
4504 instr_regwr_rhh_exec(struct rte_swx_pipeline *p)
4506 struct thread *t = &p->threads[p->thread_id];
4507 struct instruction *ip = t->ip;
4508 uint64_t *regarray, idx, src;
4510 TRACE("[Thread %2u] regwr (r[h] = h)\n", p->thread_id);
4513 regarray = instr_regarray_regarray(p, ip);
4514 idx = instr_regarray_idx_nbo(p, t, ip);
4515 src = instr_regarray_src_nbo(t, ip);
4516 regarray[idx] = src;
4523 instr_regwr_rhm_exec(struct rte_swx_pipeline *p)
4525 struct thread *t = &p->threads[p->thread_id];
4526 struct instruction *ip = t->ip;
4527 uint64_t *regarray, idx, src;
4529 TRACE("[Thread %2u] regwr (r[h] = m)\n", p->thread_id);
4532 regarray = instr_regarray_regarray(p, ip);
4533 idx = instr_regarray_idx_nbo(p, t, ip);
4534 src = instr_regarray_src_hbo(t, ip);
4535 regarray[idx] = src;
4542 instr_regwr_rmh_exec(struct rte_swx_pipeline *p)
4544 struct thread *t = &p->threads[p->thread_id];
4545 struct instruction *ip = t->ip;
4546 uint64_t *regarray, idx, src;
4548 TRACE("[Thread %2u] regwr (r[m] = h)\n", p->thread_id);
4551 regarray = instr_regarray_regarray(p, ip);
4552 idx = instr_regarray_idx_hbo(p, t, ip);
4553 src = instr_regarray_src_nbo(t, ip);
4554 regarray[idx] = src;
4561 instr_regwr_rmm_exec(struct rte_swx_pipeline *p)
4563 struct thread *t = &p->threads[p->thread_id];
4564 struct instruction *ip = t->ip;
4565 uint64_t *regarray, idx, src;
4567 TRACE("[Thread %2u] regwr (r[m] = m)\n", p->thread_id);
4570 regarray = instr_regarray_regarray(p, ip);
4571 idx = instr_regarray_idx_hbo(p, t, ip);
4572 src = instr_regarray_src_hbo(t, ip);
4573 regarray[idx] = src;
4580 instr_regwr_rhi_exec(struct rte_swx_pipeline *p)
4582 struct thread *t = &p->threads[p->thread_id];
4583 struct instruction *ip = t->ip;
4584 uint64_t *regarray, idx, src;
4586 TRACE("[Thread %2u] regwr (r[h] = i)\n", p->thread_id);
4589 regarray = instr_regarray_regarray(p, ip);
4590 idx = instr_regarray_idx_nbo(p, t, ip);
4591 src = ip->regarray.dstsrc_val;
4592 regarray[idx] = src;
4599 instr_regwr_rmi_exec(struct rte_swx_pipeline *p)
4601 struct thread *t = &p->threads[p->thread_id];
4602 struct instruction *ip = t->ip;
4603 uint64_t *regarray, idx, src;
4605 TRACE("[Thread %2u] regwr (r[m] = i)\n", p->thread_id);
4608 regarray = instr_regarray_regarray(p, ip);
4609 idx = instr_regarray_idx_hbo(p, t, ip);
4610 src = ip->regarray.dstsrc_val;
4611 regarray[idx] = src;
4618 instr_regwr_rih_exec(struct rte_swx_pipeline *p)
4620 struct thread *t = &p->threads[p->thread_id];
4621 struct instruction *ip = t->ip;
4622 uint64_t *regarray, idx, src;
4624 TRACE("[Thread %2u] regwr (r[i] = h)\n", p->thread_id);
4627 regarray = instr_regarray_regarray(p, ip);
4628 idx = instr_regarray_idx_imm(p, ip);
4629 src = instr_regarray_src_nbo(t, ip);
4630 regarray[idx] = src;
4637 instr_regwr_rim_exec(struct rte_swx_pipeline *p)
4639 struct thread *t = &p->threads[p->thread_id];
4640 struct instruction *ip = t->ip;
4641 uint64_t *regarray, idx, src;
4643 TRACE("[Thread %2u] regwr (r[i] = m)\n", p->thread_id);
4646 regarray = instr_regarray_regarray(p, ip);
4647 idx = instr_regarray_idx_imm(p, ip);
4648 src = instr_regarray_src_hbo(t, ip);
4649 regarray[idx] = src;
4656 instr_regwr_rii_exec(struct rte_swx_pipeline *p)
4658 struct thread *t = &p->threads[p->thread_id];
4659 struct instruction *ip = t->ip;
4660 uint64_t *regarray, idx, src;
4662 TRACE("[Thread %2u] regwr (r[i] = i)\n", p->thread_id);
4665 regarray = instr_regarray_regarray(p, ip);
4666 idx = instr_regarray_idx_imm(p, ip);
4667 src = ip->regarray.dstsrc_val;
4668 regarray[idx] = src;
4675 instr_regadd_rhh_exec(struct rte_swx_pipeline *p)
4677 struct thread *t = &p->threads[p->thread_id];
4678 struct instruction *ip = t->ip;
4679 uint64_t *regarray, idx, src;
4681 TRACE("[Thread %2u] regadd (r[h] += h)\n", p->thread_id);
4684 regarray = instr_regarray_regarray(p, ip);
4685 idx = instr_regarray_idx_nbo(p, t, ip);
4686 src = instr_regarray_src_nbo(t, ip);
4687 regarray[idx] += src;
4694 instr_regadd_rhm_exec(struct rte_swx_pipeline *p)
4696 struct thread *t = &p->threads[p->thread_id];
4697 struct instruction *ip = t->ip;
4698 uint64_t *regarray, idx, src;
4700 TRACE("[Thread %2u] regadd (r[h] += m)\n", p->thread_id);
4703 regarray = instr_regarray_regarray(p, ip);
4704 idx = instr_regarray_idx_nbo(p, t, ip);
4705 src = instr_regarray_src_hbo(t, ip);
4706 regarray[idx] += src;
4713 instr_regadd_rmh_exec(struct rte_swx_pipeline *p)
4715 struct thread *t = &p->threads[p->thread_id];
4716 struct instruction *ip = t->ip;
4717 uint64_t *regarray, idx, src;
4719 TRACE("[Thread %2u] regadd (r[m] += h)\n", p->thread_id);
4722 regarray = instr_regarray_regarray(p, ip);
4723 idx = instr_regarray_idx_hbo(p, t, ip);
4724 src = instr_regarray_src_nbo(t, ip);
4725 regarray[idx] += src;
4732 instr_regadd_rmm_exec(struct rte_swx_pipeline *p)
4734 struct thread *t = &p->threads[p->thread_id];
4735 struct instruction *ip = t->ip;
4736 uint64_t *regarray, idx, src;
4738 TRACE("[Thread %2u] regadd (r[m] += m)\n", p->thread_id);
4741 regarray = instr_regarray_regarray(p, ip);
4742 idx = instr_regarray_idx_hbo(p, t, ip);
4743 src = instr_regarray_src_hbo(t, ip);
4744 regarray[idx] += src;
4751 instr_regadd_rhi_exec(struct rte_swx_pipeline *p)
4753 struct thread *t = &p->threads[p->thread_id];
4754 struct instruction *ip = t->ip;
4755 uint64_t *regarray, idx, src;
4757 TRACE("[Thread %2u] regadd (r[h] += i)\n", p->thread_id);
4760 regarray = instr_regarray_regarray(p, ip);
4761 idx = instr_regarray_idx_nbo(p, t, ip);
4762 src = ip->regarray.dstsrc_val;
4763 regarray[idx] += src;
4770 instr_regadd_rmi_exec(struct rte_swx_pipeline *p)
4772 struct thread *t = &p->threads[p->thread_id];
4773 struct instruction *ip = t->ip;
4774 uint64_t *regarray, idx, src;
4776 TRACE("[Thread %2u] regadd (r[m] += i)\n", p->thread_id);
4779 regarray = instr_regarray_regarray(p, ip);
4780 idx = instr_regarray_idx_hbo(p, t, ip);
4781 src = ip->regarray.dstsrc_val;
4782 regarray[idx] += src;
4789 instr_regadd_rih_exec(struct rte_swx_pipeline *p)
4791 struct thread *t = &p->threads[p->thread_id];
4792 struct instruction *ip = t->ip;
4793 uint64_t *regarray, idx, src;
4795 TRACE("[Thread %2u] regadd (r[i] += h)\n", p->thread_id);
4798 regarray = instr_regarray_regarray(p, ip);
4799 idx = instr_regarray_idx_imm(p, ip);
4800 src = instr_regarray_src_nbo(t, ip);
4801 regarray[idx] += src;
4808 instr_regadd_rim_exec(struct rte_swx_pipeline *p)
4810 struct thread *t = &p->threads[p->thread_id];
4811 struct instruction *ip = t->ip;
4812 uint64_t *regarray, idx, src;
4814 TRACE("[Thread %2u] regadd (r[i] += m)\n", p->thread_id);
4817 regarray = instr_regarray_regarray(p, ip);
4818 idx = instr_regarray_idx_imm(p, ip);
4819 src = instr_regarray_src_hbo(t, ip);
4820 regarray[idx] += src;
4827 instr_regadd_rii_exec(struct rte_swx_pipeline *p)
4829 struct thread *t = &p->threads[p->thread_id];
4830 struct instruction *ip = t->ip;
4831 uint64_t *regarray, idx, src;
4833 TRACE("[Thread %2u] regadd (r[i] += i)\n", p->thread_id);
4836 regarray = instr_regarray_regarray(p, ip);
4837 idx = instr_regarray_idx_imm(p, ip);
4838 src = ip->regarray.dstsrc_val;
4839 regarray[idx] += src;
4848 static struct metarray *
4849 metarray_find(struct rte_swx_pipeline *p, const char *name);
4852 instr_metprefetch_translate(struct rte_swx_pipeline *p,
4853 struct action *action,
4856 struct instruction *instr,
4857 struct instruction_data *data __rte_unused)
4859 char *metarray = tokens[1], *idx = tokens[2];
4862 uint32_t idx_struct_id, idx_val;
4864 CHECK(n_tokens == 3, EINVAL);
4866 m = metarray_find(p, metarray);
4869 /* METPREFETCH_H, METPREFETCH_M. */
4870 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4872 CHECK(!fidx->var_size, EINVAL);
4874 instr->type = INSTR_METPREFETCH_M;
4876 instr->type = INSTR_METPREFETCH_H;
4878 instr->meter.metarray_id = m->id;
4879 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4880 instr->meter.idx.n_bits = fidx->n_bits;
4881 instr->meter.idx.offset = fidx->offset / 8;
4885 /* METPREFETCH_I. */
4886 idx_val = strtoul(idx, &idx, 0);
4887 CHECK(!idx[0], EINVAL);
4889 instr->type = INSTR_METPREFETCH_I;
4890 instr->meter.metarray_id = m->id;
4891 instr->meter.idx_val = idx_val;
4896 instr_meter_translate(struct rte_swx_pipeline *p,
4897 struct action *action,
4900 struct instruction *instr,
4901 struct instruction_data *data __rte_unused)
4903 char *metarray = tokens[1], *idx = tokens[2], *length = tokens[3];
4904 char *color_in = tokens[4], *color_out = tokens[5];
4906 struct field *fidx, *flength, *fcin, *fcout;
4907 uint32_t idx_struct_id, length_struct_id;
4908 uint32_t color_in_struct_id, color_out_struct_id;
4910 CHECK(n_tokens == 6, EINVAL);
4912 m = metarray_find(p, metarray);
4915 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4917 flength = struct_field_parse(p, action, length, &length_struct_id);
4918 CHECK(flength, EINVAL);
4919 CHECK(!flength->var_size, EINVAL);
4921 fcin = struct_field_parse(p, action, color_in, &color_in_struct_id);
4923 fcout = struct_field_parse(p, NULL, color_out, &color_out_struct_id);
4924 CHECK(fcout, EINVAL);
4925 CHECK(!fcout->var_size, EINVAL);
4927 /* index = HMEFT, length = HMEFT, color_in = MEFT, color_out = MEF. */
4929 CHECK(!fidx->var_size, EINVAL);
4930 CHECK(!fcin->var_size, EINVAL);
4932 instr->type = INSTR_METER_MMM;
4933 if (idx[0] == 'h' && length[0] == 'h')
4934 instr->type = INSTR_METER_HHM;
4935 if (idx[0] == 'h' && length[0] != 'h')
4936 instr->type = INSTR_METER_HMM;
4937 if (idx[0] != 'h' && length[0] == 'h')
4938 instr->type = INSTR_METER_MHM;
4940 instr->meter.metarray_id = m->id;
4942 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4943 instr->meter.idx.n_bits = fidx->n_bits;
4944 instr->meter.idx.offset = fidx->offset / 8;
4946 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4947 instr->meter.length.n_bits = flength->n_bits;
4948 instr->meter.length.offset = flength->offset / 8;
4950 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
4951 instr->meter.color_in.n_bits = fcin->n_bits;
4952 instr->meter.color_in.offset = fcin->offset / 8;
4954 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4955 instr->meter.color_out.n_bits = fcout->n_bits;
4956 instr->meter.color_out.offset = fcout->offset / 8;
4961 /* index = HMEFT, length = HMEFT, color_in = I, color_out = MEF. */
4962 if (fidx && !fcin) {
4963 uint32_t color_in_val;
4965 CHECK(!fidx->var_size, EINVAL);
4967 color_in_val = strtoul(color_in, &color_in, 0);
4968 CHECK(!color_in[0], EINVAL);
4970 instr->type = INSTR_METER_MMI;
4971 if (idx[0] == 'h' && length[0] == 'h')
4972 instr->type = INSTR_METER_HHI;
4973 if (idx[0] == 'h' && length[0] != 'h')
4974 instr->type = INSTR_METER_HMI;
4975 if (idx[0] != 'h' && length[0] == 'h')
4976 instr->type = INSTR_METER_MHI;
4978 instr->meter.metarray_id = m->id;
4980 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4981 instr->meter.idx.n_bits = fidx->n_bits;
4982 instr->meter.idx.offset = fidx->offset / 8;
4984 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4985 instr->meter.length.n_bits = flength->n_bits;
4986 instr->meter.length.offset = flength->offset / 8;
4988 instr->meter.color_in_val = color_in_val;
4990 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4991 instr->meter.color_out.n_bits = fcout->n_bits;
4992 instr->meter.color_out.offset = fcout->offset / 8;
4997 /* index = I, length = HMEFT, color_in = MEFT, color_out = MEF. */
4998 if (!fidx && fcin) {
5001 idx_val = strtoul(idx, &idx, 0);
5002 CHECK(!idx[0], EINVAL);
5004 CHECK(!fcin->var_size, EINVAL);
5006 instr->type = INSTR_METER_IMM;
5007 if (length[0] == 'h')
5008 instr->type = INSTR_METER_IHM;
5010 instr->meter.metarray_id = m->id;
5012 instr->meter.idx_val = idx_val;
5014 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5015 instr->meter.length.n_bits = flength->n_bits;
5016 instr->meter.length.offset = flength->offset / 8;
5018 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
5019 instr->meter.color_in.n_bits = fcin->n_bits;
5020 instr->meter.color_in.offset = fcin->offset / 8;
5022 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5023 instr->meter.color_out.n_bits = fcout->n_bits;
5024 instr->meter.color_out.offset = fcout->offset / 8;
5029 /* index = I, length = HMEFT, color_in = I, color_out = MEF. */
5030 if (!fidx && !fcin) {
5031 uint32_t idx_val, color_in_val;
5033 idx_val = strtoul(idx, &idx, 0);
5034 CHECK(!idx[0], EINVAL);
5036 color_in_val = strtoul(color_in, &color_in, 0);
5037 CHECK(!color_in[0], EINVAL);
5039 instr->type = INSTR_METER_IMI;
5040 if (length[0] == 'h')
5041 instr->type = INSTR_METER_IHI;
5043 instr->meter.metarray_id = m->id;
5045 instr->meter.idx_val = idx_val;
5047 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5048 instr->meter.length.n_bits = flength->n_bits;
5049 instr->meter.length.offset = flength->offset / 8;
5051 instr->meter.color_in_val = color_in_val;
5053 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5054 instr->meter.color_out.n_bits = fcout->n_bits;
5055 instr->meter.color_out.offset = fcout->offset / 8;
5063 static inline struct meter *
5064 instr_meter_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
5066 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
5068 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
5069 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
5070 uint64_t idx64 = *idx64_ptr;
5071 uint64_t idx64_mask = UINT64_MAX >> (64 - (ip)->meter.idx.n_bits);
5072 uint64_t idx = idx64 & idx64_mask & r->size_mask;
5074 return &r->metarray[idx];
5077 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5079 static inline struct meter *
5080 instr_meter_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
5082 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
5084 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
5085 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
5086 uint64_t idx64 = *idx64_ptr;
5087 uint64_t idx = (ntoh64(idx64) >> (64 - ip->meter.idx.n_bits)) & r->size_mask;
5089 return &r->metarray[idx];
5094 #define instr_meter_idx_nbo instr_meter_idx_hbo
5098 static inline struct meter *
5099 instr_meter_idx_imm(struct rte_swx_pipeline *p, struct instruction *ip)
5101 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
5103 uint64_t idx = ip->meter.idx_val & r->size_mask;
5105 return &r->metarray[idx];
5108 static inline uint32_t
5109 instr_meter_length_hbo(struct thread *t, struct instruction *ip)
5111 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
5112 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
5113 uint64_t src64 = *src64_ptr;
5114 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->meter.length.n_bits);
5115 uint64_t src = src64 & src64_mask;
5117 return (uint32_t)src;
5120 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5122 static inline uint32_t
5123 instr_meter_length_nbo(struct thread *t, struct instruction *ip)
5125 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
5126 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
5127 uint64_t src64 = *src64_ptr;
5128 uint64_t src = ntoh64(src64) >> (64 - ip->meter.length.n_bits);
5130 return (uint32_t)src;
5135 #define instr_meter_length_nbo instr_meter_length_hbo
5139 static inline enum rte_color
5140 instr_meter_color_in_hbo(struct thread *t, struct instruction *ip)
5142 uint8_t *src_struct = t->structs[ip->meter.color_in.struct_id];
5143 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.color_in.offset];
5144 uint64_t src64 = *src64_ptr;
5145 uint64_t src64_mask = UINT64_MAX >> (64 - ip->meter.color_in.n_bits);
5146 uint64_t src = src64 & src64_mask;
5148 return (enum rte_color)src;
5152 instr_meter_color_out_hbo_set(struct thread *t, struct instruction *ip, enum rte_color color_out)
5154 uint8_t *dst_struct = t->structs[ip->meter.color_out.struct_id];
5155 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->meter.color_out.offset];
5156 uint64_t dst64 = *dst64_ptr;
5157 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->meter.color_out.n_bits);
5159 uint64_t src = (uint64_t)color_out;
5161 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
5165 instr_metprefetch_h_exec(struct rte_swx_pipeline *p)
5167 struct thread *t = &p->threads[p->thread_id];
5168 struct instruction *ip = t->ip;
5171 TRACE("[Thread %2u] metprefetch (h)\n", p->thread_id);
5174 m = instr_meter_idx_nbo(p, t, ip);
5182 instr_metprefetch_m_exec(struct rte_swx_pipeline *p)
5184 struct thread *t = &p->threads[p->thread_id];
5185 struct instruction *ip = t->ip;
5188 TRACE("[Thread %2u] metprefetch (m)\n", p->thread_id);
5191 m = instr_meter_idx_hbo(p, t, ip);
5199 instr_metprefetch_i_exec(struct rte_swx_pipeline *p)
5201 struct thread *t = &p->threads[p->thread_id];
5202 struct instruction *ip = t->ip;
5205 TRACE("[Thread %2u] metprefetch (i)\n", p->thread_id);
5208 m = instr_meter_idx_imm(p, ip);
5216 instr_meter_hhm_exec(struct rte_swx_pipeline *p)
5218 struct thread *t = &p->threads[p->thread_id];
5219 struct instruction *ip = t->ip;
5221 uint64_t time, n_pkts, n_bytes;
5223 enum rte_color color_in, color_out;
5225 TRACE("[Thread %2u] meter (hhm)\n", p->thread_id);
5228 m = instr_meter_idx_nbo(p, t, ip);
5229 rte_prefetch0(m->n_pkts);
5230 time = rte_get_tsc_cycles();
5231 length = instr_meter_length_nbo(t, ip);
5232 color_in = instr_meter_color_in_hbo(t, ip);
5234 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5235 &m->profile->profile,
5240 color_out &= m->color_mask;
5242 n_pkts = m->n_pkts[color_out];
5243 n_bytes = m->n_bytes[color_out];
5245 instr_meter_color_out_hbo_set(t, ip, color_out);
5247 m->n_pkts[color_out] = n_pkts + 1;
5248 m->n_bytes[color_out] = n_bytes + length;
5255 instr_meter_hhi_exec(struct rte_swx_pipeline *p)
5257 struct thread *t = &p->threads[p->thread_id];
5258 struct instruction *ip = t->ip;
5260 uint64_t time, n_pkts, n_bytes;
5262 enum rte_color color_in, color_out;
5264 TRACE("[Thread %2u] meter (hhi)\n", p->thread_id);
5267 m = instr_meter_idx_nbo(p, t, ip);
5268 rte_prefetch0(m->n_pkts);
5269 time = rte_get_tsc_cycles();
5270 length = instr_meter_length_nbo(t, ip);
5271 color_in = (enum rte_color)ip->meter.color_in_val;
5273 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5274 &m->profile->profile,
5279 color_out &= m->color_mask;
5281 n_pkts = m->n_pkts[color_out];
5282 n_bytes = m->n_bytes[color_out];
5284 instr_meter_color_out_hbo_set(t, ip, color_out);
5286 m->n_pkts[color_out] = n_pkts + 1;
5287 m->n_bytes[color_out] = n_bytes + length;
5294 instr_meter_hmm_exec(struct rte_swx_pipeline *p)
5296 struct thread *t = &p->threads[p->thread_id];
5297 struct instruction *ip = t->ip;
5299 uint64_t time, n_pkts, n_bytes;
5301 enum rte_color color_in, color_out;
5303 TRACE("[Thread %2u] meter (hmm)\n", p->thread_id);
5306 m = instr_meter_idx_nbo(p, t, ip);
5307 rte_prefetch0(m->n_pkts);
5308 time = rte_get_tsc_cycles();
5309 length = instr_meter_length_hbo(t, ip);
5310 color_in = instr_meter_color_in_hbo(t, ip);
5312 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5313 &m->profile->profile,
5318 color_out &= m->color_mask;
5320 n_pkts = m->n_pkts[color_out];
5321 n_bytes = m->n_bytes[color_out];
5323 instr_meter_color_out_hbo_set(t, ip, color_out);
5325 m->n_pkts[color_out] = n_pkts + 1;
5326 m->n_bytes[color_out] = n_bytes + length;
5332 instr_meter_hmi_exec(struct rte_swx_pipeline *p)
5334 struct thread *t = &p->threads[p->thread_id];
5335 struct instruction *ip = t->ip;
5337 uint64_t time, n_pkts, n_bytes;
5339 enum rte_color color_in, color_out;
5341 TRACE("[Thread %2u] meter (hmi)\n", p->thread_id);
5344 m = instr_meter_idx_nbo(p, t, ip);
5345 rte_prefetch0(m->n_pkts);
5346 time = rte_get_tsc_cycles();
5347 length = instr_meter_length_hbo(t, ip);
5348 color_in = (enum rte_color)ip->meter.color_in_val;
5350 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5351 &m->profile->profile,
5356 color_out &= m->color_mask;
5358 n_pkts = m->n_pkts[color_out];
5359 n_bytes = m->n_bytes[color_out];
5361 instr_meter_color_out_hbo_set(t, ip, color_out);
5363 m->n_pkts[color_out] = n_pkts + 1;
5364 m->n_bytes[color_out] = n_bytes + length;
5371 instr_meter_mhm_exec(struct rte_swx_pipeline *p)
5373 struct thread *t = &p->threads[p->thread_id];
5374 struct instruction *ip = t->ip;
5376 uint64_t time, n_pkts, n_bytes;
5378 enum rte_color color_in, color_out;
5380 TRACE("[Thread %2u] meter (mhm)\n", p->thread_id);
5383 m = instr_meter_idx_hbo(p, t, ip);
5384 rte_prefetch0(m->n_pkts);
5385 time = rte_get_tsc_cycles();
5386 length = instr_meter_length_nbo(t, ip);
5387 color_in = instr_meter_color_in_hbo(t, ip);
5389 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5390 &m->profile->profile,
5395 color_out &= m->color_mask;
5397 n_pkts = m->n_pkts[color_out];
5398 n_bytes = m->n_bytes[color_out];
5400 instr_meter_color_out_hbo_set(t, ip, color_out);
5402 m->n_pkts[color_out] = n_pkts + 1;
5403 m->n_bytes[color_out] = n_bytes + length;
5410 instr_meter_mhi_exec(struct rte_swx_pipeline *p)
5412 struct thread *t = &p->threads[p->thread_id];
5413 struct instruction *ip = t->ip;
5415 uint64_t time, n_pkts, n_bytes;
5417 enum rte_color color_in, color_out;
5419 TRACE("[Thread %2u] meter (mhi)\n", p->thread_id);
5422 m = instr_meter_idx_hbo(p, t, ip);
5423 rte_prefetch0(m->n_pkts);
5424 time = rte_get_tsc_cycles();
5425 length = instr_meter_length_nbo(t, ip);
5426 color_in = (enum rte_color)ip->meter.color_in_val;
5428 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5429 &m->profile->profile,
5434 color_out &= m->color_mask;
5436 n_pkts = m->n_pkts[color_out];
5437 n_bytes = m->n_bytes[color_out];
5439 instr_meter_color_out_hbo_set(t, ip, color_out);
5441 m->n_pkts[color_out] = n_pkts + 1;
5442 m->n_bytes[color_out] = n_bytes + length;
5449 instr_meter_mmm_exec(struct rte_swx_pipeline *p)
5451 struct thread *t = &p->threads[p->thread_id];
5452 struct instruction *ip = t->ip;
5454 uint64_t time, n_pkts, n_bytes;
5456 enum rte_color color_in, color_out;
5458 TRACE("[Thread %2u] meter (mmm)\n", p->thread_id);
5461 m = instr_meter_idx_hbo(p, t, ip);
5462 rte_prefetch0(m->n_pkts);
5463 time = rte_get_tsc_cycles();
5464 length = instr_meter_length_hbo(t, ip);
5465 color_in = instr_meter_color_in_hbo(t, ip);
5467 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5468 &m->profile->profile,
5473 color_out &= m->color_mask;
5475 n_pkts = m->n_pkts[color_out];
5476 n_bytes = m->n_bytes[color_out];
5478 instr_meter_color_out_hbo_set(t, ip, color_out);
5480 m->n_pkts[color_out] = n_pkts + 1;
5481 m->n_bytes[color_out] = n_bytes + length;
5488 instr_meter_mmi_exec(struct rte_swx_pipeline *p)
5490 struct thread *t = &p->threads[p->thread_id];
5491 struct instruction *ip = t->ip;
5493 uint64_t time, n_pkts, n_bytes;
5495 enum rte_color color_in, color_out;
5497 TRACE("[Thread %2u] meter (mmi)\n", p->thread_id);
5500 m = instr_meter_idx_hbo(p, t, ip);
5501 rte_prefetch0(m->n_pkts);
5502 time = rte_get_tsc_cycles();
5503 length = instr_meter_length_hbo(t, ip);
5504 color_in = (enum rte_color)ip->meter.color_in_val;
5506 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5507 &m->profile->profile,
5512 color_out &= m->color_mask;
5514 n_pkts = m->n_pkts[color_out];
5515 n_bytes = m->n_bytes[color_out];
5517 instr_meter_color_out_hbo_set(t, ip, color_out);
5519 m->n_pkts[color_out] = n_pkts + 1;
5520 m->n_bytes[color_out] = n_bytes + length;
5527 instr_meter_ihm_exec(struct rte_swx_pipeline *p)
5529 struct thread *t = &p->threads[p->thread_id];
5530 struct instruction *ip = t->ip;
5532 uint64_t time, n_pkts, n_bytes;
5534 enum rte_color color_in, color_out;
5536 TRACE("[Thread %2u] meter (ihm)\n", p->thread_id);
5539 m = instr_meter_idx_imm(p, ip);
5540 rte_prefetch0(m->n_pkts);
5541 time = rte_get_tsc_cycles();
5542 length = instr_meter_length_nbo(t, ip);
5543 color_in = instr_meter_color_in_hbo(t, ip);
5545 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5546 &m->profile->profile,
5551 color_out &= m->color_mask;
5553 n_pkts = m->n_pkts[color_out];
5554 n_bytes = m->n_bytes[color_out];
5556 instr_meter_color_out_hbo_set(t, ip, color_out);
5558 m->n_pkts[color_out] = n_pkts + 1;
5559 m->n_bytes[color_out] = n_bytes + length;
5566 instr_meter_ihi_exec(struct rte_swx_pipeline *p)
5568 struct thread *t = &p->threads[p->thread_id];
5569 struct instruction *ip = t->ip;
5571 uint64_t time, n_pkts, n_bytes;
5573 enum rte_color color_in, color_out;
5575 TRACE("[Thread %2u] meter (ihi)\n", p->thread_id);
5578 m = instr_meter_idx_imm(p, ip);
5579 rte_prefetch0(m->n_pkts);
5580 time = rte_get_tsc_cycles();
5581 length = instr_meter_length_nbo(t, ip);
5582 color_in = (enum rte_color)ip->meter.color_in_val;
5584 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5585 &m->profile->profile,
5590 color_out &= m->color_mask;
5592 n_pkts = m->n_pkts[color_out];
5593 n_bytes = m->n_bytes[color_out];
5595 instr_meter_color_out_hbo_set(t, ip, color_out);
5597 m->n_pkts[color_out] = n_pkts + 1;
5598 m->n_bytes[color_out] = n_bytes + length;
5605 instr_meter_imm_exec(struct rte_swx_pipeline *p)
5607 struct thread *t = &p->threads[p->thread_id];
5608 struct instruction *ip = t->ip;
5610 uint64_t time, n_pkts, n_bytes;
5612 enum rte_color color_in, color_out;
5614 TRACE("[Thread %2u] meter (imm)\n", p->thread_id);
5617 m = instr_meter_idx_imm(p, ip);
5618 rte_prefetch0(m->n_pkts);
5619 time = rte_get_tsc_cycles();
5620 length = instr_meter_length_hbo(t, ip);
5621 color_in = instr_meter_color_in_hbo(t, ip);
5623 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5624 &m->profile->profile,
5629 color_out &= m->color_mask;
5631 n_pkts = m->n_pkts[color_out];
5632 n_bytes = m->n_bytes[color_out];
5634 instr_meter_color_out_hbo_set(t, ip, color_out);
5636 m->n_pkts[color_out] = n_pkts + 1;
5637 m->n_bytes[color_out] = n_bytes + length;
5643 instr_meter_imi_exec(struct rte_swx_pipeline *p)
5645 struct thread *t = &p->threads[p->thread_id];
5646 struct instruction *ip = t->ip;
5648 uint64_t time, n_pkts, n_bytes;
5650 enum rte_color color_in, color_out;
5652 TRACE("[Thread %2u] meter (imi)\n", p->thread_id);
5655 m = instr_meter_idx_imm(p, ip);
5656 rte_prefetch0(m->n_pkts);
5657 time = rte_get_tsc_cycles();
5658 length = instr_meter_length_hbo(t, ip);
5659 color_in = (enum rte_color)ip->meter.color_in_val;
5661 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5662 &m->profile->profile,
5667 color_out &= m->color_mask;
5669 n_pkts = m->n_pkts[color_out];
5670 n_bytes = m->n_bytes[color_out];
5672 instr_meter_color_out_hbo_set(t, ip, color_out);
5674 m->n_pkts[color_out] = n_pkts + 1;
5675 m->n_bytes[color_out] = n_bytes + length;
5685 instr_jmp_translate(struct rte_swx_pipeline *p __rte_unused,
5686 struct action *action __rte_unused,
5689 struct instruction *instr,
5690 struct instruction_data *data)
5692 CHECK(n_tokens == 2, EINVAL);
5694 strcpy(data->jmp_label, tokens[1]);
5696 instr->type = INSTR_JMP;
5697 instr->jmp.ip = NULL; /* Resolved later. */
5702 instr_jmp_valid_translate(struct rte_swx_pipeline *p,
5703 struct action *action __rte_unused,
5706 struct instruction *instr,
5707 struct instruction_data *data)
5711 CHECK(n_tokens == 3, EINVAL);
5713 strcpy(data->jmp_label, tokens[1]);
5715 h = header_parse(p, tokens[2]);
5718 instr->type = INSTR_JMP_VALID;
5719 instr->jmp.ip = NULL; /* Resolved later. */
5720 instr->jmp.header_id = h->id;
5725 instr_jmp_invalid_translate(struct rte_swx_pipeline *p,
5726 struct action *action __rte_unused,
5729 struct instruction *instr,
5730 struct instruction_data *data)
5734 CHECK(n_tokens == 3, EINVAL);
5736 strcpy(data->jmp_label, tokens[1]);
5738 h = header_parse(p, tokens[2]);
5741 instr->type = INSTR_JMP_INVALID;
5742 instr->jmp.ip = NULL; /* Resolved later. */
5743 instr->jmp.header_id = h->id;
5748 instr_jmp_hit_translate(struct rte_swx_pipeline *p __rte_unused,
5749 struct action *action,
5752 struct instruction *instr,
5753 struct instruction_data *data)
5755 CHECK(!action, EINVAL);
5756 CHECK(n_tokens == 2, EINVAL);
5758 strcpy(data->jmp_label, tokens[1]);
5760 instr->type = INSTR_JMP_HIT;
5761 instr->jmp.ip = NULL; /* Resolved later. */
5766 instr_jmp_miss_translate(struct rte_swx_pipeline *p __rte_unused,
5767 struct action *action,
5770 struct instruction *instr,
5771 struct instruction_data *data)
5773 CHECK(!action, EINVAL);
5774 CHECK(n_tokens == 2, EINVAL);
5776 strcpy(data->jmp_label, tokens[1]);
5778 instr->type = INSTR_JMP_MISS;
5779 instr->jmp.ip = NULL; /* Resolved later. */
5784 instr_jmp_action_hit_translate(struct rte_swx_pipeline *p,
5785 struct action *action,
5788 struct instruction *instr,
5789 struct instruction_data *data)
5793 CHECK(!action, EINVAL);
5794 CHECK(n_tokens == 3, EINVAL);
5796 strcpy(data->jmp_label, tokens[1]);
5798 a = action_find(p, tokens[2]);
5801 instr->type = INSTR_JMP_ACTION_HIT;
5802 instr->jmp.ip = NULL; /* Resolved later. */
5803 instr->jmp.action_id = a->id;
5808 instr_jmp_action_miss_translate(struct rte_swx_pipeline *p,
5809 struct action *action,
5812 struct instruction *instr,
5813 struct instruction_data *data)
5817 CHECK(!action, EINVAL);
5818 CHECK(n_tokens == 3, EINVAL);
5820 strcpy(data->jmp_label, tokens[1]);
5822 a = action_find(p, tokens[2]);
5825 instr->type = INSTR_JMP_ACTION_MISS;
5826 instr->jmp.ip = NULL; /* Resolved later. */
5827 instr->jmp.action_id = a->id;
5832 instr_jmp_eq_translate(struct rte_swx_pipeline *p,
5833 struct action *action,
5836 struct instruction *instr,
5837 struct instruction_data *data)
5839 char *a = tokens[2], *b = tokens[3];
5840 struct field *fa, *fb;
5842 uint32_t a_struct_id, b_struct_id;
5844 CHECK(n_tokens == 4, EINVAL);
5846 strcpy(data->jmp_label, tokens[1]);
5848 fa = struct_field_parse(p, action, a, &a_struct_id);
5850 CHECK(!fa->var_size, EINVAL);
5852 /* JMP_EQ, JMP_EQ_MH, JMP_EQ_HM, JMP_EQ_HH. */
5853 fb = struct_field_parse(p, action, b, &b_struct_id);
5855 CHECK(!fb->var_size, EINVAL);
5857 instr->type = INSTR_JMP_EQ;
5858 if (a[0] != 'h' && b[0] == 'h')
5859 instr->type = INSTR_JMP_EQ_MH;
5860 if (a[0] == 'h' && b[0] != 'h')
5861 instr->type = INSTR_JMP_EQ_HM;
5862 if (a[0] == 'h' && b[0] == 'h')
5863 instr->type = INSTR_JMP_EQ_HH;
5864 instr->jmp.ip = NULL; /* Resolved later. */
5866 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5867 instr->jmp.a.n_bits = fa->n_bits;
5868 instr->jmp.a.offset = fa->offset / 8;
5869 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5870 instr->jmp.b.n_bits = fb->n_bits;
5871 instr->jmp.b.offset = fb->offset / 8;
5876 b_val = strtoull(b, &b, 0);
5877 CHECK(!b[0], EINVAL);
5880 b_val = hton64(b_val) >> (64 - fa->n_bits);
5882 instr->type = INSTR_JMP_EQ_I;
5883 instr->jmp.ip = NULL; /* Resolved later. */
5884 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5885 instr->jmp.a.n_bits = fa->n_bits;
5886 instr->jmp.a.offset = fa->offset / 8;
5887 instr->jmp.b_val = b_val;
5892 instr_jmp_neq_translate(struct rte_swx_pipeline *p,
5893 struct action *action,
5896 struct instruction *instr,
5897 struct instruction_data *data)
5899 char *a = tokens[2], *b = tokens[3];
5900 struct field *fa, *fb;
5902 uint32_t a_struct_id, b_struct_id;
5904 CHECK(n_tokens == 4, EINVAL);
5906 strcpy(data->jmp_label, tokens[1]);
5908 fa = struct_field_parse(p, action, a, &a_struct_id);
5910 CHECK(!fa->var_size, EINVAL);
5912 /* JMP_NEQ, JMP_NEQ_MH, JMP_NEQ_HM, JMP_NEQ_HH. */
5913 fb = struct_field_parse(p, action, b, &b_struct_id);
5915 CHECK(!fb->var_size, EINVAL);
5917 instr->type = INSTR_JMP_NEQ;
5918 if (a[0] != 'h' && b[0] == 'h')
5919 instr->type = INSTR_JMP_NEQ_MH;
5920 if (a[0] == 'h' && b[0] != 'h')
5921 instr->type = INSTR_JMP_NEQ_HM;
5922 if (a[0] == 'h' && b[0] == 'h')
5923 instr->type = INSTR_JMP_NEQ_HH;
5924 instr->jmp.ip = NULL; /* Resolved later. */
5926 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5927 instr->jmp.a.n_bits = fa->n_bits;
5928 instr->jmp.a.offset = fa->offset / 8;
5929 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5930 instr->jmp.b.n_bits = fb->n_bits;
5931 instr->jmp.b.offset = fb->offset / 8;
5936 b_val = strtoull(b, &b, 0);
5937 CHECK(!b[0], EINVAL);
5940 b_val = hton64(b_val) >> (64 - fa->n_bits);
5942 instr->type = INSTR_JMP_NEQ_I;
5943 instr->jmp.ip = NULL; /* Resolved later. */
5944 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5945 instr->jmp.a.n_bits = fa->n_bits;
5946 instr->jmp.a.offset = fa->offset / 8;
5947 instr->jmp.b_val = b_val;
5952 instr_jmp_lt_translate(struct rte_swx_pipeline *p,
5953 struct action *action,
5956 struct instruction *instr,
5957 struct instruction_data *data)
5959 char *a = tokens[2], *b = tokens[3];
5960 struct field *fa, *fb;
5962 uint32_t a_struct_id, b_struct_id;
5964 CHECK(n_tokens == 4, EINVAL);
5966 strcpy(data->jmp_label, tokens[1]);
5968 fa = struct_field_parse(p, action, a, &a_struct_id);
5970 CHECK(!fa->var_size, EINVAL);
5972 /* JMP_LT, JMP_LT_MH, JMP_LT_HM, JMP_LT_HH. */
5973 fb = struct_field_parse(p, action, b, &b_struct_id);
5975 CHECK(!fb->var_size, EINVAL);
5977 instr->type = INSTR_JMP_LT;
5978 if (a[0] == 'h' && b[0] != 'h')
5979 instr->type = INSTR_JMP_LT_HM;
5980 if (a[0] != 'h' && b[0] == 'h')
5981 instr->type = INSTR_JMP_LT_MH;
5982 if (a[0] == 'h' && b[0] == 'h')
5983 instr->type = INSTR_JMP_LT_HH;
5984 instr->jmp.ip = NULL; /* Resolved later. */
5986 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5987 instr->jmp.a.n_bits = fa->n_bits;
5988 instr->jmp.a.offset = fa->offset / 8;
5989 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5990 instr->jmp.b.n_bits = fb->n_bits;
5991 instr->jmp.b.offset = fb->offset / 8;
5995 /* JMP_LT_MI, JMP_LT_HI. */
5996 b_val = strtoull(b, &b, 0);
5997 CHECK(!b[0], EINVAL);
5999 instr->type = INSTR_JMP_LT_MI;
6001 instr->type = INSTR_JMP_LT_HI;
6002 instr->jmp.ip = NULL; /* Resolved later. */
6004 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6005 instr->jmp.a.n_bits = fa->n_bits;
6006 instr->jmp.a.offset = fa->offset / 8;
6007 instr->jmp.b_val = b_val;
6012 instr_jmp_gt_translate(struct rte_swx_pipeline *p,
6013 struct action *action,
6016 struct instruction *instr,
6017 struct instruction_data *data)
6019 char *a = tokens[2], *b = tokens[3];
6020 struct field *fa, *fb;
6022 uint32_t a_struct_id, b_struct_id;
6024 CHECK(n_tokens == 4, EINVAL);
6026 strcpy(data->jmp_label, tokens[1]);
6028 fa = struct_field_parse(p, action, a, &a_struct_id);
6030 CHECK(!fa->var_size, EINVAL);
6032 /* JMP_GT, JMP_GT_MH, JMP_GT_HM, JMP_GT_HH. */
6033 fb = struct_field_parse(p, action, b, &b_struct_id);
6035 CHECK(!fb->var_size, EINVAL);
6037 instr->type = INSTR_JMP_GT;
6038 if (a[0] == 'h' && b[0] != 'h')
6039 instr->type = INSTR_JMP_GT_HM;
6040 if (a[0] != 'h' && b[0] == 'h')
6041 instr->type = INSTR_JMP_GT_MH;
6042 if (a[0] == 'h' && b[0] == 'h')
6043 instr->type = INSTR_JMP_GT_HH;
6044 instr->jmp.ip = NULL; /* Resolved later. */
6046 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6047 instr->jmp.a.n_bits = fa->n_bits;
6048 instr->jmp.a.offset = fa->offset / 8;
6049 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6050 instr->jmp.b.n_bits = fb->n_bits;
6051 instr->jmp.b.offset = fb->offset / 8;
6055 /* JMP_GT_MI, JMP_GT_HI. */
6056 b_val = strtoull(b, &b, 0);
6057 CHECK(!b[0], EINVAL);
6059 instr->type = INSTR_JMP_GT_MI;
6061 instr->type = INSTR_JMP_GT_HI;
6062 instr->jmp.ip = NULL; /* Resolved later. */
6064 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6065 instr->jmp.a.n_bits = fa->n_bits;
6066 instr->jmp.a.offset = fa->offset / 8;
6067 instr->jmp.b_val = b_val;
6072 instr_jmp_exec(struct rte_swx_pipeline *p)
6074 struct thread *t = &p->threads[p->thread_id];
6075 struct instruction *ip = t->ip;
6077 TRACE("[Thread %2u] jmp\n", p->thread_id);
6079 thread_ip_set(t, ip->jmp.ip);
6083 instr_jmp_valid_exec(struct rte_swx_pipeline *p)
6085 struct thread *t = &p->threads[p->thread_id];
6086 struct instruction *ip = t->ip;
6087 uint32_t header_id = ip->jmp.header_id;
6089 TRACE("[Thread %2u] jmpv\n", p->thread_id);
6091 t->ip = HEADER_VALID(t, header_id) ? ip->jmp.ip : (t->ip + 1);
6095 instr_jmp_invalid_exec(struct rte_swx_pipeline *p)
6097 struct thread *t = &p->threads[p->thread_id];
6098 struct instruction *ip = t->ip;
6099 uint32_t header_id = ip->jmp.header_id;
6101 TRACE("[Thread %2u] jmpnv\n", p->thread_id);
6103 t->ip = HEADER_VALID(t, header_id) ? (t->ip + 1) : ip->jmp.ip;
6107 instr_jmp_hit_exec(struct rte_swx_pipeline *p)
6109 struct thread *t = &p->threads[p->thread_id];
6110 struct instruction *ip = t->ip;
6111 struct instruction *ip_next[] = {t->ip + 1, ip->jmp.ip};
6113 TRACE("[Thread %2u] jmph\n", p->thread_id);
6115 t->ip = ip_next[t->hit];
6119 instr_jmp_miss_exec(struct rte_swx_pipeline *p)
6121 struct thread *t = &p->threads[p->thread_id];
6122 struct instruction *ip = t->ip;
6123 struct instruction *ip_next[] = {ip->jmp.ip, t->ip + 1};
6125 TRACE("[Thread %2u] jmpnh\n", p->thread_id);
6127 t->ip = ip_next[t->hit];
6131 instr_jmp_action_hit_exec(struct rte_swx_pipeline *p)
6133 struct thread *t = &p->threads[p->thread_id];
6134 struct instruction *ip = t->ip;
6136 TRACE("[Thread %2u] jmpa\n", p->thread_id);
6138 t->ip = (ip->jmp.action_id == t->action_id) ? ip->jmp.ip : (t->ip + 1);
6142 instr_jmp_action_miss_exec(struct rte_swx_pipeline *p)
6144 struct thread *t = &p->threads[p->thread_id];
6145 struct instruction *ip = t->ip;
6147 TRACE("[Thread %2u] jmpna\n", p->thread_id);
6149 t->ip = (ip->jmp.action_id == t->action_id) ? (t->ip + 1) : ip->jmp.ip;
6153 instr_jmp_eq_exec(struct rte_swx_pipeline *p)
6155 struct thread *t = &p->threads[p->thread_id];
6156 struct instruction *ip = t->ip;
6158 TRACE("[Thread %2u] jmpeq\n", p->thread_id);
6164 instr_jmp_eq_mh_exec(struct rte_swx_pipeline *p)
6166 struct thread *t = &p->threads[p->thread_id];
6167 struct instruction *ip = t->ip;
6169 TRACE("[Thread %2u] jmpeq (mh)\n", p->thread_id);
6171 JMP_CMP_MH(t, ip, ==);
6175 instr_jmp_eq_hm_exec(struct rte_swx_pipeline *p)
6177 struct thread *t = &p->threads[p->thread_id];
6178 struct instruction *ip = t->ip;
6180 TRACE("[Thread %2u] jmpeq (hm)\n", p->thread_id);
6182 JMP_CMP_HM(t, ip, ==);
6186 instr_jmp_eq_hh_exec(struct rte_swx_pipeline *p)
6188 struct thread *t = &p->threads[p->thread_id];
6189 struct instruction *ip = t->ip;
6191 TRACE("[Thread %2u] jmpeq (hh)\n", p->thread_id);
6193 JMP_CMP_HH_FAST(t, ip, ==);
6197 instr_jmp_eq_i_exec(struct rte_swx_pipeline *p)
6199 struct thread *t = &p->threads[p->thread_id];
6200 struct instruction *ip = t->ip;
6202 TRACE("[Thread %2u] jmpeq (i)\n", p->thread_id);
6204 JMP_CMP_I(t, ip, ==);
6208 instr_jmp_neq_exec(struct rte_swx_pipeline *p)
6210 struct thread *t = &p->threads[p->thread_id];
6211 struct instruction *ip = t->ip;
6213 TRACE("[Thread %2u] jmpneq\n", p->thread_id);
6219 instr_jmp_neq_mh_exec(struct rte_swx_pipeline *p)
6221 struct thread *t = &p->threads[p->thread_id];
6222 struct instruction *ip = t->ip;
6224 TRACE("[Thread %2u] jmpneq (mh)\n", p->thread_id);
6226 JMP_CMP_MH(t, ip, !=);
6230 instr_jmp_neq_hm_exec(struct rte_swx_pipeline *p)
6232 struct thread *t = &p->threads[p->thread_id];
6233 struct instruction *ip = t->ip;
6235 TRACE("[Thread %2u] jmpneq (hm)\n", p->thread_id);
6237 JMP_CMP_HM(t, ip, !=);
6241 instr_jmp_neq_hh_exec(struct rte_swx_pipeline *p)
6243 struct thread *t = &p->threads[p->thread_id];
6244 struct instruction *ip = t->ip;
6246 TRACE("[Thread %2u] jmpneq (hh)\n", p->thread_id);
6248 JMP_CMP_HH_FAST(t, ip, !=);
6252 instr_jmp_neq_i_exec(struct rte_swx_pipeline *p)
6254 struct thread *t = &p->threads[p->thread_id];
6255 struct instruction *ip = t->ip;
6257 TRACE("[Thread %2u] jmpneq (i)\n", p->thread_id);
6259 JMP_CMP_I(t, ip, !=);
6263 instr_jmp_lt_exec(struct rte_swx_pipeline *p)
6265 struct thread *t = &p->threads[p->thread_id];
6266 struct instruction *ip = t->ip;
6268 TRACE("[Thread %2u] jmplt\n", p->thread_id);
6274 instr_jmp_lt_mh_exec(struct rte_swx_pipeline *p)
6276 struct thread *t = &p->threads[p->thread_id];
6277 struct instruction *ip = t->ip;
6279 TRACE("[Thread %2u] jmplt (mh)\n", p->thread_id);
6281 JMP_CMP_MH(t, ip, <);
6285 instr_jmp_lt_hm_exec(struct rte_swx_pipeline *p)
6287 struct thread *t = &p->threads[p->thread_id];
6288 struct instruction *ip = t->ip;
6290 TRACE("[Thread %2u] jmplt (hm)\n", p->thread_id);
6292 JMP_CMP_HM(t, ip, <);
6296 instr_jmp_lt_hh_exec(struct rte_swx_pipeline *p)
6298 struct thread *t = &p->threads[p->thread_id];
6299 struct instruction *ip = t->ip;
6301 TRACE("[Thread %2u] jmplt (hh)\n", p->thread_id);
6303 JMP_CMP_HH(t, ip, <);
6307 instr_jmp_lt_mi_exec(struct rte_swx_pipeline *p)
6309 struct thread *t = &p->threads[p->thread_id];
6310 struct instruction *ip = t->ip;
6312 TRACE("[Thread %2u] jmplt (mi)\n", p->thread_id);
6314 JMP_CMP_MI(t, ip, <);
6318 instr_jmp_lt_hi_exec(struct rte_swx_pipeline *p)
6320 struct thread *t = &p->threads[p->thread_id];
6321 struct instruction *ip = t->ip;
6323 TRACE("[Thread %2u] jmplt (hi)\n", p->thread_id);
6325 JMP_CMP_HI(t, ip, <);
6329 instr_jmp_gt_exec(struct rte_swx_pipeline *p)
6331 struct thread *t = &p->threads[p->thread_id];
6332 struct instruction *ip = t->ip;
6334 TRACE("[Thread %2u] jmpgt\n", p->thread_id);
6340 instr_jmp_gt_mh_exec(struct rte_swx_pipeline *p)
6342 struct thread *t = &p->threads[p->thread_id];
6343 struct instruction *ip = t->ip;
6345 TRACE("[Thread %2u] jmpgt (mh)\n", p->thread_id);
6347 JMP_CMP_MH(t, ip, >);
6351 instr_jmp_gt_hm_exec(struct rte_swx_pipeline *p)
6353 struct thread *t = &p->threads[p->thread_id];
6354 struct instruction *ip = t->ip;
6356 TRACE("[Thread %2u] jmpgt (hm)\n", p->thread_id);
6358 JMP_CMP_HM(t, ip, >);
6362 instr_jmp_gt_hh_exec(struct rte_swx_pipeline *p)
6364 struct thread *t = &p->threads[p->thread_id];
6365 struct instruction *ip = t->ip;
6367 TRACE("[Thread %2u] jmpgt (hh)\n", p->thread_id);
6369 JMP_CMP_HH(t, ip, >);
6373 instr_jmp_gt_mi_exec(struct rte_swx_pipeline *p)
6375 struct thread *t = &p->threads[p->thread_id];
6376 struct instruction *ip = t->ip;
6378 TRACE("[Thread %2u] jmpgt (mi)\n", p->thread_id);
6380 JMP_CMP_MI(t, ip, >);
6384 instr_jmp_gt_hi_exec(struct rte_swx_pipeline *p)
6386 struct thread *t = &p->threads[p->thread_id];
6387 struct instruction *ip = t->ip;
6389 TRACE("[Thread %2u] jmpgt (hi)\n", p->thread_id);
6391 JMP_CMP_HI(t, ip, >);
6398 instr_return_translate(struct rte_swx_pipeline *p __rte_unused,
6399 struct action *action,
6400 char **tokens __rte_unused,
6402 struct instruction *instr,
6403 struct instruction_data *data __rte_unused)
6405 CHECK(action, EINVAL);
6406 CHECK(n_tokens == 1, EINVAL);
6408 instr->type = INSTR_RETURN;
6413 instr_return_exec(struct rte_swx_pipeline *p)
6415 struct thread *t = &p->threads[p->thread_id];
6417 TRACE("[Thread %2u] return\n", p->thread_id);
6423 instr_translate(struct rte_swx_pipeline *p,
6424 struct action *action,
6426 struct instruction *instr,
6427 struct instruction_data *data)
6429 char *tokens[RTE_SWX_INSTRUCTION_TOKENS_MAX];
6430 int n_tokens = 0, tpos = 0;
6432 /* Parse the instruction string into tokens. */
6436 token = strtok_r(string, " \t\v", &string);
6440 CHECK(n_tokens < RTE_SWX_INSTRUCTION_TOKENS_MAX, EINVAL);
6441 CHECK_NAME(token, EINVAL);
6443 tokens[n_tokens] = token;
6447 CHECK(n_tokens, EINVAL);
6449 /* Handle the optional instruction label. */
6450 if ((n_tokens >= 2) && !strcmp(tokens[1], ":")) {
6451 strcpy(data->label, tokens[0]);
6454 CHECK(n_tokens - tpos, EINVAL);
6457 /* Identify the instruction type. */
6458 if (!strcmp(tokens[tpos], "rx"))
6459 return instr_rx_translate(p,
6466 if (!strcmp(tokens[tpos], "tx"))
6467 return instr_tx_translate(p,
6474 if (!strcmp(tokens[tpos], "drop"))
6475 return instr_drop_translate(p,
6482 if (!strcmp(tokens[tpos], "extract"))
6483 return instr_hdr_extract_translate(p,
6490 if (!strcmp(tokens[tpos], "lookahead"))
6491 return instr_hdr_lookahead_translate(p,
6498 if (!strcmp(tokens[tpos], "emit"))
6499 return instr_hdr_emit_translate(p,
6506 if (!strcmp(tokens[tpos], "validate"))
6507 return instr_hdr_validate_translate(p,
6514 if (!strcmp(tokens[tpos], "invalidate"))
6515 return instr_hdr_invalidate_translate(p,
6522 if (!strcmp(tokens[tpos], "mov"))
6523 return instr_mov_translate(p,
6530 if (!strcmp(tokens[tpos], "add"))
6531 return instr_alu_add_translate(p,
6538 if (!strcmp(tokens[tpos], "sub"))
6539 return instr_alu_sub_translate(p,
6546 if (!strcmp(tokens[tpos], "ckadd"))
6547 return instr_alu_ckadd_translate(p,
6554 if (!strcmp(tokens[tpos], "cksub"))
6555 return instr_alu_cksub_translate(p,
6562 if (!strcmp(tokens[tpos], "and"))
6563 return instr_alu_and_translate(p,
6570 if (!strcmp(tokens[tpos], "or"))
6571 return instr_alu_or_translate(p,
6578 if (!strcmp(tokens[tpos], "xor"))
6579 return instr_alu_xor_translate(p,
6586 if (!strcmp(tokens[tpos], "shl"))
6587 return instr_alu_shl_translate(p,
6594 if (!strcmp(tokens[tpos], "shr"))
6595 return instr_alu_shr_translate(p,
6602 if (!strcmp(tokens[tpos], "regprefetch"))
6603 return instr_regprefetch_translate(p,
6610 if (!strcmp(tokens[tpos], "regrd"))
6611 return instr_regrd_translate(p,
6618 if (!strcmp(tokens[tpos], "regwr"))
6619 return instr_regwr_translate(p,
6626 if (!strcmp(tokens[tpos], "regadd"))
6627 return instr_regadd_translate(p,
6634 if (!strcmp(tokens[tpos], "metprefetch"))
6635 return instr_metprefetch_translate(p,
6642 if (!strcmp(tokens[tpos], "meter"))
6643 return instr_meter_translate(p,
6650 if (!strcmp(tokens[tpos], "table"))
6651 return instr_table_translate(p,
6658 if (!strcmp(tokens[tpos], "learn"))
6659 return instr_learn_translate(p,
6666 if (!strcmp(tokens[tpos], "forget"))
6667 return instr_forget_translate(p,
6674 if (!strcmp(tokens[tpos], "extern"))
6675 return instr_extern_translate(p,
6682 if (!strcmp(tokens[tpos], "jmp"))
6683 return instr_jmp_translate(p,
6690 if (!strcmp(tokens[tpos], "jmpv"))
6691 return instr_jmp_valid_translate(p,
6698 if (!strcmp(tokens[tpos], "jmpnv"))
6699 return instr_jmp_invalid_translate(p,
6706 if (!strcmp(tokens[tpos], "jmph"))
6707 return instr_jmp_hit_translate(p,
6714 if (!strcmp(tokens[tpos], "jmpnh"))
6715 return instr_jmp_miss_translate(p,
6722 if (!strcmp(tokens[tpos], "jmpa"))
6723 return instr_jmp_action_hit_translate(p,
6730 if (!strcmp(tokens[tpos], "jmpna"))
6731 return instr_jmp_action_miss_translate(p,
6738 if (!strcmp(tokens[tpos], "jmpeq"))
6739 return instr_jmp_eq_translate(p,
6746 if (!strcmp(tokens[tpos], "jmpneq"))
6747 return instr_jmp_neq_translate(p,
6754 if (!strcmp(tokens[tpos], "jmplt"))
6755 return instr_jmp_lt_translate(p,
6762 if (!strcmp(tokens[tpos], "jmpgt"))
6763 return instr_jmp_gt_translate(p,
6770 if (!strcmp(tokens[tpos], "return"))
6771 return instr_return_translate(p,
6781 static struct instruction_data *
6782 label_find(struct instruction_data *data, uint32_t n, const char *label)
6786 for (i = 0; i < n; i++)
6787 if (!strcmp(label, data[i].label))
6794 label_is_used(struct instruction_data *data, uint32_t n, const char *label)
6796 uint32_t count = 0, i;
6801 for (i = 0; i < n; i++)
6802 if (!strcmp(label, data[i].jmp_label))
6809 instr_label_check(struct instruction_data *instruction_data,
6810 uint32_t n_instructions)
6814 /* Check that all instruction labels are unique. */
6815 for (i = 0; i < n_instructions; i++) {
6816 struct instruction_data *data = &instruction_data[i];
6817 char *label = data->label;
6823 for (j = i + 1; j < n_instructions; j++)
6824 CHECK(strcmp(label, data[j].label), EINVAL);
6827 /* Get users for each instruction label. */
6828 for (i = 0; i < n_instructions; i++) {
6829 struct instruction_data *data = &instruction_data[i];
6830 char *label = data->label;
6832 data->n_users = label_is_used(instruction_data,
6841 instr_jmp_resolve(struct instruction *instructions,
6842 struct instruction_data *instruction_data,
6843 uint32_t n_instructions)
6847 for (i = 0; i < n_instructions; i++) {
6848 struct instruction *instr = &instructions[i];
6849 struct instruction_data *data = &instruction_data[i];
6850 struct instruction_data *found;
6852 if (!instruction_is_jmp(instr))
6855 found = label_find(instruction_data,
6858 CHECK(found, EINVAL);
6860 instr->jmp.ip = &instructions[found - instruction_data];
6867 instr_verify(struct rte_swx_pipeline *p __rte_unused,
6869 struct instruction *instr,
6870 struct instruction_data *data __rte_unused,
6871 uint32_t n_instructions)
6874 enum instruction_type type;
6877 /* Check that the first instruction is rx. */
6878 CHECK(instr[0].type == INSTR_RX, EINVAL);
6880 /* Check that there is at least one tx instruction. */
6881 for (i = 0; i < n_instructions; i++) {
6882 type = instr[i].type;
6884 if (instruction_is_tx(type))
6887 CHECK(i < n_instructions, EINVAL);
6889 /* Check that the last instruction is either tx or unconditional
6892 type = instr[n_instructions - 1].type;
6893 CHECK(instruction_is_tx(type) || (type == INSTR_JMP), EINVAL);
6897 enum instruction_type type;
6900 /* Check that there is at least one return or tx instruction. */
6901 for (i = 0; i < n_instructions; i++) {
6902 type = instr[i].type;
6904 if ((type == INSTR_RETURN) || instruction_is_tx(type))
6907 CHECK(i < n_instructions, EINVAL);
6914 instr_compact(struct instruction *instructions,
6915 struct instruction_data *instruction_data,
6916 uint32_t n_instructions)
6918 uint32_t i, pos = 0;
6920 /* Eliminate the invalid instructions that have been optimized out. */
6921 for (i = 0; i < n_instructions; i++) {
6922 struct instruction *instr = &instructions[i];
6923 struct instruction_data *data = &instruction_data[i];
6929 memcpy(&instructions[pos], instr, sizeof(*instr));
6930 memcpy(&instruction_data[pos], data, sizeof(*data));
6940 instr_pattern_extract_many_search(struct instruction *instr,
6941 struct instruction_data *data,
6943 uint32_t *n_pattern_instr)
6947 for (i = 0; i < n_instr; i++) {
6948 if (data[i].invalid)
6951 if (instr[i].type != INSTR_HDR_EXTRACT)
6954 if (i == RTE_DIM(instr->io.hdr.header_id))
6957 if (i && data[i].n_users)
6964 *n_pattern_instr = i;
6969 instr_pattern_extract_many_replace(struct instruction *instr,
6970 struct instruction_data *data,
6975 for (i = 1; i < n_instr; i++) {
6977 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
6978 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
6979 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
6981 data[i].invalid = 1;
6986 instr_pattern_extract_many_optimize(struct instruction *instructions,
6987 struct instruction_data *instruction_data,
6988 uint32_t n_instructions)
6992 for (i = 0; i < n_instructions; ) {
6993 struct instruction *instr = &instructions[i];
6994 struct instruction_data *data = &instruction_data[i];
6995 uint32_t n_instr = 0;
6999 detected = instr_pattern_extract_many_search(instr,
7004 instr_pattern_extract_many_replace(instr,
7011 /* No pattern starting at the current instruction. */
7015 /* Eliminate the invalid instructions that have been optimized out. */
7016 n_instructions = instr_compact(instructions,
7020 return n_instructions;
7024 instr_pattern_emit_many_tx_search(struct instruction *instr,
7025 struct instruction_data *data,
7027 uint32_t *n_pattern_instr)
7031 for (i = 0; i < n_instr; i++) {
7032 if (data[i].invalid)
7035 if (instr[i].type != INSTR_HDR_EMIT)
7038 if (i == RTE_DIM(instr->io.hdr.header_id))
7041 if (i && data[i].n_users)
7048 if (!instruction_is_tx(instr[i].type))
7051 if (data[i].n_users)
7056 *n_pattern_instr = i;
7061 instr_pattern_emit_many_tx_replace(struct instruction *instr,
7062 struct instruction_data *data,
7067 /* Any emit instruction in addition to the first one. */
7068 for (i = 1; i < n_instr - 1; i++) {
7070 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
7071 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
7072 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
7074 data[i].invalid = 1;
7077 /* The TX instruction is the last one in the pattern. */
7079 instr[0].io.io.offset = instr[i].io.io.offset;
7080 instr[0].io.io.n_bits = instr[i].io.io.n_bits;
7081 data[i].invalid = 1;
7085 instr_pattern_emit_many_tx_optimize(struct instruction *instructions,
7086 struct instruction_data *instruction_data,
7087 uint32_t n_instructions)
7091 for (i = 0; i < n_instructions; ) {
7092 struct instruction *instr = &instructions[i];
7093 struct instruction_data *data = &instruction_data[i];
7094 uint32_t n_instr = 0;
7097 /* Emit many + TX. */
7098 detected = instr_pattern_emit_many_tx_search(instr,
7103 instr_pattern_emit_many_tx_replace(instr,
7110 /* No pattern starting at the current instruction. */
7114 /* Eliminate the invalid instructions that have been optimized out. */
7115 n_instructions = instr_compact(instructions,
7119 return n_instructions;
7123 action_arg_src_mov_count(struct action *a,
7125 struct instruction *instructions,
7126 struct instruction_data *instruction_data,
7127 uint32_t n_instructions);
7130 instr_pattern_mov_all_validate_search(struct rte_swx_pipeline *p,
7132 struct instruction *instr,
7133 struct instruction_data *data,
7135 struct instruction *instructions,
7136 struct instruction_data *instruction_data,
7137 uint32_t n_instructions,
7138 uint32_t *n_pattern_instr)
7141 uint32_t src_field_id, i, j;
7143 /* Prerequisites. */
7147 /* First instruction: MOV_HM. */
7148 if (data[0].invalid || (instr[0].type != INSTR_MOV_HM))
7151 h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
7152 if (!h || h->st->var_size)
7155 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
7156 if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
7159 if (src_field_id == a->st->n_fields)
7162 if (instr[0].mov.dst.offset ||
7163 (instr[0].mov.dst.n_bits != h->st->fields[0].n_bits) ||
7164 instr[0].mov.src.struct_id ||
7165 (instr[0].mov.src.n_bits != a->st->fields[src_field_id].n_bits) ||
7166 (instr[0].mov.dst.n_bits != instr[0].mov.src.n_bits))
7169 if ((n_instr < h->st->n_fields + 1) ||
7170 (a->st->n_fields < src_field_id + h->st->n_fields + 1))
7173 /* Subsequent instructions: MOV_HM. */
7174 for (i = 1; i < h->st->n_fields; i++)
7175 if (data[i].invalid ||
7177 (instr[i].type != INSTR_MOV_HM) ||
7178 (instr[i].mov.dst.struct_id != h->struct_id) ||
7179 (instr[i].mov.dst.offset != h->st->fields[i].offset / 8) ||
7180 (instr[i].mov.dst.n_bits != h->st->fields[i].n_bits) ||
7181 instr[i].mov.src.struct_id ||
7182 (instr[i].mov.src.offset != a->st->fields[src_field_id + i].offset / 8) ||
7183 (instr[i].mov.src.n_bits != a->st->fields[src_field_id + i].n_bits) ||
7184 (instr[i].mov.dst.n_bits != instr[i].mov.src.n_bits))
7187 /* Last instruction: HDR_VALIDATE. */
7188 if ((instr[i].type != INSTR_HDR_VALIDATE) ||
7189 (instr[i].valid.header_id != h->id))
7192 /* Check that none of the action args that are used as source for this
7193 * DMA transfer are not used as source in any other mov instruction.
7195 for (j = src_field_id; j < src_field_id + h->st->n_fields; j++) {
7198 n_users = action_arg_src_mov_count(a,
7207 *n_pattern_instr = 1 + i;
7212 instr_pattern_mov_all_validate_replace(struct rte_swx_pipeline *p,
7214 struct instruction *instr,
7215 struct instruction_data *data,
7219 uint32_t src_field_id, src_offset, i;
7221 /* Read from the instructions before they are modified. */
7222 h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
7226 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
7227 if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
7230 if (src_field_id == a->st->n_fields)
7233 src_offset = instr[0].mov.src.offset;
7235 /* Modify the instructions. */
7236 instr[0].type = INSTR_DMA_HT;
7237 instr[0].dma.dst.header_id[0] = h->id;
7238 instr[0].dma.dst.struct_id[0] = h->struct_id;
7239 instr[0].dma.src.offset[0] = (uint8_t)src_offset;
7240 instr[0].dma.n_bytes[0] = h->st->n_bits / 8;
7242 for (i = 1; i < n_instr; i++)
7243 data[i].invalid = 1;
7245 /* Update the endianness of the action arguments to header endianness. */
7246 for (i = 0; i < h->st->n_fields; i++)
7247 a->args_endianness[src_field_id + i] = 1;
7251 instr_pattern_mov_all_validate_optimize(struct rte_swx_pipeline *p,
7253 struct instruction *instructions,
7254 struct instruction_data *instruction_data,
7255 uint32_t n_instructions)
7260 return n_instructions;
7262 for (i = 0; i < n_instructions; ) {
7263 struct instruction *instr = &instructions[i];
7264 struct instruction_data *data = &instruction_data[i];
7265 uint32_t n_instr = 0;
7268 /* Mov all + validate. */
7269 detected = instr_pattern_mov_all_validate_search(p,
7279 instr_pattern_mov_all_validate_replace(p, a, instr, data, n_instr);
7284 /* No pattern starting at the current instruction. */
7288 /* Eliminate the invalid instructions that have been optimized out. */
7289 n_instructions = instr_compact(instructions,
7293 return n_instructions;
7297 instr_pattern_dma_many_search(struct instruction *instr,
7298 struct instruction_data *data,
7300 uint32_t *n_pattern_instr)
7304 for (i = 0; i < n_instr; i++) {
7305 if (data[i].invalid)
7308 if (instr[i].type != INSTR_DMA_HT)
7311 if (i == RTE_DIM(instr->dma.dst.header_id))
7314 if (i && data[i].n_users)
7321 *n_pattern_instr = i;
7326 instr_pattern_dma_many_replace(struct instruction *instr,
7327 struct instruction_data *data,
7332 for (i = 1; i < n_instr; i++) {
7334 instr[0].dma.dst.header_id[i] = instr[i].dma.dst.header_id[0];
7335 instr[0].dma.dst.struct_id[i] = instr[i].dma.dst.struct_id[0];
7336 instr[0].dma.src.offset[i] = instr[i].dma.src.offset[0];
7337 instr[0].dma.n_bytes[i] = instr[i].dma.n_bytes[0];
7339 data[i].invalid = 1;
7344 instr_pattern_dma_many_optimize(struct instruction *instructions,
7345 struct instruction_data *instruction_data,
7346 uint32_t n_instructions)
7350 for (i = 0; i < n_instructions; ) {
7351 struct instruction *instr = &instructions[i];
7352 struct instruction_data *data = &instruction_data[i];
7353 uint32_t n_instr = 0;
7357 detected = instr_pattern_dma_many_search(instr,
7362 instr_pattern_dma_many_replace(instr, data, n_instr);
7367 /* No pattern starting at the current instruction. */
7371 /* Eliminate the invalid instructions that have been optimized out. */
7372 n_instructions = instr_compact(instructions,
7376 return n_instructions;
7380 instr_optimize(struct rte_swx_pipeline *p,
7382 struct instruction *instructions,
7383 struct instruction_data *instruction_data,
7384 uint32_t n_instructions)
7387 n_instructions = instr_pattern_extract_many_optimize(instructions,
7391 /* Emit many + TX. */
7392 n_instructions = instr_pattern_emit_many_tx_optimize(instructions,
7396 /* Mov all + validate. */
7397 n_instructions = instr_pattern_mov_all_validate_optimize(p,
7404 n_instructions = instr_pattern_dma_many_optimize(instructions,
7408 return n_instructions;
7412 instruction_config(struct rte_swx_pipeline *p,
7414 const char **instructions,
7415 uint32_t n_instructions)
7417 struct instruction *instr = NULL;
7418 struct instruction_data *data = NULL;
7422 CHECK(n_instructions, EINVAL);
7423 CHECK(instructions, EINVAL);
7424 for (i = 0; i < n_instructions; i++)
7425 CHECK_INSTRUCTION(instructions[i], EINVAL);
7427 /* Memory allocation. */
7428 instr = calloc(n_instructions, sizeof(struct instruction));
7434 data = calloc(n_instructions, sizeof(struct instruction_data));
7440 for (i = 0; i < n_instructions; i++) {
7441 char *string = strdup(instructions[i]);
7447 err = instr_translate(p, a, string, &instr[i], &data[i]);
7456 err = instr_label_check(data, n_instructions);
7460 err = instr_verify(p, a, instr, data, n_instructions);
7464 n_instructions = instr_optimize(p, a, instr, data, n_instructions);
7466 err = instr_jmp_resolve(instr, data, n_instructions);
7471 a->instructions = instr;
7472 a->n_instructions = n_instructions;
7474 p->instructions = instr;
7475 p->n_instructions = n_instructions;
7487 typedef void (*instr_exec_t)(struct rte_swx_pipeline *);
7489 static instr_exec_t instruction_table[] = {
7490 [INSTR_RX] = instr_rx_exec,
7491 [INSTR_TX] = instr_tx_exec,
7492 [INSTR_TX_I] = instr_tx_i_exec,
7494 [INSTR_HDR_EXTRACT] = instr_hdr_extract_exec,
7495 [INSTR_HDR_EXTRACT2] = instr_hdr_extract2_exec,
7496 [INSTR_HDR_EXTRACT3] = instr_hdr_extract3_exec,
7497 [INSTR_HDR_EXTRACT4] = instr_hdr_extract4_exec,
7498 [INSTR_HDR_EXTRACT5] = instr_hdr_extract5_exec,
7499 [INSTR_HDR_EXTRACT6] = instr_hdr_extract6_exec,
7500 [INSTR_HDR_EXTRACT7] = instr_hdr_extract7_exec,
7501 [INSTR_HDR_EXTRACT8] = instr_hdr_extract8_exec,
7502 [INSTR_HDR_EXTRACT_M] = instr_hdr_extract_m_exec,
7503 [INSTR_HDR_LOOKAHEAD] = instr_hdr_lookahead_exec,
7505 [INSTR_HDR_EMIT] = instr_hdr_emit_exec,
7506 [INSTR_HDR_EMIT_TX] = instr_hdr_emit_tx_exec,
7507 [INSTR_HDR_EMIT2_TX] = instr_hdr_emit2_tx_exec,
7508 [INSTR_HDR_EMIT3_TX] = instr_hdr_emit3_tx_exec,
7509 [INSTR_HDR_EMIT4_TX] = instr_hdr_emit4_tx_exec,
7510 [INSTR_HDR_EMIT5_TX] = instr_hdr_emit5_tx_exec,
7511 [INSTR_HDR_EMIT6_TX] = instr_hdr_emit6_tx_exec,
7512 [INSTR_HDR_EMIT7_TX] = instr_hdr_emit7_tx_exec,
7513 [INSTR_HDR_EMIT8_TX] = instr_hdr_emit8_tx_exec,
7515 [INSTR_HDR_VALIDATE] = instr_hdr_validate_exec,
7516 [INSTR_HDR_INVALIDATE] = instr_hdr_invalidate_exec,
7518 [INSTR_MOV] = instr_mov_exec,
7519 [INSTR_MOV_MH] = instr_mov_mh_exec,
7520 [INSTR_MOV_HM] = instr_mov_hm_exec,
7521 [INSTR_MOV_HH] = instr_mov_hh_exec,
7522 [INSTR_MOV_I] = instr_mov_i_exec,
7524 [INSTR_DMA_HT] = instr_dma_ht_exec,
7525 [INSTR_DMA_HT2] = instr_dma_ht2_exec,
7526 [INSTR_DMA_HT3] = instr_dma_ht3_exec,
7527 [INSTR_DMA_HT4] = instr_dma_ht4_exec,
7528 [INSTR_DMA_HT5] = instr_dma_ht5_exec,
7529 [INSTR_DMA_HT6] = instr_dma_ht6_exec,
7530 [INSTR_DMA_HT7] = instr_dma_ht7_exec,
7531 [INSTR_DMA_HT8] = instr_dma_ht8_exec,
7533 [INSTR_ALU_ADD] = instr_alu_add_exec,
7534 [INSTR_ALU_ADD_MH] = instr_alu_add_mh_exec,
7535 [INSTR_ALU_ADD_HM] = instr_alu_add_hm_exec,
7536 [INSTR_ALU_ADD_HH] = instr_alu_add_hh_exec,
7537 [INSTR_ALU_ADD_MI] = instr_alu_add_mi_exec,
7538 [INSTR_ALU_ADD_HI] = instr_alu_add_hi_exec,
7540 [INSTR_ALU_SUB] = instr_alu_sub_exec,
7541 [INSTR_ALU_SUB_MH] = instr_alu_sub_mh_exec,
7542 [INSTR_ALU_SUB_HM] = instr_alu_sub_hm_exec,
7543 [INSTR_ALU_SUB_HH] = instr_alu_sub_hh_exec,
7544 [INSTR_ALU_SUB_MI] = instr_alu_sub_mi_exec,
7545 [INSTR_ALU_SUB_HI] = instr_alu_sub_hi_exec,
7547 [INSTR_ALU_CKADD_FIELD] = instr_alu_ckadd_field_exec,
7548 [INSTR_ALU_CKADD_STRUCT] = instr_alu_ckadd_struct_exec,
7549 [INSTR_ALU_CKADD_STRUCT20] = instr_alu_ckadd_struct20_exec,
7550 [INSTR_ALU_CKSUB_FIELD] = instr_alu_cksub_field_exec,
7552 [INSTR_ALU_AND] = instr_alu_and_exec,
7553 [INSTR_ALU_AND_MH] = instr_alu_and_mh_exec,
7554 [INSTR_ALU_AND_HM] = instr_alu_and_hm_exec,
7555 [INSTR_ALU_AND_HH] = instr_alu_and_hh_exec,
7556 [INSTR_ALU_AND_I] = instr_alu_and_i_exec,
7558 [INSTR_ALU_OR] = instr_alu_or_exec,
7559 [INSTR_ALU_OR_MH] = instr_alu_or_mh_exec,
7560 [INSTR_ALU_OR_HM] = instr_alu_or_hm_exec,
7561 [INSTR_ALU_OR_HH] = instr_alu_or_hh_exec,
7562 [INSTR_ALU_OR_I] = instr_alu_or_i_exec,
7564 [INSTR_ALU_XOR] = instr_alu_xor_exec,
7565 [INSTR_ALU_XOR_MH] = instr_alu_xor_mh_exec,
7566 [INSTR_ALU_XOR_HM] = instr_alu_xor_hm_exec,
7567 [INSTR_ALU_XOR_HH] = instr_alu_xor_hh_exec,
7568 [INSTR_ALU_XOR_I] = instr_alu_xor_i_exec,
7570 [INSTR_ALU_SHL] = instr_alu_shl_exec,
7571 [INSTR_ALU_SHL_MH] = instr_alu_shl_mh_exec,
7572 [INSTR_ALU_SHL_HM] = instr_alu_shl_hm_exec,
7573 [INSTR_ALU_SHL_HH] = instr_alu_shl_hh_exec,
7574 [INSTR_ALU_SHL_MI] = instr_alu_shl_mi_exec,
7575 [INSTR_ALU_SHL_HI] = instr_alu_shl_hi_exec,
7577 [INSTR_ALU_SHR] = instr_alu_shr_exec,
7578 [INSTR_ALU_SHR_MH] = instr_alu_shr_mh_exec,
7579 [INSTR_ALU_SHR_HM] = instr_alu_shr_hm_exec,
7580 [INSTR_ALU_SHR_HH] = instr_alu_shr_hh_exec,
7581 [INSTR_ALU_SHR_MI] = instr_alu_shr_mi_exec,
7582 [INSTR_ALU_SHR_HI] = instr_alu_shr_hi_exec,
7584 [INSTR_REGPREFETCH_RH] = instr_regprefetch_rh_exec,
7585 [INSTR_REGPREFETCH_RM] = instr_regprefetch_rm_exec,
7586 [INSTR_REGPREFETCH_RI] = instr_regprefetch_ri_exec,
7588 [INSTR_REGRD_HRH] = instr_regrd_hrh_exec,
7589 [INSTR_REGRD_HRM] = instr_regrd_hrm_exec,
7590 [INSTR_REGRD_MRH] = instr_regrd_mrh_exec,
7591 [INSTR_REGRD_MRM] = instr_regrd_mrm_exec,
7592 [INSTR_REGRD_HRI] = instr_regrd_hri_exec,
7593 [INSTR_REGRD_MRI] = instr_regrd_mri_exec,
7595 [INSTR_REGWR_RHH] = instr_regwr_rhh_exec,
7596 [INSTR_REGWR_RHM] = instr_regwr_rhm_exec,
7597 [INSTR_REGWR_RMH] = instr_regwr_rmh_exec,
7598 [INSTR_REGWR_RMM] = instr_regwr_rmm_exec,
7599 [INSTR_REGWR_RHI] = instr_regwr_rhi_exec,
7600 [INSTR_REGWR_RMI] = instr_regwr_rmi_exec,
7601 [INSTR_REGWR_RIH] = instr_regwr_rih_exec,
7602 [INSTR_REGWR_RIM] = instr_regwr_rim_exec,
7603 [INSTR_REGWR_RII] = instr_regwr_rii_exec,
7605 [INSTR_REGADD_RHH] = instr_regadd_rhh_exec,
7606 [INSTR_REGADD_RHM] = instr_regadd_rhm_exec,
7607 [INSTR_REGADD_RMH] = instr_regadd_rmh_exec,
7608 [INSTR_REGADD_RMM] = instr_regadd_rmm_exec,
7609 [INSTR_REGADD_RHI] = instr_regadd_rhi_exec,
7610 [INSTR_REGADD_RMI] = instr_regadd_rmi_exec,
7611 [INSTR_REGADD_RIH] = instr_regadd_rih_exec,
7612 [INSTR_REGADD_RIM] = instr_regadd_rim_exec,
7613 [INSTR_REGADD_RII] = instr_regadd_rii_exec,
7615 [INSTR_METPREFETCH_H] = instr_metprefetch_h_exec,
7616 [INSTR_METPREFETCH_M] = instr_metprefetch_m_exec,
7617 [INSTR_METPREFETCH_I] = instr_metprefetch_i_exec,
7619 [INSTR_METER_HHM] = instr_meter_hhm_exec,
7620 [INSTR_METER_HHI] = instr_meter_hhi_exec,
7621 [INSTR_METER_HMM] = instr_meter_hmm_exec,
7622 [INSTR_METER_HMI] = instr_meter_hmi_exec,
7623 [INSTR_METER_MHM] = instr_meter_mhm_exec,
7624 [INSTR_METER_MHI] = instr_meter_mhi_exec,
7625 [INSTR_METER_MMM] = instr_meter_mmm_exec,
7626 [INSTR_METER_MMI] = instr_meter_mmi_exec,
7627 [INSTR_METER_IHM] = instr_meter_ihm_exec,
7628 [INSTR_METER_IHI] = instr_meter_ihi_exec,
7629 [INSTR_METER_IMM] = instr_meter_imm_exec,
7630 [INSTR_METER_IMI] = instr_meter_imi_exec,
7632 [INSTR_TABLE] = instr_table_exec,
7633 [INSTR_SELECTOR] = instr_selector_exec,
7634 [INSTR_LEARNER] = instr_learner_exec,
7635 [INSTR_LEARNER_LEARN] = instr_learn_exec,
7636 [INSTR_LEARNER_FORGET] = instr_forget_exec,
7637 [INSTR_EXTERN_OBJ] = instr_extern_obj_exec,
7638 [INSTR_EXTERN_FUNC] = instr_extern_func_exec,
7640 [INSTR_JMP] = instr_jmp_exec,
7641 [INSTR_JMP_VALID] = instr_jmp_valid_exec,
7642 [INSTR_JMP_INVALID] = instr_jmp_invalid_exec,
7643 [INSTR_JMP_HIT] = instr_jmp_hit_exec,
7644 [INSTR_JMP_MISS] = instr_jmp_miss_exec,
7645 [INSTR_JMP_ACTION_HIT] = instr_jmp_action_hit_exec,
7646 [INSTR_JMP_ACTION_MISS] = instr_jmp_action_miss_exec,
7648 [INSTR_JMP_EQ] = instr_jmp_eq_exec,
7649 [INSTR_JMP_EQ_MH] = instr_jmp_eq_mh_exec,
7650 [INSTR_JMP_EQ_HM] = instr_jmp_eq_hm_exec,
7651 [INSTR_JMP_EQ_HH] = instr_jmp_eq_hh_exec,
7652 [INSTR_JMP_EQ_I] = instr_jmp_eq_i_exec,
7654 [INSTR_JMP_NEQ] = instr_jmp_neq_exec,
7655 [INSTR_JMP_NEQ_MH] = instr_jmp_neq_mh_exec,
7656 [INSTR_JMP_NEQ_HM] = instr_jmp_neq_hm_exec,
7657 [INSTR_JMP_NEQ_HH] = instr_jmp_neq_hh_exec,
7658 [INSTR_JMP_NEQ_I] = instr_jmp_neq_i_exec,
7660 [INSTR_JMP_LT] = instr_jmp_lt_exec,
7661 [INSTR_JMP_LT_MH] = instr_jmp_lt_mh_exec,
7662 [INSTR_JMP_LT_HM] = instr_jmp_lt_hm_exec,
7663 [INSTR_JMP_LT_HH] = instr_jmp_lt_hh_exec,
7664 [INSTR_JMP_LT_MI] = instr_jmp_lt_mi_exec,
7665 [INSTR_JMP_LT_HI] = instr_jmp_lt_hi_exec,
7667 [INSTR_JMP_GT] = instr_jmp_gt_exec,
7668 [INSTR_JMP_GT_MH] = instr_jmp_gt_mh_exec,
7669 [INSTR_JMP_GT_HM] = instr_jmp_gt_hm_exec,
7670 [INSTR_JMP_GT_HH] = instr_jmp_gt_hh_exec,
7671 [INSTR_JMP_GT_MI] = instr_jmp_gt_mi_exec,
7672 [INSTR_JMP_GT_HI] = instr_jmp_gt_hi_exec,
7674 [INSTR_RETURN] = instr_return_exec,
7678 instr_exec(struct rte_swx_pipeline *p)
7680 struct thread *t = &p->threads[p->thread_id];
7681 struct instruction *ip = t->ip;
7682 instr_exec_t instr = instruction_table[ip->type];
7690 static struct action *
7691 action_find(struct rte_swx_pipeline *p, const char *name)
7693 struct action *elem;
7698 TAILQ_FOREACH(elem, &p->actions, node)
7699 if (strcmp(elem->name, name) == 0)
7705 static struct action *
7706 action_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7708 struct action *action = NULL;
7710 TAILQ_FOREACH(action, &p->actions, node)
7711 if (action->id == id)
7717 static struct field *
7718 action_field_find(struct action *a, const char *name)
7720 return a->st ? struct_type_field_find(a->st, name) : NULL;
7723 static struct field *
7724 action_field_parse(struct action *action, const char *name)
7726 if (name[0] != 't' || name[1] != '.')
7729 return action_field_find(action, &name[2]);
7733 action_has_nbo_args(struct action *a)
7737 /* Return if the action does not have any args. */
7739 return 0; /* FALSE */
7741 for (i = 0; i < a->st->n_fields; i++)
7742 if (a->args_endianness[i])
7743 return 1; /* TRUE */
7745 return 0; /* FALSE */
7749 action_does_learning(struct action *a)
7753 for (i = 0; i < a->n_instructions; i++)
7754 switch (a->instructions[i].type) {
7755 case INSTR_LEARNER_LEARN:
7756 return 1; /* TRUE */
7758 case INSTR_LEARNER_FORGET:
7759 return 1; /* TRUE */
7765 return 0; /* FALSE */
7769 rte_swx_pipeline_action_config(struct rte_swx_pipeline *p,
7771 const char *args_struct_type_name,
7772 const char **instructions,
7773 uint32_t n_instructions)
7775 struct struct_type *args_struct_type = NULL;
7781 CHECK_NAME(name, EINVAL);
7782 CHECK(!action_find(p, name), EEXIST);
7784 if (args_struct_type_name) {
7785 CHECK_NAME(args_struct_type_name, EINVAL);
7786 args_struct_type = struct_type_find(p, args_struct_type_name);
7787 CHECK(args_struct_type, EINVAL);
7788 CHECK(!args_struct_type->var_size, EINVAL);
7791 /* Node allocation. */
7792 a = calloc(1, sizeof(struct action));
7794 if (args_struct_type) {
7795 a->args_endianness = calloc(args_struct_type->n_fields, sizeof(int));
7796 if (!a->args_endianness) {
7802 /* Node initialization. */
7803 strcpy(a->name, name);
7804 a->st = args_struct_type;
7805 a->id = p->n_actions;
7807 /* Instruction translation. */
7808 err = instruction_config(p, a, instructions, n_instructions);
7810 free(a->args_endianness);
7815 /* Node add to tailq. */
7816 TAILQ_INSERT_TAIL(&p->actions, a, node);
7823 action_build(struct rte_swx_pipeline *p)
7825 struct action *action;
7827 p->action_instructions = calloc(p->n_actions,
7828 sizeof(struct instruction *));
7829 CHECK(p->action_instructions, ENOMEM);
7831 TAILQ_FOREACH(action, &p->actions, node)
7832 p->action_instructions[action->id] = action->instructions;
7838 action_build_free(struct rte_swx_pipeline *p)
7840 free(p->action_instructions);
7841 p->action_instructions = NULL;
7845 action_free(struct rte_swx_pipeline *p)
7847 action_build_free(p);
7850 struct action *action;
7852 action = TAILQ_FIRST(&p->actions);
7856 TAILQ_REMOVE(&p->actions, action, node);
7857 free(action->instructions);
7863 action_arg_src_mov_count(struct action *a,
7865 struct instruction *instructions,
7866 struct instruction_data *instruction_data,
7867 uint32_t n_instructions)
7869 uint32_t offset, n_users = 0, i;
7872 (arg_id >= a->st->n_fields) ||
7874 !instruction_data ||
7878 offset = a->st->fields[arg_id].offset / 8;
7880 for (i = 0; i < n_instructions; i++) {
7881 struct instruction *instr = &instructions[i];
7882 struct instruction_data *data = &instruction_data[i];
7884 if (data->invalid ||
7885 ((instr->type != INSTR_MOV) && (instr->type != INSTR_MOV_HM)) ||
7886 instr->mov.src.struct_id ||
7887 (instr->mov.src.offset != offset))
7899 static struct table_type *
7900 table_type_find(struct rte_swx_pipeline *p, const char *name)
7902 struct table_type *elem;
7904 TAILQ_FOREACH(elem, &p->table_types, node)
7905 if (strcmp(elem->name, name) == 0)
7911 static struct table_type *
7912 table_type_resolve(struct rte_swx_pipeline *p,
7913 const char *recommended_type_name,
7914 enum rte_swx_table_match_type match_type)
7916 struct table_type *elem;
7918 /* Only consider the recommended type if the match type is correct. */
7919 if (recommended_type_name)
7920 TAILQ_FOREACH(elem, &p->table_types, node)
7921 if (!strcmp(elem->name, recommended_type_name) &&
7922 (elem->match_type == match_type))
7925 /* Ignore the recommended type and get the first element with this match
7928 TAILQ_FOREACH(elem, &p->table_types, node)
7929 if (elem->match_type == match_type)
7935 static struct table *
7936 table_find(struct rte_swx_pipeline *p, const char *name)
7940 TAILQ_FOREACH(elem, &p->tables, node)
7941 if (strcmp(elem->name, name) == 0)
7947 static struct table *
7948 table_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7950 struct table *table = NULL;
7952 TAILQ_FOREACH(table, &p->tables, node)
7953 if (table->id == id)
7960 rte_swx_pipeline_table_type_register(struct rte_swx_pipeline *p,
7962 enum rte_swx_table_match_type match_type,
7963 struct rte_swx_table_ops *ops)
7965 struct table_type *elem;
7969 CHECK_NAME(name, EINVAL);
7970 CHECK(!table_type_find(p, name), EEXIST);
7973 CHECK(ops->create, EINVAL);
7974 CHECK(ops->lkp, EINVAL);
7975 CHECK(ops->free, EINVAL);
7977 /* Node allocation. */
7978 elem = calloc(1, sizeof(struct table_type));
7979 CHECK(elem, ENOMEM);
7981 /* Node initialization. */
7982 strcpy(elem->name, name);
7983 elem->match_type = match_type;
7984 memcpy(&elem->ops, ops, sizeof(*ops));
7986 /* Node add to tailq. */
7987 TAILQ_INSERT_TAIL(&p->table_types, elem, node);
7993 table_match_type_resolve(struct rte_swx_match_field_params *fields,
7995 enum rte_swx_table_match_type *match_type)
7997 uint32_t n_fields_em = 0, n_fields_lpm = 0, i;
7999 for (i = 0; i < n_fields; i++) {
8000 struct rte_swx_match_field_params *f = &fields[i];
8002 if (f->match_type == RTE_SWX_TABLE_MATCH_EXACT)
8005 if (f->match_type == RTE_SWX_TABLE_MATCH_LPM)
8009 if ((n_fields_lpm > 1) ||
8010 (n_fields_lpm && (n_fields_em != n_fields - 1)))
8013 *match_type = (n_fields_em == n_fields) ?
8014 RTE_SWX_TABLE_MATCH_EXACT :
8015 RTE_SWX_TABLE_MATCH_WILDCARD;
8021 table_match_fields_check(struct rte_swx_pipeline *p,
8022 struct rte_swx_pipeline_table_params *params,
8023 struct header **header)
8025 struct header *h0 = NULL;
8026 struct field *hf, *mf;
8027 uint32_t *offset = NULL, i;
8030 /* Return if no match fields. */
8031 if (!params->n_fields) {
8032 if (params->fields) {
8043 /* Memory allocation. */
8044 offset = calloc(params->n_fields, sizeof(uint32_t));
8050 /* Check that all the match fields belong to either the same header or
8053 hf = header_field_parse(p, params->fields[0].name, &h0);
8054 mf = metadata_field_parse(p, params->fields[0].name);
8055 if ((!hf && !mf) || (hf && hf->var_size)) {
8060 offset[0] = h0 ? hf->offset : mf->offset;
8062 for (i = 1; i < params->n_fields; i++)
8066 hf = header_field_parse(p, params->fields[i].name, &h);
8067 if (!hf || (h->id != h0->id) || hf->var_size) {
8072 offset[i] = hf->offset;
8074 mf = metadata_field_parse(p, params->fields[i].name);
8080 offset[i] = mf->offset;
8083 /* Check that there are no duplicated match fields. */
8084 for (i = 0; i < params->n_fields; i++) {
8087 for (j = 0; j < i; j++)
8088 if (offset[j] == offset[i]) {
8104 rte_swx_pipeline_table_config(struct rte_swx_pipeline *p,
8106 struct rte_swx_pipeline_table_params *params,
8107 const char *recommended_table_type_name,
8111 struct table_type *type;
8113 struct action *default_action;
8114 struct header *header = NULL;
8115 uint32_t action_data_size_max = 0, i;
8120 CHECK_NAME(name, EINVAL);
8121 CHECK(!table_find(p, name), EEXIST);
8122 CHECK(!selector_find(p, name), EEXIST);
8123 CHECK(!learner_find(p, name), EEXIST);
8125 CHECK(params, EINVAL);
8128 status = table_match_fields_check(p, params, &header);
8132 /* Action checks. */
8133 CHECK(params->n_actions, EINVAL);
8134 CHECK(params->action_names, EINVAL);
8135 for (i = 0; i < params->n_actions; i++) {
8136 const char *action_name = params->action_names[i];
8138 uint32_t action_data_size;
8140 CHECK_NAME(action_name, EINVAL);
8142 a = action_find(p, action_name);
8144 CHECK(!action_does_learning(a), EINVAL);
8146 action_data_size = a->st ? a->st->n_bits / 8 : 0;
8147 if (action_data_size > action_data_size_max)
8148 action_data_size_max = action_data_size;
8151 CHECK_NAME(params->default_action_name, EINVAL);
8152 for (i = 0; i < p->n_actions; i++)
8153 if (!strcmp(params->action_names[i],
8154 params->default_action_name))
8156 CHECK(i < params->n_actions, EINVAL);
8157 default_action = action_find(p, params->default_action_name);
8158 CHECK((default_action->st && params->default_action_data) ||
8159 !params->default_action_data, EINVAL);
8161 /* Table type checks. */
8162 if (recommended_table_type_name)
8163 CHECK_NAME(recommended_table_type_name, EINVAL);
8165 if (params->n_fields) {
8166 enum rte_swx_table_match_type match_type;
8168 status = table_match_type_resolve(params->fields, params->n_fields, &match_type);
8172 type = table_type_resolve(p, recommended_table_type_name, match_type);
8173 CHECK(type, EINVAL);
8178 /* Memory allocation. */
8179 t = calloc(1, sizeof(struct table));
8182 t->fields = calloc(params->n_fields, sizeof(struct match_field));
8188 t->actions = calloc(params->n_actions, sizeof(struct action *));
8195 if (action_data_size_max) {
8196 t->default_action_data = calloc(1, action_data_size_max);
8197 if (!t->default_action_data) {
8205 /* Node initialization. */
8206 strcpy(t->name, name);
8207 if (args && args[0])
8208 strcpy(t->args, args);
8211 for (i = 0; i < params->n_fields; i++) {
8212 struct rte_swx_match_field_params *field = ¶ms->fields[i];
8213 struct match_field *f = &t->fields[i];
8215 f->match_type = field->match_type;
8217 header_field_parse(p, field->name, NULL) :
8218 metadata_field_parse(p, field->name);
8220 t->n_fields = params->n_fields;
8223 for (i = 0; i < params->n_actions; i++)
8224 t->actions[i] = action_find(p, params->action_names[i]);
8225 t->default_action = default_action;
8226 if (default_action->st)
8227 memcpy(t->default_action_data,
8228 params->default_action_data,
8229 default_action->st->n_bits / 8);
8230 t->n_actions = params->n_actions;
8231 t->default_action_is_const = params->default_action_is_const;
8232 t->action_data_size_max = action_data_size_max;
8235 t->id = p->n_tables;
8237 /* Node add to tailq. */
8238 TAILQ_INSERT_TAIL(&p->tables, t, node);
8244 static struct rte_swx_table_params *
8245 table_params_get(struct table *table)
8247 struct rte_swx_table_params *params;
8248 struct field *first, *last;
8250 uint32_t key_size, key_offset, action_data_size, i;
8252 /* Memory allocation. */
8253 params = calloc(1, sizeof(struct rte_swx_table_params));
8257 /* Find first (smallest offset) and last (biggest offset) match fields. */
8258 first = table->fields[0].field;
8259 last = table->fields[0].field;
8261 for (i = 0; i < table->n_fields; i++) {
8262 struct field *f = table->fields[i].field;
8264 if (f->offset < first->offset)
8267 if (f->offset > last->offset)
8271 /* Key offset and size. */
8272 key_offset = first->offset / 8;
8273 key_size = (last->offset + last->n_bits - first->offset) / 8;
8275 /* Memory allocation. */
8276 key_mask = calloc(1, key_size);
8283 for (i = 0; i < table->n_fields; i++) {
8284 struct field *f = table->fields[i].field;
8285 uint32_t start = (f->offset - first->offset) / 8;
8286 size_t size = f->n_bits / 8;
8288 memset(&key_mask[start], 0xFF, size);
8291 /* Action data size. */
8292 action_data_size = 0;
8293 for (i = 0; i < table->n_actions; i++) {
8294 struct action *action = table->actions[i];
8295 uint32_t ads = action->st ? action->st->n_bits / 8 : 0;
8297 if (ads > action_data_size)
8298 action_data_size = ads;
8302 params->match_type = table->type->match_type;
8303 params->key_size = key_size;
8304 params->key_offset = key_offset;
8305 params->key_mask0 = key_mask;
8306 params->action_data_size = action_data_size;
8307 params->n_keys_max = table->size;
8313 table_params_free(struct rte_swx_table_params *params)
8318 free(params->key_mask0);
8323 table_stub_lkp(void *table __rte_unused,
8324 void *mailbox __rte_unused,
8325 uint8_t **key __rte_unused,
8326 uint64_t *action_id __rte_unused,
8327 uint8_t **action_data __rte_unused,
8331 return 1; /* DONE. */
8335 table_build(struct rte_swx_pipeline *p)
8339 /* Per pipeline: table statistics. */
8340 p->table_stats = calloc(p->n_tables, sizeof(struct table_statistics));
8341 CHECK(p->table_stats, ENOMEM);
8343 for (i = 0; i < p->n_tables; i++) {
8344 p->table_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
8345 CHECK(p->table_stats[i].n_pkts_action, ENOMEM);
8348 /* Per thread: table runt-time. */
8349 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8350 struct thread *t = &p->threads[i];
8351 struct table *table;
8353 t->tables = calloc(p->n_tables, sizeof(struct table_runtime));
8354 CHECK(t->tables, ENOMEM);
8356 TAILQ_FOREACH(table, &p->tables, node) {
8357 struct table_runtime *r = &t->tables[table->id];
8362 size = table->type->ops.mailbox_size_get();
8365 r->func = table->type->ops.lkp;
8369 r->mailbox = calloc(1, size);
8370 CHECK(r->mailbox, ENOMEM);
8374 r->key = table->header ?
8375 &t->structs[table->header->struct_id] :
8376 &t->structs[p->metadata_struct_id];
8378 r->func = table_stub_lkp;
8387 table_build_free(struct rte_swx_pipeline *p)
8391 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8392 struct thread *t = &p->threads[i];
8398 for (j = 0; j < p->n_tables; j++) {
8399 struct table_runtime *r = &t->tables[j];
8408 if (p->table_stats) {
8409 for (i = 0; i < p->n_tables; i++)
8410 free(p->table_stats[i].n_pkts_action);
8412 free(p->table_stats);
8417 table_free(struct rte_swx_pipeline *p)
8419 table_build_free(p);
8425 elem = TAILQ_FIRST(&p->tables);
8429 TAILQ_REMOVE(&p->tables, elem, node);
8431 free(elem->actions);
8432 free(elem->default_action_data);
8438 struct table_type *elem;
8440 elem = TAILQ_FIRST(&p->table_types);
8444 TAILQ_REMOVE(&p->table_types, elem, node);
8452 static struct selector *
8453 selector_find(struct rte_swx_pipeline *p, const char *name)
8457 TAILQ_FOREACH(s, &p->selectors, node)
8458 if (strcmp(s->name, name) == 0)
8464 static struct selector *
8465 selector_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8467 struct selector *s = NULL;
8469 TAILQ_FOREACH(s, &p->selectors, node)
8477 selector_fields_check(struct rte_swx_pipeline *p,
8478 struct rte_swx_pipeline_selector_params *params,
8479 struct header **header)
8481 struct header *h0 = NULL;
8482 struct field *hf, *mf;
8485 /* Return if no selector fields. */
8486 if (!params->n_selector_fields || !params->selector_field_names)
8489 /* Check that all the selector fields either belong to the same header
8490 * or are all meta-data fields.
8492 hf = header_field_parse(p, params->selector_field_names[0], &h0);
8493 mf = metadata_field_parse(p, params->selector_field_names[0]);
8497 for (i = 1; i < params->n_selector_fields; i++)
8501 hf = header_field_parse(p, params->selector_field_names[i], &h);
8502 if (!hf || (h->id != h0->id))
8505 mf = metadata_field_parse(p, params->selector_field_names[i]);
8510 /* Check that there are no duplicated match fields. */
8511 for (i = 0; i < params->n_selector_fields; i++) {
8512 const char *field_name = params->selector_field_names[i];
8515 for (j = i + 1; j < params->n_selector_fields; j++)
8516 if (!strcmp(params->selector_field_names[j], field_name))
8528 rte_swx_pipeline_selector_config(struct rte_swx_pipeline *p,
8530 struct rte_swx_pipeline_selector_params *params)
8533 struct header *selector_header = NULL;
8534 struct field *group_id_field, *member_id_field;
8540 CHECK_NAME(name, EINVAL);
8541 CHECK(!table_find(p, name), EEXIST);
8542 CHECK(!selector_find(p, name), EEXIST);
8543 CHECK(!learner_find(p, name), EEXIST);
8545 CHECK(params, EINVAL);
8547 CHECK_NAME(params->group_id_field_name, EINVAL);
8548 group_id_field = metadata_field_parse(p, params->group_id_field_name);
8549 CHECK(group_id_field, EINVAL);
8551 for (i = 0; i < params->n_selector_fields; i++) {
8552 const char *field_name = params->selector_field_names[i];
8554 CHECK_NAME(field_name, EINVAL);
8556 status = selector_fields_check(p, params, &selector_header);
8560 CHECK_NAME(params->member_id_field_name, EINVAL);
8561 member_id_field = metadata_field_parse(p, params->member_id_field_name);
8562 CHECK(member_id_field, EINVAL);
8564 CHECK(params->n_groups_max, EINVAL);
8566 CHECK(params->n_members_per_group_max, EINVAL);
8568 /* Memory allocation. */
8569 s = calloc(1, sizeof(struct selector));
8575 s->selector_fields = calloc(params->n_selector_fields, sizeof(struct field *));
8576 if (!s->selector_fields) {
8581 /* Node initialization. */
8582 strcpy(s->name, name);
8584 s->group_id_field = group_id_field;
8586 for (i = 0; i < params->n_selector_fields; i++) {
8587 const char *field_name = params->selector_field_names[i];
8589 s->selector_fields[i] = selector_header ?
8590 header_field_parse(p, field_name, NULL) :
8591 metadata_field_parse(p, field_name);
8594 s->n_selector_fields = params->n_selector_fields;
8596 s->selector_header = selector_header;
8598 s->member_id_field = member_id_field;
8600 s->n_groups_max = params->n_groups_max;
8602 s->n_members_per_group_max = params->n_members_per_group_max;
8604 s->id = p->n_selectors;
8606 /* Node add to tailq. */
8607 TAILQ_INSERT_TAIL(&p->selectors, s, node);
8616 free(s->selector_fields);
8624 selector_params_free(struct rte_swx_table_selector_params *params)
8629 free(params->selector_mask);
8634 static struct rte_swx_table_selector_params *
8635 selector_table_params_get(struct selector *s)
8637 struct rte_swx_table_selector_params *params = NULL;
8638 struct field *first, *last;
8641 /* Memory allocation. */
8642 params = calloc(1, sizeof(struct rte_swx_table_selector_params));
8647 params->group_id_offset = s->group_id_field->offset / 8;
8649 /* Find first (smallest offset) and last (biggest offset) selector fields. */
8650 first = s->selector_fields[0];
8651 last = s->selector_fields[0];
8653 for (i = 0; i < s->n_selector_fields; i++) {
8654 struct field *f = s->selector_fields[i];
8656 if (f->offset < first->offset)
8659 if (f->offset > last->offset)
8663 /* Selector offset and size. */
8664 params->selector_offset = first->offset / 8;
8665 params->selector_size = (last->offset + last->n_bits - first->offset) / 8;
8667 /* Memory allocation. */
8668 params->selector_mask = calloc(1, params->selector_size);
8669 if (!params->selector_mask)
8672 /* Selector mask. */
8673 for (i = 0; i < s->n_selector_fields; i++) {
8674 struct field *f = s->selector_fields[i];
8675 uint32_t start = (f->offset - first->offset) / 8;
8676 size_t size = f->n_bits / 8;
8678 memset(¶ms->selector_mask[start], 0xFF, size);
8682 params->member_id_offset = s->member_id_field->offset / 8;
8684 /* Maximum number of groups. */
8685 params->n_groups_max = s->n_groups_max;
8687 /* Maximum number of members per group. */
8688 params->n_members_per_group_max = s->n_members_per_group_max;
8693 selector_params_free(params);
8698 selector_build_free(struct rte_swx_pipeline *p)
8702 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8703 struct thread *t = &p->threads[i];
8709 for (j = 0; j < p->n_selectors; j++) {
8710 struct selector_runtime *r = &t->selectors[j];
8716 t->selectors = NULL;
8719 free(p->selector_stats);
8720 p->selector_stats = NULL;
8724 selector_build(struct rte_swx_pipeline *p)
8729 /* Per pipeline: selector statistics. */
8730 p->selector_stats = calloc(p->n_selectors, sizeof(struct selector_statistics));
8731 if (!p->selector_stats) {
8736 /* Per thread: selector run-time. */
8737 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8738 struct thread *t = &p->threads[i];
8741 t->selectors = calloc(p->n_selectors, sizeof(struct selector_runtime));
8742 if (!t->selectors) {
8747 TAILQ_FOREACH(s, &p->selectors, node) {
8748 struct selector_runtime *r = &t->selectors[s->id];
8752 size = rte_swx_table_selector_mailbox_size_get();
8754 r->mailbox = calloc(1, size);
8761 /* r->group_id_buffer. */
8762 r->group_id_buffer = &t->structs[p->metadata_struct_id];
8764 /* r->selector_buffer. */
8765 r->selector_buffer = s->selector_header ?
8766 &t->structs[s->selector_header->struct_id] :
8767 &t->structs[p->metadata_struct_id];
8769 /* r->member_id_buffer. */
8770 r->member_id_buffer = &t->structs[p->metadata_struct_id];
8777 selector_build_free(p);
8782 selector_free(struct rte_swx_pipeline *p)
8784 selector_build_free(p);
8786 /* Selector tables. */
8788 struct selector *elem;
8790 elem = TAILQ_FIRST(&p->selectors);
8794 TAILQ_REMOVE(&p->selectors, elem, node);
8795 free(elem->selector_fields);
8803 static struct learner *
8804 learner_find(struct rte_swx_pipeline *p, const char *name)
8808 TAILQ_FOREACH(l, &p->learners, node)
8809 if (!strcmp(l->name, name))
8815 static struct learner *
8816 learner_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8818 struct learner *l = NULL;
8820 TAILQ_FOREACH(l, &p->learners, node)
8828 learner_match_fields_check(struct rte_swx_pipeline *p,
8829 struct rte_swx_pipeline_learner_params *params,
8830 struct header **header)
8832 struct header *h0 = NULL;
8833 struct field *hf, *mf;
8836 /* Return if no match fields. */
8837 if (!params->n_fields || !params->field_names)
8840 /* Check that all the match fields either belong to the same header
8841 * or are all meta-data fields.
8843 hf = header_field_parse(p, params->field_names[0], &h0);
8844 mf = metadata_field_parse(p, params->field_names[0]);
8848 for (i = 1; i < params->n_fields; i++)
8852 hf = header_field_parse(p, params->field_names[i], &h);
8853 if (!hf || (h->id != h0->id))
8856 mf = metadata_field_parse(p, params->field_names[i]);
8861 /* Check that there are no duplicated match fields. */
8862 for (i = 0; i < params->n_fields; i++) {
8863 const char *field_name = params->field_names[i];
8866 for (j = i + 1; j < params->n_fields; j++)
8867 if (!strcmp(params->field_names[j], field_name))
8879 learner_action_args_check(struct rte_swx_pipeline *p, struct action *a, const char *mf_name)
8881 struct struct_type *mst = p->metadata_st, *ast = a->st;
8882 struct field *mf, *af;
8892 /* Check that mf_name is the name of a valid meta-data field. */
8893 CHECK_NAME(mf_name, EINVAL);
8894 mf = metadata_field_parse(p, mf_name);
8897 /* Check that there are enough meta-data fields, starting with the mf_name field, to cover
8898 * all the action arguments.
8900 mf_pos = mf - mst->fields;
8901 CHECK(mst->n_fields - mf_pos >= ast->n_fields, EINVAL);
8903 /* Check that the size of each of the identified meta-data fields matches exactly the size
8904 * of the corresponding action argument.
8906 for (i = 0; i < ast->n_fields; i++) {
8907 mf = &mst->fields[mf_pos + i];
8908 af = &ast->fields[i];
8910 CHECK(mf->n_bits == af->n_bits, EINVAL);
8917 learner_action_learning_check(struct rte_swx_pipeline *p,
8918 struct action *action,
8919 const char **action_names,
8924 /* For each "learn" instruction of the current action, check that the learned action (i.e.
8925 * the action passed as argument to the "learn" instruction) is also enabled for the
8926 * current learner table.
8928 for (i = 0; i < action->n_instructions; i++) {
8929 struct instruction *instr = &action->instructions[i];
8930 uint32_t found = 0, j;
8932 if (instr->type != INSTR_LEARNER_LEARN)
8935 for (j = 0; j < n_actions; j++) {
8938 a = action_find(p, action_names[j]);
8942 if (a->id == instr->learn.action_id)
8954 rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p,
8956 struct rte_swx_pipeline_learner_params *params,
8960 struct learner *l = NULL;
8961 struct action *default_action;
8962 struct header *header = NULL;
8963 uint32_t action_data_size_max = 0, i;
8968 CHECK_NAME(name, EINVAL);
8969 CHECK(!table_find(p, name), EEXIST);
8970 CHECK(!selector_find(p, name), EEXIST);
8971 CHECK(!learner_find(p, name), EEXIST);
8973 CHECK(params, EINVAL);
8976 status = learner_match_fields_check(p, params, &header);
8980 /* Action checks. */
8981 CHECK(params->n_actions, EINVAL);
8983 CHECK(params->action_names, EINVAL);
8984 for (i = 0; i < params->n_actions; i++) {
8985 const char *action_name = params->action_names[i];
8986 const char *action_field_name = params->action_field_names[i];
8988 uint32_t action_data_size;
8990 CHECK_NAME(action_name, EINVAL);
8992 a = action_find(p, action_name);
8995 status = learner_action_args_check(p, a, action_field_name);
8999 status = learner_action_learning_check(p,
9001 params->action_names,
9006 action_data_size = a->st ? a->st->n_bits / 8 : 0;
9007 if (action_data_size > action_data_size_max)
9008 action_data_size_max = action_data_size;
9011 CHECK_NAME(params->default_action_name, EINVAL);
9012 for (i = 0; i < p->n_actions; i++)
9013 if (!strcmp(params->action_names[i],
9014 params->default_action_name))
9016 CHECK(i < params->n_actions, EINVAL);
9018 default_action = action_find(p, params->default_action_name);
9019 CHECK((default_action->st && params->default_action_data) ||
9020 !params->default_action_data, EINVAL);
9022 /* Any other checks. */
9023 CHECK(size, EINVAL);
9024 CHECK(timeout, EINVAL);
9026 /* Memory allocation. */
9027 l = calloc(1, sizeof(struct learner));
9031 l->fields = calloc(params->n_fields, sizeof(struct field *));
9035 l->actions = calloc(params->n_actions, sizeof(struct action *));
9039 l->action_arg = calloc(params->n_actions, sizeof(struct field *));
9043 if (action_data_size_max) {
9044 l->default_action_data = calloc(1, action_data_size_max);
9045 if (!l->default_action_data)
9049 /* Node initialization. */
9050 strcpy(l->name, name);
9052 for (i = 0; i < params->n_fields; i++) {
9053 const char *field_name = params->field_names[i];
9055 l->fields[i] = header ?
9056 header_field_parse(p, field_name, NULL) :
9057 metadata_field_parse(p, field_name);
9060 l->n_fields = params->n_fields;
9064 for (i = 0; i < params->n_actions; i++) {
9065 const char *mf_name = params->action_field_names[i];
9067 l->actions[i] = action_find(p, params->action_names[i]);
9069 l->action_arg[i] = mf_name ? metadata_field_parse(p, mf_name) : NULL;
9072 l->default_action = default_action;
9074 if (default_action->st)
9075 memcpy(l->default_action_data,
9076 params->default_action_data,
9077 default_action->st->n_bits / 8);
9079 l->n_actions = params->n_actions;
9081 l->default_action_is_const = params->default_action_is_const;
9083 l->action_data_size_max = action_data_size_max;
9087 l->timeout = timeout;
9089 l->id = p->n_learners;
9091 /* Node add to tailq. */
9092 TAILQ_INSERT_TAIL(&p->learners, l, node);
9101 free(l->action_arg);
9110 learner_params_free(struct rte_swx_table_learner_params *params)
9115 free(params->key_mask0);
9120 static struct rte_swx_table_learner_params *
9121 learner_params_get(struct learner *l)
9123 struct rte_swx_table_learner_params *params = NULL;
9124 struct field *first, *last;
9127 /* Memory allocation. */
9128 params = calloc(1, sizeof(struct rte_swx_table_learner_params));
9132 /* Find first (smallest offset) and last (biggest offset) match fields. */
9133 first = l->fields[0];
9134 last = l->fields[0];
9136 for (i = 0; i < l->n_fields; i++) {
9137 struct field *f = l->fields[i];
9139 if (f->offset < first->offset)
9142 if (f->offset > last->offset)
9146 /* Key offset and size. */
9147 params->key_offset = first->offset / 8;
9148 params->key_size = (last->offset + last->n_bits - first->offset) / 8;
9150 /* Memory allocation. */
9151 params->key_mask0 = calloc(1, params->key_size);
9152 if (!params->key_mask0)
9156 for (i = 0; i < l->n_fields; i++) {
9157 struct field *f = l->fields[i];
9158 uint32_t start = (f->offset - first->offset) / 8;
9159 size_t size = f->n_bits / 8;
9161 memset(¶ms->key_mask0[start], 0xFF, size);
9164 /* Action data size. */
9165 params->action_data_size = l->action_data_size_max;
9167 /* Maximum number of keys. */
9168 params->n_keys_max = l->size;
9171 params->key_timeout = l->timeout;
9176 learner_params_free(params);
9181 learner_build_free(struct rte_swx_pipeline *p)
9185 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9186 struct thread *t = &p->threads[i];
9192 for (j = 0; j < p->n_learners; j++) {
9193 struct learner_runtime *r = &t->learners[j];
9196 free(r->action_data);
9203 if (p->learner_stats) {
9204 for (i = 0; i < p->n_learners; i++)
9205 free(p->learner_stats[i].n_pkts_action);
9207 free(p->learner_stats);
9212 learner_build(struct rte_swx_pipeline *p)
9217 /* Per pipeline: learner statistics. */
9218 p->learner_stats = calloc(p->n_learners, sizeof(struct learner_statistics));
9219 CHECK(p->learner_stats, ENOMEM);
9221 for (i = 0; i < p->n_learners; i++) {
9222 p->learner_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
9223 CHECK(p->learner_stats[i].n_pkts_action, ENOMEM);
9226 /* Per thread: learner run-time. */
9227 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9228 struct thread *t = &p->threads[i];
9231 t->learners = calloc(p->n_learners, sizeof(struct learner_runtime));
9237 TAILQ_FOREACH(l, &p->learners, node) {
9238 struct learner_runtime *r = &t->learners[l->id];
9243 size = rte_swx_table_learner_mailbox_size_get();
9245 r->mailbox = calloc(1, size);
9253 r->key = l->header ?
9254 &t->structs[l->header->struct_id] :
9255 &t->structs[p->metadata_struct_id];
9257 /* r->action_data. */
9258 r->action_data = calloc(p->n_actions, sizeof(uint8_t *));
9259 if (!r->action_data) {
9264 for (j = 0; j < l->n_actions; j++) {
9265 struct action *a = l->actions[j];
9266 struct field *mf = l->action_arg[j];
9267 uint8_t *m = t->structs[p->metadata_struct_id];
9269 r->action_data[a->id] = mf ? &m[mf->offset / 8] : NULL;
9277 learner_build_free(p);
9282 learner_free(struct rte_swx_pipeline *p)
9284 learner_build_free(p);
9286 /* Learner tables. */
9290 l = TAILQ_FIRST(&p->learners);
9294 TAILQ_REMOVE(&p->learners, l, node);
9297 free(l->action_arg);
9298 free(l->default_action_data);
9307 table_state_build(struct rte_swx_pipeline *p)
9309 struct table *table;
9313 p->table_state = calloc(p->n_tables + p->n_selectors,
9314 sizeof(struct rte_swx_table_state));
9315 CHECK(p->table_state, ENOMEM);
9317 TAILQ_FOREACH(table, &p->tables, node) {
9318 struct rte_swx_table_state *ts = &p->table_state[table->id];
9321 struct rte_swx_table_params *params;
9324 params = table_params_get(table);
9325 CHECK(params, ENOMEM);
9327 ts->obj = table->type->ops.create(params,
9332 table_params_free(params);
9333 CHECK(ts->obj, ENODEV);
9336 /* ts->default_action_data. */
9337 if (table->action_data_size_max) {
9338 ts->default_action_data =
9339 malloc(table->action_data_size_max);
9340 CHECK(ts->default_action_data, ENOMEM);
9342 memcpy(ts->default_action_data,
9343 table->default_action_data,
9344 table->action_data_size_max);
9347 /* ts->default_action_id. */
9348 ts->default_action_id = table->default_action->id;
9351 TAILQ_FOREACH(s, &p->selectors, node) {
9352 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + s->id];
9353 struct rte_swx_table_selector_params *params;
9356 params = selector_table_params_get(s);
9357 CHECK(params, ENOMEM);
9359 ts->obj = rte_swx_table_selector_create(params, NULL, p->numa_node);
9361 selector_params_free(params);
9362 CHECK(ts->obj, ENODEV);
9365 TAILQ_FOREACH(l, &p->learners, node) {
9366 struct rte_swx_table_state *ts = &p->table_state[p->n_tables +
9367 p->n_selectors + l->id];
9368 struct rte_swx_table_learner_params *params;
9371 params = learner_params_get(l);
9372 CHECK(params, ENOMEM);
9374 ts->obj = rte_swx_table_learner_create(params, p->numa_node);
9375 learner_params_free(params);
9376 CHECK(ts->obj, ENODEV);
9378 /* ts->default_action_data. */
9379 if (l->action_data_size_max) {
9380 ts->default_action_data = malloc(l->action_data_size_max);
9381 CHECK(ts->default_action_data, ENOMEM);
9383 memcpy(ts->default_action_data,
9384 l->default_action_data,
9385 l->action_data_size_max);
9388 /* ts->default_action_id. */
9389 ts->default_action_id = l->default_action->id;
9396 table_state_build_free(struct rte_swx_pipeline *p)
9400 if (!p->table_state)
9403 for (i = 0; i < p->n_tables; i++) {
9404 struct rte_swx_table_state *ts = &p->table_state[i];
9405 struct table *table = table_find_by_id(p, i);
9408 if (table->type && ts->obj)
9409 table->type->ops.free(ts->obj);
9411 /* ts->default_action_data. */
9412 free(ts->default_action_data);
9415 for (i = 0; i < p->n_selectors; i++) {
9416 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + i];
9420 rte_swx_table_selector_free(ts->obj);
9423 for (i = 0; i < p->n_learners; i++) {
9424 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + p->n_selectors + i];
9428 rte_swx_table_learner_free(ts->obj);
9430 /* ts->default_action_data. */
9431 free(ts->default_action_data);
9434 free(p->table_state);
9435 p->table_state = NULL;
9439 table_state_free(struct rte_swx_pipeline *p)
9441 table_state_build_free(p);
9447 static struct regarray *
9448 regarray_find(struct rte_swx_pipeline *p, const char *name)
9450 struct regarray *elem;
9452 TAILQ_FOREACH(elem, &p->regarrays, node)
9453 if (!strcmp(elem->name, name))
9459 static struct regarray *
9460 regarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9462 struct regarray *elem = NULL;
9464 TAILQ_FOREACH(elem, &p->regarrays, node)
9472 rte_swx_pipeline_regarray_config(struct rte_swx_pipeline *p,
9481 CHECK_NAME(name, EINVAL);
9482 CHECK(!regarray_find(p, name), EEXIST);
9484 CHECK(size, EINVAL);
9485 size = rte_align32pow2(size);
9487 /* Memory allocation. */
9488 r = calloc(1, sizeof(struct regarray));
9491 /* Node initialization. */
9492 strcpy(r->name, name);
9493 r->init_val = init_val;
9495 r->id = p->n_regarrays;
9497 /* Node add to tailq. */
9498 TAILQ_INSERT_TAIL(&p->regarrays, r, node);
9505 regarray_build(struct rte_swx_pipeline *p)
9507 struct regarray *regarray;
9509 if (!p->n_regarrays)
9512 p->regarray_runtime = calloc(p->n_regarrays, sizeof(struct regarray_runtime));
9513 CHECK(p->regarray_runtime, ENOMEM);
9515 TAILQ_FOREACH(regarray, &p->regarrays, node) {
9516 struct regarray_runtime *r = &p->regarray_runtime[regarray->id];
9519 r->regarray = env_malloc(regarray->size * sizeof(uint64_t),
9520 RTE_CACHE_LINE_SIZE,
9522 CHECK(r->regarray, ENOMEM);
9524 if (regarray->init_val)
9525 for (i = 0; i < regarray->size; i++)
9526 r->regarray[i] = regarray->init_val;
9528 r->size_mask = regarray->size - 1;
9535 regarray_build_free(struct rte_swx_pipeline *p)
9539 if (!p->regarray_runtime)
9542 for (i = 0; i < p->n_regarrays; i++) {
9543 struct regarray *regarray = regarray_find_by_id(p, i);
9544 struct regarray_runtime *r = &p->regarray_runtime[i];
9546 env_free(r->regarray, regarray->size * sizeof(uint64_t));
9549 free(p->regarray_runtime);
9550 p->regarray_runtime = NULL;
9554 regarray_free(struct rte_swx_pipeline *p)
9556 regarray_build_free(p);
9559 struct regarray *elem;
9561 elem = TAILQ_FIRST(&p->regarrays);
9565 TAILQ_REMOVE(&p->regarrays, elem, node);
9573 static struct meter_profile *
9574 meter_profile_find(struct rte_swx_pipeline *p, const char *name)
9576 struct meter_profile *elem;
9578 TAILQ_FOREACH(elem, &p->meter_profiles, node)
9579 if (!strcmp(elem->name, name))
9585 static struct metarray *
9586 metarray_find(struct rte_swx_pipeline *p, const char *name)
9588 struct metarray *elem;
9590 TAILQ_FOREACH(elem, &p->metarrays, node)
9591 if (!strcmp(elem->name, name))
9597 static struct metarray *
9598 metarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9600 struct metarray *elem = NULL;
9602 TAILQ_FOREACH(elem, &p->metarrays, node)
9610 rte_swx_pipeline_metarray_config(struct rte_swx_pipeline *p,
9618 CHECK_NAME(name, EINVAL);
9619 CHECK(!metarray_find(p, name), EEXIST);
9621 CHECK(size, EINVAL);
9622 size = rte_align32pow2(size);
9624 /* Memory allocation. */
9625 m = calloc(1, sizeof(struct metarray));
9628 /* Node initialization. */
9629 strcpy(m->name, name);
9631 m->id = p->n_metarrays;
9633 /* Node add to tailq. */
9634 TAILQ_INSERT_TAIL(&p->metarrays, m, node);
9640 struct meter_profile meter_profile_default = {
9649 .cir_bytes_per_period = 1,
9651 .pir_bytes_per_period = 1,
9658 meter_init(struct meter *m)
9660 memset(m, 0, sizeof(struct meter));
9661 rte_meter_trtcm_config(&m->m, &meter_profile_default.profile);
9662 m->profile = &meter_profile_default;
9663 m->color_mask = RTE_COLOR_GREEN;
9665 meter_profile_default.n_users++;
9669 metarray_build(struct rte_swx_pipeline *p)
9673 if (!p->n_metarrays)
9676 p->metarray_runtime = calloc(p->n_metarrays, sizeof(struct metarray_runtime));
9677 CHECK(p->metarray_runtime, ENOMEM);
9679 TAILQ_FOREACH(m, &p->metarrays, node) {
9680 struct metarray_runtime *r = &p->metarray_runtime[m->id];
9683 r->metarray = env_malloc(m->size * sizeof(struct meter),
9684 RTE_CACHE_LINE_SIZE,
9686 CHECK(r->metarray, ENOMEM);
9688 for (i = 0; i < m->size; i++)
9689 meter_init(&r->metarray[i]);
9691 r->size_mask = m->size - 1;
9698 metarray_build_free(struct rte_swx_pipeline *p)
9702 if (!p->metarray_runtime)
9705 for (i = 0; i < p->n_metarrays; i++) {
9706 struct metarray *m = metarray_find_by_id(p, i);
9707 struct metarray_runtime *r = &p->metarray_runtime[i];
9709 env_free(r->metarray, m->size * sizeof(struct meter));
9712 free(p->metarray_runtime);
9713 p->metarray_runtime = NULL;
9717 metarray_free(struct rte_swx_pipeline *p)
9719 metarray_build_free(p);
9723 struct metarray *elem;
9725 elem = TAILQ_FIRST(&p->metarrays);
9729 TAILQ_REMOVE(&p->metarrays, elem, node);
9733 /* Meter profiles. */
9735 struct meter_profile *elem;
9737 elem = TAILQ_FIRST(&p->meter_profiles);
9741 TAILQ_REMOVE(&p->meter_profiles, elem, node);
9750 rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
9752 struct rte_swx_pipeline *pipeline;
9754 /* Check input parameters. */
9757 /* Memory allocation. */
9758 pipeline = calloc(1, sizeof(struct rte_swx_pipeline));
9759 CHECK(pipeline, ENOMEM);
9761 /* Initialization. */
9762 TAILQ_INIT(&pipeline->struct_types);
9763 TAILQ_INIT(&pipeline->port_in_types);
9764 TAILQ_INIT(&pipeline->ports_in);
9765 TAILQ_INIT(&pipeline->port_out_types);
9766 TAILQ_INIT(&pipeline->ports_out);
9767 TAILQ_INIT(&pipeline->extern_types);
9768 TAILQ_INIT(&pipeline->extern_objs);
9769 TAILQ_INIT(&pipeline->extern_funcs);
9770 TAILQ_INIT(&pipeline->headers);
9771 TAILQ_INIT(&pipeline->actions);
9772 TAILQ_INIT(&pipeline->table_types);
9773 TAILQ_INIT(&pipeline->tables);
9774 TAILQ_INIT(&pipeline->selectors);
9775 TAILQ_INIT(&pipeline->learners);
9776 TAILQ_INIT(&pipeline->regarrays);
9777 TAILQ_INIT(&pipeline->meter_profiles);
9778 TAILQ_INIT(&pipeline->metarrays);
9780 pipeline->n_structs = 1; /* Struct 0 is reserved for action_data. */
9781 pipeline->numa_node = numa_node;
9788 rte_swx_pipeline_free(struct rte_swx_pipeline *p)
9793 free(p->instructions);
9797 table_state_free(p);
9804 extern_func_free(p);
9814 rte_swx_pipeline_instructions_config(struct rte_swx_pipeline *p,
9815 const char **instructions,
9816 uint32_t n_instructions)
9821 err = instruction_config(p, NULL, instructions, n_instructions);
9825 /* Thread instruction pointer reset. */
9826 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9827 struct thread *t = &p->threads[i];
9829 thread_ip_reset(p, t);
9836 rte_swx_pipeline_build(struct rte_swx_pipeline *p)
9841 CHECK(p->build_done == 0, EEXIST);
9843 status = port_in_build(p);
9847 status = port_out_build(p);
9851 status = struct_build(p);
9855 status = extern_obj_build(p);
9859 status = extern_func_build(p);
9863 status = header_build(p);
9867 status = metadata_build(p);
9871 status = action_build(p);
9875 status = table_build(p);
9879 status = selector_build(p);
9883 status = learner_build(p);
9887 status = table_state_build(p);
9891 status = regarray_build(p);
9895 status = metarray_build(p);
9903 metarray_build_free(p);
9904 regarray_build_free(p);
9905 table_state_build_free(p);
9906 learner_build_free(p);
9907 selector_build_free(p);
9908 table_build_free(p);
9909 action_build_free(p);
9910 metadata_build_free(p);
9911 header_build_free(p);
9912 extern_func_build_free(p);
9913 extern_obj_build_free(p);
9914 port_out_build_free(p);
9915 port_in_build_free(p);
9916 struct_build_free(p);
9922 rte_swx_pipeline_run(struct rte_swx_pipeline *p, uint32_t n_instructions)
9926 for (i = 0; i < n_instructions; i++)
9931 rte_swx_pipeline_flush(struct rte_swx_pipeline *p)
9935 for (i = 0; i < p->n_ports_out; i++) {
9936 struct port_out_runtime *port = &p->out[i];
9939 port->flush(port->obj);
9947 rte_swx_ctl_pipeline_info_get(struct rte_swx_pipeline *p,
9948 struct rte_swx_ctl_pipeline_info *pipeline)
9950 struct action *action;
9951 struct table *table;
9952 uint32_t n_actions = 0, n_tables = 0;
9954 if (!p || !pipeline)
9957 TAILQ_FOREACH(action, &p->actions, node)
9960 TAILQ_FOREACH(table, &p->tables, node)
9963 pipeline->n_ports_in = p->n_ports_in;
9964 pipeline->n_ports_out = p->n_ports_out;
9965 pipeline->n_actions = n_actions;
9966 pipeline->n_tables = n_tables;
9967 pipeline->n_selectors = p->n_selectors;
9968 pipeline->n_learners = p->n_learners;
9969 pipeline->n_regarrays = p->n_regarrays;
9970 pipeline->n_metarrays = p->n_metarrays;
9976 rte_swx_ctl_pipeline_numa_node_get(struct rte_swx_pipeline *p, int *numa_node)
9978 if (!p || !numa_node)
9981 *numa_node = p->numa_node;
9986 rte_swx_ctl_action_info_get(struct rte_swx_pipeline *p,
9988 struct rte_swx_ctl_action_info *action)
9990 struct action *a = NULL;
9992 if (!p || (action_id >= p->n_actions) || !action)
9995 a = action_find_by_id(p, action_id);
9999 strcpy(action->name, a->name);
10000 action->n_args = a->st ? a->st->n_fields : 0;
10005 rte_swx_ctl_action_arg_info_get(struct rte_swx_pipeline *p,
10006 uint32_t action_id,
10007 uint32_t action_arg_id,
10008 struct rte_swx_ctl_action_arg_info *action_arg)
10010 struct action *a = NULL;
10011 struct field *arg = NULL;
10013 if (!p || (action_id >= p->n_actions) || !action_arg)
10016 a = action_find_by_id(p, action_id);
10017 if (!a || !a->st || (action_arg_id >= a->st->n_fields))
10020 arg = &a->st->fields[action_arg_id];
10021 strcpy(action_arg->name, arg->name);
10022 action_arg->n_bits = arg->n_bits;
10023 action_arg->is_network_byte_order = a->args_endianness[action_arg_id];
10029 rte_swx_ctl_table_info_get(struct rte_swx_pipeline *p,
10031 struct rte_swx_ctl_table_info *table)
10033 struct table *t = NULL;
10038 t = table_find_by_id(p, table_id);
10042 strcpy(table->name, t->name);
10043 strcpy(table->args, t->args);
10044 table->n_match_fields = t->n_fields;
10045 table->n_actions = t->n_actions;
10046 table->default_action_is_const = t->default_action_is_const;
10047 table->size = t->size;
10052 rte_swx_ctl_table_match_field_info_get(struct rte_swx_pipeline *p,
10054 uint32_t match_field_id,
10055 struct rte_swx_ctl_table_match_field_info *match_field)
10058 struct match_field *f;
10060 if (!p || (table_id >= p->n_tables) || !match_field)
10063 t = table_find_by_id(p, table_id);
10064 if (!t || (match_field_id >= t->n_fields))
10067 f = &t->fields[match_field_id];
10068 match_field->match_type = f->match_type;
10069 match_field->is_header = t->header ? 1 : 0;
10070 match_field->n_bits = f->field->n_bits;
10071 match_field->offset = f->field->offset;
10077 rte_swx_ctl_table_action_info_get(struct rte_swx_pipeline *p,
10079 uint32_t table_action_id,
10080 struct rte_swx_ctl_table_action_info *table_action)
10084 if (!p || (table_id >= p->n_tables) || !table_action)
10087 t = table_find_by_id(p, table_id);
10088 if (!t || (table_action_id >= t->n_actions))
10091 table_action->action_id = t->actions[table_action_id]->id;
10097 rte_swx_ctl_table_ops_get(struct rte_swx_pipeline *p,
10099 struct rte_swx_table_ops *table_ops,
10104 if (!p || (table_id >= p->n_tables))
10107 t = table_find_by_id(p, table_id);
10113 memcpy(table_ops, &t->type->ops, sizeof(*table_ops));
10123 rte_swx_ctl_selector_info_get(struct rte_swx_pipeline *p,
10124 uint32_t selector_id,
10125 struct rte_swx_ctl_selector_info *selector)
10127 struct selector *s = NULL;
10129 if (!p || !selector)
10132 s = selector_find_by_id(p, selector_id);
10136 strcpy(selector->name, s->name);
10138 selector->n_selector_fields = s->n_selector_fields;
10139 selector->n_groups_max = s->n_groups_max;
10140 selector->n_members_per_group_max = s->n_members_per_group_max;
10146 rte_swx_ctl_selector_group_id_field_info_get(struct rte_swx_pipeline *p,
10147 uint32_t selector_id,
10148 struct rte_swx_ctl_table_match_field_info *field)
10150 struct selector *s;
10152 if (!p || (selector_id >= p->n_selectors) || !field)
10155 s = selector_find_by_id(p, selector_id);
10159 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10160 field->is_header = 0;
10161 field->n_bits = s->group_id_field->n_bits;
10162 field->offset = s->group_id_field->offset;
10168 rte_swx_ctl_selector_field_info_get(struct rte_swx_pipeline *p,
10169 uint32_t selector_id,
10170 uint32_t selector_field_id,
10171 struct rte_swx_ctl_table_match_field_info *field)
10173 struct selector *s;
10176 if (!p || (selector_id >= p->n_selectors) || !field)
10179 s = selector_find_by_id(p, selector_id);
10180 if (!s || (selector_field_id >= s->n_selector_fields))
10183 f = s->selector_fields[selector_field_id];
10184 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10185 field->is_header = s->selector_header ? 1 : 0;
10186 field->n_bits = f->n_bits;
10187 field->offset = f->offset;
10193 rte_swx_ctl_selector_member_id_field_info_get(struct rte_swx_pipeline *p,
10194 uint32_t selector_id,
10195 struct rte_swx_ctl_table_match_field_info *field)
10197 struct selector *s;
10199 if (!p || (selector_id >= p->n_selectors) || !field)
10202 s = selector_find_by_id(p, selector_id);
10206 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10207 field->is_header = 0;
10208 field->n_bits = s->member_id_field->n_bits;
10209 field->offset = s->member_id_field->offset;
10215 rte_swx_ctl_learner_info_get(struct rte_swx_pipeline *p,
10216 uint32_t learner_id,
10217 struct rte_swx_ctl_learner_info *learner)
10219 struct learner *l = NULL;
10221 if (!p || !learner)
10224 l = learner_find_by_id(p, learner_id);
10228 strcpy(learner->name, l->name);
10230 learner->n_match_fields = l->n_fields;
10231 learner->n_actions = l->n_actions;
10232 learner->default_action_is_const = l->default_action_is_const;
10233 learner->size = l->size;
10239 rte_swx_ctl_learner_match_field_info_get(struct rte_swx_pipeline *p,
10240 uint32_t learner_id,
10241 uint32_t match_field_id,
10242 struct rte_swx_ctl_table_match_field_info *match_field)
10247 if (!p || (learner_id >= p->n_learners) || !match_field)
10250 l = learner_find_by_id(p, learner_id);
10251 if (!l || (match_field_id >= l->n_fields))
10254 f = l->fields[match_field_id];
10255 match_field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10256 match_field->is_header = l->header ? 1 : 0;
10257 match_field->n_bits = f->n_bits;
10258 match_field->offset = f->offset;
10264 rte_swx_ctl_learner_action_info_get(struct rte_swx_pipeline *p,
10265 uint32_t learner_id,
10266 uint32_t learner_action_id,
10267 struct rte_swx_ctl_table_action_info *learner_action)
10271 if (!p || (learner_id >= p->n_learners) || !learner_action)
10274 l = learner_find_by_id(p, learner_id);
10275 if (!l || (learner_action_id >= l->n_actions))
10278 learner_action->action_id = l->actions[learner_action_id]->id;
10284 rte_swx_pipeline_table_state_get(struct rte_swx_pipeline *p,
10285 struct rte_swx_table_state **table_state)
10287 if (!p || !table_state || !p->build_done)
10290 *table_state = p->table_state;
10295 rte_swx_pipeline_table_state_set(struct rte_swx_pipeline *p,
10296 struct rte_swx_table_state *table_state)
10298 if (!p || !table_state || !p->build_done)
10301 p->table_state = table_state;
10306 rte_swx_ctl_pipeline_port_in_stats_read(struct rte_swx_pipeline *p,
10308 struct rte_swx_port_in_stats *stats)
10310 struct port_in *port;
10315 port = port_in_find(p, port_id);
10319 port->type->ops.stats_read(port->obj, stats);
10324 rte_swx_ctl_pipeline_port_out_stats_read(struct rte_swx_pipeline *p,
10326 struct rte_swx_port_out_stats *stats)
10328 struct port_out *port;
10333 port = port_out_find(p, port_id);
10337 port->type->ops.stats_read(port->obj, stats);
10342 rte_swx_ctl_pipeline_table_stats_read(struct rte_swx_pipeline *p,
10343 const char *table_name,
10344 struct rte_swx_table_stats *stats)
10346 struct table *table;
10347 struct table_statistics *table_stats;
10349 if (!p || !table_name || !table_name[0] || !stats || !stats->n_pkts_action)
10352 table = table_find(p, table_name);
10356 table_stats = &p->table_stats[table->id];
10358 memcpy(stats->n_pkts_action,
10359 table_stats->n_pkts_action,
10360 p->n_actions * sizeof(uint64_t));
10362 stats->n_pkts_hit = table_stats->n_pkts_hit[1];
10363 stats->n_pkts_miss = table_stats->n_pkts_hit[0];
10369 rte_swx_ctl_pipeline_selector_stats_read(struct rte_swx_pipeline *p,
10370 const char *selector_name,
10371 struct rte_swx_pipeline_selector_stats *stats)
10373 struct selector *s;
10375 if (!p || !selector_name || !selector_name[0] || !stats)
10378 s = selector_find(p, selector_name);
10382 stats->n_pkts = p->selector_stats[s->id].n_pkts;
10388 rte_swx_ctl_pipeline_learner_stats_read(struct rte_swx_pipeline *p,
10389 const char *learner_name,
10390 struct rte_swx_learner_stats *stats)
10393 struct learner_statistics *learner_stats;
10395 if (!p || !learner_name || !learner_name[0] || !stats || !stats->n_pkts_action)
10398 l = learner_find(p, learner_name);
10402 learner_stats = &p->learner_stats[l->id];
10404 memcpy(stats->n_pkts_action,
10405 learner_stats->n_pkts_action,
10406 p->n_actions * sizeof(uint64_t));
10408 stats->n_pkts_hit = learner_stats->n_pkts_hit[1];
10409 stats->n_pkts_miss = learner_stats->n_pkts_hit[0];
10411 stats->n_pkts_learn_ok = learner_stats->n_pkts_learn[0];
10412 stats->n_pkts_learn_err = learner_stats->n_pkts_learn[1];
10414 stats->n_pkts_forget = learner_stats->n_pkts_forget;
10420 rte_swx_ctl_regarray_info_get(struct rte_swx_pipeline *p,
10421 uint32_t regarray_id,
10422 struct rte_swx_ctl_regarray_info *regarray)
10424 struct regarray *r;
10426 if (!p || !regarray)
10429 r = regarray_find_by_id(p, regarray_id);
10433 strcpy(regarray->name, r->name);
10434 regarray->size = r->size;
10439 rte_swx_ctl_pipeline_regarray_read(struct rte_swx_pipeline *p,
10440 const char *regarray_name,
10441 uint32_t regarray_index,
10444 struct regarray *regarray;
10445 struct regarray_runtime *r;
10447 if (!p || !regarray_name || !value)
10450 regarray = regarray_find(p, regarray_name);
10451 if (!regarray || (regarray_index >= regarray->size))
10454 r = &p->regarray_runtime[regarray->id];
10455 *value = r->regarray[regarray_index];
10460 rte_swx_ctl_pipeline_regarray_write(struct rte_swx_pipeline *p,
10461 const char *regarray_name,
10462 uint32_t regarray_index,
10465 struct regarray *regarray;
10466 struct regarray_runtime *r;
10468 if (!p || !regarray_name)
10471 regarray = regarray_find(p, regarray_name);
10472 if (!regarray || (regarray_index >= regarray->size))
10475 r = &p->regarray_runtime[regarray->id];
10476 r->regarray[regarray_index] = value;
10481 rte_swx_ctl_metarray_info_get(struct rte_swx_pipeline *p,
10482 uint32_t metarray_id,
10483 struct rte_swx_ctl_metarray_info *metarray)
10485 struct metarray *m;
10487 if (!p || !metarray)
10490 m = metarray_find_by_id(p, metarray_id);
10494 strcpy(metarray->name, m->name);
10495 metarray->size = m->size;
10500 rte_swx_ctl_meter_profile_add(struct rte_swx_pipeline *p,
10502 struct rte_meter_trtcm_params *params)
10504 struct meter_profile *mp;
10508 CHECK_NAME(name, EINVAL);
10509 CHECK(params, EINVAL);
10510 CHECK(!meter_profile_find(p, name), EEXIST);
10512 /* Node allocation. */
10513 mp = calloc(1, sizeof(struct meter_profile));
10516 /* Node initialization. */
10517 strcpy(mp->name, name);
10518 memcpy(&mp->params, params, sizeof(struct rte_meter_trtcm_params));
10519 status = rte_meter_trtcm_profile_config(&mp->profile, params);
10525 /* Node add to tailq. */
10526 TAILQ_INSERT_TAIL(&p->meter_profiles, mp, node);
10532 rte_swx_ctl_meter_profile_delete(struct rte_swx_pipeline *p,
10535 struct meter_profile *mp;
10538 CHECK_NAME(name, EINVAL);
10540 mp = meter_profile_find(p, name);
10542 CHECK(!mp->n_users, EBUSY);
10544 /* Remove node from tailq. */
10545 TAILQ_REMOVE(&p->meter_profiles, mp, node);
10552 rte_swx_ctl_meter_reset(struct rte_swx_pipeline *p,
10553 const char *metarray_name,
10554 uint32_t metarray_index)
10556 struct meter_profile *mp_old;
10557 struct metarray *metarray;
10558 struct metarray_runtime *metarray_runtime;
10562 CHECK_NAME(metarray_name, EINVAL);
10564 metarray = metarray_find(p, metarray_name);
10565 CHECK(metarray, EINVAL);
10566 CHECK(metarray_index < metarray->size, EINVAL);
10568 metarray_runtime = &p->metarray_runtime[metarray->id];
10569 m = &metarray_runtime->metarray[metarray_index];
10570 mp_old = m->profile;
10580 rte_swx_ctl_meter_set(struct rte_swx_pipeline *p,
10581 const char *metarray_name,
10582 uint32_t metarray_index,
10583 const char *profile_name)
10585 struct meter_profile *mp, *mp_old;
10586 struct metarray *metarray;
10587 struct metarray_runtime *metarray_runtime;
10591 CHECK_NAME(metarray_name, EINVAL);
10593 metarray = metarray_find(p, metarray_name);
10594 CHECK(metarray, EINVAL);
10595 CHECK(metarray_index < metarray->size, EINVAL);
10597 mp = meter_profile_find(p, profile_name);
10600 metarray_runtime = &p->metarray_runtime[metarray->id];
10601 m = &metarray_runtime->metarray[metarray_index];
10602 mp_old = m->profile;
10604 memset(m, 0, sizeof(struct meter));
10605 rte_meter_trtcm_config(&m->m, &mp->profile);
10607 m->color_mask = RTE_COLORS;
10616 rte_swx_ctl_meter_stats_read(struct rte_swx_pipeline *p,
10617 const char *metarray_name,
10618 uint32_t metarray_index,
10619 struct rte_swx_ctl_meter_stats *stats)
10621 struct metarray *metarray;
10622 struct metarray_runtime *metarray_runtime;
10626 CHECK_NAME(metarray_name, EINVAL);
10628 metarray = metarray_find(p, metarray_name);
10629 CHECK(metarray, EINVAL);
10630 CHECK(metarray_index < metarray->size, EINVAL);
10632 CHECK(stats, EINVAL);
10634 metarray_runtime = &p->metarray_runtime[metarray->id];
10635 m = &metarray_runtime->metarray[metarray_index];
10637 memcpy(stats->n_pkts, m->n_pkts, sizeof(m->n_pkts));
10638 memcpy(stats->n_bytes, m->n_bytes, sizeof(m->n_bytes));