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 emit_handler(struct thread *t)
1573 struct header_out_runtime *h0 = &t->headers_out[0];
1574 struct header_out_runtime *h1 = &t->headers_out[1];
1575 uint32_t offset = 0, i;
1577 /* No header change or header decapsulation. */
1578 if ((t->n_headers_out == 1) &&
1579 (h0->ptr + h0->n_bytes == t->ptr)) {
1580 TRACE("Emit handler: no header change or header decap.\n");
1582 t->pkt.offset -= h0->n_bytes;
1583 t->pkt.length += h0->n_bytes;
1588 /* Header encapsulation (optionally, with prior header decasulation). */
1589 if ((t->n_headers_out == 2) &&
1590 (h1->ptr + h1->n_bytes == t->ptr) &&
1591 (h0->ptr == h0->ptr0)) {
1594 TRACE("Emit handler: header encapsulation.\n");
1596 offset = h0->n_bytes + h1->n_bytes;
1597 memcpy(t->ptr - offset, h0->ptr, h0->n_bytes);
1598 t->pkt.offset -= offset;
1599 t->pkt.length += offset;
1604 /* Header insertion. */
1607 /* Header extraction. */
1610 /* For any other case. */
1611 TRACE("Emit handler: complex case.\n");
1613 for (i = 0; i < t->n_headers_out; i++) {
1614 struct header_out_runtime *h = &t->headers_out[i];
1616 memcpy(&t->header_out_storage[offset], h->ptr, h->n_bytes);
1617 offset += h->n_bytes;
1621 memcpy(t->ptr - offset, t->header_out_storage, offset);
1622 t->pkt.offset -= offset;
1623 t->pkt.length += offset;
1628 instr_tx_exec(struct rte_swx_pipeline *p);
1631 instr_tx_exec(struct rte_swx_pipeline *p)
1633 struct thread *t = &p->threads[p->thread_id];
1634 struct instruction *ip = t->ip;
1635 uint64_t port_id = METADATA_READ(t, ip->io.io.offset, ip->io.io.n_bits);
1636 struct port_out_runtime *port = &p->out[port_id];
1637 struct rte_swx_pkt *pkt = &t->pkt;
1639 TRACE("[Thread %2u]: tx 1 pkt to port %u\n",
1647 port->pkt_tx(port->obj, pkt);
1650 thread_ip_reset(p, t);
1655 instr_tx_i_exec(struct rte_swx_pipeline *p)
1657 struct thread *t = &p->threads[p->thread_id];
1658 struct instruction *ip = t->ip;
1659 uint64_t port_id = ip->io.io.val;
1660 struct port_out_runtime *port = &p->out[port_id];
1661 struct rte_swx_pkt *pkt = &t->pkt;
1663 TRACE("[Thread %2u]: tx (i) 1 pkt to port %u\n",
1671 port->pkt_tx(port->obj, pkt);
1674 thread_ip_reset(p, t);
1682 instr_hdr_extract_translate(struct rte_swx_pipeline *p,
1683 struct action *action,
1686 struct instruction *instr,
1687 struct instruction_data *data __rte_unused)
1691 CHECK(!action, EINVAL);
1692 CHECK((n_tokens == 2) || (n_tokens == 3), EINVAL);
1694 h = header_parse(p, tokens[1]);
1697 if (n_tokens == 2) {
1698 CHECK(!h->st->var_size, EINVAL);
1700 instr->type = INSTR_HDR_EXTRACT;
1701 instr->io.hdr.header_id[0] = h->id;
1702 instr->io.hdr.struct_id[0] = h->struct_id;
1703 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
1707 CHECK(h->st->var_size, EINVAL);
1709 mf = metadata_field_parse(p, tokens[2]);
1711 CHECK(!mf->var_size, EINVAL);
1713 instr->type = INSTR_HDR_EXTRACT_M;
1714 instr->io.io.offset = mf->offset / 8;
1715 instr->io.io.n_bits = mf->n_bits;
1716 instr->io.hdr.header_id[0] = h->id;
1717 instr->io.hdr.struct_id[0] = h->struct_id;
1718 instr->io.hdr.n_bytes[0] = h->st->n_bits_min / 8;
1725 instr_hdr_lookahead_translate(struct rte_swx_pipeline *p,
1726 struct action *action,
1729 struct instruction *instr,
1730 struct instruction_data *data __rte_unused)
1734 CHECK(!action, EINVAL);
1735 CHECK(n_tokens == 2, EINVAL);
1737 h = header_parse(p, tokens[1]);
1739 CHECK(!h->st->var_size, EINVAL);
1741 instr->type = INSTR_HDR_LOOKAHEAD;
1742 instr->io.hdr.header_id[0] = h->id;
1743 instr->io.hdr.struct_id[0] = h->struct_id;
1744 instr->io.hdr.n_bytes[0] = 0; /* Unused. */
1750 __instr_hdr_extract_exec(struct rte_swx_pipeline *p, uint32_t n_extract);
1753 __instr_hdr_extract_exec(struct rte_swx_pipeline *p, uint32_t n_extract)
1755 struct thread *t = &p->threads[p->thread_id];
1756 struct instruction *ip = t->ip;
1757 uint64_t valid_headers = t->valid_headers;
1758 uint8_t *ptr = t->ptr;
1759 uint32_t offset = t->pkt.offset;
1760 uint32_t length = t->pkt.length;
1763 for (i = 0; i < n_extract; i++) {
1764 uint32_t header_id = ip->io.hdr.header_id[i];
1765 uint32_t struct_id = ip->io.hdr.struct_id[i];
1766 uint32_t n_bytes = ip->io.hdr.n_bytes[i];
1768 TRACE("[Thread %2u]: extract header %u (%u bytes)\n",
1774 t->structs[struct_id] = ptr;
1775 valid_headers = MASK64_BIT_SET(valid_headers, header_id);
1784 t->valid_headers = valid_headers;
1787 t->pkt.offset = offset;
1788 t->pkt.length = length;
1793 instr_hdr_extract_exec(struct rte_swx_pipeline *p)
1795 __instr_hdr_extract_exec(p, 1);
1802 instr_hdr_extract2_exec(struct rte_swx_pipeline *p)
1804 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n",
1807 __instr_hdr_extract_exec(p, 2);
1814 instr_hdr_extract3_exec(struct rte_swx_pipeline *p)
1816 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n",
1819 __instr_hdr_extract_exec(p, 3);
1826 instr_hdr_extract4_exec(struct rte_swx_pipeline *p)
1828 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n",
1831 __instr_hdr_extract_exec(p, 4);
1838 instr_hdr_extract5_exec(struct rte_swx_pipeline *p)
1840 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n",
1843 __instr_hdr_extract_exec(p, 5);
1850 instr_hdr_extract6_exec(struct rte_swx_pipeline *p)
1852 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n",
1855 __instr_hdr_extract_exec(p, 6);
1862 instr_hdr_extract7_exec(struct rte_swx_pipeline *p)
1864 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n",
1867 __instr_hdr_extract_exec(p, 7);
1874 instr_hdr_extract8_exec(struct rte_swx_pipeline *p)
1876 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n",
1879 __instr_hdr_extract_exec(p, 8);
1886 instr_hdr_extract_m_exec(struct rte_swx_pipeline *p)
1888 struct thread *t = &p->threads[p->thread_id];
1889 struct instruction *ip = t->ip;
1891 uint64_t valid_headers = t->valid_headers;
1892 uint8_t *ptr = t->ptr;
1893 uint32_t offset = t->pkt.offset;
1894 uint32_t length = t->pkt.length;
1896 uint32_t n_bytes_last = METADATA_READ(t, ip->io.io.offset, ip->io.io.n_bits);
1897 uint32_t header_id = ip->io.hdr.header_id[0];
1898 uint32_t struct_id = ip->io.hdr.struct_id[0];
1899 uint32_t n_bytes = ip->io.hdr.n_bytes[0];
1901 struct header_runtime *h = &t->headers[header_id];
1903 TRACE("[Thread %2u]: extract header %u (%u + %u bytes)\n",
1909 n_bytes += n_bytes_last;
1912 t->structs[struct_id] = ptr;
1913 t->valid_headers = MASK64_BIT_SET(valid_headers, header_id);
1914 h->n_bytes = n_bytes;
1917 t->pkt.offset = offset + n_bytes;
1918 t->pkt.length = length - n_bytes;
1919 t->ptr = ptr + n_bytes;
1926 instr_hdr_lookahead_exec(struct rte_swx_pipeline *p)
1928 struct thread *t = &p->threads[p->thread_id];
1929 struct instruction *ip = t->ip;
1931 uint64_t valid_headers = t->valid_headers;
1932 uint8_t *ptr = t->ptr;
1934 uint32_t header_id = ip->io.hdr.header_id[0];
1935 uint32_t struct_id = ip->io.hdr.struct_id[0];
1937 TRACE("[Thread %2u]: lookahead header %u\n",
1942 t->structs[struct_id] = ptr;
1943 t->valid_headers = MASK64_BIT_SET(valid_headers, header_id);
1953 instr_hdr_emit_translate(struct rte_swx_pipeline *p,
1954 struct action *action __rte_unused,
1957 struct instruction *instr,
1958 struct instruction_data *data __rte_unused)
1962 CHECK(n_tokens == 2, EINVAL);
1964 h = header_parse(p, tokens[1]);
1967 instr->type = INSTR_HDR_EMIT;
1968 instr->io.hdr.header_id[0] = h->id;
1969 instr->io.hdr.struct_id[0] = h->struct_id;
1970 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
1975 __instr_hdr_emit_exec(struct rte_swx_pipeline *p, uint32_t n_emit);
1978 __instr_hdr_emit_exec(struct rte_swx_pipeline *p, uint32_t n_emit)
1980 struct thread *t = &p->threads[p->thread_id];
1981 struct instruction *ip = t->ip;
1982 uint64_t valid_headers = t->valid_headers;
1983 uint32_t n_headers_out = t->n_headers_out;
1984 struct header_out_runtime *ho = &t->headers_out[n_headers_out - 1];
1985 uint8_t *ho_ptr = NULL;
1986 uint32_t ho_nbytes = 0, first = 1, i;
1988 for (i = 0; i < n_emit; i++) {
1989 uint32_t header_id = ip->io.hdr.header_id[i];
1990 uint32_t struct_id = ip->io.hdr.struct_id[i];
1992 struct header_runtime *hi = &t->headers[header_id];
1993 uint8_t *hi_ptr0 = hi->ptr0;
1994 uint32_t n_bytes = hi->n_bytes;
1996 uint8_t *hi_ptr = t->structs[struct_id];
1998 if (!MASK64_BIT_GET(valid_headers, header_id))
2001 TRACE("[Thread %2u]: emit header %u\n",
2009 if (!t->n_headers_out) {
2010 ho = &t->headers_out[0];
2016 ho_nbytes = n_bytes;
2023 ho_nbytes = ho->n_bytes;
2027 if (ho_ptr + ho_nbytes == hi_ptr) {
2028 ho_nbytes += n_bytes;
2030 ho->n_bytes = ho_nbytes;
2037 ho_nbytes = n_bytes;
2043 ho->n_bytes = ho_nbytes;
2044 t->n_headers_out = n_headers_out;
2048 instr_hdr_emit_exec(struct rte_swx_pipeline *p)
2050 __instr_hdr_emit_exec(p, 1);
2057 instr_hdr_emit_tx_exec(struct rte_swx_pipeline *p)
2059 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n",
2062 __instr_hdr_emit_exec(p, 1);
2067 instr_hdr_emit2_tx_exec(struct rte_swx_pipeline *p)
2069 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n",
2072 __instr_hdr_emit_exec(p, 2);
2077 instr_hdr_emit3_tx_exec(struct rte_swx_pipeline *p)
2079 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n",
2082 __instr_hdr_emit_exec(p, 3);
2087 instr_hdr_emit4_tx_exec(struct rte_swx_pipeline *p)
2089 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n",
2092 __instr_hdr_emit_exec(p, 4);
2097 instr_hdr_emit5_tx_exec(struct rte_swx_pipeline *p)
2099 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n",
2102 __instr_hdr_emit_exec(p, 5);
2107 instr_hdr_emit6_tx_exec(struct rte_swx_pipeline *p)
2109 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n",
2112 __instr_hdr_emit_exec(p, 6);
2117 instr_hdr_emit7_tx_exec(struct rte_swx_pipeline *p)
2119 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n",
2122 __instr_hdr_emit_exec(p, 7);
2127 instr_hdr_emit8_tx_exec(struct rte_swx_pipeline *p)
2129 TRACE("[Thread %2u] *** The next 9 instructions are fused. ***\n",
2132 __instr_hdr_emit_exec(p, 8);
2140 instr_hdr_validate_translate(struct rte_swx_pipeline *p,
2141 struct action *action __rte_unused,
2144 struct instruction *instr,
2145 struct instruction_data *data __rte_unused)
2149 CHECK(n_tokens == 2, EINVAL);
2151 h = header_parse(p, tokens[1]);
2154 instr->type = INSTR_HDR_VALIDATE;
2155 instr->valid.header_id = h->id;
2160 instr_hdr_validate_exec(struct rte_swx_pipeline *p)
2162 struct thread *t = &p->threads[p->thread_id];
2163 struct instruction *ip = t->ip;
2164 uint32_t header_id = ip->valid.header_id;
2166 TRACE("[Thread %2u] validate header %u\n", p->thread_id, header_id);
2169 t->valid_headers = MASK64_BIT_SET(t->valid_headers, header_id);
2179 instr_hdr_invalidate_translate(struct rte_swx_pipeline *p,
2180 struct action *action __rte_unused,
2183 struct instruction *instr,
2184 struct instruction_data *data __rte_unused)
2188 CHECK(n_tokens == 2, EINVAL);
2190 h = header_parse(p, tokens[1]);
2193 instr->type = INSTR_HDR_INVALIDATE;
2194 instr->valid.header_id = h->id;
2199 instr_hdr_invalidate_exec(struct rte_swx_pipeline *p)
2201 struct thread *t = &p->threads[p->thread_id];
2202 struct instruction *ip = t->ip;
2203 uint32_t header_id = ip->valid.header_id;
2205 TRACE("[Thread %2u] invalidate header %u\n", p->thread_id, header_id);
2208 t->valid_headers = MASK64_BIT_CLR(t->valid_headers, header_id);
2217 static struct table *
2218 table_find(struct rte_swx_pipeline *p, const char *name);
2220 static struct selector *
2221 selector_find(struct rte_swx_pipeline *p, const char *name);
2223 static struct learner *
2224 learner_find(struct rte_swx_pipeline *p, const char *name);
2227 instr_table_translate(struct rte_swx_pipeline *p,
2228 struct action *action,
2231 struct instruction *instr,
2232 struct instruction_data *data __rte_unused)
2238 CHECK(!action, EINVAL);
2239 CHECK(n_tokens == 2, EINVAL);
2241 t = table_find(p, tokens[1]);
2243 instr->type = INSTR_TABLE;
2244 instr->table.table_id = t->id;
2248 s = selector_find(p, tokens[1]);
2250 instr->type = INSTR_SELECTOR;
2251 instr->table.table_id = s->id;
2255 l = learner_find(p, tokens[1]);
2257 instr->type = INSTR_LEARNER;
2258 instr->table.table_id = l->id;
2266 instr_table_exec(struct rte_swx_pipeline *p)
2268 struct thread *t = &p->threads[p->thread_id];
2269 struct instruction *ip = t->ip;
2270 uint32_t table_id = ip->table.table_id;
2271 struct rte_swx_table_state *ts = &t->table_state[table_id];
2272 struct table_runtime *table = &t->tables[table_id];
2273 struct table_statistics *stats = &p->table_stats[table_id];
2274 uint64_t action_id, n_pkts_hit, n_pkts_action;
2275 uint8_t *action_data;
2279 done = table->func(ts->obj,
2287 TRACE("[Thread %2u] table %u (not finalized)\n",
2295 action_id = hit ? action_id : ts->default_action_id;
2296 action_data = hit ? action_data : ts->default_action_data;
2297 n_pkts_hit = stats->n_pkts_hit[hit];
2298 n_pkts_action = stats->n_pkts_action[action_id];
2300 TRACE("[Thread %2u] table %u (%s, action %u)\n",
2303 hit ? "hit" : "miss",
2304 (uint32_t)action_id);
2306 t->action_id = action_id;
2307 t->structs[0] = action_data;
2309 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2310 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2313 thread_ip_action_call(p, t, action_id);
2317 instr_selector_exec(struct rte_swx_pipeline *p)
2319 struct thread *t = &p->threads[p->thread_id];
2320 struct instruction *ip = t->ip;
2321 uint32_t selector_id = ip->table.table_id;
2322 struct rte_swx_table_state *ts = &t->table_state[p->n_tables + selector_id];
2323 struct selector_runtime *selector = &t->selectors[selector_id];
2324 struct selector_statistics *stats = &p->selector_stats[selector_id];
2325 uint64_t n_pkts = stats->n_pkts;
2329 done = rte_swx_table_selector_select(ts->obj,
2331 selector->group_id_buffer,
2332 selector->selector_buffer,
2333 selector->member_id_buffer);
2336 TRACE("[Thread %2u] selector %u (not finalized)\n",
2345 TRACE("[Thread %2u] selector %u\n",
2349 stats->n_pkts = n_pkts + 1;
2356 instr_learner_exec(struct rte_swx_pipeline *p)
2358 struct thread *t = &p->threads[p->thread_id];
2359 struct instruction *ip = t->ip;
2360 uint32_t learner_id = ip->table.table_id;
2361 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2362 p->n_selectors + learner_id];
2363 struct learner_runtime *l = &t->learners[learner_id];
2364 struct learner_statistics *stats = &p->learner_stats[learner_id];
2365 uint64_t action_id, n_pkts_hit, n_pkts_action, time;
2366 uint8_t *action_data;
2370 time = rte_get_tsc_cycles();
2372 done = rte_swx_table_learner_lookup(ts->obj,
2381 TRACE("[Thread %2u] learner %u (not finalized)\n",
2389 action_id = hit ? action_id : ts->default_action_id;
2390 action_data = hit ? action_data : ts->default_action_data;
2391 n_pkts_hit = stats->n_pkts_hit[hit];
2392 n_pkts_action = stats->n_pkts_action[action_id];
2394 TRACE("[Thread %2u] learner %u (%s, action %u)\n",
2397 hit ? "hit" : "miss",
2398 (uint32_t)action_id);
2400 t->action_id = action_id;
2401 t->structs[0] = action_data;
2403 t->learner_id = learner_id;
2405 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2406 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2409 thread_ip_action_call(p, t, action_id);
2415 static struct action *
2416 action_find(struct rte_swx_pipeline *p, const char *name);
2419 action_has_nbo_args(struct action *a);
2422 instr_learn_translate(struct rte_swx_pipeline *p,
2423 struct action *action,
2426 struct instruction *instr,
2427 struct instruction_data *data __rte_unused)
2431 CHECK(action, EINVAL);
2432 CHECK(n_tokens == 2, EINVAL);
2434 a = action_find(p, tokens[1]);
2436 CHECK(!action_has_nbo_args(a), EINVAL);
2438 instr->type = INSTR_LEARNER_LEARN;
2439 instr->learn.action_id = a->id;
2445 instr_learn_exec(struct rte_swx_pipeline *p)
2447 struct thread *t = &p->threads[p->thread_id];
2448 struct instruction *ip = t->ip;
2449 uint64_t action_id = ip->learn.action_id;
2450 uint32_t learner_id = t->learner_id;
2451 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2452 p->n_selectors + learner_id];
2453 struct learner_runtime *l = &t->learners[learner_id];
2454 struct learner_statistics *stats = &p->learner_stats[learner_id];
2458 status = rte_swx_table_learner_add(ts->obj,
2462 l->action_data[action_id]);
2464 TRACE("[Thread %2u] learner %u learn %s\n",
2467 status ? "ok" : "error");
2469 stats->n_pkts_learn[status] += 1;
2479 instr_forget_translate(struct rte_swx_pipeline *p __rte_unused,
2480 struct action *action,
2481 char **tokens __rte_unused,
2483 struct instruction *instr,
2484 struct instruction_data *data __rte_unused)
2486 CHECK(action, EINVAL);
2487 CHECK(n_tokens == 1, EINVAL);
2489 instr->type = INSTR_LEARNER_FORGET;
2495 instr_forget_exec(struct rte_swx_pipeline *p)
2497 struct thread *t = &p->threads[p->thread_id];
2498 uint32_t learner_id = t->learner_id;
2499 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2500 p->n_selectors + learner_id];
2501 struct learner_runtime *l = &t->learners[learner_id];
2502 struct learner_statistics *stats = &p->learner_stats[learner_id];
2505 rte_swx_table_learner_delete(ts->obj, l->mailbox);
2507 TRACE("[Thread %2u] learner %u forget\n",
2511 stats->n_pkts_forget += 1;
2521 instr_extern_translate(struct rte_swx_pipeline *p,
2522 struct action *action __rte_unused,
2525 struct instruction *instr,
2526 struct instruction_data *data __rte_unused)
2528 char *token = tokens[1];
2530 CHECK(n_tokens == 2, EINVAL);
2532 if (token[0] == 'e') {
2533 struct extern_obj *obj;
2534 struct extern_type_member_func *func;
2536 func = extern_obj_member_func_parse(p, token, &obj);
2537 CHECK(func, EINVAL);
2539 instr->type = INSTR_EXTERN_OBJ;
2540 instr->ext_obj.ext_obj_id = obj->id;
2541 instr->ext_obj.func_id = func->id;
2546 if (token[0] == 'f') {
2547 struct extern_func *func;
2549 func = extern_func_parse(p, token);
2550 CHECK(func, EINVAL);
2552 instr->type = INSTR_EXTERN_FUNC;
2553 instr->ext_func.ext_func_id = func->id;
2562 instr_extern_obj_exec(struct rte_swx_pipeline *p)
2564 struct thread *t = &p->threads[p->thread_id];
2565 struct instruction *ip = t->ip;
2566 uint32_t obj_id = ip->ext_obj.ext_obj_id;
2567 uint32_t func_id = ip->ext_obj.func_id;
2568 struct extern_obj_runtime *obj = &t->extern_objs[obj_id];
2569 rte_swx_extern_type_member_func_t func = obj->funcs[func_id];
2571 TRACE("[Thread %2u] extern obj %u member func %u\n",
2576 /* Extern object member function execute. */
2577 uint32_t done = func(obj->obj, obj->mailbox);
2580 thread_ip_inc_cond(t, done);
2581 thread_yield_cond(p, done ^ 1);
2585 instr_extern_func_exec(struct rte_swx_pipeline *p)
2587 struct thread *t = &p->threads[p->thread_id];
2588 struct instruction *ip = t->ip;
2589 uint32_t ext_func_id = ip->ext_func.ext_func_id;
2590 struct extern_func_runtime *ext_func = &t->extern_funcs[ext_func_id];
2591 rte_swx_extern_func_t func = ext_func->func;
2593 TRACE("[Thread %2u] extern func %u\n",
2597 /* Extern function execute. */
2598 uint32_t done = func(ext_func->mailbox);
2601 thread_ip_inc_cond(t, done);
2602 thread_yield_cond(p, done ^ 1);
2609 instr_mov_translate(struct rte_swx_pipeline *p,
2610 struct action *action,
2613 struct instruction *instr,
2614 struct instruction_data *data __rte_unused)
2616 char *dst = tokens[1], *src = tokens[2];
2617 struct field *fdst, *fsrc;
2619 uint32_t dst_struct_id = 0, src_struct_id = 0;
2621 CHECK(n_tokens == 3, EINVAL);
2623 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2624 CHECK(fdst, EINVAL);
2625 CHECK(!fdst->var_size, EINVAL);
2627 /* MOV, MOV_MH, MOV_HM or MOV_HH. */
2628 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2630 CHECK(!fsrc->var_size, EINVAL);
2632 instr->type = INSTR_MOV;
2633 if (dst[0] != 'h' && src[0] == 'h')
2634 instr->type = INSTR_MOV_MH;
2635 if (dst[0] == 'h' && src[0] != 'h')
2636 instr->type = INSTR_MOV_HM;
2637 if (dst[0] == 'h' && src[0] == 'h')
2638 instr->type = INSTR_MOV_HH;
2640 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
2641 instr->mov.dst.n_bits = fdst->n_bits;
2642 instr->mov.dst.offset = fdst->offset / 8;
2643 instr->mov.src.struct_id = (uint8_t)src_struct_id;
2644 instr->mov.src.n_bits = fsrc->n_bits;
2645 instr->mov.src.offset = fsrc->offset / 8;
2650 src_val = strtoull(src, &src, 0);
2651 CHECK(!src[0], EINVAL);
2654 src_val = hton64(src_val) >> (64 - fdst->n_bits);
2656 instr->type = INSTR_MOV_I;
2657 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
2658 instr->mov.dst.n_bits = fdst->n_bits;
2659 instr->mov.dst.offset = fdst->offset / 8;
2660 instr->mov.src_val = src_val;
2665 instr_mov_exec(struct rte_swx_pipeline *p)
2667 struct thread *t = &p->threads[p->thread_id];
2668 struct instruction *ip = t->ip;
2670 TRACE("[Thread %2u] mov\n",
2680 instr_mov_mh_exec(struct rte_swx_pipeline *p)
2682 struct thread *t = &p->threads[p->thread_id];
2683 struct instruction *ip = t->ip;
2685 TRACE("[Thread %2u] mov (mh)\n",
2695 instr_mov_hm_exec(struct rte_swx_pipeline *p)
2697 struct thread *t = &p->threads[p->thread_id];
2698 struct instruction *ip = t->ip;
2700 TRACE("[Thread %2u] mov (hm)\n",
2710 instr_mov_hh_exec(struct rte_swx_pipeline *p)
2712 struct thread *t = &p->threads[p->thread_id];
2713 struct instruction *ip = t->ip;
2715 TRACE("[Thread %2u] mov (hh)\n",
2725 instr_mov_i_exec(struct rte_swx_pipeline *p)
2727 struct thread *t = &p->threads[p->thread_id];
2728 struct instruction *ip = t->ip;
2730 TRACE("[Thread %2u] mov m.f %" PRIx64 "\n",
2744 __instr_dma_ht_exec(struct rte_swx_pipeline *p, uint32_t n_dma);
2747 __instr_dma_ht_exec(struct rte_swx_pipeline *p, uint32_t n_dma)
2749 struct thread *t = &p->threads[p->thread_id];
2750 struct instruction *ip = t->ip;
2751 uint8_t *action_data = t->structs[0];
2752 uint64_t valid_headers = t->valid_headers;
2755 for (i = 0; i < n_dma; i++) {
2756 uint32_t header_id = ip->dma.dst.header_id[i];
2757 uint32_t struct_id = ip->dma.dst.struct_id[i];
2758 uint32_t offset = ip->dma.src.offset[i];
2759 uint32_t n_bytes = ip->dma.n_bytes[i];
2761 struct header_runtime *h = &t->headers[header_id];
2762 uint8_t *h_ptr0 = h->ptr0;
2763 uint8_t *h_ptr = t->structs[struct_id];
2765 void *dst = MASK64_BIT_GET(valid_headers, header_id) ?
2767 void *src = &action_data[offset];
2769 TRACE("[Thread %2u] dma h.s t.f\n", p->thread_id);
2772 memcpy(dst, src, n_bytes);
2773 t->structs[struct_id] = dst;
2774 valid_headers = MASK64_BIT_SET(valid_headers, header_id);
2777 t->valid_headers = valid_headers;
2781 instr_dma_ht_exec(struct rte_swx_pipeline *p)
2783 __instr_dma_ht_exec(p, 1);
2790 instr_dma_ht2_exec(struct rte_swx_pipeline *p)
2792 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n",
2795 __instr_dma_ht_exec(p, 2);
2802 instr_dma_ht3_exec(struct rte_swx_pipeline *p)
2804 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n",
2807 __instr_dma_ht_exec(p, 3);
2814 instr_dma_ht4_exec(struct rte_swx_pipeline *p)
2816 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n",
2819 __instr_dma_ht_exec(p, 4);
2826 instr_dma_ht5_exec(struct rte_swx_pipeline *p)
2828 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n",
2831 __instr_dma_ht_exec(p, 5);
2838 instr_dma_ht6_exec(struct rte_swx_pipeline *p)
2840 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n",
2843 __instr_dma_ht_exec(p, 6);
2850 instr_dma_ht7_exec(struct rte_swx_pipeline *p)
2852 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n",
2855 __instr_dma_ht_exec(p, 7);
2862 instr_dma_ht8_exec(struct rte_swx_pipeline *p)
2864 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n",
2867 __instr_dma_ht_exec(p, 8);
2877 instr_alu_add_translate(struct rte_swx_pipeline *p,
2878 struct action *action,
2881 struct instruction *instr,
2882 struct instruction_data *data __rte_unused)
2884 char *dst = tokens[1], *src = tokens[2];
2885 struct field *fdst, *fsrc;
2887 uint32_t dst_struct_id = 0, src_struct_id = 0;
2889 CHECK(n_tokens == 3, EINVAL);
2891 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2892 CHECK(fdst, EINVAL);
2893 CHECK(!fdst->var_size, EINVAL);
2895 /* ADD, ADD_HM, ADD_MH, ADD_HH. */
2896 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2898 CHECK(!fsrc->var_size, EINVAL);
2900 instr->type = INSTR_ALU_ADD;
2901 if (dst[0] == 'h' && src[0] != 'h')
2902 instr->type = INSTR_ALU_ADD_HM;
2903 if (dst[0] != 'h' && src[0] == 'h')
2904 instr->type = INSTR_ALU_ADD_MH;
2905 if (dst[0] == 'h' && src[0] == 'h')
2906 instr->type = INSTR_ALU_ADD_HH;
2908 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2909 instr->alu.dst.n_bits = fdst->n_bits;
2910 instr->alu.dst.offset = fdst->offset / 8;
2911 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2912 instr->alu.src.n_bits = fsrc->n_bits;
2913 instr->alu.src.offset = fsrc->offset / 8;
2917 /* ADD_MI, ADD_HI. */
2918 src_val = strtoull(src, &src, 0);
2919 CHECK(!src[0], EINVAL);
2921 instr->type = INSTR_ALU_ADD_MI;
2923 instr->type = INSTR_ALU_ADD_HI;
2925 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2926 instr->alu.dst.n_bits = fdst->n_bits;
2927 instr->alu.dst.offset = fdst->offset / 8;
2928 instr->alu.src_val = src_val;
2933 instr_alu_sub_translate(struct rte_swx_pipeline *p,
2934 struct action *action,
2937 struct instruction *instr,
2938 struct instruction_data *data __rte_unused)
2940 char *dst = tokens[1], *src = tokens[2];
2941 struct field *fdst, *fsrc;
2943 uint32_t dst_struct_id = 0, src_struct_id = 0;
2945 CHECK(n_tokens == 3, EINVAL);
2947 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2948 CHECK(fdst, EINVAL);
2949 CHECK(!fdst->var_size, EINVAL);
2951 /* SUB, SUB_HM, SUB_MH, SUB_HH. */
2952 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2954 CHECK(!fsrc->var_size, EINVAL);
2956 instr->type = INSTR_ALU_SUB;
2957 if (dst[0] == 'h' && src[0] != 'h')
2958 instr->type = INSTR_ALU_SUB_HM;
2959 if (dst[0] != 'h' && src[0] == 'h')
2960 instr->type = INSTR_ALU_SUB_MH;
2961 if (dst[0] == 'h' && src[0] == 'h')
2962 instr->type = INSTR_ALU_SUB_HH;
2964 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2965 instr->alu.dst.n_bits = fdst->n_bits;
2966 instr->alu.dst.offset = fdst->offset / 8;
2967 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2968 instr->alu.src.n_bits = fsrc->n_bits;
2969 instr->alu.src.offset = fsrc->offset / 8;
2973 /* SUB_MI, SUB_HI. */
2974 src_val = strtoull(src, &src, 0);
2975 CHECK(!src[0], EINVAL);
2977 instr->type = INSTR_ALU_SUB_MI;
2979 instr->type = INSTR_ALU_SUB_HI;
2981 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2982 instr->alu.dst.n_bits = fdst->n_bits;
2983 instr->alu.dst.offset = fdst->offset / 8;
2984 instr->alu.src_val = src_val;
2989 instr_alu_ckadd_translate(struct rte_swx_pipeline *p,
2990 struct action *action __rte_unused,
2993 struct instruction *instr,
2994 struct instruction_data *data __rte_unused)
2996 char *dst = tokens[1], *src = tokens[2];
2997 struct header *hdst, *hsrc;
2998 struct field *fdst, *fsrc;
3000 CHECK(n_tokens == 3, EINVAL);
3002 fdst = header_field_parse(p, dst, &hdst);
3003 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
3004 CHECK(!fdst->var_size, EINVAL);
3007 fsrc = header_field_parse(p, src, &hsrc);
3009 CHECK(!fsrc->var_size, EINVAL);
3011 instr->type = INSTR_ALU_CKADD_FIELD;
3012 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
3013 instr->alu.dst.n_bits = fdst->n_bits;
3014 instr->alu.dst.offset = fdst->offset / 8;
3015 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
3016 instr->alu.src.n_bits = fsrc->n_bits;
3017 instr->alu.src.offset = fsrc->offset / 8;
3021 /* CKADD_STRUCT, CKADD_STRUCT20. */
3022 hsrc = header_parse(p, src);
3023 CHECK(hsrc, EINVAL);
3024 CHECK(!hsrc->st->var_size, EINVAL);
3026 instr->type = INSTR_ALU_CKADD_STRUCT;
3027 if ((hsrc->st->n_bits / 8) == 20)
3028 instr->type = INSTR_ALU_CKADD_STRUCT20;
3030 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
3031 instr->alu.dst.n_bits = fdst->n_bits;
3032 instr->alu.dst.offset = fdst->offset / 8;
3033 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
3034 instr->alu.src.n_bits = hsrc->st->n_bits;
3035 instr->alu.src.offset = 0; /* Unused. */
3040 instr_alu_cksub_translate(struct rte_swx_pipeline *p,
3041 struct action *action __rte_unused,
3044 struct instruction *instr,
3045 struct instruction_data *data __rte_unused)
3047 char *dst = tokens[1], *src = tokens[2];
3048 struct header *hdst, *hsrc;
3049 struct field *fdst, *fsrc;
3051 CHECK(n_tokens == 3, EINVAL);
3053 fdst = header_field_parse(p, dst, &hdst);
3054 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
3055 CHECK(!fdst->var_size, EINVAL);
3057 fsrc = header_field_parse(p, src, &hsrc);
3058 CHECK(fsrc, EINVAL);
3059 CHECK(!fsrc->var_size, EINVAL);
3061 instr->type = INSTR_ALU_CKSUB_FIELD;
3062 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
3063 instr->alu.dst.n_bits = fdst->n_bits;
3064 instr->alu.dst.offset = fdst->offset / 8;
3065 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
3066 instr->alu.src.n_bits = fsrc->n_bits;
3067 instr->alu.src.offset = fsrc->offset / 8;
3072 instr_alu_shl_translate(struct rte_swx_pipeline *p,
3073 struct action *action,
3076 struct instruction *instr,
3077 struct instruction_data *data __rte_unused)
3079 char *dst = tokens[1], *src = tokens[2];
3080 struct field *fdst, *fsrc;
3082 uint32_t dst_struct_id = 0, src_struct_id = 0;
3084 CHECK(n_tokens == 3, EINVAL);
3086 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3087 CHECK(fdst, EINVAL);
3088 CHECK(!fdst->var_size, EINVAL);
3090 /* SHL, SHL_HM, SHL_MH, SHL_HH. */
3091 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3093 CHECK(!fsrc->var_size, EINVAL);
3095 instr->type = INSTR_ALU_SHL;
3096 if (dst[0] == 'h' && src[0] != 'h')
3097 instr->type = INSTR_ALU_SHL_HM;
3098 if (dst[0] != 'h' && src[0] == 'h')
3099 instr->type = INSTR_ALU_SHL_MH;
3100 if (dst[0] == 'h' && src[0] == 'h')
3101 instr->type = INSTR_ALU_SHL_HH;
3103 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3104 instr->alu.dst.n_bits = fdst->n_bits;
3105 instr->alu.dst.offset = fdst->offset / 8;
3106 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3107 instr->alu.src.n_bits = fsrc->n_bits;
3108 instr->alu.src.offset = fsrc->offset / 8;
3112 /* SHL_MI, SHL_HI. */
3113 src_val = strtoull(src, &src, 0);
3114 CHECK(!src[0], EINVAL);
3116 instr->type = INSTR_ALU_SHL_MI;
3118 instr->type = INSTR_ALU_SHL_HI;
3120 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3121 instr->alu.dst.n_bits = fdst->n_bits;
3122 instr->alu.dst.offset = fdst->offset / 8;
3123 instr->alu.src_val = src_val;
3128 instr_alu_shr_translate(struct rte_swx_pipeline *p,
3129 struct action *action,
3132 struct instruction *instr,
3133 struct instruction_data *data __rte_unused)
3135 char *dst = tokens[1], *src = tokens[2];
3136 struct field *fdst, *fsrc;
3138 uint32_t dst_struct_id = 0, src_struct_id = 0;
3140 CHECK(n_tokens == 3, EINVAL);
3142 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3143 CHECK(fdst, EINVAL);
3144 CHECK(!fdst->var_size, EINVAL);
3146 /* SHR, SHR_HM, SHR_MH, SHR_HH. */
3147 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3149 CHECK(!fsrc->var_size, EINVAL);
3151 instr->type = INSTR_ALU_SHR;
3152 if (dst[0] == 'h' && src[0] != 'h')
3153 instr->type = INSTR_ALU_SHR_HM;
3154 if (dst[0] != 'h' && src[0] == 'h')
3155 instr->type = INSTR_ALU_SHR_MH;
3156 if (dst[0] == 'h' && src[0] == 'h')
3157 instr->type = INSTR_ALU_SHR_HH;
3159 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3160 instr->alu.dst.n_bits = fdst->n_bits;
3161 instr->alu.dst.offset = fdst->offset / 8;
3162 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3163 instr->alu.src.n_bits = fsrc->n_bits;
3164 instr->alu.src.offset = fsrc->offset / 8;
3168 /* SHR_MI, SHR_HI. */
3169 src_val = strtoull(src, &src, 0);
3170 CHECK(!src[0], EINVAL);
3172 instr->type = INSTR_ALU_SHR_MI;
3174 instr->type = INSTR_ALU_SHR_HI;
3176 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3177 instr->alu.dst.n_bits = fdst->n_bits;
3178 instr->alu.dst.offset = fdst->offset / 8;
3179 instr->alu.src_val = src_val;
3184 instr_alu_and_translate(struct rte_swx_pipeline *p,
3185 struct action *action,
3188 struct instruction *instr,
3189 struct instruction_data *data __rte_unused)
3191 char *dst = tokens[1], *src = tokens[2];
3192 struct field *fdst, *fsrc;
3194 uint32_t dst_struct_id = 0, src_struct_id = 0;
3196 CHECK(n_tokens == 3, EINVAL);
3198 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3199 CHECK(fdst, EINVAL);
3200 CHECK(!fdst->var_size, EINVAL);
3202 /* AND, AND_MH, AND_HM, AND_HH. */
3203 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3205 CHECK(!fsrc->var_size, EINVAL);
3207 instr->type = INSTR_ALU_AND;
3208 if (dst[0] != 'h' && src[0] == 'h')
3209 instr->type = INSTR_ALU_AND_MH;
3210 if (dst[0] == 'h' && src[0] != 'h')
3211 instr->type = INSTR_ALU_AND_HM;
3212 if (dst[0] == 'h' && src[0] == 'h')
3213 instr->type = INSTR_ALU_AND_HH;
3215 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3216 instr->alu.dst.n_bits = fdst->n_bits;
3217 instr->alu.dst.offset = fdst->offset / 8;
3218 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3219 instr->alu.src.n_bits = fsrc->n_bits;
3220 instr->alu.src.offset = fsrc->offset / 8;
3225 src_val = strtoull(src, &src, 0);
3226 CHECK(!src[0], EINVAL);
3229 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3231 instr->type = INSTR_ALU_AND_I;
3232 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3233 instr->alu.dst.n_bits = fdst->n_bits;
3234 instr->alu.dst.offset = fdst->offset / 8;
3235 instr->alu.src_val = src_val;
3240 instr_alu_or_translate(struct rte_swx_pipeline *p,
3241 struct action *action,
3244 struct instruction *instr,
3245 struct instruction_data *data __rte_unused)
3247 char *dst = tokens[1], *src = tokens[2];
3248 struct field *fdst, *fsrc;
3250 uint32_t dst_struct_id = 0, src_struct_id = 0;
3252 CHECK(n_tokens == 3, EINVAL);
3254 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3255 CHECK(fdst, EINVAL);
3256 CHECK(!fdst->var_size, EINVAL);
3258 /* OR, OR_MH, OR_HM, OR_HH. */
3259 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3261 CHECK(!fsrc->var_size, EINVAL);
3263 instr->type = INSTR_ALU_OR;
3264 if (dst[0] != 'h' && src[0] == 'h')
3265 instr->type = INSTR_ALU_OR_MH;
3266 if (dst[0] == 'h' && src[0] != 'h')
3267 instr->type = INSTR_ALU_OR_HM;
3268 if (dst[0] == 'h' && src[0] == 'h')
3269 instr->type = INSTR_ALU_OR_HH;
3271 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3272 instr->alu.dst.n_bits = fdst->n_bits;
3273 instr->alu.dst.offset = fdst->offset / 8;
3274 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3275 instr->alu.src.n_bits = fsrc->n_bits;
3276 instr->alu.src.offset = fsrc->offset / 8;
3281 src_val = strtoull(src, &src, 0);
3282 CHECK(!src[0], EINVAL);
3285 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3287 instr->type = INSTR_ALU_OR_I;
3288 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3289 instr->alu.dst.n_bits = fdst->n_bits;
3290 instr->alu.dst.offset = fdst->offset / 8;
3291 instr->alu.src_val = src_val;
3296 instr_alu_xor_translate(struct rte_swx_pipeline *p,
3297 struct action *action,
3300 struct instruction *instr,
3301 struct instruction_data *data __rte_unused)
3303 char *dst = tokens[1], *src = tokens[2];
3304 struct field *fdst, *fsrc;
3306 uint32_t dst_struct_id = 0, src_struct_id = 0;
3308 CHECK(n_tokens == 3, EINVAL);
3310 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3311 CHECK(fdst, EINVAL);
3312 CHECK(!fdst->var_size, EINVAL);
3314 /* XOR, XOR_MH, XOR_HM, XOR_HH. */
3315 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3317 CHECK(!fsrc->var_size, EINVAL);
3319 instr->type = INSTR_ALU_XOR;
3320 if (dst[0] != 'h' && src[0] == 'h')
3321 instr->type = INSTR_ALU_XOR_MH;
3322 if (dst[0] == 'h' && src[0] != 'h')
3323 instr->type = INSTR_ALU_XOR_HM;
3324 if (dst[0] == 'h' && src[0] == 'h')
3325 instr->type = INSTR_ALU_XOR_HH;
3327 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3328 instr->alu.dst.n_bits = fdst->n_bits;
3329 instr->alu.dst.offset = fdst->offset / 8;
3330 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3331 instr->alu.src.n_bits = fsrc->n_bits;
3332 instr->alu.src.offset = fsrc->offset / 8;
3337 src_val = strtoull(src, &src, 0);
3338 CHECK(!src[0], EINVAL);
3341 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3343 instr->type = INSTR_ALU_XOR_I;
3344 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3345 instr->alu.dst.n_bits = fdst->n_bits;
3346 instr->alu.dst.offset = fdst->offset / 8;
3347 instr->alu.src_val = src_val;
3352 instr_alu_add_exec(struct rte_swx_pipeline *p)
3354 struct thread *t = &p->threads[p->thread_id];
3355 struct instruction *ip = t->ip;
3357 TRACE("[Thread %2u] add\n", p->thread_id);
3367 instr_alu_add_mh_exec(struct rte_swx_pipeline *p)
3369 struct thread *t = &p->threads[p->thread_id];
3370 struct instruction *ip = t->ip;
3372 TRACE("[Thread %2u] add (mh)\n", p->thread_id);
3382 instr_alu_add_hm_exec(struct rte_swx_pipeline *p)
3384 struct thread *t = &p->threads[p->thread_id];
3385 struct instruction *ip = t->ip;
3387 TRACE("[Thread %2u] add (hm)\n", p->thread_id);
3397 instr_alu_add_hh_exec(struct rte_swx_pipeline *p)
3399 struct thread *t = &p->threads[p->thread_id];
3400 struct instruction *ip = t->ip;
3402 TRACE("[Thread %2u] add (hh)\n", p->thread_id);
3412 instr_alu_add_mi_exec(struct rte_swx_pipeline *p)
3414 struct thread *t = &p->threads[p->thread_id];
3415 struct instruction *ip = t->ip;
3417 TRACE("[Thread %2u] add (mi)\n", p->thread_id);
3427 instr_alu_add_hi_exec(struct rte_swx_pipeline *p)
3429 struct thread *t = &p->threads[p->thread_id];
3430 struct instruction *ip = t->ip;
3432 TRACE("[Thread %2u] add (hi)\n", p->thread_id);
3442 instr_alu_sub_exec(struct rte_swx_pipeline *p)
3444 struct thread *t = &p->threads[p->thread_id];
3445 struct instruction *ip = t->ip;
3447 TRACE("[Thread %2u] sub\n", p->thread_id);
3457 instr_alu_sub_mh_exec(struct rte_swx_pipeline *p)
3459 struct thread *t = &p->threads[p->thread_id];
3460 struct instruction *ip = t->ip;
3462 TRACE("[Thread %2u] sub (mh)\n", p->thread_id);
3472 instr_alu_sub_hm_exec(struct rte_swx_pipeline *p)
3474 struct thread *t = &p->threads[p->thread_id];
3475 struct instruction *ip = t->ip;
3477 TRACE("[Thread %2u] sub (hm)\n", p->thread_id);
3487 instr_alu_sub_hh_exec(struct rte_swx_pipeline *p)
3489 struct thread *t = &p->threads[p->thread_id];
3490 struct instruction *ip = t->ip;
3492 TRACE("[Thread %2u] sub (hh)\n", p->thread_id);
3502 instr_alu_sub_mi_exec(struct rte_swx_pipeline *p)
3504 struct thread *t = &p->threads[p->thread_id];
3505 struct instruction *ip = t->ip;
3507 TRACE("[Thread %2u] sub (mi)\n", p->thread_id);
3517 instr_alu_sub_hi_exec(struct rte_swx_pipeline *p)
3519 struct thread *t = &p->threads[p->thread_id];
3520 struct instruction *ip = t->ip;
3522 TRACE("[Thread %2u] sub (hi)\n", p->thread_id);
3532 instr_alu_shl_exec(struct rte_swx_pipeline *p)
3534 struct thread *t = &p->threads[p->thread_id];
3535 struct instruction *ip = t->ip;
3537 TRACE("[Thread %2u] shl\n", p->thread_id);
3547 instr_alu_shl_mh_exec(struct rte_swx_pipeline *p)
3549 struct thread *t = &p->threads[p->thread_id];
3550 struct instruction *ip = t->ip;
3552 TRACE("[Thread %2u] shl (mh)\n", p->thread_id);
3562 instr_alu_shl_hm_exec(struct rte_swx_pipeline *p)
3564 struct thread *t = &p->threads[p->thread_id];
3565 struct instruction *ip = t->ip;
3567 TRACE("[Thread %2u] shl (hm)\n", p->thread_id);
3577 instr_alu_shl_hh_exec(struct rte_swx_pipeline *p)
3579 struct thread *t = &p->threads[p->thread_id];
3580 struct instruction *ip = t->ip;
3582 TRACE("[Thread %2u] shl (hh)\n", p->thread_id);
3592 instr_alu_shl_mi_exec(struct rte_swx_pipeline *p)
3594 struct thread *t = &p->threads[p->thread_id];
3595 struct instruction *ip = t->ip;
3597 TRACE("[Thread %2u] shl (mi)\n", p->thread_id);
3607 instr_alu_shl_hi_exec(struct rte_swx_pipeline *p)
3609 struct thread *t = &p->threads[p->thread_id];
3610 struct instruction *ip = t->ip;
3612 TRACE("[Thread %2u] shl (hi)\n", p->thread_id);
3622 instr_alu_shr_exec(struct rte_swx_pipeline *p)
3624 struct thread *t = &p->threads[p->thread_id];
3625 struct instruction *ip = t->ip;
3627 TRACE("[Thread %2u] shr\n", p->thread_id);
3637 instr_alu_shr_mh_exec(struct rte_swx_pipeline *p)
3639 struct thread *t = &p->threads[p->thread_id];
3640 struct instruction *ip = t->ip;
3642 TRACE("[Thread %2u] shr (mh)\n", p->thread_id);
3652 instr_alu_shr_hm_exec(struct rte_swx_pipeline *p)
3654 struct thread *t = &p->threads[p->thread_id];
3655 struct instruction *ip = t->ip;
3657 TRACE("[Thread %2u] shr (hm)\n", p->thread_id);
3667 instr_alu_shr_hh_exec(struct rte_swx_pipeline *p)
3669 struct thread *t = &p->threads[p->thread_id];
3670 struct instruction *ip = t->ip;
3672 TRACE("[Thread %2u] shr (hh)\n", p->thread_id);
3682 instr_alu_shr_mi_exec(struct rte_swx_pipeline *p)
3684 struct thread *t = &p->threads[p->thread_id];
3685 struct instruction *ip = t->ip;
3687 TRACE("[Thread %2u] shr (mi)\n", p->thread_id);
3697 instr_alu_shr_hi_exec(struct rte_swx_pipeline *p)
3699 struct thread *t = &p->threads[p->thread_id];
3700 struct instruction *ip = t->ip;
3702 TRACE("[Thread %2u] shr (hi)\n", p->thread_id);
3712 instr_alu_and_exec(struct rte_swx_pipeline *p)
3714 struct thread *t = &p->threads[p->thread_id];
3715 struct instruction *ip = t->ip;
3717 TRACE("[Thread %2u] and\n", p->thread_id);
3727 instr_alu_and_mh_exec(struct rte_swx_pipeline *p)
3729 struct thread *t = &p->threads[p->thread_id];
3730 struct instruction *ip = t->ip;
3732 TRACE("[Thread %2u] and (mh)\n", p->thread_id);
3742 instr_alu_and_hm_exec(struct rte_swx_pipeline *p)
3744 struct thread *t = &p->threads[p->thread_id];
3745 struct instruction *ip = t->ip;
3747 TRACE("[Thread %2u] and (hm)\n", p->thread_id);
3750 ALU_HM_FAST(t, ip, &);
3757 instr_alu_and_hh_exec(struct rte_swx_pipeline *p)
3759 struct thread *t = &p->threads[p->thread_id];
3760 struct instruction *ip = t->ip;
3762 TRACE("[Thread %2u] and (hh)\n", p->thread_id);
3765 ALU_HH_FAST(t, ip, &);
3772 instr_alu_and_i_exec(struct rte_swx_pipeline *p)
3774 struct thread *t = &p->threads[p->thread_id];
3775 struct instruction *ip = t->ip;
3777 TRACE("[Thread %2u] and (i)\n", p->thread_id);
3787 instr_alu_or_exec(struct rte_swx_pipeline *p)
3789 struct thread *t = &p->threads[p->thread_id];
3790 struct instruction *ip = t->ip;
3792 TRACE("[Thread %2u] or\n", p->thread_id);
3802 instr_alu_or_mh_exec(struct rte_swx_pipeline *p)
3804 struct thread *t = &p->threads[p->thread_id];
3805 struct instruction *ip = t->ip;
3807 TRACE("[Thread %2u] or (mh)\n", p->thread_id);
3817 instr_alu_or_hm_exec(struct rte_swx_pipeline *p)
3819 struct thread *t = &p->threads[p->thread_id];
3820 struct instruction *ip = t->ip;
3822 TRACE("[Thread %2u] or (hm)\n", p->thread_id);
3825 ALU_HM_FAST(t, ip, |);
3832 instr_alu_or_hh_exec(struct rte_swx_pipeline *p)
3834 struct thread *t = &p->threads[p->thread_id];
3835 struct instruction *ip = t->ip;
3837 TRACE("[Thread %2u] or (hh)\n", p->thread_id);
3840 ALU_HH_FAST(t, ip, |);
3847 instr_alu_or_i_exec(struct rte_swx_pipeline *p)
3849 struct thread *t = &p->threads[p->thread_id];
3850 struct instruction *ip = t->ip;
3852 TRACE("[Thread %2u] or (i)\n", p->thread_id);
3862 instr_alu_xor_exec(struct rte_swx_pipeline *p)
3864 struct thread *t = &p->threads[p->thread_id];
3865 struct instruction *ip = t->ip;
3867 TRACE("[Thread %2u] xor\n", p->thread_id);
3877 instr_alu_xor_mh_exec(struct rte_swx_pipeline *p)
3879 struct thread *t = &p->threads[p->thread_id];
3880 struct instruction *ip = t->ip;
3882 TRACE("[Thread %2u] xor (mh)\n", p->thread_id);
3892 instr_alu_xor_hm_exec(struct rte_swx_pipeline *p)
3894 struct thread *t = &p->threads[p->thread_id];
3895 struct instruction *ip = t->ip;
3897 TRACE("[Thread %2u] xor (hm)\n", p->thread_id);
3900 ALU_HM_FAST(t, ip, ^);
3907 instr_alu_xor_hh_exec(struct rte_swx_pipeline *p)
3909 struct thread *t = &p->threads[p->thread_id];
3910 struct instruction *ip = t->ip;
3912 TRACE("[Thread %2u] xor (hh)\n", p->thread_id);
3915 ALU_HH_FAST(t, ip, ^);
3922 instr_alu_xor_i_exec(struct rte_swx_pipeline *p)
3924 struct thread *t = &p->threads[p->thread_id];
3925 struct instruction *ip = t->ip;
3927 TRACE("[Thread %2u] xor (i)\n", p->thread_id);
3937 instr_alu_ckadd_field_exec(struct rte_swx_pipeline *p)
3939 struct thread *t = &p->threads[p->thread_id];
3940 struct instruction *ip = t->ip;
3941 uint8_t *dst_struct, *src_struct;
3942 uint16_t *dst16_ptr, dst;
3943 uint64_t *src64_ptr, src64, src64_mask, src;
3946 TRACE("[Thread %2u] ckadd (field)\n", p->thread_id);
3949 dst_struct = t->structs[ip->alu.dst.struct_id];
3950 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
3953 src_struct = t->structs[ip->alu.src.struct_id];
3954 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
3956 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
3957 src = src64 & src64_mask;
3962 /* The first input (r) is a 16-bit number. The second and the third
3963 * inputs are 32-bit numbers. In the worst case scenario, the sum of the
3964 * three numbers (output r) is a 34-bit number.
3966 r += (src >> 32) + (src & 0xFFFFFFFF);
3968 /* The first input is a 16-bit number. The second input is an 18-bit
3969 * number. In the worst case scenario, the sum of the two numbers is a
3972 r = (r & 0xFFFF) + (r >> 16);
3974 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
3975 * a 3-bit number (0 .. 7). Their sum is a 17-bit number (0 .. 0x10006).
3977 r = (r & 0xFFFF) + (r >> 16);
3979 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
3980 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
3981 * 0x10006), the output r is (0 .. 7). So no carry bit can be generated,
3982 * therefore the output r is always a 16-bit number.
3984 r = (r & 0xFFFF) + (r >> 16);
3989 *dst16_ptr = (uint16_t)r;
3996 instr_alu_cksub_field_exec(struct rte_swx_pipeline *p)
3998 struct thread *t = &p->threads[p->thread_id];
3999 struct instruction *ip = t->ip;
4000 uint8_t *dst_struct, *src_struct;
4001 uint16_t *dst16_ptr, dst;
4002 uint64_t *src64_ptr, src64, src64_mask, src;
4005 TRACE("[Thread %2u] cksub (field)\n", p->thread_id);
4008 dst_struct = t->structs[ip->alu.dst.struct_id];
4009 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
4012 src_struct = t->structs[ip->alu.src.struct_id];
4013 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
4015 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
4016 src = src64 & src64_mask;
4021 /* Subtraction in 1's complement arithmetic (i.e. a '- b) is the same as
4022 * the following sequence of operations in 2's complement arithmetic:
4023 * a '- b = (a - b) % 0xFFFF.
4025 * In order to prevent an underflow for the below subtraction, in which
4026 * a 33-bit number (the subtrahend) is taken out of a 16-bit number (the
4027 * minuend), we first add a multiple of the 0xFFFF modulus to the
4028 * minuend. The number we add to the minuend needs to be a 34-bit number
4029 * or higher, so for readability reasons we picked the 36-bit multiple.
4030 * We are effectively turning the 16-bit minuend into a 36-bit number:
4031 * (a - b) % 0xFFFF = (a + 0xFFFF00000 - b) % 0xFFFF.
4033 r += 0xFFFF00000ULL; /* The output r is a 36-bit number. */
4035 /* A 33-bit number is subtracted from a 36-bit number (the input r). The
4036 * result (the output r) is a 36-bit number.
4038 r -= (src >> 32) + (src & 0xFFFFFFFF);
4040 /* The first input is a 16-bit number. The second input is a 20-bit
4041 * number. Their sum is a 21-bit number.
4043 r = (r & 0xFFFF) + (r >> 16);
4045 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
4046 * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1001E).
4048 r = (r & 0xFFFF) + (r >> 16);
4050 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
4051 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
4052 * 0x1001E), the output r is (0 .. 31). So no carry bit can be
4053 * generated, therefore the output r is always a 16-bit number.
4055 r = (r & 0xFFFF) + (r >> 16);
4060 *dst16_ptr = (uint16_t)r;
4067 instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline *p)
4069 struct thread *t = &p->threads[p->thread_id];
4070 struct instruction *ip = t->ip;
4071 uint8_t *dst_struct, *src_struct;
4072 uint16_t *dst16_ptr;
4073 uint32_t *src32_ptr;
4076 TRACE("[Thread %2u] ckadd (struct of 20 bytes)\n", p->thread_id);
4079 dst_struct = t->structs[ip->alu.dst.struct_id];
4080 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
4082 src_struct = t->structs[ip->alu.src.struct_id];
4083 src32_ptr = (uint32_t *)&src_struct[0];
4085 r0 = src32_ptr[0]; /* r0 is a 32-bit number. */
4086 r1 = src32_ptr[1]; /* r1 is a 32-bit number. */
4087 r0 += src32_ptr[2]; /* The output r0 is a 33-bit number. */
4088 r1 += src32_ptr[3]; /* The output r1 is a 33-bit number. */
4089 r0 += r1 + src32_ptr[4]; /* The output r0 is a 35-bit number. */
4091 /* The first input is a 16-bit number. The second input is a 19-bit
4092 * number. Their sum is a 20-bit number.
4094 r0 = (r0 & 0xFFFF) + (r0 >> 16);
4096 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
4097 * a 4-bit number (0 .. 15). The sum is a 17-bit number (0 .. 0x1000E).
4099 r0 = (r0 & 0xFFFF) + (r0 >> 16);
4101 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
4102 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
4103 * 0x1000E), the output r is (0 .. 15). So no carry bit can be
4104 * generated, therefore the output r is always a 16-bit number.
4106 r0 = (r0 & 0xFFFF) + (r0 >> 16);
4109 r0 = r0 ? r0 : 0xFFFF;
4111 *dst16_ptr = (uint16_t)r0;
4118 instr_alu_ckadd_struct_exec(struct rte_swx_pipeline *p)
4120 struct thread *t = &p->threads[p->thread_id];
4121 struct instruction *ip = t->ip;
4122 uint8_t *dst_struct, *src_struct;
4123 uint16_t *dst16_ptr;
4124 uint32_t *src32_ptr;
4128 TRACE("[Thread %2u] ckadd (struct)\n", p->thread_id);
4131 dst_struct = t->structs[ip->alu.dst.struct_id];
4132 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
4134 src_struct = t->structs[ip->alu.src.struct_id];
4135 src32_ptr = (uint32_t *)&src_struct[0];
4137 /* The max number of 32-bit words in a 256-byte header is 8 = 2^3.
4138 * Therefore, in the worst case scenario, a 35-bit number is added to a
4139 * 16-bit number (the input r), so the output r is 36-bit number.
4141 for (i = 0; i < ip->alu.src.n_bits / 32; i++, src32_ptr++)
4144 /* The first input is a 16-bit number. The second input is a 20-bit
4145 * number. Their sum is a 21-bit number.
4147 r = (r & 0xFFFF) + (r >> 16);
4149 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
4150 * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1000E).
4152 r = (r & 0xFFFF) + (r >> 16);
4154 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
4155 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
4156 * 0x1001E), the output r is (0 .. 31). So no carry bit can be
4157 * generated, therefore the output r is always a 16-bit number.
4159 r = (r & 0xFFFF) + (r >> 16);
4164 *dst16_ptr = (uint16_t)r;
4173 static struct regarray *
4174 regarray_find(struct rte_swx_pipeline *p, const char *name);
4177 instr_regprefetch_translate(struct rte_swx_pipeline *p,
4178 struct action *action,
4181 struct instruction *instr,
4182 struct instruction_data *data __rte_unused)
4184 char *regarray = tokens[1], *idx = tokens[2];
4187 uint32_t idx_struct_id, idx_val;
4189 CHECK(n_tokens == 3, EINVAL);
4191 r = regarray_find(p, regarray);
4194 /* REGPREFETCH_RH, REGPREFETCH_RM. */
4195 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4197 CHECK(!fidx->var_size, EINVAL);
4199 instr->type = INSTR_REGPREFETCH_RM;
4201 instr->type = INSTR_REGPREFETCH_RH;
4203 instr->regarray.regarray_id = r->id;
4204 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4205 instr->regarray.idx.n_bits = fidx->n_bits;
4206 instr->regarray.idx.offset = fidx->offset / 8;
4207 instr->regarray.dstsrc_val = 0; /* Unused. */
4211 /* REGPREFETCH_RI. */
4212 idx_val = strtoul(idx, &idx, 0);
4213 CHECK(!idx[0], EINVAL);
4215 instr->type = INSTR_REGPREFETCH_RI;
4216 instr->regarray.regarray_id = r->id;
4217 instr->regarray.idx_val = idx_val;
4218 instr->regarray.dstsrc_val = 0; /* Unused. */
4223 instr_regrd_translate(struct rte_swx_pipeline *p,
4224 struct action *action,
4227 struct instruction *instr,
4228 struct instruction_data *data __rte_unused)
4230 char *dst = tokens[1], *regarray = tokens[2], *idx = tokens[3];
4232 struct field *fdst, *fidx;
4233 uint32_t dst_struct_id, idx_struct_id, idx_val;
4235 CHECK(n_tokens == 4, EINVAL);
4237 r = regarray_find(p, regarray);
4240 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4241 CHECK(fdst, EINVAL);
4242 CHECK(!fdst->var_size, EINVAL);
4244 /* REGRD_HRH, REGRD_HRM, REGRD_MRH, REGRD_MRM. */
4245 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4247 CHECK(!fidx->var_size, EINVAL);
4249 instr->type = INSTR_REGRD_MRM;
4250 if (dst[0] == 'h' && idx[0] != 'h')
4251 instr->type = INSTR_REGRD_HRM;
4252 if (dst[0] != 'h' && idx[0] == 'h')
4253 instr->type = INSTR_REGRD_MRH;
4254 if (dst[0] == 'h' && idx[0] == 'h')
4255 instr->type = INSTR_REGRD_HRH;
4257 instr->regarray.regarray_id = r->id;
4258 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4259 instr->regarray.idx.n_bits = fidx->n_bits;
4260 instr->regarray.idx.offset = fidx->offset / 8;
4261 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
4262 instr->regarray.dstsrc.n_bits = fdst->n_bits;
4263 instr->regarray.dstsrc.offset = fdst->offset / 8;
4267 /* REGRD_MRI, REGRD_HRI. */
4268 idx_val = strtoul(idx, &idx, 0);
4269 CHECK(!idx[0], EINVAL);
4271 instr->type = INSTR_REGRD_MRI;
4273 instr->type = INSTR_REGRD_HRI;
4275 instr->regarray.regarray_id = r->id;
4276 instr->regarray.idx_val = idx_val;
4277 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
4278 instr->regarray.dstsrc.n_bits = fdst->n_bits;
4279 instr->regarray.dstsrc.offset = fdst->offset / 8;
4284 instr_regwr_translate(struct rte_swx_pipeline *p,
4285 struct action *action,
4288 struct instruction *instr,
4289 struct instruction_data *data __rte_unused)
4291 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
4293 struct field *fidx, *fsrc;
4295 uint32_t idx_struct_id, idx_val, src_struct_id;
4297 CHECK(n_tokens == 4, EINVAL);
4299 r = regarray_find(p, regarray);
4302 /* REGWR_RHH, REGWR_RHM, REGWR_RMH, REGWR_RMM. */
4303 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4304 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4306 CHECK(!fidx->var_size, EINVAL);
4307 CHECK(!fsrc->var_size, EINVAL);
4309 instr->type = INSTR_REGWR_RMM;
4310 if (idx[0] == 'h' && src[0] != 'h')
4311 instr->type = INSTR_REGWR_RHM;
4312 if (idx[0] != 'h' && src[0] == 'h')
4313 instr->type = INSTR_REGWR_RMH;
4314 if (idx[0] == 'h' && src[0] == 'h')
4315 instr->type = INSTR_REGWR_RHH;
4317 instr->regarray.regarray_id = r->id;
4318 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4319 instr->regarray.idx.n_bits = fidx->n_bits;
4320 instr->regarray.idx.offset = fidx->offset / 8;
4321 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4322 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4323 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4327 /* REGWR_RHI, REGWR_RMI. */
4328 if (fidx && !fsrc) {
4329 CHECK(!fidx->var_size, EINVAL);
4331 src_val = strtoull(src, &src, 0);
4332 CHECK(!src[0], EINVAL);
4334 instr->type = INSTR_REGWR_RMI;
4336 instr->type = INSTR_REGWR_RHI;
4338 instr->regarray.regarray_id = r->id;
4339 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4340 instr->regarray.idx.n_bits = fidx->n_bits;
4341 instr->regarray.idx.offset = fidx->offset / 8;
4342 instr->regarray.dstsrc_val = src_val;
4346 /* REGWR_RIH, REGWR_RIM. */
4347 if (!fidx && fsrc) {
4348 idx_val = strtoul(idx, &idx, 0);
4349 CHECK(!idx[0], EINVAL);
4351 CHECK(!fsrc->var_size, EINVAL);
4353 instr->type = INSTR_REGWR_RIM;
4355 instr->type = INSTR_REGWR_RIH;
4357 instr->regarray.regarray_id = r->id;
4358 instr->regarray.idx_val = idx_val;
4359 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4360 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4361 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4366 src_val = strtoull(src, &src, 0);
4367 CHECK(!src[0], EINVAL);
4369 idx_val = strtoul(idx, &idx, 0);
4370 CHECK(!idx[0], EINVAL);
4372 instr->type = INSTR_REGWR_RII;
4373 instr->regarray.idx_val = idx_val;
4374 instr->regarray.dstsrc_val = src_val;
4380 instr_regadd_translate(struct rte_swx_pipeline *p,
4381 struct action *action,
4384 struct instruction *instr,
4385 struct instruction_data *data __rte_unused)
4387 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
4389 struct field *fidx, *fsrc;
4391 uint32_t idx_struct_id, idx_val, src_struct_id;
4393 CHECK(n_tokens == 4, EINVAL);
4395 r = regarray_find(p, regarray);
4398 /* REGADD_RHH, REGADD_RHM, REGADD_RMH, REGADD_RMM. */
4399 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4400 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4402 CHECK(!fidx->var_size, EINVAL);
4403 CHECK(!fsrc->var_size, EINVAL);
4405 instr->type = INSTR_REGADD_RMM;
4406 if (idx[0] == 'h' && src[0] != 'h')
4407 instr->type = INSTR_REGADD_RHM;
4408 if (idx[0] != 'h' && src[0] == 'h')
4409 instr->type = INSTR_REGADD_RMH;
4410 if (idx[0] == 'h' && src[0] == 'h')
4411 instr->type = INSTR_REGADD_RHH;
4413 instr->regarray.regarray_id = r->id;
4414 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4415 instr->regarray.idx.n_bits = fidx->n_bits;
4416 instr->regarray.idx.offset = fidx->offset / 8;
4417 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4418 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4419 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4423 /* REGADD_RHI, REGADD_RMI. */
4424 if (fidx && !fsrc) {
4425 CHECK(!fidx->var_size, EINVAL);
4427 src_val = strtoull(src, &src, 0);
4428 CHECK(!src[0], EINVAL);
4430 instr->type = INSTR_REGADD_RMI;
4432 instr->type = INSTR_REGADD_RHI;
4434 instr->regarray.regarray_id = r->id;
4435 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4436 instr->regarray.idx.n_bits = fidx->n_bits;
4437 instr->regarray.idx.offset = fidx->offset / 8;
4438 instr->regarray.dstsrc_val = src_val;
4442 /* REGADD_RIH, REGADD_RIM. */
4443 if (!fidx && fsrc) {
4444 idx_val = strtoul(idx, &idx, 0);
4445 CHECK(!idx[0], EINVAL);
4447 CHECK(!fsrc->var_size, EINVAL);
4449 instr->type = INSTR_REGADD_RIM;
4451 instr->type = INSTR_REGADD_RIH;
4453 instr->regarray.regarray_id = r->id;
4454 instr->regarray.idx_val = idx_val;
4455 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4456 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4457 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4462 src_val = strtoull(src, &src, 0);
4463 CHECK(!src[0], EINVAL);
4465 idx_val = strtoul(idx, &idx, 0);
4466 CHECK(!idx[0], EINVAL);
4468 instr->type = INSTR_REGADD_RII;
4469 instr->regarray.idx_val = idx_val;
4470 instr->regarray.dstsrc_val = src_val;
4474 static inline uint64_t *
4475 instr_regarray_regarray(struct rte_swx_pipeline *p, struct instruction *ip)
4477 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4481 static inline uint64_t
4482 instr_regarray_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
4484 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4486 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
4487 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
4488 uint64_t idx64 = *idx64_ptr;
4489 uint64_t idx64_mask = UINT64_MAX >> (64 - ip->regarray.idx.n_bits);
4490 uint64_t idx = idx64 & idx64_mask & r->size_mask;
4495 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4497 static inline uint64_t
4498 instr_regarray_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
4500 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4502 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
4503 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
4504 uint64_t idx64 = *idx64_ptr;
4505 uint64_t idx = (ntoh64(idx64) >> (64 - ip->regarray.idx.n_bits)) & r->size_mask;
4512 #define instr_regarray_idx_nbo instr_regarray_idx_hbo
4516 static inline uint64_t
4517 instr_regarray_idx_imm(struct rte_swx_pipeline *p, struct instruction *ip)
4519 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4521 uint64_t idx = ip->regarray.idx_val & r->size_mask;
4526 static inline uint64_t
4527 instr_regarray_src_hbo(struct thread *t, struct instruction *ip)
4529 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
4530 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
4531 uint64_t src64 = *src64_ptr;
4532 uint64_t src64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
4533 uint64_t src = src64 & src64_mask;
4538 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4540 static inline uint64_t
4541 instr_regarray_src_nbo(struct thread *t, struct instruction *ip)
4543 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
4544 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
4545 uint64_t src64 = *src64_ptr;
4546 uint64_t src = ntoh64(src64) >> (64 - ip->regarray.dstsrc.n_bits);
4553 #define instr_regarray_src_nbo instr_regarray_src_hbo
4558 instr_regarray_dst_hbo_src_hbo_set(struct thread *t, struct instruction *ip, uint64_t src)
4560 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
4561 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
4562 uint64_t dst64 = *dst64_ptr;
4563 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
4565 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
4569 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4572 instr_regarray_dst_nbo_src_hbo_set(struct thread *t, struct instruction *ip, uint64_t src)
4574 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
4575 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
4576 uint64_t dst64 = *dst64_ptr;
4577 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
4579 src = hton64(src) >> (64 - ip->regarray.dstsrc.n_bits);
4580 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
4585 #define instr_regarray_dst_nbo_src_hbo_set instr_regarray_dst_hbo_src_hbo_set
4590 instr_regprefetch_rh_exec(struct rte_swx_pipeline *p)
4592 struct thread *t = &p->threads[p->thread_id];
4593 struct instruction *ip = t->ip;
4594 uint64_t *regarray, idx;
4596 TRACE("[Thread %2u] regprefetch (r[h])\n", p->thread_id);
4599 regarray = instr_regarray_regarray(p, ip);
4600 idx = instr_regarray_idx_nbo(p, t, ip);
4601 rte_prefetch0(®array[idx]);
4608 instr_regprefetch_rm_exec(struct rte_swx_pipeline *p)
4610 struct thread *t = &p->threads[p->thread_id];
4611 struct instruction *ip = t->ip;
4612 uint64_t *regarray, idx;
4614 TRACE("[Thread %2u] regprefetch (r[m])\n", p->thread_id);
4617 regarray = instr_regarray_regarray(p, ip);
4618 idx = instr_regarray_idx_hbo(p, t, ip);
4619 rte_prefetch0(®array[idx]);
4626 instr_regprefetch_ri_exec(struct rte_swx_pipeline *p)
4628 struct thread *t = &p->threads[p->thread_id];
4629 struct instruction *ip = t->ip;
4630 uint64_t *regarray, idx;
4632 TRACE("[Thread %2u] regprefetch (r[i])\n", p->thread_id);
4635 regarray = instr_regarray_regarray(p, ip);
4636 idx = instr_regarray_idx_imm(p, ip);
4637 rte_prefetch0(®array[idx]);
4644 instr_regrd_hrh_exec(struct rte_swx_pipeline *p)
4646 struct thread *t = &p->threads[p->thread_id];
4647 struct instruction *ip = t->ip;
4648 uint64_t *regarray, idx;
4650 TRACE("[Thread %2u] regrd (h = r[h])\n", p->thread_id);
4653 regarray = instr_regarray_regarray(p, ip);
4654 idx = instr_regarray_idx_nbo(p, t, ip);
4655 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
4662 instr_regrd_hrm_exec(struct rte_swx_pipeline *p)
4664 struct thread *t = &p->threads[p->thread_id];
4665 struct instruction *ip = t->ip;
4666 uint64_t *regarray, idx;
4668 TRACE("[Thread %2u] regrd (h = r[m])\n", p->thread_id);
4671 regarray = instr_regarray_regarray(p, ip);
4672 idx = instr_regarray_idx_hbo(p, t, ip);
4673 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
4680 instr_regrd_mrh_exec(struct rte_swx_pipeline *p)
4682 struct thread *t = &p->threads[p->thread_id];
4683 struct instruction *ip = t->ip;
4684 uint64_t *regarray, idx;
4686 TRACE("[Thread %2u] regrd (m = r[h])\n", p->thread_id);
4689 regarray = instr_regarray_regarray(p, ip);
4690 idx = instr_regarray_idx_nbo(p, t, ip);
4691 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
4698 instr_regrd_mrm_exec(struct rte_swx_pipeline *p)
4700 struct thread *t = &p->threads[p->thread_id];
4701 struct instruction *ip = t->ip;
4702 uint64_t *regarray, idx;
4705 regarray = instr_regarray_regarray(p, ip);
4706 idx = instr_regarray_idx_hbo(p, t, ip);
4707 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
4714 instr_regrd_hri_exec(struct rte_swx_pipeline *p)
4716 struct thread *t = &p->threads[p->thread_id];
4717 struct instruction *ip = t->ip;
4718 uint64_t *regarray, idx;
4720 TRACE("[Thread %2u] regrd (h = r[i])\n", p->thread_id);
4723 regarray = instr_regarray_regarray(p, ip);
4724 idx = instr_regarray_idx_imm(p, ip);
4725 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
4732 instr_regrd_mri_exec(struct rte_swx_pipeline *p)
4734 struct thread *t = &p->threads[p->thread_id];
4735 struct instruction *ip = t->ip;
4736 uint64_t *regarray, idx;
4738 TRACE("[Thread %2u] regrd (m = r[i])\n", p->thread_id);
4741 regarray = instr_regarray_regarray(p, ip);
4742 idx = instr_regarray_idx_imm(p, ip);
4743 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
4750 instr_regwr_rhh_exec(struct rte_swx_pipeline *p)
4752 struct thread *t = &p->threads[p->thread_id];
4753 struct instruction *ip = t->ip;
4754 uint64_t *regarray, idx, src;
4756 TRACE("[Thread %2u] regwr (r[h] = h)\n", p->thread_id);
4759 regarray = instr_regarray_regarray(p, ip);
4760 idx = instr_regarray_idx_nbo(p, t, ip);
4761 src = instr_regarray_src_nbo(t, ip);
4762 regarray[idx] = src;
4769 instr_regwr_rhm_exec(struct rte_swx_pipeline *p)
4771 struct thread *t = &p->threads[p->thread_id];
4772 struct instruction *ip = t->ip;
4773 uint64_t *regarray, idx, src;
4775 TRACE("[Thread %2u] regwr (r[h] = m)\n", p->thread_id);
4778 regarray = instr_regarray_regarray(p, ip);
4779 idx = instr_regarray_idx_nbo(p, t, ip);
4780 src = instr_regarray_src_hbo(t, ip);
4781 regarray[idx] = src;
4788 instr_regwr_rmh_exec(struct rte_swx_pipeline *p)
4790 struct thread *t = &p->threads[p->thread_id];
4791 struct instruction *ip = t->ip;
4792 uint64_t *regarray, idx, src;
4794 TRACE("[Thread %2u] regwr (r[m] = h)\n", p->thread_id);
4797 regarray = instr_regarray_regarray(p, ip);
4798 idx = instr_regarray_idx_hbo(p, t, ip);
4799 src = instr_regarray_src_nbo(t, ip);
4800 regarray[idx] = src;
4807 instr_regwr_rmm_exec(struct rte_swx_pipeline *p)
4809 struct thread *t = &p->threads[p->thread_id];
4810 struct instruction *ip = t->ip;
4811 uint64_t *regarray, idx, src;
4813 TRACE("[Thread %2u] regwr (r[m] = m)\n", p->thread_id);
4816 regarray = instr_regarray_regarray(p, ip);
4817 idx = instr_regarray_idx_hbo(p, t, ip);
4818 src = instr_regarray_src_hbo(t, ip);
4819 regarray[idx] = src;
4826 instr_regwr_rhi_exec(struct rte_swx_pipeline *p)
4828 struct thread *t = &p->threads[p->thread_id];
4829 struct instruction *ip = t->ip;
4830 uint64_t *regarray, idx, src;
4832 TRACE("[Thread %2u] regwr (r[h] = i)\n", p->thread_id);
4835 regarray = instr_regarray_regarray(p, ip);
4836 idx = instr_regarray_idx_nbo(p, t, ip);
4837 src = ip->regarray.dstsrc_val;
4838 regarray[idx] = src;
4845 instr_regwr_rmi_exec(struct rte_swx_pipeline *p)
4847 struct thread *t = &p->threads[p->thread_id];
4848 struct instruction *ip = t->ip;
4849 uint64_t *regarray, idx, src;
4851 TRACE("[Thread %2u] regwr (r[m] = i)\n", p->thread_id);
4854 regarray = instr_regarray_regarray(p, ip);
4855 idx = instr_regarray_idx_hbo(p, t, ip);
4856 src = ip->regarray.dstsrc_val;
4857 regarray[idx] = src;
4864 instr_regwr_rih_exec(struct rte_swx_pipeline *p)
4866 struct thread *t = &p->threads[p->thread_id];
4867 struct instruction *ip = t->ip;
4868 uint64_t *regarray, idx, src;
4870 TRACE("[Thread %2u] regwr (r[i] = h)\n", p->thread_id);
4873 regarray = instr_regarray_regarray(p, ip);
4874 idx = instr_regarray_idx_imm(p, ip);
4875 src = instr_regarray_src_nbo(t, ip);
4876 regarray[idx] = src;
4883 instr_regwr_rim_exec(struct rte_swx_pipeline *p)
4885 struct thread *t = &p->threads[p->thread_id];
4886 struct instruction *ip = t->ip;
4887 uint64_t *regarray, idx, src;
4889 TRACE("[Thread %2u] regwr (r[i] = m)\n", p->thread_id);
4892 regarray = instr_regarray_regarray(p, ip);
4893 idx = instr_regarray_idx_imm(p, ip);
4894 src = instr_regarray_src_hbo(t, ip);
4895 regarray[idx] = src;
4902 instr_regwr_rii_exec(struct rte_swx_pipeline *p)
4904 struct thread *t = &p->threads[p->thread_id];
4905 struct instruction *ip = t->ip;
4906 uint64_t *regarray, idx, src;
4908 TRACE("[Thread %2u] regwr (r[i] = i)\n", p->thread_id);
4911 regarray = instr_regarray_regarray(p, ip);
4912 idx = instr_regarray_idx_imm(p, ip);
4913 src = ip->regarray.dstsrc_val;
4914 regarray[idx] = src;
4921 instr_regadd_rhh_exec(struct rte_swx_pipeline *p)
4923 struct thread *t = &p->threads[p->thread_id];
4924 struct instruction *ip = t->ip;
4925 uint64_t *regarray, idx, src;
4927 TRACE("[Thread %2u] regadd (r[h] += h)\n", p->thread_id);
4930 regarray = instr_regarray_regarray(p, ip);
4931 idx = instr_regarray_idx_nbo(p, t, ip);
4932 src = instr_regarray_src_nbo(t, ip);
4933 regarray[idx] += src;
4940 instr_regadd_rhm_exec(struct rte_swx_pipeline *p)
4942 struct thread *t = &p->threads[p->thread_id];
4943 struct instruction *ip = t->ip;
4944 uint64_t *regarray, idx, src;
4946 TRACE("[Thread %2u] regadd (r[h] += m)\n", p->thread_id);
4949 regarray = instr_regarray_regarray(p, ip);
4950 idx = instr_regarray_idx_nbo(p, t, ip);
4951 src = instr_regarray_src_hbo(t, ip);
4952 regarray[idx] += src;
4959 instr_regadd_rmh_exec(struct rte_swx_pipeline *p)
4961 struct thread *t = &p->threads[p->thread_id];
4962 struct instruction *ip = t->ip;
4963 uint64_t *regarray, idx, src;
4965 TRACE("[Thread %2u] regadd (r[m] += h)\n", p->thread_id);
4968 regarray = instr_regarray_regarray(p, ip);
4969 idx = instr_regarray_idx_hbo(p, t, ip);
4970 src = instr_regarray_src_nbo(t, ip);
4971 regarray[idx] += src;
4978 instr_regadd_rmm_exec(struct rte_swx_pipeline *p)
4980 struct thread *t = &p->threads[p->thread_id];
4981 struct instruction *ip = t->ip;
4982 uint64_t *regarray, idx, src;
4984 TRACE("[Thread %2u] regadd (r[m] += m)\n", p->thread_id);
4987 regarray = instr_regarray_regarray(p, ip);
4988 idx = instr_regarray_idx_hbo(p, t, ip);
4989 src = instr_regarray_src_hbo(t, ip);
4990 regarray[idx] += src;
4997 instr_regadd_rhi_exec(struct rte_swx_pipeline *p)
4999 struct thread *t = &p->threads[p->thread_id];
5000 struct instruction *ip = t->ip;
5001 uint64_t *regarray, idx, src;
5003 TRACE("[Thread %2u] regadd (r[h] += i)\n", p->thread_id);
5006 regarray = instr_regarray_regarray(p, ip);
5007 idx = instr_regarray_idx_nbo(p, t, ip);
5008 src = ip->regarray.dstsrc_val;
5009 regarray[idx] += src;
5016 instr_regadd_rmi_exec(struct rte_swx_pipeline *p)
5018 struct thread *t = &p->threads[p->thread_id];
5019 struct instruction *ip = t->ip;
5020 uint64_t *regarray, idx, src;
5022 TRACE("[Thread %2u] regadd (r[m] += i)\n", p->thread_id);
5025 regarray = instr_regarray_regarray(p, ip);
5026 idx = instr_regarray_idx_hbo(p, t, ip);
5027 src = ip->regarray.dstsrc_val;
5028 regarray[idx] += src;
5035 instr_regadd_rih_exec(struct rte_swx_pipeline *p)
5037 struct thread *t = &p->threads[p->thread_id];
5038 struct instruction *ip = t->ip;
5039 uint64_t *regarray, idx, src;
5041 TRACE("[Thread %2u] regadd (r[i] += h)\n", p->thread_id);
5044 regarray = instr_regarray_regarray(p, ip);
5045 idx = instr_regarray_idx_imm(p, ip);
5046 src = instr_regarray_src_nbo(t, ip);
5047 regarray[idx] += src;
5054 instr_regadd_rim_exec(struct rte_swx_pipeline *p)
5056 struct thread *t = &p->threads[p->thread_id];
5057 struct instruction *ip = t->ip;
5058 uint64_t *regarray, idx, src;
5060 TRACE("[Thread %2u] regadd (r[i] += m)\n", p->thread_id);
5063 regarray = instr_regarray_regarray(p, ip);
5064 idx = instr_regarray_idx_imm(p, ip);
5065 src = instr_regarray_src_hbo(t, ip);
5066 regarray[idx] += src;
5073 instr_regadd_rii_exec(struct rte_swx_pipeline *p)
5075 struct thread *t = &p->threads[p->thread_id];
5076 struct instruction *ip = t->ip;
5077 uint64_t *regarray, idx, src;
5079 TRACE("[Thread %2u] regadd (r[i] += i)\n", p->thread_id);
5082 regarray = instr_regarray_regarray(p, ip);
5083 idx = instr_regarray_idx_imm(p, ip);
5084 src = ip->regarray.dstsrc_val;
5085 regarray[idx] += src;
5094 static struct metarray *
5095 metarray_find(struct rte_swx_pipeline *p, const char *name);
5098 instr_metprefetch_translate(struct rte_swx_pipeline *p,
5099 struct action *action,
5102 struct instruction *instr,
5103 struct instruction_data *data __rte_unused)
5105 char *metarray = tokens[1], *idx = tokens[2];
5108 uint32_t idx_struct_id, idx_val;
5110 CHECK(n_tokens == 3, EINVAL);
5112 m = metarray_find(p, metarray);
5115 /* METPREFETCH_H, METPREFETCH_M. */
5116 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
5118 CHECK(!fidx->var_size, EINVAL);
5120 instr->type = INSTR_METPREFETCH_M;
5122 instr->type = INSTR_METPREFETCH_H;
5124 instr->meter.metarray_id = m->id;
5125 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
5126 instr->meter.idx.n_bits = fidx->n_bits;
5127 instr->meter.idx.offset = fidx->offset / 8;
5131 /* METPREFETCH_I. */
5132 idx_val = strtoul(idx, &idx, 0);
5133 CHECK(!idx[0], EINVAL);
5135 instr->type = INSTR_METPREFETCH_I;
5136 instr->meter.metarray_id = m->id;
5137 instr->meter.idx_val = idx_val;
5142 instr_meter_translate(struct rte_swx_pipeline *p,
5143 struct action *action,
5146 struct instruction *instr,
5147 struct instruction_data *data __rte_unused)
5149 char *metarray = tokens[1], *idx = tokens[2], *length = tokens[3];
5150 char *color_in = tokens[4], *color_out = tokens[5];
5152 struct field *fidx, *flength, *fcin, *fcout;
5153 uint32_t idx_struct_id, length_struct_id;
5154 uint32_t color_in_struct_id, color_out_struct_id;
5156 CHECK(n_tokens == 6, EINVAL);
5158 m = metarray_find(p, metarray);
5161 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
5163 flength = struct_field_parse(p, action, length, &length_struct_id);
5164 CHECK(flength, EINVAL);
5165 CHECK(!flength->var_size, EINVAL);
5167 fcin = struct_field_parse(p, action, color_in, &color_in_struct_id);
5169 fcout = struct_field_parse(p, NULL, color_out, &color_out_struct_id);
5170 CHECK(fcout, EINVAL);
5171 CHECK(!fcout->var_size, EINVAL);
5173 /* index = HMEFT, length = HMEFT, color_in = MEFT, color_out = MEF. */
5175 CHECK(!fidx->var_size, EINVAL);
5176 CHECK(!fcin->var_size, EINVAL);
5178 instr->type = INSTR_METER_MMM;
5179 if (idx[0] == 'h' && length[0] == 'h')
5180 instr->type = INSTR_METER_HHM;
5181 if (idx[0] == 'h' && length[0] != 'h')
5182 instr->type = INSTR_METER_HMM;
5183 if (idx[0] != 'h' && length[0] == 'h')
5184 instr->type = INSTR_METER_MHM;
5186 instr->meter.metarray_id = m->id;
5188 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
5189 instr->meter.idx.n_bits = fidx->n_bits;
5190 instr->meter.idx.offset = fidx->offset / 8;
5192 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5193 instr->meter.length.n_bits = flength->n_bits;
5194 instr->meter.length.offset = flength->offset / 8;
5196 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
5197 instr->meter.color_in.n_bits = fcin->n_bits;
5198 instr->meter.color_in.offset = fcin->offset / 8;
5200 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5201 instr->meter.color_out.n_bits = fcout->n_bits;
5202 instr->meter.color_out.offset = fcout->offset / 8;
5207 /* index = HMEFT, length = HMEFT, color_in = I, color_out = MEF. */
5208 if (fidx && !fcin) {
5209 uint32_t color_in_val;
5211 CHECK(!fidx->var_size, EINVAL);
5213 color_in_val = strtoul(color_in, &color_in, 0);
5214 CHECK(!color_in[0], EINVAL);
5216 instr->type = INSTR_METER_MMI;
5217 if (idx[0] == 'h' && length[0] == 'h')
5218 instr->type = INSTR_METER_HHI;
5219 if (idx[0] == 'h' && length[0] != 'h')
5220 instr->type = INSTR_METER_HMI;
5221 if (idx[0] != 'h' && length[0] == 'h')
5222 instr->type = INSTR_METER_MHI;
5224 instr->meter.metarray_id = m->id;
5226 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
5227 instr->meter.idx.n_bits = fidx->n_bits;
5228 instr->meter.idx.offset = fidx->offset / 8;
5230 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5231 instr->meter.length.n_bits = flength->n_bits;
5232 instr->meter.length.offset = flength->offset / 8;
5234 instr->meter.color_in_val = color_in_val;
5236 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5237 instr->meter.color_out.n_bits = fcout->n_bits;
5238 instr->meter.color_out.offset = fcout->offset / 8;
5243 /* index = I, length = HMEFT, color_in = MEFT, color_out = MEF. */
5244 if (!fidx && fcin) {
5247 idx_val = strtoul(idx, &idx, 0);
5248 CHECK(!idx[0], EINVAL);
5250 CHECK(!fcin->var_size, EINVAL);
5252 instr->type = INSTR_METER_IMM;
5253 if (length[0] == 'h')
5254 instr->type = INSTR_METER_IHM;
5256 instr->meter.metarray_id = m->id;
5258 instr->meter.idx_val = idx_val;
5260 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5261 instr->meter.length.n_bits = flength->n_bits;
5262 instr->meter.length.offset = flength->offset / 8;
5264 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
5265 instr->meter.color_in.n_bits = fcin->n_bits;
5266 instr->meter.color_in.offset = fcin->offset / 8;
5268 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5269 instr->meter.color_out.n_bits = fcout->n_bits;
5270 instr->meter.color_out.offset = fcout->offset / 8;
5275 /* index = I, length = HMEFT, color_in = I, color_out = MEF. */
5276 if (!fidx && !fcin) {
5277 uint32_t idx_val, color_in_val;
5279 idx_val = strtoul(idx, &idx, 0);
5280 CHECK(!idx[0], EINVAL);
5282 color_in_val = strtoul(color_in, &color_in, 0);
5283 CHECK(!color_in[0], EINVAL);
5285 instr->type = INSTR_METER_IMI;
5286 if (length[0] == 'h')
5287 instr->type = INSTR_METER_IHI;
5289 instr->meter.metarray_id = m->id;
5291 instr->meter.idx_val = idx_val;
5293 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5294 instr->meter.length.n_bits = flength->n_bits;
5295 instr->meter.length.offset = flength->offset / 8;
5297 instr->meter.color_in_val = color_in_val;
5299 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5300 instr->meter.color_out.n_bits = fcout->n_bits;
5301 instr->meter.color_out.offset = fcout->offset / 8;
5309 static inline struct meter *
5310 instr_meter_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
5312 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
5314 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
5315 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
5316 uint64_t idx64 = *idx64_ptr;
5317 uint64_t idx64_mask = UINT64_MAX >> (64 - (ip)->meter.idx.n_bits);
5318 uint64_t idx = idx64 & idx64_mask & r->size_mask;
5320 return &r->metarray[idx];
5323 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5325 static inline struct meter *
5326 instr_meter_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
5328 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
5330 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
5331 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
5332 uint64_t idx64 = *idx64_ptr;
5333 uint64_t idx = (ntoh64(idx64) >> (64 - ip->meter.idx.n_bits)) & r->size_mask;
5335 return &r->metarray[idx];
5340 #define instr_meter_idx_nbo instr_meter_idx_hbo
5344 static inline struct meter *
5345 instr_meter_idx_imm(struct rte_swx_pipeline *p, struct instruction *ip)
5347 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
5349 uint64_t idx = ip->meter.idx_val & r->size_mask;
5351 return &r->metarray[idx];
5354 static inline uint32_t
5355 instr_meter_length_hbo(struct thread *t, struct instruction *ip)
5357 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
5358 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
5359 uint64_t src64 = *src64_ptr;
5360 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->meter.length.n_bits);
5361 uint64_t src = src64 & src64_mask;
5363 return (uint32_t)src;
5366 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5368 static inline uint32_t
5369 instr_meter_length_nbo(struct thread *t, struct instruction *ip)
5371 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
5372 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
5373 uint64_t src64 = *src64_ptr;
5374 uint64_t src = ntoh64(src64) >> (64 - ip->meter.length.n_bits);
5376 return (uint32_t)src;
5381 #define instr_meter_length_nbo instr_meter_length_hbo
5385 static inline enum rte_color
5386 instr_meter_color_in_hbo(struct thread *t, struct instruction *ip)
5388 uint8_t *src_struct = t->structs[ip->meter.color_in.struct_id];
5389 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.color_in.offset];
5390 uint64_t src64 = *src64_ptr;
5391 uint64_t src64_mask = UINT64_MAX >> (64 - ip->meter.color_in.n_bits);
5392 uint64_t src = src64 & src64_mask;
5394 return (enum rte_color)src;
5398 instr_meter_color_out_hbo_set(struct thread *t, struct instruction *ip, enum rte_color color_out)
5400 uint8_t *dst_struct = t->structs[ip->meter.color_out.struct_id];
5401 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->meter.color_out.offset];
5402 uint64_t dst64 = *dst64_ptr;
5403 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->meter.color_out.n_bits);
5405 uint64_t src = (uint64_t)color_out;
5407 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
5411 instr_metprefetch_h_exec(struct rte_swx_pipeline *p)
5413 struct thread *t = &p->threads[p->thread_id];
5414 struct instruction *ip = t->ip;
5417 TRACE("[Thread %2u] metprefetch (h)\n", p->thread_id);
5420 m = instr_meter_idx_nbo(p, t, ip);
5428 instr_metprefetch_m_exec(struct rte_swx_pipeline *p)
5430 struct thread *t = &p->threads[p->thread_id];
5431 struct instruction *ip = t->ip;
5434 TRACE("[Thread %2u] metprefetch (m)\n", p->thread_id);
5437 m = instr_meter_idx_hbo(p, t, ip);
5445 instr_metprefetch_i_exec(struct rte_swx_pipeline *p)
5447 struct thread *t = &p->threads[p->thread_id];
5448 struct instruction *ip = t->ip;
5451 TRACE("[Thread %2u] metprefetch (i)\n", p->thread_id);
5454 m = instr_meter_idx_imm(p, ip);
5462 instr_meter_hhm_exec(struct rte_swx_pipeline *p)
5464 struct thread *t = &p->threads[p->thread_id];
5465 struct instruction *ip = t->ip;
5467 uint64_t time, n_pkts, n_bytes;
5469 enum rte_color color_in, color_out;
5471 TRACE("[Thread %2u] meter (hhm)\n", p->thread_id);
5474 m = instr_meter_idx_nbo(p, t, ip);
5475 rte_prefetch0(m->n_pkts);
5476 time = rte_get_tsc_cycles();
5477 length = instr_meter_length_nbo(t, ip);
5478 color_in = instr_meter_color_in_hbo(t, ip);
5480 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5481 &m->profile->profile,
5486 color_out &= m->color_mask;
5488 n_pkts = m->n_pkts[color_out];
5489 n_bytes = m->n_bytes[color_out];
5491 instr_meter_color_out_hbo_set(t, ip, color_out);
5493 m->n_pkts[color_out] = n_pkts + 1;
5494 m->n_bytes[color_out] = n_bytes + length;
5501 instr_meter_hhi_exec(struct rte_swx_pipeline *p)
5503 struct thread *t = &p->threads[p->thread_id];
5504 struct instruction *ip = t->ip;
5506 uint64_t time, n_pkts, n_bytes;
5508 enum rte_color color_in, color_out;
5510 TRACE("[Thread %2u] meter (hhi)\n", p->thread_id);
5513 m = instr_meter_idx_nbo(p, t, ip);
5514 rte_prefetch0(m->n_pkts);
5515 time = rte_get_tsc_cycles();
5516 length = instr_meter_length_nbo(t, ip);
5517 color_in = (enum rte_color)ip->meter.color_in_val;
5519 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5520 &m->profile->profile,
5525 color_out &= m->color_mask;
5527 n_pkts = m->n_pkts[color_out];
5528 n_bytes = m->n_bytes[color_out];
5530 instr_meter_color_out_hbo_set(t, ip, color_out);
5532 m->n_pkts[color_out] = n_pkts + 1;
5533 m->n_bytes[color_out] = n_bytes + length;
5540 instr_meter_hmm_exec(struct rte_swx_pipeline *p)
5542 struct thread *t = &p->threads[p->thread_id];
5543 struct instruction *ip = t->ip;
5545 uint64_t time, n_pkts, n_bytes;
5547 enum rte_color color_in, color_out;
5549 TRACE("[Thread %2u] meter (hmm)\n", p->thread_id);
5552 m = instr_meter_idx_nbo(p, t, ip);
5553 rte_prefetch0(m->n_pkts);
5554 time = rte_get_tsc_cycles();
5555 length = instr_meter_length_hbo(t, ip);
5556 color_in = instr_meter_color_in_hbo(t, ip);
5558 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5559 &m->profile->profile,
5564 color_out &= m->color_mask;
5566 n_pkts = m->n_pkts[color_out];
5567 n_bytes = m->n_bytes[color_out];
5569 instr_meter_color_out_hbo_set(t, ip, color_out);
5571 m->n_pkts[color_out] = n_pkts + 1;
5572 m->n_bytes[color_out] = n_bytes + length;
5578 instr_meter_hmi_exec(struct rte_swx_pipeline *p)
5580 struct thread *t = &p->threads[p->thread_id];
5581 struct instruction *ip = t->ip;
5583 uint64_t time, n_pkts, n_bytes;
5585 enum rte_color color_in, color_out;
5587 TRACE("[Thread %2u] meter (hmi)\n", p->thread_id);
5590 m = instr_meter_idx_nbo(p, t, ip);
5591 rte_prefetch0(m->n_pkts);
5592 time = rte_get_tsc_cycles();
5593 length = instr_meter_length_hbo(t, ip);
5594 color_in = (enum rte_color)ip->meter.color_in_val;
5596 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5597 &m->profile->profile,
5602 color_out &= m->color_mask;
5604 n_pkts = m->n_pkts[color_out];
5605 n_bytes = m->n_bytes[color_out];
5607 instr_meter_color_out_hbo_set(t, ip, color_out);
5609 m->n_pkts[color_out] = n_pkts + 1;
5610 m->n_bytes[color_out] = n_bytes + length;
5617 instr_meter_mhm_exec(struct rte_swx_pipeline *p)
5619 struct thread *t = &p->threads[p->thread_id];
5620 struct instruction *ip = t->ip;
5622 uint64_t time, n_pkts, n_bytes;
5624 enum rte_color color_in, color_out;
5626 TRACE("[Thread %2u] meter (mhm)\n", p->thread_id);
5629 m = instr_meter_idx_hbo(p, t, ip);
5630 rte_prefetch0(m->n_pkts);
5631 time = rte_get_tsc_cycles();
5632 length = instr_meter_length_nbo(t, ip);
5633 color_in = instr_meter_color_in_hbo(t, ip);
5635 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5636 &m->profile->profile,
5641 color_out &= m->color_mask;
5643 n_pkts = m->n_pkts[color_out];
5644 n_bytes = m->n_bytes[color_out];
5646 instr_meter_color_out_hbo_set(t, ip, color_out);
5648 m->n_pkts[color_out] = n_pkts + 1;
5649 m->n_bytes[color_out] = n_bytes + length;
5656 instr_meter_mhi_exec(struct rte_swx_pipeline *p)
5658 struct thread *t = &p->threads[p->thread_id];
5659 struct instruction *ip = t->ip;
5661 uint64_t time, n_pkts, n_bytes;
5663 enum rte_color color_in, color_out;
5665 TRACE("[Thread %2u] meter (mhi)\n", p->thread_id);
5668 m = instr_meter_idx_hbo(p, t, ip);
5669 rte_prefetch0(m->n_pkts);
5670 time = rte_get_tsc_cycles();
5671 length = instr_meter_length_nbo(t, ip);
5672 color_in = (enum rte_color)ip->meter.color_in_val;
5674 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5675 &m->profile->profile,
5680 color_out &= m->color_mask;
5682 n_pkts = m->n_pkts[color_out];
5683 n_bytes = m->n_bytes[color_out];
5685 instr_meter_color_out_hbo_set(t, ip, color_out);
5687 m->n_pkts[color_out] = n_pkts + 1;
5688 m->n_bytes[color_out] = n_bytes + length;
5695 instr_meter_mmm_exec(struct rte_swx_pipeline *p)
5697 struct thread *t = &p->threads[p->thread_id];
5698 struct instruction *ip = t->ip;
5700 uint64_t time, n_pkts, n_bytes;
5702 enum rte_color color_in, color_out;
5704 TRACE("[Thread %2u] meter (mmm)\n", p->thread_id);
5707 m = instr_meter_idx_hbo(p, t, ip);
5708 rte_prefetch0(m->n_pkts);
5709 time = rte_get_tsc_cycles();
5710 length = instr_meter_length_hbo(t, ip);
5711 color_in = instr_meter_color_in_hbo(t, ip);
5713 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5714 &m->profile->profile,
5719 color_out &= m->color_mask;
5721 n_pkts = m->n_pkts[color_out];
5722 n_bytes = m->n_bytes[color_out];
5724 instr_meter_color_out_hbo_set(t, ip, color_out);
5726 m->n_pkts[color_out] = n_pkts + 1;
5727 m->n_bytes[color_out] = n_bytes + length;
5734 instr_meter_mmi_exec(struct rte_swx_pipeline *p)
5736 struct thread *t = &p->threads[p->thread_id];
5737 struct instruction *ip = t->ip;
5739 uint64_t time, n_pkts, n_bytes;
5741 enum rte_color color_in, color_out;
5743 TRACE("[Thread %2u] meter (mmi)\n", p->thread_id);
5746 m = instr_meter_idx_hbo(p, t, ip);
5747 rte_prefetch0(m->n_pkts);
5748 time = rte_get_tsc_cycles();
5749 length = instr_meter_length_hbo(t, ip);
5750 color_in = (enum rte_color)ip->meter.color_in_val;
5752 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5753 &m->profile->profile,
5758 color_out &= m->color_mask;
5760 n_pkts = m->n_pkts[color_out];
5761 n_bytes = m->n_bytes[color_out];
5763 instr_meter_color_out_hbo_set(t, ip, color_out);
5765 m->n_pkts[color_out] = n_pkts + 1;
5766 m->n_bytes[color_out] = n_bytes + length;
5773 instr_meter_ihm_exec(struct rte_swx_pipeline *p)
5775 struct thread *t = &p->threads[p->thread_id];
5776 struct instruction *ip = t->ip;
5778 uint64_t time, n_pkts, n_bytes;
5780 enum rte_color color_in, color_out;
5782 TRACE("[Thread %2u] meter (ihm)\n", p->thread_id);
5785 m = instr_meter_idx_imm(p, ip);
5786 rte_prefetch0(m->n_pkts);
5787 time = rte_get_tsc_cycles();
5788 length = instr_meter_length_nbo(t, ip);
5789 color_in = instr_meter_color_in_hbo(t, ip);
5791 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5792 &m->profile->profile,
5797 color_out &= m->color_mask;
5799 n_pkts = m->n_pkts[color_out];
5800 n_bytes = m->n_bytes[color_out];
5802 instr_meter_color_out_hbo_set(t, ip, color_out);
5804 m->n_pkts[color_out] = n_pkts + 1;
5805 m->n_bytes[color_out] = n_bytes + length;
5812 instr_meter_ihi_exec(struct rte_swx_pipeline *p)
5814 struct thread *t = &p->threads[p->thread_id];
5815 struct instruction *ip = t->ip;
5817 uint64_t time, n_pkts, n_bytes;
5819 enum rte_color color_in, color_out;
5821 TRACE("[Thread %2u] meter (ihi)\n", p->thread_id);
5824 m = instr_meter_idx_imm(p, ip);
5825 rte_prefetch0(m->n_pkts);
5826 time = rte_get_tsc_cycles();
5827 length = instr_meter_length_nbo(t, ip);
5828 color_in = (enum rte_color)ip->meter.color_in_val;
5830 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5831 &m->profile->profile,
5836 color_out &= m->color_mask;
5838 n_pkts = m->n_pkts[color_out];
5839 n_bytes = m->n_bytes[color_out];
5841 instr_meter_color_out_hbo_set(t, ip, color_out);
5843 m->n_pkts[color_out] = n_pkts + 1;
5844 m->n_bytes[color_out] = n_bytes + length;
5851 instr_meter_imm_exec(struct rte_swx_pipeline *p)
5853 struct thread *t = &p->threads[p->thread_id];
5854 struct instruction *ip = t->ip;
5856 uint64_t time, n_pkts, n_bytes;
5858 enum rte_color color_in, color_out;
5860 TRACE("[Thread %2u] meter (imm)\n", p->thread_id);
5863 m = instr_meter_idx_imm(p, ip);
5864 rte_prefetch0(m->n_pkts);
5865 time = rte_get_tsc_cycles();
5866 length = instr_meter_length_hbo(t, ip);
5867 color_in = instr_meter_color_in_hbo(t, ip);
5869 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5870 &m->profile->profile,
5875 color_out &= m->color_mask;
5877 n_pkts = m->n_pkts[color_out];
5878 n_bytes = m->n_bytes[color_out];
5880 instr_meter_color_out_hbo_set(t, ip, color_out);
5882 m->n_pkts[color_out] = n_pkts + 1;
5883 m->n_bytes[color_out] = n_bytes + length;
5889 instr_meter_imi_exec(struct rte_swx_pipeline *p)
5891 struct thread *t = &p->threads[p->thread_id];
5892 struct instruction *ip = t->ip;
5894 uint64_t time, n_pkts, n_bytes;
5896 enum rte_color color_in, color_out;
5898 TRACE("[Thread %2u] meter (imi)\n", p->thread_id);
5901 m = instr_meter_idx_imm(p, ip);
5902 rte_prefetch0(m->n_pkts);
5903 time = rte_get_tsc_cycles();
5904 length = instr_meter_length_hbo(t, ip);
5905 color_in = (enum rte_color)ip->meter.color_in_val;
5907 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5908 &m->profile->profile,
5913 color_out &= m->color_mask;
5915 n_pkts = m->n_pkts[color_out];
5916 n_bytes = m->n_bytes[color_out];
5918 instr_meter_color_out_hbo_set(t, ip, color_out);
5920 m->n_pkts[color_out] = n_pkts + 1;
5921 m->n_bytes[color_out] = n_bytes + length;
5931 instr_jmp_translate(struct rte_swx_pipeline *p __rte_unused,
5932 struct action *action __rte_unused,
5935 struct instruction *instr,
5936 struct instruction_data *data)
5938 CHECK(n_tokens == 2, EINVAL);
5940 strcpy(data->jmp_label, tokens[1]);
5942 instr->type = INSTR_JMP;
5943 instr->jmp.ip = NULL; /* Resolved later. */
5948 instr_jmp_valid_translate(struct rte_swx_pipeline *p,
5949 struct action *action __rte_unused,
5952 struct instruction *instr,
5953 struct instruction_data *data)
5957 CHECK(n_tokens == 3, EINVAL);
5959 strcpy(data->jmp_label, tokens[1]);
5961 h = header_parse(p, tokens[2]);
5964 instr->type = INSTR_JMP_VALID;
5965 instr->jmp.ip = NULL; /* Resolved later. */
5966 instr->jmp.header_id = h->id;
5971 instr_jmp_invalid_translate(struct rte_swx_pipeline *p,
5972 struct action *action __rte_unused,
5975 struct instruction *instr,
5976 struct instruction_data *data)
5980 CHECK(n_tokens == 3, EINVAL);
5982 strcpy(data->jmp_label, tokens[1]);
5984 h = header_parse(p, tokens[2]);
5987 instr->type = INSTR_JMP_INVALID;
5988 instr->jmp.ip = NULL; /* Resolved later. */
5989 instr->jmp.header_id = h->id;
5994 instr_jmp_hit_translate(struct rte_swx_pipeline *p __rte_unused,
5995 struct action *action,
5998 struct instruction *instr,
5999 struct instruction_data *data)
6001 CHECK(!action, EINVAL);
6002 CHECK(n_tokens == 2, EINVAL);
6004 strcpy(data->jmp_label, tokens[1]);
6006 instr->type = INSTR_JMP_HIT;
6007 instr->jmp.ip = NULL; /* Resolved later. */
6012 instr_jmp_miss_translate(struct rte_swx_pipeline *p __rte_unused,
6013 struct action *action,
6016 struct instruction *instr,
6017 struct instruction_data *data)
6019 CHECK(!action, EINVAL);
6020 CHECK(n_tokens == 2, EINVAL);
6022 strcpy(data->jmp_label, tokens[1]);
6024 instr->type = INSTR_JMP_MISS;
6025 instr->jmp.ip = NULL; /* Resolved later. */
6030 instr_jmp_action_hit_translate(struct rte_swx_pipeline *p,
6031 struct action *action,
6034 struct instruction *instr,
6035 struct instruction_data *data)
6039 CHECK(!action, EINVAL);
6040 CHECK(n_tokens == 3, EINVAL);
6042 strcpy(data->jmp_label, tokens[1]);
6044 a = action_find(p, tokens[2]);
6047 instr->type = INSTR_JMP_ACTION_HIT;
6048 instr->jmp.ip = NULL; /* Resolved later. */
6049 instr->jmp.action_id = a->id;
6054 instr_jmp_action_miss_translate(struct rte_swx_pipeline *p,
6055 struct action *action,
6058 struct instruction *instr,
6059 struct instruction_data *data)
6063 CHECK(!action, EINVAL);
6064 CHECK(n_tokens == 3, EINVAL);
6066 strcpy(data->jmp_label, tokens[1]);
6068 a = action_find(p, tokens[2]);
6071 instr->type = INSTR_JMP_ACTION_MISS;
6072 instr->jmp.ip = NULL; /* Resolved later. */
6073 instr->jmp.action_id = a->id;
6078 instr_jmp_eq_translate(struct rte_swx_pipeline *p,
6079 struct action *action,
6082 struct instruction *instr,
6083 struct instruction_data *data)
6085 char *a = tokens[2], *b = tokens[3];
6086 struct field *fa, *fb;
6088 uint32_t a_struct_id, b_struct_id;
6090 CHECK(n_tokens == 4, EINVAL);
6092 strcpy(data->jmp_label, tokens[1]);
6094 fa = struct_field_parse(p, action, a, &a_struct_id);
6096 CHECK(!fa->var_size, EINVAL);
6098 /* JMP_EQ, JMP_EQ_MH, JMP_EQ_HM, JMP_EQ_HH. */
6099 fb = struct_field_parse(p, action, b, &b_struct_id);
6101 CHECK(!fb->var_size, EINVAL);
6103 instr->type = INSTR_JMP_EQ;
6104 if (a[0] != 'h' && b[0] == 'h')
6105 instr->type = INSTR_JMP_EQ_MH;
6106 if (a[0] == 'h' && b[0] != 'h')
6107 instr->type = INSTR_JMP_EQ_HM;
6108 if (a[0] == 'h' && b[0] == 'h')
6109 instr->type = INSTR_JMP_EQ_HH;
6110 instr->jmp.ip = NULL; /* Resolved later. */
6112 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6113 instr->jmp.a.n_bits = fa->n_bits;
6114 instr->jmp.a.offset = fa->offset / 8;
6115 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6116 instr->jmp.b.n_bits = fb->n_bits;
6117 instr->jmp.b.offset = fb->offset / 8;
6122 b_val = strtoull(b, &b, 0);
6123 CHECK(!b[0], EINVAL);
6126 b_val = hton64(b_val) >> (64 - fa->n_bits);
6128 instr->type = INSTR_JMP_EQ_I;
6129 instr->jmp.ip = NULL; /* Resolved later. */
6130 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6131 instr->jmp.a.n_bits = fa->n_bits;
6132 instr->jmp.a.offset = fa->offset / 8;
6133 instr->jmp.b_val = b_val;
6138 instr_jmp_neq_translate(struct rte_swx_pipeline *p,
6139 struct action *action,
6142 struct instruction *instr,
6143 struct instruction_data *data)
6145 char *a = tokens[2], *b = tokens[3];
6146 struct field *fa, *fb;
6148 uint32_t a_struct_id, b_struct_id;
6150 CHECK(n_tokens == 4, EINVAL);
6152 strcpy(data->jmp_label, tokens[1]);
6154 fa = struct_field_parse(p, action, a, &a_struct_id);
6156 CHECK(!fa->var_size, EINVAL);
6158 /* JMP_NEQ, JMP_NEQ_MH, JMP_NEQ_HM, JMP_NEQ_HH. */
6159 fb = struct_field_parse(p, action, b, &b_struct_id);
6161 CHECK(!fb->var_size, EINVAL);
6163 instr->type = INSTR_JMP_NEQ;
6164 if (a[0] != 'h' && b[0] == 'h')
6165 instr->type = INSTR_JMP_NEQ_MH;
6166 if (a[0] == 'h' && b[0] != 'h')
6167 instr->type = INSTR_JMP_NEQ_HM;
6168 if (a[0] == 'h' && b[0] == 'h')
6169 instr->type = INSTR_JMP_NEQ_HH;
6170 instr->jmp.ip = NULL; /* Resolved later. */
6172 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6173 instr->jmp.a.n_bits = fa->n_bits;
6174 instr->jmp.a.offset = fa->offset / 8;
6175 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6176 instr->jmp.b.n_bits = fb->n_bits;
6177 instr->jmp.b.offset = fb->offset / 8;
6182 b_val = strtoull(b, &b, 0);
6183 CHECK(!b[0], EINVAL);
6186 b_val = hton64(b_val) >> (64 - fa->n_bits);
6188 instr->type = INSTR_JMP_NEQ_I;
6189 instr->jmp.ip = NULL; /* Resolved later. */
6190 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6191 instr->jmp.a.n_bits = fa->n_bits;
6192 instr->jmp.a.offset = fa->offset / 8;
6193 instr->jmp.b_val = b_val;
6198 instr_jmp_lt_translate(struct rte_swx_pipeline *p,
6199 struct action *action,
6202 struct instruction *instr,
6203 struct instruction_data *data)
6205 char *a = tokens[2], *b = tokens[3];
6206 struct field *fa, *fb;
6208 uint32_t a_struct_id, b_struct_id;
6210 CHECK(n_tokens == 4, EINVAL);
6212 strcpy(data->jmp_label, tokens[1]);
6214 fa = struct_field_parse(p, action, a, &a_struct_id);
6216 CHECK(!fa->var_size, EINVAL);
6218 /* JMP_LT, JMP_LT_MH, JMP_LT_HM, JMP_LT_HH. */
6219 fb = struct_field_parse(p, action, b, &b_struct_id);
6221 CHECK(!fb->var_size, EINVAL);
6223 instr->type = INSTR_JMP_LT;
6224 if (a[0] == 'h' && b[0] != 'h')
6225 instr->type = INSTR_JMP_LT_HM;
6226 if (a[0] != 'h' && b[0] == 'h')
6227 instr->type = INSTR_JMP_LT_MH;
6228 if (a[0] == 'h' && b[0] == 'h')
6229 instr->type = INSTR_JMP_LT_HH;
6230 instr->jmp.ip = NULL; /* Resolved later. */
6232 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6233 instr->jmp.a.n_bits = fa->n_bits;
6234 instr->jmp.a.offset = fa->offset / 8;
6235 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6236 instr->jmp.b.n_bits = fb->n_bits;
6237 instr->jmp.b.offset = fb->offset / 8;
6241 /* JMP_LT_MI, JMP_LT_HI. */
6242 b_val = strtoull(b, &b, 0);
6243 CHECK(!b[0], EINVAL);
6245 instr->type = INSTR_JMP_LT_MI;
6247 instr->type = INSTR_JMP_LT_HI;
6248 instr->jmp.ip = NULL; /* Resolved later. */
6250 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6251 instr->jmp.a.n_bits = fa->n_bits;
6252 instr->jmp.a.offset = fa->offset / 8;
6253 instr->jmp.b_val = b_val;
6258 instr_jmp_gt_translate(struct rte_swx_pipeline *p,
6259 struct action *action,
6262 struct instruction *instr,
6263 struct instruction_data *data)
6265 char *a = tokens[2], *b = tokens[3];
6266 struct field *fa, *fb;
6268 uint32_t a_struct_id, b_struct_id;
6270 CHECK(n_tokens == 4, EINVAL);
6272 strcpy(data->jmp_label, tokens[1]);
6274 fa = struct_field_parse(p, action, a, &a_struct_id);
6276 CHECK(!fa->var_size, EINVAL);
6278 /* JMP_GT, JMP_GT_MH, JMP_GT_HM, JMP_GT_HH. */
6279 fb = struct_field_parse(p, action, b, &b_struct_id);
6281 CHECK(!fb->var_size, EINVAL);
6283 instr->type = INSTR_JMP_GT;
6284 if (a[0] == 'h' && b[0] != 'h')
6285 instr->type = INSTR_JMP_GT_HM;
6286 if (a[0] != 'h' && b[0] == 'h')
6287 instr->type = INSTR_JMP_GT_MH;
6288 if (a[0] == 'h' && b[0] == 'h')
6289 instr->type = INSTR_JMP_GT_HH;
6290 instr->jmp.ip = NULL; /* Resolved later. */
6292 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6293 instr->jmp.a.n_bits = fa->n_bits;
6294 instr->jmp.a.offset = fa->offset / 8;
6295 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6296 instr->jmp.b.n_bits = fb->n_bits;
6297 instr->jmp.b.offset = fb->offset / 8;
6301 /* JMP_GT_MI, JMP_GT_HI. */
6302 b_val = strtoull(b, &b, 0);
6303 CHECK(!b[0], EINVAL);
6305 instr->type = INSTR_JMP_GT_MI;
6307 instr->type = INSTR_JMP_GT_HI;
6308 instr->jmp.ip = NULL; /* Resolved later. */
6310 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6311 instr->jmp.a.n_bits = fa->n_bits;
6312 instr->jmp.a.offset = fa->offset / 8;
6313 instr->jmp.b_val = b_val;
6318 instr_jmp_exec(struct rte_swx_pipeline *p)
6320 struct thread *t = &p->threads[p->thread_id];
6321 struct instruction *ip = t->ip;
6323 TRACE("[Thread %2u] jmp\n", p->thread_id);
6325 thread_ip_set(t, ip->jmp.ip);
6329 instr_jmp_valid_exec(struct rte_swx_pipeline *p)
6331 struct thread *t = &p->threads[p->thread_id];
6332 struct instruction *ip = t->ip;
6333 uint32_t header_id = ip->jmp.header_id;
6335 TRACE("[Thread %2u] jmpv\n", p->thread_id);
6337 t->ip = HEADER_VALID(t, header_id) ? ip->jmp.ip : (t->ip + 1);
6341 instr_jmp_invalid_exec(struct rte_swx_pipeline *p)
6343 struct thread *t = &p->threads[p->thread_id];
6344 struct instruction *ip = t->ip;
6345 uint32_t header_id = ip->jmp.header_id;
6347 TRACE("[Thread %2u] jmpnv\n", p->thread_id);
6349 t->ip = HEADER_VALID(t, header_id) ? (t->ip + 1) : ip->jmp.ip;
6353 instr_jmp_hit_exec(struct rte_swx_pipeline *p)
6355 struct thread *t = &p->threads[p->thread_id];
6356 struct instruction *ip = t->ip;
6357 struct instruction *ip_next[] = {t->ip + 1, ip->jmp.ip};
6359 TRACE("[Thread %2u] jmph\n", p->thread_id);
6361 t->ip = ip_next[t->hit];
6365 instr_jmp_miss_exec(struct rte_swx_pipeline *p)
6367 struct thread *t = &p->threads[p->thread_id];
6368 struct instruction *ip = t->ip;
6369 struct instruction *ip_next[] = {ip->jmp.ip, t->ip + 1};
6371 TRACE("[Thread %2u] jmpnh\n", p->thread_id);
6373 t->ip = ip_next[t->hit];
6377 instr_jmp_action_hit_exec(struct rte_swx_pipeline *p)
6379 struct thread *t = &p->threads[p->thread_id];
6380 struct instruction *ip = t->ip;
6382 TRACE("[Thread %2u] jmpa\n", p->thread_id);
6384 t->ip = (ip->jmp.action_id == t->action_id) ? ip->jmp.ip : (t->ip + 1);
6388 instr_jmp_action_miss_exec(struct rte_swx_pipeline *p)
6390 struct thread *t = &p->threads[p->thread_id];
6391 struct instruction *ip = t->ip;
6393 TRACE("[Thread %2u] jmpna\n", p->thread_id);
6395 t->ip = (ip->jmp.action_id == t->action_id) ? (t->ip + 1) : ip->jmp.ip;
6399 instr_jmp_eq_exec(struct rte_swx_pipeline *p)
6401 struct thread *t = &p->threads[p->thread_id];
6402 struct instruction *ip = t->ip;
6404 TRACE("[Thread %2u] jmpeq\n", p->thread_id);
6410 instr_jmp_eq_mh_exec(struct rte_swx_pipeline *p)
6412 struct thread *t = &p->threads[p->thread_id];
6413 struct instruction *ip = t->ip;
6415 TRACE("[Thread %2u] jmpeq (mh)\n", p->thread_id);
6417 JMP_CMP_MH(t, ip, ==);
6421 instr_jmp_eq_hm_exec(struct rte_swx_pipeline *p)
6423 struct thread *t = &p->threads[p->thread_id];
6424 struct instruction *ip = t->ip;
6426 TRACE("[Thread %2u] jmpeq (hm)\n", p->thread_id);
6428 JMP_CMP_HM(t, ip, ==);
6432 instr_jmp_eq_hh_exec(struct rte_swx_pipeline *p)
6434 struct thread *t = &p->threads[p->thread_id];
6435 struct instruction *ip = t->ip;
6437 TRACE("[Thread %2u] jmpeq (hh)\n", p->thread_id);
6439 JMP_CMP_HH_FAST(t, ip, ==);
6443 instr_jmp_eq_i_exec(struct rte_swx_pipeline *p)
6445 struct thread *t = &p->threads[p->thread_id];
6446 struct instruction *ip = t->ip;
6448 TRACE("[Thread %2u] jmpeq (i)\n", p->thread_id);
6450 JMP_CMP_I(t, ip, ==);
6454 instr_jmp_neq_exec(struct rte_swx_pipeline *p)
6456 struct thread *t = &p->threads[p->thread_id];
6457 struct instruction *ip = t->ip;
6459 TRACE("[Thread %2u] jmpneq\n", p->thread_id);
6465 instr_jmp_neq_mh_exec(struct rte_swx_pipeline *p)
6467 struct thread *t = &p->threads[p->thread_id];
6468 struct instruction *ip = t->ip;
6470 TRACE("[Thread %2u] jmpneq (mh)\n", p->thread_id);
6472 JMP_CMP_MH(t, ip, !=);
6476 instr_jmp_neq_hm_exec(struct rte_swx_pipeline *p)
6478 struct thread *t = &p->threads[p->thread_id];
6479 struct instruction *ip = t->ip;
6481 TRACE("[Thread %2u] jmpneq (hm)\n", p->thread_id);
6483 JMP_CMP_HM(t, ip, !=);
6487 instr_jmp_neq_hh_exec(struct rte_swx_pipeline *p)
6489 struct thread *t = &p->threads[p->thread_id];
6490 struct instruction *ip = t->ip;
6492 TRACE("[Thread %2u] jmpneq (hh)\n", p->thread_id);
6494 JMP_CMP_HH_FAST(t, ip, !=);
6498 instr_jmp_neq_i_exec(struct rte_swx_pipeline *p)
6500 struct thread *t = &p->threads[p->thread_id];
6501 struct instruction *ip = t->ip;
6503 TRACE("[Thread %2u] jmpneq (i)\n", p->thread_id);
6505 JMP_CMP_I(t, ip, !=);
6509 instr_jmp_lt_exec(struct rte_swx_pipeline *p)
6511 struct thread *t = &p->threads[p->thread_id];
6512 struct instruction *ip = t->ip;
6514 TRACE("[Thread %2u] jmplt\n", p->thread_id);
6520 instr_jmp_lt_mh_exec(struct rte_swx_pipeline *p)
6522 struct thread *t = &p->threads[p->thread_id];
6523 struct instruction *ip = t->ip;
6525 TRACE("[Thread %2u] jmplt (mh)\n", p->thread_id);
6527 JMP_CMP_MH(t, ip, <);
6531 instr_jmp_lt_hm_exec(struct rte_swx_pipeline *p)
6533 struct thread *t = &p->threads[p->thread_id];
6534 struct instruction *ip = t->ip;
6536 TRACE("[Thread %2u] jmplt (hm)\n", p->thread_id);
6538 JMP_CMP_HM(t, ip, <);
6542 instr_jmp_lt_hh_exec(struct rte_swx_pipeline *p)
6544 struct thread *t = &p->threads[p->thread_id];
6545 struct instruction *ip = t->ip;
6547 TRACE("[Thread %2u] jmplt (hh)\n", p->thread_id);
6549 JMP_CMP_HH(t, ip, <);
6553 instr_jmp_lt_mi_exec(struct rte_swx_pipeline *p)
6555 struct thread *t = &p->threads[p->thread_id];
6556 struct instruction *ip = t->ip;
6558 TRACE("[Thread %2u] jmplt (mi)\n", p->thread_id);
6560 JMP_CMP_MI(t, ip, <);
6564 instr_jmp_lt_hi_exec(struct rte_swx_pipeline *p)
6566 struct thread *t = &p->threads[p->thread_id];
6567 struct instruction *ip = t->ip;
6569 TRACE("[Thread %2u] jmplt (hi)\n", p->thread_id);
6571 JMP_CMP_HI(t, ip, <);
6575 instr_jmp_gt_exec(struct rte_swx_pipeline *p)
6577 struct thread *t = &p->threads[p->thread_id];
6578 struct instruction *ip = t->ip;
6580 TRACE("[Thread %2u] jmpgt\n", p->thread_id);
6586 instr_jmp_gt_mh_exec(struct rte_swx_pipeline *p)
6588 struct thread *t = &p->threads[p->thread_id];
6589 struct instruction *ip = t->ip;
6591 TRACE("[Thread %2u] jmpgt (mh)\n", p->thread_id);
6593 JMP_CMP_MH(t, ip, >);
6597 instr_jmp_gt_hm_exec(struct rte_swx_pipeline *p)
6599 struct thread *t = &p->threads[p->thread_id];
6600 struct instruction *ip = t->ip;
6602 TRACE("[Thread %2u] jmpgt (hm)\n", p->thread_id);
6604 JMP_CMP_HM(t, ip, >);
6608 instr_jmp_gt_hh_exec(struct rte_swx_pipeline *p)
6610 struct thread *t = &p->threads[p->thread_id];
6611 struct instruction *ip = t->ip;
6613 TRACE("[Thread %2u] jmpgt (hh)\n", p->thread_id);
6615 JMP_CMP_HH(t, ip, >);
6619 instr_jmp_gt_mi_exec(struct rte_swx_pipeline *p)
6621 struct thread *t = &p->threads[p->thread_id];
6622 struct instruction *ip = t->ip;
6624 TRACE("[Thread %2u] jmpgt (mi)\n", p->thread_id);
6626 JMP_CMP_MI(t, ip, >);
6630 instr_jmp_gt_hi_exec(struct rte_swx_pipeline *p)
6632 struct thread *t = &p->threads[p->thread_id];
6633 struct instruction *ip = t->ip;
6635 TRACE("[Thread %2u] jmpgt (hi)\n", p->thread_id);
6637 JMP_CMP_HI(t, ip, >);
6644 instr_return_translate(struct rte_swx_pipeline *p __rte_unused,
6645 struct action *action,
6646 char **tokens __rte_unused,
6648 struct instruction *instr,
6649 struct instruction_data *data __rte_unused)
6651 CHECK(action, EINVAL);
6652 CHECK(n_tokens == 1, EINVAL);
6654 instr->type = INSTR_RETURN;
6659 instr_return_exec(struct rte_swx_pipeline *p)
6661 struct thread *t = &p->threads[p->thread_id];
6663 TRACE("[Thread %2u] return\n", p->thread_id);
6669 instr_translate(struct rte_swx_pipeline *p,
6670 struct action *action,
6672 struct instruction *instr,
6673 struct instruction_data *data)
6675 char *tokens[RTE_SWX_INSTRUCTION_TOKENS_MAX];
6676 int n_tokens = 0, tpos = 0;
6678 /* Parse the instruction string into tokens. */
6682 token = strtok_r(string, " \t\v", &string);
6686 CHECK(n_tokens < RTE_SWX_INSTRUCTION_TOKENS_MAX, EINVAL);
6687 CHECK_NAME(token, EINVAL);
6689 tokens[n_tokens] = token;
6693 CHECK(n_tokens, EINVAL);
6695 /* Handle the optional instruction label. */
6696 if ((n_tokens >= 2) && !strcmp(tokens[1], ":")) {
6697 strcpy(data->label, tokens[0]);
6700 CHECK(n_tokens - tpos, EINVAL);
6703 /* Identify the instruction type. */
6704 if (!strcmp(tokens[tpos], "rx"))
6705 return instr_rx_translate(p,
6712 if (!strcmp(tokens[tpos], "tx"))
6713 return instr_tx_translate(p,
6720 if (!strcmp(tokens[tpos], "drop"))
6721 return instr_drop_translate(p,
6728 if (!strcmp(tokens[tpos], "extract"))
6729 return instr_hdr_extract_translate(p,
6736 if (!strcmp(tokens[tpos], "lookahead"))
6737 return instr_hdr_lookahead_translate(p,
6744 if (!strcmp(tokens[tpos], "emit"))
6745 return instr_hdr_emit_translate(p,
6752 if (!strcmp(tokens[tpos], "validate"))
6753 return instr_hdr_validate_translate(p,
6760 if (!strcmp(tokens[tpos], "invalidate"))
6761 return instr_hdr_invalidate_translate(p,
6768 if (!strcmp(tokens[tpos], "mov"))
6769 return instr_mov_translate(p,
6776 if (!strcmp(tokens[tpos], "add"))
6777 return instr_alu_add_translate(p,
6784 if (!strcmp(tokens[tpos], "sub"))
6785 return instr_alu_sub_translate(p,
6792 if (!strcmp(tokens[tpos], "ckadd"))
6793 return instr_alu_ckadd_translate(p,
6800 if (!strcmp(tokens[tpos], "cksub"))
6801 return instr_alu_cksub_translate(p,
6808 if (!strcmp(tokens[tpos], "and"))
6809 return instr_alu_and_translate(p,
6816 if (!strcmp(tokens[tpos], "or"))
6817 return instr_alu_or_translate(p,
6824 if (!strcmp(tokens[tpos], "xor"))
6825 return instr_alu_xor_translate(p,
6832 if (!strcmp(tokens[tpos], "shl"))
6833 return instr_alu_shl_translate(p,
6840 if (!strcmp(tokens[tpos], "shr"))
6841 return instr_alu_shr_translate(p,
6848 if (!strcmp(tokens[tpos], "regprefetch"))
6849 return instr_regprefetch_translate(p,
6856 if (!strcmp(tokens[tpos], "regrd"))
6857 return instr_regrd_translate(p,
6864 if (!strcmp(tokens[tpos], "regwr"))
6865 return instr_regwr_translate(p,
6872 if (!strcmp(tokens[tpos], "regadd"))
6873 return instr_regadd_translate(p,
6880 if (!strcmp(tokens[tpos], "metprefetch"))
6881 return instr_metprefetch_translate(p,
6888 if (!strcmp(tokens[tpos], "meter"))
6889 return instr_meter_translate(p,
6896 if (!strcmp(tokens[tpos], "table"))
6897 return instr_table_translate(p,
6904 if (!strcmp(tokens[tpos], "learn"))
6905 return instr_learn_translate(p,
6912 if (!strcmp(tokens[tpos], "forget"))
6913 return instr_forget_translate(p,
6920 if (!strcmp(tokens[tpos], "extern"))
6921 return instr_extern_translate(p,
6928 if (!strcmp(tokens[tpos], "jmp"))
6929 return instr_jmp_translate(p,
6936 if (!strcmp(tokens[tpos], "jmpv"))
6937 return instr_jmp_valid_translate(p,
6944 if (!strcmp(tokens[tpos], "jmpnv"))
6945 return instr_jmp_invalid_translate(p,
6952 if (!strcmp(tokens[tpos], "jmph"))
6953 return instr_jmp_hit_translate(p,
6960 if (!strcmp(tokens[tpos], "jmpnh"))
6961 return instr_jmp_miss_translate(p,
6968 if (!strcmp(tokens[tpos], "jmpa"))
6969 return instr_jmp_action_hit_translate(p,
6976 if (!strcmp(tokens[tpos], "jmpna"))
6977 return instr_jmp_action_miss_translate(p,
6984 if (!strcmp(tokens[tpos], "jmpeq"))
6985 return instr_jmp_eq_translate(p,
6992 if (!strcmp(tokens[tpos], "jmpneq"))
6993 return instr_jmp_neq_translate(p,
7000 if (!strcmp(tokens[tpos], "jmplt"))
7001 return instr_jmp_lt_translate(p,
7008 if (!strcmp(tokens[tpos], "jmpgt"))
7009 return instr_jmp_gt_translate(p,
7016 if (!strcmp(tokens[tpos], "return"))
7017 return instr_return_translate(p,
7027 static struct instruction_data *
7028 label_find(struct instruction_data *data, uint32_t n, const char *label)
7032 for (i = 0; i < n; i++)
7033 if (!strcmp(label, data[i].label))
7040 label_is_used(struct instruction_data *data, uint32_t n, const char *label)
7042 uint32_t count = 0, i;
7047 for (i = 0; i < n; i++)
7048 if (!strcmp(label, data[i].jmp_label))
7055 instr_label_check(struct instruction_data *instruction_data,
7056 uint32_t n_instructions)
7060 /* Check that all instruction labels are unique. */
7061 for (i = 0; i < n_instructions; i++) {
7062 struct instruction_data *data = &instruction_data[i];
7063 char *label = data->label;
7069 for (j = i + 1; j < n_instructions; j++)
7070 CHECK(strcmp(label, data[j].label), EINVAL);
7073 /* Get users for each instruction label. */
7074 for (i = 0; i < n_instructions; i++) {
7075 struct instruction_data *data = &instruction_data[i];
7076 char *label = data->label;
7078 data->n_users = label_is_used(instruction_data,
7087 instr_jmp_resolve(struct instruction *instructions,
7088 struct instruction_data *instruction_data,
7089 uint32_t n_instructions)
7093 for (i = 0; i < n_instructions; i++) {
7094 struct instruction *instr = &instructions[i];
7095 struct instruction_data *data = &instruction_data[i];
7096 struct instruction_data *found;
7098 if (!instruction_is_jmp(instr))
7101 found = label_find(instruction_data,
7104 CHECK(found, EINVAL);
7106 instr->jmp.ip = &instructions[found - instruction_data];
7113 instr_verify(struct rte_swx_pipeline *p __rte_unused,
7115 struct instruction *instr,
7116 struct instruction_data *data __rte_unused,
7117 uint32_t n_instructions)
7120 enum instruction_type type;
7123 /* Check that the first instruction is rx. */
7124 CHECK(instr[0].type == INSTR_RX, EINVAL);
7126 /* Check that there is at least one tx instruction. */
7127 for (i = 0; i < n_instructions; i++) {
7128 type = instr[i].type;
7130 if (instruction_is_tx(type))
7133 CHECK(i < n_instructions, EINVAL);
7135 /* Check that the last instruction is either tx or unconditional
7138 type = instr[n_instructions - 1].type;
7139 CHECK(instruction_is_tx(type) || (type == INSTR_JMP), EINVAL);
7143 enum instruction_type type;
7146 /* Check that there is at least one return or tx instruction. */
7147 for (i = 0; i < n_instructions; i++) {
7148 type = instr[i].type;
7150 if ((type == INSTR_RETURN) || instruction_is_tx(type))
7153 CHECK(i < n_instructions, EINVAL);
7160 instr_compact(struct instruction *instructions,
7161 struct instruction_data *instruction_data,
7162 uint32_t n_instructions)
7164 uint32_t i, pos = 0;
7166 /* Eliminate the invalid instructions that have been optimized out. */
7167 for (i = 0; i < n_instructions; i++) {
7168 struct instruction *instr = &instructions[i];
7169 struct instruction_data *data = &instruction_data[i];
7175 memcpy(&instructions[pos], instr, sizeof(*instr));
7176 memcpy(&instruction_data[pos], data, sizeof(*data));
7186 instr_pattern_extract_many_search(struct instruction *instr,
7187 struct instruction_data *data,
7189 uint32_t *n_pattern_instr)
7193 for (i = 0; i < n_instr; i++) {
7194 if (data[i].invalid)
7197 if (instr[i].type != INSTR_HDR_EXTRACT)
7200 if (i == RTE_DIM(instr->io.hdr.header_id))
7203 if (i && data[i].n_users)
7210 *n_pattern_instr = i;
7215 instr_pattern_extract_many_replace(struct instruction *instr,
7216 struct instruction_data *data,
7221 for (i = 1; i < n_instr; i++) {
7223 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
7224 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
7225 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
7227 data[i].invalid = 1;
7232 instr_pattern_extract_many_optimize(struct instruction *instructions,
7233 struct instruction_data *instruction_data,
7234 uint32_t n_instructions)
7238 for (i = 0; i < n_instructions; ) {
7239 struct instruction *instr = &instructions[i];
7240 struct instruction_data *data = &instruction_data[i];
7241 uint32_t n_instr = 0;
7245 detected = instr_pattern_extract_many_search(instr,
7250 instr_pattern_extract_many_replace(instr,
7257 /* No pattern starting at the current instruction. */
7261 /* Eliminate the invalid instructions that have been optimized out. */
7262 n_instructions = instr_compact(instructions,
7266 return n_instructions;
7270 instr_pattern_emit_many_tx_search(struct instruction *instr,
7271 struct instruction_data *data,
7273 uint32_t *n_pattern_instr)
7277 for (i = 0; i < n_instr; i++) {
7278 if (data[i].invalid)
7281 if (instr[i].type != INSTR_HDR_EMIT)
7284 if (i == RTE_DIM(instr->io.hdr.header_id))
7287 if (i && data[i].n_users)
7294 if (!instruction_is_tx(instr[i].type))
7297 if (data[i].n_users)
7302 *n_pattern_instr = i;
7307 instr_pattern_emit_many_tx_replace(struct instruction *instr,
7308 struct instruction_data *data,
7313 /* Any emit instruction in addition to the first one. */
7314 for (i = 1; i < n_instr - 1; i++) {
7316 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
7317 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
7318 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
7320 data[i].invalid = 1;
7323 /* The TX instruction is the last one in the pattern. */
7325 instr[0].io.io.offset = instr[i].io.io.offset;
7326 instr[0].io.io.n_bits = instr[i].io.io.n_bits;
7327 data[i].invalid = 1;
7331 instr_pattern_emit_many_tx_optimize(struct instruction *instructions,
7332 struct instruction_data *instruction_data,
7333 uint32_t n_instructions)
7337 for (i = 0; i < n_instructions; ) {
7338 struct instruction *instr = &instructions[i];
7339 struct instruction_data *data = &instruction_data[i];
7340 uint32_t n_instr = 0;
7343 /* Emit many + TX. */
7344 detected = instr_pattern_emit_many_tx_search(instr,
7349 instr_pattern_emit_many_tx_replace(instr,
7356 /* No pattern starting at the current instruction. */
7360 /* Eliminate the invalid instructions that have been optimized out. */
7361 n_instructions = instr_compact(instructions,
7365 return n_instructions;
7369 action_arg_src_mov_count(struct action *a,
7371 struct instruction *instructions,
7372 struct instruction_data *instruction_data,
7373 uint32_t n_instructions);
7376 instr_pattern_mov_all_validate_search(struct rte_swx_pipeline *p,
7378 struct instruction *instr,
7379 struct instruction_data *data,
7381 struct instruction *instructions,
7382 struct instruction_data *instruction_data,
7383 uint32_t n_instructions,
7384 uint32_t *n_pattern_instr)
7387 uint32_t src_field_id, i, j;
7389 /* Prerequisites. */
7393 /* First instruction: MOV_HM. */
7394 if (data[0].invalid || (instr[0].type != INSTR_MOV_HM))
7397 h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
7398 if (!h || h->st->var_size)
7401 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
7402 if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
7405 if (src_field_id == a->st->n_fields)
7408 if (instr[0].mov.dst.offset ||
7409 (instr[0].mov.dst.n_bits != h->st->fields[0].n_bits) ||
7410 instr[0].mov.src.struct_id ||
7411 (instr[0].mov.src.n_bits != a->st->fields[src_field_id].n_bits) ||
7412 (instr[0].mov.dst.n_bits != instr[0].mov.src.n_bits))
7415 if ((n_instr < h->st->n_fields + 1) ||
7416 (a->st->n_fields < src_field_id + h->st->n_fields + 1))
7419 /* Subsequent instructions: MOV_HM. */
7420 for (i = 1; i < h->st->n_fields; i++)
7421 if (data[i].invalid ||
7423 (instr[i].type != INSTR_MOV_HM) ||
7424 (instr[i].mov.dst.struct_id != h->struct_id) ||
7425 (instr[i].mov.dst.offset != h->st->fields[i].offset / 8) ||
7426 (instr[i].mov.dst.n_bits != h->st->fields[i].n_bits) ||
7427 instr[i].mov.src.struct_id ||
7428 (instr[i].mov.src.offset != a->st->fields[src_field_id + i].offset / 8) ||
7429 (instr[i].mov.src.n_bits != a->st->fields[src_field_id + i].n_bits) ||
7430 (instr[i].mov.dst.n_bits != instr[i].mov.src.n_bits))
7433 /* Last instruction: HDR_VALIDATE. */
7434 if ((instr[i].type != INSTR_HDR_VALIDATE) ||
7435 (instr[i].valid.header_id != h->id))
7438 /* Check that none of the action args that are used as source for this
7439 * DMA transfer are not used as source in any other mov instruction.
7441 for (j = src_field_id; j < src_field_id + h->st->n_fields; j++) {
7444 n_users = action_arg_src_mov_count(a,
7453 *n_pattern_instr = 1 + i;
7458 instr_pattern_mov_all_validate_replace(struct rte_swx_pipeline *p,
7460 struct instruction *instr,
7461 struct instruction_data *data,
7465 uint32_t src_field_id, src_offset, i;
7467 /* Read from the instructions before they are modified. */
7468 h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
7472 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
7473 if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
7476 if (src_field_id == a->st->n_fields)
7479 src_offset = instr[0].mov.src.offset;
7481 /* Modify the instructions. */
7482 instr[0].type = INSTR_DMA_HT;
7483 instr[0].dma.dst.header_id[0] = h->id;
7484 instr[0].dma.dst.struct_id[0] = h->struct_id;
7485 instr[0].dma.src.offset[0] = (uint8_t)src_offset;
7486 instr[0].dma.n_bytes[0] = h->st->n_bits / 8;
7488 for (i = 1; i < n_instr; i++)
7489 data[i].invalid = 1;
7491 /* Update the endianness of the action arguments to header endianness. */
7492 for (i = 0; i < h->st->n_fields; i++)
7493 a->args_endianness[src_field_id + i] = 1;
7497 instr_pattern_mov_all_validate_optimize(struct rte_swx_pipeline *p,
7499 struct instruction *instructions,
7500 struct instruction_data *instruction_data,
7501 uint32_t n_instructions)
7506 return n_instructions;
7508 for (i = 0; i < n_instructions; ) {
7509 struct instruction *instr = &instructions[i];
7510 struct instruction_data *data = &instruction_data[i];
7511 uint32_t n_instr = 0;
7514 /* Mov all + validate. */
7515 detected = instr_pattern_mov_all_validate_search(p,
7525 instr_pattern_mov_all_validate_replace(p, a, instr, data, n_instr);
7530 /* No pattern starting at the current instruction. */
7534 /* Eliminate the invalid instructions that have been optimized out. */
7535 n_instructions = instr_compact(instructions,
7539 return n_instructions;
7543 instr_pattern_dma_many_search(struct instruction *instr,
7544 struct instruction_data *data,
7546 uint32_t *n_pattern_instr)
7550 for (i = 0; i < n_instr; i++) {
7551 if (data[i].invalid)
7554 if (instr[i].type != INSTR_DMA_HT)
7557 if (i == RTE_DIM(instr->dma.dst.header_id))
7560 if (i && data[i].n_users)
7567 *n_pattern_instr = i;
7572 instr_pattern_dma_many_replace(struct instruction *instr,
7573 struct instruction_data *data,
7578 for (i = 1; i < n_instr; i++) {
7580 instr[0].dma.dst.header_id[i] = instr[i].dma.dst.header_id[0];
7581 instr[0].dma.dst.struct_id[i] = instr[i].dma.dst.struct_id[0];
7582 instr[0].dma.src.offset[i] = instr[i].dma.src.offset[0];
7583 instr[0].dma.n_bytes[i] = instr[i].dma.n_bytes[0];
7585 data[i].invalid = 1;
7590 instr_pattern_dma_many_optimize(struct instruction *instructions,
7591 struct instruction_data *instruction_data,
7592 uint32_t n_instructions)
7596 for (i = 0; i < n_instructions; ) {
7597 struct instruction *instr = &instructions[i];
7598 struct instruction_data *data = &instruction_data[i];
7599 uint32_t n_instr = 0;
7603 detected = instr_pattern_dma_many_search(instr,
7608 instr_pattern_dma_many_replace(instr, data, n_instr);
7613 /* No pattern starting at the current instruction. */
7617 /* Eliminate the invalid instructions that have been optimized out. */
7618 n_instructions = instr_compact(instructions,
7622 return n_instructions;
7626 instr_optimize(struct rte_swx_pipeline *p,
7628 struct instruction *instructions,
7629 struct instruction_data *instruction_data,
7630 uint32_t n_instructions)
7633 n_instructions = instr_pattern_extract_many_optimize(instructions,
7637 /* Emit many + TX. */
7638 n_instructions = instr_pattern_emit_many_tx_optimize(instructions,
7642 /* Mov all + validate. */
7643 n_instructions = instr_pattern_mov_all_validate_optimize(p,
7650 n_instructions = instr_pattern_dma_many_optimize(instructions,
7654 return n_instructions;
7658 instruction_config(struct rte_swx_pipeline *p,
7660 const char **instructions,
7661 uint32_t n_instructions)
7663 struct instruction *instr = NULL;
7664 struct instruction_data *data = NULL;
7668 CHECK(n_instructions, EINVAL);
7669 CHECK(instructions, EINVAL);
7670 for (i = 0; i < n_instructions; i++)
7671 CHECK_INSTRUCTION(instructions[i], EINVAL);
7673 /* Memory allocation. */
7674 instr = calloc(n_instructions, sizeof(struct instruction));
7680 data = calloc(n_instructions, sizeof(struct instruction_data));
7686 for (i = 0; i < n_instructions; i++) {
7687 char *string = strdup(instructions[i]);
7693 err = instr_translate(p, a, string, &instr[i], &data[i]);
7702 err = instr_label_check(data, n_instructions);
7706 err = instr_verify(p, a, instr, data, n_instructions);
7710 n_instructions = instr_optimize(p, a, instr, data, n_instructions);
7712 err = instr_jmp_resolve(instr, data, n_instructions);
7717 a->instructions = instr;
7718 a->n_instructions = n_instructions;
7720 p->instructions = instr;
7721 p->n_instructions = n_instructions;
7733 typedef void (*instr_exec_t)(struct rte_swx_pipeline *);
7735 static instr_exec_t instruction_table[] = {
7736 [INSTR_RX] = instr_rx_exec,
7737 [INSTR_TX] = instr_tx_exec,
7738 [INSTR_TX_I] = instr_tx_i_exec,
7740 [INSTR_HDR_EXTRACT] = instr_hdr_extract_exec,
7741 [INSTR_HDR_EXTRACT2] = instr_hdr_extract2_exec,
7742 [INSTR_HDR_EXTRACT3] = instr_hdr_extract3_exec,
7743 [INSTR_HDR_EXTRACT4] = instr_hdr_extract4_exec,
7744 [INSTR_HDR_EXTRACT5] = instr_hdr_extract5_exec,
7745 [INSTR_HDR_EXTRACT6] = instr_hdr_extract6_exec,
7746 [INSTR_HDR_EXTRACT7] = instr_hdr_extract7_exec,
7747 [INSTR_HDR_EXTRACT8] = instr_hdr_extract8_exec,
7748 [INSTR_HDR_EXTRACT_M] = instr_hdr_extract_m_exec,
7749 [INSTR_HDR_LOOKAHEAD] = instr_hdr_lookahead_exec,
7751 [INSTR_HDR_EMIT] = instr_hdr_emit_exec,
7752 [INSTR_HDR_EMIT_TX] = instr_hdr_emit_tx_exec,
7753 [INSTR_HDR_EMIT2_TX] = instr_hdr_emit2_tx_exec,
7754 [INSTR_HDR_EMIT3_TX] = instr_hdr_emit3_tx_exec,
7755 [INSTR_HDR_EMIT4_TX] = instr_hdr_emit4_tx_exec,
7756 [INSTR_HDR_EMIT5_TX] = instr_hdr_emit5_tx_exec,
7757 [INSTR_HDR_EMIT6_TX] = instr_hdr_emit6_tx_exec,
7758 [INSTR_HDR_EMIT7_TX] = instr_hdr_emit7_tx_exec,
7759 [INSTR_HDR_EMIT8_TX] = instr_hdr_emit8_tx_exec,
7761 [INSTR_HDR_VALIDATE] = instr_hdr_validate_exec,
7762 [INSTR_HDR_INVALIDATE] = instr_hdr_invalidate_exec,
7764 [INSTR_MOV] = instr_mov_exec,
7765 [INSTR_MOV_MH] = instr_mov_mh_exec,
7766 [INSTR_MOV_HM] = instr_mov_hm_exec,
7767 [INSTR_MOV_HH] = instr_mov_hh_exec,
7768 [INSTR_MOV_I] = instr_mov_i_exec,
7770 [INSTR_DMA_HT] = instr_dma_ht_exec,
7771 [INSTR_DMA_HT2] = instr_dma_ht2_exec,
7772 [INSTR_DMA_HT3] = instr_dma_ht3_exec,
7773 [INSTR_DMA_HT4] = instr_dma_ht4_exec,
7774 [INSTR_DMA_HT5] = instr_dma_ht5_exec,
7775 [INSTR_DMA_HT6] = instr_dma_ht6_exec,
7776 [INSTR_DMA_HT7] = instr_dma_ht7_exec,
7777 [INSTR_DMA_HT8] = instr_dma_ht8_exec,
7779 [INSTR_ALU_ADD] = instr_alu_add_exec,
7780 [INSTR_ALU_ADD_MH] = instr_alu_add_mh_exec,
7781 [INSTR_ALU_ADD_HM] = instr_alu_add_hm_exec,
7782 [INSTR_ALU_ADD_HH] = instr_alu_add_hh_exec,
7783 [INSTR_ALU_ADD_MI] = instr_alu_add_mi_exec,
7784 [INSTR_ALU_ADD_HI] = instr_alu_add_hi_exec,
7786 [INSTR_ALU_SUB] = instr_alu_sub_exec,
7787 [INSTR_ALU_SUB_MH] = instr_alu_sub_mh_exec,
7788 [INSTR_ALU_SUB_HM] = instr_alu_sub_hm_exec,
7789 [INSTR_ALU_SUB_HH] = instr_alu_sub_hh_exec,
7790 [INSTR_ALU_SUB_MI] = instr_alu_sub_mi_exec,
7791 [INSTR_ALU_SUB_HI] = instr_alu_sub_hi_exec,
7793 [INSTR_ALU_CKADD_FIELD] = instr_alu_ckadd_field_exec,
7794 [INSTR_ALU_CKADD_STRUCT] = instr_alu_ckadd_struct_exec,
7795 [INSTR_ALU_CKADD_STRUCT20] = instr_alu_ckadd_struct20_exec,
7796 [INSTR_ALU_CKSUB_FIELD] = instr_alu_cksub_field_exec,
7798 [INSTR_ALU_AND] = instr_alu_and_exec,
7799 [INSTR_ALU_AND_MH] = instr_alu_and_mh_exec,
7800 [INSTR_ALU_AND_HM] = instr_alu_and_hm_exec,
7801 [INSTR_ALU_AND_HH] = instr_alu_and_hh_exec,
7802 [INSTR_ALU_AND_I] = instr_alu_and_i_exec,
7804 [INSTR_ALU_OR] = instr_alu_or_exec,
7805 [INSTR_ALU_OR_MH] = instr_alu_or_mh_exec,
7806 [INSTR_ALU_OR_HM] = instr_alu_or_hm_exec,
7807 [INSTR_ALU_OR_HH] = instr_alu_or_hh_exec,
7808 [INSTR_ALU_OR_I] = instr_alu_or_i_exec,
7810 [INSTR_ALU_XOR] = instr_alu_xor_exec,
7811 [INSTR_ALU_XOR_MH] = instr_alu_xor_mh_exec,
7812 [INSTR_ALU_XOR_HM] = instr_alu_xor_hm_exec,
7813 [INSTR_ALU_XOR_HH] = instr_alu_xor_hh_exec,
7814 [INSTR_ALU_XOR_I] = instr_alu_xor_i_exec,
7816 [INSTR_ALU_SHL] = instr_alu_shl_exec,
7817 [INSTR_ALU_SHL_MH] = instr_alu_shl_mh_exec,
7818 [INSTR_ALU_SHL_HM] = instr_alu_shl_hm_exec,
7819 [INSTR_ALU_SHL_HH] = instr_alu_shl_hh_exec,
7820 [INSTR_ALU_SHL_MI] = instr_alu_shl_mi_exec,
7821 [INSTR_ALU_SHL_HI] = instr_alu_shl_hi_exec,
7823 [INSTR_ALU_SHR] = instr_alu_shr_exec,
7824 [INSTR_ALU_SHR_MH] = instr_alu_shr_mh_exec,
7825 [INSTR_ALU_SHR_HM] = instr_alu_shr_hm_exec,
7826 [INSTR_ALU_SHR_HH] = instr_alu_shr_hh_exec,
7827 [INSTR_ALU_SHR_MI] = instr_alu_shr_mi_exec,
7828 [INSTR_ALU_SHR_HI] = instr_alu_shr_hi_exec,
7830 [INSTR_REGPREFETCH_RH] = instr_regprefetch_rh_exec,
7831 [INSTR_REGPREFETCH_RM] = instr_regprefetch_rm_exec,
7832 [INSTR_REGPREFETCH_RI] = instr_regprefetch_ri_exec,
7834 [INSTR_REGRD_HRH] = instr_regrd_hrh_exec,
7835 [INSTR_REGRD_HRM] = instr_regrd_hrm_exec,
7836 [INSTR_REGRD_MRH] = instr_regrd_mrh_exec,
7837 [INSTR_REGRD_MRM] = instr_regrd_mrm_exec,
7838 [INSTR_REGRD_HRI] = instr_regrd_hri_exec,
7839 [INSTR_REGRD_MRI] = instr_regrd_mri_exec,
7841 [INSTR_REGWR_RHH] = instr_regwr_rhh_exec,
7842 [INSTR_REGWR_RHM] = instr_regwr_rhm_exec,
7843 [INSTR_REGWR_RMH] = instr_regwr_rmh_exec,
7844 [INSTR_REGWR_RMM] = instr_regwr_rmm_exec,
7845 [INSTR_REGWR_RHI] = instr_regwr_rhi_exec,
7846 [INSTR_REGWR_RMI] = instr_regwr_rmi_exec,
7847 [INSTR_REGWR_RIH] = instr_regwr_rih_exec,
7848 [INSTR_REGWR_RIM] = instr_regwr_rim_exec,
7849 [INSTR_REGWR_RII] = instr_regwr_rii_exec,
7851 [INSTR_REGADD_RHH] = instr_regadd_rhh_exec,
7852 [INSTR_REGADD_RHM] = instr_regadd_rhm_exec,
7853 [INSTR_REGADD_RMH] = instr_regadd_rmh_exec,
7854 [INSTR_REGADD_RMM] = instr_regadd_rmm_exec,
7855 [INSTR_REGADD_RHI] = instr_regadd_rhi_exec,
7856 [INSTR_REGADD_RMI] = instr_regadd_rmi_exec,
7857 [INSTR_REGADD_RIH] = instr_regadd_rih_exec,
7858 [INSTR_REGADD_RIM] = instr_regadd_rim_exec,
7859 [INSTR_REGADD_RII] = instr_regadd_rii_exec,
7861 [INSTR_METPREFETCH_H] = instr_metprefetch_h_exec,
7862 [INSTR_METPREFETCH_M] = instr_metprefetch_m_exec,
7863 [INSTR_METPREFETCH_I] = instr_metprefetch_i_exec,
7865 [INSTR_METER_HHM] = instr_meter_hhm_exec,
7866 [INSTR_METER_HHI] = instr_meter_hhi_exec,
7867 [INSTR_METER_HMM] = instr_meter_hmm_exec,
7868 [INSTR_METER_HMI] = instr_meter_hmi_exec,
7869 [INSTR_METER_MHM] = instr_meter_mhm_exec,
7870 [INSTR_METER_MHI] = instr_meter_mhi_exec,
7871 [INSTR_METER_MMM] = instr_meter_mmm_exec,
7872 [INSTR_METER_MMI] = instr_meter_mmi_exec,
7873 [INSTR_METER_IHM] = instr_meter_ihm_exec,
7874 [INSTR_METER_IHI] = instr_meter_ihi_exec,
7875 [INSTR_METER_IMM] = instr_meter_imm_exec,
7876 [INSTR_METER_IMI] = instr_meter_imi_exec,
7878 [INSTR_TABLE] = instr_table_exec,
7879 [INSTR_SELECTOR] = instr_selector_exec,
7880 [INSTR_LEARNER] = instr_learner_exec,
7881 [INSTR_LEARNER_LEARN] = instr_learn_exec,
7882 [INSTR_LEARNER_FORGET] = instr_forget_exec,
7883 [INSTR_EXTERN_OBJ] = instr_extern_obj_exec,
7884 [INSTR_EXTERN_FUNC] = instr_extern_func_exec,
7886 [INSTR_JMP] = instr_jmp_exec,
7887 [INSTR_JMP_VALID] = instr_jmp_valid_exec,
7888 [INSTR_JMP_INVALID] = instr_jmp_invalid_exec,
7889 [INSTR_JMP_HIT] = instr_jmp_hit_exec,
7890 [INSTR_JMP_MISS] = instr_jmp_miss_exec,
7891 [INSTR_JMP_ACTION_HIT] = instr_jmp_action_hit_exec,
7892 [INSTR_JMP_ACTION_MISS] = instr_jmp_action_miss_exec,
7894 [INSTR_JMP_EQ] = instr_jmp_eq_exec,
7895 [INSTR_JMP_EQ_MH] = instr_jmp_eq_mh_exec,
7896 [INSTR_JMP_EQ_HM] = instr_jmp_eq_hm_exec,
7897 [INSTR_JMP_EQ_HH] = instr_jmp_eq_hh_exec,
7898 [INSTR_JMP_EQ_I] = instr_jmp_eq_i_exec,
7900 [INSTR_JMP_NEQ] = instr_jmp_neq_exec,
7901 [INSTR_JMP_NEQ_MH] = instr_jmp_neq_mh_exec,
7902 [INSTR_JMP_NEQ_HM] = instr_jmp_neq_hm_exec,
7903 [INSTR_JMP_NEQ_HH] = instr_jmp_neq_hh_exec,
7904 [INSTR_JMP_NEQ_I] = instr_jmp_neq_i_exec,
7906 [INSTR_JMP_LT] = instr_jmp_lt_exec,
7907 [INSTR_JMP_LT_MH] = instr_jmp_lt_mh_exec,
7908 [INSTR_JMP_LT_HM] = instr_jmp_lt_hm_exec,
7909 [INSTR_JMP_LT_HH] = instr_jmp_lt_hh_exec,
7910 [INSTR_JMP_LT_MI] = instr_jmp_lt_mi_exec,
7911 [INSTR_JMP_LT_HI] = instr_jmp_lt_hi_exec,
7913 [INSTR_JMP_GT] = instr_jmp_gt_exec,
7914 [INSTR_JMP_GT_MH] = instr_jmp_gt_mh_exec,
7915 [INSTR_JMP_GT_HM] = instr_jmp_gt_hm_exec,
7916 [INSTR_JMP_GT_HH] = instr_jmp_gt_hh_exec,
7917 [INSTR_JMP_GT_MI] = instr_jmp_gt_mi_exec,
7918 [INSTR_JMP_GT_HI] = instr_jmp_gt_hi_exec,
7920 [INSTR_RETURN] = instr_return_exec,
7924 instr_exec(struct rte_swx_pipeline *p)
7926 struct thread *t = &p->threads[p->thread_id];
7927 struct instruction *ip = t->ip;
7928 instr_exec_t instr = instruction_table[ip->type];
7936 static struct action *
7937 action_find(struct rte_swx_pipeline *p, const char *name)
7939 struct action *elem;
7944 TAILQ_FOREACH(elem, &p->actions, node)
7945 if (strcmp(elem->name, name) == 0)
7951 static struct action *
7952 action_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7954 struct action *action = NULL;
7956 TAILQ_FOREACH(action, &p->actions, node)
7957 if (action->id == id)
7963 static struct field *
7964 action_field_find(struct action *a, const char *name)
7966 return a->st ? struct_type_field_find(a->st, name) : NULL;
7969 static struct field *
7970 action_field_parse(struct action *action, const char *name)
7972 if (name[0] != 't' || name[1] != '.')
7975 return action_field_find(action, &name[2]);
7979 action_has_nbo_args(struct action *a)
7983 /* Return if the action does not have any args. */
7985 return 0; /* FALSE */
7987 for (i = 0; i < a->st->n_fields; i++)
7988 if (a->args_endianness[i])
7989 return 1; /* TRUE */
7991 return 0; /* FALSE */
7995 action_does_learning(struct action *a)
7999 for (i = 0; i < a->n_instructions; i++)
8000 switch (a->instructions[i].type) {
8001 case INSTR_LEARNER_LEARN:
8002 return 1; /* TRUE */
8004 case INSTR_LEARNER_FORGET:
8005 return 1; /* TRUE */
8011 return 0; /* FALSE */
8015 rte_swx_pipeline_action_config(struct rte_swx_pipeline *p,
8017 const char *args_struct_type_name,
8018 const char **instructions,
8019 uint32_t n_instructions)
8021 struct struct_type *args_struct_type = NULL;
8027 CHECK_NAME(name, EINVAL);
8028 CHECK(!action_find(p, name), EEXIST);
8030 if (args_struct_type_name) {
8031 CHECK_NAME(args_struct_type_name, EINVAL);
8032 args_struct_type = struct_type_find(p, args_struct_type_name);
8033 CHECK(args_struct_type, EINVAL);
8034 CHECK(!args_struct_type->var_size, EINVAL);
8037 /* Node allocation. */
8038 a = calloc(1, sizeof(struct action));
8040 if (args_struct_type) {
8041 a->args_endianness = calloc(args_struct_type->n_fields, sizeof(int));
8042 if (!a->args_endianness) {
8048 /* Node initialization. */
8049 strcpy(a->name, name);
8050 a->st = args_struct_type;
8051 a->id = p->n_actions;
8053 /* Instruction translation. */
8054 err = instruction_config(p, a, instructions, n_instructions);
8056 free(a->args_endianness);
8061 /* Node add to tailq. */
8062 TAILQ_INSERT_TAIL(&p->actions, a, node);
8069 action_build(struct rte_swx_pipeline *p)
8071 struct action *action;
8073 p->action_instructions = calloc(p->n_actions,
8074 sizeof(struct instruction *));
8075 CHECK(p->action_instructions, ENOMEM);
8077 TAILQ_FOREACH(action, &p->actions, node)
8078 p->action_instructions[action->id] = action->instructions;
8084 action_build_free(struct rte_swx_pipeline *p)
8086 free(p->action_instructions);
8087 p->action_instructions = NULL;
8091 action_free(struct rte_swx_pipeline *p)
8093 action_build_free(p);
8096 struct action *action;
8098 action = TAILQ_FIRST(&p->actions);
8102 TAILQ_REMOVE(&p->actions, action, node);
8103 free(action->instructions);
8109 action_arg_src_mov_count(struct action *a,
8111 struct instruction *instructions,
8112 struct instruction_data *instruction_data,
8113 uint32_t n_instructions)
8115 uint32_t offset, n_users = 0, i;
8118 (arg_id >= a->st->n_fields) ||
8120 !instruction_data ||
8124 offset = a->st->fields[arg_id].offset / 8;
8126 for (i = 0; i < n_instructions; i++) {
8127 struct instruction *instr = &instructions[i];
8128 struct instruction_data *data = &instruction_data[i];
8130 if (data->invalid ||
8131 ((instr->type != INSTR_MOV) && (instr->type != INSTR_MOV_HM)) ||
8132 instr->mov.src.struct_id ||
8133 (instr->mov.src.offset != offset))
8145 static struct table_type *
8146 table_type_find(struct rte_swx_pipeline *p, const char *name)
8148 struct table_type *elem;
8150 TAILQ_FOREACH(elem, &p->table_types, node)
8151 if (strcmp(elem->name, name) == 0)
8157 static struct table_type *
8158 table_type_resolve(struct rte_swx_pipeline *p,
8159 const char *recommended_type_name,
8160 enum rte_swx_table_match_type match_type)
8162 struct table_type *elem;
8164 /* Only consider the recommended type if the match type is correct. */
8165 if (recommended_type_name)
8166 TAILQ_FOREACH(elem, &p->table_types, node)
8167 if (!strcmp(elem->name, recommended_type_name) &&
8168 (elem->match_type == match_type))
8171 /* Ignore the recommended type and get the first element with this match
8174 TAILQ_FOREACH(elem, &p->table_types, node)
8175 if (elem->match_type == match_type)
8181 static struct table *
8182 table_find(struct rte_swx_pipeline *p, const char *name)
8186 TAILQ_FOREACH(elem, &p->tables, node)
8187 if (strcmp(elem->name, name) == 0)
8193 static struct table *
8194 table_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8196 struct table *table = NULL;
8198 TAILQ_FOREACH(table, &p->tables, node)
8199 if (table->id == id)
8206 rte_swx_pipeline_table_type_register(struct rte_swx_pipeline *p,
8208 enum rte_swx_table_match_type match_type,
8209 struct rte_swx_table_ops *ops)
8211 struct table_type *elem;
8215 CHECK_NAME(name, EINVAL);
8216 CHECK(!table_type_find(p, name), EEXIST);
8219 CHECK(ops->create, EINVAL);
8220 CHECK(ops->lkp, EINVAL);
8221 CHECK(ops->free, EINVAL);
8223 /* Node allocation. */
8224 elem = calloc(1, sizeof(struct table_type));
8225 CHECK(elem, ENOMEM);
8227 /* Node initialization. */
8228 strcpy(elem->name, name);
8229 elem->match_type = match_type;
8230 memcpy(&elem->ops, ops, sizeof(*ops));
8232 /* Node add to tailq. */
8233 TAILQ_INSERT_TAIL(&p->table_types, elem, node);
8239 table_match_type_resolve(struct rte_swx_match_field_params *fields,
8241 enum rte_swx_table_match_type *match_type)
8243 uint32_t n_fields_em = 0, n_fields_lpm = 0, i;
8245 for (i = 0; i < n_fields; i++) {
8246 struct rte_swx_match_field_params *f = &fields[i];
8248 if (f->match_type == RTE_SWX_TABLE_MATCH_EXACT)
8251 if (f->match_type == RTE_SWX_TABLE_MATCH_LPM)
8255 if ((n_fields_lpm > 1) ||
8256 (n_fields_lpm && (n_fields_em != n_fields - 1)))
8259 *match_type = (n_fields_em == n_fields) ?
8260 RTE_SWX_TABLE_MATCH_EXACT :
8261 RTE_SWX_TABLE_MATCH_WILDCARD;
8267 table_match_fields_check(struct rte_swx_pipeline *p,
8268 struct rte_swx_pipeline_table_params *params,
8269 struct header **header)
8271 struct header *h0 = NULL;
8272 struct field *hf, *mf;
8273 uint32_t *offset = NULL, i;
8276 /* Return if no match fields. */
8277 if (!params->n_fields) {
8278 if (params->fields) {
8289 /* Memory allocation. */
8290 offset = calloc(params->n_fields, sizeof(uint32_t));
8296 /* Check that all the match fields belong to either the same header or
8299 hf = header_field_parse(p, params->fields[0].name, &h0);
8300 mf = metadata_field_parse(p, params->fields[0].name);
8301 if ((!hf && !mf) || (hf && hf->var_size)) {
8306 offset[0] = h0 ? hf->offset : mf->offset;
8308 for (i = 1; i < params->n_fields; i++)
8312 hf = header_field_parse(p, params->fields[i].name, &h);
8313 if (!hf || (h->id != h0->id) || hf->var_size) {
8318 offset[i] = hf->offset;
8320 mf = metadata_field_parse(p, params->fields[i].name);
8326 offset[i] = mf->offset;
8329 /* Check that there are no duplicated match fields. */
8330 for (i = 0; i < params->n_fields; i++) {
8333 for (j = 0; j < i; j++)
8334 if (offset[j] == offset[i]) {
8350 rte_swx_pipeline_table_config(struct rte_swx_pipeline *p,
8352 struct rte_swx_pipeline_table_params *params,
8353 const char *recommended_table_type_name,
8357 struct table_type *type;
8359 struct action *default_action;
8360 struct header *header = NULL;
8361 uint32_t action_data_size_max = 0, i;
8366 CHECK_NAME(name, EINVAL);
8367 CHECK(!table_find(p, name), EEXIST);
8368 CHECK(!selector_find(p, name), EEXIST);
8369 CHECK(!learner_find(p, name), EEXIST);
8371 CHECK(params, EINVAL);
8374 status = table_match_fields_check(p, params, &header);
8378 /* Action checks. */
8379 CHECK(params->n_actions, EINVAL);
8380 CHECK(params->action_names, EINVAL);
8381 for (i = 0; i < params->n_actions; i++) {
8382 const char *action_name = params->action_names[i];
8384 uint32_t action_data_size;
8386 CHECK_NAME(action_name, EINVAL);
8388 a = action_find(p, action_name);
8390 CHECK(!action_does_learning(a), EINVAL);
8392 action_data_size = a->st ? a->st->n_bits / 8 : 0;
8393 if (action_data_size > action_data_size_max)
8394 action_data_size_max = action_data_size;
8397 CHECK_NAME(params->default_action_name, EINVAL);
8398 for (i = 0; i < p->n_actions; i++)
8399 if (!strcmp(params->action_names[i],
8400 params->default_action_name))
8402 CHECK(i < params->n_actions, EINVAL);
8403 default_action = action_find(p, params->default_action_name);
8404 CHECK((default_action->st && params->default_action_data) ||
8405 !params->default_action_data, EINVAL);
8407 /* Table type checks. */
8408 if (recommended_table_type_name)
8409 CHECK_NAME(recommended_table_type_name, EINVAL);
8411 if (params->n_fields) {
8412 enum rte_swx_table_match_type match_type;
8414 status = table_match_type_resolve(params->fields, params->n_fields, &match_type);
8418 type = table_type_resolve(p, recommended_table_type_name, match_type);
8419 CHECK(type, EINVAL);
8424 /* Memory allocation. */
8425 t = calloc(1, sizeof(struct table));
8428 t->fields = calloc(params->n_fields, sizeof(struct match_field));
8434 t->actions = calloc(params->n_actions, sizeof(struct action *));
8441 if (action_data_size_max) {
8442 t->default_action_data = calloc(1, action_data_size_max);
8443 if (!t->default_action_data) {
8451 /* Node initialization. */
8452 strcpy(t->name, name);
8453 if (args && args[0])
8454 strcpy(t->args, args);
8457 for (i = 0; i < params->n_fields; i++) {
8458 struct rte_swx_match_field_params *field = ¶ms->fields[i];
8459 struct match_field *f = &t->fields[i];
8461 f->match_type = field->match_type;
8463 header_field_parse(p, field->name, NULL) :
8464 metadata_field_parse(p, field->name);
8466 t->n_fields = params->n_fields;
8469 for (i = 0; i < params->n_actions; i++)
8470 t->actions[i] = action_find(p, params->action_names[i]);
8471 t->default_action = default_action;
8472 if (default_action->st)
8473 memcpy(t->default_action_data,
8474 params->default_action_data,
8475 default_action->st->n_bits / 8);
8476 t->n_actions = params->n_actions;
8477 t->default_action_is_const = params->default_action_is_const;
8478 t->action_data_size_max = action_data_size_max;
8481 t->id = p->n_tables;
8483 /* Node add to tailq. */
8484 TAILQ_INSERT_TAIL(&p->tables, t, node);
8490 static struct rte_swx_table_params *
8491 table_params_get(struct table *table)
8493 struct rte_swx_table_params *params;
8494 struct field *first, *last;
8496 uint32_t key_size, key_offset, action_data_size, i;
8498 /* Memory allocation. */
8499 params = calloc(1, sizeof(struct rte_swx_table_params));
8503 /* Find first (smallest offset) and last (biggest offset) match fields. */
8504 first = table->fields[0].field;
8505 last = table->fields[0].field;
8507 for (i = 0; i < table->n_fields; i++) {
8508 struct field *f = table->fields[i].field;
8510 if (f->offset < first->offset)
8513 if (f->offset > last->offset)
8517 /* Key offset and size. */
8518 key_offset = first->offset / 8;
8519 key_size = (last->offset + last->n_bits - first->offset) / 8;
8521 /* Memory allocation. */
8522 key_mask = calloc(1, key_size);
8529 for (i = 0; i < table->n_fields; i++) {
8530 struct field *f = table->fields[i].field;
8531 uint32_t start = (f->offset - first->offset) / 8;
8532 size_t size = f->n_bits / 8;
8534 memset(&key_mask[start], 0xFF, size);
8537 /* Action data size. */
8538 action_data_size = 0;
8539 for (i = 0; i < table->n_actions; i++) {
8540 struct action *action = table->actions[i];
8541 uint32_t ads = action->st ? action->st->n_bits / 8 : 0;
8543 if (ads > action_data_size)
8544 action_data_size = ads;
8548 params->match_type = table->type->match_type;
8549 params->key_size = key_size;
8550 params->key_offset = key_offset;
8551 params->key_mask0 = key_mask;
8552 params->action_data_size = action_data_size;
8553 params->n_keys_max = table->size;
8559 table_params_free(struct rte_swx_table_params *params)
8564 free(params->key_mask0);
8569 table_stub_lkp(void *table __rte_unused,
8570 void *mailbox __rte_unused,
8571 uint8_t **key __rte_unused,
8572 uint64_t *action_id __rte_unused,
8573 uint8_t **action_data __rte_unused,
8577 return 1; /* DONE. */
8581 table_build(struct rte_swx_pipeline *p)
8585 /* Per pipeline: table statistics. */
8586 p->table_stats = calloc(p->n_tables, sizeof(struct table_statistics));
8587 CHECK(p->table_stats, ENOMEM);
8589 for (i = 0; i < p->n_tables; i++) {
8590 p->table_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
8591 CHECK(p->table_stats[i].n_pkts_action, ENOMEM);
8594 /* Per thread: table runt-time. */
8595 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8596 struct thread *t = &p->threads[i];
8597 struct table *table;
8599 t->tables = calloc(p->n_tables, sizeof(struct table_runtime));
8600 CHECK(t->tables, ENOMEM);
8602 TAILQ_FOREACH(table, &p->tables, node) {
8603 struct table_runtime *r = &t->tables[table->id];
8608 size = table->type->ops.mailbox_size_get();
8611 r->func = table->type->ops.lkp;
8615 r->mailbox = calloc(1, size);
8616 CHECK(r->mailbox, ENOMEM);
8620 r->key = table->header ?
8621 &t->structs[table->header->struct_id] :
8622 &t->structs[p->metadata_struct_id];
8624 r->func = table_stub_lkp;
8633 table_build_free(struct rte_swx_pipeline *p)
8637 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8638 struct thread *t = &p->threads[i];
8644 for (j = 0; j < p->n_tables; j++) {
8645 struct table_runtime *r = &t->tables[j];
8654 if (p->table_stats) {
8655 for (i = 0; i < p->n_tables; i++)
8656 free(p->table_stats[i].n_pkts_action);
8658 free(p->table_stats);
8663 table_free(struct rte_swx_pipeline *p)
8665 table_build_free(p);
8671 elem = TAILQ_FIRST(&p->tables);
8675 TAILQ_REMOVE(&p->tables, elem, node);
8677 free(elem->actions);
8678 free(elem->default_action_data);
8684 struct table_type *elem;
8686 elem = TAILQ_FIRST(&p->table_types);
8690 TAILQ_REMOVE(&p->table_types, elem, node);
8698 static struct selector *
8699 selector_find(struct rte_swx_pipeline *p, const char *name)
8703 TAILQ_FOREACH(s, &p->selectors, node)
8704 if (strcmp(s->name, name) == 0)
8710 static struct selector *
8711 selector_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8713 struct selector *s = NULL;
8715 TAILQ_FOREACH(s, &p->selectors, node)
8723 selector_fields_check(struct rte_swx_pipeline *p,
8724 struct rte_swx_pipeline_selector_params *params,
8725 struct header **header)
8727 struct header *h0 = NULL;
8728 struct field *hf, *mf;
8731 /* Return if no selector fields. */
8732 if (!params->n_selector_fields || !params->selector_field_names)
8735 /* Check that all the selector fields either belong to the same header
8736 * or are all meta-data fields.
8738 hf = header_field_parse(p, params->selector_field_names[0], &h0);
8739 mf = metadata_field_parse(p, params->selector_field_names[0]);
8743 for (i = 1; i < params->n_selector_fields; i++)
8747 hf = header_field_parse(p, params->selector_field_names[i], &h);
8748 if (!hf || (h->id != h0->id))
8751 mf = metadata_field_parse(p, params->selector_field_names[i]);
8756 /* Check that there are no duplicated match fields. */
8757 for (i = 0; i < params->n_selector_fields; i++) {
8758 const char *field_name = params->selector_field_names[i];
8761 for (j = i + 1; j < params->n_selector_fields; j++)
8762 if (!strcmp(params->selector_field_names[j], field_name))
8774 rte_swx_pipeline_selector_config(struct rte_swx_pipeline *p,
8776 struct rte_swx_pipeline_selector_params *params)
8779 struct header *selector_header = NULL;
8780 struct field *group_id_field, *member_id_field;
8786 CHECK_NAME(name, EINVAL);
8787 CHECK(!table_find(p, name), EEXIST);
8788 CHECK(!selector_find(p, name), EEXIST);
8789 CHECK(!learner_find(p, name), EEXIST);
8791 CHECK(params, EINVAL);
8793 CHECK_NAME(params->group_id_field_name, EINVAL);
8794 group_id_field = metadata_field_parse(p, params->group_id_field_name);
8795 CHECK(group_id_field, EINVAL);
8797 for (i = 0; i < params->n_selector_fields; i++) {
8798 const char *field_name = params->selector_field_names[i];
8800 CHECK_NAME(field_name, EINVAL);
8802 status = selector_fields_check(p, params, &selector_header);
8806 CHECK_NAME(params->member_id_field_name, EINVAL);
8807 member_id_field = metadata_field_parse(p, params->member_id_field_name);
8808 CHECK(member_id_field, EINVAL);
8810 CHECK(params->n_groups_max, EINVAL);
8812 CHECK(params->n_members_per_group_max, EINVAL);
8814 /* Memory allocation. */
8815 s = calloc(1, sizeof(struct selector));
8821 s->selector_fields = calloc(params->n_selector_fields, sizeof(struct field *));
8822 if (!s->selector_fields) {
8827 /* Node initialization. */
8828 strcpy(s->name, name);
8830 s->group_id_field = group_id_field;
8832 for (i = 0; i < params->n_selector_fields; i++) {
8833 const char *field_name = params->selector_field_names[i];
8835 s->selector_fields[i] = selector_header ?
8836 header_field_parse(p, field_name, NULL) :
8837 metadata_field_parse(p, field_name);
8840 s->n_selector_fields = params->n_selector_fields;
8842 s->selector_header = selector_header;
8844 s->member_id_field = member_id_field;
8846 s->n_groups_max = params->n_groups_max;
8848 s->n_members_per_group_max = params->n_members_per_group_max;
8850 s->id = p->n_selectors;
8852 /* Node add to tailq. */
8853 TAILQ_INSERT_TAIL(&p->selectors, s, node);
8862 free(s->selector_fields);
8870 selector_params_free(struct rte_swx_table_selector_params *params)
8875 free(params->selector_mask);
8880 static struct rte_swx_table_selector_params *
8881 selector_table_params_get(struct selector *s)
8883 struct rte_swx_table_selector_params *params = NULL;
8884 struct field *first, *last;
8887 /* Memory allocation. */
8888 params = calloc(1, sizeof(struct rte_swx_table_selector_params));
8893 params->group_id_offset = s->group_id_field->offset / 8;
8895 /* Find first (smallest offset) and last (biggest offset) selector fields. */
8896 first = s->selector_fields[0];
8897 last = s->selector_fields[0];
8899 for (i = 0; i < s->n_selector_fields; i++) {
8900 struct field *f = s->selector_fields[i];
8902 if (f->offset < first->offset)
8905 if (f->offset > last->offset)
8909 /* Selector offset and size. */
8910 params->selector_offset = first->offset / 8;
8911 params->selector_size = (last->offset + last->n_bits - first->offset) / 8;
8913 /* Memory allocation. */
8914 params->selector_mask = calloc(1, params->selector_size);
8915 if (!params->selector_mask)
8918 /* Selector mask. */
8919 for (i = 0; i < s->n_selector_fields; i++) {
8920 struct field *f = s->selector_fields[i];
8921 uint32_t start = (f->offset - first->offset) / 8;
8922 size_t size = f->n_bits / 8;
8924 memset(¶ms->selector_mask[start], 0xFF, size);
8928 params->member_id_offset = s->member_id_field->offset / 8;
8930 /* Maximum number of groups. */
8931 params->n_groups_max = s->n_groups_max;
8933 /* Maximum number of members per group. */
8934 params->n_members_per_group_max = s->n_members_per_group_max;
8939 selector_params_free(params);
8944 selector_build_free(struct rte_swx_pipeline *p)
8948 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8949 struct thread *t = &p->threads[i];
8955 for (j = 0; j < p->n_selectors; j++) {
8956 struct selector_runtime *r = &t->selectors[j];
8962 t->selectors = NULL;
8965 free(p->selector_stats);
8966 p->selector_stats = NULL;
8970 selector_build(struct rte_swx_pipeline *p)
8975 /* Per pipeline: selector statistics. */
8976 p->selector_stats = calloc(p->n_selectors, sizeof(struct selector_statistics));
8977 if (!p->selector_stats) {
8982 /* Per thread: selector run-time. */
8983 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8984 struct thread *t = &p->threads[i];
8987 t->selectors = calloc(p->n_selectors, sizeof(struct selector_runtime));
8988 if (!t->selectors) {
8993 TAILQ_FOREACH(s, &p->selectors, node) {
8994 struct selector_runtime *r = &t->selectors[s->id];
8998 size = rte_swx_table_selector_mailbox_size_get();
9000 r->mailbox = calloc(1, size);
9007 /* r->group_id_buffer. */
9008 r->group_id_buffer = &t->structs[p->metadata_struct_id];
9010 /* r->selector_buffer. */
9011 r->selector_buffer = s->selector_header ?
9012 &t->structs[s->selector_header->struct_id] :
9013 &t->structs[p->metadata_struct_id];
9015 /* r->member_id_buffer. */
9016 r->member_id_buffer = &t->structs[p->metadata_struct_id];
9023 selector_build_free(p);
9028 selector_free(struct rte_swx_pipeline *p)
9030 selector_build_free(p);
9032 /* Selector tables. */
9034 struct selector *elem;
9036 elem = TAILQ_FIRST(&p->selectors);
9040 TAILQ_REMOVE(&p->selectors, elem, node);
9041 free(elem->selector_fields);
9049 static struct learner *
9050 learner_find(struct rte_swx_pipeline *p, const char *name)
9054 TAILQ_FOREACH(l, &p->learners, node)
9055 if (!strcmp(l->name, name))
9061 static struct learner *
9062 learner_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9064 struct learner *l = NULL;
9066 TAILQ_FOREACH(l, &p->learners, node)
9074 learner_match_fields_check(struct rte_swx_pipeline *p,
9075 struct rte_swx_pipeline_learner_params *params,
9076 struct header **header)
9078 struct header *h0 = NULL;
9079 struct field *hf, *mf;
9082 /* Return if no match fields. */
9083 if (!params->n_fields || !params->field_names)
9086 /* Check that all the match fields either belong to the same header
9087 * or are all meta-data fields.
9089 hf = header_field_parse(p, params->field_names[0], &h0);
9090 mf = metadata_field_parse(p, params->field_names[0]);
9094 for (i = 1; i < params->n_fields; i++)
9098 hf = header_field_parse(p, params->field_names[i], &h);
9099 if (!hf || (h->id != h0->id))
9102 mf = metadata_field_parse(p, params->field_names[i]);
9107 /* Check that there are no duplicated match fields. */
9108 for (i = 0; i < params->n_fields; i++) {
9109 const char *field_name = params->field_names[i];
9112 for (j = i + 1; j < params->n_fields; j++)
9113 if (!strcmp(params->field_names[j], field_name))
9125 learner_action_args_check(struct rte_swx_pipeline *p, struct action *a, const char *mf_name)
9127 struct struct_type *mst = p->metadata_st, *ast = a->st;
9128 struct field *mf, *af;
9138 /* Check that mf_name is the name of a valid meta-data field. */
9139 CHECK_NAME(mf_name, EINVAL);
9140 mf = metadata_field_parse(p, mf_name);
9143 /* Check that there are enough meta-data fields, starting with the mf_name field, to cover
9144 * all the action arguments.
9146 mf_pos = mf - mst->fields;
9147 CHECK(mst->n_fields - mf_pos >= ast->n_fields, EINVAL);
9149 /* Check that the size of each of the identified meta-data fields matches exactly the size
9150 * of the corresponding action argument.
9152 for (i = 0; i < ast->n_fields; i++) {
9153 mf = &mst->fields[mf_pos + i];
9154 af = &ast->fields[i];
9156 CHECK(mf->n_bits == af->n_bits, EINVAL);
9163 learner_action_learning_check(struct rte_swx_pipeline *p,
9164 struct action *action,
9165 const char **action_names,
9170 /* For each "learn" instruction of the current action, check that the learned action (i.e.
9171 * the action passed as argument to the "learn" instruction) is also enabled for the
9172 * current learner table.
9174 for (i = 0; i < action->n_instructions; i++) {
9175 struct instruction *instr = &action->instructions[i];
9176 uint32_t found = 0, j;
9178 if (instr->type != INSTR_LEARNER_LEARN)
9181 for (j = 0; j < n_actions; j++) {
9184 a = action_find(p, action_names[j]);
9188 if (a->id == instr->learn.action_id)
9200 rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p,
9202 struct rte_swx_pipeline_learner_params *params,
9206 struct learner *l = NULL;
9207 struct action *default_action;
9208 struct header *header = NULL;
9209 uint32_t action_data_size_max = 0, i;
9214 CHECK_NAME(name, EINVAL);
9215 CHECK(!table_find(p, name), EEXIST);
9216 CHECK(!selector_find(p, name), EEXIST);
9217 CHECK(!learner_find(p, name), EEXIST);
9219 CHECK(params, EINVAL);
9222 status = learner_match_fields_check(p, params, &header);
9226 /* Action checks. */
9227 CHECK(params->n_actions, EINVAL);
9229 CHECK(params->action_names, EINVAL);
9230 for (i = 0; i < params->n_actions; i++) {
9231 const char *action_name = params->action_names[i];
9232 const char *action_field_name = params->action_field_names[i];
9234 uint32_t action_data_size;
9236 CHECK_NAME(action_name, EINVAL);
9238 a = action_find(p, action_name);
9241 status = learner_action_args_check(p, a, action_field_name);
9245 status = learner_action_learning_check(p,
9247 params->action_names,
9252 action_data_size = a->st ? a->st->n_bits / 8 : 0;
9253 if (action_data_size > action_data_size_max)
9254 action_data_size_max = action_data_size;
9257 CHECK_NAME(params->default_action_name, EINVAL);
9258 for (i = 0; i < p->n_actions; i++)
9259 if (!strcmp(params->action_names[i],
9260 params->default_action_name))
9262 CHECK(i < params->n_actions, EINVAL);
9264 default_action = action_find(p, params->default_action_name);
9265 CHECK((default_action->st && params->default_action_data) ||
9266 !params->default_action_data, EINVAL);
9268 /* Any other checks. */
9269 CHECK(size, EINVAL);
9270 CHECK(timeout, EINVAL);
9272 /* Memory allocation. */
9273 l = calloc(1, sizeof(struct learner));
9277 l->fields = calloc(params->n_fields, sizeof(struct field *));
9281 l->actions = calloc(params->n_actions, sizeof(struct action *));
9285 l->action_arg = calloc(params->n_actions, sizeof(struct field *));
9289 if (action_data_size_max) {
9290 l->default_action_data = calloc(1, action_data_size_max);
9291 if (!l->default_action_data)
9295 /* Node initialization. */
9296 strcpy(l->name, name);
9298 for (i = 0; i < params->n_fields; i++) {
9299 const char *field_name = params->field_names[i];
9301 l->fields[i] = header ?
9302 header_field_parse(p, field_name, NULL) :
9303 metadata_field_parse(p, field_name);
9306 l->n_fields = params->n_fields;
9310 for (i = 0; i < params->n_actions; i++) {
9311 const char *mf_name = params->action_field_names[i];
9313 l->actions[i] = action_find(p, params->action_names[i]);
9315 l->action_arg[i] = mf_name ? metadata_field_parse(p, mf_name) : NULL;
9318 l->default_action = default_action;
9320 if (default_action->st)
9321 memcpy(l->default_action_data,
9322 params->default_action_data,
9323 default_action->st->n_bits / 8);
9325 l->n_actions = params->n_actions;
9327 l->default_action_is_const = params->default_action_is_const;
9329 l->action_data_size_max = action_data_size_max;
9333 l->timeout = timeout;
9335 l->id = p->n_learners;
9337 /* Node add to tailq. */
9338 TAILQ_INSERT_TAIL(&p->learners, l, node);
9347 free(l->action_arg);
9356 learner_params_free(struct rte_swx_table_learner_params *params)
9361 free(params->key_mask0);
9366 static struct rte_swx_table_learner_params *
9367 learner_params_get(struct learner *l)
9369 struct rte_swx_table_learner_params *params = NULL;
9370 struct field *first, *last;
9373 /* Memory allocation. */
9374 params = calloc(1, sizeof(struct rte_swx_table_learner_params));
9378 /* Find first (smallest offset) and last (biggest offset) match fields. */
9379 first = l->fields[0];
9380 last = l->fields[0];
9382 for (i = 0; i < l->n_fields; i++) {
9383 struct field *f = l->fields[i];
9385 if (f->offset < first->offset)
9388 if (f->offset > last->offset)
9392 /* Key offset and size. */
9393 params->key_offset = first->offset / 8;
9394 params->key_size = (last->offset + last->n_bits - first->offset) / 8;
9396 /* Memory allocation. */
9397 params->key_mask0 = calloc(1, params->key_size);
9398 if (!params->key_mask0)
9402 for (i = 0; i < l->n_fields; i++) {
9403 struct field *f = l->fields[i];
9404 uint32_t start = (f->offset - first->offset) / 8;
9405 size_t size = f->n_bits / 8;
9407 memset(¶ms->key_mask0[start], 0xFF, size);
9410 /* Action data size. */
9411 params->action_data_size = l->action_data_size_max;
9413 /* Maximum number of keys. */
9414 params->n_keys_max = l->size;
9417 params->key_timeout = l->timeout;
9422 learner_params_free(params);
9427 learner_build_free(struct rte_swx_pipeline *p)
9431 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9432 struct thread *t = &p->threads[i];
9438 for (j = 0; j < p->n_learners; j++) {
9439 struct learner_runtime *r = &t->learners[j];
9442 free(r->action_data);
9449 if (p->learner_stats) {
9450 for (i = 0; i < p->n_learners; i++)
9451 free(p->learner_stats[i].n_pkts_action);
9453 free(p->learner_stats);
9458 learner_build(struct rte_swx_pipeline *p)
9463 /* Per pipeline: learner statistics. */
9464 p->learner_stats = calloc(p->n_learners, sizeof(struct learner_statistics));
9465 CHECK(p->learner_stats, ENOMEM);
9467 for (i = 0; i < p->n_learners; i++) {
9468 p->learner_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
9469 CHECK(p->learner_stats[i].n_pkts_action, ENOMEM);
9472 /* Per thread: learner run-time. */
9473 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9474 struct thread *t = &p->threads[i];
9477 t->learners = calloc(p->n_learners, sizeof(struct learner_runtime));
9483 TAILQ_FOREACH(l, &p->learners, node) {
9484 struct learner_runtime *r = &t->learners[l->id];
9489 size = rte_swx_table_learner_mailbox_size_get();
9491 r->mailbox = calloc(1, size);
9499 r->key = l->header ?
9500 &t->structs[l->header->struct_id] :
9501 &t->structs[p->metadata_struct_id];
9503 /* r->action_data. */
9504 r->action_data = calloc(p->n_actions, sizeof(uint8_t *));
9505 if (!r->action_data) {
9510 for (j = 0; j < l->n_actions; j++) {
9511 struct action *a = l->actions[j];
9512 struct field *mf = l->action_arg[j];
9513 uint8_t *m = t->structs[p->metadata_struct_id];
9515 r->action_data[a->id] = mf ? &m[mf->offset / 8] : NULL;
9523 learner_build_free(p);
9528 learner_free(struct rte_swx_pipeline *p)
9530 learner_build_free(p);
9532 /* Learner tables. */
9536 l = TAILQ_FIRST(&p->learners);
9540 TAILQ_REMOVE(&p->learners, l, node);
9543 free(l->action_arg);
9544 free(l->default_action_data);
9553 table_state_build(struct rte_swx_pipeline *p)
9555 struct table *table;
9559 p->table_state = calloc(p->n_tables + p->n_selectors,
9560 sizeof(struct rte_swx_table_state));
9561 CHECK(p->table_state, ENOMEM);
9563 TAILQ_FOREACH(table, &p->tables, node) {
9564 struct rte_swx_table_state *ts = &p->table_state[table->id];
9567 struct rte_swx_table_params *params;
9570 params = table_params_get(table);
9571 CHECK(params, ENOMEM);
9573 ts->obj = table->type->ops.create(params,
9578 table_params_free(params);
9579 CHECK(ts->obj, ENODEV);
9582 /* ts->default_action_data. */
9583 if (table->action_data_size_max) {
9584 ts->default_action_data =
9585 malloc(table->action_data_size_max);
9586 CHECK(ts->default_action_data, ENOMEM);
9588 memcpy(ts->default_action_data,
9589 table->default_action_data,
9590 table->action_data_size_max);
9593 /* ts->default_action_id. */
9594 ts->default_action_id = table->default_action->id;
9597 TAILQ_FOREACH(s, &p->selectors, node) {
9598 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + s->id];
9599 struct rte_swx_table_selector_params *params;
9602 params = selector_table_params_get(s);
9603 CHECK(params, ENOMEM);
9605 ts->obj = rte_swx_table_selector_create(params, NULL, p->numa_node);
9607 selector_params_free(params);
9608 CHECK(ts->obj, ENODEV);
9611 TAILQ_FOREACH(l, &p->learners, node) {
9612 struct rte_swx_table_state *ts = &p->table_state[p->n_tables +
9613 p->n_selectors + l->id];
9614 struct rte_swx_table_learner_params *params;
9617 params = learner_params_get(l);
9618 CHECK(params, ENOMEM);
9620 ts->obj = rte_swx_table_learner_create(params, p->numa_node);
9621 learner_params_free(params);
9622 CHECK(ts->obj, ENODEV);
9624 /* ts->default_action_data. */
9625 if (l->action_data_size_max) {
9626 ts->default_action_data = malloc(l->action_data_size_max);
9627 CHECK(ts->default_action_data, ENOMEM);
9629 memcpy(ts->default_action_data,
9630 l->default_action_data,
9631 l->action_data_size_max);
9634 /* ts->default_action_id. */
9635 ts->default_action_id = l->default_action->id;
9642 table_state_build_free(struct rte_swx_pipeline *p)
9646 if (!p->table_state)
9649 for (i = 0; i < p->n_tables; i++) {
9650 struct rte_swx_table_state *ts = &p->table_state[i];
9651 struct table *table = table_find_by_id(p, i);
9654 if (table->type && ts->obj)
9655 table->type->ops.free(ts->obj);
9657 /* ts->default_action_data. */
9658 free(ts->default_action_data);
9661 for (i = 0; i < p->n_selectors; i++) {
9662 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + i];
9666 rte_swx_table_selector_free(ts->obj);
9669 for (i = 0; i < p->n_learners; i++) {
9670 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + p->n_selectors + i];
9674 rte_swx_table_learner_free(ts->obj);
9676 /* ts->default_action_data. */
9677 free(ts->default_action_data);
9680 free(p->table_state);
9681 p->table_state = NULL;
9685 table_state_free(struct rte_swx_pipeline *p)
9687 table_state_build_free(p);
9693 static struct regarray *
9694 regarray_find(struct rte_swx_pipeline *p, const char *name)
9696 struct regarray *elem;
9698 TAILQ_FOREACH(elem, &p->regarrays, node)
9699 if (!strcmp(elem->name, name))
9705 static struct regarray *
9706 regarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9708 struct regarray *elem = NULL;
9710 TAILQ_FOREACH(elem, &p->regarrays, node)
9718 rte_swx_pipeline_regarray_config(struct rte_swx_pipeline *p,
9727 CHECK_NAME(name, EINVAL);
9728 CHECK(!regarray_find(p, name), EEXIST);
9730 CHECK(size, EINVAL);
9731 size = rte_align32pow2(size);
9733 /* Memory allocation. */
9734 r = calloc(1, sizeof(struct regarray));
9737 /* Node initialization. */
9738 strcpy(r->name, name);
9739 r->init_val = init_val;
9741 r->id = p->n_regarrays;
9743 /* Node add to tailq. */
9744 TAILQ_INSERT_TAIL(&p->regarrays, r, node);
9751 regarray_build(struct rte_swx_pipeline *p)
9753 struct regarray *regarray;
9755 if (!p->n_regarrays)
9758 p->regarray_runtime = calloc(p->n_regarrays, sizeof(struct regarray_runtime));
9759 CHECK(p->regarray_runtime, ENOMEM);
9761 TAILQ_FOREACH(regarray, &p->regarrays, node) {
9762 struct regarray_runtime *r = &p->regarray_runtime[regarray->id];
9765 r->regarray = env_malloc(regarray->size * sizeof(uint64_t),
9766 RTE_CACHE_LINE_SIZE,
9768 CHECK(r->regarray, ENOMEM);
9770 if (regarray->init_val)
9771 for (i = 0; i < regarray->size; i++)
9772 r->regarray[i] = regarray->init_val;
9774 r->size_mask = regarray->size - 1;
9781 regarray_build_free(struct rte_swx_pipeline *p)
9785 if (!p->regarray_runtime)
9788 for (i = 0; i < p->n_regarrays; i++) {
9789 struct regarray *regarray = regarray_find_by_id(p, i);
9790 struct regarray_runtime *r = &p->regarray_runtime[i];
9792 env_free(r->regarray, regarray->size * sizeof(uint64_t));
9795 free(p->regarray_runtime);
9796 p->regarray_runtime = NULL;
9800 regarray_free(struct rte_swx_pipeline *p)
9802 regarray_build_free(p);
9805 struct regarray *elem;
9807 elem = TAILQ_FIRST(&p->regarrays);
9811 TAILQ_REMOVE(&p->regarrays, elem, node);
9819 static struct meter_profile *
9820 meter_profile_find(struct rte_swx_pipeline *p, const char *name)
9822 struct meter_profile *elem;
9824 TAILQ_FOREACH(elem, &p->meter_profiles, node)
9825 if (!strcmp(elem->name, name))
9831 static struct metarray *
9832 metarray_find(struct rte_swx_pipeline *p, const char *name)
9834 struct metarray *elem;
9836 TAILQ_FOREACH(elem, &p->metarrays, node)
9837 if (!strcmp(elem->name, name))
9843 static struct metarray *
9844 metarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9846 struct metarray *elem = NULL;
9848 TAILQ_FOREACH(elem, &p->metarrays, node)
9856 rte_swx_pipeline_metarray_config(struct rte_swx_pipeline *p,
9864 CHECK_NAME(name, EINVAL);
9865 CHECK(!metarray_find(p, name), EEXIST);
9867 CHECK(size, EINVAL);
9868 size = rte_align32pow2(size);
9870 /* Memory allocation. */
9871 m = calloc(1, sizeof(struct metarray));
9874 /* Node initialization. */
9875 strcpy(m->name, name);
9877 m->id = p->n_metarrays;
9879 /* Node add to tailq. */
9880 TAILQ_INSERT_TAIL(&p->metarrays, m, node);
9886 struct meter_profile meter_profile_default = {
9895 .cir_bytes_per_period = 1,
9897 .pir_bytes_per_period = 1,
9904 meter_init(struct meter *m)
9906 memset(m, 0, sizeof(struct meter));
9907 rte_meter_trtcm_config(&m->m, &meter_profile_default.profile);
9908 m->profile = &meter_profile_default;
9909 m->color_mask = RTE_COLOR_GREEN;
9911 meter_profile_default.n_users++;
9915 metarray_build(struct rte_swx_pipeline *p)
9919 if (!p->n_metarrays)
9922 p->metarray_runtime = calloc(p->n_metarrays, sizeof(struct metarray_runtime));
9923 CHECK(p->metarray_runtime, ENOMEM);
9925 TAILQ_FOREACH(m, &p->metarrays, node) {
9926 struct metarray_runtime *r = &p->metarray_runtime[m->id];
9929 r->metarray = env_malloc(m->size * sizeof(struct meter),
9930 RTE_CACHE_LINE_SIZE,
9932 CHECK(r->metarray, ENOMEM);
9934 for (i = 0; i < m->size; i++)
9935 meter_init(&r->metarray[i]);
9937 r->size_mask = m->size - 1;
9944 metarray_build_free(struct rte_swx_pipeline *p)
9948 if (!p->metarray_runtime)
9951 for (i = 0; i < p->n_metarrays; i++) {
9952 struct metarray *m = metarray_find_by_id(p, i);
9953 struct metarray_runtime *r = &p->metarray_runtime[i];
9955 env_free(r->metarray, m->size * sizeof(struct meter));
9958 free(p->metarray_runtime);
9959 p->metarray_runtime = NULL;
9963 metarray_free(struct rte_swx_pipeline *p)
9965 metarray_build_free(p);
9969 struct metarray *elem;
9971 elem = TAILQ_FIRST(&p->metarrays);
9975 TAILQ_REMOVE(&p->metarrays, elem, node);
9979 /* Meter profiles. */
9981 struct meter_profile *elem;
9983 elem = TAILQ_FIRST(&p->meter_profiles);
9987 TAILQ_REMOVE(&p->meter_profiles, elem, node);
9996 rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
9998 struct rte_swx_pipeline *pipeline;
10000 /* Check input parameters. */
10003 /* Memory allocation. */
10004 pipeline = calloc(1, sizeof(struct rte_swx_pipeline));
10005 CHECK(pipeline, ENOMEM);
10007 /* Initialization. */
10008 TAILQ_INIT(&pipeline->struct_types);
10009 TAILQ_INIT(&pipeline->port_in_types);
10010 TAILQ_INIT(&pipeline->ports_in);
10011 TAILQ_INIT(&pipeline->port_out_types);
10012 TAILQ_INIT(&pipeline->ports_out);
10013 TAILQ_INIT(&pipeline->extern_types);
10014 TAILQ_INIT(&pipeline->extern_objs);
10015 TAILQ_INIT(&pipeline->extern_funcs);
10016 TAILQ_INIT(&pipeline->headers);
10017 TAILQ_INIT(&pipeline->actions);
10018 TAILQ_INIT(&pipeline->table_types);
10019 TAILQ_INIT(&pipeline->tables);
10020 TAILQ_INIT(&pipeline->selectors);
10021 TAILQ_INIT(&pipeline->learners);
10022 TAILQ_INIT(&pipeline->regarrays);
10023 TAILQ_INIT(&pipeline->meter_profiles);
10024 TAILQ_INIT(&pipeline->metarrays);
10026 pipeline->n_structs = 1; /* Struct 0 is reserved for action_data. */
10027 pipeline->numa_node = numa_node;
10034 rte_swx_pipeline_free(struct rte_swx_pipeline *p)
10039 free(p->instructions);
10043 table_state_free(p);
10050 extern_func_free(p);
10051 extern_obj_free(p);
10060 rte_swx_pipeline_instructions_config(struct rte_swx_pipeline *p,
10061 const char **instructions,
10062 uint32_t n_instructions)
10067 err = instruction_config(p, NULL, instructions, n_instructions);
10071 /* Thread instruction pointer reset. */
10072 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
10073 struct thread *t = &p->threads[i];
10075 thread_ip_reset(p, t);
10082 rte_swx_pipeline_build(struct rte_swx_pipeline *p)
10087 CHECK(p->build_done == 0, EEXIST);
10089 status = port_in_build(p);
10093 status = port_out_build(p);
10097 status = struct_build(p);
10101 status = extern_obj_build(p);
10105 status = extern_func_build(p);
10109 status = header_build(p);
10113 status = metadata_build(p);
10117 status = action_build(p);
10121 status = table_build(p);
10125 status = selector_build(p);
10129 status = learner_build(p);
10133 status = table_state_build(p);
10137 status = regarray_build(p);
10141 status = metarray_build(p);
10149 metarray_build_free(p);
10150 regarray_build_free(p);
10151 table_state_build_free(p);
10152 learner_build_free(p);
10153 selector_build_free(p);
10154 table_build_free(p);
10155 action_build_free(p);
10156 metadata_build_free(p);
10157 header_build_free(p);
10158 extern_func_build_free(p);
10159 extern_obj_build_free(p);
10160 port_out_build_free(p);
10161 port_in_build_free(p);
10162 struct_build_free(p);
10168 rte_swx_pipeline_run(struct rte_swx_pipeline *p, uint32_t n_instructions)
10172 for (i = 0; i < n_instructions; i++)
10177 rte_swx_pipeline_flush(struct rte_swx_pipeline *p)
10181 for (i = 0; i < p->n_ports_out; i++) {
10182 struct port_out_runtime *port = &p->out[i];
10185 port->flush(port->obj);
10193 rte_swx_ctl_pipeline_info_get(struct rte_swx_pipeline *p,
10194 struct rte_swx_ctl_pipeline_info *pipeline)
10196 struct action *action;
10197 struct table *table;
10198 uint32_t n_actions = 0, n_tables = 0;
10200 if (!p || !pipeline)
10203 TAILQ_FOREACH(action, &p->actions, node)
10206 TAILQ_FOREACH(table, &p->tables, node)
10209 pipeline->n_ports_in = p->n_ports_in;
10210 pipeline->n_ports_out = p->n_ports_out;
10211 pipeline->n_actions = n_actions;
10212 pipeline->n_tables = n_tables;
10213 pipeline->n_selectors = p->n_selectors;
10214 pipeline->n_learners = p->n_learners;
10215 pipeline->n_regarrays = p->n_regarrays;
10216 pipeline->n_metarrays = p->n_metarrays;
10222 rte_swx_ctl_pipeline_numa_node_get(struct rte_swx_pipeline *p, int *numa_node)
10224 if (!p || !numa_node)
10227 *numa_node = p->numa_node;
10232 rte_swx_ctl_action_info_get(struct rte_swx_pipeline *p,
10233 uint32_t action_id,
10234 struct rte_swx_ctl_action_info *action)
10236 struct action *a = NULL;
10238 if (!p || (action_id >= p->n_actions) || !action)
10241 a = action_find_by_id(p, action_id);
10245 strcpy(action->name, a->name);
10246 action->n_args = a->st ? a->st->n_fields : 0;
10251 rte_swx_ctl_action_arg_info_get(struct rte_swx_pipeline *p,
10252 uint32_t action_id,
10253 uint32_t action_arg_id,
10254 struct rte_swx_ctl_action_arg_info *action_arg)
10256 struct action *a = NULL;
10257 struct field *arg = NULL;
10259 if (!p || (action_id >= p->n_actions) || !action_arg)
10262 a = action_find_by_id(p, action_id);
10263 if (!a || !a->st || (action_arg_id >= a->st->n_fields))
10266 arg = &a->st->fields[action_arg_id];
10267 strcpy(action_arg->name, arg->name);
10268 action_arg->n_bits = arg->n_bits;
10269 action_arg->is_network_byte_order = a->args_endianness[action_arg_id];
10275 rte_swx_ctl_table_info_get(struct rte_swx_pipeline *p,
10277 struct rte_swx_ctl_table_info *table)
10279 struct table *t = NULL;
10284 t = table_find_by_id(p, table_id);
10288 strcpy(table->name, t->name);
10289 strcpy(table->args, t->args);
10290 table->n_match_fields = t->n_fields;
10291 table->n_actions = t->n_actions;
10292 table->default_action_is_const = t->default_action_is_const;
10293 table->size = t->size;
10298 rte_swx_ctl_table_match_field_info_get(struct rte_swx_pipeline *p,
10300 uint32_t match_field_id,
10301 struct rte_swx_ctl_table_match_field_info *match_field)
10304 struct match_field *f;
10306 if (!p || (table_id >= p->n_tables) || !match_field)
10309 t = table_find_by_id(p, table_id);
10310 if (!t || (match_field_id >= t->n_fields))
10313 f = &t->fields[match_field_id];
10314 match_field->match_type = f->match_type;
10315 match_field->is_header = t->header ? 1 : 0;
10316 match_field->n_bits = f->field->n_bits;
10317 match_field->offset = f->field->offset;
10323 rte_swx_ctl_table_action_info_get(struct rte_swx_pipeline *p,
10325 uint32_t table_action_id,
10326 struct rte_swx_ctl_table_action_info *table_action)
10330 if (!p || (table_id >= p->n_tables) || !table_action)
10333 t = table_find_by_id(p, table_id);
10334 if (!t || (table_action_id >= t->n_actions))
10337 table_action->action_id = t->actions[table_action_id]->id;
10343 rte_swx_ctl_table_ops_get(struct rte_swx_pipeline *p,
10345 struct rte_swx_table_ops *table_ops,
10350 if (!p || (table_id >= p->n_tables))
10353 t = table_find_by_id(p, table_id);
10359 memcpy(table_ops, &t->type->ops, sizeof(*table_ops));
10369 rte_swx_ctl_selector_info_get(struct rte_swx_pipeline *p,
10370 uint32_t selector_id,
10371 struct rte_swx_ctl_selector_info *selector)
10373 struct selector *s = NULL;
10375 if (!p || !selector)
10378 s = selector_find_by_id(p, selector_id);
10382 strcpy(selector->name, s->name);
10384 selector->n_selector_fields = s->n_selector_fields;
10385 selector->n_groups_max = s->n_groups_max;
10386 selector->n_members_per_group_max = s->n_members_per_group_max;
10392 rte_swx_ctl_selector_group_id_field_info_get(struct rte_swx_pipeline *p,
10393 uint32_t selector_id,
10394 struct rte_swx_ctl_table_match_field_info *field)
10396 struct selector *s;
10398 if (!p || (selector_id >= p->n_selectors) || !field)
10401 s = selector_find_by_id(p, selector_id);
10405 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10406 field->is_header = 0;
10407 field->n_bits = s->group_id_field->n_bits;
10408 field->offset = s->group_id_field->offset;
10414 rte_swx_ctl_selector_field_info_get(struct rte_swx_pipeline *p,
10415 uint32_t selector_id,
10416 uint32_t selector_field_id,
10417 struct rte_swx_ctl_table_match_field_info *field)
10419 struct selector *s;
10422 if (!p || (selector_id >= p->n_selectors) || !field)
10425 s = selector_find_by_id(p, selector_id);
10426 if (!s || (selector_field_id >= s->n_selector_fields))
10429 f = s->selector_fields[selector_field_id];
10430 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10431 field->is_header = s->selector_header ? 1 : 0;
10432 field->n_bits = f->n_bits;
10433 field->offset = f->offset;
10439 rte_swx_ctl_selector_member_id_field_info_get(struct rte_swx_pipeline *p,
10440 uint32_t selector_id,
10441 struct rte_swx_ctl_table_match_field_info *field)
10443 struct selector *s;
10445 if (!p || (selector_id >= p->n_selectors) || !field)
10448 s = selector_find_by_id(p, selector_id);
10452 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10453 field->is_header = 0;
10454 field->n_bits = s->member_id_field->n_bits;
10455 field->offset = s->member_id_field->offset;
10461 rte_swx_ctl_learner_info_get(struct rte_swx_pipeline *p,
10462 uint32_t learner_id,
10463 struct rte_swx_ctl_learner_info *learner)
10465 struct learner *l = NULL;
10467 if (!p || !learner)
10470 l = learner_find_by_id(p, learner_id);
10474 strcpy(learner->name, l->name);
10476 learner->n_match_fields = l->n_fields;
10477 learner->n_actions = l->n_actions;
10478 learner->default_action_is_const = l->default_action_is_const;
10479 learner->size = l->size;
10485 rte_swx_ctl_learner_match_field_info_get(struct rte_swx_pipeline *p,
10486 uint32_t learner_id,
10487 uint32_t match_field_id,
10488 struct rte_swx_ctl_table_match_field_info *match_field)
10493 if (!p || (learner_id >= p->n_learners) || !match_field)
10496 l = learner_find_by_id(p, learner_id);
10497 if (!l || (match_field_id >= l->n_fields))
10500 f = l->fields[match_field_id];
10501 match_field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10502 match_field->is_header = l->header ? 1 : 0;
10503 match_field->n_bits = f->n_bits;
10504 match_field->offset = f->offset;
10510 rte_swx_ctl_learner_action_info_get(struct rte_swx_pipeline *p,
10511 uint32_t learner_id,
10512 uint32_t learner_action_id,
10513 struct rte_swx_ctl_table_action_info *learner_action)
10517 if (!p || (learner_id >= p->n_learners) || !learner_action)
10520 l = learner_find_by_id(p, learner_id);
10521 if (!l || (learner_action_id >= l->n_actions))
10524 learner_action->action_id = l->actions[learner_action_id]->id;
10530 rte_swx_pipeline_table_state_get(struct rte_swx_pipeline *p,
10531 struct rte_swx_table_state **table_state)
10533 if (!p || !table_state || !p->build_done)
10536 *table_state = p->table_state;
10541 rte_swx_pipeline_table_state_set(struct rte_swx_pipeline *p,
10542 struct rte_swx_table_state *table_state)
10544 if (!p || !table_state || !p->build_done)
10547 p->table_state = table_state;
10552 rte_swx_ctl_pipeline_port_in_stats_read(struct rte_swx_pipeline *p,
10554 struct rte_swx_port_in_stats *stats)
10556 struct port_in *port;
10561 port = port_in_find(p, port_id);
10565 port->type->ops.stats_read(port->obj, stats);
10570 rte_swx_ctl_pipeline_port_out_stats_read(struct rte_swx_pipeline *p,
10572 struct rte_swx_port_out_stats *stats)
10574 struct port_out *port;
10579 port = port_out_find(p, port_id);
10583 port->type->ops.stats_read(port->obj, stats);
10588 rte_swx_ctl_pipeline_table_stats_read(struct rte_swx_pipeline *p,
10589 const char *table_name,
10590 struct rte_swx_table_stats *stats)
10592 struct table *table;
10593 struct table_statistics *table_stats;
10595 if (!p || !table_name || !table_name[0] || !stats || !stats->n_pkts_action)
10598 table = table_find(p, table_name);
10602 table_stats = &p->table_stats[table->id];
10604 memcpy(stats->n_pkts_action,
10605 table_stats->n_pkts_action,
10606 p->n_actions * sizeof(uint64_t));
10608 stats->n_pkts_hit = table_stats->n_pkts_hit[1];
10609 stats->n_pkts_miss = table_stats->n_pkts_hit[0];
10615 rte_swx_ctl_pipeline_selector_stats_read(struct rte_swx_pipeline *p,
10616 const char *selector_name,
10617 struct rte_swx_pipeline_selector_stats *stats)
10619 struct selector *s;
10621 if (!p || !selector_name || !selector_name[0] || !stats)
10624 s = selector_find(p, selector_name);
10628 stats->n_pkts = p->selector_stats[s->id].n_pkts;
10634 rte_swx_ctl_pipeline_learner_stats_read(struct rte_swx_pipeline *p,
10635 const char *learner_name,
10636 struct rte_swx_learner_stats *stats)
10639 struct learner_statistics *learner_stats;
10641 if (!p || !learner_name || !learner_name[0] || !stats || !stats->n_pkts_action)
10644 l = learner_find(p, learner_name);
10648 learner_stats = &p->learner_stats[l->id];
10650 memcpy(stats->n_pkts_action,
10651 learner_stats->n_pkts_action,
10652 p->n_actions * sizeof(uint64_t));
10654 stats->n_pkts_hit = learner_stats->n_pkts_hit[1];
10655 stats->n_pkts_miss = learner_stats->n_pkts_hit[0];
10657 stats->n_pkts_learn_ok = learner_stats->n_pkts_learn[0];
10658 stats->n_pkts_learn_err = learner_stats->n_pkts_learn[1];
10660 stats->n_pkts_forget = learner_stats->n_pkts_forget;
10666 rte_swx_ctl_regarray_info_get(struct rte_swx_pipeline *p,
10667 uint32_t regarray_id,
10668 struct rte_swx_ctl_regarray_info *regarray)
10670 struct regarray *r;
10672 if (!p || !regarray)
10675 r = regarray_find_by_id(p, regarray_id);
10679 strcpy(regarray->name, r->name);
10680 regarray->size = r->size;
10685 rte_swx_ctl_pipeline_regarray_read(struct rte_swx_pipeline *p,
10686 const char *regarray_name,
10687 uint32_t regarray_index,
10690 struct regarray *regarray;
10691 struct regarray_runtime *r;
10693 if (!p || !regarray_name || !value)
10696 regarray = regarray_find(p, regarray_name);
10697 if (!regarray || (regarray_index >= regarray->size))
10700 r = &p->regarray_runtime[regarray->id];
10701 *value = r->regarray[regarray_index];
10706 rte_swx_ctl_pipeline_regarray_write(struct rte_swx_pipeline *p,
10707 const char *regarray_name,
10708 uint32_t regarray_index,
10711 struct regarray *regarray;
10712 struct regarray_runtime *r;
10714 if (!p || !regarray_name)
10717 regarray = regarray_find(p, regarray_name);
10718 if (!regarray || (regarray_index >= regarray->size))
10721 r = &p->regarray_runtime[regarray->id];
10722 r->regarray[regarray_index] = value;
10727 rte_swx_ctl_metarray_info_get(struct rte_swx_pipeline *p,
10728 uint32_t metarray_id,
10729 struct rte_swx_ctl_metarray_info *metarray)
10731 struct metarray *m;
10733 if (!p || !metarray)
10736 m = metarray_find_by_id(p, metarray_id);
10740 strcpy(metarray->name, m->name);
10741 metarray->size = m->size;
10746 rte_swx_ctl_meter_profile_add(struct rte_swx_pipeline *p,
10748 struct rte_meter_trtcm_params *params)
10750 struct meter_profile *mp;
10754 CHECK_NAME(name, EINVAL);
10755 CHECK(params, EINVAL);
10756 CHECK(!meter_profile_find(p, name), EEXIST);
10758 /* Node allocation. */
10759 mp = calloc(1, sizeof(struct meter_profile));
10762 /* Node initialization. */
10763 strcpy(mp->name, name);
10764 memcpy(&mp->params, params, sizeof(struct rte_meter_trtcm_params));
10765 status = rte_meter_trtcm_profile_config(&mp->profile, params);
10771 /* Node add to tailq. */
10772 TAILQ_INSERT_TAIL(&p->meter_profiles, mp, node);
10778 rte_swx_ctl_meter_profile_delete(struct rte_swx_pipeline *p,
10781 struct meter_profile *mp;
10784 CHECK_NAME(name, EINVAL);
10786 mp = meter_profile_find(p, name);
10788 CHECK(!mp->n_users, EBUSY);
10790 /* Remove node from tailq. */
10791 TAILQ_REMOVE(&p->meter_profiles, mp, node);
10798 rte_swx_ctl_meter_reset(struct rte_swx_pipeline *p,
10799 const char *metarray_name,
10800 uint32_t metarray_index)
10802 struct meter_profile *mp_old;
10803 struct metarray *metarray;
10804 struct metarray_runtime *metarray_runtime;
10808 CHECK_NAME(metarray_name, EINVAL);
10810 metarray = metarray_find(p, metarray_name);
10811 CHECK(metarray, EINVAL);
10812 CHECK(metarray_index < metarray->size, EINVAL);
10814 metarray_runtime = &p->metarray_runtime[metarray->id];
10815 m = &metarray_runtime->metarray[metarray_index];
10816 mp_old = m->profile;
10826 rte_swx_ctl_meter_set(struct rte_swx_pipeline *p,
10827 const char *metarray_name,
10828 uint32_t metarray_index,
10829 const char *profile_name)
10831 struct meter_profile *mp, *mp_old;
10832 struct metarray *metarray;
10833 struct metarray_runtime *metarray_runtime;
10837 CHECK_NAME(metarray_name, EINVAL);
10839 metarray = metarray_find(p, metarray_name);
10840 CHECK(metarray, EINVAL);
10841 CHECK(metarray_index < metarray->size, EINVAL);
10843 mp = meter_profile_find(p, profile_name);
10846 metarray_runtime = &p->metarray_runtime[metarray->id];
10847 m = &metarray_runtime->metarray[metarray_index];
10848 mp_old = m->profile;
10850 memset(m, 0, sizeof(struct meter));
10851 rte_meter_trtcm_config(&m->m, &mp->profile);
10853 m->color_mask = RTE_COLORS;
10862 rte_swx_ctl_meter_stats_read(struct rte_swx_pipeline *p,
10863 const char *metarray_name,
10864 uint32_t metarray_index,
10865 struct rte_swx_ctl_meter_stats *stats)
10867 struct metarray *metarray;
10868 struct metarray_runtime *metarray_runtime;
10872 CHECK_NAME(metarray_name, EINVAL);
10874 metarray = metarray_find(p, metarray_name);
10875 CHECK(metarray, EINVAL);
10876 CHECK(metarray_index < metarray->size, EINVAL);
10878 CHECK(stats, EINVAL);
10880 metarray_runtime = &p->metarray_runtime[metarray->id];
10881 m = &metarray_runtime->metarray[metarray_index];
10883 memcpy(stats->n_pkts, m->n_pkts, sizeof(m->n_pkts));
10884 memcpy(stats->n_bytes, m->n_bytes, sizeof(m->n_bytes));