1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2020 Intel Corporation
10 #include <rte_common.h>
12 #include "rte_swx_pipeline.h"
14 #define CHECK(condition, err_code) \
20 #define CHECK_NAME(name, err_code) \
21 CHECK((name) && (name)[0], err_code)
27 char name[RTE_SWX_NAME_SIZE];
33 TAILQ_ENTRY(struct_type) node;
34 char name[RTE_SWX_NAME_SIZE];
40 TAILQ_HEAD(struct_type_tailq, struct_type);
46 TAILQ_ENTRY(port_in_type) node;
47 char name[RTE_SWX_NAME_SIZE];
48 struct rte_swx_port_in_ops ops;
51 TAILQ_HEAD(port_in_type_tailq, port_in_type);
54 TAILQ_ENTRY(port_in) node;
55 struct port_in_type *type;
60 TAILQ_HEAD(port_in_tailq, port_in);
62 struct port_in_runtime {
63 rte_swx_port_in_pkt_rx_t pkt_rx;
70 struct port_out_type {
71 TAILQ_ENTRY(port_out_type) node;
72 char name[RTE_SWX_NAME_SIZE];
73 struct rte_swx_port_out_ops ops;
76 TAILQ_HEAD(port_out_type_tailq, port_out_type);
79 TAILQ_ENTRY(port_out) node;
80 struct port_out_type *type;
85 TAILQ_HEAD(port_out_tailq, port_out);
87 struct port_out_runtime {
88 rte_swx_port_out_pkt_tx_t pkt_tx;
89 rte_swx_port_out_flush_t flush;
96 struct extern_type_member_func {
97 TAILQ_ENTRY(extern_type_member_func) node;
98 char name[RTE_SWX_NAME_SIZE];
99 rte_swx_extern_type_member_func_t func;
103 TAILQ_HEAD(extern_type_member_func_tailq, extern_type_member_func);
106 TAILQ_ENTRY(extern_type) node;
107 char name[RTE_SWX_NAME_SIZE];
108 struct struct_type *mailbox_struct_type;
109 rte_swx_extern_type_constructor_t constructor;
110 rte_swx_extern_type_destructor_t destructor;
111 struct extern_type_member_func_tailq funcs;
115 TAILQ_HEAD(extern_type_tailq, extern_type);
118 TAILQ_ENTRY(extern_obj) node;
119 char name[RTE_SWX_NAME_SIZE];
120 struct extern_type *type;
126 TAILQ_HEAD(extern_obj_tailq, extern_obj);
128 #ifndef RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX
129 #define RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX 8
132 struct extern_obj_runtime {
135 rte_swx_extern_type_member_func_t funcs[RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX];
142 TAILQ_ENTRY(extern_func) node;
143 char name[RTE_SWX_NAME_SIZE];
144 struct struct_type *mailbox_struct_type;
145 rte_swx_extern_func_t func;
150 TAILQ_HEAD(extern_func_tailq, extern_func);
152 struct extern_func_runtime {
154 rte_swx_extern_func_t func;
161 TAILQ_ENTRY(header) node;
162 char name[RTE_SWX_NAME_SIZE];
163 struct struct_type *st;
168 TAILQ_HEAD(header_tailq, header);
170 struct header_runtime {
174 struct header_out_runtime {
187 /* Packet headers. */
188 struct header_runtime *headers; /* Extracted or generated headers. */
189 struct header_out_runtime *headers_out; /* Emitted headers. */
190 uint8_t *header_storage;
191 uint8_t *header_out_storage;
192 uint64_t valid_headers;
193 uint32_t n_headers_out;
195 /* Packet meta-data. */
198 /* Extern objects and functions. */
199 struct extern_obj_runtime *extern_objs;
200 struct extern_func_runtime *extern_funcs;
203 #ifndef RTE_SWX_PIPELINE_THREADS_MAX
204 #define RTE_SWX_PIPELINE_THREADS_MAX 16
207 struct rte_swx_pipeline {
208 struct struct_type_tailq struct_types;
209 struct port_in_type_tailq port_in_types;
210 struct port_in_tailq ports_in;
211 struct port_out_type_tailq port_out_types;
212 struct port_out_tailq ports_out;
213 struct extern_type_tailq extern_types;
214 struct extern_obj_tailq extern_objs;
215 struct extern_func_tailq extern_funcs;
216 struct header_tailq headers;
217 struct struct_type *metadata_st;
218 uint32_t metadata_struct_id;
220 struct port_in_runtime *in;
221 struct port_out_runtime *out;
222 struct thread threads[RTE_SWX_PIPELINE_THREADS_MAX];
226 uint32_t n_ports_out;
227 uint32_t n_extern_objs;
228 uint32_t n_extern_funcs;
237 static struct struct_type *
238 struct_type_find(struct rte_swx_pipeline *p, const char *name)
240 struct struct_type *elem;
242 TAILQ_FOREACH(elem, &p->struct_types, node)
243 if (strcmp(elem->name, name) == 0)
250 rte_swx_pipeline_struct_type_register(struct rte_swx_pipeline *p,
252 struct rte_swx_field_params *fields,
255 struct struct_type *st;
259 CHECK_NAME(name, EINVAL);
260 CHECK(fields, EINVAL);
261 CHECK(n_fields, EINVAL);
263 for (i = 0; i < n_fields; i++) {
264 struct rte_swx_field_params *f = &fields[i];
267 CHECK_NAME(f->name, EINVAL);
268 CHECK(f->n_bits, EINVAL);
269 CHECK(f->n_bits <= 64, EINVAL);
270 CHECK((f->n_bits & 7) == 0, EINVAL);
272 for (j = 0; j < i; j++) {
273 struct rte_swx_field_params *f_prev = &fields[j];
275 CHECK(strcmp(f->name, f_prev->name), EINVAL);
279 CHECK(!struct_type_find(p, name), EEXIST);
281 /* Node allocation. */
282 st = calloc(1, sizeof(struct struct_type));
285 st->fields = calloc(n_fields, sizeof(struct field));
291 /* Node initialization. */
292 strcpy(st->name, name);
293 for (i = 0; i < n_fields; i++) {
294 struct field *dst = &st->fields[i];
295 struct rte_swx_field_params *src = &fields[i];
297 strcpy(dst->name, src->name);
298 dst->n_bits = src->n_bits;
299 dst->offset = st->n_bits;
301 st->n_bits += src->n_bits;
303 st->n_fields = n_fields;
305 /* Node add to tailq. */
306 TAILQ_INSERT_TAIL(&p->struct_types, st, node);
312 struct_build(struct rte_swx_pipeline *p)
316 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
317 struct thread *t = &p->threads[i];
319 t->structs = calloc(p->n_structs, sizeof(uint8_t *));
320 CHECK(t->structs, ENOMEM);
327 struct_build_free(struct rte_swx_pipeline *p)
331 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
332 struct thread *t = &p->threads[i];
340 struct_free(struct rte_swx_pipeline *p)
342 struct_build_free(p);
346 struct struct_type *elem;
348 elem = TAILQ_FIRST(&p->struct_types);
352 TAILQ_REMOVE(&p->struct_types, elem, node);
361 static struct port_in_type *
362 port_in_type_find(struct rte_swx_pipeline *p, const char *name)
364 struct port_in_type *elem;
369 TAILQ_FOREACH(elem, &p->port_in_types, node)
370 if (strcmp(elem->name, name) == 0)
377 rte_swx_pipeline_port_in_type_register(struct rte_swx_pipeline *p,
379 struct rte_swx_port_in_ops *ops)
381 struct port_in_type *elem;
384 CHECK_NAME(name, EINVAL);
386 CHECK(ops->create, EINVAL);
387 CHECK(ops->free, EINVAL);
388 CHECK(ops->pkt_rx, EINVAL);
389 CHECK(ops->stats_read, EINVAL);
391 CHECK(!port_in_type_find(p, name), EEXIST);
393 /* Node allocation. */
394 elem = calloc(1, sizeof(struct port_in_type));
397 /* Node initialization. */
398 strcpy(elem->name, name);
399 memcpy(&elem->ops, ops, sizeof(*ops));
401 /* Node add to tailq. */
402 TAILQ_INSERT_TAIL(&p->port_in_types, elem, node);
407 static struct port_in *
408 port_in_find(struct rte_swx_pipeline *p, uint32_t port_id)
410 struct port_in *port;
412 TAILQ_FOREACH(port, &p->ports_in, node)
413 if (port->id == port_id)
420 rte_swx_pipeline_port_in_config(struct rte_swx_pipeline *p,
422 const char *port_type_name,
425 struct port_in_type *type = NULL;
426 struct port_in *port = NULL;
431 CHECK(!port_in_find(p, port_id), EINVAL);
433 CHECK_NAME(port_type_name, EINVAL);
434 type = port_in_type_find(p, port_type_name);
437 obj = type->ops.create(args);
440 /* Node allocation. */
441 port = calloc(1, sizeof(struct port_in));
444 /* Node initialization. */
449 /* Node add to tailq. */
450 TAILQ_INSERT_TAIL(&p->ports_in, port, node);
451 if (p->n_ports_in < port_id + 1)
452 p->n_ports_in = port_id + 1;
458 port_in_build(struct rte_swx_pipeline *p)
460 struct port_in *port;
463 CHECK(p->n_ports_in, EINVAL);
464 CHECK(rte_is_power_of_2(p->n_ports_in), EINVAL);
466 for (i = 0; i < p->n_ports_in; i++)
467 CHECK(port_in_find(p, i), EINVAL);
469 p->in = calloc(p->n_ports_in, sizeof(struct port_in_runtime));
470 CHECK(p->in, ENOMEM);
472 TAILQ_FOREACH(port, &p->ports_in, node) {
473 struct port_in_runtime *in = &p->in[port->id];
475 in->pkt_rx = port->type->ops.pkt_rx;
483 port_in_build_free(struct rte_swx_pipeline *p)
490 port_in_free(struct rte_swx_pipeline *p)
492 port_in_build_free(p);
496 struct port_in *port;
498 port = TAILQ_FIRST(&p->ports_in);
502 TAILQ_REMOVE(&p->ports_in, port, node);
503 port->type->ops.free(port->obj);
507 /* Input port types. */
509 struct port_in_type *elem;
511 elem = TAILQ_FIRST(&p->port_in_types);
515 TAILQ_REMOVE(&p->port_in_types, elem, node);
523 static struct port_out_type *
524 port_out_type_find(struct rte_swx_pipeline *p, const char *name)
526 struct port_out_type *elem;
531 TAILQ_FOREACH(elem, &p->port_out_types, node)
532 if (!strcmp(elem->name, name))
539 rte_swx_pipeline_port_out_type_register(struct rte_swx_pipeline *p,
541 struct rte_swx_port_out_ops *ops)
543 struct port_out_type *elem;
546 CHECK_NAME(name, EINVAL);
548 CHECK(ops->create, EINVAL);
549 CHECK(ops->free, EINVAL);
550 CHECK(ops->pkt_tx, EINVAL);
551 CHECK(ops->stats_read, EINVAL);
553 CHECK(!port_out_type_find(p, name), EEXIST);
555 /* Node allocation. */
556 elem = calloc(1, sizeof(struct port_out_type));
559 /* Node initialization. */
560 strcpy(elem->name, name);
561 memcpy(&elem->ops, ops, sizeof(*ops));
563 /* Node add to tailq. */
564 TAILQ_INSERT_TAIL(&p->port_out_types, elem, node);
569 static struct port_out *
570 port_out_find(struct rte_swx_pipeline *p, uint32_t port_id)
572 struct port_out *port;
574 TAILQ_FOREACH(port, &p->ports_out, node)
575 if (port->id == port_id)
582 rte_swx_pipeline_port_out_config(struct rte_swx_pipeline *p,
584 const char *port_type_name,
587 struct port_out_type *type = NULL;
588 struct port_out *port = NULL;
593 CHECK(!port_out_find(p, port_id), EINVAL);
595 CHECK_NAME(port_type_name, EINVAL);
596 type = port_out_type_find(p, port_type_name);
599 obj = type->ops.create(args);
602 /* Node allocation. */
603 port = calloc(1, sizeof(struct port_out));
606 /* Node initialization. */
611 /* Node add to tailq. */
612 TAILQ_INSERT_TAIL(&p->ports_out, port, node);
613 if (p->n_ports_out < port_id + 1)
614 p->n_ports_out = port_id + 1;
620 port_out_build(struct rte_swx_pipeline *p)
622 struct port_out *port;
625 CHECK(p->n_ports_out, EINVAL);
627 for (i = 0; i < p->n_ports_out; i++)
628 CHECK(port_out_find(p, i), EINVAL);
630 p->out = calloc(p->n_ports_out, sizeof(struct port_out_runtime));
631 CHECK(p->out, ENOMEM);
633 TAILQ_FOREACH(port, &p->ports_out, node) {
634 struct port_out_runtime *out = &p->out[port->id];
636 out->pkt_tx = port->type->ops.pkt_tx;
637 out->flush = port->type->ops.flush;
638 out->obj = port->obj;
645 port_out_build_free(struct rte_swx_pipeline *p)
652 port_out_free(struct rte_swx_pipeline *p)
654 port_out_build_free(p);
658 struct port_out *port;
660 port = TAILQ_FIRST(&p->ports_out);
664 TAILQ_REMOVE(&p->ports_out, port, node);
665 port->type->ops.free(port->obj);
669 /* Output port types. */
671 struct port_out_type *elem;
673 elem = TAILQ_FIRST(&p->port_out_types);
677 TAILQ_REMOVE(&p->port_out_types, elem, node);
685 static struct extern_type *
686 extern_type_find(struct rte_swx_pipeline *p, const char *name)
688 struct extern_type *elem;
690 TAILQ_FOREACH(elem, &p->extern_types, node)
691 if (strcmp(elem->name, name) == 0)
697 static struct extern_type_member_func *
698 extern_type_member_func_find(struct extern_type *type, const char *name)
700 struct extern_type_member_func *elem;
702 TAILQ_FOREACH(elem, &type->funcs, node)
703 if (strcmp(elem->name, name) == 0)
709 static struct extern_obj *
710 extern_obj_find(struct rte_swx_pipeline *p, const char *name)
712 struct extern_obj *elem;
714 TAILQ_FOREACH(elem, &p->extern_objs, node)
715 if (strcmp(elem->name, name) == 0)
722 rte_swx_pipeline_extern_type_register(struct rte_swx_pipeline *p,
724 const char *mailbox_struct_type_name,
725 rte_swx_extern_type_constructor_t constructor,
726 rte_swx_extern_type_destructor_t destructor)
728 struct extern_type *elem;
729 struct struct_type *mailbox_struct_type;
733 CHECK_NAME(name, EINVAL);
734 CHECK(!extern_type_find(p, name), EEXIST);
736 CHECK_NAME(mailbox_struct_type_name, EINVAL);
737 mailbox_struct_type = struct_type_find(p, mailbox_struct_type_name);
738 CHECK(mailbox_struct_type, EINVAL);
740 CHECK(constructor, EINVAL);
741 CHECK(destructor, EINVAL);
743 /* Node allocation. */
744 elem = calloc(1, sizeof(struct extern_type));
747 /* Node initialization. */
748 strcpy(elem->name, name);
749 elem->mailbox_struct_type = mailbox_struct_type;
750 elem->constructor = constructor;
751 elem->destructor = destructor;
752 TAILQ_INIT(&elem->funcs);
754 /* Node add to tailq. */
755 TAILQ_INSERT_TAIL(&p->extern_types, elem, node);
761 rte_swx_pipeline_extern_type_member_func_register(struct rte_swx_pipeline *p,
762 const char *extern_type_name,
764 rte_swx_extern_type_member_func_t member_func)
766 struct extern_type *type;
767 struct extern_type_member_func *type_member;
771 CHECK(extern_type_name, EINVAL);
772 type = extern_type_find(p, extern_type_name);
774 CHECK(type->n_funcs < RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX, ENOSPC);
777 CHECK(!extern_type_member_func_find(type, name), EEXIST);
779 CHECK(member_func, EINVAL);
781 /* Node allocation. */
782 type_member = calloc(1, sizeof(struct extern_type_member_func));
783 CHECK(type_member, ENOMEM);
785 /* Node initialization. */
786 strcpy(type_member->name, name);
787 type_member->func = member_func;
788 type_member->id = type->n_funcs;
790 /* Node add to tailq. */
791 TAILQ_INSERT_TAIL(&type->funcs, type_member, node);
798 rte_swx_pipeline_extern_object_config(struct rte_swx_pipeline *p,
799 const char *extern_type_name,
803 struct extern_type *type;
804 struct extern_obj *obj;
809 CHECK_NAME(extern_type_name, EINVAL);
810 type = extern_type_find(p, extern_type_name);
813 CHECK_NAME(name, EINVAL);
814 CHECK(!extern_obj_find(p, name), EEXIST);
816 /* Node allocation. */
817 obj = calloc(1, sizeof(struct extern_obj));
820 /* Object construction. */
821 obj_handle = type->constructor(args);
827 /* Node initialization. */
828 strcpy(obj->name, name);
830 obj->obj = obj_handle;
831 obj->struct_id = p->n_structs;
832 obj->id = p->n_extern_objs;
834 /* Node add to tailq. */
835 TAILQ_INSERT_TAIL(&p->extern_objs, obj, node);
843 extern_obj_build(struct rte_swx_pipeline *p)
847 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
848 struct thread *t = &p->threads[i];
849 struct extern_obj *obj;
851 t->extern_objs = calloc(p->n_extern_objs,
852 sizeof(struct extern_obj_runtime));
853 CHECK(t->extern_objs, ENOMEM);
855 TAILQ_FOREACH(obj, &p->extern_objs, node) {
856 struct extern_obj_runtime *r =
857 &t->extern_objs[obj->id];
858 struct extern_type_member_func *func;
859 uint32_t mailbox_size =
860 obj->type->mailbox_struct_type->n_bits / 8;
864 r->mailbox = calloc(1, mailbox_size);
865 CHECK(r->mailbox, ENOMEM);
867 TAILQ_FOREACH(func, &obj->type->funcs, node)
868 r->funcs[func->id] = func->func;
870 t->structs[obj->struct_id] = r->mailbox;
878 extern_obj_build_free(struct rte_swx_pipeline *p)
882 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
883 struct thread *t = &p->threads[i];
889 for (j = 0; j < p->n_extern_objs; j++) {
890 struct extern_obj_runtime *r = &t->extern_objs[j];
895 free(t->extern_objs);
896 t->extern_objs = NULL;
901 extern_obj_free(struct rte_swx_pipeline *p)
903 extern_obj_build_free(p);
905 /* Extern objects. */
907 struct extern_obj *elem;
909 elem = TAILQ_FIRST(&p->extern_objs);
913 TAILQ_REMOVE(&p->extern_objs, elem, node);
915 elem->type->destructor(elem->obj);
921 struct extern_type *elem;
923 elem = TAILQ_FIRST(&p->extern_types);
927 TAILQ_REMOVE(&p->extern_types, elem, node);
930 struct extern_type_member_func *func;
932 func = TAILQ_FIRST(&elem->funcs);
936 TAILQ_REMOVE(&elem->funcs, func, node);
947 static struct extern_func *
948 extern_func_find(struct rte_swx_pipeline *p, const char *name)
950 struct extern_func *elem;
952 TAILQ_FOREACH(elem, &p->extern_funcs, node)
953 if (strcmp(elem->name, name) == 0)
960 rte_swx_pipeline_extern_func_register(struct rte_swx_pipeline *p,
962 const char *mailbox_struct_type_name,
963 rte_swx_extern_func_t func)
965 struct extern_func *f;
966 struct struct_type *mailbox_struct_type;
970 CHECK_NAME(name, EINVAL);
971 CHECK(!extern_func_find(p, name), EEXIST);
973 CHECK_NAME(mailbox_struct_type_name, EINVAL);
974 mailbox_struct_type = struct_type_find(p, mailbox_struct_type_name);
975 CHECK(mailbox_struct_type, EINVAL);
979 /* Node allocation. */
980 f = calloc(1, sizeof(struct extern_func));
983 /* Node initialization. */
984 strcpy(f->name, name);
985 f->mailbox_struct_type = mailbox_struct_type;
987 f->struct_id = p->n_structs;
988 f->id = p->n_extern_funcs;
990 /* Node add to tailq. */
991 TAILQ_INSERT_TAIL(&p->extern_funcs, f, node);
999 extern_func_build(struct rte_swx_pipeline *p)
1003 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1004 struct thread *t = &p->threads[i];
1005 struct extern_func *func;
1007 /* Memory allocation. */
1008 t->extern_funcs = calloc(p->n_extern_funcs,
1009 sizeof(struct extern_func_runtime));
1010 CHECK(t->extern_funcs, ENOMEM);
1012 /* Extern function. */
1013 TAILQ_FOREACH(func, &p->extern_funcs, node) {
1014 struct extern_func_runtime *r =
1015 &t->extern_funcs[func->id];
1016 uint32_t mailbox_size =
1017 func->mailbox_struct_type->n_bits / 8;
1019 r->func = func->func;
1021 r->mailbox = calloc(1, mailbox_size);
1022 CHECK(r->mailbox, ENOMEM);
1024 t->structs[func->struct_id] = r->mailbox;
1032 extern_func_build_free(struct rte_swx_pipeline *p)
1036 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1037 struct thread *t = &p->threads[i];
1040 if (!t->extern_funcs)
1043 for (j = 0; j < p->n_extern_funcs; j++) {
1044 struct extern_func_runtime *r = &t->extern_funcs[j];
1049 free(t->extern_funcs);
1050 t->extern_funcs = NULL;
1055 extern_func_free(struct rte_swx_pipeline *p)
1057 extern_func_build_free(p);
1060 struct extern_func *elem;
1062 elem = TAILQ_FIRST(&p->extern_funcs);
1066 TAILQ_REMOVE(&p->extern_funcs, elem, node);
1074 static struct header *
1075 header_find(struct rte_swx_pipeline *p, const char *name)
1077 struct header *elem;
1079 TAILQ_FOREACH(elem, &p->headers, node)
1080 if (strcmp(elem->name, name) == 0)
1087 rte_swx_pipeline_packet_header_register(struct rte_swx_pipeline *p,
1089 const char *struct_type_name)
1091 struct struct_type *st;
1093 size_t n_headers_max;
1096 CHECK_NAME(name, EINVAL);
1097 CHECK_NAME(struct_type_name, EINVAL);
1099 CHECK(!header_find(p, name), EEXIST);
1101 st = struct_type_find(p, struct_type_name);
1104 n_headers_max = RTE_SIZEOF_FIELD(struct thread, valid_headers) * 8;
1105 CHECK(p->n_headers < n_headers_max, ENOSPC);
1107 /* Node allocation. */
1108 h = calloc(1, sizeof(struct header));
1111 /* Node initialization. */
1112 strcpy(h->name, name);
1114 h->struct_id = p->n_structs;
1115 h->id = p->n_headers;
1117 /* Node add to tailq. */
1118 TAILQ_INSERT_TAIL(&p->headers, h, node);
1126 header_build(struct rte_swx_pipeline *p)
1129 uint32_t n_bytes = 0, i;
1131 TAILQ_FOREACH(h, &p->headers, node) {
1132 n_bytes += h->st->n_bits / 8;
1135 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1136 struct thread *t = &p->threads[i];
1137 uint32_t offset = 0;
1139 t->headers = calloc(p->n_headers,
1140 sizeof(struct header_runtime));
1141 CHECK(t->headers, ENOMEM);
1143 t->headers_out = calloc(p->n_headers,
1144 sizeof(struct header_out_runtime));
1145 CHECK(t->headers_out, ENOMEM);
1147 t->header_storage = calloc(1, n_bytes);
1148 CHECK(t->header_storage, ENOMEM);
1150 t->header_out_storage = calloc(1, n_bytes);
1151 CHECK(t->header_out_storage, ENOMEM);
1153 TAILQ_FOREACH(h, &p->headers, node) {
1154 uint8_t *header_storage;
1156 header_storage = &t->header_storage[offset];
1157 offset += h->st->n_bits / 8;
1159 t->headers[h->id].ptr0 = header_storage;
1160 t->structs[h->struct_id] = header_storage;
1168 header_build_free(struct rte_swx_pipeline *p)
1172 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1173 struct thread *t = &p->threads[i];
1175 free(t->headers_out);
1176 t->headers_out = NULL;
1181 free(t->header_out_storage);
1182 t->header_out_storage = NULL;
1184 free(t->header_storage);
1185 t->header_storage = NULL;
1190 header_free(struct rte_swx_pipeline *p)
1192 header_build_free(p);
1195 struct header *elem;
1197 elem = TAILQ_FIRST(&p->headers);
1201 TAILQ_REMOVE(&p->headers, elem, node);
1210 rte_swx_pipeline_packet_metadata_register(struct rte_swx_pipeline *p,
1211 const char *struct_type_name)
1213 struct struct_type *st = NULL;
1217 CHECK_NAME(struct_type_name, EINVAL);
1218 st = struct_type_find(p, struct_type_name);
1220 CHECK(!p->metadata_st, EINVAL);
1222 p->metadata_st = st;
1223 p->metadata_struct_id = p->n_structs;
1231 metadata_build(struct rte_swx_pipeline *p)
1233 uint32_t n_bytes = p->metadata_st->n_bits / 8;
1236 /* Thread-level initialization. */
1237 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1238 struct thread *t = &p->threads[i];
1241 metadata = calloc(1, n_bytes);
1242 CHECK(metadata, ENOMEM);
1244 t->metadata = metadata;
1245 t->structs[p->metadata_struct_id] = metadata;
1252 metadata_build_free(struct rte_swx_pipeline *p)
1256 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1257 struct thread *t = &p->threads[i];
1265 metadata_free(struct rte_swx_pipeline *p)
1267 metadata_build_free(p);
1274 rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
1276 struct rte_swx_pipeline *pipeline;
1278 /* Check input parameters. */
1281 /* Memory allocation. */
1282 pipeline = calloc(1, sizeof(struct rte_swx_pipeline));
1283 CHECK(pipeline, ENOMEM);
1285 /* Initialization. */
1286 TAILQ_INIT(&pipeline->struct_types);
1287 TAILQ_INIT(&pipeline->port_in_types);
1288 TAILQ_INIT(&pipeline->ports_in);
1289 TAILQ_INIT(&pipeline->port_out_types);
1290 TAILQ_INIT(&pipeline->ports_out);
1291 TAILQ_INIT(&pipeline->extern_types);
1292 TAILQ_INIT(&pipeline->extern_objs);
1293 TAILQ_INIT(&pipeline->extern_funcs);
1294 TAILQ_INIT(&pipeline->headers);
1296 pipeline->n_structs = 1; /* Struct 0 is reserved for action_data. */
1297 pipeline->numa_node = numa_node;
1304 rte_swx_pipeline_free(struct rte_swx_pipeline *p)
1311 extern_func_free(p);
1321 rte_swx_pipeline_build(struct rte_swx_pipeline *p)
1326 CHECK(p->build_done == 0, EEXIST);
1328 status = port_in_build(p);
1332 status = port_out_build(p);
1336 status = struct_build(p);
1340 status = extern_obj_build(p);
1344 status = extern_func_build(p);
1348 status = header_build(p);
1352 status = metadata_build(p);
1360 metadata_build_free(p);
1361 header_build_free(p);
1362 extern_func_build_free(p);
1363 extern_obj_build_free(p);
1364 port_out_build_free(p);
1365 port_in_build_free(p);
1366 struct_build_free(p);