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;
1521 instr_rx_exec(struct rte_swx_pipeline *p);
1524 instr_rx_exec(struct rte_swx_pipeline *p)
1526 struct thread *t = &p->threads[p->thread_id];
1527 struct instruction *ip = t->ip;
1528 struct port_in_runtime *port = &p->in[p->port_id];
1529 struct rte_swx_pkt *pkt = &t->pkt;
1533 pkt_received = port->pkt_rx(port->obj, pkt);
1534 t->ptr = &pkt->pkt[pkt->offset];
1535 rte_prefetch0(t->ptr);
1537 TRACE("[Thread %2u] rx %s from port %u\n",
1539 pkt_received ? "1 pkt" : "0 pkts",
1543 t->valid_headers = 0;
1544 t->n_headers_out = 0;
1547 METADATA_WRITE(t, ip->io.io.offset, ip->io.io.n_bits, p->port_id);
1550 t->table_state = p->table_state;
1553 pipeline_port_inc(p);
1554 thread_ip_inc_cond(t, pkt_received);
1562 instr_tx_translate(struct rte_swx_pipeline *p,
1563 struct action *action __rte_unused,
1566 struct instruction *instr,
1567 struct instruction_data *data __rte_unused)
1569 char *port = tokens[1];
1573 CHECK(n_tokens == 2, EINVAL);
1575 f = metadata_field_parse(p, port);
1577 instr->type = INSTR_TX;
1578 instr->io.io.offset = f->offset / 8;
1579 instr->io.io.n_bits = f->n_bits;
1584 port_val = strtoul(port, &port, 0);
1585 CHECK(!port[0], EINVAL);
1587 instr->type = INSTR_TX_I;
1588 instr->io.io.val = port_val;
1593 instr_drop_translate(struct rte_swx_pipeline *p,
1594 struct action *action __rte_unused,
1595 char **tokens __rte_unused,
1597 struct instruction *instr,
1598 struct instruction_data *data __rte_unused)
1600 CHECK(n_tokens == 1, EINVAL);
1603 instr->type = INSTR_TX_I;
1604 instr->io.io.val = p->n_ports_out - 1;
1609 emit_handler(struct thread *t)
1611 struct header_out_runtime *h0 = &t->headers_out[0];
1612 struct header_out_runtime *h1 = &t->headers_out[1];
1613 uint32_t offset = 0, i;
1615 /* No header change or header decapsulation. */
1616 if ((t->n_headers_out == 1) &&
1617 (h0->ptr + h0->n_bytes == t->ptr)) {
1618 TRACE("Emit handler: no header change or header decap.\n");
1620 t->pkt.offset -= h0->n_bytes;
1621 t->pkt.length += h0->n_bytes;
1626 /* Header encapsulation (optionally, with prior header decasulation). */
1627 if ((t->n_headers_out == 2) &&
1628 (h1->ptr + h1->n_bytes == t->ptr) &&
1629 (h0->ptr == h0->ptr0)) {
1632 TRACE("Emit handler: header encapsulation.\n");
1634 offset = h0->n_bytes + h1->n_bytes;
1635 memcpy(t->ptr - offset, h0->ptr, h0->n_bytes);
1636 t->pkt.offset -= offset;
1637 t->pkt.length += offset;
1642 /* Header insertion. */
1645 /* Header extraction. */
1648 /* For any other case. */
1649 TRACE("Emit handler: complex case.\n");
1651 for (i = 0; i < t->n_headers_out; i++) {
1652 struct header_out_runtime *h = &t->headers_out[i];
1654 memcpy(&t->header_out_storage[offset], h->ptr, h->n_bytes);
1655 offset += h->n_bytes;
1659 memcpy(t->ptr - offset, t->header_out_storage, offset);
1660 t->pkt.offset -= offset;
1661 t->pkt.length += offset;
1666 instr_tx_exec(struct rte_swx_pipeline *p);
1669 instr_tx_exec(struct rte_swx_pipeline *p)
1671 struct thread *t = &p->threads[p->thread_id];
1672 struct instruction *ip = t->ip;
1673 uint64_t port_id = METADATA_READ(t, ip->io.io.offset, ip->io.io.n_bits);
1674 struct port_out_runtime *port = &p->out[port_id];
1675 struct rte_swx_pkt *pkt = &t->pkt;
1677 TRACE("[Thread %2u]: tx 1 pkt to port %u\n",
1685 port->pkt_tx(port->obj, pkt);
1688 thread_ip_reset(p, t);
1693 instr_tx_i_exec(struct rte_swx_pipeline *p)
1695 struct thread *t = &p->threads[p->thread_id];
1696 struct instruction *ip = t->ip;
1697 uint64_t port_id = ip->io.io.val;
1698 struct port_out_runtime *port = &p->out[port_id];
1699 struct rte_swx_pkt *pkt = &t->pkt;
1701 TRACE("[Thread %2u]: tx (i) 1 pkt to port %u\n",
1709 port->pkt_tx(port->obj, pkt);
1712 thread_ip_reset(p, t);
1720 instr_hdr_extract_translate(struct rte_swx_pipeline *p,
1721 struct action *action,
1724 struct instruction *instr,
1725 struct instruction_data *data __rte_unused)
1729 CHECK(!action, EINVAL);
1730 CHECK((n_tokens == 2) || (n_tokens == 3), EINVAL);
1732 h = header_parse(p, tokens[1]);
1735 if (n_tokens == 2) {
1736 CHECK(!h->st->var_size, EINVAL);
1738 instr->type = INSTR_HDR_EXTRACT;
1739 instr->io.hdr.header_id[0] = h->id;
1740 instr->io.hdr.struct_id[0] = h->struct_id;
1741 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
1745 CHECK(h->st->var_size, EINVAL);
1747 mf = metadata_field_parse(p, tokens[2]);
1749 CHECK(!mf->var_size, EINVAL);
1751 instr->type = INSTR_HDR_EXTRACT_M;
1752 instr->io.io.offset = mf->offset / 8;
1753 instr->io.io.n_bits = mf->n_bits;
1754 instr->io.hdr.header_id[0] = h->id;
1755 instr->io.hdr.struct_id[0] = h->struct_id;
1756 instr->io.hdr.n_bytes[0] = h->st->n_bits_min / 8;
1763 instr_hdr_lookahead_translate(struct rte_swx_pipeline *p,
1764 struct action *action,
1767 struct instruction *instr,
1768 struct instruction_data *data __rte_unused)
1772 CHECK(!action, EINVAL);
1773 CHECK(n_tokens == 2, EINVAL);
1775 h = header_parse(p, tokens[1]);
1777 CHECK(!h->st->var_size, EINVAL);
1779 instr->type = INSTR_HDR_LOOKAHEAD;
1780 instr->io.hdr.header_id[0] = h->id;
1781 instr->io.hdr.struct_id[0] = h->struct_id;
1782 instr->io.hdr.n_bytes[0] = 0; /* Unused. */
1788 __instr_hdr_extract_exec(struct rte_swx_pipeline *p, uint32_t n_extract);
1791 __instr_hdr_extract_exec(struct rte_swx_pipeline *p, uint32_t n_extract)
1793 struct thread *t = &p->threads[p->thread_id];
1794 struct instruction *ip = t->ip;
1795 uint64_t valid_headers = t->valid_headers;
1796 uint8_t *ptr = t->ptr;
1797 uint32_t offset = t->pkt.offset;
1798 uint32_t length = t->pkt.length;
1801 for (i = 0; i < n_extract; i++) {
1802 uint32_t header_id = ip->io.hdr.header_id[i];
1803 uint32_t struct_id = ip->io.hdr.struct_id[i];
1804 uint32_t n_bytes = ip->io.hdr.n_bytes[i];
1806 TRACE("[Thread %2u]: extract header %u (%u bytes)\n",
1812 t->structs[struct_id] = ptr;
1813 valid_headers = MASK64_BIT_SET(valid_headers, header_id);
1822 t->valid_headers = valid_headers;
1825 t->pkt.offset = offset;
1826 t->pkt.length = length;
1831 instr_hdr_extract_exec(struct rte_swx_pipeline *p)
1833 __instr_hdr_extract_exec(p, 1);
1840 instr_hdr_extract2_exec(struct rte_swx_pipeline *p)
1842 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n",
1845 __instr_hdr_extract_exec(p, 2);
1852 instr_hdr_extract3_exec(struct rte_swx_pipeline *p)
1854 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n",
1857 __instr_hdr_extract_exec(p, 3);
1864 instr_hdr_extract4_exec(struct rte_swx_pipeline *p)
1866 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n",
1869 __instr_hdr_extract_exec(p, 4);
1876 instr_hdr_extract5_exec(struct rte_swx_pipeline *p)
1878 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n",
1881 __instr_hdr_extract_exec(p, 5);
1888 instr_hdr_extract6_exec(struct rte_swx_pipeline *p)
1890 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n",
1893 __instr_hdr_extract_exec(p, 6);
1900 instr_hdr_extract7_exec(struct rte_swx_pipeline *p)
1902 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n",
1905 __instr_hdr_extract_exec(p, 7);
1912 instr_hdr_extract8_exec(struct rte_swx_pipeline *p)
1914 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n",
1917 __instr_hdr_extract_exec(p, 8);
1924 instr_hdr_extract_m_exec(struct rte_swx_pipeline *p)
1926 struct thread *t = &p->threads[p->thread_id];
1927 struct instruction *ip = t->ip;
1929 uint64_t valid_headers = t->valid_headers;
1930 uint8_t *ptr = t->ptr;
1931 uint32_t offset = t->pkt.offset;
1932 uint32_t length = t->pkt.length;
1934 uint32_t n_bytes_last = METADATA_READ(t, ip->io.io.offset, ip->io.io.n_bits);
1935 uint32_t header_id = ip->io.hdr.header_id[0];
1936 uint32_t struct_id = ip->io.hdr.struct_id[0];
1937 uint32_t n_bytes = ip->io.hdr.n_bytes[0];
1939 struct header_runtime *h = &t->headers[header_id];
1941 TRACE("[Thread %2u]: extract header %u (%u + %u bytes)\n",
1947 n_bytes += n_bytes_last;
1950 t->structs[struct_id] = ptr;
1951 t->valid_headers = MASK64_BIT_SET(valid_headers, header_id);
1952 h->n_bytes = n_bytes;
1955 t->pkt.offset = offset + n_bytes;
1956 t->pkt.length = length - n_bytes;
1957 t->ptr = ptr + n_bytes;
1964 instr_hdr_lookahead_exec(struct rte_swx_pipeline *p)
1966 struct thread *t = &p->threads[p->thread_id];
1967 struct instruction *ip = t->ip;
1969 uint64_t valid_headers = t->valid_headers;
1970 uint8_t *ptr = t->ptr;
1972 uint32_t header_id = ip->io.hdr.header_id[0];
1973 uint32_t struct_id = ip->io.hdr.struct_id[0];
1975 TRACE("[Thread %2u]: lookahead header %u\n",
1980 t->structs[struct_id] = ptr;
1981 t->valid_headers = MASK64_BIT_SET(valid_headers, header_id);
1991 instr_hdr_emit_translate(struct rte_swx_pipeline *p,
1992 struct action *action __rte_unused,
1995 struct instruction *instr,
1996 struct instruction_data *data __rte_unused)
2000 CHECK(n_tokens == 2, EINVAL);
2002 h = header_parse(p, tokens[1]);
2005 instr->type = INSTR_HDR_EMIT;
2006 instr->io.hdr.header_id[0] = h->id;
2007 instr->io.hdr.struct_id[0] = h->struct_id;
2008 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
2013 __instr_hdr_emit_exec(struct rte_swx_pipeline *p, uint32_t n_emit);
2016 __instr_hdr_emit_exec(struct rte_swx_pipeline *p, uint32_t n_emit)
2018 struct thread *t = &p->threads[p->thread_id];
2019 struct instruction *ip = t->ip;
2020 uint64_t valid_headers = t->valid_headers;
2021 uint32_t n_headers_out = t->n_headers_out;
2022 struct header_out_runtime *ho = &t->headers_out[n_headers_out - 1];
2023 uint8_t *ho_ptr = NULL;
2024 uint32_t ho_nbytes = 0, first = 1, i;
2026 for (i = 0; i < n_emit; i++) {
2027 uint32_t header_id = ip->io.hdr.header_id[i];
2028 uint32_t struct_id = ip->io.hdr.struct_id[i];
2030 struct header_runtime *hi = &t->headers[header_id];
2031 uint8_t *hi_ptr0 = hi->ptr0;
2032 uint32_t n_bytes = hi->n_bytes;
2034 uint8_t *hi_ptr = t->structs[struct_id];
2036 if (!MASK64_BIT_GET(valid_headers, header_id))
2039 TRACE("[Thread %2u]: emit header %u\n",
2047 if (!t->n_headers_out) {
2048 ho = &t->headers_out[0];
2054 ho_nbytes = n_bytes;
2061 ho_nbytes = ho->n_bytes;
2065 if (ho_ptr + ho_nbytes == hi_ptr) {
2066 ho_nbytes += n_bytes;
2068 ho->n_bytes = ho_nbytes;
2075 ho_nbytes = n_bytes;
2081 ho->n_bytes = ho_nbytes;
2082 t->n_headers_out = n_headers_out;
2086 instr_hdr_emit_exec(struct rte_swx_pipeline *p)
2088 __instr_hdr_emit_exec(p, 1);
2095 instr_hdr_emit_tx_exec(struct rte_swx_pipeline *p)
2097 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n",
2100 __instr_hdr_emit_exec(p, 1);
2105 instr_hdr_emit2_tx_exec(struct rte_swx_pipeline *p)
2107 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n",
2110 __instr_hdr_emit_exec(p, 2);
2115 instr_hdr_emit3_tx_exec(struct rte_swx_pipeline *p)
2117 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n",
2120 __instr_hdr_emit_exec(p, 3);
2125 instr_hdr_emit4_tx_exec(struct rte_swx_pipeline *p)
2127 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n",
2130 __instr_hdr_emit_exec(p, 4);
2135 instr_hdr_emit5_tx_exec(struct rte_swx_pipeline *p)
2137 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n",
2140 __instr_hdr_emit_exec(p, 5);
2145 instr_hdr_emit6_tx_exec(struct rte_swx_pipeline *p)
2147 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n",
2150 __instr_hdr_emit_exec(p, 6);
2155 instr_hdr_emit7_tx_exec(struct rte_swx_pipeline *p)
2157 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n",
2160 __instr_hdr_emit_exec(p, 7);
2165 instr_hdr_emit8_tx_exec(struct rte_swx_pipeline *p)
2167 TRACE("[Thread %2u] *** The next 9 instructions are fused. ***\n",
2170 __instr_hdr_emit_exec(p, 8);
2178 instr_hdr_validate_translate(struct rte_swx_pipeline *p,
2179 struct action *action __rte_unused,
2182 struct instruction *instr,
2183 struct instruction_data *data __rte_unused)
2187 CHECK(n_tokens == 2, EINVAL);
2189 h = header_parse(p, tokens[1]);
2192 instr->type = INSTR_HDR_VALIDATE;
2193 instr->valid.header_id = h->id;
2198 instr_hdr_validate_exec(struct rte_swx_pipeline *p)
2200 struct thread *t = &p->threads[p->thread_id];
2201 struct instruction *ip = t->ip;
2202 uint32_t header_id = ip->valid.header_id;
2204 TRACE("[Thread %2u] validate header %u\n", p->thread_id, header_id);
2207 t->valid_headers = MASK64_BIT_SET(t->valid_headers, header_id);
2217 instr_hdr_invalidate_translate(struct rte_swx_pipeline *p,
2218 struct action *action __rte_unused,
2221 struct instruction *instr,
2222 struct instruction_data *data __rte_unused)
2226 CHECK(n_tokens == 2, EINVAL);
2228 h = header_parse(p, tokens[1]);
2231 instr->type = INSTR_HDR_INVALIDATE;
2232 instr->valid.header_id = h->id;
2237 instr_hdr_invalidate_exec(struct rte_swx_pipeline *p)
2239 struct thread *t = &p->threads[p->thread_id];
2240 struct instruction *ip = t->ip;
2241 uint32_t header_id = ip->valid.header_id;
2243 TRACE("[Thread %2u] invalidate header %u\n", p->thread_id, header_id);
2246 t->valid_headers = MASK64_BIT_CLR(t->valid_headers, header_id);
2255 static struct table *
2256 table_find(struct rte_swx_pipeline *p, const char *name);
2258 static struct selector *
2259 selector_find(struct rte_swx_pipeline *p, const char *name);
2261 static struct learner *
2262 learner_find(struct rte_swx_pipeline *p, const char *name);
2265 instr_table_translate(struct rte_swx_pipeline *p,
2266 struct action *action,
2269 struct instruction *instr,
2270 struct instruction_data *data __rte_unused)
2276 CHECK(!action, EINVAL);
2277 CHECK(n_tokens == 2, EINVAL);
2279 t = table_find(p, tokens[1]);
2281 instr->type = INSTR_TABLE;
2282 instr->table.table_id = t->id;
2286 s = selector_find(p, tokens[1]);
2288 instr->type = INSTR_SELECTOR;
2289 instr->table.table_id = s->id;
2293 l = learner_find(p, tokens[1]);
2295 instr->type = INSTR_LEARNER;
2296 instr->table.table_id = l->id;
2304 instr_table_exec(struct rte_swx_pipeline *p)
2306 struct thread *t = &p->threads[p->thread_id];
2307 struct instruction *ip = t->ip;
2308 uint32_t table_id = ip->table.table_id;
2309 struct rte_swx_table_state *ts = &t->table_state[table_id];
2310 struct table_runtime *table = &t->tables[table_id];
2311 struct table_statistics *stats = &p->table_stats[table_id];
2312 uint64_t action_id, n_pkts_hit, n_pkts_action;
2313 uint8_t *action_data;
2317 done = table->func(ts->obj,
2325 TRACE("[Thread %2u] table %u (not finalized)\n",
2333 action_id = hit ? action_id : ts->default_action_id;
2334 action_data = hit ? action_data : ts->default_action_data;
2335 n_pkts_hit = stats->n_pkts_hit[hit];
2336 n_pkts_action = stats->n_pkts_action[action_id];
2338 TRACE("[Thread %2u] table %u (%s, action %u)\n",
2341 hit ? "hit" : "miss",
2342 (uint32_t)action_id);
2344 t->action_id = action_id;
2345 t->structs[0] = action_data;
2347 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2348 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2351 thread_ip_action_call(p, t, action_id);
2355 instr_selector_exec(struct rte_swx_pipeline *p)
2357 struct thread *t = &p->threads[p->thread_id];
2358 struct instruction *ip = t->ip;
2359 uint32_t selector_id = ip->table.table_id;
2360 struct rte_swx_table_state *ts = &t->table_state[p->n_tables + selector_id];
2361 struct selector_runtime *selector = &t->selectors[selector_id];
2362 struct selector_statistics *stats = &p->selector_stats[selector_id];
2363 uint64_t n_pkts = stats->n_pkts;
2367 done = rte_swx_table_selector_select(ts->obj,
2369 selector->group_id_buffer,
2370 selector->selector_buffer,
2371 selector->member_id_buffer);
2374 TRACE("[Thread %2u] selector %u (not finalized)\n",
2383 TRACE("[Thread %2u] selector %u\n",
2387 stats->n_pkts = n_pkts + 1;
2394 instr_learner_exec(struct rte_swx_pipeline *p)
2396 struct thread *t = &p->threads[p->thread_id];
2397 struct instruction *ip = t->ip;
2398 uint32_t learner_id = ip->table.table_id;
2399 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2400 p->n_selectors + learner_id];
2401 struct learner_runtime *l = &t->learners[learner_id];
2402 struct learner_statistics *stats = &p->learner_stats[learner_id];
2403 uint64_t action_id, n_pkts_hit, n_pkts_action, time;
2404 uint8_t *action_data;
2408 time = rte_get_tsc_cycles();
2410 done = rte_swx_table_learner_lookup(ts->obj,
2419 TRACE("[Thread %2u] learner %u (not finalized)\n",
2427 action_id = hit ? action_id : ts->default_action_id;
2428 action_data = hit ? action_data : ts->default_action_data;
2429 n_pkts_hit = stats->n_pkts_hit[hit];
2430 n_pkts_action = stats->n_pkts_action[action_id];
2432 TRACE("[Thread %2u] learner %u (%s, action %u)\n",
2435 hit ? "hit" : "miss",
2436 (uint32_t)action_id);
2438 t->action_id = action_id;
2439 t->structs[0] = action_data;
2441 t->learner_id = learner_id;
2443 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
2444 stats->n_pkts_action[action_id] = n_pkts_action + 1;
2447 thread_ip_action_call(p, t, action_id);
2453 static struct action *
2454 action_find(struct rte_swx_pipeline *p, const char *name);
2457 action_has_nbo_args(struct action *a);
2460 instr_learn_translate(struct rte_swx_pipeline *p,
2461 struct action *action,
2464 struct instruction *instr,
2465 struct instruction_data *data __rte_unused)
2469 CHECK(action, EINVAL);
2470 CHECK(n_tokens == 2, EINVAL);
2472 a = action_find(p, tokens[1]);
2474 CHECK(!action_has_nbo_args(a), EINVAL);
2476 instr->type = INSTR_LEARNER_LEARN;
2477 instr->learn.action_id = a->id;
2483 instr_learn_exec(struct rte_swx_pipeline *p)
2485 struct thread *t = &p->threads[p->thread_id];
2486 struct instruction *ip = t->ip;
2487 uint64_t action_id = ip->learn.action_id;
2488 uint32_t learner_id = t->learner_id;
2489 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2490 p->n_selectors + learner_id];
2491 struct learner_runtime *l = &t->learners[learner_id];
2492 struct learner_statistics *stats = &p->learner_stats[learner_id];
2496 status = rte_swx_table_learner_add(ts->obj,
2500 l->action_data[action_id]);
2502 TRACE("[Thread %2u] learner %u learn %s\n",
2505 status ? "ok" : "error");
2507 stats->n_pkts_learn[status] += 1;
2517 instr_forget_translate(struct rte_swx_pipeline *p __rte_unused,
2518 struct action *action,
2519 char **tokens __rte_unused,
2521 struct instruction *instr,
2522 struct instruction_data *data __rte_unused)
2524 CHECK(action, EINVAL);
2525 CHECK(n_tokens == 1, EINVAL);
2527 instr->type = INSTR_LEARNER_FORGET;
2533 instr_forget_exec(struct rte_swx_pipeline *p)
2535 struct thread *t = &p->threads[p->thread_id];
2536 uint32_t learner_id = t->learner_id;
2537 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2538 p->n_selectors + learner_id];
2539 struct learner_runtime *l = &t->learners[learner_id];
2540 struct learner_statistics *stats = &p->learner_stats[learner_id];
2543 rte_swx_table_learner_delete(ts->obj, l->mailbox);
2545 TRACE("[Thread %2u] learner %u forget\n",
2549 stats->n_pkts_forget += 1;
2559 instr_extern_translate(struct rte_swx_pipeline *p,
2560 struct action *action __rte_unused,
2563 struct instruction *instr,
2564 struct instruction_data *data __rte_unused)
2566 char *token = tokens[1];
2568 CHECK(n_tokens == 2, EINVAL);
2570 if (token[0] == 'e') {
2571 struct extern_obj *obj;
2572 struct extern_type_member_func *func;
2574 func = extern_obj_member_func_parse(p, token, &obj);
2575 CHECK(func, EINVAL);
2577 instr->type = INSTR_EXTERN_OBJ;
2578 instr->ext_obj.ext_obj_id = obj->id;
2579 instr->ext_obj.func_id = func->id;
2584 if (token[0] == 'f') {
2585 struct extern_func *func;
2587 func = extern_func_parse(p, token);
2588 CHECK(func, EINVAL);
2590 instr->type = INSTR_EXTERN_FUNC;
2591 instr->ext_func.ext_func_id = func->id;
2600 instr_extern_obj_exec(struct rte_swx_pipeline *p)
2602 struct thread *t = &p->threads[p->thread_id];
2603 struct instruction *ip = t->ip;
2604 uint32_t obj_id = ip->ext_obj.ext_obj_id;
2605 uint32_t func_id = ip->ext_obj.func_id;
2606 struct extern_obj_runtime *obj = &t->extern_objs[obj_id];
2607 rte_swx_extern_type_member_func_t func = obj->funcs[func_id];
2609 TRACE("[Thread %2u] extern obj %u member func %u\n",
2614 /* Extern object member function execute. */
2615 uint32_t done = func(obj->obj, obj->mailbox);
2618 thread_ip_inc_cond(t, done);
2619 thread_yield_cond(p, done ^ 1);
2623 instr_extern_func_exec(struct rte_swx_pipeline *p)
2625 struct thread *t = &p->threads[p->thread_id];
2626 struct instruction *ip = t->ip;
2627 uint32_t ext_func_id = ip->ext_func.ext_func_id;
2628 struct extern_func_runtime *ext_func = &t->extern_funcs[ext_func_id];
2629 rte_swx_extern_func_t func = ext_func->func;
2631 TRACE("[Thread %2u] extern func %u\n",
2635 /* Extern function execute. */
2636 uint32_t done = func(ext_func->mailbox);
2639 thread_ip_inc_cond(t, done);
2640 thread_yield_cond(p, done ^ 1);
2647 instr_mov_translate(struct rte_swx_pipeline *p,
2648 struct action *action,
2651 struct instruction *instr,
2652 struct instruction_data *data __rte_unused)
2654 char *dst = tokens[1], *src = tokens[2];
2655 struct field *fdst, *fsrc;
2657 uint32_t dst_struct_id = 0, src_struct_id = 0;
2659 CHECK(n_tokens == 3, EINVAL);
2661 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2662 CHECK(fdst, EINVAL);
2663 CHECK(!fdst->var_size, EINVAL);
2665 /* MOV, MOV_MH, MOV_HM or MOV_HH. */
2666 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2668 CHECK(!fsrc->var_size, EINVAL);
2670 instr->type = INSTR_MOV;
2671 if (dst[0] != 'h' && src[0] == 'h')
2672 instr->type = INSTR_MOV_MH;
2673 if (dst[0] == 'h' && src[0] != 'h')
2674 instr->type = INSTR_MOV_HM;
2675 if (dst[0] == 'h' && src[0] == 'h')
2676 instr->type = INSTR_MOV_HH;
2678 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
2679 instr->mov.dst.n_bits = fdst->n_bits;
2680 instr->mov.dst.offset = fdst->offset / 8;
2681 instr->mov.src.struct_id = (uint8_t)src_struct_id;
2682 instr->mov.src.n_bits = fsrc->n_bits;
2683 instr->mov.src.offset = fsrc->offset / 8;
2688 src_val = strtoull(src, &src, 0);
2689 CHECK(!src[0], EINVAL);
2692 src_val = hton64(src_val) >> (64 - fdst->n_bits);
2694 instr->type = INSTR_MOV_I;
2695 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
2696 instr->mov.dst.n_bits = fdst->n_bits;
2697 instr->mov.dst.offset = fdst->offset / 8;
2698 instr->mov.src_val = src_val;
2703 instr_mov_exec(struct rte_swx_pipeline *p)
2705 struct thread *t = &p->threads[p->thread_id];
2706 struct instruction *ip = t->ip;
2708 TRACE("[Thread %2u] mov\n",
2718 instr_mov_mh_exec(struct rte_swx_pipeline *p)
2720 struct thread *t = &p->threads[p->thread_id];
2721 struct instruction *ip = t->ip;
2723 TRACE("[Thread %2u] mov (mh)\n",
2733 instr_mov_hm_exec(struct rte_swx_pipeline *p)
2735 struct thread *t = &p->threads[p->thread_id];
2736 struct instruction *ip = t->ip;
2738 TRACE("[Thread %2u] mov (hm)\n",
2748 instr_mov_hh_exec(struct rte_swx_pipeline *p)
2750 struct thread *t = &p->threads[p->thread_id];
2751 struct instruction *ip = t->ip;
2753 TRACE("[Thread %2u] mov (hh)\n",
2763 instr_mov_i_exec(struct rte_swx_pipeline *p)
2765 struct thread *t = &p->threads[p->thread_id];
2766 struct instruction *ip = t->ip;
2768 TRACE("[Thread %2u] mov m.f %" PRIx64 "\n",
2782 __instr_dma_ht_exec(struct rte_swx_pipeline *p, uint32_t n_dma);
2785 __instr_dma_ht_exec(struct rte_swx_pipeline *p, uint32_t n_dma)
2787 struct thread *t = &p->threads[p->thread_id];
2788 struct instruction *ip = t->ip;
2789 uint8_t *action_data = t->structs[0];
2790 uint64_t valid_headers = t->valid_headers;
2793 for (i = 0; i < n_dma; i++) {
2794 uint32_t header_id = ip->dma.dst.header_id[i];
2795 uint32_t struct_id = ip->dma.dst.struct_id[i];
2796 uint32_t offset = ip->dma.src.offset[i];
2797 uint32_t n_bytes = ip->dma.n_bytes[i];
2799 struct header_runtime *h = &t->headers[header_id];
2800 uint8_t *h_ptr0 = h->ptr0;
2801 uint8_t *h_ptr = t->structs[struct_id];
2803 void *dst = MASK64_BIT_GET(valid_headers, header_id) ?
2805 void *src = &action_data[offset];
2807 TRACE("[Thread %2u] dma h.s t.f\n", p->thread_id);
2810 memcpy(dst, src, n_bytes);
2811 t->structs[struct_id] = dst;
2812 valid_headers = MASK64_BIT_SET(valid_headers, header_id);
2815 t->valid_headers = valid_headers;
2819 instr_dma_ht_exec(struct rte_swx_pipeline *p)
2821 __instr_dma_ht_exec(p, 1);
2828 instr_dma_ht2_exec(struct rte_swx_pipeline *p)
2830 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n",
2833 __instr_dma_ht_exec(p, 2);
2840 instr_dma_ht3_exec(struct rte_swx_pipeline *p)
2842 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n",
2845 __instr_dma_ht_exec(p, 3);
2852 instr_dma_ht4_exec(struct rte_swx_pipeline *p)
2854 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n",
2857 __instr_dma_ht_exec(p, 4);
2864 instr_dma_ht5_exec(struct rte_swx_pipeline *p)
2866 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n",
2869 __instr_dma_ht_exec(p, 5);
2876 instr_dma_ht6_exec(struct rte_swx_pipeline *p)
2878 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n",
2881 __instr_dma_ht_exec(p, 6);
2888 instr_dma_ht7_exec(struct rte_swx_pipeline *p)
2890 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n",
2893 __instr_dma_ht_exec(p, 7);
2900 instr_dma_ht8_exec(struct rte_swx_pipeline *p)
2902 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n",
2905 __instr_dma_ht_exec(p, 8);
2915 instr_alu_add_translate(struct rte_swx_pipeline *p,
2916 struct action *action,
2919 struct instruction *instr,
2920 struct instruction_data *data __rte_unused)
2922 char *dst = tokens[1], *src = tokens[2];
2923 struct field *fdst, *fsrc;
2925 uint32_t dst_struct_id = 0, src_struct_id = 0;
2927 CHECK(n_tokens == 3, EINVAL);
2929 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2930 CHECK(fdst, EINVAL);
2931 CHECK(!fdst->var_size, EINVAL);
2933 /* ADD, ADD_HM, ADD_MH, ADD_HH. */
2934 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2936 CHECK(!fsrc->var_size, EINVAL);
2938 instr->type = INSTR_ALU_ADD;
2939 if (dst[0] == 'h' && src[0] != 'h')
2940 instr->type = INSTR_ALU_ADD_HM;
2941 if (dst[0] != 'h' && src[0] == 'h')
2942 instr->type = INSTR_ALU_ADD_MH;
2943 if (dst[0] == 'h' && src[0] == 'h')
2944 instr->type = INSTR_ALU_ADD_HH;
2946 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2947 instr->alu.dst.n_bits = fdst->n_bits;
2948 instr->alu.dst.offset = fdst->offset / 8;
2949 instr->alu.src.struct_id = (uint8_t)src_struct_id;
2950 instr->alu.src.n_bits = fsrc->n_bits;
2951 instr->alu.src.offset = fsrc->offset / 8;
2955 /* ADD_MI, ADD_HI. */
2956 src_val = strtoull(src, &src, 0);
2957 CHECK(!src[0], EINVAL);
2959 instr->type = INSTR_ALU_ADD_MI;
2961 instr->type = INSTR_ALU_ADD_HI;
2963 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
2964 instr->alu.dst.n_bits = fdst->n_bits;
2965 instr->alu.dst.offset = fdst->offset / 8;
2966 instr->alu.src_val = src_val;
2971 instr_alu_sub_translate(struct rte_swx_pipeline *p,
2972 struct action *action,
2975 struct instruction *instr,
2976 struct instruction_data *data __rte_unused)
2978 char *dst = tokens[1], *src = tokens[2];
2979 struct field *fdst, *fsrc;
2981 uint32_t dst_struct_id = 0, src_struct_id = 0;
2983 CHECK(n_tokens == 3, EINVAL);
2985 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
2986 CHECK(fdst, EINVAL);
2987 CHECK(!fdst->var_size, EINVAL);
2989 /* SUB, SUB_HM, SUB_MH, SUB_HH. */
2990 fsrc = struct_field_parse(p, action, src, &src_struct_id);
2992 CHECK(!fsrc->var_size, EINVAL);
2994 instr->type = INSTR_ALU_SUB;
2995 if (dst[0] == 'h' && src[0] != 'h')
2996 instr->type = INSTR_ALU_SUB_HM;
2997 if (dst[0] != 'h' && src[0] == 'h')
2998 instr->type = INSTR_ALU_SUB_MH;
2999 if (dst[0] == 'h' && src[0] == 'h')
3000 instr->type = INSTR_ALU_SUB_HH;
3002 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3003 instr->alu.dst.n_bits = fdst->n_bits;
3004 instr->alu.dst.offset = fdst->offset / 8;
3005 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3006 instr->alu.src.n_bits = fsrc->n_bits;
3007 instr->alu.src.offset = fsrc->offset / 8;
3011 /* SUB_MI, SUB_HI. */
3012 src_val = strtoull(src, &src, 0);
3013 CHECK(!src[0], EINVAL);
3015 instr->type = INSTR_ALU_SUB_MI;
3017 instr->type = INSTR_ALU_SUB_HI;
3019 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3020 instr->alu.dst.n_bits = fdst->n_bits;
3021 instr->alu.dst.offset = fdst->offset / 8;
3022 instr->alu.src_val = src_val;
3027 instr_alu_ckadd_translate(struct rte_swx_pipeline *p,
3028 struct action *action __rte_unused,
3031 struct instruction *instr,
3032 struct instruction_data *data __rte_unused)
3034 char *dst = tokens[1], *src = tokens[2];
3035 struct header *hdst, *hsrc;
3036 struct field *fdst, *fsrc;
3038 CHECK(n_tokens == 3, EINVAL);
3040 fdst = header_field_parse(p, dst, &hdst);
3041 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
3042 CHECK(!fdst->var_size, EINVAL);
3045 fsrc = header_field_parse(p, src, &hsrc);
3047 CHECK(!fsrc->var_size, EINVAL);
3049 instr->type = INSTR_ALU_CKADD_FIELD;
3050 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
3051 instr->alu.dst.n_bits = fdst->n_bits;
3052 instr->alu.dst.offset = fdst->offset / 8;
3053 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
3054 instr->alu.src.n_bits = fsrc->n_bits;
3055 instr->alu.src.offset = fsrc->offset / 8;
3059 /* CKADD_STRUCT, CKADD_STRUCT20. */
3060 hsrc = header_parse(p, src);
3061 CHECK(hsrc, EINVAL);
3062 CHECK(!hsrc->st->var_size, EINVAL);
3064 instr->type = INSTR_ALU_CKADD_STRUCT;
3065 if ((hsrc->st->n_bits / 8) == 20)
3066 instr->type = INSTR_ALU_CKADD_STRUCT20;
3068 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
3069 instr->alu.dst.n_bits = fdst->n_bits;
3070 instr->alu.dst.offset = fdst->offset / 8;
3071 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
3072 instr->alu.src.n_bits = hsrc->st->n_bits;
3073 instr->alu.src.offset = 0; /* Unused. */
3078 instr_alu_cksub_translate(struct rte_swx_pipeline *p,
3079 struct action *action __rte_unused,
3082 struct instruction *instr,
3083 struct instruction_data *data __rte_unused)
3085 char *dst = tokens[1], *src = tokens[2];
3086 struct header *hdst, *hsrc;
3087 struct field *fdst, *fsrc;
3089 CHECK(n_tokens == 3, EINVAL);
3091 fdst = header_field_parse(p, dst, &hdst);
3092 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
3093 CHECK(!fdst->var_size, EINVAL);
3095 fsrc = header_field_parse(p, src, &hsrc);
3096 CHECK(fsrc, EINVAL);
3097 CHECK(!fsrc->var_size, EINVAL);
3099 instr->type = INSTR_ALU_CKSUB_FIELD;
3100 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
3101 instr->alu.dst.n_bits = fdst->n_bits;
3102 instr->alu.dst.offset = fdst->offset / 8;
3103 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
3104 instr->alu.src.n_bits = fsrc->n_bits;
3105 instr->alu.src.offset = fsrc->offset / 8;
3110 instr_alu_shl_translate(struct rte_swx_pipeline *p,
3111 struct action *action,
3114 struct instruction *instr,
3115 struct instruction_data *data __rte_unused)
3117 char *dst = tokens[1], *src = tokens[2];
3118 struct field *fdst, *fsrc;
3120 uint32_t dst_struct_id = 0, src_struct_id = 0;
3122 CHECK(n_tokens == 3, EINVAL);
3124 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3125 CHECK(fdst, EINVAL);
3126 CHECK(!fdst->var_size, EINVAL);
3128 /* SHL, SHL_HM, SHL_MH, SHL_HH. */
3129 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3131 CHECK(!fsrc->var_size, EINVAL);
3133 instr->type = INSTR_ALU_SHL;
3134 if (dst[0] == 'h' && src[0] != 'h')
3135 instr->type = INSTR_ALU_SHL_HM;
3136 if (dst[0] != 'h' && src[0] == 'h')
3137 instr->type = INSTR_ALU_SHL_MH;
3138 if (dst[0] == 'h' && src[0] == 'h')
3139 instr->type = INSTR_ALU_SHL_HH;
3141 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3142 instr->alu.dst.n_bits = fdst->n_bits;
3143 instr->alu.dst.offset = fdst->offset / 8;
3144 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3145 instr->alu.src.n_bits = fsrc->n_bits;
3146 instr->alu.src.offset = fsrc->offset / 8;
3150 /* SHL_MI, SHL_HI. */
3151 src_val = strtoull(src, &src, 0);
3152 CHECK(!src[0], EINVAL);
3154 instr->type = INSTR_ALU_SHL_MI;
3156 instr->type = INSTR_ALU_SHL_HI;
3158 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3159 instr->alu.dst.n_bits = fdst->n_bits;
3160 instr->alu.dst.offset = fdst->offset / 8;
3161 instr->alu.src_val = src_val;
3166 instr_alu_shr_translate(struct rte_swx_pipeline *p,
3167 struct action *action,
3170 struct instruction *instr,
3171 struct instruction_data *data __rte_unused)
3173 char *dst = tokens[1], *src = tokens[2];
3174 struct field *fdst, *fsrc;
3176 uint32_t dst_struct_id = 0, src_struct_id = 0;
3178 CHECK(n_tokens == 3, EINVAL);
3180 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3181 CHECK(fdst, EINVAL);
3182 CHECK(!fdst->var_size, EINVAL);
3184 /* SHR, SHR_HM, SHR_MH, SHR_HH. */
3185 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3187 CHECK(!fsrc->var_size, EINVAL);
3189 instr->type = INSTR_ALU_SHR;
3190 if (dst[0] == 'h' && src[0] != 'h')
3191 instr->type = INSTR_ALU_SHR_HM;
3192 if (dst[0] != 'h' && src[0] == 'h')
3193 instr->type = INSTR_ALU_SHR_MH;
3194 if (dst[0] == 'h' && src[0] == 'h')
3195 instr->type = INSTR_ALU_SHR_HH;
3197 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3198 instr->alu.dst.n_bits = fdst->n_bits;
3199 instr->alu.dst.offset = fdst->offset / 8;
3200 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3201 instr->alu.src.n_bits = fsrc->n_bits;
3202 instr->alu.src.offset = fsrc->offset / 8;
3206 /* SHR_MI, SHR_HI. */
3207 src_val = strtoull(src, &src, 0);
3208 CHECK(!src[0], EINVAL);
3210 instr->type = INSTR_ALU_SHR_MI;
3212 instr->type = INSTR_ALU_SHR_HI;
3214 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3215 instr->alu.dst.n_bits = fdst->n_bits;
3216 instr->alu.dst.offset = fdst->offset / 8;
3217 instr->alu.src_val = src_val;
3222 instr_alu_and_translate(struct rte_swx_pipeline *p,
3223 struct action *action,
3226 struct instruction *instr,
3227 struct instruction_data *data __rte_unused)
3229 char *dst = tokens[1], *src = tokens[2];
3230 struct field *fdst, *fsrc;
3232 uint32_t dst_struct_id = 0, src_struct_id = 0;
3234 CHECK(n_tokens == 3, EINVAL);
3236 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3237 CHECK(fdst, EINVAL);
3238 CHECK(!fdst->var_size, EINVAL);
3240 /* AND, AND_MH, AND_HM, AND_HH. */
3241 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3243 CHECK(!fsrc->var_size, EINVAL);
3245 instr->type = INSTR_ALU_AND;
3246 if (dst[0] != 'h' && src[0] == 'h')
3247 instr->type = INSTR_ALU_AND_MH;
3248 if (dst[0] == 'h' && src[0] != 'h')
3249 instr->type = INSTR_ALU_AND_HM;
3250 if (dst[0] == 'h' && src[0] == 'h')
3251 instr->type = INSTR_ALU_AND_HH;
3253 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3254 instr->alu.dst.n_bits = fdst->n_bits;
3255 instr->alu.dst.offset = fdst->offset / 8;
3256 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3257 instr->alu.src.n_bits = fsrc->n_bits;
3258 instr->alu.src.offset = fsrc->offset / 8;
3263 src_val = strtoull(src, &src, 0);
3264 CHECK(!src[0], EINVAL);
3267 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3269 instr->type = INSTR_ALU_AND_I;
3270 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3271 instr->alu.dst.n_bits = fdst->n_bits;
3272 instr->alu.dst.offset = fdst->offset / 8;
3273 instr->alu.src_val = src_val;
3278 instr_alu_or_translate(struct rte_swx_pipeline *p,
3279 struct action *action,
3282 struct instruction *instr,
3283 struct instruction_data *data __rte_unused)
3285 char *dst = tokens[1], *src = tokens[2];
3286 struct field *fdst, *fsrc;
3288 uint32_t dst_struct_id = 0, src_struct_id = 0;
3290 CHECK(n_tokens == 3, EINVAL);
3292 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3293 CHECK(fdst, EINVAL);
3294 CHECK(!fdst->var_size, EINVAL);
3296 /* OR, OR_MH, OR_HM, OR_HH. */
3297 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3299 CHECK(!fsrc->var_size, EINVAL);
3301 instr->type = INSTR_ALU_OR;
3302 if (dst[0] != 'h' && src[0] == 'h')
3303 instr->type = INSTR_ALU_OR_MH;
3304 if (dst[0] == 'h' && src[0] != 'h')
3305 instr->type = INSTR_ALU_OR_HM;
3306 if (dst[0] == 'h' && src[0] == 'h')
3307 instr->type = INSTR_ALU_OR_HH;
3309 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3310 instr->alu.dst.n_bits = fdst->n_bits;
3311 instr->alu.dst.offset = fdst->offset / 8;
3312 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3313 instr->alu.src.n_bits = fsrc->n_bits;
3314 instr->alu.src.offset = fsrc->offset / 8;
3319 src_val = strtoull(src, &src, 0);
3320 CHECK(!src[0], EINVAL);
3323 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3325 instr->type = INSTR_ALU_OR_I;
3326 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3327 instr->alu.dst.n_bits = fdst->n_bits;
3328 instr->alu.dst.offset = fdst->offset / 8;
3329 instr->alu.src_val = src_val;
3334 instr_alu_xor_translate(struct rte_swx_pipeline *p,
3335 struct action *action,
3338 struct instruction *instr,
3339 struct instruction_data *data __rte_unused)
3341 char *dst = tokens[1], *src = tokens[2];
3342 struct field *fdst, *fsrc;
3344 uint32_t dst_struct_id = 0, src_struct_id = 0;
3346 CHECK(n_tokens == 3, EINVAL);
3348 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3349 CHECK(fdst, EINVAL);
3350 CHECK(!fdst->var_size, EINVAL);
3352 /* XOR, XOR_MH, XOR_HM, XOR_HH. */
3353 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3355 CHECK(!fsrc->var_size, EINVAL);
3357 instr->type = INSTR_ALU_XOR;
3358 if (dst[0] != 'h' && src[0] == 'h')
3359 instr->type = INSTR_ALU_XOR_MH;
3360 if (dst[0] == 'h' && src[0] != 'h')
3361 instr->type = INSTR_ALU_XOR_HM;
3362 if (dst[0] == 'h' && src[0] == 'h')
3363 instr->type = INSTR_ALU_XOR_HH;
3365 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3366 instr->alu.dst.n_bits = fdst->n_bits;
3367 instr->alu.dst.offset = fdst->offset / 8;
3368 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3369 instr->alu.src.n_bits = fsrc->n_bits;
3370 instr->alu.src.offset = fsrc->offset / 8;
3375 src_val = strtoull(src, &src, 0);
3376 CHECK(!src[0], EINVAL);
3379 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3381 instr->type = INSTR_ALU_XOR_I;
3382 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3383 instr->alu.dst.n_bits = fdst->n_bits;
3384 instr->alu.dst.offset = fdst->offset / 8;
3385 instr->alu.src_val = src_val;
3390 instr_alu_add_exec(struct rte_swx_pipeline *p)
3392 struct thread *t = &p->threads[p->thread_id];
3393 struct instruction *ip = t->ip;
3395 TRACE("[Thread %2u] add\n", p->thread_id);
3405 instr_alu_add_mh_exec(struct rte_swx_pipeline *p)
3407 struct thread *t = &p->threads[p->thread_id];
3408 struct instruction *ip = t->ip;
3410 TRACE("[Thread %2u] add (mh)\n", p->thread_id);
3420 instr_alu_add_hm_exec(struct rte_swx_pipeline *p)
3422 struct thread *t = &p->threads[p->thread_id];
3423 struct instruction *ip = t->ip;
3425 TRACE("[Thread %2u] add (hm)\n", p->thread_id);
3435 instr_alu_add_hh_exec(struct rte_swx_pipeline *p)
3437 struct thread *t = &p->threads[p->thread_id];
3438 struct instruction *ip = t->ip;
3440 TRACE("[Thread %2u] add (hh)\n", p->thread_id);
3450 instr_alu_add_mi_exec(struct rte_swx_pipeline *p)
3452 struct thread *t = &p->threads[p->thread_id];
3453 struct instruction *ip = t->ip;
3455 TRACE("[Thread %2u] add (mi)\n", p->thread_id);
3465 instr_alu_add_hi_exec(struct rte_swx_pipeline *p)
3467 struct thread *t = &p->threads[p->thread_id];
3468 struct instruction *ip = t->ip;
3470 TRACE("[Thread %2u] add (hi)\n", p->thread_id);
3480 instr_alu_sub_exec(struct rte_swx_pipeline *p)
3482 struct thread *t = &p->threads[p->thread_id];
3483 struct instruction *ip = t->ip;
3485 TRACE("[Thread %2u] sub\n", p->thread_id);
3495 instr_alu_sub_mh_exec(struct rte_swx_pipeline *p)
3497 struct thread *t = &p->threads[p->thread_id];
3498 struct instruction *ip = t->ip;
3500 TRACE("[Thread %2u] sub (mh)\n", p->thread_id);
3510 instr_alu_sub_hm_exec(struct rte_swx_pipeline *p)
3512 struct thread *t = &p->threads[p->thread_id];
3513 struct instruction *ip = t->ip;
3515 TRACE("[Thread %2u] sub (hm)\n", p->thread_id);
3525 instr_alu_sub_hh_exec(struct rte_swx_pipeline *p)
3527 struct thread *t = &p->threads[p->thread_id];
3528 struct instruction *ip = t->ip;
3530 TRACE("[Thread %2u] sub (hh)\n", p->thread_id);
3540 instr_alu_sub_mi_exec(struct rte_swx_pipeline *p)
3542 struct thread *t = &p->threads[p->thread_id];
3543 struct instruction *ip = t->ip;
3545 TRACE("[Thread %2u] sub (mi)\n", p->thread_id);
3555 instr_alu_sub_hi_exec(struct rte_swx_pipeline *p)
3557 struct thread *t = &p->threads[p->thread_id];
3558 struct instruction *ip = t->ip;
3560 TRACE("[Thread %2u] sub (hi)\n", p->thread_id);
3570 instr_alu_shl_exec(struct rte_swx_pipeline *p)
3572 struct thread *t = &p->threads[p->thread_id];
3573 struct instruction *ip = t->ip;
3575 TRACE("[Thread %2u] shl\n", p->thread_id);
3585 instr_alu_shl_mh_exec(struct rte_swx_pipeline *p)
3587 struct thread *t = &p->threads[p->thread_id];
3588 struct instruction *ip = t->ip;
3590 TRACE("[Thread %2u] shl (mh)\n", p->thread_id);
3600 instr_alu_shl_hm_exec(struct rte_swx_pipeline *p)
3602 struct thread *t = &p->threads[p->thread_id];
3603 struct instruction *ip = t->ip;
3605 TRACE("[Thread %2u] shl (hm)\n", p->thread_id);
3615 instr_alu_shl_hh_exec(struct rte_swx_pipeline *p)
3617 struct thread *t = &p->threads[p->thread_id];
3618 struct instruction *ip = t->ip;
3620 TRACE("[Thread %2u] shl (hh)\n", p->thread_id);
3630 instr_alu_shl_mi_exec(struct rte_swx_pipeline *p)
3632 struct thread *t = &p->threads[p->thread_id];
3633 struct instruction *ip = t->ip;
3635 TRACE("[Thread %2u] shl (mi)\n", p->thread_id);
3645 instr_alu_shl_hi_exec(struct rte_swx_pipeline *p)
3647 struct thread *t = &p->threads[p->thread_id];
3648 struct instruction *ip = t->ip;
3650 TRACE("[Thread %2u] shl (hi)\n", p->thread_id);
3660 instr_alu_shr_exec(struct rte_swx_pipeline *p)
3662 struct thread *t = &p->threads[p->thread_id];
3663 struct instruction *ip = t->ip;
3665 TRACE("[Thread %2u] shr\n", p->thread_id);
3675 instr_alu_shr_mh_exec(struct rte_swx_pipeline *p)
3677 struct thread *t = &p->threads[p->thread_id];
3678 struct instruction *ip = t->ip;
3680 TRACE("[Thread %2u] shr (mh)\n", p->thread_id);
3690 instr_alu_shr_hm_exec(struct rte_swx_pipeline *p)
3692 struct thread *t = &p->threads[p->thread_id];
3693 struct instruction *ip = t->ip;
3695 TRACE("[Thread %2u] shr (hm)\n", p->thread_id);
3705 instr_alu_shr_hh_exec(struct rte_swx_pipeline *p)
3707 struct thread *t = &p->threads[p->thread_id];
3708 struct instruction *ip = t->ip;
3710 TRACE("[Thread %2u] shr (hh)\n", p->thread_id);
3720 instr_alu_shr_mi_exec(struct rte_swx_pipeline *p)
3722 struct thread *t = &p->threads[p->thread_id];
3723 struct instruction *ip = t->ip;
3725 TRACE("[Thread %2u] shr (mi)\n", p->thread_id);
3735 instr_alu_shr_hi_exec(struct rte_swx_pipeline *p)
3737 struct thread *t = &p->threads[p->thread_id];
3738 struct instruction *ip = t->ip;
3740 TRACE("[Thread %2u] shr (hi)\n", p->thread_id);
3750 instr_alu_and_exec(struct rte_swx_pipeline *p)
3752 struct thread *t = &p->threads[p->thread_id];
3753 struct instruction *ip = t->ip;
3755 TRACE("[Thread %2u] and\n", p->thread_id);
3765 instr_alu_and_mh_exec(struct rte_swx_pipeline *p)
3767 struct thread *t = &p->threads[p->thread_id];
3768 struct instruction *ip = t->ip;
3770 TRACE("[Thread %2u] and (mh)\n", p->thread_id);
3780 instr_alu_and_hm_exec(struct rte_swx_pipeline *p)
3782 struct thread *t = &p->threads[p->thread_id];
3783 struct instruction *ip = t->ip;
3785 TRACE("[Thread %2u] and (hm)\n", p->thread_id);
3788 ALU_HM_FAST(t, ip, &);
3795 instr_alu_and_hh_exec(struct rte_swx_pipeline *p)
3797 struct thread *t = &p->threads[p->thread_id];
3798 struct instruction *ip = t->ip;
3800 TRACE("[Thread %2u] and (hh)\n", p->thread_id);
3803 ALU_HH_FAST(t, ip, &);
3810 instr_alu_and_i_exec(struct rte_swx_pipeline *p)
3812 struct thread *t = &p->threads[p->thread_id];
3813 struct instruction *ip = t->ip;
3815 TRACE("[Thread %2u] and (i)\n", p->thread_id);
3825 instr_alu_or_exec(struct rte_swx_pipeline *p)
3827 struct thread *t = &p->threads[p->thread_id];
3828 struct instruction *ip = t->ip;
3830 TRACE("[Thread %2u] or\n", p->thread_id);
3840 instr_alu_or_mh_exec(struct rte_swx_pipeline *p)
3842 struct thread *t = &p->threads[p->thread_id];
3843 struct instruction *ip = t->ip;
3845 TRACE("[Thread %2u] or (mh)\n", p->thread_id);
3855 instr_alu_or_hm_exec(struct rte_swx_pipeline *p)
3857 struct thread *t = &p->threads[p->thread_id];
3858 struct instruction *ip = t->ip;
3860 TRACE("[Thread %2u] or (hm)\n", p->thread_id);
3863 ALU_HM_FAST(t, ip, |);
3870 instr_alu_or_hh_exec(struct rte_swx_pipeline *p)
3872 struct thread *t = &p->threads[p->thread_id];
3873 struct instruction *ip = t->ip;
3875 TRACE("[Thread %2u] or (hh)\n", p->thread_id);
3878 ALU_HH_FAST(t, ip, |);
3885 instr_alu_or_i_exec(struct rte_swx_pipeline *p)
3887 struct thread *t = &p->threads[p->thread_id];
3888 struct instruction *ip = t->ip;
3890 TRACE("[Thread %2u] or (i)\n", p->thread_id);
3900 instr_alu_xor_exec(struct rte_swx_pipeline *p)
3902 struct thread *t = &p->threads[p->thread_id];
3903 struct instruction *ip = t->ip;
3905 TRACE("[Thread %2u] xor\n", p->thread_id);
3915 instr_alu_xor_mh_exec(struct rte_swx_pipeline *p)
3917 struct thread *t = &p->threads[p->thread_id];
3918 struct instruction *ip = t->ip;
3920 TRACE("[Thread %2u] xor (mh)\n", p->thread_id);
3930 instr_alu_xor_hm_exec(struct rte_swx_pipeline *p)
3932 struct thread *t = &p->threads[p->thread_id];
3933 struct instruction *ip = t->ip;
3935 TRACE("[Thread %2u] xor (hm)\n", p->thread_id);
3938 ALU_HM_FAST(t, ip, ^);
3945 instr_alu_xor_hh_exec(struct rte_swx_pipeline *p)
3947 struct thread *t = &p->threads[p->thread_id];
3948 struct instruction *ip = t->ip;
3950 TRACE("[Thread %2u] xor (hh)\n", p->thread_id);
3953 ALU_HH_FAST(t, ip, ^);
3960 instr_alu_xor_i_exec(struct rte_swx_pipeline *p)
3962 struct thread *t = &p->threads[p->thread_id];
3963 struct instruction *ip = t->ip;
3965 TRACE("[Thread %2u] xor (i)\n", p->thread_id);
3975 instr_alu_ckadd_field_exec(struct rte_swx_pipeline *p)
3977 struct thread *t = &p->threads[p->thread_id];
3978 struct instruction *ip = t->ip;
3979 uint8_t *dst_struct, *src_struct;
3980 uint16_t *dst16_ptr, dst;
3981 uint64_t *src64_ptr, src64, src64_mask, src;
3984 TRACE("[Thread %2u] ckadd (field)\n", p->thread_id);
3987 dst_struct = t->structs[ip->alu.dst.struct_id];
3988 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
3991 src_struct = t->structs[ip->alu.src.struct_id];
3992 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
3994 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
3995 src = src64 & src64_mask;
4000 /* The first input (r) is a 16-bit number. The second and the third
4001 * inputs are 32-bit numbers. In the worst case scenario, the sum of the
4002 * three numbers (output r) is a 34-bit number.
4004 r += (src >> 32) + (src & 0xFFFFFFFF);
4006 /* The first input is a 16-bit number. The second input is an 18-bit
4007 * number. In the worst case scenario, the sum of the two numbers is a
4010 r = (r & 0xFFFF) + (r >> 16);
4012 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
4013 * a 3-bit number (0 .. 7). Their sum is a 17-bit number (0 .. 0x10006).
4015 r = (r & 0xFFFF) + (r >> 16);
4017 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
4018 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
4019 * 0x10006), the output r is (0 .. 7). So no carry bit can be generated,
4020 * therefore the output r is always a 16-bit number.
4022 r = (r & 0xFFFF) + (r >> 16);
4027 *dst16_ptr = (uint16_t)r;
4034 instr_alu_cksub_field_exec(struct rte_swx_pipeline *p)
4036 struct thread *t = &p->threads[p->thread_id];
4037 struct instruction *ip = t->ip;
4038 uint8_t *dst_struct, *src_struct;
4039 uint16_t *dst16_ptr, dst;
4040 uint64_t *src64_ptr, src64, src64_mask, src;
4043 TRACE("[Thread %2u] cksub (field)\n", p->thread_id);
4046 dst_struct = t->structs[ip->alu.dst.struct_id];
4047 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
4050 src_struct = t->structs[ip->alu.src.struct_id];
4051 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
4053 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
4054 src = src64 & src64_mask;
4059 /* Subtraction in 1's complement arithmetic (i.e. a '- b) is the same as
4060 * the following sequence of operations in 2's complement arithmetic:
4061 * a '- b = (a - b) % 0xFFFF.
4063 * In order to prevent an underflow for the below subtraction, in which
4064 * a 33-bit number (the subtrahend) is taken out of a 16-bit number (the
4065 * minuend), we first add a multiple of the 0xFFFF modulus to the
4066 * minuend. The number we add to the minuend needs to be a 34-bit number
4067 * or higher, so for readability reasons we picked the 36-bit multiple.
4068 * We are effectively turning the 16-bit minuend into a 36-bit number:
4069 * (a - b) % 0xFFFF = (a + 0xFFFF00000 - b) % 0xFFFF.
4071 r += 0xFFFF00000ULL; /* The output r is a 36-bit number. */
4073 /* A 33-bit number is subtracted from a 36-bit number (the input r). The
4074 * result (the output r) is a 36-bit number.
4076 r -= (src >> 32) + (src & 0xFFFFFFFF);
4078 /* The first input is a 16-bit number. The second input is a 20-bit
4079 * number. Their sum is a 21-bit number.
4081 r = (r & 0xFFFF) + (r >> 16);
4083 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
4084 * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1001E).
4086 r = (r & 0xFFFF) + (r >> 16);
4088 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
4089 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
4090 * 0x1001E), the output r is (0 .. 31). So no carry bit can be
4091 * generated, therefore the output r is always a 16-bit number.
4093 r = (r & 0xFFFF) + (r >> 16);
4098 *dst16_ptr = (uint16_t)r;
4105 instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline *p)
4107 struct thread *t = &p->threads[p->thread_id];
4108 struct instruction *ip = t->ip;
4109 uint8_t *dst_struct, *src_struct;
4110 uint16_t *dst16_ptr;
4111 uint32_t *src32_ptr;
4114 TRACE("[Thread %2u] ckadd (struct of 20 bytes)\n", p->thread_id);
4117 dst_struct = t->structs[ip->alu.dst.struct_id];
4118 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
4120 src_struct = t->structs[ip->alu.src.struct_id];
4121 src32_ptr = (uint32_t *)&src_struct[0];
4123 r0 = src32_ptr[0]; /* r0 is a 32-bit number. */
4124 r1 = src32_ptr[1]; /* r1 is a 32-bit number. */
4125 r0 += src32_ptr[2]; /* The output r0 is a 33-bit number. */
4126 r1 += src32_ptr[3]; /* The output r1 is a 33-bit number. */
4127 r0 += r1 + src32_ptr[4]; /* The output r0 is a 35-bit number. */
4129 /* The first input is a 16-bit number. The second input is a 19-bit
4130 * number. Their sum is a 20-bit number.
4132 r0 = (r0 & 0xFFFF) + (r0 >> 16);
4134 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
4135 * a 4-bit number (0 .. 15). The sum is a 17-bit number (0 .. 0x1000E).
4137 r0 = (r0 & 0xFFFF) + (r0 >> 16);
4139 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
4140 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
4141 * 0x1000E), the output r is (0 .. 15). So no carry bit can be
4142 * generated, therefore the output r is always a 16-bit number.
4144 r0 = (r0 & 0xFFFF) + (r0 >> 16);
4147 r0 = r0 ? r0 : 0xFFFF;
4149 *dst16_ptr = (uint16_t)r0;
4156 instr_alu_ckadd_struct_exec(struct rte_swx_pipeline *p)
4158 struct thread *t = &p->threads[p->thread_id];
4159 struct instruction *ip = t->ip;
4160 uint8_t *dst_struct, *src_struct;
4161 uint16_t *dst16_ptr;
4162 uint32_t *src32_ptr;
4166 TRACE("[Thread %2u] ckadd (struct)\n", p->thread_id);
4169 dst_struct = t->structs[ip->alu.dst.struct_id];
4170 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
4172 src_struct = t->structs[ip->alu.src.struct_id];
4173 src32_ptr = (uint32_t *)&src_struct[0];
4175 /* The max number of 32-bit words in a 256-byte header is 8 = 2^3.
4176 * Therefore, in the worst case scenario, a 35-bit number is added to a
4177 * 16-bit number (the input r), so the output r is 36-bit number.
4179 for (i = 0; i < ip->alu.src.n_bits / 32; i++, src32_ptr++)
4182 /* The first input is a 16-bit number. The second input is a 20-bit
4183 * number. Their sum is a 21-bit number.
4185 r = (r & 0xFFFF) + (r >> 16);
4187 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
4188 * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1000E).
4190 r = (r & 0xFFFF) + (r >> 16);
4192 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
4193 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
4194 * 0x1001E), the output r is (0 .. 31). So no carry bit can be
4195 * generated, therefore the output r is always a 16-bit number.
4197 r = (r & 0xFFFF) + (r >> 16);
4202 *dst16_ptr = (uint16_t)r;
4211 static struct regarray *
4212 regarray_find(struct rte_swx_pipeline *p, const char *name);
4215 instr_regprefetch_translate(struct rte_swx_pipeline *p,
4216 struct action *action,
4219 struct instruction *instr,
4220 struct instruction_data *data __rte_unused)
4222 char *regarray = tokens[1], *idx = tokens[2];
4225 uint32_t idx_struct_id, idx_val;
4227 CHECK(n_tokens == 3, EINVAL);
4229 r = regarray_find(p, regarray);
4232 /* REGPREFETCH_RH, REGPREFETCH_RM. */
4233 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4235 CHECK(!fidx->var_size, EINVAL);
4237 instr->type = INSTR_REGPREFETCH_RM;
4239 instr->type = INSTR_REGPREFETCH_RH;
4241 instr->regarray.regarray_id = r->id;
4242 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4243 instr->regarray.idx.n_bits = fidx->n_bits;
4244 instr->regarray.idx.offset = fidx->offset / 8;
4245 instr->regarray.dstsrc_val = 0; /* Unused. */
4249 /* REGPREFETCH_RI. */
4250 idx_val = strtoul(idx, &idx, 0);
4251 CHECK(!idx[0], EINVAL);
4253 instr->type = INSTR_REGPREFETCH_RI;
4254 instr->regarray.regarray_id = r->id;
4255 instr->regarray.idx_val = idx_val;
4256 instr->regarray.dstsrc_val = 0; /* Unused. */
4261 instr_regrd_translate(struct rte_swx_pipeline *p,
4262 struct action *action,
4265 struct instruction *instr,
4266 struct instruction_data *data __rte_unused)
4268 char *dst = tokens[1], *regarray = tokens[2], *idx = tokens[3];
4270 struct field *fdst, *fidx;
4271 uint32_t dst_struct_id, idx_struct_id, idx_val;
4273 CHECK(n_tokens == 4, EINVAL);
4275 r = regarray_find(p, regarray);
4278 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4279 CHECK(fdst, EINVAL);
4280 CHECK(!fdst->var_size, EINVAL);
4282 /* REGRD_HRH, REGRD_HRM, REGRD_MRH, REGRD_MRM. */
4283 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4285 CHECK(!fidx->var_size, EINVAL);
4287 instr->type = INSTR_REGRD_MRM;
4288 if (dst[0] == 'h' && idx[0] != 'h')
4289 instr->type = INSTR_REGRD_HRM;
4290 if (dst[0] != 'h' && idx[0] == 'h')
4291 instr->type = INSTR_REGRD_MRH;
4292 if (dst[0] == 'h' && idx[0] == 'h')
4293 instr->type = INSTR_REGRD_HRH;
4295 instr->regarray.regarray_id = r->id;
4296 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4297 instr->regarray.idx.n_bits = fidx->n_bits;
4298 instr->regarray.idx.offset = fidx->offset / 8;
4299 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
4300 instr->regarray.dstsrc.n_bits = fdst->n_bits;
4301 instr->regarray.dstsrc.offset = fdst->offset / 8;
4305 /* REGRD_MRI, REGRD_HRI. */
4306 idx_val = strtoul(idx, &idx, 0);
4307 CHECK(!idx[0], EINVAL);
4309 instr->type = INSTR_REGRD_MRI;
4311 instr->type = INSTR_REGRD_HRI;
4313 instr->regarray.regarray_id = r->id;
4314 instr->regarray.idx_val = idx_val;
4315 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
4316 instr->regarray.dstsrc.n_bits = fdst->n_bits;
4317 instr->regarray.dstsrc.offset = fdst->offset / 8;
4322 instr_regwr_translate(struct rte_swx_pipeline *p,
4323 struct action *action,
4326 struct instruction *instr,
4327 struct instruction_data *data __rte_unused)
4329 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
4331 struct field *fidx, *fsrc;
4333 uint32_t idx_struct_id, idx_val, src_struct_id;
4335 CHECK(n_tokens == 4, EINVAL);
4337 r = regarray_find(p, regarray);
4340 /* REGWR_RHH, REGWR_RHM, REGWR_RMH, REGWR_RMM. */
4341 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4342 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4344 CHECK(!fidx->var_size, EINVAL);
4345 CHECK(!fsrc->var_size, EINVAL);
4347 instr->type = INSTR_REGWR_RMM;
4348 if (idx[0] == 'h' && src[0] != 'h')
4349 instr->type = INSTR_REGWR_RHM;
4350 if (idx[0] != 'h' && src[0] == 'h')
4351 instr->type = INSTR_REGWR_RMH;
4352 if (idx[0] == 'h' && src[0] == 'h')
4353 instr->type = INSTR_REGWR_RHH;
4355 instr->regarray.regarray_id = r->id;
4356 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4357 instr->regarray.idx.n_bits = fidx->n_bits;
4358 instr->regarray.idx.offset = fidx->offset / 8;
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;
4365 /* REGWR_RHI, REGWR_RMI. */
4366 if (fidx && !fsrc) {
4367 CHECK(!fidx->var_size, EINVAL);
4369 src_val = strtoull(src, &src, 0);
4370 CHECK(!src[0], EINVAL);
4372 instr->type = INSTR_REGWR_RMI;
4374 instr->type = INSTR_REGWR_RHI;
4376 instr->regarray.regarray_id = r->id;
4377 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4378 instr->regarray.idx.n_bits = fidx->n_bits;
4379 instr->regarray.idx.offset = fidx->offset / 8;
4380 instr->regarray.dstsrc_val = src_val;
4384 /* REGWR_RIH, REGWR_RIM. */
4385 if (!fidx && fsrc) {
4386 idx_val = strtoul(idx, &idx, 0);
4387 CHECK(!idx[0], EINVAL);
4389 CHECK(!fsrc->var_size, EINVAL);
4391 instr->type = INSTR_REGWR_RIM;
4393 instr->type = INSTR_REGWR_RIH;
4395 instr->regarray.regarray_id = r->id;
4396 instr->regarray.idx_val = idx_val;
4397 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4398 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4399 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4404 src_val = strtoull(src, &src, 0);
4405 CHECK(!src[0], EINVAL);
4407 idx_val = strtoul(idx, &idx, 0);
4408 CHECK(!idx[0], EINVAL);
4410 instr->type = INSTR_REGWR_RII;
4411 instr->regarray.idx_val = idx_val;
4412 instr->regarray.dstsrc_val = src_val;
4418 instr_regadd_translate(struct rte_swx_pipeline *p,
4419 struct action *action,
4422 struct instruction *instr,
4423 struct instruction_data *data __rte_unused)
4425 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
4427 struct field *fidx, *fsrc;
4429 uint32_t idx_struct_id, idx_val, src_struct_id;
4431 CHECK(n_tokens == 4, EINVAL);
4433 r = regarray_find(p, regarray);
4436 /* REGADD_RHH, REGADD_RHM, REGADD_RMH, REGADD_RMM. */
4437 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4438 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4440 CHECK(!fidx->var_size, EINVAL);
4441 CHECK(!fsrc->var_size, EINVAL);
4443 instr->type = INSTR_REGADD_RMM;
4444 if (idx[0] == 'h' && src[0] != 'h')
4445 instr->type = INSTR_REGADD_RHM;
4446 if (idx[0] != 'h' && src[0] == 'h')
4447 instr->type = INSTR_REGADD_RMH;
4448 if (idx[0] == 'h' && src[0] == 'h')
4449 instr->type = INSTR_REGADD_RHH;
4451 instr->regarray.regarray_id = r->id;
4452 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4453 instr->regarray.idx.n_bits = fidx->n_bits;
4454 instr->regarray.idx.offset = fidx->offset / 8;
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;
4461 /* REGADD_RHI, REGADD_RMI. */
4462 if (fidx && !fsrc) {
4463 CHECK(!fidx->var_size, EINVAL);
4465 src_val = strtoull(src, &src, 0);
4466 CHECK(!src[0], EINVAL);
4468 instr->type = INSTR_REGADD_RMI;
4470 instr->type = INSTR_REGADD_RHI;
4472 instr->regarray.regarray_id = r->id;
4473 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4474 instr->regarray.idx.n_bits = fidx->n_bits;
4475 instr->regarray.idx.offset = fidx->offset / 8;
4476 instr->regarray.dstsrc_val = src_val;
4480 /* REGADD_RIH, REGADD_RIM. */
4481 if (!fidx && fsrc) {
4482 idx_val = strtoul(idx, &idx, 0);
4483 CHECK(!idx[0], EINVAL);
4485 CHECK(!fsrc->var_size, EINVAL);
4487 instr->type = INSTR_REGADD_RIM;
4489 instr->type = INSTR_REGADD_RIH;
4491 instr->regarray.regarray_id = r->id;
4492 instr->regarray.idx_val = idx_val;
4493 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4494 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4495 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4500 src_val = strtoull(src, &src, 0);
4501 CHECK(!src[0], EINVAL);
4503 idx_val = strtoul(idx, &idx, 0);
4504 CHECK(!idx[0], EINVAL);
4506 instr->type = INSTR_REGADD_RII;
4507 instr->regarray.idx_val = idx_val;
4508 instr->regarray.dstsrc_val = src_val;
4512 static inline uint64_t *
4513 instr_regarray_regarray(struct rte_swx_pipeline *p, struct instruction *ip)
4515 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4519 static inline uint64_t
4520 instr_regarray_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
4522 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4524 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
4525 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
4526 uint64_t idx64 = *idx64_ptr;
4527 uint64_t idx64_mask = UINT64_MAX >> (64 - ip->regarray.idx.n_bits);
4528 uint64_t idx = idx64 & idx64_mask & r->size_mask;
4533 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4535 static inline uint64_t
4536 instr_regarray_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
4538 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4540 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
4541 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
4542 uint64_t idx64 = *idx64_ptr;
4543 uint64_t idx = (ntoh64(idx64) >> (64 - ip->regarray.idx.n_bits)) & r->size_mask;
4550 #define instr_regarray_idx_nbo instr_regarray_idx_hbo
4554 static inline uint64_t
4555 instr_regarray_idx_imm(struct rte_swx_pipeline *p, struct instruction *ip)
4557 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
4559 uint64_t idx = ip->regarray.idx_val & r->size_mask;
4564 static inline uint64_t
4565 instr_regarray_src_hbo(struct thread *t, struct instruction *ip)
4567 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
4568 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
4569 uint64_t src64 = *src64_ptr;
4570 uint64_t src64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
4571 uint64_t src = src64 & src64_mask;
4576 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4578 static inline uint64_t
4579 instr_regarray_src_nbo(struct thread *t, struct instruction *ip)
4581 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
4582 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
4583 uint64_t src64 = *src64_ptr;
4584 uint64_t src = ntoh64(src64) >> (64 - ip->regarray.dstsrc.n_bits);
4591 #define instr_regarray_src_nbo instr_regarray_src_hbo
4596 instr_regarray_dst_hbo_src_hbo_set(struct thread *t, struct instruction *ip, uint64_t src)
4598 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
4599 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
4600 uint64_t dst64 = *dst64_ptr;
4601 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
4603 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
4607 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4610 instr_regarray_dst_nbo_src_hbo_set(struct thread *t, struct instruction *ip, uint64_t src)
4612 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
4613 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
4614 uint64_t dst64 = *dst64_ptr;
4615 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
4617 src = hton64(src) >> (64 - ip->regarray.dstsrc.n_bits);
4618 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
4623 #define instr_regarray_dst_nbo_src_hbo_set instr_regarray_dst_hbo_src_hbo_set
4628 instr_regprefetch_rh_exec(struct rte_swx_pipeline *p)
4630 struct thread *t = &p->threads[p->thread_id];
4631 struct instruction *ip = t->ip;
4632 uint64_t *regarray, idx;
4634 TRACE("[Thread %2u] regprefetch (r[h])\n", p->thread_id);
4637 regarray = instr_regarray_regarray(p, ip);
4638 idx = instr_regarray_idx_nbo(p, t, ip);
4639 rte_prefetch0(®array[idx]);
4646 instr_regprefetch_rm_exec(struct rte_swx_pipeline *p)
4648 struct thread *t = &p->threads[p->thread_id];
4649 struct instruction *ip = t->ip;
4650 uint64_t *regarray, idx;
4652 TRACE("[Thread %2u] regprefetch (r[m])\n", p->thread_id);
4655 regarray = instr_regarray_regarray(p, ip);
4656 idx = instr_regarray_idx_hbo(p, t, ip);
4657 rte_prefetch0(®array[idx]);
4664 instr_regprefetch_ri_exec(struct rte_swx_pipeline *p)
4666 struct thread *t = &p->threads[p->thread_id];
4667 struct instruction *ip = t->ip;
4668 uint64_t *regarray, idx;
4670 TRACE("[Thread %2u] regprefetch (r[i])\n", p->thread_id);
4673 regarray = instr_regarray_regarray(p, ip);
4674 idx = instr_regarray_idx_imm(p, ip);
4675 rte_prefetch0(®array[idx]);
4682 instr_regrd_hrh_exec(struct rte_swx_pipeline *p)
4684 struct thread *t = &p->threads[p->thread_id];
4685 struct instruction *ip = t->ip;
4686 uint64_t *regarray, idx;
4688 TRACE("[Thread %2u] regrd (h = r[h])\n", p->thread_id);
4691 regarray = instr_regarray_regarray(p, ip);
4692 idx = instr_regarray_idx_nbo(p, t, ip);
4693 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
4700 instr_regrd_hrm_exec(struct rte_swx_pipeline *p)
4702 struct thread *t = &p->threads[p->thread_id];
4703 struct instruction *ip = t->ip;
4704 uint64_t *regarray, idx;
4706 TRACE("[Thread %2u] regrd (h = r[m])\n", p->thread_id);
4709 regarray = instr_regarray_regarray(p, ip);
4710 idx = instr_regarray_idx_hbo(p, t, ip);
4711 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
4718 instr_regrd_mrh_exec(struct rte_swx_pipeline *p)
4720 struct thread *t = &p->threads[p->thread_id];
4721 struct instruction *ip = t->ip;
4722 uint64_t *regarray, idx;
4724 TRACE("[Thread %2u] regrd (m = r[h])\n", p->thread_id);
4727 regarray = instr_regarray_regarray(p, ip);
4728 idx = instr_regarray_idx_nbo(p, t, ip);
4729 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
4736 instr_regrd_mrm_exec(struct rte_swx_pipeline *p)
4738 struct thread *t = &p->threads[p->thread_id];
4739 struct instruction *ip = t->ip;
4740 uint64_t *regarray, idx;
4743 regarray = instr_regarray_regarray(p, ip);
4744 idx = instr_regarray_idx_hbo(p, t, ip);
4745 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
4752 instr_regrd_hri_exec(struct rte_swx_pipeline *p)
4754 struct thread *t = &p->threads[p->thread_id];
4755 struct instruction *ip = t->ip;
4756 uint64_t *regarray, idx;
4758 TRACE("[Thread %2u] regrd (h = r[i])\n", p->thread_id);
4761 regarray = instr_regarray_regarray(p, ip);
4762 idx = instr_regarray_idx_imm(p, ip);
4763 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
4770 instr_regrd_mri_exec(struct rte_swx_pipeline *p)
4772 struct thread *t = &p->threads[p->thread_id];
4773 struct instruction *ip = t->ip;
4774 uint64_t *regarray, idx;
4776 TRACE("[Thread %2u] regrd (m = r[i])\n", p->thread_id);
4779 regarray = instr_regarray_regarray(p, ip);
4780 idx = instr_regarray_idx_imm(p, ip);
4781 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
4788 instr_regwr_rhh_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[h] = h)\n", p->thread_id);
4797 regarray = instr_regarray_regarray(p, ip);
4798 idx = instr_regarray_idx_nbo(p, t, ip);
4799 src = instr_regarray_src_nbo(t, ip);
4800 regarray[idx] = src;
4807 instr_regwr_rhm_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[h] = m)\n", p->thread_id);
4816 regarray = instr_regarray_regarray(p, ip);
4817 idx = instr_regarray_idx_nbo(p, t, ip);
4818 src = instr_regarray_src_hbo(t, ip);
4819 regarray[idx] = src;
4826 instr_regwr_rmh_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[m] = h)\n", p->thread_id);
4835 regarray = instr_regarray_regarray(p, ip);
4836 idx = instr_regarray_idx_hbo(p, t, ip);
4837 src = instr_regarray_src_nbo(t, ip);
4838 regarray[idx] = src;
4845 instr_regwr_rmm_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] = m)\n", p->thread_id);
4854 regarray = instr_regarray_regarray(p, ip);
4855 idx = instr_regarray_idx_hbo(p, t, ip);
4856 src = instr_regarray_src_hbo(t, ip);
4857 regarray[idx] = src;
4864 instr_regwr_rhi_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[h] = i)\n", p->thread_id);
4873 regarray = instr_regarray_regarray(p, ip);
4874 idx = instr_regarray_idx_nbo(p, t, ip);
4875 src = ip->regarray.dstsrc_val;
4876 regarray[idx] = src;
4883 instr_regwr_rmi_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[m] = i)\n", p->thread_id);
4892 regarray = instr_regarray_regarray(p, ip);
4893 idx = instr_regarray_idx_hbo(p, t, ip);
4894 src = ip->regarray.dstsrc_val;
4895 regarray[idx] = src;
4902 instr_regwr_rih_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] = h)\n", p->thread_id);
4911 regarray = instr_regarray_regarray(p, ip);
4912 idx = instr_regarray_idx_imm(p, ip);
4913 src = instr_regarray_src_nbo(t, ip);
4914 regarray[idx] = src;
4921 instr_regwr_rim_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] regwr (r[i] = m)\n", p->thread_id);
4930 regarray = instr_regarray_regarray(p, ip);
4931 idx = instr_regarray_idx_imm(p, ip);
4932 src = instr_regarray_src_hbo(t, ip);
4933 regarray[idx] = src;
4940 instr_regwr_rii_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] regwr (r[i] = i)\n", p->thread_id);
4949 regarray = instr_regarray_regarray(p, ip);
4950 idx = instr_regarray_idx_imm(p, ip);
4951 src = ip->regarray.dstsrc_val;
4952 regarray[idx] = src;
4959 instr_regadd_rhh_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[h] += h)\n", p->thread_id);
4968 regarray = instr_regarray_regarray(p, ip);
4969 idx = instr_regarray_idx_nbo(p, t, ip);
4970 src = instr_regarray_src_nbo(t, ip);
4971 regarray[idx] += src;
4978 instr_regadd_rhm_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[h] += m)\n", p->thread_id);
4987 regarray = instr_regarray_regarray(p, ip);
4988 idx = instr_regarray_idx_nbo(p, t, ip);
4989 src = instr_regarray_src_hbo(t, ip);
4990 regarray[idx] += src;
4997 instr_regadd_rmh_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[m] += h)\n", p->thread_id);
5006 regarray = instr_regarray_regarray(p, ip);
5007 idx = instr_regarray_idx_hbo(p, t, ip);
5008 src = instr_regarray_src_nbo(t, ip);
5009 regarray[idx] += src;
5016 instr_regadd_rmm_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] += m)\n", p->thread_id);
5025 regarray = instr_regarray_regarray(p, ip);
5026 idx = instr_regarray_idx_hbo(p, t, ip);
5027 src = instr_regarray_src_hbo(t, ip);
5028 regarray[idx] += src;
5035 instr_regadd_rhi_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[h] += i)\n", p->thread_id);
5044 regarray = instr_regarray_regarray(p, ip);
5045 idx = instr_regarray_idx_nbo(p, t, ip);
5046 src = ip->regarray.dstsrc_val;
5047 regarray[idx] += src;
5054 instr_regadd_rmi_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[m] += i)\n", p->thread_id);
5063 regarray = instr_regarray_regarray(p, ip);
5064 idx = instr_regarray_idx_hbo(p, t, ip);
5065 src = ip->regarray.dstsrc_val;
5066 regarray[idx] += src;
5073 instr_regadd_rih_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] += h)\n", p->thread_id);
5082 regarray = instr_regarray_regarray(p, ip);
5083 idx = instr_regarray_idx_imm(p, ip);
5084 src = instr_regarray_src_nbo(t, ip);
5085 regarray[idx] += src;
5092 instr_regadd_rim_exec(struct rte_swx_pipeline *p)
5094 struct thread *t = &p->threads[p->thread_id];
5095 struct instruction *ip = t->ip;
5096 uint64_t *regarray, idx, src;
5098 TRACE("[Thread %2u] regadd (r[i] += m)\n", p->thread_id);
5101 regarray = instr_regarray_regarray(p, ip);
5102 idx = instr_regarray_idx_imm(p, ip);
5103 src = instr_regarray_src_hbo(t, ip);
5104 regarray[idx] += src;
5111 instr_regadd_rii_exec(struct rte_swx_pipeline *p)
5113 struct thread *t = &p->threads[p->thread_id];
5114 struct instruction *ip = t->ip;
5115 uint64_t *regarray, idx, src;
5117 TRACE("[Thread %2u] regadd (r[i] += i)\n", p->thread_id);
5120 regarray = instr_regarray_regarray(p, ip);
5121 idx = instr_regarray_idx_imm(p, ip);
5122 src = ip->regarray.dstsrc_val;
5123 regarray[idx] += src;
5132 static struct metarray *
5133 metarray_find(struct rte_swx_pipeline *p, const char *name);
5136 instr_metprefetch_translate(struct rte_swx_pipeline *p,
5137 struct action *action,
5140 struct instruction *instr,
5141 struct instruction_data *data __rte_unused)
5143 char *metarray = tokens[1], *idx = tokens[2];
5146 uint32_t idx_struct_id, idx_val;
5148 CHECK(n_tokens == 3, EINVAL);
5150 m = metarray_find(p, metarray);
5153 /* METPREFETCH_H, METPREFETCH_M. */
5154 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
5156 CHECK(!fidx->var_size, EINVAL);
5158 instr->type = INSTR_METPREFETCH_M;
5160 instr->type = INSTR_METPREFETCH_H;
5162 instr->meter.metarray_id = m->id;
5163 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
5164 instr->meter.idx.n_bits = fidx->n_bits;
5165 instr->meter.idx.offset = fidx->offset / 8;
5169 /* METPREFETCH_I. */
5170 idx_val = strtoul(idx, &idx, 0);
5171 CHECK(!idx[0], EINVAL);
5173 instr->type = INSTR_METPREFETCH_I;
5174 instr->meter.metarray_id = m->id;
5175 instr->meter.idx_val = idx_val;
5180 instr_meter_translate(struct rte_swx_pipeline *p,
5181 struct action *action,
5184 struct instruction *instr,
5185 struct instruction_data *data __rte_unused)
5187 char *metarray = tokens[1], *idx = tokens[2], *length = tokens[3];
5188 char *color_in = tokens[4], *color_out = tokens[5];
5190 struct field *fidx, *flength, *fcin, *fcout;
5191 uint32_t idx_struct_id, length_struct_id;
5192 uint32_t color_in_struct_id, color_out_struct_id;
5194 CHECK(n_tokens == 6, EINVAL);
5196 m = metarray_find(p, metarray);
5199 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
5201 flength = struct_field_parse(p, action, length, &length_struct_id);
5202 CHECK(flength, EINVAL);
5203 CHECK(!flength->var_size, EINVAL);
5205 fcin = struct_field_parse(p, action, color_in, &color_in_struct_id);
5207 fcout = struct_field_parse(p, NULL, color_out, &color_out_struct_id);
5208 CHECK(fcout, EINVAL);
5209 CHECK(!fcout->var_size, EINVAL);
5211 /* index = HMEFT, length = HMEFT, color_in = MEFT, color_out = MEF. */
5213 CHECK(!fidx->var_size, EINVAL);
5214 CHECK(!fcin->var_size, EINVAL);
5216 instr->type = INSTR_METER_MMM;
5217 if (idx[0] == 'h' && length[0] == 'h')
5218 instr->type = INSTR_METER_HHM;
5219 if (idx[0] == 'h' && length[0] != 'h')
5220 instr->type = INSTR_METER_HMM;
5221 if (idx[0] != 'h' && length[0] == 'h')
5222 instr->type = INSTR_METER_MHM;
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.struct_id = (uint8_t)color_in_struct_id;
5235 instr->meter.color_in.n_bits = fcin->n_bits;
5236 instr->meter.color_in.offset = fcin->offset / 8;
5238 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5239 instr->meter.color_out.n_bits = fcout->n_bits;
5240 instr->meter.color_out.offset = fcout->offset / 8;
5245 /* index = HMEFT, length = HMEFT, color_in = I, color_out = MEF. */
5246 if (fidx && !fcin) {
5247 uint32_t color_in_val;
5249 CHECK(!fidx->var_size, EINVAL);
5251 color_in_val = strtoul(color_in, &color_in, 0);
5252 CHECK(!color_in[0], EINVAL);
5254 instr->type = INSTR_METER_MMI;
5255 if (idx[0] == 'h' && length[0] == 'h')
5256 instr->type = INSTR_METER_HHI;
5257 if (idx[0] == 'h' && length[0] != 'h')
5258 instr->type = INSTR_METER_HMI;
5259 if (idx[0] != 'h' && length[0] == 'h')
5260 instr->type = INSTR_METER_MHI;
5262 instr->meter.metarray_id = m->id;
5264 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
5265 instr->meter.idx.n_bits = fidx->n_bits;
5266 instr->meter.idx.offset = fidx->offset / 8;
5268 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5269 instr->meter.length.n_bits = flength->n_bits;
5270 instr->meter.length.offset = flength->offset / 8;
5272 instr->meter.color_in_val = color_in_val;
5274 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5275 instr->meter.color_out.n_bits = fcout->n_bits;
5276 instr->meter.color_out.offset = fcout->offset / 8;
5281 /* index = I, length = HMEFT, color_in = MEFT, color_out = MEF. */
5282 if (!fidx && fcin) {
5285 idx_val = strtoul(idx, &idx, 0);
5286 CHECK(!idx[0], EINVAL);
5288 CHECK(!fcin->var_size, EINVAL);
5290 instr->type = INSTR_METER_IMM;
5291 if (length[0] == 'h')
5292 instr->type = INSTR_METER_IHM;
5294 instr->meter.metarray_id = m->id;
5296 instr->meter.idx_val = idx_val;
5298 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5299 instr->meter.length.n_bits = flength->n_bits;
5300 instr->meter.length.offset = flength->offset / 8;
5302 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
5303 instr->meter.color_in.n_bits = fcin->n_bits;
5304 instr->meter.color_in.offset = fcin->offset / 8;
5306 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5307 instr->meter.color_out.n_bits = fcout->n_bits;
5308 instr->meter.color_out.offset = fcout->offset / 8;
5313 /* index = I, length = HMEFT, color_in = I, color_out = MEF. */
5314 if (!fidx && !fcin) {
5315 uint32_t idx_val, color_in_val;
5317 idx_val = strtoul(idx, &idx, 0);
5318 CHECK(!idx[0], EINVAL);
5320 color_in_val = strtoul(color_in, &color_in, 0);
5321 CHECK(!color_in[0], EINVAL);
5323 instr->type = INSTR_METER_IMI;
5324 if (length[0] == 'h')
5325 instr->type = INSTR_METER_IHI;
5327 instr->meter.metarray_id = m->id;
5329 instr->meter.idx_val = idx_val;
5331 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5332 instr->meter.length.n_bits = flength->n_bits;
5333 instr->meter.length.offset = flength->offset / 8;
5335 instr->meter.color_in_val = color_in_val;
5337 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5338 instr->meter.color_out.n_bits = fcout->n_bits;
5339 instr->meter.color_out.offset = fcout->offset / 8;
5347 static inline struct meter *
5348 instr_meter_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
5350 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
5352 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
5353 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
5354 uint64_t idx64 = *idx64_ptr;
5355 uint64_t idx64_mask = UINT64_MAX >> (64 - (ip)->meter.idx.n_bits);
5356 uint64_t idx = idx64 & idx64_mask & r->size_mask;
5358 return &r->metarray[idx];
5361 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5363 static inline struct meter *
5364 instr_meter_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
5366 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
5368 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
5369 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
5370 uint64_t idx64 = *idx64_ptr;
5371 uint64_t idx = (ntoh64(idx64) >> (64 - ip->meter.idx.n_bits)) & r->size_mask;
5373 return &r->metarray[idx];
5378 #define instr_meter_idx_nbo instr_meter_idx_hbo
5382 static inline struct meter *
5383 instr_meter_idx_imm(struct rte_swx_pipeline *p, struct instruction *ip)
5385 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
5387 uint64_t idx = ip->meter.idx_val & r->size_mask;
5389 return &r->metarray[idx];
5392 static inline uint32_t
5393 instr_meter_length_hbo(struct thread *t, struct instruction *ip)
5395 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
5396 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
5397 uint64_t src64 = *src64_ptr;
5398 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->meter.length.n_bits);
5399 uint64_t src = src64 & src64_mask;
5401 return (uint32_t)src;
5404 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5406 static inline uint32_t
5407 instr_meter_length_nbo(struct thread *t, struct instruction *ip)
5409 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
5410 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
5411 uint64_t src64 = *src64_ptr;
5412 uint64_t src = ntoh64(src64) >> (64 - ip->meter.length.n_bits);
5414 return (uint32_t)src;
5419 #define instr_meter_length_nbo instr_meter_length_hbo
5423 static inline enum rte_color
5424 instr_meter_color_in_hbo(struct thread *t, struct instruction *ip)
5426 uint8_t *src_struct = t->structs[ip->meter.color_in.struct_id];
5427 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.color_in.offset];
5428 uint64_t src64 = *src64_ptr;
5429 uint64_t src64_mask = UINT64_MAX >> (64 - ip->meter.color_in.n_bits);
5430 uint64_t src = src64 & src64_mask;
5432 return (enum rte_color)src;
5436 instr_meter_color_out_hbo_set(struct thread *t, struct instruction *ip, enum rte_color color_out)
5438 uint8_t *dst_struct = t->structs[ip->meter.color_out.struct_id];
5439 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->meter.color_out.offset];
5440 uint64_t dst64 = *dst64_ptr;
5441 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->meter.color_out.n_bits);
5443 uint64_t src = (uint64_t)color_out;
5445 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
5449 instr_metprefetch_h_exec(struct rte_swx_pipeline *p)
5451 struct thread *t = &p->threads[p->thread_id];
5452 struct instruction *ip = t->ip;
5455 TRACE("[Thread %2u] metprefetch (h)\n", p->thread_id);
5458 m = instr_meter_idx_nbo(p, t, ip);
5466 instr_metprefetch_m_exec(struct rte_swx_pipeline *p)
5468 struct thread *t = &p->threads[p->thread_id];
5469 struct instruction *ip = t->ip;
5472 TRACE("[Thread %2u] metprefetch (m)\n", p->thread_id);
5475 m = instr_meter_idx_hbo(p, t, ip);
5483 instr_metprefetch_i_exec(struct rte_swx_pipeline *p)
5485 struct thread *t = &p->threads[p->thread_id];
5486 struct instruction *ip = t->ip;
5489 TRACE("[Thread %2u] metprefetch (i)\n", p->thread_id);
5492 m = instr_meter_idx_imm(p, ip);
5500 instr_meter_hhm_exec(struct rte_swx_pipeline *p)
5502 struct thread *t = &p->threads[p->thread_id];
5503 struct instruction *ip = t->ip;
5505 uint64_t time, n_pkts, n_bytes;
5507 enum rte_color color_in, color_out;
5509 TRACE("[Thread %2u] meter (hhm)\n", p->thread_id);
5512 m = instr_meter_idx_nbo(p, t, ip);
5513 rte_prefetch0(m->n_pkts);
5514 time = rte_get_tsc_cycles();
5515 length = instr_meter_length_nbo(t, ip);
5516 color_in = instr_meter_color_in_hbo(t, ip);
5518 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5519 &m->profile->profile,
5524 color_out &= m->color_mask;
5526 n_pkts = m->n_pkts[color_out];
5527 n_bytes = m->n_bytes[color_out];
5529 instr_meter_color_out_hbo_set(t, ip, color_out);
5531 m->n_pkts[color_out] = n_pkts + 1;
5532 m->n_bytes[color_out] = n_bytes + length;
5539 instr_meter_hhi_exec(struct rte_swx_pipeline *p)
5541 struct thread *t = &p->threads[p->thread_id];
5542 struct instruction *ip = t->ip;
5544 uint64_t time, n_pkts, n_bytes;
5546 enum rte_color color_in, color_out;
5548 TRACE("[Thread %2u] meter (hhi)\n", p->thread_id);
5551 m = instr_meter_idx_nbo(p, t, ip);
5552 rte_prefetch0(m->n_pkts);
5553 time = rte_get_tsc_cycles();
5554 length = instr_meter_length_nbo(t, ip);
5555 color_in = (enum rte_color)ip->meter.color_in_val;
5557 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5558 &m->profile->profile,
5563 color_out &= m->color_mask;
5565 n_pkts = m->n_pkts[color_out];
5566 n_bytes = m->n_bytes[color_out];
5568 instr_meter_color_out_hbo_set(t, ip, color_out);
5570 m->n_pkts[color_out] = n_pkts + 1;
5571 m->n_bytes[color_out] = n_bytes + length;
5578 instr_meter_hmm_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 (hmm)\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 = instr_meter_color_in_hbo(t, ip);
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;
5616 instr_meter_hmi_exec(struct rte_swx_pipeline *p)
5618 struct thread *t = &p->threads[p->thread_id];
5619 struct instruction *ip = t->ip;
5621 uint64_t time, n_pkts, n_bytes;
5623 enum rte_color color_in, color_out;
5625 TRACE("[Thread %2u] meter (hmi)\n", p->thread_id);
5628 m = instr_meter_idx_nbo(p, t, ip);
5629 rte_prefetch0(m->n_pkts);
5630 time = rte_get_tsc_cycles();
5631 length = instr_meter_length_hbo(t, ip);
5632 color_in = (enum rte_color)ip->meter.color_in_val;
5634 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5635 &m->profile->profile,
5640 color_out &= m->color_mask;
5642 n_pkts = m->n_pkts[color_out];
5643 n_bytes = m->n_bytes[color_out];
5645 instr_meter_color_out_hbo_set(t, ip, color_out);
5647 m->n_pkts[color_out] = n_pkts + 1;
5648 m->n_bytes[color_out] = n_bytes + length;
5655 instr_meter_mhm_exec(struct rte_swx_pipeline *p)
5657 struct thread *t = &p->threads[p->thread_id];
5658 struct instruction *ip = t->ip;
5660 uint64_t time, n_pkts, n_bytes;
5662 enum rte_color color_in, color_out;
5664 TRACE("[Thread %2u] meter (mhm)\n", p->thread_id);
5667 m = instr_meter_idx_hbo(p, t, ip);
5668 rte_prefetch0(m->n_pkts);
5669 time = rte_get_tsc_cycles();
5670 length = instr_meter_length_nbo(t, ip);
5671 color_in = instr_meter_color_in_hbo(t, ip);
5673 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5674 &m->profile->profile,
5679 color_out &= m->color_mask;
5681 n_pkts = m->n_pkts[color_out];
5682 n_bytes = m->n_bytes[color_out];
5684 instr_meter_color_out_hbo_set(t, ip, color_out);
5686 m->n_pkts[color_out] = n_pkts + 1;
5687 m->n_bytes[color_out] = n_bytes + length;
5694 instr_meter_mhi_exec(struct rte_swx_pipeline *p)
5696 struct thread *t = &p->threads[p->thread_id];
5697 struct instruction *ip = t->ip;
5699 uint64_t time, n_pkts, n_bytes;
5701 enum rte_color color_in, color_out;
5703 TRACE("[Thread %2u] meter (mhi)\n", p->thread_id);
5706 m = instr_meter_idx_hbo(p, t, ip);
5707 rte_prefetch0(m->n_pkts);
5708 time = rte_get_tsc_cycles();
5709 length = instr_meter_length_nbo(t, ip);
5710 color_in = (enum rte_color)ip->meter.color_in_val;
5712 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5713 &m->profile->profile,
5718 color_out &= m->color_mask;
5720 n_pkts = m->n_pkts[color_out];
5721 n_bytes = m->n_bytes[color_out];
5723 instr_meter_color_out_hbo_set(t, ip, color_out);
5725 m->n_pkts[color_out] = n_pkts + 1;
5726 m->n_bytes[color_out] = n_bytes + length;
5733 instr_meter_mmm_exec(struct rte_swx_pipeline *p)
5735 struct thread *t = &p->threads[p->thread_id];
5736 struct instruction *ip = t->ip;
5738 uint64_t time, n_pkts, n_bytes;
5740 enum rte_color color_in, color_out;
5742 TRACE("[Thread %2u] meter (mmm)\n", p->thread_id);
5745 m = instr_meter_idx_hbo(p, t, ip);
5746 rte_prefetch0(m->n_pkts);
5747 time = rte_get_tsc_cycles();
5748 length = instr_meter_length_hbo(t, ip);
5749 color_in = instr_meter_color_in_hbo(t, ip);
5751 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5752 &m->profile->profile,
5757 color_out &= m->color_mask;
5759 n_pkts = m->n_pkts[color_out];
5760 n_bytes = m->n_bytes[color_out];
5762 instr_meter_color_out_hbo_set(t, ip, color_out);
5764 m->n_pkts[color_out] = n_pkts + 1;
5765 m->n_bytes[color_out] = n_bytes + length;
5772 instr_meter_mmi_exec(struct rte_swx_pipeline *p)
5774 struct thread *t = &p->threads[p->thread_id];
5775 struct instruction *ip = t->ip;
5777 uint64_t time, n_pkts, n_bytes;
5779 enum rte_color color_in, color_out;
5781 TRACE("[Thread %2u] meter (mmi)\n", p->thread_id);
5784 m = instr_meter_idx_hbo(p, t, ip);
5785 rte_prefetch0(m->n_pkts);
5786 time = rte_get_tsc_cycles();
5787 length = instr_meter_length_hbo(t, ip);
5788 color_in = (enum rte_color)ip->meter.color_in_val;
5790 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5791 &m->profile->profile,
5796 color_out &= m->color_mask;
5798 n_pkts = m->n_pkts[color_out];
5799 n_bytes = m->n_bytes[color_out];
5801 instr_meter_color_out_hbo_set(t, ip, color_out);
5803 m->n_pkts[color_out] = n_pkts + 1;
5804 m->n_bytes[color_out] = n_bytes + length;
5811 instr_meter_ihm_exec(struct rte_swx_pipeline *p)
5813 struct thread *t = &p->threads[p->thread_id];
5814 struct instruction *ip = t->ip;
5816 uint64_t time, n_pkts, n_bytes;
5818 enum rte_color color_in, color_out;
5820 TRACE("[Thread %2u] meter (ihm)\n", p->thread_id);
5823 m = instr_meter_idx_imm(p, ip);
5824 rte_prefetch0(m->n_pkts);
5825 time = rte_get_tsc_cycles();
5826 length = instr_meter_length_nbo(t, ip);
5827 color_in = instr_meter_color_in_hbo(t, ip);
5829 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5830 &m->profile->profile,
5835 color_out &= m->color_mask;
5837 n_pkts = m->n_pkts[color_out];
5838 n_bytes = m->n_bytes[color_out];
5840 instr_meter_color_out_hbo_set(t, ip, color_out);
5842 m->n_pkts[color_out] = n_pkts + 1;
5843 m->n_bytes[color_out] = n_bytes + length;
5850 instr_meter_ihi_exec(struct rte_swx_pipeline *p)
5852 struct thread *t = &p->threads[p->thread_id];
5853 struct instruction *ip = t->ip;
5855 uint64_t time, n_pkts, n_bytes;
5857 enum rte_color color_in, color_out;
5859 TRACE("[Thread %2u] meter (ihi)\n", p->thread_id);
5862 m = instr_meter_idx_imm(p, ip);
5863 rte_prefetch0(m->n_pkts);
5864 time = rte_get_tsc_cycles();
5865 length = instr_meter_length_nbo(t, ip);
5866 color_in = (enum rte_color)ip->meter.color_in_val;
5868 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5869 &m->profile->profile,
5874 color_out &= m->color_mask;
5876 n_pkts = m->n_pkts[color_out];
5877 n_bytes = m->n_bytes[color_out];
5879 instr_meter_color_out_hbo_set(t, ip, color_out);
5881 m->n_pkts[color_out] = n_pkts + 1;
5882 m->n_bytes[color_out] = n_bytes + length;
5889 instr_meter_imm_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 (imm)\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 = instr_meter_color_in_hbo(t, ip);
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;
5927 instr_meter_imi_exec(struct rte_swx_pipeline *p)
5929 struct thread *t = &p->threads[p->thread_id];
5930 struct instruction *ip = t->ip;
5932 uint64_t time, n_pkts, n_bytes;
5934 enum rte_color color_in, color_out;
5936 TRACE("[Thread %2u] meter (imi)\n", p->thread_id);
5939 m = instr_meter_idx_imm(p, ip);
5940 rte_prefetch0(m->n_pkts);
5941 time = rte_get_tsc_cycles();
5942 length = instr_meter_length_hbo(t, ip);
5943 color_in = (enum rte_color)ip->meter.color_in_val;
5945 color_out = rte_meter_trtcm_color_aware_check(&m->m,
5946 &m->profile->profile,
5951 color_out &= m->color_mask;
5953 n_pkts = m->n_pkts[color_out];
5954 n_bytes = m->n_bytes[color_out];
5956 instr_meter_color_out_hbo_set(t, ip, color_out);
5958 m->n_pkts[color_out] = n_pkts + 1;
5959 m->n_bytes[color_out] = n_bytes + length;
5969 instr_jmp_translate(struct rte_swx_pipeline *p __rte_unused,
5970 struct action *action __rte_unused,
5973 struct instruction *instr,
5974 struct instruction_data *data)
5976 CHECK(n_tokens == 2, EINVAL);
5978 strcpy(data->jmp_label, tokens[1]);
5980 instr->type = INSTR_JMP;
5981 instr->jmp.ip = NULL; /* Resolved later. */
5986 instr_jmp_valid_translate(struct rte_swx_pipeline *p,
5987 struct action *action __rte_unused,
5990 struct instruction *instr,
5991 struct instruction_data *data)
5995 CHECK(n_tokens == 3, EINVAL);
5997 strcpy(data->jmp_label, tokens[1]);
5999 h = header_parse(p, tokens[2]);
6002 instr->type = INSTR_JMP_VALID;
6003 instr->jmp.ip = NULL; /* Resolved later. */
6004 instr->jmp.header_id = h->id;
6009 instr_jmp_invalid_translate(struct rte_swx_pipeline *p,
6010 struct action *action __rte_unused,
6013 struct instruction *instr,
6014 struct instruction_data *data)
6018 CHECK(n_tokens == 3, EINVAL);
6020 strcpy(data->jmp_label, tokens[1]);
6022 h = header_parse(p, tokens[2]);
6025 instr->type = INSTR_JMP_INVALID;
6026 instr->jmp.ip = NULL; /* Resolved later. */
6027 instr->jmp.header_id = h->id;
6032 instr_jmp_hit_translate(struct rte_swx_pipeline *p __rte_unused,
6033 struct action *action,
6036 struct instruction *instr,
6037 struct instruction_data *data)
6039 CHECK(!action, EINVAL);
6040 CHECK(n_tokens == 2, EINVAL);
6042 strcpy(data->jmp_label, tokens[1]);
6044 instr->type = INSTR_JMP_HIT;
6045 instr->jmp.ip = NULL; /* Resolved later. */
6050 instr_jmp_miss_translate(struct rte_swx_pipeline *p __rte_unused,
6051 struct action *action,
6054 struct instruction *instr,
6055 struct instruction_data *data)
6057 CHECK(!action, EINVAL);
6058 CHECK(n_tokens == 2, EINVAL);
6060 strcpy(data->jmp_label, tokens[1]);
6062 instr->type = INSTR_JMP_MISS;
6063 instr->jmp.ip = NULL; /* Resolved later. */
6068 instr_jmp_action_hit_translate(struct rte_swx_pipeline *p,
6069 struct action *action,
6072 struct instruction *instr,
6073 struct instruction_data *data)
6077 CHECK(!action, EINVAL);
6078 CHECK(n_tokens == 3, EINVAL);
6080 strcpy(data->jmp_label, tokens[1]);
6082 a = action_find(p, tokens[2]);
6085 instr->type = INSTR_JMP_ACTION_HIT;
6086 instr->jmp.ip = NULL; /* Resolved later. */
6087 instr->jmp.action_id = a->id;
6092 instr_jmp_action_miss_translate(struct rte_swx_pipeline *p,
6093 struct action *action,
6096 struct instruction *instr,
6097 struct instruction_data *data)
6101 CHECK(!action, EINVAL);
6102 CHECK(n_tokens == 3, EINVAL);
6104 strcpy(data->jmp_label, tokens[1]);
6106 a = action_find(p, tokens[2]);
6109 instr->type = INSTR_JMP_ACTION_MISS;
6110 instr->jmp.ip = NULL; /* Resolved later. */
6111 instr->jmp.action_id = a->id;
6116 instr_jmp_eq_translate(struct rte_swx_pipeline *p,
6117 struct action *action,
6120 struct instruction *instr,
6121 struct instruction_data *data)
6123 char *a = tokens[2], *b = tokens[3];
6124 struct field *fa, *fb;
6126 uint32_t a_struct_id, b_struct_id;
6128 CHECK(n_tokens == 4, EINVAL);
6130 strcpy(data->jmp_label, tokens[1]);
6132 fa = struct_field_parse(p, action, a, &a_struct_id);
6134 CHECK(!fa->var_size, EINVAL);
6136 /* JMP_EQ, JMP_EQ_MH, JMP_EQ_HM, JMP_EQ_HH. */
6137 fb = struct_field_parse(p, action, b, &b_struct_id);
6139 CHECK(!fb->var_size, EINVAL);
6141 instr->type = INSTR_JMP_EQ;
6142 if (a[0] != 'h' && b[0] == 'h')
6143 instr->type = INSTR_JMP_EQ_MH;
6144 if (a[0] == 'h' && b[0] != 'h')
6145 instr->type = INSTR_JMP_EQ_HM;
6146 if (a[0] == 'h' && b[0] == 'h')
6147 instr->type = INSTR_JMP_EQ_HH;
6148 instr->jmp.ip = NULL; /* Resolved later. */
6150 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6151 instr->jmp.a.n_bits = fa->n_bits;
6152 instr->jmp.a.offset = fa->offset / 8;
6153 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6154 instr->jmp.b.n_bits = fb->n_bits;
6155 instr->jmp.b.offset = fb->offset / 8;
6160 b_val = strtoull(b, &b, 0);
6161 CHECK(!b[0], EINVAL);
6164 b_val = hton64(b_val) >> (64 - fa->n_bits);
6166 instr->type = INSTR_JMP_EQ_I;
6167 instr->jmp.ip = NULL; /* Resolved later. */
6168 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6169 instr->jmp.a.n_bits = fa->n_bits;
6170 instr->jmp.a.offset = fa->offset / 8;
6171 instr->jmp.b_val = b_val;
6176 instr_jmp_neq_translate(struct rte_swx_pipeline *p,
6177 struct action *action,
6180 struct instruction *instr,
6181 struct instruction_data *data)
6183 char *a = tokens[2], *b = tokens[3];
6184 struct field *fa, *fb;
6186 uint32_t a_struct_id, b_struct_id;
6188 CHECK(n_tokens == 4, EINVAL);
6190 strcpy(data->jmp_label, tokens[1]);
6192 fa = struct_field_parse(p, action, a, &a_struct_id);
6194 CHECK(!fa->var_size, EINVAL);
6196 /* JMP_NEQ, JMP_NEQ_MH, JMP_NEQ_HM, JMP_NEQ_HH. */
6197 fb = struct_field_parse(p, action, b, &b_struct_id);
6199 CHECK(!fb->var_size, EINVAL);
6201 instr->type = INSTR_JMP_NEQ;
6202 if (a[0] != 'h' && b[0] == 'h')
6203 instr->type = INSTR_JMP_NEQ_MH;
6204 if (a[0] == 'h' && b[0] != 'h')
6205 instr->type = INSTR_JMP_NEQ_HM;
6206 if (a[0] == 'h' && b[0] == 'h')
6207 instr->type = INSTR_JMP_NEQ_HH;
6208 instr->jmp.ip = NULL; /* Resolved later. */
6210 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6211 instr->jmp.a.n_bits = fa->n_bits;
6212 instr->jmp.a.offset = fa->offset / 8;
6213 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6214 instr->jmp.b.n_bits = fb->n_bits;
6215 instr->jmp.b.offset = fb->offset / 8;
6220 b_val = strtoull(b, &b, 0);
6221 CHECK(!b[0], EINVAL);
6224 b_val = hton64(b_val) >> (64 - fa->n_bits);
6226 instr->type = INSTR_JMP_NEQ_I;
6227 instr->jmp.ip = NULL; /* Resolved later. */
6228 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6229 instr->jmp.a.n_bits = fa->n_bits;
6230 instr->jmp.a.offset = fa->offset / 8;
6231 instr->jmp.b_val = b_val;
6236 instr_jmp_lt_translate(struct rte_swx_pipeline *p,
6237 struct action *action,
6240 struct instruction *instr,
6241 struct instruction_data *data)
6243 char *a = tokens[2], *b = tokens[3];
6244 struct field *fa, *fb;
6246 uint32_t a_struct_id, b_struct_id;
6248 CHECK(n_tokens == 4, EINVAL);
6250 strcpy(data->jmp_label, tokens[1]);
6252 fa = struct_field_parse(p, action, a, &a_struct_id);
6254 CHECK(!fa->var_size, EINVAL);
6256 /* JMP_LT, JMP_LT_MH, JMP_LT_HM, JMP_LT_HH. */
6257 fb = struct_field_parse(p, action, b, &b_struct_id);
6259 CHECK(!fb->var_size, EINVAL);
6261 instr->type = INSTR_JMP_LT;
6262 if (a[0] == 'h' && b[0] != 'h')
6263 instr->type = INSTR_JMP_LT_HM;
6264 if (a[0] != 'h' && b[0] == 'h')
6265 instr->type = INSTR_JMP_LT_MH;
6266 if (a[0] == 'h' && b[0] == 'h')
6267 instr->type = INSTR_JMP_LT_HH;
6268 instr->jmp.ip = NULL; /* Resolved later. */
6270 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6271 instr->jmp.a.n_bits = fa->n_bits;
6272 instr->jmp.a.offset = fa->offset / 8;
6273 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6274 instr->jmp.b.n_bits = fb->n_bits;
6275 instr->jmp.b.offset = fb->offset / 8;
6279 /* JMP_LT_MI, JMP_LT_HI. */
6280 b_val = strtoull(b, &b, 0);
6281 CHECK(!b[0], EINVAL);
6283 instr->type = INSTR_JMP_LT_MI;
6285 instr->type = INSTR_JMP_LT_HI;
6286 instr->jmp.ip = NULL; /* Resolved later. */
6288 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6289 instr->jmp.a.n_bits = fa->n_bits;
6290 instr->jmp.a.offset = fa->offset / 8;
6291 instr->jmp.b_val = b_val;
6296 instr_jmp_gt_translate(struct rte_swx_pipeline *p,
6297 struct action *action,
6300 struct instruction *instr,
6301 struct instruction_data *data)
6303 char *a = tokens[2], *b = tokens[3];
6304 struct field *fa, *fb;
6306 uint32_t a_struct_id, b_struct_id;
6308 CHECK(n_tokens == 4, EINVAL);
6310 strcpy(data->jmp_label, tokens[1]);
6312 fa = struct_field_parse(p, action, a, &a_struct_id);
6314 CHECK(!fa->var_size, EINVAL);
6316 /* JMP_GT, JMP_GT_MH, JMP_GT_HM, JMP_GT_HH. */
6317 fb = struct_field_parse(p, action, b, &b_struct_id);
6319 CHECK(!fb->var_size, EINVAL);
6321 instr->type = INSTR_JMP_GT;
6322 if (a[0] == 'h' && b[0] != 'h')
6323 instr->type = INSTR_JMP_GT_HM;
6324 if (a[0] != 'h' && b[0] == 'h')
6325 instr->type = INSTR_JMP_GT_MH;
6326 if (a[0] == 'h' && b[0] == 'h')
6327 instr->type = INSTR_JMP_GT_HH;
6328 instr->jmp.ip = NULL; /* Resolved later. */
6330 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6331 instr->jmp.a.n_bits = fa->n_bits;
6332 instr->jmp.a.offset = fa->offset / 8;
6333 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6334 instr->jmp.b.n_bits = fb->n_bits;
6335 instr->jmp.b.offset = fb->offset / 8;
6339 /* JMP_GT_MI, JMP_GT_HI. */
6340 b_val = strtoull(b, &b, 0);
6341 CHECK(!b[0], EINVAL);
6343 instr->type = INSTR_JMP_GT_MI;
6345 instr->type = INSTR_JMP_GT_HI;
6346 instr->jmp.ip = NULL; /* Resolved later. */
6348 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6349 instr->jmp.a.n_bits = fa->n_bits;
6350 instr->jmp.a.offset = fa->offset / 8;
6351 instr->jmp.b_val = b_val;
6356 instr_jmp_exec(struct rte_swx_pipeline *p)
6358 struct thread *t = &p->threads[p->thread_id];
6359 struct instruction *ip = t->ip;
6361 TRACE("[Thread %2u] jmp\n", p->thread_id);
6363 thread_ip_set(t, ip->jmp.ip);
6367 instr_jmp_valid_exec(struct rte_swx_pipeline *p)
6369 struct thread *t = &p->threads[p->thread_id];
6370 struct instruction *ip = t->ip;
6371 uint32_t header_id = ip->jmp.header_id;
6373 TRACE("[Thread %2u] jmpv\n", p->thread_id);
6375 t->ip = HEADER_VALID(t, header_id) ? ip->jmp.ip : (t->ip + 1);
6379 instr_jmp_invalid_exec(struct rte_swx_pipeline *p)
6381 struct thread *t = &p->threads[p->thread_id];
6382 struct instruction *ip = t->ip;
6383 uint32_t header_id = ip->jmp.header_id;
6385 TRACE("[Thread %2u] jmpnv\n", p->thread_id);
6387 t->ip = HEADER_VALID(t, header_id) ? (t->ip + 1) : ip->jmp.ip;
6391 instr_jmp_hit_exec(struct rte_swx_pipeline *p)
6393 struct thread *t = &p->threads[p->thread_id];
6394 struct instruction *ip = t->ip;
6395 struct instruction *ip_next[] = {t->ip + 1, ip->jmp.ip};
6397 TRACE("[Thread %2u] jmph\n", p->thread_id);
6399 t->ip = ip_next[t->hit];
6403 instr_jmp_miss_exec(struct rte_swx_pipeline *p)
6405 struct thread *t = &p->threads[p->thread_id];
6406 struct instruction *ip = t->ip;
6407 struct instruction *ip_next[] = {ip->jmp.ip, t->ip + 1};
6409 TRACE("[Thread %2u] jmpnh\n", p->thread_id);
6411 t->ip = ip_next[t->hit];
6415 instr_jmp_action_hit_exec(struct rte_swx_pipeline *p)
6417 struct thread *t = &p->threads[p->thread_id];
6418 struct instruction *ip = t->ip;
6420 TRACE("[Thread %2u] jmpa\n", p->thread_id);
6422 t->ip = (ip->jmp.action_id == t->action_id) ? ip->jmp.ip : (t->ip + 1);
6426 instr_jmp_action_miss_exec(struct rte_swx_pipeline *p)
6428 struct thread *t = &p->threads[p->thread_id];
6429 struct instruction *ip = t->ip;
6431 TRACE("[Thread %2u] jmpna\n", p->thread_id);
6433 t->ip = (ip->jmp.action_id == t->action_id) ? (t->ip + 1) : ip->jmp.ip;
6437 instr_jmp_eq_exec(struct rte_swx_pipeline *p)
6439 struct thread *t = &p->threads[p->thread_id];
6440 struct instruction *ip = t->ip;
6442 TRACE("[Thread %2u] jmpeq\n", p->thread_id);
6448 instr_jmp_eq_mh_exec(struct rte_swx_pipeline *p)
6450 struct thread *t = &p->threads[p->thread_id];
6451 struct instruction *ip = t->ip;
6453 TRACE("[Thread %2u] jmpeq (mh)\n", p->thread_id);
6455 JMP_CMP_MH(t, ip, ==);
6459 instr_jmp_eq_hm_exec(struct rte_swx_pipeline *p)
6461 struct thread *t = &p->threads[p->thread_id];
6462 struct instruction *ip = t->ip;
6464 TRACE("[Thread %2u] jmpeq (hm)\n", p->thread_id);
6466 JMP_CMP_HM(t, ip, ==);
6470 instr_jmp_eq_hh_exec(struct rte_swx_pipeline *p)
6472 struct thread *t = &p->threads[p->thread_id];
6473 struct instruction *ip = t->ip;
6475 TRACE("[Thread %2u] jmpeq (hh)\n", p->thread_id);
6477 JMP_CMP_HH_FAST(t, ip, ==);
6481 instr_jmp_eq_i_exec(struct rte_swx_pipeline *p)
6483 struct thread *t = &p->threads[p->thread_id];
6484 struct instruction *ip = t->ip;
6486 TRACE("[Thread %2u] jmpeq (i)\n", p->thread_id);
6488 JMP_CMP_I(t, ip, ==);
6492 instr_jmp_neq_exec(struct rte_swx_pipeline *p)
6494 struct thread *t = &p->threads[p->thread_id];
6495 struct instruction *ip = t->ip;
6497 TRACE("[Thread %2u] jmpneq\n", p->thread_id);
6503 instr_jmp_neq_mh_exec(struct rte_swx_pipeline *p)
6505 struct thread *t = &p->threads[p->thread_id];
6506 struct instruction *ip = t->ip;
6508 TRACE("[Thread %2u] jmpneq (mh)\n", p->thread_id);
6510 JMP_CMP_MH(t, ip, !=);
6514 instr_jmp_neq_hm_exec(struct rte_swx_pipeline *p)
6516 struct thread *t = &p->threads[p->thread_id];
6517 struct instruction *ip = t->ip;
6519 TRACE("[Thread %2u] jmpneq (hm)\n", p->thread_id);
6521 JMP_CMP_HM(t, ip, !=);
6525 instr_jmp_neq_hh_exec(struct rte_swx_pipeline *p)
6527 struct thread *t = &p->threads[p->thread_id];
6528 struct instruction *ip = t->ip;
6530 TRACE("[Thread %2u] jmpneq (hh)\n", p->thread_id);
6532 JMP_CMP_HH_FAST(t, ip, !=);
6536 instr_jmp_neq_i_exec(struct rte_swx_pipeline *p)
6538 struct thread *t = &p->threads[p->thread_id];
6539 struct instruction *ip = t->ip;
6541 TRACE("[Thread %2u] jmpneq (i)\n", p->thread_id);
6543 JMP_CMP_I(t, ip, !=);
6547 instr_jmp_lt_exec(struct rte_swx_pipeline *p)
6549 struct thread *t = &p->threads[p->thread_id];
6550 struct instruction *ip = t->ip;
6552 TRACE("[Thread %2u] jmplt\n", p->thread_id);
6558 instr_jmp_lt_mh_exec(struct rte_swx_pipeline *p)
6560 struct thread *t = &p->threads[p->thread_id];
6561 struct instruction *ip = t->ip;
6563 TRACE("[Thread %2u] jmplt (mh)\n", p->thread_id);
6565 JMP_CMP_MH(t, ip, <);
6569 instr_jmp_lt_hm_exec(struct rte_swx_pipeline *p)
6571 struct thread *t = &p->threads[p->thread_id];
6572 struct instruction *ip = t->ip;
6574 TRACE("[Thread %2u] jmplt (hm)\n", p->thread_id);
6576 JMP_CMP_HM(t, ip, <);
6580 instr_jmp_lt_hh_exec(struct rte_swx_pipeline *p)
6582 struct thread *t = &p->threads[p->thread_id];
6583 struct instruction *ip = t->ip;
6585 TRACE("[Thread %2u] jmplt (hh)\n", p->thread_id);
6587 JMP_CMP_HH(t, ip, <);
6591 instr_jmp_lt_mi_exec(struct rte_swx_pipeline *p)
6593 struct thread *t = &p->threads[p->thread_id];
6594 struct instruction *ip = t->ip;
6596 TRACE("[Thread %2u] jmplt (mi)\n", p->thread_id);
6598 JMP_CMP_MI(t, ip, <);
6602 instr_jmp_lt_hi_exec(struct rte_swx_pipeline *p)
6604 struct thread *t = &p->threads[p->thread_id];
6605 struct instruction *ip = t->ip;
6607 TRACE("[Thread %2u] jmplt (hi)\n", p->thread_id);
6609 JMP_CMP_HI(t, ip, <);
6613 instr_jmp_gt_exec(struct rte_swx_pipeline *p)
6615 struct thread *t = &p->threads[p->thread_id];
6616 struct instruction *ip = t->ip;
6618 TRACE("[Thread %2u] jmpgt\n", p->thread_id);
6624 instr_jmp_gt_mh_exec(struct rte_swx_pipeline *p)
6626 struct thread *t = &p->threads[p->thread_id];
6627 struct instruction *ip = t->ip;
6629 TRACE("[Thread %2u] jmpgt (mh)\n", p->thread_id);
6631 JMP_CMP_MH(t, ip, >);
6635 instr_jmp_gt_hm_exec(struct rte_swx_pipeline *p)
6637 struct thread *t = &p->threads[p->thread_id];
6638 struct instruction *ip = t->ip;
6640 TRACE("[Thread %2u] jmpgt (hm)\n", p->thread_id);
6642 JMP_CMP_HM(t, ip, >);
6646 instr_jmp_gt_hh_exec(struct rte_swx_pipeline *p)
6648 struct thread *t = &p->threads[p->thread_id];
6649 struct instruction *ip = t->ip;
6651 TRACE("[Thread %2u] jmpgt (hh)\n", p->thread_id);
6653 JMP_CMP_HH(t, ip, >);
6657 instr_jmp_gt_mi_exec(struct rte_swx_pipeline *p)
6659 struct thread *t = &p->threads[p->thread_id];
6660 struct instruction *ip = t->ip;
6662 TRACE("[Thread %2u] jmpgt (mi)\n", p->thread_id);
6664 JMP_CMP_MI(t, ip, >);
6668 instr_jmp_gt_hi_exec(struct rte_swx_pipeline *p)
6670 struct thread *t = &p->threads[p->thread_id];
6671 struct instruction *ip = t->ip;
6673 TRACE("[Thread %2u] jmpgt (hi)\n", p->thread_id);
6675 JMP_CMP_HI(t, ip, >);
6682 instr_return_translate(struct rte_swx_pipeline *p __rte_unused,
6683 struct action *action,
6684 char **tokens __rte_unused,
6686 struct instruction *instr,
6687 struct instruction_data *data __rte_unused)
6689 CHECK(action, EINVAL);
6690 CHECK(n_tokens == 1, EINVAL);
6692 instr->type = INSTR_RETURN;
6697 instr_return_exec(struct rte_swx_pipeline *p)
6699 struct thread *t = &p->threads[p->thread_id];
6701 TRACE("[Thread %2u] return\n", p->thread_id);
6707 instr_translate(struct rte_swx_pipeline *p,
6708 struct action *action,
6710 struct instruction *instr,
6711 struct instruction_data *data)
6713 char *tokens[RTE_SWX_INSTRUCTION_TOKENS_MAX];
6714 int n_tokens = 0, tpos = 0;
6716 /* Parse the instruction string into tokens. */
6720 token = strtok_r(string, " \t\v", &string);
6724 CHECK(n_tokens < RTE_SWX_INSTRUCTION_TOKENS_MAX, EINVAL);
6725 CHECK_NAME(token, EINVAL);
6727 tokens[n_tokens] = token;
6731 CHECK(n_tokens, EINVAL);
6733 /* Handle the optional instruction label. */
6734 if ((n_tokens >= 2) && !strcmp(tokens[1], ":")) {
6735 strcpy(data->label, tokens[0]);
6738 CHECK(n_tokens - tpos, EINVAL);
6741 /* Identify the instruction type. */
6742 if (!strcmp(tokens[tpos], "rx"))
6743 return instr_rx_translate(p,
6750 if (!strcmp(tokens[tpos], "tx"))
6751 return instr_tx_translate(p,
6758 if (!strcmp(tokens[tpos], "drop"))
6759 return instr_drop_translate(p,
6766 if (!strcmp(tokens[tpos], "extract"))
6767 return instr_hdr_extract_translate(p,
6774 if (!strcmp(tokens[tpos], "lookahead"))
6775 return instr_hdr_lookahead_translate(p,
6782 if (!strcmp(tokens[tpos], "emit"))
6783 return instr_hdr_emit_translate(p,
6790 if (!strcmp(tokens[tpos], "validate"))
6791 return instr_hdr_validate_translate(p,
6798 if (!strcmp(tokens[tpos], "invalidate"))
6799 return instr_hdr_invalidate_translate(p,
6806 if (!strcmp(tokens[tpos], "mov"))
6807 return instr_mov_translate(p,
6814 if (!strcmp(tokens[tpos], "add"))
6815 return instr_alu_add_translate(p,
6822 if (!strcmp(tokens[tpos], "sub"))
6823 return instr_alu_sub_translate(p,
6830 if (!strcmp(tokens[tpos], "ckadd"))
6831 return instr_alu_ckadd_translate(p,
6838 if (!strcmp(tokens[tpos], "cksub"))
6839 return instr_alu_cksub_translate(p,
6846 if (!strcmp(tokens[tpos], "and"))
6847 return instr_alu_and_translate(p,
6854 if (!strcmp(tokens[tpos], "or"))
6855 return instr_alu_or_translate(p,
6862 if (!strcmp(tokens[tpos], "xor"))
6863 return instr_alu_xor_translate(p,
6870 if (!strcmp(tokens[tpos], "shl"))
6871 return instr_alu_shl_translate(p,
6878 if (!strcmp(tokens[tpos], "shr"))
6879 return instr_alu_shr_translate(p,
6886 if (!strcmp(tokens[tpos], "regprefetch"))
6887 return instr_regprefetch_translate(p,
6894 if (!strcmp(tokens[tpos], "regrd"))
6895 return instr_regrd_translate(p,
6902 if (!strcmp(tokens[tpos], "regwr"))
6903 return instr_regwr_translate(p,
6910 if (!strcmp(tokens[tpos], "regadd"))
6911 return instr_regadd_translate(p,
6918 if (!strcmp(tokens[tpos], "metprefetch"))
6919 return instr_metprefetch_translate(p,
6926 if (!strcmp(tokens[tpos], "meter"))
6927 return instr_meter_translate(p,
6934 if (!strcmp(tokens[tpos], "table"))
6935 return instr_table_translate(p,
6942 if (!strcmp(tokens[tpos], "learn"))
6943 return instr_learn_translate(p,
6950 if (!strcmp(tokens[tpos], "forget"))
6951 return instr_forget_translate(p,
6958 if (!strcmp(tokens[tpos], "extern"))
6959 return instr_extern_translate(p,
6966 if (!strcmp(tokens[tpos], "jmp"))
6967 return instr_jmp_translate(p,
6974 if (!strcmp(tokens[tpos], "jmpv"))
6975 return instr_jmp_valid_translate(p,
6982 if (!strcmp(tokens[tpos], "jmpnv"))
6983 return instr_jmp_invalid_translate(p,
6990 if (!strcmp(tokens[tpos], "jmph"))
6991 return instr_jmp_hit_translate(p,
6998 if (!strcmp(tokens[tpos], "jmpnh"))
6999 return instr_jmp_miss_translate(p,
7006 if (!strcmp(tokens[tpos], "jmpa"))
7007 return instr_jmp_action_hit_translate(p,
7014 if (!strcmp(tokens[tpos], "jmpna"))
7015 return instr_jmp_action_miss_translate(p,
7022 if (!strcmp(tokens[tpos], "jmpeq"))
7023 return instr_jmp_eq_translate(p,
7030 if (!strcmp(tokens[tpos], "jmpneq"))
7031 return instr_jmp_neq_translate(p,
7038 if (!strcmp(tokens[tpos], "jmplt"))
7039 return instr_jmp_lt_translate(p,
7046 if (!strcmp(tokens[tpos], "jmpgt"))
7047 return instr_jmp_gt_translate(p,
7054 if (!strcmp(tokens[tpos], "return"))
7055 return instr_return_translate(p,
7065 static struct instruction_data *
7066 label_find(struct instruction_data *data, uint32_t n, const char *label)
7070 for (i = 0; i < n; i++)
7071 if (!strcmp(label, data[i].label))
7078 label_is_used(struct instruction_data *data, uint32_t n, const char *label)
7080 uint32_t count = 0, i;
7085 for (i = 0; i < n; i++)
7086 if (!strcmp(label, data[i].jmp_label))
7093 instr_label_check(struct instruction_data *instruction_data,
7094 uint32_t n_instructions)
7098 /* Check that all instruction labels are unique. */
7099 for (i = 0; i < n_instructions; i++) {
7100 struct instruction_data *data = &instruction_data[i];
7101 char *label = data->label;
7107 for (j = i + 1; j < n_instructions; j++)
7108 CHECK(strcmp(label, data[j].label), EINVAL);
7111 /* Get users for each instruction label. */
7112 for (i = 0; i < n_instructions; i++) {
7113 struct instruction_data *data = &instruction_data[i];
7114 char *label = data->label;
7116 data->n_users = label_is_used(instruction_data,
7125 instr_jmp_resolve(struct instruction *instructions,
7126 struct instruction_data *instruction_data,
7127 uint32_t n_instructions)
7131 for (i = 0; i < n_instructions; i++) {
7132 struct instruction *instr = &instructions[i];
7133 struct instruction_data *data = &instruction_data[i];
7134 struct instruction_data *found;
7136 if (!instruction_is_jmp(instr))
7139 found = label_find(instruction_data,
7142 CHECK(found, EINVAL);
7144 instr->jmp.ip = &instructions[found - instruction_data];
7151 instr_verify(struct rte_swx_pipeline *p __rte_unused,
7153 struct instruction *instr,
7154 struct instruction_data *data __rte_unused,
7155 uint32_t n_instructions)
7158 enum instruction_type type;
7161 /* Check that the first instruction is rx. */
7162 CHECK(instr[0].type == INSTR_RX, EINVAL);
7164 /* Check that there is at least one tx instruction. */
7165 for (i = 0; i < n_instructions; i++) {
7166 type = instr[i].type;
7168 if (instruction_is_tx(type))
7171 CHECK(i < n_instructions, EINVAL);
7173 /* Check that the last instruction is either tx or unconditional
7176 type = instr[n_instructions - 1].type;
7177 CHECK(instruction_is_tx(type) || (type == INSTR_JMP), EINVAL);
7181 enum instruction_type type;
7184 /* Check that there is at least one return or tx instruction. */
7185 for (i = 0; i < n_instructions; i++) {
7186 type = instr[i].type;
7188 if ((type == INSTR_RETURN) || instruction_is_tx(type))
7191 CHECK(i < n_instructions, EINVAL);
7198 instr_compact(struct instruction *instructions,
7199 struct instruction_data *instruction_data,
7200 uint32_t n_instructions)
7202 uint32_t i, pos = 0;
7204 /* Eliminate the invalid instructions that have been optimized out. */
7205 for (i = 0; i < n_instructions; i++) {
7206 struct instruction *instr = &instructions[i];
7207 struct instruction_data *data = &instruction_data[i];
7213 memcpy(&instructions[pos], instr, sizeof(*instr));
7214 memcpy(&instruction_data[pos], data, sizeof(*data));
7224 instr_pattern_extract_many_search(struct instruction *instr,
7225 struct instruction_data *data,
7227 uint32_t *n_pattern_instr)
7231 for (i = 0; i < n_instr; i++) {
7232 if (data[i].invalid)
7235 if (instr[i].type != INSTR_HDR_EXTRACT)
7238 if (i == RTE_DIM(instr->io.hdr.header_id))
7241 if (i && data[i].n_users)
7248 *n_pattern_instr = i;
7253 instr_pattern_extract_many_replace(struct instruction *instr,
7254 struct instruction_data *data,
7259 for (i = 1; i < n_instr; i++) {
7261 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
7262 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
7263 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
7265 data[i].invalid = 1;
7270 instr_pattern_extract_many_optimize(struct instruction *instructions,
7271 struct instruction_data *instruction_data,
7272 uint32_t n_instructions)
7276 for (i = 0; i < n_instructions; ) {
7277 struct instruction *instr = &instructions[i];
7278 struct instruction_data *data = &instruction_data[i];
7279 uint32_t n_instr = 0;
7283 detected = instr_pattern_extract_many_search(instr,
7288 instr_pattern_extract_many_replace(instr,
7295 /* No pattern starting at the current instruction. */
7299 /* Eliminate the invalid instructions that have been optimized out. */
7300 n_instructions = instr_compact(instructions,
7304 return n_instructions;
7308 instr_pattern_emit_many_tx_search(struct instruction *instr,
7309 struct instruction_data *data,
7311 uint32_t *n_pattern_instr)
7315 for (i = 0; i < n_instr; i++) {
7316 if (data[i].invalid)
7319 if (instr[i].type != INSTR_HDR_EMIT)
7322 if (i == RTE_DIM(instr->io.hdr.header_id))
7325 if (i && data[i].n_users)
7332 if (!instruction_is_tx(instr[i].type))
7335 if (data[i].n_users)
7340 *n_pattern_instr = i;
7345 instr_pattern_emit_many_tx_replace(struct instruction *instr,
7346 struct instruction_data *data,
7351 /* Any emit instruction in addition to the first one. */
7352 for (i = 1; i < n_instr - 1; i++) {
7354 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
7355 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
7356 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
7358 data[i].invalid = 1;
7361 /* The TX instruction is the last one in the pattern. */
7363 instr[0].io.io.offset = instr[i].io.io.offset;
7364 instr[0].io.io.n_bits = instr[i].io.io.n_bits;
7365 data[i].invalid = 1;
7369 instr_pattern_emit_many_tx_optimize(struct instruction *instructions,
7370 struct instruction_data *instruction_data,
7371 uint32_t n_instructions)
7375 for (i = 0; i < n_instructions; ) {
7376 struct instruction *instr = &instructions[i];
7377 struct instruction_data *data = &instruction_data[i];
7378 uint32_t n_instr = 0;
7381 /* Emit many + TX. */
7382 detected = instr_pattern_emit_many_tx_search(instr,
7387 instr_pattern_emit_many_tx_replace(instr,
7394 /* No pattern starting at the current instruction. */
7398 /* Eliminate the invalid instructions that have been optimized out. */
7399 n_instructions = instr_compact(instructions,
7403 return n_instructions;
7407 action_arg_src_mov_count(struct action *a,
7409 struct instruction *instructions,
7410 struct instruction_data *instruction_data,
7411 uint32_t n_instructions);
7414 instr_pattern_mov_all_validate_search(struct rte_swx_pipeline *p,
7416 struct instruction *instr,
7417 struct instruction_data *data,
7419 struct instruction *instructions,
7420 struct instruction_data *instruction_data,
7421 uint32_t n_instructions,
7422 uint32_t *n_pattern_instr)
7425 uint32_t src_field_id, i, j;
7427 /* Prerequisites. */
7431 /* First instruction: MOV_HM. */
7432 if (data[0].invalid || (instr[0].type != INSTR_MOV_HM))
7435 h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
7436 if (!h || h->st->var_size)
7439 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
7440 if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
7443 if (src_field_id == a->st->n_fields)
7446 if (instr[0].mov.dst.offset ||
7447 (instr[0].mov.dst.n_bits != h->st->fields[0].n_bits) ||
7448 instr[0].mov.src.struct_id ||
7449 (instr[0].mov.src.n_bits != a->st->fields[src_field_id].n_bits) ||
7450 (instr[0].mov.dst.n_bits != instr[0].mov.src.n_bits))
7453 if ((n_instr < h->st->n_fields + 1) ||
7454 (a->st->n_fields < src_field_id + h->st->n_fields + 1))
7457 /* Subsequent instructions: MOV_HM. */
7458 for (i = 1; i < h->st->n_fields; i++)
7459 if (data[i].invalid ||
7461 (instr[i].type != INSTR_MOV_HM) ||
7462 (instr[i].mov.dst.struct_id != h->struct_id) ||
7463 (instr[i].mov.dst.offset != h->st->fields[i].offset / 8) ||
7464 (instr[i].mov.dst.n_bits != h->st->fields[i].n_bits) ||
7465 instr[i].mov.src.struct_id ||
7466 (instr[i].mov.src.offset != a->st->fields[src_field_id + i].offset / 8) ||
7467 (instr[i].mov.src.n_bits != a->st->fields[src_field_id + i].n_bits) ||
7468 (instr[i].mov.dst.n_bits != instr[i].mov.src.n_bits))
7471 /* Last instruction: HDR_VALIDATE. */
7472 if ((instr[i].type != INSTR_HDR_VALIDATE) ||
7473 (instr[i].valid.header_id != h->id))
7476 /* Check that none of the action args that are used as source for this
7477 * DMA transfer are not used as source in any other mov instruction.
7479 for (j = src_field_id; j < src_field_id + h->st->n_fields; j++) {
7482 n_users = action_arg_src_mov_count(a,
7491 *n_pattern_instr = 1 + i;
7496 instr_pattern_mov_all_validate_replace(struct rte_swx_pipeline *p,
7498 struct instruction *instr,
7499 struct instruction_data *data,
7503 uint32_t src_field_id, src_offset, i;
7505 /* Read from the instructions before they are modified. */
7506 h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
7510 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
7511 if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
7514 if (src_field_id == a->st->n_fields)
7517 src_offset = instr[0].mov.src.offset;
7519 /* Modify the instructions. */
7520 instr[0].type = INSTR_DMA_HT;
7521 instr[0].dma.dst.header_id[0] = h->id;
7522 instr[0].dma.dst.struct_id[0] = h->struct_id;
7523 instr[0].dma.src.offset[0] = (uint8_t)src_offset;
7524 instr[0].dma.n_bytes[0] = h->st->n_bits / 8;
7526 for (i = 1; i < n_instr; i++)
7527 data[i].invalid = 1;
7529 /* Update the endianness of the action arguments to header endianness. */
7530 for (i = 0; i < h->st->n_fields; i++)
7531 a->args_endianness[src_field_id + i] = 1;
7535 instr_pattern_mov_all_validate_optimize(struct rte_swx_pipeline *p,
7537 struct instruction *instructions,
7538 struct instruction_data *instruction_data,
7539 uint32_t n_instructions)
7544 return n_instructions;
7546 for (i = 0; i < n_instructions; ) {
7547 struct instruction *instr = &instructions[i];
7548 struct instruction_data *data = &instruction_data[i];
7549 uint32_t n_instr = 0;
7552 /* Mov all + validate. */
7553 detected = instr_pattern_mov_all_validate_search(p,
7563 instr_pattern_mov_all_validate_replace(p, a, instr, data, n_instr);
7568 /* No pattern starting at the current instruction. */
7572 /* Eliminate the invalid instructions that have been optimized out. */
7573 n_instructions = instr_compact(instructions,
7577 return n_instructions;
7581 instr_pattern_dma_many_search(struct instruction *instr,
7582 struct instruction_data *data,
7584 uint32_t *n_pattern_instr)
7588 for (i = 0; i < n_instr; i++) {
7589 if (data[i].invalid)
7592 if (instr[i].type != INSTR_DMA_HT)
7595 if (i == RTE_DIM(instr->dma.dst.header_id))
7598 if (i && data[i].n_users)
7605 *n_pattern_instr = i;
7610 instr_pattern_dma_many_replace(struct instruction *instr,
7611 struct instruction_data *data,
7616 for (i = 1; i < n_instr; i++) {
7618 instr[0].dma.dst.header_id[i] = instr[i].dma.dst.header_id[0];
7619 instr[0].dma.dst.struct_id[i] = instr[i].dma.dst.struct_id[0];
7620 instr[0].dma.src.offset[i] = instr[i].dma.src.offset[0];
7621 instr[0].dma.n_bytes[i] = instr[i].dma.n_bytes[0];
7623 data[i].invalid = 1;
7628 instr_pattern_dma_many_optimize(struct instruction *instructions,
7629 struct instruction_data *instruction_data,
7630 uint32_t n_instructions)
7634 for (i = 0; i < n_instructions; ) {
7635 struct instruction *instr = &instructions[i];
7636 struct instruction_data *data = &instruction_data[i];
7637 uint32_t n_instr = 0;
7641 detected = instr_pattern_dma_many_search(instr,
7646 instr_pattern_dma_many_replace(instr, data, n_instr);
7651 /* No pattern starting at the current instruction. */
7655 /* Eliminate the invalid instructions that have been optimized out. */
7656 n_instructions = instr_compact(instructions,
7660 return n_instructions;
7664 instr_optimize(struct rte_swx_pipeline *p,
7666 struct instruction *instructions,
7667 struct instruction_data *instruction_data,
7668 uint32_t n_instructions)
7671 n_instructions = instr_pattern_extract_many_optimize(instructions,
7675 /* Emit many + TX. */
7676 n_instructions = instr_pattern_emit_many_tx_optimize(instructions,
7680 /* Mov all + validate. */
7681 n_instructions = instr_pattern_mov_all_validate_optimize(p,
7688 n_instructions = instr_pattern_dma_many_optimize(instructions,
7692 return n_instructions;
7696 instruction_config(struct rte_swx_pipeline *p,
7698 const char **instructions,
7699 uint32_t n_instructions)
7701 struct instruction *instr = NULL;
7702 struct instruction_data *data = NULL;
7706 CHECK(n_instructions, EINVAL);
7707 CHECK(instructions, EINVAL);
7708 for (i = 0; i < n_instructions; i++)
7709 CHECK_INSTRUCTION(instructions[i], EINVAL);
7711 /* Memory allocation. */
7712 instr = calloc(n_instructions, sizeof(struct instruction));
7718 data = calloc(n_instructions, sizeof(struct instruction_data));
7724 for (i = 0; i < n_instructions; i++) {
7725 char *string = strdup(instructions[i]);
7731 err = instr_translate(p, a, string, &instr[i], &data[i]);
7740 err = instr_label_check(data, n_instructions);
7744 err = instr_verify(p, a, instr, data, n_instructions);
7748 n_instructions = instr_optimize(p, a, instr, data, n_instructions);
7750 err = instr_jmp_resolve(instr, data, n_instructions);
7755 a->instructions = instr;
7756 a->n_instructions = n_instructions;
7758 p->instructions = instr;
7759 p->n_instructions = n_instructions;
7771 typedef void (*instr_exec_t)(struct rte_swx_pipeline *);
7773 static instr_exec_t instruction_table[] = {
7774 [INSTR_RX] = instr_rx_exec,
7775 [INSTR_TX] = instr_tx_exec,
7776 [INSTR_TX_I] = instr_tx_i_exec,
7778 [INSTR_HDR_EXTRACT] = instr_hdr_extract_exec,
7779 [INSTR_HDR_EXTRACT2] = instr_hdr_extract2_exec,
7780 [INSTR_HDR_EXTRACT3] = instr_hdr_extract3_exec,
7781 [INSTR_HDR_EXTRACT4] = instr_hdr_extract4_exec,
7782 [INSTR_HDR_EXTRACT5] = instr_hdr_extract5_exec,
7783 [INSTR_HDR_EXTRACT6] = instr_hdr_extract6_exec,
7784 [INSTR_HDR_EXTRACT7] = instr_hdr_extract7_exec,
7785 [INSTR_HDR_EXTRACT8] = instr_hdr_extract8_exec,
7786 [INSTR_HDR_EXTRACT_M] = instr_hdr_extract_m_exec,
7787 [INSTR_HDR_LOOKAHEAD] = instr_hdr_lookahead_exec,
7789 [INSTR_HDR_EMIT] = instr_hdr_emit_exec,
7790 [INSTR_HDR_EMIT_TX] = instr_hdr_emit_tx_exec,
7791 [INSTR_HDR_EMIT2_TX] = instr_hdr_emit2_tx_exec,
7792 [INSTR_HDR_EMIT3_TX] = instr_hdr_emit3_tx_exec,
7793 [INSTR_HDR_EMIT4_TX] = instr_hdr_emit4_tx_exec,
7794 [INSTR_HDR_EMIT5_TX] = instr_hdr_emit5_tx_exec,
7795 [INSTR_HDR_EMIT6_TX] = instr_hdr_emit6_tx_exec,
7796 [INSTR_HDR_EMIT7_TX] = instr_hdr_emit7_tx_exec,
7797 [INSTR_HDR_EMIT8_TX] = instr_hdr_emit8_tx_exec,
7799 [INSTR_HDR_VALIDATE] = instr_hdr_validate_exec,
7800 [INSTR_HDR_INVALIDATE] = instr_hdr_invalidate_exec,
7802 [INSTR_MOV] = instr_mov_exec,
7803 [INSTR_MOV_MH] = instr_mov_mh_exec,
7804 [INSTR_MOV_HM] = instr_mov_hm_exec,
7805 [INSTR_MOV_HH] = instr_mov_hh_exec,
7806 [INSTR_MOV_I] = instr_mov_i_exec,
7808 [INSTR_DMA_HT] = instr_dma_ht_exec,
7809 [INSTR_DMA_HT2] = instr_dma_ht2_exec,
7810 [INSTR_DMA_HT3] = instr_dma_ht3_exec,
7811 [INSTR_DMA_HT4] = instr_dma_ht4_exec,
7812 [INSTR_DMA_HT5] = instr_dma_ht5_exec,
7813 [INSTR_DMA_HT6] = instr_dma_ht6_exec,
7814 [INSTR_DMA_HT7] = instr_dma_ht7_exec,
7815 [INSTR_DMA_HT8] = instr_dma_ht8_exec,
7817 [INSTR_ALU_ADD] = instr_alu_add_exec,
7818 [INSTR_ALU_ADD_MH] = instr_alu_add_mh_exec,
7819 [INSTR_ALU_ADD_HM] = instr_alu_add_hm_exec,
7820 [INSTR_ALU_ADD_HH] = instr_alu_add_hh_exec,
7821 [INSTR_ALU_ADD_MI] = instr_alu_add_mi_exec,
7822 [INSTR_ALU_ADD_HI] = instr_alu_add_hi_exec,
7824 [INSTR_ALU_SUB] = instr_alu_sub_exec,
7825 [INSTR_ALU_SUB_MH] = instr_alu_sub_mh_exec,
7826 [INSTR_ALU_SUB_HM] = instr_alu_sub_hm_exec,
7827 [INSTR_ALU_SUB_HH] = instr_alu_sub_hh_exec,
7828 [INSTR_ALU_SUB_MI] = instr_alu_sub_mi_exec,
7829 [INSTR_ALU_SUB_HI] = instr_alu_sub_hi_exec,
7831 [INSTR_ALU_CKADD_FIELD] = instr_alu_ckadd_field_exec,
7832 [INSTR_ALU_CKADD_STRUCT] = instr_alu_ckadd_struct_exec,
7833 [INSTR_ALU_CKADD_STRUCT20] = instr_alu_ckadd_struct20_exec,
7834 [INSTR_ALU_CKSUB_FIELD] = instr_alu_cksub_field_exec,
7836 [INSTR_ALU_AND] = instr_alu_and_exec,
7837 [INSTR_ALU_AND_MH] = instr_alu_and_mh_exec,
7838 [INSTR_ALU_AND_HM] = instr_alu_and_hm_exec,
7839 [INSTR_ALU_AND_HH] = instr_alu_and_hh_exec,
7840 [INSTR_ALU_AND_I] = instr_alu_and_i_exec,
7842 [INSTR_ALU_OR] = instr_alu_or_exec,
7843 [INSTR_ALU_OR_MH] = instr_alu_or_mh_exec,
7844 [INSTR_ALU_OR_HM] = instr_alu_or_hm_exec,
7845 [INSTR_ALU_OR_HH] = instr_alu_or_hh_exec,
7846 [INSTR_ALU_OR_I] = instr_alu_or_i_exec,
7848 [INSTR_ALU_XOR] = instr_alu_xor_exec,
7849 [INSTR_ALU_XOR_MH] = instr_alu_xor_mh_exec,
7850 [INSTR_ALU_XOR_HM] = instr_alu_xor_hm_exec,
7851 [INSTR_ALU_XOR_HH] = instr_alu_xor_hh_exec,
7852 [INSTR_ALU_XOR_I] = instr_alu_xor_i_exec,
7854 [INSTR_ALU_SHL] = instr_alu_shl_exec,
7855 [INSTR_ALU_SHL_MH] = instr_alu_shl_mh_exec,
7856 [INSTR_ALU_SHL_HM] = instr_alu_shl_hm_exec,
7857 [INSTR_ALU_SHL_HH] = instr_alu_shl_hh_exec,
7858 [INSTR_ALU_SHL_MI] = instr_alu_shl_mi_exec,
7859 [INSTR_ALU_SHL_HI] = instr_alu_shl_hi_exec,
7861 [INSTR_ALU_SHR] = instr_alu_shr_exec,
7862 [INSTR_ALU_SHR_MH] = instr_alu_shr_mh_exec,
7863 [INSTR_ALU_SHR_HM] = instr_alu_shr_hm_exec,
7864 [INSTR_ALU_SHR_HH] = instr_alu_shr_hh_exec,
7865 [INSTR_ALU_SHR_MI] = instr_alu_shr_mi_exec,
7866 [INSTR_ALU_SHR_HI] = instr_alu_shr_hi_exec,
7868 [INSTR_REGPREFETCH_RH] = instr_regprefetch_rh_exec,
7869 [INSTR_REGPREFETCH_RM] = instr_regprefetch_rm_exec,
7870 [INSTR_REGPREFETCH_RI] = instr_regprefetch_ri_exec,
7872 [INSTR_REGRD_HRH] = instr_regrd_hrh_exec,
7873 [INSTR_REGRD_HRM] = instr_regrd_hrm_exec,
7874 [INSTR_REGRD_MRH] = instr_regrd_mrh_exec,
7875 [INSTR_REGRD_MRM] = instr_regrd_mrm_exec,
7876 [INSTR_REGRD_HRI] = instr_regrd_hri_exec,
7877 [INSTR_REGRD_MRI] = instr_regrd_mri_exec,
7879 [INSTR_REGWR_RHH] = instr_regwr_rhh_exec,
7880 [INSTR_REGWR_RHM] = instr_regwr_rhm_exec,
7881 [INSTR_REGWR_RMH] = instr_regwr_rmh_exec,
7882 [INSTR_REGWR_RMM] = instr_regwr_rmm_exec,
7883 [INSTR_REGWR_RHI] = instr_regwr_rhi_exec,
7884 [INSTR_REGWR_RMI] = instr_regwr_rmi_exec,
7885 [INSTR_REGWR_RIH] = instr_regwr_rih_exec,
7886 [INSTR_REGWR_RIM] = instr_regwr_rim_exec,
7887 [INSTR_REGWR_RII] = instr_regwr_rii_exec,
7889 [INSTR_REGADD_RHH] = instr_regadd_rhh_exec,
7890 [INSTR_REGADD_RHM] = instr_regadd_rhm_exec,
7891 [INSTR_REGADD_RMH] = instr_regadd_rmh_exec,
7892 [INSTR_REGADD_RMM] = instr_regadd_rmm_exec,
7893 [INSTR_REGADD_RHI] = instr_regadd_rhi_exec,
7894 [INSTR_REGADD_RMI] = instr_regadd_rmi_exec,
7895 [INSTR_REGADD_RIH] = instr_regadd_rih_exec,
7896 [INSTR_REGADD_RIM] = instr_regadd_rim_exec,
7897 [INSTR_REGADD_RII] = instr_regadd_rii_exec,
7899 [INSTR_METPREFETCH_H] = instr_metprefetch_h_exec,
7900 [INSTR_METPREFETCH_M] = instr_metprefetch_m_exec,
7901 [INSTR_METPREFETCH_I] = instr_metprefetch_i_exec,
7903 [INSTR_METER_HHM] = instr_meter_hhm_exec,
7904 [INSTR_METER_HHI] = instr_meter_hhi_exec,
7905 [INSTR_METER_HMM] = instr_meter_hmm_exec,
7906 [INSTR_METER_HMI] = instr_meter_hmi_exec,
7907 [INSTR_METER_MHM] = instr_meter_mhm_exec,
7908 [INSTR_METER_MHI] = instr_meter_mhi_exec,
7909 [INSTR_METER_MMM] = instr_meter_mmm_exec,
7910 [INSTR_METER_MMI] = instr_meter_mmi_exec,
7911 [INSTR_METER_IHM] = instr_meter_ihm_exec,
7912 [INSTR_METER_IHI] = instr_meter_ihi_exec,
7913 [INSTR_METER_IMM] = instr_meter_imm_exec,
7914 [INSTR_METER_IMI] = instr_meter_imi_exec,
7916 [INSTR_TABLE] = instr_table_exec,
7917 [INSTR_SELECTOR] = instr_selector_exec,
7918 [INSTR_LEARNER] = instr_learner_exec,
7919 [INSTR_LEARNER_LEARN] = instr_learn_exec,
7920 [INSTR_LEARNER_FORGET] = instr_forget_exec,
7921 [INSTR_EXTERN_OBJ] = instr_extern_obj_exec,
7922 [INSTR_EXTERN_FUNC] = instr_extern_func_exec,
7924 [INSTR_JMP] = instr_jmp_exec,
7925 [INSTR_JMP_VALID] = instr_jmp_valid_exec,
7926 [INSTR_JMP_INVALID] = instr_jmp_invalid_exec,
7927 [INSTR_JMP_HIT] = instr_jmp_hit_exec,
7928 [INSTR_JMP_MISS] = instr_jmp_miss_exec,
7929 [INSTR_JMP_ACTION_HIT] = instr_jmp_action_hit_exec,
7930 [INSTR_JMP_ACTION_MISS] = instr_jmp_action_miss_exec,
7932 [INSTR_JMP_EQ] = instr_jmp_eq_exec,
7933 [INSTR_JMP_EQ_MH] = instr_jmp_eq_mh_exec,
7934 [INSTR_JMP_EQ_HM] = instr_jmp_eq_hm_exec,
7935 [INSTR_JMP_EQ_HH] = instr_jmp_eq_hh_exec,
7936 [INSTR_JMP_EQ_I] = instr_jmp_eq_i_exec,
7938 [INSTR_JMP_NEQ] = instr_jmp_neq_exec,
7939 [INSTR_JMP_NEQ_MH] = instr_jmp_neq_mh_exec,
7940 [INSTR_JMP_NEQ_HM] = instr_jmp_neq_hm_exec,
7941 [INSTR_JMP_NEQ_HH] = instr_jmp_neq_hh_exec,
7942 [INSTR_JMP_NEQ_I] = instr_jmp_neq_i_exec,
7944 [INSTR_JMP_LT] = instr_jmp_lt_exec,
7945 [INSTR_JMP_LT_MH] = instr_jmp_lt_mh_exec,
7946 [INSTR_JMP_LT_HM] = instr_jmp_lt_hm_exec,
7947 [INSTR_JMP_LT_HH] = instr_jmp_lt_hh_exec,
7948 [INSTR_JMP_LT_MI] = instr_jmp_lt_mi_exec,
7949 [INSTR_JMP_LT_HI] = instr_jmp_lt_hi_exec,
7951 [INSTR_JMP_GT] = instr_jmp_gt_exec,
7952 [INSTR_JMP_GT_MH] = instr_jmp_gt_mh_exec,
7953 [INSTR_JMP_GT_HM] = instr_jmp_gt_hm_exec,
7954 [INSTR_JMP_GT_HH] = instr_jmp_gt_hh_exec,
7955 [INSTR_JMP_GT_MI] = instr_jmp_gt_mi_exec,
7956 [INSTR_JMP_GT_HI] = instr_jmp_gt_hi_exec,
7958 [INSTR_RETURN] = instr_return_exec,
7962 instr_exec(struct rte_swx_pipeline *p)
7964 struct thread *t = &p->threads[p->thread_id];
7965 struct instruction *ip = t->ip;
7966 instr_exec_t instr = instruction_table[ip->type];
7974 static struct action *
7975 action_find(struct rte_swx_pipeline *p, const char *name)
7977 struct action *elem;
7982 TAILQ_FOREACH(elem, &p->actions, node)
7983 if (strcmp(elem->name, name) == 0)
7989 static struct action *
7990 action_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
7992 struct action *action = NULL;
7994 TAILQ_FOREACH(action, &p->actions, node)
7995 if (action->id == id)
8001 static struct field *
8002 action_field_find(struct action *a, const char *name)
8004 return a->st ? struct_type_field_find(a->st, name) : NULL;
8007 static struct field *
8008 action_field_parse(struct action *action, const char *name)
8010 if (name[0] != 't' || name[1] != '.')
8013 return action_field_find(action, &name[2]);
8017 action_has_nbo_args(struct action *a)
8021 /* Return if the action does not have any args. */
8023 return 0; /* FALSE */
8025 for (i = 0; i < a->st->n_fields; i++)
8026 if (a->args_endianness[i])
8027 return 1; /* TRUE */
8029 return 0; /* FALSE */
8033 action_does_learning(struct action *a)
8037 for (i = 0; i < a->n_instructions; i++)
8038 switch (a->instructions[i].type) {
8039 case INSTR_LEARNER_LEARN:
8040 return 1; /* TRUE */
8042 case INSTR_LEARNER_FORGET:
8043 return 1; /* TRUE */
8049 return 0; /* FALSE */
8053 rte_swx_pipeline_action_config(struct rte_swx_pipeline *p,
8055 const char *args_struct_type_name,
8056 const char **instructions,
8057 uint32_t n_instructions)
8059 struct struct_type *args_struct_type = NULL;
8065 CHECK_NAME(name, EINVAL);
8066 CHECK(!action_find(p, name), EEXIST);
8068 if (args_struct_type_name) {
8069 CHECK_NAME(args_struct_type_name, EINVAL);
8070 args_struct_type = struct_type_find(p, args_struct_type_name);
8071 CHECK(args_struct_type, EINVAL);
8072 CHECK(!args_struct_type->var_size, EINVAL);
8075 /* Node allocation. */
8076 a = calloc(1, sizeof(struct action));
8078 if (args_struct_type) {
8079 a->args_endianness = calloc(args_struct_type->n_fields, sizeof(int));
8080 if (!a->args_endianness) {
8086 /* Node initialization. */
8087 strcpy(a->name, name);
8088 a->st = args_struct_type;
8089 a->id = p->n_actions;
8091 /* Instruction translation. */
8092 err = instruction_config(p, a, instructions, n_instructions);
8094 free(a->args_endianness);
8099 /* Node add to tailq. */
8100 TAILQ_INSERT_TAIL(&p->actions, a, node);
8107 action_build(struct rte_swx_pipeline *p)
8109 struct action *action;
8111 p->action_instructions = calloc(p->n_actions,
8112 sizeof(struct instruction *));
8113 CHECK(p->action_instructions, ENOMEM);
8115 TAILQ_FOREACH(action, &p->actions, node)
8116 p->action_instructions[action->id] = action->instructions;
8122 action_build_free(struct rte_swx_pipeline *p)
8124 free(p->action_instructions);
8125 p->action_instructions = NULL;
8129 action_free(struct rte_swx_pipeline *p)
8131 action_build_free(p);
8134 struct action *action;
8136 action = TAILQ_FIRST(&p->actions);
8140 TAILQ_REMOVE(&p->actions, action, node);
8141 free(action->instructions);
8147 action_arg_src_mov_count(struct action *a,
8149 struct instruction *instructions,
8150 struct instruction_data *instruction_data,
8151 uint32_t n_instructions)
8153 uint32_t offset, n_users = 0, i;
8156 (arg_id >= a->st->n_fields) ||
8158 !instruction_data ||
8162 offset = a->st->fields[arg_id].offset / 8;
8164 for (i = 0; i < n_instructions; i++) {
8165 struct instruction *instr = &instructions[i];
8166 struct instruction_data *data = &instruction_data[i];
8168 if (data->invalid ||
8169 ((instr->type != INSTR_MOV) && (instr->type != INSTR_MOV_HM)) ||
8170 instr->mov.src.struct_id ||
8171 (instr->mov.src.offset != offset))
8183 static struct table_type *
8184 table_type_find(struct rte_swx_pipeline *p, const char *name)
8186 struct table_type *elem;
8188 TAILQ_FOREACH(elem, &p->table_types, node)
8189 if (strcmp(elem->name, name) == 0)
8195 static struct table_type *
8196 table_type_resolve(struct rte_swx_pipeline *p,
8197 const char *recommended_type_name,
8198 enum rte_swx_table_match_type match_type)
8200 struct table_type *elem;
8202 /* Only consider the recommended type if the match type is correct. */
8203 if (recommended_type_name)
8204 TAILQ_FOREACH(elem, &p->table_types, node)
8205 if (!strcmp(elem->name, recommended_type_name) &&
8206 (elem->match_type == match_type))
8209 /* Ignore the recommended type and get the first element with this match
8212 TAILQ_FOREACH(elem, &p->table_types, node)
8213 if (elem->match_type == match_type)
8219 static struct table *
8220 table_find(struct rte_swx_pipeline *p, const char *name)
8224 TAILQ_FOREACH(elem, &p->tables, node)
8225 if (strcmp(elem->name, name) == 0)
8231 static struct table *
8232 table_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8234 struct table *table = NULL;
8236 TAILQ_FOREACH(table, &p->tables, node)
8237 if (table->id == id)
8244 rte_swx_pipeline_table_type_register(struct rte_swx_pipeline *p,
8246 enum rte_swx_table_match_type match_type,
8247 struct rte_swx_table_ops *ops)
8249 struct table_type *elem;
8253 CHECK_NAME(name, EINVAL);
8254 CHECK(!table_type_find(p, name), EEXIST);
8257 CHECK(ops->create, EINVAL);
8258 CHECK(ops->lkp, EINVAL);
8259 CHECK(ops->free, EINVAL);
8261 /* Node allocation. */
8262 elem = calloc(1, sizeof(struct table_type));
8263 CHECK(elem, ENOMEM);
8265 /* Node initialization. */
8266 strcpy(elem->name, name);
8267 elem->match_type = match_type;
8268 memcpy(&elem->ops, ops, sizeof(*ops));
8270 /* Node add to tailq. */
8271 TAILQ_INSERT_TAIL(&p->table_types, elem, node);
8277 table_match_type_resolve(struct rte_swx_match_field_params *fields,
8279 enum rte_swx_table_match_type *match_type)
8281 uint32_t n_fields_em = 0, n_fields_lpm = 0, i;
8283 for (i = 0; i < n_fields; i++) {
8284 struct rte_swx_match_field_params *f = &fields[i];
8286 if (f->match_type == RTE_SWX_TABLE_MATCH_EXACT)
8289 if (f->match_type == RTE_SWX_TABLE_MATCH_LPM)
8293 if ((n_fields_lpm > 1) ||
8294 (n_fields_lpm && (n_fields_em != n_fields - 1)))
8297 *match_type = (n_fields_em == n_fields) ?
8298 RTE_SWX_TABLE_MATCH_EXACT :
8299 RTE_SWX_TABLE_MATCH_WILDCARD;
8305 table_match_fields_check(struct rte_swx_pipeline *p,
8306 struct rte_swx_pipeline_table_params *params,
8307 struct header **header)
8309 struct header *h0 = NULL;
8310 struct field *hf, *mf;
8311 uint32_t *offset = NULL, i;
8314 /* Return if no match fields. */
8315 if (!params->n_fields) {
8316 if (params->fields) {
8327 /* Memory allocation. */
8328 offset = calloc(params->n_fields, sizeof(uint32_t));
8334 /* Check that all the match fields belong to either the same header or
8337 hf = header_field_parse(p, params->fields[0].name, &h0);
8338 mf = metadata_field_parse(p, params->fields[0].name);
8339 if ((!hf && !mf) || (hf && hf->var_size)) {
8344 offset[0] = h0 ? hf->offset : mf->offset;
8346 for (i = 1; i < params->n_fields; i++)
8350 hf = header_field_parse(p, params->fields[i].name, &h);
8351 if (!hf || (h->id != h0->id) || hf->var_size) {
8356 offset[i] = hf->offset;
8358 mf = metadata_field_parse(p, params->fields[i].name);
8364 offset[i] = mf->offset;
8367 /* Check that there are no duplicated match fields. */
8368 for (i = 0; i < params->n_fields; i++) {
8371 for (j = 0; j < i; j++)
8372 if (offset[j] == offset[i]) {
8388 rte_swx_pipeline_table_config(struct rte_swx_pipeline *p,
8390 struct rte_swx_pipeline_table_params *params,
8391 const char *recommended_table_type_name,
8395 struct table_type *type;
8397 struct action *default_action;
8398 struct header *header = NULL;
8399 uint32_t action_data_size_max = 0, i;
8404 CHECK_NAME(name, EINVAL);
8405 CHECK(!table_find(p, name), EEXIST);
8406 CHECK(!selector_find(p, name), EEXIST);
8407 CHECK(!learner_find(p, name), EEXIST);
8409 CHECK(params, EINVAL);
8412 status = table_match_fields_check(p, params, &header);
8416 /* Action checks. */
8417 CHECK(params->n_actions, EINVAL);
8418 CHECK(params->action_names, EINVAL);
8419 for (i = 0; i < params->n_actions; i++) {
8420 const char *action_name = params->action_names[i];
8422 uint32_t action_data_size;
8424 CHECK_NAME(action_name, EINVAL);
8426 a = action_find(p, action_name);
8428 CHECK(!action_does_learning(a), EINVAL);
8430 action_data_size = a->st ? a->st->n_bits / 8 : 0;
8431 if (action_data_size > action_data_size_max)
8432 action_data_size_max = action_data_size;
8435 CHECK_NAME(params->default_action_name, EINVAL);
8436 for (i = 0; i < p->n_actions; i++)
8437 if (!strcmp(params->action_names[i],
8438 params->default_action_name))
8440 CHECK(i < params->n_actions, EINVAL);
8441 default_action = action_find(p, params->default_action_name);
8442 CHECK((default_action->st && params->default_action_data) ||
8443 !params->default_action_data, EINVAL);
8445 /* Table type checks. */
8446 if (recommended_table_type_name)
8447 CHECK_NAME(recommended_table_type_name, EINVAL);
8449 if (params->n_fields) {
8450 enum rte_swx_table_match_type match_type;
8452 status = table_match_type_resolve(params->fields, params->n_fields, &match_type);
8456 type = table_type_resolve(p, recommended_table_type_name, match_type);
8457 CHECK(type, EINVAL);
8462 /* Memory allocation. */
8463 t = calloc(1, sizeof(struct table));
8466 t->fields = calloc(params->n_fields, sizeof(struct match_field));
8472 t->actions = calloc(params->n_actions, sizeof(struct action *));
8479 if (action_data_size_max) {
8480 t->default_action_data = calloc(1, action_data_size_max);
8481 if (!t->default_action_data) {
8489 /* Node initialization. */
8490 strcpy(t->name, name);
8491 if (args && args[0])
8492 strcpy(t->args, args);
8495 for (i = 0; i < params->n_fields; i++) {
8496 struct rte_swx_match_field_params *field = ¶ms->fields[i];
8497 struct match_field *f = &t->fields[i];
8499 f->match_type = field->match_type;
8501 header_field_parse(p, field->name, NULL) :
8502 metadata_field_parse(p, field->name);
8504 t->n_fields = params->n_fields;
8507 for (i = 0; i < params->n_actions; i++)
8508 t->actions[i] = action_find(p, params->action_names[i]);
8509 t->default_action = default_action;
8510 if (default_action->st)
8511 memcpy(t->default_action_data,
8512 params->default_action_data,
8513 default_action->st->n_bits / 8);
8514 t->n_actions = params->n_actions;
8515 t->default_action_is_const = params->default_action_is_const;
8516 t->action_data_size_max = action_data_size_max;
8519 t->id = p->n_tables;
8521 /* Node add to tailq. */
8522 TAILQ_INSERT_TAIL(&p->tables, t, node);
8528 static struct rte_swx_table_params *
8529 table_params_get(struct table *table)
8531 struct rte_swx_table_params *params;
8532 struct field *first, *last;
8534 uint32_t key_size, key_offset, action_data_size, i;
8536 /* Memory allocation. */
8537 params = calloc(1, sizeof(struct rte_swx_table_params));
8541 /* Find first (smallest offset) and last (biggest offset) match fields. */
8542 first = table->fields[0].field;
8543 last = table->fields[0].field;
8545 for (i = 0; i < table->n_fields; i++) {
8546 struct field *f = table->fields[i].field;
8548 if (f->offset < first->offset)
8551 if (f->offset > last->offset)
8555 /* Key offset and size. */
8556 key_offset = first->offset / 8;
8557 key_size = (last->offset + last->n_bits - first->offset) / 8;
8559 /* Memory allocation. */
8560 key_mask = calloc(1, key_size);
8567 for (i = 0; i < table->n_fields; i++) {
8568 struct field *f = table->fields[i].field;
8569 uint32_t start = (f->offset - first->offset) / 8;
8570 size_t size = f->n_bits / 8;
8572 memset(&key_mask[start], 0xFF, size);
8575 /* Action data size. */
8576 action_data_size = 0;
8577 for (i = 0; i < table->n_actions; i++) {
8578 struct action *action = table->actions[i];
8579 uint32_t ads = action->st ? action->st->n_bits / 8 : 0;
8581 if (ads > action_data_size)
8582 action_data_size = ads;
8586 params->match_type = table->type->match_type;
8587 params->key_size = key_size;
8588 params->key_offset = key_offset;
8589 params->key_mask0 = key_mask;
8590 params->action_data_size = action_data_size;
8591 params->n_keys_max = table->size;
8597 table_params_free(struct rte_swx_table_params *params)
8602 free(params->key_mask0);
8607 table_stub_lkp(void *table __rte_unused,
8608 void *mailbox __rte_unused,
8609 uint8_t **key __rte_unused,
8610 uint64_t *action_id __rte_unused,
8611 uint8_t **action_data __rte_unused,
8615 return 1; /* DONE. */
8619 table_build(struct rte_swx_pipeline *p)
8623 /* Per pipeline: table statistics. */
8624 p->table_stats = calloc(p->n_tables, sizeof(struct table_statistics));
8625 CHECK(p->table_stats, ENOMEM);
8627 for (i = 0; i < p->n_tables; i++) {
8628 p->table_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
8629 CHECK(p->table_stats[i].n_pkts_action, ENOMEM);
8632 /* Per thread: table runt-time. */
8633 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8634 struct thread *t = &p->threads[i];
8635 struct table *table;
8637 t->tables = calloc(p->n_tables, sizeof(struct table_runtime));
8638 CHECK(t->tables, ENOMEM);
8640 TAILQ_FOREACH(table, &p->tables, node) {
8641 struct table_runtime *r = &t->tables[table->id];
8646 size = table->type->ops.mailbox_size_get();
8649 r->func = table->type->ops.lkp;
8653 r->mailbox = calloc(1, size);
8654 CHECK(r->mailbox, ENOMEM);
8658 r->key = table->header ?
8659 &t->structs[table->header->struct_id] :
8660 &t->structs[p->metadata_struct_id];
8662 r->func = table_stub_lkp;
8671 table_build_free(struct rte_swx_pipeline *p)
8675 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8676 struct thread *t = &p->threads[i];
8682 for (j = 0; j < p->n_tables; j++) {
8683 struct table_runtime *r = &t->tables[j];
8692 if (p->table_stats) {
8693 for (i = 0; i < p->n_tables; i++)
8694 free(p->table_stats[i].n_pkts_action);
8696 free(p->table_stats);
8701 table_free(struct rte_swx_pipeline *p)
8703 table_build_free(p);
8709 elem = TAILQ_FIRST(&p->tables);
8713 TAILQ_REMOVE(&p->tables, elem, node);
8715 free(elem->actions);
8716 free(elem->default_action_data);
8722 struct table_type *elem;
8724 elem = TAILQ_FIRST(&p->table_types);
8728 TAILQ_REMOVE(&p->table_types, elem, node);
8736 static struct selector *
8737 selector_find(struct rte_swx_pipeline *p, const char *name)
8741 TAILQ_FOREACH(s, &p->selectors, node)
8742 if (strcmp(s->name, name) == 0)
8748 static struct selector *
8749 selector_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8751 struct selector *s = NULL;
8753 TAILQ_FOREACH(s, &p->selectors, node)
8761 selector_fields_check(struct rte_swx_pipeline *p,
8762 struct rte_swx_pipeline_selector_params *params,
8763 struct header **header)
8765 struct header *h0 = NULL;
8766 struct field *hf, *mf;
8769 /* Return if no selector fields. */
8770 if (!params->n_selector_fields || !params->selector_field_names)
8773 /* Check that all the selector fields either belong to the same header
8774 * or are all meta-data fields.
8776 hf = header_field_parse(p, params->selector_field_names[0], &h0);
8777 mf = metadata_field_parse(p, params->selector_field_names[0]);
8781 for (i = 1; i < params->n_selector_fields; i++)
8785 hf = header_field_parse(p, params->selector_field_names[i], &h);
8786 if (!hf || (h->id != h0->id))
8789 mf = metadata_field_parse(p, params->selector_field_names[i]);
8794 /* Check that there are no duplicated match fields. */
8795 for (i = 0; i < params->n_selector_fields; i++) {
8796 const char *field_name = params->selector_field_names[i];
8799 for (j = i + 1; j < params->n_selector_fields; j++)
8800 if (!strcmp(params->selector_field_names[j], field_name))
8812 rte_swx_pipeline_selector_config(struct rte_swx_pipeline *p,
8814 struct rte_swx_pipeline_selector_params *params)
8817 struct header *selector_header = NULL;
8818 struct field *group_id_field, *member_id_field;
8824 CHECK_NAME(name, EINVAL);
8825 CHECK(!table_find(p, name), EEXIST);
8826 CHECK(!selector_find(p, name), EEXIST);
8827 CHECK(!learner_find(p, name), EEXIST);
8829 CHECK(params, EINVAL);
8831 CHECK_NAME(params->group_id_field_name, EINVAL);
8832 group_id_field = metadata_field_parse(p, params->group_id_field_name);
8833 CHECK(group_id_field, EINVAL);
8835 for (i = 0; i < params->n_selector_fields; i++) {
8836 const char *field_name = params->selector_field_names[i];
8838 CHECK_NAME(field_name, EINVAL);
8840 status = selector_fields_check(p, params, &selector_header);
8844 CHECK_NAME(params->member_id_field_name, EINVAL);
8845 member_id_field = metadata_field_parse(p, params->member_id_field_name);
8846 CHECK(member_id_field, EINVAL);
8848 CHECK(params->n_groups_max, EINVAL);
8850 CHECK(params->n_members_per_group_max, EINVAL);
8852 /* Memory allocation. */
8853 s = calloc(1, sizeof(struct selector));
8859 s->selector_fields = calloc(params->n_selector_fields, sizeof(struct field *));
8860 if (!s->selector_fields) {
8865 /* Node initialization. */
8866 strcpy(s->name, name);
8868 s->group_id_field = group_id_field;
8870 for (i = 0; i < params->n_selector_fields; i++) {
8871 const char *field_name = params->selector_field_names[i];
8873 s->selector_fields[i] = selector_header ?
8874 header_field_parse(p, field_name, NULL) :
8875 metadata_field_parse(p, field_name);
8878 s->n_selector_fields = params->n_selector_fields;
8880 s->selector_header = selector_header;
8882 s->member_id_field = member_id_field;
8884 s->n_groups_max = params->n_groups_max;
8886 s->n_members_per_group_max = params->n_members_per_group_max;
8888 s->id = p->n_selectors;
8890 /* Node add to tailq. */
8891 TAILQ_INSERT_TAIL(&p->selectors, s, node);
8900 free(s->selector_fields);
8908 selector_params_free(struct rte_swx_table_selector_params *params)
8913 free(params->selector_mask);
8918 static struct rte_swx_table_selector_params *
8919 selector_table_params_get(struct selector *s)
8921 struct rte_swx_table_selector_params *params = NULL;
8922 struct field *first, *last;
8925 /* Memory allocation. */
8926 params = calloc(1, sizeof(struct rte_swx_table_selector_params));
8931 params->group_id_offset = s->group_id_field->offset / 8;
8933 /* Find first (smallest offset) and last (biggest offset) selector fields. */
8934 first = s->selector_fields[0];
8935 last = s->selector_fields[0];
8937 for (i = 0; i < s->n_selector_fields; i++) {
8938 struct field *f = s->selector_fields[i];
8940 if (f->offset < first->offset)
8943 if (f->offset > last->offset)
8947 /* Selector offset and size. */
8948 params->selector_offset = first->offset / 8;
8949 params->selector_size = (last->offset + last->n_bits - first->offset) / 8;
8951 /* Memory allocation. */
8952 params->selector_mask = calloc(1, params->selector_size);
8953 if (!params->selector_mask)
8956 /* Selector mask. */
8957 for (i = 0; i < s->n_selector_fields; i++) {
8958 struct field *f = s->selector_fields[i];
8959 uint32_t start = (f->offset - first->offset) / 8;
8960 size_t size = f->n_bits / 8;
8962 memset(¶ms->selector_mask[start], 0xFF, size);
8966 params->member_id_offset = s->member_id_field->offset / 8;
8968 /* Maximum number of groups. */
8969 params->n_groups_max = s->n_groups_max;
8971 /* Maximum number of members per group. */
8972 params->n_members_per_group_max = s->n_members_per_group_max;
8977 selector_params_free(params);
8982 selector_build_free(struct rte_swx_pipeline *p)
8986 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8987 struct thread *t = &p->threads[i];
8993 for (j = 0; j < p->n_selectors; j++) {
8994 struct selector_runtime *r = &t->selectors[j];
9000 t->selectors = NULL;
9003 free(p->selector_stats);
9004 p->selector_stats = NULL;
9008 selector_build(struct rte_swx_pipeline *p)
9013 /* Per pipeline: selector statistics. */
9014 p->selector_stats = calloc(p->n_selectors, sizeof(struct selector_statistics));
9015 if (!p->selector_stats) {
9020 /* Per thread: selector run-time. */
9021 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9022 struct thread *t = &p->threads[i];
9025 t->selectors = calloc(p->n_selectors, sizeof(struct selector_runtime));
9026 if (!t->selectors) {
9031 TAILQ_FOREACH(s, &p->selectors, node) {
9032 struct selector_runtime *r = &t->selectors[s->id];
9036 size = rte_swx_table_selector_mailbox_size_get();
9038 r->mailbox = calloc(1, size);
9045 /* r->group_id_buffer. */
9046 r->group_id_buffer = &t->structs[p->metadata_struct_id];
9048 /* r->selector_buffer. */
9049 r->selector_buffer = s->selector_header ?
9050 &t->structs[s->selector_header->struct_id] :
9051 &t->structs[p->metadata_struct_id];
9053 /* r->member_id_buffer. */
9054 r->member_id_buffer = &t->structs[p->metadata_struct_id];
9061 selector_build_free(p);
9066 selector_free(struct rte_swx_pipeline *p)
9068 selector_build_free(p);
9070 /* Selector tables. */
9072 struct selector *elem;
9074 elem = TAILQ_FIRST(&p->selectors);
9078 TAILQ_REMOVE(&p->selectors, elem, node);
9079 free(elem->selector_fields);
9087 static struct learner *
9088 learner_find(struct rte_swx_pipeline *p, const char *name)
9092 TAILQ_FOREACH(l, &p->learners, node)
9093 if (!strcmp(l->name, name))
9099 static struct learner *
9100 learner_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9102 struct learner *l = NULL;
9104 TAILQ_FOREACH(l, &p->learners, node)
9112 learner_match_fields_check(struct rte_swx_pipeline *p,
9113 struct rte_swx_pipeline_learner_params *params,
9114 struct header **header)
9116 struct header *h0 = NULL;
9117 struct field *hf, *mf;
9120 /* Return if no match fields. */
9121 if (!params->n_fields || !params->field_names)
9124 /* Check that all the match fields either belong to the same header
9125 * or are all meta-data fields.
9127 hf = header_field_parse(p, params->field_names[0], &h0);
9128 mf = metadata_field_parse(p, params->field_names[0]);
9132 for (i = 1; i < params->n_fields; i++)
9136 hf = header_field_parse(p, params->field_names[i], &h);
9137 if (!hf || (h->id != h0->id))
9140 mf = metadata_field_parse(p, params->field_names[i]);
9145 /* Check that there are no duplicated match fields. */
9146 for (i = 0; i < params->n_fields; i++) {
9147 const char *field_name = params->field_names[i];
9150 for (j = i + 1; j < params->n_fields; j++)
9151 if (!strcmp(params->field_names[j], field_name))
9163 learner_action_args_check(struct rte_swx_pipeline *p, struct action *a, const char *mf_name)
9165 struct struct_type *mst = p->metadata_st, *ast = a->st;
9166 struct field *mf, *af;
9176 /* Check that mf_name is the name of a valid meta-data field. */
9177 CHECK_NAME(mf_name, EINVAL);
9178 mf = metadata_field_parse(p, mf_name);
9181 /* Check that there are enough meta-data fields, starting with the mf_name field, to cover
9182 * all the action arguments.
9184 mf_pos = mf - mst->fields;
9185 CHECK(mst->n_fields - mf_pos >= ast->n_fields, EINVAL);
9187 /* Check that the size of each of the identified meta-data fields matches exactly the size
9188 * of the corresponding action argument.
9190 for (i = 0; i < ast->n_fields; i++) {
9191 mf = &mst->fields[mf_pos + i];
9192 af = &ast->fields[i];
9194 CHECK(mf->n_bits == af->n_bits, EINVAL);
9201 learner_action_learning_check(struct rte_swx_pipeline *p,
9202 struct action *action,
9203 const char **action_names,
9208 /* For each "learn" instruction of the current action, check that the learned action (i.e.
9209 * the action passed as argument to the "learn" instruction) is also enabled for the
9210 * current learner table.
9212 for (i = 0; i < action->n_instructions; i++) {
9213 struct instruction *instr = &action->instructions[i];
9214 uint32_t found = 0, j;
9216 if (instr->type != INSTR_LEARNER_LEARN)
9219 for (j = 0; j < n_actions; j++) {
9222 a = action_find(p, action_names[j]);
9226 if (a->id == instr->learn.action_id)
9238 rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p,
9240 struct rte_swx_pipeline_learner_params *params,
9244 struct learner *l = NULL;
9245 struct action *default_action;
9246 struct header *header = NULL;
9247 uint32_t action_data_size_max = 0, i;
9252 CHECK_NAME(name, EINVAL);
9253 CHECK(!table_find(p, name), EEXIST);
9254 CHECK(!selector_find(p, name), EEXIST);
9255 CHECK(!learner_find(p, name), EEXIST);
9257 CHECK(params, EINVAL);
9260 status = learner_match_fields_check(p, params, &header);
9264 /* Action checks. */
9265 CHECK(params->n_actions, EINVAL);
9267 CHECK(params->action_names, EINVAL);
9268 for (i = 0; i < params->n_actions; i++) {
9269 const char *action_name = params->action_names[i];
9270 const char *action_field_name = params->action_field_names[i];
9272 uint32_t action_data_size;
9274 CHECK_NAME(action_name, EINVAL);
9276 a = action_find(p, action_name);
9279 status = learner_action_args_check(p, a, action_field_name);
9283 status = learner_action_learning_check(p,
9285 params->action_names,
9290 action_data_size = a->st ? a->st->n_bits / 8 : 0;
9291 if (action_data_size > action_data_size_max)
9292 action_data_size_max = action_data_size;
9295 CHECK_NAME(params->default_action_name, EINVAL);
9296 for (i = 0; i < p->n_actions; i++)
9297 if (!strcmp(params->action_names[i],
9298 params->default_action_name))
9300 CHECK(i < params->n_actions, EINVAL);
9302 default_action = action_find(p, params->default_action_name);
9303 CHECK((default_action->st && params->default_action_data) ||
9304 !params->default_action_data, EINVAL);
9306 /* Any other checks. */
9307 CHECK(size, EINVAL);
9308 CHECK(timeout, EINVAL);
9310 /* Memory allocation. */
9311 l = calloc(1, sizeof(struct learner));
9315 l->fields = calloc(params->n_fields, sizeof(struct field *));
9319 l->actions = calloc(params->n_actions, sizeof(struct action *));
9323 l->action_arg = calloc(params->n_actions, sizeof(struct field *));
9327 if (action_data_size_max) {
9328 l->default_action_data = calloc(1, action_data_size_max);
9329 if (!l->default_action_data)
9333 /* Node initialization. */
9334 strcpy(l->name, name);
9336 for (i = 0; i < params->n_fields; i++) {
9337 const char *field_name = params->field_names[i];
9339 l->fields[i] = header ?
9340 header_field_parse(p, field_name, NULL) :
9341 metadata_field_parse(p, field_name);
9344 l->n_fields = params->n_fields;
9348 for (i = 0; i < params->n_actions; i++) {
9349 const char *mf_name = params->action_field_names[i];
9351 l->actions[i] = action_find(p, params->action_names[i]);
9353 l->action_arg[i] = mf_name ? metadata_field_parse(p, mf_name) : NULL;
9356 l->default_action = default_action;
9358 if (default_action->st)
9359 memcpy(l->default_action_data,
9360 params->default_action_data,
9361 default_action->st->n_bits / 8);
9363 l->n_actions = params->n_actions;
9365 l->default_action_is_const = params->default_action_is_const;
9367 l->action_data_size_max = action_data_size_max;
9371 l->timeout = timeout;
9373 l->id = p->n_learners;
9375 /* Node add to tailq. */
9376 TAILQ_INSERT_TAIL(&p->learners, l, node);
9385 free(l->action_arg);
9394 learner_params_free(struct rte_swx_table_learner_params *params)
9399 free(params->key_mask0);
9404 static struct rte_swx_table_learner_params *
9405 learner_params_get(struct learner *l)
9407 struct rte_swx_table_learner_params *params = NULL;
9408 struct field *first, *last;
9411 /* Memory allocation. */
9412 params = calloc(1, sizeof(struct rte_swx_table_learner_params));
9416 /* Find first (smallest offset) and last (biggest offset) match fields. */
9417 first = l->fields[0];
9418 last = l->fields[0];
9420 for (i = 0; i < l->n_fields; i++) {
9421 struct field *f = l->fields[i];
9423 if (f->offset < first->offset)
9426 if (f->offset > last->offset)
9430 /* Key offset and size. */
9431 params->key_offset = first->offset / 8;
9432 params->key_size = (last->offset + last->n_bits - first->offset) / 8;
9434 /* Memory allocation. */
9435 params->key_mask0 = calloc(1, params->key_size);
9436 if (!params->key_mask0)
9440 for (i = 0; i < l->n_fields; i++) {
9441 struct field *f = l->fields[i];
9442 uint32_t start = (f->offset - first->offset) / 8;
9443 size_t size = f->n_bits / 8;
9445 memset(¶ms->key_mask0[start], 0xFF, size);
9448 /* Action data size. */
9449 params->action_data_size = l->action_data_size_max;
9451 /* Maximum number of keys. */
9452 params->n_keys_max = l->size;
9455 params->key_timeout = l->timeout;
9460 learner_params_free(params);
9465 learner_build_free(struct rte_swx_pipeline *p)
9469 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9470 struct thread *t = &p->threads[i];
9476 for (j = 0; j < p->n_learners; j++) {
9477 struct learner_runtime *r = &t->learners[j];
9480 free(r->action_data);
9487 if (p->learner_stats) {
9488 for (i = 0; i < p->n_learners; i++)
9489 free(p->learner_stats[i].n_pkts_action);
9491 free(p->learner_stats);
9496 learner_build(struct rte_swx_pipeline *p)
9501 /* Per pipeline: learner statistics. */
9502 p->learner_stats = calloc(p->n_learners, sizeof(struct learner_statistics));
9503 CHECK(p->learner_stats, ENOMEM);
9505 for (i = 0; i < p->n_learners; i++) {
9506 p->learner_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
9507 CHECK(p->learner_stats[i].n_pkts_action, ENOMEM);
9510 /* Per thread: learner run-time. */
9511 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9512 struct thread *t = &p->threads[i];
9515 t->learners = calloc(p->n_learners, sizeof(struct learner_runtime));
9521 TAILQ_FOREACH(l, &p->learners, node) {
9522 struct learner_runtime *r = &t->learners[l->id];
9527 size = rte_swx_table_learner_mailbox_size_get();
9529 r->mailbox = calloc(1, size);
9537 r->key = l->header ?
9538 &t->structs[l->header->struct_id] :
9539 &t->structs[p->metadata_struct_id];
9541 /* r->action_data. */
9542 r->action_data = calloc(p->n_actions, sizeof(uint8_t *));
9543 if (!r->action_data) {
9548 for (j = 0; j < l->n_actions; j++) {
9549 struct action *a = l->actions[j];
9550 struct field *mf = l->action_arg[j];
9551 uint8_t *m = t->structs[p->metadata_struct_id];
9553 r->action_data[a->id] = mf ? &m[mf->offset / 8] : NULL;
9561 learner_build_free(p);
9566 learner_free(struct rte_swx_pipeline *p)
9568 learner_build_free(p);
9570 /* Learner tables. */
9574 l = TAILQ_FIRST(&p->learners);
9578 TAILQ_REMOVE(&p->learners, l, node);
9581 free(l->action_arg);
9582 free(l->default_action_data);
9591 table_state_build(struct rte_swx_pipeline *p)
9593 struct table *table;
9597 p->table_state = calloc(p->n_tables + p->n_selectors,
9598 sizeof(struct rte_swx_table_state));
9599 CHECK(p->table_state, ENOMEM);
9601 TAILQ_FOREACH(table, &p->tables, node) {
9602 struct rte_swx_table_state *ts = &p->table_state[table->id];
9605 struct rte_swx_table_params *params;
9608 params = table_params_get(table);
9609 CHECK(params, ENOMEM);
9611 ts->obj = table->type->ops.create(params,
9616 table_params_free(params);
9617 CHECK(ts->obj, ENODEV);
9620 /* ts->default_action_data. */
9621 if (table->action_data_size_max) {
9622 ts->default_action_data =
9623 malloc(table->action_data_size_max);
9624 CHECK(ts->default_action_data, ENOMEM);
9626 memcpy(ts->default_action_data,
9627 table->default_action_data,
9628 table->action_data_size_max);
9631 /* ts->default_action_id. */
9632 ts->default_action_id = table->default_action->id;
9635 TAILQ_FOREACH(s, &p->selectors, node) {
9636 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + s->id];
9637 struct rte_swx_table_selector_params *params;
9640 params = selector_table_params_get(s);
9641 CHECK(params, ENOMEM);
9643 ts->obj = rte_swx_table_selector_create(params, NULL, p->numa_node);
9645 selector_params_free(params);
9646 CHECK(ts->obj, ENODEV);
9649 TAILQ_FOREACH(l, &p->learners, node) {
9650 struct rte_swx_table_state *ts = &p->table_state[p->n_tables +
9651 p->n_selectors + l->id];
9652 struct rte_swx_table_learner_params *params;
9655 params = learner_params_get(l);
9656 CHECK(params, ENOMEM);
9658 ts->obj = rte_swx_table_learner_create(params, p->numa_node);
9659 learner_params_free(params);
9660 CHECK(ts->obj, ENODEV);
9662 /* ts->default_action_data. */
9663 if (l->action_data_size_max) {
9664 ts->default_action_data = malloc(l->action_data_size_max);
9665 CHECK(ts->default_action_data, ENOMEM);
9667 memcpy(ts->default_action_data,
9668 l->default_action_data,
9669 l->action_data_size_max);
9672 /* ts->default_action_id. */
9673 ts->default_action_id = l->default_action->id;
9680 table_state_build_free(struct rte_swx_pipeline *p)
9684 if (!p->table_state)
9687 for (i = 0; i < p->n_tables; i++) {
9688 struct rte_swx_table_state *ts = &p->table_state[i];
9689 struct table *table = table_find_by_id(p, i);
9692 if (table->type && ts->obj)
9693 table->type->ops.free(ts->obj);
9695 /* ts->default_action_data. */
9696 free(ts->default_action_data);
9699 for (i = 0; i < p->n_selectors; i++) {
9700 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + i];
9704 rte_swx_table_selector_free(ts->obj);
9707 for (i = 0; i < p->n_learners; i++) {
9708 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + p->n_selectors + i];
9712 rte_swx_table_learner_free(ts->obj);
9714 /* ts->default_action_data. */
9715 free(ts->default_action_data);
9718 free(p->table_state);
9719 p->table_state = NULL;
9723 table_state_free(struct rte_swx_pipeline *p)
9725 table_state_build_free(p);
9731 static struct regarray *
9732 regarray_find(struct rte_swx_pipeline *p, const char *name)
9734 struct regarray *elem;
9736 TAILQ_FOREACH(elem, &p->regarrays, node)
9737 if (!strcmp(elem->name, name))
9743 static struct regarray *
9744 regarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9746 struct regarray *elem = NULL;
9748 TAILQ_FOREACH(elem, &p->regarrays, node)
9756 rte_swx_pipeline_regarray_config(struct rte_swx_pipeline *p,
9765 CHECK_NAME(name, EINVAL);
9766 CHECK(!regarray_find(p, name), EEXIST);
9768 CHECK(size, EINVAL);
9769 size = rte_align32pow2(size);
9771 /* Memory allocation. */
9772 r = calloc(1, sizeof(struct regarray));
9775 /* Node initialization. */
9776 strcpy(r->name, name);
9777 r->init_val = init_val;
9779 r->id = p->n_regarrays;
9781 /* Node add to tailq. */
9782 TAILQ_INSERT_TAIL(&p->regarrays, r, node);
9789 regarray_build(struct rte_swx_pipeline *p)
9791 struct regarray *regarray;
9793 if (!p->n_regarrays)
9796 p->regarray_runtime = calloc(p->n_regarrays, sizeof(struct regarray_runtime));
9797 CHECK(p->regarray_runtime, ENOMEM);
9799 TAILQ_FOREACH(regarray, &p->regarrays, node) {
9800 struct regarray_runtime *r = &p->regarray_runtime[regarray->id];
9803 r->regarray = env_malloc(regarray->size * sizeof(uint64_t),
9804 RTE_CACHE_LINE_SIZE,
9806 CHECK(r->regarray, ENOMEM);
9808 if (regarray->init_val)
9809 for (i = 0; i < regarray->size; i++)
9810 r->regarray[i] = regarray->init_val;
9812 r->size_mask = regarray->size - 1;
9819 regarray_build_free(struct rte_swx_pipeline *p)
9823 if (!p->regarray_runtime)
9826 for (i = 0; i < p->n_regarrays; i++) {
9827 struct regarray *regarray = regarray_find_by_id(p, i);
9828 struct regarray_runtime *r = &p->regarray_runtime[i];
9830 env_free(r->regarray, regarray->size * sizeof(uint64_t));
9833 free(p->regarray_runtime);
9834 p->regarray_runtime = NULL;
9838 regarray_free(struct rte_swx_pipeline *p)
9840 regarray_build_free(p);
9843 struct regarray *elem;
9845 elem = TAILQ_FIRST(&p->regarrays);
9849 TAILQ_REMOVE(&p->regarrays, elem, node);
9857 static struct meter_profile *
9858 meter_profile_find(struct rte_swx_pipeline *p, const char *name)
9860 struct meter_profile *elem;
9862 TAILQ_FOREACH(elem, &p->meter_profiles, node)
9863 if (!strcmp(elem->name, name))
9869 static struct metarray *
9870 metarray_find(struct rte_swx_pipeline *p, const char *name)
9872 struct metarray *elem;
9874 TAILQ_FOREACH(elem, &p->metarrays, node)
9875 if (!strcmp(elem->name, name))
9881 static struct metarray *
9882 metarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9884 struct metarray *elem = NULL;
9886 TAILQ_FOREACH(elem, &p->metarrays, node)
9894 rte_swx_pipeline_metarray_config(struct rte_swx_pipeline *p,
9902 CHECK_NAME(name, EINVAL);
9903 CHECK(!metarray_find(p, name), EEXIST);
9905 CHECK(size, EINVAL);
9906 size = rte_align32pow2(size);
9908 /* Memory allocation. */
9909 m = calloc(1, sizeof(struct metarray));
9912 /* Node initialization. */
9913 strcpy(m->name, name);
9915 m->id = p->n_metarrays;
9917 /* Node add to tailq. */
9918 TAILQ_INSERT_TAIL(&p->metarrays, m, node);
9924 struct meter_profile meter_profile_default = {
9933 .cir_bytes_per_period = 1,
9935 .pir_bytes_per_period = 1,
9942 meter_init(struct meter *m)
9944 memset(m, 0, sizeof(struct meter));
9945 rte_meter_trtcm_config(&m->m, &meter_profile_default.profile);
9946 m->profile = &meter_profile_default;
9947 m->color_mask = RTE_COLOR_GREEN;
9949 meter_profile_default.n_users++;
9953 metarray_build(struct rte_swx_pipeline *p)
9957 if (!p->n_metarrays)
9960 p->metarray_runtime = calloc(p->n_metarrays, sizeof(struct metarray_runtime));
9961 CHECK(p->metarray_runtime, ENOMEM);
9963 TAILQ_FOREACH(m, &p->metarrays, node) {
9964 struct metarray_runtime *r = &p->metarray_runtime[m->id];
9967 r->metarray = env_malloc(m->size * sizeof(struct meter),
9968 RTE_CACHE_LINE_SIZE,
9970 CHECK(r->metarray, ENOMEM);
9972 for (i = 0; i < m->size; i++)
9973 meter_init(&r->metarray[i]);
9975 r->size_mask = m->size - 1;
9982 metarray_build_free(struct rte_swx_pipeline *p)
9986 if (!p->metarray_runtime)
9989 for (i = 0; i < p->n_metarrays; i++) {
9990 struct metarray *m = metarray_find_by_id(p, i);
9991 struct metarray_runtime *r = &p->metarray_runtime[i];
9993 env_free(r->metarray, m->size * sizeof(struct meter));
9996 free(p->metarray_runtime);
9997 p->metarray_runtime = NULL;
10001 metarray_free(struct rte_swx_pipeline *p)
10003 metarray_build_free(p);
10005 /* Meter arrays. */
10007 struct metarray *elem;
10009 elem = TAILQ_FIRST(&p->metarrays);
10013 TAILQ_REMOVE(&p->metarrays, elem, node);
10017 /* Meter profiles. */
10019 struct meter_profile *elem;
10021 elem = TAILQ_FIRST(&p->meter_profiles);
10025 TAILQ_REMOVE(&p->meter_profiles, elem, node);
10034 rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
10036 struct rte_swx_pipeline *pipeline;
10038 /* Check input parameters. */
10041 /* Memory allocation. */
10042 pipeline = calloc(1, sizeof(struct rte_swx_pipeline));
10043 CHECK(pipeline, ENOMEM);
10045 /* Initialization. */
10046 TAILQ_INIT(&pipeline->struct_types);
10047 TAILQ_INIT(&pipeline->port_in_types);
10048 TAILQ_INIT(&pipeline->ports_in);
10049 TAILQ_INIT(&pipeline->port_out_types);
10050 TAILQ_INIT(&pipeline->ports_out);
10051 TAILQ_INIT(&pipeline->extern_types);
10052 TAILQ_INIT(&pipeline->extern_objs);
10053 TAILQ_INIT(&pipeline->extern_funcs);
10054 TAILQ_INIT(&pipeline->headers);
10055 TAILQ_INIT(&pipeline->actions);
10056 TAILQ_INIT(&pipeline->table_types);
10057 TAILQ_INIT(&pipeline->tables);
10058 TAILQ_INIT(&pipeline->selectors);
10059 TAILQ_INIT(&pipeline->learners);
10060 TAILQ_INIT(&pipeline->regarrays);
10061 TAILQ_INIT(&pipeline->meter_profiles);
10062 TAILQ_INIT(&pipeline->metarrays);
10064 pipeline->n_structs = 1; /* Struct 0 is reserved for action_data. */
10065 pipeline->numa_node = numa_node;
10072 rte_swx_pipeline_free(struct rte_swx_pipeline *p)
10077 free(p->instructions);
10081 table_state_free(p);
10088 extern_func_free(p);
10089 extern_obj_free(p);
10098 rte_swx_pipeline_instructions_config(struct rte_swx_pipeline *p,
10099 const char **instructions,
10100 uint32_t n_instructions)
10105 err = instruction_config(p, NULL, instructions, n_instructions);
10109 /* Thread instruction pointer reset. */
10110 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
10111 struct thread *t = &p->threads[i];
10113 thread_ip_reset(p, t);
10120 rte_swx_pipeline_build(struct rte_swx_pipeline *p)
10125 CHECK(p->build_done == 0, EEXIST);
10127 status = port_in_build(p);
10131 status = port_out_build(p);
10135 status = struct_build(p);
10139 status = extern_obj_build(p);
10143 status = extern_func_build(p);
10147 status = header_build(p);
10151 status = metadata_build(p);
10155 status = action_build(p);
10159 status = table_build(p);
10163 status = selector_build(p);
10167 status = learner_build(p);
10171 status = table_state_build(p);
10175 status = regarray_build(p);
10179 status = metarray_build(p);
10187 metarray_build_free(p);
10188 regarray_build_free(p);
10189 table_state_build_free(p);
10190 learner_build_free(p);
10191 selector_build_free(p);
10192 table_build_free(p);
10193 action_build_free(p);
10194 metadata_build_free(p);
10195 header_build_free(p);
10196 extern_func_build_free(p);
10197 extern_obj_build_free(p);
10198 port_out_build_free(p);
10199 port_in_build_free(p);
10200 struct_build_free(p);
10206 rte_swx_pipeline_run(struct rte_swx_pipeline *p, uint32_t n_instructions)
10210 for (i = 0; i < n_instructions; i++)
10215 rte_swx_pipeline_flush(struct rte_swx_pipeline *p)
10219 for (i = 0; i < p->n_ports_out; i++) {
10220 struct port_out_runtime *port = &p->out[i];
10223 port->flush(port->obj);
10231 rte_swx_ctl_pipeline_info_get(struct rte_swx_pipeline *p,
10232 struct rte_swx_ctl_pipeline_info *pipeline)
10234 struct action *action;
10235 struct table *table;
10236 uint32_t n_actions = 0, n_tables = 0;
10238 if (!p || !pipeline)
10241 TAILQ_FOREACH(action, &p->actions, node)
10244 TAILQ_FOREACH(table, &p->tables, node)
10247 pipeline->n_ports_in = p->n_ports_in;
10248 pipeline->n_ports_out = p->n_ports_out;
10249 pipeline->n_actions = n_actions;
10250 pipeline->n_tables = n_tables;
10251 pipeline->n_selectors = p->n_selectors;
10252 pipeline->n_learners = p->n_learners;
10253 pipeline->n_regarrays = p->n_regarrays;
10254 pipeline->n_metarrays = p->n_metarrays;
10260 rte_swx_ctl_pipeline_numa_node_get(struct rte_swx_pipeline *p, int *numa_node)
10262 if (!p || !numa_node)
10265 *numa_node = p->numa_node;
10270 rte_swx_ctl_action_info_get(struct rte_swx_pipeline *p,
10271 uint32_t action_id,
10272 struct rte_swx_ctl_action_info *action)
10274 struct action *a = NULL;
10276 if (!p || (action_id >= p->n_actions) || !action)
10279 a = action_find_by_id(p, action_id);
10283 strcpy(action->name, a->name);
10284 action->n_args = a->st ? a->st->n_fields : 0;
10289 rte_swx_ctl_action_arg_info_get(struct rte_swx_pipeline *p,
10290 uint32_t action_id,
10291 uint32_t action_arg_id,
10292 struct rte_swx_ctl_action_arg_info *action_arg)
10294 struct action *a = NULL;
10295 struct field *arg = NULL;
10297 if (!p || (action_id >= p->n_actions) || !action_arg)
10300 a = action_find_by_id(p, action_id);
10301 if (!a || !a->st || (action_arg_id >= a->st->n_fields))
10304 arg = &a->st->fields[action_arg_id];
10305 strcpy(action_arg->name, arg->name);
10306 action_arg->n_bits = arg->n_bits;
10307 action_arg->is_network_byte_order = a->args_endianness[action_arg_id];
10313 rte_swx_ctl_table_info_get(struct rte_swx_pipeline *p,
10315 struct rte_swx_ctl_table_info *table)
10317 struct table *t = NULL;
10322 t = table_find_by_id(p, table_id);
10326 strcpy(table->name, t->name);
10327 strcpy(table->args, t->args);
10328 table->n_match_fields = t->n_fields;
10329 table->n_actions = t->n_actions;
10330 table->default_action_is_const = t->default_action_is_const;
10331 table->size = t->size;
10336 rte_swx_ctl_table_match_field_info_get(struct rte_swx_pipeline *p,
10338 uint32_t match_field_id,
10339 struct rte_swx_ctl_table_match_field_info *match_field)
10342 struct match_field *f;
10344 if (!p || (table_id >= p->n_tables) || !match_field)
10347 t = table_find_by_id(p, table_id);
10348 if (!t || (match_field_id >= t->n_fields))
10351 f = &t->fields[match_field_id];
10352 match_field->match_type = f->match_type;
10353 match_field->is_header = t->header ? 1 : 0;
10354 match_field->n_bits = f->field->n_bits;
10355 match_field->offset = f->field->offset;
10361 rte_swx_ctl_table_action_info_get(struct rte_swx_pipeline *p,
10363 uint32_t table_action_id,
10364 struct rte_swx_ctl_table_action_info *table_action)
10368 if (!p || (table_id >= p->n_tables) || !table_action)
10371 t = table_find_by_id(p, table_id);
10372 if (!t || (table_action_id >= t->n_actions))
10375 table_action->action_id = t->actions[table_action_id]->id;
10381 rte_swx_ctl_table_ops_get(struct rte_swx_pipeline *p,
10383 struct rte_swx_table_ops *table_ops,
10388 if (!p || (table_id >= p->n_tables))
10391 t = table_find_by_id(p, table_id);
10397 memcpy(table_ops, &t->type->ops, sizeof(*table_ops));
10407 rte_swx_ctl_selector_info_get(struct rte_swx_pipeline *p,
10408 uint32_t selector_id,
10409 struct rte_swx_ctl_selector_info *selector)
10411 struct selector *s = NULL;
10413 if (!p || !selector)
10416 s = selector_find_by_id(p, selector_id);
10420 strcpy(selector->name, s->name);
10422 selector->n_selector_fields = s->n_selector_fields;
10423 selector->n_groups_max = s->n_groups_max;
10424 selector->n_members_per_group_max = s->n_members_per_group_max;
10430 rte_swx_ctl_selector_group_id_field_info_get(struct rte_swx_pipeline *p,
10431 uint32_t selector_id,
10432 struct rte_swx_ctl_table_match_field_info *field)
10434 struct selector *s;
10436 if (!p || (selector_id >= p->n_selectors) || !field)
10439 s = selector_find_by_id(p, selector_id);
10443 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10444 field->is_header = 0;
10445 field->n_bits = s->group_id_field->n_bits;
10446 field->offset = s->group_id_field->offset;
10452 rte_swx_ctl_selector_field_info_get(struct rte_swx_pipeline *p,
10453 uint32_t selector_id,
10454 uint32_t selector_field_id,
10455 struct rte_swx_ctl_table_match_field_info *field)
10457 struct selector *s;
10460 if (!p || (selector_id >= p->n_selectors) || !field)
10463 s = selector_find_by_id(p, selector_id);
10464 if (!s || (selector_field_id >= s->n_selector_fields))
10467 f = s->selector_fields[selector_field_id];
10468 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10469 field->is_header = s->selector_header ? 1 : 0;
10470 field->n_bits = f->n_bits;
10471 field->offset = f->offset;
10477 rte_swx_ctl_selector_member_id_field_info_get(struct rte_swx_pipeline *p,
10478 uint32_t selector_id,
10479 struct rte_swx_ctl_table_match_field_info *field)
10481 struct selector *s;
10483 if (!p || (selector_id >= p->n_selectors) || !field)
10486 s = selector_find_by_id(p, selector_id);
10490 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10491 field->is_header = 0;
10492 field->n_bits = s->member_id_field->n_bits;
10493 field->offset = s->member_id_field->offset;
10499 rte_swx_ctl_learner_info_get(struct rte_swx_pipeline *p,
10500 uint32_t learner_id,
10501 struct rte_swx_ctl_learner_info *learner)
10503 struct learner *l = NULL;
10505 if (!p || !learner)
10508 l = learner_find_by_id(p, learner_id);
10512 strcpy(learner->name, l->name);
10514 learner->n_match_fields = l->n_fields;
10515 learner->n_actions = l->n_actions;
10516 learner->default_action_is_const = l->default_action_is_const;
10517 learner->size = l->size;
10523 rte_swx_ctl_learner_match_field_info_get(struct rte_swx_pipeline *p,
10524 uint32_t learner_id,
10525 uint32_t match_field_id,
10526 struct rte_swx_ctl_table_match_field_info *match_field)
10531 if (!p || (learner_id >= p->n_learners) || !match_field)
10534 l = learner_find_by_id(p, learner_id);
10535 if (!l || (match_field_id >= l->n_fields))
10538 f = l->fields[match_field_id];
10539 match_field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
10540 match_field->is_header = l->header ? 1 : 0;
10541 match_field->n_bits = f->n_bits;
10542 match_field->offset = f->offset;
10548 rte_swx_ctl_learner_action_info_get(struct rte_swx_pipeline *p,
10549 uint32_t learner_id,
10550 uint32_t learner_action_id,
10551 struct rte_swx_ctl_table_action_info *learner_action)
10555 if (!p || (learner_id >= p->n_learners) || !learner_action)
10558 l = learner_find_by_id(p, learner_id);
10559 if (!l || (learner_action_id >= l->n_actions))
10562 learner_action->action_id = l->actions[learner_action_id]->id;
10568 rte_swx_pipeline_table_state_get(struct rte_swx_pipeline *p,
10569 struct rte_swx_table_state **table_state)
10571 if (!p || !table_state || !p->build_done)
10574 *table_state = p->table_state;
10579 rte_swx_pipeline_table_state_set(struct rte_swx_pipeline *p,
10580 struct rte_swx_table_state *table_state)
10582 if (!p || !table_state || !p->build_done)
10585 p->table_state = table_state;
10590 rte_swx_ctl_pipeline_port_in_stats_read(struct rte_swx_pipeline *p,
10592 struct rte_swx_port_in_stats *stats)
10594 struct port_in *port;
10599 port = port_in_find(p, port_id);
10603 port->type->ops.stats_read(port->obj, stats);
10608 rte_swx_ctl_pipeline_port_out_stats_read(struct rte_swx_pipeline *p,
10610 struct rte_swx_port_out_stats *stats)
10612 struct port_out *port;
10617 port = port_out_find(p, port_id);
10621 port->type->ops.stats_read(port->obj, stats);
10626 rte_swx_ctl_pipeline_table_stats_read(struct rte_swx_pipeline *p,
10627 const char *table_name,
10628 struct rte_swx_table_stats *stats)
10630 struct table *table;
10631 struct table_statistics *table_stats;
10633 if (!p || !table_name || !table_name[0] || !stats || !stats->n_pkts_action)
10636 table = table_find(p, table_name);
10640 table_stats = &p->table_stats[table->id];
10642 memcpy(stats->n_pkts_action,
10643 table_stats->n_pkts_action,
10644 p->n_actions * sizeof(uint64_t));
10646 stats->n_pkts_hit = table_stats->n_pkts_hit[1];
10647 stats->n_pkts_miss = table_stats->n_pkts_hit[0];
10653 rte_swx_ctl_pipeline_selector_stats_read(struct rte_swx_pipeline *p,
10654 const char *selector_name,
10655 struct rte_swx_pipeline_selector_stats *stats)
10657 struct selector *s;
10659 if (!p || !selector_name || !selector_name[0] || !stats)
10662 s = selector_find(p, selector_name);
10666 stats->n_pkts = p->selector_stats[s->id].n_pkts;
10672 rte_swx_ctl_pipeline_learner_stats_read(struct rte_swx_pipeline *p,
10673 const char *learner_name,
10674 struct rte_swx_learner_stats *stats)
10677 struct learner_statistics *learner_stats;
10679 if (!p || !learner_name || !learner_name[0] || !stats || !stats->n_pkts_action)
10682 l = learner_find(p, learner_name);
10686 learner_stats = &p->learner_stats[l->id];
10688 memcpy(stats->n_pkts_action,
10689 learner_stats->n_pkts_action,
10690 p->n_actions * sizeof(uint64_t));
10692 stats->n_pkts_hit = learner_stats->n_pkts_hit[1];
10693 stats->n_pkts_miss = learner_stats->n_pkts_hit[0];
10695 stats->n_pkts_learn_ok = learner_stats->n_pkts_learn[0];
10696 stats->n_pkts_learn_err = learner_stats->n_pkts_learn[1];
10698 stats->n_pkts_forget = learner_stats->n_pkts_forget;
10704 rte_swx_ctl_regarray_info_get(struct rte_swx_pipeline *p,
10705 uint32_t regarray_id,
10706 struct rte_swx_ctl_regarray_info *regarray)
10708 struct regarray *r;
10710 if (!p || !regarray)
10713 r = regarray_find_by_id(p, regarray_id);
10717 strcpy(regarray->name, r->name);
10718 regarray->size = r->size;
10723 rte_swx_ctl_pipeline_regarray_read(struct rte_swx_pipeline *p,
10724 const char *regarray_name,
10725 uint32_t regarray_index,
10728 struct regarray *regarray;
10729 struct regarray_runtime *r;
10731 if (!p || !regarray_name || !value)
10734 regarray = regarray_find(p, regarray_name);
10735 if (!regarray || (regarray_index >= regarray->size))
10738 r = &p->regarray_runtime[regarray->id];
10739 *value = r->regarray[regarray_index];
10744 rte_swx_ctl_pipeline_regarray_write(struct rte_swx_pipeline *p,
10745 const char *regarray_name,
10746 uint32_t regarray_index,
10749 struct regarray *regarray;
10750 struct regarray_runtime *r;
10752 if (!p || !regarray_name)
10755 regarray = regarray_find(p, regarray_name);
10756 if (!regarray || (regarray_index >= regarray->size))
10759 r = &p->regarray_runtime[regarray->id];
10760 r->regarray[regarray_index] = value;
10765 rte_swx_ctl_metarray_info_get(struct rte_swx_pipeline *p,
10766 uint32_t metarray_id,
10767 struct rte_swx_ctl_metarray_info *metarray)
10769 struct metarray *m;
10771 if (!p || !metarray)
10774 m = metarray_find_by_id(p, metarray_id);
10778 strcpy(metarray->name, m->name);
10779 metarray->size = m->size;
10784 rte_swx_ctl_meter_profile_add(struct rte_swx_pipeline *p,
10786 struct rte_meter_trtcm_params *params)
10788 struct meter_profile *mp;
10792 CHECK_NAME(name, EINVAL);
10793 CHECK(params, EINVAL);
10794 CHECK(!meter_profile_find(p, name), EEXIST);
10796 /* Node allocation. */
10797 mp = calloc(1, sizeof(struct meter_profile));
10800 /* Node initialization. */
10801 strcpy(mp->name, name);
10802 memcpy(&mp->params, params, sizeof(struct rte_meter_trtcm_params));
10803 status = rte_meter_trtcm_profile_config(&mp->profile, params);
10809 /* Node add to tailq. */
10810 TAILQ_INSERT_TAIL(&p->meter_profiles, mp, node);
10816 rte_swx_ctl_meter_profile_delete(struct rte_swx_pipeline *p,
10819 struct meter_profile *mp;
10822 CHECK_NAME(name, EINVAL);
10824 mp = meter_profile_find(p, name);
10826 CHECK(!mp->n_users, EBUSY);
10828 /* Remove node from tailq. */
10829 TAILQ_REMOVE(&p->meter_profiles, mp, node);
10836 rte_swx_ctl_meter_reset(struct rte_swx_pipeline *p,
10837 const char *metarray_name,
10838 uint32_t metarray_index)
10840 struct meter_profile *mp_old;
10841 struct metarray *metarray;
10842 struct metarray_runtime *metarray_runtime;
10846 CHECK_NAME(metarray_name, EINVAL);
10848 metarray = metarray_find(p, metarray_name);
10849 CHECK(metarray, EINVAL);
10850 CHECK(metarray_index < metarray->size, EINVAL);
10852 metarray_runtime = &p->metarray_runtime[metarray->id];
10853 m = &metarray_runtime->metarray[metarray_index];
10854 mp_old = m->profile;
10864 rte_swx_ctl_meter_set(struct rte_swx_pipeline *p,
10865 const char *metarray_name,
10866 uint32_t metarray_index,
10867 const char *profile_name)
10869 struct meter_profile *mp, *mp_old;
10870 struct metarray *metarray;
10871 struct metarray_runtime *metarray_runtime;
10875 CHECK_NAME(metarray_name, EINVAL);
10877 metarray = metarray_find(p, metarray_name);
10878 CHECK(metarray, EINVAL);
10879 CHECK(metarray_index < metarray->size, EINVAL);
10881 mp = meter_profile_find(p, profile_name);
10884 metarray_runtime = &p->metarray_runtime[metarray->id];
10885 m = &metarray_runtime->metarray[metarray_index];
10886 mp_old = m->profile;
10888 memset(m, 0, sizeof(struct meter));
10889 rte_meter_trtcm_config(&m->m, &mp->profile);
10891 m->color_mask = RTE_COLORS;
10900 rte_swx_ctl_meter_stats_read(struct rte_swx_pipeline *p,
10901 const char *metarray_name,
10902 uint32_t metarray_index,
10903 struct rte_swx_ctl_meter_stats *stats)
10905 struct metarray *metarray;
10906 struct metarray_runtime *metarray_runtime;
10910 CHECK_NAME(metarray_name, EINVAL);
10912 metarray = metarray_find(p, metarray_name);
10913 CHECK(metarray, EINVAL);
10914 CHECK(metarray_index < metarray->size, EINVAL);
10916 CHECK(stats, EINVAL);
10918 metarray_runtime = &p->metarray_runtime[metarray->id];
10919 m = &metarray_runtime->metarray[metarray_index];
10921 memcpy(stats->n_pkts, m->n_pkts, sizeof(m->n_pkts));
10922 memcpy(stats->n_bytes, m->n_bytes, sizeof(m->n_bytes));