1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2020 Intel Corporation
9 #include "rte_swx_pipeline_internal.h"
11 #define CHECK(condition, err_code) \
17 #define CHECK_NAME(name, err_code) \
20 (strnlen((name), RTE_SWX_NAME_SIZE) < RTE_SWX_NAME_SIZE), \
23 #define CHECK_INSTRUCTION(instr, err_code) \
26 (strnlen((instr), RTE_SWX_INSTRUCTION_SIZE) < \
27 RTE_SWX_INSTRUCTION_SIZE), \
33 #ifndef RTE_SWX_PIPELINE_HUGE_PAGES_DISABLE
35 #include <rte_malloc.h>
38 env_malloc(size_t size, size_t alignment, int numa_node)
40 return rte_zmalloc_socket(NULL, size, alignment, numa_node);
44 env_free(void *start, size_t size __rte_unused)
54 env_malloc(size_t size, size_t alignment __rte_unused, int numa_node)
58 if (numa_available() == -1)
61 start = numa_alloc_onnode(size, numa_node);
65 memset(start, 0, size);
70 env_free(void *start, size_t size)
72 if (numa_available() == -1)
75 numa_free(start, size);
83 static struct struct_type *
84 struct_type_find(struct rte_swx_pipeline *p, const char *name)
86 struct struct_type *elem;
88 TAILQ_FOREACH(elem, &p->struct_types, node)
89 if (strcmp(elem->name, name) == 0)
96 struct_type_field_find(struct struct_type *st, const char *name)
100 for (i = 0; i < st->n_fields; i++) {
101 struct field *f = &st->fields[i];
103 if (strcmp(f->name, name) == 0)
111 rte_swx_pipeline_struct_type_register(struct rte_swx_pipeline *p,
113 struct rte_swx_field_params *fields,
115 int last_field_has_variable_size)
117 struct struct_type *st;
121 CHECK_NAME(name, EINVAL);
122 CHECK(fields, EINVAL);
123 CHECK(n_fields, EINVAL);
125 for (i = 0; i < n_fields; i++) {
126 struct rte_swx_field_params *f = &fields[i];
127 int var_size = ((i == n_fields - 1) && last_field_has_variable_size) ? 1 : 0;
130 CHECK_NAME(f->name, EINVAL);
131 CHECK(f->n_bits, EINVAL);
132 CHECK((f->n_bits <= 64) || var_size, EINVAL);
133 CHECK((f->n_bits & 7) == 0, EINVAL);
135 for (j = 0; j < i; j++) {
136 struct rte_swx_field_params *f_prev = &fields[j];
138 CHECK(strcmp(f->name, f_prev->name), EINVAL);
142 CHECK(!struct_type_find(p, name), EEXIST);
144 /* Node allocation. */
145 st = calloc(1, sizeof(struct struct_type));
148 st->fields = calloc(n_fields, sizeof(struct field));
154 /* Node initialization. */
155 strcpy(st->name, name);
156 for (i = 0; i < n_fields; i++) {
157 struct field *dst = &st->fields[i];
158 struct rte_swx_field_params *src = &fields[i];
159 int var_size = ((i == n_fields - 1) && last_field_has_variable_size) ? 1 : 0;
161 strcpy(dst->name, src->name);
162 dst->n_bits = src->n_bits;
163 dst->offset = st->n_bits;
164 dst->var_size = var_size;
166 st->n_bits += src->n_bits;
167 st->n_bits_min += var_size ? 0 : src->n_bits;
169 st->n_fields = n_fields;
170 st->var_size = last_field_has_variable_size;
172 /* Node add to tailq. */
173 TAILQ_INSERT_TAIL(&p->struct_types, st, node);
179 struct_build(struct rte_swx_pipeline *p)
183 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
184 struct thread *t = &p->threads[i];
186 t->structs = calloc(p->n_structs, sizeof(uint8_t *));
187 CHECK(t->structs, ENOMEM);
194 struct_build_free(struct rte_swx_pipeline *p)
198 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
199 struct thread *t = &p->threads[i];
207 struct_free(struct rte_swx_pipeline *p)
209 struct_build_free(p);
213 struct struct_type *elem;
215 elem = TAILQ_FIRST(&p->struct_types);
219 TAILQ_REMOVE(&p->struct_types, elem, node);
228 static struct port_in_type *
229 port_in_type_find(struct rte_swx_pipeline *p, const char *name)
231 struct port_in_type *elem;
236 TAILQ_FOREACH(elem, &p->port_in_types, node)
237 if (strcmp(elem->name, name) == 0)
244 rte_swx_pipeline_port_in_type_register(struct rte_swx_pipeline *p,
246 struct rte_swx_port_in_ops *ops)
248 struct port_in_type *elem;
251 CHECK_NAME(name, EINVAL);
253 CHECK(ops->create, EINVAL);
254 CHECK(ops->free, EINVAL);
255 CHECK(ops->pkt_rx, EINVAL);
256 CHECK(ops->stats_read, EINVAL);
258 CHECK(!port_in_type_find(p, name), EEXIST);
260 /* Node allocation. */
261 elem = calloc(1, sizeof(struct port_in_type));
264 /* Node initialization. */
265 strcpy(elem->name, name);
266 memcpy(&elem->ops, ops, sizeof(*ops));
268 /* Node add to tailq. */
269 TAILQ_INSERT_TAIL(&p->port_in_types, elem, node);
274 static struct port_in *
275 port_in_find(struct rte_swx_pipeline *p, uint32_t port_id)
277 struct port_in *port;
279 TAILQ_FOREACH(port, &p->ports_in, node)
280 if (port->id == port_id)
287 rte_swx_pipeline_port_in_config(struct rte_swx_pipeline *p,
289 const char *port_type_name,
292 struct port_in_type *type = NULL;
293 struct port_in *port = NULL;
298 CHECK(!port_in_find(p, port_id), EINVAL);
300 CHECK_NAME(port_type_name, EINVAL);
301 type = port_in_type_find(p, port_type_name);
304 obj = type->ops.create(args);
307 /* Node allocation. */
308 port = calloc(1, sizeof(struct port_in));
311 /* Node initialization. */
316 /* Node add to tailq. */
317 TAILQ_INSERT_TAIL(&p->ports_in, port, node);
318 if (p->n_ports_in < port_id + 1)
319 p->n_ports_in = port_id + 1;
325 port_in_build(struct rte_swx_pipeline *p)
327 struct port_in *port;
330 CHECK(p->n_ports_in, EINVAL);
331 CHECK(rte_is_power_of_2(p->n_ports_in), EINVAL);
333 for (i = 0; i < p->n_ports_in; i++)
334 CHECK(port_in_find(p, i), EINVAL);
336 p->in = calloc(p->n_ports_in, sizeof(struct port_in_runtime));
337 CHECK(p->in, ENOMEM);
339 TAILQ_FOREACH(port, &p->ports_in, node) {
340 struct port_in_runtime *in = &p->in[port->id];
342 in->pkt_rx = port->type->ops.pkt_rx;
350 port_in_build_free(struct rte_swx_pipeline *p)
357 port_in_free(struct rte_swx_pipeline *p)
359 port_in_build_free(p);
363 struct port_in *port;
365 port = TAILQ_FIRST(&p->ports_in);
369 TAILQ_REMOVE(&p->ports_in, port, node);
370 port->type->ops.free(port->obj);
374 /* Input port types. */
376 struct port_in_type *elem;
378 elem = TAILQ_FIRST(&p->port_in_types);
382 TAILQ_REMOVE(&p->port_in_types, elem, node);
390 static struct port_out_type *
391 port_out_type_find(struct rte_swx_pipeline *p, const char *name)
393 struct port_out_type *elem;
398 TAILQ_FOREACH(elem, &p->port_out_types, node)
399 if (!strcmp(elem->name, name))
406 rte_swx_pipeline_port_out_type_register(struct rte_swx_pipeline *p,
408 struct rte_swx_port_out_ops *ops)
410 struct port_out_type *elem;
413 CHECK_NAME(name, EINVAL);
415 CHECK(ops->create, EINVAL);
416 CHECK(ops->free, EINVAL);
417 CHECK(ops->pkt_tx, EINVAL);
418 CHECK(ops->stats_read, EINVAL);
420 CHECK(!port_out_type_find(p, name), EEXIST);
422 /* Node allocation. */
423 elem = calloc(1, sizeof(struct port_out_type));
426 /* Node initialization. */
427 strcpy(elem->name, name);
428 memcpy(&elem->ops, ops, sizeof(*ops));
430 /* Node add to tailq. */
431 TAILQ_INSERT_TAIL(&p->port_out_types, elem, node);
436 static struct port_out *
437 port_out_find(struct rte_swx_pipeline *p, uint32_t port_id)
439 struct port_out *port;
441 TAILQ_FOREACH(port, &p->ports_out, node)
442 if (port->id == port_id)
449 rte_swx_pipeline_port_out_config(struct rte_swx_pipeline *p,
451 const char *port_type_name,
454 struct port_out_type *type = NULL;
455 struct port_out *port = NULL;
460 CHECK(!port_out_find(p, port_id), EINVAL);
462 CHECK_NAME(port_type_name, EINVAL);
463 type = port_out_type_find(p, port_type_name);
466 obj = type->ops.create(args);
469 /* Node allocation. */
470 port = calloc(1, sizeof(struct port_out));
473 /* Node initialization. */
478 /* Node add to tailq. */
479 TAILQ_INSERT_TAIL(&p->ports_out, port, node);
480 if (p->n_ports_out < port_id + 1)
481 p->n_ports_out = port_id + 1;
487 port_out_build(struct rte_swx_pipeline *p)
489 struct port_out *port;
492 CHECK(p->n_ports_out, EINVAL);
494 for (i = 0; i < p->n_ports_out; i++)
495 CHECK(port_out_find(p, i), EINVAL);
497 p->out = calloc(p->n_ports_out, sizeof(struct port_out_runtime));
498 CHECK(p->out, ENOMEM);
500 TAILQ_FOREACH(port, &p->ports_out, node) {
501 struct port_out_runtime *out = &p->out[port->id];
503 out->pkt_tx = port->type->ops.pkt_tx;
504 out->flush = port->type->ops.flush;
505 out->obj = port->obj;
512 port_out_build_free(struct rte_swx_pipeline *p)
519 port_out_free(struct rte_swx_pipeline *p)
521 port_out_build_free(p);
525 struct port_out *port;
527 port = TAILQ_FIRST(&p->ports_out);
531 TAILQ_REMOVE(&p->ports_out, port, node);
532 port->type->ops.free(port->obj);
536 /* Output port types. */
538 struct port_out_type *elem;
540 elem = TAILQ_FIRST(&p->port_out_types);
544 TAILQ_REMOVE(&p->port_out_types, elem, node);
552 static struct extern_type *
553 extern_type_find(struct rte_swx_pipeline *p, const char *name)
555 struct extern_type *elem;
557 TAILQ_FOREACH(elem, &p->extern_types, node)
558 if (strcmp(elem->name, name) == 0)
564 static struct extern_type_member_func *
565 extern_type_member_func_find(struct extern_type *type, const char *name)
567 struct extern_type_member_func *elem;
569 TAILQ_FOREACH(elem, &type->funcs, node)
570 if (strcmp(elem->name, name) == 0)
576 static struct extern_obj *
577 extern_obj_find(struct rte_swx_pipeline *p, const char *name)
579 struct extern_obj *elem;
581 TAILQ_FOREACH(elem, &p->extern_objs, node)
582 if (strcmp(elem->name, name) == 0)
588 static struct extern_type_member_func *
589 extern_obj_member_func_parse(struct rte_swx_pipeline *p,
591 struct extern_obj **obj)
593 struct extern_obj *object;
594 struct extern_type_member_func *func;
595 char *object_name, *func_name;
597 if (name[0] != 'e' || name[1] != '.')
600 object_name = strdup(&name[2]);
604 func_name = strchr(object_name, '.');
613 object = extern_obj_find(p, object_name);
619 func = extern_type_member_func_find(object->type, func_name);
632 static struct field *
633 extern_obj_mailbox_field_parse(struct rte_swx_pipeline *p,
635 struct extern_obj **object)
637 struct extern_obj *obj;
639 char *obj_name, *field_name;
641 if ((name[0] != 'e') || (name[1] != '.'))
644 obj_name = strdup(&name[2]);
648 field_name = strchr(obj_name, '.');
657 obj = extern_obj_find(p, obj_name);
663 f = struct_type_field_find(obj->type->mailbox_struct_type, field_name);
677 rte_swx_pipeline_extern_type_register(struct rte_swx_pipeline *p,
679 const char *mailbox_struct_type_name,
680 rte_swx_extern_type_constructor_t constructor,
681 rte_swx_extern_type_destructor_t destructor)
683 struct extern_type *elem;
684 struct struct_type *mailbox_struct_type;
688 CHECK_NAME(name, EINVAL);
689 CHECK(!extern_type_find(p, name), EEXIST);
691 CHECK_NAME(mailbox_struct_type_name, EINVAL);
692 mailbox_struct_type = struct_type_find(p, mailbox_struct_type_name);
693 CHECK(mailbox_struct_type, EINVAL);
694 CHECK(!mailbox_struct_type->var_size, EINVAL);
696 CHECK(constructor, EINVAL);
697 CHECK(destructor, EINVAL);
699 /* Node allocation. */
700 elem = calloc(1, sizeof(struct extern_type));
703 /* Node initialization. */
704 strcpy(elem->name, name);
705 elem->mailbox_struct_type = mailbox_struct_type;
706 elem->constructor = constructor;
707 elem->destructor = destructor;
708 TAILQ_INIT(&elem->funcs);
710 /* Node add to tailq. */
711 TAILQ_INSERT_TAIL(&p->extern_types, elem, node);
717 rte_swx_pipeline_extern_type_member_func_register(struct rte_swx_pipeline *p,
718 const char *extern_type_name,
720 rte_swx_extern_type_member_func_t member_func)
722 struct extern_type *type;
723 struct extern_type_member_func *type_member;
727 CHECK_NAME(extern_type_name, EINVAL);
728 type = extern_type_find(p, extern_type_name);
730 CHECK(type->n_funcs < RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX, ENOSPC);
732 CHECK_NAME(name, EINVAL);
733 CHECK(!extern_type_member_func_find(type, name), EEXIST);
735 CHECK(member_func, EINVAL);
737 /* Node allocation. */
738 type_member = calloc(1, sizeof(struct extern_type_member_func));
739 CHECK(type_member, ENOMEM);
741 /* Node initialization. */
742 strcpy(type_member->name, name);
743 type_member->func = member_func;
744 type_member->id = type->n_funcs;
746 /* Node add to tailq. */
747 TAILQ_INSERT_TAIL(&type->funcs, type_member, node);
754 rte_swx_pipeline_extern_object_config(struct rte_swx_pipeline *p,
755 const char *extern_type_name,
759 struct extern_type *type;
760 struct extern_obj *obj;
765 CHECK_NAME(extern_type_name, EINVAL);
766 type = extern_type_find(p, extern_type_name);
769 CHECK_NAME(name, EINVAL);
770 CHECK(!extern_obj_find(p, name), EEXIST);
772 /* Node allocation. */
773 obj = calloc(1, sizeof(struct extern_obj));
776 /* Object construction. */
777 obj_handle = type->constructor(args);
783 /* Node initialization. */
784 strcpy(obj->name, name);
786 obj->obj = obj_handle;
787 obj->struct_id = p->n_structs;
788 obj->id = p->n_extern_objs;
790 /* Node add to tailq. */
791 TAILQ_INSERT_TAIL(&p->extern_objs, obj, node);
799 extern_obj_build(struct rte_swx_pipeline *p)
803 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
804 struct thread *t = &p->threads[i];
805 struct extern_obj *obj;
807 t->extern_objs = calloc(p->n_extern_objs,
808 sizeof(struct extern_obj_runtime));
809 CHECK(t->extern_objs, ENOMEM);
811 TAILQ_FOREACH(obj, &p->extern_objs, node) {
812 struct extern_obj_runtime *r =
813 &t->extern_objs[obj->id];
814 struct extern_type_member_func *func;
815 uint32_t mailbox_size =
816 obj->type->mailbox_struct_type->n_bits / 8;
820 r->mailbox = calloc(1, mailbox_size);
821 CHECK(r->mailbox, ENOMEM);
823 TAILQ_FOREACH(func, &obj->type->funcs, node)
824 r->funcs[func->id] = func->func;
826 t->structs[obj->struct_id] = r->mailbox;
834 extern_obj_build_free(struct rte_swx_pipeline *p)
838 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
839 struct thread *t = &p->threads[i];
845 for (j = 0; j < p->n_extern_objs; j++) {
846 struct extern_obj_runtime *r = &t->extern_objs[j];
851 free(t->extern_objs);
852 t->extern_objs = NULL;
857 extern_obj_free(struct rte_swx_pipeline *p)
859 extern_obj_build_free(p);
861 /* Extern objects. */
863 struct extern_obj *elem;
865 elem = TAILQ_FIRST(&p->extern_objs);
869 TAILQ_REMOVE(&p->extern_objs, elem, node);
871 elem->type->destructor(elem->obj);
877 struct extern_type *elem;
879 elem = TAILQ_FIRST(&p->extern_types);
883 TAILQ_REMOVE(&p->extern_types, elem, node);
886 struct extern_type_member_func *func;
888 func = TAILQ_FIRST(&elem->funcs);
892 TAILQ_REMOVE(&elem->funcs, func, node);
903 static struct extern_func *
904 extern_func_find(struct rte_swx_pipeline *p, const char *name)
906 struct extern_func *elem;
908 TAILQ_FOREACH(elem, &p->extern_funcs, node)
909 if (strcmp(elem->name, name) == 0)
915 static struct extern_func *
916 extern_func_parse(struct rte_swx_pipeline *p,
919 if (name[0] != 'f' || name[1] != '.')
922 return extern_func_find(p, &name[2]);
925 static struct field *
926 extern_func_mailbox_field_parse(struct rte_swx_pipeline *p,
928 struct extern_func **function)
930 struct extern_func *func;
932 char *func_name, *field_name;
934 if ((name[0] != 'f') || (name[1] != '.'))
937 func_name = strdup(&name[2]);
941 field_name = strchr(func_name, '.');
950 func = extern_func_find(p, func_name);
956 f = struct_type_field_find(func->mailbox_struct_type, field_name);
970 rte_swx_pipeline_extern_func_register(struct rte_swx_pipeline *p,
972 const char *mailbox_struct_type_name,
973 rte_swx_extern_func_t func)
975 struct extern_func *f;
976 struct struct_type *mailbox_struct_type;
980 CHECK_NAME(name, EINVAL);
981 CHECK(!extern_func_find(p, name), EEXIST);
983 CHECK_NAME(mailbox_struct_type_name, EINVAL);
984 mailbox_struct_type = struct_type_find(p, mailbox_struct_type_name);
985 CHECK(mailbox_struct_type, EINVAL);
986 CHECK(!mailbox_struct_type->var_size, EINVAL);
990 /* Node allocation. */
991 f = calloc(1, sizeof(struct extern_func));
994 /* Node initialization. */
995 strcpy(f->name, name);
996 f->mailbox_struct_type = mailbox_struct_type;
998 f->struct_id = p->n_structs;
999 f->id = p->n_extern_funcs;
1001 /* Node add to tailq. */
1002 TAILQ_INSERT_TAIL(&p->extern_funcs, f, node);
1003 p->n_extern_funcs++;
1010 extern_func_build(struct rte_swx_pipeline *p)
1014 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1015 struct thread *t = &p->threads[i];
1016 struct extern_func *func;
1018 /* Memory allocation. */
1019 t->extern_funcs = calloc(p->n_extern_funcs,
1020 sizeof(struct extern_func_runtime));
1021 CHECK(t->extern_funcs, ENOMEM);
1023 /* Extern function. */
1024 TAILQ_FOREACH(func, &p->extern_funcs, node) {
1025 struct extern_func_runtime *r =
1026 &t->extern_funcs[func->id];
1027 uint32_t mailbox_size =
1028 func->mailbox_struct_type->n_bits / 8;
1030 r->func = func->func;
1032 r->mailbox = calloc(1, mailbox_size);
1033 CHECK(r->mailbox, ENOMEM);
1035 t->structs[func->struct_id] = r->mailbox;
1043 extern_func_build_free(struct rte_swx_pipeline *p)
1047 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1048 struct thread *t = &p->threads[i];
1051 if (!t->extern_funcs)
1054 for (j = 0; j < p->n_extern_funcs; j++) {
1055 struct extern_func_runtime *r = &t->extern_funcs[j];
1060 free(t->extern_funcs);
1061 t->extern_funcs = NULL;
1066 extern_func_free(struct rte_swx_pipeline *p)
1068 extern_func_build_free(p);
1071 struct extern_func *elem;
1073 elem = TAILQ_FIRST(&p->extern_funcs);
1077 TAILQ_REMOVE(&p->extern_funcs, elem, node);
1085 static struct header *
1086 header_find(struct rte_swx_pipeline *p, const char *name)
1088 struct header *elem;
1090 TAILQ_FOREACH(elem, &p->headers, node)
1091 if (strcmp(elem->name, name) == 0)
1097 static struct header *
1098 header_find_by_struct_id(struct rte_swx_pipeline *p, uint32_t struct_id)
1100 struct header *elem;
1102 TAILQ_FOREACH(elem, &p->headers, node)
1103 if (elem->struct_id == struct_id)
1109 static struct header *
1110 header_parse(struct rte_swx_pipeline *p,
1113 if (name[0] != 'h' || name[1] != '.')
1116 return header_find(p, &name[2]);
1119 static struct field *
1120 header_field_parse(struct rte_swx_pipeline *p,
1122 struct header **header)
1126 char *header_name, *field_name;
1128 if ((name[0] != 'h') || (name[1] != '.'))
1131 header_name = strdup(&name[2]);
1135 field_name = strchr(header_name, '.');
1144 h = header_find(p, header_name);
1150 f = struct_type_field_find(h->st, field_name);
1164 rte_swx_pipeline_packet_header_register(struct rte_swx_pipeline *p,
1166 const char *struct_type_name)
1168 struct struct_type *st;
1170 size_t n_headers_max;
1173 CHECK_NAME(name, EINVAL);
1174 CHECK_NAME(struct_type_name, EINVAL);
1176 CHECK(!header_find(p, name), EEXIST);
1178 st = struct_type_find(p, struct_type_name);
1181 n_headers_max = RTE_SIZEOF_FIELD(struct thread, valid_headers) * 8;
1182 CHECK(p->n_headers < n_headers_max, ENOSPC);
1184 /* Node allocation. */
1185 h = calloc(1, sizeof(struct header));
1188 /* Node initialization. */
1189 strcpy(h->name, name);
1191 h->struct_id = p->n_structs;
1192 h->id = p->n_headers;
1194 /* Node add to tailq. */
1195 TAILQ_INSERT_TAIL(&p->headers, h, node);
1203 header_build(struct rte_swx_pipeline *p)
1206 uint32_t n_bytes = 0, i;
1208 TAILQ_FOREACH(h, &p->headers, node) {
1209 n_bytes += h->st->n_bits / 8;
1212 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1213 struct thread *t = &p->threads[i];
1214 uint32_t offset = 0;
1216 t->headers = calloc(p->n_headers,
1217 sizeof(struct header_runtime));
1218 CHECK(t->headers, ENOMEM);
1220 t->headers_out = calloc(p->n_headers,
1221 sizeof(struct header_out_runtime));
1222 CHECK(t->headers_out, ENOMEM);
1224 t->header_storage = calloc(1, n_bytes);
1225 CHECK(t->header_storage, ENOMEM);
1227 t->header_out_storage = calloc(1, n_bytes);
1228 CHECK(t->header_out_storage, ENOMEM);
1230 TAILQ_FOREACH(h, &p->headers, node) {
1231 uint8_t *header_storage;
1232 uint32_t n_bytes = h->st->n_bits / 8;
1234 header_storage = &t->header_storage[offset];
1237 t->headers[h->id].ptr0 = header_storage;
1238 t->headers[h->id].n_bytes = n_bytes;
1240 t->structs[h->struct_id] = header_storage;
1248 header_build_free(struct rte_swx_pipeline *p)
1252 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1253 struct thread *t = &p->threads[i];
1255 free(t->headers_out);
1256 t->headers_out = NULL;
1261 free(t->header_out_storage);
1262 t->header_out_storage = NULL;
1264 free(t->header_storage);
1265 t->header_storage = NULL;
1270 header_free(struct rte_swx_pipeline *p)
1272 header_build_free(p);
1275 struct header *elem;
1277 elem = TAILQ_FIRST(&p->headers);
1281 TAILQ_REMOVE(&p->headers, elem, node);
1289 static struct field *
1290 metadata_field_parse(struct rte_swx_pipeline *p, const char *name)
1292 if (!p->metadata_st)
1295 if (name[0] != 'm' || name[1] != '.')
1298 return struct_type_field_find(p->metadata_st, &name[2]);
1302 rte_swx_pipeline_packet_metadata_register(struct rte_swx_pipeline *p,
1303 const char *struct_type_name)
1305 struct struct_type *st = NULL;
1309 CHECK_NAME(struct_type_name, EINVAL);
1310 st = struct_type_find(p, struct_type_name);
1312 CHECK(!st->var_size, EINVAL);
1313 CHECK(!p->metadata_st, EINVAL);
1315 p->metadata_st = st;
1316 p->metadata_struct_id = p->n_structs;
1324 metadata_build(struct rte_swx_pipeline *p)
1326 uint32_t n_bytes = p->metadata_st->n_bits / 8;
1329 /* Thread-level initialization. */
1330 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1331 struct thread *t = &p->threads[i];
1334 metadata = calloc(1, n_bytes);
1335 CHECK(metadata, ENOMEM);
1337 t->metadata = metadata;
1338 t->structs[p->metadata_struct_id] = metadata;
1345 metadata_build_free(struct rte_swx_pipeline *p)
1349 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1350 struct thread *t = &p->threads[i];
1358 metadata_free(struct rte_swx_pipeline *p)
1360 metadata_build_free(p);
1367 instruction_is_tx(enum instruction_type type)
1380 instruction_is_jmp(struct instruction *instr)
1382 switch (instr->type) {
1384 case INSTR_JMP_VALID:
1385 case INSTR_JMP_INVALID:
1387 case INSTR_JMP_MISS:
1388 case INSTR_JMP_ACTION_HIT:
1389 case INSTR_JMP_ACTION_MISS:
1391 case INSTR_JMP_EQ_MH:
1392 case INSTR_JMP_EQ_HM:
1393 case INSTR_JMP_EQ_HH:
1394 case INSTR_JMP_EQ_I:
1396 case INSTR_JMP_NEQ_MH:
1397 case INSTR_JMP_NEQ_HM:
1398 case INSTR_JMP_NEQ_HH:
1399 case INSTR_JMP_NEQ_I:
1401 case INSTR_JMP_LT_MH:
1402 case INSTR_JMP_LT_HM:
1403 case INSTR_JMP_LT_HH:
1404 case INSTR_JMP_LT_MI:
1405 case INSTR_JMP_LT_HI:
1407 case INSTR_JMP_GT_MH:
1408 case INSTR_JMP_GT_HM:
1409 case INSTR_JMP_GT_HH:
1410 case INSTR_JMP_GT_MI:
1411 case INSTR_JMP_GT_HI:
1419 static struct field *
1420 action_field_parse(struct action *action, const char *name);
1422 static struct field *
1423 struct_field_parse(struct rte_swx_pipeline *p,
1424 struct action *action,
1426 uint32_t *struct_id)
1433 struct header *header;
1435 f = header_field_parse(p, name, &header);
1439 *struct_id = header->struct_id;
1445 f = metadata_field_parse(p, name);
1449 *struct_id = p->metadata_struct_id;
1458 f = action_field_parse(action, name);
1468 struct extern_obj *obj;
1470 f = extern_obj_mailbox_field_parse(p, name, &obj);
1474 *struct_id = obj->struct_id;
1480 struct extern_func *func;
1482 f = extern_func_mailbox_field_parse(p, name, &func);
1486 *struct_id = func->struct_id;
1499 instr_rx_translate(struct rte_swx_pipeline *p,
1500 struct action *action,
1503 struct instruction *instr,
1504 struct instruction_data *data __rte_unused)
1508 CHECK(!action, EINVAL);
1509 CHECK(n_tokens == 2, EINVAL);
1511 f = metadata_field_parse(p, tokens[1]);
1514 instr->type = INSTR_RX;
1515 instr->io.io.offset = f->offset / 8;
1516 instr->io.io.n_bits = f->n_bits;
1524 instr_tx_translate(struct rte_swx_pipeline *p,
1525 struct action *action __rte_unused,
1528 struct instruction *instr,
1529 struct instruction_data *data __rte_unused)
1531 char *port = tokens[1];
1535 CHECK(n_tokens == 2, EINVAL);
1537 f = metadata_field_parse(p, port);
1539 instr->type = INSTR_TX;
1540 instr->io.io.offset = f->offset / 8;
1541 instr->io.io.n_bits = f->n_bits;
1546 port_val = strtoul(port, &port, 0);
1547 CHECK(!port[0], EINVAL);
1549 instr->type = INSTR_TX_I;
1550 instr->io.io.val = port_val;
1555 instr_drop_translate(struct rte_swx_pipeline *p,
1556 struct action *action __rte_unused,
1557 char **tokens __rte_unused,
1559 struct instruction *instr,
1560 struct instruction_data *data __rte_unused)
1562 CHECK(n_tokens == 1, EINVAL);
1565 instr->type = INSTR_TX_I;
1566 instr->io.io.val = p->n_ports_out - 1;
1571 instr_tx_exec(struct rte_swx_pipeline *p)
1573 struct thread *t = &p->threads[p->thread_id];
1574 struct instruction *ip = t->ip;
1576 __instr_tx_exec(p, t, ip);
1579 thread_ip_reset(p, t);
1584 instr_tx_i_exec(struct rte_swx_pipeline *p)
1586 struct thread *t = &p->threads[p->thread_id];
1587 struct instruction *ip = t->ip;
1589 __instr_tx_i_exec(p, t, ip);
1592 thread_ip_reset(p, t);
1600 instr_hdr_extract_translate(struct rte_swx_pipeline *p,
1601 struct action *action,
1604 struct instruction *instr,
1605 struct instruction_data *data __rte_unused)
1609 CHECK(!action, EINVAL);
1610 CHECK((n_tokens == 2) || (n_tokens == 3), EINVAL);
1612 h = header_parse(p, tokens[1]);
1615 if (n_tokens == 2) {
1616 CHECK(!h->st->var_size, EINVAL);
1618 instr->type = INSTR_HDR_EXTRACT;
1619 instr->io.hdr.header_id[0] = h->id;
1620 instr->io.hdr.struct_id[0] = h->struct_id;
1621 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
1625 CHECK(h->st->var_size, EINVAL);
1627 mf = metadata_field_parse(p, tokens[2]);
1629 CHECK(!mf->var_size, EINVAL);
1631 instr->type = INSTR_HDR_EXTRACT_M;
1632 instr->io.io.offset = mf->offset / 8;
1633 instr->io.io.n_bits = mf->n_bits;
1634 instr->io.hdr.header_id[0] = h->id;
1635 instr->io.hdr.struct_id[0] = h->struct_id;
1636 instr->io.hdr.n_bytes[0] = h->st->n_bits_min / 8;
1643 instr_hdr_lookahead_translate(struct rte_swx_pipeline *p,
1644 struct action *action,
1647 struct instruction *instr,
1648 struct instruction_data *data __rte_unused)
1652 CHECK(!action, EINVAL);
1653 CHECK(n_tokens == 2, EINVAL);
1655 h = header_parse(p, tokens[1]);
1657 CHECK(!h->st->var_size, EINVAL);
1659 instr->type = INSTR_HDR_LOOKAHEAD;
1660 instr->io.hdr.header_id[0] = h->id;
1661 instr->io.hdr.struct_id[0] = h->struct_id;
1662 instr->io.hdr.n_bytes[0] = 0; /* Unused. */
1668 instr_hdr_extract_exec(struct rte_swx_pipeline *p)
1670 struct thread *t = &p->threads[p->thread_id];
1671 struct instruction *ip = t->ip;
1673 __instr_hdr_extract_exec(p, t, ip);
1680 instr_hdr_extract2_exec(struct rte_swx_pipeline *p)
1682 struct thread *t = &p->threads[p->thread_id];
1683 struct instruction *ip = t->ip;
1685 __instr_hdr_extract2_exec(p, t, ip);
1692 instr_hdr_extract3_exec(struct rte_swx_pipeline *p)
1694 struct thread *t = &p->threads[p->thread_id];
1695 struct instruction *ip = t->ip;
1697 __instr_hdr_extract3_exec(p, t, ip);
1704 instr_hdr_extract4_exec(struct rte_swx_pipeline *p)
1706 struct thread *t = &p->threads[p->thread_id];
1707 struct instruction *ip = t->ip;
1709 __instr_hdr_extract4_exec(p, t, ip);
1716 instr_hdr_extract5_exec(struct rte_swx_pipeline *p)
1718 struct thread *t = &p->threads[p->thread_id];
1719 struct instruction *ip = t->ip;
1721 __instr_hdr_extract5_exec(p, t, ip);
1728 instr_hdr_extract6_exec(struct rte_swx_pipeline *p)
1730 struct thread *t = &p->threads[p->thread_id];
1731 struct instruction *ip = t->ip;
1733 __instr_hdr_extract6_exec(p, t, ip);
1740 instr_hdr_extract7_exec(struct rte_swx_pipeline *p)
1742 struct thread *t = &p->threads[p->thread_id];
1743 struct instruction *ip = t->ip;
1745 __instr_hdr_extract7_exec(p, t, ip);
1752 instr_hdr_extract8_exec(struct rte_swx_pipeline *p)
1754 struct thread *t = &p->threads[p->thread_id];
1755 struct instruction *ip = t->ip;
1757 __instr_hdr_extract8_exec(p, t, ip);
1764 instr_hdr_extract_m_exec(struct rte_swx_pipeline *p)
1766 struct thread *t = &p->threads[p->thread_id];
1767 struct instruction *ip = t->ip;
1769 __instr_hdr_extract_m_exec(p, t, ip);
1776 instr_hdr_lookahead_exec(struct rte_swx_pipeline *p)
1778 struct thread *t = &p->threads[p->thread_id];
1779 struct instruction *ip = t->ip;
1781 __instr_hdr_lookahead_exec(p, t, ip);
1791 instr_hdr_emit_translate(struct rte_swx_pipeline *p,
1792 struct action *action __rte_unused,
1795 struct instruction *instr,
1796 struct instruction_data *data __rte_unused)
1800 CHECK(n_tokens == 2, EINVAL);
1802 h = header_parse(p, tokens[1]);
1805 instr->type = INSTR_HDR_EMIT;
1806 instr->io.hdr.header_id[0] = h->id;
1807 instr->io.hdr.struct_id[0] = h->struct_id;
1808 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
1813 instr_hdr_emit_exec(struct rte_swx_pipeline *p)
1815 struct thread *t = &p->threads[p->thread_id];
1816 struct instruction *ip = t->ip;
1818 __instr_hdr_emit_exec(p, t, ip);
1825 instr_hdr_emit_tx_exec(struct rte_swx_pipeline *p)
1827 struct thread *t = &p->threads[p->thread_id];
1828 struct instruction *ip = t->ip;
1830 __instr_hdr_emit_tx_exec(p, t, ip);
1833 thread_ip_reset(p, t);
1838 instr_hdr_emit2_tx_exec(struct rte_swx_pipeline *p)
1840 struct thread *t = &p->threads[p->thread_id];
1841 struct instruction *ip = t->ip;
1843 __instr_hdr_emit2_tx_exec(p, t, ip);
1846 thread_ip_reset(p, t);
1851 instr_hdr_emit3_tx_exec(struct rte_swx_pipeline *p)
1853 struct thread *t = &p->threads[p->thread_id];
1854 struct instruction *ip = t->ip;
1856 __instr_hdr_emit3_tx_exec(p, t, ip);
1859 thread_ip_reset(p, t);
1864 instr_hdr_emit4_tx_exec(struct rte_swx_pipeline *p)
1866 struct thread *t = &p->threads[p->thread_id];
1867 struct instruction *ip = t->ip;
1869 __instr_hdr_emit4_tx_exec(p, t, ip);
1872 thread_ip_reset(p, t);
1877 instr_hdr_emit5_tx_exec(struct rte_swx_pipeline *p)
1879 struct thread *t = &p->threads[p->thread_id];
1880 struct instruction *ip = t->ip;
1882 __instr_hdr_emit5_tx_exec(p, t, ip);
1885 thread_ip_reset(p, t);
1890 instr_hdr_emit6_tx_exec(struct rte_swx_pipeline *p)
1892 struct thread *t = &p->threads[p->thread_id];
1893 struct instruction *ip = t->ip;
1895 __instr_hdr_emit6_tx_exec(p, t, ip);
1898 thread_ip_reset(p, t);
1903 instr_hdr_emit7_tx_exec(struct rte_swx_pipeline *p)
1905 struct thread *t = &p->threads[p->thread_id];
1906 struct instruction *ip = t->ip;
1908 __instr_hdr_emit7_tx_exec(p, t, ip);
1911 thread_ip_reset(p, t);
1916 instr_hdr_emit8_tx_exec(struct rte_swx_pipeline *p)
1918 struct thread *t = &p->threads[p->thread_id];
1919 struct instruction *ip = t->ip;
1921 __instr_hdr_emit8_tx_exec(p, t, ip);
1924 thread_ip_reset(p, t);
1932 instr_hdr_validate_translate(struct rte_swx_pipeline *p,
1933 struct action *action __rte_unused,
1936 struct instruction *instr,
1937 struct instruction_data *data __rte_unused)
1941 CHECK(n_tokens == 2, EINVAL);
1943 h = header_parse(p, tokens[1]);
1946 instr->type = INSTR_HDR_VALIDATE;
1947 instr->valid.header_id = h->id;
1952 instr_hdr_validate_exec(struct rte_swx_pipeline *p)
1954 struct thread *t = &p->threads[p->thread_id];
1955 struct instruction *ip = t->ip;
1957 __instr_hdr_validate_exec(p, t, ip);
1967 instr_hdr_invalidate_translate(struct rte_swx_pipeline *p,
1968 struct action *action __rte_unused,
1971 struct instruction *instr,
1972 struct instruction_data *data __rte_unused)
1976 CHECK(n_tokens == 2, EINVAL);
1978 h = header_parse(p, tokens[1]);
1981 instr->type = INSTR_HDR_INVALIDATE;
1982 instr->valid.header_id = h->id;
1987 instr_hdr_invalidate_exec(struct rte_swx_pipeline *p)
1989 struct thread *t = &p->threads[p->thread_id];
1990 struct instruction *ip = t->ip;
1992 __instr_hdr_invalidate_exec(p, t, ip);
2001 static struct table *
2002 table_find(struct rte_swx_pipeline *p, const char *name);
2004 static struct selector *
2005 selector_find(struct rte_swx_pipeline *p, const char *name);
2007 static struct learner *
2008 learner_find(struct rte_swx_pipeline *p, const char *name);
2011 instr_table_translate(struct rte_swx_pipeline *p,
2012 struct action *action,
2015 struct instruction *instr,
2016 struct instruction_data *data __rte_unused)
2022 CHECK(!action, EINVAL);
2023 CHECK(n_tokens == 2, EINVAL);
2025 t = table_find(p, tokens[1]);
2027 instr->type = INSTR_TABLE;
2028 instr->table.table_id = t->id;
2032 s = selector_find(p, tokens[1]);
2034 instr->type = INSTR_SELECTOR;
2035 instr->table.table_id = s->id;
2039 l = learner_find(p, tokens[1]);
2041 instr->type = INSTR_LEARNER;
2042 instr->table.table_id = l->id;
2050 instr_table_exec(struct rte_swx_pipeline *p)
2052 struct thread *t = &p->threads[p->thread_id];
2053 struct instruction *ip = t->ip;
2054 uint32_t table_id = ip->table.table_id;
2055 struct rte_swx_table_state *ts = &t->table_state[table_id];
2056 struct table_runtime *table = &t->tables[table_id];
2057 struct table_statistics *stats = &p->table_stats[table_id];
2058 uint64_t action_id, n_pkts_hit, n_pkts_action;
2059 uint8_t *action_data;
2063 done = table->func(ts->obj,
2071 TRACE("[Thread %2u] table %u (not finalized)\n",
2079 action_id = hit ? action_id : ts->default_action_id;
2080 action_data = hit ? action_data : ts->default_action_data;
2081 n_pkts_hit = stats->n_pkts_hit[hit];
2082 n_pkts_action = stats->n_pkts_action[action_id];
2084 TRACE("[Thread %2u] table %u (%s, action %u)\n",
2087 hit ? "hit" : "miss",
2088 (uint32_t)action_id);
2090 t->action_id = action_id;
2091 t->structs[0] = action_data;
2093 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2094 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2097 thread_ip_action_call(p, t, action_id);
2101 instr_selector_exec(struct rte_swx_pipeline *p)
2103 struct thread *t = &p->threads[p->thread_id];
2104 struct instruction *ip = t->ip;
2105 uint32_t selector_id = ip->table.table_id;
2106 struct rte_swx_table_state *ts = &t->table_state[p->n_tables + selector_id];
2107 struct selector_runtime *selector = &t->selectors[selector_id];
2108 struct selector_statistics *stats = &p->selector_stats[selector_id];
2109 uint64_t n_pkts = stats->n_pkts;
2113 done = rte_swx_table_selector_select(ts->obj,
2115 selector->group_id_buffer,
2116 selector->selector_buffer,
2117 selector->member_id_buffer);
2120 TRACE("[Thread %2u] selector %u (not finalized)\n",
2129 TRACE("[Thread %2u] selector %u\n",
2133 stats->n_pkts = n_pkts + 1;
2140 instr_learner_exec(struct rte_swx_pipeline *p)
2142 struct thread *t = &p->threads[p->thread_id];
2143 struct instruction *ip = t->ip;
2144 uint32_t learner_id = ip->table.table_id;
2145 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2146 p->n_selectors + learner_id];
2147 struct learner_runtime *l = &t->learners[learner_id];
2148 struct learner_statistics *stats = &p->learner_stats[learner_id];
2149 uint64_t action_id, n_pkts_hit, n_pkts_action, time;
2150 uint8_t *action_data;
2154 time = rte_get_tsc_cycles();
2156 done = rte_swx_table_learner_lookup(ts->obj,
2165 TRACE("[Thread %2u] learner %u (not finalized)\n",
2173 action_id = hit ? action_id : ts->default_action_id;
2174 action_data = hit ? action_data : ts->default_action_data;
2175 n_pkts_hit = stats->n_pkts_hit[hit];
2176 n_pkts_action = stats->n_pkts_action[action_id];
2178 TRACE("[Thread %2u] learner %u (%s, action %u)\n",
2181 hit ? "hit" : "miss",
2182 (uint32_t)action_id);
2184 t->action_id = action_id;
2185 t->structs[0] = action_data;
2187 t->learner_id = learner_id;
2189 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2190 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2193 thread_ip_action_call(p, t, action_id);
2199 static struct action *
2200 action_find(struct rte_swx_pipeline *p, const char *name);
2203 action_has_nbo_args(struct action *a);
2206 instr_learn_translate(struct rte_swx_pipeline *p,
2207 struct action *action,
2210 struct instruction *instr,
2211 struct instruction_data *data __rte_unused)
2215 CHECK(action, EINVAL);
2216 CHECK(n_tokens == 2, EINVAL);
2218 a = action_find(p, tokens[1]);
2220 CHECK(!action_has_nbo_args(a), EINVAL);
2222 instr->type = INSTR_LEARNER_LEARN;
2223 instr->learn.action_id = a->id;
2229 instr_learn_exec(struct rte_swx_pipeline *p)
2231 struct thread *t = &p->threads[p->thread_id];
2232 struct instruction *ip = t->ip;
2234 __instr_learn_exec(p, t, ip);
2244 instr_forget_translate(struct rte_swx_pipeline *p __rte_unused,
2245 struct action *action,
2246 char **tokens __rte_unused,
2248 struct instruction *instr,
2249 struct instruction_data *data __rte_unused)
2251 CHECK(action, EINVAL);
2252 CHECK(n_tokens == 1, EINVAL);
2254 instr->type = INSTR_LEARNER_FORGET;
2260 instr_forget_exec(struct rte_swx_pipeline *p)
2262 struct thread *t = &p->threads[p->thread_id];
2263 struct instruction *ip = t->ip;
2265 __instr_forget_exec(p, t, ip);
2275 instr_extern_translate(struct rte_swx_pipeline *p,
2276 struct action *action __rte_unused,
2279 struct instruction *instr,
2280 struct instruction_data *data __rte_unused)
2282 char *token = tokens[1];
2284 CHECK(n_tokens == 2, EINVAL);
2286 if (token[0] == 'e') {
2287 struct extern_obj *obj;
2288 struct extern_type_member_func *func;
2290 func = extern_obj_member_func_parse(p, token, &obj);
2291 CHECK(func, EINVAL);
2293 instr->type = INSTR_EXTERN_OBJ;
2294 instr->ext_obj.ext_obj_id = obj->id;
2295 instr->ext_obj.func_id = func->id;
2300 if (token[0] == 'f') {
2301 struct extern_func *func;
2303 func = extern_func_parse(p, token);
2304 CHECK(func, EINVAL);
2306 instr->type = INSTR_EXTERN_FUNC;
2307 instr->ext_func.ext_func_id = func->id;
2316 instr_extern_obj_exec(struct rte_swx_pipeline *p)
2318 struct thread *t = &p->threads[p->thread_id];
2319 struct instruction *ip = t->ip;
2322 /* Extern object member function execute. */
2323 done = __instr_extern_obj_exec(p, t, ip);
2326 thread_ip_inc_cond(t, done);
2327 thread_yield_cond(p, done ^ 1);
2331 instr_extern_func_exec(struct rte_swx_pipeline *p)
2333 struct thread *t = &p->threads[p->thread_id];
2334 struct instruction *ip = t->ip;
2337 /* Extern function execute. */
2338 done = __instr_extern_func_exec(p, t, ip);
2341 thread_ip_inc_cond(t, done);
2342 thread_yield_cond(p, done ^ 1);
2349 instr_mov_translate(struct rte_swx_pipeline *p,
2350 struct action *action,
2353 struct instruction *instr,
2354 struct instruction_data *data __rte_unused)
2356 char *dst = tokens[1], *src = tokens[2];
2357 struct field *fdst, *fsrc;
2359 uint32_t dst_struct_id = 0, src_struct_id = 0;
2361 CHECK(n_tokens == 3, EINVAL);
2363 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2364 CHECK(fdst, EINVAL);
2365 CHECK(!fdst->var_size, EINVAL);
2367 /* MOV, MOV_MH, MOV_HM or MOV_HH. */
2368 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2370 CHECK(!fsrc->var_size, EINVAL);
2372 instr->type = INSTR_MOV;
2373 if (dst[0] != 'h' && src[0] == 'h')
2374 instr->type = INSTR_MOV_MH;
2375 if (dst[0] == 'h' && src[0] != 'h')
2376 instr->type = INSTR_MOV_HM;
2377 if (dst[0] == 'h' && src[0] == 'h')
2378 instr->type = INSTR_MOV_HH;
2380 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
2381 instr->mov.dst.n_bits = fdst->n_bits;
2382 instr->mov.dst.offset = fdst->offset / 8;
2383 instr->mov.src.struct_id = (uint8_t)src_struct_id;
2384 instr->mov.src.n_bits = fsrc->n_bits;
2385 instr->mov.src.offset = fsrc->offset / 8;
2390 src_val = strtoull(src, &src, 0);
2391 CHECK(!src[0], EINVAL);
2394 src_val = hton64(src_val) >> (64 - fdst->n_bits);
2396 instr->type = INSTR_MOV_I;
2397 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
2398 instr->mov.dst.n_bits = fdst->n_bits;
2399 instr->mov.dst.offset = fdst->offset / 8;
2400 instr->mov.src_val = src_val;
2405 instr_mov_exec(struct rte_swx_pipeline *p)
2407 struct thread *t = &p->threads[p->thread_id];
2408 struct instruction *ip = t->ip;
2410 __instr_mov_exec(p, t, ip);
2417 instr_mov_mh_exec(struct rte_swx_pipeline *p)
2419 struct thread *t = &p->threads[p->thread_id];
2420 struct instruction *ip = t->ip;
2422 __instr_mov_mh_exec(p, t, ip);
2429 instr_mov_hm_exec(struct rte_swx_pipeline *p)
2431 struct thread *t = &p->threads[p->thread_id];
2432 struct instruction *ip = t->ip;
2434 __instr_mov_hm_exec(p, t, ip);
2441 instr_mov_hh_exec(struct rte_swx_pipeline *p)
2443 struct thread *t = &p->threads[p->thread_id];
2444 struct instruction *ip = t->ip;
2446 __instr_mov_hh_exec(p, t, ip);
2453 instr_mov_i_exec(struct rte_swx_pipeline *p)
2455 struct thread *t = &p->threads[p->thread_id];
2456 struct instruction *ip = t->ip;
2458 __instr_mov_i_exec(p, t, ip);
2468 instr_dma_ht_exec(struct rte_swx_pipeline *p)
2470 struct thread *t = &p->threads[p->thread_id];
2471 struct instruction *ip = t->ip;
2473 __instr_dma_ht_exec(p, t, ip);
2480 instr_dma_ht2_exec(struct rte_swx_pipeline *p)
2482 struct thread *t = &p->threads[p->thread_id];
2483 struct instruction *ip = t->ip;
2485 __instr_dma_ht2_exec(p, t, ip);
2492 instr_dma_ht3_exec(struct rte_swx_pipeline *p)
2494 struct thread *t = &p->threads[p->thread_id];
2495 struct instruction *ip = t->ip;
2497 __instr_dma_ht3_exec(p, t, ip);
2504 instr_dma_ht4_exec(struct rte_swx_pipeline *p)
2506 struct thread *t = &p->threads[p->thread_id];
2507 struct instruction *ip = t->ip;
2509 __instr_dma_ht4_exec(p, t, ip);
2516 instr_dma_ht5_exec(struct rte_swx_pipeline *p)
2518 struct thread *t = &p->threads[p->thread_id];
2519 struct instruction *ip = t->ip;
2521 __instr_dma_ht5_exec(p, t, ip);
2528 instr_dma_ht6_exec(struct rte_swx_pipeline *p)
2530 struct thread *t = &p->threads[p->thread_id];
2531 struct instruction *ip = t->ip;
2533 __instr_dma_ht6_exec(p, t, ip);
2540 instr_dma_ht7_exec(struct rte_swx_pipeline *p)
2542 struct thread *t = &p->threads[p->thread_id];
2543 struct instruction *ip = t->ip;
2545 __instr_dma_ht7_exec(p, t, ip);
2552 instr_dma_ht8_exec(struct rte_swx_pipeline *p)
2554 struct thread *t = &p->threads[p->thread_id];
2555 struct instruction *ip = t->ip;
2557 __instr_dma_ht8_exec(p, t, ip);
2567 instr_alu_add_translate(struct rte_swx_pipeline *p,
2568 struct action *action,
2571 struct instruction *instr,
2572 struct instruction_data *data __rte_unused)
2574 char *dst = tokens[1], *src = tokens[2];
2575 struct field *fdst, *fsrc;
2577 uint32_t dst_struct_id = 0, src_struct_id = 0;
2579 CHECK(n_tokens == 3, EINVAL);
2581 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2582 CHECK(fdst, EINVAL);
2583 CHECK(!fdst->var_size, EINVAL);
2585 /* ADD, ADD_HM, ADD_MH, ADD_HH. */
2586 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2588 CHECK(!fsrc->var_size, EINVAL);
2590 instr->type = INSTR_ALU_ADD;
2591 if (dst[0] == 'h' && src[0] != 'h')
2592 instr->type = INSTR_ALU_ADD_HM;
2593 if (dst[0] != 'h' && src[0] == 'h')
2594 instr->type = INSTR_ALU_ADD_MH;
2595 if (dst[0] == 'h' && src[0] == 'h')
2596 instr->type = INSTR_ALU_ADD_HH;
2598 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2599 instr->alu.dst.n_bits = fdst->n_bits;
2600 instr->alu.dst.offset = fdst->offset / 8;
2601 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2602 instr->alu.src.n_bits = fsrc->n_bits;
2603 instr->alu.src.offset = fsrc->offset / 8;
2607 /* ADD_MI, ADD_HI. */
2608 src_val = strtoull(src, &src, 0);
2609 CHECK(!src[0], EINVAL);
2611 instr->type = INSTR_ALU_ADD_MI;
2613 instr->type = INSTR_ALU_ADD_HI;
2615 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2616 instr->alu.dst.n_bits = fdst->n_bits;
2617 instr->alu.dst.offset = fdst->offset / 8;
2618 instr->alu.src_val = src_val;
2623 instr_alu_sub_translate(struct rte_swx_pipeline *p,
2624 struct action *action,
2627 struct instruction *instr,
2628 struct instruction_data *data __rte_unused)
2630 char *dst = tokens[1], *src = tokens[2];
2631 struct field *fdst, *fsrc;
2633 uint32_t dst_struct_id = 0, src_struct_id = 0;
2635 CHECK(n_tokens == 3, EINVAL);
2637 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2638 CHECK(fdst, EINVAL);
2639 CHECK(!fdst->var_size, EINVAL);
2641 /* SUB, SUB_HM, SUB_MH, SUB_HH. */
2642 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2644 CHECK(!fsrc->var_size, EINVAL);
2646 instr->type = INSTR_ALU_SUB;
2647 if (dst[0] == 'h' && src[0] != 'h')
2648 instr->type = INSTR_ALU_SUB_HM;
2649 if (dst[0] != 'h' && src[0] == 'h')
2650 instr->type = INSTR_ALU_SUB_MH;
2651 if (dst[0] == 'h' && src[0] == 'h')
2652 instr->type = INSTR_ALU_SUB_HH;
2654 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2655 instr->alu.dst.n_bits = fdst->n_bits;
2656 instr->alu.dst.offset = fdst->offset / 8;
2657 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2658 instr->alu.src.n_bits = fsrc->n_bits;
2659 instr->alu.src.offset = fsrc->offset / 8;
2663 /* SUB_MI, SUB_HI. */
2664 src_val = strtoull(src, &src, 0);
2665 CHECK(!src[0], EINVAL);
2667 instr->type = INSTR_ALU_SUB_MI;
2669 instr->type = INSTR_ALU_SUB_HI;
2671 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2672 instr->alu.dst.n_bits = fdst->n_bits;
2673 instr->alu.dst.offset = fdst->offset / 8;
2674 instr->alu.src_val = src_val;
2679 instr_alu_ckadd_translate(struct rte_swx_pipeline *p,
2680 struct action *action __rte_unused,
2683 struct instruction *instr,
2684 struct instruction_data *data __rte_unused)
2686 char *dst = tokens[1], *src = tokens[2];
2687 struct header *hdst, *hsrc;
2688 struct field *fdst, *fsrc;
2690 CHECK(n_tokens == 3, EINVAL);
2692 fdst = header_field_parse(p, dst, &hdst);
2693 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
2694 CHECK(!fdst->var_size, EINVAL);
2697 fsrc = header_field_parse(p, src, &hsrc);
2699 CHECK(!fsrc->var_size, EINVAL);
2701 instr->type = INSTR_ALU_CKADD_FIELD;
2702 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2703 instr->alu.dst.n_bits = fdst->n_bits;
2704 instr->alu.dst.offset = fdst->offset / 8;
2705 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2706 instr->alu.src.n_bits = fsrc->n_bits;
2707 instr->alu.src.offset = fsrc->offset / 8;
2711 /* CKADD_STRUCT, CKADD_STRUCT20. */
2712 hsrc = header_parse(p, src);
2713 CHECK(hsrc, EINVAL);
2714 CHECK(!hsrc->st->var_size, EINVAL);
2716 instr->type = INSTR_ALU_CKADD_STRUCT;
2717 if ((hsrc->st->n_bits / 8) == 20)
2718 instr->type = INSTR_ALU_CKADD_STRUCT20;
2720 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2721 instr->alu.dst.n_bits = fdst->n_bits;
2722 instr->alu.dst.offset = fdst->offset / 8;
2723 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2724 instr->alu.src.n_bits = hsrc->st->n_bits;
2725 instr->alu.src.offset = 0; /* Unused. */
2730 instr_alu_cksub_translate(struct rte_swx_pipeline *p,
2731 struct action *action __rte_unused,
2734 struct instruction *instr,
2735 struct instruction_data *data __rte_unused)
2737 char *dst = tokens[1], *src = tokens[2];
2738 struct header *hdst, *hsrc;
2739 struct field *fdst, *fsrc;
2741 CHECK(n_tokens == 3, EINVAL);
2743 fdst = header_field_parse(p, dst, &hdst);
2744 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
2745 CHECK(!fdst->var_size, EINVAL);
2747 fsrc = header_field_parse(p, src, &hsrc);
2748 CHECK(fsrc, EINVAL);
2749 CHECK(!fsrc->var_size, EINVAL);
2751 instr->type = INSTR_ALU_CKSUB_FIELD;
2752 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
2753 instr->alu.dst.n_bits = fdst->n_bits;
2754 instr->alu.dst.offset = fdst->offset / 8;
2755 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
2756 instr->alu.src.n_bits = fsrc->n_bits;
2757 instr->alu.src.offset = fsrc->offset / 8;
2762 instr_alu_shl_translate(struct rte_swx_pipeline *p,
2763 struct action *action,
2766 struct instruction *instr,
2767 struct instruction_data *data __rte_unused)
2769 char *dst = tokens[1], *src = tokens[2];
2770 struct field *fdst, *fsrc;
2772 uint32_t dst_struct_id = 0, src_struct_id = 0;
2774 CHECK(n_tokens == 3, EINVAL);
2776 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2777 CHECK(fdst, EINVAL);
2778 CHECK(!fdst->var_size, EINVAL);
2780 /* SHL, SHL_HM, SHL_MH, SHL_HH. */
2781 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2783 CHECK(!fsrc->var_size, EINVAL);
2785 instr->type = INSTR_ALU_SHL;
2786 if (dst[0] == 'h' && src[0] != 'h')
2787 instr->type = INSTR_ALU_SHL_HM;
2788 if (dst[0] != 'h' && src[0] == 'h')
2789 instr->type = INSTR_ALU_SHL_MH;
2790 if (dst[0] == 'h' && src[0] == 'h')
2791 instr->type = INSTR_ALU_SHL_HH;
2793 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2794 instr->alu.dst.n_bits = fdst->n_bits;
2795 instr->alu.dst.offset = fdst->offset / 8;
2796 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2797 instr->alu.src.n_bits = fsrc->n_bits;
2798 instr->alu.src.offset = fsrc->offset / 8;
2802 /* SHL_MI, SHL_HI. */
2803 src_val = strtoull(src, &src, 0);
2804 CHECK(!src[0], EINVAL);
2806 instr->type = INSTR_ALU_SHL_MI;
2808 instr->type = INSTR_ALU_SHL_HI;
2810 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2811 instr->alu.dst.n_bits = fdst->n_bits;
2812 instr->alu.dst.offset = fdst->offset / 8;
2813 instr->alu.src_val = src_val;
2818 instr_alu_shr_translate(struct rte_swx_pipeline *p,
2819 struct action *action,
2822 struct instruction *instr,
2823 struct instruction_data *data __rte_unused)
2825 char *dst = tokens[1], *src = tokens[2];
2826 struct field *fdst, *fsrc;
2828 uint32_t dst_struct_id = 0, src_struct_id = 0;
2830 CHECK(n_tokens == 3, EINVAL);
2832 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2833 CHECK(fdst, EINVAL);
2834 CHECK(!fdst->var_size, EINVAL);
2836 /* SHR, SHR_HM, SHR_MH, SHR_HH. */
2837 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2839 CHECK(!fsrc->var_size, EINVAL);
2841 instr->type = INSTR_ALU_SHR;
2842 if (dst[0] == 'h' && src[0] != 'h')
2843 instr->type = INSTR_ALU_SHR_HM;
2844 if (dst[0] != 'h' && src[0] == 'h')
2845 instr->type = INSTR_ALU_SHR_MH;
2846 if (dst[0] == 'h' && src[0] == 'h')
2847 instr->type = INSTR_ALU_SHR_HH;
2849 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2850 instr->alu.dst.n_bits = fdst->n_bits;
2851 instr->alu.dst.offset = fdst->offset / 8;
2852 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2853 instr->alu.src.n_bits = fsrc->n_bits;
2854 instr->alu.src.offset = fsrc->offset / 8;
2858 /* SHR_MI, SHR_HI. */
2859 src_val = strtoull(src, &src, 0);
2860 CHECK(!src[0], EINVAL);
2862 instr->type = INSTR_ALU_SHR_MI;
2864 instr->type = INSTR_ALU_SHR_HI;
2866 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2867 instr->alu.dst.n_bits = fdst->n_bits;
2868 instr->alu.dst.offset = fdst->offset / 8;
2869 instr->alu.src_val = src_val;
2874 instr_alu_and_translate(struct rte_swx_pipeline *p,
2875 struct action *action,
2878 struct instruction *instr,
2879 struct instruction_data *data __rte_unused)
2881 char *dst = tokens[1], *src = tokens[2];
2882 struct field *fdst, *fsrc;
2884 uint32_t dst_struct_id = 0, src_struct_id = 0;
2886 CHECK(n_tokens == 3, EINVAL);
2888 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2889 CHECK(fdst, EINVAL);
2890 CHECK(!fdst->var_size, EINVAL);
2892 /* AND, AND_MH, AND_HM, AND_HH. */
2893 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2895 CHECK(!fsrc->var_size, EINVAL);
2897 instr->type = INSTR_ALU_AND;
2898 if (dst[0] != 'h' && src[0] == 'h')
2899 instr->type = INSTR_ALU_AND_MH;
2900 if (dst[0] == 'h' && src[0] != 'h')
2901 instr->type = INSTR_ALU_AND_HM;
2902 if (dst[0] == 'h' && src[0] == 'h')
2903 instr->type = INSTR_ALU_AND_HH;
2905 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2906 instr->alu.dst.n_bits = fdst->n_bits;
2907 instr->alu.dst.offset = fdst->offset / 8;
2908 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2909 instr->alu.src.n_bits = fsrc->n_bits;
2910 instr->alu.src.offset = fsrc->offset / 8;
2915 src_val = strtoull(src, &src, 0);
2916 CHECK(!src[0], EINVAL);
2919 src_val = hton64(src_val) >> (64 - fdst->n_bits);
2921 instr->type = INSTR_ALU_AND_I;
2922 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2923 instr->alu.dst.n_bits = fdst->n_bits;
2924 instr->alu.dst.offset = fdst->offset / 8;
2925 instr->alu.src_val = src_val;
2930 instr_alu_or_translate(struct rte_swx_pipeline *p,
2931 struct action *action,
2934 struct instruction *instr,
2935 struct instruction_data *data __rte_unused)
2937 char *dst = tokens[1], *src = tokens[2];
2938 struct field *fdst, *fsrc;
2940 uint32_t dst_struct_id = 0, src_struct_id = 0;
2942 CHECK(n_tokens == 3, EINVAL);
2944 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2945 CHECK(fdst, EINVAL);
2946 CHECK(!fdst->var_size, EINVAL);
2948 /* OR, OR_MH, OR_HM, OR_HH. */
2949 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2951 CHECK(!fsrc->var_size, EINVAL);
2953 instr->type = INSTR_ALU_OR;
2954 if (dst[0] != 'h' && src[0] == 'h')
2955 instr->type = INSTR_ALU_OR_MH;
2956 if (dst[0] == 'h' && src[0] != 'h')
2957 instr->type = INSTR_ALU_OR_HM;
2958 if (dst[0] == 'h' && src[0] == 'h')
2959 instr->type = INSTR_ALU_OR_HH;
2961 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2962 instr->alu.dst.n_bits = fdst->n_bits;
2963 instr->alu.dst.offset = fdst->offset / 8;
2964 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2965 instr->alu.src.n_bits = fsrc->n_bits;
2966 instr->alu.src.offset = fsrc->offset / 8;
2971 src_val = strtoull(src, &src, 0);
2972 CHECK(!src[0], EINVAL);
2975 src_val = hton64(src_val) >> (64 - fdst->n_bits);
2977 instr->type = INSTR_ALU_OR_I;
2978 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2979 instr->alu.dst.n_bits = fdst->n_bits;
2980 instr->alu.dst.offset = fdst->offset / 8;
2981 instr->alu.src_val = src_val;
2986 instr_alu_xor_translate(struct rte_swx_pipeline *p,
2987 struct action *action,
2990 struct instruction *instr,
2991 struct instruction_data *data __rte_unused)
2993 char *dst = tokens[1], *src = tokens[2];
2994 struct field *fdst, *fsrc;
2996 uint32_t dst_struct_id = 0, src_struct_id = 0;
2998 CHECK(n_tokens == 3, EINVAL);
3000 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3001 CHECK(fdst, EINVAL);
3002 CHECK(!fdst->var_size, EINVAL);
3004 /* XOR, XOR_MH, XOR_HM, XOR_HH. */
3005 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3007 CHECK(!fsrc->var_size, EINVAL);
3009 instr->type = INSTR_ALU_XOR;
3010 if (dst[0] != 'h' && src[0] == 'h')
3011 instr->type = INSTR_ALU_XOR_MH;
3012 if (dst[0] == 'h' && src[0] != 'h')
3013 instr->type = INSTR_ALU_XOR_HM;
3014 if (dst[0] == 'h' && src[0] == 'h')
3015 instr->type = INSTR_ALU_XOR_HH;
3017 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3018 instr->alu.dst.n_bits = fdst->n_bits;
3019 instr->alu.dst.offset = fdst->offset / 8;
3020 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3021 instr->alu.src.n_bits = fsrc->n_bits;
3022 instr->alu.src.offset = fsrc->offset / 8;
3027 src_val = strtoull(src, &src, 0);
3028 CHECK(!src[0], EINVAL);
3031 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3033 instr->type = INSTR_ALU_XOR_I;
3034 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3035 instr->alu.dst.n_bits = fdst->n_bits;
3036 instr->alu.dst.offset = fdst->offset / 8;
3037 instr->alu.src_val = src_val;
3042 instr_alu_add_exec(struct rte_swx_pipeline *p)
3044 struct thread *t = &p->threads[p->thread_id];
3045 struct instruction *ip = t->ip;
3048 __instr_alu_add_exec(p, t, ip);
3055 instr_alu_add_mh_exec(struct rte_swx_pipeline *p)
3057 struct thread *t = &p->threads[p->thread_id];
3058 struct instruction *ip = t->ip;
3061 __instr_alu_add_mh_exec(p, t, ip);
3068 instr_alu_add_hm_exec(struct rte_swx_pipeline *p)
3070 struct thread *t = &p->threads[p->thread_id];
3071 struct instruction *ip = t->ip;
3074 __instr_alu_add_hm_exec(p, t, ip);
3081 instr_alu_add_hh_exec(struct rte_swx_pipeline *p)
3083 struct thread *t = &p->threads[p->thread_id];
3084 struct instruction *ip = t->ip;
3087 __instr_alu_add_hh_exec(p, t, ip);
3094 instr_alu_add_mi_exec(struct rte_swx_pipeline *p)
3096 struct thread *t = &p->threads[p->thread_id];
3097 struct instruction *ip = t->ip;
3100 __instr_alu_add_mi_exec(p, t, ip);
3107 instr_alu_add_hi_exec(struct rte_swx_pipeline *p)
3109 struct thread *t = &p->threads[p->thread_id];
3110 struct instruction *ip = t->ip;
3113 __instr_alu_add_hi_exec(p, t, ip);
3120 instr_alu_sub_exec(struct rte_swx_pipeline *p)
3122 struct thread *t = &p->threads[p->thread_id];
3123 struct instruction *ip = t->ip;
3126 __instr_alu_sub_exec(p, t, ip);
3133 instr_alu_sub_mh_exec(struct rte_swx_pipeline *p)
3135 struct thread *t = &p->threads[p->thread_id];
3136 struct instruction *ip = t->ip;
3139 __instr_alu_sub_mh_exec(p, t, ip);
3146 instr_alu_sub_hm_exec(struct rte_swx_pipeline *p)
3148 struct thread *t = &p->threads[p->thread_id];
3149 struct instruction *ip = t->ip;
3152 __instr_alu_sub_hm_exec(p, t, ip);
3159 instr_alu_sub_hh_exec(struct rte_swx_pipeline *p)
3161 struct thread *t = &p->threads[p->thread_id];
3162 struct instruction *ip = t->ip;
3165 __instr_alu_sub_hh_exec(p, t, ip);
3172 instr_alu_sub_mi_exec(struct rte_swx_pipeline *p)
3174 struct thread *t = &p->threads[p->thread_id];
3175 struct instruction *ip = t->ip;
3178 __instr_alu_sub_mi_exec(p, t, ip);
3185 instr_alu_sub_hi_exec(struct rte_swx_pipeline *p)
3187 struct thread *t = &p->threads[p->thread_id];
3188 struct instruction *ip = t->ip;
3191 __instr_alu_sub_hi_exec(p, t, ip);
3198 instr_alu_shl_exec(struct rte_swx_pipeline *p)
3200 struct thread *t = &p->threads[p->thread_id];
3201 struct instruction *ip = t->ip;
3204 __instr_alu_shl_exec(p, t, ip);
3211 instr_alu_shl_mh_exec(struct rte_swx_pipeline *p)
3213 struct thread *t = &p->threads[p->thread_id];
3214 struct instruction *ip = t->ip;
3217 __instr_alu_shl_mh_exec(p, t, ip);
3224 instr_alu_shl_hm_exec(struct rte_swx_pipeline *p)
3226 struct thread *t = &p->threads[p->thread_id];
3227 struct instruction *ip = t->ip;
3230 __instr_alu_shl_hm_exec(p, t, ip);
3237 instr_alu_shl_hh_exec(struct rte_swx_pipeline *p)
3239 struct thread *t = &p->threads[p->thread_id];
3240 struct instruction *ip = t->ip;
3243 __instr_alu_shl_hh_exec(p, t, ip);
3250 instr_alu_shl_mi_exec(struct rte_swx_pipeline *p)
3252 struct thread *t = &p->threads[p->thread_id];
3253 struct instruction *ip = t->ip;
3256 __instr_alu_shl_mi_exec(p, t, ip);
3263 instr_alu_shl_hi_exec(struct rte_swx_pipeline *p)
3265 struct thread *t = &p->threads[p->thread_id];
3266 struct instruction *ip = t->ip;
3269 __instr_alu_shl_hi_exec(p, t, ip);
3276 instr_alu_shr_exec(struct rte_swx_pipeline *p)
3278 struct thread *t = &p->threads[p->thread_id];
3279 struct instruction *ip = t->ip;
3282 __instr_alu_shr_exec(p, t, ip);
3289 instr_alu_shr_mh_exec(struct rte_swx_pipeline *p)
3291 struct thread *t = &p->threads[p->thread_id];
3292 struct instruction *ip = t->ip;
3295 __instr_alu_shr_mh_exec(p, t, ip);
3302 instr_alu_shr_hm_exec(struct rte_swx_pipeline *p)
3304 struct thread *t = &p->threads[p->thread_id];
3305 struct instruction *ip = t->ip;
3308 __instr_alu_shr_hm_exec(p, t, ip);
3315 instr_alu_shr_hh_exec(struct rte_swx_pipeline *p)
3317 struct thread *t = &p->threads[p->thread_id];
3318 struct instruction *ip = t->ip;
3321 __instr_alu_shr_hh_exec(p, t, ip);
3328 instr_alu_shr_mi_exec(struct rte_swx_pipeline *p)
3330 struct thread *t = &p->threads[p->thread_id];
3331 struct instruction *ip = t->ip;
3334 __instr_alu_shr_mi_exec(p, t, ip);
3341 instr_alu_shr_hi_exec(struct rte_swx_pipeline *p)
3343 struct thread *t = &p->threads[p->thread_id];
3344 struct instruction *ip = t->ip;
3347 __instr_alu_shr_hi_exec(p, t, ip);
3354 instr_alu_and_exec(struct rte_swx_pipeline *p)
3356 struct thread *t = &p->threads[p->thread_id];
3357 struct instruction *ip = t->ip;
3360 __instr_alu_and_exec(p, t, ip);
3367 instr_alu_and_mh_exec(struct rte_swx_pipeline *p)
3369 struct thread *t = &p->threads[p->thread_id];
3370 struct instruction *ip = t->ip;
3373 __instr_alu_and_mh_exec(p, t, ip);
3380 instr_alu_and_hm_exec(struct rte_swx_pipeline *p)
3382 struct thread *t = &p->threads[p->thread_id];
3383 struct instruction *ip = t->ip;
3386 __instr_alu_and_hm_exec(p, t, ip);
3393 instr_alu_and_hh_exec(struct rte_swx_pipeline *p)
3395 struct thread *t = &p->threads[p->thread_id];
3396 struct instruction *ip = t->ip;
3399 __instr_alu_and_hh_exec(p, t, ip);
3406 instr_alu_and_i_exec(struct rte_swx_pipeline *p)
3408 struct thread *t = &p->threads[p->thread_id];
3409 struct instruction *ip = t->ip;
3412 __instr_alu_and_i_exec(p, t, ip);
3419 instr_alu_or_exec(struct rte_swx_pipeline *p)
3421 struct thread *t = &p->threads[p->thread_id];
3422 struct instruction *ip = t->ip;
3425 __instr_alu_or_exec(p, t, ip);
3432 instr_alu_or_mh_exec(struct rte_swx_pipeline *p)
3434 struct thread *t = &p->threads[p->thread_id];
3435 struct instruction *ip = t->ip;
3438 __instr_alu_or_mh_exec(p, t, ip);
3445 instr_alu_or_hm_exec(struct rte_swx_pipeline *p)
3447 struct thread *t = &p->threads[p->thread_id];
3448 struct instruction *ip = t->ip;
3451 __instr_alu_or_hm_exec(p, t, ip);
3458 instr_alu_or_hh_exec(struct rte_swx_pipeline *p)
3460 struct thread *t = &p->threads[p->thread_id];
3461 struct instruction *ip = t->ip;
3464 __instr_alu_or_hh_exec(p, t, ip);
3471 instr_alu_or_i_exec(struct rte_swx_pipeline *p)
3473 struct thread *t = &p->threads[p->thread_id];
3474 struct instruction *ip = t->ip;
3477 __instr_alu_or_i_exec(p, t, ip);
3484 instr_alu_xor_exec(struct rte_swx_pipeline *p)
3486 struct thread *t = &p->threads[p->thread_id];
3487 struct instruction *ip = t->ip;
3490 __instr_alu_xor_exec(p, t, ip);
3497 instr_alu_xor_mh_exec(struct rte_swx_pipeline *p)
3499 struct thread *t = &p->threads[p->thread_id];
3500 struct instruction *ip = t->ip;
3503 __instr_alu_xor_mh_exec(p, t, ip);
3510 instr_alu_xor_hm_exec(struct rte_swx_pipeline *p)
3512 struct thread *t = &p->threads[p->thread_id];
3513 struct instruction *ip = t->ip;
3516 __instr_alu_xor_hm_exec(p, t, ip);
3523 instr_alu_xor_hh_exec(struct rte_swx_pipeline *p)
3525 struct thread *t = &p->threads[p->thread_id];
3526 struct instruction *ip = t->ip;
3529 __instr_alu_xor_hh_exec(p, t, ip);
3536 instr_alu_xor_i_exec(struct rte_swx_pipeline *p)
3538 struct thread *t = &p->threads[p->thread_id];
3539 struct instruction *ip = t->ip;
3542 __instr_alu_xor_i_exec(p, t, ip);
3549 instr_alu_ckadd_field_exec(struct rte_swx_pipeline *p)
3551 struct thread *t = &p->threads[p->thread_id];
3552 struct instruction *ip = t->ip;
3555 __instr_alu_ckadd_field_exec(p, t, ip);
3562 instr_alu_cksub_field_exec(struct rte_swx_pipeline *p)
3564 struct thread *t = &p->threads[p->thread_id];
3565 struct instruction *ip = t->ip;
3568 __instr_alu_cksub_field_exec(p, t, ip);
3575 instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline *p)
3577 struct thread *t = &p->threads[p->thread_id];
3578 struct instruction *ip = t->ip;
3581 __instr_alu_ckadd_struct20_exec(p, t, ip);
3588 instr_alu_ckadd_struct_exec(struct rte_swx_pipeline *p)
3590 struct thread *t = &p->threads[p->thread_id];
3591 struct instruction *ip = t->ip;
3594 __instr_alu_ckadd_struct_exec(p, t, ip);
3603 static struct regarray *
3604 regarray_find(struct rte_swx_pipeline *p, const char *name);
3607 instr_regprefetch_translate(struct rte_swx_pipeline *p,
3608 struct action *action,
3611 struct instruction *instr,
3612 struct instruction_data *data __rte_unused)
3614 char *regarray = tokens[1], *idx = tokens[2];
3617 uint32_t idx_struct_id, idx_val;
3619 CHECK(n_tokens == 3, EINVAL);
3621 r = regarray_find(p, regarray);
3624 /* REGPREFETCH_RH, REGPREFETCH_RM. */
3625 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
3627 CHECK(!fidx->var_size, EINVAL);
3629 instr->type = INSTR_REGPREFETCH_RM;
3631 instr->type = INSTR_REGPREFETCH_RH;
3633 instr->regarray.regarray_id = r->id;
3634 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
3635 instr->regarray.idx.n_bits = fidx->n_bits;
3636 instr->regarray.idx.offset = fidx->offset / 8;
3637 instr->regarray.dstsrc_val = 0; /* Unused. */
3641 /* REGPREFETCH_RI. */
3642 idx_val = strtoul(idx, &idx, 0);
3643 CHECK(!idx[0], EINVAL);
3645 instr->type = INSTR_REGPREFETCH_RI;
3646 instr->regarray.regarray_id = r->id;
3647 instr->regarray.idx_val = idx_val;
3648 instr->regarray.dstsrc_val = 0; /* Unused. */
3653 instr_regrd_translate(struct rte_swx_pipeline *p,
3654 struct action *action,
3657 struct instruction *instr,
3658 struct instruction_data *data __rte_unused)
3660 char *dst = tokens[1], *regarray = tokens[2], *idx = tokens[3];
3662 struct field *fdst, *fidx;
3663 uint32_t dst_struct_id, idx_struct_id, idx_val;
3665 CHECK(n_tokens == 4, EINVAL);
3667 r = regarray_find(p, regarray);
3670 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3671 CHECK(fdst, EINVAL);
3672 CHECK(!fdst->var_size, EINVAL);
3674 /* REGRD_HRH, REGRD_HRM, REGRD_MRH, REGRD_MRM. */
3675 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
3677 CHECK(!fidx->var_size, EINVAL);
3679 instr->type = INSTR_REGRD_MRM;
3680 if (dst[0] == 'h' && idx[0] != 'h')
3681 instr->type = INSTR_REGRD_HRM;
3682 if (dst[0] != 'h' && idx[0] == 'h')
3683 instr->type = INSTR_REGRD_MRH;
3684 if (dst[0] == 'h' && idx[0] == 'h')
3685 instr->type = INSTR_REGRD_HRH;
3687 instr->regarray.regarray_id = r->id;
3688 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
3689 instr->regarray.idx.n_bits = fidx->n_bits;
3690 instr->regarray.idx.offset = fidx->offset / 8;
3691 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
3692 instr->regarray.dstsrc.n_bits = fdst->n_bits;
3693 instr->regarray.dstsrc.offset = fdst->offset / 8;
3697 /* REGRD_MRI, REGRD_HRI. */
3698 idx_val = strtoul(idx, &idx, 0);
3699 CHECK(!idx[0], EINVAL);
3701 instr->type = INSTR_REGRD_MRI;
3703 instr->type = INSTR_REGRD_HRI;
3705 instr->regarray.regarray_id = r->id;
3706 instr->regarray.idx_val = idx_val;
3707 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
3708 instr->regarray.dstsrc.n_bits = fdst->n_bits;
3709 instr->regarray.dstsrc.offset = fdst->offset / 8;
3714 instr_regwr_translate(struct rte_swx_pipeline *p,
3715 struct action *action,
3718 struct instruction *instr,
3719 struct instruction_data *data __rte_unused)
3721 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
3723 struct field *fidx, *fsrc;
3725 uint32_t idx_struct_id, idx_val, src_struct_id;
3727 CHECK(n_tokens == 4, EINVAL);
3729 r = regarray_find(p, regarray);
3732 /* REGWR_RHH, REGWR_RHM, REGWR_RMH, REGWR_RMM. */
3733 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
3734 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3736 CHECK(!fidx->var_size, EINVAL);
3737 CHECK(!fsrc->var_size, EINVAL);
3739 instr->type = INSTR_REGWR_RMM;
3740 if (idx[0] == 'h' && src[0] != 'h')
3741 instr->type = INSTR_REGWR_RHM;
3742 if (idx[0] != 'h' && src[0] == 'h')
3743 instr->type = INSTR_REGWR_RMH;
3744 if (idx[0] == 'h' && src[0] == 'h')
3745 instr->type = INSTR_REGWR_RHH;
3747 instr->regarray.regarray_id = r->id;
3748 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
3749 instr->regarray.idx.n_bits = fidx->n_bits;
3750 instr->regarray.idx.offset = fidx->offset / 8;
3751 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
3752 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
3753 instr->regarray.dstsrc.offset = fsrc->offset / 8;
3757 /* REGWR_RHI, REGWR_RMI. */
3758 if (fidx && !fsrc) {
3759 CHECK(!fidx->var_size, EINVAL);
3761 src_val = strtoull(src, &src, 0);
3762 CHECK(!src[0], EINVAL);
3764 instr->type = INSTR_REGWR_RMI;
3766 instr->type = INSTR_REGWR_RHI;
3768 instr->regarray.regarray_id = r->id;
3769 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
3770 instr->regarray.idx.n_bits = fidx->n_bits;
3771 instr->regarray.idx.offset = fidx->offset / 8;
3772 instr->regarray.dstsrc_val = src_val;
3776 /* REGWR_RIH, REGWR_RIM. */
3777 if (!fidx && fsrc) {
3778 idx_val = strtoul(idx, &idx, 0);
3779 CHECK(!idx[0], EINVAL);
3781 CHECK(!fsrc->var_size, EINVAL);
3783 instr->type = INSTR_REGWR_RIM;
3785 instr->type = INSTR_REGWR_RIH;
3787 instr->regarray.regarray_id = r->id;
3788 instr->regarray.idx_val = idx_val;
3789 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
3790 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
3791 instr->regarray.dstsrc.offset = fsrc->offset / 8;
3796 src_val = strtoull(src, &src, 0);
3797 CHECK(!src[0], EINVAL);
3799 idx_val = strtoul(idx, &idx, 0);
3800 CHECK(!idx[0], EINVAL);
3802 instr->type = INSTR_REGWR_RII;
3803 instr->regarray.idx_val = idx_val;
3804 instr->regarray.dstsrc_val = src_val;
3810 instr_regadd_translate(struct rte_swx_pipeline *p,
3811 struct action *action,
3814 struct instruction *instr,
3815 struct instruction_data *data __rte_unused)
3817 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
3819 struct field *fidx, *fsrc;
3821 uint32_t idx_struct_id, idx_val, src_struct_id;
3823 CHECK(n_tokens == 4, EINVAL);
3825 r = regarray_find(p, regarray);
3828 /* REGADD_RHH, REGADD_RHM, REGADD_RMH, REGADD_RMM. */
3829 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
3830 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3832 CHECK(!fidx->var_size, EINVAL);
3833 CHECK(!fsrc->var_size, EINVAL);
3835 instr->type = INSTR_REGADD_RMM;
3836 if (idx[0] == 'h' && src[0] != 'h')
3837 instr->type = INSTR_REGADD_RHM;
3838 if (idx[0] != 'h' && src[0] == 'h')
3839 instr->type = INSTR_REGADD_RMH;
3840 if (idx[0] == 'h' && src[0] == 'h')
3841 instr->type = INSTR_REGADD_RHH;
3843 instr->regarray.regarray_id = r->id;
3844 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
3845 instr->regarray.idx.n_bits = fidx->n_bits;
3846 instr->regarray.idx.offset = fidx->offset / 8;
3847 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
3848 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
3849 instr->regarray.dstsrc.offset = fsrc->offset / 8;
3853 /* REGADD_RHI, REGADD_RMI. */
3854 if (fidx && !fsrc) {
3855 CHECK(!fidx->var_size, EINVAL);
3857 src_val = strtoull(src, &src, 0);
3858 CHECK(!src[0], EINVAL);
3860 instr->type = INSTR_REGADD_RMI;
3862 instr->type = INSTR_REGADD_RHI;
3864 instr->regarray.regarray_id = r->id;
3865 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
3866 instr->regarray.idx.n_bits = fidx->n_bits;
3867 instr->regarray.idx.offset = fidx->offset / 8;
3868 instr->regarray.dstsrc_val = src_val;
3872 /* REGADD_RIH, REGADD_RIM. */
3873 if (!fidx && fsrc) {
3874 idx_val = strtoul(idx, &idx, 0);
3875 CHECK(!idx[0], EINVAL);
3877 CHECK(!fsrc->var_size, EINVAL);
3879 instr->type = INSTR_REGADD_RIM;
3881 instr->type = INSTR_REGADD_RIH;
3883 instr->regarray.regarray_id = r->id;
3884 instr->regarray.idx_val = idx_val;
3885 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
3886 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
3887 instr->regarray.dstsrc.offset = fsrc->offset / 8;
3892 src_val = strtoull(src, &src, 0);
3893 CHECK(!src[0], EINVAL);
3895 idx_val = strtoul(idx, &idx, 0);
3896 CHECK(!idx[0], EINVAL);
3898 instr->type = INSTR_REGADD_RII;
3899 instr->regarray.idx_val = idx_val;
3900 instr->regarray.dstsrc_val = src_val;
3905 instr_regprefetch_rh_exec(struct rte_swx_pipeline *p)
3907 struct thread *t = &p->threads[p->thread_id];
3908 struct instruction *ip = t->ip;
3911 __instr_regprefetch_rh_exec(p, t, ip);
3918 instr_regprefetch_rm_exec(struct rte_swx_pipeline *p)
3920 struct thread *t = &p->threads[p->thread_id];
3921 struct instruction *ip = t->ip;
3924 __instr_regprefetch_rm_exec(p, t, ip);
3931 instr_regprefetch_ri_exec(struct rte_swx_pipeline *p)
3933 struct thread *t = &p->threads[p->thread_id];
3934 struct instruction *ip = t->ip;
3937 __instr_regprefetch_ri_exec(p, t, ip);
3944 instr_regrd_hrh_exec(struct rte_swx_pipeline *p)
3946 struct thread *t = &p->threads[p->thread_id];
3947 struct instruction *ip = t->ip;
3950 __instr_regrd_hrh_exec(p, t, ip);
3957 instr_regrd_hrm_exec(struct rte_swx_pipeline *p)
3959 struct thread *t = &p->threads[p->thread_id];
3960 struct instruction *ip = t->ip;
3963 __instr_regrd_hrm_exec(p, t, ip);
3970 instr_regrd_mrh_exec(struct rte_swx_pipeline *p)
3972 struct thread *t = &p->threads[p->thread_id];
3973 struct instruction *ip = t->ip;
3976 __instr_regrd_mrh_exec(p, t, ip);
3983 instr_regrd_mrm_exec(struct rte_swx_pipeline *p)
3985 struct thread *t = &p->threads[p->thread_id];
3986 struct instruction *ip = t->ip;
3989 __instr_regrd_mrm_exec(p, t, ip);
3996 instr_regrd_hri_exec(struct rte_swx_pipeline *p)
3998 struct thread *t = &p->threads[p->thread_id];
3999 struct instruction *ip = t->ip;
4002 __instr_regrd_hri_exec(p, t, ip);
4009 instr_regrd_mri_exec(struct rte_swx_pipeline *p)
4011 struct thread *t = &p->threads[p->thread_id];
4012 struct instruction *ip = t->ip;
4015 __instr_regrd_mri_exec(p, t, ip);
4022 instr_regwr_rhh_exec(struct rte_swx_pipeline *p)
4024 struct thread *t = &p->threads[p->thread_id];
4025 struct instruction *ip = t->ip;
4028 __instr_regwr_rhh_exec(p, t, ip);
4035 instr_regwr_rhm_exec(struct rte_swx_pipeline *p)
4037 struct thread *t = &p->threads[p->thread_id];
4038 struct instruction *ip = t->ip;
4041 __instr_regwr_rhm_exec(p, t, ip);
4048 instr_regwr_rmh_exec(struct rte_swx_pipeline *p)
4050 struct thread *t = &p->threads[p->thread_id];
4051 struct instruction *ip = t->ip;
4054 __instr_regwr_rmh_exec(p, t, ip);
4061 instr_regwr_rmm_exec(struct rte_swx_pipeline *p)
4063 struct thread *t = &p->threads[p->thread_id];
4064 struct instruction *ip = t->ip;
4067 __instr_regwr_rmm_exec(p, t, ip);
4074 instr_regwr_rhi_exec(struct rte_swx_pipeline *p)
4076 struct thread *t = &p->threads[p->thread_id];
4077 struct instruction *ip = t->ip;
4080 __instr_regwr_rhi_exec(p, t, ip);
4087 instr_regwr_rmi_exec(struct rte_swx_pipeline *p)
4089 struct thread *t = &p->threads[p->thread_id];
4090 struct instruction *ip = t->ip;
4093 __instr_regwr_rmi_exec(p, t, ip);
4100 instr_regwr_rih_exec(struct rte_swx_pipeline *p)
4102 struct thread *t = &p->threads[p->thread_id];
4103 struct instruction *ip = t->ip;
4106 __instr_regwr_rih_exec(p, t, ip);
4113 instr_regwr_rim_exec(struct rte_swx_pipeline *p)
4115 struct thread *t = &p->threads[p->thread_id];
4116 struct instruction *ip = t->ip;
4119 __instr_regwr_rim_exec(p, t, ip);
4126 instr_regwr_rii_exec(struct rte_swx_pipeline *p)
4128 struct thread *t = &p->threads[p->thread_id];
4129 struct instruction *ip = t->ip;
4132 __instr_regwr_rii_exec(p, t, ip);
4139 instr_regadd_rhh_exec(struct rte_swx_pipeline *p)
4141 struct thread *t = &p->threads[p->thread_id];
4142 struct instruction *ip = t->ip;
4145 __instr_regadd_rhh_exec(p, t, ip);
4152 instr_regadd_rhm_exec(struct rte_swx_pipeline *p)
4154 struct thread *t = &p->threads[p->thread_id];
4155 struct instruction *ip = t->ip;
4158 __instr_regadd_rhm_exec(p, t, ip);
4165 instr_regadd_rmh_exec(struct rte_swx_pipeline *p)
4167 struct thread *t = &p->threads[p->thread_id];
4168 struct instruction *ip = t->ip;
4171 __instr_regadd_rmh_exec(p, t, ip);
4178 instr_regadd_rmm_exec(struct rte_swx_pipeline *p)
4180 struct thread *t = &p->threads[p->thread_id];
4181 struct instruction *ip = t->ip;
4184 __instr_regadd_rmm_exec(p, t, ip);
4191 instr_regadd_rhi_exec(struct rte_swx_pipeline *p)
4193 struct thread *t = &p->threads[p->thread_id];
4194 struct instruction *ip = t->ip;
4197 __instr_regadd_rhi_exec(p, t, ip);
4204 instr_regadd_rmi_exec(struct rte_swx_pipeline *p)
4206 struct thread *t = &p->threads[p->thread_id];
4207 struct instruction *ip = t->ip;
4210 __instr_regadd_rmi_exec(p, t, ip);
4217 instr_regadd_rih_exec(struct rte_swx_pipeline *p)
4219 struct thread *t = &p->threads[p->thread_id];
4220 struct instruction *ip = t->ip;
4223 __instr_regadd_rih_exec(p, t, ip);
4230 instr_regadd_rim_exec(struct rte_swx_pipeline *p)
4232 struct thread *t = &p->threads[p->thread_id];
4233 struct instruction *ip = t->ip;
4236 __instr_regadd_rim_exec(p, t, ip);
4243 instr_regadd_rii_exec(struct rte_swx_pipeline *p)
4245 struct thread *t = &p->threads[p->thread_id];
4246 struct instruction *ip = t->ip;
4249 __instr_regadd_rii_exec(p, t, ip);
4258 static struct metarray *
4259 metarray_find(struct rte_swx_pipeline *p, const char *name);
4262 instr_metprefetch_translate(struct rte_swx_pipeline *p,
4263 struct action *action,
4266 struct instruction *instr,
4267 struct instruction_data *data __rte_unused)
4269 char *metarray = tokens[1], *idx = tokens[2];
4272 uint32_t idx_struct_id, idx_val;
4274 CHECK(n_tokens == 3, EINVAL);
4276 m = metarray_find(p, metarray);
4279 /* METPREFETCH_H, METPREFETCH_M. */
4280 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4282 CHECK(!fidx->var_size, EINVAL);
4284 instr->type = INSTR_METPREFETCH_M;
4286 instr->type = INSTR_METPREFETCH_H;
4288 instr->meter.metarray_id = m->id;
4289 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4290 instr->meter.idx.n_bits = fidx->n_bits;
4291 instr->meter.idx.offset = fidx->offset / 8;
4295 /* METPREFETCH_I. */
4296 idx_val = strtoul(idx, &idx, 0);
4297 CHECK(!idx[0], EINVAL);
4299 instr->type = INSTR_METPREFETCH_I;
4300 instr->meter.metarray_id = m->id;
4301 instr->meter.idx_val = idx_val;
4306 instr_meter_translate(struct rte_swx_pipeline *p,
4307 struct action *action,
4310 struct instruction *instr,
4311 struct instruction_data *data __rte_unused)
4313 char *metarray = tokens[1], *idx = tokens[2], *length = tokens[3];
4314 char *color_in = tokens[4], *color_out = tokens[5];
4316 struct field *fidx, *flength, *fcin, *fcout;
4317 uint32_t idx_struct_id, length_struct_id;
4318 uint32_t color_in_struct_id, color_out_struct_id;
4320 CHECK(n_tokens == 6, EINVAL);
4322 m = metarray_find(p, metarray);
4325 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4327 flength = struct_field_parse(p, action, length, &length_struct_id);
4328 CHECK(flength, EINVAL);
4329 CHECK(!flength->var_size, EINVAL);
4331 fcin = struct_field_parse(p, action, color_in, &color_in_struct_id);
4333 fcout = struct_field_parse(p, NULL, color_out, &color_out_struct_id);
4334 CHECK(fcout, EINVAL);
4335 CHECK(!fcout->var_size, EINVAL);
4337 /* index = HMEFT, length = HMEFT, color_in = MEFT, color_out = MEF. */
4339 CHECK(!fidx->var_size, EINVAL);
4340 CHECK(!fcin->var_size, EINVAL);
4342 instr->type = INSTR_METER_MMM;
4343 if (idx[0] == 'h' && length[0] == 'h')
4344 instr->type = INSTR_METER_HHM;
4345 if (idx[0] == 'h' && length[0] != 'h')
4346 instr->type = INSTR_METER_HMM;
4347 if (idx[0] != 'h' && length[0] == 'h')
4348 instr->type = INSTR_METER_MHM;
4350 instr->meter.metarray_id = m->id;
4352 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4353 instr->meter.idx.n_bits = fidx->n_bits;
4354 instr->meter.idx.offset = fidx->offset / 8;
4356 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4357 instr->meter.length.n_bits = flength->n_bits;
4358 instr->meter.length.offset = flength->offset / 8;
4360 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
4361 instr->meter.color_in.n_bits = fcin->n_bits;
4362 instr->meter.color_in.offset = fcin->offset / 8;
4364 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4365 instr->meter.color_out.n_bits = fcout->n_bits;
4366 instr->meter.color_out.offset = fcout->offset / 8;
4371 /* index = HMEFT, length = HMEFT, color_in = I, color_out = MEF. */
4372 if (fidx && !fcin) {
4373 uint32_t color_in_val;
4375 CHECK(!fidx->var_size, EINVAL);
4377 color_in_val = strtoul(color_in, &color_in, 0);
4378 CHECK(!color_in[0], EINVAL);
4380 instr->type = INSTR_METER_MMI;
4381 if (idx[0] == 'h' && length[0] == 'h')
4382 instr->type = INSTR_METER_HHI;
4383 if (idx[0] == 'h' && length[0] != 'h')
4384 instr->type = INSTR_METER_HMI;
4385 if (idx[0] != 'h' && length[0] == 'h')
4386 instr->type = INSTR_METER_MHI;
4388 instr->meter.metarray_id = m->id;
4390 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
4391 instr->meter.idx.n_bits = fidx->n_bits;
4392 instr->meter.idx.offset = fidx->offset / 8;
4394 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4395 instr->meter.length.n_bits = flength->n_bits;
4396 instr->meter.length.offset = flength->offset / 8;
4398 instr->meter.color_in_val = color_in_val;
4400 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4401 instr->meter.color_out.n_bits = fcout->n_bits;
4402 instr->meter.color_out.offset = fcout->offset / 8;
4407 /* index = I, length = HMEFT, color_in = MEFT, color_out = MEF. */
4408 if (!fidx && fcin) {
4411 idx_val = strtoul(idx, &idx, 0);
4412 CHECK(!idx[0], EINVAL);
4414 CHECK(!fcin->var_size, EINVAL);
4416 instr->type = INSTR_METER_IMM;
4417 if (length[0] == 'h')
4418 instr->type = INSTR_METER_IHM;
4420 instr->meter.metarray_id = m->id;
4422 instr->meter.idx_val = idx_val;
4424 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4425 instr->meter.length.n_bits = flength->n_bits;
4426 instr->meter.length.offset = flength->offset / 8;
4428 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
4429 instr->meter.color_in.n_bits = fcin->n_bits;
4430 instr->meter.color_in.offset = fcin->offset / 8;
4432 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4433 instr->meter.color_out.n_bits = fcout->n_bits;
4434 instr->meter.color_out.offset = fcout->offset / 8;
4439 /* index = I, length = HMEFT, color_in = I, color_out = MEF. */
4440 if (!fidx && !fcin) {
4441 uint32_t idx_val, color_in_val;
4443 idx_val = strtoul(idx, &idx, 0);
4444 CHECK(!idx[0], EINVAL);
4446 color_in_val = strtoul(color_in, &color_in, 0);
4447 CHECK(!color_in[0], EINVAL);
4449 instr->type = INSTR_METER_IMI;
4450 if (length[0] == 'h')
4451 instr->type = INSTR_METER_IHI;
4453 instr->meter.metarray_id = m->id;
4455 instr->meter.idx_val = idx_val;
4457 instr->meter.length.struct_id = (uint8_t)length_struct_id;
4458 instr->meter.length.n_bits = flength->n_bits;
4459 instr->meter.length.offset = flength->offset / 8;
4461 instr->meter.color_in_val = color_in_val;
4463 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
4464 instr->meter.color_out.n_bits = fcout->n_bits;
4465 instr->meter.color_out.offset = fcout->offset / 8;
4473 static inline struct meter *
4474 instr_meter_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
4476 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
4478 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
4479 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
4480 uint64_t idx64 = *idx64_ptr;
4481 uint64_t idx64_mask = UINT64_MAX >> (64 - (ip)->meter.idx.n_bits);
4482 uint64_t idx = idx64 & idx64_mask & r->size_mask;
4484 return &r->metarray[idx];
4487 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4489 static inline struct meter *
4490 instr_meter_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
4492 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
4494 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
4495 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
4496 uint64_t idx64 = *idx64_ptr;
4497 uint64_t idx = (ntoh64(idx64) >> (64 - ip->meter.idx.n_bits)) & r->size_mask;
4499 return &r->metarray[idx];
4504 #define instr_meter_idx_nbo instr_meter_idx_hbo
4508 static inline struct meter *
4509 instr_meter_idx_imm(struct rte_swx_pipeline *p, struct instruction *ip)
4511 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
4513 uint64_t idx = ip->meter.idx_val & r->size_mask;
4515 return &r->metarray[idx];
4518 static inline uint32_t
4519 instr_meter_length_hbo(struct thread *t, struct instruction *ip)
4521 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
4522 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
4523 uint64_t src64 = *src64_ptr;
4524 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->meter.length.n_bits);
4525 uint64_t src = src64 & src64_mask;
4527 return (uint32_t)src;
4530 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4532 static inline uint32_t
4533 instr_meter_length_nbo(struct thread *t, struct instruction *ip)
4535 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
4536 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
4537 uint64_t src64 = *src64_ptr;
4538 uint64_t src = ntoh64(src64) >> (64 - ip->meter.length.n_bits);
4540 return (uint32_t)src;
4545 #define instr_meter_length_nbo instr_meter_length_hbo
4549 static inline enum rte_color
4550 instr_meter_color_in_hbo(struct thread *t, struct instruction *ip)
4552 uint8_t *src_struct = t->structs[ip->meter.color_in.struct_id];
4553 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.color_in.offset];
4554 uint64_t src64 = *src64_ptr;
4555 uint64_t src64_mask = UINT64_MAX >> (64 - ip->meter.color_in.n_bits);
4556 uint64_t src = src64 & src64_mask;
4558 return (enum rte_color)src;
4562 instr_meter_color_out_hbo_set(struct thread *t, struct instruction *ip, enum rte_color color_out)
4564 uint8_t *dst_struct = t->structs[ip->meter.color_out.struct_id];
4565 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->meter.color_out.offset];
4566 uint64_t dst64 = *dst64_ptr;
4567 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->meter.color_out.n_bits);
4569 uint64_t src = (uint64_t)color_out;
4571 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
4575 instr_metprefetch_h_exec(struct rte_swx_pipeline *p)
4577 struct thread *t = &p->threads[p->thread_id];
4578 struct instruction *ip = t->ip;
4581 TRACE("[Thread %2u] metprefetch (h)\n", p->thread_id);
4584 m = instr_meter_idx_nbo(p, t, ip);
4592 instr_metprefetch_m_exec(struct rte_swx_pipeline *p)
4594 struct thread *t = &p->threads[p->thread_id];
4595 struct instruction *ip = t->ip;
4598 TRACE("[Thread %2u] metprefetch (m)\n", p->thread_id);
4601 m = instr_meter_idx_hbo(p, t, ip);
4609 instr_metprefetch_i_exec(struct rte_swx_pipeline *p)
4611 struct thread *t = &p->threads[p->thread_id];
4612 struct instruction *ip = t->ip;
4615 TRACE("[Thread %2u] metprefetch (i)\n", p->thread_id);
4618 m = instr_meter_idx_imm(p, ip);
4626 instr_meter_hhm_exec(struct rte_swx_pipeline *p)
4628 struct thread *t = &p->threads[p->thread_id];
4629 struct instruction *ip = t->ip;
4631 uint64_t time, n_pkts, n_bytes;
4633 enum rte_color color_in, color_out;
4635 TRACE("[Thread %2u] meter (hhm)\n", p->thread_id);
4638 m = instr_meter_idx_nbo(p, t, ip);
4639 rte_prefetch0(m->n_pkts);
4640 time = rte_get_tsc_cycles();
4641 length = instr_meter_length_nbo(t, ip);
4642 color_in = instr_meter_color_in_hbo(t, ip);
4644 color_out = rte_meter_trtcm_color_aware_check(&m->m,
4645 &m->profile->profile,
4650 color_out &= m->color_mask;
4652 n_pkts = m->n_pkts[color_out];
4653 n_bytes = m->n_bytes[color_out];
4655 instr_meter_color_out_hbo_set(t, ip, color_out);
4657 m->n_pkts[color_out] = n_pkts + 1;
4658 m->n_bytes[color_out] = n_bytes + length;
4665 instr_meter_hhi_exec(struct rte_swx_pipeline *p)
4667 struct thread *t = &p->threads[p->thread_id];
4668 struct instruction *ip = t->ip;
4670 uint64_t time, n_pkts, n_bytes;
4672 enum rte_color color_in, color_out;
4674 TRACE("[Thread %2u] meter (hhi)\n", p->thread_id);
4677 m = instr_meter_idx_nbo(p, t, ip);
4678 rte_prefetch0(m->n_pkts);
4679 time = rte_get_tsc_cycles();
4680 length = instr_meter_length_nbo(t, ip);
4681 color_in = (enum rte_color)ip->meter.color_in_val;
4683 color_out = rte_meter_trtcm_color_aware_check(&m->m,
4684 &m->profile->profile,
4689 color_out &= m->color_mask;
4691 n_pkts = m->n_pkts[color_out];
4692 n_bytes = m->n_bytes[color_out];
4694 instr_meter_color_out_hbo_set(t, ip, color_out);
4696 m->n_pkts[color_out] = n_pkts + 1;
4697 m->n_bytes[color_out] = n_bytes + length;
4704 instr_meter_hmm_exec(struct rte_swx_pipeline *p)
4706 struct thread *t = &p->threads[p->thread_id];
4707 struct instruction *ip = t->ip;
4709 uint64_t time, n_pkts, n_bytes;
4711 enum rte_color color_in, color_out;
4713 TRACE("[Thread %2u] meter (hmm)\n", p->thread_id);
4716 m = instr_meter_idx_nbo(p, t, ip);
4717 rte_prefetch0(m->n_pkts);
4718 time = rte_get_tsc_cycles();
4719 length = instr_meter_length_hbo(t, ip);
4720 color_in = instr_meter_color_in_hbo(t, ip);
4722 color_out = rte_meter_trtcm_color_aware_check(&m->m,
4723 &m->profile->profile,
4728 color_out &= m->color_mask;
4730 n_pkts = m->n_pkts[color_out];
4731 n_bytes = m->n_bytes[color_out];
4733 instr_meter_color_out_hbo_set(t, ip, color_out);
4735 m->n_pkts[color_out] = n_pkts + 1;
4736 m->n_bytes[color_out] = n_bytes + length;
4742 instr_meter_hmi_exec(struct rte_swx_pipeline *p)
4744 struct thread *t = &p->threads[p->thread_id];
4745 struct instruction *ip = t->ip;
4747 uint64_t time, n_pkts, n_bytes;
4749 enum rte_color color_in, color_out;
4751 TRACE("[Thread %2u] meter (hmi)\n", p->thread_id);
4754 m = instr_meter_idx_nbo(p, t, ip);
4755 rte_prefetch0(m->n_pkts);
4756 time = rte_get_tsc_cycles();
4757 length = instr_meter_length_hbo(t, ip);
4758 color_in = (enum rte_color)ip->meter.color_in_val;
4760 color_out = rte_meter_trtcm_color_aware_check(&m->m,
4761 &m->profile->profile,
4766 color_out &= m->color_mask;
4768 n_pkts = m->n_pkts[color_out];
4769 n_bytes = m->n_bytes[color_out];
4771 instr_meter_color_out_hbo_set(t, ip, color_out);
4773 m->n_pkts[color_out] = n_pkts + 1;
4774 m->n_bytes[color_out] = n_bytes + length;
4781 instr_meter_mhm_exec(struct rte_swx_pipeline *p)
4783 struct thread *t = &p->threads[p->thread_id];
4784 struct instruction *ip = t->ip;
4786 uint64_t time, n_pkts, n_bytes;
4788 enum rte_color color_in, color_out;
4790 TRACE("[Thread %2u] meter (mhm)\n", p->thread_id);
4793 m = instr_meter_idx_hbo(p, t, ip);
4794 rte_prefetch0(m->n_pkts);
4795 time = rte_get_tsc_cycles();
4796 length = instr_meter_length_nbo(t, ip);
4797 color_in = instr_meter_color_in_hbo(t, ip);
4799 color_out = rte_meter_trtcm_color_aware_check(&m->m,
4800 &m->profile->profile,
4805 color_out &= m->color_mask;
4807 n_pkts = m->n_pkts[color_out];
4808 n_bytes = m->n_bytes[color_out];
4810 instr_meter_color_out_hbo_set(t, ip, color_out);
4812 m->n_pkts[color_out] = n_pkts + 1;
4813 m->n_bytes[color_out] = n_bytes + length;
4820 instr_meter_mhi_exec(struct rte_swx_pipeline *p)
4822 struct thread *t = &p->threads[p->thread_id];
4823 struct instruction *ip = t->ip;
4825 uint64_t time, n_pkts, n_bytes;
4827 enum rte_color color_in, color_out;
4829 TRACE("[Thread %2u] meter (mhi)\n", p->thread_id);
4832 m = instr_meter_idx_hbo(p, t, ip);
4833 rte_prefetch0(m->n_pkts);
4834 time = rte_get_tsc_cycles();
4835 length = instr_meter_length_nbo(t, ip);
4836 color_in = (enum rte_color)ip->meter.color_in_val;
4838 color_out = rte_meter_trtcm_color_aware_check(&m->m,
4839 &m->profile->profile,
4844 color_out &= m->color_mask;
4846 n_pkts = m->n_pkts[color_out];
4847 n_bytes = m->n_bytes[color_out];
4849 instr_meter_color_out_hbo_set(t, ip, color_out);
4851 m->n_pkts[color_out] = n_pkts + 1;
4852 m->n_bytes[color_out] = n_bytes + length;
4859 instr_meter_mmm_exec(struct rte_swx_pipeline *p)
4861 struct thread *t = &p->threads[p->thread_id];
4862 struct instruction *ip = t->ip;
4864 uint64_t time, n_pkts, n_bytes;
4866 enum rte_color color_in, color_out;
4868 TRACE("[Thread %2u] meter (mmm)\n", p->thread_id);
4871 m = instr_meter_idx_hbo(p, t, ip);
4872 rte_prefetch0(m->n_pkts);
4873 time = rte_get_tsc_cycles();
4874 length = instr_meter_length_hbo(t, ip);
4875 color_in = instr_meter_color_in_hbo(t, ip);
4877 color_out = rte_meter_trtcm_color_aware_check(&m->m,
4878 &m->profile->profile,
4883 color_out &= m->color_mask;
4885 n_pkts = m->n_pkts[color_out];
4886 n_bytes = m->n_bytes[color_out];
4888 instr_meter_color_out_hbo_set(t, ip, color_out);
4890 m->n_pkts[color_out] = n_pkts + 1;
4891 m->n_bytes[color_out] = n_bytes + length;
4898 instr_meter_mmi_exec(struct rte_swx_pipeline *p)
4900 struct thread *t = &p->threads[p->thread_id];
4901 struct instruction *ip = t->ip;
4903 uint64_t time, n_pkts, n_bytes;
4905 enum rte_color color_in, color_out;
4907 TRACE("[Thread %2u] meter (mmi)\n", p->thread_id);
4910 m = instr_meter_idx_hbo(p, t, ip);
4911 rte_prefetch0(m->n_pkts);
4912 time = rte_get_tsc_cycles();
4913 length = instr_meter_length_hbo(t, ip);
4914 color_in = (enum rte_color)ip->meter.color_in_val;
4916 color_out = rte_meter_trtcm_color_aware_check(&m->m,
4917 &m->profile->profile,
4922 color_out &= m->color_mask;
4924 n_pkts = m->n_pkts[color_out];
4925 n_bytes = m->n_bytes[color_out];
4927 instr_meter_color_out_hbo_set(t, ip, color_out);
4929 m->n_pkts[color_out] = n_pkts + 1;
4930 m->n_bytes[color_out] = n_bytes + length;
4937 instr_meter_ihm_exec(struct rte_swx_pipeline *p)
4939 struct thread *t = &p->threads[p->thread_id];
4940 struct instruction *ip = t->ip;
4942 uint64_t time, n_pkts, n_bytes;
4944 enum rte_color color_in, color_out;
4946 TRACE("[Thread %2u] meter (ihm)\n", p->thread_id);
4949 m = instr_meter_idx_imm(p, ip);
4950 rte_prefetch0(m->n_pkts);
4951 time = rte_get_tsc_cycles();
4952 length = instr_meter_length_nbo(t, ip);
4953 color_in = instr_meter_color_in_hbo(t, ip);
4955 color_out = rte_meter_trtcm_color_aware_check(&m->m,
4956 &m->profile->profile,
4961 color_out &= m->color_mask;
4963 n_pkts = m->n_pkts[color_out];
4964 n_bytes = m->n_bytes[color_out];
4966 instr_meter_color_out_hbo_set(t, ip, color_out);
4968 m->n_pkts[color_out] = n_pkts + 1;
4969 m->n_bytes[color_out] = n_bytes + length;
4976 instr_meter_ihi_exec(struct rte_swx_pipeline *p)
4978 struct thread *t = &p->threads[p->thread_id];
4979 struct instruction *ip = t->ip;
4981 uint64_t time, n_pkts, n_bytes;
4983 enum rte_color color_in, color_out;
4985 TRACE("[Thread %2u] meter (ihi)\n", p->thread_id);
4988 m = instr_meter_idx_imm(p, ip);
4989 rte_prefetch0(m->n_pkts);
4990 time = rte_get_tsc_cycles();
4991 length = instr_meter_length_nbo(t, ip);
4992 color_in = (enum rte_color)ip->meter.color_in_val;
4994 color_out = rte_meter_trtcm_color_aware_check(&m->m,
4995 &m->profile->profile,
5000 color_out &= m->color_mask;
5002 n_pkts = m->n_pkts[color_out];
5003 n_bytes = m->n_bytes[color_out];
5005 instr_meter_color_out_hbo_set(t, ip, color_out);
5007 m->n_pkts[color_out] = n_pkts + 1;
5008 m->n_bytes[color_out] = n_bytes + length;
5015 instr_meter_imm_exec(struct rte_swx_pipeline *p)
5017 struct thread *t = &p->threads[p->thread_id];
5018 struct instruction *ip = t->ip;
5020 uint64_t time, n_pkts, n_bytes;
5022 enum rte_color color_in, color_out;
5024 TRACE("[Thread %2u] meter (imm)\n", p->thread_id);
5027 m = instr_meter_idx_imm(p, ip);
5028 rte_prefetch0(m->n_pkts);
5029 time = rte_get_tsc_cycles();
5030 length = instr_meter_length_hbo(t, ip);
5031 color_in = instr_meter_color_in_hbo(t, ip);
5033 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5034 &m->profile->profile,
5039 color_out &= m->color_mask;
5041 n_pkts = m->n_pkts[color_out];
5042 n_bytes = m->n_bytes[color_out];
5044 instr_meter_color_out_hbo_set(t, ip, color_out);
5046 m->n_pkts[color_out] = n_pkts + 1;
5047 m->n_bytes[color_out] = n_bytes + length;
5053 instr_meter_imi_exec(struct rte_swx_pipeline *p)
5055 struct thread *t = &p->threads[p->thread_id];
5056 struct instruction *ip = t->ip;
5058 uint64_t time, n_pkts, n_bytes;
5060 enum rte_color color_in, color_out;
5062 TRACE("[Thread %2u] meter (imi)\n", p->thread_id);
5065 m = instr_meter_idx_imm(p, ip);
5066 rte_prefetch0(m->n_pkts);
5067 time = rte_get_tsc_cycles();
5068 length = instr_meter_length_hbo(t, ip);
5069 color_in = (enum rte_color)ip->meter.color_in_val;
5071 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5072 &m->profile->profile,
5077 color_out &= m->color_mask;
5079 n_pkts = m->n_pkts[color_out];
5080 n_bytes = m->n_bytes[color_out];
5082 instr_meter_color_out_hbo_set(t, ip, color_out);
5084 m->n_pkts[color_out] = n_pkts + 1;
5085 m->n_bytes[color_out] = n_bytes + length;
5095 instr_jmp_translate(struct rte_swx_pipeline *p __rte_unused,
5096 struct action *action __rte_unused,
5099 struct instruction *instr,
5100 struct instruction_data *data)
5102 CHECK(n_tokens == 2, EINVAL);
5104 strcpy(data->jmp_label, tokens[1]);
5106 instr->type = INSTR_JMP;
5107 instr->jmp.ip = NULL; /* Resolved later. */
5112 instr_jmp_valid_translate(struct rte_swx_pipeline *p,
5113 struct action *action __rte_unused,
5116 struct instruction *instr,
5117 struct instruction_data *data)
5121 CHECK(n_tokens == 3, EINVAL);
5123 strcpy(data->jmp_label, tokens[1]);
5125 h = header_parse(p, tokens[2]);
5128 instr->type = INSTR_JMP_VALID;
5129 instr->jmp.ip = NULL; /* Resolved later. */
5130 instr->jmp.header_id = h->id;
5135 instr_jmp_invalid_translate(struct rte_swx_pipeline *p,
5136 struct action *action __rte_unused,
5139 struct instruction *instr,
5140 struct instruction_data *data)
5144 CHECK(n_tokens == 3, EINVAL);
5146 strcpy(data->jmp_label, tokens[1]);
5148 h = header_parse(p, tokens[2]);
5151 instr->type = INSTR_JMP_INVALID;
5152 instr->jmp.ip = NULL; /* Resolved later. */
5153 instr->jmp.header_id = h->id;
5158 instr_jmp_hit_translate(struct rte_swx_pipeline *p __rte_unused,
5159 struct action *action,
5162 struct instruction *instr,
5163 struct instruction_data *data)
5165 CHECK(!action, EINVAL);
5166 CHECK(n_tokens == 2, EINVAL);
5168 strcpy(data->jmp_label, tokens[1]);
5170 instr->type = INSTR_JMP_HIT;
5171 instr->jmp.ip = NULL; /* Resolved later. */
5176 instr_jmp_miss_translate(struct rte_swx_pipeline *p __rte_unused,
5177 struct action *action,
5180 struct instruction *instr,
5181 struct instruction_data *data)
5183 CHECK(!action, EINVAL);
5184 CHECK(n_tokens == 2, EINVAL);
5186 strcpy(data->jmp_label, tokens[1]);
5188 instr->type = INSTR_JMP_MISS;
5189 instr->jmp.ip = NULL; /* Resolved later. */
5194 instr_jmp_action_hit_translate(struct rte_swx_pipeline *p,
5195 struct action *action,
5198 struct instruction *instr,
5199 struct instruction_data *data)
5203 CHECK(!action, EINVAL);
5204 CHECK(n_tokens == 3, EINVAL);
5206 strcpy(data->jmp_label, tokens[1]);
5208 a = action_find(p, tokens[2]);
5211 instr->type = INSTR_JMP_ACTION_HIT;
5212 instr->jmp.ip = NULL; /* Resolved later. */
5213 instr->jmp.action_id = a->id;
5218 instr_jmp_action_miss_translate(struct rte_swx_pipeline *p,
5219 struct action *action,
5222 struct instruction *instr,
5223 struct instruction_data *data)
5227 CHECK(!action, EINVAL);
5228 CHECK(n_tokens == 3, EINVAL);
5230 strcpy(data->jmp_label, tokens[1]);
5232 a = action_find(p, tokens[2]);
5235 instr->type = INSTR_JMP_ACTION_MISS;
5236 instr->jmp.ip = NULL; /* Resolved later. */
5237 instr->jmp.action_id = a->id;
5242 instr_jmp_eq_translate(struct rte_swx_pipeline *p,
5243 struct action *action,
5246 struct instruction *instr,
5247 struct instruction_data *data)
5249 char *a = tokens[2], *b = tokens[3];
5250 struct field *fa, *fb;
5252 uint32_t a_struct_id, b_struct_id;
5254 CHECK(n_tokens == 4, EINVAL);
5256 strcpy(data->jmp_label, tokens[1]);
5258 fa = struct_field_parse(p, action, a, &a_struct_id);
5260 CHECK(!fa->var_size, EINVAL);
5262 /* JMP_EQ, JMP_EQ_MH, JMP_EQ_HM, JMP_EQ_HH. */
5263 fb = struct_field_parse(p, action, b, &b_struct_id);
5265 CHECK(!fb->var_size, EINVAL);
5267 instr->type = INSTR_JMP_EQ;
5268 if (a[0] != 'h' && b[0] == 'h')
5269 instr->type = INSTR_JMP_EQ_MH;
5270 if (a[0] == 'h' && b[0] != 'h')
5271 instr->type = INSTR_JMP_EQ_HM;
5272 if (a[0] == 'h' && b[0] == 'h')
5273 instr->type = INSTR_JMP_EQ_HH;
5274 instr->jmp.ip = NULL; /* Resolved later. */
5276 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5277 instr->jmp.a.n_bits = fa->n_bits;
5278 instr->jmp.a.offset = fa->offset / 8;
5279 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5280 instr->jmp.b.n_bits = fb->n_bits;
5281 instr->jmp.b.offset = fb->offset / 8;
5286 b_val = strtoull(b, &b, 0);
5287 CHECK(!b[0], EINVAL);
5290 b_val = hton64(b_val) >> (64 - fa->n_bits);
5292 instr->type = INSTR_JMP_EQ_I;
5293 instr->jmp.ip = NULL; /* Resolved later. */
5294 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5295 instr->jmp.a.n_bits = fa->n_bits;
5296 instr->jmp.a.offset = fa->offset / 8;
5297 instr->jmp.b_val = b_val;
5302 instr_jmp_neq_translate(struct rte_swx_pipeline *p,
5303 struct action *action,
5306 struct instruction *instr,
5307 struct instruction_data *data)
5309 char *a = tokens[2], *b = tokens[3];
5310 struct field *fa, *fb;
5312 uint32_t a_struct_id, b_struct_id;
5314 CHECK(n_tokens == 4, EINVAL);
5316 strcpy(data->jmp_label, tokens[1]);
5318 fa = struct_field_parse(p, action, a, &a_struct_id);
5320 CHECK(!fa->var_size, EINVAL);
5322 /* JMP_NEQ, JMP_NEQ_MH, JMP_NEQ_HM, JMP_NEQ_HH. */
5323 fb = struct_field_parse(p, action, b, &b_struct_id);
5325 CHECK(!fb->var_size, EINVAL);
5327 instr->type = INSTR_JMP_NEQ;
5328 if (a[0] != 'h' && b[0] == 'h')
5329 instr->type = INSTR_JMP_NEQ_MH;
5330 if (a[0] == 'h' && b[0] != 'h')
5331 instr->type = INSTR_JMP_NEQ_HM;
5332 if (a[0] == 'h' && b[0] == 'h')
5333 instr->type = INSTR_JMP_NEQ_HH;
5334 instr->jmp.ip = NULL; /* Resolved later. */
5336 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5337 instr->jmp.a.n_bits = fa->n_bits;
5338 instr->jmp.a.offset = fa->offset / 8;
5339 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5340 instr->jmp.b.n_bits = fb->n_bits;
5341 instr->jmp.b.offset = fb->offset / 8;
5346 b_val = strtoull(b, &b, 0);
5347 CHECK(!b[0], EINVAL);
5350 b_val = hton64(b_val) >> (64 - fa->n_bits);
5352 instr->type = INSTR_JMP_NEQ_I;
5353 instr->jmp.ip = NULL; /* Resolved later. */
5354 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5355 instr->jmp.a.n_bits = fa->n_bits;
5356 instr->jmp.a.offset = fa->offset / 8;
5357 instr->jmp.b_val = b_val;
5362 instr_jmp_lt_translate(struct rte_swx_pipeline *p,
5363 struct action *action,
5366 struct instruction *instr,
5367 struct instruction_data *data)
5369 char *a = tokens[2], *b = tokens[3];
5370 struct field *fa, *fb;
5372 uint32_t a_struct_id, b_struct_id;
5374 CHECK(n_tokens == 4, EINVAL);
5376 strcpy(data->jmp_label, tokens[1]);
5378 fa = struct_field_parse(p, action, a, &a_struct_id);
5380 CHECK(!fa->var_size, EINVAL);
5382 /* JMP_LT, JMP_LT_MH, JMP_LT_HM, JMP_LT_HH. */
5383 fb = struct_field_parse(p, action, b, &b_struct_id);
5385 CHECK(!fb->var_size, EINVAL);
5387 instr->type = INSTR_JMP_LT;
5388 if (a[0] == 'h' && b[0] != 'h')
5389 instr->type = INSTR_JMP_LT_HM;
5390 if (a[0] != 'h' && b[0] == 'h')
5391 instr->type = INSTR_JMP_LT_MH;
5392 if (a[0] == 'h' && b[0] == 'h')
5393 instr->type = INSTR_JMP_LT_HH;
5394 instr->jmp.ip = NULL; /* Resolved later. */
5396 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5397 instr->jmp.a.n_bits = fa->n_bits;
5398 instr->jmp.a.offset = fa->offset / 8;
5399 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5400 instr->jmp.b.n_bits = fb->n_bits;
5401 instr->jmp.b.offset = fb->offset / 8;
5405 /* JMP_LT_MI, JMP_LT_HI. */
5406 b_val = strtoull(b, &b, 0);
5407 CHECK(!b[0], EINVAL);
5409 instr->type = INSTR_JMP_LT_MI;
5411 instr->type = INSTR_JMP_LT_HI;
5412 instr->jmp.ip = NULL; /* Resolved later. */
5414 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5415 instr->jmp.a.n_bits = fa->n_bits;
5416 instr->jmp.a.offset = fa->offset / 8;
5417 instr->jmp.b_val = b_val;
5422 instr_jmp_gt_translate(struct rte_swx_pipeline *p,
5423 struct action *action,
5426 struct instruction *instr,
5427 struct instruction_data *data)
5429 char *a = tokens[2], *b = tokens[3];
5430 struct field *fa, *fb;
5432 uint32_t a_struct_id, b_struct_id;
5434 CHECK(n_tokens == 4, EINVAL);
5436 strcpy(data->jmp_label, tokens[1]);
5438 fa = struct_field_parse(p, action, a, &a_struct_id);
5440 CHECK(!fa->var_size, EINVAL);
5442 /* JMP_GT, JMP_GT_MH, JMP_GT_HM, JMP_GT_HH. */
5443 fb = struct_field_parse(p, action, b, &b_struct_id);
5445 CHECK(!fb->var_size, EINVAL);
5447 instr->type = INSTR_JMP_GT;
5448 if (a[0] == 'h' && b[0] != 'h')
5449 instr->type = INSTR_JMP_GT_HM;
5450 if (a[0] != 'h' && b[0] == 'h')
5451 instr->type = INSTR_JMP_GT_MH;
5452 if (a[0] == 'h' && b[0] == 'h')
5453 instr->type = INSTR_JMP_GT_HH;
5454 instr->jmp.ip = NULL; /* Resolved later. */
5456 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5457 instr->jmp.a.n_bits = fa->n_bits;
5458 instr->jmp.a.offset = fa->offset / 8;
5459 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
5460 instr->jmp.b.n_bits = fb->n_bits;
5461 instr->jmp.b.offset = fb->offset / 8;
5465 /* JMP_GT_MI, JMP_GT_HI. */
5466 b_val = strtoull(b, &b, 0);
5467 CHECK(!b[0], EINVAL);
5469 instr->type = INSTR_JMP_GT_MI;
5471 instr->type = INSTR_JMP_GT_HI;
5472 instr->jmp.ip = NULL; /* Resolved later. */
5474 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
5475 instr->jmp.a.n_bits = fa->n_bits;
5476 instr->jmp.a.offset = fa->offset / 8;
5477 instr->jmp.b_val = b_val;
5482 instr_jmp_exec(struct rte_swx_pipeline *p)
5484 struct thread *t = &p->threads[p->thread_id];
5485 struct instruction *ip = t->ip;
5487 TRACE("[Thread %2u] jmp\n", p->thread_id);
5489 thread_ip_set(t, ip->jmp.ip);
5493 instr_jmp_valid_exec(struct rte_swx_pipeline *p)
5495 struct thread *t = &p->threads[p->thread_id];
5496 struct instruction *ip = t->ip;
5497 uint32_t header_id = ip->jmp.header_id;
5499 TRACE("[Thread %2u] jmpv\n", p->thread_id);
5501 t->ip = HEADER_VALID(t, header_id) ? ip->jmp.ip : (t->ip + 1);
5505 instr_jmp_invalid_exec(struct rte_swx_pipeline *p)
5507 struct thread *t = &p->threads[p->thread_id];
5508 struct instruction *ip = t->ip;
5509 uint32_t header_id = ip->jmp.header_id;
5511 TRACE("[Thread %2u] jmpnv\n", p->thread_id);
5513 t->ip = HEADER_VALID(t, header_id) ? (t->ip + 1) : ip->jmp.ip;
5517 instr_jmp_hit_exec(struct rte_swx_pipeline *p)
5519 struct thread *t = &p->threads[p->thread_id];
5520 struct instruction *ip = t->ip;
5521 struct instruction *ip_next[] = {t->ip + 1, ip->jmp.ip};
5523 TRACE("[Thread %2u] jmph\n", p->thread_id);
5525 t->ip = ip_next[t->hit];
5529 instr_jmp_miss_exec(struct rte_swx_pipeline *p)
5531 struct thread *t = &p->threads[p->thread_id];
5532 struct instruction *ip = t->ip;
5533 struct instruction *ip_next[] = {ip->jmp.ip, t->ip + 1};
5535 TRACE("[Thread %2u] jmpnh\n", p->thread_id);
5537 t->ip = ip_next[t->hit];
5541 instr_jmp_action_hit_exec(struct rte_swx_pipeline *p)
5543 struct thread *t = &p->threads[p->thread_id];
5544 struct instruction *ip = t->ip;
5546 TRACE("[Thread %2u] jmpa\n", p->thread_id);
5548 t->ip = (ip->jmp.action_id == t->action_id) ? ip->jmp.ip : (t->ip + 1);
5552 instr_jmp_action_miss_exec(struct rte_swx_pipeline *p)
5554 struct thread *t = &p->threads[p->thread_id];
5555 struct instruction *ip = t->ip;
5557 TRACE("[Thread %2u] jmpna\n", p->thread_id);
5559 t->ip = (ip->jmp.action_id == t->action_id) ? (t->ip + 1) : ip->jmp.ip;
5563 instr_jmp_eq_exec(struct rte_swx_pipeline *p)
5565 struct thread *t = &p->threads[p->thread_id];
5566 struct instruction *ip = t->ip;
5568 TRACE("[Thread %2u] jmpeq\n", p->thread_id);
5574 instr_jmp_eq_mh_exec(struct rte_swx_pipeline *p)
5576 struct thread *t = &p->threads[p->thread_id];
5577 struct instruction *ip = t->ip;
5579 TRACE("[Thread %2u] jmpeq (mh)\n", p->thread_id);
5581 JMP_CMP_MH(t, ip, ==);
5585 instr_jmp_eq_hm_exec(struct rte_swx_pipeline *p)
5587 struct thread *t = &p->threads[p->thread_id];
5588 struct instruction *ip = t->ip;
5590 TRACE("[Thread %2u] jmpeq (hm)\n", p->thread_id);
5592 JMP_CMP_HM(t, ip, ==);
5596 instr_jmp_eq_hh_exec(struct rte_swx_pipeline *p)
5598 struct thread *t = &p->threads[p->thread_id];
5599 struct instruction *ip = t->ip;
5601 TRACE("[Thread %2u] jmpeq (hh)\n", p->thread_id);
5603 JMP_CMP_HH_FAST(t, ip, ==);
5607 instr_jmp_eq_i_exec(struct rte_swx_pipeline *p)
5609 struct thread *t = &p->threads[p->thread_id];
5610 struct instruction *ip = t->ip;
5612 TRACE("[Thread %2u] jmpeq (i)\n", p->thread_id);
5614 JMP_CMP_I(t, ip, ==);
5618 instr_jmp_neq_exec(struct rte_swx_pipeline *p)
5620 struct thread *t = &p->threads[p->thread_id];
5621 struct instruction *ip = t->ip;
5623 TRACE("[Thread %2u] jmpneq\n", p->thread_id);
5629 instr_jmp_neq_mh_exec(struct rte_swx_pipeline *p)
5631 struct thread *t = &p->threads[p->thread_id];
5632 struct instruction *ip = t->ip;
5634 TRACE("[Thread %2u] jmpneq (mh)\n", p->thread_id);
5636 JMP_CMP_MH(t, ip, !=);
5640 instr_jmp_neq_hm_exec(struct rte_swx_pipeline *p)
5642 struct thread *t = &p->threads[p->thread_id];
5643 struct instruction *ip = t->ip;
5645 TRACE("[Thread %2u] jmpneq (hm)\n", p->thread_id);
5647 JMP_CMP_HM(t, ip, !=);
5651 instr_jmp_neq_hh_exec(struct rte_swx_pipeline *p)
5653 struct thread *t = &p->threads[p->thread_id];
5654 struct instruction *ip = t->ip;
5656 TRACE("[Thread %2u] jmpneq (hh)\n", p->thread_id);
5658 JMP_CMP_HH_FAST(t, ip, !=);
5662 instr_jmp_neq_i_exec(struct rte_swx_pipeline *p)
5664 struct thread *t = &p->threads[p->thread_id];
5665 struct instruction *ip = t->ip;
5667 TRACE("[Thread %2u] jmpneq (i)\n", p->thread_id);
5669 JMP_CMP_I(t, ip, !=);
5673 instr_jmp_lt_exec(struct rte_swx_pipeline *p)
5675 struct thread *t = &p->threads[p->thread_id];
5676 struct instruction *ip = t->ip;
5678 TRACE("[Thread %2u] jmplt\n", p->thread_id);
5684 instr_jmp_lt_mh_exec(struct rte_swx_pipeline *p)
5686 struct thread *t = &p->threads[p->thread_id];
5687 struct instruction *ip = t->ip;
5689 TRACE("[Thread %2u] jmplt (mh)\n", p->thread_id);
5691 JMP_CMP_MH(t, ip, <);
5695 instr_jmp_lt_hm_exec(struct rte_swx_pipeline *p)
5697 struct thread *t = &p->threads[p->thread_id];
5698 struct instruction *ip = t->ip;
5700 TRACE("[Thread %2u] jmplt (hm)\n", p->thread_id);
5702 JMP_CMP_HM(t, ip, <);
5706 instr_jmp_lt_hh_exec(struct rte_swx_pipeline *p)
5708 struct thread *t = &p->threads[p->thread_id];
5709 struct instruction *ip = t->ip;
5711 TRACE("[Thread %2u] jmplt (hh)\n", p->thread_id);
5713 JMP_CMP_HH(t, ip, <);
5717 instr_jmp_lt_mi_exec(struct rte_swx_pipeline *p)
5719 struct thread *t = &p->threads[p->thread_id];
5720 struct instruction *ip = t->ip;
5722 TRACE("[Thread %2u] jmplt (mi)\n", p->thread_id);
5724 JMP_CMP_MI(t, ip, <);
5728 instr_jmp_lt_hi_exec(struct rte_swx_pipeline *p)
5730 struct thread *t = &p->threads[p->thread_id];
5731 struct instruction *ip = t->ip;
5733 TRACE("[Thread %2u] jmplt (hi)\n", p->thread_id);
5735 JMP_CMP_HI(t, ip, <);
5739 instr_jmp_gt_exec(struct rte_swx_pipeline *p)
5741 struct thread *t = &p->threads[p->thread_id];
5742 struct instruction *ip = t->ip;
5744 TRACE("[Thread %2u] jmpgt\n", p->thread_id);
5750 instr_jmp_gt_mh_exec(struct rte_swx_pipeline *p)
5752 struct thread *t = &p->threads[p->thread_id];
5753 struct instruction *ip = t->ip;
5755 TRACE("[Thread %2u] jmpgt (mh)\n", p->thread_id);
5757 JMP_CMP_MH(t, ip, >);
5761 instr_jmp_gt_hm_exec(struct rte_swx_pipeline *p)
5763 struct thread *t = &p->threads[p->thread_id];
5764 struct instruction *ip = t->ip;
5766 TRACE("[Thread %2u] jmpgt (hm)\n", p->thread_id);
5768 JMP_CMP_HM(t, ip, >);
5772 instr_jmp_gt_hh_exec(struct rte_swx_pipeline *p)
5774 struct thread *t = &p->threads[p->thread_id];
5775 struct instruction *ip = t->ip;
5777 TRACE("[Thread %2u] jmpgt (hh)\n", p->thread_id);
5779 JMP_CMP_HH(t, ip, >);
5783 instr_jmp_gt_mi_exec(struct rte_swx_pipeline *p)
5785 struct thread *t = &p->threads[p->thread_id];
5786 struct instruction *ip = t->ip;
5788 TRACE("[Thread %2u] jmpgt (mi)\n", p->thread_id);
5790 JMP_CMP_MI(t, ip, >);
5794 instr_jmp_gt_hi_exec(struct rte_swx_pipeline *p)
5796 struct thread *t = &p->threads[p->thread_id];
5797 struct instruction *ip = t->ip;
5799 TRACE("[Thread %2u] jmpgt (hi)\n", p->thread_id);
5801 JMP_CMP_HI(t, ip, >);
5808 instr_return_translate(struct rte_swx_pipeline *p __rte_unused,
5809 struct action *action,
5810 char **tokens __rte_unused,
5812 struct instruction *instr,
5813 struct instruction_data *data __rte_unused)
5815 CHECK(action, EINVAL);
5816 CHECK(n_tokens == 1, EINVAL);
5818 instr->type = INSTR_RETURN;
5823 instr_return_exec(struct rte_swx_pipeline *p)
5825 struct thread *t = &p->threads[p->thread_id];
5827 TRACE("[Thread %2u] return\n", p->thread_id);
5833 instr_translate(struct rte_swx_pipeline *p,
5834 struct action *action,
5836 struct instruction *instr,
5837 struct instruction_data *data)
5839 char *tokens[RTE_SWX_INSTRUCTION_TOKENS_MAX];
5840 int n_tokens = 0, tpos = 0;
5842 /* Parse the instruction string into tokens. */
5846 token = strtok_r(string, " \t\v", &string);
5850 CHECK(n_tokens < RTE_SWX_INSTRUCTION_TOKENS_MAX, EINVAL);
5851 CHECK_NAME(token, EINVAL);
5853 tokens[n_tokens] = token;
5857 CHECK(n_tokens, EINVAL);
5859 /* Handle the optional instruction label. */
5860 if ((n_tokens >= 2) && !strcmp(tokens[1], ":")) {
5861 strcpy(data->label, tokens[0]);
5864 CHECK(n_tokens - tpos, EINVAL);
5867 /* Identify the instruction type. */
5868 if (!strcmp(tokens[tpos], "rx"))
5869 return instr_rx_translate(p,
5876 if (!strcmp(tokens[tpos], "tx"))
5877 return instr_tx_translate(p,
5884 if (!strcmp(tokens[tpos], "drop"))
5885 return instr_drop_translate(p,
5892 if (!strcmp(tokens[tpos], "extract"))
5893 return instr_hdr_extract_translate(p,
5900 if (!strcmp(tokens[tpos], "lookahead"))
5901 return instr_hdr_lookahead_translate(p,
5908 if (!strcmp(tokens[tpos], "emit"))
5909 return instr_hdr_emit_translate(p,
5916 if (!strcmp(tokens[tpos], "validate"))
5917 return instr_hdr_validate_translate(p,
5924 if (!strcmp(tokens[tpos], "invalidate"))
5925 return instr_hdr_invalidate_translate(p,
5932 if (!strcmp(tokens[tpos], "mov"))
5933 return instr_mov_translate(p,
5940 if (!strcmp(tokens[tpos], "add"))
5941 return instr_alu_add_translate(p,
5948 if (!strcmp(tokens[tpos], "sub"))
5949 return instr_alu_sub_translate(p,
5956 if (!strcmp(tokens[tpos], "ckadd"))
5957 return instr_alu_ckadd_translate(p,
5964 if (!strcmp(tokens[tpos], "cksub"))
5965 return instr_alu_cksub_translate(p,
5972 if (!strcmp(tokens[tpos], "and"))
5973 return instr_alu_and_translate(p,
5980 if (!strcmp(tokens[tpos], "or"))
5981 return instr_alu_or_translate(p,
5988 if (!strcmp(tokens[tpos], "xor"))
5989 return instr_alu_xor_translate(p,
5996 if (!strcmp(tokens[tpos], "shl"))
5997 return instr_alu_shl_translate(p,
6004 if (!strcmp(tokens[tpos], "shr"))
6005 return instr_alu_shr_translate(p,
6012 if (!strcmp(tokens[tpos], "regprefetch"))
6013 return instr_regprefetch_translate(p,
6020 if (!strcmp(tokens[tpos], "regrd"))
6021 return instr_regrd_translate(p,
6028 if (!strcmp(tokens[tpos], "regwr"))
6029 return instr_regwr_translate(p,
6036 if (!strcmp(tokens[tpos], "regadd"))
6037 return instr_regadd_translate(p,
6044 if (!strcmp(tokens[tpos], "metprefetch"))
6045 return instr_metprefetch_translate(p,
6052 if (!strcmp(tokens[tpos], "meter"))
6053 return instr_meter_translate(p,
6060 if (!strcmp(tokens[tpos], "table"))
6061 return instr_table_translate(p,
6068 if (!strcmp(tokens[tpos], "learn"))
6069 return instr_learn_translate(p,
6076 if (!strcmp(tokens[tpos], "forget"))
6077 return instr_forget_translate(p,
6084 if (!strcmp(tokens[tpos], "extern"))
6085 return instr_extern_translate(p,
6092 if (!strcmp(tokens[tpos], "jmp"))
6093 return instr_jmp_translate(p,
6100 if (!strcmp(tokens[tpos], "jmpv"))
6101 return instr_jmp_valid_translate(p,
6108 if (!strcmp(tokens[tpos], "jmpnv"))
6109 return instr_jmp_invalid_translate(p,
6116 if (!strcmp(tokens[tpos], "jmph"))
6117 return instr_jmp_hit_translate(p,
6124 if (!strcmp(tokens[tpos], "jmpnh"))
6125 return instr_jmp_miss_translate(p,
6132 if (!strcmp(tokens[tpos], "jmpa"))
6133 return instr_jmp_action_hit_translate(p,
6140 if (!strcmp(tokens[tpos], "jmpna"))
6141 return instr_jmp_action_miss_translate(p,
6148 if (!strcmp(tokens[tpos], "jmpeq"))
6149 return instr_jmp_eq_translate(p,
6156 if (!strcmp(tokens[tpos], "jmpneq"))
6157 return instr_jmp_neq_translate(p,
6164 if (!strcmp(tokens[tpos], "jmplt"))
6165 return instr_jmp_lt_translate(p,
6172 if (!strcmp(tokens[tpos], "jmpgt"))
6173 return instr_jmp_gt_translate(p,
6180 if (!strcmp(tokens[tpos], "return"))
6181 return instr_return_translate(p,
6191 static struct instruction_data *
6192 label_find(struct instruction_data *data, uint32_t n, const char *label)
6196 for (i = 0; i < n; i++)
6197 if (!strcmp(label, data[i].label))
6204 label_is_used(struct instruction_data *data, uint32_t n, const char *label)
6206 uint32_t count = 0, i;
6211 for (i = 0; i < n; i++)
6212 if (!strcmp(label, data[i].jmp_label))
6219 instr_label_check(struct instruction_data *instruction_data,
6220 uint32_t n_instructions)
6224 /* Check that all instruction labels are unique. */
6225 for (i = 0; i < n_instructions; i++) {
6226 struct instruction_data *data = &instruction_data[i];
6227 char *label = data->label;
6233 for (j = i + 1; j < n_instructions; j++)
6234 CHECK(strcmp(label, data[j].label), EINVAL);
6237 /* Get users for each instruction label. */
6238 for (i = 0; i < n_instructions; i++) {
6239 struct instruction_data *data = &instruction_data[i];
6240 char *label = data->label;
6242 data->n_users = label_is_used(instruction_data,
6251 instr_jmp_resolve(struct instruction *instructions,
6252 struct instruction_data *instruction_data,
6253 uint32_t n_instructions)
6257 for (i = 0; i < n_instructions; i++) {
6258 struct instruction *instr = &instructions[i];
6259 struct instruction_data *data = &instruction_data[i];
6260 struct instruction_data *found;
6262 if (!instruction_is_jmp(instr))
6265 found = label_find(instruction_data,
6268 CHECK(found, EINVAL);
6270 instr->jmp.ip = &instructions[found - instruction_data];
6277 instr_verify(struct rte_swx_pipeline *p __rte_unused,
6279 struct instruction *instr,
6280 struct instruction_data *data __rte_unused,
6281 uint32_t n_instructions)
6284 enum instruction_type type;
6287 /* Check that the first instruction is rx. */
6288 CHECK(instr[0].type == INSTR_RX, EINVAL);
6290 /* Check that there is at least one tx instruction. */
6291 for (i = 0; i < n_instructions; i++) {
6292 type = instr[i].type;
6294 if (instruction_is_tx(type))
6297 CHECK(i < n_instructions, EINVAL);
6299 /* Check that the last instruction is either tx or unconditional
6302 type = instr[n_instructions - 1].type;
6303 CHECK(instruction_is_tx(type) || (type == INSTR_JMP), EINVAL);
6307 enum instruction_type type;
6310 /* Check that there is at least one return or tx instruction. */
6311 for (i = 0; i < n_instructions; i++) {
6312 type = instr[i].type;
6314 if ((type == INSTR_RETURN) || instruction_is_tx(type))
6317 CHECK(i < n_instructions, EINVAL);
6324 instr_compact(struct instruction *instructions,
6325 struct instruction_data *instruction_data,
6326 uint32_t n_instructions)
6328 uint32_t i, pos = 0;
6330 /* Eliminate the invalid instructions that have been optimized out. */
6331 for (i = 0; i < n_instructions; i++) {
6332 struct instruction *instr = &instructions[i];
6333 struct instruction_data *data = &instruction_data[i];
6339 memcpy(&instructions[pos], instr, sizeof(*instr));
6340 memcpy(&instruction_data[pos], data, sizeof(*data));
6350 instr_pattern_extract_many_search(struct instruction *instr,
6351 struct instruction_data *data,
6353 uint32_t *n_pattern_instr)
6357 for (i = 0; i < n_instr; i++) {
6358 if (data[i].invalid)
6361 if (instr[i].type != INSTR_HDR_EXTRACT)
6364 if (i == RTE_DIM(instr->io.hdr.header_id))
6367 if (i && data[i].n_users)
6374 *n_pattern_instr = i;
6379 instr_pattern_extract_many_replace(struct instruction *instr,
6380 struct instruction_data *data,
6385 for (i = 1; i < n_instr; i++) {
6387 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
6388 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
6389 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
6391 data[i].invalid = 1;
6396 instr_pattern_extract_many_optimize(struct instruction *instructions,
6397 struct instruction_data *instruction_data,
6398 uint32_t n_instructions)
6402 for (i = 0; i < n_instructions; ) {
6403 struct instruction *instr = &instructions[i];
6404 struct instruction_data *data = &instruction_data[i];
6405 uint32_t n_instr = 0;
6409 detected = instr_pattern_extract_many_search(instr,
6414 instr_pattern_extract_many_replace(instr,
6421 /* No pattern starting at the current instruction. */
6425 /* Eliminate the invalid instructions that have been optimized out. */
6426 n_instructions = instr_compact(instructions,
6430 return n_instructions;
6434 instr_pattern_emit_many_tx_search(struct instruction *instr,
6435 struct instruction_data *data,
6437 uint32_t *n_pattern_instr)
6441 for (i = 0; i < n_instr; i++) {
6442 if (data[i].invalid)
6445 if (instr[i].type != INSTR_HDR_EMIT)
6448 if (i == RTE_DIM(instr->io.hdr.header_id))
6451 if (i && data[i].n_users)
6458 if (!instruction_is_tx(instr[i].type))
6461 if (data[i].n_users)
6466 *n_pattern_instr = i;
6471 instr_pattern_emit_many_tx_replace(struct instruction *instr,
6472 struct instruction_data *data,
6477 /* Any emit instruction in addition to the first one. */
6478 for (i = 1; i < n_instr - 1; i++) {
6480 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
6481 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
6482 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
6484 data[i].invalid = 1;
6487 /* The TX instruction is the last one in the pattern. */
6489 instr[0].io.io.offset = instr[i].io.io.offset;
6490 instr[0].io.io.n_bits = instr[i].io.io.n_bits;
6491 data[i].invalid = 1;
6495 instr_pattern_emit_many_tx_optimize(struct instruction *instructions,
6496 struct instruction_data *instruction_data,
6497 uint32_t n_instructions)
6501 for (i = 0; i < n_instructions; ) {
6502 struct instruction *instr = &instructions[i];
6503 struct instruction_data *data = &instruction_data[i];
6504 uint32_t n_instr = 0;
6507 /* Emit many + TX. */
6508 detected = instr_pattern_emit_many_tx_search(instr,
6513 instr_pattern_emit_many_tx_replace(instr,
6520 /* No pattern starting at the current instruction. */
6524 /* Eliminate the invalid instructions that have been optimized out. */
6525 n_instructions = instr_compact(instructions,
6529 return n_instructions;
6533 action_arg_src_mov_count(struct action *a,
6535 struct instruction *instructions,
6536 struct instruction_data *instruction_data,
6537 uint32_t n_instructions);
6540 instr_pattern_mov_all_validate_search(struct rte_swx_pipeline *p,
6542 struct instruction *instr,
6543 struct instruction_data *data,
6545 struct instruction *instructions,
6546 struct instruction_data *instruction_data,
6547 uint32_t n_instructions,
6548 uint32_t *n_pattern_instr)
6551 uint32_t src_field_id, i, j;
6553 /* Prerequisites. */
6557 /* First instruction: MOV_HM. */
6558 if (data[0].invalid || (instr[0].type != INSTR_MOV_HM))
6561 h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
6562 if (!h || h->st->var_size)
6565 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
6566 if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
6569 if (src_field_id == a->st->n_fields)
6572 if (instr[0].mov.dst.offset ||
6573 (instr[0].mov.dst.n_bits != h->st->fields[0].n_bits) ||
6574 instr[0].mov.src.struct_id ||
6575 (instr[0].mov.src.n_bits != a->st->fields[src_field_id].n_bits) ||
6576 (instr[0].mov.dst.n_bits != instr[0].mov.src.n_bits))
6579 if ((n_instr < h->st->n_fields + 1) ||
6580 (a->st->n_fields < src_field_id + h->st->n_fields + 1))
6583 /* Subsequent instructions: MOV_HM. */
6584 for (i = 1; i < h->st->n_fields; i++)
6585 if (data[i].invalid ||
6587 (instr[i].type != INSTR_MOV_HM) ||
6588 (instr[i].mov.dst.struct_id != h->struct_id) ||
6589 (instr[i].mov.dst.offset != h->st->fields[i].offset / 8) ||
6590 (instr[i].mov.dst.n_bits != h->st->fields[i].n_bits) ||
6591 instr[i].mov.src.struct_id ||
6592 (instr[i].mov.src.offset != a->st->fields[src_field_id + i].offset / 8) ||
6593 (instr[i].mov.src.n_bits != a->st->fields[src_field_id + i].n_bits) ||
6594 (instr[i].mov.dst.n_bits != instr[i].mov.src.n_bits))
6597 /* Last instruction: HDR_VALIDATE. */
6598 if ((instr[i].type != INSTR_HDR_VALIDATE) ||
6599 (instr[i].valid.header_id != h->id))
6602 /* Check that none of the action args that are used as source for this
6603 * DMA transfer are not used as source in any other mov instruction.
6605 for (j = src_field_id; j < src_field_id + h->st->n_fields; j++) {
6608 n_users = action_arg_src_mov_count(a,
6617 *n_pattern_instr = 1 + i;
6622 instr_pattern_mov_all_validate_replace(struct rte_swx_pipeline *p,
6624 struct instruction *instr,
6625 struct instruction_data *data,
6629 uint32_t src_field_id, src_offset, i;
6631 /* Read from the instructions before they are modified. */
6632 h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
6636 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
6637 if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
6640 if (src_field_id == a->st->n_fields)
6643 src_offset = instr[0].mov.src.offset;
6645 /* Modify the instructions. */
6646 instr[0].type = INSTR_DMA_HT;
6647 instr[0].dma.dst.header_id[0] = h->id;
6648 instr[0].dma.dst.struct_id[0] = h->struct_id;
6649 instr[0].dma.src.offset[0] = (uint8_t)src_offset;
6650 instr[0].dma.n_bytes[0] = h->st->n_bits / 8;
6652 for (i = 1; i < n_instr; i++)
6653 data[i].invalid = 1;
6655 /* Update the endianness of the action arguments to header endianness. */
6656 for (i = 0; i < h->st->n_fields; i++)
6657 a->args_endianness[src_field_id + i] = 1;
6661 instr_pattern_mov_all_validate_optimize(struct rte_swx_pipeline *p,
6663 struct instruction *instructions,
6664 struct instruction_data *instruction_data,
6665 uint32_t n_instructions)
6670 return n_instructions;
6672 for (i = 0; i < n_instructions; ) {
6673 struct instruction *instr = &instructions[i];
6674 struct instruction_data *data = &instruction_data[i];
6675 uint32_t n_instr = 0;
6678 /* Mov all + validate. */
6679 detected = instr_pattern_mov_all_validate_search(p,
6689 instr_pattern_mov_all_validate_replace(p, a, instr, data, n_instr);
6694 /* No pattern starting at the current instruction. */
6698 /* Eliminate the invalid instructions that have been optimized out. */
6699 n_instructions = instr_compact(instructions,
6703 return n_instructions;
6707 instr_pattern_dma_many_search(struct instruction *instr,
6708 struct instruction_data *data,
6710 uint32_t *n_pattern_instr)
6714 for (i = 0; i < n_instr; i++) {
6715 if (data[i].invalid)
6718 if (instr[i].type != INSTR_DMA_HT)
6721 if (i == RTE_DIM(instr->dma.dst.header_id))
6724 if (i && data[i].n_users)
6731 *n_pattern_instr = i;
6736 instr_pattern_dma_many_replace(struct instruction *instr,
6737 struct instruction_data *data,
6742 for (i = 1; i < n_instr; i++) {
6744 instr[0].dma.dst.header_id[i] = instr[i].dma.dst.header_id[0];
6745 instr[0].dma.dst.struct_id[i] = instr[i].dma.dst.struct_id[0];
6746 instr[0].dma.src.offset[i] = instr[i].dma.src.offset[0];
6747 instr[0].dma.n_bytes[i] = instr[i].dma.n_bytes[0];
6749 data[i].invalid = 1;
6754 instr_pattern_dma_many_optimize(struct instruction *instructions,
6755 struct instruction_data *instruction_data,
6756 uint32_t n_instructions)
6760 for (i = 0; i < n_instructions; ) {
6761 struct instruction *instr = &instructions[i];
6762 struct instruction_data *data = &instruction_data[i];
6763 uint32_t n_instr = 0;
6767 detected = instr_pattern_dma_many_search(instr,
6772 instr_pattern_dma_many_replace(instr, data, n_instr);
6777 /* No pattern starting at the current instruction. */
6781 /* Eliminate the invalid instructions that have been optimized out. */
6782 n_instructions = instr_compact(instructions,
6786 return n_instructions;
6790 instr_optimize(struct rte_swx_pipeline *p,
6792 struct instruction *instructions,
6793 struct instruction_data *instruction_data,
6794 uint32_t n_instructions)
6797 n_instructions = instr_pattern_extract_many_optimize(instructions,
6801 /* Emit many + TX. */
6802 n_instructions = instr_pattern_emit_many_tx_optimize(instructions,
6806 /* Mov all + validate. */
6807 n_instructions = instr_pattern_mov_all_validate_optimize(p,
6814 n_instructions = instr_pattern_dma_many_optimize(instructions,
6818 return n_instructions;
6822 instruction_config(struct rte_swx_pipeline *p,
6824 const char **instructions,
6825 uint32_t n_instructions)
6827 struct instruction *instr = NULL;
6828 struct instruction_data *data = NULL;
6832 CHECK(n_instructions, EINVAL);
6833 CHECK(instructions, EINVAL);
6834 for (i = 0; i < n_instructions; i++)
6835 CHECK_INSTRUCTION(instructions[i], EINVAL);
6837 /* Memory allocation. */
6838 instr = calloc(n_instructions, sizeof(struct instruction));
6844 data = calloc(n_instructions, sizeof(struct instruction_data));
6850 for (i = 0; i < n_instructions; i++) {
6851 char *string = strdup(instructions[i]);
6857 err = instr_translate(p, a, string, &instr[i], &data[i]);
6866 err = instr_label_check(data, n_instructions);
6870 err = instr_verify(p, a, instr, data, n_instructions);
6874 n_instructions = instr_optimize(p, a, instr, data, n_instructions);
6876 err = instr_jmp_resolve(instr, data, n_instructions);
6881 a->instructions = instr;
6882 a->n_instructions = n_instructions;
6884 p->instructions = instr;
6885 p->n_instructions = n_instructions;
6897 typedef void (*instr_exec_t)(struct rte_swx_pipeline *);
6899 static instr_exec_t instruction_table[] = {
6900 [INSTR_RX] = instr_rx_exec,
6901 [INSTR_TX] = instr_tx_exec,
6902 [INSTR_TX_I] = instr_tx_i_exec,
6904 [INSTR_HDR_EXTRACT] = instr_hdr_extract_exec,
6905 [INSTR_HDR_EXTRACT2] = instr_hdr_extract2_exec,
6906 [INSTR_HDR_EXTRACT3] = instr_hdr_extract3_exec,
6907 [INSTR_HDR_EXTRACT4] = instr_hdr_extract4_exec,
6908 [INSTR_HDR_EXTRACT5] = instr_hdr_extract5_exec,
6909 [INSTR_HDR_EXTRACT6] = instr_hdr_extract6_exec,
6910 [INSTR_HDR_EXTRACT7] = instr_hdr_extract7_exec,
6911 [INSTR_HDR_EXTRACT8] = instr_hdr_extract8_exec,
6912 [INSTR_HDR_EXTRACT_M] = instr_hdr_extract_m_exec,
6913 [INSTR_HDR_LOOKAHEAD] = instr_hdr_lookahead_exec,
6915 [INSTR_HDR_EMIT] = instr_hdr_emit_exec,
6916 [INSTR_HDR_EMIT_TX] = instr_hdr_emit_tx_exec,
6917 [INSTR_HDR_EMIT2_TX] = instr_hdr_emit2_tx_exec,
6918 [INSTR_HDR_EMIT3_TX] = instr_hdr_emit3_tx_exec,
6919 [INSTR_HDR_EMIT4_TX] = instr_hdr_emit4_tx_exec,
6920 [INSTR_HDR_EMIT5_TX] = instr_hdr_emit5_tx_exec,
6921 [INSTR_HDR_EMIT6_TX] = instr_hdr_emit6_tx_exec,
6922 [INSTR_HDR_EMIT7_TX] = instr_hdr_emit7_tx_exec,
6923 [INSTR_HDR_EMIT8_TX] = instr_hdr_emit8_tx_exec,
6925 [INSTR_HDR_VALIDATE] = instr_hdr_validate_exec,
6926 [INSTR_HDR_INVALIDATE] = instr_hdr_invalidate_exec,
6928 [INSTR_MOV] = instr_mov_exec,
6929 [INSTR_MOV_MH] = instr_mov_mh_exec,
6930 [INSTR_MOV_HM] = instr_mov_hm_exec,
6931 [INSTR_MOV_HH] = instr_mov_hh_exec,
6932 [INSTR_MOV_I] = instr_mov_i_exec,
6934 [INSTR_DMA_HT] = instr_dma_ht_exec,
6935 [INSTR_DMA_HT2] = instr_dma_ht2_exec,
6936 [INSTR_DMA_HT3] = instr_dma_ht3_exec,
6937 [INSTR_DMA_HT4] = instr_dma_ht4_exec,
6938 [INSTR_DMA_HT5] = instr_dma_ht5_exec,
6939 [INSTR_DMA_HT6] = instr_dma_ht6_exec,
6940 [INSTR_DMA_HT7] = instr_dma_ht7_exec,
6941 [INSTR_DMA_HT8] = instr_dma_ht8_exec,
6943 [INSTR_ALU_ADD] = instr_alu_add_exec,
6944 [INSTR_ALU_ADD_MH] = instr_alu_add_mh_exec,
6945 [INSTR_ALU_ADD_HM] = instr_alu_add_hm_exec,
6946 [INSTR_ALU_ADD_HH] = instr_alu_add_hh_exec,
6947 [INSTR_ALU_ADD_MI] = instr_alu_add_mi_exec,
6948 [INSTR_ALU_ADD_HI] = instr_alu_add_hi_exec,
6950 [INSTR_ALU_SUB] = instr_alu_sub_exec,
6951 [INSTR_ALU_SUB_MH] = instr_alu_sub_mh_exec,
6952 [INSTR_ALU_SUB_HM] = instr_alu_sub_hm_exec,
6953 [INSTR_ALU_SUB_HH] = instr_alu_sub_hh_exec,
6954 [INSTR_ALU_SUB_MI] = instr_alu_sub_mi_exec,
6955 [INSTR_ALU_SUB_HI] = instr_alu_sub_hi_exec,
6957 [INSTR_ALU_CKADD_FIELD] = instr_alu_ckadd_field_exec,
6958 [INSTR_ALU_CKADD_STRUCT] = instr_alu_ckadd_struct_exec,
6959 [INSTR_ALU_CKADD_STRUCT20] = instr_alu_ckadd_struct20_exec,
6960 [INSTR_ALU_CKSUB_FIELD] = instr_alu_cksub_field_exec,
6962 [INSTR_ALU_AND] = instr_alu_and_exec,
6963 [INSTR_ALU_AND_MH] = instr_alu_and_mh_exec,
6964 [INSTR_ALU_AND_HM] = instr_alu_and_hm_exec,
6965 [INSTR_ALU_AND_HH] = instr_alu_and_hh_exec,
6966 [INSTR_ALU_AND_I] = instr_alu_and_i_exec,
6968 [INSTR_ALU_OR] = instr_alu_or_exec,
6969 [INSTR_ALU_OR_MH] = instr_alu_or_mh_exec,
6970 [INSTR_ALU_OR_HM] = instr_alu_or_hm_exec,
6971 [INSTR_ALU_OR_HH] = instr_alu_or_hh_exec,
6972 [INSTR_ALU_OR_I] = instr_alu_or_i_exec,
6974 [INSTR_ALU_XOR] = instr_alu_xor_exec,
6975 [INSTR_ALU_XOR_MH] = instr_alu_xor_mh_exec,
6976 [INSTR_ALU_XOR_HM] = instr_alu_xor_hm_exec,
6977 [INSTR_ALU_XOR_HH] = instr_alu_xor_hh_exec,
6978 [INSTR_ALU_XOR_I] = instr_alu_xor_i_exec,
6980 [INSTR_ALU_SHL] = instr_alu_shl_exec,
6981 [INSTR_ALU_SHL_MH] = instr_alu_shl_mh_exec,
6982 [INSTR_ALU_SHL_HM] = instr_alu_shl_hm_exec,
6983 [INSTR_ALU_SHL_HH] = instr_alu_shl_hh_exec,
6984 [INSTR_ALU_SHL_MI] = instr_alu_shl_mi_exec,
6985 [INSTR_ALU_SHL_HI] = instr_alu_shl_hi_exec,
6987 [INSTR_ALU_SHR] = instr_alu_shr_exec,
6988 [INSTR_ALU_SHR_MH] = instr_alu_shr_mh_exec,
6989 [INSTR_ALU_SHR_HM] = instr_alu_shr_hm_exec,
6990 [INSTR_ALU_SHR_HH] = instr_alu_shr_hh_exec,
6991 [INSTR_ALU_SHR_MI] = instr_alu_shr_mi_exec,
6992 [INSTR_ALU_SHR_HI] = instr_alu_shr_hi_exec,
6994 [INSTR_REGPREFETCH_RH] = instr_regprefetch_rh_exec,
6995 [INSTR_REGPREFETCH_RM] = instr_regprefetch_rm_exec,
6996 [INSTR_REGPREFETCH_RI] = instr_regprefetch_ri_exec,
6998 [INSTR_REGRD_HRH] = instr_regrd_hrh_exec,
6999 [INSTR_REGRD_HRM] = instr_regrd_hrm_exec,
7000 [INSTR_REGRD_MRH] = instr_regrd_mrh_exec,
7001 [INSTR_REGRD_MRM] = instr_regrd_mrm_exec,
7002 [INSTR_REGRD_HRI] = instr_regrd_hri_exec,
7003 [INSTR_REGRD_MRI] = instr_regrd_mri_exec,
7005 [INSTR_REGWR_RHH] = instr_regwr_rhh_exec,
7006 [INSTR_REGWR_RHM] = instr_regwr_rhm_exec,
7007 [INSTR_REGWR_RMH] = instr_regwr_rmh_exec,
7008 [INSTR_REGWR_RMM] = instr_regwr_rmm_exec,
7009 [INSTR_REGWR_RHI] = instr_regwr_rhi_exec,
7010 [INSTR_REGWR_RMI] = instr_regwr_rmi_exec,
7011 [INSTR_REGWR_RIH] = instr_regwr_rih_exec,
7012 [INSTR_REGWR_RIM] = instr_regwr_rim_exec,
7013 [INSTR_REGWR_RII] = instr_regwr_rii_exec,
7015 [INSTR_REGADD_RHH] = instr_regadd_rhh_exec,
7016 [INSTR_REGADD_RHM] = instr_regadd_rhm_exec,
7017 [INSTR_REGADD_RMH] = instr_regadd_rmh_exec,
7018 [INSTR_REGADD_RMM] = instr_regadd_rmm_exec,
7019 [INSTR_REGADD_RHI] = instr_regadd_rhi_exec,
7020 [INSTR_REGADD_RMI] = instr_regadd_rmi_exec,
7021 [INSTR_REGADD_RIH] = instr_regadd_rih_exec,
7022 [INSTR_REGADD_RIM] = instr_regadd_rim_exec,
7023 [INSTR_REGADD_RII] = instr_regadd_rii_exec,
7025 [INSTR_METPREFETCH_H] = instr_metprefetch_h_exec,
7026 [INSTR_METPREFETCH_M] = instr_metprefetch_m_exec,
7027 [INSTR_METPREFETCH_I] = instr_metprefetch_i_exec,
7029 [INSTR_METER_HHM] = instr_meter_hhm_exec,
7030 [INSTR_METER_HHI] = instr_meter_hhi_exec,
7031 [INSTR_METER_HMM] = instr_meter_hmm_exec,
7032 [INSTR_METER_HMI] = instr_meter_hmi_exec,
7033 [INSTR_METER_MHM] = instr_meter_mhm_exec,
7034 [INSTR_METER_MHI] = instr_meter_mhi_exec,
7035 [INSTR_METER_MMM] = instr_meter_mmm_exec,
7036 [INSTR_METER_MMI] = instr_meter_mmi_exec,
7037 [INSTR_METER_IHM] = instr_meter_ihm_exec,
7038 [INSTR_METER_IHI] = instr_meter_ihi_exec,
7039 [INSTR_METER_IMM] = instr_meter_imm_exec,
7040 [INSTR_METER_IMI] = instr_meter_imi_exec,
7042 [INSTR_TABLE] = instr_table_exec,
7043 [INSTR_SELECTOR] = instr_selector_exec,
7044 [INSTR_LEARNER] = instr_learner_exec,
7045 [INSTR_LEARNER_LEARN] = instr_learn_exec,
7046 [INSTR_LEARNER_FORGET] = instr_forget_exec,
7047 [INSTR_EXTERN_OBJ] = instr_extern_obj_exec,
7048 [INSTR_EXTERN_FUNC] = instr_extern_func_exec,
7050 [INSTR_JMP] = instr_jmp_exec,
7051 [INSTR_JMP_VALID] = instr_jmp_valid_exec,
7052 [INSTR_JMP_INVALID] = instr_jmp_invalid_exec,
7053 [INSTR_JMP_HIT] = instr_jmp_hit_exec,
7054 [INSTR_JMP_MISS] = instr_jmp_miss_exec,
7055 [INSTR_JMP_ACTION_HIT] = instr_jmp_action_hit_exec,
7056 [INSTR_JMP_ACTION_MISS] = instr_jmp_action_miss_exec,
7058 [INSTR_JMP_EQ] = instr_jmp_eq_exec,
7059 [INSTR_JMP_EQ_MH] = instr_jmp_eq_mh_exec,
7060 [INSTR_JMP_EQ_HM] = instr_jmp_eq_hm_exec,
7061 [INSTR_JMP_EQ_HH] = instr_jmp_eq_hh_exec,
7062 [INSTR_JMP_EQ_I] = instr_jmp_eq_i_exec,
7064 [INSTR_JMP_NEQ] = instr_jmp_neq_exec,
7065 [INSTR_JMP_NEQ_MH] = instr_jmp_neq_mh_exec,
7066 [INSTR_JMP_NEQ_HM] = instr_jmp_neq_hm_exec,
7067 [INSTR_JMP_NEQ_HH] = instr_jmp_neq_hh_exec,
7068 [INSTR_JMP_NEQ_I] = instr_jmp_neq_i_exec,
7070 [INSTR_JMP_LT] = instr_jmp_lt_exec,
7071 [INSTR_JMP_LT_MH] = instr_jmp_lt_mh_exec,
7072 [INSTR_JMP_LT_HM] = instr_jmp_lt_hm_exec,
7073 [INSTR_JMP_LT_HH] = instr_jmp_lt_hh_exec,
7074 [INSTR_JMP_LT_MI] = instr_jmp_lt_mi_exec,
7075 [INSTR_JMP_LT_HI] = instr_jmp_lt_hi_exec,
7077 [INSTR_JMP_GT] = instr_jmp_gt_exec,
7078 [INSTR_JMP_GT_MH] = instr_jmp_gt_mh_exec,
7079 [INSTR_JMP_GT_HM] = instr_jmp_gt_hm_exec,
7080 [INSTR_JMP_GT_HH] = instr_jmp_gt_hh_exec,
7081 [INSTR_JMP_GT_MI] = instr_jmp_gt_mi_exec,
7082 [INSTR_JMP_GT_HI] = instr_jmp_gt_hi_exec,
7084 [INSTR_RETURN] = instr_return_exec,
7088 instr_exec(struct rte_swx_pipeline *p)
7090 struct thread *t = &p->threads[p->thread_id];
7091 struct instruction *ip = t->ip;
7092 instr_exec_t instr = instruction_table[ip->type];
7100 static struct action *
7101 action_find(struct rte_swx_pipeline *p, const char *name)
7103 struct action *elem;
7108 TAILQ_FOREACH(elem, &p->actions, node)
7109 if (strcmp(elem->name, name) == 0)
7115 static struct action *
7116 action_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7118 struct action *action = NULL;
7120 TAILQ_FOREACH(action, &p->actions, node)
7121 if (action->id == id)
7127 static struct field *
7128 action_field_find(struct action *a, const char *name)
7130 return a->st ? struct_type_field_find(a->st, name) : NULL;
7133 static struct field *
7134 action_field_parse(struct action *action, const char *name)
7136 if (name[0] != 't' || name[1] != '.')
7139 return action_field_find(action, &name[2]);
7143 action_has_nbo_args(struct action *a)
7147 /* Return if the action does not have any args. */
7149 return 0; /* FALSE */
7151 for (i = 0; i < a->st->n_fields; i++)
7152 if (a->args_endianness[i])
7153 return 1; /* TRUE */
7155 return 0; /* FALSE */
7159 action_does_learning(struct action *a)
7163 for (i = 0; i < a->n_instructions; i++)
7164 switch (a->instructions[i].type) {
7165 case INSTR_LEARNER_LEARN:
7166 return 1; /* TRUE */
7168 case INSTR_LEARNER_FORGET:
7169 return 1; /* TRUE */
7175 return 0; /* FALSE */
7179 rte_swx_pipeline_action_config(struct rte_swx_pipeline *p,
7181 const char *args_struct_type_name,
7182 const char **instructions,
7183 uint32_t n_instructions)
7185 struct struct_type *args_struct_type = NULL;
7191 CHECK_NAME(name, EINVAL);
7192 CHECK(!action_find(p, name), EEXIST);
7194 if (args_struct_type_name) {
7195 CHECK_NAME(args_struct_type_name, EINVAL);
7196 args_struct_type = struct_type_find(p, args_struct_type_name);
7197 CHECK(args_struct_type, EINVAL);
7198 CHECK(!args_struct_type->var_size, EINVAL);
7201 /* Node allocation. */
7202 a = calloc(1, sizeof(struct action));
7204 if (args_struct_type) {
7205 a->args_endianness = calloc(args_struct_type->n_fields, sizeof(int));
7206 if (!a->args_endianness) {
7212 /* Node initialization. */
7213 strcpy(a->name, name);
7214 a->st = args_struct_type;
7215 a->id = p->n_actions;
7217 /* Instruction translation. */
7218 err = instruction_config(p, a, instructions, n_instructions);
7220 free(a->args_endianness);
7225 /* Node add to tailq. */
7226 TAILQ_INSERT_TAIL(&p->actions, a, node);
7233 action_build(struct rte_swx_pipeline *p)
7235 struct action *action;
7237 p->action_instructions = calloc(p->n_actions,
7238 sizeof(struct instruction *));
7239 CHECK(p->action_instructions, ENOMEM);
7241 TAILQ_FOREACH(action, &p->actions, node)
7242 p->action_instructions[action->id] = action->instructions;
7248 action_build_free(struct rte_swx_pipeline *p)
7250 free(p->action_instructions);
7251 p->action_instructions = NULL;
7255 action_free(struct rte_swx_pipeline *p)
7257 action_build_free(p);
7260 struct action *action;
7262 action = TAILQ_FIRST(&p->actions);
7266 TAILQ_REMOVE(&p->actions, action, node);
7267 free(action->instructions);
7273 action_arg_src_mov_count(struct action *a,
7275 struct instruction *instructions,
7276 struct instruction_data *instruction_data,
7277 uint32_t n_instructions)
7279 uint32_t offset, n_users = 0, i;
7282 (arg_id >= a->st->n_fields) ||
7284 !instruction_data ||
7288 offset = a->st->fields[arg_id].offset / 8;
7290 for (i = 0; i < n_instructions; i++) {
7291 struct instruction *instr = &instructions[i];
7292 struct instruction_data *data = &instruction_data[i];
7294 if (data->invalid ||
7295 ((instr->type != INSTR_MOV) && (instr->type != INSTR_MOV_HM)) ||
7296 instr->mov.src.struct_id ||
7297 (instr->mov.src.offset != offset))
7309 static struct table_type *
7310 table_type_find(struct rte_swx_pipeline *p, const char *name)
7312 struct table_type *elem;
7314 TAILQ_FOREACH(elem, &p->table_types, node)
7315 if (strcmp(elem->name, name) == 0)
7321 static struct table_type *
7322 table_type_resolve(struct rte_swx_pipeline *p,
7323 const char *recommended_type_name,
7324 enum rte_swx_table_match_type match_type)
7326 struct table_type *elem;
7328 /* Only consider the recommended type if the match type is correct. */
7329 if (recommended_type_name)
7330 TAILQ_FOREACH(elem, &p->table_types, node)
7331 if (!strcmp(elem->name, recommended_type_name) &&
7332 (elem->match_type == match_type))
7335 /* Ignore the recommended type and get the first element with this match
7338 TAILQ_FOREACH(elem, &p->table_types, node)
7339 if (elem->match_type == match_type)
7345 static struct table *
7346 table_find(struct rte_swx_pipeline *p, const char *name)
7350 TAILQ_FOREACH(elem, &p->tables, node)
7351 if (strcmp(elem->name, name) == 0)
7357 static struct table *
7358 table_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7360 struct table *table = NULL;
7362 TAILQ_FOREACH(table, &p->tables, node)
7363 if (table->id == id)
7370 rte_swx_pipeline_table_type_register(struct rte_swx_pipeline *p,
7372 enum rte_swx_table_match_type match_type,
7373 struct rte_swx_table_ops *ops)
7375 struct table_type *elem;
7379 CHECK_NAME(name, EINVAL);
7380 CHECK(!table_type_find(p, name), EEXIST);
7383 CHECK(ops->create, EINVAL);
7384 CHECK(ops->lkp, EINVAL);
7385 CHECK(ops->free, EINVAL);
7387 /* Node allocation. */
7388 elem = calloc(1, sizeof(struct table_type));
7389 CHECK(elem, ENOMEM);
7391 /* Node initialization. */
7392 strcpy(elem->name, name);
7393 elem->match_type = match_type;
7394 memcpy(&elem->ops, ops, sizeof(*ops));
7396 /* Node add to tailq. */
7397 TAILQ_INSERT_TAIL(&p->table_types, elem, node);
7403 table_match_type_resolve(struct rte_swx_match_field_params *fields,
7405 enum rte_swx_table_match_type *match_type)
7407 uint32_t n_fields_em = 0, n_fields_lpm = 0, i;
7409 for (i = 0; i < n_fields; i++) {
7410 struct rte_swx_match_field_params *f = &fields[i];
7412 if (f->match_type == RTE_SWX_TABLE_MATCH_EXACT)
7415 if (f->match_type == RTE_SWX_TABLE_MATCH_LPM)
7419 if ((n_fields_lpm > 1) ||
7420 (n_fields_lpm && (n_fields_em != n_fields - 1)))
7423 *match_type = (n_fields_em == n_fields) ?
7424 RTE_SWX_TABLE_MATCH_EXACT :
7425 RTE_SWX_TABLE_MATCH_WILDCARD;
7431 table_match_fields_check(struct rte_swx_pipeline *p,
7432 struct rte_swx_pipeline_table_params *params,
7433 struct header **header)
7435 struct header *h0 = NULL;
7436 struct field *hf, *mf;
7437 uint32_t *offset = NULL, i;
7440 /* Return if no match fields. */
7441 if (!params->n_fields) {
7442 if (params->fields) {
7453 /* Memory allocation. */
7454 offset = calloc(params->n_fields, sizeof(uint32_t));
7460 /* Check that all the match fields belong to either the same header or
7463 hf = header_field_parse(p, params->fields[0].name, &h0);
7464 mf = metadata_field_parse(p, params->fields[0].name);
7465 if ((!hf && !mf) || (hf && hf->var_size)) {
7470 offset[0] = h0 ? hf->offset : mf->offset;
7472 for (i = 1; i < params->n_fields; i++)
7476 hf = header_field_parse(p, params->fields[i].name, &h);
7477 if (!hf || (h->id != h0->id) || hf->var_size) {
7482 offset[i] = hf->offset;
7484 mf = metadata_field_parse(p, params->fields[i].name);
7490 offset[i] = mf->offset;
7493 /* Check that there are no duplicated match fields. */
7494 for (i = 0; i < params->n_fields; i++) {
7497 for (j = 0; j < i; j++)
7498 if (offset[j] == offset[i]) {
7514 rte_swx_pipeline_table_config(struct rte_swx_pipeline *p,
7516 struct rte_swx_pipeline_table_params *params,
7517 const char *recommended_table_type_name,
7521 struct table_type *type;
7523 struct action *default_action;
7524 struct header *header = NULL;
7525 uint32_t action_data_size_max = 0, i;
7530 CHECK_NAME(name, EINVAL);
7531 CHECK(!table_find(p, name), EEXIST);
7532 CHECK(!selector_find(p, name), EEXIST);
7533 CHECK(!learner_find(p, name), EEXIST);
7535 CHECK(params, EINVAL);
7538 status = table_match_fields_check(p, params, &header);
7542 /* Action checks. */
7543 CHECK(params->n_actions, EINVAL);
7544 CHECK(params->action_names, EINVAL);
7545 for (i = 0; i < params->n_actions; i++) {
7546 const char *action_name = params->action_names[i];
7548 uint32_t action_data_size;
7550 CHECK_NAME(action_name, EINVAL);
7552 a = action_find(p, action_name);
7554 CHECK(!action_does_learning(a), EINVAL);
7556 action_data_size = a->st ? a->st->n_bits / 8 : 0;
7557 if (action_data_size > action_data_size_max)
7558 action_data_size_max = action_data_size;
7561 CHECK_NAME(params->default_action_name, EINVAL);
7562 for (i = 0; i < p->n_actions; i++)
7563 if (!strcmp(params->action_names[i],
7564 params->default_action_name))
7566 CHECK(i < params->n_actions, EINVAL);
7567 default_action = action_find(p, params->default_action_name);
7568 CHECK((default_action->st && params->default_action_data) ||
7569 !params->default_action_data, EINVAL);
7571 /* Table type checks. */
7572 if (recommended_table_type_name)
7573 CHECK_NAME(recommended_table_type_name, EINVAL);
7575 if (params->n_fields) {
7576 enum rte_swx_table_match_type match_type;
7578 status = table_match_type_resolve(params->fields, params->n_fields, &match_type);
7582 type = table_type_resolve(p, recommended_table_type_name, match_type);
7583 CHECK(type, EINVAL);
7588 /* Memory allocation. */
7589 t = calloc(1, sizeof(struct table));
7592 t->fields = calloc(params->n_fields, sizeof(struct match_field));
7598 t->actions = calloc(params->n_actions, sizeof(struct action *));
7605 if (action_data_size_max) {
7606 t->default_action_data = calloc(1, action_data_size_max);
7607 if (!t->default_action_data) {
7615 /* Node initialization. */
7616 strcpy(t->name, name);
7617 if (args && args[0])
7618 strcpy(t->args, args);
7621 for (i = 0; i < params->n_fields; i++) {
7622 struct rte_swx_match_field_params *field = ¶ms->fields[i];
7623 struct match_field *f = &t->fields[i];
7625 f->match_type = field->match_type;
7627 header_field_parse(p, field->name, NULL) :
7628 metadata_field_parse(p, field->name);
7630 t->n_fields = params->n_fields;
7633 for (i = 0; i < params->n_actions; i++)
7634 t->actions[i] = action_find(p, params->action_names[i]);
7635 t->default_action = default_action;
7636 if (default_action->st)
7637 memcpy(t->default_action_data,
7638 params->default_action_data,
7639 default_action->st->n_bits / 8);
7640 t->n_actions = params->n_actions;
7641 t->default_action_is_const = params->default_action_is_const;
7642 t->action_data_size_max = action_data_size_max;
7645 t->id = p->n_tables;
7647 /* Node add to tailq. */
7648 TAILQ_INSERT_TAIL(&p->tables, t, node);
7654 static struct rte_swx_table_params *
7655 table_params_get(struct table *table)
7657 struct rte_swx_table_params *params;
7658 struct field *first, *last;
7660 uint32_t key_size, key_offset, action_data_size, i;
7662 /* Memory allocation. */
7663 params = calloc(1, sizeof(struct rte_swx_table_params));
7667 /* Find first (smallest offset) and last (biggest offset) match fields. */
7668 first = table->fields[0].field;
7669 last = table->fields[0].field;
7671 for (i = 0; i < table->n_fields; i++) {
7672 struct field *f = table->fields[i].field;
7674 if (f->offset < first->offset)
7677 if (f->offset > last->offset)
7681 /* Key offset and size. */
7682 key_offset = first->offset / 8;
7683 key_size = (last->offset + last->n_bits - first->offset) / 8;
7685 /* Memory allocation. */
7686 key_mask = calloc(1, key_size);
7693 for (i = 0; i < table->n_fields; i++) {
7694 struct field *f = table->fields[i].field;
7695 uint32_t start = (f->offset - first->offset) / 8;
7696 size_t size = f->n_bits / 8;
7698 memset(&key_mask[start], 0xFF, size);
7701 /* Action data size. */
7702 action_data_size = 0;
7703 for (i = 0; i < table->n_actions; i++) {
7704 struct action *action = table->actions[i];
7705 uint32_t ads = action->st ? action->st->n_bits / 8 : 0;
7707 if (ads > action_data_size)
7708 action_data_size = ads;
7712 params->match_type = table->type->match_type;
7713 params->key_size = key_size;
7714 params->key_offset = key_offset;
7715 params->key_mask0 = key_mask;
7716 params->action_data_size = action_data_size;
7717 params->n_keys_max = table->size;
7723 table_params_free(struct rte_swx_table_params *params)
7728 free(params->key_mask0);
7733 table_stub_lkp(void *table __rte_unused,
7734 void *mailbox __rte_unused,
7735 uint8_t **key __rte_unused,
7736 uint64_t *action_id __rte_unused,
7737 uint8_t **action_data __rte_unused,
7741 return 1; /* DONE. */
7745 table_build(struct rte_swx_pipeline *p)
7749 /* Per pipeline: table statistics. */
7750 p->table_stats = calloc(p->n_tables, sizeof(struct table_statistics));
7751 CHECK(p->table_stats, ENOMEM);
7753 for (i = 0; i < p->n_tables; i++) {
7754 p->table_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
7755 CHECK(p->table_stats[i].n_pkts_action, ENOMEM);
7758 /* Per thread: table runt-time. */
7759 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
7760 struct thread *t = &p->threads[i];
7761 struct table *table;
7763 t->tables = calloc(p->n_tables, sizeof(struct table_runtime));
7764 CHECK(t->tables, ENOMEM);
7766 TAILQ_FOREACH(table, &p->tables, node) {
7767 struct table_runtime *r = &t->tables[table->id];
7772 size = table->type->ops.mailbox_size_get();
7775 r->func = table->type->ops.lkp;
7779 r->mailbox = calloc(1, size);
7780 CHECK(r->mailbox, ENOMEM);
7784 r->key = table->header ?
7785 &t->structs[table->header->struct_id] :
7786 &t->structs[p->metadata_struct_id];
7788 r->func = table_stub_lkp;
7797 table_build_free(struct rte_swx_pipeline *p)
7801 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
7802 struct thread *t = &p->threads[i];
7808 for (j = 0; j < p->n_tables; j++) {
7809 struct table_runtime *r = &t->tables[j];
7818 if (p->table_stats) {
7819 for (i = 0; i < p->n_tables; i++)
7820 free(p->table_stats[i].n_pkts_action);
7822 free(p->table_stats);
7827 table_free(struct rte_swx_pipeline *p)
7829 table_build_free(p);
7835 elem = TAILQ_FIRST(&p->tables);
7839 TAILQ_REMOVE(&p->tables, elem, node);
7841 free(elem->actions);
7842 free(elem->default_action_data);
7848 struct table_type *elem;
7850 elem = TAILQ_FIRST(&p->table_types);
7854 TAILQ_REMOVE(&p->table_types, elem, node);
7862 static struct selector *
7863 selector_find(struct rte_swx_pipeline *p, const char *name)
7867 TAILQ_FOREACH(s, &p->selectors, node)
7868 if (strcmp(s->name, name) == 0)
7874 static struct selector *
7875 selector_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7877 struct selector *s = NULL;
7879 TAILQ_FOREACH(s, &p->selectors, node)
7887 selector_fields_check(struct rte_swx_pipeline *p,
7888 struct rte_swx_pipeline_selector_params *params,
7889 struct header **header)
7891 struct header *h0 = NULL;
7892 struct field *hf, *mf;
7895 /* Return if no selector fields. */
7896 if (!params->n_selector_fields || !params->selector_field_names)
7899 /* Check that all the selector fields either belong to the same header
7900 * or are all meta-data fields.
7902 hf = header_field_parse(p, params->selector_field_names[0], &h0);
7903 mf = metadata_field_parse(p, params->selector_field_names[0]);
7907 for (i = 1; i < params->n_selector_fields; i++)
7911 hf = header_field_parse(p, params->selector_field_names[i], &h);
7912 if (!hf || (h->id != h0->id))
7915 mf = metadata_field_parse(p, params->selector_field_names[i]);
7920 /* Check that there are no duplicated match fields. */
7921 for (i = 0; i < params->n_selector_fields; i++) {
7922 const char *field_name = params->selector_field_names[i];
7925 for (j = i + 1; j < params->n_selector_fields; j++)
7926 if (!strcmp(params->selector_field_names[j], field_name))
7938 rte_swx_pipeline_selector_config(struct rte_swx_pipeline *p,
7940 struct rte_swx_pipeline_selector_params *params)
7943 struct header *selector_header = NULL;
7944 struct field *group_id_field, *member_id_field;
7950 CHECK_NAME(name, EINVAL);
7951 CHECK(!table_find(p, name), EEXIST);
7952 CHECK(!selector_find(p, name), EEXIST);
7953 CHECK(!learner_find(p, name), EEXIST);
7955 CHECK(params, EINVAL);
7957 CHECK_NAME(params->group_id_field_name, EINVAL);
7958 group_id_field = metadata_field_parse(p, params->group_id_field_name);
7959 CHECK(group_id_field, EINVAL);
7961 for (i = 0; i < params->n_selector_fields; i++) {
7962 const char *field_name = params->selector_field_names[i];
7964 CHECK_NAME(field_name, EINVAL);
7966 status = selector_fields_check(p, params, &selector_header);
7970 CHECK_NAME(params->member_id_field_name, EINVAL);
7971 member_id_field = metadata_field_parse(p, params->member_id_field_name);
7972 CHECK(member_id_field, EINVAL);
7974 CHECK(params->n_groups_max, EINVAL);
7976 CHECK(params->n_members_per_group_max, EINVAL);
7978 /* Memory allocation. */
7979 s = calloc(1, sizeof(struct selector));
7985 s->selector_fields = calloc(params->n_selector_fields, sizeof(struct field *));
7986 if (!s->selector_fields) {
7991 /* Node initialization. */
7992 strcpy(s->name, name);
7994 s->group_id_field = group_id_field;
7996 for (i = 0; i < params->n_selector_fields; i++) {
7997 const char *field_name = params->selector_field_names[i];
7999 s->selector_fields[i] = selector_header ?
8000 header_field_parse(p, field_name, NULL) :
8001 metadata_field_parse(p, field_name);
8004 s->n_selector_fields = params->n_selector_fields;
8006 s->selector_header = selector_header;
8008 s->member_id_field = member_id_field;
8010 s->n_groups_max = params->n_groups_max;
8012 s->n_members_per_group_max = params->n_members_per_group_max;
8014 s->id = p->n_selectors;
8016 /* Node add to tailq. */
8017 TAILQ_INSERT_TAIL(&p->selectors, s, node);
8026 free(s->selector_fields);
8034 selector_params_free(struct rte_swx_table_selector_params *params)
8039 free(params->selector_mask);
8044 static struct rte_swx_table_selector_params *
8045 selector_table_params_get(struct selector *s)
8047 struct rte_swx_table_selector_params *params = NULL;
8048 struct field *first, *last;
8051 /* Memory allocation. */
8052 params = calloc(1, sizeof(struct rte_swx_table_selector_params));
8057 params->group_id_offset = s->group_id_field->offset / 8;
8059 /* Find first (smallest offset) and last (biggest offset) selector fields. */
8060 first = s->selector_fields[0];
8061 last = s->selector_fields[0];
8063 for (i = 0; i < s->n_selector_fields; i++) {
8064 struct field *f = s->selector_fields[i];
8066 if (f->offset < first->offset)
8069 if (f->offset > last->offset)
8073 /* Selector offset and size. */
8074 params->selector_offset = first->offset / 8;
8075 params->selector_size = (last->offset + last->n_bits - first->offset) / 8;
8077 /* Memory allocation. */
8078 params->selector_mask = calloc(1, params->selector_size);
8079 if (!params->selector_mask)
8082 /* Selector mask. */
8083 for (i = 0; i < s->n_selector_fields; i++) {
8084 struct field *f = s->selector_fields[i];
8085 uint32_t start = (f->offset - first->offset) / 8;
8086 size_t size = f->n_bits / 8;
8088 memset(¶ms->selector_mask[start], 0xFF, size);
8092 params->member_id_offset = s->member_id_field->offset / 8;
8094 /* Maximum number of groups. */
8095 params->n_groups_max = s->n_groups_max;
8097 /* Maximum number of members per group. */
8098 params->n_members_per_group_max = s->n_members_per_group_max;
8103 selector_params_free(params);
8108 selector_build_free(struct rte_swx_pipeline *p)
8112 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8113 struct thread *t = &p->threads[i];
8119 for (j = 0; j < p->n_selectors; j++) {
8120 struct selector_runtime *r = &t->selectors[j];
8126 t->selectors = NULL;
8129 free(p->selector_stats);
8130 p->selector_stats = NULL;
8134 selector_build(struct rte_swx_pipeline *p)
8139 /* Per pipeline: selector statistics. */
8140 p->selector_stats = calloc(p->n_selectors, sizeof(struct selector_statistics));
8141 if (!p->selector_stats) {
8146 /* Per thread: selector run-time. */
8147 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8148 struct thread *t = &p->threads[i];
8151 t->selectors = calloc(p->n_selectors, sizeof(struct selector_runtime));
8152 if (!t->selectors) {
8157 TAILQ_FOREACH(s, &p->selectors, node) {
8158 struct selector_runtime *r = &t->selectors[s->id];
8162 size = rte_swx_table_selector_mailbox_size_get();
8164 r->mailbox = calloc(1, size);
8171 /* r->group_id_buffer. */
8172 r->group_id_buffer = &t->structs[p->metadata_struct_id];
8174 /* r->selector_buffer. */
8175 r->selector_buffer = s->selector_header ?
8176 &t->structs[s->selector_header->struct_id] :
8177 &t->structs[p->metadata_struct_id];
8179 /* r->member_id_buffer. */
8180 r->member_id_buffer = &t->structs[p->metadata_struct_id];
8187 selector_build_free(p);
8192 selector_free(struct rte_swx_pipeline *p)
8194 selector_build_free(p);
8196 /* Selector tables. */
8198 struct selector *elem;
8200 elem = TAILQ_FIRST(&p->selectors);
8204 TAILQ_REMOVE(&p->selectors, elem, node);
8205 free(elem->selector_fields);
8213 static struct learner *
8214 learner_find(struct rte_swx_pipeline *p, const char *name)
8218 TAILQ_FOREACH(l, &p->learners, node)
8219 if (!strcmp(l->name, name))
8225 static struct learner *
8226 learner_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8228 struct learner *l = NULL;
8230 TAILQ_FOREACH(l, &p->learners, node)
8238 learner_match_fields_check(struct rte_swx_pipeline *p,
8239 struct rte_swx_pipeline_learner_params *params,
8240 struct header **header)
8242 struct header *h0 = NULL;
8243 struct field *hf, *mf;
8246 /* Return if no match fields. */
8247 if (!params->n_fields || !params->field_names)
8250 /* Check that all the match fields either belong to the same header
8251 * or are all meta-data fields.
8253 hf = header_field_parse(p, params->field_names[0], &h0);
8254 mf = metadata_field_parse(p, params->field_names[0]);
8258 for (i = 1; i < params->n_fields; i++)
8262 hf = header_field_parse(p, params->field_names[i], &h);
8263 if (!hf || (h->id != h0->id))
8266 mf = metadata_field_parse(p, params->field_names[i]);
8271 /* Check that there are no duplicated match fields. */
8272 for (i = 0; i < params->n_fields; i++) {
8273 const char *field_name = params->field_names[i];
8276 for (j = i + 1; j < params->n_fields; j++)
8277 if (!strcmp(params->field_names[j], field_name))
8289 learner_action_args_check(struct rte_swx_pipeline *p, struct action *a, const char *mf_name)
8291 struct struct_type *mst = p->metadata_st, *ast = a->st;
8292 struct field *mf, *af;
8302 /* Check that mf_name is the name of a valid meta-data field. */
8303 CHECK_NAME(mf_name, EINVAL);
8304 mf = metadata_field_parse(p, mf_name);
8307 /* Check that there are enough meta-data fields, starting with the mf_name field, to cover
8308 * all the action arguments.
8310 mf_pos = mf - mst->fields;
8311 CHECK(mst->n_fields - mf_pos >= ast->n_fields, EINVAL);
8313 /* Check that the size of each of the identified meta-data fields matches exactly the size
8314 * of the corresponding action argument.
8316 for (i = 0; i < ast->n_fields; i++) {
8317 mf = &mst->fields[mf_pos + i];
8318 af = &ast->fields[i];
8320 CHECK(mf->n_bits == af->n_bits, EINVAL);
8327 learner_action_learning_check(struct rte_swx_pipeline *p,
8328 struct action *action,
8329 const char **action_names,
8334 /* For each "learn" instruction of the current action, check that the learned action (i.e.
8335 * the action passed as argument to the "learn" instruction) is also enabled for the
8336 * current learner table.
8338 for (i = 0; i < action->n_instructions; i++) {
8339 struct instruction *instr = &action->instructions[i];
8340 uint32_t found = 0, j;
8342 if (instr->type != INSTR_LEARNER_LEARN)
8345 for (j = 0; j < n_actions; j++) {
8348 a = action_find(p, action_names[j]);
8352 if (a->id == instr->learn.action_id)
8364 rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p,
8366 struct rte_swx_pipeline_learner_params *params,
8370 struct learner *l = NULL;
8371 struct action *default_action;
8372 struct header *header = NULL;
8373 uint32_t action_data_size_max = 0, i;
8378 CHECK_NAME(name, EINVAL);
8379 CHECK(!table_find(p, name), EEXIST);
8380 CHECK(!selector_find(p, name), EEXIST);
8381 CHECK(!learner_find(p, name), EEXIST);
8383 CHECK(params, EINVAL);
8386 status = learner_match_fields_check(p, params, &header);
8390 /* Action checks. */
8391 CHECK(params->n_actions, EINVAL);
8393 CHECK(params->action_names, EINVAL);
8394 for (i = 0; i < params->n_actions; i++) {
8395 const char *action_name = params->action_names[i];
8396 const char *action_field_name = params->action_field_names[i];
8398 uint32_t action_data_size;
8400 CHECK_NAME(action_name, EINVAL);
8402 a = action_find(p, action_name);
8405 status = learner_action_args_check(p, a, action_field_name);
8409 status = learner_action_learning_check(p,
8411 params->action_names,
8416 action_data_size = a->st ? a->st->n_bits / 8 : 0;
8417 if (action_data_size > action_data_size_max)
8418 action_data_size_max = action_data_size;
8421 CHECK_NAME(params->default_action_name, EINVAL);
8422 for (i = 0; i < p->n_actions; i++)
8423 if (!strcmp(params->action_names[i],
8424 params->default_action_name))
8426 CHECK(i < params->n_actions, EINVAL);
8428 default_action = action_find(p, params->default_action_name);
8429 CHECK((default_action->st && params->default_action_data) ||
8430 !params->default_action_data, EINVAL);
8432 /* Any other checks. */
8433 CHECK(size, EINVAL);
8434 CHECK(timeout, EINVAL);
8436 /* Memory allocation. */
8437 l = calloc(1, sizeof(struct learner));
8441 l->fields = calloc(params->n_fields, sizeof(struct field *));
8445 l->actions = calloc(params->n_actions, sizeof(struct action *));
8449 l->action_arg = calloc(params->n_actions, sizeof(struct field *));
8453 if (action_data_size_max) {
8454 l->default_action_data = calloc(1, action_data_size_max);
8455 if (!l->default_action_data)
8459 /* Node initialization. */
8460 strcpy(l->name, name);
8462 for (i = 0; i < params->n_fields; i++) {
8463 const char *field_name = params->field_names[i];
8465 l->fields[i] = header ?
8466 header_field_parse(p, field_name, NULL) :
8467 metadata_field_parse(p, field_name);
8470 l->n_fields = params->n_fields;
8474 for (i = 0; i < params->n_actions; i++) {
8475 const char *mf_name = params->action_field_names[i];
8477 l->actions[i] = action_find(p, params->action_names[i]);
8479 l->action_arg[i] = mf_name ? metadata_field_parse(p, mf_name) : NULL;
8482 l->default_action = default_action;
8484 if (default_action->st)
8485 memcpy(l->default_action_data,
8486 params->default_action_data,
8487 default_action->st->n_bits / 8);
8489 l->n_actions = params->n_actions;
8491 l->default_action_is_const = params->default_action_is_const;
8493 l->action_data_size_max = action_data_size_max;
8497 l->timeout = timeout;
8499 l->id = p->n_learners;
8501 /* Node add to tailq. */
8502 TAILQ_INSERT_TAIL(&p->learners, l, node);
8511 free(l->action_arg);
8520 learner_params_free(struct rte_swx_table_learner_params *params)
8525 free(params->key_mask0);
8530 static struct rte_swx_table_learner_params *
8531 learner_params_get(struct learner *l)
8533 struct rte_swx_table_learner_params *params = NULL;
8534 struct field *first, *last;
8537 /* Memory allocation. */
8538 params = calloc(1, sizeof(struct rte_swx_table_learner_params));
8542 /* Find first (smallest offset) and last (biggest offset) match fields. */
8543 first = l->fields[0];
8544 last = l->fields[0];
8546 for (i = 0; i < l->n_fields; i++) {
8547 struct field *f = l->fields[i];
8549 if (f->offset < first->offset)
8552 if (f->offset > last->offset)
8556 /* Key offset and size. */
8557 params->key_offset = first->offset / 8;
8558 params->key_size = (last->offset + last->n_bits - first->offset) / 8;
8560 /* Memory allocation. */
8561 params->key_mask0 = calloc(1, params->key_size);
8562 if (!params->key_mask0)
8566 for (i = 0; i < l->n_fields; i++) {
8567 struct field *f = l->fields[i];
8568 uint32_t start = (f->offset - first->offset) / 8;
8569 size_t size = f->n_bits / 8;
8571 memset(¶ms->key_mask0[start], 0xFF, size);
8574 /* Action data size. */
8575 params->action_data_size = l->action_data_size_max;
8577 /* Maximum number of keys. */
8578 params->n_keys_max = l->size;
8581 params->key_timeout = l->timeout;
8586 learner_params_free(params);
8591 learner_build_free(struct rte_swx_pipeline *p)
8595 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8596 struct thread *t = &p->threads[i];
8602 for (j = 0; j < p->n_learners; j++) {
8603 struct learner_runtime *r = &t->learners[j];
8606 free(r->action_data);
8613 if (p->learner_stats) {
8614 for (i = 0; i < p->n_learners; i++)
8615 free(p->learner_stats[i].n_pkts_action);
8617 free(p->learner_stats);
8622 learner_build(struct rte_swx_pipeline *p)
8627 /* Per pipeline: learner statistics. */
8628 p->learner_stats = calloc(p->n_learners, sizeof(struct learner_statistics));
8629 CHECK(p->learner_stats, ENOMEM);
8631 for (i = 0; i < p->n_learners; i++) {
8632 p->learner_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
8633 CHECK(p->learner_stats[i].n_pkts_action, ENOMEM);
8636 /* Per thread: learner run-time. */
8637 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8638 struct thread *t = &p->threads[i];
8641 t->learners = calloc(p->n_learners, sizeof(struct learner_runtime));
8647 TAILQ_FOREACH(l, &p->learners, node) {
8648 struct learner_runtime *r = &t->learners[l->id];
8653 size = rte_swx_table_learner_mailbox_size_get();
8655 r->mailbox = calloc(1, size);
8663 r->key = l->header ?
8664 &t->structs[l->header->struct_id] :
8665 &t->structs[p->metadata_struct_id];
8667 /* r->action_data. */
8668 r->action_data = calloc(p->n_actions, sizeof(uint8_t *));
8669 if (!r->action_data) {
8674 for (j = 0; j < l->n_actions; j++) {
8675 struct action *a = l->actions[j];
8676 struct field *mf = l->action_arg[j];
8677 uint8_t *m = t->structs[p->metadata_struct_id];
8679 r->action_data[a->id] = mf ? &m[mf->offset / 8] : NULL;
8687 learner_build_free(p);
8692 learner_free(struct rte_swx_pipeline *p)
8694 learner_build_free(p);
8696 /* Learner tables. */
8700 l = TAILQ_FIRST(&p->learners);
8704 TAILQ_REMOVE(&p->learners, l, node);
8707 free(l->action_arg);
8708 free(l->default_action_data);
8717 table_state_build(struct rte_swx_pipeline *p)
8719 struct table *table;
8723 p->table_state = calloc(p->n_tables + p->n_selectors,
8724 sizeof(struct rte_swx_table_state));
8725 CHECK(p->table_state, ENOMEM);
8727 TAILQ_FOREACH(table, &p->tables, node) {
8728 struct rte_swx_table_state *ts = &p->table_state[table->id];
8731 struct rte_swx_table_params *params;
8734 params = table_params_get(table);
8735 CHECK(params, ENOMEM);
8737 ts->obj = table->type->ops.create(params,
8742 table_params_free(params);
8743 CHECK(ts->obj, ENODEV);
8746 /* ts->default_action_data. */
8747 if (table->action_data_size_max) {
8748 ts->default_action_data =
8749 malloc(table->action_data_size_max);
8750 CHECK(ts->default_action_data, ENOMEM);
8752 memcpy(ts->default_action_data,
8753 table->default_action_data,
8754 table->action_data_size_max);
8757 /* ts->default_action_id. */
8758 ts->default_action_id = table->default_action->id;
8761 TAILQ_FOREACH(s, &p->selectors, node) {
8762 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + s->id];
8763 struct rte_swx_table_selector_params *params;
8766 params = selector_table_params_get(s);
8767 CHECK(params, ENOMEM);
8769 ts->obj = rte_swx_table_selector_create(params, NULL, p->numa_node);
8771 selector_params_free(params);
8772 CHECK(ts->obj, ENODEV);
8775 TAILQ_FOREACH(l, &p->learners, node) {
8776 struct rte_swx_table_state *ts = &p->table_state[p->n_tables +
8777 p->n_selectors + l->id];
8778 struct rte_swx_table_learner_params *params;
8781 params = learner_params_get(l);
8782 CHECK(params, ENOMEM);
8784 ts->obj = rte_swx_table_learner_create(params, p->numa_node);
8785 learner_params_free(params);
8786 CHECK(ts->obj, ENODEV);
8788 /* ts->default_action_data. */
8789 if (l->action_data_size_max) {
8790 ts->default_action_data = malloc(l->action_data_size_max);
8791 CHECK(ts->default_action_data, ENOMEM);
8793 memcpy(ts->default_action_data,
8794 l->default_action_data,
8795 l->action_data_size_max);
8798 /* ts->default_action_id. */
8799 ts->default_action_id = l->default_action->id;
8806 table_state_build_free(struct rte_swx_pipeline *p)
8810 if (!p->table_state)
8813 for (i = 0; i < p->n_tables; i++) {
8814 struct rte_swx_table_state *ts = &p->table_state[i];
8815 struct table *table = table_find_by_id(p, i);
8818 if (table->type && ts->obj)
8819 table->type->ops.free(ts->obj);
8821 /* ts->default_action_data. */
8822 free(ts->default_action_data);
8825 for (i = 0; i < p->n_selectors; i++) {
8826 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + i];
8830 rte_swx_table_selector_free(ts->obj);
8833 for (i = 0; i < p->n_learners; i++) {
8834 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + p->n_selectors + i];
8838 rte_swx_table_learner_free(ts->obj);
8840 /* ts->default_action_data. */
8841 free(ts->default_action_data);
8844 free(p->table_state);
8845 p->table_state = NULL;
8849 table_state_free(struct rte_swx_pipeline *p)
8851 table_state_build_free(p);
8857 static struct regarray *
8858 regarray_find(struct rte_swx_pipeline *p, const char *name)
8860 struct regarray *elem;
8862 TAILQ_FOREACH(elem, &p->regarrays, node)
8863 if (!strcmp(elem->name, name))
8869 static struct regarray *
8870 regarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8872 struct regarray *elem = NULL;
8874 TAILQ_FOREACH(elem, &p->regarrays, node)
8882 rte_swx_pipeline_regarray_config(struct rte_swx_pipeline *p,
8891 CHECK_NAME(name, EINVAL);
8892 CHECK(!regarray_find(p, name), EEXIST);
8894 CHECK(size, EINVAL);
8895 size = rte_align32pow2(size);
8897 /* Memory allocation. */
8898 r = calloc(1, sizeof(struct regarray));
8901 /* Node initialization. */
8902 strcpy(r->name, name);
8903 r->init_val = init_val;
8905 r->id = p->n_regarrays;
8907 /* Node add to tailq. */
8908 TAILQ_INSERT_TAIL(&p->regarrays, r, node);
8915 regarray_build(struct rte_swx_pipeline *p)
8917 struct regarray *regarray;
8919 if (!p->n_regarrays)
8922 p->regarray_runtime = calloc(p->n_regarrays, sizeof(struct regarray_runtime));
8923 CHECK(p->regarray_runtime, ENOMEM);
8925 TAILQ_FOREACH(regarray, &p->regarrays, node) {
8926 struct regarray_runtime *r = &p->regarray_runtime[regarray->id];
8929 r->regarray = env_malloc(regarray->size * sizeof(uint64_t),
8930 RTE_CACHE_LINE_SIZE,
8932 CHECK(r->regarray, ENOMEM);
8934 if (regarray->init_val)
8935 for (i = 0; i < regarray->size; i++)
8936 r->regarray[i] = regarray->init_val;
8938 r->size_mask = regarray->size - 1;
8945 regarray_build_free(struct rte_swx_pipeline *p)
8949 if (!p->regarray_runtime)
8952 for (i = 0; i < p->n_regarrays; i++) {
8953 struct regarray *regarray = regarray_find_by_id(p, i);
8954 struct regarray_runtime *r = &p->regarray_runtime[i];
8956 env_free(r->regarray, regarray->size * sizeof(uint64_t));
8959 free(p->regarray_runtime);
8960 p->regarray_runtime = NULL;
8964 regarray_free(struct rte_swx_pipeline *p)
8966 regarray_build_free(p);
8969 struct regarray *elem;
8971 elem = TAILQ_FIRST(&p->regarrays);
8975 TAILQ_REMOVE(&p->regarrays, elem, node);
8983 static struct meter_profile *
8984 meter_profile_find(struct rte_swx_pipeline *p, const char *name)
8986 struct meter_profile *elem;
8988 TAILQ_FOREACH(elem, &p->meter_profiles, node)
8989 if (!strcmp(elem->name, name))
8995 static struct metarray *
8996 metarray_find(struct rte_swx_pipeline *p, const char *name)
8998 struct metarray *elem;
9000 TAILQ_FOREACH(elem, &p->metarrays, node)
9001 if (!strcmp(elem->name, name))
9007 static struct metarray *
9008 metarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9010 struct metarray *elem = NULL;
9012 TAILQ_FOREACH(elem, &p->metarrays, node)
9020 rte_swx_pipeline_metarray_config(struct rte_swx_pipeline *p,
9028 CHECK_NAME(name, EINVAL);
9029 CHECK(!metarray_find(p, name), EEXIST);
9031 CHECK(size, EINVAL);
9032 size = rte_align32pow2(size);
9034 /* Memory allocation. */
9035 m = calloc(1, sizeof(struct metarray));
9038 /* Node initialization. */
9039 strcpy(m->name, name);
9041 m->id = p->n_metarrays;
9043 /* Node add to tailq. */
9044 TAILQ_INSERT_TAIL(&p->metarrays, m, node);
9050 struct meter_profile meter_profile_default = {
9059 .cir_bytes_per_period = 1,
9061 .pir_bytes_per_period = 1,
9068 meter_init(struct meter *m)
9070 memset(m, 0, sizeof(struct meter));
9071 rte_meter_trtcm_config(&m->m, &meter_profile_default.profile);
9072 m->profile = &meter_profile_default;
9073 m->color_mask = RTE_COLOR_GREEN;
9075 meter_profile_default.n_users++;
9079 metarray_build(struct rte_swx_pipeline *p)
9083 if (!p->n_metarrays)
9086 p->metarray_runtime = calloc(p->n_metarrays, sizeof(struct metarray_runtime));
9087 CHECK(p->metarray_runtime, ENOMEM);
9089 TAILQ_FOREACH(m, &p->metarrays, node) {
9090 struct metarray_runtime *r = &p->metarray_runtime[m->id];
9093 r->metarray = env_malloc(m->size * sizeof(struct meter),
9094 RTE_CACHE_LINE_SIZE,
9096 CHECK(r->metarray, ENOMEM);
9098 for (i = 0; i < m->size; i++)
9099 meter_init(&r->metarray[i]);
9101 r->size_mask = m->size - 1;
9108 metarray_build_free(struct rte_swx_pipeline *p)
9112 if (!p->metarray_runtime)
9115 for (i = 0; i < p->n_metarrays; i++) {
9116 struct metarray *m = metarray_find_by_id(p, i);
9117 struct metarray_runtime *r = &p->metarray_runtime[i];
9119 env_free(r->metarray, m->size * sizeof(struct meter));
9122 free(p->metarray_runtime);
9123 p->metarray_runtime = NULL;
9127 metarray_free(struct rte_swx_pipeline *p)
9129 metarray_build_free(p);
9133 struct metarray *elem;
9135 elem = TAILQ_FIRST(&p->metarrays);
9139 TAILQ_REMOVE(&p->metarrays, elem, node);
9143 /* Meter profiles. */
9145 struct meter_profile *elem;
9147 elem = TAILQ_FIRST(&p->meter_profiles);
9151 TAILQ_REMOVE(&p->meter_profiles, elem, node);
9160 rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
9162 struct rte_swx_pipeline *pipeline;
9164 /* Check input parameters. */
9167 /* Memory allocation. */
9168 pipeline = calloc(1, sizeof(struct rte_swx_pipeline));
9169 CHECK(pipeline, ENOMEM);
9171 /* Initialization. */
9172 TAILQ_INIT(&pipeline->struct_types);
9173 TAILQ_INIT(&pipeline->port_in_types);
9174 TAILQ_INIT(&pipeline->ports_in);
9175 TAILQ_INIT(&pipeline->port_out_types);
9176 TAILQ_INIT(&pipeline->ports_out);
9177 TAILQ_INIT(&pipeline->extern_types);
9178 TAILQ_INIT(&pipeline->extern_objs);
9179 TAILQ_INIT(&pipeline->extern_funcs);
9180 TAILQ_INIT(&pipeline->headers);
9181 TAILQ_INIT(&pipeline->actions);
9182 TAILQ_INIT(&pipeline->table_types);
9183 TAILQ_INIT(&pipeline->tables);
9184 TAILQ_INIT(&pipeline->selectors);
9185 TAILQ_INIT(&pipeline->learners);
9186 TAILQ_INIT(&pipeline->regarrays);
9187 TAILQ_INIT(&pipeline->meter_profiles);
9188 TAILQ_INIT(&pipeline->metarrays);
9190 pipeline->n_structs = 1; /* Struct 0 is reserved for action_data. */
9191 pipeline->numa_node = numa_node;
9198 rte_swx_pipeline_free(struct rte_swx_pipeline *p)
9203 free(p->instructions);
9207 table_state_free(p);
9214 extern_func_free(p);
9224 rte_swx_pipeline_instructions_config(struct rte_swx_pipeline *p,
9225 const char **instructions,
9226 uint32_t n_instructions)
9231 err = instruction_config(p, NULL, instructions, n_instructions);
9235 /* Thread instruction pointer reset. */
9236 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9237 struct thread *t = &p->threads[i];
9239 thread_ip_reset(p, t);
9246 rte_swx_pipeline_build(struct rte_swx_pipeline *p)
9251 CHECK(p->build_done == 0, EEXIST);
9253 status = port_in_build(p);
9257 status = port_out_build(p);
9261 status = struct_build(p);
9265 status = extern_obj_build(p);
9269 status = extern_func_build(p);
9273 status = header_build(p);
9277 status = metadata_build(p);
9281 status = action_build(p);
9285 status = table_build(p);
9289 status = selector_build(p);
9293 status = learner_build(p);
9297 status = table_state_build(p);
9301 status = regarray_build(p);
9305 status = metarray_build(p);
9313 metarray_build_free(p);
9314 regarray_build_free(p);
9315 table_state_build_free(p);
9316 learner_build_free(p);
9317 selector_build_free(p);
9318 table_build_free(p);
9319 action_build_free(p);
9320 metadata_build_free(p);
9321 header_build_free(p);
9322 extern_func_build_free(p);
9323 extern_obj_build_free(p);
9324 port_out_build_free(p);
9325 port_in_build_free(p);
9326 struct_build_free(p);
9332 rte_swx_pipeline_run(struct rte_swx_pipeline *p, uint32_t n_instructions)
9336 for (i = 0; i < n_instructions; i++)
9341 rte_swx_pipeline_flush(struct rte_swx_pipeline *p)
9345 for (i = 0; i < p->n_ports_out; i++) {
9346 struct port_out_runtime *port = &p->out[i];
9349 port->flush(port->obj);
9357 rte_swx_ctl_pipeline_info_get(struct rte_swx_pipeline *p,
9358 struct rte_swx_ctl_pipeline_info *pipeline)
9360 struct action *action;
9361 struct table *table;
9362 uint32_t n_actions = 0, n_tables = 0;
9364 if (!p || !pipeline)
9367 TAILQ_FOREACH(action, &p->actions, node)
9370 TAILQ_FOREACH(table, &p->tables, node)
9373 pipeline->n_ports_in = p->n_ports_in;
9374 pipeline->n_ports_out = p->n_ports_out;
9375 pipeline->n_actions = n_actions;
9376 pipeline->n_tables = n_tables;
9377 pipeline->n_selectors = p->n_selectors;
9378 pipeline->n_learners = p->n_learners;
9379 pipeline->n_regarrays = p->n_regarrays;
9380 pipeline->n_metarrays = p->n_metarrays;
9386 rte_swx_ctl_pipeline_numa_node_get(struct rte_swx_pipeline *p, int *numa_node)
9388 if (!p || !numa_node)
9391 *numa_node = p->numa_node;
9396 rte_swx_ctl_action_info_get(struct rte_swx_pipeline *p,
9398 struct rte_swx_ctl_action_info *action)
9400 struct action *a = NULL;
9402 if (!p || (action_id >= p->n_actions) || !action)
9405 a = action_find_by_id(p, action_id);
9409 strcpy(action->name, a->name);
9410 action->n_args = a->st ? a->st->n_fields : 0;
9415 rte_swx_ctl_action_arg_info_get(struct rte_swx_pipeline *p,
9417 uint32_t action_arg_id,
9418 struct rte_swx_ctl_action_arg_info *action_arg)
9420 struct action *a = NULL;
9421 struct field *arg = NULL;
9423 if (!p || (action_id >= p->n_actions) || !action_arg)
9426 a = action_find_by_id(p, action_id);
9427 if (!a || !a->st || (action_arg_id >= a->st->n_fields))
9430 arg = &a->st->fields[action_arg_id];
9431 strcpy(action_arg->name, arg->name);
9432 action_arg->n_bits = arg->n_bits;
9433 action_arg->is_network_byte_order = a->args_endianness[action_arg_id];
9439 rte_swx_ctl_table_info_get(struct rte_swx_pipeline *p,
9441 struct rte_swx_ctl_table_info *table)
9443 struct table *t = NULL;
9448 t = table_find_by_id(p, table_id);
9452 strcpy(table->name, t->name);
9453 strcpy(table->args, t->args);
9454 table->n_match_fields = t->n_fields;
9455 table->n_actions = t->n_actions;
9456 table->default_action_is_const = t->default_action_is_const;
9457 table->size = t->size;
9462 rte_swx_ctl_table_match_field_info_get(struct rte_swx_pipeline *p,
9464 uint32_t match_field_id,
9465 struct rte_swx_ctl_table_match_field_info *match_field)
9468 struct match_field *f;
9470 if (!p || (table_id >= p->n_tables) || !match_field)
9473 t = table_find_by_id(p, table_id);
9474 if (!t || (match_field_id >= t->n_fields))
9477 f = &t->fields[match_field_id];
9478 match_field->match_type = f->match_type;
9479 match_field->is_header = t->header ? 1 : 0;
9480 match_field->n_bits = f->field->n_bits;
9481 match_field->offset = f->field->offset;
9487 rte_swx_ctl_table_action_info_get(struct rte_swx_pipeline *p,
9489 uint32_t table_action_id,
9490 struct rte_swx_ctl_table_action_info *table_action)
9494 if (!p || (table_id >= p->n_tables) || !table_action)
9497 t = table_find_by_id(p, table_id);
9498 if (!t || (table_action_id >= t->n_actions))
9501 table_action->action_id = t->actions[table_action_id]->id;
9507 rte_swx_ctl_table_ops_get(struct rte_swx_pipeline *p,
9509 struct rte_swx_table_ops *table_ops,
9514 if (!p || (table_id >= p->n_tables))
9517 t = table_find_by_id(p, table_id);
9523 memcpy(table_ops, &t->type->ops, sizeof(*table_ops));
9533 rte_swx_ctl_selector_info_get(struct rte_swx_pipeline *p,
9534 uint32_t selector_id,
9535 struct rte_swx_ctl_selector_info *selector)
9537 struct selector *s = NULL;
9539 if (!p || !selector)
9542 s = selector_find_by_id(p, selector_id);
9546 strcpy(selector->name, s->name);
9548 selector->n_selector_fields = s->n_selector_fields;
9549 selector->n_groups_max = s->n_groups_max;
9550 selector->n_members_per_group_max = s->n_members_per_group_max;
9556 rte_swx_ctl_selector_group_id_field_info_get(struct rte_swx_pipeline *p,
9557 uint32_t selector_id,
9558 struct rte_swx_ctl_table_match_field_info *field)
9562 if (!p || (selector_id >= p->n_selectors) || !field)
9565 s = selector_find_by_id(p, selector_id);
9569 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
9570 field->is_header = 0;
9571 field->n_bits = s->group_id_field->n_bits;
9572 field->offset = s->group_id_field->offset;
9578 rte_swx_ctl_selector_field_info_get(struct rte_swx_pipeline *p,
9579 uint32_t selector_id,
9580 uint32_t selector_field_id,
9581 struct rte_swx_ctl_table_match_field_info *field)
9586 if (!p || (selector_id >= p->n_selectors) || !field)
9589 s = selector_find_by_id(p, selector_id);
9590 if (!s || (selector_field_id >= s->n_selector_fields))
9593 f = s->selector_fields[selector_field_id];
9594 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
9595 field->is_header = s->selector_header ? 1 : 0;
9596 field->n_bits = f->n_bits;
9597 field->offset = f->offset;
9603 rte_swx_ctl_selector_member_id_field_info_get(struct rte_swx_pipeline *p,
9604 uint32_t selector_id,
9605 struct rte_swx_ctl_table_match_field_info *field)
9609 if (!p || (selector_id >= p->n_selectors) || !field)
9612 s = selector_find_by_id(p, selector_id);
9616 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
9617 field->is_header = 0;
9618 field->n_bits = s->member_id_field->n_bits;
9619 field->offset = s->member_id_field->offset;
9625 rte_swx_ctl_learner_info_get(struct rte_swx_pipeline *p,
9626 uint32_t learner_id,
9627 struct rte_swx_ctl_learner_info *learner)
9629 struct learner *l = NULL;
9634 l = learner_find_by_id(p, learner_id);
9638 strcpy(learner->name, l->name);
9640 learner->n_match_fields = l->n_fields;
9641 learner->n_actions = l->n_actions;
9642 learner->default_action_is_const = l->default_action_is_const;
9643 learner->size = l->size;
9649 rte_swx_ctl_learner_match_field_info_get(struct rte_swx_pipeline *p,
9650 uint32_t learner_id,
9651 uint32_t match_field_id,
9652 struct rte_swx_ctl_table_match_field_info *match_field)
9657 if (!p || (learner_id >= p->n_learners) || !match_field)
9660 l = learner_find_by_id(p, learner_id);
9661 if (!l || (match_field_id >= l->n_fields))
9664 f = l->fields[match_field_id];
9665 match_field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
9666 match_field->is_header = l->header ? 1 : 0;
9667 match_field->n_bits = f->n_bits;
9668 match_field->offset = f->offset;
9674 rte_swx_ctl_learner_action_info_get(struct rte_swx_pipeline *p,
9675 uint32_t learner_id,
9676 uint32_t learner_action_id,
9677 struct rte_swx_ctl_table_action_info *learner_action)
9681 if (!p || (learner_id >= p->n_learners) || !learner_action)
9684 l = learner_find_by_id(p, learner_id);
9685 if (!l || (learner_action_id >= l->n_actions))
9688 learner_action->action_id = l->actions[learner_action_id]->id;
9694 rte_swx_pipeline_table_state_get(struct rte_swx_pipeline *p,
9695 struct rte_swx_table_state **table_state)
9697 if (!p || !table_state || !p->build_done)
9700 *table_state = p->table_state;
9705 rte_swx_pipeline_table_state_set(struct rte_swx_pipeline *p,
9706 struct rte_swx_table_state *table_state)
9708 if (!p || !table_state || !p->build_done)
9711 p->table_state = table_state;
9716 rte_swx_ctl_pipeline_port_in_stats_read(struct rte_swx_pipeline *p,
9718 struct rte_swx_port_in_stats *stats)
9720 struct port_in *port;
9725 port = port_in_find(p, port_id);
9729 port->type->ops.stats_read(port->obj, stats);
9734 rte_swx_ctl_pipeline_port_out_stats_read(struct rte_swx_pipeline *p,
9736 struct rte_swx_port_out_stats *stats)
9738 struct port_out *port;
9743 port = port_out_find(p, port_id);
9747 port->type->ops.stats_read(port->obj, stats);
9752 rte_swx_ctl_pipeline_table_stats_read(struct rte_swx_pipeline *p,
9753 const char *table_name,
9754 struct rte_swx_table_stats *stats)
9756 struct table *table;
9757 struct table_statistics *table_stats;
9759 if (!p || !table_name || !table_name[0] || !stats || !stats->n_pkts_action)
9762 table = table_find(p, table_name);
9766 table_stats = &p->table_stats[table->id];
9768 memcpy(stats->n_pkts_action,
9769 table_stats->n_pkts_action,
9770 p->n_actions * sizeof(uint64_t));
9772 stats->n_pkts_hit = table_stats->n_pkts_hit[1];
9773 stats->n_pkts_miss = table_stats->n_pkts_hit[0];
9779 rte_swx_ctl_pipeline_selector_stats_read(struct rte_swx_pipeline *p,
9780 const char *selector_name,
9781 struct rte_swx_pipeline_selector_stats *stats)
9785 if (!p || !selector_name || !selector_name[0] || !stats)
9788 s = selector_find(p, selector_name);
9792 stats->n_pkts = p->selector_stats[s->id].n_pkts;
9798 rte_swx_ctl_pipeline_learner_stats_read(struct rte_swx_pipeline *p,
9799 const char *learner_name,
9800 struct rte_swx_learner_stats *stats)
9803 struct learner_statistics *learner_stats;
9805 if (!p || !learner_name || !learner_name[0] || !stats || !stats->n_pkts_action)
9808 l = learner_find(p, learner_name);
9812 learner_stats = &p->learner_stats[l->id];
9814 memcpy(stats->n_pkts_action,
9815 learner_stats->n_pkts_action,
9816 p->n_actions * sizeof(uint64_t));
9818 stats->n_pkts_hit = learner_stats->n_pkts_hit[1];
9819 stats->n_pkts_miss = learner_stats->n_pkts_hit[0];
9821 stats->n_pkts_learn_ok = learner_stats->n_pkts_learn[0];
9822 stats->n_pkts_learn_err = learner_stats->n_pkts_learn[1];
9824 stats->n_pkts_forget = learner_stats->n_pkts_forget;
9830 rte_swx_ctl_regarray_info_get(struct rte_swx_pipeline *p,
9831 uint32_t regarray_id,
9832 struct rte_swx_ctl_regarray_info *regarray)
9836 if (!p || !regarray)
9839 r = regarray_find_by_id(p, regarray_id);
9843 strcpy(regarray->name, r->name);
9844 regarray->size = r->size;
9849 rte_swx_ctl_pipeline_regarray_read(struct rte_swx_pipeline *p,
9850 const char *regarray_name,
9851 uint32_t regarray_index,
9854 struct regarray *regarray;
9855 struct regarray_runtime *r;
9857 if (!p || !regarray_name || !value)
9860 regarray = regarray_find(p, regarray_name);
9861 if (!regarray || (regarray_index >= regarray->size))
9864 r = &p->regarray_runtime[regarray->id];
9865 *value = r->regarray[regarray_index];
9870 rte_swx_ctl_pipeline_regarray_write(struct rte_swx_pipeline *p,
9871 const char *regarray_name,
9872 uint32_t regarray_index,
9875 struct regarray *regarray;
9876 struct regarray_runtime *r;
9878 if (!p || !regarray_name)
9881 regarray = regarray_find(p, regarray_name);
9882 if (!regarray || (regarray_index >= regarray->size))
9885 r = &p->regarray_runtime[regarray->id];
9886 r->regarray[regarray_index] = value;
9891 rte_swx_ctl_metarray_info_get(struct rte_swx_pipeline *p,
9892 uint32_t metarray_id,
9893 struct rte_swx_ctl_metarray_info *metarray)
9897 if (!p || !metarray)
9900 m = metarray_find_by_id(p, metarray_id);
9904 strcpy(metarray->name, m->name);
9905 metarray->size = m->size;
9910 rte_swx_ctl_meter_profile_add(struct rte_swx_pipeline *p,
9912 struct rte_meter_trtcm_params *params)
9914 struct meter_profile *mp;
9918 CHECK_NAME(name, EINVAL);
9919 CHECK(params, EINVAL);
9920 CHECK(!meter_profile_find(p, name), EEXIST);
9922 /* Node allocation. */
9923 mp = calloc(1, sizeof(struct meter_profile));
9926 /* Node initialization. */
9927 strcpy(mp->name, name);
9928 memcpy(&mp->params, params, sizeof(struct rte_meter_trtcm_params));
9929 status = rte_meter_trtcm_profile_config(&mp->profile, params);
9935 /* Node add to tailq. */
9936 TAILQ_INSERT_TAIL(&p->meter_profiles, mp, node);
9942 rte_swx_ctl_meter_profile_delete(struct rte_swx_pipeline *p,
9945 struct meter_profile *mp;
9948 CHECK_NAME(name, EINVAL);
9950 mp = meter_profile_find(p, name);
9952 CHECK(!mp->n_users, EBUSY);
9954 /* Remove node from tailq. */
9955 TAILQ_REMOVE(&p->meter_profiles, mp, node);
9962 rte_swx_ctl_meter_reset(struct rte_swx_pipeline *p,
9963 const char *metarray_name,
9964 uint32_t metarray_index)
9966 struct meter_profile *mp_old;
9967 struct metarray *metarray;
9968 struct metarray_runtime *metarray_runtime;
9972 CHECK_NAME(metarray_name, EINVAL);
9974 metarray = metarray_find(p, metarray_name);
9975 CHECK(metarray, EINVAL);
9976 CHECK(metarray_index < metarray->size, EINVAL);
9978 metarray_runtime = &p->metarray_runtime[metarray->id];
9979 m = &metarray_runtime->metarray[metarray_index];
9980 mp_old = m->profile;
9990 rte_swx_ctl_meter_set(struct rte_swx_pipeline *p,
9991 const char *metarray_name,
9992 uint32_t metarray_index,
9993 const char *profile_name)
9995 struct meter_profile *mp, *mp_old;
9996 struct metarray *metarray;
9997 struct metarray_runtime *metarray_runtime;
10001 CHECK_NAME(metarray_name, EINVAL);
10003 metarray = metarray_find(p, metarray_name);
10004 CHECK(metarray, EINVAL);
10005 CHECK(metarray_index < metarray->size, EINVAL);
10007 mp = meter_profile_find(p, profile_name);
10010 metarray_runtime = &p->metarray_runtime[metarray->id];
10011 m = &metarray_runtime->metarray[metarray_index];
10012 mp_old = m->profile;
10014 memset(m, 0, sizeof(struct meter));
10015 rte_meter_trtcm_config(&m->m, &mp->profile);
10017 m->color_mask = RTE_COLORS;
10026 rte_swx_ctl_meter_stats_read(struct rte_swx_pipeline *p,
10027 const char *metarray_name,
10028 uint32_t metarray_index,
10029 struct rte_swx_ctl_meter_stats *stats)
10031 struct metarray *metarray;
10032 struct metarray_runtime *metarray_runtime;
10036 CHECK_NAME(metarray_name, EINVAL);
10038 metarray = metarray_find(p, metarray_name);
10039 CHECK(metarray, EINVAL);
10040 CHECK(metarray_index < metarray->size, EINVAL);
10042 CHECK(stats, EINVAL);
10044 metarray_runtime = &p->metarray_runtime[metarray->id];
10045 m = &metarray_runtime->metarray[metarray_index];
10047 memcpy(stats->n_pkts, m->n_pkts, sizeof(m->n_pkts));
10048 memcpy(stats->n_bytes, m->n_bytes, sizeof(m->n_bytes));