1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2020 Intel Corporation
10 #include <arpa/inet.h>
12 #include <rte_common.h>
13 #include <rte_prefetch.h>
14 #include <rte_byteorder.h>
15 #include <rte_cycles.h>
16 #include <rte_meter.h>
18 #include <rte_swx_table_selector.h>
19 #include <rte_swx_table_learner.h>
21 #include "rte_swx_pipeline.h"
22 #include "rte_swx_ctl.h"
24 #define CHECK(condition, err_code) \
30 #define CHECK_NAME(name, err_code) \
33 (strnlen((name), RTE_SWX_NAME_SIZE) < RTE_SWX_NAME_SIZE), \
36 #define CHECK_INSTRUCTION(instr, err_code) \
39 (strnlen((instr), RTE_SWX_INSTRUCTION_SIZE) < \
40 RTE_SWX_INSTRUCTION_SIZE), \
48 #define TRACE(...) printf(__VA_ARGS__)
56 #define ntoh64(x) rte_be_to_cpu_64(x)
57 #define hton64(x) rte_cpu_to_be_64(x)
59 #ifndef RTE_SWX_PIPELINE_HUGE_PAGES_DISABLE
61 #include <rte_malloc.h>
64 env_malloc(size_t size, size_t alignment, int numa_node)
66 return rte_zmalloc_socket(NULL, size, alignment, numa_node);
70 env_free(void *start, size_t size __rte_unused)
80 env_malloc(size_t size, size_t alignment __rte_unused, int numa_node)
84 if (numa_available() == -1)
87 start = numa_alloc_onnode(size, numa_node);
91 memset(start, 0, size);
96 env_free(void *start, size_t size)
98 if (numa_available() == -1)
101 numa_free(start, size);
110 char name[RTE_SWX_NAME_SIZE];
117 TAILQ_ENTRY(struct_type) node;
118 char name[RTE_SWX_NAME_SIZE];
119 struct field *fields;
126 TAILQ_HEAD(struct_type_tailq, struct_type);
131 struct port_in_type {
132 TAILQ_ENTRY(port_in_type) node;
133 char name[RTE_SWX_NAME_SIZE];
134 struct rte_swx_port_in_ops ops;
137 TAILQ_HEAD(port_in_type_tailq, port_in_type);
140 TAILQ_ENTRY(port_in) node;
141 struct port_in_type *type;
146 TAILQ_HEAD(port_in_tailq, port_in);
148 struct port_in_runtime {
149 rte_swx_port_in_pkt_rx_t pkt_rx;
156 struct port_out_type {
157 TAILQ_ENTRY(port_out_type) node;
158 char name[RTE_SWX_NAME_SIZE];
159 struct rte_swx_port_out_ops ops;
162 TAILQ_HEAD(port_out_type_tailq, port_out_type);
165 TAILQ_ENTRY(port_out) node;
166 struct port_out_type *type;
171 TAILQ_HEAD(port_out_tailq, port_out);
173 struct port_out_runtime {
174 rte_swx_port_out_pkt_tx_t pkt_tx;
175 rte_swx_port_out_flush_t flush;
182 struct extern_type_member_func {
183 TAILQ_ENTRY(extern_type_member_func) node;
184 char name[RTE_SWX_NAME_SIZE];
185 rte_swx_extern_type_member_func_t func;
189 TAILQ_HEAD(extern_type_member_func_tailq, extern_type_member_func);
192 TAILQ_ENTRY(extern_type) node;
193 char name[RTE_SWX_NAME_SIZE];
194 struct struct_type *mailbox_struct_type;
195 rte_swx_extern_type_constructor_t constructor;
196 rte_swx_extern_type_destructor_t destructor;
197 struct extern_type_member_func_tailq funcs;
201 TAILQ_HEAD(extern_type_tailq, extern_type);
204 TAILQ_ENTRY(extern_obj) node;
205 char name[RTE_SWX_NAME_SIZE];
206 struct extern_type *type;
212 TAILQ_HEAD(extern_obj_tailq, extern_obj);
214 #ifndef RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX
215 #define RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX 8
218 struct extern_obj_runtime {
221 rte_swx_extern_type_member_func_t funcs[RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX];
228 TAILQ_ENTRY(extern_func) node;
229 char name[RTE_SWX_NAME_SIZE];
230 struct struct_type *mailbox_struct_type;
231 rte_swx_extern_func_t func;
236 TAILQ_HEAD(extern_func_tailq, extern_func);
238 struct extern_func_runtime {
240 rte_swx_extern_func_t func;
247 TAILQ_ENTRY(header) node;
248 char name[RTE_SWX_NAME_SIZE];
249 struct struct_type *st;
254 TAILQ_HEAD(header_tailq, header);
256 struct header_runtime {
261 struct header_out_runtime {
271 /* Packet headers are always in Network Byte Order (NBO), i.e. big endian.
272 * Packet meta-data fields are always assumed to be in Host Byte Order (HBO).
273 * Table entry fields can be in either NBO or HBO; they are assumed to be in HBO
274 * when transferred to packet meta-data and in NBO when transferred to packet
278 /* Notation conventions:
279 * -Header field: H = h.header.field (dst/src)
280 * -Meta-data field: M = m.field (dst/src)
281 * -Extern object mailbox field: E = e.field (dst/src)
282 * -Extern function mailbox field: F = f.field (dst/src)
283 * -Table action data field: T = t.field (src only)
284 * -Immediate value: I = 32-bit unsigned value (src only)
287 enum instruction_type {
294 INSTR_TX, /* port_out = M */
295 INSTR_TX_I, /* port_out = I */
297 /* extract h.header */
307 /* extract h.header m.last_field_size */
310 /* lookahead h.header */
324 /* validate h.header */
327 /* invalidate h.header */
328 INSTR_HDR_INVALIDATE,
332 * dst = HMEF, src = HMEFTI
334 INSTR_MOV, /* dst = MEF, src = MEFT */
335 INSTR_MOV_MH, /* dst = MEF, src = H */
336 INSTR_MOV_HM, /* dst = H, src = MEFT */
337 INSTR_MOV_HH, /* dst = H, src = H */
338 INSTR_MOV_I, /* dst = HMEF, src = I */
340 /* dma h.header t.field
341 * memcpy(h.header, t.field, sizeof(h.header))
354 * dst = HMEF, src = HMEFTI
356 INSTR_ALU_ADD, /* dst = MEF, src = MEF */
357 INSTR_ALU_ADD_MH, /* dst = MEF, src = H */
358 INSTR_ALU_ADD_HM, /* dst = H, src = MEF */
359 INSTR_ALU_ADD_HH, /* dst = H, src = H */
360 INSTR_ALU_ADD_MI, /* dst = MEF, src = I */
361 INSTR_ALU_ADD_HI, /* dst = H, src = I */
365 * dst = HMEF, src = HMEFTI
367 INSTR_ALU_SUB, /* dst = MEF, src = MEF */
368 INSTR_ALU_SUB_MH, /* dst = MEF, src = H */
369 INSTR_ALU_SUB_HM, /* dst = H, src = MEF */
370 INSTR_ALU_SUB_HH, /* dst = H, src = H */
371 INSTR_ALU_SUB_MI, /* dst = MEF, src = I */
372 INSTR_ALU_SUB_HI, /* dst = H, src = I */
375 * dst = dst '+ src[0:1] '+ src[2:3] + ...
376 * dst = H, src = {H, h.header}
378 INSTR_ALU_CKADD_FIELD, /* src = H */
379 INSTR_ALU_CKADD_STRUCT20, /* src = h.header, with sizeof(header) = 20 */
380 INSTR_ALU_CKADD_STRUCT, /* src = h.hdeader, with any sizeof(header) */
386 INSTR_ALU_CKSUB_FIELD,
390 * dst = HMEF, src = HMEFTI
392 INSTR_ALU_AND, /* dst = MEF, src = MEFT */
393 INSTR_ALU_AND_MH, /* dst = MEF, src = H */
394 INSTR_ALU_AND_HM, /* dst = H, src = MEFT */
395 INSTR_ALU_AND_HH, /* dst = H, src = H */
396 INSTR_ALU_AND_I, /* dst = HMEF, src = I */
400 * dst = HMEF, src = HMEFTI
402 INSTR_ALU_OR, /* dst = MEF, src = MEFT */
403 INSTR_ALU_OR_MH, /* dst = MEF, src = H */
404 INSTR_ALU_OR_HM, /* dst = H, src = MEFT */
405 INSTR_ALU_OR_HH, /* dst = H, src = H */
406 INSTR_ALU_OR_I, /* dst = HMEF, src = I */
410 * dst = HMEF, src = HMEFTI
412 INSTR_ALU_XOR, /* dst = MEF, src = MEFT */
413 INSTR_ALU_XOR_MH, /* dst = MEF, src = H */
414 INSTR_ALU_XOR_HM, /* dst = H, src = MEFT */
415 INSTR_ALU_XOR_HH, /* dst = H, src = H */
416 INSTR_ALU_XOR_I, /* dst = HMEF, src = I */
420 * dst = HMEF, src = HMEFTI
422 INSTR_ALU_SHL, /* dst = MEF, src = MEF */
423 INSTR_ALU_SHL_MH, /* dst = MEF, src = H */
424 INSTR_ALU_SHL_HM, /* dst = H, src = MEF */
425 INSTR_ALU_SHL_HH, /* dst = H, src = H */
426 INSTR_ALU_SHL_MI, /* dst = MEF, src = I */
427 INSTR_ALU_SHL_HI, /* dst = H, src = I */
431 * dst = HMEF, src = HMEFTI
433 INSTR_ALU_SHR, /* dst = MEF, src = MEF */
434 INSTR_ALU_SHR_MH, /* dst = MEF, src = H */
435 INSTR_ALU_SHR_HM, /* dst = H, src = MEF */
436 INSTR_ALU_SHR_HH, /* dst = H, src = H */
437 INSTR_ALU_SHR_MI, /* dst = MEF, src = I */
438 INSTR_ALU_SHR_HI, /* dst = H, src = I */
440 /* regprefetch REGARRAY index
441 * prefetch REGARRAY[index]
444 INSTR_REGPREFETCH_RH, /* index = H */
445 INSTR_REGPREFETCH_RM, /* index = MEFT */
446 INSTR_REGPREFETCH_RI, /* index = I */
448 /* regrd dst REGARRAY index
449 * dst = REGARRAY[index]
450 * dst = HMEF, index = HMEFTI
452 INSTR_REGRD_HRH, /* dst = H, index = H */
453 INSTR_REGRD_HRM, /* dst = H, index = MEFT */
454 INSTR_REGRD_HRI, /* dst = H, index = I */
455 INSTR_REGRD_MRH, /* dst = MEF, index = H */
456 INSTR_REGRD_MRM, /* dst = MEF, index = MEFT */
457 INSTR_REGRD_MRI, /* dst = MEF, index = I */
459 /* regwr REGARRAY index src
460 * REGARRAY[index] = src
461 * index = HMEFTI, src = HMEFTI
463 INSTR_REGWR_RHH, /* index = H, src = H */
464 INSTR_REGWR_RHM, /* index = H, src = MEFT */
465 INSTR_REGWR_RHI, /* index = H, src = I */
466 INSTR_REGWR_RMH, /* index = MEFT, src = H */
467 INSTR_REGWR_RMM, /* index = MEFT, src = MEFT */
468 INSTR_REGWR_RMI, /* index = MEFT, src = I */
469 INSTR_REGWR_RIH, /* index = I, src = H */
470 INSTR_REGWR_RIM, /* index = I, src = MEFT */
471 INSTR_REGWR_RII, /* index = I, src = I */
473 /* regadd REGARRAY index src
474 * REGARRAY[index] += src
475 * index = HMEFTI, src = HMEFTI
477 INSTR_REGADD_RHH, /* index = H, src = H */
478 INSTR_REGADD_RHM, /* index = H, src = MEFT */
479 INSTR_REGADD_RHI, /* index = H, src = I */
480 INSTR_REGADD_RMH, /* index = MEFT, src = H */
481 INSTR_REGADD_RMM, /* index = MEFT, src = MEFT */
482 INSTR_REGADD_RMI, /* index = MEFT, src = I */
483 INSTR_REGADD_RIH, /* index = I, src = H */
484 INSTR_REGADD_RIM, /* index = I, src = MEFT */
485 INSTR_REGADD_RII, /* index = I, src = I */
487 /* metprefetch METARRAY index
488 * prefetch METARRAY[index]
491 INSTR_METPREFETCH_H, /* index = H */
492 INSTR_METPREFETCH_M, /* index = MEFT */
493 INSTR_METPREFETCH_I, /* index = I */
495 /* meter METARRAY index length color_in color_out
496 * color_out = meter(METARRAY[index], length, color_in)
497 * index = HMEFTI, length = HMEFT, color_in = MEFTI, color_out = MEF
499 INSTR_METER_HHM, /* index = H, length = H, color_in = MEFT */
500 INSTR_METER_HHI, /* index = H, length = H, color_in = I */
501 INSTR_METER_HMM, /* index = H, length = MEFT, color_in = MEFT */
502 INSTR_METER_HMI, /* index = H, length = MEFT, color_in = I */
503 INSTR_METER_MHM, /* index = MEFT, length = H, color_in = MEFT */
504 INSTR_METER_MHI, /* index = MEFT, length = H, color_in = I */
505 INSTR_METER_MMM, /* index = MEFT, length = MEFT, color_in = MEFT */
506 INSTR_METER_MMI, /* index = MEFT, length = MEFT, color_in = I */
507 INSTR_METER_IHM, /* index = I, length = H, color_in = MEFT */
508 INSTR_METER_IHI, /* index = I, length = H, color_in = I */
509 INSTR_METER_IMM, /* index = I, length = MEFT, color_in = MEFT */
510 INSTR_METER_IMI, /* index = I, length = MEFT, color_in = I */
517 /* learn LEARNER ACTION_NAME */
521 INSTR_LEARNER_FORGET,
523 /* extern e.obj.func */
534 /* jmpv LABEL h.header
535 * Jump if header is valid
539 /* jmpnv LABEL h.header
540 * Jump if header is invalid
545 * Jump if table lookup hit
550 * Jump if table lookup miss
557 INSTR_JMP_ACTION_HIT,
559 /* jmpna LABEL ACTION
560 * Jump if action not run
562 INSTR_JMP_ACTION_MISS,
565 * Jump if a is equal to b
566 * a = HMEFT, b = HMEFTI
568 INSTR_JMP_EQ, /* a = MEFT, b = MEFT */
569 INSTR_JMP_EQ_MH, /* a = MEFT, b = H */
570 INSTR_JMP_EQ_HM, /* a = H, b = MEFT */
571 INSTR_JMP_EQ_HH, /* a = H, b = H */
572 INSTR_JMP_EQ_I, /* (a, b) = (MEFT, I) or (a, b) = (H, I) */
575 * Jump if a is not equal to b
576 * a = HMEFT, b = HMEFTI
578 INSTR_JMP_NEQ, /* a = MEFT, b = MEFT */
579 INSTR_JMP_NEQ_MH, /* a = MEFT, b = H */
580 INSTR_JMP_NEQ_HM, /* a = H, b = MEFT */
581 INSTR_JMP_NEQ_HH, /* a = H, b = H */
582 INSTR_JMP_NEQ_I, /* (a, b) = (MEFT, I) or (a, b) = (H, I) */
585 * Jump if a is less than b
586 * a = HMEFT, b = HMEFTI
588 INSTR_JMP_LT, /* a = MEFT, b = MEFT */
589 INSTR_JMP_LT_MH, /* a = MEFT, b = H */
590 INSTR_JMP_LT_HM, /* a = H, b = MEFT */
591 INSTR_JMP_LT_HH, /* a = H, b = H */
592 INSTR_JMP_LT_MI, /* a = MEFT, b = I */
593 INSTR_JMP_LT_HI, /* a = H, b = I */
596 * Jump if a is greater than b
597 * a = HMEFT, b = HMEFTI
599 INSTR_JMP_GT, /* a = MEFT, b = MEFT */
600 INSTR_JMP_GT_MH, /* a = MEFT, b = H */
601 INSTR_JMP_GT_HM, /* a = H, b = MEFT */
602 INSTR_JMP_GT_HH, /* a = H, b = H */
603 INSTR_JMP_GT_MI, /* a = MEFT, b = I */
604 INSTR_JMP_GT_HI, /* a = H, b = I */
612 struct instr_operand {
633 uint8_t header_id[8];
634 uint8_t struct_id[8];
639 struct instr_hdr_validity {
651 struct instr_extern_obj {
656 struct instr_extern_func {
660 struct instr_dst_src {
661 struct instr_operand dst;
663 struct instr_operand src;
668 struct instr_regarray {
673 struct instr_operand idx;
678 struct instr_operand dstsrc;
688 struct instr_operand idx;
692 struct instr_operand length;
695 struct instr_operand color_in;
696 uint32_t color_in_val;
699 struct instr_operand color_out;
704 uint8_t header_id[8];
705 uint8_t struct_id[8];
716 struct instruction *ip;
719 struct instr_operand a;
725 struct instr_operand b;
731 enum instruction_type type;
734 struct instr_hdr_validity valid;
735 struct instr_dst_src mov;
736 struct instr_regarray regarray;
737 struct instr_meter meter;
738 struct instr_dma dma;
739 struct instr_dst_src alu;
740 struct instr_table table;
741 struct instr_learn learn;
742 struct instr_extern_obj ext_obj;
743 struct instr_extern_func ext_func;
744 struct instr_jmp jmp;
748 struct instruction_data {
749 char label[RTE_SWX_NAME_SIZE];
750 char jmp_label[RTE_SWX_NAME_SIZE];
751 uint32_t n_users; /* user = jmp instruction to this instruction. */
759 TAILQ_ENTRY(action) node;
760 char name[RTE_SWX_NAME_SIZE];
761 struct struct_type *st;
762 int *args_endianness; /* 0 = Host Byte Order (HBO); 1 = Network Byte Order (NBO). */
763 struct instruction *instructions;
764 uint32_t n_instructions;
768 TAILQ_HEAD(action_tailq, action);
774 TAILQ_ENTRY(table_type) node;
775 char name[RTE_SWX_NAME_SIZE];
776 enum rte_swx_table_match_type match_type;
777 struct rte_swx_table_ops ops;
780 TAILQ_HEAD(table_type_tailq, table_type);
783 enum rte_swx_table_match_type match_type;
788 TAILQ_ENTRY(table) node;
789 char name[RTE_SWX_NAME_SIZE];
790 char args[RTE_SWX_NAME_SIZE];
791 struct table_type *type; /* NULL when n_fields == 0. */
794 struct match_field *fields;
796 struct header *header; /* Only valid when n_fields > 0. */
799 struct action **actions;
800 struct action *default_action;
801 uint8_t *default_action_data;
803 int default_action_is_const;
804 uint32_t action_data_size_max;
810 TAILQ_HEAD(table_tailq, table);
812 struct table_runtime {
813 rte_swx_table_lookup_t func;
818 struct table_statistics {
819 uint64_t n_pkts_hit[2]; /* 0 = Miss, 1 = Hit. */
820 uint64_t *n_pkts_action;
827 TAILQ_ENTRY(selector) node;
828 char name[RTE_SWX_NAME_SIZE];
830 struct field *group_id_field;
831 struct field **selector_fields;
832 uint32_t n_selector_fields;
833 struct header *selector_header;
834 struct field *member_id_field;
836 uint32_t n_groups_max;
837 uint32_t n_members_per_group_max;
842 TAILQ_HEAD(selector_tailq, selector);
844 struct selector_runtime {
846 uint8_t **group_id_buffer;
847 uint8_t **selector_buffer;
848 uint8_t **member_id_buffer;
851 struct selector_statistics {
859 TAILQ_ENTRY(learner) node;
860 char name[RTE_SWX_NAME_SIZE];
863 struct field **fields;
865 struct header *header;
868 struct action **actions;
869 struct field **action_arg;
870 struct action *default_action;
871 uint8_t *default_action_data;
873 int default_action_is_const;
874 uint32_t action_data_size_max;
881 TAILQ_HEAD(learner_tailq, learner);
883 struct learner_runtime {
886 uint8_t **action_data;
889 struct learner_statistics {
890 uint64_t n_pkts_hit[2]; /* 0 = Miss, 1 = Hit. */
891 uint64_t n_pkts_learn[2]; /* 0 = Learn OK, 1 = Learn error. */
892 uint64_t n_pkts_forget;
893 uint64_t *n_pkts_action;
900 TAILQ_ENTRY(regarray) node;
901 char name[RTE_SWX_NAME_SIZE];
907 TAILQ_HEAD(regarray_tailq, regarray);
909 struct regarray_runtime {
917 struct meter_profile {
918 TAILQ_ENTRY(meter_profile) node;
919 char name[RTE_SWX_NAME_SIZE];
920 struct rte_meter_trtcm_params params;
921 struct rte_meter_trtcm_profile profile;
925 TAILQ_HEAD(meter_profile_tailq, meter_profile);
928 TAILQ_ENTRY(metarray) node;
929 char name[RTE_SWX_NAME_SIZE];
934 TAILQ_HEAD(metarray_tailq, metarray);
937 struct rte_meter_trtcm m;
938 struct meter_profile *profile;
939 enum rte_color color_mask;
942 uint64_t n_pkts[RTE_COLORS];
943 uint64_t n_bytes[RTE_COLORS];
946 struct metarray_runtime {
947 struct meter *metarray;
956 struct rte_swx_pkt pkt;
962 /* Packet headers. */
963 struct header_runtime *headers; /* Extracted or generated headers. */
964 struct header_out_runtime *headers_out; /* Emitted headers. */
965 uint8_t *header_storage;
966 uint8_t *header_out_storage;
967 uint64_t valid_headers;
968 uint32_t n_headers_out;
970 /* Packet meta-data. */
974 struct table_runtime *tables;
975 struct selector_runtime *selectors;
976 struct learner_runtime *learners;
977 struct rte_swx_table_state *table_state;
979 int hit; /* 0 = Miss, 1 = Hit. */
983 /* Extern objects and functions. */
984 struct extern_obj_runtime *extern_objs;
985 struct extern_func_runtime *extern_funcs;
988 struct instruction *ip;
989 struct instruction *ret;
992 #define MASK64_BIT_GET(mask, pos) ((mask) & (1LLU << (pos)))
993 #define MASK64_BIT_SET(mask, pos) ((mask) | (1LLU << (pos)))
994 #define MASK64_BIT_CLR(mask, pos) ((mask) & ~(1LLU << (pos)))
996 #define HEADER_VALID(thread, header_id) \
997 MASK64_BIT_GET((thread)->valid_headers, header_id)
999 #define ALU(thread, ip, operator) \
1001 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
1002 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
1003 uint64_t dst64 = *dst64_ptr; \
1004 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
1005 uint64_t dst = dst64 & dst64_mask; \
1007 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
1008 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
1009 uint64_t src64 = *src64_ptr; \
1010 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->alu.src.n_bits); \
1011 uint64_t src = src64 & src64_mask; \
1013 uint64_t result = dst operator src; \
1015 *dst64_ptr = (dst64 & ~dst64_mask) | (result & dst64_mask); \
1018 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1020 #define ALU_MH(thread, ip, operator) \
1022 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
1023 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
1024 uint64_t dst64 = *dst64_ptr; \
1025 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
1026 uint64_t dst = dst64 & dst64_mask; \
1028 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
1029 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
1030 uint64_t src64 = *src64_ptr; \
1031 uint64_t src = ntoh64(src64) >> (64 - (ip)->alu.src.n_bits); \
1033 uint64_t result = dst operator src; \
1035 *dst64_ptr = (dst64 & ~dst64_mask) | (result & dst64_mask); \
1038 #define ALU_HM(thread, ip, operator) \
1040 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
1041 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
1042 uint64_t dst64 = *dst64_ptr; \
1043 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
1044 uint64_t dst = ntoh64(dst64) >> (64 - (ip)->alu.dst.n_bits); \
1046 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
1047 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
1048 uint64_t src64 = *src64_ptr; \
1049 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->alu.src.n_bits); \
1050 uint64_t src = src64 & src64_mask; \
1052 uint64_t result = dst operator src; \
1053 result = hton64(result << (64 - (ip)->alu.dst.n_bits)); \
1055 *dst64_ptr = (dst64 & ~dst64_mask) | result; \
1058 #define ALU_HM_FAST(thread, ip, operator) \
1060 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
1061 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
1062 uint64_t dst64 = *dst64_ptr; \
1063 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
1064 uint64_t dst = dst64 & dst64_mask; \
1066 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
1067 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
1068 uint64_t src64 = *src64_ptr; \
1069 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->alu.src.n_bits); \
1070 uint64_t src = hton64(src64 & src64_mask) >> (64 - (ip)->alu.dst.n_bits); \
1072 uint64_t result = dst operator src; \
1074 *dst64_ptr = (dst64 & ~dst64_mask) | result; \
1077 #define ALU_HH(thread, ip, operator) \
1079 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
1080 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
1081 uint64_t dst64 = *dst64_ptr; \
1082 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
1083 uint64_t dst = ntoh64(dst64) >> (64 - (ip)->alu.dst.n_bits); \
1085 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
1086 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
1087 uint64_t src64 = *src64_ptr; \
1088 uint64_t src = ntoh64(src64) >> (64 - (ip)->alu.src.n_bits); \
1090 uint64_t result = dst operator src; \
1091 result = hton64(result << (64 - (ip)->alu.dst.n_bits)); \
1093 *dst64_ptr = (dst64 & ~dst64_mask) | result; \
1096 #define ALU_HH_FAST(thread, ip, operator) \
1098 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
1099 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
1100 uint64_t dst64 = *dst64_ptr; \
1101 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
1102 uint64_t dst = dst64 & dst64_mask; \
1104 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
1105 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
1106 uint64_t src64 = *src64_ptr; \
1107 uint64_t src = (src64 << (64 - (ip)->alu.src.n_bits)) >> (64 - (ip)->alu.dst.n_bits); \
1109 uint64_t result = dst operator src; \
1111 *dst64_ptr = (dst64 & ~dst64_mask) | result; \
1118 #define ALU_HM_FAST ALU
1120 #define ALU_HH_FAST ALU
1124 #define ALU_I(thread, ip, operator) \
1126 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
1127 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
1128 uint64_t dst64 = *dst64_ptr; \
1129 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
1130 uint64_t dst = dst64 & dst64_mask; \
1132 uint64_t src = (ip)->alu.src_val; \
1134 uint64_t result = dst operator src; \
1136 *dst64_ptr = (dst64 & ~dst64_mask) | (result & dst64_mask); \
1139 #define ALU_MI ALU_I
1141 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1143 #define ALU_HI(thread, ip, operator) \
1145 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
1146 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
1147 uint64_t dst64 = *dst64_ptr; \
1148 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
1149 uint64_t dst = ntoh64(dst64) >> (64 - (ip)->alu.dst.n_bits); \
1151 uint64_t src = (ip)->alu.src_val; \
1153 uint64_t result = dst operator src; \
1154 result = hton64(result << (64 - (ip)->alu.dst.n_bits)); \
1156 *dst64_ptr = (dst64 & ~dst64_mask) | result; \
1161 #define ALU_HI ALU_I
1165 #define MOV(thread, ip) \
1167 uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id]; \
1168 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset]; \
1169 uint64_t dst64 = *dst64_ptr; \
1170 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits); \
1172 uint8_t *src_struct = (thread)->structs[(ip)->mov.src.struct_id]; \
1173 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->mov.src.offset]; \
1174 uint64_t src64 = *src64_ptr; \
1175 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->mov.src.n_bits); \
1176 uint64_t src = src64 & src64_mask; \
1178 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask); \
1181 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1183 #define MOV_MH(thread, ip) \
1185 uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id]; \
1186 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset]; \
1187 uint64_t dst64 = *dst64_ptr; \
1188 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits); \
1190 uint8_t *src_struct = (thread)->structs[(ip)->mov.src.struct_id]; \
1191 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->mov.src.offset]; \
1192 uint64_t src64 = *src64_ptr; \
1193 uint64_t src = ntoh64(src64) >> (64 - (ip)->mov.src.n_bits); \
1195 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask); \
1198 #define MOV_HM(thread, ip) \
1200 uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id]; \
1201 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset]; \
1202 uint64_t dst64 = *dst64_ptr; \
1203 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits); \
1205 uint8_t *src_struct = (thread)->structs[(ip)->mov.src.struct_id]; \
1206 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->mov.src.offset]; \
1207 uint64_t src64 = *src64_ptr; \
1208 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->mov.src.n_bits); \
1209 uint64_t src = src64 & src64_mask; \
1211 src = hton64(src) >> (64 - (ip)->mov.dst.n_bits); \
1212 *dst64_ptr = (dst64 & ~dst64_mask) | src; \
1215 #define MOV_HH(thread, ip) \
1217 uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id]; \
1218 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset]; \
1219 uint64_t dst64 = *dst64_ptr; \
1220 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits); \
1222 uint8_t *src_struct = (thread)->structs[(ip)->mov.src.struct_id]; \
1223 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->mov.src.offset]; \
1224 uint64_t src64 = *src64_ptr; \
1226 uint64_t src = src64 << (64 - (ip)->mov.src.n_bits); \
1227 src = src >> (64 - (ip)->mov.dst.n_bits); \
1228 *dst64_ptr = (dst64 & ~dst64_mask) | src; \
1239 #define MOV_I(thread, ip) \
1241 uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id]; \
1242 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset]; \
1243 uint64_t dst64 = *dst64_ptr; \
1244 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits); \
1246 uint64_t src = (ip)->mov.src_val; \
1248 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask); \
1251 #define JMP_CMP(thread, ip, operator) \
1253 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1254 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1255 uint64_t a64 = *a64_ptr; \
1256 uint64_t a64_mask = UINT64_MAX >> (64 - (ip)->jmp.a.n_bits); \
1257 uint64_t a = a64 & a64_mask; \
1259 uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id]; \
1260 uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset]; \
1261 uint64_t b64 = *b64_ptr; \
1262 uint64_t b64_mask = UINT64_MAX >> (64 - (ip)->jmp.b.n_bits); \
1263 uint64_t b = b64 & b64_mask; \
1265 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1268 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1270 #define JMP_CMP_MH(thread, ip, operator) \
1272 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1273 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1274 uint64_t a64 = *a64_ptr; \
1275 uint64_t a64_mask = UINT64_MAX >> (64 - (ip)->jmp.a.n_bits); \
1276 uint64_t a = a64 & a64_mask; \
1278 uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id]; \
1279 uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset]; \
1280 uint64_t b64 = *b64_ptr; \
1281 uint64_t b = ntoh64(b64) >> (64 - (ip)->jmp.b.n_bits); \
1283 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1286 #define JMP_CMP_HM(thread, ip, operator) \
1288 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1289 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1290 uint64_t a64 = *a64_ptr; \
1291 uint64_t a = ntoh64(a64) >> (64 - (ip)->jmp.a.n_bits); \
1293 uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id]; \
1294 uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset]; \
1295 uint64_t b64 = *b64_ptr; \
1296 uint64_t b64_mask = UINT64_MAX >> (64 - (ip)->jmp.b.n_bits); \
1297 uint64_t b = b64 & b64_mask; \
1299 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1302 #define JMP_CMP_HH(thread, ip, operator) \
1304 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1305 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1306 uint64_t a64 = *a64_ptr; \
1307 uint64_t a = ntoh64(a64) >> (64 - (ip)->jmp.a.n_bits); \
1309 uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id]; \
1310 uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset]; \
1311 uint64_t b64 = *b64_ptr; \
1312 uint64_t b = ntoh64(b64) >> (64 - (ip)->jmp.b.n_bits); \
1314 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1317 #define JMP_CMP_HH_FAST(thread, ip, operator) \
1319 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1320 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1321 uint64_t a64 = *a64_ptr; \
1322 uint64_t a = a64 << (64 - (ip)->jmp.a.n_bits); \
1324 uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id]; \
1325 uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset]; \
1326 uint64_t b64 = *b64_ptr; \
1327 uint64_t b = b64 << (64 - (ip)->jmp.b.n_bits); \
1329 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1334 #define JMP_CMP_MH JMP_CMP
1335 #define JMP_CMP_HM JMP_CMP
1336 #define JMP_CMP_HH JMP_CMP
1337 #define JMP_CMP_HH_FAST JMP_CMP
1341 #define JMP_CMP_I(thread, ip, operator) \
1343 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1344 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1345 uint64_t a64 = *a64_ptr; \
1346 uint64_t a64_mask = UINT64_MAX >> (64 - (ip)->jmp.a.n_bits); \
1347 uint64_t a = a64 & a64_mask; \
1349 uint64_t b = (ip)->jmp.b_val; \
1351 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1354 #define JMP_CMP_MI JMP_CMP_I
1356 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1358 #define JMP_CMP_HI(thread, ip, operator) \
1360 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1361 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1362 uint64_t a64 = *a64_ptr; \
1363 uint64_t a = ntoh64(a64) >> (64 - (ip)->jmp.a.n_bits); \
1365 uint64_t b = (ip)->jmp.b_val; \
1367 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1372 #define JMP_CMP_HI JMP_CMP_I
1376 #define METADATA_READ(thread, offset, n_bits) \
1378 uint64_t *m64_ptr = (uint64_t *)&(thread)->metadata[offset]; \
1379 uint64_t m64 = *m64_ptr; \
1380 uint64_t m64_mask = UINT64_MAX >> (64 - (n_bits)); \
1384 #define METADATA_WRITE(thread, offset, n_bits, value) \
1386 uint64_t *m64_ptr = (uint64_t *)&(thread)->metadata[offset]; \
1387 uint64_t m64 = *m64_ptr; \
1388 uint64_t m64_mask = UINT64_MAX >> (64 - (n_bits)); \
1390 uint64_t m_new = value; \
1392 *m64_ptr = (m64 & ~m64_mask) | (m_new & m64_mask); \
1395 #ifndef RTE_SWX_PIPELINE_THREADS_MAX
1396 #define RTE_SWX_PIPELINE_THREADS_MAX 16
1399 struct rte_swx_pipeline {
1400 struct struct_type_tailq struct_types;
1401 struct port_in_type_tailq port_in_types;
1402 struct port_in_tailq ports_in;
1403 struct port_out_type_tailq port_out_types;
1404 struct port_out_tailq ports_out;
1405 struct extern_type_tailq extern_types;
1406 struct extern_obj_tailq extern_objs;
1407 struct extern_func_tailq extern_funcs;
1408 struct header_tailq headers;
1409 struct struct_type *metadata_st;
1410 uint32_t metadata_struct_id;
1411 struct action_tailq actions;
1412 struct table_type_tailq table_types;
1413 struct table_tailq tables;
1414 struct selector_tailq selectors;
1415 struct learner_tailq learners;
1416 struct regarray_tailq regarrays;
1417 struct meter_profile_tailq meter_profiles;
1418 struct metarray_tailq metarrays;
1420 struct port_in_runtime *in;
1421 struct port_out_runtime *out;
1422 struct instruction **action_instructions;
1423 struct rte_swx_table_state *table_state;
1424 struct table_statistics *table_stats;
1425 struct selector_statistics *selector_stats;
1426 struct learner_statistics *learner_stats;
1427 struct regarray_runtime *regarray_runtime;
1428 struct metarray_runtime *metarray_runtime;
1429 struct instruction *instructions;
1430 struct thread threads[RTE_SWX_PIPELINE_THREADS_MAX];
1433 uint32_t n_ports_in;
1434 uint32_t n_ports_out;
1435 uint32_t n_extern_objs;
1436 uint32_t n_extern_funcs;
1439 uint32_t n_selectors;
1440 uint32_t n_learners;
1441 uint32_t n_regarrays;
1442 uint32_t n_metarrays;
1446 uint32_t n_instructions;
1454 static struct struct_type *
1455 struct_type_find(struct rte_swx_pipeline *p, const char *name)
1457 struct struct_type *elem;
1459 TAILQ_FOREACH(elem, &p->struct_types, node)
1460 if (strcmp(elem->name, name) == 0)
1466 static struct field *
1467 struct_type_field_find(struct struct_type *st, const char *name)
1471 for (i = 0; i < st->n_fields; i++) {
1472 struct field *f = &st->fields[i];
1474 if (strcmp(f->name, name) == 0)
1482 rte_swx_pipeline_struct_type_register(struct rte_swx_pipeline *p,
1484 struct rte_swx_field_params *fields,
1486 int last_field_has_variable_size)
1488 struct struct_type *st;
1492 CHECK_NAME(name, EINVAL);
1493 CHECK(fields, EINVAL);
1494 CHECK(n_fields, EINVAL);
1496 for (i = 0; i < n_fields; i++) {
1497 struct rte_swx_field_params *f = &fields[i];
1498 int var_size = ((i == n_fields - 1) && last_field_has_variable_size) ? 1 : 0;
1501 CHECK_NAME(f->name, EINVAL);
1502 CHECK(f->n_bits, EINVAL);
1503 CHECK((f->n_bits <= 64) || var_size, EINVAL);
1504 CHECK((f->n_bits & 7) == 0, EINVAL);
1506 for (j = 0; j < i; j++) {
1507 struct rte_swx_field_params *f_prev = &fields[j];
1509 CHECK(strcmp(f->name, f_prev->name), EINVAL);
1513 CHECK(!struct_type_find(p, name), EEXIST);
1515 /* Node allocation. */
1516 st = calloc(1, sizeof(struct struct_type));
1519 st->fields = calloc(n_fields, sizeof(struct field));
1525 /* Node initialization. */
1526 strcpy(st->name, name);
1527 for (i = 0; i < n_fields; i++) {
1528 struct field *dst = &st->fields[i];
1529 struct rte_swx_field_params *src = &fields[i];
1530 int var_size = ((i == n_fields - 1) && last_field_has_variable_size) ? 1 : 0;
1532 strcpy(dst->name, src->name);
1533 dst->n_bits = src->n_bits;
1534 dst->offset = st->n_bits;
1535 dst->var_size = var_size;
1537 st->n_bits += src->n_bits;
1538 st->n_bits_min += var_size ? 0 : src->n_bits;
1540 st->n_fields = n_fields;
1541 st->var_size = last_field_has_variable_size;
1543 /* Node add to tailq. */
1544 TAILQ_INSERT_TAIL(&p->struct_types, st, node);
1550 struct_build(struct rte_swx_pipeline *p)
1554 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1555 struct thread *t = &p->threads[i];
1557 t->structs = calloc(p->n_structs, sizeof(uint8_t *));
1558 CHECK(t->structs, ENOMEM);
1565 struct_build_free(struct rte_swx_pipeline *p)
1569 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1570 struct thread *t = &p->threads[i];
1578 struct_free(struct rte_swx_pipeline *p)
1580 struct_build_free(p);
1584 struct struct_type *elem;
1586 elem = TAILQ_FIRST(&p->struct_types);
1590 TAILQ_REMOVE(&p->struct_types, elem, node);
1599 static struct port_in_type *
1600 port_in_type_find(struct rte_swx_pipeline *p, const char *name)
1602 struct port_in_type *elem;
1607 TAILQ_FOREACH(elem, &p->port_in_types, node)
1608 if (strcmp(elem->name, name) == 0)
1615 rte_swx_pipeline_port_in_type_register(struct rte_swx_pipeline *p,
1617 struct rte_swx_port_in_ops *ops)
1619 struct port_in_type *elem;
1622 CHECK_NAME(name, EINVAL);
1624 CHECK(ops->create, EINVAL);
1625 CHECK(ops->free, EINVAL);
1626 CHECK(ops->pkt_rx, EINVAL);
1627 CHECK(ops->stats_read, EINVAL);
1629 CHECK(!port_in_type_find(p, name), EEXIST);
1631 /* Node allocation. */
1632 elem = calloc(1, sizeof(struct port_in_type));
1633 CHECK(elem, ENOMEM);
1635 /* Node initialization. */
1636 strcpy(elem->name, name);
1637 memcpy(&elem->ops, ops, sizeof(*ops));
1639 /* Node add to tailq. */
1640 TAILQ_INSERT_TAIL(&p->port_in_types, elem, node);
1645 static struct port_in *
1646 port_in_find(struct rte_swx_pipeline *p, uint32_t port_id)
1648 struct port_in *port;
1650 TAILQ_FOREACH(port, &p->ports_in, node)
1651 if (port->id == port_id)
1658 rte_swx_pipeline_port_in_config(struct rte_swx_pipeline *p,
1660 const char *port_type_name,
1663 struct port_in_type *type = NULL;
1664 struct port_in *port = NULL;
1669 CHECK(!port_in_find(p, port_id), EINVAL);
1671 CHECK_NAME(port_type_name, EINVAL);
1672 type = port_in_type_find(p, port_type_name);
1673 CHECK(type, EINVAL);
1675 obj = type->ops.create(args);
1678 /* Node allocation. */
1679 port = calloc(1, sizeof(struct port_in));
1680 CHECK(port, ENOMEM);
1682 /* Node initialization. */
1687 /* Node add to tailq. */
1688 TAILQ_INSERT_TAIL(&p->ports_in, port, node);
1689 if (p->n_ports_in < port_id + 1)
1690 p->n_ports_in = port_id + 1;
1696 port_in_build(struct rte_swx_pipeline *p)
1698 struct port_in *port;
1701 CHECK(p->n_ports_in, EINVAL);
1702 CHECK(rte_is_power_of_2(p->n_ports_in), EINVAL);
1704 for (i = 0; i < p->n_ports_in; i++)
1705 CHECK(port_in_find(p, i), EINVAL);
1707 p->in = calloc(p->n_ports_in, sizeof(struct port_in_runtime));
1708 CHECK(p->in, ENOMEM);
1710 TAILQ_FOREACH(port, &p->ports_in, node) {
1711 struct port_in_runtime *in = &p->in[port->id];
1713 in->pkt_rx = port->type->ops.pkt_rx;
1714 in->obj = port->obj;
1721 port_in_build_free(struct rte_swx_pipeline *p)
1728 port_in_free(struct rte_swx_pipeline *p)
1730 port_in_build_free(p);
1734 struct port_in *port;
1736 port = TAILQ_FIRST(&p->ports_in);
1740 TAILQ_REMOVE(&p->ports_in, port, node);
1741 port->type->ops.free(port->obj);
1745 /* Input port types. */
1747 struct port_in_type *elem;
1749 elem = TAILQ_FIRST(&p->port_in_types);
1753 TAILQ_REMOVE(&p->port_in_types, elem, node);
1761 static struct port_out_type *
1762 port_out_type_find(struct rte_swx_pipeline *p, const char *name)
1764 struct port_out_type *elem;
1769 TAILQ_FOREACH(elem, &p->port_out_types, node)
1770 if (!strcmp(elem->name, name))
1777 rte_swx_pipeline_port_out_type_register(struct rte_swx_pipeline *p,
1779 struct rte_swx_port_out_ops *ops)
1781 struct port_out_type *elem;
1784 CHECK_NAME(name, EINVAL);
1786 CHECK(ops->create, EINVAL);
1787 CHECK(ops->free, EINVAL);
1788 CHECK(ops->pkt_tx, EINVAL);
1789 CHECK(ops->stats_read, EINVAL);
1791 CHECK(!port_out_type_find(p, name), EEXIST);
1793 /* Node allocation. */
1794 elem = calloc(1, sizeof(struct port_out_type));
1795 CHECK(elem, ENOMEM);
1797 /* Node initialization. */
1798 strcpy(elem->name, name);
1799 memcpy(&elem->ops, ops, sizeof(*ops));
1801 /* Node add to tailq. */
1802 TAILQ_INSERT_TAIL(&p->port_out_types, elem, node);
1807 static struct port_out *
1808 port_out_find(struct rte_swx_pipeline *p, uint32_t port_id)
1810 struct port_out *port;
1812 TAILQ_FOREACH(port, &p->ports_out, node)
1813 if (port->id == port_id)
1820 rte_swx_pipeline_port_out_config(struct rte_swx_pipeline *p,
1822 const char *port_type_name,
1825 struct port_out_type *type = NULL;
1826 struct port_out *port = NULL;
1831 CHECK(!port_out_find(p, port_id), EINVAL);
1833 CHECK_NAME(port_type_name, EINVAL);
1834 type = port_out_type_find(p, port_type_name);
1835 CHECK(type, EINVAL);
1837 obj = type->ops.create(args);
1840 /* Node allocation. */
1841 port = calloc(1, sizeof(struct port_out));
1842 CHECK(port, ENOMEM);
1844 /* Node initialization. */
1849 /* Node add to tailq. */
1850 TAILQ_INSERT_TAIL(&p->ports_out, port, node);
1851 if (p->n_ports_out < port_id + 1)
1852 p->n_ports_out = port_id + 1;
1858 port_out_build(struct rte_swx_pipeline *p)
1860 struct port_out *port;
1863 CHECK(p->n_ports_out, EINVAL);
1865 for (i = 0; i < p->n_ports_out; i++)
1866 CHECK(port_out_find(p, i), EINVAL);
1868 p->out = calloc(p->n_ports_out, sizeof(struct port_out_runtime));
1869 CHECK(p->out, ENOMEM);
1871 TAILQ_FOREACH(port, &p->ports_out, node) {
1872 struct port_out_runtime *out = &p->out[port->id];
1874 out->pkt_tx = port->type->ops.pkt_tx;
1875 out->flush = port->type->ops.flush;
1876 out->obj = port->obj;
1883 port_out_build_free(struct rte_swx_pipeline *p)
1890 port_out_free(struct rte_swx_pipeline *p)
1892 port_out_build_free(p);
1896 struct port_out *port;
1898 port = TAILQ_FIRST(&p->ports_out);
1902 TAILQ_REMOVE(&p->ports_out, port, node);
1903 port->type->ops.free(port->obj);
1907 /* Output port types. */
1909 struct port_out_type *elem;
1911 elem = TAILQ_FIRST(&p->port_out_types);
1915 TAILQ_REMOVE(&p->port_out_types, elem, node);
1923 static struct extern_type *
1924 extern_type_find(struct rte_swx_pipeline *p, const char *name)
1926 struct extern_type *elem;
1928 TAILQ_FOREACH(elem, &p->extern_types, node)
1929 if (strcmp(elem->name, name) == 0)
1935 static struct extern_type_member_func *
1936 extern_type_member_func_find(struct extern_type *type, const char *name)
1938 struct extern_type_member_func *elem;
1940 TAILQ_FOREACH(elem, &type->funcs, node)
1941 if (strcmp(elem->name, name) == 0)
1947 static struct extern_obj *
1948 extern_obj_find(struct rte_swx_pipeline *p, const char *name)
1950 struct extern_obj *elem;
1952 TAILQ_FOREACH(elem, &p->extern_objs, node)
1953 if (strcmp(elem->name, name) == 0)
1959 static struct extern_type_member_func *
1960 extern_obj_member_func_parse(struct rte_swx_pipeline *p,
1962 struct extern_obj **obj)
1964 struct extern_obj *object;
1965 struct extern_type_member_func *func;
1966 char *object_name, *func_name;
1968 if (name[0] != 'e' || name[1] != '.')
1971 object_name = strdup(&name[2]);
1975 func_name = strchr(object_name, '.');
1984 object = extern_obj_find(p, object_name);
1990 func = extern_type_member_func_find(object->type, func_name);
2003 static struct field *
2004 extern_obj_mailbox_field_parse(struct rte_swx_pipeline *p,
2006 struct extern_obj **object)
2008 struct extern_obj *obj;
2010 char *obj_name, *field_name;
2012 if ((name[0] != 'e') || (name[1] != '.'))
2015 obj_name = strdup(&name[2]);
2019 field_name = strchr(obj_name, '.');
2028 obj = extern_obj_find(p, obj_name);
2034 f = struct_type_field_find(obj->type->mailbox_struct_type, field_name);
2048 rte_swx_pipeline_extern_type_register(struct rte_swx_pipeline *p,
2050 const char *mailbox_struct_type_name,
2051 rte_swx_extern_type_constructor_t constructor,
2052 rte_swx_extern_type_destructor_t destructor)
2054 struct extern_type *elem;
2055 struct struct_type *mailbox_struct_type;
2059 CHECK_NAME(name, EINVAL);
2060 CHECK(!extern_type_find(p, name), EEXIST);
2062 CHECK_NAME(mailbox_struct_type_name, EINVAL);
2063 mailbox_struct_type = struct_type_find(p, mailbox_struct_type_name);
2064 CHECK(mailbox_struct_type, EINVAL);
2065 CHECK(!mailbox_struct_type->var_size, EINVAL);
2067 CHECK(constructor, EINVAL);
2068 CHECK(destructor, EINVAL);
2070 /* Node allocation. */
2071 elem = calloc(1, sizeof(struct extern_type));
2072 CHECK(elem, ENOMEM);
2074 /* Node initialization. */
2075 strcpy(elem->name, name);
2076 elem->mailbox_struct_type = mailbox_struct_type;
2077 elem->constructor = constructor;
2078 elem->destructor = destructor;
2079 TAILQ_INIT(&elem->funcs);
2081 /* Node add to tailq. */
2082 TAILQ_INSERT_TAIL(&p->extern_types, elem, node);
2088 rte_swx_pipeline_extern_type_member_func_register(struct rte_swx_pipeline *p,
2089 const char *extern_type_name,
2091 rte_swx_extern_type_member_func_t member_func)
2093 struct extern_type *type;
2094 struct extern_type_member_func *type_member;
2098 CHECK_NAME(extern_type_name, EINVAL);
2099 type = extern_type_find(p, extern_type_name);
2100 CHECK(type, EINVAL);
2101 CHECK(type->n_funcs < RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX, ENOSPC);
2103 CHECK_NAME(name, EINVAL);
2104 CHECK(!extern_type_member_func_find(type, name), EEXIST);
2106 CHECK(member_func, EINVAL);
2108 /* Node allocation. */
2109 type_member = calloc(1, sizeof(struct extern_type_member_func));
2110 CHECK(type_member, ENOMEM);
2112 /* Node initialization. */
2113 strcpy(type_member->name, name);
2114 type_member->func = member_func;
2115 type_member->id = type->n_funcs;
2117 /* Node add to tailq. */
2118 TAILQ_INSERT_TAIL(&type->funcs, type_member, node);
2125 rte_swx_pipeline_extern_object_config(struct rte_swx_pipeline *p,
2126 const char *extern_type_name,
2130 struct extern_type *type;
2131 struct extern_obj *obj;
2136 CHECK_NAME(extern_type_name, EINVAL);
2137 type = extern_type_find(p, extern_type_name);
2138 CHECK(type, EINVAL);
2140 CHECK_NAME(name, EINVAL);
2141 CHECK(!extern_obj_find(p, name), EEXIST);
2143 /* Node allocation. */
2144 obj = calloc(1, sizeof(struct extern_obj));
2147 /* Object construction. */
2148 obj_handle = type->constructor(args);
2154 /* Node initialization. */
2155 strcpy(obj->name, name);
2157 obj->obj = obj_handle;
2158 obj->struct_id = p->n_structs;
2159 obj->id = p->n_extern_objs;
2161 /* Node add to tailq. */
2162 TAILQ_INSERT_TAIL(&p->extern_objs, obj, node);
2170 extern_obj_build(struct rte_swx_pipeline *p)
2174 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
2175 struct thread *t = &p->threads[i];
2176 struct extern_obj *obj;
2178 t->extern_objs = calloc(p->n_extern_objs,
2179 sizeof(struct extern_obj_runtime));
2180 CHECK(t->extern_objs, ENOMEM);
2182 TAILQ_FOREACH(obj, &p->extern_objs, node) {
2183 struct extern_obj_runtime *r =
2184 &t->extern_objs[obj->id];
2185 struct extern_type_member_func *func;
2186 uint32_t mailbox_size =
2187 obj->type->mailbox_struct_type->n_bits / 8;
2191 r->mailbox = calloc(1, mailbox_size);
2192 CHECK(r->mailbox, ENOMEM);
2194 TAILQ_FOREACH(func, &obj->type->funcs, node)
2195 r->funcs[func->id] = func->func;
2197 t->structs[obj->struct_id] = r->mailbox;
2205 extern_obj_build_free(struct rte_swx_pipeline *p)
2209 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
2210 struct thread *t = &p->threads[i];
2213 if (!t->extern_objs)
2216 for (j = 0; j < p->n_extern_objs; j++) {
2217 struct extern_obj_runtime *r = &t->extern_objs[j];
2222 free(t->extern_objs);
2223 t->extern_objs = NULL;
2228 extern_obj_free(struct rte_swx_pipeline *p)
2230 extern_obj_build_free(p);
2232 /* Extern objects. */
2234 struct extern_obj *elem;
2236 elem = TAILQ_FIRST(&p->extern_objs);
2240 TAILQ_REMOVE(&p->extern_objs, elem, node);
2242 elem->type->destructor(elem->obj);
2248 struct extern_type *elem;
2250 elem = TAILQ_FIRST(&p->extern_types);
2254 TAILQ_REMOVE(&p->extern_types, elem, node);
2257 struct extern_type_member_func *func;
2259 func = TAILQ_FIRST(&elem->funcs);
2263 TAILQ_REMOVE(&elem->funcs, func, node);
2274 static struct extern_func *
2275 extern_func_find(struct rte_swx_pipeline *p, const char *name)
2277 struct extern_func *elem;
2279 TAILQ_FOREACH(elem, &p->extern_funcs, node)
2280 if (strcmp(elem->name, name) == 0)
2286 static struct extern_func *
2287 extern_func_parse(struct rte_swx_pipeline *p,
2290 if (name[0] != 'f' || name[1] != '.')
2293 return extern_func_find(p, &name[2]);
2296 static struct field *
2297 extern_func_mailbox_field_parse(struct rte_swx_pipeline *p,
2299 struct extern_func **function)
2301 struct extern_func *func;
2303 char *func_name, *field_name;
2305 if ((name[0] != 'f') || (name[1] != '.'))
2308 func_name = strdup(&name[2]);
2312 field_name = strchr(func_name, '.');
2321 func = extern_func_find(p, func_name);
2327 f = struct_type_field_find(func->mailbox_struct_type, field_name);
2341 rte_swx_pipeline_extern_func_register(struct rte_swx_pipeline *p,
2343 const char *mailbox_struct_type_name,
2344 rte_swx_extern_func_t func)
2346 struct extern_func *f;
2347 struct struct_type *mailbox_struct_type;
2351 CHECK_NAME(name, EINVAL);
2352 CHECK(!extern_func_find(p, name), EEXIST);
2354 CHECK_NAME(mailbox_struct_type_name, EINVAL);
2355 mailbox_struct_type = struct_type_find(p, mailbox_struct_type_name);
2356 CHECK(mailbox_struct_type, EINVAL);
2357 CHECK(!mailbox_struct_type->var_size, EINVAL);
2359 CHECK(func, EINVAL);
2361 /* Node allocation. */
2362 f = calloc(1, sizeof(struct extern_func));
2363 CHECK(func, ENOMEM);
2365 /* Node initialization. */
2366 strcpy(f->name, name);
2367 f->mailbox_struct_type = mailbox_struct_type;
2369 f->struct_id = p->n_structs;
2370 f->id = p->n_extern_funcs;
2372 /* Node add to tailq. */
2373 TAILQ_INSERT_TAIL(&p->extern_funcs, f, node);
2374 p->n_extern_funcs++;
2381 extern_func_build(struct rte_swx_pipeline *p)
2385 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
2386 struct thread *t = &p->threads[i];
2387 struct extern_func *func;
2389 /* Memory allocation. */
2390 t->extern_funcs = calloc(p->n_extern_funcs,
2391 sizeof(struct extern_func_runtime));
2392 CHECK(t->extern_funcs, ENOMEM);
2394 /* Extern function. */
2395 TAILQ_FOREACH(func, &p->extern_funcs, node) {
2396 struct extern_func_runtime *r =
2397 &t->extern_funcs[func->id];
2398 uint32_t mailbox_size =
2399 func->mailbox_struct_type->n_bits / 8;
2401 r->func = func->func;
2403 r->mailbox = calloc(1, mailbox_size);
2404 CHECK(r->mailbox, ENOMEM);
2406 t->structs[func->struct_id] = r->mailbox;
2414 extern_func_build_free(struct rte_swx_pipeline *p)
2418 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
2419 struct thread *t = &p->threads[i];
2422 if (!t->extern_funcs)
2425 for (j = 0; j < p->n_extern_funcs; j++) {
2426 struct extern_func_runtime *r = &t->extern_funcs[j];
2431 free(t->extern_funcs);
2432 t->extern_funcs = NULL;
2437 extern_func_free(struct rte_swx_pipeline *p)
2439 extern_func_build_free(p);
2442 struct extern_func *elem;
2444 elem = TAILQ_FIRST(&p->extern_funcs);
2448 TAILQ_REMOVE(&p->extern_funcs, elem, node);
2456 static struct header *
2457 header_find(struct rte_swx_pipeline *p, const char *name)
2459 struct header *elem;
2461 TAILQ_FOREACH(elem, &p->headers, node)
2462 if (strcmp(elem->name, name) == 0)
2468 static struct header *
2469 header_find_by_struct_id(struct rte_swx_pipeline *p, uint32_t struct_id)
2471 struct header *elem;
2473 TAILQ_FOREACH(elem, &p->headers, node)
2474 if (elem->struct_id == struct_id)
2480 static struct header *
2481 header_parse(struct rte_swx_pipeline *p,
2484 if (name[0] != 'h' || name[1] != '.')
2487 return header_find(p, &name[2]);
2490 static struct field *
2491 header_field_parse(struct rte_swx_pipeline *p,
2493 struct header **header)
2497 char *header_name, *field_name;
2499 if ((name[0] != 'h') || (name[1] != '.'))
2502 header_name = strdup(&name[2]);
2506 field_name = strchr(header_name, '.');
2515 h = header_find(p, header_name);
2521 f = struct_type_field_find(h->st, field_name);
2535 rte_swx_pipeline_packet_header_register(struct rte_swx_pipeline *p,
2537 const char *struct_type_name)
2539 struct struct_type *st;
2541 size_t n_headers_max;
2544 CHECK_NAME(name, EINVAL);
2545 CHECK_NAME(struct_type_name, EINVAL);
2547 CHECK(!header_find(p, name), EEXIST);
2549 st = struct_type_find(p, struct_type_name);
2552 n_headers_max = RTE_SIZEOF_FIELD(struct thread, valid_headers) * 8;
2553 CHECK(p->n_headers < n_headers_max, ENOSPC);
2555 /* Node allocation. */
2556 h = calloc(1, sizeof(struct header));
2559 /* Node initialization. */
2560 strcpy(h->name, name);
2562 h->struct_id = p->n_structs;
2563 h->id = p->n_headers;
2565 /* Node add to tailq. */
2566 TAILQ_INSERT_TAIL(&p->headers, h, node);
2574 header_build(struct rte_swx_pipeline *p)
2577 uint32_t n_bytes = 0, i;
2579 TAILQ_FOREACH(h, &p->headers, node) {
2580 n_bytes += h->st->n_bits / 8;
2583 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
2584 struct thread *t = &p->threads[i];
2585 uint32_t offset = 0;
2587 t->headers = calloc(p->n_headers,
2588 sizeof(struct header_runtime));
2589 CHECK(t->headers, ENOMEM);
2591 t->headers_out = calloc(p->n_headers,
2592 sizeof(struct header_out_runtime));
2593 CHECK(t->headers_out, ENOMEM);
2595 t->header_storage = calloc(1, n_bytes);
2596 CHECK(t->header_storage, ENOMEM);
2598 t->header_out_storage = calloc(1, n_bytes);
2599 CHECK(t->header_out_storage, ENOMEM);
2601 TAILQ_FOREACH(h, &p->headers, node) {
2602 uint8_t *header_storage;
2603 uint32_t n_bytes = h->st->n_bits / 8;
2605 header_storage = &t->header_storage[offset];
2608 t->headers[h->id].ptr0 = header_storage;
2609 t->headers[h->id].n_bytes = n_bytes;
2611 t->structs[h->struct_id] = header_storage;
2619 header_build_free(struct rte_swx_pipeline *p)
2623 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
2624 struct thread *t = &p->threads[i];
2626 free(t->headers_out);
2627 t->headers_out = NULL;
2632 free(t->header_out_storage);
2633 t->header_out_storage = NULL;
2635 free(t->header_storage);
2636 t->header_storage = NULL;
2641 header_free(struct rte_swx_pipeline *p)
2643 header_build_free(p);
2646 struct header *elem;
2648 elem = TAILQ_FIRST(&p->headers);
2652 TAILQ_REMOVE(&p->headers, elem, node);
2660 static struct field *
2661 metadata_field_parse(struct rte_swx_pipeline *p, const char *name)
2663 if (!p->metadata_st)
2666 if (name[0] != 'm' || name[1] != '.')
2669 return struct_type_field_find(p->metadata_st, &name[2]);
2673 rte_swx_pipeline_packet_metadata_register(struct rte_swx_pipeline *p,
2674 const char *struct_type_name)
2676 struct struct_type *st = NULL;
2680 CHECK_NAME(struct_type_name, EINVAL);
2681 st = struct_type_find(p, struct_type_name);
2683 CHECK(!st->var_size, EINVAL);
2684 CHECK(!p->metadata_st, EINVAL);
2686 p->metadata_st = st;
2687 p->metadata_struct_id = p->n_structs;
2695 metadata_build(struct rte_swx_pipeline *p)
2697 uint32_t n_bytes = p->metadata_st->n_bits / 8;
2700 /* Thread-level initialization. */
2701 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
2702 struct thread *t = &p->threads[i];
2705 metadata = calloc(1, n_bytes);
2706 CHECK(metadata, ENOMEM);
2708 t->metadata = metadata;
2709 t->structs[p->metadata_struct_id] = metadata;
2716 metadata_build_free(struct rte_swx_pipeline *p)
2720 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
2721 struct thread *t = &p->threads[i];
2729 metadata_free(struct rte_swx_pipeline *p)
2731 metadata_build_free(p);
2738 instruction_is_tx(enum instruction_type type)
2751 instruction_is_jmp(struct instruction *instr)
2753 switch (instr->type) {
2755 case INSTR_JMP_VALID:
2756 case INSTR_JMP_INVALID:
2758 case INSTR_JMP_MISS:
2759 case INSTR_JMP_ACTION_HIT:
2760 case INSTR_JMP_ACTION_MISS:
2762 case INSTR_JMP_EQ_MH:
2763 case INSTR_JMP_EQ_HM:
2764 case INSTR_JMP_EQ_HH:
2765 case INSTR_JMP_EQ_I:
2767 case INSTR_JMP_NEQ_MH:
2768 case INSTR_JMP_NEQ_HM:
2769 case INSTR_JMP_NEQ_HH:
2770 case INSTR_JMP_NEQ_I:
2772 case INSTR_JMP_LT_MH:
2773 case INSTR_JMP_LT_HM:
2774 case INSTR_JMP_LT_HH:
2775 case INSTR_JMP_LT_MI:
2776 case INSTR_JMP_LT_HI:
2778 case INSTR_JMP_GT_MH:
2779 case INSTR_JMP_GT_HM:
2780 case INSTR_JMP_GT_HH:
2781 case INSTR_JMP_GT_MI:
2782 case INSTR_JMP_GT_HI:
2790 static struct field *
2791 action_field_parse(struct action *action, const char *name);
2793 static struct field *
2794 struct_field_parse(struct rte_swx_pipeline *p,
2795 struct action *action,
2797 uint32_t *struct_id)
2804 struct header *header;
2806 f = header_field_parse(p, name, &header);
2810 *struct_id = header->struct_id;
2816 f = metadata_field_parse(p, name);
2820 *struct_id = p->metadata_struct_id;
2829 f = action_field_parse(action, name);
2839 struct extern_obj *obj;
2841 f = extern_obj_mailbox_field_parse(p, name, &obj);
2845 *struct_id = obj->struct_id;
2851 struct extern_func *func;
2853 f = extern_func_mailbox_field_parse(p, name, &func);
2857 *struct_id = func->struct_id;
2867 pipeline_port_inc(struct rte_swx_pipeline *p)
2869 p->port_id = (p->port_id + 1) & (p->n_ports_in - 1);
2873 thread_ip_reset(struct rte_swx_pipeline *p, struct thread *t)
2875 t->ip = p->instructions;
2879 thread_ip_set(struct thread *t, struct instruction *ip)
2885 thread_ip_action_call(struct rte_swx_pipeline *p,
2890 t->ip = p->action_instructions[action_id];
2894 thread_ip_inc(struct rte_swx_pipeline *p);
2897 thread_ip_inc(struct rte_swx_pipeline *p)
2899 struct thread *t = &p->threads[p->thread_id];
2905 thread_ip_inc_cond(struct thread *t, int cond)
2911 thread_yield(struct rte_swx_pipeline *p)
2913 p->thread_id = (p->thread_id + 1) & (RTE_SWX_PIPELINE_THREADS_MAX - 1);
2917 thread_yield_cond(struct rte_swx_pipeline *p, int cond)
2919 p->thread_id = (p->thread_id + cond) & (RTE_SWX_PIPELINE_THREADS_MAX - 1);
2926 instr_rx_translate(struct rte_swx_pipeline *p,
2927 struct action *action,
2930 struct instruction *instr,
2931 struct instruction_data *data __rte_unused)
2935 CHECK(!action, EINVAL);
2936 CHECK(n_tokens == 2, EINVAL);
2938 f = metadata_field_parse(p, tokens[1]);
2941 instr->type = INSTR_RX;
2942 instr->io.io.offset = f->offset / 8;
2943 instr->io.io.n_bits = f->n_bits;
2948 instr_rx_exec(struct rte_swx_pipeline *p);
2951 instr_rx_exec(struct rte_swx_pipeline *p)
2953 struct thread *t = &p->threads[p->thread_id];
2954 struct instruction *ip = t->ip;
2955 struct port_in_runtime *port = &p->in[p->port_id];
2956 struct rte_swx_pkt *pkt = &t->pkt;
2960 pkt_received = port->pkt_rx(port->obj, pkt);
2961 t->ptr = &pkt->pkt[pkt->offset];
2962 rte_prefetch0(t->ptr);
2964 TRACE("[Thread %2u] rx %s from port %u\n",
2966 pkt_received ? "1 pkt" : "0 pkts",
2970 t->valid_headers = 0;
2971 t->n_headers_out = 0;
2974 METADATA_WRITE(t, ip->io.io.offset, ip->io.io.n_bits, p->port_id);
2977 t->table_state = p->table_state;
2980 pipeline_port_inc(p);
2981 thread_ip_inc_cond(t, pkt_received);
2989 instr_tx_translate(struct rte_swx_pipeline *p,
2990 struct action *action __rte_unused,
2993 struct instruction *instr,
2994 struct instruction_data *data __rte_unused)
2996 char *port = tokens[1];
3000 CHECK(n_tokens == 2, EINVAL);
3002 f = metadata_field_parse(p, port);
3004 instr->type = INSTR_TX;
3005 instr->io.io.offset = f->offset / 8;
3006 instr->io.io.n_bits = f->n_bits;
3011 port_val = strtoul(port, &port, 0);
3012 CHECK(!port[0], EINVAL);
3014 instr->type = INSTR_TX_I;
3015 instr->io.io.val = port_val;
3020 instr_drop_translate(struct rte_swx_pipeline *p,
3021 struct action *action __rte_unused,
3022 char **tokens __rte_unused,
3024 struct instruction *instr,
3025 struct instruction_data *data __rte_unused)
3027 CHECK(n_tokens == 1, EINVAL);
3030 instr->type = INSTR_TX_I;
3031 instr->io.io.val = p->n_ports_out - 1;
3036 emit_handler(struct thread *t)
3038 struct header_out_runtime *h0 = &t->headers_out[0];
3039 struct header_out_runtime *h1 = &t->headers_out[1];
3040 uint32_t offset = 0, i;
3042 /* No header change or header decapsulation. */
3043 if ((t->n_headers_out == 1) &&
3044 (h0->ptr + h0->n_bytes == t->ptr)) {
3045 TRACE("Emit handler: no header change or header decap.\n");
3047 t->pkt.offset -= h0->n_bytes;
3048 t->pkt.length += h0->n_bytes;
3053 /* Header encapsulation (optionally, with prior header decasulation). */
3054 if ((t->n_headers_out == 2) &&
3055 (h1->ptr + h1->n_bytes == t->ptr) &&
3056 (h0->ptr == h0->ptr0)) {
3059 TRACE("Emit handler: header encapsulation.\n");
3061 offset = h0->n_bytes + h1->n_bytes;
3062 memcpy(t->ptr - offset, h0->ptr, h0->n_bytes);
3063 t->pkt.offset -= offset;
3064 t->pkt.length += offset;
3069 /* Header insertion. */
3072 /* Header extraction. */
3075 /* For any other case. */
3076 TRACE("Emit handler: complex case.\n");
3078 for (i = 0; i < t->n_headers_out; i++) {
3079 struct header_out_runtime *h = &t->headers_out[i];
3081 memcpy(&t->header_out_storage[offset], h->ptr, h->n_bytes);
3082 offset += h->n_bytes;
3086 memcpy(t->ptr - offset, t->header_out_storage, offset);
3087 t->pkt.offset -= offset;
3088 t->pkt.length += offset;
3093 instr_tx_exec(struct rte_swx_pipeline *p);
3096 instr_tx_exec(struct rte_swx_pipeline *p)
3098 struct thread *t = &p->threads[p->thread_id];
3099 struct instruction *ip = t->ip;
3100 uint64_t port_id = METADATA_READ(t, ip->io.io.offset, ip->io.io.n_bits);
3101 struct port_out_runtime *port = &p->out[port_id];
3102 struct rte_swx_pkt *pkt = &t->pkt;
3104 TRACE("[Thread %2u]: tx 1 pkt to port %u\n",
3112 port->pkt_tx(port->obj, pkt);
3115 thread_ip_reset(p, t);
3120 instr_tx_i_exec(struct rte_swx_pipeline *p)
3122 struct thread *t = &p->threads[p->thread_id];
3123 struct instruction *ip = t->ip;
3124 uint64_t port_id = ip->io.io.val;
3125 struct port_out_runtime *port = &p->out[port_id];
3126 struct rte_swx_pkt *pkt = &t->pkt;
3128 TRACE("[Thread %2u]: tx (i) 1 pkt to port %u\n",
3136 port->pkt_tx(port->obj, pkt);
3139 thread_ip_reset(p, t);
3147 instr_hdr_extract_translate(struct rte_swx_pipeline *p,
3148 struct action *action,
3151 struct instruction *instr,
3152 struct instruction_data *data __rte_unused)
3156 CHECK(!action, EINVAL);
3157 CHECK((n_tokens == 2) || (n_tokens == 3), EINVAL);
3159 h = header_parse(p, tokens[1]);
3162 if (n_tokens == 2) {
3163 CHECK(!h->st->var_size, EINVAL);
3165 instr->type = INSTR_HDR_EXTRACT;
3166 instr->io.hdr.header_id[0] = h->id;
3167 instr->io.hdr.struct_id[0] = h->struct_id;
3168 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
3172 CHECK(h->st->var_size, EINVAL);
3174 mf = metadata_field_parse(p, tokens[2]);
3176 CHECK(!mf->var_size, EINVAL);
3178 instr->type = INSTR_HDR_EXTRACT_M;
3179 instr->io.io.offset = mf->offset / 8;
3180 instr->io.io.n_bits = mf->n_bits;
3181 instr->io.hdr.header_id[0] = h->id;
3182 instr->io.hdr.struct_id[0] = h->struct_id;
3183 instr->io.hdr.n_bytes[0] = h->st->n_bits_min / 8;
3190 instr_hdr_lookahead_translate(struct rte_swx_pipeline *p,
3191 struct action *action,
3194 struct instruction *instr,
3195 struct instruction_data *data __rte_unused)
3199 CHECK(!action, EINVAL);
3200 CHECK(n_tokens == 2, EINVAL);
3202 h = header_parse(p, tokens[1]);
3204 CHECK(!h->st->var_size, EINVAL);
3206 instr->type = INSTR_HDR_LOOKAHEAD;
3207 instr->io.hdr.header_id[0] = h->id;
3208 instr->io.hdr.struct_id[0] = h->struct_id;
3209 instr->io.hdr.n_bytes[0] = 0; /* Unused. */
3215 __instr_hdr_extract_exec(struct rte_swx_pipeline *p, uint32_t n_extract);
3218 __instr_hdr_extract_exec(struct rte_swx_pipeline *p, uint32_t n_extract)
3220 struct thread *t = &p->threads[p->thread_id];
3221 struct instruction *ip = t->ip;
3222 uint64_t valid_headers = t->valid_headers;
3223 uint8_t *ptr = t->ptr;
3224 uint32_t offset = t->pkt.offset;
3225 uint32_t length = t->pkt.length;
3228 for (i = 0; i < n_extract; i++) {
3229 uint32_t header_id = ip->io.hdr.header_id[i];
3230 uint32_t struct_id = ip->io.hdr.struct_id[i];
3231 uint32_t n_bytes = ip->io.hdr.n_bytes[i];
3233 TRACE("[Thread %2u]: extract header %u (%u bytes)\n",
3239 t->structs[struct_id] = ptr;
3240 valid_headers = MASK64_BIT_SET(valid_headers, header_id);
3249 t->valid_headers = valid_headers;
3252 t->pkt.offset = offset;
3253 t->pkt.length = length;
3258 instr_hdr_extract_exec(struct rte_swx_pipeline *p)
3260 __instr_hdr_extract_exec(p, 1);
3267 instr_hdr_extract2_exec(struct rte_swx_pipeline *p)
3269 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n",
3272 __instr_hdr_extract_exec(p, 2);
3279 instr_hdr_extract3_exec(struct rte_swx_pipeline *p)
3281 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n",
3284 __instr_hdr_extract_exec(p, 3);
3291 instr_hdr_extract4_exec(struct rte_swx_pipeline *p)
3293 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n",
3296 __instr_hdr_extract_exec(p, 4);
3303 instr_hdr_extract5_exec(struct rte_swx_pipeline *p)
3305 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n",
3308 __instr_hdr_extract_exec(p, 5);
3315 instr_hdr_extract6_exec(struct rte_swx_pipeline *p)
3317 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n",
3320 __instr_hdr_extract_exec(p, 6);
3327 instr_hdr_extract7_exec(struct rte_swx_pipeline *p)
3329 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n",
3332 __instr_hdr_extract_exec(p, 7);
3339 instr_hdr_extract8_exec(struct rte_swx_pipeline *p)
3341 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n",
3344 __instr_hdr_extract_exec(p, 8);
3351 instr_hdr_extract_m_exec(struct rte_swx_pipeline *p)
3353 struct thread *t = &p->threads[p->thread_id];
3354 struct instruction *ip = t->ip;
3356 uint64_t valid_headers = t->valid_headers;
3357 uint8_t *ptr = t->ptr;
3358 uint32_t offset = t->pkt.offset;
3359 uint32_t length = t->pkt.length;
3361 uint32_t n_bytes_last = METADATA_READ(t, ip->io.io.offset, ip->io.io.n_bits);
3362 uint32_t header_id = ip->io.hdr.header_id[0];
3363 uint32_t struct_id = ip->io.hdr.struct_id[0];
3364 uint32_t n_bytes = ip->io.hdr.n_bytes[0];
3366 struct header_runtime *h = &t->headers[header_id];
3368 TRACE("[Thread %2u]: extract header %u (%u + %u bytes)\n",
3374 n_bytes += n_bytes_last;
3377 t->structs[struct_id] = ptr;
3378 t->valid_headers = MASK64_BIT_SET(valid_headers, header_id);
3379 h->n_bytes = n_bytes;
3382 t->pkt.offset = offset + n_bytes;
3383 t->pkt.length = length - n_bytes;
3384 t->ptr = ptr + n_bytes;
3391 instr_hdr_lookahead_exec(struct rte_swx_pipeline *p)
3393 struct thread *t = &p->threads[p->thread_id];
3394 struct instruction *ip = t->ip;
3396 uint64_t valid_headers = t->valid_headers;
3397 uint8_t *ptr = t->ptr;
3399 uint32_t header_id = ip->io.hdr.header_id[0];
3400 uint32_t struct_id = ip->io.hdr.struct_id[0];
3402 TRACE("[Thread %2u]: lookahead header %u\n",
3407 t->structs[struct_id] = ptr;
3408 t->valid_headers = MASK64_BIT_SET(valid_headers, header_id);
3418 instr_hdr_emit_translate(struct rte_swx_pipeline *p,
3419 struct action *action __rte_unused,
3422 struct instruction *instr,
3423 struct instruction_data *data __rte_unused)
3427 CHECK(n_tokens == 2, EINVAL);
3429 h = header_parse(p, tokens[1]);
3432 instr->type = INSTR_HDR_EMIT;
3433 instr->io.hdr.header_id[0] = h->id;
3434 instr->io.hdr.struct_id[0] = h->struct_id;
3435 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
3440 __instr_hdr_emit_exec(struct rte_swx_pipeline *p, uint32_t n_emit);
3443 __instr_hdr_emit_exec(struct rte_swx_pipeline *p, uint32_t n_emit)
3445 struct thread *t = &p->threads[p->thread_id];
3446 struct instruction *ip = t->ip;
3447 uint64_t valid_headers = t->valid_headers;
3448 uint32_t n_headers_out = t->n_headers_out;
3449 struct header_out_runtime *ho = &t->headers_out[n_headers_out - 1];
3450 uint8_t *ho_ptr = NULL;
3451 uint32_t ho_nbytes = 0, first = 1, i;
3453 for (i = 0; i < n_emit; i++) {
3454 uint32_t header_id = ip->io.hdr.header_id[i];
3455 uint32_t struct_id = ip->io.hdr.struct_id[i];
3457 struct header_runtime *hi = &t->headers[header_id];
3458 uint8_t *hi_ptr0 = hi->ptr0;
3459 uint32_t n_bytes = hi->n_bytes;
3461 uint8_t *hi_ptr = t->structs[struct_id];
3463 if (!MASK64_BIT_GET(valid_headers, header_id))
3466 TRACE("[Thread %2u]: emit header %u\n",
3474 if (!t->n_headers_out) {
3475 ho = &t->headers_out[0];
3481 ho_nbytes = n_bytes;
3488 ho_nbytes = ho->n_bytes;
3492 if (ho_ptr + ho_nbytes == hi_ptr) {
3493 ho_nbytes += n_bytes;
3495 ho->n_bytes = ho_nbytes;
3502 ho_nbytes = n_bytes;
3508 ho->n_bytes = ho_nbytes;
3509 t->n_headers_out = n_headers_out;
3513 instr_hdr_emit_exec(struct rte_swx_pipeline *p)
3515 __instr_hdr_emit_exec(p, 1);
3522 instr_hdr_emit_tx_exec(struct rte_swx_pipeline *p)
3524 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n",
3527 __instr_hdr_emit_exec(p, 1);
3532 instr_hdr_emit2_tx_exec(struct rte_swx_pipeline *p)
3534 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n",
3537 __instr_hdr_emit_exec(p, 2);
3542 instr_hdr_emit3_tx_exec(struct rte_swx_pipeline *p)
3544 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n",
3547 __instr_hdr_emit_exec(p, 3);
3552 instr_hdr_emit4_tx_exec(struct rte_swx_pipeline *p)
3554 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n",
3557 __instr_hdr_emit_exec(p, 4);
3562 instr_hdr_emit5_tx_exec(struct rte_swx_pipeline *p)
3564 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n",
3567 __instr_hdr_emit_exec(p, 5);
3572 instr_hdr_emit6_tx_exec(struct rte_swx_pipeline *p)
3574 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n",
3577 __instr_hdr_emit_exec(p, 6);
3582 instr_hdr_emit7_tx_exec(struct rte_swx_pipeline *p)
3584 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n",
3587 __instr_hdr_emit_exec(p, 7);
3592 instr_hdr_emit8_tx_exec(struct rte_swx_pipeline *p)
3594 TRACE("[Thread %2u] *** The next 9 instructions are fused. ***\n",
3597 __instr_hdr_emit_exec(p, 8);
3605 instr_hdr_validate_translate(struct rte_swx_pipeline *p,
3606 struct action *action __rte_unused,
3609 struct instruction *instr,
3610 struct instruction_data *data __rte_unused)
3614 CHECK(n_tokens == 2, EINVAL);
3616 h = header_parse(p, tokens[1]);
3619 instr->type = INSTR_HDR_VALIDATE;
3620 instr->valid.header_id = h->id;
3625 instr_hdr_validate_exec(struct rte_swx_pipeline *p)
3627 struct thread *t = &p->threads[p->thread_id];
3628 struct instruction *ip = t->ip;
3629 uint32_t header_id = ip->valid.header_id;
3631 TRACE("[Thread %2u] validate header %u\n", p->thread_id, header_id);
3634 t->valid_headers = MASK64_BIT_SET(t->valid_headers, header_id);
3644 instr_hdr_invalidate_translate(struct rte_swx_pipeline *p,
3645 struct action *action __rte_unused,
3648 struct instruction *instr,
3649 struct instruction_data *data __rte_unused)
3653 CHECK(n_tokens == 2, EINVAL);
3655 h = header_parse(p, tokens[1]);
3658 instr->type = INSTR_HDR_INVALIDATE;
3659 instr->valid.header_id = h->id;
3664 instr_hdr_invalidate_exec(struct rte_swx_pipeline *p)
3666 struct thread *t = &p->threads[p->thread_id];
3667 struct instruction *ip = t->ip;
3668 uint32_t header_id = ip->valid.header_id;
3670 TRACE("[Thread %2u] invalidate header %u\n", p->thread_id, header_id);
3673 t->valid_headers = MASK64_BIT_CLR(t->valid_headers, header_id);
3682 static struct table *
3683 table_find(struct rte_swx_pipeline *p, const char *name);
3685 static struct selector *
3686 selector_find(struct rte_swx_pipeline *p, const char *name);
3688 static struct learner *
3689 learner_find(struct rte_swx_pipeline *p, const char *name);
3692 instr_table_translate(struct rte_swx_pipeline *p,
3693 struct action *action,
3696 struct instruction *instr,
3697 struct instruction_data *data __rte_unused)
3703 CHECK(!action, EINVAL);
3704 CHECK(n_tokens == 2, EINVAL);
3706 t = table_find(p, tokens[1]);
3708 instr->type = INSTR_TABLE;
3709 instr->table.table_id = t->id;
3713 s = selector_find(p, tokens[1]);
3715 instr->type = INSTR_SELECTOR;
3716 instr->table.table_id = s->id;
3720 l = learner_find(p, tokens[1]);
3722 instr->type = INSTR_LEARNER;
3723 instr->table.table_id = l->id;
3731 instr_table_exec(struct rte_swx_pipeline *p)
3733 struct thread *t = &p->threads[p->thread_id];
3734 struct instruction *ip = t->ip;
3735 uint32_t table_id = ip->table.table_id;
3736 struct rte_swx_table_state *ts = &t->table_state[table_id];
3737 struct table_runtime *table = &t->tables[table_id];
3738 struct table_statistics *stats = &p->table_stats[table_id];
3739 uint64_t action_id, n_pkts_hit, n_pkts_action;
3740 uint8_t *action_data;
3744 done = table->func(ts->obj,
3752 TRACE("[Thread %2u] table %u (not finalized)\n",
3760 action_id = hit ? action_id : ts->default_action_id;
3761 action_data = hit ? action_data : ts->default_action_data;
3762 n_pkts_hit = stats->n_pkts_hit[hit];
3763 n_pkts_action = stats->n_pkts_action[action_id];
3765 TRACE("[Thread %2u] table %u (%s, action %u)\n",
3768 hit ? "hit" : "miss",
3769 (uint32_t)action_id);
3771 t->action_id = action_id;
3772 t->structs[0] = action_data;
3774 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
3775 stats->n_pkts_action[action_id] = n_pkts_action + 1;
3778 thread_ip_action_call(p, t, action_id);
3782 instr_selector_exec(struct rte_swx_pipeline *p)
3784 struct thread *t = &p->threads[p->thread_id];
3785 struct instruction *ip = t->ip;
3786 uint32_t selector_id = ip->table.table_id;
3787 struct rte_swx_table_state *ts = &t->table_state[p->n_tables + selector_id];
3788 struct selector_runtime *selector = &t->selectors[selector_id];
3789 struct selector_statistics *stats = &p->selector_stats[selector_id];
3790 uint64_t n_pkts = stats->n_pkts;
3794 done = rte_swx_table_selector_select(ts->obj,
3796 selector->group_id_buffer,
3797 selector->selector_buffer,
3798 selector->member_id_buffer);
3801 TRACE("[Thread %2u] selector %u (not finalized)\n",
3810 TRACE("[Thread %2u] selector %u\n",
3814 stats->n_pkts = n_pkts + 1;
3821 instr_learner_exec(struct rte_swx_pipeline *p)
3823 struct thread *t = &p->threads[p->thread_id];
3824 struct instruction *ip = t->ip;
3825 uint32_t learner_id = ip->table.table_id;
3826 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
3827 p->n_selectors + learner_id];
3828 struct learner_runtime *l = &t->learners[learner_id];
3829 struct learner_statistics *stats = &p->learner_stats[learner_id];
3830 uint64_t action_id, n_pkts_hit, n_pkts_action, time;
3831 uint8_t *action_data;
3835 time = rte_get_tsc_cycles();
3837 done = rte_swx_table_learner_lookup(ts->obj,
3846 TRACE("[Thread %2u] learner %u (not finalized)\n",
3854 action_id = hit ? action_id : ts->default_action_id;
3855 action_data = hit ? action_data : ts->default_action_data;
3856 n_pkts_hit = stats->n_pkts_hit[hit];
3857 n_pkts_action = stats->n_pkts_action[action_id];
3859 TRACE("[Thread %2u] learner %u (%s, action %u)\n",
3862 hit ? "hit" : "miss",
3863 (uint32_t)action_id);
3865 t->action_id = action_id;
3866 t->structs[0] = action_data;
3868 t->learner_id = learner_id;
3870 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
3871 stats->n_pkts_action[action_id] = n_pkts_action + 1;
3874 thread_ip_action_call(p, t, action_id);
3880 static struct action *
3881 action_find(struct rte_swx_pipeline *p, const char *name);
3884 action_has_nbo_args(struct action *a);
3887 instr_learn_translate(struct rte_swx_pipeline *p,
3888 struct action *action,
3891 struct instruction *instr,
3892 struct instruction_data *data __rte_unused)
3896 CHECK(action, EINVAL);
3897 CHECK(n_tokens == 2, EINVAL);
3899 a = action_find(p, tokens[1]);
3901 CHECK(!action_has_nbo_args(a), EINVAL);
3903 instr->type = INSTR_LEARNER_LEARN;
3904 instr->learn.action_id = a->id;
3910 instr_learn_exec(struct rte_swx_pipeline *p)
3912 struct thread *t = &p->threads[p->thread_id];
3913 struct instruction *ip = t->ip;
3914 uint64_t action_id = ip->learn.action_id;
3915 uint32_t learner_id = t->learner_id;
3916 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
3917 p->n_selectors + learner_id];
3918 struct learner_runtime *l = &t->learners[learner_id];
3919 struct learner_statistics *stats = &p->learner_stats[learner_id];
3923 status = rte_swx_table_learner_add(ts->obj,
3927 l->action_data[action_id]);
3929 TRACE("[Thread %2u] learner %u learn %s\n",
3932 status ? "ok" : "error");
3934 stats->n_pkts_learn[status] += 1;
3944 instr_forget_translate(struct rte_swx_pipeline *p __rte_unused,
3945 struct action *action,
3946 char **tokens __rte_unused,
3948 struct instruction *instr,
3949 struct instruction_data *data __rte_unused)
3951 CHECK(action, EINVAL);
3952 CHECK(n_tokens == 1, EINVAL);
3954 instr->type = INSTR_LEARNER_FORGET;
3960 instr_forget_exec(struct rte_swx_pipeline *p)
3962 struct thread *t = &p->threads[p->thread_id];
3963 uint32_t learner_id = t->learner_id;
3964 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
3965 p->n_selectors + learner_id];
3966 struct learner_runtime *l = &t->learners[learner_id];
3967 struct learner_statistics *stats = &p->learner_stats[learner_id];
3970 rte_swx_table_learner_delete(ts->obj, l->mailbox);
3972 TRACE("[Thread %2u] learner %u forget\n",
3976 stats->n_pkts_forget += 1;
3986 instr_extern_translate(struct rte_swx_pipeline *p,
3987 struct action *action __rte_unused,
3990 struct instruction *instr,
3991 struct instruction_data *data __rte_unused)
3993 char *token = tokens[1];
3995 CHECK(n_tokens == 2, EINVAL);
3997 if (token[0] == 'e') {
3998 struct extern_obj *obj;
3999 struct extern_type_member_func *func;
4001 func = extern_obj_member_func_parse(p, token, &obj);
4002 CHECK(func, EINVAL);
4004 instr->type = INSTR_EXTERN_OBJ;
4005 instr->ext_obj.ext_obj_id = obj->id;
4006 instr->ext_obj.func_id = func->id;
4011 if (token[0] == 'f') {
4012 struct extern_func *func;
4014 func = extern_func_parse(p, token);
4015 CHECK(func, EINVAL);
4017 instr->type = INSTR_EXTERN_FUNC;
4018 instr->ext_func.ext_func_id = func->id;
4027 instr_extern_obj_exec(struct rte_swx_pipeline *p)
4029 struct thread *t = &p->threads[p->thread_id];
4030 struct instruction *ip = t->ip;
4031 uint32_t obj_id = ip->ext_obj.ext_obj_id;
4032 uint32_t func_id = ip->ext_obj.func_id;
4033 struct extern_obj_runtime *obj = &t->extern_objs[obj_id];
4034 rte_swx_extern_type_member_func_t func = obj->funcs[func_id];
4036 TRACE("[Thread %2u] extern obj %u member func %u\n",
4041 /* Extern object member function execute. */
4042 uint32_t done = func(obj->obj, obj->mailbox);
4045 thread_ip_inc_cond(t, done);
4046 thread_yield_cond(p, done ^ 1);
4050 instr_extern_func_exec(struct rte_swx_pipeline *p)
4052 struct thread *t = &p->threads[p->thread_id];
4053 struct instruction *ip = t->ip;
4054 uint32_t ext_func_id = ip->ext_func.ext_func_id;
4055 struct extern_func_runtime *ext_func = &t->extern_funcs[ext_func_id];
4056 rte_swx_extern_func_t func = ext_func->func;
4058 TRACE("[Thread %2u] extern func %u\n",
4062 /* Extern function execute. */
4063 uint32_t done = func(ext_func->mailbox);
4066 thread_ip_inc_cond(t, done);
4067 thread_yield_cond(p, done ^ 1);
4074 instr_mov_translate(struct rte_swx_pipeline *p,
4075 struct action *action,
4078 struct instruction *instr,
4079 struct instruction_data *data __rte_unused)
4081 char *dst = tokens[1], *src = tokens[2];
4082 struct field *fdst, *fsrc;
4084 uint32_t dst_struct_id = 0, src_struct_id = 0;
4086 CHECK(n_tokens == 3, EINVAL);
4088 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4089 CHECK(fdst, EINVAL);
4090 CHECK(!fdst->var_size, EINVAL);
4092 /* MOV, MOV_MH, MOV_HM or MOV_HH. */
4093 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4095 CHECK(!fsrc->var_size, EINVAL);
4097 instr->type = INSTR_MOV;
4098 if (dst[0] != 'h' && src[0] == 'h')
4099 instr->type = INSTR_MOV_MH;
4100 if (dst[0] == 'h' && src[0] != 'h')
4101 instr->type = INSTR_MOV_HM;
4102 if (dst[0] == 'h' && src[0] == 'h')
4103 instr->type = INSTR_MOV_HH;
4105 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
4106 instr->mov.dst.n_bits = fdst->n_bits;
4107 instr->mov.dst.offset = fdst->offset / 8;
4108 instr->mov.src.struct_id = (uint8_t)src_struct_id;
4109 instr->mov.src.n_bits = fsrc->n_bits;
4110 instr->mov.src.offset = fsrc->offset / 8;
4115 src_val = strtoull(src, &src, 0);
4116 CHECK(!src[0], EINVAL);
4119 src_val = hton64(src_val) >> (64 - fdst->n_bits);
4121 instr->type = INSTR_MOV_I;
4122 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
4123 instr->mov.dst.n_bits = fdst->n_bits;
4124 instr->mov.dst.offset = fdst->offset / 8;
4125 instr->mov.src_val = src_val;
4130 instr_mov_exec(struct rte_swx_pipeline *p)
4132 struct thread *t = &p->threads[p->thread_id];
4133 struct instruction *ip = t->ip;
4135 TRACE("[Thread %2u] mov\n",
4145 instr_mov_mh_exec(struct rte_swx_pipeline *p)
4147 struct thread *t = &p->threads[p->thread_id];
4148 struct instruction *ip = t->ip;
4150 TRACE("[Thread %2u] mov (mh)\n",
4160 instr_mov_hm_exec(struct rte_swx_pipeline *p)
4162 struct thread *t = &p->threads[p->thread_id];
4163 struct instruction *ip = t->ip;
4165 TRACE("[Thread %2u] mov (hm)\n",
4175 instr_mov_hh_exec(struct rte_swx_pipeline *p)
4177 struct thread *t = &p->threads[p->thread_id];
4178 struct instruction *ip = t->ip;
4180 TRACE("[Thread %2u] mov (hh)\n",
4190 instr_mov_i_exec(struct rte_swx_pipeline *p)
4192 struct thread *t = &p->threads[p->thread_id];
4193 struct instruction *ip = t->ip;
4195 TRACE("[Thread %2u] mov m.f %" PRIx64 "\n",
4209 __instr_dma_ht_exec(struct rte_swx_pipeline *p, uint32_t n_dma);
4212 __instr_dma_ht_exec(struct rte_swx_pipeline *p, uint32_t n_dma)
4214 struct thread *t = &p->threads[p->thread_id];
4215 struct instruction *ip = t->ip;
4216 uint8_t *action_data = t->structs[0];
4217 uint64_t valid_headers = t->valid_headers;
4220 for (i = 0; i < n_dma; i++) {
4221 uint32_t header_id = ip->dma.dst.header_id[i];
4222 uint32_t struct_id = ip->dma.dst.struct_id[i];
4223 uint32_t offset = ip->dma.src.offset[i];
4224 uint32_t n_bytes = ip->dma.n_bytes[i];
4226 struct header_runtime *h = &t->headers[header_id];
4227 uint8_t *h_ptr0 = h->ptr0;
4228 uint8_t *h_ptr = t->structs[struct_id];
4230 void *dst = MASK64_BIT_GET(valid_headers, header_id) ?
4232 void *src = &action_data[offset];
4234 TRACE("[Thread %2u] dma h.s t.f\n", p->thread_id);
4237 memcpy(dst, src, n_bytes);
4238 t->structs[struct_id] = dst;
4239 valid_headers = MASK64_BIT_SET(valid_headers, header_id);
4242 t->valid_headers = valid_headers;
4246 instr_dma_ht_exec(struct rte_swx_pipeline *p)
4248 __instr_dma_ht_exec(p, 1);
4255 instr_dma_ht2_exec(struct rte_swx_pipeline *p)
4257 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n",
4260 __instr_dma_ht_exec(p, 2);
4267 instr_dma_ht3_exec(struct rte_swx_pipeline *p)
4269 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n",
4272 __instr_dma_ht_exec(p, 3);
4279 instr_dma_ht4_exec(struct rte_swx_pipeline *p)
4281 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n",
4284 __instr_dma_ht_exec(p, 4);
4291 instr_dma_ht5_exec(struct rte_swx_pipeline *p)
4293 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n",
4296 __instr_dma_ht_exec(p, 5);
4303 instr_dma_ht6_exec(struct rte_swx_pipeline *p)
4305 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n",
4308 __instr_dma_ht_exec(p, 6);
4315 instr_dma_ht7_exec(struct rte_swx_pipeline *p)
4317 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n",
4320 __instr_dma_ht_exec(p, 7);
4327 instr_dma_ht8_exec(struct rte_swx_pipeline *p)
4329 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n",
4332 __instr_dma_ht_exec(p, 8);
4342 instr_alu_add_translate(struct rte_swx_pipeline *p,
4343 struct action *action,
4346 struct instruction *instr,
4347 struct instruction_data *data __rte_unused)
4349 char *dst = tokens[1], *src = tokens[2];
4350 struct field *fdst, *fsrc;
4352 uint32_t dst_struct_id = 0, src_struct_id = 0;
4354 CHECK(n_tokens == 3, EINVAL);
4356 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4357 CHECK(fdst, EINVAL);
4358 CHECK(!fdst->var_size, EINVAL);
4360 /* ADD, ADD_HM, ADD_MH, ADD_HH. */
4361 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4363 CHECK(!fsrc->var_size, EINVAL);
4365 instr->type = INSTR_ALU_ADD;
4366 if (dst[0] == 'h' && src[0] != 'h')
4367 instr->type = INSTR_ALU_ADD_HM;
4368 if (dst[0] != 'h' && src[0] == 'h')
4369 instr->type = INSTR_ALU_ADD_MH;
4370 if (dst[0] == 'h' && src[0] == 'h')
4371 instr->type = INSTR_ALU_ADD_HH;
4373 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4374 instr->alu.dst.n_bits = fdst->n_bits;
4375 instr->alu.dst.offset = fdst->offset / 8;
4376 instr->alu.src.struct_id = (uint8_t)src_struct_id;
4377 instr->alu.src.n_bits = fsrc->n_bits;
4378 instr->alu.src.offset = fsrc->offset / 8;
4382 /* ADD_MI, ADD_HI. */
4383 src_val = strtoull(src, &src, 0);
4384 CHECK(!src[0], EINVAL);
4386 instr->type = INSTR_ALU_ADD_MI;
4388 instr->type = INSTR_ALU_ADD_HI;
4390 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4391 instr->alu.dst.n_bits = fdst->n_bits;
4392 instr->alu.dst.offset = fdst->offset / 8;
4393 instr->alu.src_val = src_val;
4398 instr_alu_sub_translate(struct rte_swx_pipeline *p,
4399 struct action *action,
4402 struct instruction *instr,
4403 struct instruction_data *data __rte_unused)
4405 char *dst = tokens[1], *src = tokens[2];
4406 struct field *fdst, *fsrc;
4408 uint32_t dst_struct_id = 0, src_struct_id = 0;
4410 CHECK(n_tokens == 3, EINVAL);
4412 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4413 CHECK(fdst, EINVAL);
4414 CHECK(!fdst->var_size, EINVAL);
4416 /* SUB, SUB_HM, SUB_MH, SUB_HH. */
4417 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4419 CHECK(!fsrc->var_size, EINVAL);
4421 instr->type = INSTR_ALU_SUB;
4422 if (dst[0] == 'h' && src[0] != 'h')
4423 instr->type = INSTR_ALU_SUB_HM;
4424 if (dst[0] != 'h' && src[0] == 'h')
4425 instr->type = INSTR_ALU_SUB_MH;
4426 if (dst[0] == 'h' && src[0] == 'h')
4427 instr->type = INSTR_ALU_SUB_HH;
4429 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4430 instr->alu.dst.n_bits = fdst->n_bits;
4431 instr->alu.dst.offset = fdst->offset / 8;
4432 instr->alu.src.struct_id = (uint8_t)src_struct_id;
4433 instr->alu.src.n_bits = fsrc->n_bits;
4434 instr->alu.src.offset = fsrc->offset / 8;
4438 /* SUB_MI, SUB_HI. */
4439 src_val = strtoull(src, &src, 0);
4440 CHECK(!src[0], EINVAL);
4442 instr->type = INSTR_ALU_SUB_MI;
4444 instr->type = INSTR_ALU_SUB_HI;
4446 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4447 instr->alu.dst.n_bits = fdst->n_bits;
4448 instr->alu.dst.offset = fdst->offset / 8;
4449 instr->alu.src_val = src_val;
4454 instr_alu_ckadd_translate(struct rte_swx_pipeline *p,
4455 struct action *action __rte_unused,
4458 struct instruction *instr,
4459 struct instruction_data *data __rte_unused)
4461 char *dst = tokens[1], *src = tokens[2];
4462 struct header *hdst, *hsrc;
4463 struct field *fdst, *fsrc;
4465 CHECK(n_tokens == 3, EINVAL);
4467 fdst = header_field_parse(p, dst, &hdst);
4468 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
4469 CHECK(!fdst->var_size, EINVAL);
4472 fsrc = header_field_parse(p, src, &hsrc);
4474 CHECK(!fsrc->var_size, EINVAL);
4476 instr->type = INSTR_ALU_CKADD_FIELD;
4477 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
4478 instr->alu.dst.n_bits = fdst->n_bits;
4479 instr->alu.dst.offset = fdst->offset / 8;
4480 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
4481 instr->alu.src.n_bits = fsrc->n_bits;
4482 instr->alu.src.offset = fsrc->offset / 8;
4486 /* CKADD_STRUCT, CKADD_STRUCT20. */
4487 hsrc = header_parse(p, src);
4488 CHECK(hsrc, EINVAL);
4489 CHECK(!hsrc->st->var_size, EINVAL);
4491 instr->type = INSTR_ALU_CKADD_STRUCT;
4492 if ((hsrc->st->n_bits / 8) == 20)
4493 instr->type = INSTR_ALU_CKADD_STRUCT20;
4495 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
4496 instr->alu.dst.n_bits = fdst->n_bits;
4497 instr->alu.dst.offset = fdst->offset / 8;
4498 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
4499 instr->alu.src.n_bits = hsrc->st->n_bits;
4500 instr->alu.src.offset = 0; /* Unused. */
4505 instr_alu_cksub_translate(struct rte_swx_pipeline *p,
4506 struct action *action __rte_unused,
4509 struct instruction *instr,
4510 struct instruction_data *data __rte_unused)
4512 char *dst = tokens[1], *src = tokens[2];
4513 struct header *hdst, *hsrc;
4514 struct field *fdst, *fsrc;
4516 CHECK(n_tokens == 3, EINVAL);
4518 fdst = header_field_parse(p, dst, &hdst);
4519 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
4520 CHECK(!fdst->var_size, EINVAL);
4522 fsrc = header_field_parse(p, src, &hsrc);
4523 CHECK(fsrc, EINVAL);
4524 CHECK(!fsrc->var_size, EINVAL);
4526 instr->type = INSTR_ALU_CKSUB_FIELD;
4527 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
4528 instr->alu.dst.n_bits = fdst->n_bits;
4529 instr->alu.dst.offset = fdst->offset / 8;
4530 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
4531 instr->alu.src.n_bits = fsrc->n_bits;
4532 instr->alu.src.offset = fsrc->offset / 8;
4537 instr_alu_shl_translate(struct rte_swx_pipeline *p,
4538 struct action *action,
4541 struct instruction *instr,
4542 struct instruction_data *data __rte_unused)
4544 char *dst = tokens[1], *src = tokens[2];
4545 struct field *fdst, *fsrc;
4547 uint32_t dst_struct_id = 0, src_struct_id = 0;
4549 CHECK(n_tokens == 3, EINVAL);
4551 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4552 CHECK(fdst, EINVAL);
4553 CHECK(!fdst->var_size, EINVAL);
4555 /* SHL, SHL_HM, SHL_MH, SHL_HH. */
4556 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4558 CHECK(!fsrc->var_size, EINVAL);
4560 instr->type = INSTR_ALU_SHL;
4561 if (dst[0] == 'h' && src[0] != 'h')
4562 instr->type = INSTR_ALU_SHL_HM;
4563 if (dst[0] != 'h' && src[0] == 'h')
4564 instr->type = INSTR_ALU_SHL_MH;
4565 if (dst[0] == 'h' && src[0] == 'h')
4566 instr->type = INSTR_ALU_SHL_HH;
4568 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4569 instr->alu.dst.n_bits = fdst->n_bits;
4570 instr->alu.dst.offset = fdst->offset / 8;
4571 instr->alu.src.struct_id = (uint8_t)src_struct_id;
4572 instr->alu.src.n_bits = fsrc->n_bits;
4573 instr->alu.src.offset = fsrc->offset / 8;
4577 /* SHL_MI, SHL_HI. */
4578 src_val = strtoull(src, &src, 0);
4579 CHECK(!src[0], EINVAL);
4581 instr->type = INSTR_ALU_SHL_MI;
4583 instr->type = INSTR_ALU_SHL_HI;
4585 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4586 instr->alu.dst.n_bits = fdst->n_bits;
4587 instr->alu.dst.offset = fdst->offset / 8;
4588 instr->alu.src_val = src_val;
4593 instr_alu_shr_translate(struct rte_swx_pipeline *p,
4594 struct action *action,
4597 struct instruction *instr,
4598 struct instruction_data *data __rte_unused)
4600 char *dst = tokens[1], *src = tokens[2];
4601 struct field *fdst, *fsrc;
4603 uint32_t dst_struct_id = 0, src_struct_id = 0;
4605 CHECK(n_tokens == 3, EINVAL);
4607 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4608 CHECK(fdst, EINVAL);
4609 CHECK(!fdst->var_size, EINVAL);
4611 /* SHR, SHR_HM, SHR_MH, SHR_HH. */
4612 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4614 CHECK(!fsrc->var_size, EINVAL);
4616 instr->type = INSTR_ALU_SHR;
4617 if (dst[0] == 'h' && src[0] != 'h')
4618 instr->type = INSTR_ALU_SHR_HM;
4619 if (dst[0] != 'h' && src[0] == 'h')
4620 instr->type = INSTR_ALU_SHR_MH;
4621 if (dst[0] == 'h' && src[0] == 'h')
4622 instr->type = INSTR_ALU_SHR_HH;
4624 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4625 instr->alu.dst.n_bits = fdst->n_bits;
4626 instr->alu.dst.offset = fdst->offset / 8;
4627 instr->alu.src.struct_id = (uint8_t)src_struct_id;
4628 instr->alu.src.n_bits = fsrc->n_bits;
4629 instr->alu.src.offset = fsrc->offset / 8;
4633 /* SHR_MI, SHR_HI. */
4634 src_val = strtoull(src, &src, 0);
4635 CHECK(!src[0], EINVAL);
4637 instr->type = INSTR_ALU_SHR_MI;
4639 instr->type = INSTR_ALU_SHR_HI;
4641 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4642 instr->alu.dst.n_bits = fdst->n_bits;
4643 instr->alu.dst.offset = fdst->offset / 8;
4644 instr->alu.src_val = src_val;
4649 instr_alu_and_translate(struct rte_swx_pipeline *p,
4650 struct action *action,
4653 struct instruction *instr,
4654 struct instruction_data *data __rte_unused)
4656 char *dst = tokens[1], *src = tokens[2];
4657 struct field *fdst, *fsrc;
4659 uint32_t dst_struct_id = 0, src_struct_id = 0;
4661 CHECK(n_tokens == 3, EINVAL);
4663 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4664 CHECK(fdst, EINVAL);
4665 CHECK(!fdst->var_size, EINVAL);
4667 /* AND, AND_MH, AND_HM, AND_HH. */
4668 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4670 CHECK(!fsrc->var_size, EINVAL);
4672 instr->type = INSTR_ALU_AND;
4673 if (dst[0] != 'h' && src[0] == 'h')
4674 instr->type = INSTR_ALU_AND_MH;
4675 if (dst[0] == 'h' && src[0] != 'h')
4676 instr->type = INSTR_ALU_AND_HM;
4677 if (dst[0] == 'h' && src[0] == 'h')
4678 instr->type = INSTR_ALU_AND_HH;
4680 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4681 instr->alu.dst.n_bits = fdst->n_bits;
4682 instr->alu.dst.offset = fdst->offset / 8;
4683 instr->alu.src.struct_id = (uint8_t)src_struct_id;
4684 instr->alu.src.n_bits = fsrc->n_bits;
4685 instr->alu.src.offset = fsrc->offset / 8;
4690 src_val = strtoull(src, &src, 0);
4691 CHECK(!src[0], EINVAL);
4694 src_val = hton64(src_val) >> (64 - fdst->n_bits);
4696 instr->type = INSTR_ALU_AND_I;
4697 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4698 instr->alu.dst.n_bits = fdst->n_bits;
4699 instr->alu.dst.offset = fdst->offset / 8;
4700 instr->alu.src_val = src_val;
4705 instr_alu_or_translate(struct rte_swx_pipeline *p,
4706 struct action *action,
4709 struct instruction *instr,
4710 struct instruction_data *data __rte_unused)
4712 char *dst = tokens[1], *src = tokens[2];
4713 struct field *fdst, *fsrc;
4715 uint32_t dst_struct_id = 0, src_struct_id = 0;
4717 CHECK(n_tokens == 3, EINVAL);
4719 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4720 CHECK(fdst, EINVAL);
4721 CHECK(!fdst->var_size, EINVAL);
4723 /* OR, OR_MH, OR_HM, OR_HH. */
4724 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4726 CHECK(!fsrc->var_size, EINVAL);
4728 instr->type = INSTR_ALU_OR;
4729 if (dst[0] != 'h' && src[0] == 'h')
4730 instr->type = INSTR_ALU_OR_MH;
4731 if (dst[0] == 'h' && src[0] != 'h')
4732 instr->type = INSTR_ALU_OR_HM;
4733 if (dst[0] == 'h' && src[0] == 'h')
4734 instr->type = INSTR_ALU_OR_HH;
4736 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4737 instr->alu.dst.n_bits = fdst->n_bits;
4738 instr->alu.dst.offset = fdst->offset / 8;
4739 instr->alu.src.struct_id = (uint8_t)src_struct_id;
4740 instr->alu.src.n_bits = fsrc->n_bits;
4741 instr->alu.src.offset = fsrc->offset / 8;
4746 src_val = strtoull(src, &src, 0);
4747 CHECK(!src[0], EINVAL);
4750 src_val = hton64(src_val) >> (64 - fdst->n_bits);
4752 instr->type = INSTR_ALU_OR_I;
4753 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4754 instr->alu.dst.n_bits = fdst->n_bits;
4755 instr->alu.dst.offset = fdst->offset / 8;
4756 instr->alu.src_val = src_val;
4761 instr_alu_xor_translate(struct rte_swx_pipeline *p,
4762 struct action *action,
4765 struct instruction *instr,
4766 struct instruction_data *data __rte_unused)
4768 char *dst = tokens[1], *src = tokens[2];
4769 struct field *fdst, *fsrc;
4771 uint32_t dst_struct_id = 0, src_struct_id = 0;
4773 CHECK(n_tokens == 3, EINVAL);
4775 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4776 CHECK(fdst, EINVAL);
4777 CHECK(!fdst->var_size, EINVAL);
4779 /* XOR, XOR_MH, XOR_HM, XOR_HH. */
4780 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4782 CHECK(!fsrc->var_size, EINVAL);
4784 instr->type = INSTR_ALU_XOR;
4785 if (dst[0] != 'h' && src[0] == 'h')
4786 instr->type = INSTR_ALU_XOR_MH;
4787 if (dst[0] == 'h' && src[0] != 'h')
4788 instr->type = INSTR_ALU_XOR_HM;
4789 if (dst[0] == 'h' && src[0] == 'h')
4790 instr->type = INSTR_ALU_XOR_HH;
4792 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4793 instr->alu.dst.n_bits = fdst->n_bits;
4794 instr->alu.dst.offset = fdst->offset / 8;
4795 instr->alu.src.struct_id = (uint8_t)src_struct_id;
4796 instr->alu.src.n_bits = fsrc->n_bits;
4797 instr->alu.src.offset = fsrc->offset / 8;
4802 src_val = strtoull(src, &src, 0);
4803 CHECK(!src[0], EINVAL);
4806 src_val = hton64(src_val) >> (64 - fdst->n_bits);
4808 instr->type = INSTR_ALU_XOR_I;
4809 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4810 instr->alu.dst.n_bits = fdst->n_bits;
4811 instr->alu.dst.offset = fdst->offset / 8;
4812 instr->alu.src_val = src_val;
4817 instr_alu_add_exec(struct rte_swx_pipeline *p)
4819 struct thread *t = &p->threads[p->thread_id];
4820 struct instruction *ip = t->ip;
4822 TRACE("[Thread %2u] add\n", p->thread_id);
4832 instr_alu_add_mh_exec(struct rte_swx_pipeline *p)
4834 struct thread *t = &p->threads[p->thread_id];
4835 struct instruction *ip = t->ip;
4837 TRACE("[Thread %2u] add (mh)\n", p->thread_id);
4847 instr_alu_add_hm_exec(struct rte_swx_pipeline *p)
4849 struct thread *t = &p->threads[p->thread_id];
4850 struct instruction *ip = t->ip;
4852 TRACE("[Thread %2u] add (hm)\n", p->thread_id);
4862 instr_alu_add_hh_exec(struct rte_swx_pipeline *p)
4864 struct thread *t = &p->threads[p->thread_id];
4865 struct instruction *ip = t->ip;
4867 TRACE("[Thread %2u] add (hh)\n", p->thread_id);
4877 instr_alu_add_mi_exec(struct rte_swx_pipeline *p)
4879 struct thread *t = &p->threads[p->thread_id];
4880 struct instruction *ip = t->ip;
4882 TRACE("[Thread %2u] add (mi)\n", p->thread_id);
4892 instr_alu_add_hi_exec(struct rte_swx_pipeline *p)
4894 struct thread *t = &p->threads[p->thread_id];
4895 struct instruction *ip = t->ip;
4897 TRACE("[Thread %2u] add (hi)\n", p->thread_id);
4907 instr_alu_sub_exec(struct rte_swx_pipeline *p)
4909 struct thread *t = &p->threads[p->thread_id];
4910 struct instruction *ip = t->ip;
4912 TRACE("[Thread %2u] sub\n", p->thread_id);
4922 instr_alu_sub_mh_exec(struct rte_swx_pipeline *p)
4924 struct thread *t = &p->threads[p->thread_id];
4925 struct instruction *ip = t->ip;
4927 TRACE("[Thread %2u] sub (mh)\n", p->thread_id);
4937 instr_alu_sub_hm_exec(struct rte_swx_pipeline *p)
4939 struct thread *t = &p->threads[p->thread_id];
4940 struct instruction *ip = t->ip;
4942 TRACE("[Thread %2u] sub (hm)\n", p->thread_id);
4952 instr_alu_sub_hh_exec(struct rte_swx_pipeline *p)
4954 struct thread *t = &p->threads[p->thread_id];
4955 struct instruction *ip = t->ip;
4957 TRACE("[Thread %2u] sub (hh)\n", p->thread_id);
4967 instr_alu_sub_mi_exec(struct rte_swx_pipeline *p)
4969 struct thread *t = &p->threads[p->thread_id];
4970 struct instruction *ip = t->ip;
4972 TRACE("[Thread %2u] sub (mi)\n", p->thread_id);
4982 instr_alu_sub_hi_exec(struct rte_swx_pipeline *p)
4984 struct thread *t = &p->threads[p->thread_id];
4985 struct instruction *ip = t->ip;
4987 TRACE("[Thread %2u] sub (hi)\n", p->thread_id);
4997 instr_alu_shl_exec(struct rte_swx_pipeline *p)
4999 struct thread *t = &p->threads[p->thread_id];
5000 struct instruction *ip = t->ip;
5002 TRACE("[Thread %2u] shl\n", p->thread_id);
5012 instr_alu_shl_mh_exec(struct rte_swx_pipeline *p)
5014 struct thread *t = &p->threads[p->thread_id];
5015 struct instruction *ip = t->ip;
5017 TRACE("[Thread %2u] shl (mh)\n", p->thread_id);
5027 instr_alu_shl_hm_exec(struct rte_swx_pipeline *p)
5029 struct thread *t = &p->threads[p->thread_id];
5030 struct instruction *ip = t->ip;
5032 TRACE("[Thread %2u] shl (hm)\n", p->thread_id);
5042 instr_alu_shl_hh_exec(struct rte_swx_pipeline *p)
5044 struct thread *t = &p->threads[p->thread_id];
5045 struct instruction *ip = t->ip;
5047 TRACE("[Thread %2u] shl (hh)\n", p->thread_id);
5057 instr_alu_shl_mi_exec(struct rte_swx_pipeline *p)
5059 struct thread *t = &p->threads[p->thread_id];
5060 struct instruction *ip = t->ip;
5062 TRACE("[Thread %2u] shl (mi)\n", p->thread_id);
5072 instr_alu_shl_hi_exec(struct rte_swx_pipeline *p)
5074 struct thread *t = &p->threads[p->thread_id];
5075 struct instruction *ip = t->ip;
5077 TRACE("[Thread %2u] shl (hi)\n", p->thread_id);
5087 instr_alu_shr_exec(struct rte_swx_pipeline *p)
5089 struct thread *t = &p->threads[p->thread_id];
5090 struct instruction *ip = t->ip;
5092 TRACE("[Thread %2u] shr\n", p->thread_id);
5102 instr_alu_shr_mh_exec(struct rte_swx_pipeline *p)
5104 struct thread *t = &p->threads[p->thread_id];
5105 struct instruction *ip = t->ip;
5107 TRACE("[Thread %2u] shr (mh)\n", p->thread_id);
5117 instr_alu_shr_hm_exec(struct rte_swx_pipeline *p)
5119 struct thread *t = &p->threads[p->thread_id];
5120 struct instruction *ip = t->ip;
5122 TRACE("[Thread %2u] shr (hm)\n", p->thread_id);
5132 instr_alu_shr_hh_exec(struct rte_swx_pipeline *p)
5134 struct thread *t = &p->threads[p->thread_id];
5135 struct instruction *ip = t->ip;
5137 TRACE("[Thread %2u] shr (hh)\n", p->thread_id);
5147 instr_alu_shr_mi_exec(struct rte_swx_pipeline *p)
5149 struct thread *t = &p->threads[p->thread_id];
5150 struct instruction *ip = t->ip;
5152 TRACE("[Thread %2u] shr (mi)\n", p->thread_id);
5162 instr_alu_shr_hi_exec(struct rte_swx_pipeline *p)
5164 struct thread *t = &p->threads[p->thread_id];
5165 struct instruction *ip = t->ip;
5167 TRACE("[Thread %2u] shr (hi)\n", p->thread_id);
5177 instr_alu_and_exec(struct rte_swx_pipeline *p)
5179 struct thread *t = &p->threads[p->thread_id];
5180 struct instruction *ip = t->ip;
5182 TRACE("[Thread %2u] and\n", p->thread_id);
5192 instr_alu_and_mh_exec(struct rte_swx_pipeline *p)
5194 struct thread *t = &p->threads[p->thread_id];
5195 struct instruction *ip = t->ip;
5197 TRACE("[Thread %2u] and (mh)\n", p->thread_id);
5207 instr_alu_and_hm_exec(struct rte_swx_pipeline *p)
5209 struct thread *t = &p->threads[p->thread_id];
5210 struct instruction *ip = t->ip;
5212 TRACE("[Thread %2u] and (hm)\n", p->thread_id);
5215 ALU_HM_FAST(t, ip, &);
5222 instr_alu_and_hh_exec(struct rte_swx_pipeline *p)
5224 struct thread *t = &p->threads[p->thread_id];
5225 struct instruction *ip = t->ip;
5227 TRACE("[Thread %2u] and (hh)\n", p->thread_id);
5230 ALU_HH_FAST(t, ip, &);
5237 instr_alu_and_i_exec(struct rte_swx_pipeline *p)
5239 struct thread *t = &p->threads[p->thread_id];
5240 struct instruction *ip = t->ip;
5242 TRACE("[Thread %2u] and (i)\n", p->thread_id);
5252 instr_alu_or_exec(struct rte_swx_pipeline *p)
5254 struct thread *t = &p->threads[p->thread_id];
5255 struct instruction *ip = t->ip;
5257 TRACE("[Thread %2u] or\n", p->thread_id);
5267 instr_alu_or_mh_exec(struct rte_swx_pipeline *p)
5269 struct thread *t = &p->threads[p->thread_id];
5270 struct instruction *ip = t->ip;
5272 TRACE("[Thread %2u] or (mh)\n", p->thread_id);
5282 instr_alu_or_hm_exec(struct rte_swx_pipeline *p)
5284 struct thread *t = &p->threads[p->thread_id];
5285 struct instruction *ip = t->ip;
5287 TRACE("[Thread %2u] or (hm)\n", p->thread_id);
5290 ALU_HM_FAST(t, ip, |);
5297 instr_alu_or_hh_exec(struct rte_swx_pipeline *p)
5299 struct thread *t = &p->threads[p->thread_id];
5300 struct instruction *ip = t->ip;
5302 TRACE("[Thread %2u] or (hh)\n", p->thread_id);
5305 ALU_HH_FAST(t, ip, |);
5312 instr_alu_or_i_exec(struct rte_swx_pipeline *p)
5314 struct thread *t = &p->threads[p->thread_id];
5315 struct instruction *ip = t->ip;
5317 TRACE("[Thread %2u] or (i)\n", p->thread_id);
5327 instr_alu_xor_exec(struct rte_swx_pipeline *p)
5329 struct thread *t = &p->threads[p->thread_id];
5330 struct instruction *ip = t->ip;
5332 TRACE("[Thread %2u] xor\n", p->thread_id);
5342 instr_alu_xor_mh_exec(struct rte_swx_pipeline *p)
5344 struct thread *t = &p->threads[p->thread_id];
5345 struct instruction *ip = t->ip;
5347 TRACE("[Thread %2u] xor (mh)\n", p->thread_id);
5357 instr_alu_xor_hm_exec(struct rte_swx_pipeline *p)
5359 struct thread *t = &p->threads[p->thread_id];
5360 struct instruction *ip = t->ip;
5362 TRACE("[Thread %2u] xor (hm)\n", p->thread_id);
5365 ALU_HM_FAST(t, ip, ^);
5372 instr_alu_xor_hh_exec(struct rte_swx_pipeline *p)
5374 struct thread *t = &p->threads[p->thread_id];
5375 struct instruction *ip = t->ip;
5377 TRACE("[Thread %2u] xor (hh)\n", p->thread_id);
5380 ALU_HH_FAST(t, ip, ^);
5387 instr_alu_xor_i_exec(struct rte_swx_pipeline *p)
5389 struct thread *t = &p->threads[p->thread_id];
5390 struct instruction *ip = t->ip;
5392 TRACE("[Thread %2u] xor (i)\n", p->thread_id);
5402 instr_alu_ckadd_field_exec(struct rte_swx_pipeline *p)
5404 struct thread *t = &p->threads[p->thread_id];
5405 struct instruction *ip = t->ip;
5406 uint8_t *dst_struct, *src_struct;
5407 uint16_t *dst16_ptr, dst;
5408 uint64_t *src64_ptr, src64, src64_mask, src;
5411 TRACE("[Thread %2u] ckadd (field)\n", p->thread_id);
5414 dst_struct = t->structs[ip->alu.dst.struct_id];
5415 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
5418 src_struct = t->structs[ip->alu.src.struct_id];
5419 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
5421 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
5422 src = src64 & src64_mask;
5427 /* The first input (r) is a 16-bit number. The second and the third
5428 * inputs are 32-bit numbers. In the worst case scenario, the sum of the
5429 * three numbers (output r) is a 34-bit number.
5431 r += (src >> 32) + (src & 0xFFFFFFFF);
5433 /* The first input is a 16-bit number. The second input is an 18-bit
5434 * number. In the worst case scenario, the sum of the two numbers is a
5437 r = (r & 0xFFFF) + (r >> 16);
5439 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
5440 * a 3-bit number (0 .. 7). Their sum is a 17-bit number (0 .. 0x10006).
5442 r = (r & 0xFFFF) + (r >> 16);
5444 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
5445 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
5446 * 0x10006), the output r is (0 .. 7). So no carry bit can be generated,
5447 * therefore the output r is always a 16-bit number.
5449 r = (r & 0xFFFF) + (r >> 16);
5454 *dst16_ptr = (uint16_t)r;
5461 instr_alu_cksub_field_exec(struct rte_swx_pipeline *p)
5463 struct thread *t = &p->threads[p->thread_id];
5464 struct instruction *ip = t->ip;
5465 uint8_t *dst_struct, *src_struct;
5466 uint16_t *dst16_ptr, dst;
5467 uint64_t *src64_ptr, src64, src64_mask, src;
5470 TRACE("[Thread %2u] cksub (field)\n", p->thread_id);
5473 dst_struct = t->structs[ip->alu.dst.struct_id];
5474 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
5477 src_struct = t->structs[ip->alu.src.struct_id];
5478 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
5480 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
5481 src = src64 & src64_mask;
5486 /* Subtraction in 1's complement arithmetic (i.e. a '- b) is the same as
5487 * the following sequence of operations in 2's complement arithmetic:
5488 * a '- b = (a - b) % 0xFFFF.
5490 * In order to prevent an underflow for the below subtraction, in which
5491 * a 33-bit number (the subtrahend) is taken out of a 16-bit number (the
5492 * minuend), we first add a multiple of the 0xFFFF modulus to the
5493 * minuend. The number we add to the minuend needs to be a 34-bit number
5494 * or higher, so for readability reasons we picked the 36-bit multiple.
5495 * We are effectively turning the 16-bit minuend into a 36-bit number:
5496 * (a - b) % 0xFFFF = (a + 0xFFFF00000 - b) % 0xFFFF.
5498 r += 0xFFFF00000ULL; /* The output r is a 36-bit number. */
5500 /* A 33-bit number is subtracted from a 36-bit number (the input r). The
5501 * result (the output r) is a 36-bit number.
5503 r -= (src >> 32) + (src & 0xFFFFFFFF);
5505 /* The first input is a 16-bit number. The second input is a 20-bit
5506 * number. Their sum is a 21-bit number.
5508 r = (r & 0xFFFF) + (r >> 16);
5510 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
5511 * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1001E).
5513 r = (r & 0xFFFF) + (r >> 16);
5515 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
5516 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
5517 * 0x1001E), the output r is (0 .. 31). So no carry bit can be
5518 * generated, therefore the output r is always a 16-bit number.
5520 r = (r & 0xFFFF) + (r >> 16);
5525 *dst16_ptr = (uint16_t)r;
5532 instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline *p)
5534 struct thread *t = &p->threads[p->thread_id];
5535 struct instruction *ip = t->ip;
5536 uint8_t *dst_struct, *src_struct;
5537 uint16_t *dst16_ptr;
5538 uint32_t *src32_ptr;
5541 TRACE("[Thread %2u] ckadd (struct of 20 bytes)\n", p->thread_id);
5544 dst_struct = t->structs[ip->alu.dst.struct_id];
5545 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
5547 src_struct = t->structs[ip->alu.src.struct_id];
5548 src32_ptr = (uint32_t *)&src_struct[0];
5550 r0 = src32_ptr[0]; /* r0 is a 32-bit number. */
5551 r1 = src32_ptr[1]; /* r1 is a 32-bit number. */
5552 r0 += src32_ptr[2]; /* The output r0 is a 33-bit number. */
5553 r1 += src32_ptr[3]; /* The output r1 is a 33-bit number. */
5554 r0 += r1 + src32_ptr[4]; /* The output r0 is a 35-bit number. */
5556 /* The first input is a 16-bit number. The second input is a 19-bit
5557 * number. Their sum is a 20-bit number.
5559 r0 = (r0 & 0xFFFF) + (r0 >> 16);
5561 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
5562 * a 4-bit number (0 .. 15). The sum is a 17-bit number (0 .. 0x1000E).
5564 r0 = (r0 & 0xFFFF) + (r0 >> 16);
5566 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
5567 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
5568 * 0x1000E), the output r is (0 .. 15). So no carry bit can be
5569 * generated, therefore the output r is always a 16-bit number.
5571 r0 = (r0 & 0xFFFF) + (r0 >> 16);
5574 r0 = r0 ? r0 : 0xFFFF;
5576 *dst16_ptr = (uint16_t)r0;
5583 instr_alu_ckadd_struct_exec(struct rte_swx_pipeline *p)
5585 struct thread *t = &p->threads[p->thread_id];
5586 struct instruction *ip = t->ip;
5587 uint8_t *dst_struct, *src_struct;
5588 uint16_t *dst16_ptr;
5589 uint32_t *src32_ptr;
5593 TRACE("[Thread %2u] ckadd (struct)\n", p->thread_id);
5596 dst_struct = t->structs[ip->alu.dst.struct_id];
5597 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
5599 src_struct = t->structs[ip->alu.src.struct_id];
5600 src32_ptr = (uint32_t *)&src_struct[0];
5602 /* The max number of 32-bit words in a 256-byte header is 8 = 2^3.
5603 * Therefore, in the worst case scenario, a 35-bit number is added to a
5604 * 16-bit number (the input r), so the output r is 36-bit number.
5606 for (i = 0; i < ip->alu.src.n_bits / 32; i++, src32_ptr++)
5609 /* The first input is a 16-bit number. The second input is a 20-bit
5610 * number. Their sum is a 21-bit number.
5612 r = (r & 0xFFFF) + (r >> 16);
5614 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
5615 * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1000E).
5617 r = (r & 0xFFFF) + (r >> 16);
5619 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
5620 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
5621 * 0x1001E), the output r is (0 .. 31). So no carry bit can be
5622 * generated, therefore the output r is always a 16-bit number.
5624 r = (r & 0xFFFF) + (r >> 16);
5629 *dst16_ptr = (uint16_t)r;
5638 static struct regarray *
5639 regarray_find(struct rte_swx_pipeline *p, const char *name);
5642 instr_regprefetch_translate(struct rte_swx_pipeline *p,
5643 struct action *action,
5646 struct instruction *instr,
5647 struct instruction_data *data __rte_unused)
5649 char *regarray = tokens[1], *idx = tokens[2];
5652 uint32_t idx_struct_id, idx_val;
5654 CHECK(n_tokens == 3, EINVAL);
5656 r = regarray_find(p, regarray);
5659 /* REGPREFETCH_RH, REGPREFETCH_RM. */
5660 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
5662 CHECK(!fidx->var_size, EINVAL);
5664 instr->type = INSTR_REGPREFETCH_RM;
5666 instr->type = INSTR_REGPREFETCH_RH;
5668 instr->regarray.regarray_id = r->id;
5669 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
5670 instr->regarray.idx.n_bits = fidx->n_bits;
5671 instr->regarray.idx.offset = fidx->offset / 8;
5672 instr->regarray.dstsrc_val = 0; /* Unused. */
5676 /* REGPREFETCH_RI. */
5677 idx_val = strtoul(idx, &idx, 0);
5678 CHECK(!idx[0], EINVAL);
5680 instr->type = INSTR_REGPREFETCH_RI;
5681 instr->regarray.regarray_id = r->id;
5682 instr->regarray.idx_val = idx_val;
5683 instr->regarray.dstsrc_val = 0; /* Unused. */
5688 instr_regrd_translate(struct rte_swx_pipeline *p,
5689 struct action *action,
5692 struct instruction *instr,
5693 struct instruction_data *data __rte_unused)
5695 char *dst = tokens[1], *regarray = tokens[2], *idx = tokens[3];
5697 struct field *fdst, *fidx;
5698 uint32_t dst_struct_id, idx_struct_id, idx_val;
5700 CHECK(n_tokens == 4, EINVAL);
5702 r = regarray_find(p, regarray);
5705 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
5706 CHECK(fdst, EINVAL);
5707 CHECK(!fdst->var_size, EINVAL);
5709 /* REGRD_HRH, REGRD_HRM, REGRD_MRH, REGRD_MRM. */
5710 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
5712 CHECK(!fidx->var_size, EINVAL);
5714 instr->type = INSTR_REGRD_MRM;
5715 if (dst[0] == 'h' && idx[0] != 'h')
5716 instr->type = INSTR_REGRD_HRM;
5717 if (dst[0] != 'h' && idx[0] == 'h')
5718 instr->type = INSTR_REGRD_MRH;
5719 if (dst[0] == 'h' && idx[0] == 'h')
5720 instr->type = INSTR_REGRD_HRH;
5722 instr->regarray.regarray_id = r->id;
5723 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
5724 instr->regarray.idx.n_bits = fidx->n_bits;
5725 instr->regarray.idx.offset = fidx->offset / 8;
5726 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
5727 instr->regarray.dstsrc.n_bits = fdst->n_bits;
5728 instr->regarray.dstsrc.offset = fdst->offset / 8;
5732 /* REGRD_MRI, REGRD_HRI. */
5733 idx_val = strtoul(idx, &idx, 0);
5734 CHECK(!idx[0], EINVAL);
5736 instr->type = INSTR_REGRD_MRI;
5738 instr->type = INSTR_REGRD_HRI;
5740 instr->regarray.regarray_id = r->id;
5741 instr->regarray.idx_val = idx_val;
5742 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
5743 instr->regarray.dstsrc.n_bits = fdst->n_bits;
5744 instr->regarray.dstsrc.offset = fdst->offset / 8;
5749 instr_regwr_translate(struct rte_swx_pipeline *p,
5750 struct action *action,
5753 struct instruction *instr,
5754 struct instruction_data *data __rte_unused)
5756 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
5758 struct field *fidx, *fsrc;
5760 uint32_t idx_struct_id, idx_val, src_struct_id;
5762 CHECK(n_tokens == 4, EINVAL);
5764 r = regarray_find(p, regarray);
5767 /* REGWR_RHH, REGWR_RHM, REGWR_RMH, REGWR_RMM. */
5768 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
5769 fsrc = struct_field_parse(p, action, src, &src_struct_id);
5771 CHECK(!fidx->var_size, EINVAL);
5772 CHECK(!fsrc->var_size, EINVAL);
5774 instr->type = INSTR_REGWR_RMM;
5775 if (idx[0] == 'h' && src[0] != 'h')
5776 instr->type = INSTR_REGWR_RHM;
5777 if (idx[0] != 'h' && src[0] == 'h')
5778 instr->type = INSTR_REGWR_RMH;
5779 if (idx[0] == 'h' && src[0] == 'h')
5780 instr->type = INSTR_REGWR_RHH;
5782 instr->regarray.regarray_id = r->id;
5783 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
5784 instr->regarray.idx.n_bits = fidx->n_bits;
5785 instr->regarray.idx.offset = fidx->offset / 8;
5786 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
5787 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
5788 instr->regarray.dstsrc.offset = fsrc->offset / 8;
5792 /* REGWR_RHI, REGWR_RMI. */
5793 if (fidx && !fsrc) {
5794 CHECK(!fidx->var_size, EINVAL);
5796 src_val = strtoull(src, &src, 0);
5797 CHECK(!src[0], EINVAL);
5799 instr->type = INSTR_REGWR_RMI;
5801 instr->type = INSTR_REGWR_RHI;
5803 instr->regarray.regarray_id = r->id;
5804 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
5805 instr->regarray.idx.n_bits = fidx->n_bits;
5806 instr->regarray.idx.offset = fidx->offset / 8;
5807 instr->regarray.dstsrc_val = src_val;
5811 /* REGWR_RIH, REGWR_RIM. */
5812 if (!fidx && fsrc) {
5813 idx_val = strtoul(idx, &idx, 0);
5814 CHECK(!idx[0], EINVAL);
5816 CHECK(!fsrc->var_size, EINVAL);
5818 instr->type = INSTR_REGWR_RIM;
5820 instr->type = INSTR_REGWR_RIH;
5822 instr->regarray.regarray_id = r->id;
5823 instr->regarray.idx_val = idx_val;
5824 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
5825 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
5826 instr->regarray.dstsrc.offset = fsrc->offset / 8;
5831 src_val = strtoull(src, &src, 0);
5832 CHECK(!src[0], EINVAL);
5834 idx_val = strtoul(idx, &idx, 0);
5835 CHECK(!idx[0], EINVAL);
5837 instr->type = INSTR_REGWR_RII;
5838 instr->regarray.idx_val = idx_val;
5839 instr->regarray.dstsrc_val = src_val;
5845 instr_regadd_translate(struct rte_swx_pipeline *p,
5846 struct action *action,
5849 struct instruction *instr,
5850 struct instruction_data *data __rte_unused)
5852 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
5854 struct field *fidx, *fsrc;
5856 uint32_t idx_struct_id, idx_val, src_struct_id;
5858 CHECK(n_tokens == 4, EINVAL);
5860 r = regarray_find(p, regarray);
5863 /* REGADD_RHH, REGADD_RHM, REGADD_RMH, REGADD_RMM. */
5864 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
5865 fsrc = struct_field_parse(p, action, src, &src_struct_id);
5867 CHECK(!fidx->var_size, EINVAL);
5868 CHECK(!fsrc->var_size, EINVAL);
5870 instr->type = INSTR_REGADD_RMM;
5871 if (idx[0] == 'h' && src[0] != 'h')
5872 instr->type = INSTR_REGADD_RHM;
5873 if (idx[0] != 'h' && src[0] == 'h')
5874 instr->type = INSTR_REGADD_RMH;
5875 if (idx[0] == 'h' && src[0] == 'h')
5876 instr->type = INSTR_REGADD_RHH;
5878 instr->regarray.regarray_id = r->id;
5879 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
5880 instr->regarray.idx.n_bits = fidx->n_bits;
5881 instr->regarray.idx.offset = fidx->offset / 8;
5882 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
5883 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
5884 instr->regarray.dstsrc.offset = fsrc->offset / 8;
5888 /* REGADD_RHI, REGADD_RMI. */
5889 if (fidx && !fsrc) {
5890 CHECK(!fidx->var_size, EINVAL);
5892 src_val = strtoull(src, &src, 0);
5893 CHECK(!src[0], EINVAL);
5895 instr->type = INSTR_REGADD_RMI;
5897 instr->type = INSTR_REGADD_RHI;
5899 instr->regarray.regarray_id = r->id;
5900 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
5901 instr->regarray.idx.n_bits = fidx->n_bits;
5902 instr->regarray.idx.offset = fidx->offset / 8;
5903 instr->regarray.dstsrc_val = src_val;
5907 /* REGADD_RIH, REGADD_RIM. */
5908 if (!fidx && fsrc) {
5909 idx_val = strtoul(idx, &idx, 0);
5910 CHECK(!idx[0], EINVAL);
5912 CHECK(!fsrc->var_size, EINVAL);
5914 instr->type = INSTR_REGADD_RIM;
5916 instr->type = INSTR_REGADD_RIH;
5918 instr->regarray.regarray_id = r->id;
5919 instr->regarray.idx_val = idx_val;
5920 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
5921 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
5922 instr->regarray.dstsrc.offset = fsrc->offset / 8;
5927 src_val = strtoull(src, &src, 0);
5928 CHECK(!src[0], EINVAL);
5930 idx_val = strtoul(idx, &idx, 0);
5931 CHECK(!idx[0], EINVAL);
5933 instr->type = INSTR_REGADD_RII;
5934 instr->regarray.idx_val = idx_val;
5935 instr->regarray.dstsrc_val = src_val;
5939 static inline uint64_t *
5940 instr_regarray_regarray(struct rte_swx_pipeline *p, struct instruction *ip)
5942 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
5946 static inline uint64_t
5947 instr_regarray_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
5949 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
5951 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
5952 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
5953 uint64_t idx64 = *idx64_ptr;
5954 uint64_t idx64_mask = UINT64_MAX >> (64 - ip->regarray.idx.n_bits);
5955 uint64_t idx = idx64 & idx64_mask & r->size_mask;
5960 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5962 static inline uint64_t
5963 instr_regarray_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
5965 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
5967 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
5968 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
5969 uint64_t idx64 = *idx64_ptr;
5970 uint64_t idx = (ntoh64(idx64) >> (64 - ip->regarray.idx.n_bits)) & r->size_mask;
5977 #define instr_regarray_idx_nbo instr_regarray_idx_hbo
5981 static inline uint64_t
5982 instr_regarray_idx_imm(struct rte_swx_pipeline *p, struct instruction *ip)
5984 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
5986 uint64_t idx = ip->regarray.idx_val & r->size_mask;
5991 static inline uint64_t
5992 instr_regarray_src_hbo(struct thread *t, struct instruction *ip)
5994 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
5995 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
5996 uint64_t src64 = *src64_ptr;
5997 uint64_t src64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
5998 uint64_t src = src64 & src64_mask;
6003 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
6005 static inline uint64_t
6006 instr_regarray_src_nbo(struct thread *t, struct instruction *ip)
6008 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
6009 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
6010 uint64_t src64 = *src64_ptr;
6011 uint64_t src = ntoh64(src64) >> (64 - ip->regarray.dstsrc.n_bits);
6018 #define instr_regarray_src_nbo instr_regarray_src_hbo
6023 instr_regarray_dst_hbo_src_hbo_set(struct thread *t, struct instruction *ip, uint64_t src)
6025 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
6026 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
6027 uint64_t dst64 = *dst64_ptr;
6028 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
6030 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
6034 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
6037 instr_regarray_dst_nbo_src_hbo_set(struct thread *t, struct instruction *ip, uint64_t src)
6039 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
6040 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
6041 uint64_t dst64 = *dst64_ptr;
6042 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
6044 src = hton64(src) >> (64 - ip->regarray.dstsrc.n_bits);
6045 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
6050 #define instr_regarray_dst_nbo_src_hbo_set instr_regarray_dst_hbo_src_hbo_set
6055 instr_regprefetch_rh_exec(struct rte_swx_pipeline *p)
6057 struct thread *t = &p->threads[p->thread_id];
6058 struct instruction *ip = t->ip;
6059 uint64_t *regarray, idx;
6061 TRACE("[Thread %2u] regprefetch (r[h])\n", p->thread_id);
6064 regarray = instr_regarray_regarray(p, ip);
6065 idx = instr_regarray_idx_nbo(p, t, ip);
6066 rte_prefetch0(®array[idx]);
6073 instr_regprefetch_rm_exec(struct rte_swx_pipeline *p)
6075 struct thread *t = &p->threads[p->thread_id];
6076 struct instruction *ip = t->ip;
6077 uint64_t *regarray, idx;
6079 TRACE("[Thread %2u] regprefetch (r[m])\n", p->thread_id);
6082 regarray = instr_regarray_regarray(p, ip);
6083 idx = instr_regarray_idx_hbo(p, t, ip);
6084 rte_prefetch0(®array[idx]);
6091 instr_regprefetch_ri_exec(struct rte_swx_pipeline *p)
6093 struct thread *t = &p->threads[p->thread_id];
6094 struct instruction *ip = t->ip;
6095 uint64_t *regarray, idx;
6097 TRACE("[Thread %2u] regprefetch (r[i])\n", p->thread_id);
6100 regarray = instr_regarray_regarray(p, ip);
6101 idx = instr_regarray_idx_imm(p, ip);
6102 rte_prefetch0(®array[idx]);
6109 instr_regrd_hrh_exec(struct rte_swx_pipeline *p)
6111 struct thread *t = &p->threads[p->thread_id];
6112 struct instruction *ip = t->ip;
6113 uint64_t *regarray, idx;
6115 TRACE("[Thread %2u] regrd (h = r[h])\n", p->thread_id);
6118 regarray = instr_regarray_regarray(p, ip);
6119 idx = instr_regarray_idx_nbo(p, t, ip);
6120 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
6127 instr_regrd_hrm_exec(struct rte_swx_pipeline *p)
6129 struct thread *t = &p->threads[p->thread_id];
6130 struct instruction *ip = t->ip;
6131 uint64_t *regarray, idx;
6133 TRACE("[Thread %2u] regrd (h = r[m])\n", p->thread_id);
6136 regarray = instr_regarray_regarray(p, ip);
6137 idx = instr_regarray_idx_hbo(p, t, ip);
6138 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
6145 instr_regrd_mrh_exec(struct rte_swx_pipeline *p)
6147 struct thread *t = &p->threads[p->thread_id];
6148 struct instruction *ip = t->ip;
6149 uint64_t *regarray, idx;
6151 TRACE("[Thread %2u] regrd (m = r[h])\n", p->thread_id);
6154 regarray = instr_regarray_regarray(p, ip);
6155 idx = instr_regarray_idx_nbo(p, t, ip);
6156 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
6163 instr_regrd_mrm_exec(struct rte_swx_pipeline *p)
6165 struct thread *t = &p->threads[p->thread_id];
6166 struct instruction *ip = t->ip;
6167 uint64_t *regarray, idx;
6170 regarray = instr_regarray_regarray(p, ip);
6171 idx = instr_regarray_idx_hbo(p, t, ip);
6172 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
6179 instr_regrd_hri_exec(struct rte_swx_pipeline *p)
6181 struct thread *t = &p->threads[p->thread_id];
6182 struct instruction *ip = t->ip;
6183 uint64_t *regarray, idx;
6185 TRACE("[Thread %2u] regrd (h = r[i])\n", p->thread_id);
6188 regarray = instr_regarray_regarray(p, ip);
6189 idx = instr_regarray_idx_imm(p, ip);
6190 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
6197 instr_regrd_mri_exec(struct rte_swx_pipeline *p)
6199 struct thread *t = &p->threads[p->thread_id];
6200 struct instruction *ip = t->ip;
6201 uint64_t *regarray, idx;
6203 TRACE("[Thread %2u] regrd (m = r[i])\n", p->thread_id);
6206 regarray = instr_regarray_regarray(p, ip);
6207 idx = instr_regarray_idx_imm(p, ip);
6208 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
6215 instr_regwr_rhh_exec(struct rte_swx_pipeline *p)
6217 struct thread *t = &p->threads[p->thread_id];
6218 struct instruction *ip = t->ip;
6219 uint64_t *regarray, idx, src;
6221 TRACE("[Thread %2u] regwr (r[h] = h)\n", p->thread_id);
6224 regarray = instr_regarray_regarray(p, ip);
6225 idx = instr_regarray_idx_nbo(p, t, ip);
6226 src = instr_regarray_src_nbo(t, ip);
6227 regarray[idx] = src;
6234 instr_regwr_rhm_exec(struct rte_swx_pipeline *p)
6236 struct thread *t = &p->threads[p->thread_id];
6237 struct instruction *ip = t->ip;
6238 uint64_t *regarray, idx, src;
6240 TRACE("[Thread %2u] regwr (r[h] = m)\n", p->thread_id);
6243 regarray = instr_regarray_regarray(p, ip);
6244 idx = instr_regarray_idx_nbo(p, t, ip);
6245 src = instr_regarray_src_hbo(t, ip);
6246 regarray[idx] = src;
6253 instr_regwr_rmh_exec(struct rte_swx_pipeline *p)
6255 struct thread *t = &p->threads[p->thread_id];
6256 struct instruction *ip = t->ip;
6257 uint64_t *regarray, idx, src;
6259 TRACE("[Thread %2u] regwr (r[m] = h)\n", p->thread_id);
6262 regarray = instr_regarray_regarray(p, ip);
6263 idx = instr_regarray_idx_hbo(p, t, ip);
6264 src = instr_regarray_src_nbo(t, ip);
6265 regarray[idx] = src;
6272 instr_regwr_rmm_exec(struct rte_swx_pipeline *p)
6274 struct thread *t = &p->threads[p->thread_id];
6275 struct instruction *ip = t->ip;
6276 uint64_t *regarray, idx, src;
6278 TRACE("[Thread %2u] regwr (r[m] = m)\n", p->thread_id);
6281 regarray = instr_regarray_regarray(p, ip);
6282 idx = instr_regarray_idx_hbo(p, t, ip);
6283 src = instr_regarray_src_hbo(t, ip);
6284 regarray[idx] = src;
6291 instr_regwr_rhi_exec(struct rte_swx_pipeline *p)
6293 struct thread *t = &p->threads[p->thread_id];
6294 struct instruction *ip = t->ip;
6295 uint64_t *regarray, idx, src;
6297 TRACE("[Thread %2u] regwr (r[h] = i)\n", p->thread_id);
6300 regarray = instr_regarray_regarray(p, ip);
6301 idx = instr_regarray_idx_nbo(p, t, ip);
6302 src = ip->regarray.dstsrc_val;
6303 regarray[idx] = src;
6310 instr_regwr_rmi_exec(struct rte_swx_pipeline *p)
6312 struct thread *t = &p->threads[p->thread_id];
6313 struct instruction *ip = t->ip;
6314 uint64_t *regarray, idx, src;
6316 TRACE("[Thread %2u] regwr (r[m] = i)\n", p->thread_id);
6319 regarray = instr_regarray_regarray(p, ip);
6320 idx = instr_regarray_idx_hbo(p, t, ip);
6321 src = ip->regarray.dstsrc_val;
6322 regarray[idx] = src;
6329 instr_regwr_rih_exec(struct rte_swx_pipeline *p)
6331 struct thread *t = &p->threads[p->thread_id];
6332 struct instruction *ip = t->ip;
6333 uint64_t *regarray, idx, src;
6335 TRACE("[Thread %2u] regwr (r[i] = h)\n", p->thread_id);
6338 regarray = instr_regarray_regarray(p, ip);
6339 idx = instr_regarray_idx_imm(p, ip);
6340 src = instr_regarray_src_nbo(t, ip);
6341 regarray[idx] = src;
6348 instr_regwr_rim_exec(struct rte_swx_pipeline *p)
6350 struct thread *t = &p->threads[p->thread_id];
6351 struct instruction *ip = t->ip;
6352 uint64_t *regarray, idx, src;
6354 TRACE("[Thread %2u] regwr (r[i] = m)\n", p->thread_id);
6357 regarray = instr_regarray_regarray(p, ip);
6358 idx = instr_regarray_idx_imm(p, ip);
6359 src = instr_regarray_src_hbo(t, ip);
6360 regarray[idx] = src;
6367 instr_regwr_rii_exec(struct rte_swx_pipeline *p)
6369 struct thread *t = &p->threads[p->thread_id];
6370 struct instruction *ip = t->ip;
6371 uint64_t *regarray, idx, src;
6373 TRACE("[Thread %2u] regwr (r[i] = i)\n", p->thread_id);
6376 regarray = instr_regarray_regarray(p, ip);
6377 idx = instr_regarray_idx_imm(p, ip);
6378 src = ip->regarray.dstsrc_val;
6379 regarray[idx] = src;
6386 instr_regadd_rhh_exec(struct rte_swx_pipeline *p)
6388 struct thread *t = &p->threads[p->thread_id];
6389 struct instruction *ip = t->ip;
6390 uint64_t *regarray, idx, src;
6392 TRACE("[Thread %2u] regadd (r[h] += h)\n", p->thread_id);
6395 regarray = instr_regarray_regarray(p, ip);
6396 idx = instr_regarray_idx_nbo(p, t, ip);
6397 src = instr_regarray_src_nbo(t, ip);
6398 regarray[idx] += src;
6405 instr_regadd_rhm_exec(struct rte_swx_pipeline *p)
6407 struct thread *t = &p->threads[p->thread_id];
6408 struct instruction *ip = t->ip;
6409 uint64_t *regarray, idx, src;
6411 TRACE("[Thread %2u] regadd (r[h] += m)\n", p->thread_id);
6414 regarray = instr_regarray_regarray(p, ip);
6415 idx = instr_regarray_idx_nbo(p, t, ip);
6416 src = instr_regarray_src_hbo(t, ip);
6417 regarray[idx] += src;
6424 instr_regadd_rmh_exec(struct rte_swx_pipeline *p)
6426 struct thread *t = &p->threads[p->thread_id];
6427 struct instruction *ip = t->ip;
6428 uint64_t *regarray, idx, src;
6430 TRACE("[Thread %2u] regadd (r[m] += h)\n", p->thread_id);
6433 regarray = instr_regarray_regarray(p, ip);
6434 idx = instr_regarray_idx_hbo(p, t, ip);
6435 src = instr_regarray_src_nbo(t, ip);
6436 regarray[idx] += src;
6443 instr_regadd_rmm_exec(struct rte_swx_pipeline *p)
6445 struct thread *t = &p->threads[p->thread_id];
6446 struct instruction *ip = t->ip;
6447 uint64_t *regarray, idx, src;
6449 TRACE("[Thread %2u] regadd (r[m] += m)\n", p->thread_id);
6452 regarray = instr_regarray_regarray(p, ip);
6453 idx = instr_regarray_idx_hbo(p, t, ip);
6454 src = instr_regarray_src_hbo(t, ip);
6455 regarray[idx] += src;
6462 instr_regadd_rhi_exec(struct rte_swx_pipeline *p)
6464 struct thread *t = &p->threads[p->thread_id];
6465 struct instruction *ip = t->ip;
6466 uint64_t *regarray, idx, src;
6468 TRACE("[Thread %2u] regadd (r[h] += i)\n", p->thread_id);
6471 regarray = instr_regarray_regarray(p, ip);
6472 idx = instr_regarray_idx_nbo(p, t, ip);
6473 src = ip->regarray.dstsrc_val;
6474 regarray[idx] += src;
6481 instr_regadd_rmi_exec(struct rte_swx_pipeline *p)
6483 struct thread *t = &p->threads[p->thread_id];
6484 struct instruction *ip = t->ip;
6485 uint64_t *regarray, idx, src;
6487 TRACE("[Thread %2u] regadd (r[m] += i)\n", p->thread_id);
6490 regarray = instr_regarray_regarray(p, ip);
6491 idx = instr_regarray_idx_hbo(p, t, ip);
6492 src = ip->regarray.dstsrc_val;
6493 regarray[idx] += src;
6500 instr_regadd_rih_exec(struct rte_swx_pipeline *p)
6502 struct thread *t = &p->threads[p->thread_id];
6503 struct instruction *ip = t->ip;
6504 uint64_t *regarray, idx, src;
6506 TRACE("[Thread %2u] regadd (r[i] += h)\n", p->thread_id);
6509 regarray = instr_regarray_regarray(p, ip);
6510 idx = instr_regarray_idx_imm(p, ip);
6511 src = instr_regarray_src_nbo(t, ip);
6512 regarray[idx] += src;
6519 instr_regadd_rim_exec(struct rte_swx_pipeline *p)
6521 struct thread *t = &p->threads[p->thread_id];
6522 struct instruction *ip = t->ip;
6523 uint64_t *regarray, idx, src;
6525 TRACE("[Thread %2u] regadd (r[i] += m)\n", p->thread_id);
6528 regarray = instr_regarray_regarray(p, ip);
6529 idx = instr_regarray_idx_imm(p, ip);
6530 src = instr_regarray_src_hbo(t, ip);
6531 regarray[idx] += src;
6538 instr_regadd_rii_exec(struct rte_swx_pipeline *p)
6540 struct thread *t = &p->threads[p->thread_id];
6541 struct instruction *ip = t->ip;
6542 uint64_t *regarray, idx, src;
6544 TRACE("[Thread %2u] regadd (r[i] += i)\n", p->thread_id);
6547 regarray = instr_regarray_regarray(p, ip);
6548 idx = instr_regarray_idx_imm(p, ip);
6549 src = ip->regarray.dstsrc_val;
6550 regarray[idx] += src;
6559 static struct metarray *
6560 metarray_find(struct rte_swx_pipeline *p, const char *name);
6563 instr_metprefetch_translate(struct rte_swx_pipeline *p,
6564 struct action *action,
6567 struct instruction *instr,
6568 struct instruction_data *data __rte_unused)
6570 char *metarray = tokens[1], *idx = tokens[2];
6573 uint32_t idx_struct_id, idx_val;
6575 CHECK(n_tokens == 3, EINVAL);
6577 m = metarray_find(p, metarray);
6580 /* METPREFETCH_H, METPREFETCH_M. */
6581 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
6583 CHECK(!fidx->var_size, EINVAL);
6585 instr->type = INSTR_METPREFETCH_M;
6587 instr->type = INSTR_METPREFETCH_H;
6589 instr->meter.metarray_id = m->id;
6590 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
6591 instr->meter.idx.n_bits = fidx->n_bits;
6592 instr->meter.idx.offset = fidx->offset / 8;
6596 /* METPREFETCH_I. */
6597 idx_val = strtoul(idx, &idx, 0);
6598 CHECK(!idx[0], EINVAL);
6600 instr->type = INSTR_METPREFETCH_I;
6601 instr->meter.metarray_id = m->id;
6602 instr->meter.idx_val = idx_val;
6607 instr_meter_translate(struct rte_swx_pipeline *p,
6608 struct action *action,
6611 struct instruction *instr,
6612 struct instruction_data *data __rte_unused)
6614 char *metarray = tokens[1], *idx = tokens[2], *length = tokens[3];
6615 char *color_in = tokens[4], *color_out = tokens[5];
6617 struct field *fidx, *flength, *fcin, *fcout;
6618 uint32_t idx_struct_id, length_struct_id;
6619 uint32_t color_in_struct_id, color_out_struct_id;
6621 CHECK(n_tokens == 6, EINVAL);
6623 m = metarray_find(p, metarray);
6626 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
6628 flength = struct_field_parse(p, action, length, &length_struct_id);
6629 CHECK(flength, EINVAL);
6630 CHECK(!flength->var_size, EINVAL);
6632 fcin = struct_field_parse(p, action, color_in, &color_in_struct_id);
6634 fcout = struct_field_parse(p, NULL, color_out, &color_out_struct_id);
6635 CHECK(fcout, EINVAL);
6636 CHECK(!fcout->var_size, EINVAL);
6638 /* index = HMEFT, length = HMEFT, color_in = MEFT, color_out = MEF. */
6640 CHECK(!fidx->var_size, EINVAL);
6641 CHECK(!fcin->var_size, EINVAL);
6643 instr->type = INSTR_METER_MMM;
6644 if (idx[0] == 'h' && length[0] == 'h')
6645 instr->type = INSTR_METER_HHM;
6646 if (idx[0] == 'h' && length[0] != 'h')
6647 instr->type = INSTR_METER_HMM;
6648 if (idx[0] != 'h' && length[0] == 'h')
6649 instr->type = INSTR_METER_MHM;
6651 instr->meter.metarray_id = m->id;
6653 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
6654 instr->meter.idx.n_bits = fidx->n_bits;
6655 instr->meter.idx.offset = fidx->offset / 8;
6657 instr->meter.length.struct_id = (uint8_t)length_struct_id;
6658 instr->meter.length.n_bits = flength->n_bits;
6659 instr->meter.length.offset = flength->offset / 8;
6661 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
6662 instr->meter.color_in.n_bits = fcin->n_bits;
6663 instr->meter.color_in.offset = fcin->offset / 8;
6665 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
6666 instr->meter.color_out.n_bits = fcout->n_bits;
6667 instr->meter.color_out.offset = fcout->offset / 8;
6672 /* index = HMEFT, length = HMEFT, color_in = I, color_out = MEF. */
6673 if (fidx && !fcin) {
6674 uint32_t color_in_val;
6676 CHECK(!fidx->var_size, EINVAL);
6678 color_in_val = strtoul(color_in, &color_in, 0);
6679 CHECK(!color_in[0], EINVAL);
6681 instr->type = INSTR_METER_MMI;
6682 if (idx[0] == 'h' && length[0] == 'h')
6683 instr->type = INSTR_METER_HHI;
6684 if (idx[0] == 'h' && length[0] != 'h')
6685 instr->type = INSTR_METER_HMI;
6686 if (idx[0] != 'h' && length[0] == 'h')
6687 instr->type = INSTR_METER_MHI;
6689 instr->meter.metarray_id = m->id;
6691 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
6692 instr->meter.idx.n_bits = fidx->n_bits;
6693 instr->meter.idx.offset = fidx->offset / 8;
6695 instr->meter.length.struct_id = (uint8_t)length_struct_id;
6696 instr->meter.length.n_bits = flength->n_bits;
6697 instr->meter.length.offset = flength->offset / 8;
6699 instr->meter.color_in_val = color_in_val;
6701 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
6702 instr->meter.color_out.n_bits = fcout->n_bits;
6703 instr->meter.color_out.offset = fcout->offset / 8;
6708 /* index = I, length = HMEFT, color_in = MEFT, color_out = MEF. */
6709 if (!fidx && fcin) {
6712 idx_val = strtoul(idx, &idx, 0);
6713 CHECK(!idx[0], EINVAL);
6715 CHECK(!fcin->var_size, EINVAL);
6717 instr->type = INSTR_METER_IMM;
6718 if (length[0] == 'h')
6719 instr->type = INSTR_METER_IHM;
6721 instr->meter.metarray_id = m->id;
6723 instr->meter.idx_val = idx_val;
6725 instr->meter.length.struct_id = (uint8_t)length_struct_id;
6726 instr->meter.length.n_bits = flength->n_bits;
6727 instr->meter.length.offset = flength->offset / 8;
6729 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
6730 instr->meter.color_in.n_bits = fcin->n_bits;
6731 instr->meter.color_in.offset = fcin->offset / 8;
6733 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
6734 instr->meter.color_out.n_bits = fcout->n_bits;
6735 instr->meter.color_out.offset = fcout->offset / 8;
6740 /* index = I, length = HMEFT, color_in = I, color_out = MEF. */
6741 if (!fidx && !fcin) {
6742 uint32_t idx_val, color_in_val;
6744 idx_val = strtoul(idx, &idx, 0);
6745 CHECK(!idx[0], EINVAL);
6747 color_in_val = strtoul(color_in, &color_in, 0);
6748 CHECK(!color_in[0], EINVAL);
6750 instr->type = INSTR_METER_IMI;
6751 if (length[0] == 'h')
6752 instr->type = INSTR_METER_IHI;
6754 instr->meter.metarray_id = m->id;
6756 instr->meter.idx_val = idx_val;
6758 instr->meter.length.struct_id = (uint8_t)length_struct_id;
6759 instr->meter.length.n_bits = flength->n_bits;
6760 instr->meter.length.offset = flength->offset / 8;
6762 instr->meter.color_in_val = color_in_val;
6764 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
6765 instr->meter.color_out.n_bits = fcout->n_bits;
6766 instr->meter.color_out.offset = fcout->offset / 8;
6774 static inline struct meter *
6775 instr_meter_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
6777 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
6779 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
6780 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
6781 uint64_t idx64 = *idx64_ptr;
6782 uint64_t idx64_mask = UINT64_MAX >> (64 - (ip)->meter.idx.n_bits);
6783 uint64_t idx = idx64 & idx64_mask & r->size_mask;
6785 return &r->metarray[idx];
6788 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
6790 static inline struct meter *
6791 instr_meter_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
6793 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
6795 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
6796 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
6797 uint64_t idx64 = *idx64_ptr;
6798 uint64_t idx = (ntoh64(idx64) >> (64 - ip->meter.idx.n_bits)) & r->size_mask;
6800 return &r->metarray[idx];
6805 #define instr_meter_idx_nbo instr_meter_idx_hbo
6809 static inline struct meter *
6810 instr_meter_idx_imm(struct rte_swx_pipeline *p, struct instruction *ip)
6812 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
6814 uint64_t idx = ip->meter.idx_val & r->size_mask;
6816 return &r->metarray[idx];
6819 static inline uint32_t
6820 instr_meter_length_hbo(struct thread *t, struct instruction *ip)
6822 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
6823 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
6824 uint64_t src64 = *src64_ptr;
6825 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->meter.length.n_bits);
6826 uint64_t src = src64 & src64_mask;
6828 return (uint32_t)src;
6831 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
6833 static inline uint32_t
6834 instr_meter_length_nbo(struct thread *t, struct instruction *ip)
6836 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
6837 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
6838 uint64_t src64 = *src64_ptr;
6839 uint64_t src = ntoh64(src64) >> (64 - ip->meter.length.n_bits);
6841 return (uint32_t)src;
6846 #define instr_meter_length_nbo instr_meter_length_hbo
6850 static inline enum rte_color
6851 instr_meter_color_in_hbo(struct thread *t, struct instruction *ip)
6853 uint8_t *src_struct = t->structs[ip->meter.color_in.struct_id];
6854 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.color_in.offset];
6855 uint64_t src64 = *src64_ptr;
6856 uint64_t src64_mask = UINT64_MAX >> (64 - ip->meter.color_in.n_bits);
6857 uint64_t src = src64 & src64_mask;
6859 return (enum rte_color)src;
6863 instr_meter_color_out_hbo_set(struct thread *t, struct instruction *ip, enum rte_color color_out)
6865 uint8_t *dst_struct = t->structs[ip->meter.color_out.struct_id];
6866 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->meter.color_out.offset];
6867 uint64_t dst64 = *dst64_ptr;
6868 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->meter.color_out.n_bits);
6870 uint64_t src = (uint64_t)color_out;
6872 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
6876 instr_metprefetch_h_exec(struct rte_swx_pipeline *p)
6878 struct thread *t = &p->threads[p->thread_id];
6879 struct instruction *ip = t->ip;
6882 TRACE("[Thread %2u] metprefetch (h)\n", p->thread_id);
6885 m = instr_meter_idx_nbo(p, t, ip);
6893 instr_metprefetch_m_exec(struct rte_swx_pipeline *p)
6895 struct thread *t = &p->threads[p->thread_id];
6896 struct instruction *ip = t->ip;
6899 TRACE("[Thread %2u] metprefetch (m)\n", p->thread_id);
6902 m = instr_meter_idx_hbo(p, t, ip);
6910 instr_metprefetch_i_exec(struct rte_swx_pipeline *p)
6912 struct thread *t = &p->threads[p->thread_id];
6913 struct instruction *ip = t->ip;
6916 TRACE("[Thread %2u] metprefetch (i)\n", p->thread_id);
6919 m = instr_meter_idx_imm(p, ip);
6927 instr_meter_hhm_exec(struct rte_swx_pipeline *p)
6929 struct thread *t = &p->threads[p->thread_id];
6930 struct instruction *ip = t->ip;
6932 uint64_t time, n_pkts, n_bytes;
6934 enum rte_color color_in, color_out;
6936 TRACE("[Thread %2u] meter (hhm)\n", p->thread_id);
6939 m = instr_meter_idx_nbo(p, t, ip);
6940 rte_prefetch0(m->n_pkts);
6941 time = rte_get_tsc_cycles();
6942 length = instr_meter_length_nbo(t, ip);
6943 color_in = instr_meter_color_in_hbo(t, ip);
6945 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6946 &m->profile->profile,
6951 color_out &= m->color_mask;
6953 n_pkts = m->n_pkts[color_out];
6954 n_bytes = m->n_bytes[color_out];
6956 instr_meter_color_out_hbo_set(t, ip, color_out);
6958 m->n_pkts[color_out] = n_pkts + 1;
6959 m->n_bytes[color_out] = n_bytes + length;
6966 instr_meter_hhi_exec(struct rte_swx_pipeline *p)
6968 struct thread *t = &p->threads[p->thread_id];
6969 struct instruction *ip = t->ip;
6971 uint64_t time, n_pkts, n_bytes;
6973 enum rte_color color_in, color_out;
6975 TRACE("[Thread %2u] meter (hhi)\n", p->thread_id);
6978 m = instr_meter_idx_nbo(p, t, ip);
6979 rte_prefetch0(m->n_pkts);
6980 time = rte_get_tsc_cycles();
6981 length = instr_meter_length_nbo(t, ip);
6982 color_in = (enum rte_color)ip->meter.color_in_val;
6984 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6985 &m->profile->profile,
6990 color_out &= m->color_mask;
6992 n_pkts = m->n_pkts[color_out];
6993 n_bytes = m->n_bytes[color_out];
6995 instr_meter_color_out_hbo_set(t, ip, color_out);
6997 m->n_pkts[color_out] = n_pkts + 1;
6998 m->n_bytes[color_out] = n_bytes + length;
7005 instr_meter_hmm_exec(struct rte_swx_pipeline *p)
7007 struct thread *t = &p->threads[p->thread_id];
7008 struct instruction *ip = t->ip;
7010 uint64_t time, n_pkts, n_bytes;
7012 enum rte_color color_in, color_out;
7014 TRACE("[Thread %2u] meter (hmm)\n", p->thread_id);
7017 m = instr_meter_idx_nbo(p, t, ip);
7018 rte_prefetch0(m->n_pkts);
7019 time = rte_get_tsc_cycles();
7020 length = instr_meter_length_hbo(t, ip);
7021 color_in = instr_meter_color_in_hbo(t, ip);
7023 color_out = rte_meter_trtcm_color_aware_check(&m->m,
7024 &m->profile->profile,
7029 color_out &= m->color_mask;
7031 n_pkts = m->n_pkts[color_out];
7032 n_bytes = m->n_bytes[color_out];
7034 instr_meter_color_out_hbo_set(t, ip, color_out);
7036 m->n_pkts[color_out] = n_pkts + 1;
7037 m->n_bytes[color_out] = n_bytes + length;
7043 instr_meter_hmi_exec(struct rte_swx_pipeline *p)
7045 struct thread *t = &p->threads[p->thread_id];
7046 struct instruction *ip = t->ip;
7048 uint64_t time, n_pkts, n_bytes;
7050 enum rte_color color_in, color_out;
7052 TRACE("[Thread %2u] meter (hmi)\n", p->thread_id);
7055 m = instr_meter_idx_nbo(p, t, ip);
7056 rte_prefetch0(m->n_pkts);
7057 time = rte_get_tsc_cycles();
7058 length = instr_meter_length_hbo(t, ip);
7059 color_in = (enum rte_color)ip->meter.color_in_val;
7061 color_out = rte_meter_trtcm_color_aware_check(&m->m,
7062 &m->profile->profile,
7067 color_out &= m->color_mask;
7069 n_pkts = m->n_pkts[color_out];
7070 n_bytes = m->n_bytes[color_out];
7072 instr_meter_color_out_hbo_set(t, ip, color_out);
7074 m->n_pkts[color_out] = n_pkts + 1;
7075 m->n_bytes[color_out] = n_bytes + length;
7082 instr_meter_mhm_exec(struct rte_swx_pipeline *p)
7084 struct thread *t = &p->threads[p->thread_id];
7085 struct instruction *ip = t->ip;
7087 uint64_t time, n_pkts, n_bytes;
7089 enum rte_color color_in, color_out;
7091 TRACE("[Thread %2u] meter (mhm)\n", p->thread_id);
7094 m = instr_meter_idx_hbo(p, t, ip);
7095 rte_prefetch0(m->n_pkts);
7096 time = rte_get_tsc_cycles();
7097 length = instr_meter_length_nbo(t, ip);
7098 color_in = instr_meter_color_in_hbo(t, ip);
7100 color_out = rte_meter_trtcm_color_aware_check(&m->m,
7101 &m->profile->profile,
7106 color_out &= m->color_mask;
7108 n_pkts = m->n_pkts[color_out];
7109 n_bytes = m->n_bytes[color_out];
7111 instr_meter_color_out_hbo_set(t, ip, color_out);
7113 m->n_pkts[color_out] = n_pkts + 1;
7114 m->n_bytes[color_out] = n_bytes + length;
7121 instr_meter_mhi_exec(struct rte_swx_pipeline *p)
7123 struct thread *t = &p->threads[p->thread_id];
7124 struct instruction *ip = t->ip;
7126 uint64_t time, n_pkts, n_bytes;
7128 enum rte_color color_in, color_out;
7130 TRACE("[Thread %2u] meter (mhi)\n", p->thread_id);
7133 m = instr_meter_idx_hbo(p, t, ip);
7134 rte_prefetch0(m->n_pkts);
7135 time = rte_get_tsc_cycles();
7136 length = instr_meter_length_nbo(t, ip);
7137 color_in = (enum rte_color)ip->meter.color_in_val;
7139 color_out = rte_meter_trtcm_color_aware_check(&m->m,
7140 &m->profile->profile,
7145 color_out &= m->color_mask;
7147 n_pkts = m->n_pkts[color_out];
7148 n_bytes = m->n_bytes[color_out];
7150 instr_meter_color_out_hbo_set(t, ip, color_out);
7152 m->n_pkts[color_out] = n_pkts + 1;
7153 m->n_bytes[color_out] = n_bytes + length;
7160 instr_meter_mmm_exec(struct rte_swx_pipeline *p)
7162 struct thread *t = &p->threads[p->thread_id];
7163 struct instruction *ip = t->ip;
7165 uint64_t time, n_pkts, n_bytes;
7167 enum rte_color color_in, color_out;
7169 TRACE("[Thread %2u] meter (mmm)\n", p->thread_id);
7172 m = instr_meter_idx_hbo(p, t, ip);
7173 rte_prefetch0(m->n_pkts);
7174 time = rte_get_tsc_cycles();
7175 length = instr_meter_length_hbo(t, ip);
7176 color_in = instr_meter_color_in_hbo(t, ip);
7178 color_out = rte_meter_trtcm_color_aware_check(&m->m,
7179 &m->profile->profile,
7184 color_out &= m->color_mask;
7186 n_pkts = m->n_pkts[color_out];
7187 n_bytes = m->n_bytes[color_out];
7189 instr_meter_color_out_hbo_set(t, ip, color_out);
7191 m->n_pkts[color_out] = n_pkts + 1;
7192 m->n_bytes[color_out] = n_bytes + length;
7199 instr_meter_mmi_exec(struct rte_swx_pipeline *p)
7201 struct thread *t = &p->threads[p->thread_id];
7202 struct instruction *ip = t->ip;
7204 uint64_t time, n_pkts, n_bytes;
7206 enum rte_color color_in, color_out;
7208 TRACE("[Thread %2u] meter (mmi)\n", p->thread_id);
7211 m = instr_meter_idx_hbo(p, t, ip);
7212 rte_prefetch0(m->n_pkts);
7213 time = rte_get_tsc_cycles();
7214 length = instr_meter_length_hbo(t, ip);
7215 color_in = (enum rte_color)ip->meter.color_in_val;
7217 color_out = rte_meter_trtcm_color_aware_check(&m->m,
7218 &m->profile->profile,
7223 color_out &= m->color_mask;
7225 n_pkts = m->n_pkts[color_out];
7226 n_bytes = m->n_bytes[color_out];
7228 instr_meter_color_out_hbo_set(t, ip, color_out);
7230 m->n_pkts[color_out] = n_pkts + 1;
7231 m->n_bytes[color_out] = n_bytes + length;
7238 instr_meter_ihm_exec(struct rte_swx_pipeline *p)
7240 struct thread *t = &p->threads[p->thread_id];
7241 struct instruction *ip = t->ip;
7243 uint64_t time, n_pkts, n_bytes;
7245 enum rte_color color_in, color_out;
7247 TRACE("[Thread %2u] meter (ihm)\n", p->thread_id);
7250 m = instr_meter_idx_imm(p, ip);
7251 rte_prefetch0(m->n_pkts);
7252 time = rte_get_tsc_cycles();
7253 length = instr_meter_length_nbo(t, ip);
7254 color_in = instr_meter_color_in_hbo(t, ip);
7256 color_out = rte_meter_trtcm_color_aware_check(&m->m,
7257 &m->profile->profile,
7262 color_out &= m->color_mask;
7264 n_pkts = m->n_pkts[color_out];
7265 n_bytes = m->n_bytes[color_out];
7267 instr_meter_color_out_hbo_set(t, ip, color_out);
7269 m->n_pkts[color_out] = n_pkts + 1;
7270 m->n_bytes[color_out] = n_bytes + length;
7277 instr_meter_ihi_exec(struct rte_swx_pipeline *p)
7279 struct thread *t = &p->threads[p->thread_id];
7280 struct instruction *ip = t->ip;
7282 uint64_t time, n_pkts, n_bytes;
7284 enum rte_color color_in, color_out;
7286 TRACE("[Thread %2u] meter (ihi)\n", p->thread_id);
7289 m = instr_meter_idx_imm(p, ip);
7290 rte_prefetch0(m->n_pkts);
7291 time = rte_get_tsc_cycles();
7292 length = instr_meter_length_nbo(t, ip);
7293 color_in = (enum rte_color)ip->meter.color_in_val;
7295 color_out = rte_meter_trtcm_color_aware_check(&m->m,
7296 &m->profile->profile,
7301 color_out &= m->color_mask;
7303 n_pkts = m->n_pkts[color_out];
7304 n_bytes = m->n_bytes[color_out];
7306 instr_meter_color_out_hbo_set(t, ip, color_out);
7308 m->n_pkts[color_out] = n_pkts + 1;
7309 m->n_bytes[color_out] = n_bytes + length;
7316 instr_meter_imm_exec(struct rte_swx_pipeline *p)
7318 struct thread *t = &p->threads[p->thread_id];
7319 struct instruction *ip = t->ip;
7321 uint64_t time, n_pkts, n_bytes;
7323 enum rte_color color_in, color_out;
7325 TRACE("[Thread %2u] meter (imm)\n", p->thread_id);
7328 m = instr_meter_idx_imm(p, ip);
7329 rte_prefetch0(m->n_pkts);
7330 time = rte_get_tsc_cycles();
7331 length = instr_meter_length_hbo(t, ip);
7332 color_in = instr_meter_color_in_hbo(t, ip);
7334 color_out = rte_meter_trtcm_color_aware_check(&m->m,
7335 &m->profile->profile,
7340 color_out &= m->color_mask;
7342 n_pkts = m->n_pkts[color_out];
7343 n_bytes = m->n_bytes[color_out];
7345 instr_meter_color_out_hbo_set(t, ip, color_out);
7347 m->n_pkts[color_out] = n_pkts + 1;
7348 m->n_bytes[color_out] = n_bytes + length;
7354 instr_meter_imi_exec(struct rte_swx_pipeline *p)
7356 struct thread *t = &p->threads[p->thread_id];
7357 struct instruction *ip = t->ip;
7359 uint64_t time, n_pkts, n_bytes;
7361 enum rte_color color_in, color_out;
7363 TRACE("[Thread %2u] meter (imi)\n", p->thread_id);
7366 m = instr_meter_idx_imm(p, ip);
7367 rte_prefetch0(m->n_pkts);
7368 time = rte_get_tsc_cycles();
7369 length = instr_meter_length_hbo(t, ip);
7370 color_in = (enum rte_color)ip->meter.color_in_val;
7372 color_out = rte_meter_trtcm_color_aware_check(&m->m,
7373 &m->profile->profile,
7378 color_out &= m->color_mask;
7380 n_pkts = m->n_pkts[color_out];
7381 n_bytes = m->n_bytes[color_out];
7383 instr_meter_color_out_hbo_set(t, ip, color_out);
7385 m->n_pkts[color_out] = n_pkts + 1;
7386 m->n_bytes[color_out] = n_bytes + length;
7396 instr_jmp_translate(struct rte_swx_pipeline *p __rte_unused,
7397 struct action *action __rte_unused,
7400 struct instruction *instr,
7401 struct instruction_data *data)
7403 CHECK(n_tokens == 2, EINVAL);
7405 strcpy(data->jmp_label, tokens[1]);
7407 instr->type = INSTR_JMP;
7408 instr->jmp.ip = NULL; /* Resolved later. */
7413 instr_jmp_valid_translate(struct rte_swx_pipeline *p,
7414 struct action *action __rte_unused,
7417 struct instruction *instr,
7418 struct instruction_data *data)
7422 CHECK(n_tokens == 3, EINVAL);
7424 strcpy(data->jmp_label, tokens[1]);
7426 h = header_parse(p, tokens[2]);
7429 instr->type = INSTR_JMP_VALID;
7430 instr->jmp.ip = NULL; /* Resolved later. */
7431 instr->jmp.header_id = h->id;
7436 instr_jmp_invalid_translate(struct rte_swx_pipeline *p,
7437 struct action *action __rte_unused,
7440 struct instruction *instr,
7441 struct instruction_data *data)
7445 CHECK(n_tokens == 3, EINVAL);
7447 strcpy(data->jmp_label, tokens[1]);
7449 h = header_parse(p, tokens[2]);
7452 instr->type = INSTR_JMP_INVALID;
7453 instr->jmp.ip = NULL; /* Resolved later. */
7454 instr->jmp.header_id = h->id;
7459 instr_jmp_hit_translate(struct rte_swx_pipeline *p __rte_unused,
7460 struct action *action,
7463 struct instruction *instr,
7464 struct instruction_data *data)
7466 CHECK(!action, EINVAL);
7467 CHECK(n_tokens == 2, EINVAL);
7469 strcpy(data->jmp_label, tokens[1]);
7471 instr->type = INSTR_JMP_HIT;
7472 instr->jmp.ip = NULL; /* Resolved later. */
7477 instr_jmp_miss_translate(struct rte_swx_pipeline *p __rte_unused,
7478 struct action *action,
7481 struct instruction *instr,
7482 struct instruction_data *data)
7484 CHECK(!action, EINVAL);
7485 CHECK(n_tokens == 2, EINVAL);
7487 strcpy(data->jmp_label, tokens[1]);
7489 instr->type = INSTR_JMP_MISS;
7490 instr->jmp.ip = NULL; /* Resolved later. */
7495 instr_jmp_action_hit_translate(struct rte_swx_pipeline *p,
7496 struct action *action,
7499 struct instruction *instr,
7500 struct instruction_data *data)
7504 CHECK(!action, EINVAL);
7505 CHECK(n_tokens == 3, EINVAL);
7507 strcpy(data->jmp_label, tokens[1]);
7509 a = action_find(p, tokens[2]);
7512 instr->type = INSTR_JMP_ACTION_HIT;
7513 instr->jmp.ip = NULL; /* Resolved later. */
7514 instr->jmp.action_id = a->id;
7519 instr_jmp_action_miss_translate(struct rte_swx_pipeline *p,
7520 struct action *action,
7523 struct instruction *instr,
7524 struct instruction_data *data)
7528 CHECK(!action, EINVAL);
7529 CHECK(n_tokens == 3, EINVAL);
7531 strcpy(data->jmp_label, tokens[1]);
7533 a = action_find(p, tokens[2]);
7536 instr->type = INSTR_JMP_ACTION_MISS;
7537 instr->jmp.ip = NULL; /* Resolved later. */
7538 instr->jmp.action_id = a->id;
7543 instr_jmp_eq_translate(struct rte_swx_pipeline *p,
7544 struct action *action,
7547 struct instruction *instr,
7548 struct instruction_data *data)
7550 char *a = tokens[2], *b = tokens[3];
7551 struct field *fa, *fb;
7553 uint32_t a_struct_id, b_struct_id;
7555 CHECK(n_tokens == 4, EINVAL);
7557 strcpy(data->jmp_label, tokens[1]);
7559 fa = struct_field_parse(p, action, a, &a_struct_id);
7561 CHECK(!fa->var_size, EINVAL);
7563 /* JMP_EQ, JMP_EQ_MH, JMP_EQ_HM, JMP_EQ_HH. */
7564 fb = struct_field_parse(p, action, b, &b_struct_id);
7566 CHECK(!fb->var_size, EINVAL);
7568 instr->type = INSTR_JMP_EQ;
7569 if (a[0] != 'h' && b[0] == 'h')
7570 instr->type = INSTR_JMP_EQ_MH;
7571 if (a[0] == 'h' && b[0] != 'h')
7572 instr->type = INSTR_JMP_EQ_HM;
7573 if (a[0] == 'h' && b[0] == 'h')
7574 instr->type = INSTR_JMP_EQ_HH;
7575 instr->jmp.ip = NULL; /* Resolved later. */
7577 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
7578 instr->jmp.a.n_bits = fa->n_bits;
7579 instr->jmp.a.offset = fa->offset / 8;
7580 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
7581 instr->jmp.b.n_bits = fb->n_bits;
7582 instr->jmp.b.offset = fb->offset / 8;
7587 b_val = strtoull(b, &b, 0);
7588 CHECK(!b[0], EINVAL);
7591 b_val = hton64(b_val) >> (64 - fa->n_bits);
7593 instr->type = INSTR_JMP_EQ_I;
7594 instr->jmp.ip = NULL; /* Resolved later. */
7595 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
7596 instr->jmp.a.n_bits = fa->n_bits;
7597 instr->jmp.a.offset = fa->offset / 8;
7598 instr->jmp.b_val = b_val;
7603 instr_jmp_neq_translate(struct rte_swx_pipeline *p,
7604 struct action *action,
7607 struct instruction *instr,
7608 struct instruction_data *data)
7610 char *a = tokens[2], *b = tokens[3];
7611 struct field *fa, *fb;
7613 uint32_t a_struct_id, b_struct_id;
7615 CHECK(n_tokens == 4, EINVAL);
7617 strcpy(data->jmp_label, tokens[1]);
7619 fa = struct_field_parse(p, action, a, &a_struct_id);
7621 CHECK(!fa->var_size, EINVAL);
7623 /* JMP_NEQ, JMP_NEQ_MH, JMP_NEQ_HM, JMP_NEQ_HH. */
7624 fb = struct_field_parse(p, action, b, &b_struct_id);
7626 CHECK(!fb->var_size, EINVAL);
7628 instr->type = INSTR_JMP_NEQ;
7629 if (a[0] != 'h' && b[0] == 'h')
7630 instr->type = INSTR_JMP_NEQ_MH;
7631 if (a[0] == 'h' && b[0] != 'h')
7632 instr->type = INSTR_JMP_NEQ_HM;
7633 if (a[0] == 'h' && b[0] == 'h')
7634 instr->type = INSTR_JMP_NEQ_HH;
7635 instr->jmp.ip = NULL; /* Resolved later. */
7637 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
7638 instr->jmp.a.n_bits = fa->n_bits;
7639 instr->jmp.a.offset = fa->offset / 8;
7640 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
7641 instr->jmp.b.n_bits = fb->n_bits;
7642 instr->jmp.b.offset = fb->offset / 8;
7647 b_val = strtoull(b, &b, 0);
7648 CHECK(!b[0], EINVAL);
7651 b_val = hton64(b_val) >> (64 - fa->n_bits);
7653 instr->type = INSTR_JMP_NEQ_I;
7654 instr->jmp.ip = NULL; /* Resolved later. */
7655 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
7656 instr->jmp.a.n_bits = fa->n_bits;
7657 instr->jmp.a.offset = fa->offset / 8;
7658 instr->jmp.b_val = b_val;
7663 instr_jmp_lt_translate(struct rte_swx_pipeline *p,
7664 struct action *action,
7667 struct instruction *instr,
7668 struct instruction_data *data)
7670 char *a = tokens[2], *b = tokens[3];
7671 struct field *fa, *fb;
7673 uint32_t a_struct_id, b_struct_id;
7675 CHECK(n_tokens == 4, EINVAL);
7677 strcpy(data->jmp_label, tokens[1]);
7679 fa = struct_field_parse(p, action, a, &a_struct_id);
7681 CHECK(!fa->var_size, EINVAL);
7683 /* JMP_LT, JMP_LT_MH, JMP_LT_HM, JMP_LT_HH. */
7684 fb = struct_field_parse(p, action, b, &b_struct_id);
7686 CHECK(!fb->var_size, EINVAL);
7688 instr->type = INSTR_JMP_LT;
7689 if (a[0] == 'h' && b[0] != 'h')
7690 instr->type = INSTR_JMP_LT_HM;
7691 if (a[0] != 'h' && b[0] == 'h')
7692 instr->type = INSTR_JMP_LT_MH;
7693 if (a[0] == 'h' && b[0] == 'h')
7694 instr->type = INSTR_JMP_LT_HH;
7695 instr->jmp.ip = NULL; /* Resolved later. */
7697 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
7698 instr->jmp.a.n_bits = fa->n_bits;
7699 instr->jmp.a.offset = fa->offset / 8;
7700 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
7701 instr->jmp.b.n_bits = fb->n_bits;
7702 instr->jmp.b.offset = fb->offset / 8;
7706 /* JMP_LT_MI, JMP_LT_HI. */
7707 b_val = strtoull(b, &b, 0);
7708 CHECK(!b[0], EINVAL);
7710 instr->type = INSTR_JMP_LT_MI;
7712 instr->type = INSTR_JMP_LT_HI;
7713 instr->jmp.ip = NULL; /* Resolved later. */
7715 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
7716 instr->jmp.a.n_bits = fa->n_bits;
7717 instr->jmp.a.offset = fa->offset / 8;
7718 instr->jmp.b_val = b_val;
7723 instr_jmp_gt_translate(struct rte_swx_pipeline *p,
7724 struct action *action,
7727 struct instruction *instr,
7728 struct instruction_data *data)
7730 char *a = tokens[2], *b = tokens[3];
7731 struct field *fa, *fb;
7733 uint32_t a_struct_id, b_struct_id;
7735 CHECK(n_tokens == 4, EINVAL);
7737 strcpy(data->jmp_label, tokens[1]);
7739 fa = struct_field_parse(p, action, a, &a_struct_id);
7741 CHECK(!fa->var_size, EINVAL);
7743 /* JMP_GT, JMP_GT_MH, JMP_GT_HM, JMP_GT_HH. */
7744 fb = struct_field_parse(p, action, b, &b_struct_id);
7746 CHECK(!fb->var_size, EINVAL);
7748 instr->type = INSTR_JMP_GT;
7749 if (a[0] == 'h' && b[0] != 'h')
7750 instr->type = INSTR_JMP_GT_HM;
7751 if (a[0] != 'h' && b[0] == 'h')
7752 instr->type = INSTR_JMP_GT_MH;
7753 if (a[0] == 'h' && b[0] == 'h')
7754 instr->type = INSTR_JMP_GT_HH;
7755 instr->jmp.ip = NULL; /* Resolved later. */
7757 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
7758 instr->jmp.a.n_bits = fa->n_bits;
7759 instr->jmp.a.offset = fa->offset / 8;
7760 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
7761 instr->jmp.b.n_bits = fb->n_bits;
7762 instr->jmp.b.offset = fb->offset / 8;
7766 /* JMP_GT_MI, JMP_GT_HI. */
7767 b_val = strtoull(b, &b, 0);
7768 CHECK(!b[0], EINVAL);
7770 instr->type = INSTR_JMP_GT_MI;
7772 instr->type = INSTR_JMP_GT_HI;
7773 instr->jmp.ip = NULL; /* Resolved later. */
7775 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
7776 instr->jmp.a.n_bits = fa->n_bits;
7777 instr->jmp.a.offset = fa->offset / 8;
7778 instr->jmp.b_val = b_val;
7783 instr_jmp_exec(struct rte_swx_pipeline *p)
7785 struct thread *t = &p->threads[p->thread_id];
7786 struct instruction *ip = t->ip;
7788 TRACE("[Thread %2u] jmp\n", p->thread_id);
7790 thread_ip_set(t, ip->jmp.ip);
7794 instr_jmp_valid_exec(struct rte_swx_pipeline *p)
7796 struct thread *t = &p->threads[p->thread_id];
7797 struct instruction *ip = t->ip;
7798 uint32_t header_id = ip->jmp.header_id;
7800 TRACE("[Thread %2u] jmpv\n", p->thread_id);
7802 t->ip = HEADER_VALID(t, header_id) ? ip->jmp.ip : (t->ip + 1);
7806 instr_jmp_invalid_exec(struct rte_swx_pipeline *p)
7808 struct thread *t = &p->threads[p->thread_id];
7809 struct instruction *ip = t->ip;
7810 uint32_t header_id = ip->jmp.header_id;
7812 TRACE("[Thread %2u] jmpnv\n", p->thread_id);
7814 t->ip = HEADER_VALID(t, header_id) ? (t->ip + 1) : ip->jmp.ip;
7818 instr_jmp_hit_exec(struct rte_swx_pipeline *p)
7820 struct thread *t = &p->threads[p->thread_id];
7821 struct instruction *ip = t->ip;
7822 struct instruction *ip_next[] = {t->ip + 1, ip->jmp.ip};
7824 TRACE("[Thread %2u] jmph\n", p->thread_id);
7826 t->ip = ip_next[t->hit];
7830 instr_jmp_miss_exec(struct rte_swx_pipeline *p)
7832 struct thread *t = &p->threads[p->thread_id];
7833 struct instruction *ip = t->ip;
7834 struct instruction *ip_next[] = {ip->jmp.ip, t->ip + 1};
7836 TRACE("[Thread %2u] jmpnh\n", p->thread_id);
7838 t->ip = ip_next[t->hit];
7842 instr_jmp_action_hit_exec(struct rte_swx_pipeline *p)
7844 struct thread *t = &p->threads[p->thread_id];
7845 struct instruction *ip = t->ip;
7847 TRACE("[Thread %2u] jmpa\n", p->thread_id);
7849 t->ip = (ip->jmp.action_id == t->action_id) ? ip->jmp.ip : (t->ip + 1);
7853 instr_jmp_action_miss_exec(struct rte_swx_pipeline *p)
7855 struct thread *t = &p->threads[p->thread_id];
7856 struct instruction *ip = t->ip;
7858 TRACE("[Thread %2u] jmpna\n", p->thread_id);
7860 t->ip = (ip->jmp.action_id == t->action_id) ? (t->ip + 1) : ip->jmp.ip;
7864 instr_jmp_eq_exec(struct rte_swx_pipeline *p)
7866 struct thread *t = &p->threads[p->thread_id];
7867 struct instruction *ip = t->ip;
7869 TRACE("[Thread %2u] jmpeq\n", p->thread_id);
7875 instr_jmp_eq_mh_exec(struct rte_swx_pipeline *p)
7877 struct thread *t = &p->threads[p->thread_id];
7878 struct instruction *ip = t->ip;
7880 TRACE("[Thread %2u] jmpeq (mh)\n", p->thread_id);
7882 JMP_CMP_MH(t, ip, ==);
7886 instr_jmp_eq_hm_exec(struct rte_swx_pipeline *p)
7888 struct thread *t = &p->threads[p->thread_id];
7889 struct instruction *ip = t->ip;
7891 TRACE("[Thread %2u] jmpeq (hm)\n", p->thread_id);
7893 JMP_CMP_HM(t, ip, ==);
7897 instr_jmp_eq_hh_exec(struct rte_swx_pipeline *p)
7899 struct thread *t = &p->threads[p->thread_id];
7900 struct instruction *ip = t->ip;
7902 TRACE("[Thread %2u] jmpeq (hh)\n", p->thread_id);
7904 JMP_CMP_HH_FAST(t, ip, ==);
7908 instr_jmp_eq_i_exec(struct rte_swx_pipeline *p)
7910 struct thread *t = &p->threads[p->thread_id];
7911 struct instruction *ip = t->ip;
7913 TRACE("[Thread %2u] jmpeq (i)\n", p->thread_id);
7915 JMP_CMP_I(t, ip, ==);
7919 instr_jmp_neq_exec(struct rte_swx_pipeline *p)
7921 struct thread *t = &p->threads[p->thread_id];
7922 struct instruction *ip = t->ip;
7924 TRACE("[Thread %2u] jmpneq\n", p->thread_id);
7930 instr_jmp_neq_mh_exec(struct rte_swx_pipeline *p)
7932 struct thread *t = &p->threads[p->thread_id];
7933 struct instruction *ip = t->ip;
7935 TRACE("[Thread %2u] jmpneq (mh)\n", p->thread_id);
7937 JMP_CMP_MH(t, ip, !=);
7941 instr_jmp_neq_hm_exec(struct rte_swx_pipeline *p)
7943 struct thread *t = &p->threads[p->thread_id];
7944 struct instruction *ip = t->ip;
7946 TRACE("[Thread %2u] jmpneq (hm)\n", p->thread_id);
7948 JMP_CMP_HM(t, ip, !=);
7952 instr_jmp_neq_hh_exec(struct rte_swx_pipeline *p)
7954 struct thread *t = &p->threads[p->thread_id];
7955 struct instruction *ip = t->ip;
7957 TRACE("[Thread %2u] jmpneq (hh)\n", p->thread_id);
7959 JMP_CMP_HH_FAST(t, ip, !=);
7963 instr_jmp_neq_i_exec(struct rte_swx_pipeline *p)
7965 struct thread *t = &p->threads[p->thread_id];
7966 struct instruction *ip = t->ip;
7968 TRACE("[Thread %2u] jmpneq (i)\n", p->thread_id);
7970 JMP_CMP_I(t, ip, !=);
7974 instr_jmp_lt_exec(struct rte_swx_pipeline *p)
7976 struct thread *t = &p->threads[p->thread_id];
7977 struct instruction *ip = t->ip;
7979 TRACE("[Thread %2u] jmplt\n", p->thread_id);
7985 instr_jmp_lt_mh_exec(struct rte_swx_pipeline *p)
7987 struct thread *t = &p->threads[p->thread_id];
7988 struct instruction *ip = t->ip;
7990 TRACE("[Thread %2u] jmplt (mh)\n", p->thread_id);
7992 JMP_CMP_MH(t, ip, <);
7996 instr_jmp_lt_hm_exec(struct rte_swx_pipeline *p)
7998 struct thread *t = &p->threads[p->thread_id];
7999 struct instruction *ip = t->ip;
8001 TRACE("[Thread %2u] jmplt (hm)\n", p->thread_id);
8003 JMP_CMP_HM(t, ip, <);
8007 instr_jmp_lt_hh_exec(struct rte_swx_pipeline *p)
8009 struct thread *t = &p->threads[p->thread_id];
8010 struct instruction *ip = t->ip;
8012 TRACE("[Thread %2u] jmplt (hh)\n", p->thread_id);
8014 JMP_CMP_HH(t, ip, <);
8018 instr_jmp_lt_mi_exec(struct rte_swx_pipeline *p)
8020 struct thread *t = &p->threads[p->thread_id];
8021 struct instruction *ip = t->ip;
8023 TRACE("[Thread %2u] jmplt (mi)\n", p->thread_id);
8025 JMP_CMP_MI(t, ip, <);
8029 instr_jmp_lt_hi_exec(struct rte_swx_pipeline *p)
8031 struct thread *t = &p->threads[p->thread_id];
8032 struct instruction *ip = t->ip;
8034 TRACE("[Thread %2u] jmplt (hi)\n", p->thread_id);
8036 JMP_CMP_HI(t, ip, <);
8040 instr_jmp_gt_exec(struct rte_swx_pipeline *p)
8042 struct thread *t = &p->threads[p->thread_id];
8043 struct instruction *ip = t->ip;
8045 TRACE("[Thread %2u] jmpgt\n", p->thread_id);
8051 instr_jmp_gt_mh_exec(struct rte_swx_pipeline *p)
8053 struct thread *t = &p->threads[p->thread_id];
8054 struct instruction *ip = t->ip;
8056 TRACE("[Thread %2u] jmpgt (mh)\n", p->thread_id);
8058 JMP_CMP_MH(t, ip, >);
8062 instr_jmp_gt_hm_exec(struct rte_swx_pipeline *p)
8064 struct thread *t = &p->threads[p->thread_id];
8065 struct instruction *ip = t->ip;
8067 TRACE("[Thread %2u] jmpgt (hm)\n", p->thread_id);
8069 JMP_CMP_HM(t, ip, >);
8073 instr_jmp_gt_hh_exec(struct rte_swx_pipeline *p)
8075 struct thread *t = &p->threads[p->thread_id];
8076 struct instruction *ip = t->ip;
8078 TRACE("[Thread %2u] jmpgt (hh)\n", p->thread_id);
8080 JMP_CMP_HH(t, ip, >);
8084 instr_jmp_gt_mi_exec(struct rte_swx_pipeline *p)
8086 struct thread *t = &p->threads[p->thread_id];
8087 struct instruction *ip = t->ip;
8089 TRACE("[Thread %2u] jmpgt (mi)\n", p->thread_id);
8091 JMP_CMP_MI(t, ip, >);
8095 instr_jmp_gt_hi_exec(struct rte_swx_pipeline *p)
8097 struct thread *t = &p->threads[p->thread_id];
8098 struct instruction *ip = t->ip;
8100 TRACE("[Thread %2u] jmpgt (hi)\n", p->thread_id);
8102 JMP_CMP_HI(t, ip, >);
8109 instr_return_translate(struct rte_swx_pipeline *p __rte_unused,
8110 struct action *action,
8111 char **tokens __rte_unused,
8113 struct instruction *instr,
8114 struct instruction_data *data __rte_unused)
8116 CHECK(action, EINVAL);
8117 CHECK(n_tokens == 1, EINVAL);
8119 instr->type = INSTR_RETURN;
8124 instr_return_exec(struct rte_swx_pipeline *p)
8126 struct thread *t = &p->threads[p->thread_id];
8128 TRACE("[Thread %2u] return\n", p->thread_id);
8134 instr_translate(struct rte_swx_pipeline *p,
8135 struct action *action,
8137 struct instruction *instr,
8138 struct instruction_data *data)
8140 char *tokens[RTE_SWX_INSTRUCTION_TOKENS_MAX];
8141 int n_tokens = 0, tpos = 0;
8143 /* Parse the instruction string into tokens. */
8147 token = strtok_r(string, " \t\v", &string);
8151 CHECK(n_tokens < RTE_SWX_INSTRUCTION_TOKENS_MAX, EINVAL);
8152 CHECK_NAME(token, EINVAL);
8154 tokens[n_tokens] = token;
8158 CHECK(n_tokens, EINVAL);
8160 /* Handle the optional instruction label. */
8161 if ((n_tokens >= 2) && !strcmp(tokens[1], ":")) {
8162 strcpy(data->label, tokens[0]);
8165 CHECK(n_tokens - tpos, EINVAL);
8168 /* Identify the instruction type. */
8169 if (!strcmp(tokens[tpos], "rx"))
8170 return instr_rx_translate(p,
8177 if (!strcmp(tokens[tpos], "tx"))
8178 return instr_tx_translate(p,
8185 if (!strcmp(tokens[tpos], "drop"))
8186 return instr_drop_translate(p,
8193 if (!strcmp(tokens[tpos], "extract"))
8194 return instr_hdr_extract_translate(p,
8201 if (!strcmp(tokens[tpos], "lookahead"))
8202 return instr_hdr_lookahead_translate(p,
8209 if (!strcmp(tokens[tpos], "emit"))
8210 return instr_hdr_emit_translate(p,
8217 if (!strcmp(tokens[tpos], "validate"))
8218 return instr_hdr_validate_translate(p,
8225 if (!strcmp(tokens[tpos], "invalidate"))
8226 return instr_hdr_invalidate_translate(p,
8233 if (!strcmp(tokens[tpos], "mov"))
8234 return instr_mov_translate(p,
8241 if (!strcmp(tokens[tpos], "add"))
8242 return instr_alu_add_translate(p,
8249 if (!strcmp(tokens[tpos], "sub"))
8250 return instr_alu_sub_translate(p,
8257 if (!strcmp(tokens[tpos], "ckadd"))
8258 return instr_alu_ckadd_translate(p,
8265 if (!strcmp(tokens[tpos], "cksub"))
8266 return instr_alu_cksub_translate(p,
8273 if (!strcmp(tokens[tpos], "and"))
8274 return instr_alu_and_translate(p,
8281 if (!strcmp(tokens[tpos], "or"))
8282 return instr_alu_or_translate(p,
8289 if (!strcmp(tokens[tpos], "xor"))
8290 return instr_alu_xor_translate(p,
8297 if (!strcmp(tokens[tpos], "shl"))
8298 return instr_alu_shl_translate(p,
8305 if (!strcmp(tokens[tpos], "shr"))
8306 return instr_alu_shr_translate(p,
8313 if (!strcmp(tokens[tpos], "regprefetch"))
8314 return instr_regprefetch_translate(p,
8321 if (!strcmp(tokens[tpos], "regrd"))
8322 return instr_regrd_translate(p,
8329 if (!strcmp(tokens[tpos], "regwr"))
8330 return instr_regwr_translate(p,
8337 if (!strcmp(tokens[tpos], "regadd"))
8338 return instr_regadd_translate(p,
8345 if (!strcmp(tokens[tpos], "metprefetch"))
8346 return instr_metprefetch_translate(p,
8353 if (!strcmp(tokens[tpos], "meter"))
8354 return instr_meter_translate(p,
8361 if (!strcmp(tokens[tpos], "table"))
8362 return instr_table_translate(p,
8369 if (!strcmp(tokens[tpos], "learn"))
8370 return instr_learn_translate(p,
8377 if (!strcmp(tokens[tpos], "forget"))
8378 return instr_forget_translate(p,
8385 if (!strcmp(tokens[tpos], "extern"))
8386 return instr_extern_translate(p,
8393 if (!strcmp(tokens[tpos], "jmp"))
8394 return instr_jmp_translate(p,
8401 if (!strcmp(tokens[tpos], "jmpv"))
8402 return instr_jmp_valid_translate(p,
8409 if (!strcmp(tokens[tpos], "jmpnv"))
8410 return instr_jmp_invalid_translate(p,
8417 if (!strcmp(tokens[tpos], "jmph"))
8418 return instr_jmp_hit_translate(p,
8425 if (!strcmp(tokens[tpos], "jmpnh"))
8426 return instr_jmp_miss_translate(p,
8433 if (!strcmp(tokens[tpos], "jmpa"))
8434 return instr_jmp_action_hit_translate(p,
8441 if (!strcmp(tokens[tpos], "jmpna"))
8442 return instr_jmp_action_miss_translate(p,
8449 if (!strcmp(tokens[tpos], "jmpeq"))
8450 return instr_jmp_eq_translate(p,
8457 if (!strcmp(tokens[tpos], "jmpneq"))
8458 return instr_jmp_neq_translate(p,
8465 if (!strcmp(tokens[tpos], "jmplt"))
8466 return instr_jmp_lt_translate(p,
8473 if (!strcmp(tokens[tpos], "jmpgt"))
8474 return instr_jmp_gt_translate(p,
8481 if (!strcmp(tokens[tpos], "return"))
8482 return instr_return_translate(p,
8492 static struct instruction_data *
8493 label_find(struct instruction_data *data, uint32_t n, const char *label)
8497 for (i = 0; i < n; i++)
8498 if (!strcmp(label, data[i].label))
8505 label_is_used(struct instruction_data *data, uint32_t n, const char *label)
8507 uint32_t count = 0, i;
8512 for (i = 0; i < n; i++)
8513 if (!strcmp(label, data[i].jmp_label))
8520 instr_label_check(struct instruction_data *instruction_data,
8521 uint32_t n_instructions)
8525 /* Check that all instruction labels are unique. */
8526 for (i = 0; i < n_instructions; i++) {
8527 struct instruction_data *data = &instruction_data[i];
8528 char *label = data->label;
8534 for (j = i + 1; j < n_instructions; j++)
8535 CHECK(strcmp(label, data[j].label), EINVAL);
8538 /* Get users for each instruction label. */
8539 for (i = 0; i < n_instructions; i++) {
8540 struct instruction_data *data = &instruction_data[i];
8541 char *label = data->label;
8543 data->n_users = label_is_used(instruction_data,
8552 instr_jmp_resolve(struct instruction *instructions,
8553 struct instruction_data *instruction_data,
8554 uint32_t n_instructions)
8558 for (i = 0; i < n_instructions; i++) {
8559 struct instruction *instr = &instructions[i];
8560 struct instruction_data *data = &instruction_data[i];
8561 struct instruction_data *found;
8563 if (!instruction_is_jmp(instr))
8566 found = label_find(instruction_data,
8569 CHECK(found, EINVAL);
8571 instr->jmp.ip = &instructions[found - instruction_data];
8578 instr_verify(struct rte_swx_pipeline *p __rte_unused,
8580 struct instruction *instr,
8581 struct instruction_data *data __rte_unused,
8582 uint32_t n_instructions)
8585 enum instruction_type type;
8588 /* Check that the first instruction is rx. */
8589 CHECK(instr[0].type == INSTR_RX, EINVAL);
8591 /* Check that there is at least one tx instruction. */
8592 for (i = 0; i < n_instructions; i++) {
8593 type = instr[i].type;
8595 if (instruction_is_tx(type))
8598 CHECK(i < n_instructions, EINVAL);
8600 /* Check that the last instruction is either tx or unconditional
8603 type = instr[n_instructions - 1].type;
8604 CHECK(instruction_is_tx(type) || (type == INSTR_JMP), EINVAL);
8608 enum instruction_type type;
8611 /* Check that there is at least one return or tx instruction. */
8612 for (i = 0; i < n_instructions; i++) {
8613 type = instr[i].type;
8615 if ((type == INSTR_RETURN) || instruction_is_tx(type))
8618 CHECK(i < n_instructions, EINVAL);
8625 instr_compact(struct instruction *instructions,
8626 struct instruction_data *instruction_data,
8627 uint32_t n_instructions)
8629 uint32_t i, pos = 0;
8631 /* Eliminate the invalid instructions that have been optimized out. */
8632 for (i = 0; i < n_instructions; i++) {
8633 struct instruction *instr = &instructions[i];
8634 struct instruction_data *data = &instruction_data[i];
8640 memcpy(&instructions[pos], instr, sizeof(*instr));
8641 memcpy(&instruction_data[pos], data, sizeof(*data));
8651 instr_pattern_extract_many_search(struct instruction *instr,
8652 struct instruction_data *data,
8654 uint32_t *n_pattern_instr)
8658 for (i = 0; i < n_instr; i++) {
8659 if (data[i].invalid)
8662 if (instr[i].type != INSTR_HDR_EXTRACT)
8665 if (i == RTE_DIM(instr->io.hdr.header_id))
8668 if (i && data[i].n_users)
8675 *n_pattern_instr = i;
8680 instr_pattern_extract_many_replace(struct instruction *instr,
8681 struct instruction_data *data,
8686 for (i = 1; i < n_instr; i++) {
8688 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
8689 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
8690 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
8692 data[i].invalid = 1;
8697 instr_pattern_extract_many_optimize(struct instruction *instructions,
8698 struct instruction_data *instruction_data,
8699 uint32_t n_instructions)
8703 for (i = 0; i < n_instructions; ) {
8704 struct instruction *instr = &instructions[i];
8705 struct instruction_data *data = &instruction_data[i];
8706 uint32_t n_instr = 0;
8710 detected = instr_pattern_extract_many_search(instr,
8715 instr_pattern_extract_many_replace(instr,
8722 /* No pattern starting at the current instruction. */
8726 /* Eliminate the invalid instructions that have been optimized out. */
8727 n_instructions = instr_compact(instructions,
8731 return n_instructions;
8735 instr_pattern_emit_many_tx_search(struct instruction *instr,
8736 struct instruction_data *data,
8738 uint32_t *n_pattern_instr)
8742 for (i = 0; i < n_instr; i++) {
8743 if (data[i].invalid)
8746 if (instr[i].type != INSTR_HDR_EMIT)
8749 if (i == RTE_DIM(instr->io.hdr.header_id))
8752 if (i && data[i].n_users)
8759 if (!instruction_is_tx(instr[i].type))
8762 if (data[i].n_users)
8767 *n_pattern_instr = i;
8772 instr_pattern_emit_many_tx_replace(struct instruction *instr,
8773 struct instruction_data *data,
8778 /* Any emit instruction in addition to the first one. */
8779 for (i = 1; i < n_instr - 1; i++) {
8781 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
8782 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
8783 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
8785 data[i].invalid = 1;
8788 /* The TX instruction is the last one in the pattern. */
8790 instr[0].io.io.offset = instr[i].io.io.offset;
8791 instr[0].io.io.n_bits = instr[i].io.io.n_bits;
8792 data[i].invalid = 1;
8796 instr_pattern_emit_many_tx_optimize(struct instruction *instructions,
8797 struct instruction_data *instruction_data,
8798 uint32_t n_instructions)
8802 for (i = 0; i < n_instructions; ) {
8803 struct instruction *instr = &instructions[i];
8804 struct instruction_data *data = &instruction_data[i];
8805 uint32_t n_instr = 0;
8808 /* Emit many + TX. */
8809 detected = instr_pattern_emit_many_tx_search(instr,
8814 instr_pattern_emit_many_tx_replace(instr,
8821 /* No pattern starting at the current instruction. */
8825 /* Eliminate the invalid instructions that have been optimized out. */
8826 n_instructions = instr_compact(instructions,
8830 return n_instructions;
8834 action_arg_src_mov_count(struct action *a,
8836 struct instruction *instructions,
8837 struct instruction_data *instruction_data,
8838 uint32_t n_instructions);
8841 instr_pattern_mov_all_validate_search(struct rte_swx_pipeline *p,
8843 struct instruction *instr,
8844 struct instruction_data *data,
8846 struct instruction *instructions,
8847 struct instruction_data *instruction_data,
8848 uint32_t n_instructions,
8849 uint32_t *n_pattern_instr)
8852 uint32_t src_field_id, i, j;
8854 /* Prerequisites. */
8858 /* First instruction: MOV_HM. */
8859 if (data[0].invalid || (instr[0].type != INSTR_MOV_HM))
8862 h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
8863 if (!h || h->st->var_size)
8866 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
8867 if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
8870 if (src_field_id == a->st->n_fields)
8873 if (instr[0].mov.dst.offset ||
8874 (instr[0].mov.dst.n_bits != h->st->fields[0].n_bits) ||
8875 instr[0].mov.src.struct_id ||
8876 (instr[0].mov.src.n_bits != a->st->fields[src_field_id].n_bits) ||
8877 (instr[0].mov.dst.n_bits != instr[0].mov.src.n_bits))
8880 if ((n_instr < h->st->n_fields + 1) ||
8881 (a->st->n_fields < src_field_id + h->st->n_fields + 1))
8884 /* Subsequent instructions: MOV_HM. */
8885 for (i = 1; i < h->st->n_fields; i++)
8886 if (data[i].invalid ||
8888 (instr[i].type != INSTR_MOV_HM) ||
8889 (instr[i].mov.dst.struct_id != h->struct_id) ||
8890 (instr[i].mov.dst.offset != h->st->fields[i].offset / 8) ||
8891 (instr[i].mov.dst.n_bits != h->st->fields[i].n_bits) ||
8892 instr[i].mov.src.struct_id ||
8893 (instr[i].mov.src.offset != a->st->fields[src_field_id + i].offset / 8) ||
8894 (instr[i].mov.src.n_bits != a->st->fields[src_field_id + i].n_bits) ||
8895 (instr[i].mov.dst.n_bits != instr[i].mov.src.n_bits))
8898 /* Last instruction: HDR_VALIDATE. */
8899 if ((instr[i].type != INSTR_HDR_VALIDATE) ||
8900 (instr[i].valid.header_id != h->id))
8903 /* Check that none of the action args that are used as source for this
8904 * DMA transfer are not used as source in any other mov instruction.
8906 for (j = src_field_id; j < src_field_id + h->st->n_fields; j++) {
8909 n_users = action_arg_src_mov_count(a,
8918 *n_pattern_instr = 1 + i;
8923 instr_pattern_mov_all_validate_replace(struct rte_swx_pipeline *p,
8925 struct instruction *instr,
8926 struct instruction_data *data,
8930 uint32_t src_field_id, src_offset, i;
8932 /* Read from the instructions before they are modified. */
8933 h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
8937 for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
8938 if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
8941 if (src_field_id == a->st->n_fields)
8944 src_offset = instr[0].mov.src.offset;
8946 /* Modify the instructions. */
8947 instr[0].type = INSTR_DMA_HT;
8948 instr[0].dma.dst.header_id[0] = h->id;
8949 instr[0].dma.dst.struct_id[0] = h->struct_id;
8950 instr[0].dma.src.offset[0] = (uint8_t)src_offset;
8951 instr[0].dma.n_bytes[0] = h->st->n_bits / 8;
8953 for (i = 1; i < n_instr; i++)
8954 data[i].invalid = 1;
8956 /* Update the endianness of the action arguments to header endianness. */
8957 for (i = 0; i < h->st->n_fields; i++)
8958 a->args_endianness[src_field_id + i] = 1;
8962 instr_pattern_mov_all_validate_optimize(struct rte_swx_pipeline *p,
8964 struct instruction *instructions,
8965 struct instruction_data *instruction_data,
8966 uint32_t n_instructions)
8971 return n_instructions;
8973 for (i = 0; i < n_instructions; ) {
8974 struct instruction *instr = &instructions[i];
8975 struct instruction_data *data = &instruction_data[i];
8976 uint32_t n_instr = 0;
8979 /* Mov all + validate. */
8980 detected = instr_pattern_mov_all_validate_search(p,
8990 instr_pattern_mov_all_validate_replace(p, a, instr, data, n_instr);
8995 /* No pattern starting at the current instruction. */
8999 /* Eliminate the invalid instructions that have been optimized out. */
9000 n_instructions = instr_compact(instructions,
9004 return n_instructions;
9008 instr_pattern_dma_many_search(struct instruction *instr,
9009 struct instruction_data *data,
9011 uint32_t *n_pattern_instr)
9015 for (i = 0; i < n_instr; i++) {
9016 if (data[i].invalid)
9019 if (instr[i].type != INSTR_DMA_HT)
9022 if (i == RTE_DIM(instr->dma.dst.header_id))
9025 if (i && data[i].n_users)
9032 *n_pattern_instr = i;
9037 instr_pattern_dma_many_replace(struct instruction *instr,
9038 struct instruction_data *data,
9043 for (i = 1; i < n_instr; i++) {
9045 instr[0].dma.dst.header_id[i] = instr[i].dma.dst.header_id[0];
9046 instr[0].dma.dst.struct_id[i] = instr[i].dma.dst.struct_id[0];
9047 instr[0].dma.src.offset[i] = instr[i].dma.src.offset[0];
9048 instr[0].dma.n_bytes[i] = instr[i].dma.n_bytes[0];
9050 data[i].invalid = 1;
9055 instr_pattern_dma_many_optimize(struct instruction *instructions,
9056 struct instruction_data *instruction_data,
9057 uint32_t n_instructions)
9061 for (i = 0; i < n_instructions; ) {
9062 struct instruction *instr = &instructions[i];
9063 struct instruction_data *data = &instruction_data[i];
9064 uint32_t n_instr = 0;
9068 detected = instr_pattern_dma_many_search(instr,
9073 instr_pattern_dma_many_replace(instr, data, n_instr);
9078 /* No pattern starting at the current instruction. */
9082 /* Eliminate the invalid instructions that have been optimized out. */
9083 n_instructions = instr_compact(instructions,
9087 return n_instructions;
9091 instr_optimize(struct rte_swx_pipeline *p,
9093 struct instruction *instructions,
9094 struct instruction_data *instruction_data,
9095 uint32_t n_instructions)
9098 n_instructions = instr_pattern_extract_many_optimize(instructions,
9102 /* Emit many + TX. */
9103 n_instructions = instr_pattern_emit_many_tx_optimize(instructions,
9107 /* Mov all + validate. */
9108 n_instructions = instr_pattern_mov_all_validate_optimize(p,
9115 n_instructions = instr_pattern_dma_many_optimize(instructions,
9119 return n_instructions;
9123 instruction_config(struct rte_swx_pipeline *p,
9125 const char **instructions,
9126 uint32_t n_instructions)
9128 struct instruction *instr = NULL;
9129 struct instruction_data *data = NULL;
9133 CHECK(n_instructions, EINVAL);
9134 CHECK(instructions, EINVAL);
9135 for (i = 0; i < n_instructions; i++)
9136 CHECK_INSTRUCTION(instructions[i], EINVAL);
9138 /* Memory allocation. */
9139 instr = calloc(n_instructions, sizeof(struct instruction));
9145 data = calloc(n_instructions, sizeof(struct instruction_data));
9151 for (i = 0; i < n_instructions; i++) {
9152 char *string = strdup(instructions[i]);
9158 err = instr_translate(p, a, string, &instr[i], &data[i]);
9167 err = instr_label_check(data, n_instructions);
9171 err = instr_verify(p, a, instr, data, n_instructions);
9175 n_instructions = instr_optimize(p, a, instr, data, n_instructions);
9177 err = instr_jmp_resolve(instr, data, n_instructions);
9182 a->instructions = instr;
9183 a->n_instructions = n_instructions;
9185 p->instructions = instr;
9186 p->n_instructions = n_instructions;
9198 typedef void (*instr_exec_t)(struct rte_swx_pipeline *);
9200 static instr_exec_t instruction_table[] = {
9201 [INSTR_RX] = instr_rx_exec,
9202 [INSTR_TX] = instr_tx_exec,
9203 [INSTR_TX_I] = instr_tx_i_exec,
9205 [INSTR_HDR_EXTRACT] = instr_hdr_extract_exec,
9206 [INSTR_HDR_EXTRACT2] = instr_hdr_extract2_exec,
9207 [INSTR_HDR_EXTRACT3] = instr_hdr_extract3_exec,
9208 [INSTR_HDR_EXTRACT4] = instr_hdr_extract4_exec,
9209 [INSTR_HDR_EXTRACT5] = instr_hdr_extract5_exec,
9210 [INSTR_HDR_EXTRACT6] = instr_hdr_extract6_exec,
9211 [INSTR_HDR_EXTRACT7] = instr_hdr_extract7_exec,
9212 [INSTR_HDR_EXTRACT8] = instr_hdr_extract8_exec,
9213 [INSTR_HDR_EXTRACT_M] = instr_hdr_extract_m_exec,
9214 [INSTR_HDR_LOOKAHEAD] = instr_hdr_lookahead_exec,
9216 [INSTR_HDR_EMIT] = instr_hdr_emit_exec,
9217 [INSTR_HDR_EMIT_TX] = instr_hdr_emit_tx_exec,
9218 [INSTR_HDR_EMIT2_TX] = instr_hdr_emit2_tx_exec,
9219 [INSTR_HDR_EMIT3_TX] = instr_hdr_emit3_tx_exec,
9220 [INSTR_HDR_EMIT4_TX] = instr_hdr_emit4_tx_exec,
9221 [INSTR_HDR_EMIT5_TX] = instr_hdr_emit5_tx_exec,
9222 [INSTR_HDR_EMIT6_TX] = instr_hdr_emit6_tx_exec,
9223 [INSTR_HDR_EMIT7_TX] = instr_hdr_emit7_tx_exec,
9224 [INSTR_HDR_EMIT8_TX] = instr_hdr_emit8_tx_exec,
9226 [INSTR_HDR_VALIDATE] = instr_hdr_validate_exec,
9227 [INSTR_HDR_INVALIDATE] = instr_hdr_invalidate_exec,
9229 [INSTR_MOV] = instr_mov_exec,
9230 [INSTR_MOV_MH] = instr_mov_mh_exec,
9231 [INSTR_MOV_HM] = instr_mov_hm_exec,
9232 [INSTR_MOV_HH] = instr_mov_hh_exec,
9233 [INSTR_MOV_I] = instr_mov_i_exec,
9235 [INSTR_DMA_HT] = instr_dma_ht_exec,
9236 [INSTR_DMA_HT2] = instr_dma_ht2_exec,
9237 [INSTR_DMA_HT3] = instr_dma_ht3_exec,
9238 [INSTR_DMA_HT4] = instr_dma_ht4_exec,
9239 [INSTR_DMA_HT5] = instr_dma_ht5_exec,
9240 [INSTR_DMA_HT6] = instr_dma_ht6_exec,
9241 [INSTR_DMA_HT7] = instr_dma_ht7_exec,
9242 [INSTR_DMA_HT8] = instr_dma_ht8_exec,
9244 [INSTR_ALU_ADD] = instr_alu_add_exec,
9245 [INSTR_ALU_ADD_MH] = instr_alu_add_mh_exec,
9246 [INSTR_ALU_ADD_HM] = instr_alu_add_hm_exec,
9247 [INSTR_ALU_ADD_HH] = instr_alu_add_hh_exec,
9248 [INSTR_ALU_ADD_MI] = instr_alu_add_mi_exec,
9249 [INSTR_ALU_ADD_HI] = instr_alu_add_hi_exec,
9251 [INSTR_ALU_SUB] = instr_alu_sub_exec,
9252 [INSTR_ALU_SUB_MH] = instr_alu_sub_mh_exec,
9253 [INSTR_ALU_SUB_HM] = instr_alu_sub_hm_exec,
9254 [INSTR_ALU_SUB_HH] = instr_alu_sub_hh_exec,
9255 [INSTR_ALU_SUB_MI] = instr_alu_sub_mi_exec,
9256 [INSTR_ALU_SUB_HI] = instr_alu_sub_hi_exec,
9258 [INSTR_ALU_CKADD_FIELD] = instr_alu_ckadd_field_exec,
9259 [INSTR_ALU_CKADD_STRUCT] = instr_alu_ckadd_struct_exec,
9260 [INSTR_ALU_CKADD_STRUCT20] = instr_alu_ckadd_struct20_exec,
9261 [INSTR_ALU_CKSUB_FIELD] = instr_alu_cksub_field_exec,
9263 [INSTR_ALU_AND] = instr_alu_and_exec,
9264 [INSTR_ALU_AND_MH] = instr_alu_and_mh_exec,
9265 [INSTR_ALU_AND_HM] = instr_alu_and_hm_exec,
9266 [INSTR_ALU_AND_HH] = instr_alu_and_hh_exec,
9267 [INSTR_ALU_AND_I] = instr_alu_and_i_exec,
9269 [INSTR_ALU_OR] = instr_alu_or_exec,
9270 [INSTR_ALU_OR_MH] = instr_alu_or_mh_exec,
9271 [INSTR_ALU_OR_HM] = instr_alu_or_hm_exec,
9272 [INSTR_ALU_OR_HH] = instr_alu_or_hh_exec,
9273 [INSTR_ALU_OR_I] = instr_alu_or_i_exec,
9275 [INSTR_ALU_XOR] = instr_alu_xor_exec,
9276 [INSTR_ALU_XOR_MH] = instr_alu_xor_mh_exec,
9277 [INSTR_ALU_XOR_HM] = instr_alu_xor_hm_exec,
9278 [INSTR_ALU_XOR_HH] = instr_alu_xor_hh_exec,
9279 [INSTR_ALU_XOR_I] = instr_alu_xor_i_exec,
9281 [INSTR_ALU_SHL] = instr_alu_shl_exec,
9282 [INSTR_ALU_SHL_MH] = instr_alu_shl_mh_exec,
9283 [INSTR_ALU_SHL_HM] = instr_alu_shl_hm_exec,
9284 [INSTR_ALU_SHL_HH] = instr_alu_shl_hh_exec,
9285 [INSTR_ALU_SHL_MI] = instr_alu_shl_mi_exec,
9286 [INSTR_ALU_SHL_HI] = instr_alu_shl_hi_exec,
9288 [INSTR_ALU_SHR] = instr_alu_shr_exec,
9289 [INSTR_ALU_SHR_MH] = instr_alu_shr_mh_exec,
9290 [INSTR_ALU_SHR_HM] = instr_alu_shr_hm_exec,
9291 [INSTR_ALU_SHR_HH] = instr_alu_shr_hh_exec,
9292 [INSTR_ALU_SHR_MI] = instr_alu_shr_mi_exec,
9293 [INSTR_ALU_SHR_HI] = instr_alu_shr_hi_exec,
9295 [INSTR_REGPREFETCH_RH] = instr_regprefetch_rh_exec,
9296 [INSTR_REGPREFETCH_RM] = instr_regprefetch_rm_exec,
9297 [INSTR_REGPREFETCH_RI] = instr_regprefetch_ri_exec,
9299 [INSTR_REGRD_HRH] = instr_regrd_hrh_exec,
9300 [INSTR_REGRD_HRM] = instr_regrd_hrm_exec,
9301 [INSTR_REGRD_MRH] = instr_regrd_mrh_exec,
9302 [INSTR_REGRD_MRM] = instr_regrd_mrm_exec,
9303 [INSTR_REGRD_HRI] = instr_regrd_hri_exec,
9304 [INSTR_REGRD_MRI] = instr_regrd_mri_exec,
9306 [INSTR_REGWR_RHH] = instr_regwr_rhh_exec,
9307 [INSTR_REGWR_RHM] = instr_regwr_rhm_exec,
9308 [INSTR_REGWR_RMH] = instr_regwr_rmh_exec,
9309 [INSTR_REGWR_RMM] = instr_regwr_rmm_exec,
9310 [INSTR_REGWR_RHI] = instr_regwr_rhi_exec,
9311 [INSTR_REGWR_RMI] = instr_regwr_rmi_exec,
9312 [INSTR_REGWR_RIH] = instr_regwr_rih_exec,
9313 [INSTR_REGWR_RIM] = instr_regwr_rim_exec,
9314 [INSTR_REGWR_RII] = instr_regwr_rii_exec,
9316 [INSTR_REGADD_RHH] = instr_regadd_rhh_exec,
9317 [INSTR_REGADD_RHM] = instr_regadd_rhm_exec,
9318 [INSTR_REGADD_RMH] = instr_regadd_rmh_exec,
9319 [INSTR_REGADD_RMM] = instr_regadd_rmm_exec,
9320 [INSTR_REGADD_RHI] = instr_regadd_rhi_exec,
9321 [INSTR_REGADD_RMI] = instr_regadd_rmi_exec,
9322 [INSTR_REGADD_RIH] = instr_regadd_rih_exec,
9323 [INSTR_REGADD_RIM] = instr_regadd_rim_exec,
9324 [INSTR_REGADD_RII] = instr_regadd_rii_exec,
9326 [INSTR_METPREFETCH_H] = instr_metprefetch_h_exec,
9327 [INSTR_METPREFETCH_M] = instr_metprefetch_m_exec,
9328 [INSTR_METPREFETCH_I] = instr_metprefetch_i_exec,
9330 [INSTR_METER_HHM] = instr_meter_hhm_exec,
9331 [INSTR_METER_HHI] = instr_meter_hhi_exec,
9332 [INSTR_METER_HMM] = instr_meter_hmm_exec,
9333 [INSTR_METER_HMI] = instr_meter_hmi_exec,
9334 [INSTR_METER_MHM] = instr_meter_mhm_exec,
9335 [INSTR_METER_MHI] = instr_meter_mhi_exec,
9336 [INSTR_METER_MMM] = instr_meter_mmm_exec,
9337 [INSTR_METER_MMI] = instr_meter_mmi_exec,
9338 [INSTR_METER_IHM] = instr_meter_ihm_exec,
9339 [INSTR_METER_IHI] = instr_meter_ihi_exec,
9340 [INSTR_METER_IMM] = instr_meter_imm_exec,
9341 [INSTR_METER_IMI] = instr_meter_imi_exec,
9343 [INSTR_TABLE] = instr_table_exec,
9344 [INSTR_SELECTOR] = instr_selector_exec,
9345 [INSTR_LEARNER] = instr_learner_exec,
9346 [INSTR_LEARNER_LEARN] = instr_learn_exec,
9347 [INSTR_LEARNER_FORGET] = instr_forget_exec,
9348 [INSTR_EXTERN_OBJ] = instr_extern_obj_exec,
9349 [INSTR_EXTERN_FUNC] = instr_extern_func_exec,
9351 [INSTR_JMP] = instr_jmp_exec,
9352 [INSTR_JMP_VALID] = instr_jmp_valid_exec,
9353 [INSTR_JMP_INVALID] = instr_jmp_invalid_exec,
9354 [INSTR_JMP_HIT] = instr_jmp_hit_exec,
9355 [INSTR_JMP_MISS] = instr_jmp_miss_exec,
9356 [INSTR_JMP_ACTION_HIT] = instr_jmp_action_hit_exec,
9357 [INSTR_JMP_ACTION_MISS] = instr_jmp_action_miss_exec,
9359 [INSTR_JMP_EQ] = instr_jmp_eq_exec,
9360 [INSTR_JMP_EQ_MH] = instr_jmp_eq_mh_exec,
9361 [INSTR_JMP_EQ_HM] = instr_jmp_eq_hm_exec,
9362 [INSTR_JMP_EQ_HH] = instr_jmp_eq_hh_exec,
9363 [INSTR_JMP_EQ_I] = instr_jmp_eq_i_exec,
9365 [INSTR_JMP_NEQ] = instr_jmp_neq_exec,
9366 [INSTR_JMP_NEQ_MH] = instr_jmp_neq_mh_exec,
9367 [INSTR_JMP_NEQ_HM] = instr_jmp_neq_hm_exec,
9368 [INSTR_JMP_NEQ_HH] = instr_jmp_neq_hh_exec,
9369 [INSTR_JMP_NEQ_I] = instr_jmp_neq_i_exec,
9371 [INSTR_JMP_LT] = instr_jmp_lt_exec,
9372 [INSTR_JMP_LT_MH] = instr_jmp_lt_mh_exec,
9373 [INSTR_JMP_LT_HM] = instr_jmp_lt_hm_exec,
9374 [INSTR_JMP_LT_HH] = instr_jmp_lt_hh_exec,
9375 [INSTR_JMP_LT_MI] = instr_jmp_lt_mi_exec,
9376 [INSTR_JMP_LT_HI] = instr_jmp_lt_hi_exec,
9378 [INSTR_JMP_GT] = instr_jmp_gt_exec,
9379 [INSTR_JMP_GT_MH] = instr_jmp_gt_mh_exec,
9380 [INSTR_JMP_GT_HM] = instr_jmp_gt_hm_exec,
9381 [INSTR_JMP_GT_HH] = instr_jmp_gt_hh_exec,
9382 [INSTR_JMP_GT_MI] = instr_jmp_gt_mi_exec,
9383 [INSTR_JMP_GT_HI] = instr_jmp_gt_hi_exec,
9385 [INSTR_RETURN] = instr_return_exec,
9389 instr_exec(struct rte_swx_pipeline *p)
9391 struct thread *t = &p->threads[p->thread_id];
9392 struct instruction *ip = t->ip;
9393 instr_exec_t instr = instruction_table[ip->type];
9401 static struct action *
9402 action_find(struct rte_swx_pipeline *p, const char *name)
9404 struct action *elem;
9409 TAILQ_FOREACH(elem, &p->actions, node)
9410 if (strcmp(elem->name, name) == 0)
9416 static struct action *
9417 action_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9419 struct action *action = NULL;
9421 TAILQ_FOREACH(action, &p->actions, node)
9422 if (action->id == id)
9428 static struct field *
9429 action_field_find(struct action *a, const char *name)
9431 return a->st ? struct_type_field_find(a->st, name) : NULL;
9434 static struct field *
9435 action_field_parse(struct action *action, const char *name)
9437 if (name[0] != 't' || name[1] != '.')
9440 return action_field_find(action, &name[2]);
9444 action_has_nbo_args(struct action *a)
9448 /* Return if the action does not have any args. */
9450 return 0; /* FALSE */
9452 for (i = 0; i < a->st->n_fields; i++)
9453 if (a->args_endianness[i])
9454 return 1; /* TRUE */
9456 return 0; /* FALSE */
9460 action_does_learning(struct action *a)
9464 for (i = 0; i < a->n_instructions; i++)
9465 switch (a->instructions[i].type) {
9466 case INSTR_LEARNER_LEARN:
9467 return 1; /* TRUE */
9469 case INSTR_LEARNER_FORGET:
9470 return 1; /* TRUE */
9476 return 0; /* FALSE */
9480 rte_swx_pipeline_action_config(struct rte_swx_pipeline *p,
9482 const char *args_struct_type_name,
9483 const char **instructions,
9484 uint32_t n_instructions)
9486 struct struct_type *args_struct_type = NULL;
9492 CHECK_NAME(name, EINVAL);
9493 CHECK(!action_find(p, name), EEXIST);
9495 if (args_struct_type_name) {
9496 CHECK_NAME(args_struct_type_name, EINVAL);
9497 args_struct_type = struct_type_find(p, args_struct_type_name);
9498 CHECK(args_struct_type, EINVAL);
9499 CHECK(!args_struct_type->var_size, EINVAL);
9502 /* Node allocation. */
9503 a = calloc(1, sizeof(struct action));
9505 if (args_struct_type) {
9506 a->args_endianness = calloc(args_struct_type->n_fields, sizeof(int));
9507 if (!a->args_endianness) {
9513 /* Node initialization. */
9514 strcpy(a->name, name);
9515 a->st = args_struct_type;
9516 a->id = p->n_actions;
9518 /* Instruction translation. */
9519 err = instruction_config(p, a, instructions, n_instructions);
9521 free(a->args_endianness);
9526 /* Node add to tailq. */
9527 TAILQ_INSERT_TAIL(&p->actions, a, node);
9534 action_build(struct rte_swx_pipeline *p)
9536 struct action *action;
9538 p->action_instructions = calloc(p->n_actions,
9539 sizeof(struct instruction *));
9540 CHECK(p->action_instructions, ENOMEM);
9542 TAILQ_FOREACH(action, &p->actions, node)
9543 p->action_instructions[action->id] = action->instructions;
9549 action_build_free(struct rte_swx_pipeline *p)
9551 free(p->action_instructions);
9552 p->action_instructions = NULL;
9556 action_free(struct rte_swx_pipeline *p)
9558 action_build_free(p);
9561 struct action *action;
9563 action = TAILQ_FIRST(&p->actions);
9567 TAILQ_REMOVE(&p->actions, action, node);
9568 free(action->instructions);
9574 action_arg_src_mov_count(struct action *a,
9576 struct instruction *instructions,
9577 struct instruction_data *instruction_data,
9578 uint32_t n_instructions)
9580 uint32_t offset, n_users = 0, i;
9583 (arg_id >= a->st->n_fields) ||
9585 !instruction_data ||
9589 offset = a->st->fields[arg_id].offset / 8;
9591 for (i = 0; i < n_instructions; i++) {
9592 struct instruction *instr = &instructions[i];
9593 struct instruction_data *data = &instruction_data[i];
9595 if (data->invalid ||
9596 ((instr->type != INSTR_MOV) && (instr->type != INSTR_MOV_HM)) ||
9597 instr->mov.src.struct_id ||
9598 (instr->mov.src.offset != offset))
9610 static struct table_type *
9611 table_type_find(struct rte_swx_pipeline *p, const char *name)
9613 struct table_type *elem;
9615 TAILQ_FOREACH(elem, &p->table_types, node)
9616 if (strcmp(elem->name, name) == 0)
9622 static struct table_type *
9623 table_type_resolve(struct rte_swx_pipeline *p,
9624 const char *recommended_type_name,
9625 enum rte_swx_table_match_type match_type)
9627 struct table_type *elem;
9629 /* Only consider the recommended type if the match type is correct. */
9630 if (recommended_type_name)
9631 TAILQ_FOREACH(elem, &p->table_types, node)
9632 if (!strcmp(elem->name, recommended_type_name) &&
9633 (elem->match_type == match_type))
9636 /* Ignore the recommended type and get the first element with this match
9639 TAILQ_FOREACH(elem, &p->table_types, node)
9640 if (elem->match_type == match_type)
9646 static struct table *
9647 table_find(struct rte_swx_pipeline *p, const char *name)
9651 TAILQ_FOREACH(elem, &p->tables, node)
9652 if (strcmp(elem->name, name) == 0)
9658 static struct table *
9659 table_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9661 struct table *table = NULL;
9663 TAILQ_FOREACH(table, &p->tables, node)
9664 if (table->id == id)
9671 rte_swx_pipeline_table_type_register(struct rte_swx_pipeline *p,
9673 enum rte_swx_table_match_type match_type,
9674 struct rte_swx_table_ops *ops)
9676 struct table_type *elem;
9680 CHECK_NAME(name, EINVAL);
9681 CHECK(!table_type_find(p, name), EEXIST);
9684 CHECK(ops->create, EINVAL);
9685 CHECK(ops->lkp, EINVAL);
9686 CHECK(ops->free, EINVAL);
9688 /* Node allocation. */
9689 elem = calloc(1, sizeof(struct table_type));
9690 CHECK(elem, ENOMEM);
9692 /* Node initialization. */
9693 strcpy(elem->name, name);
9694 elem->match_type = match_type;
9695 memcpy(&elem->ops, ops, sizeof(*ops));
9697 /* Node add to tailq. */
9698 TAILQ_INSERT_TAIL(&p->table_types, elem, node);
9704 table_match_type_resolve(struct rte_swx_match_field_params *fields,
9706 enum rte_swx_table_match_type *match_type)
9708 uint32_t n_fields_em = 0, n_fields_lpm = 0, i;
9710 for (i = 0; i < n_fields; i++) {
9711 struct rte_swx_match_field_params *f = &fields[i];
9713 if (f->match_type == RTE_SWX_TABLE_MATCH_EXACT)
9716 if (f->match_type == RTE_SWX_TABLE_MATCH_LPM)
9720 if ((n_fields_lpm > 1) ||
9721 (n_fields_lpm && (n_fields_em != n_fields - 1)))
9724 *match_type = (n_fields_em == n_fields) ?
9725 RTE_SWX_TABLE_MATCH_EXACT :
9726 RTE_SWX_TABLE_MATCH_WILDCARD;
9732 table_match_fields_check(struct rte_swx_pipeline *p,
9733 struct rte_swx_pipeline_table_params *params,
9734 struct header **header)
9736 struct header *h0 = NULL;
9737 struct field *hf, *mf;
9738 uint32_t *offset = NULL, i;
9741 /* Return if no match fields. */
9742 if (!params->n_fields) {
9743 if (params->fields) {
9754 /* Memory allocation. */
9755 offset = calloc(params->n_fields, sizeof(uint32_t));
9761 /* Check that all the match fields belong to either the same header or
9764 hf = header_field_parse(p, params->fields[0].name, &h0);
9765 mf = metadata_field_parse(p, params->fields[0].name);
9766 if ((!hf && !mf) || (hf && hf->var_size)) {
9771 offset[0] = h0 ? hf->offset : mf->offset;
9773 for (i = 1; i < params->n_fields; i++)
9777 hf = header_field_parse(p, params->fields[i].name, &h);
9778 if (!hf || (h->id != h0->id) || hf->var_size) {
9783 offset[i] = hf->offset;
9785 mf = metadata_field_parse(p, params->fields[i].name);
9791 offset[i] = mf->offset;
9794 /* Check that there are no duplicated match fields. */
9795 for (i = 0; i < params->n_fields; i++) {
9798 for (j = 0; j < i; j++)
9799 if (offset[j] == offset[i]) {
9815 rte_swx_pipeline_table_config(struct rte_swx_pipeline *p,
9817 struct rte_swx_pipeline_table_params *params,
9818 const char *recommended_table_type_name,
9822 struct table_type *type;
9824 struct action *default_action;
9825 struct header *header = NULL;
9826 uint32_t action_data_size_max = 0, i;
9831 CHECK_NAME(name, EINVAL);
9832 CHECK(!table_find(p, name), EEXIST);
9833 CHECK(!selector_find(p, name), EEXIST);
9834 CHECK(!learner_find(p, name), EEXIST);
9836 CHECK(params, EINVAL);
9839 status = table_match_fields_check(p, params, &header);
9843 /* Action checks. */
9844 CHECK(params->n_actions, EINVAL);
9845 CHECK(params->action_names, EINVAL);
9846 for (i = 0; i < params->n_actions; i++) {
9847 const char *action_name = params->action_names[i];
9849 uint32_t action_data_size;
9851 CHECK_NAME(action_name, EINVAL);
9853 a = action_find(p, action_name);
9855 CHECK(!action_does_learning(a), EINVAL);
9857 action_data_size = a->st ? a->st->n_bits / 8 : 0;
9858 if (action_data_size > action_data_size_max)
9859 action_data_size_max = action_data_size;
9862 CHECK_NAME(params->default_action_name, EINVAL);
9863 for (i = 0; i < p->n_actions; i++)
9864 if (!strcmp(params->action_names[i],
9865 params->default_action_name))
9867 CHECK(i < params->n_actions, EINVAL);
9868 default_action = action_find(p, params->default_action_name);
9869 CHECK((default_action->st && params->default_action_data) ||
9870 !params->default_action_data, EINVAL);
9872 /* Table type checks. */
9873 if (recommended_table_type_name)
9874 CHECK_NAME(recommended_table_type_name, EINVAL);
9876 if (params->n_fields) {
9877 enum rte_swx_table_match_type match_type;
9879 status = table_match_type_resolve(params->fields, params->n_fields, &match_type);
9883 type = table_type_resolve(p, recommended_table_type_name, match_type);
9884 CHECK(type, EINVAL);
9889 /* Memory allocation. */
9890 t = calloc(1, sizeof(struct table));
9893 t->fields = calloc(params->n_fields, sizeof(struct match_field));
9899 t->actions = calloc(params->n_actions, sizeof(struct action *));
9906 if (action_data_size_max) {
9907 t->default_action_data = calloc(1, action_data_size_max);
9908 if (!t->default_action_data) {
9916 /* Node initialization. */
9917 strcpy(t->name, name);
9918 if (args && args[0])
9919 strcpy(t->args, args);
9922 for (i = 0; i < params->n_fields; i++) {
9923 struct rte_swx_match_field_params *field = ¶ms->fields[i];
9924 struct match_field *f = &t->fields[i];
9926 f->match_type = field->match_type;
9928 header_field_parse(p, field->name, NULL) :
9929 metadata_field_parse(p, field->name);
9931 t->n_fields = params->n_fields;
9934 for (i = 0; i < params->n_actions; i++)
9935 t->actions[i] = action_find(p, params->action_names[i]);
9936 t->default_action = default_action;
9937 if (default_action->st)
9938 memcpy(t->default_action_data,
9939 params->default_action_data,
9940 default_action->st->n_bits / 8);
9941 t->n_actions = params->n_actions;
9942 t->default_action_is_const = params->default_action_is_const;
9943 t->action_data_size_max = action_data_size_max;
9946 t->id = p->n_tables;
9948 /* Node add to tailq. */
9949 TAILQ_INSERT_TAIL(&p->tables, t, node);
9955 static struct rte_swx_table_params *
9956 table_params_get(struct table *table)
9958 struct rte_swx_table_params *params;
9959 struct field *first, *last;
9961 uint32_t key_size, key_offset, action_data_size, i;
9963 /* Memory allocation. */
9964 params = calloc(1, sizeof(struct rte_swx_table_params));
9968 /* Find first (smallest offset) and last (biggest offset) match fields. */
9969 first = table->fields[0].field;
9970 last = table->fields[0].field;
9972 for (i = 0; i < table->n_fields; i++) {
9973 struct field *f = table->fields[i].field;
9975 if (f->offset < first->offset)
9978 if (f->offset > last->offset)
9982 /* Key offset and size. */
9983 key_offset = first->offset / 8;
9984 key_size = (last->offset + last->n_bits - first->offset) / 8;
9986 /* Memory allocation. */
9987 key_mask = calloc(1, key_size);
9994 for (i = 0; i < table->n_fields; i++) {
9995 struct field *f = table->fields[i].field;
9996 uint32_t start = (f->offset - first->offset) / 8;
9997 size_t size = f->n_bits / 8;
9999 memset(&key_mask[start], 0xFF, size);
10002 /* Action data size. */
10003 action_data_size = 0;
10004 for (i = 0; i < table->n_actions; i++) {
10005 struct action *action = table->actions[i];
10006 uint32_t ads = action->st ? action->st->n_bits / 8 : 0;
10008 if (ads > action_data_size)
10009 action_data_size = ads;
10013 params->match_type = table->type->match_type;
10014 params->key_size = key_size;
10015 params->key_offset = key_offset;
10016 params->key_mask0 = key_mask;
10017 params->action_data_size = action_data_size;
10018 params->n_keys_max = table->size;
10024 table_params_free(struct rte_swx_table_params *params)
10029 free(params->key_mask0);
10034 table_stub_lkp(void *table __rte_unused,
10035 void *mailbox __rte_unused,
10036 uint8_t **key __rte_unused,
10037 uint64_t *action_id __rte_unused,
10038 uint8_t **action_data __rte_unused,
10042 return 1; /* DONE. */
10046 table_build(struct rte_swx_pipeline *p)
10050 /* Per pipeline: table statistics. */
10051 p->table_stats = calloc(p->n_tables, sizeof(struct table_statistics));
10052 CHECK(p->table_stats, ENOMEM);
10054 for (i = 0; i < p->n_tables; i++) {
10055 p->table_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
10056 CHECK(p->table_stats[i].n_pkts_action, ENOMEM);
10059 /* Per thread: table runt-time. */
10060 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
10061 struct thread *t = &p->threads[i];
10062 struct table *table;
10064 t->tables = calloc(p->n_tables, sizeof(struct table_runtime));
10065 CHECK(t->tables, ENOMEM);
10067 TAILQ_FOREACH(table, &p->tables, node) {
10068 struct table_runtime *r = &t->tables[table->id];
10073 size = table->type->ops.mailbox_size_get();
10076 r->func = table->type->ops.lkp;
10080 r->mailbox = calloc(1, size);
10081 CHECK(r->mailbox, ENOMEM);
10085 r->key = table->header ?
10086 &t->structs[table->header->struct_id] :
10087 &t->structs[p->metadata_struct_id];
10089 r->func = table_stub_lkp;
10098 table_build_free(struct rte_swx_pipeline *p)
10102 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
10103 struct thread *t = &p->threads[i];
10109 for (j = 0; j < p->n_tables; j++) {
10110 struct table_runtime *r = &t->tables[j];
10119 if (p->table_stats) {
10120 for (i = 0; i < p->n_tables; i++)
10121 free(p->table_stats[i].n_pkts_action);
10123 free(p->table_stats);
10128 table_free(struct rte_swx_pipeline *p)
10130 table_build_free(p);
10134 struct table *elem;
10136 elem = TAILQ_FIRST(&p->tables);
10140 TAILQ_REMOVE(&p->tables, elem, node);
10141 free(elem->fields);
10142 free(elem->actions);
10143 free(elem->default_action_data);
10149 struct table_type *elem;
10151 elem = TAILQ_FIRST(&p->table_types);
10155 TAILQ_REMOVE(&p->table_types, elem, node);
10163 static struct selector *
10164 selector_find(struct rte_swx_pipeline *p, const char *name)
10166 struct selector *s;
10168 TAILQ_FOREACH(s, &p->selectors, node)
10169 if (strcmp(s->name, name) == 0)
10175 static struct selector *
10176 selector_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
10178 struct selector *s = NULL;
10180 TAILQ_FOREACH(s, &p->selectors, node)
10188 selector_fields_check(struct rte_swx_pipeline *p,
10189 struct rte_swx_pipeline_selector_params *params,
10190 struct header **header)
10192 struct header *h0 = NULL;
10193 struct field *hf, *mf;
10196 /* Return if no selector fields. */
10197 if (!params->n_selector_fields || !params->selector_field_names)
10200 /* Check that all the selector fields either belong to the same header
10201 * or are all meta-data fields.
10203 hf = header_field_parse(p, params->selector_field_names[0], &h0);
10204 mf = metadata_field_parse(p, params->selector_field_names[0]);
10208 for (i = 1; i < params->n_selector_fields; i++)
10212 hf = header_field_parse(p, params->selector_field_names[i], &h);
10213 if (!hf || (h->id != h0->id))
10216 mf = metadata_field_parse(p, params->selector_field_names[i]);
10221 /* Check that there are no duplicated match fields. */
10222 for (i = 0; i < params->n_selector_fields; i++) {
10223 const char *field_name = params->selector_field_names[i];
10226 for (j = i + 1; j < params->n_selector_fields; j++)
10227 if (!strcmp(params->selector_field_names[j], field_name))
10239 rte_swx_pipeline_selector_config(struct rte_swx_pipeline *p,
10241 struct rte_swx_pipeline_selector_params *params)
10243 struct selector *s;
10244 struct header *selector_header = NULL;
10245 struct field *group_id_field, *member_id_field;
10251 CHECK_NAME(name, EINVAL);
10252 CHECK(!table_find(p, name), EEXIST);
10253 CHECK(!selector_find(p, name), EEXIST);
10254 CHECK(!learner_find(p, name), EEXIST);
10256 CHECK(params, EINVAL);
10258 CHECK_NAME(params->group_id_field_name, EINVAL);
10259 group_id_field = metadata_field_parse(p, params->group_id_field_name);
10260 CHECK(group_id_field, EINVAL);
10262 for (i = 0; i < params->n_selector_fields; i++) {
10263 const char *field_name = params->selector_field_names[i];
10265 CHECK_NAME(field_name, EINVAL);
10267 status = selector_fields_check(p, params, &selector_header);
10271 CHECK_NAME(params->member_id_field_name, EINVAL);
10272 member_id_field = metadata_field_parse(p, params->member_id_field_name);
10273 CHECK(member_id_field, EINVAL);
10275 CHECK(params->n_groups_max, EINVAL);
10277 CHECK(params->n_members_per_group_max, EINVAL);
10279 /* Memory allocation. */
10280 s = calloc(1, sizeof(struct selector));
10286 s->selector_fields = calloc(params->n_selector_fields, sizeof(struct field *));
10287 if (!s->selector_fields) {
10292 /* Node initialization. */
10293 strcpy(s->name, name);
10295 s->group_id_field = group_id_field;
10297 for (i = 0; i < params->n_selector_fields; i++) {
10298 const char *field_name = params->selector_field_names[i];
10300 s->selector_fields[i] = selector_header ?
10301 header_field_parse(p, field_name, NULL) :
10302 metadata_field_parse(p, field_name);
10305 s->n_selector_fields = params->n_selector_fields;
10307 s->selector_header = selector_header;
10309 s->member_id_field = member_id_field;
10311 s->n_groups_max = params->n_groups_max;
10313 s->n_members_per_group_max = params->n_members_per_group_max;
10315 s->id = p->n_selectors;
10317 /* Node add to tailq. */
10318 TAILQ_INSERT_TAIL(&p->selectors, s, node);
10327 free(s->selector_fields);
10335 selector_params_free(struct rte_swx_table_selector_params *params)
10340 free(params->selector_mask);
10345 static struct rte_swx_table_selector_params *
10346 selector_table_params_get(struct selector *s)
10348 struct rte_swx_table_selector_params *params = NULL;
10349 struct field *first, *last;
10352 /* Memory allocation. */
10353 params = calloc(1, sizeof(struct rte_swx_table_selector_params));
10358 params->group_id_offset = s->group_id_field->offset / 8;
10360 /* Find first (smallest offset) and last (biggest offset) selector fields. */
10361 first = s->selector_fields[0];
10362 last = s->selector_fields[0];
10364 for (i = 0; i < s->n_selector_fields; i++) {
10365 struct field *f = s->selector_fields[i];
10367 if (f->offset < first->offset)
10370 if (f->offset > last->offset)
10374 /* Selector offset and size. */
10375 params->selector_offset = first->offset / 8;
10376 params->selector_size = (last->offset + last->n_bits - first->offset) / 8;
10378 /* Memory allocation. */
10379 params->selector_mask = calloc(1, params->selector_size);
10380 if (!params->selector_mask)
10383 /* Selector mask. */
10384 for (i = 0; i < s->n_selector_fields; i++) {
10385 struct field *f = s->selector_fields[i];
10386 uint32_t start = (f->offset - first->offset) / 8;
10387 size_t size = f->n_bits / 8;
10389 memset(¶ms->selector_mask[start], 0xFF, size);
10393 params->member_id_offset = s->member_id_field->offset / 8;
10395 /* Maximum number of groups. */
10396 params->n_groups_max = s->n_groups_max;
10398 /* Maximum number of members per group. */
10399 params->n_members_per_group_max = s->n_members_per_group_max;
10404 selector_params_free(params);
10409 selector_build_free(struct rte_swx_pipeline *p)
10413 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
10414 struct thread *t = &p->threads[i];
10420 for (j = 0; j < p->n_selectors; j++) {
10421 struct selector_runtime *r = &t->selectors[j];
10426 free(t->selectors);
10427 t->selectors = NULL;
10430 free(p->selector_stats);
10431 p->selector_stats = NULL;
10435 selector_build(struct rte_swx_pipeline *p)
10440 /* Per pipeline: selector statistics. */
10441 p->selector_stats = calloc(p->n_selectors, sizeof(struct selector_statistics));
10442 if (!p->selector_stats) {
10447 /* Per thread: selector run-time. */
10448 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
10449 struct thread *t = &p->threads[i];
10450 struct selector *s;
10452 t->selectors = calloc(p->n_selectors, sizeof(struct selector_runtime));
10453 if (!t->selectors) {
10458 TAILQ_FOREACH(s, &p->selectors, node) {
10459 struct selector_runtime *r = &t->selectors[s->id];
10463 size = rte_swx_table_selector_mailbox_size_get();
10465 r->mailbox = calloc(1, size);
10472 /* r->group_id_buffer. */
10473 r->group_id_buffer = &t->structs[p->metadata_struct_id];
10475 /* r->selector_buffer. */
10476 r->selector_buffer = s->selector_header ?
10477 &t->structs[s->selector_header->struct_id] :
10478 &t->structs[p->metadata_struct_id];
10480 /* r->member_id_buffer. */
10481 r->member_id_buffer = &t->structs[p->metadata_struct_id];
10488 selector_build_free(p);
10493 selector_free(struct rte_swx_pipeline *p)
10495 selector_build_free(p);
10497 /* Selector tables. */
10499 struct selector *elem;
10501 elem = TAILQ_FIRST(&p->selectors);
10505 TAILQ_REMOVE(&p->selectors, elem, node);
10506 free(elem->selector_fields);
10514 static struct learner *
10515 learner_find(struct rte_swx_pipeline *p, const char *name)
10519 TAILQ_FOREACH(l, &p->learners, node)
10520 if (!strcmp(l->name, name))
10526 static struct learner *
10527 learner_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
10529 struct learner *l = NULL;
10531 TAILQ_FOREACH(l, &p->learners, node)
10539 learner_match_fields_check(struct rte_swx_pipeline *p,
10540 struct rte_swx_pipeline_learner_params *params,
10541 struct header **header)
10543 struct header *h0 = NULL;
10544 struct field *hf, *mf;
10547 /* Return if no match fields. */
10548 if (!params->n_fields || !params->field_names)
10551 /* Check that all the match fields either belong to the same header
10552 * or are all meta-data fields.
10554 hf = header_field_parse(p, params->field_names[0], &h0);
10555 mf = metadata_field_parse(p, params->field_names[0]);
10559 for (i = 1; i < params->n_fields; i++)
10563 hf = header_field_parse(p, params->field_names[i], &h);
10564 if (!hf || (h->id != h0->id))
10567 mf = metadata_field_parse(p, params->field_names[i]);
10572 /* Check that there are no duplicated match fields. */
10573 for (i = 0; i < params->n_fields; i++) {
10574 const char *field_name = params->field_names[i];
10577 for (j = i + 1; j < params->n_fields; j++)
10578 if (!strcmp(params->field_names[j], field_name))
10590 learner_action_args_check(struct rte_swx_pipeline *p, struct action *a, const char *mf_name)
10592 struct struct_type *mst = p->metadata_st, *ast = a->st;
10593 struct field *mf, *af;
10594 uint32_t mf_pos, i;
10603 /* Check that mf_name is the name of a valid meta-data field. */
10604 CHECK_NAME(mf_name, EINVAL);
10605 mf = metadata_field_parse(p, mf_name);
10608 /* Check that there are enough meta-data fields, starting with the mf_name field, to cover
10609 * all the action arguments.
10611 mf_pos = mf - mst->fields;
10612 CHECK(mst->n_fields - mf_pos >= ast->n_fields, EINVAL);
10614 /* Check that the size of each of the identified meta-data fields matches exactly the size
10615 * of the corresponding action argument.
10617 for (i = 0; i < ast->n_fields; i++) {
10618 mf = &mst->fields[mf_pos + i];
10619 af = &ast->fields[i];
10621 CHECK(mf->n_bits == af->n_bits, EINVAL);
10628 learner_action_learning_check(struct rte_swx_pipeline *p,
10629 struct action *action,
10630 const char **action_names,
10631 uint32_t n_actions)
10635 /* For each "learn" instruction of the current action, check that the learned action (i.e.
10636 * the action passed as argument to the "learn" instruction) is also enabled for the
10637 * current learner table.
10639 for (i = 0; i < action->n_instructions; i++) {
10640 struct instruction *instr = &action->instructions[i];
10641 uint32_t found = 0, j;
10643 if (instr->type != INSTR_LEARNER_LEARN)
10646 for (j = 0; j < n_actions; j++) {
10649 a = action_find(p, action_names[j]);
10653 if (a->id == instr->learn.action_id)
10665 rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p,
10667 struct rte_swx_pipeline_learner_params *params,
10671 struct learner *l = NULL;
10672 struct action *default_action;
10673 struct header *header = NULL;
10674 uint32_t action_data_size_max = 0, i;
10679 CHECK_NAME(name, EINVAL);
10680 CHECK(!table_find(p, name), EEXIST);
10681 CHECK(!selector_find(p, name), EEXIST);
10682 CHECK(!learner_find(p, name), EEXIST);
10684 CHECK(params, EINVAL);
10686 /* Match checks. */
10687 status = learner_match_fields_check(p, params, &header);
10691 /* Action checks. */
10692 CHECK(params->n_actions, EINVAL);
10694 CHECK(params->action_names, EINVAL);
10695 for (i = 0; i < params->n_actions; i++) {
10696 const char *action_name = params->action_names[i];
10697 const char *action_field_name = params->action_field_names[i];
10699 uint32_t action_data_size;
10701 CHECK_NAME(action_name, EINVAL);
10703 a = action_find(p, action_name);
10706 status = learner_action_args_check(p, a, action_field_name);
10710 status = learner_action_learning_check(p,
10712 params->action_names,
10713 params->n_actions);
10717 action_data_size = a->st ? a->st->n_bits / 8 : 0;
10718 if (action_data_size > action_data_size_max)
10719 action_data_size_max = action_data_size;
10722 CHECK_NAME(params->default_action_name, EINVAL);
10723 for (i = 0; i < p->n_actions; i++)
10724 if (!strcmp(params->action_names[i],
10725 params->default_action_name))
10727 CHECK(i < params->n_actions, EINVAL);
10729 default_action = action_find(p, params->default_action_name);
10730 CHECK((default_action->st && params->default_action_data) ||
10731 !params->default_action_data, EINVAL);
10733 /* Any other checks. */
10734 CHECK(size, EINVAL);
10735 CHECK(timeout, EINVAL);
10737 /* Memory allocation. */
10738 l = calloc(1, sizeof(struct learner));
10742 l->fields = calloc(params->n_fields, sizeof(struct field *));
10746 l->actions = calloc(params->n_actions, sizeof(struct action *));
10750 l->action_arg = calloc(params->n_actions, sizeof(struct field *));
10751 if (!l->action_arg)
10754 if (action_data_size_max) {
10755 l->default_action_data = calloc(1, action_data_size_max);
10756 if (!l->default_action_data)
10760 /* Node initialization. */
10761 strcpy(l->name, name);
10763 for (i = 0; i < params->n_fields; i++) {
10764 const char *field_name = params->field_names[i];
10766 l->fields[i] = header ?
10767 header_field_parse(p, field_name, NULL) :
10768 metadata_field_parse(p, field_name);
10771 l->n_fields = params->n_fields;
10773 l->header = header;
10775 for (i = 0; i < params->n_actions; i++) {
10776 const char *mf_name = params->action_field_names[i];
10778 l->actions[i] = action_find(p, params->action_names[i]);
10780 l->action_arg[i] = mf_name ? metadata_field_parse(p, mf_name) : NULL;
10783 l->default_action = default_action;
10785 if (default_action->st)
10786 memcpy(l->default_action_data,
10787 params->default_action_data,
10788 default_action->st->n_bits / 8);
10790 l->n_actions = params->n_actions;
10792 l->default_action_is_const = params->default_action_is_const;
10794 l->action_data_size_max = action_data_size_max;
10798 l->timeout = timeout;
10800 l->id = p->n_learners;
10802 /* Node add to tailq. */
10803 TAILQ_INSERT_TAIL(&p->learners, l, node);
10812 free(l->action_arg);
10821 learner_params_free(struct rte_swx_table_learner_params *params)
10826 free(params->key_mask0);
10831 static struct rte_swx_table_learner_params *
10832 learner_params_get(struct learner *l)
10834 struct rte_swx_table_learner_params *params = NULL;
10835 struct field *first, *last;
10838 /* Memory allocation. */
10839 params = calloc(1, sizeof(struct rte_swx_table_learner_params));
10843 /* Find first (smallest offset) and last (biggest offset) match fields. */
10844 first = l->fields[0];
10845 last = l->fields[0];
10847 for (i = 0; i < l->n_fields; i++) {
10848 struct field *f = l->fields[i];
10850 if (f->offset < first->offset)
10853 if (f->offset > last->offset)
10857 /* Key offset and size. */
10858 params->key_offset = first->offset / 8;
10859 params->key_size = (last->offset + last->n_bits - first->offset) / 8;
10861 /* Memory allocation. */
10862 params->key_mask0 = calloc(1, params->key_size);
10863 if (!params->key_mask0)
10867 for (i = 0; i < l->n_fields; i++) {
10868 struct field *f = l->fields[i];
10869 uint32_t start = (f->offset - first->offset) / 8;
10870 size_t size = f->n_bits / 8;
10872 memset(¶ms->key_mask0[start], 0xFF, size);
10875 /* Action data size. */
10876 params->action_data_size = l->action_data_size_max;
10878 /* Maximum number of keys. */
10879 params->n_keys_max = l->size;
10882 params->key_timeout = l->timeout;
10887 learner_params_free(params);
10892 learner_build_free(struct rte_swx_pipeline *p)
10896 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
10897 struct thread *t = &p->threads[i];
10903 for (j = 0; j < p->n_learners; j++) {
10904 struct learner_runtime *r = &t->learners[j];
10907 free(r->action_data);
10911 t->learners = NULL;
10914 if (p->learner_stats) {
10915 for (i = 0; i < p->n_learners; i++)
10916 free(p->learner_stats[i].n_pkts_action);
10918 free(p->learner_stats);
10923 learner_build(struct rte_swx_pipeline *p)
10928 /* Per pipeline: learner statistics. */
10929 p->learner_stats = calloc(p->n_learners, sizeof(struct learner_statistics));
10930 CHECK(p->learner_stats, ENOMEM);
10932 for (i = 0; i < p->n_learners; i++) {
10933 p->learner_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
10934 CHECK(p->learner_stats[i].n_pkts_action, ENOMEM);
10937 /* Per thread: learner run-time. */
10938 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
10939 struct thread *t = &p->threads[i];
10942 t->learners = calloc(p->n_learners, sizeof(struct learner_runtime));
10943 if (!t->learners) {
10948 TAILQ_FOREACH(l, &p->learners, node) {
10949 struct learner_runtime *r = &t->learners[l->id];
10954 size = rte_swx_table_learner_mailbox_size_get();
10956 r->mailbox = calloc(1, size);
10964 r->key = l->header ?
10965 &t->structs[l->header->struct_id] :
10966 &t->structs[p->metadata_struct_id];
10968 /* r->action_data. */
10969 r->action_data = calloc(p->n_actions, sizeof(uint8_t *));
10970 if (!r->action_data) {
10975 for (j = 0; j < l->n_actions; j++) {
10976 struct action *a = l->actions[j];
10977 struct field *mf = l->action_arg[j];
10978 uint8_t *m = t->structs[p->metadata_struct_id];
10980 r->action_data[a->id] = mf ? &m[mf->offset / 8] : NULL;
10988 learner_build_free(p);
10993 learner_free(struct rte_swx_pipeline *p)
10995 learner_build_free(p);
10997 /* Learner tables. */
11001 l = TAILQ_FIRST(&p->learners);
11005 TAILQ_REMOVE(&p->learners, l, node);
11008 free(l->action_arg);
11009 free(l->default_action_data);
11018 table_state_build(struct rte_swx_pipeline *p)
11020 struct table *table;
11021 struct selector *s;
11024 p->table_state = calloc(p->n_tables + p->n_selectors,
11025 sizeof(struct rte_swx_table_state));
11026 CHECK(p->table_state, ENOMEM);
11028 TAILQ_FOREACH(table, &p->tables, node) {
11029 struct rte_swx_table_state *ts = &p->table_state[table->id];
11032 struct rte_swx_table_params *params;
11035 params = table_params_get(table);
11036 CHECK(params, ENOMEM);
11038 ts->obj = table->type->ops.create(params,
11043 table_params_free(params);
11044 CHECK(ts->obj, ENODEV);
11047 /* ts->default_action_data. */
11048 if (table->action_data_size_max) {
11049 ts->default_action_data =
11050 malloc(table->action_data_size_max);
11051 CHECK(ts->default_action_data, ENOMEM);
11053 memcpy(ts->default_action_data,
11054 table->default_action_data,
11055 table->action_data_size_max);
11058 /* ts->default_action_id. */
11059 ts->default_action_id = table->default_action->id;
11062 TAILQ_FOREACH(s, &p->selectors, node) {
11063 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + s->id];
11064 struct rte_swx_table_selector_params *params;
11067 params = selector_table_params_get(s);
11068 CHECK(params, ENOMEM);
11070 ts->obj = rte_swx_table_selector_create(params, NULL, p->numa_node);
11072 selector_params_free(params);
11073 CHECK(ts->obj, ENODEV);
11076 TAILQ_FOREACH(l, &p->learners, node) {
11077 struct rte_swx_table_state *ts = &p->table_state[p->n_tables +
11078 p->n_selectors + l->id];
11079 struct rte_swx_table_learner_params *params;
11082 params = learner_params_get(l);
11083 CHECK(params, ENOMEM);
11085 ts->obj = rte_swx_table_learner_create(params, p->numa_node);
11086 learner_params_free(params);
11087 CHECK(ts->obj, ENODEV);
11089 /* ts->default_action_data. */
11090 if (l->action_data_size_max) {
11091 ts->default_action_data = malloc(l->action_data_size_max);
11092 CHECK(ts->default_action_data, ENOMEM);
11094 memcpy(ts->default_action_data,
11095 l->default_action_data,
11096 l->action_data_size_max);
11099 /* ts->default_action_id. */
11100 ts->default_action_id = l->default_action->id;
11107 table_state_build_free(struct rte_swx_pipeline *p)
11111 if (!p->table_state)
11114 for (i = 0; i < p->n_tables; i++) {
11115 struct rte_swx_table_state *ts = &p->table_state[i];
11116 struct table *table = table_find_by_id(p, i);
11119 if (table->type && ts->obj)
11120 table->type->ops.free(ts->obj);
11122 /* ts->default_action_data. */
11123 free(ts->default_action_data);
11126 for (i = 0; i < p->n_selectors; i++) {
11127 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + i];
11131 rte_swx_table_selector_free(ts->obj);
11134 for (i = 0; i < p->n_learners; i++) {
11135 struct rte_swx_table_state *ts = &p->table_state[p->n_tables + p->n_selectors + i];
11139 rte_swx_table_learner_free(ts->obj);
11141 /* ts->default_action_data. */
11142 free(ts->default_action_data);
11145 free(p->table_state);
11146 p->table_state = NULL;
11150 table_state_free(struct rte_swx_pipeline *p)
11152 table_state_build_free(p);
11158 static struct regarray *
11159 regarray_find(struct rte_swx_pipeline *p, const char *name)
11161 struct regarray *elem;
11163 TAILQ_FOREACH(elem, &p->regarrays, node)
11164 if (!strcmp(elem->name, name))
11170 static struct regarray *
11171 regarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
11173 struct regarray *elem = NULL;
11175 TAILQ_FOREACH(elem, &p->regarrays, node)
11176 if (elem->id == id)
11183 rte_swx_pipeline_regarray_config(struct rte_swx_pipeline *p,
11188 struct regarray *r;
11192 CHECK_NAME(name, EINVAL);
11193 CHECK(!regarray_find(p, name), EEXIST);
11195 CHECK(size, EINVAL);
11196 size = rte_align32pow2(size);
11198 /* Memory allocation. */
11199 r = calloc(1, sizeof(struct regarray));
11202 /* Node initialization. */
11203 strcpy(r->name, name);
11204 r->init_val = init_val;
11206 r->id = p->n_regarrays;
11208 /* Node add to tailq. */
11209 TAILQ_INSERT_TAIL(&p->regarrays, r, node);
11216 regarray_build(struct rte_swx_pipeline *p)
11218 struct regarray *regarray;
11220 if (!p->n_regarrays)
11223 p->regarray_runtime = calloc(p->n_regarrays, sizeof(struct regarray_runtime));
11224 CHECK(p->regarray_runtime, ENOMEM);
11226 TAILQ_FOREACH(regarray, &p->regarrays, node) {
11227 struct regarray_runtime *r = &p->regarray_runtime[regarray->id];
11230 r->regarray = env_malloc(regarray->size * sizeof(uint64_t),
11231 RTE_CACHE_LINE_SIZE,
11233 CHECK(r->regarray, ENOMEM);
11235 if (regarray->init_val)
11236 for (i = 0; i < regarray->size; i++)
11237 r->regarray[i] = regarray->init_val;
11239 r->size_mask = regarray->size - 1;
11246 regarray_build_free(struct rte_swx_pipeline *p)
11250 if (!p->regarray_runtime)
11253 for (i = 0; i < p->n_regarrays; i++) {
11254 struct regarray *regarray = regarray_find_by_id(p, i);
11255 struct regarray_runtime *r = &p->regarray_runtime[i];
11257 env_free(r->regarray, regarray->size * sizeof(uint64_t));
11260 free(p->regarray_runtime);
11261 p->regarray_runtime = NULL;
11265 regarray_free(struct rte_swx_pipeline *p)
11267 regarray_build_free(p);
11270 struct regarray *elem;
11272 elem = TAILQ_FIRST(&p->regarrays);
11276 TAILQ_REMOVE(&p->regarrays, elem, node);
11284 static struct meter_profile *
11285 meter_profile_find(struct rte_swx_pipeline *p, const char *name)
11287 struct meter_profile *elem;
11289 TAILQ_FOREACH(elem, &p->meter_profiles, node)
11290 if (!strcmp(elem->name, name))
11296 static struct metarray *
11297 metarray_find(struct rte_swx_pipeline *p, const char *name)
11299 struct metarray *elem;
11301 TAILQ_FOREACH(elem, &p->metarrays, node)
11302 if (!strcmp(elem->name, name))
11308 static struct metarray *
11309 metarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
11311 struct metarray *elem = NULL;
11313 TAILQ_FOREACH(elem, &p->metarrays, node)
11314 if (elem->id == id)
11321 rte_swx_pipeline_metarray_config(struct rte_swx_pipeline *p,
11325 struct metarray *m;
11329 CHECK_NAME(name, EINVAL);
11330 CHECK(!metarray_find(p, name), EEXIST);
11332 CHECK(size, EINVAL);
11333 size = rte_align32pow2(size);
11335 /* Memory allocation. */
11336 m = calloc(1, sizeof(struct metarray));
11339 /* Node initialization. */
11340 strcpy(m->name, name);
11342 m->id = p->n_metarrays;
11344 /* Node add to tailq. */
11345 TAILQ_INSERT_TAIL(&p->metarrays, m, node);
11351 struct meter_profile meter_profile_default = {
11360 .cir_bytes_per_period = 1,
11362 .pir_bytes_per_period = 1,
11369 meter_init(struct meter *m)
11371 memset(m, 0, sizeof(struct meter));
11372 rte_meter_trtcm_config(&m->m, &meter_profile_default.profile);
11373 m->profile = &meter_profile_default;
11374 m->color_mask = RTE_COLOR_GREEN;
11376 meter_profile_default.n_users++;
11380 metarray_build(struct rte_swx_pipeline *p)
11382 struct metarray *m;
11384 if (!p->n_metarrays)
11387 p->metarray_runtime = calloc(p->n_metarrays, sizeof(struct metarray_runtime));
11388 CHECK(p->metarray_runtime, ENOMEM);
11390 TAILQ_FOREACH(m, &p->metarrays, node) {
11391 struct metarray_runtime *r = &p->metarray_runtime[m->id];
11394 r->metarray = env_malloc(m->size * sizeof(struct meter),
11395 RTE_CACHE_LINE_SIZE,
11397 CHECK(r->metarray, ENOMEM);
11399 for (i = 0; i < m->size; i++)
11400 meter_init(&r->metarray[i]);
11402 r->size_mask = m->size - 1;
11409 metarray_build_free(struct rte_swx_pipeline *p)
11413 if (!p->metarray_runtime)
11416 for (i = 0; i < p->n_metarrays; i++) {
11417 struct metarray *m = metarray_find_by_id(p, i);
11418 struct metarray_runtime *r = &p->metarray_runtime[i];
11420 env_free(r->metarray, m->size * sizeof(struct meter));
11423 free(p->metarray_runtime);
11424 p->metarray_runtime = NULL;
11428 metarray_free(struct rte_swx_pipeline *p)
11430 metarray_build_free(p);
11432 /* Meter arrays. */
11434 struct metarray *elem;
11436 elem = TAILQ_FIRST(&p->metarrays);
11440 TAILQ_REMOVE(&p->metarrays, elem, node);
11444 /* Meter profiles. */
11446 struct meter_profile *elem;
11448 elem = TAILQ_FIRST(&p->meter_profiles);
11452 TAILQ_REMOVE(&p->meter_profiles, elem, node);
11461 rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
11463 struct rte_swx_pipeline *pipeline;
11465 /* Check input parameters. */
11468 /* Memory allocation. */
11469 pipeline = calloc(1, sizeof(struct rte_swx_pipeline));
11470 CHECK(pipeline, ENOMEM);
11472 /* Initialization. */
11473 TAILQ_INIT(&pipeline->struct_types);
11474 TAILQ_INIT(&pipeline->port_in_types);
11475 TAILQ_INIT(&pipeline->ports_in);
11476 TAILQ_INIT(&pipeline->port_out_types);
11477 TAILQ_INIT(&pipeline->ports_out);
11478 TAILQ_INIT(&pipeline->extern_types);
11479 TAILQ_INIT(&pipeline->extern_objs);
11480 TAILQ_INIT(&pipeline->extern_funcs);
11481 TAILQ_INIT(&pipeline->headers);
11482 TAILQ_INIT(&pipeline->actions);
11483 TAILQ_INIT(&pipeline->table_types);
11484 TAILQ_INIT(&pipeline->tables);
11485 TAILQ_INIT(&pipeline->selectors);
11486 TAILQ_INIT(&pipeline->learners);
11487 TAILQ_INIT(&pipeline->regarrays);
11488 TAILQ_INIT(&pipeline->meter_profiles);
11489 TAILQ_INIT(&pipeline->metarrays);
11491 pipeline->n_structs = 1; /* Struct 0 is reserved for action_data. */
11492 pipeline->numa_node = numa_node;
11499 rte_swx_pipeline_free(struct rte_swx_pipeline *p)
11504 free(p->instructions);
11508 table_state_free(p);
11515 extern_func_free(p);
11516 extern_obj_free(p);
11525 rte_swx_pipeline_instructions_config(struct rte_swx_pipeline *p,
11526 const char **instructions,
11527 uint32_t n_instructions)
11532 err = instruction_config(p, NULL, instructions, n_instructions);
11536 /* Thread instruction pointer reset. */
11537 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
11538 struct thread *t = &p->threads[i];
11540 thread_ip_reset(p, t);
11547 rte_swx_pipeline_build(struct rte_swx_pipeline *p)
11552 CHECK(p->build_done == 0, EEXIST);
11554 status = port_in_build(p);
11558 status = port_out_build(p);
11562 status = struct_build(p);
11566 status = extern_obj_build(p);
11570 status = extern_func_build(p);
11574 status = header_build(p);
11578 status = metadata_build(p);
11582 status = action_build(p);
11586 status = table_build(p);
11590 status = selector_build(p);
11594 status = learner_build(p);
11598 status = table_state_build(p);
11602 status = regarray_build(p);
11606 status = metarray_build(p);
11614 metarray_build_free(p);
11615 regarray_build_free(p);
11616 table_state_build_free(p);
11617 learner_build_free(p);
11618 selector_build_free(p);
11619 table_build_free(p);
11620 action_build_free(p);
11621 metadata_build_free(p);
11622 header_build_free(p);
11623 extern_func_build_free(p);
11624 extern_obj_build_free(p);
11625 port_out_build_free(p);
11626 port_in_build_free(p);
11627 struct_build_free(p);
11633 rte_swx_pipeline_run(struct rte_swx_pipeline *p, uint32_t n_instructions)
11637 for (i = 0; i < n_instructions; i++)
11642 rte_swx_pipeline_flush(struct rte_swx_pipeline *p)
11646 for (i = 0; i < p->n_ports_out; i++) {
11647 struct port_out_runtime *port = &p->out[i];
11650 port->flush(port->obj);
11658 rte_swx_ctl_pipeline_info_get(struct rte_swx_pipeline *p,
11659 struct rte_swx_ctl_pipeline_info *pipeline)
11661 struct action *action;
11662 struct table *table;
11663 uint32_t n_actions = 0, n_tables = 0;
11665 if (!p || !pipeline)
11668 TAILQ_FOREACH(action, &p->actions, node)
11671 TAILQ_FOREACH(table, &p->tables, node)
11674 pipeline->n_ports_in = p->n_ports_in;
11675 pipeline->n_ports_out = p->n_ports_out;
11676 pipeline->n_actions = n_actions;
11677 pipeline->n_tables = n_tables;
11678 pipeline->n_selectors = p->n_selectors;
11679 pipeline->n_learners = p->n_learners;
11680 pipeline->n_regarrays = p->n_regarrays;
11681 pipeline->n_metarrays = p->n_metarrays;
11687 rte_swx_ctl_pipeline_numa_node_get(struct rte_swx_pipeline *p, int *numa_node)
11689 if (!p || !numa_node)
11692 *numa_node = p->numa_node;
11697 rte_swx_ctl_action_info_get(struct rte_swx_pipeline *p,
11698 uint32_t action_id,
11699 struct rte_swx_ctl_action_info *action)
11701 struct action *a = NULL;
11703 if (!p || (action_id >= p->n_actions) || !action)
11706 a = action_find_by_id(p, action_id);
11710 strcpy(action->name, a->name);
11711 action->n_args = a->st ? a->st->n_fields : 0;
11716 rte_swx_ctl_action_arg_info_get(struct rte_swx_pipeline *p,
11717 uint32_t action_id,
11718 uint32_t action_arg_id,
11719 struct rte_swx_ctl_action_arg_info *action_arg)
11721 struct action *a = NULL;
11722 struct field *arg = NULL;
11724 if (!p || (action_id >= p->n_actions) || !action_arg)
11727 a = action_find_by_id(p, action_id);
11728 if (!a || !a->st || (action_arg_id >= a->st->n_fields))
11731 arg = &a->st->fields[action_arg_id];
11732 strcpy(action_arg->name, arg->name);
11733 action_arg->n_bits = arg->n_bits;
11734 action_arg->is_network_byte_order = a->args_endianness[action_arg_id];
11740 rte_swx_ctl_table_info_get(struct rte_swx_pipeline *p,
11742 struct rte_swx_ctl_table_info *table)
11744 struct table *t = NULL;
11749 t = table_find_by_id(p, table_id);
11753 strcpy(table->name, t->name);
11754 strcpy(table->args, t->args);
11755 table->n_match_fields = t->n_fields;
11756 table->n_actions = t->n_actions;
11757 table->default_action_is_const = t->default_action_is_const;
11758 table->size = t->size;
11763 rte_swx_ctl_table_match_field_info_get(struct rte_swx_pipeline *p,
11765 uint32_t match_field_id,
11766 struct rte_swx_ctl_table_match_field_info *match_field)
11769 struct match_field *f;
11771 if (!p || (table_id >= p->n_tables) || !match_field)
11774 t = table_find_by_id(p, table_id);
11775 if (!t || (match_field_id >= t->n_fields))
11778 f = &t->fields[match_field_id];
11779 match_field->match_type = f->match_type;
11780 match_field->is_header = t->header ? 1 : 0;
11781 match_field->n_bits = f->field->n_bits;
11782 match_field->offset = f->field->offset;
11788 rte_swx_ctl_table_action_info_get(struct rte_swx_pipeline *p,
11790 uint32_t table_action_id,
11791 struct rte_swx_ctl_table_action_info *table_action)
11795 if (!p || (table_id >= p->n_tables) || !table_action)
11798 t = table_find_by_id(p, table_id);
11799 if (!t || (table_action_id >= t->n_actions))
11802 table_action->action_id = t->actions[table_action_id]->id;
11808 rte_swx_ctl_table_ops_get(struct rte_swx_pipeline *p,
11810 struct rte_swx_table_ops *table_ops,
11815 if (!p || (table_id >= p->n_tables))
11818 t = table_find_by_id(p, table_id);
11824 memcpy(table_ops, &t->type->ops, sizeof(*table_ops));
11834 rte_swx_ctl_selector_info_get(struct rte_swx_pipeline *p,
11835 uint32_t selector_id,
11836 struct rte_swx_ctl_selector_info *selector)
11838 struct selector *s = NULL;
11840 if (!p || !selector)
11843 s = selector_find_by_id(p, selector_id);
11847 strcpy(selector->name, s->name);
11849 selector->n_selector_fields = s->n_selector_fields;
11850 selector->n_groups_max = s->n_groups_max;
11851 selector->n_members_per_group_max = s->n_members_per_group_max;
11857 rte_swx_ctl_selector_group_id_field_info_get(struct rte_swx_pipeline *p,
11858 uint32_t selector_id,
11859 struct rte_swx_ctl_table_match_field_info *field)
11861 struct selector *s;
11863 if (!p || (selector_id >= p->n_selectors) || !field)
11866 s = selector_find_by_id(p, selector_id);
11870 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
11871 field->is_header = 0;
11872 field->n_bits = s->group_id_field->n_bits;
11873 field->offset = s->group_id_field->offset;
11879 rte_swx_ctl_selector_field_info_get(struct rte_swx_pipeline *p,
11880 uint32_t selector_id,
11881 uint32_t selector_field_id,
11882 struct rte_swx_ctl_table_match_field_info *field)
11884 struct selector *s;
11887 if (!p || (selector_id >= p->n_selectors) || !field)
11890 s = selector_find_by_id(p, selector_id);
11891 if (!s || (selector_field_id >= s->n_selector_fields))
11894 f = s->selector_fields[selector_field_id];
11895 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
11896 field->is_header = s->selector_header ? 1 : 0;
11897 field->n_bits = f->n_bits;
11898 field->offset = f->offset;
11904 rte_swx_ctl_selector_member_id_field_info_get(struct rte_swx_pipeline *p,
11905 uint32_t selector_id,
11906 struct rte_swx_ctl_table_match_field_info *field)
11908 struct selector *s;
11910 if (!p || (selector_id >= p->n_selectors) || !field)
11913 s = selector_find_by_id(p, selector_id);
11917 field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
11918 field->is_header = 0;
11919 field->n_bits = s->member_id_field->n_bits;
11920 field->offset = s->member_id_field->offset;
11926 rte_swx_ctl_learner_info_get(struct rte_swx_pipeline *p,
11927 uint32_t learner_id,
11928 struct rte_swx_ctl_learner_info *learner)
11930 struct learner *l = NULL;
11932 if (!p || !learner)
11935 l = learner_find_by_id(p, learner_id);
11939 strcpy(learner->name, l->name);
11941 learner->n_match_fields = l->n_fields;
11942 learner->n_actions = l->n_actions;
11943 learner->default_action_is_const = l->default_action_is_const;
11944 learner->size = l->size;
11950 rte_swx_ctl_learner_match_field_info_get(struct rte_swx_pipeline *p,
11951 uint32_t learner_id,
11952 uint32_t match_field_id,
11953 struct rte_swx_ctl_table_match_field_info *match_field)
11958 if (!p || (learner_id >= p->n_learners) || !match_field)
11961 l = learner_find_by_id(p, learner_id);
11962 if (!l || (match_field_id >= l->n_fields))
11965 f = l->fields[match_field_id];
11966 match_field->match_type = RTE_SWX_TABLE_MATCH_EXACT;
11967 match_field->is_header = l->header ? 1 : 0;
11968 match_field->n_bits = f->n_bits;
11969 match_field->offset = f->offset;
11975 rte_swx_ctl_learner_action_info_get(struct rte_swx_pipeline *p,
11976 uint32_t learner_id,
11977 uint32_t learner_action_id,
11978 struct rte_swx_ctl_table_action_info *learner_action)
11982 if (!p || (learner_id >= p->n_learners) || !learner_action)
11985 l = learner_find_by_id(p, learner_id);
11986 if (!l || (learner_action_id >= l->n_actions))
11989 learner_action->action_id = l->actions[learner_action_id]->id;
11995 rte_swx_pipeline_table_state_get(struct rte_swx_pipeline *p,
11996 struct rte_swx_table_state **table_state)
11998 if (!p || !table_state || !p->build_done)
12001 *table_state = p->table_state;
12006 rte_swx_pipeline_table_state_set(struct rte_swx_pipeline *p,
12007 struct rte_swx_table_state *table_state)
12009 if (!p || !table_state || !p->build_done)
12012 p->table_state = table_state;
12017 rte_swx_ctl_pipeline_port_in_stats_read(struct rte_swx_pipeline *p,
12019 struct rte_swx_port_in_stats *stats)
12021 struct port_in *port;
12026 port = port_in_find(p, port_id);
12030 port->type->ops.stats_read(port->obj, stats);
12035 rte_swx_ctl_pipeline_port_out_stats_read(struct rte_swx_pipeline *p,
12037 struct rte_swx_port_out_stats *stats)
12039 struct port_out *port;
12044 port = port_out_find(p, port_id);
12048 port->type->ops.stats_read(port->obj, stats);
12053 rte_swx_ctl_pipeline_table_stats_read(struct rte_swx_pipeline *p,
12054 const char *table_name,
12055 struct rte_swx_table_stats *stats)
12057 struct table *table;
12058 struct table_statistics *table_stats;
12060 if (!p || !table_name || !table_name[0] || !stats || !stats->n_pkts_action)
12063 table = table_find(p, table_name);
12067 table_stats = &p->table_stats[table->id];
12069 memcpy(stats->n_pkts_action,
12070 table_stats->n_pkts_action,
12071 p->n_actions * sizeof(uint64_t));
12073 stats->n_pkts_hit = table_stats->n_pkts_hit[1];
12074 stats->n_pkts_miss = table_stats->n_pkts_hit[0];
12080 rte_swx_ctl_pipeline_selector_stats_read(struct rte_swx_pipeline *p,
12081 const char *selector_name,
12082 struct rte_swx_pipeline_selector_stats *stats)
12084 struct selector *s;
12086 if (!p || !selector_name || !selector_name[0] || !stats)
12089 s = selector_find(p, selector_name);
12093 stats->n_pkts = p->selector_stats[s->id].n_pkts;
12099 rte_swx_ctl_pipeline_learner_stats_read(struct rte_swx_pipeline *p,
12100 const char *learner_name,
12101 struct rte_swx_learner_stats *stats)
12104 struct learner_statistics *learner_stats;
12106 if (!p || !learner_name || !learner_name[0] || !stats || !stats->n_pkts_action)
12109 l = learner_find(p, learner_name);
12113 learner_stats = &p->learner_stats[l->id];
12115 memcpy(stats->n_pkts_action,
12116 learner_stats->n_pkts_action,
12117 p->n_actions * sizeof(uint64_t));
12119 stats->n_pkts_hit = learner_stats->n_pkts_hit[1];
12120 stats->n_pkts_miss = learner_stats->n_pkts_hit[0];
12122 stats->n_pkts_learn_ok = learner_stats->n_pkts_learn[0];
12123 stats->n_pkts_learn_err = learner_stats->n_pkts_learn[1];
12125 stats->n_pkts_forget = learner_stats->n_pkts_forget;
12131 rte_swx_ctl_regarray_info_get(struct rte_swx_pipeline *p,
12132 uint32_t regarray_id,
12133 struct rte_swx_ctl_regarray_info *regarray)
12135 struct regarray *r;
12137 if (!p || !regarray)
12140 r = regarray_find_by_id(p, regarray_id);
12144 strcpy(regarray->name, r->name);
12145 regarray->size = r->size;
12150 rte_swx_ctl_pipeline_regarray_read(struct rte_swx_pipeline *p,
12151 const char *regarray_name,
12152 uint32_t regarray_index,
12155 struct regarray *regarray;
12156 struct regarray_runtime *r;
12158 if (!p || !regarray_name || !value)
12161 regarray = regarray_find(p, regarray_name);
12162 if (!regarray || (regarray_index >= regarray->size))
12165 r = &p->regarray_runtime[regarray->id];
12166 *value = r->regarray[regarray_index];
12171 rte_swx_ctl_pipeline_regarray_write(struct rte_swx_pipeline *p,
12172 const char *regarray_name,
12173 uint32_t regarray_index,
12176 struct regarray *regarray;
12177 struct regarray_runtime *r;
12179 if (!p || !regarray_name)
12182 regarray = regarray_find(p, regarray_name);
12183 if (!regarray || (regarray_index >= regarray->size))
12186 r = &p->regarray_runtime[regarray->id];
12187 r->regarray[regarray_index] = value;
12192 rte_swx_ctl_metarray_info_get(struct rte_swx_pipeline *p,
12193 uint32_t metarray_id,
12194 struct rte_swx_ctl_metarray_info *metarray)
12196 struct metarray *m;
12198 if (!p || !metarray)
12201 m = metarray_find_by_id(p, metarray_id);
12205 strcpy(metarray->name, m->name);
12206 metarray->size = m->size;
12211 rte_swx_ctl_meter_profile_add(struct rte_swx_pipeline *p,
12213 struct rte_meter_trtcm_params *params)
12215 struct meter_profile *mp;
12219 CHECK_NAME(name, EINVAL);
12220 CHECK(params, EINVAL);
12221 CHECK(!meter_profile_find(p, name), EEXIST);
12223 /* Node allocation. */
12224 mp = calloc(1, sizeof(struct meter_profile));
12227 /* Node initialization. */
12228 strcpy(mp->name, name);
12229 memcpy(&mp->params, params, sizeof(struct rte_meter_trtcm_params));
12230 status = rte_meter_trtcm_profile_config(&mp->profile, params);
12236 /* Node add to tailq. */
12237 TAILQ_INSERT_TAIL(&p->meter_profiles, mp, node);
12243 rte_swx_ctl_meter_profile_delete(struct rte_swx_pipeline *p,
12246 struct meter_profile *mp;
12249 CHECK_NAME(name, EINVAL);
12251 mp = meter_profile_find(p, name);
12253 CHECK(!mp->n_users, EBUSY);
12255 /* Remove node from tailq. */
12256 TAILQ_REMOVE(&p->meter_profiles, mp, node);
12263 rte_swx_ctl_meter_reset(struct rte_swx_pipeline *p,
12264 const char *metarray_name,
12265 uint32_t metarray_index)
12267 struct meter_profile *mp_old;
12268 struct metarray *metarray;
12269 struct metarray_runtime *metarray_runtime;
12273 CHECK_NAME(metarray_name, EINVAL);
12275 metarray = metarray_find(p, metarray_name);
12276 CHECK(metarray, EINVAL);
12277 CHECK(metarray_index < metarray->size, EINVAL);
12279 metarray_runtime = &p->metarray_runtime[metarray->id];
12280 m = &metarray_runtime->metarray[metarray_index];
12281 mp_old = m->profile;
12291 rte_swx_ctl_meter_set(struct rte_swx_pipeline *p,
12292 const char *metarray_name,
12293 uint32_t metarray_index,
12294 const char *profile_name)
12296 struct meter_profile *mp, *mp_old;
12297 struct metarray *metarray;
12298 struct metarray_runtime *metarray_runtime;
12302 CHECK_NAME(metarray_name, EINVAL);
12304 metarray = metarray_find(p, metarray_name);
12305 CHECK(metarray, EINVAL);
12306 CHECK(metarray_index < metarray->size, EINVAL);
12308 mp = meter_profile_find(p, profile_name);
12311 metarray_runtime = &p->metarray_runtime[metarray->id];
12312 m = &metarray_runtime->metarray[metarray_index];
12313 mp_old = m->profile;
12315 memset(m, 0, sizeof(struct meter));
12316 rte_meter_trtcm_config(&m->m, &mp->profile);
12318 m->color_mask = RTE_COLORS;
12327 rte_swx_ctl_meter_stats_read(struct rte_swx_pipeline *p,
12328 const char *metarray_name,
12329 uint32_t metarray_index,
12330 struct rte_swx_ctl_meter_stats *stats)
12332 struct metarray *metarray;
12333 struct metarray_runtime *metarray_runtime;
12337 CHECK_NAME(metarray_name, EINVAL);
12339 metarray = metarray_find(p, metarray_name);
12340 CHECK(metarray, EINVAL);
12341 CHECK(metarray_index < metarray->size, EINVAL);
12343 CHECK(stats, EINVAL);
12345 metarray_runtime = &p->metarray_runtime[metarray->id];
12346 m = &metarray_runtime->metarray[metarray_index];
12348 memcpy(stats->n_pkts, m->n_pkts, sizeof(m->n_pkts));
12349 memcpy(stats->n_bytes, m->n_bytes, sizeof(m->n_bytes));