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_pipeline.h"
19 #include "rte_swx_ctl.h"
21 #define CHECK(condition, err_code) \
27 #define CHECK_NAME(name, err_code) \
30 (strnlen((name), RTE_SWX_NAME_SIZE) < RTE_SWX_NAME_SIZE), \
33 #define CHECK_INSTRUCTION(instr, err_code) \
36 (strnlen((instr), RTE_SWX_INSTRUCTION_SIZE) < \
37 RTE_SWX_INSTRUCTION_SIZE), \
45 #define TRACE(...) printf(__VA_ARGS__)
53 #define ntoh64(x) rte_be_to_cpu_64(x)
54 #define hton64(x) rte_cpu_to_be_64(x)
56 #ifndef RTE_SWX_PIPELINE_HUGE_PAGES_DISABLE
58 #include <rte_malloc.h>
61 env_malloc(size_t size, size_t alignment, int numa_node)
63 return rte_zmalloc_socket(NULL, size, alignment, numa_node);
67 env_free(void *start, size_t size __rte_unused)
77 env_malloc(size_t size, size_t alignment __rte_unused, int numa_node)
81 if (numa_available() == -1)
84 start = numa_alloc_onnode(size, numa_node);
88 memset(start, 0, size);
93 env_free(void *start, size_t size)
95 if (numa_available() == -1)
98 numa_free(start, size);
107 char name[RTE_SWX_NAME_SIZE];
113 TAILQ_ENTRY(struct_type) node;
114 char name[RTE_SWX_NAME_SIZE];
115 struct field *fields;
120 TAILQ_HEAD(struct_type_tailq, struct_type);
125 struct port_in_type {
126 TAILQ_ENTRY(port_in_type) node;
127 char name[RTE_SWX_NAME_SIZE];
128 struct rte_swx_port_in_ops ops;
131 TAILQ_HEAD(port_in_type_tailq, port_in_type);
134 TAILQ_ENTRY(port_in) node;
135 struct port_in_type *type;
140 TAILQ_HEAD(port_in_tailq, port_in);
142 struct port_in_runtime {
143 rte_swx_port_in_pkt_rx_t pkt_rx;
150 struct port_out_type {
151 TAILQ_ENTRY(port_out_type) node;
152 char name[RTE_SWX_NAME_SIZE];
153 struct rte_swx_port_out_ops ops;
156 TAILQ_HEAD(port_out_type_tailq, port_out_type);
159 TAILQ_ENTRY(port_out) node;
160 struct port_out_type *type;
165 TAILQ_HEAD(port_out_tailq, port_out);
167 struct port_out_runtime {
168 rte_swx_port_out_pkt_tx_t pkt_tx;
169 rte_swx_port_out_flush_t flush;
176 struct extern_type_member_func {
177 TAILQ_ENTRY(extern_type_member_func) node;
178 char name[RTE_SWX_NAME_SIZE];
179 rte_swx_extern_type_member_func_t func;
183 TAILQ_HEAD(extern_type_member_func_tailq, extern_type_member_func);
186 TAILQ_ENTRY(extern_type) node;
187 char name[RTE_SWX_NAME_SIZE];
188 struct struct_type *mailbox_struct_type;
189 rte_swx_extern_type_constructor_t constructor;
190 rte_swx_extern_type_destructor_t destructor;
191 struct extern_type_member_func_tailq funcs;
195 TAILQ_HEAD(extern_type_tailq, extern_type);
198 TAILQ_ENTRY(extern_obj) node;
199 char name[RTE_SWX_NAME_SIZE];
200 struct extern_type *type;
206 TAILQ_HEAD(extern_obj_tailq, extern_obj);
208 #ifndef RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX
209 #define RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX 8
212 struct extern_obj_runtime {
215 rte_swx_extern_type_member_func_t funcs[RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX];
222 TAILQ_ENTRY(extern_func) node;
223 char name[RTE_SWX_NAME_SIZE];
224 struct struct_type *mailbox_struct_type;
225 rte_swx_extern_func_t func;
230 TAILQ_HEAD(extern_func_tailq, extern_func);
232 struct extern_func_runtime {
234 rte_swx_extern_func_t func;
241 TAILQ_ENTRY(header) node;
242 char name[RTE_SWX_NAME_SIZE];
243 struct struct_type *st;
248 TAILQ_HEAD(header_tailq, header);
250 struct header_runtime {
254 struct header_out_runtime {
264 /* Packet headers are always in Network Byte Order (NBO), i.e. big endian.
265 * Packet meta-data fields are always assumed to be in Host Byte Order (HBO).
266 * Table entry fields can be in either NBO or HBO; they are assumed to be in HBO
267 * when transferred to packet meta-data and in NBO when transferred to packet
271 /* Notation conventions:
272 * -Header field: H = h.header.field (dst/src)
273 * -Meta-data field: M = m.field (dst/src)
274 * -Extern object mailbox field: E = e.field (dst/src)
275 * -Extern function mailbox field: F = f.field (dst/src)
276 * -Table action data field: T = t.field (src only)
277 * -Immediate value: I = 32-bit unsigned value (src only)
280 enum instruction_type {
287 /* extract h.header */
308 /* validate h.header */
311 /* invalidate h.header */
312 INSTR_HDR_INVALIDATE,
316 * dst = HMEF, src = HMEFTI
318 INSTR_MOV, /* dst = MEF, src = MEFT */
319 INSTR_MOV_S, /* (dst, src) = (MEF, H) or (dst, src) = (H, MEFT) */
320 INSTR_MOV_I, /* dst = HMEF, src = I */
322 /* dma h.header t.field
323 * memcpy(h.header, t.field, sizeof(h.header))
336 * dst = HMEF, src = HMEFTI
338 INSTR_ALU_ADD, /* dst = MEF, src = MEF */
339 INSTR_ALU_ADD_MH, /* dst = MEF, src = H */
340 INSTR_ALU_ADD_HM, /* dst = H, src = MEF */
341 INSTR_ALU_ADD_HH, /* dst = H, src = H */
342 INSTR_ALU_ADD_MI, /* dst = MEF, src = I */
343 INSTR_ALU_ADD_HI, /* dst = H, src = I */
347 * dst = HMEF, src = HMEFTI
349 INSTR_ALU_SUB, /* dst = MEF, src = MEF */
350 INSTR_ALU_SUB_MH, /* dst = MEF, src = H */
351 INSTR_ALU_SUB_HM, /* dst = H, src = MEF */
352 INSTR_ALU_SUB_HH, /* dst = H, src = H */
353 INSTR_ALU_SUB_MI, /* dst = MEF, src = I */
354 INSTR_ALU_SUB_HI, /* dst = H, src = I */
357 * dst = dst '+ src[0:1] '+ src[2:3] + ...
358 * dst = H, src = {H, h.header}
360 INSTR_ALU_CKADD_FIELD, /* src = H */
361 INSTR_ALU_CKADD_STRUCT20, /* src = h.header, with sizeof(header) = 20 */
362 INSTR_ALU_CKADD_STRUCT, /* src = h.hdeader, with any sizeof(header) */
368 INSTR_ALU_CKSUB_FIELD,
372 * dst = HMEF, src = HMEFTI
374 INSTR_ALU_AND, /* dst = MEF, src = MEFT */
375 INSTR_ALU_AND_S, /* (dst, src) = (MEF, H) or (dst, src) = (H, MEFT) */
376 INSTR_ALU_AND_I, /* dst = HMEF, src = I */
380 * dst = HMEF, src = HMEFTI
382 INSTR_ALU_OR, /* dst = MEF, src = MEFT */
383 INSTR_ALU_OR_S, /* (dst, src) = (MEF, H) or (dst, src) = (H, MEFT) */
384 INSTR_ALU_OR_I, /* dst = HMEF, src = I */
388 * dst = HMEF, src = HMEFTI
390 INSTR_ALU_XOR, /* dst = MEF, src = MEFT */
391 INSTR_ALU_XOR_S, /* (dst, src) = (MEF, H) or (dst, src) = (H, MEFT) */
392 INSTR_ALU_XOR_I, /* dst = HMEF, src = I */
396 * dst = HMEF, src = HMEFTI
398 INSTR_ALU_SHL, /* dst = MEF, src = MEF */
399 INSTR_ALU_SHL_MH, /* dst = MEF, src = H */
400 INSTR_ALU_SHL_HM, /* dst = H, src = MEF */
401 INSTR_ALU_SHL_HH, /* dst = H, src = H */
402 INSTR_ALU_SHL_MI, /* dst = MEF, src = I */
403 INSTR_ALU_SHL_HI, /* dst = H, src = I */
407 * dst = HMEF, src = HMEFTI
409 INSTR_ALU_SHR, /* dst = MEF, src = MEF */
410 INSTR_ALU_SHR_MH, /* dst = MEF, src = H */
411 INSTR_ALU_SHR_HM, /* dst = H, src = MEF */
412 INSTR_ALU_SHR_HH, /* dst = H, src = H */
413 INSTR_ALU_SHR_MI, /* dst = MEF, src = I */
414 INSTR_ALU_SHR_HI, /* dst = H, src = I */
416 /* regprefetch REGARRAY index
417 * prefetch REGARRAY[index]
420 INSTR_REGPREFETCH_RH, /* index = H */
421 INSTR_REGPREFETCH_RM, /* index = MEFT */
422 INSTR_REGPREFETCH_RI, /* index = I */
424 /* regrd dst REGARRAY index
425 * dst = REGARRAY[index]
426 * dst = HMEF, index = HMEFTI
428 INSTR_REGRD_HRH, /* dst = H, index = H */
429 INSTR_REGRD_HRM, /* dst = H, index = MEFT */
430 INSTR_REGRD_HRI, /* dst = H, index = I */
431 INSTR_REGRD_MRH, /* dst = MEF, index = H */
432 INSTR_REGRD_MRM, /* dst = MEF, index = MEFT */
433 INSTR_REGRD_MRI, /* dst = MEF, index = I */
435 /* regwr REGARRAY index src
436 * REGARRAY[index] = src
437 * index = HMEFTI, src = HMEFTI
439 INSTR_REGWR_RHH, /* index = H, src = H */
440 INSTR_REGWR_RHM, /* index = H, src = MEFT */
441 INSTR_REGWR_RHI, /* index = H, src = I */
442 INSTR_REGWR_RMH, /* index = MEFT, src = H */
443 INSTR_REGWR_RMM, /* index = MEFT, src = MEFT */
444 INSTR_REGWR_RMI, /* index = MEFT, src = I */
445 INSTR_REGWR_RIH, /* index = I, src = H */
446 INSTR_REGWR_RIM, /* index = I, src = MEFT */
447 INSTR_REGWR_RII, /* index = I, src = I */
449 /* regadd REGARRAY index src
450 * REGARRAY[index] += src
451 * index = HMEFTI, src = HMEFTI
453 INSTR_REGADD_RHH, /* index = H, src = H */
454 INSTR_REGADD_RHM, /* index = H, src = MEFT */
455 INSTR_REGADD_RHI, /* index = H, src = I */
456 INSTR_REGADD_RMH, /* index = MEFT, src = H */
457 INSTR_REGADD_RMM, /* index = MEFT, src = MEFT */
458 INSTR_REGADD_RMI, /* index = MEFT, src = I */
459 INSTR_REGADD_RIH, /* index = I, src = H */
460 INSTR_REGADD_RIM, /* index = I, src = MEFT */
461 INSTR_REGADD_RII, /* index = I, src = I */
463 /* metprefetch METARRAY index
464 * prefetch METARRAY[index]
467 INSTR_METPREFETCH_H, /* index = H */
468 INSTR_METPREFETCH_M, /* index = MEFT */
469 INSTR_METPREFETCH_I, /* index = I */
471 /* meter METARRAY index length color_in color_out
472 * color_out = meter(METARRAY[index], length, color_in)
473 * index = HMEFTI, length = HMEFT, color_in = MEFTI, color_out = MEF
475 INSTR_METER_HHM, /* index = H, length = H, color_in = MEFT */
476 INSTR_METER_HHI, /* index = H, length = H, color_in = I */
477 INSTR_METER_HMM, /* index = H, length = MEFT, color_in = MEFT */
478 INSTR_METER_HMI, /* index = H, length = MEFT, color_in = I */
479 INSTR_METER_MHM, /* index = MEFT, length = H, color_in = MEFT */
480 INSTR_METER_MHI, /* index = MEFT, length = H, color_in = I */
481 INSTR_METER_MMM, /* index = MEFT, length = MEFT, color_in = MEFT */
482 INSTR_METER_MMI, /* index = MEFT, length = MEFT, color_in = I */
483 INSTR_METER_IHM, /* index = I, length = H, color_in = MEFT */
484 INSTR_METER_IHI, /* index = I, length = H, color_in = I */
485 INSTR_METER_IMM, /* index = I, length = MEFT, color_in = MEFT */
486 INSTR_METER_IMI, /* index = I, length = MEFT, color_in = I */
491 /* extern e.obj.func */
502 /* jmpv LABEL h.header
503 * Jump if header is valid
507 /* jmpnv LABEL h.header
508 * Jump if header is invalid
513 * Jump if table lookup hit
518 * Jump if table lookup miss
525 INSTR_JMP_ACTION_HIT,
527 /* jmpna LABEL ACTION
528 * Jump if action not run
530 INSTR_JMP_ACTION_MISS,
533 * Jump is a is equal to b
534 * a = HMEFT, b = HMEFTI
536 INSTR_JMP_EQ, /* (a, b) = (MEFT, MEFT) or (a, b) = (H, H) */
537 INSTR_JMP_EQ_S, /* (a, b) = (MEFT, H) or (a, b) = (H, MEFT) */
538 INSTR_JMP_EQ_I, /* (a, b) = (MEFT, I) or (a, b) = (H, I) */
541 * Jump is a is not equal to b
542 * a = HMEFT, b = HMEFTI
544 INSTR_JMP_NEQ, /* (a, b) = (MEFT, MEFT) or (a, b) = (H, H) */
545 INSTR_JMP_NEQ_S, /* (a, b) = (MEFT, H) or (a, b) = (H, MEFT) */
546 INSTR_JMP_NEQ_I, /* (a, b) = (MEFT, I) or (a, b) = (H, I) */
549 * Jump if a is less than b
550 * a = HMEFT, b = HMEFTI
552 INSTR_JMP_LT, /* a = MEF, b = MEF */
553 INSTR_JMP_LT_MH, /* a = MEF, b = H */
554 INSTR_JMP_LT_HM, /* a = H, b = MEF */
555 INSTR_JMP_LT_HH, /* a = H, b = H */
556 INSTR_JMP_LT_MI, /* a = MEF, b = I */
557 INSTR_JMP_LT_HI, /* a = H, b = I */
560 * Jump if a is greater than b
561 * a = HMEFT, b = HMEFTI
563 INSTR_JMP_GT, /* a = MEF, b = MEF */
564 INSTR_JMP_GT_MH, /* a = MEF, b = H */
565 INSTR_JMP_GT_HM, /* a = H, b = MEF */
566 INSTR_JMP_GT_HH, /* a = H, b = H */
567 INSTR_JMP_GT_MI, /* a = MEF, b = I */
568 INSTR_JMP_GT_HI, /* a = H, b = I */
576 struct instr_operand {
591 uint8_t header_id[8];
592 uint8_t struct_id[8];
597 struct instr_hdr_validity {
605 struct instr_extern_obj {
610 struct instr_extern_func {
614 struct instr_dst_src {
615 struct instr_operand dst;
617 struct instr_operand src;
622 struct instr_regarray {
627 struct instr_operand idx;
632 struct instr_operand dstsrc;
642 struct instr_operand idx;
646 struct instr_operand length;
649 struct instr_operand color_in;
650 uint32_t color_in_val;
653 struct instr_operand color_out;
658 uint8_t header_id[8];
659 uint8_t struct_id[8];
670 struct instruction *ip;
673 struct instr_operand a;
679 struct instr_operand b;
685 enum instruction_type type;
688 struct instr_hdr_validity valid;
689 struct instr_dst_src mov;
690 struct instr_regarray regarray;
691 struct instr_meter meter;
692 struct instr_dma dma;
693 struct instr_dst_src alu;
694 struct instr_table table;
695 struct instr_extern_obj ext_obj;
696 struct instr_extern_func ext_func;
697 struct instr_jmp jmp;
701 struct instruction_data {
702 char label[RTE_SWX_NAME_SIZE];
703 char jmp_label[RTE_SWX_NAME_SIZE];
704 uint32_t n_users; /* user = jmp instruction to this instruction. */
712 TAILQ_ENTRY(action) node;
713 char name[RTE_SWX_NAME_SIZE];
714 struct struct_type *st;
715 struct instruction *instructions;
716 uint32_t n_instructions;
720 TAILQ_HEAD(action_tailq, action);
726 TAILQ_ENTRY(table_type) node;
727 char name[RTE_SWX_NAME_SIZE];
728 enum rte_swx_table_match_type match_type;
729 struct rte_swx_table_ops ops;
732 TAILQ_HEAD(table_type_tailq, table_type);
735 enum rte_swx_table_match_type match_type;
740 TAILQ_ENTRY(table) node;
741 char name[RTE_SWX_NAME_SIZE];
742 char args[RTE_SWX_NAME_SIZE];
743 struct table_type *type; /* NULL when n_fields == 0. */
746 struct match_field *fields;
748 struct header *header; /* Only valid when n_fields > 0. */
751 struct action **actions;
752 struct action *default_action;
753 uint8_t *default_action_data;
755 int default_action_is_const;
756 uint32_t action_data_size_max;
762 TAILQ_HEAD(table_tailq, table);
764 struct table_runtime {
765 rte_swx_table_lookup_t func;
774 TAILQ_ENTRY(regarray) node;
775 char name[RTE_SWX_NAME_SIZE];
781 TAILQ_HEAD(regarray_tailq, regarray);
783 struct regarray_runtime {
791 struct meter_profile {
792 TAILQ_ENTRY(meter_profile) node;
793 char name[RTE_SWX_NAME_SIZE];
794 struct rte_meter_trtcm_params params;
795 struct rte_meter_trtcm_profile profile;
799 TAILQ_HEAD(meter_profile_tailq, meter_profile);
802 TAILQ_ENTRY(metarray) node;
803 char name[RTE_SWX_NAME_SIZE];
808 TAILQ_HEAD(metarray_tailq, metarray);
811 struct rte_meter_trtcm m;
812 struct meter_profile *profile;
813 enum rte_color color_mask;
816 uint64_t n_pkts[RTE_COLORS];
817 uint64_t n_bytes[RTE_COLORS];
820 struct metarray_runtime {
821 struct meter *metarray;
830 struct rte_swx_pkt pkt;
836 /* Packet headers. */
837 struct header_runtime *headers; /* Extracted or generated headers. */
838 struct header_out_runtime *headers_out; /* Emitted headers. */
839 uint8_t *header_storage;
840 uint8_t *header_out_storage;
841 uint64_t valid_headers;
842 uint32_t n_headers_out;
844 /* Packet meta-data. */
848 struct table_runtime *tables;
849 struct rte_swx_table_state *table_state;
851 int hit; /* 0 = Miss, 1 = Hit. */
853 /* Extern objects and functions. */
854 struct extern_obj_runtime *extern_objs;
855 struct extern_func_runtime *extern_funcs;
858 struct instruction *ip;
859 struct instruction *ret;
862 #define MASK64_BIT_GET(mask, pos) ((mask) & (1LLU << (pos)))
863 #define MASK64_BIT_SET(mask, pos) ((mask) | (1LLU << (pos)))
864 #define MASK64_BIT_CLR(mask, pos) ((mask) & ~(1LLU << (pos)))
866 #define HEADER_VALID(thread, header_id) \
867 MASK64_BIT_GET((thread)->valid_headers, header_id)
869 #define ALU(thread, ip, operator) \
871 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
872 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
873 uint64_t dst64 = *dst64_ptr; \
874 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
875 uint64_t dst = dst64 & dst64_mask; \
877 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
878 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
879 uint64_t src64 = *src64_ptr; \
880 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->alu.src.n_bits); \
881 uint64_t src = src64 & src64_mask; \
883 uint64_t result = dst operator src; \
885 *dst64_ptr = (dst64 & ~dst64_mask) | (result & dst64_mask); \
888 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
890 #define ALU_S(thread, ip, operator) \
892 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
893 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
894 uint64_t dst64 = *dst64_ptr; \
895 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
896 uint64_t dst = dst64 & dst64_mask; \
898 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
899 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
900 uint64_t src64 = *src64_ptr; \
901 uint64_t src = ntoh64(src64) >> (64 - (ip)->alu.src.n_bits); \
903 uint64_t result = dst operator src; \
905 *dst64_ptr = (dst64 & ~dst64_mask) | (result & dst64_mask); \
910 #define ALU_HM(thread, ip, operator) \
912 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
913 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
914 uint64_t dst64 = *dst64_ptr; \
915 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
916 uint64_t dst = ntoh64(dst64) >> (64 - (ip)->alu.dst.n_bits); \
918 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
919 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
920 uint64_t src64 = *src64_ptr; \
921 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->alu.src.n_bits); \
922 uint64_t src = src64 & src64_mask; \
924 uint64_t result = dst operator src; \
925 result = hton64(result << (64 - (ip)->alu.dst.n_bits)); \
927 *dst64_ptr = (dst64 & ~dst64_mask) | result; \
930 #define ALU_HH(thread, ip, operator) \
932 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
933 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
934 uint64_t dst64 = *dst64_ptr; \
935 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
936 uint64_t dst = ntoh64(dst64) >> (64 - (ip)->alu.dst.n_bits); \
938 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
939 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
940 uint64_t src64 = *src64_ptr; \
941 uint64_t src = ntoh64(src64) >> (64 - (ip)->alu.src.n_bits); \
943 uint64_t result = dst operator src; \
944 result = hton64(result << (64 - (ip)->alu.dst.n_bits)); \
946 *dst64_ptr = (dst64 & ~dst64_mask) | result; \
958 #define ALU_I(thread, ip, operator) \
960 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
961 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
962 uint64_t dst64 = *dst64_ptr; \
963 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
964 uint64_t dst = dst64 & dst64_mask; \
966 uint64_t src = (ip)->alu.src_val; \
968 uint64_t result = dst operator src; \
970 *dst64_ptr = (dst64 & ~dst64_mask) | (result & dst64_mask); \
975 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
977 #define ALU_HI(thread, ip, operator) \
979 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
980 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
981 uint64_t dst64 = *dst64_ptr; \
982 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
983 uint64_t dst = ntoh64(dst64) >> (64 - (ip)->alu.dst.n_bits); \
985 uint64_t src = (ip)->alu.src_val; \
987 uint64_t result = dst operator src; \
988 result = hton64(result << (64 - (ip)->alu.dst.n_bits)); \
990 *dst64_ptr = (dst64 & ~dst64_mask) | result; \
999 #define MOV(thread, ip) \
1001 uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id]; \
1002 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset]; \
1003 uint64_t dst64 = *dst64_ptr; \
1004 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits); \
1006 uint8_t *src_struct = (thread)->structs[(ip)->mov.src.struct_id]; \
1007 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->mov.src.offset]; \
1008 uint64_t src64 = *src64_ptr; \
1009 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->mov.src.n_bits); \
1010 uint64_t src = src64 & src64_mask; \
1012 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask); \
1015 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1017 #define MOV_S(thread, ip) \
1019 uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id]; \
1020 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset]; \
1021 uint64_t dst64 = *dst64_ptr; \
1022 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits); \
1024 uint8_t *src_struct = (thread)->structs[(ip)->mov.src.struct_id]; \
1025 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->mov.src.offset]; \
1026 uint64_t src64 = *src64_ptr; \
1027 uint64_t src = ntoh64(src64) >> (64 - (ip)->mov.src.n_bits); \
1029 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask); \
1038 #define MOV_I(thread, ip) \
1040 uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id]; \
1041 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset]; \
1042 uint64_t dst64 = *dst64_ptr; \
1043 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits); \
1045 uint64_t src = (ip)->mov.src_val; \
1047 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask); \
1050 #define JMP_CMP(thread, ip, operator) \
1052 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1053 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1054 uint64_t a64 = *a64_ptr; \
1055 uint64_t a64_mask = UINT64_MAX >> (64 - (ip)->jmp.a.n_bits); \
1056 uint64_t a = a64 & a64_mask; \
1058 uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id]; \
1059 uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset]; \
1060 uint64_t b64 = *b64_ptr; \
1061 uint64_t b64_mask = UINT64_MAX >> (64 - (ip)->jmp.b.n_bits); \
1062 uint64_t b = b64 & b64_mask; \
1064 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1067 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1069 #define JMP_CMP_S(thread, ip, operator) \
1071 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1072 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1073 uint64_t a64 = *a64_ptr; \
1074 uint64_t a64_mask = UINT64_MAX >> (64 - (ip)->jmp.a.n_bits); \
1075 uint64_t a = a64 & a64_mask; \
1077 uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id]; \
1078 uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset]; \
1079 uint64_t b64 = *b64_ptr; \
1080 uint64_t b = ntoh64(b64) >> (64 - (ip)->jmp.b.n_bits); \
1082 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1085 #define JMP_CMP_MH JMP_CMP_S
1087 #define JMP_CMP_HM(thread, ip, operator) \
1089 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1090 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1091 uint64_t a64 = *a64_ptr; \
1092 uint64_t a = ntoh64(a64) >> (64 - (ip)->jmp.a.n_bits); \
1094 uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id]; \
1095 uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset]; \
1096 uint64_t b64 = *b64_ptr; \
1097 uint64_t b64_mask = UINT64_MAX >> (64 - (ip)->jmp.b.n_bits); \
1098 uint64_t b = b64 & b64_mask; \
1100 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1103 #define JMP_CMP_HH(thread, ip, operator) \
1105 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1106 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1107 uint64_t a64 = *a64_ptr; \
1108 uint64_t a = ntoh64(a64) >> (64 - (ip)->jmp.a.n_bits); \
1110 uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id]; \
1111 uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset]; \
1112 uint64_t b64 = *b64_ptr; \
1113 uint64_t b = ntoh64(b64) >> (64 - (ip)->jmp.b.n_bits); \
1115 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1120 #define JMP_CMP_S JMP_CMP
1121 #define JMP_CMP_MH JMP_CMP
1122 #define JMP_CMP_HM JMP_CMP
1123 #define JMP_CMP_HH JMP_CMP
1127 #define JMP_CMP_I(thread, ip, operator) \
1129 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1130 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1131 uint64_t a64 = *a64_ptr; \
1132 uint64_t a64_mask = UINT64_MAX >> (64 - (ip)->jmp.a.n_bits); \
1133 uint64_t a = a64 & a64_mask; \
1135 uint64_t b = (ip)->jmp.b_val; \
1137 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1140 #define JMP_CMP_MI JMP_CMP_I
1142 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1144 #define JMP_CMP_HI(thread, ip, operator) \
1146 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1147 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1148 uint64_t a64 = *a64_ptr; \
1149 uint64_t a = ntoh64(a64) >> (64 - (ip)->jmp.a.n_bits); \
1151 uint64_t b = (ip)->jmp.b_val; \
1153 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1158 #define JMP_CMP_HI JMP_CMP_I
1162 #define METADATA_READ(thread, offset, n_bits) \
1164 uint64_t *m64_ptr = (uint64_t *)&(thread)->metadata[offset]; \
1165 uint64_t m64 = *m64_ptr; \
1166 uint64_t m64_mask = UINT64_MAX >> (64 - (n_bits)); \
1170 #define METADATA_WRITE(thread, offset, n_bits, value) \
1172 uint64_t *m64_ptr = (uint64_t *)&(thread)->metadata[offset]; \
1173 uint64_t m64 = *m64_ptr; \
1174 uint64_t m64_mask = UINT64_MAX >> (64 - (n_bits)); \
1176 uint64_t m_new = value; \
1178 *m64_ptr = (m64 & ~m64_mask) | (m_new & m64_mask); \
1181 #ifndef RTE_SWX_PIPELINE_THREADS_MAX
1182 #define RTE_SWX_PIPELINE_THREADS_MAX 16
1185 struct rte_swx_pipeline {
1186 struct struct_type_tailq struct_types;
1187 struct port_in_type_tailq port_in_types;
1188 struct port_in_tailq ports_in;
1189 struct port_out_type_tailq port_out_types;
1190 struct port_out_tailq ports_out;
1191 struct extern_type_tailq extern_types;
1192 struct extern_obj_tailq extern_objs;
1193 struct extern_func_tailq extern_funcs;
1194 struct header_tailq headers;
1195 struct struct_type *metadata_st;
1196 uint32_t metadata_struct_id;
1197 struct action_tailq actions;
1198 struct table_type_tailq table_types;
1199 struct table_tailq tables;
1200 struct regarray_tailq regarrays;
1201 struct meter_profile_tailq meter_profiles;
1202 struct metarray_tailq metarrays;
1204 struct port_in_runtime *in;
1205 struct port_out_runtime *out;
1206 struct instruction **action_instructions;
1207 struct rte_swx_table_state *table_state;
1208 struct regarray_runtime *regarray_runtime;
1209 struct metarray_runtime *metarray_runtime;
1210 struct instruction *instructions;
1211 struct thread threads[RTE_SWX_PIPELINE_THREADS_MAX];
1214 uint32_t n_ports_in;
1215 uint32_t n_ports_out;
1216 uint32_t n_extern_objs;
1217 uint32_t n_extern_funcs;
1220 uint32_t n_regarrays;
1221 uint32_t n_metarrays;
1225 uint32_t n_instructions;
1233 static struct struct_type *
1234 struct_type_find(struct rte_swx_pipeline *p, const char *name)
1236 struct struct_type *elem;
1238 TAILQ_FOREACH(elem, &p->struct_types, node)
1239 if (strcmp(elem->name, name) == 0)
1245 static struct field *
1246 struct_type_field_find(struct struct_type *st, const char *name)
1250 for (i = 0; i < st->n_fields; i++) {
1251 struct field *f = &st->fields[i];
1253 if (strcmp(f->name, name) == 0)
1261 rte_swx_pipeline_struct_type_register(struct rte_swx_pipeline *p,
1263 struct rte_swx_field_params *fields,
1266 struct struct_type *st;
1270 CHECK_NAME(name, EINVAL);
1271 CHECK(fields, EINVAL);
1272 CHECK(n_fields, EINVAL);
1274 for (i = 0; i < n_fields; i++) {
1275 struct rte_swx_field_params *f = &fields[i];
1278 CHECK_NAME(f->name, EINVAL);
1279 CHECK(f->n_bits, EINVAL);
1280 CHECK(f->n_bits <= 64, EINVAL);
1281 CHECK((f->n_bits & 7) == 0, EINVAL);
1283 for (j = 0; j < i; j++) {
1284 struct rte_swx_field_params *f_prev = &fields[j];
1286 CHECK(strcmp(f->name, f_prev->name), EINVAL);
1290 CHECK(!struct_type_find(p, name), EEXIST);
1292 /* Node allocation. */
1293 st = calloc(1, sizeof(struct struct_type));
1296 st->fields = calloc(n_fields, sizeof(struct field));
1302 /* Node initialization. */
1303 strcpy(st->name, name);
1304 for (i = 0; i < n_fields; i++) {
1305 struct field *dst = &st->fields[i];
1306 struct rte_swx_field_params *src = &fields[i];
1308 strcpy(dst->name, src->name);
1309 dst->n_bits = src->n_bits;
1310 dst->offset = st->n_bits;
1312 st->n_bits += src->n_bits;
1314 st->n_fields = n_fields;
1316 /* Node add to tailq. */
1317 TAILQ_INSERT_TAIL(&p->struct_types, st, node);
1323 struct_build(struct rte_swx_pipeline *p)
1327 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1328 struct thread *t = &p->threads[i];
1330 t->structs = calloc(p->n_structs, sizeof(uint8_t *));
1331 CHECK(t->structs, ENOMEM);
1338 struct_build_free(struct rte_swx_pipeline *p)
1342 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1343 struct thread *t = &p->threads[i];
1351 struct_free(struct rte_swx_pipeline *p)
1353 struct_build_free(p);
1357 struct struct_type *elem;
1359 elem = TAILQ_FIRST(&p->struct_types);
1363 TAILQ_REMOVE(&p->struct_types, elem, node);
1372 static struct port_in_type *
1373 port_in_type_find(struct rte_swx_pipeline *p, const char *name)
1375 struct port_in_type *elem;
1380 TAILQ_FOREACH(elem, &p->port_in_types, node)
1381 if (strcmp(elem->name, name) == 0)
1388 rte_swx_pipeline_port_in_type_register(struct rte_swx_pipeline *p,
1390 struct rte_swx_port_in_ops *ops)
1392 struct port_in_type *elem;
1395 CHECK_NAME(name, EINVAL);
1397 CHECK(ops->create, EINVAL);
1398 CHECK(ops->free, EINVAL);
1399 CHECK(ops->pkt_rx, EINVAL);
1400 CHECK(ops->stats_read, EINVAL);
1402 CHECK(!port_in_type_find(p, name), EEXIST);
1404 /* Node allocation. */
1405 elem = calloc(1, sizeof(struct port_in_type));
1406 CHECK(elem, ENOMEM);
1408 /* Node initialization. */
1409 strcpy(elem->name, name);
1410 memcpy(&elem->ops, ops, sizeof(*ops));
1412 /* Node add to tailq. */
1413 TAILQ_INSERT_TAIL(&p->port_in_types, elem, node);
1418 static struct port_in *
1419 port_in_find(struct rte_swx_pipeline *p, uint32_t port_id)
1421 struct port_in *port;
1423 TAILQ_FOREACH(port, &p->ports_in, node)
1424 if (port->id == port_id)
1431 rte_swx_pipeline_port_in_config(struct rte_swx_pipeline *p,
1433 const char *port_type_name,
1436 struct port_in_type *type = NULL;
1437 struct port_in *port = NULL;
1442 CHECK(!port_in_find(p, port_id), EINVAL);
1444 CHECK_NAME(port_type_name, EINVAL);
1445 type = port_in_type_find(p, port_type_name);
1446 CHECK(type, EINVAL);
1448 obj = type->ops.create(args);
1451 /* Node allocation. */
1452 port = calloc(1, sizeof(struct port_in));
1453 CHECK(port, ENOMEM);
1455 /* Node initialization. */
1460 /* Node add to tailq. */
1461 TAILQ_INSERT_TAIL(&p->ports_in, port, node);
1462 if (p->n_ports_in < port_id + 1)
1463 p->n_ports_in = port_id + 1;
1469 port_in_build(struct rte_swx_pipeline *p)
1471 struct port_in *port;
1474 CHECK(p->n_ports_in, EINVAL);
1475 CHECK(rte_is_power_of_2(p->n_ports_in), EINVAL);
1477 for (i = 0; i < p->n_ports_in; i++)
1478 CHECK(port_in_find(p, i), EINVAL);
1480 p->in = calloc(p->n_ports_in, sizeof(struct port_in_runtime));
1481 CHECK(p->in, ENOMEM);
1483 TAILQ_FOREACH(port, &p->ports_in, node) {
1484 struct port_in_runtime *in = &p->in[port->id];
1486 in->pkt_rx = port->type->ops.pkt_rx;
1487 in->obj = port->obj;
1494 port_in_build_free(struct rte_swx_pipeline *p)
1501 port_in_free(struct rte_swx_pipeline *p)
1503 port_in_build_free(p);
1507 struct port_in *port;
1509 port = TAILQ_FIRST(&p->ports_in);
1513 TAILQ_REMOVE(&p->ports_in, port, node);
1514 port->type->ops.free(port->obj);
1518 /* Input port types. */
1520 struct port_in_type *elem;
1522 elem = TAILQ_FIRST(&p->port_in_types);
1526 TAILQ_REMOVE(&p->port_in_types, elem, node);
1534 static struct port_out_type *
1535 port_out_type_find(struct rte_swx_pipeline *p, const char *name)
1537 struct port_out_type *elem;
1542 TAILQ_FOREACH(elem, &p->port_out_types, node)
1543 if (!strcmp(elem->name, name))
1550 rte_swx_pipeline_port_out_type_register(struct rte_swx_pipeline *p,
1552 struct rte_swx_port_out_ops *ops)
1554 struct port_out_type *elem;
1557 CHECK_NAME(name, EINVAL);
1559 CHECK(ops->create, EINVAL);
1560 CHECK(ops->free, EINVAL);
1561 CHECK(ops->pkt_tx, EINVAL);
1562 CHECK(ops->stats_read, EINVAL);
1564 CHECK(!port_out_type_find(p, name), EEXIST);
1566 /* Node allocation. */
1567 elem = calloc(1, sizeof(struct port_out_type));
1568 CHECK(elem, ENOMEM);
1570 /* Node initialization. */
1571 strcpy(elem->name, name);
1572 memcpy(&elem->ops, ops, sizeof(*ops));
1574 /* Node add to tailq. */
1575 TAILQ_INSERT_TAIL(&p->port_out_types, elem, node);
1580 static struct port_out *
1581 port_out_find(struct rte_swx_pipeline *p, uint32_t port_id)
1583 struct port_out *port;
1585 TAILQ_FOREACH(port, &p->ports_out, node)
1586 if (port->id == port_id)
1593 rte_swx_pipeline_port_out_config(struct rte_swx_pipeline *p,
1595 const char *port_type_name,
1598 struct port_out_type *type = NULL;
1599 struct port_out *port = NULL;
1604 CHECK(!port_out_find(p, port_id), EINVAL);
1606 CHECK_NAME(port_type_name, EINVAL);
1607 type = port_out_type_find(p, port_type_name);
1608 CHECK(type, EINVAL);
1610 obj = type->ops.create(args);
1613 /* Node allocation. */
1614 port = calloc(1, sizeof(struct port_out));
1615 CHECK(port, ENOMEM);
1617 /* Node initialization. */
1622 /* Node add to tailq. */
1623 TAILQ_INSERT_TAIL(&p->ports_out, port, node);
1624 if (p->n_ports_out < port_id + 1)
1625 p->n_ports_out = port_id + 1;
1631 port_out_build(struct rte_swx_pipeline *p)
1633 struct port_out *port;
1636 CHECK(p->n_ports_out, EINVAL);
1638 for (i = 0; i < p->n_ports_out; i++)
1639 CHECK(port_out_find(p, i), EINVAL);
1641 p->out = calloc(p->n_ports_out, sizeof(struct port_out_runtime));
1642 CHECK(p->out, ENOMEM);
1644 TAILQ_FOREACH(port, &p->ports_out, node) {
1645 struct port_out_runtime *out = &p->out[port->id];
1647 out->pkt_tx = port->type->ops.pkt_tx;
1648 out->flush = port->type->ops.flush;
1649 out->obj = port->obj;
1656 port_out_build_free(struct rte_swx_pipeline *p)
1663 port_out_free(struct rte_swx_pipeline *p)
1665 port_out_build_free(p);
1669 struct port_out *port;
1671 port = TAILQ_FIRST(&p->ports_out);
1675 TAILQ_REMOVE(&p->ports_out, port, node);
1676 port->type->ops.free(port->obj);
1680 /* Output port types. */
1682 struct port_out_type *elem;
1684 elem = TAILQ_FIRST(&p->port_out_types);
1688 TAILQ_REMOVE(&p->port_out_types, elem, node);
1696 static struct extern_type *
1697 extern_type_find(struct rte_swx_pipeline *p, const char *name)
1699 struct extern_type *elem;
1701 TAILQ_FOREACH(elem, &p->extern_types, node)
1702 if (strcmp(elem->name, name) == 0)
1708 static struct extern_type_member_func *
1709 extern_type_member_func_find(struct extern_type *type, const char *name)
1711 struct extern_type_member_func *elem;
1713 TAILQ_FOREACH(elem, &type->funcs, node)
1714 if (strcmp(elem->name, name) == 0)
1720 static struct extern_obj *
1721 extern_obj_find(struct rte_swx_pipeline *p, const char *name)
1723 struct extern_obj *elem;
1725 TAILQ_FOREACH(elem, &p->extern_objs, node)
1726 if (strcmp(elem->name, name) == 0)
1732 static struct extern_type_member_func *
1733 extern_obj_member_func_parse(struct rte_swx_pipeline *p,
1735 struct extern_obj **obj)
1737 struct extern_obj *object;
1738 struct extern_type_member_func *func;
1739 char *object_name, *func_name;
1741 if (name[0] != 'e' || name[1] != '.')
1744 object_name = strdup(&name[2]);
1748 func_name = strchr(object_name, '.');
1757 object = extern_obj_find(p, object_name);
1763 func = extern_type_member_func_find(object->type, func_name);
1776 static struct field *
1777 extern_obj_mailbox_field_parse(struct rte_swx_pipeline *p,
1779 struct extern_obj **object)
1781 struct extern_obj *obj;
1783 char *obj_name, *field_name;
1785 if ((name[0] != 'e') || (name[1] != '.'))
1788 obj_name = strdup(&name[2]);
1792 field_name = strchr(obj_name, '.');
1801 obj = extern_obj_find(p, obj_name);
1807 f = struct_type_field_find(obj->type->mailbox_struct_type, field_name);
1821 rte_swx_pipeline_extern_type_register(struct rte_swx_pipeline *p,
1823 const char *mailbox_struct_type_name,
1824 rte_swx_extern_type_constructor_t constructor,
1825 rte_swx_extern_type_destructor_t destructor)
1827 struct extern_type *elem;
1828 struct struct_type *mailbox_struct_type;
1832 CHECK_NAME(name, EINVAL);
1833 CHECK(!extern_type_find(p, name), EEXIST);
1835 CHECK_NAME(mailbox_struct_type_name, EINVAL);
1836 mailbox_struct_type = struct_type_find(p, mailbox_struct_type_name);
1837 CHECK(mailbox_struct_type, EINVAL);
1839 CHECK(constructor, EINVAL);
1840 CHECK(destructor, EINVAL);
1842 /* Node allocation. */
1843 elem = calloc(1, sizeof(struct extern_type));
1844 CHECK(elem, ENOMEM);
1846 /* Node initialization. */
1847 strcpy(elem->name, name);
1848 elem->mailbox_struct_type = mailbox_struct_type;
1849 elem->constructor = constructor;
1850 elem->destructor = destructor;
1851 TAILQ_INIT(&elem->funcs);
1853 /* Node add to tailq. */
1854 TAILQ_INSERT_TAIL(&p->extern_types, elem, node);
1860 rte_swx_pipeline_extern_type_member_func_register(struct rte_swx_pipeline *p,
1861 const char *extern_type_name,
1863 rte_swx_extern_type_member_func_t member_func)
1865 struct extern_type *type;
1866 struct extern_type_member_func *type_member;
1870 CHECK_NAME(extern_type_name, EINVAL);
1871 type = extern_type_find(p, extern_type_name);
1872 CHECK(type, EINVAL);
1873 CHECK(type->n_funcs < RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX, ENOSPC);
1875 CHECK_NAME(name, EINVAL);
1876 CHECK(!extern_type_member_func_find(type, name), EEXIST);
1878 CHECK(member_func, EINVAL);
1880 /* Node allocation. */
1881 type_member = calloc(1, sizeof(struct extern_type_member_func));
1882 CHECK(type_member, ENOMEM);
1884 /* Node initialization. */
1885 strcpy(type_member->name, name);
1886 type_member->func = member_func;
1887 type_member->id = type->n_funcs;
1889 /* Node add to tailq. */
1890 TAILQ_INSERT_TAIL(&type->funcs, type_member, node);
1897 rte_swx_pipeline_extern_object_config(struct rte_swx_pipeline *p,
1898 const char *extern_type_name,
1902 struct extern_type *type;
1903 struct extern_obj *obj;
1908 CHECK_NAME(extern_type_name, EINVAL);
1909 type = extern_type_find(p, extern_type_name);
1910 CHECK(type, EINVAL);
1912 CHECK_NAME(name, EINVAL);
1913 CHECK(!extern_obj_find(p, name), EEXIST);
1915 /* Node allocation. */
1916 obj = calloc(1, sizeof(struct extern_obj));
1919 /* Object construction. */
1920 obj_handle = type->constructor(args);
1926 /* Node initialization. */
1927 strcpy(obj->name, name);
1929 obj->obj = obj_handle;
1930 obj->struct_id = p->n_structs;
1931 obj->id = p->n_extern_objs;
1933 /* Node add to tailq. */
1934 TAILQ_INSERT_TAIL(&p->extern_objs, obj, node);
1942 extern_obj_build(struct rte_swx_pipeline *p)
1946 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1947 struct thread *t = &p->threads[i];
1948 struct extern_obj *obj;
1950 t->extern_objs = calloc(p->n_extern_objs,
1951 sizeof(struct extern_obj_runtime));
1952 CHECK(t->extern_objs, ENOMEM);
1954 TAILQ_FOREACH(obj, &p->extern_objs, node) {
1955 struct extern_obj_runtime *r =
1956 &t->extern_objs[obj->id];
1957 struct extern_type_member_func *func;
1958 uint32_t mailbox_size =
1959 obj->type->mailbox_struct_type->n_bits / 8;
1963 r->mailbox = calloc(1, mailbox_size);
1964 CHECK(r->mailbox, ENOMEM);
1966 TAILQ_FOREACH(func, &obj->type->funcs, node)
1967 r->funcs[func->id] = func->func;
1969 t->structs[obj->struct_id] = r->mailbox;
1977 extern_obj_build_free(struct rte_swx_pipeline *p)
1981 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1982 struct thread *t = &p->threads[i];
1985 if (!t->extern_objs)
1988 for (j = 0; j < p->n_extern_objs; j++) {
1989 struct extern_obj_runtime *r = &t->extern_objs[j];
1994 free(t->extern_objs);
1995 t->extern_objs = NULL;
2000 extern_obj_free(struct rte_swx_pipeline *p)
2002 extern_obj_build_free(p);
2004 /* Extern objects. */
2006 struct extern_obj *elem;
2008 elem = TAILQ_FIRST(&p->extern_objs);
2012 TAILQ_REMOVE(&p->extern_objs, elem, node);
2014 elem->type->destructor(elem->obj);
2020 struct extern_type *elem;
2022 elem = TAILQ_FIRST(&p->extern_types);
2026 TAILQ_REMOVE(&p->extern_types, elem, node);
2029 struct extern_type_member_func *func;
2031 func = TAILQ_FIRST(&elem->funcs);
2035 TAILQ_REMOVE(&elem->funcs, func, node);
2046 static struct extern_func *
2047 extern_func_find(struct rte_swx_pipeline *p, const char *name)
2049 struct extern_func *elem;
2051 TAILQ_FOREACH(elem, &p->extern_funcs, node)
2052 if (strcmp(elem->name, name) == 0)
2058 static struct extern_func *
2059 extern_func_parse(struct rte_swx_pipeline *p,
2062 if (name[0] != 'f' || name[1] != '.')
2065 return extern_func_find(p, &name[2]);
2068 static struct field *
2069 extern_func_mailbox_field_parse(struct rte_swx_pipeline *p,
2071 struct extern_func **function)
2073 struct extern_func *func;
2075 char *func_name, *field_name;
2077 if ((name[0] != 'f') || (name[1] != '.'))
2080 func_name = strdup(&name[2]);
2084 field_name = strchr(func_name, '.');
2093 func = extern_func_find(p, func_name);
2099 f = struct_type_field_find(func->mailbox_struct_type, field_name);
2113 rte_swx_pipeline_extern_func_register(struct rte_swx_pipeline *p,
2115 const char *mailbox_struct_type_name,
2116 rte_swx_extern_func_t func)
2118 struct extern_func *f;
2119 struct struct_type *mailbox_struct_type;
2123 CHECK_NAME(name, EINVAL);
2124 CHECK(!extern_func_find(p, name), EEXIST);
2126 CHECK_NAME(mailbox_struct_type_name, EINVAL);
2127 mailbox_struct_type = struct_type_find(p, mailbox_struct_type_name);
2128 CHECK(mailbox_struct_type, EINVAL);
2130 CHECK(func, EINVAL);
2132 /* Node allocation. */
2133 f = calloc(1, sizeof(struct extern_func));
2134 CHECK(func, ENOMEM);
2136 /* Node initialization. */
2137 strcpy(f->name, name);
2138 f->mailbox_struct_type = mailbox_struct_type;
2140 f->struct_id = p->n_structs;
2141 f->id = p->n_extern_funcs;
2143 /* Node add to tailq. */
2144 TAILQ_INSERT_TAIL(&p->extern_funcs, f, node);
2145 p->n_extern_funcs++;
2152 extern_func_build(struct rte_swx_pipeline *p)
2156 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
2157 struct thread *t = &p->threads[i];
2158 struct extern_func *func;
2160 /* Memory allocation. */
2161 t->extern_funcs = calloc(p->n_extern_funcs,
2162 sizeof(struct extern_func_runtime));
2163 CHECK(t->extern_funcs, ENOMEM);
2165 /* Extern function. */
2166 TAILQ_FOREACH(func, &p->extern_funcs, node) {
2167 struct extern_func_runtime *r =
2168 &t->extern_funcs[func->id];
2169 uint32_t mailbox_size =
2170 func->mailbox_struct_type->n_bits / 8;
2172 r->func = func->func;
2174 r->mailbox = calloc(1, mailbox_size);
2175 CHECK(r->mailbox, ENOMEM);
2177 t->structs[func->struct_id] = r->mailbox;
2185 extern_func_build_free(struct rte_swx_pipeline *p)
2189 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
2190 struct thread *t = &p->threads[i];
2193 if (!t->extern_funcs)
2196 for (j = 0; j < p->n_extern_funcs; j++) {
2197 struct extern_func_runtime *r = &t->extern_funcs[j];
2202 free(t->extern_funcs);
2203 t->extern_funcs = NULL;
2208 extern_func_free(struct rte_swx_pipeline *p)
2210 extern_func_build_free(p);
2213 struct extern_func *elem;
2215 elem = TAILQ_FIRST(&p->extern_funcs);
2219 TAILQ_REMOVE(&p->extern_funcs, elem, node);
2227 static struct header *
2228 header_find(struct rte_swx_pipeline *p, const char *name)
2230 struct header *elem;
2232 TAILQ_FOREACH(elem, &p->headers, node)
2233 if (strcmp(elem->name, name) == 0)
2239 static struct header *
2240 header_parse(struct rte_swx_pipeline *p,
2243 if (name[0] != 'h' || name[1] != '.')
2246 return header_find(p, &name[2]);
2249 static struct field *
2250 header_field_parse(struct rte_swx_pipeline *p,
2252 struct header **header)
2256 char *header_name, *field_name;
2258 if ((name[0] != 'h') || (name[1] != '.'))
2261 header_name = strdup(&name[2]);
2265 field_name = strchr(header_name, '.');
2274 h = header_find(p, header_name);
2280 f = struct_type_field_find(h->st, field_name);
2294 rte_swx_pipeline_packet_header_register(struct rte_swx_pipeline *p,
2296 const char *struct_type_name)
2298 struct struct_type *st;
2300 size_t n_headers_max;
2303 CHECK_NAME(name, EINVAL);
2304 CHECK_NAME(struct_type_name, EINVAL);
2306 CHECK(!header_find(p, name), EEXIST);
2308 st = struct_type_find(p, struct_type_name);
2311 n_headers_max = RTE_SIZEOF_FIELD(struct thread, valid_headers) * 8;
2312 CHECK(p->n_headers < n_headers_max, ENOSPC);
2314 /* Node allocation. */
2315 h = calloc(1, sizeof(struct header));
2318 /* Node initialization. */
2319 strcpy(h->name, name);
2321 h->struct_id = p->n_structs;
2322 h->id = p->n_headers;
2324 /* Node add to tailq. */
2325 TAILQ_INSERT_TAIL(&p->headers, h, node);
2333 header_build(struct rte_swx_pipeline *p)
2336 uint32_t n_bytes = 0, i;
2338 TAILQ_FOREACH(h, &p->headers, node) {
2339 n_bytes += h->st->n_bits / 8;
2342 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
2343 struct thread *t = &p->threads[i];
2344 uint32_t offset = 0;
2346 t->headers = calloc(p->n_headers,
2347 sizeof(struct header_runtime));
2348 CHECK(t->headers, ENOMEM);
2350 t->headers_out = calloc(p->n_headers,
2351 sizeof(struct header_out_runtime));
2352 CHECK(t->headers_out, ENOMEM);
2354 t->header_storage = calloc(1, n_bytes);
2355 CHECK(t->header_storage, ENOMEM);
2357 t->header_out_storage = calloc(1, n_bytes);
2358 CHECK(t->header_out_storage, ENOMEM);
2360 TAILQ_FOREACH(h, &p->headers, node) {
2361 uint8_t *header_storage;
2363 header_storage = &t->header_storage[offset];
2364 offset += h->st->n_bits / 8;
2366 t->headers[h->id].ptr0 = header_storage;
2367 t->structs[h->struct_id] = header_storage;
2375 header_build_free(struct rte_swx_pipeline *p)
2379 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
2380 struct thread *t = &p->threads[i];
2382 free(t->headers_out);
2383 t->headers_out = NULL;
2388 free(t->header_out_storage);
2389 t->header_out_storage = NULL;
2391 free(t->header_storage);
2392 t->header_storage = NULL;
2397 header_free(struct rte_swx_pipeline *p)
2399 header_build_free(p);
2402 struct header *elem;
2404 elem = TAILQ_FIRST(&p->headers);
2408 TAILQ_REMOVE(&p->headers, elem, node);
2416 static struct field *
2417 metadata_field_parse(struct rte_swx_pipeline *p, const char *name)
2419 if (!p->metadata_st)
2422 if (name[0] != 'm' || name[1] != '.')
2425 return struct_type_field_find(p->metadata_st, &name[2]);
2429 rte_swx_pipeline_packet_metadata_register(struct rte_swx_pipeline *p,
2430 const char *struct_type_name)
2432 struct struct_type *st = NULL;
2436 CHECK_NAME(struct_type_name, EINVAL);
2437 st = struct_type_find(p, struct_type_name);
2439 CHECK(!p->metadata_st, EINVAL);
2441 p->metadata_st = st;
2442 p->metadata_struct_id = p->n_structs;
2450 metadata_build(struct rte_swx_pipeline *p)
2452 uint32_t n_bytes = p->metadata_st->n_bits / 8;
2455 /* Thread-level initialization. */
2456 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
2457 struct thread *t = &p->threads[i];
2460 metadata = calloc(1, n_bytes);
2461 CHECK(metadata, ENOMEM);
2463 t->metadata = metadata;
2464 t->structs[p->metadata_struct_id] = metadata;
2471 metadata_build_free(struct rte_swx_pipeline *p)
2475 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
2476 struct thread *t = &p->threads[i];
2484 metadata_free(struct rte_swx_pipeline *p)
2486 metadata_build_free(p);
2493 instruction_is_jmp(struct instruction *instr)
2495 switch (instr->type) {
2497 case INSTR_JMP_VALID:
2498 case INSTR_JMP_INVALID:
2500 case INSTR_JMP_MISS:
2501 case INSTR_JMP_ACTION_HIT:
2502 case INSTR_JMP_ACTION_MISS:
2504 case INSTR_JMP_EQ_S:
2505 case INSTR_JMP_EQ_I:
2507 case INSTR_JMP_NEQ_S:
2508 case INSTR_JMP_NEQ_I:
2510 case INSTR_JMP_LT_MH:
2511 case INSTR_JMP_LT_HM:
2512 case INSTR_JMP_LT_HH:
2513 case INSTR_JMP_LT_MI:
2514 case INSTR_JMP_LT_HI:
2516 case INSTR_JMP_GT_MH:
2517 case INSTR_JMP_GT_HM:
2518 case INSTR_JMP_GT_HH:
2519 case INSTR_JMP_GT_MI:
2520 case INSTR_JMP_GT_HI:
2528 static struct field *
2529 action_field_parse(struct action *action, const char *name);
2531 static struct field *
2532 struct_field_parse(struct rte_swx_pipeline *p,
2533 struct action *action,
2535 uint32_t *struct_id)
2542 struct header *header;
2544 f = header_field_parse(p, name, &header);
2548 *struct_id = header->struct_id;
2554 f = metadata_field_parse(p, name);
2558 *struct_id = p->metadata_struct_id;
2567 f = action_field_parse(action, name);
2577 struct extern_obj *obj;
2579 f = extern_obj_mailbox_field_parse(p, name, &obj);
2583 *struct_id = obj->struct_id;
2589 struct extern_func *func;
2591 f = extern_func_mailbox_field_parse(p, name, &func);
2595 *struct_id = func->struct_id;
2605 pipeline_port_inc(struct rte_swx_pipeline *p)
2607 p->port_id = (p->port_id + 1) & (p->n_ports_in - 1);
2611 thread_ip_reset(struct rte_swx_pipeline *p, struct thread *t)
2613 t->ip = p->instructions;
2617 thread_ip_set(struct thread *t, struct instruction *ip)
2623 thread_ip_action_call(struct rte_swx_pipeline *p,
2628 t->ip = p->action_instructions[action_id];
2632 thread_ip_inc(struct rte_swx_pipeline *p);
2635 thread_ip_inc(struct rte_swx_pipeline *p)
2637 struct thread *t = &p->threads[p->thread_id];
2643 thread_ip_inc_cond(struct thread *t, int cond)
2649 thread_yield(struct rte_swx_pipeline *p)
2651 p->thread_id = (p->thread_id + 1) & (RTE_SWX_PIPELINE_THREADS_MAX - 1);
2655 thread_yield_cond(struct rte_swx_pipeline *p, int cond)
2657 p->thread_id = (p->thread_id + cond) & (RTE_SWX_PIPELINE_THREADS_MAX - 1);
2664 instr_rx_translate(struct rte_swx_pipeline *p,
2665 struct action *action,
2668 struct instruction *instr,
2669 struct instruction_data *data __rte_unused)
2673 CHECK(!action, EINVAL);
2674 CHECK(n_tokens == 2, EINVAL);
2676 f = metadata_field_parse(p, tokens[1]);
2679 instr->type = INSTR_RX;
2680 instr->io.io.offset = f->offset / 8;
2681 instr->io.io.n_bits = f->n_bits;
2686 instr_rx_exec(struct rte_swx_pipeline *p);
2689 instr_rx_exec(struct rte_swx_pipeline *p)
2691 struct thread *t = &p->threads[p->thread_id];
2692 struct instruction *ip = t->ip;
2693 struct port_in_runtime *port = &p->in[p->port_id];
2694 struct rte_swx_pkt *pkt = &t->pkt;
2698 pkt_received = port->pkt_rx(port->obj, pkt);
2699 t->ptr = &pkt->pkt[pkt->offset];
2700 rte_prefetch0(t->ptr);
2702 TRACE("[Thread %2u] rx %s from port %u\n",
2704 pkt_received ? "1 pkt" : "0 pkts",
2708 t->valid_headers = 0;
2709 t->n_headers_out = 0;
2712 METADATA_WRITE(t, ip->io.io.offset, ip->io.io.n_bits, p->port_id);
2715 t->table_state = p->table_state;
2718 pipeline_port_inc(p);
2719 thread_ip_inc_cond(t, pkt_received);
2727 instr_tx_translate(struct rte_swx_pipeline *p,
2728 struct action *action __rte_unused,
2731 struct instruction *instr,
2732 struct instruction_data *data __rte_unused)
2736 CHECK(n_tokens == 2, EINVAL);
2738 f = metadata_field_parse(p, tokens[1]);
2741 instr->type = INSTR_TX;
2742 instr->io.io.offset = f->offset / 8;
2743 instr->io.io.n_bits = f->n_bits;
2748 emit_handler(struct thread *t)
2750 struct header_out_runtime *h0 = &t->headers_out[0];
2751 struct header_out_runtime *h1 = &t->headers_out[1];
2752 uint32_t offset = 0, i;
2754 /* No header change or header decapsulation. */
2755 if ((t->n_headers_out == 1) &&
2756 (h0->ptr + h0->n_bytes == t->ptr)) {
2757 TRACE("Emit handler: no header change or header decap.\n");
2759 t->pkt.offset -= h0->n_bytes;
2760 t->pkt.length += h0->n_bytes;
2765 /* Header encapsulation (optionally, with prior header decasulation). */
2766 if ((t->n_headers_out == 2) &&
2767 (h1->ptr + h1->n_bytes == t->ptr) &&
2768 (h0->ptr == h0->ptr0)) {
2771 TRACE("Emit handler: header encapsulation.\n");
2773 offset = h0->n_bytes + h1->n_bytes;
2774 memcpy(t->ptr - offset, h0->ptr, h0->n_bytes);
2775 t->pkt.offset -= offset;
2776 t->pkt.length += offset;
2781 /* Header insertion. */
2784 /* Header extraction. */
2787 /* For any other case. */
2788 TRACE("Emit handler: complex case.\n");
2790 for (i = 0; i < t->n_headers_out; i++) {
2791 struct header_out_runtime *h = &t->headers_out[i];
2793 memcpy(&t->header_out_storage[offset], h->ptr, h->n_bytes);
2794 offset += h->n_bytes;
2798 memcpy(t->ptr - offset, t->header_out_storage, offset);
2799 t->pkt.offset -= offset;
2800 t->pkt.length += offset;
2805 instr_tx_exec(struct rte_swx_pipeline *p);
2808 instr_tx_exec(struct rte_swx_pipeline *p)
2810 struct thread *t = &p->threads[p->thread_id];
2811 struct instruction *ip = t->ip;
2812 uint64_t port_id = METADATA_READ(t, ip->io.io.offset, ip->io.io.n_bits);
2813 struct port_out_runtime *port = &p->out[port_id];
2814 struct rte_swx_pkt *pkt = &t->pkt;
2816 TRACE("[Thread %2u]: tx 1 pkt to port %u\n",
2824 port->pkt_tx(port->obj, pkt);
2827 thread_ip_reset(p, t);
2835 instr_hdr_extract_translate(struct rte_swx_pipeline *p,
2836 struct action *action,
2839 struct instruction *instr,
2840 struct instruction_data *data __rte_unused)
2844 CHECK(!action, EINVAL);
2845 CHECK(n_tokens == 2, EINVAL);
2847 h = header_parse(p, tokens[1]);
2850 instr->type = INSTR_HDR_EXTRACT;
2851 instr->io.hdr.header_id[0] = h->id;
2852 instr->io.hdr.struct_id[0] = h->struct_id;
2853 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
2858 __instr_hdr_extract_exec(struct rte_swx_pipeline *p, uint32_t n_extract);
2861 __instr_hdr_extract_exec(struct rte_swx_pipeline *p, uint32_t n_extract)
2863 struct thread *t = &p->threads[p->thread_id];
2864 struct instruction *ip = t->ip;
2865 uint64_t valid_headers = t->valid_headers;
2866 uint8_t *ptr = t->ptr;
2867 uint32_t offset = t->pkt.offset;
2868 uint32_t length = t->pkt.length;
2871 for (i = 0; i < n_extract; i++) {
2872 uint32_t header_id = ip->io.hdr.header_id[i];
2873 uint32_t struct_id = ip->io.hdr.struct_id[i];
2874 uint32_t n_bytes = ip->io.hdr.n_bytes[i];
2876 TRACE("[Thread %2u]: extract header %u (%u bytes)\n",
2882 t->structs[struct_id] = ptr;
2883 valid_headers = MASK64_BIT_SET(valid_headers, header_id);
2892 t->valid_headers = valid_headers;
2895 t->pkt.offset = offset;
2896 t->pkt.length = length;
2901 instr_hdr_extract_exec(struct rte_swx_pipeline *p)
2903 __instr_hdr_extract_exec(p, 1);
2910 instr_hdr_extract2_exec(struct rte_swx_pipeline *p)
2912 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n",
2915 __instr_hdr_extract_exec(p, 2);
2922 instr_hdr_extract3_exec(struct rte_swx_pipeline *p)
2924 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n",
2927 __instr_hdr_extract_exec(p, 3);
2934 instr_hdr_extract4_exec(struct rte_swx_pipeline *p)
2936 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n",
2939 __instr_hdr_extract_exec(p, 4);
2946 instr_hdr_extract5_exec(struct rte_swx_pipeline *p)
2948 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n",
2951 __instr_hdr_extract_exec(p, 5);
2958 instr_hdr_extract6_exec(struct rte_swx_pipeline *p)
2960 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n",
2963 __instr_hdr_extract_exec(p, 6);
2970 instr_hdr_extract7_exec(struct rte_swx_pipeline *p)
2972 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n",
2975 __instr_hdr_extract_exec(p, 7);
2982 instr_hdr_extract8_exec(struct rte_swx_pipeline *p)
2984 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n",
2987 __instr_hdr_extract_exec(p, 8);
2997 instr_hdr_emit_translate(struct rte_swx_pipeline *p,
2998 struct action *action __rte_unused,
3001 struct instruction *instr,
3002 struct instruction_data *data __rte_unused)
3006 CHECK(n_tokens == 2, EINVAL);
3008 h = header_parse(p, tokens[1]);
3011 instr->type = INSTR_HDR_EMIT;
3012 instr->io.hdr.header_id[0] = h->id;
3013 instr->io.hdr.struct_id[0] = h->struct_id;
3014 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
3019 __instr_hdr_emit_exec(struct rte_swx_pipeline *p, uint32_t n_emit);
3022 __instr_hdr_emit_exec(struct rte_swx_pipeline *p, uint32_t n_emit)
3024 struct thread *t = &p->threads[p->thread_id];
3025 struct instruction *ip = t->ip;
3026 uint32_t n_headers_out = t->n_headers_out;
3027 struct header_out_runtime *ho = &t->headers_out[n_headers_out - 1];
3028 uint8_t *ho_ptr = NULL;
3029 uint32_t ho_nbytes = 0, i;
3031 for (i = 0; i < n_emit; i++) {
3032 uint32_t header_id = ip->io.hdr.header_id[i];
3033 uint32_t struct_id = ip->io.hdr.struct_id[i];
3034 uint32_t n_bytes = ip->io.hdr.n_bytes[i];
3036 struct header_runtime *hi = &t->headers[header_id];
3037 uint8_t *hi_ptr = t->structs[struct_id];
3039 TRACE("[Thread %2u]: emit header %u\n",
3045 if (!t->n_headers_out) {
3046 ho = &t->headers_out[0];
3048 ho->ptr0 = hi->ptr0;
3052 ho_nbytes = n_bytes;
3059 ho_nbytes = ho->n_bytes;
3063 if (ho_ptr + ho_nbytes == hi_ptr) {
3064 ho_nbytes += n_bytes;
3066 ho->n_bytes = ho_nbytes;
3069 ho->ptr0 = hi->ptr0;
3073 ho_nbytes = n_bytes;
3079 ho->n_bytes = ho_nbytes;
3080 t->n_headers_out = n_headers_out;
3084 instr_hdr_emit_exec(struct rte_swx_pipeline *p)
3086 __instr_hdr_emit_exec(p, 1);
3093 instr_hdr_emit_tx_exec(struct rte_swx_pipeline *p)
3095 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n",
3098 __instr_hdr_emit_exec(p, 1);
3103 instr_hdr_emit2_tx_exec(struct rte_swx_pipeline *p)
3105 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n",
3108 __instr_hdr_emit_exec(p, 2);
3113 instr_hdr_emit3_tx_exec(struct rte_swx_pipeline *p)
3115 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n",
3118 __instr_hdr_emit_exec(p, 3);
3123 instr_hdr_emit4_tx_exec(struct rte_swx_pipeline *p)
3125 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n",
3128 __instr_hdr_emit_exec(p, 4);
3133 instr_hdr_emit5_tx_exec(struct rte_swx_pipeline *p)
3135 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n",
3138 __instr_hdr_emit_exec(p, 5);
3143 instr_hdr_emit6_tx_exec(struct rte_swx_pipeline *p)
3145 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n",
3148 __instr_hdr_emit_exec(p, 6);
3153 instr_hdr_emit7_tx_exec(struct rte_swx_pipeline *p)
3155 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n",
3158 __instr_hdr_emit_exec(p, 7);
3163 instr_hdr_emit8_tx_exec(struct rte_swx_pipeline *p)
3165 TRACE("[Thread %2u] *** The next 9 instructions are fused. ***\n",
3168 __instr_hdr_emit_exec(p, 8);
3176 instr_hdr_validate_translate(struct rte_swx_pipeline *p,
3177 struct action *action __rte_unused,
3180 struct instruction *instr,
3181 struct instruction_data *data __rte_unused)
3185 CHECK(n_tokens == 2, EINVAL);
3187 h = header_parse(p, tokens[1]);
3190 instr->type = INSTR_HDR_VALIDATE;
3191 instr->valid.header_id = h->id;
3196 instr_hdr_validate_exec(struct rte_swx_pipeline *p)
3198 struct thread *t = &p->threads[p->thread_id];
3199 struct instruction *ip = t->ip;
3200 uint32_t header_id = ip->valid.header_id;
3202 TRACE("[Thread %2u] validate header %u\n", p->thread_id, header_id);
3205 t->valid_headers = MASK64_BIT_SET(t->valid_headers, header_id);
3215 instr_hdr_invalidate_translate(struct rte_swx_pipeline *p,
3216 struct action *action __rte_unused,
3219 struct instruction *instr,
3220 struct instruction_data *data __rte_unused)
3224 CHECK(n_tokens == 2, EINVAL);
3226 h = header_parse(p, tokens[1]);
3229 instr->type = INSTR_HDR_INVALIDATE;
3230 instr->valid.header_id = h->id;
3235 instr_hdr_invalidate_exec(struct rte_swx_pipeline *p)
3237 struct thread *t = &p->threads[p->thread_id];
3238 struct instruction *ip = t->ip;
3239 uint32_t header_id = ip->valid.header_id;
3241 TRACE("[Thread %2u] invalidate header %u\n", p->thread_id, header_id);
3244 t->valid_headers = MASK64_BIT_CLR(t->valid_headers, header_id);
3253 static struct table *
3254 table_find(struct rte_swx_pipeline *p, const char *name);
3257 instr_table_translate(struct rte_swx_pipeline *p,
3258 struct action *action,
3261 struct instruction *instr,
3262 struct instruction_data *data __rte_unused)
3266 CHECK(!action, EINVAL);
3267 CHECK(n_tokens == 2, EINVAL);
3269 t = table_find(p, tokens[1]);
3272 instr->type = INSTR_TABLE;
3273 instr->table.table_id = t->id;
3278 instr_table_exec(struct rte_swx_pipeline *p)
3280 struct thread *t = &p->threads[p->thread_id];
3281 struct instruction *ip = t->ip;
3282 uint32_t table_id = ip->table.table_id;
3283 struct rte_swx_table_state *ts = &t->table_state[table_id];
3284 struct table_runtime *table = &t->tables[table_id];
3286 uint8_t *action_data;
3290 done = table->func(ts->obj,
3298 TRACE("[Thread %2u] table %u (not finalized)\n",
3306 action_id = hit ? action_id : ts->default_action_id;
3307 action_data = hit ? action_data : ts->default_action_data;
3309 TRACE("[Thread %2u] table %u (%s, action %u)\n",
3312 hit ? "hit" : "miss",
3313 (uint32_t)action_id);
3315 t->action_id = action_id;
3316 t->structs[0] = action_data;
3320 thread_ip_action_call(p, t, action_id);
3327 instr_extern_translate(struct rte_swx_pipeline *p,
3328 struct action *action __rte_unused,
3331 struct instruction *instr,
3332 struct instruction_data *data __rte_unused)
3334 char *token = tokens[1];
3336 CHECK(n_tokens == 2, EINVAL);
3338 if (token[0] == 'e') {
3339 struct extern_obj *obj;
3340 struct extern_type_member_func *func;
3342 func = extern_obj_member_func_parse(p, token, &obj);
3343 CHECK(func, EINVAL);
3345 instr->type = INSTR_EXTERN_OBJ;
3346 instr->ext_obj.ext_obj_id = obj->id;
3347 instr->ext_obj.func_id = func->id;
3352 if (token[0] == 'f') {
3353 struct extern_func *func;
3355 func = extern_func_parse(p, token);
3356 CHECK(func, EINVAL);
3358 instr->type = INSTR_EXTERN_FUNC;
3359 instr->ext_func.ext_func_id = func->id;
3368 instr_extern_obj_exec(struct rte_swx_pipeline *p)
3370 struct thread *t = &p->threads[p->thread_id];
3371 struct instruction *ip = t->ip;
3372 uint32_t obj_id = ip->ext_obj.ext_obj_id;
3373 uint32_t func_id = ip->ext_obj.func_id;
3374 struct extern_obj_runtime *obj = &t->extern_objs[obj_id];
3375 rte_swx_extern_type_member_func_t func = obj->funcs[func_id];
3377 TRACE("[Thread %2u] extern obj %u member func %u\n",
3382 /* Extern object member function execute. */
3383 uint32_t done = func(obj->obj, obj->mailbox);
3386 thread_ip_inc_cond(t, done);
3387 thread_yield_cond(p, done ^ 1);
3391 instr_extern_func_exec(struct rte_swx_pipeline *p)
3393 struct thread *t = &p->threads[p->thread_id];
3394 struct instruction *ip = t->ip;
3395 uint32_t ext_func_id = ip->ext_func.ext_func_id;
3396 struct extern_func_runtime *ext_func = &t->extern_funcs[ext_func_id];
3397 rte_swx_extern_func_t func = ext_func->func;
3399 TRACE("[Thread %2u] extern func %u\n",
3403 /* Extern function execute. */
3404 uint32_t done = func(ext_func->mailbox);
3407 thread_ip_inc_cond(t, done);
3408 thread_yield_cond(p, done ^ 1);
3415 instr_mov_translate(struct rte_swx_pipeline *p,
3416 struct action *action,
3419 struct instruction *instr,
3420 struct instruction_data *data __rte_unused)
3422 char *dst = tokens[1], *src = tokens[2];
3423 struct field *fdst, *fsrc;
3425 uint32_t dst_struct_id, src_struct_id;
3427 CHECK(n_tokens == 3, EINVAL);
3429 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3430 CHECK(fdst, EINVAL);
3433 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3435 instr->type = INSTR_MOV;
3436 if ((dst[0] == 'h' && src[0] != 'h') ||
3437 (dst[0] != 'h' && src[0] == 'h'))
3438 instr->type = INSTR_MOV_S;
3440 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
3441 instr->mov.dst.n_bits = fdst->n_bits;
3442 instr->mov.dst.offset = fdst->offset / 8;
3443 instr->mov.src.struct_id = (uint8_t)src_struct_id;
3444 instr->mov.src.n_bits = fsrc->n_bits;
3445 instr->mov.src.offset = fsrc->offset / 8;
3450 src_val = strtoull(src, &src, 0);
3451 CHECK(!src[0], EINVAL);
3454 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3456 instr->type = INSTR_MOV_I;
3457 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
3458 instr->mov.dst.n_bits = fdst->n_bits;
3459 instr->mov.dst.offset = fdst->offset / 8;
3460 instr->mov.src_val = src_val;
3465 instr_mov_exec(struct rte_swx_pipeline *p)
3467 struct thread *t = &p->threads[p->thread_id];
3468 struct instruction *ip = t->ip;
3470 TRACE("[Thread %2u] mov\n",
3480 instr_mov_s_exec(struct rte_swx_pipeline *p)
3482 struct thread *t = &p->threads[p->thread_id];
3483 struct instruction *ip = t->ip;
3485 TRACE("[Thread %2u] mov (s)\n",
3495 instr_mov_i_exec(struct rte_swx_pipeline *p)
3497 struct thread *t = &p->threads[p->thread_id];
3498 struct instruction *ip = t->ip;
3500 TRACE("[Thread %2u] mov m.f %" PRIx64 "\n",
3514 instr_dma_translate(struct rte_swx_pipeline *p,
3515 struct action *action,
3518 struct instruction *instr,
3519 struct instruction_data *data __rte_unused)
3521 char *dst = tokens[1];
3522 char *src = tokens[2];
3526 CHECK(action, EINVAL);
3527 CHECK(n_tokens == 3, EINVAL);
3529 h = header_parse(p, dst);
3532 tf = action_field_parse(action, src);
3535 instr->type = INSTR_DMA_HT;
3536 instr->dma.dst.header_id[0] = h->id;
3537 instr->dma.dst.struct_id[0] = h->struct_id;
3538 instr->dma.n_bytes[0] = h->st->n_bits / 8;
3539 instr->dma.src.offset[0] = tf->offset / 8;
3545 __instr_dma_ht_exec(struct rte_swx_pipeline *p, uint32_t n_dma);
3548 __instr_dma_ht_exec(struct rte_swx_pipeline *p, uint32_t n_dma)
3550 struct thread *t = &p->threads[p->thread_id];
3551 struct instruction *ip = t->ip;
3552 uint8_t *action_data = t->structs[0];
3553 uint64_t valid_headers = t->valid_headers;
3556 for (i = 0; i < n_dma; i++) {
3557 uint32_t header_id = ip->dma.dst.header_id[i];
3558 uint32_t struct_id = ip->dma.dst.struct_id[i];
3559 uint32_t offset = ip->dma.src.offset[i];
3560 uint32_t n_bytes = ip->dma.n_bytes[i];
3562 struct header_runtime *h = &t->headers[header_id];
3563 uint8_t *h_ptr0 = h->ptr0;
3564 uint8_t *h_ptr = t->structs[struct_id];
3566 void *dst = MASK64_BIT_GET(valid_headers, header_id) ?
3568 void *src = &action_data[offset];
3570 TRACE("[Thread %2u] dma h.s t.f\n", p->thread_id);
3573 memcpy(dst, src, n_bytes);
3574 t->structs[struct_id] = dst;
3575 valid_headers = MASK64_BIT_SET(valid_headers, header_id);
3578 t->valid_headers = valid_headers;
3582 instr_dma_ht_exec(struct rte_swx_pipeline *p)
3584 __instr_dma_ht_exec(p, 1);
3591 instr_dma_ht2_exec(struct rte_swx_pipeline *p)
3593 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n",
3596 __instr_dma_ht_exec(p, 2);
3603 instr_dma_ht3_exec(struct rte_swx_pipeline *p)
3605 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n",
3608 __instr_dma_ht_exec(p, 3);
3615 instr_dma_ht4_exec(struct rte_swx_pipeline *p)
3617 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n",
3620 __instr_dma_ht_exec(p, 4);
3627 instr_dma_ht5_exec(struct rte_swx_pipeline *p)
3629 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n",
3632 __instr_dma_ht_exec(p, 5);
3639 instr_dma_ht6_exec(struct rte_swx_pipeline *p)
3641 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n",
3644 __instr_dma_ht_exec(p, 6);
3651 instr_dma_ht7_exec(struct rte_swx_pipeline *p)
3653 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n",
3656 __instr_dma_ht_exec(p, 7);
3663 instr_dma_ht8_exec(struct rte_swx_pipeline *p)
3665 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n",
3668 __instr_dma_ht_exec(p, 8);
3678 instr_alu_add_translate(struct rte_swx_pipeline *p,
3679 struct action *action,
3682 struct instruction *instr,
3683 struct instruction_data *data __rte_unused)
3685 char *dst = tokens[1], *src = tokens[2];
3686 struct field *fdst, *fsrc;
3688 uint32_t dst_struct_id, src_struct_id;
3690 CHECK(n_tokens == 3, EINVAL);
3692 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3693 CHECK(fdst, EINVAL);
3695 /* ADD, ADD_HM, ADD_MH, ADD_HH. */
3696 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3698 instr->type = INSTR_ALU_ADD;
3699 if (dst[0] == 'h' && src[0] != 'h')
3700 instr->type = INSTR_ALU_ADD_HM;
3701 if (dst[0] != 'h' && src[0] == 'h')
3702 instr->type = INSTR_ALU_ADD_MH;
3703 if (dst[0] == 'h' && src[0] == 'h')
3704 instr->type = INSTR_ALU_ADD_HH;
3706 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3707 instr->alu.dst.n_bits = fdst->n_bits;
3708 instr->alu.dst.offset = fdst->offset / 8;
3709 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3710 instr->alu.src.n_bits = fsrc->n_bits;
3711 instr->alu.src.offset = fsrc->offset / 8;
3715 /* ADD_MI, ADD_HI. */
3716 src_val = strtoull(src, &src, 0);
3717 CHECK(!src[0], EINVAL);
3719 instr->type = INSTR_ALU_ADD_MI;
3721 instr->type = INSTR_ALU_ADD_HI;
3723 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3724 instr->alu.dst.n_bits = fdst->n_bits;
3725 instr->alu.dst.offset = fdst->offset / 8;
3726 instr->alu.src_val = src_val;
3731 instr_alu_sub_translate(struct rte_swx_pipeline *p,
3732 struct action *action,
3735 struct instruction *instr,
3736 struct instruction_data *data __rte_unused)
3738 char *dst = tokens[1], *src = tokens[2];
3739 struct field *fdst, *fsrc;
3741 uint32_t dst_struct_id, src_struct_id;
3743 CHECK(n_tokens == 3, EINVAL);
3745 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3746 CHECK(fdst, EINVAL);
3748 /* SUB, SUB_HM, SUB_MH, SUB_HH. */
3749 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3751 instr->type = INSTR_ALU_SUB;
3752 if (dst[0] == 'h' && src[0] != 'h')
3753 instr->type = INSTR_ALU_SUB_HM;
3754 if (dst[0] != 'h' && src[0] == 'h')
3755 instr->type = INSTR_ALU_SUB_MH;
3756 if (dst[0] == 'h' && src[0] == 'h')
3757 instr->type = INSTR_ALU_SUB_HH;
3759 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3760 instr->alu.dst.n_bits = fdst->n_bits;
3761 instr->alu.dst.offset = fdst->offset / 8;
3762 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3763 instr->alu.src.n_bits = fsrc->n_bits;
3764 instr->alu.src.offset = fsrc->offset / 8;
3768 /* SUB_MI, SUB_HI. */
3769 src_val = strtoull(src, &src, 0);
3770 CHECK(!src[0], EINVAL);
3772 instr->type = INSTR_ALU_SUB_MI;
3774 instr->type = INSTR_ALU_SUB_HI;
3776 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3777 instr->alu.dst.n_bits = fdst->n_bits;
3778 instr->alu.dst.offset = fdst->offset / 8;
3779 instr->alu.src_val = src_val;
3784 instr_alu_ckadd_translate(struct rte_swx_pipeline *p,
3785 struct action *action __rte_unused,
3788 struct instruction *instr,
3789 struct instruction_data *data __rte_unused)
3791 char *dst = tokens[1], *src = tokens[2];
3792 struct header *hdst, *hsrc;
3793 struct field *fdst, *fsrc;
3795 CHECK(n_tokens == 3, EINVAL);
3797 fdst = header_field_parse(p, dst, &hdst);
3798 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
3801 fsrc = header_field_parse(p, src, &hsrc);
3803 instr->type = INSTR_ALU_CKADD_FIELD;
3804 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
3805 instr->alu.dst.n_bits = fdst->n_bits;
3806 instr->alu.dst.offset = fdst->offset / 8;
3807 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
3808 instr->alu.src.n_bits = fsrc->n_bits;
3809 instr->alu.src.offset = fsrc->offset / 8;
3813 /* CKADD_STRUCT, CKADD_STRUCT20. */
3814 hsrc = header_parse(p, src);
3815 CHECK(hsrc, EINVAL);
3817 instr->type = INSTR_ALU_CKADD_STRUCT;
3818 if ((hsrc->st->n_bits / 8) == 20)
3819 instr->type = INSTR_ALU_CKADD_STRUCT20;
3821 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
3822 instr->alu.dst.n_bits = fdst->n_bits;
3823 instr->alu.dst.offset = fdst->offset / 8;
3824 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
3825 instr->alu.src.n_bits = hsrc->st->n_bits;
3826 instr->alu.src.offset = 0; /* Unused. */
3831 instr_alu_cksub_translate(struct rte_swx_pipeline *p,
3832 struct action *action __rte_unused,
3835 struct instruction *instr,
3836 struct instruction_data *data __rte_unused)
3838 char *dst = tokens[1], *src = tokens[2];
3839 struct header *hdst, *hsrc;
3840 struct field *fdst, *fsrc;
3842 CHECK(n_tokens == 3, EINVAL);
3844 fdst = header_field_parse(p, dst, &hdst);
3845 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
3847 fsrc = header_field_parse(p, src, &hsrc);
3848 CHECK(fsrc, EINVAL);
3850 instr->type = INSTR_ALU_CKSUB_FIELD;
3851 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
3852 instr->alu.dst.n_bits = fdst->n_bits;
3853 instr->alu.dst.offset = fdst->offset / 8;
3854 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
3855 instr->alu.src.n_bits = fsrc->n_bits;
3856 instr->alu.src.offset = fsrc->offset / 8;
3861 instr_alu_shl_translate(struct rte_swx_pipeline *p,
3862 struct action *action,
3865 struct instruction *instr,
3866 struct instruction_data *data __rte_unused)
3868 char *dst = tokens[1], *src = tokens[2];
3869 struct field *fdst, *fsrc;
3871 uint32_t dst_struct_id, src_struct_id;
3873 CHECK(n_tokens == 3, EINVAL);
3875 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3876 CHECK(fdst, EINVAL);
3878 /* SHL, SHL_HM, SHL_MH, SHL_HH. */
3879 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3881 instr->type = INSTR_ALU_SHL;
3882 if (dst[0] == 'h' && src[0] != 'h')
3883 instr->type = INSTR_ALU_SHL_HM;
3884 if (dst[0] != 'h' && src[0] == 'h')
3885 instr->type = INSTR_ALU_SHL_MH;
3886 if (dst[0] == 'h' && src[0] == 'h')
3887 instr->type = INSTR_ALU_SHL_HH;
3889 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3890 instr->alu.dst.n_bits = fdst->n_bits;
3891 instr->alu.dst.offset = fdst->offset / 8;
3892 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3893 instr->alu.src.n_bits = fsrc->n_bits;
3894 instr->alu.src.offset = fsrc->offset / 8;
3898 /* SHL_MI, SHL_HI. */
3899 src_val = strtoull(src, &src, 0);
3900 CHECK(!src[0], EINVAL);
3902 instr->type = INSTR_ALU_SHL_MI;
3904 instr->type = INSTR_ALU_SHL_HI;
3906 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3907 instr->alu.dst.n_bits = fdst->n_bits;
3908 instr->alu.dst.offset = fdst->offset / 8;
3909 instr->alu.src_val = src_val;
3914 instr_alu_shr_translate(struct rte_swx_pipeline *p,
3915 struct action *action,
3918 struct instruction *instr,
3919 struct instruction_data *data __rte_unused)
3921 char *dst = tokens[1], *src = tokens[2];
3922 struct field *fdst, *fsrc;
3924 uint32_t dst_struct_id, src_struct_id;
3926 CHECK(n_tokens == 3, EINVAL);
3928 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3929 CHECK(fdst, EINVAL);
3931 /* SHR, SHR_HM, SHR_MH, SHR_HH. */
3932 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3934 instr->type = INSTR_ALU_SHR;
3935 if (dst[0] == 'h' && src[0] != 'h')
3936 instr->type = INSTR_ALU_SHR_HM;
3937 if (dst[0] != 'h' && src[0] == 'h')
3938 instr->type = INSTR_ALU_SHR_MH;
3939 if (dst[0] == 'h' && src[0] == 'h')
3940 instr->type = INSTR_ALU_SHR_HH;
3942 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3943 instr->alu.dst.n_bits = fdst->n_bits;
3944 instr->alu.dst.offset = fdst->offset / 8;
3945 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3946 instr->alu.src.n_bits = fsrc->n_bits;
3947 instr->alu.src.offset = fsrc->offset / 8;
3951 /* SHR_MI, SHR_HI. */
3952 src_val = strtoull(src, &src, 0);
3953 CHECK(!src[0], EINVAL);
3955 instr->type = INSTR_ALU_SHR_MI;
3957 instr->type = INSTR_ALU_SHR_HI;
3959 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3960 instr->alu.dst.n_bits = fdst->n_bits;
3961 instr->alu.dst.offset = fdst->offset / 8;
3962 instr->alu.src_val = src_val;
3967 instr_alu_and_translate(struct rte_swx_pipeline *p,
3968 struct action *action,
3971 struct instruction *instr,
3972 struct instruction_data *data __rte_unused)
3974 char *dst = tokens[1], *src = tokens[2];
3975 struct field *fdst, *fsrc;
3977 uint32_t dst_struct_id, src_struct_id;
3979 CHECK(n_tokens == 3, EINVAL);
3981 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3982 CHECK(fdst, EINVAL);
3985 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3987 instr->type = INSTR_ALU_AND;
3988 if ((dst[0] == 'h' && src[0] != 'h') ||
3989 (dst[0] != 'h' && src[0] == 'h'))
3990 instr->type = INSTR_ALU_AND_S;
3992 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3993 instr->alu.dst.n_bits = fdst->n_bits;
3994 instr->alu.dst.offset = fdst->offset / 8;
3995 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3996 instr->alu.src.n_bits = fsrc->n_bits;
3997 instr->alu.src.offset = fsrc->offset / 8;
4002 src_val = strtoull(src, &src, 0);
4003 CHECK(!src[0], EINVAL);
4006 src_val = hton64(src_val) >> (64 - fdst->n_bits);
4008 instr->type = INSTR_ALU_AND_I;
4009 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4010 instr->alu.dst.n_bits = fdst->n_bits;
4011 instr->alu.dst.offset = fdst->offset / 8;
4012 instr->alu.src_val = src_val;
4017 instr_alu_or_translate(struct rte_swx_pipeline *p,
4018 struct action *action,
4021 struct instruction *instr,
4022 struct instruction_data *data __rte_unused)
4024 char *dst = tokens[1], *src = tokens[2];
4025 struct field *fdst, *fsrc;
4027 uint32_t dst_struct_id, src_struct_id;
4029 CHECK(n_tokens == 3, EINVAL);
4031 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4032 CHECK(fdst, EINVAL);
4035 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4037 instr->type = INSTR_ALU_OR;
4038 if ((dst[0] == 'h' && src[0] != 'h') ||
4039 (dst[0] != 'h' && src[0] == 'h'))
4040 instr->type = INSTR_ALU_OR_S;
4042 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4043 instr->alu.dst.n_bits = fdst->n_bits;
4044 instr->alu.dst.offset = fdst->offset / 8;
4045 instr->alu.src.struct_id = (uint8_t)src_struct_id;
4046 instr->alu.src.n_bits = fsrc->n_bits;
4047 instr->alu.src.offset = fsrc->offset / 8;
4052 src_val = strtoull(src, &src, 0);
4053 CHECK(!src[0], EINVAL);
4056 src_val = hton64(src_val) >> (64 - fdst->n_bits);
4058 instr->type = INSTR_ALU_OR_I;
4059 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4060 instr->alu.dst.n_bits = fdst->n_bits;
4061 instr->alu.dst.offset = fdst->offset / 8;
4062 instr->alu.src_val = src_val;
4067 instr_alu_xor_translate(struct rte_swx_pipeline *p,
4068 struct action *action,
4071 struct instruction *instr,
4072 struct instruction_data *data __rte_unused)
4074 char *dst = tokens[1], *src = tokens[2];
4075 struct field *fdst, *fsrc;
4077 uint32_t dst_struct_id, src_struct_id;
4079 CHECK(n_tokens == 3, EINVAL);
4081 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4082 CHECK(fdst, EINVAL);
4085 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4087 instr->type = INSTR_ALU_XOR;
4088 if ((dst[0] == 'h' && src[0] != 'h') ||
4089 (dst[0] != 'h' && src[0] == 'h'))
4090 instr->type = INSTR_ALU_XOR_S;
4092 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4093 instr->alu.dst.n_bits = fdst->n_bits;
4094 instr->alu.dst.offset = fdst->offset / 8;
4095 instr->alu.src.struct_id = (uint8_t)src_struct_id;
4096 instr->alu.src.n_bits = fsrc->n_bits;
4097 instr->alu.src.offset = fsrc->offset / 8;
4102 src_val = strtoull(src, &src, 0);
4103 CHECK(!src[0], EINVAL);
4106 src_val = hton64(src_val) >> (64 - fdst->n_bits);
4108 instr->type = INSTR_ALU_XOR_I;
4109 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4110 instr->alu.dst.n_bits = fdst->n_bits;
4111 instr->alu.dst.offset = fdst->offset / 8;
4112 instr->alu.src_val = src_val;
4117 instr_alu_add_exec(struct rte_swx_pipeline *p)
4119 struct thread *t = &p->threads[p->thread_id];
4120 struct instruction *ip = t->ip;
4122 TRACE("[Thread %2u] add\n", p->thread_id);
4132 instr_alu_add_mh_exec(struct rte_swx_pipeline *p)
4134 struct thread *t = &p->threads[p->thread_id];
4135 struct instruction *ip = t->ip;
4137 TRACE("[Thread %2u] add (mh)\n", p->thread_id);
4147 instr_alu_add_hm_exec(struct rte_swx_pipeline *p)
4149 struct thread *t = &p->threads[p->thread_id];
4150 struct instruction *ip = t->ip;
4152 TRACE("[Thread %2u] add (hm)\n", p->thread_id);
4162 instr_alu_add_hh_exec(struct rte_swx_pipeline *p)
4164 struct thread *t = &p->threads[p->thread_id];
4165 struct instruction *ip = t->ip;
4167 TRACE("[Thread %2u] add (hh)\n", p->thread_id);
4177 instr_alu_add_mi_exec(struct rte_swx_pipeline *p)
4179 struct thread *t = &p->threads[p->thread_id];
4180 struct instruction *ip = t->ip;
4182 TRACE("[Thread %2u] add (mi)\n", p->thread_id);
4192 instr_alu_add_hi_exec(struct rte_swx_pipeline *p)
4194 struct thread *t = &p->threads[p->thread_id];
4195 struct instruction *ip = t->ip;
4197 TRACE("[Thread %2u] add (hi)\n", p->thread_id);
4207 instr_alu_sub_exec(struct rte_swx_pipeline *p)
4209 struct thread *t = &p->threads[p->thread_id];
4210 struct instruction *ip = t->ip;
4212 TRACE("[Thread %2u] sub\n", p->thread_id);
4222 instr_alu_sub_mh_exec(struct rte_swx_pipeline *p)
4224 struct thread *t = &p->threads[p->thread_id];
4225 struct instruction *ip = t->ip;
4227 TRACE("[Thread %2u] sub (mh)\n", p->thread_id);
4237 instr_alu_sub_hm_exec(struct rte_swx_pipeline *p)
4239 struct thread *t = &p->threads[p->thread_id];
4240 struct instruction *ip = t->ip;
4242 TRACE("[Thread %2u] sub (hm)\n", p->thread_id);
4252 instr_alu_sub_hh_exec(struct rte_swx_pipeline *p)
4254 struct thread *t = &p->threads[p->thread_id];
4255 struct instruction *ip = t->ip;
4257 TRACE("[Thread %2u] sub (hh)\n", p->thread_id);
4267 instr_alu_sub_mi_exec(struct rte_swx_pipeline *p)
4269 struct thread *t = &p->threads[p->thread_id];
4270 struct instruction *ip = t->ip;
4272 TRACE("[Thread %2u] sub (mi)\n", p->thread_id);
4282 instr_alu_sub_hi_exec(struct rte_swx_pipeline *p)
4284 struct thread *t = &p->threads[p->thread_id];
4285 struct instruction *ip = t->ip;
4287 TRACE("[Thread %2u] sub (hi)\n", p->thread_id);
4297 instr_alu_shl_exec(struct rte_swx_pipeline *p)
4299 struct thread *t = &p->threads[p->thread_id];
4300 struct instruction *ip = t->ip;
4302 TRACE("[Thread %2u] shl\n", p->thread_id);
4312 instr_alu_shl_mh_exec(struct rte_swx_pipeline *p)
4314 struct thread *t = &p->threads[p->thread_id];
4315 struct instruction *ip = t->ip;
4317 TRACE("[Thread %2u] shl (mh)\n", p->thread_id);
4327 instr_alu_shl_hm_exec(struct rte_swx_pipeline *p)
4329 struct thread *t = &p->threads[p->thread_id];
4330 struct instruction *ip = t->ip;
4332 TRACE("[Thread %2u] shl (hm)\n", p->thread_id);
4342 instr_alu_shl_hh_exec(struct rte_swx_pipeline *p)
4344 struct thread *t = &p->threads[p->thread_id];
4345 struct instruction *ip = t->ip;
4347 TRACE("[Thread %2u] shl (hh)\n", p->thread_id);
4357 instr_alu_shl_mi_exec(struct rte_swx_pipeline *p)
4359 struct thread *t = &p->threads[p->thread_id];
4360 struct instruction *ip = t->ip;
4362 TRACE("[Thread %2u] shl (mi)\n", p->thread_id);
4372 instr_alu_shl_hi_exec(struct rte_swx_pipeline *p)
4374 struct thread *t = &p->threads[p->thread_id];
4375 struct instruction *ip = t->ip;
4377 TRACE("[Thread %2u] shl (hi)\n", p->thread_id);
4387 instr_alu_shr_exec(struct rte_swx_pipeline *p)
4389 struct thread *t = &p->threads[p->thread_id];
4390 struct instruction *ip = t->ip;
4392 TRACE("[Thread %2u] shr\n", p->thread_id);
4402 instr_alu_shr_mh_exec(struct rte_swx_pipeline *p)
4404 struct thread *t = &p->threads[p->thread_id];
4405 struct instruction *ip = t->ip;
4407 TRACE("[Thread %2u] shr (mh)\n", p->thread_id);
4417 instr_alu_shr_hm_exec(struct rte_swx_pipeline *p)
4419 struct thread *t = &p->threads[p->thread_id];
4420 struct instruction *ip = t->ip;
4422 TRACE("[Thread %2u] shr (hm)\n", p->thread_id);
4432 instr_alu_shr_hh_exec(struct rte_swx_pipeline *p)
4434 struct thread *t = &p->threads[p->thread_id];
4435 struct instruction *ip = t->ip;
4437 TRACE("[Thread %2u] shr (hh)\n", p->thread_id);
4447 instr_alu_shr_mi_exec(struct rte_swx_pipeline *p)
4449 struct thread *t = &p->threads[p->thread_id];
4450 struct instruction *ip = t->ip;
4452 TRACE("[Thread %2u] shr (mi)\n", p->thread_id);
4462 instr_alu_shr_hi_exec(struct rte_swx_pipeline *p)
4464 struct thread *t = &p->threads[p->thread_id];
4465 struct instruction *ip = t->ip;
4467 TRACE("[Thread %2u] shr (hi)\n", p->thread_id);
4477 instr_alu_and_exec(struct rte_swx_pipeline *p)
4479 struct thread *t = &p->threads[p->thread_id];
4480 struct instruction *ip = t->ip;
4482 TRACE("[Thread %2u] and\n", p->thread_id);
4492 instr_alu_and_s_exec(struct rte_swx_pipeline *p)
4494 struct thread *t = &p->threads[p->thread_id];
4495 struct instruction *ip = t->ip;
4497 TRACE("[Thread %2u] and (s)\n", p->thread_id);
4507 instr_alu_and_i_exec(struct rte_swx_pipeline *p)
4509 struct thread *t = &p->threads[p->thread_id];
4510 struct instruction *ip = t->ip;
4512 TRACE("[Thread %2u] and (i)\n", p->thread_id);
4522 instr_alu_or_exec(struct rte_swx_pipeline *p)
4524 struct thread *t = &p->threads[p->thread_id];
4525 struct instruction *ip = t->ip;
4527 TRACE("[Thread %2u] or\n", p->thread_id);
4537 instr_alu_or_s_exec(struct rte_swx_pipeline *p)
4539 struct thread *t = &p->threads[p->thread_id];
4540 struct instruction *ip = t->ip;
4542 TRACE("[Thread %2u] or (s)\n", p->thread_id);
4552 instr_alu_or_i_exec(struct rte_swx_pipeline *p)
4554 struct thread *t = &p->threads[p->thread_id];
4555 struct instruction *ip = t->ip;
4557 TRACE("[Thread %2u] or (i)\n", p->thread_id);
4567 instr_alu_xor_exec(struct rte_swx_pipeline *p)
4569 struct thread *t = &p->threads[p->thread_id];
4570 struct instruction *ip = t->ip;
4572 TRACE("[Thread %2u] xor\n", p->thread_id);
4582 instr_alu_xor_s_exec(struct rte_swx_pipeline *p)
4584 struct thread *t = &p->threads[p->thread_id];
4585 struct instruction *ip = t->ip;
4587 TRACE("[Thread %2u] xor (s)\n", p->thread_id);
4597 instr_alu_xor_i_exec(struct rte_swx_pipeline *p)
4599 struct thread *t = &p->threads[p->thread_id];
4600 struct instruction *ip = t->ip;
4602 TRACE("[Thread %2u] xor (i)\n", p->thread_id);
4612 instr_alu_ckadd_field_exec(struct rte_swx_pipeline *p)
4614 struct thread *t = &p->threads[p->thread_id];
4615 struct instruction *ip = t->ip;
4616 uint8_t *dst_struct, *src_struct;
4617 uint16_t *dst16_ptr, dst;
4618 uint64_t *src64_ptr, src64, src64_mask, src;
4621 TRACE("[Thread %2u] ckadd (field)\n", p->thread_id);
4624 dst_struct = t->structs[ip->alu.dst.struct_id];
4625 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
4628 src_struct = t->structs[ip->alu.src.struct_id];
4629 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
4631 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
4632 src = src64 & src64_mask;
4637 /* The first input (r) is a 16-bit number. The second and the third
4638 * inputs are 32-bit numbers. In the worst case scenario, the sum of the
4639 * three numbers (output r) is a 34-bit number.
4641 r += (src >> 32) + (src & 0xFFFFFFFF);
4643 /* The first input is a 16-bit number. The second input is an 18-bit
4644 * number. In the worst case scenario, the sum of the two numbers is a
4647 r = (r & 0xFFFF) + (r >> 16);
4649 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
4650 * a 3-bit number (0 .. 7). Their sum is a 17-bit number (0 .. 0x10006).
4652 r = (r & 0xFFFF) + (r >> 16);
4654 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
4655 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
4656 * 0x10006), the output r is (0 .. 7). So no carry bit can be generated,
4657 * therefore the output r is always a 16-bit number.
4659 r = (r & 0xFFFF) + (r >> 16);
4664 *dst16_ptr = (uint16_t)r;
4671 instr_alu_cksub_field_exec(struct rte_swx_pipeline *p)
4673 struct thread *t = &p->threads[p->thread_id];
4674 struct instruction *ip = t->ip;
4675 uint8_t *dst_struct, *src_struct;
4676 uint16_t *dst16_ptr, dst;
4677 uint64_t *src64_ptr, src64, src64_mask, src;
4680 TRACE("[Thread %2u] cksub (field)\n", p->thread_id);
4683 dst_struct = t->structs[ip->alu.dst.struct_id];
4684 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
4687 src_struct = t->structs[ip->alu.src.struct_id];
4688 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
4690 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
4691 src = src64 & src64_mask;
4696 /* Subtraction in 1's complement arithmetic (i.e. a '- b) is the same as
4697 * the following sequence of operations in 2's complement arithmetic:
4698 * a '- b = (a - b) % 0xFFFF.
4700 * In order to prevent an underflow for the below subtraction, in which
4701 * a 33-bit number (the subtrahend) is taken out of a 16-bit number (the
4702 * minuend), we first add a multiple of the 0xFFFF modulus to the
4703 * minuend. The number we add to the minuend needs to be a 34-bit number
4704 * or higher, so for readability reasons we picked the 36-bit multiple.
4705 * We are effectively turning the 16-bit minuend into a 36-bit number:
4706 * (a - b) % 0xFFFF = (a + 0xFFFF00000 - b) % 0xFFFF.
4708 r += 0xFFFF00000ULL; /* The output r is a 36-bit number. */
4710 /* A 33-bit number is subtracted from a 36-bit number (the input r). The
4711 * result (the output r) is a 36-bit number.
4713 r -= (src >> 32) + (src & 0xFFFFFFFF);
4715 /* The first input is a 16-bit number. The second input is a 20-bit
4716 * number. Their sum is a 21-bit number.
4718 r = (r & 0xFFFF) + (r >> 16);
4720 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
4721 * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1001E).
4723 r = (r & 0xFFFF) + (r >> 16);
4725 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
4726 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
4727 * 0x1001E), the output r is (0 .. 31). So no carry bit can be
4728 * generated, therefore the output r is always a 16-bit number.
4730 r = (r & 0xFFFF) + (r >> 16);
4735 *dst16_ptr = (uint16_t)r;
4742 instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline *p)
4744 struct thread *t = &p->threads[p->thread_id];
4745 struct instruction *ip = t->ip;
4746 uint8_t *dst_struct, *src_struct;
4747 uint16_t *dst16_ptr;
4748 uint32_t *src32_ptr;
4751 TRACE("[Thread %2u] ckadd (struct of 20 bytes)\n", p->thread_id);
4754 dst_struct = t->structs[ip->alu.dst.struct_id];
4755 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
4757 src_struct = t->structs[ip->alu.src.struct_id];
4758 src32_ptr = (uint32_t *)&src_struct[0];
4760 r0 = src32_ptr[0]; /* r0 is a 32-bit number. */
4761 r1 = src32_ptr[1]; /* r1 is a 32-bit number. */
4762 r0 += src32_ptr[2]; /* The output r0 is a 33-bit number. */
4763 r1 += src32_ptr[3]; /* The output r1 is a 33-bit number. */
4764 r0 += r1 + src32_ptr[4]; /* The output r0 is a 35-bit number. */
4766 /* The first input is a 16-bit number. The second input is a 19-bit
4767 * number. Their sum is a 20-bit number.
4769 r0 = (r0 & 0xFFFF) + (r0 >> 16);
4771 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
4772 * a 4-bit number (0 .. 15). The sum is a 17-bit number (0 .. 0x1000E).
4774 r0 = (r0 & 0xFFFF) + (r0 >> 16);
4776 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
4777 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
4778 * 0x1000E), the output r is (0 .. 15). So no carry bit can be
4779 * generated, therefore the output r is always a 16-bit number.
4781 r0 = (r0 & 0xFFFF) + (r0 >> 16);
4784 r0 = r0 ? r0 : 0xFFFF;
4786 *dst16_ptr = (uint16_t)r0;
4793 instr_alu_ckadd_struct_exec(struct rte_swx_pipeline *p)
4795 struct thread *t = &p->threads[p->thread_id];
4796 struct instruction *ip = t->ip;
4797 uint8_t *dst_struct, *src_struct;
4798 uint16_t *dst16_ptr;
4799 uint32_t *src32_ptr;
4803 TRACE("[Thread %2u] ckadd (struct)\n", p->thread_id);
4806 dst_struct = t->structs[ip->alu.dst.struct_id];
4807 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
4809 src_struct = t->structs[ip->alu.src.struct_id];
4810 src32_ptr = (uint32_t *)&src_struct[0];
4812 /* The max number of 32-bit words in a 256-byte header is 8 = 2^3.
4813 * Therefore, in the worst case scenario, a 35-bit number is added to a
4814 * 16-bit number (the input r), so the output r is 36-bit number.
4816 for (i = 0; i < ip->alu.src.n_bits / 32; i++, src32_ptr++)
4819 /* The first input is a 16-bit number. The second input is a 20-bit
4820 * number. Their sum is a 21-bit number.
4822 r = (r & 0xFFFF) + (r >> 16);
4824 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
4825 * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1000E).
4827 r = (r & 0xFFFF) + (r >> 16);
4829 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
4830 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
4831 * 0x1001E), the output r is (0 .. 31). So no carry bit can be
4832 * generated, therefore the output r is always a 16-bit number.
4834 r = (r & 0xFFFF) + (r >> 16);
4839 *dst16_ptr = (uint16_t)r;
4848 static struct regarray *
4849 regarray_find(struct rte_swx_pipeline *p, const char *name);
4852 instr_regprefetch_translate(struct rte_swx_pipeline *p,
4853 struct action *action,
4856 struct instruction *instr,
4857 struct instruction_data *data __rte_unused)
4859 char *regarray = tokens[1], *idx = tokens[2];
4862 uint32_t idx_struct_id, idx_val;
4864 CHECK(n_tokens == 3, EINVAL);
4866 r = regarray_find(p, regarray);
4869 /* REGPREFETCH_RH, REGPREFETCH_RM. */
4870 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4872 instr->type = INSTR_REGPREFETCH_RM;
4874 instr->type = INSTR_REGPREFETCH_RH;
4876 instr->regarray.regarray_id = r->id;
4877 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4878 instr->regarray.idx.n_bits = fidx->n_bits;
4879 instr->regarray.idx.offset = fidx->offset / 8;
4880 instr->regarray.dstsrc_val = 0; /* Unused. */
4884 /* REGPREFETCH_RI. */
4885 idx_val = strtoul(idx, &idx, 0);
4886 CHECK(!idx[0], EINVAL);
4888 instr->type = INSTR_REGPREFETCH_RI;
4889 instr->regarray.regarray_id = r->id;
4890 instr->regarray.idx_val = idx_val;
4891 instr->regarray.dstsrc_val = 0; /* Unused. */
4896 instr_regrd_translate(struct rte_swx_pipeline *p,
4897 struct action *action,
4900 struct instruction *instr,
4901 struct instruction_data *data __rte_unused)
4903 char *dst = tokens[1], *regarray = tokens[2], *idx = tokens[3];
4905 struct field *fdst, *fidx;
4906 uint32_t dst_struct_id, idx_struct_id, idx_val;
4908 CHECK(n_tokens == 4, EINVAL);
4910 r = regarray_find(p, regarray);
4913 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4914 CHECK(fdst, EINVAL);
4916 /* REGRD_HRH, REGRD_HRM, REGRD_MRH, REGRD_MRM. */
4917 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4919 instr->type = INSTR_REGRD_MRM;
4920 if (dst[0] == 'h' && idx[0] != 'h')
4921 instr->type = INSTR_REGRD_HRM;
4922 if (dst[0] != 'h' && idx[0] == 'h')
4923 instr->type = INSTR_REGRD_MRH;
4924 if (dst[0] == 'h' && idx[0] == 'h')
4925 instr->type = INSTR_REGRD_HRH;
4927 instr->regarray.regarray_id = r->id;
4928 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4929 instr->regarray.idx.n_bits = fidx->n_bits;
4930 instr->regarray.idx.offset = fidx->offset / 8;
4931 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
4932 instr->regarray.dstsrc.n_bits = fdst->n_bits;
4933 instr->regarray.dstsrc.offset = fdst->offset / 8;
4937 /* REGRD_MRI, REGRD_HRI. */
4938 idx_val = strtoul(idx, &idx, 0);
4939 CHECK(!idx[0], EINVAL);
4941 instr->type = INSTR_REGRD_MRI;
4943 instr->type = INSTR_REGRD_HRI;
4945 instr->regarray.regarray_id = r->id;
4946 instr->regarray.idx_val = idx_val;
4947 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
4948 instr->regarray.dstsrc.n_bits = fdst->n_bits;
4949 instr->regarray.dstsrc.offset = fdst->offset / 8;
4954 instr_regwr_translate(struct rte_swx_pipeline *p,
4955 struct action *action,
4958 struct instruction *instr,
4959 struct instruction_data *data __rte_unused)
4961 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
4963 struct field *fidx, *fsrc;
4965 uint32_t idx_struct_id, idx_val, src_struct_id;
4967 CHECK(n_tokens == 4, EINVAL);
4969 r = regarray_find(p, regarray);
4972 /* REGWR_RHH, REGWR_RHM, REGWR_RMH, REGWR_RMM. */
4973 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4974 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4976 instr->type = INSTR_REGWR_RMM;
4977 if (idx[0] == 'h' && src[0] != 'h')
4978 instr->type = INSTR_REGWR_RHM;
4979 if (idx[0] != 'h' && src[0] == 'h')
4980 instr->type = INSTR_REGWR_RMH;
4981 if (idx[0] == 'h' && src[0] == 'h')
4982 instr->type = INSTR_REGWR_RHH;
4984 instr->regarray.regarray_id = r->id;
4985 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4986 instr->regarray.idx.n_bits = fidx->n_bits;
4987 instr->regarray.idx.offset = fidx->offset / 8;
4988 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
4989 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
4990 instr->regarray.dstsrc.offset = fsrc->offset / 8;
4994 /* REGWR_RHI, REGWR_RMI. */
4995 if (fidx && !fsrc) {
4996 src_val = strtoull(src, &src, 0);
4997 CHECK(!src[0], EINVAL);
4999 instr->type = INSTR_REGWR_RMI;
5001 instr->type = INSTR_REGWR_RHI;
5003 instr->regarray.regarray_id = r->id;
5004 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
5005 instr->regarray.idx.n_bits = fidx->n_bits;
5006 instr->regarray.idx.offset = fidx->offset / 8;
5007 instr->regarray.dstsrc_val = src_val;
5011 /* REGWR_RIH, REGWR_RIM. */
5012 if (!fidx && fsrc) {
5013 idx_val = strtoul(idx, &idx, 0);
5014 CHECK(!idx[0], EINVAL);
5016 instr->type = INSTR_REGWR_RIM;
5018 instr->type = INSTR_REGWR_RIH;
5020 instr->regarray.regarray_id = r->id;
5021 instr->regarray.idx_val = idx_val;
5022 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
5023 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
5024 instr->regarray.dstsrc.offset = fsrc->offset / 8;
5029 src_val = strtoull(src, &src, 0);
5030 CHECK(!src[0], EINVAL);
5032 idx_val = strtoul(idx, &idx, 0);
5033 CHECK(!idx[0], EINVAL);
5035 instr->type = INSTR_REGWR_RII;
5036 instr->regarray.idx_val = idx_val;
5037 instr->regarray.dstsrc_val = src_val;
5043 instr_regadd_translate(struct rte_swx_pipeline *p,
5044 struct action *action,
5047 struct instruction *instr,
5048 struct instruction_data *data __rte_unused)
5050 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
5052 struct field *fidx, *fsrc;
5054 uint32_t idx_struct_id, idx_val, src_struct_id;
5056 CHECK(n_tokens == 4, EINVAL);
5058 r = regarray_find(p, regarray);
5061 /* REGADD_RHH, REGADD_RHM, REGADD_RMH, REGADD_RMM. */
5062 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
5063 fsrc = struct_field_parse(p, action, src, &src_struct_id);
5065 instr->type = INSTR_REGADD_RMM;
5066 if (idx[0] == 'h' && src[0] != 'h')
5067 instr->type = INSTR_REGADD_RHM;
5068 if (idx[0] != 'h' && src[0] == 'h')
5069 instr->type = INSTR_REGADD_RMH;
5070 if (idx[0] == 'h' && src[0] == 'h')
5071 instr->type = INSTR_REGADD_RHH;
5073 instr->regarray.regarray_id = r->id;
5074 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
5075 instr->regarray.idx.n_bits = fidx->n_bits;
5076 instr->regarray.idx.offset = fidx->offset / 8;
5077 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
5078 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
5079 instr->regarray.dstsrc.offset = fsrc->offset / 8;
5083 /* REGADD_RHI, REGADD_RMI. */
5084 if (fidx && !fsrc) {
5085 src_val = strtoull(src, &src, 0);
5086 CHECK(!src[0], EINVAL);
5088 instr->type = INSTR_REGADD_RMI;
5090 instr->type = INSTR_REGADD_RHI;
5092 instr->regarray.regarray_id = r->id;
5093 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
5094 instr->regarray.idx.n_bits = fidx->n_bits;
5095 instr->regarray.idx.offset = fidx->offset / 8;
5096 instr->regarray.dstsrc_val = src_val;
5100 /* REGADD_RIH, REGADD_RIM. */
5101 if (!fidx && fsrc) {
5102 idx_val = strtoul(idx, &idx, 0);
5103 CHECK(!idx[0], EINVAL);
5105 instr->type = INSTR_REGADD_RIM;
5107 instr->type = INSTR_REGADD_RIH;
5109 instr->regarray.regarray_id = r->id;
5110 instr->regarray.idx_val = idx_val;
5111 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
5112 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
5113 instr->regarray.dstsrc.offset = fsrc->offset / 8;
5118 src_val = strtoull(src, &src, 0);
5119 CHECK(!src[0], EINVAL);
5121 idx_val = strtoul(idx, &idx, 0);
5122 CHECK(!idx[0], EINVAL);
5124 instr->type = INSTR_REGADD_RII;
5125 instr->regarray.idx_val = idx_val;
5126 instr->regarray.dstsrc_val = src_val;
5130 static inline uint64_t *
5131 instr_regarray_regarray(struct rte_swx_pipeline *p, struct instruction *ip)
5133 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
5137 static inline uint64_t
5138 instr_regarray_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
5140 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
5142 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
5143 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
5144 uint64_t idx64 = *idx64_ptr;
5145 uint64_t idx64_mask = UINT64_MAX >> (64 - ip->regarray.idx.n_bits);
5146 uint64_t idx = idx64 & idx64_mask & r->size_mask;
5151 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5153 static inline uint64_t
5154 instr_regarray_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
5156 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
5158 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
5159 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
5160 uint64_t idx64 = *idx64_ptr;
5161 uint64_t idx = (ntoh64(idx64) >> (64 - ip->regarray.idx.n_bits)) & r->size_mask;
5168 #define instr_regarray_idx_nbo instr_regarray_idx_hbo
5172 static inline uint64_t
5173 instr_regarray_idx_imm(struct rte_swx_pipeline *p, struct instruction *ip)
5175 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
5177 uint64_t idx = ip->regarray.idx_val & r->size_mask;
5182 static inline uint64_t
5183 instr_regarray_src_hbo(struct thread *t, struct instruction *ip)
5185 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
5186 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
5187 uint64_t src64 = *src64_ptr;
5188 uint64_t src64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
5189 uint64_t src = src64 & src64_mask;
5194 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5196 static inline uint64_t
5197 instr_regarray_src_nbo(struct thread *t, struct instruction *ip)
5199 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
5200 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
5201 uint64_t src64 = *src64_ptr;
5202 uint64_t src = ntoh64(src64) >> (64 - ip->regarray.dstsrc.n_bits);
5209 #define instr_regarray_src_nbo instr_regarray_src_hbo
5214 instr_regarray_dst_hbo_src_hbo_set(struct thread *t, struct instruction *ip, uint64_t src)
5216 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
5217 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
5218 uint64_t dst64 = *dst64_ptr;
5219 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
5221 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
5225 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5228 instr_regarray_dst_nbo_src_hbo_set(struct thread *t, struct instruction *ip, uint64_t src)
5230 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
5231 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
5232 uint64_t dst64 = *dst64_ptr;
5233 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
5235 src = hton64(src) >> (64 - ip->regarray.dstsrc.n_bits);
5236 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
5241 #define instr_regarray_dst_nbo_src_hbo_set instr_regarray_dst_hbo_src_hbo_set
5246 instr_regprefetch_rh_exec(struct rte_swx_pipeline *p)
5248 struct thread *t = &p->threads[p->thread_id];
5249 struct instruction *ip = t->ip;
5250 uint64_t *regarray, idx;
5252 TRACE("[Thread %2u] regprefetch (r[h])\n", p->thread_id);
5255 regarray = instr_regarray_regarray(p, ip);
5256 idx = instr_regarray_idx_nbo(p, t, ip);
5257 rte_prefetch0(®array[idx]);
5264 instr_regprefetch_rm_exec(struct rte_swx_pipeline *p)
5266 struct thread *t = &p->threads[p->thread_id];
5267 struct instruction *ip = t->ip;
5268 uint64_t *regarray, idx;
5270 TRACE("[Thread %2u] regprefetch (r[m])\n", p->thread_id);
5273 regarray = instr_regarray_regarray(p, ip);
5274 idx = instr_regarray_idx_hbo(p, t, ip);
5275 rte_prefetch0(®array[idx]);
5282 instr_regprefetch_ri_exec(struct rte_swx_pipeline *p)
5284 struct thread *t = &p->threads[p->thread_id];
5285 struct instruction *ip = t->ip;
5286 uint64_t *regarray, idx;
5288 TRACE("[Thread %2u] regprefetch (r[i])\n", p->thread_id);
5291 regarray = instr_regarray_regarray(p, ip);
5292 idx = instr_regarray_idx_imm(p, ip);
5293 rte_prefetch0(®array[idx]);
5300 instr_regrd_hrh_exec(struct rte_swx_pipeline *p)
5302 struct thread *t = &p->threads[p->thread_id];
5303 struct instruction *ip = t->ip;
5304 uint64_t *regarray, idx;
5306 TRACE("[Thread %2u] regrd (h = r[h])\n", p->thread_id);
5309 regarray = instr_regarray_regarray(p, ip);
5310 idx = instr_regarray_idx_nbo(p, t, ip);
5311 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
5318 instr_regrd_hrm_exec(struct rte_swx_pipeline *p)
5320 struct thread *t = &p->threads[p->thread_id];
5321 struct instruction *ip = t->ip;
5322 uint64_t *regarray, idx;
5324 TRACE("[Thread %2u] regrd (h = r[m])\n", p->thread_id);
5327 regarray = instr_regarray_regarray(p, ip);
5328 idx = instr_regarray_idx_hbo(p, t, ip);
5329 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
5336 instr_regrd_mrh_exec(struct rte_swx_pipeline *p)
5338 struct thread *t = &p->threads[p->thread_id];
5339 struct instruction *ip = t->ip;
5340 uint64_t *regarray, idx;
5342 TRACE("[Thread %2u] regrd (m = r[h])\n", p->thread_id);
5345 regarray = instr_regarray_regarray(p, ip);
5346 idx = instr_regarray_idx_nbo(p, t, ip);
5347 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
5354 instr_regrd_mrm_exec(struct rte_swx_pipeline *p)
5356 struct thread *t = &p->threads[p->thread_id];
5357 struct instruction *ip = t->ip;
5358 uint64_t *regarray, idx;
5361 regarray = instr_regarray_regarray(p, ip);
5362 idx = instr_regarray_idx_hbo(p, t, ip);
5363 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
5370 instr_regrd_hri_exec(struct rte_swx_pipeline *p)
5372 struct thread *t = &p->threads[p->thread_id];
5373 struct instruction *ip = t->ip;
5374 uint64_t *regarray, idx;
5376 TRACE("[Thread %2u] regrd (h = r[i])\n", p->thread_id);
5379 regarray = instr_regarray_regarray(p, ip);
5380 idx = instr_regarray_idx_imm(p, ip);
5381 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
5388 instr_regrd_mri_exec(struct rte_swx_pipeline *p)
5390 struct thread *t = &p->threads[p->thread_id];
5391 struct instruction *ip = t->ip;
5392 uint64_t *regarray, idx;
5394 TRACE("[Thread %2u] regrd (m = r[i])\n", p->thread_id);
5397 regarray = instr_regarray_regarray(p, ip);
5398 idx = instr_regarray_idx_imm(p, ip);
5399 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
5406 instr_regwr_rhh_exec(struct rte_swx_pipeline *p)
5408 struct thread *t = &p->threads[p->thread_id];
5409 struct instruction *ip = t->ip;
5410 uint64_t *regarray, idx, src;
5412 TRACE("[Thread %2u] regwr (r[h] = h)\n", p->thread_id);
5415 regarray = instr_regarray_regarray(p, ip);
5416 idx = instr_regarray_idx_nbo(p, t, ip);
5417 src = instr_regarray_src_nbo(t, ip);
5418 regarray[idx] = src;
5425 instr_regwr_rhm_exec(struct rte_swx_pipeline *p)
5427 struct thread *t = &p->threads[p->thread_id];
5428 struct instruction *ip = t->ip;
5429 uint64_t *regarray, idx, src;
5431 TRACE("[Thread %2u] regwr (r[h] = m)\n", p->thread_id);
5434 regarray = instr_regarray_regarray(p, ip);
5435 idx = instr_regarray_idx_nbo(p, t, ip);
5436 src = instr_regarray_src_hbo(t, ip);
5437 regarray[idx] = src;
5444 instr_regwr_rmh_exec(struct rte_swx_pipeline *p)
5446 struct thread *t = &p->threads[p->thread_id];
5447 struct instruction *ip = t->ip;
5448 uint64_t *regarray, idx, src;
5450 TRACE("[Thread %2u] regwr (r[m] = h)\n", p->thread_id);
5453 regarray = instr_regarray_regarray(p, ip);
5454 idx = instr_regarray_idx_hbo(p, t, ip);
5455 src = instr_regarray_src_nbo(t, ip);
5456 regarray[idx] = src;
5463 instr_regwr_rmm_exec(struct rte_swx_pipeline *p)
5465 struct thread *t = &p->threads[p->thread_id];
5466 struct instruction *ip = t->ip;
5467 uint64_t *regarray, idx, src;
5469 TRACE("[Thread %2u] regwr (r[m] = m)\n", p->thread_id);
5472 regarray = instr_regarray_regarray(p, ip);
5473 idx = instr_regarray_idx_hbo(p, t, ip);
5474 src = instr_regarray_src_hbo(t, ip);
5475 regarray[idx] = src;
5482 instr_regwr_rhi_exec(struct rte_swx_pipeline *p)
5484 struct thread *t = &p->threads[p->thread_id];
5485 struct instruction *ip = t->ip;
5486 uint64_t *regarray, idx, src;
5488 TRACE("[Thread %2u] regwr (r[h] = i)\n", p->thread_id);
5491 regarray = instr_regarray_regarray(p, ip);
5492 idx = instr_regarray_idx_nbo(p, t, ip);
5493 src = ip->regarray.dstsrc_val;
5494 regarray[idx] = src;
5501 instr_regwr_rmi_exec(struct rte_swx_pipeline *p)
5503 struct thread *t = &p->threads[p->thread_id];
5504 struct instruction *ip = t->ip;
5505 uint64_t *regarray, idx, src;
5507 TRACE("[Thread %2u] regwr (r[m] = i)\n", p->thread_id);
5510 regarray = instr_regarray_regarray(p, ip);
5511 idx = instr_regarray_idx_hbo(p, t, ip);
5512 src = ip->regarray.dstsrc_val;
5513 regarray[idx] = src;
5520 instr_regwr_rih_exec(struct rte_swx_pipeline *p)
5522 struct thread *t = &p->threads[p->thread_id];
5523 struct instruction *ip = t->ip;
5524 uint64_t *regarray, idx, src;
5526 TRACE("[Thread %2u] regwr (r[i] = h)\n", p->thread_id);
5529 regarray = instr_regarray_regarray(p, ip);
5530 idx = instr_regarray_idx_imm(p, ip);
5531 src = instr_regarray_src_nbo(t, ip);
5532 regarray[idx] = src;
5539 instr_regwr_rim_exec(struct rte_swx_pipeline *p)
5541 struct thread *t = &p->threads[p->thread_id];
5542 struct instruction *ip = t->ip;
5543 uint64_t *regarray, idx, src;
5545 TRACE("[Thread %2u] regwr (r[i] = m)\n", p->thread_id);
5548 regarray = instr_regarray_regarray(p, ip);
5549 idx = instr_regarray_idx_imm(p, ip);
5550 src = instr_regarray_src_hbo(t, ip);
5551 regarray[idx] = src;
5558 instr_regwr_rii_exec(struct rte_swx_pipeline *p)
5560 struct thread *t = &p->threads[p->thread_id];
5561 struct instruction *ip = t->ip;
5562 uint64_t *regarray, idx, src;
5564 TRACE("[Thread %2u] regwr (r[i] = i)\n", p->thread_id);
5567 regarray = instr_regarray_regarray(p, ip);
5568 idx = instr_regarray_idx_imm(p, ip);
5569 src = ip->regarray.dstsrc_val;
5570 regarray[idx] = src;
5577 instr_regadd_rhh_exec(struct rte_swx_pipeline *p)
5579 struct thread *t = &p->threads[p->thread_id];
5580 struct instruction *ip = t->ip;
5581 uint64_t *regarray, idx, src;
5583 TRACE("[Thread %2u] regadd (r[h] += h)\n", p->thread_id);
5586 regarray = instr_regarray_regarray(p, ip);
5587 idx = instr_regarray_idx_nbo(p, t, ip);
5588 src = instr_regarray_src_nbo(t, ip);
5589 regarray[idx] += src;
5596 instr_regadd_rhm_exec(struct rte_swx_pipeline *p)
5598 struct thread *t = &p->threads[p->thread_id];
5599 struct instruction *ip = t->ip;
5600 uint64_t *regarray, idx, src;
5602 TRACE("[Thread %2u] regadd (r[h] += m)\n", p->thread_id);
5605 regarray = instr_regarray_regarray(p, ip);
5606 idx = instr_regarray_idx_nbo(p, t, ip);
5607 src = instr_regarray_src_hbo(t, ip);
5608 regarray[idx] += src;
5615 instr_regadd_rmh_exec(struct rte_swx_pipeline *p)
5617 struct thread *t = &p->threads[p->thread_id];
5618 struct instruction *ip = t->ip;
5619 uint64_t *regarray, idx, src;
5621 TRACE("[Thread %2u] regadd (r[m] += h)\n", p->thread_id);
5624 regarray = instr_regarray_regarray(p, ip);
5625 idx = instr_regarray_idx_hbo(p, t, ip);
5626 src = instr_regarray_src_nbo(t, ip);
5627 regarray[idx] += src;
5634 instr_regadd_rmm_exec(struct rte_swx_pipeline *p)
5636 struct thread *t = &p->threads[p->thread_id];
5637 struct instruction *ip = t->ip;
5638 uint64_t *regarray, idx, src;
5640 TRACE("[Thread %2u] regadd (r[m] += m)\n", p->thread_id);
5643 regarray = instr_regarray_regarray(p, ip);
5644 idx = instr_regarray_idx_hbo(p, t, ip);
5645 src = instr_regarray_src_hbo(t, ip);
5646 regarray[idx] += src;
5653 instr_regadd_rhi_exec(struct rte_swx_pipeline *p)
5655 struct thread *t = &p->threads[p->thread_id];
5656 struct instruction *ip = t->ip;
5657 uint64_t *regarray, idx, src;
5659 TRACE("[Thread %2u] regadd (r[h] += i)\n", p->thread_id);
5662 regarray = instr_regarray_regarray(p, ip);
5663 idx = instr_regarray_idx_nbo(p, t, ip);
5664 src = ip->regarray.dstsrc_val;
5665 regarray[idx] += src;
5672 instr_regadd_rmi_exec(struct rte_swx_pipeline *p)
5674 struct thread *t = &p->threads[p->thread_id];
5675 struct instruction *ip = t->ip;
5676 uint64_t *regarray, idx, src;
5678 TRACE("[Thread %2u] regadd (r[m] += i)\n", p->thread_id);
5681 regarray = instr_regarray_regarray(p, ip);
5682 idx = instr_regarray_idx_hbo(p, t, ip);
5683 src = ip->regarray.dstsrc_val;
5684 regarray[idx] += src;
5691 instr_regadd_rih_exec(struct rte_swx_pipeline *p)
5693 struct thread *t = &p->threads[p->thread_id];
5694 struct instruction *ip = t->ip;
5695 uint64_t *regarray, idx, src;
5697 TRACE("[Thread %2u] regadd (r[i] += h)\n", p->thread_id);
5700 regarray = instr_regarray_regarray(p, ip);
5701 idx = instr_regarray_idx_imm(p, ip);
5702 src = instr_regarray_src_nbo(t, ip);
5703 regarray[idx] += src;
5710 instr_regadd_rim_exec(struct rte_swx_pipeline *p)
5712 struct thread *t = &p->threads[p->thread_id];
5713 struct instruction *ip = t->ip;
5714 uint64_t *regarray, idx, src;
5716 TRACE("[Thread %2u] regadd (r[i] += m)\n", p->thread_id);
5719 regarray = instr_regarray_regarray(p, ip);
5720 idx = instr_regarray_idx_imm(p, ip);
5721 src = instr_regarray_src_hbo(t, ip);
5722 regarray[idx] += src;
5729 instr_regadd_rii_exec(struct rte_swx_pipeline *p)
5731 struct thread *t = &p->threads[p->thread_id];
5732 struct instruction *ip = t->ip;
5733 uint64_t *regarray, idx, src;
5735 TRACE("[Thread %2u] regadd (r[i] += i)\n", p->thread_id);
5738 regarray = instr_regarray_regarray(p, ip);
5739 idx = instr_regarray_idx_imm(p, ip);
5740 src = ip->regarray.dstsrc_val;
5741 regarray[idx] += src;
5750 static struct metarray *
5751 metarray_find(struct rte_swx_pipeline *p, const char *name);
5754 instr_metprefetch_translate(struct rte_swx_pipeline *p,
5755 struct action *action,
5758 struct instruction *instr,
5759 struct instruction_data *data __rte_unused)
5761 char *metarray = tokens[1], *idx = tokens[2];
5764 uint32_t idx_struct_id, idx_val;
5766 CHECK(n_tokens == 3, EINVAL);
5768 m = metarray_find(p, metarray);
5771 /* METPREFETCH_H, METPREFETCH_M. */
5772 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
5774 instr->type = INSTR_METPREFETCH_M;
5776 instr->type = INSTR_METPREFETCH_H;
5778 instr->meter.metarray_id = m->id;
5779 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
5780 instr->meter.idx.n_bits = fidx->n_bits;
5781 instr->meter.idx.offset = fidx->offset / 8;
5785 /* METPREFETCH_I. */
5786 idx_val = strtoul(idx, &idx, 0);
5787 CHECK(!idx[0], EINVAL);
5789 instr->type = INSTR_METPREFETCH_I;
5790 instr->meter.metarray_id = m->id;
5791 instr->meter.idx_val = idx_val;
5796 instr_meter_translate(struct rte_swx_pipeline *p,
5797 struct action *action,
5800 struct instruction *instr,
5801 struct instruction_data *data __rte_unused)
5803 char *metarray = tokens[1], *idx = tokens[2], *length = tokens[3];
5804 char *color_in = tokens[4], *color_out = tokens[5];
5806 struct field *fidx, *flength, *fcin, *fcout;
5807 uint32_t idx_struct_id, length_struct_id;
5808 uint32_t color_in_struct_id, color_out_struct_id;
5810 CHECK(n_tokens == 6, EINVAL);
5812 m = metarray_find(p, metarray);
5815 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
5817 flength = struct_field_parse(p, action, length, &length_struct_id);
5818 CHECK(flength, EINVAL);
5820 fcin = struct_field_parse(p, action, color_in, &color_in_struct_id);
5822 fcout = struct_field_parse(p, NULL, color_out, &color_out_struct_id);
5823 CHECK(fcout, EINVAL);
5825 /* index = HMEFT, length = HMEFT, color_in = MEFT, color_out = MEF. */
5827 instr->type = INSTR_METER_MMM;
5828 if (idx[0] == 'h' && length[0] == 'h')
5829 instr->type = INSTR_METER_HHM;
5830 if (idx[0] == 'h' && length[0] != 'h')
5831 instr->type = INSTR_METER_HMM;
5832 if (idx[0] != 'h' && length[0] == 'h')
5833 instr->type = INSTR_METER_MHM;
5835 instr->meter.metarray_id = m->id;
5837 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
5838 instr->meter.idx.n_bits = fidx->n_bits;
5839 instr->meter.idx.offset = fidx->offset / 8;
5841 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5842 instr->meter.length.n_bits = flength->n_bits;
5843 instr->meter.length.offset = flength->offset / 8;
5845 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
5846 instr->meter.color_in.n_bits = fcin->n_bits;
5847 instr->meter.color_in.offset = fcin->offset / 8;
5849 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5850 instr->meter.color_out.n_bits = fcout->n_bits;
5851 instr->meter.color_out.offset = fcout->offset / 8;
5856 /* index = HMEFT, length = HMEFT, color_in = I, color_out = MEF. */
5857 if (fidx && !fcin) {
5858 uint32_t color_in_val = strtoul(color_in, &color_in, 0);
5859 CHECK(!color_in[0], EINVAL);
5861 instr->type = INSTR_METER_MMI;
5862 if (idx[0] == 'h' && length[0] == 'h')
5863 instr->type = INSTR_METER_HHI;
5864 if (idx[0] == 'h' && length[0] != 'h')
5865 instr->type = INSTR_METER_HMI;
5866 if (idx[0] != 'h' && length[0] == 'h')
5867 instr->type = INSTR_METER_MHI;
5869 instr->meter.metarray_id = m->id;
5871 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
5872 instr->meter.idx.n_bits = fidx->n_bits;
5873 instr->meter.idx.offset = fidx->offset / 8;
5875 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5876 instr->meter.length.n_bits = flength->n_bits;
5877 instr->meter.length.offset = flength->offset / 8;
5879 instr->meter.color_in_val = color_in_val;
5881 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5882 instr->meter.color_out.n_bits = fcout->n_bits;
5883 instr->meter.color_out.offset = fcout->offset / 8;
5888 /* index = I, length = HMEFT, color_in = MEFT, color_out = MEF. */
5889 if (!fidx && fcin) {
5892 idx_val = strtoul(idx, &idx, 0);
5893 CHECK(!idx[0], EINVAL);
5895 instr->type = INSTR_METER_IMM;
5896 if (length[0] == 'h')
5897 instr->type = INSTR_METER_IHM;
5899 instr->meter.metarray_id = m->id;
5901 instr->meter.idx_val = idx_val;
5903 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5904 instr->meter.length.n_bits = flength->n_bits;
5905 instr->meter.length.offset = flength->offset / 8;
5907 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
5908 instr->meter.color_in.n_bits = fcin->n_bits;
5909 instr->meter.color_in.offset = fcin->offset / 8;
5911 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5912 instr->meter.color_out.n_bits = fcout->n_bits;
5913 instr->meter.color_out.offset = fcout->offset / 8;
5918 /* index = I, length = HMEFT, color_in = I, color_out = MEF. */
5919 if (!fidx && !fcin) {
5920 uint32_t idx_val, color_in_val;
5922 idx_val = strtoul(idx, &idx, 0);
5923 CHECK(!idx[0], EINVAL);
5925 color_in_val = strtoul(color_in, &color_in, 0);
5926 CHECK(!color_in[0], EINVAL);
5928 instr->type = INSTR_METER_IMI;
5929 if (length[0] == 'h')
5930 instr->type = INSTR_METER_IHI;
5932 instr->meter.metarray_id = m->id;
5934 instr->meter.idx_val = idx_val;
5936 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5937 instr->meter.length.n_bits = flength->n_bits;
5938 instr->meter.length.offset = flength->offset / 8;
5940 instr->meter.color_in_val = color_in_val;
5942 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5943 instr->meter.color_out.n_bits = fcout->n_bits;
5944 instr->meter.color_out.offset = fcout->offset / 8;
5952 static inline struct meter *
5953 instr_meter_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
5955 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
5957 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
5958 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
5959 uint64_t idx64 = *idx64_ptr;
5960 uint64_t idx64_mask = UINT64_MAX >> (64 - (ip)->meter.idx.n_bits);
5961 uint64_t idx = idx64 & idx64_mask & r->size_mask;
5963 return &r->metarray[idx];
5966 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5968 static inline struct meter *
5969 instr_meter_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
5971 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
5973 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
5974 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
5975 uint64_t idx64 = *idx64_ptr;
5976 uint64_t idx = (ntoh64(idx64) >> (64 - ip->meter.idx.n_bits)) & r->size_mask;
5978 return &r->metarray[idx];
5983 #define instr_meter_idx_nbo instr_meter_idx_hbo
5987 static inline struct meter *
5988 instr_meter_idx_imm(struct rte_swx_pipeline *p, struct instruction *ip)
5990 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
5992 uint64_t idx = ip->meter.idx_val & r->size_mask;
5994 return &r->metarray[idx];
5997 static inline uint32_t
5998 instr_meter_length_hbo(struct thread *t, struct instruction *ip)
6000 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
6001 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
6002 uint64_t src64 = *src64_ptr;
6003 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->meter.length.n_bits);
6004 uint64_t src = src64 & src64_mask;
6006 return (uint32_t)src;
6009 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
6011 static inline uint32_t
6012 instr_meter_length_nbo(struct thread *t, struct instruction *ip)
6014 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
6015 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
6016 uint64_t src64 = *src64_ptr;
6017 uint64_t src = ntoh64(src64) >> (64 - ip->meter.length.n_bits);
6019 return (uint32_t)src;
6024 #define instr_meter_length_nbo instr_meter_length_hbo
6028 static inline enum rte_color
6029 instr_meter_color_in_hbo(struct thread *t, struct instruction *ip)
6031 uint8_t *src_struct = t->structs[ip->meter.color_in.struct_id];
6032 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.color_in.offset];
6033 uint64_t src64 = *src64_ptr;
6034 uint64_t src64_mask = UINT64_MAX >> (64 - ip->meter.color_in.n_bits);
6035 uint64_t src = src64 & src64_mask;
6037 return (enum rte_color)src;
6041 instr_meter_color_out_hbo_set(struct thread *t, struct instruction *ip, enum rte_color color_out)
6043 uint8_t *dst_struct = t->structs[ip->meter.color_out.struct_id];
6044 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->meter.color_out.offset];
6045 uint64_t dst64 = *dst64_ptr;
6046 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->meter.color_out.n_bits);
6048 uint64_t src = (uint64_t)color_out;
6050 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
6054 instr_metprefetch_h_exec(struct rte_swx_pipeline *p)
6056 struct thread *t = &p->threads[p->thread_id];
6057 struct instruction *ip = t->ip;
6060 TRACE("[Thread %2u] metprefetch (h)\n", p->thread_id);
6063 m = instr_meter_idx_nbo(p, t, ip);
6071 instr_metprefetch_m_exec(struct rte_swx_pipeline *p)
6073 struct thread *t = &p->threads[p->thread_id];
6074 struct instruction *ip = t->ip;
6077 TRACE("[Thread %2u] metprefetch (m)\n", p->thread_id);
6080 m = instr_meter_idx_hbo(p, t, ip);
6088 instr_metprefetch_i_exec(struct rte_swx_pipeline *p)
6090 struct thread *t = &p->threads[p->thread_id];
6091 struct instruction *ip = t->ip;
6094 TRACE("[Thread %2u] metprefetch (i)\n", p->thread_id);
6097 m = instr_meter_idx_imm(p, ip);
6105 instr_meter_hhm_exec(struct rte_swx_pipeline *p)
6107 struct thread *t = &p->threads[p->thread_id];
6108 struct instruction *ip = t->ip;
6110 uint64_t time, n_pkts, n_bytes;
6112 enum rte_color color_in, color_out;
6114 TRACE("[Thread %2u] meter (hhm)\n", p->thread_id);
6117 m = instr_meter_idx_nbo(p, t, ip);
6118 rte_prefetch0(m->n_pkts);
6119 time = rte_get_tsc_cycles();
6120 length = instr_meter_length_nbo(t, ip);
6121 color_in = instr_meter_color_in_hbo(t, ip);
6123 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6124 &m->profile->profile,
6129 color_out &= m->color_mask;
6131 n_pkts = m->n_pkts[color_out];
6132 n_bytes = m->n_bytes[color_out];
6134 instr_meter_color_out_hbo_set(t, ip, color_out);
6136 m->n_pkts[color_out] = n_pkts + 1;
6137 m->n_bytes[color_out] = n_bytes + length;
6144 instr_meter_hhi_exec(struct rte_swx_pipeline *p)
6146 struct thread *t = &p->threads[p->thread_id];
6147 struct instruction *ip = t->ip;
6149 uint64_t time, n_pkts, n_bytes;
6151 enum rte_color color_in, color_out;
6153 TRACE("[Thread %2u] meter (hhi)\n", p->thread_id);
6156 m = instr_meter_idx_nbo(p, t, ip);
6157 rte_prefetch0(m->n_pkts);
6158 time = rte_get_tsc_cycles();
6159 length = instr_meter_length_nbo(t, ip);
6160 color_in = (enum rte_color)ip->meter.color_in_val;
6162 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6163 &m->profile->profile,
6168 color_out &= m->color_mask;
6170 n_pkts = m->n_pkts[color_out];
6171 n_bytes = m->n_bytes[color_out];
6173 instr_meter_color_out_hbo_set(t, ip, color_out);
6175 m->n_pkts[color_out] = n_pkts + 1;
6176 m->n_bytes[color_out] = n_bytes + length;
6183 instr_meter_hmm_exec(struct rte_swx_pipeline *p)
6185 struct thread *t = &p->threads[p->thread_id];
6186 struct instruction *ip = t->ip;
6188 uint64_t time, n_pkts, n_bytes;
6190 enum rte_color color_in, color_out;
6192 TRACE("[Thread %2u] meter (hmm)\n", p->thread_id);
6195 m = instr_meter_idx_nbo(p, t, ip);
6196 rte_prefetch0(m->n_pkts);
6197 time = rte_get_tsc_cycles();
6198 length = instr_meter_length_hbo(t, ip);
6199 color_in = instr_meter_color_in_hbo(t, ip);
6201 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6202 &m->profile->profile,
6207 color_out &= m->color_mask;
6209 n_pkts = m->n_pkts[color_out];
6210 n_bytes = m->n_bytes[color_out];
6212 instr_meter_color_out_hbo_set(t, ip, color_out);
6214 m->n_pkts[color_out] = n_pkts + 1;
6215 m->n_bytes[color_out] = n_bytes + length;
6221 instr_meter_hmi_exec(struct rte_swx_pipeline *p)
6223 struct thread *t = &p->threads[p->thread_id];
6224 struct instruction *ip = t->ip;
6226 uint64_t time, n_pkts, n_bytes;
6228 enum rte_color color_in, color_out;
6230 TRACE("[Thread %2u] meter (hmi)\n", p->thread_id);
6233 m = instr_meter_idx_nbo(p, t, ip);
6234 rte_prefetch0(m->n_pkts);
6235 time = rte_get_tsc_cycles();
6236 length = instr_meter_length_hbo(t, ip);
6237 color_in = (enum rte_color)ip->meter.color_in_val;
6239 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6240 &m->profile->profile,
6245 color_out &= m->color_mask;
6247 n_pkts = m->n_pkts[color_out];
6248 n_bytes = m->n_bytes[color_out];
6250 instr_meter_color_out_hbo_set(t, ip, color_out);
6252 m->n_pkts[color_out] = n_pkts + 1;
6253 m->n_bytes[color_out] = n_bytes + length;
6260 instr_meter_mhm_exec(struct rte_swx_pipeline *p)
6262 struct thread *t = &p->threads[p->thread_id];
6263 struct instruction *ip = t->ip;
6265 uint64_t time, n_pkts, n_bytes;
6267 enum rte_color color_in, color_out;
6269 TRACE("[Thread %2u] meter (mhm)\n", p->thread_id);
6272 m = instr_meter_idx_hbo(p, t, ip);
6273 rte_prefetch0(m->n_pkts);
6274 time = rte_get_tsc_cycles();
6275 length = instr_meter_length_nbo(t, ip);
6276 color_in = instr_meter_color_in_hbo(t, ip);
6278 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6279 &m->profile->profile,
6284 color_out &= m->color_mask;
6286 n_pkts = m->n_pkts[color_out];
6287 n_bytes = m->n_bytes[color_out];
6289 instr_meter_color_out_hbo_set(t, ip, color_out);
6291 m->n_pkts[color_out] = n_pkts + 1;
6292 m->n_bytes[color_out] = n_bytes + length;
6299 instr_meter_mhi_exec(struct rte_swx_pipeline *p)
6301 struct thread *t = &p->threads[p->thread_id];
6302 struct instruction *ip = t->ip;
6304 uint64_t time, n_pkts, n_bytes;
6306 enum rte_color color_in, color_out;
6308 TRACE("[Thread %2u] meter (mhi)\n", p->thread_id);
6311 m = instr_meter_idx_hbo(p, t, ip);
6312 rte_prefetch0(m->n_pkts);
6313 time = rte_get_tsc_cycles();
6314 length = instr_meter_length_nbo(t, ip);
6315 color_in = (enum rte_color)ip->meter.color_in_val;
6317 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6318 &m->profile->profile,
6323 color_out &= m->color_mask;
6325 n_pkts = m->n_pkts[color_out];
6326 n_bytes = m->n_bytes[color_out];
6328 instr_meter_color_out_hbo_set(t, ip, color_out);
6330 m->n_pkts[color_out] = n_pkts + 1;
6331 m->n_bytes[color_out] = n_bytes + length;
6338 instr_meter_mmm_exec(struct rte_swx_pipeline *p)
6340 struct thread *t = &p->threads[p->thread_id];
6341 struct instruction *ip = t->ip;
6343 uint64_t time, n_pkts, n_bytes;
6345 enum rte_color color_in, color_out;
6347 TRACE("[Thread %2u] meter (mmm)\n", p->thread_id);
6350 m = instr_meter_idx_hbo(p, t, ip);
6351 rte_prefetch0(m->n_pkts);
6352 time = rte_get_tsc_cycles();
6353 length = instr_meter_length_hbo(t, ip);
6354 color_in = instr_meter_color_in_hbo(t, ip);
6356 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6357 &m->profile->profile,
6362 color_out &= m->color_mask;
6364 n_pkts = m->n_pkts[color_out];
6365 n_bytes = m->n_bytes[color_out];
6367 instr_meter_color_out_hbo_set(t, ip, color_out);
6369 m->n_pkts[color_out] = n_pkts + 1;
6370 m->n_bytes[color_out] = n_bytes + length;
6377 instr_meter_mmi_exec(struct rte_swx_pipeline *p)
6379 struct thread *t = &p->threads[p->thread_id];
6380 struct instruction *ip = t->ip;
6382 uint64_t time, n_pkts, n_bytes;
6384 enum rte_color color_in, color_out;
6386 TRACE("[Thread %2u] meter (mmi)\n", p->thread_id);
6389 m = instr_meter_idx_hbo(p, t, ip);
6390 rte_prefetch0(m->n_pkts);
6391 time = rte_get_tsc_cycles();
6392 length = instr_meter_length_hbo(t, ip);
6393 color_in = (enum rte_color)ip->meter.color_in_val;
6395 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6396 &m->profile->profile,
6401 color_out &= m->color_mask;
6403 n_pkts = m->n_pkts[color_out];
6404 n_bytes = m->n_bytes[color_out];
6406 instr_meter_color_out_hbo_set(t, ip, color_out);
6408 m->n_pkts[color_out] = n_pkts + 1;
6409 m->n_bytes[color_out] = n_bytes + length;
6416 instr_meter_ihm_exec(struct rte_swx_pipeline *p)
6418 struct thread *t = &p->threads[p->thread_id];
6419 struct instruction *ip = t->ip;
6421 uint64_t time, n_pkts, n_bytes;
6423 enum rte_color color_in, color_out;
6425 TRACE("[Thread %2u] meter (ihm)\n", p->thread_id);
6428 m = instr_meter_idx_imm(p, ip);
6429 rte_prefetch0(m->n_pkts);
6430 time = rte_get_tsc_cycles();
6431 length = instr_meter_length_nbo(t, ip);
6432 color_in = instr_meter_color_in_hbo(t, ip);
6434 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6435 &m->profile->profile,
6440 color_out &= m->color_mask;
6442 n_pkts = m->n_pkts[color_out];
6443 n_bytes = m->n_bytes[color_out];
6445 instr_meter_color_out_hbo_set(t, ip, color_out);
6447 m->n_pkts[color_out] = n_pkts + 1;
6448 m->n_bytes[color_out] = n_bytes + length;
6455 instr_meter_ihi_exec(struct rte_swx_pipeline *p)
6457 struct thread *t = &p->threads[p->thread_id];
6458 struct instruction *ip = t->ip;
6460 uint64_t time, n_pkts, n_bytes;
6462 enum rte_color color_in, color_out;
6464 TRACE("[Thread %2u] meter (ihi)\n", p->thread_id);
6467 m = instr_meter_idx_imm(p, ip);
6468 rte_prefetch0(m->n_pkts);
6469 time = rte_get_tsc_cycles();
6470 length = instr_meter_length_nbo(t, ip);
6471 color_in = (enum rte_color)ip->meter.color_in_val;
6473 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6474 &m->profile->profile,
6479 color_out &= m->color_mask;
6481 n_pkts = m->n_pkts[color_out];
6482 n_bytes = m->n_bytes[color_out];
6484 instr_meter_color_out_hbo_set(t, ip, color_out);
6486 m->n_pkts[color_out] = n_pkts + 1;
6487 m->n_bytes[color_out] = n_bytes + length;
6494 instr_meter_imm_exec(struct rte_swx_pipeline *p)
6496 struct thread *t = &p->threads[p->thread_id];
6497 struct instruction *ip = t->ip;
6499 uint64_t time, n_pkts, n_bytes;
6501 enum rte_color color_in, color_out;
6503 TRACE("[Thread %2u] meter (imm)\n", p->thread_id);
6506 m = instr_meter_idx_imm(p, ip);
6507 rte_prefetch0(m->n_pkts);
6508 time = rte_get_tsc_cycles();
6509 length = instr_meter_length_hbo(t, ip);
6510 color_in = instr_meter_color_in_hbo(t, ip);
6512 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6513 &m->profile->profile,
6518 color_out &= m->color_mask;
6520 n_pkts = m->n_pkts[color_out];
6521 n_bytes = m->n_bytes[color_out];
6523 instr_meter_color_out_hbo_set(t, ip, color_out);
6525 m->n_pkts[color_out] = n_pkts + 1;
6526 m->n_bytes[color_out] = n_bytes + length;
6532 instr_meter_imi_exec(struct rte_swx_pipeline *p)
6534 struct thread *t = &p->threads[p->thread_id];
6535 struct instruction *ip = t->ip;
6537 uint64_t time, n_pkts, n_bytes;
6539 enum rte_color color_in, color_out;
6541 TRACE("[Thread %2u] meter (imi)\n", p->thread_id);
6544 m = instr_meter_idx_imm(p, ip);
6545 rte_prefetch0(m->n_pkts);
6546 time = rte_get_tsc_cycles();
6547 length = instr_meter_length_hbo(t, ip);
6548 color_in = (enum rte_color)ip->meter.color_in_val;
6550 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6551 &m->profile->profile,
6556 color_out &= m->color_mask;
6558 n_pkts = m->n_pkts[color_out];
6559 n_bytes = m->n_bytes[color_out];
6561 instr_meter_color_out_hbo_set(t, ip, color_out);
6563 m->n_pkts[color_out] = n_pkts + 1;
6564 m->n_bytes[color_out] = n_bytes + length;
6573 static struct action *
6574 action_find(struct rte_swx_pipeline *p, const char *name);
6577 instr_jmp_translate(struct rte_swx_pipeline *p __rte_unused,
6578 struct action *action __rte_unused,
6581 struct instruction *instr,
6582 struct instruction_data *data)
6584 CHECK(n_tokens == 2, EINVAL);
6586 strcpy(data->jmp_label, tokens[1]);
6588 instr->type = INSTR_JMP;
6589 instr->jmp.ip = NULL; /* Resolved later. */
6594 instr_jmp_valid_translate(struct rte_swx_pipeline *p,
6595 struct action *action __rte_unused,
6598 struct instruction *instr,
6599 struct instruction_data *data)
6603 CHECK(n_tokens == 3, EINVAL);
6605 strcpy(data->jmp_label, tokens[1]);
6607 h = header_parse(p, tokens[2]);
6610 instr->type = INSTR_JMP_VALID;
6611 instr->jmp.ip = NULL; /* Resolved later. */
6612 instr->jmp.header_id = h->id;
6617 instr_jmp_invalid_translate(struct rte_swx_pipeline *p,
6618 struct action *action __rte_unused,
6621 struct instruction *instr,
6622 struct instruction_data *data)
6626 CHECK(n_tokens == 3, EINVAL);
6628 strcpy(data->jmp_label, tokens[1]);
6630 h = header_parse(p, tokens[2]);
6633 instr->type = INSTR_JMP_INVALID;
6634 instr->jmp.ip = NULL; /* Resolved later. */
6635 instr->jmp.header_id = h->id;
6640 instr_jmp_hit_translate(struct rte_swx_pipeline *p __rte_unused,
6641 struct action *action,
6644 struct instruction *instr,
6645 struct instruction_data *data)
6647 CHECK(!action, EINVAL);
6648 CHECK(n_tokens == 2, EINVAL);
6650 strcpy(data->jmp_label, tokens[1]);
6652 instr->type = INSTR_JMP_HIT;
6653 instr->jmp.ip = NULL; /* Resolved later. */
6658 instr_jmp_miss_translate(struct rte_swx_pipeline *p __rte_unused,
6659 struct action *action,
6662 struct instruction *instr,
6663 struct instruction_data *data)
6665 CHECK(!action, EINVAL);
6666 CHECK(n_tokens == 2, EINVAL);
6668 strcpy(data->jmp_label, tokens[1]);
6670 instr->type = INSTR_JMP_MISS;
6671 instr->jmp.ip = NULL; /* Resolved later. */
6676 instr_jmp_action_hit_translate(struct rte_swx_pipeline *p,
6677 struct action *action,
6680 struct instruction *instr,
6681 struct instruction_data *data)
6685 CHECK(!action, EINVAL);
6686 CHECK(n_tokens == 3, EINVAL);
6688 strcpy(data->jmp_label, tokens[1]);
6690 a = action_find(p, tokens[2]);
6693 instr->type = INSTR_JMP_ACTION_HIT;
6694 instr->jmp.ip = NULL; /* Resolved later. */
6695 instr->jmp.action_id = a->id;
6700 instr_jmp_action_miss_translate(struct rte_swx_pipeline *p,
6701 struct action *action,
6704 struct instruction *instr,
6705 struct instruction_data *data)
6709 CHECK(!action, EINVAL);
6710 CHECK(n_tokens == 3, EINVAL);
6712 strcpy(data->jmp_label, tokens[1]);
6714 a = action_find(p, tokens[2]);
6717 instr->type = INSTR_JMP_ACTION_MISS;
6718 instr->jmp.ip = NULL; /* Resolved later. */
6719 instr->jmp.action_id = a->id;
6724 instr_jmp_eq_translate(struct rte_swx_pipeline *p,
6725 struct action *action,
6728 struct instruction *instr,
6729 struct instruction_data *data)
6731 char *a = tokens[2], *b = tokens[3];
6732 struct field *fa, *fb;
6734 uint32_t a_struct_id, b_struct_id;
6736 CHECK(n_tokens == 4, EINVAL);
6738 strcpy(data->jmp_label, tokens[1]);
6740 fa = struct_field_parse(p, action, a, &a_struct_id);
6743 /* JMP_EQ or JMP_EQ_S. */
6744 fb = struct_field_parse(p, action, b, &b_struct_id);
6746 instr->type = INSTR_JMP_EQ;
6747 if ((a[0] == 'h' && b[0] != 'h') ||
6748 (a[0] != 'h' && b[0] == 'h'))
6749 instr->type = INSTR_JMP_EQ_S;
6750 instr->jmp.ip = NULL; /* Resolved later. */
6752 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6753 instr->jmp.a.n_bits = fa->n_bits;
6754 instr->jmp.a.offset = fa->offset / 8;
6755 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6756 instr->jmp.b.n_bits = fb->n_bits;
6757 instr->jmp.b.offset = fb->offset / 8;
6762 b_val = strtoull(b, &b, 0);
6763 CHECK(!b[0], EINVAL);
6766 b_val = hton64(b_val) >> (64 - fa->n_bits);
6768 instr->type = INSTR_JMP_EQ_I;
6769 instr->jmp.ip = NULL; /* Resolved later. */
6770 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6771 instr->jmp.a.n_bits = fa->n_bits;
6772 instr->jmp.a.offset = fa->offset / 8;
6773 instr->jmp.b_val = b_val;
6778 instr_jmp_neq_translate(struct rte_swx_pipeline *p,
6779 struct action *action,
6782 struct instruction *instr,
6783 struct instruction_data *data)
6785 char *a = tokens[2], *b = tokens[3];
6786 struct field *fa, *fb;
6788 uint32_t a_struct_id, b_struct_id;
6790 CHECK(n_tokens == 4, EINVAL);
6792 strcpy(data->jmp_label, tokens[1]);
6794 fa = struct_field_parse(p, action, a, &a_struct_id);
6797 /* JMP_NEQ or JMP_NEQ_S. */
6798 fb = struct_field_parse(p, action, b, &b_struct_id);
6800 instr->type = INSTR_JMP_NEQ;
6801 if ((a[0] == 'h' && b[0] != 'h') ||
6802 (a[0] != 'h' && b[0] == 'h'))
6803 instr->type = INSTR_JMP_NEQ_S;
6804 instr->jmp.ip = NULL; /* Resolved later. */
6806 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6807 instr->jmp.a.n_bits = fa->n_bits;
6808 instr->jmp.a.offset = fa->offset / 8;
6809 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6810 instr->jmp.b.n_bits = fb->n_bits;
6811 instr->jmp.b.offset = fb->offset / 8;
6816 b_val = strtoull(b, &b, 0);
6817 CHECK(!b[0], EINVAL);
6820 b_val = hton64(b_val) >> (64 - fa->n_bits);
6822 instr->type = INSTR_JMP_NEQ_I;
6823 instr->jmp.ip = NULL; /* Resolved later. */
6824 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6825 instr->jmp.a.n_bits = fa->n_bits;
6826 instr->jmp.a.offset = fa->offset / 8;
6827 instr->jmp.b_val = b_val;
6832 instr_jmp_lt_translate(struct rte_swx_pipeline *p,
6833 struct action *action,
6836 struct instruction *instr,
6837 struct instruction_data *data)
6839 char *a = tokens[2], *b = tokens[3];
6840 struct field *fa, *fb;
6842 uint32_t a_struct_id, b_struct_id;
6844 CHECK(n_tokens == 4, EINVAL);
6846 strcpy(data->jmp_label, tokens[1]);
6848 fa = struct_field_parse(p, action, a, &a_struct_id);
6851 /* JMP_LT, JMP_LT_MH, JMP_LT_HM, JMP_LT_HH. */
6852 fb = struct_field_parse(p, action, b, &b_struct_id);
6854 instr->type = INSTR_JMP_LT;
6855 if (a[0] == 'h' && b[0] != 'h')
6856 instr->type = INSTR_JMP_LT_HM;
6857 if (a[0] != 'h' && b[0] == 'h')
6858 instr->type = INSTR_JMP_LT_MH;
6859 if (a[0] == 'h' && b[0] == 'h')
6860 instr->type = INSTR_JMP_LT_HH;
6861 instr->jmp.ip = NULL; /* Resolved later. */
6863 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6864 instr->jmp.a.n_bits = fa->n_bits;
6865 instr->jmp.a.offset = fa->offset / 8;
6866 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6867 instr->jmp.b.n_bits = fb->n_bits;
6868 instr->jmp.b.offset = fb->offset / 8;
6872 /* JMP_LT_MI, JMP_LT_HI. */
6873 b_val = strtoull(b, &b, 0);
6874 CHECK(!b[0], EINVAL);
6876 instr->type = INSTR_JMP_LT_MI;
6878 instr->type = INSTR_JMP_LT_HI;
6879 instr->jmp.ip = NULL; /* Resolved later. */
6881 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6882 instr->jmp.a.n_bits = fa->n_bits;
6883 instr->jmp.a.offset = fa->offset / 8;
6884 instr->jmp.b_val = b_val;
6889 instr_jmp_gt_translate(struct rte_swx_pipeline *p,
6890 struct action *action,
6893 struct instruction *instr,
6894 struct instruction_data *data)
6896 char *a = tokens[2], *b = tokens[3];
6897 struct field *fa, *fb;
6899 uint32_t a_struct_id, b_struct_id;
6901 CHECK(n_tokens == 4, EINVAL);
6903 strcpy(data->jmp_label, tokens[1]);
6905 fa = struct_field_parse(p, action, a, &a_struct_id);
6908 /* JMP_GT, JMP_GT_MH, JMP_GT_HM, JMP_GT_HH. */
6909 fb = struct_field_parse(p, action, b, &b_struct_id);
6911 instr->type = INSTR_JMP_GT;
6912 if (a[0] == 'h' && b[0] != 'h')
6913 instr->type = INSTR_JMP_GT_HM;
6914 if (a[0] != 'h' && b[0] == 'h')
6915 instr->type = INSTR_JMP_GT_MH;
6916 if (a[0] == 'h' && b[0] == 'h')
6917 instr->type = INSTR_JMP_GT_HH;
6918 instr->jmp.ip = NULL; /* Resolved later. */
6920 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6921 instr->jmp.a.n_bits = fa->n_bits;
6922 instr->jmp.a.offset = fa->offset / 8;
6923 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6924 instr->jmp.b.n_bits = fb->n_bits;
6925 instr->jmp.b.offset = fb->offset / 8;
6929 /* JMP_GT_MI, JMP_GT_HI. */
6930 b_val = strtoull(b, &b, 0);
6931 CHECK(!b[0], EINVAL);
6933 instr->type = INSTR_JMP_GT_MI;
6935 instr->type = INSTR_JMP_GT_HI;
6936 instr->jmp.ip = NULL; /* Resolved later. */
6938 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6939 instr->jmp.a.n_bits = fa->n_bits;
6940 instr->jmp.a.offset = fa->offset / 8;
6941 instr->jmp.b_val = b_val;
6946 instr_jmp_exec(struct rte_swx_pipeline *p)
6948 struct thread *t = &p->threads[p->thread_id];
6949 struct instruction *ip = t->ip;
6951 TRACE("[Thread %2u] jmp\n", p->thread_id);
6953 thread_ip_set(t, ip->jmp.ip);
6957 instr_jmp_valid_exec(struct rte_swx_pipeline *p)
6959 struct thread *t = &p->threads[p->thread_id];
6960 struct instruction *ip = t->ip;
6961 uint32_t header_id = ip->jmp.header_id;
6963 TRACE("[Thread %2u] jmpv\n", p->thread_id);
6965 t->ip = HEADER_VALID(t, header_id) ? ip->jmp.ip : (t->ip + 1);
6969 instr_jmp_invalid_exec(struct rte_swx_pipeline *p)
6971 struct thread *t = &p->threads[p->thread_id];
6972 struct instruction *ip = t->ip;
6973 uint32_t header_id = ip->jmp.header_id;
6975 TRACE("[Thread %2u] jmpnv\n", p->thread_id);
6977 t->ip = HEADER_VALID(t, header_id) ? (t->ip + 1) : ip->jmp.ip;
6981 instr_jmp_hit_exec(struct rte_swx_pipeline *p)
6983 struct thread *t = &p->threads[p->thread_id];
6984 struct instruction *ip = t->ip;
6985 struct instruction *ip_next[] = {t->ip + 1, ip->jmp.ip};
6987 TRACE("[Thread %2u] jmph\n", p->thread_id);
6989 t->ip = ip_next[t->hit];
6993 instr_jmp_miss_exec(struct rte_swx_pipeline *p)
6995 struct thread *t = &p->threads[p->thread_id];
6996 struct instruction *ip = t->ip;
6997 struct instruction *ip_next[] = {ip->jmp.ip, t->ip + 1};
6999 TRACE("[Thread %2u] jmpnh\n", p->thread_id);
7001 t->ip = ip_next[t->hit];
7005 instr_jmp_action_hit_exec(struct rte_swx_pipeline *p)
7007 struct thread *t = &p->threads[p->thread_id];
7008 struct instruction *ip = t->ip;
7010 TRACE("[Thread %2u] jmpa\n", p->thread_id);
7012 t->ip = (ip->jmp.action_id == t->action_id) ? ip->jmp.ip : (t->ip + 1);
7016 instr_jmp_action_miss_exec(struct rte_swx_pipeline *p)
7018 struct thread *t = &p->threads[p->thread_id];
7019 struct instruction *ip = t->ip;
7021 TRACE("[Thread %2u] jmpna\n", p->thread_id);
7023 t->ip = (ip->jmp.action_id == t->action_id) ? (t->ip + 1) : ip->jmp.ip;
7027 instr_jmp_eq_exec(struct rte_swx_pipeline *p)
7029 struct thread *t = &p->threads[p->thread_id];
7030 struct instruction *ip = t->ip;
7032 TRACE("[Thread %2u] jmpeq\n", p->thread_id);
7038 instr_jmp_eq_s_exec(struct rte_swx_pipeline *p)
7040 struct thread *t = &p->threads[p->thread_id];
7041 struct instruction *ip = t->ip;
7043 TRACE("[Thread %2u] jmpeq (s)\n", p->thread_id);
7045 JMP_CMP_S(t, ip, ==);
7049 instr_jmp_eq_i_exec(struct rte_swx_pipeline *p)
7051 struct thread *t = &p->threads[p->thread_id];
7052 struct instruction *ip = t->ip;
7054 TRACE("[Thread %2u] jmpeq (i)\n", p->thread_id);
7056 JMP_CMP_I(t, ip, ==);
7060 instr_jmp_neq_exec(struct rte_swx_pipeline *p)
7062 struct thread *t = &p->threads[p->thread_id];
7063 struct instruction *ip = t->ip;
7065 TRACE("[Thread %2u] jmpneq\n", p->thread_id);
7071 instr_jmp_neq_s_exec(struct rte_swx_pipeline *p)
7073 struct thread *t = &p->threads[p->thread_id];
7074 struct instruction *ip = t->ip;
7076 TRACE("[Thread %2u] jmpneq (s)\n", p->thread_id);
7078 JMP_CMP_S(t, ip, !=);
7082 instr_jmp_neq_i_exec(struct rte_swx_pipeline *p)
7084 struct thread *t = &p->threads[p->thread_id];
7085 struct instruction *ip = t->ip;
7087 TRACE("[Thread %2u] jmpneq (i)\n", p->thread_id);
7089 JMP_CMP_I(t, ip, !=);
7093 instr_jmp_lt_exec(struct rte_swx_pipeline *p)
7095 struct thread *t = &p->threads[p->thread_id];
7096 struct instruction *ip = t->ip;
7098 TRACE("[Thread %2u] jmplt\n", p->thread_id);
7104 instr_jmp_lt_mh_exec(struct rte_swx_pipeline *p)
7106 struct thread *t = &p->threads[p->thread_id];
7107 struct instruction *ip = t->ip;
7109 TRACE("[Thread %2u] jmplt (mh)\n", p->thread_id);
7111 JMP_CMP_MH(t, ip, <);
7115 instr_jmp_lt_hm_exec(struct rte_swx_pipeline *p)
7117 struct thread *t = &p->threads[p->thread_id];
7118 struct instruction *ip = t->ip;
7120 TRACE("[Thread %2u] jmplt (hm)\n", p->thread_id);
7122 JMP_CMP_HM(t, ip, <);
7126 instr_jmp_lt_hh_exec(struct rte_swx_pipeline *p)
7128 struct thread *t = &p->threads[p->thread_id];
7129 struct instruction *ip = t->ip;
7131 TRACE("[Thread %2u] jmplt (hh)\n", p->thread_id);
7133 JMP_CMP_HH(t, ip, <);
7137 instr_jmp_lt_mi_exec(struct rte_swx_pipeline *p)
7139 struct thread *t = &p->threads[p->thread_id];
7140 struct instruction *ip = t->ip;
7142 TRACE("[Thread %2u] jmplt (mi)\n", p->thread_id);
7144 JMP_CMP_MI(t, ip, <);
7148 instr_jmp_lt_hi_exec(struct rte_swx_pipeline *p)
7150 struct thread *t = &p->threads[p->thread_id];
7151 struct instruction *ip = t->ip;
7153 TRACE("[Thread %2u] jmplt (hi)\n", p->thread_id);
7155 JMP_CMP_HI(t, ip, <);
7159 instr_jmp_gt_exec(struct rte_swx_pipeline *p)
7161 struct thread *t = &p->threads[p->thread_id];
7162 struct instruction *ip = t->ip;
7164 TRACE("[Thread %2u] jmpgt\n", p->thread_id);
7170 instr_jmp_gt_mh_exec(struct rte_swx_pipeline *p)
7172 struct thread *t = &p->threads[p->thread_id];
7173 struct instruction *ip = t->ip;
7175 TRACE("[Thread %2u] jmpgt (mh)\n", p->thread_id);
7177 JMP_CMP_MH(t, ip, >);
7181 instr_jmp_gt_hm_exec(struct rte_swx_pipeline *p)
7183 struct thread *t = &p->threads[p->thread_id];
7184 struct instruction *ip = t->ip;
7186 TRACE("[Thread %2u] jmpgt (hm)\n", p->thread_id);
7188 JMP_CMP_HM(t, ip, >);
7192 instr_jmp_gt_hh_exec(struct rte_swx_pipeline *p)
7194 struct thread *t = &p->threads[p->thread_id];
7195 struct instruction *ip = t->ip;
7197 TRACE("[Thread %2u] jmpgt (hh)\n", p->thread_id);
7199 JMP_CMP_HH(t, ip, >);
7203 instr_jmp_gt_mi_exec(struct rte_swx_pipeline *p)
7205 struct thread *t = &p->threads[p->thread_id];
7206 struct instruction *ip = t->ip;
7208 TRACE("[Thread %2u] jmpgt (mi)\n", p->thread_id);
7210 JMP_CMP_MI(t, ip, >);
7214 instr_jmp_gt_hi_exec(struct rte_swx_pipeline *p)
7216 struct thread *t = &p->threads[p->thread_id];
7217 struct instruction *ip = t->ip;
7219 TRACE("[Thread %2u] jmpgt (hi)\n", p->thread_id);
7221 JMP_CMP_HI(t, ip, >);
7228 instr_return_translate(struct rte_swx_pipeline *p __rte_unused,
7229 struct action *action,
7230 char **tokens __rte_unused,
7232 struct instruction *instr,
7233 struct instruction_data *data __rte_unused)
7235 CHECK(action, EINVAL);
7236 CHECK(n_tokens == 1, EINVAL);
7238 instr->type = INSTR_RETURN;
7243 instr_return_exec(struct rte_swx_pipeline *p)
7245 struct thread *t = &p->threads[p->thread_id];
7247 TRACE("[Thread %2u] return\n", p->thread_id);
7253 instr_translate(struct rte_swx_pipeline *p,
7254 struct action *action,
7256 struct instruction *instr,
7257 struct instruction_data *data)
7259 char *tokens[RTE_SWX_INSTRUCTION_TOKENS_MAX];
7260 int n_tokens = 0, tpos = 0;
7262 /* Parse the instruction string into tokens. */
7266 token = strtok_r(string, " \t\v", &string);
7270 CHECK(n_tokens < RTE_SWX_INSTRUCTION_TOKENS_MAX, EINVAL);
7271 CHECK_NAME(token, EINVAL);
7273 tokens[n_tokens] = token;
7277 CHECK(n_tokens, EINVAL);
7279 /* Handle the optional instruction label. */
7280 if ((n_tokens >= 2) && !strcmp(tokens[1], ":")) {
7281 strcpy(data->label, tokens[0]);
7284 CHECK(n_tokens - tpos, EINVAL);
7287 /* Identify the instruction type. */
7288 if (!strcmp(tokens[tpos], "rx"))
7289 return instr_rx_translate(p,
7296 if (!strcmp(tokens[tpos], "tx"))
7297 return instr_tx_translate(p,
7304 if (!strcmp(tokens[tpos], "extract"))
7305 return instr_hdr_extract_translate(p,
7312 if (!strcmp(tokens[tpos], "emit"))
7313 return instr_hdr_emit_translate(p,
7320 if (!strcmp(tokens[tpos], "validate"))
7321 return instr_hdr_validate_translate(p,
7328 if (!strcmp(tokens[tpos], "invalidate"))
7329 return instr_hdr_invalidate_translate(p,
7336 if (!strcmp(tokens[tpos], "mov"))
7337 return instr_mov_translate(p,
7344 if (!strcmp(tokens[tpos], "dma"))
7345 return instr_dma_translate(p,
7352 if (!strcmp(tokens[tpos], "add"))
7353 return instr_alu_add_translate(p,
7360 if (!strcmp(tokens[tpos], "sub"))
7361 return instr_alu_sub_translate(p,
7368 if (!strcmp(tokens[tpos], "ckadd"))
7369 return instr_alu_ckadd_translate(p,
7376 if (!strcmp(tokens[tpos], "cksub"))
7377 return instr_alu_cksub_translate(p,
7384 if (!strcmp(tokens[tpos], "and"))
7385 return instr_alu_and_translate(p,
7392 if (!strcmp(tokens[tpos], "or"))
7393 return instr_alu_or_translate(p,
7400 if (!strcmp(tokens[tpos], "xor"))
7401 return instr_alu_xor_translate(p,
7408 if (!strcmp(tokens[tpos], "shl"))
7409 return instr_alu_shl_translate(p,
7416 if (!strcmp(tokens[tpos], "shr"))
7417 return instr_alu_shr_translate(p,
7424 if (!strcmp(tokens[tpos], "regprefetch"))
7425 return instr_regprefetch_translate(p,
7432 if (!strcmp(tokens[tpos], "regrd"))
7433 return instr_regrd_translate(p,
7440 if (!strcmp(tokens[tpos], "regwr"))
7441 return instr_regwr_translate(p,
7448 if (!strcmp(tokens[tpos], "regadd"))
7449 return instr_regadd_translate(p,
7456 if (!strcmp(tokens[tpos], "metprefetch"))
7457 return instr_metprefetch_translate(p,
7464 if (!strcmp(tokens[tpos], "meter"))
7465 return instr_meter_translate(p,
7472 if (!strcmp(tokens[tpos], "table"))
7473 return instr_table_translate(p,
7480 if (!strcmp(tokens[tpos], "extern"))
7481 return instr_extern_translate(p,
7488 if (!strcmp(tokens[tpos], "jmp"))
7489 return instr_jmp_translate(p,
7496 if (!strcmp(tokens[tpos], "jmpv"))
7497 return instr_jmp_valid_translate(p,
7504 if (!strcmp(tokens[tpos], "jmpnv"))
7505 return instr_jmp_invalid_translate(p,
7512 if (!strcmp(tokens[tpos], "jmph"))
7513 return instr_jmp_hit_translate(p,
7520 if (!strcmp(tokens[tpos], "jmpnh"))
7521 return instr_jmp_miss_translate(p,
7528 if (!strcmp(tokens[tpos], "jmpa"))
7529 return instr_jmp_action_hit_translate(p,
7536 if (!strcmp(tokens[tpos], "jmpna"))
7537 return instr_jmp_action_miss_translate(p,
7544 if (!strcmp(tokens[tpos], "jmpeq"))
7545 return instr_jmp_eq_translate(p,
7552 if (!strcmp(tokens[tpos], "jmpneq"))
7553 return instr_jmp_neq_translate(p,
7560 if (!strcmp(tokens[tpos], "jmplt"))
7561 return instr_jmp_lt_translate(p,
7568 if (!strcmp(tokens[tpos], "jmpgt"))
7569 return instr_jmp_gt_translate(p,
7576 if (!strcmp(tokens[tpos], "return"))
7577 return instr_return_translate(p,
7587 static struct instruction_data *
7588 label_find(struct instruction_data *data, uint32_t n, const char *label)
7592 for (i = 0; i < n; i++)
7593 if (!strcmp(label, data[i].label))
7600 label_is_used(struct instruction_data *data, uint32_t n, const char *label)
7602 uint32_t count = 0, i;
7607 for (i = 0; i < n; i++)
7608 if (!strcmp(label, data[i].jmp_label))
7615 instr_label_check(struct instruction_data *instruction_data,
7616 uint32_t n_instructions)
7620 /* Check that all instruction labels are unique. */
7621 for (i = 0; i < n_instructions; i++) {
7622 struct instruction_data *data = &instruction_data[i];
7623 char *label = data->label;
7629 for (j = i + 1; j < n_instructions; j++)
7630 CHECK(strcmp(label, data[j].label), EINVAL);
7633 /* Get users for each instruction label. */
7634 for (i = 0; i < n_instructions; i++) {
7635 struct instruction_data *data = &instruction_data[i];
7636 char *label = data->label;
7638 data->n_users = label_is_used(instruction_data,
7647 instr_jmp_resolve(struct instruction *instructions,
7648 struct instruction_data *instruction_data,
7649 uint32_t n_instructions)
7653 for (i = 0; i < n_instructions; i++) {
7654 struct instruction *instr = &instructions[i];
7655 struct instruction_data *data = &instruction_data[i];
7656 struct instruction_data *found;
7658 if (!instruction_is_jmp(instr))
7661 found = label_find(instruction_data,
7664 CHECK(found, EINVAL);
7666 instr->jmp.ip = &instructions[found - instruction_data];
7673 instr_verify(struct rte_swx_pipeline *p __rte_unused,
7675 struct instruction *instr,
7676 struct instruction_data *data __rte_unused,
7677 uint32_t n_instructions)
7680 enum instruction_type type;
7683 /* Check that the first instruction is rx. */
7684 CHECK(instr[0].type == INSTR_RX, EINVAL);
7686 /* Check that there is at least one tx instruction. */
7687 for (i = 0; i < n_instructions; i++) {
7688 type = instr[i].type;
7690 if (type == INSTR_TX)
7693 CHECK(i < n_instructions, EINVAL);
7695 /* Check that the last instruction is either tx or unconditional
7698 type = instr[n_instructions - 1].type;
7699 CHECK((type == INSTR_TX) || (type == INSTR_JMP), EINVAL);
7703 enum instruction_type type;
7706 /* Check that there is at least one return or tx instruction. */
7707 for (i = 0; i < n_instructions; i++) {
7708 type = instr[i].type;
7710 if ((type == INSTR_RETURN) || (type == INSTR_TX))
7713 CHECK(i < n_instructions, EINVAL);
7720 instr_pattern_extract_many_detect(struct instruction *instr,
7721 struct instruction_data *data,
7723 uint32_t *n_pattern_instr)
7727 for (i = 0; i < n_instr; i++) {
7728 if (data[i].invalid)
7731 if (instr[i].type != INSTR_HDR_EXTRACT)
7734 if (i == RTE_DIM(instr->io.hdr.header_id))
7737 if (i && data[i].n_users)
7744 *n_pattern_instr = i;
7749 instr_pattern_extract_many_optimize(struct instruction *instr,
7750 struct instruction_data *data,
7755 for (i = 1; i < n_instr; i++) {
7757 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
7758 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
7759 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
7761 data[i].invalid = 1;
7766 instr_pattern_emit_many_tx_detect(struct instruction *instr,
7767 struct instruction_data *data,
7769 uint32_t *n_pattern_instr)
7773 for (i = 0; i < n_instr; i++) {
7774 if (data[i].invalid)
7777 if (instr[i].type != INSTR_HDR_EMIT)
7780 if (i == RTE_DIM(instr->io.hdr.header_id))
7783 if (i && data[i].n_users)
7790 if (instr[i].type != INSTR_TX)
7793 if (data[i].n_users)
7798 *n_pattern_instr = i;
7803 instr_pattern_emit_many_tx_optimize(struct instruction *instr,
7804 struct instruction_data *data,
7809 /* Any emit instruction in addition to the first one. */
7810 for (i = 1; i < n_instr - 1; i++) {
7812 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
7813 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
7814 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
7816 data[i].invalid = 1;
7819 /* The TX instruction is the last one in the pattern. */
7821 instr[0].io.io.offset = instr[i].io.io.offset;
7822 instr[0].io.io.n_bits = instr[i].io.io.n_bits;
7823 data[i].invalid = 1;
7827 instr_pattern_dma_many_detect(struct instruction *instr,
7828 struct instruction_data *data,
7830 uint32_t *n_pattern_instr)
7834 for (i = 0; i < n_instr; i++) {
7835 if (data[i].invalid)
7838 if (instr[i].type != INSTR_DMA_HT)
7841 if (i == RTE_DIM(instr->dma.dst.header_id))
7844 if (i && data[i].n_users)
7851 *n_pattern_instr = i;
7856 instr_pattern_dma_many_optimize(struct instruction *instr,
7857 struct instruction_data *data,
7862 for (i = 1; i < n_instr; i++) {
7864 instr[0].dma.dst.header_id[i] = instr[i].dma.dst.header_id[0];
7865 instr[0].dma.dst.struct_id[i] = instr[i].dma.dst.struct_id[0];
7866 instr[0].dma.src.offset[i] = instr[i].dma.src.offset[0];
7867 instr[0].dma.n_bytes[i] = instr[i].dma.n_bytes[0];
7869 data[i].invalid = 1;
7874 instr_optimize(struct instruction *instructions,
7875 struct instruction_data *instruction_data,
7876 uint32_t n_instructions)
7878 uint32_t i, pos = 0;
7880 for (i = 0; i < n_instructions; ) {
7881 struct instruction *instr = &instructions[i];
7882 struct instruction_data *data = &instruction_data[i];
7883 uint32_t n_instr = 0;
7887 detected = instr_pattern_extract_many_detect(instr,
7892 instr_pattern_extract_many_optimize(instr,
7899 /* Emit many + TX. */
7900 detected = instr_pattern_emit_many_tx_detect(instr,
7905 instr_pattern_emit_many_tx_optimize(instr,
7913 detected = instr_pattern_dma_many_detect(instr,
7918 instr_pattern_dma_many_optimize(instr, data, n_instr);
7923 /* No pattern starting at the current instruction. */
7927 /* Eliminate the invalid instructions that have been optimized out. */
7928 for (i = 0; i < n_instructions; i++) {
7929 struct instruction *instr = &instructions[i];
7930 struct instruction_data *data = &instruction_data[i];
7936 memcpy(&instructions[pos], instr, sizeof(*instr));
7937 memcpy(&instruction_data[pos], data, sizeof(*data));
7947 instruction_config(struct rte_swx_pipeline *p,
7949 const char **instructions,
7950 uint32_t n_instructions)
7952 struct instruction *instr = NULL;
7953 struct instruction_data *data = NULL;
7957 CHECK(n_instructions, EINVAL);
7958 CHECK(instructions, EINVAL);
7959 for (i = 0; i < n_instructions; i++)
7960 CHECK_INSTRUCTION(instructions[i], EINVAL);
7962 /* Memory allocation. */
7963 instr = calloc(n_instructions, sizeof(struct instruction));
7969 data = calloc(n_instructions, sizeof(struct instruction_data));
7975 for (i = 0; i < n_instructions; i++) {
7976 char *string = strdup(instructions[i]);
7982 err = instr_translate(p, a, string, &instr[i], &data[i]);
7991 err = instr_label_check(data, n_instructions);
7995 err = instr_verify(p, a, instr, data, n_instructions);
7999 n_instructions = instr_optimize(instr, data, n_instructions);
8001 err = instr_jmp_resolve(instr, data, n_instructions);
8006 a->instructions = instr;
8007 a->n_instructions = n_instructions;
8009 p->instructions = instr;
8010 p->n_instructions = n_instructions;
8022 typedef void (*instr_exec_t)(struct rte_swx_pipeline *);
8024 static instr_exec_t instruction_table[] = {
8025 [INSTR_RX] = instr_rx_exec,
8026 [INSTR_TX] = instr_tx_exec,
8028 [INSTR_HDR_EXTRACT] = instr_hdr_extract_exec,
8029 [INSTR_HDR_EXTRACT2] = instr_hdr_extract2_exec,
8030 [INSTR_HDR_EXTRACT3] = instr_hdr_extract3_exec,
8031 [INSTR_HDR_EXTRACT4] = instr_hdr_extract4_exec,
8032 [INSTR_HDR_EXTRACT5] = instr_hdr_extract5_exec,
8033 [INSTR_HDR_EXTRACT6] = instr_hdr_extract6_exec,
8034 [INSTR_HDR_EXTRACT7] = instr_hdr_extract7_exec,
8035 [INSTR_HDR_EXTRACT8] = instr_hdr_extract8_exec,
8037 [INSTR_HDR_EMIT] = instr_hdr_emit_exec,
8038 [INSTR_HDR_EMIT_TX] = instr_hdr_emit_tx_exec,
8039 [INSTR_HDR_EMIT2_TX] = instr_hdr_emit2_tx_exec,
8040 [INSTR_HDR_EMIT3_TX] = instr_hdr_emit3_tx_exec,
8041 [INSTR_HDR_EMIT4_TX] = instr_hdr_emit4_tx_exec,
8042 [INSTR_HDR_EMIT5_TX] = instr_hdr_emit5_tx_exec,
8043 [INSTR_HDR_EMIT6_TX] = instr_hdr_emit6_tx_exec,
8044 [INSTR_HDR_EMIT7_TX] = instr_hdr_emit7_tx_exec,
8045 [INSTR_HDR_EMIT8_TX] = instr_hdr_emit8_tx_exec,
8047 [INSTR_HDR_VALIDATE] = instr_hdr_validate_exec,
8048 [INSTR_HDR_INVALIDATE] = instr_hdr_invalidate_exec,
8050 [INSTR_MOV] = instr_mov_exec,
8051 [INSTR_MOV_S] = instr_mov_s_exec,
8052 [INSTR_MOV_I] = instr_mov_i_exec,
8054 [INSTR_DMA_HT] = instr_dma_ht_exec,
8055 [INSTR_DMA_HT2] = instr_dma_ht2_exec,
8056 [INSTR_DMA_HT3] = instr_dma_ht3_exec,
8057 [INSTR_DMA_HT4] = instr_dma_ht4_exec,
8058 [INSTR_DMA_HT5] = instr_dma_ht5_exec,
8059 [INSTR_DMA_HT6] = instr_dma_ht6_exec,
8060 [INSTR_DMA_HT7] = instr_dma_ht7_exec,
8061 [INSTR_DMA_HT8] = instr_dma_ht8_exec,
8063 [INSTR_ALU_ADD] = instr_alu_add_exec,
8064 [INSTR_ALU_ADD_MH] = instr_alu_add_mh_exec,
8065 [INSTR_ALU_ADD_HM] = instr_alu_add_hm_exec,
8066 [INSTR_ALU_ADD_HH] = instr_alu_add_hh_exec,
8067 [INSTR_ALU_ADD_MI] = instr_alu_add_mi_exec,
8068 [INSTR_ALU_ADD_HI] = instr_alu_add_hi_exec,
8070 [INSTR_ALU_SUB] = instr_alu_sub_exec,
8071 [INSTR_ALU_SUB_MH] = instr_alu_sub_mh_exec,
8072 [INSTR_ALU_SUB_HM] = instr_alu_sub_hm_exec,
8073 [INSTR_ALU_SUB_HH] = instr_alu_sub_hh_exec,
8074 [INSTR_ALU_SUB_MI] = instr_alu_sub_mi_exec,
8075 [INSTR_ALU_SUB_HI] = instr_alu_sub_hi_exec,
8077 [INSTR_ALU_CKADD_FIELD] = instr_alu_ckadd_field_exec,
8078 [INSTR_ALU_CKADD_STRUCT] = instr_alu_ckadd_struct_exec,
8079 [INSTR_ALU_CKADD_STRUCT20] = instr_alu_ckadd_struct20_exec,
8080 [INSTR_ALU_CKSUB_FIELD] = instr_alu_cksub_field_exec,
8082 [INSTR_ALU_AND] = instr_alu_and_exec,
8083 [INSTR_ALU_AND_S] = instr_alu_and_s_exec,
8084 [INSTR_ALU_AND_I] = instr_alu_and_i_exec,
8086 [INSTR_ALU_OR] = instr_alu_or_exec,
8087 [INSTR_ALU_OR_S] = instr_alu_or_s_exec,
8088 [INSTR_ALU_OR_I] = instr_alu_or_i_exec,
8090 [INSTR_ALU_XOR] = instr_alu_xor_exec,
8091 [INSTR_ALU_XOR_S] = instr_alu_xor_s_exec,
8092 [INSTR_ALU_XOR_I] = instr_alu_xor_i_exec,
8094 [INSTR_ALU_SHL] = instr_alu_shl_exec,
8095 [INSTR_ALU_SHL_MH] = instr_alu_shl_mh_exec,
8096 [INSTR_ALU_SHL_HM] = instr_alu_shl_hm_exec,
8097 [INSTR_ALU_SHL_HH] = instr_alu_shl_hh_exec,
8098 [INSTR_ALU_SHL_MI] = instr_alu_shl_mi_exec,
8099 [INSTR_ALU_SHL_HI] = instr_alu_shl_hi_exec,
8101 [INSTR_ALU_SHR] = instr_alu_shr_exec,
8102 [INSTR_ALU_SHR_MH] = instr_alu_shr_mh_exec,
8103 [INSTR_ALU_SHR_HM] = instr_alu_shr_hm_exec,
8104 [INSTR_ALU_SHR_HH] = instr_alu_shr_hh_exec,
8105 [INSTR_ALU_SHR_MI] = instr_alu_shr_mi_exec,
8106 [INSTR_ALU_SHR_HI] = instr_alu_shr_hi_exec,
8108 [INSTR_REGPREFETCH_RH] = instr_regprefetch_rh_exec,
8109 [INSTR_REGPREFETCH_RM] = instr_regprefetch_rm_exec,
8110 [INSTR_REGPREFETCH_RI] = instr_regprefetch_ri_exec,
8112 [INSTR_REGRD_HRH] = instr_regrd_hrh_exec,
8113 [INSTR_REGRD_HRM] = instr_regrd_hrm_exec,
8114 [INSTR_REGRD_MRH] = instr_regrd_mrh_exec,
8115 [INSTR_REGRD_MRM] = instr_regrd_mrm_exec,
8116 [INSTR_REGRD_HRI] = instr_regrd_hri_exec,
8117 [INSTR_REGRD_MRI] = instr_regrd_mri_exec,
8119 [INSTR_REGWR_RHH] = instr_regwr_rhh_exec,
8120 [INSTR_REGWR_RHM] = instr_regwr_rhm_exec,
8121 [INSTR_REGWR_RMH] = instr_regwr_rmh_exec,
8122 [INSTR_REGWR_RMM] = instr_regwr_rmm_exec,
8123 [INSTR_REGWR_RHI] = instr_regwr_rhi_exec,
8124 [INSTR_REGWR_RMI] = instr_regwr_rmi_exec,
8125 [INSTR_REGWR_RIH] = instr_regwr_rih_exec,
8126 [INSTR_REGWR_RIM] = instr_regwr_rim_exec,
8127 [INSTR_REGWR_RII] = instr_regwr_rii_exec,
8129 [INSTR_REGADD_RHH] = instr_regadd_rhh_exec,
8130 [INSTR_REGADD_RHM] = instr_regadd_rhm_exec,
8131 [INSTR_REGADD_RMH] = instr_regadd_rmh_exec,
8132 [INSTR_REGADD_RMM] = instr_regadd_rmm_exec,
8133 [INSTR_REGADD_RHI] = instr_regadd_rhi_exec,
8134 [INSTR_REGADD_RMI] = instr_regadd_rmi_exec,
8135 [INSTR_REGADD_RIH] = instr_regadd_rih_exec,
8136 [INSTR_REGADD_RIM] = instr_regadd_rim_exec,
8137 [INSTR_REGADD_RII] = instr_regadd_rii_exec,
8139 [INSTR_METPREFETCH_H] = instr_metprefetch_h_exec,
8140 [INSTR_METPREFETCH_M] = instr_metprefetch_m_exec,
8141 [INSTR_METPREFETCH_I] = instr_metprefetch_i_exec,
8143 [INSTR_METER_HHM] = instr_meter_hhm_exec,
8144 [INSTR_METER_HHI] = instr_meter_hhi_exec,
8145 [INSTR_METER_HMM] = instr_meter_hmm_exec,
8146 [INSTR_METER_HMI] = instr_meter_hmi_exec,
8147 [INSTR_METER_MHM] = instr_meter_mhm_exec,
8148 [INSTR_METER_MHI] = instr_meter_mhi_exec,
8149 [INSTR_METER_MMM] = instr_meter_mmm_exec,
8150 [INSTR_METER_MMI] = instr_meter_mmi_exec,
8151 [INSTR_METER_IHM] = instr_meter_ihm_exec,
8152 [INSTR_METER_IHI] = instr_meter_ihi_exec,
8153 [INSTR_METER_IMM] = instr_meter_imm_exec,
8154 [INSTR_METER_IMI] = instr_meter_imi_exec,
8156 [INSTR_TABLE] = instr_table_exec,
8157 [INSTR_EXTERN_OBJ] = instr_extern_obj_exec,
8158 [INSTR_EXTERN_FUNC] = instr_extern_func_exec,
8160 [INSTR_JMP] = instr_jmp_exec,
8161 [INSTR_JMP_VALID] = instr_jmp_valid_exec,
8162 [INSTR_JMP_INVALID] = instr_jmp_invalid_exec,
8163 [INSTR_JMP_HIT] = instr_jmp_hit_exec,
8164 [INSTR_JMP_MISS] = instr_jmp_miss_exec,
8165 [INSTR_JMP_ACTION_HIT] = instr_jmp_action_hit_exec,
8166 [INSTR_JMP_ACTION_MISS] = instr_jmp_action_miss_exec,
8168 [INSTR_JMP_EQ] = instr_jmp_eq_exec,
8169 [INSTR_JMP_EQ_S] = instr_jmp_eq_s_exec,
8170 [INSTR_JMP_EQ_I] = instr_jmp_eq_i_exec,
8172 [INSTR_JMP_NEQ] = instr_jmp_neq_exec,
8173 [INSTR_JMP_NEQ_S] = instr_jmp_neq_s_exec,
8174 [INSTR_JMP_NEQ_I] = instr_jmp_neq_i_exec,
8176 [INSTR_JMP_LT] = instr_jmp_lt_exec,
8177 [INSTR_JMP_LT_MH] = instr_jmp_lt_mh_exec,
8178 [INSTR_JMP_LT_HM] = instr_jmp_lt_hm_exec,
8179 [INSTR_JMP_LT_HH] = instr_jmp_lt_hh_exec,
8180 [INSTR_JMP_LT_MI] = instr_jmp_lt_mi_exec,
8181 [INSTR_JMP_LT_HI] = instr_jmp_lt_hi_exec,
8183 [INSTR_JMP_GT] = instr_jmp_gt_exec,
8184 [INSTR_JMP_GT_MH] = instr_jmp_gt_mh_exec,
8185 [INSTR_JMP_GT_HM] = instr_jmp_gt_hm_exec,
8186 [INSTR_JMP_GT_HH] = instr_jmp_gt_hh_exec,
8187 [INSTR_JMP_GT_MI] = instr_jmp_gt_mi_exec,
8188 [INSTR_JMP_GT_HI] = instr_jmp_gt_hi_exec,
8190 [INSTR_RETURN] = instr_return_exec,
8194 instr_exec(struct rte_swx_pipeline *p)
8196 struct thread *t = &p->threads[p->thread_id];
8197 struct instruction *ip = t->ip;
8198 instr_exec_t instr = instruction_table[ip->type];
8206 static struct action *
8207 action_find(struct rte_swx_pipeline *p, const char *name)
8209 struct action *elem;
8214 TAILQ_FOREACH(elem, &p->actions, node)
8215 if (strcmp(elem->name, name) == 0)
8221 static struct action *
8222 action_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8224 struct action *action = NULL;
8226 TAILQ_FOREACH(action, &p->actions, node)
8227 if (action->id == id)
8233 static struct field *
8234 action_field_find(struct action *a, const char *name)
8236 return a->st ? struct_type_field_find(a->st, name) : NULL;
8239 static struct field *
8240 action_field_parse(struct action *action, const char *name)
8242 if (name[0] != 't' || name[1] != '.')
8245 return action_field_find(action, &name[2]);
8249 rte_swx_pipeline_action_config(struct rte_swx_pipeline *p,
8251 const char *args_struct_type_name,
8252 const char **instructions,
8253 uint32_t n_instructions)
8255 struct struct_type *args_struct_type;
8261 CHECK_NAME(name, EINVAL);
8262 CHECK(!action_find(p, name), EEXIST);
8264 if (args_struct_type_name) {
8265 CHECK_NAME(args_struct_type_name, EINVAL);
8266 args_struct_type = struct_type_find(p, args_struct_type_name);
8267 CHECK(args_struct_type, EINVAL);
8269 args_struct_type = NULL;
8272 /* Node allocation. */
8273 a = calloc(1, sizeof(struct action));
8276 /* Node initialization. */
8277 strcpy(a->name, name);
8278 a->st = args_struct_type;
8279 a->id = p->n_actions;
8281 /* Instruction translation. */
8282 err = instruction_config(p, a, instructions, n_instructions);
8288 /* Node add to tailq. */
8289 TAILQ_INSERT_TAIL(&p->actions, a, node);
8296 action_build(struct rte_swx_pipeline *p)
8298 struct action *action;
8300 p->action_instructions = calloc(p->n_actions,
8301 sizeof(struct instruction *));
8302 CHECK(p->action_instructions, ENOMEM);
8304 TAILQ_FOREACH(action, &p->actions, node)
8305 p->action_instructions[action->id] = action->instructions;
8311 action_build_free(struct rte_swx_pipeline *p)
8313 free(p->action_instructions);
8314 p->action_instructions = NULL;
8318 action_free(struct rte_swx_pipeline *p)
8320 action_build_free(p);
8323 struct action *action;
8325 action = TAILQ_FIRST(&p->actions);
8329 TAILQ_REMOVE(&p->actions, action, node);
8330 free(action->instructions);
8338 static struct table_type *
8339 table_type_find(struct rte_swx_pipeline *p, const char *name)
8341 struct table_type *elem;
8343 TAILQ_FOREACH(elem, &p->table_types, node)
8344 if (strcmp(elem->name, name) == 0)
8350 static struct table_type *
8351 table_type_resolve(struct rte_swx_pipeline *p,
8352 const char *recommended_type_name,
8353 enum rte_swx_table_match_type match_type)
8355 struct table_type *elem;
8357 /* Only consider the recommended type if the match type is correct. */
8358 if (recommended_type_name)
8359 TAILQ_FOREACH(elem, &p->table_types, node)
8360 if (!strcmp(elem->name, recommended_type_name) &&
8361 (elem->match_type == match_type))
8364 /* Ignore the recommended type and get the first element with this match
8367 TAILQ_FOREACH(elem, &p->table_types, node)
8368 if (elem->match_type == match_type)
8374 static struct table *
8375 table_find(struct rte_swx_pipeline *p, const char *name)
8379 TAILQ_FOREACH(elem, &p->tables, node)
8380 if (strcmp(elem->name, name) == 0)
8386 static struct table *
8387 table_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8389 struct table *table = NULL;
8391 TAILQ_FOREACH(table, &p->tables, node)
8392 if (table->id == id)
8399 rte_swx_pipeline_table_type_register(struct rte_swx_pipeline *p,
8401 enum rte_swx_table_match_type match_type,
8402 struct rte_swx_table_ops *ops)
8404 struct table_type *elem;
8408 CHECK_NAME(name, EINVAL);
8409 CHECK(!table_type_find(p, name), EEXIST);
8412 CHECK(ops->create, EINVAL);
8413 CHECK(ops->lkp, EINVAL);
8414 CHECK(ops->free, EINVAL);
8416 /* Node allocation. */
8417 elem = calloc(1, sizeof(struct table_type));
8418 CHECK(elem, ENOMEM);
8420 /* Node initialization. */
8421 strcpy(elem->name, name);
8422 elem->match_type = match_type;
8423 memcpy(&elem->ops, ops, sizeof(*ops));
8425 /* Node add to tailq. */
8426 TAILQ_INSERT_TAIL(&p->table_types, elem, node);
8431 static enum rte_swx_table_match_type
8432 table_match_type_resolve(struct rte_swx_match_field_params *fields,
8434 uint32_t max_offset_field_id)
8436 uint32_t n_fields_em = 0, i;
8438 for (i = 0; i < n_fields; i++)
8439 if (fields[i].match_type == RTE_SWX_TABLE_MATCH_EXACT)
8442 if (n_fields_em == n_fields)
8443 return RTE_SWX_TABLE_MATCH_EXACT;
8445 if ((n_fields_em == n_fields - 1) &&
8446 (fields[max_offset_field_id].match_type == RTE_SWX_TABLE_MATCH_LPM))
8447 return RTE_SWX_TABLE_MATCH_LPM;
8449 return RTE_SWX_TABLE_MATCH_WILDCARD;
8453 table_match_fields_check(struct rte_swx_pipeline *p,
8454 struct rte_swx_pipeline_table_params *params,
8455 struct header **header,
8456 uint32_t *min_offset_field_id,
8457 uint32_t *max_offset_field_id)
8459 struct header *h0 = NULL;
8460 struct field *hf, *mf;
8461 uint32_t *offset = NULL, min_offset, max_offset, min_offset_pos, max_offset_pos, i;
8464 /* Return if no match fields. */
8465 if (!params->n_fields) {
8466 if (params->fields) {
8474 /* Memory allocation. */
8475 offset = calloc(params->n_fields, sizeof(uint32_t));
8481 /* Check that all the match fields belong to either the same header or
8484 hf = header_field_parse(p, params->fields[0].name, &h0);
8485 mf = metadata_field_parse(p, params->fields[0].name);
8491 offset[0] = h0 ? hf->offset : mf->offset;
8493 for (i = 1; i < params->n_fields; i++)
8497 hf = header_field_parse(p, params->fields[i].name, &h);
8498 if (!hf || (h->id != h0->id)) {
8503 offset[i] = hf->offset;
8505 mf = metadata_field_parse(p, params->fields[i].name);
8511 offset[i] = mf->offset;
8514 /* Check that there are no duplicated match fields. */
8515 for (i = 0; i < params->n_fields; i++) {
8518 for (j = 0; j < i; j++)
8519 if (offset[j] == offset[i]) {
8525 /* Find the min and max offset fields. */
8526 min_offset = offset[0];
8527 max_offset = offset[0];
8531 for (i = 1; i < params->n_fields; i++) {
8532 if (offset[i] < min_offset) {
8533 min_offset = offset[i];
8537 if (offset[i] > max_offset) {
8538 max_offset = offset[i];
8547 if (min_offset_field_id)
8548 *min_offset_field_id = min_offset_pos;
8550 if (max_offset_field_id)
8551 *max_offset_field_id = max_offset_pos;
8559 rte_swx_pipeline_table_config(struct rte_swx_pipeline *p,
8561 struct rte_swx_pipeline_table_params *params,
8562 const char *recommended_table_type_name,
8566 struct table_type *type;
8568 struct action *default_action;
8569 struct header *header = NULL;
8570 uint32_t action_data_size_max = 0, min_offset_field_id = 0, max_offset_field_id = 0, i;
8575 CHECK_NAME(name, EINVAL);
8576 CHECK(!table_find(p, name), EEXIST);
8578 CHECK(params, EINVAL);
8581 status = table_match_fields_check(p,
8584 &min_offset_field_id,
8585 &max_offset_field_id);
8589 /* Action checks. */
8590 CHECK(params->n_actions, EINVAL);
8591 CHECK(params->action_names, EINVAL);
8592 for (i = 0; i < params->n_actions; i++) {
8593 const char *action_name = params->action_names[i];
8595 uint32_t action_data_size;
8597 CHECK_NAME(action_name, EINVAL);
8599 a = action_find(p, action_name);
8602 action_data_size = a->st ? a->st->n_bits / 8 : 0;
8603 if (action_data_size > action_data_size_max)
8604 action_data_size_max = action_data_size;
8607 CHECK_NAME(params->default_action_name, EINVAL);
8608 for (i = 0; i < p->n_actions; i++)
8609 if (!strcmp(params->action_names[i],
8610 params->default_action_name))
8612 CHECK(i < params->n_actions, EINVAL);
8613 default_action = action_find(p, params->default_action_name);
8614 CHECK((default_action->st && params->default_action_data) ||
8615 !params->default_action_data, EINVAL);
8617 /* Table type checks. */
8618 if (recommended_table_type_name)
8619 CHECK_NAME(recommended_table_type_name, EINVAL);
8621 if (params->n_fields) {
8622 enum rte_swx_table_match_type match_type;
8624 match_type = table_match_type_resolve(params->fields,
8626 max_offset_field_id);
8627 type = table_type_resolve(p,
8628 recommended_table_type_name,
8630 CHECK(type, EINVAL);
8635 /* Memory allocation. */
8636 t = calloc(1, sizeof(struct table));
8639 t->fields = calloc(params->n_fields, sizeof(struct match_field));
8645 t->actions = calloc(params->n_actions, sizeof(struct action *));
8652 if (action_data_size_max) {
8653 t->default_action_data = calloc(1, action_data_size_max);
8654 if (!t->default_action_data) {
8662 /* Node initialization. */
8663 strcpy(t->name, name);
8664 if (args && args[0])
8665 strcpy(t->args, args);
8668 for (i = 0; i < params->n_fields; i++) {
8669 struct rte_swx_match_field_params *field = ¶ms->fields[i];
8670 struct match_field *f = &t->fields[i];
8672 f->match_type = field->match_type;
8674 header_field_parse(p, field->name, NULL) :
8675 metadata_field_parse(p, field->name);
8677 t->n_fields = params->n_fields;
8680 for (i = 0; i < params->n_actions; i++)
8681 t->actions[i] = action_find(p, params->action_names[i]);
8682 t->default_action = default_action;
8683 if (default_action->st)
8684 memcpy(t->default_action_data,
8685 params->default_action_data,
8686 default_action->st->n_bits / 8);
8687 t->n_actions = params->n_actions;
8688 t->default_action_is_const = params->default_action_is_const;
8689 t->action_data_size_max = action_data_size_max;
8692 t->id = p->n_tables;
8694 /* Node add to tailq. */
8695 TAILQ_INSERT_TAIL(&p->tables, t, node);
8701 static struct rte_swx_table_params *
8702 table_params_get(struct table *table)
8704 struct rte_swx_table_params *params;
8705 struct field *first, *last;
8707 uint32_t key_size, key_offset, action_data_size, i;
8709 /* Memory allocation. */
8710 params = calloc(1, sizeof(struct rte_swx_table_params));
8714 /* Find first (smallest offset) and last (biggest offset) match fields. */
8715 first = table->fields[0].field;
8716 last = table->fields[0].field;
8718 for (i = 0; i < table->n_fields; i++) {
8719 struct field *f = table->fields[i].field;
8721 if (f->offset < first->offset)
8724 if (f->offset > last->offset)
8728 /* Key offset and size. */
8729 key_offset = first->offset / 8;
8730 key_size = (last->offset + last->n_bits - first->offset) / 8;
8732 /* Memory allocation. */
8733 key_mask = calloc(1, key_size);
8740 for (i = 0; i < table->n_fields; i++) {
8741 struct field *f = table->fields[i].field;
8742 uint32_t start = (f->offset - first->offset) / 8;
8743 size_t size = f->n_bits / 8;
8745 memset(&key_mask[start], 0xFF, size);
8748 /* Action data size. */
8749 action_data_size = 0;
8750 for (i = 0; i < table->n_actions; i++) {
8751 struct action *action = table->actions[i];
8752 uint32_t ads = action->st ? action->st->n_bits / 8 : 0;
8754 if (ads > action_data_size)
8755 action_data_size = ads;
8759 params->match_type = table->type->match_type;
8760 params->key_size = key_size;
8761 params->key_offset = key_offset;
8762 params->key_mask0 = key_mask;
8763 params->action_data_size = action_data_size;
8764 params->n_keys_max = table->size;
8770 table_params_free(struct rte_swx_table_params *params)
8775 free(params->key_mask0);
8780 table_state_build(struct rte_swx_pipeline *p)
8782 struct table *table;
8784 p->table_state = calloc(p->n_tables,
8785 sizeof(struct rte_swx_table_state));
8786 CHECK(p->table_state, ENOMEM);
8788 TAILQ_FOREACH(table, &p->tables, node) {
8789 struct rte_swx_table_state *ts = &p->table_state[table->id];
8792 struct rte_swx_table_params *params;
8795 params = table_params_get(table);
8796 CHECK(params, ENOMEM);
8798 ts->obj = table->type->ops.create(params,
8803 table_params_free(params);
8804 CHECK(ts->obj, ENODEV);
8807 /* ts->default_action_data. */
8808 if (table->action_data_size_max) {
8809 ts->default_action_data =
8810 malloc(table->action_data_size_max);
8811 CHECK(ts->default_action_data, ENOMEM);
8813 memcpy(ts->default_action_data,
8814 table->default_action_data,
8815 table->action_data_size_max);
8818 /* ts->default_action_id. */
8819 ts->default_action_id = table->default_action->id;
8826 table_state_build_free(struct rte_swx_pipeline *p)
8830 if (!p->table_state)
8833 for (i = 0; i < p->n_tables; i++) {
8834 struct rte_swx_table_state *ts = &p->table_state[i];
8835 struct table *table = table_find_by_id(p, i);
8838 if (table->type && ts->obj)
8839 table->type->ops.free(ts->obj);
8841 /* ts->default_action_data. */
8842 free(ts->default_action_data);
8845 free(p->table_state);
8846 p->table_state = NULL;
8850 table_state_free(struct rte_swx_pipeline *p)
8852 table_state_build_free(p);
8856 table_stub_lkp(void *table __rte_unused,
8857 void *mailbox __rte_unused,
8858 uint8_t **key __rte_unused,
8859 uint64_t *action_id __rte_unused,
8860 uint8_t **action_data __rte_unused,
8864 return 1; /* DONE. */
8868 table_build(struct rte_swx_pipeline *p)
8872 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8873 struct thread *t = &p->threads[i];
8874 struct table *table;
8876 t->tables = calloc(p->n_tables, sizeof(struct table_runtime));
8877 CHECK(t->tables, ENOMEM);
8879 TAILQ_FOREACH(table, &p->tables, node) {
8880 struct table_runtime *r = &t->tables[table->id];
8885 size = table->type->ops.mailbox_size_get();
8888 r->func = table->type->ops.lkp;
8892 r->mailbox = calloc(1, size);
8893 CHECK(r->mailbox, ENOMEM);
8897 r->key = table->header ?
8898 &t->structs[table->header->struct_id] :
8899 &t->structs[p->metadata_struct_id];
8901 r->func = table_stub_lkp;
8910 table_build_free(struct rte_swx_pipeline *p)
8914 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8915 struct thread *t = &p->threads[i];
8921 for (j = 0; j < p->n_tables; j++) {
8922 struct table_runtime *r = &t->tables[j];
8933 table_free(struct rte_swx_pipeline *p)
8935 table_build_free(p);
8941 elem = TAILQ_FIRST(&p->tables);
8945 TAILQ_REMOVE(&p->tables, elem, node);
8947 free(elem->actions);
8948 free(elem->default_action_data);
8954 struct table_type *elem;
8956 elem = TAILQ_FIRST(&p->table_types);
8960 TAILQ_REMOVE(&p->table_types, elem, node);
8968 static struct regarray *
8969 regarray_find(struct rte_swx_pipeline *p, const char *name)
8971 struct regarray *elem;
8973 TAILQ_FOREACH(elem, &p->regarrays, node)
8974 if (!strcmp(elem->name, name))
8980 static struct regarray *
8981 regarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8983 struct regarray *elem = NULL;
8985 TAILQ_FOREACH(elem, &p->regarrays, node)
8993 rte_swx_pipeline_regarray_config(struct rte_swx_pipeline *p,
9002 CHECK_NAME(name, EINVAL);
9003 CHECK(!regarray_find(p, name), EEXIST);
9005 CHECK(size, EINVAL);
9006 size = rte_align32pow2(size);
9008 /* Memory allocation. */
9009 r = calloc(1, sizeof(struct regarray));
9012 /* Node initialization. */
9013 strcpy(r->name, name);
9014 r->init_val = init_val;
9016 r->id = p->n_regarrays;
9018 /* Node add to tailq. */
9019 TAILQ_INSERT_TAIL(&p->regarrays, r, node);
9026 regarray_build(struct rte_swx_pipeline *p)
9028 struct regarray *regarray;
9030 if (!p->n_regarrays)
9033 p->regarray_runtime = calloc(p->n_regarrays, sizeof(struct regarray_runtime));
9034 CHECK(p->regarray_runtime, ENOMEM);
9036 TAILQ_FOREACH(regarray, &p->regarrays, node) {
9037 struct regarray_runtime *r = &p->regarray_runtime[regarray->id];
9040 r->regarray = env_malloc(regarray->size * sizeof(uint64_t),
9041 RTE_CACHE_LINE_SIZE,
9043 CHECK(r->regarray, ENOMEM);
9045 if (regarray->init_val)
9046 for (i = 0; i < regarray->size; i++)
9047 r->regarray[i] = regarray->init_val;
9049 r->size_mask = regarray->size - 1;
9056 regarray_build_free(struct rte_swx_pipeline *p)
9060 if (!p->regarray_runtime)
9063 for (i = 0; i < p->n_regarrays; i++) {
9064 struct regarray *regarray = regarray_find_by_id(p, i);
9065 struct regarray_runtime *r = &p->regarray_runtime[i];
9067 env_free(r->regarray, regarray->size * sizeof(uint64_t));
9070 free(p->regarray_runtime);
9071 p->regarray_runtime = NULL;
9075 regarray_free(struct rte_swx_pipeline *p)
9077 regarray_build_free(p);
9080 struct regarray *elem;
9082 elem = TAILQ_FIRST(&p->regarrays);
9086 TAILQ_REMOVE(&p->regarrays, elem, node);
9094 static struct meter_profile *
9095 meter_profile_find(struct rte_swx_pipeline *p, const char *name)
9097 struct meter_profile *elem;
9099 TAILQ_FOREACH(elem, &p->meter_profiles, node)
9100 if (!strcmp(elem->name, name))
9106 static struct metarray *
9107 metarray_find(struct rte_swx_pipeline *p, const char *name)
9109 struct metarray *elem;
9111 TAILQ_FOREACH(elem, &p->metarrays, node)
9112 if (!strcmp(elem->name, name))
9118 static struct metarray *
9119 metarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9121 struct metarray *elem = NULL;
9123 TAILQ_FOREACH(elem, &p->metarrays, node)
9131 rte_swx_pipeline_metarray_config(struct rte_swx_pipeline *p,
9139 CHECK_NAME(name, EINVAL);
9140 CHECK(!metarray_find(p, name), EEXIST);
9142 CHECK(size, EINVAL);
9143 size = rte_align32pow2(size);
9145 /* Memory allocation. */
9146 m = calloc(1, sizeof(struct metarray));
9149 /* Node initialization. */
9150 strcpy(m->name, name);
9152 m->id = p->n_metarrays;
9154 /* Node add to tailq. */
9155 TAILQ_INSERT_TAIL(&p->metarrays, m, node);
9161 struct meter_profile meter_profile_default = {
9170 .cir_bytes_per_period = 1,
9172 .pir_bytes_per_period = 1,
9179 meter_init(struct meter *m)
9181 memset(m, 0, sizeof(struct meter));
9182 rte_meter_trtcm_config(&m->m, &meter_profile_default.profile);
9183 m->profile = &meter_profile_default;
9184 m->color_mask = RTE_COLOR_GREEN;
9186 meter_profile_default.n_users++;
9190 metarray_build(struct rte_swx_pipeline *p)
9194 if (!p->n_metarrays)
9197 p->metarray_runtime = calloc(p->n_metarrays, sizeof(struct metarray_runtime));
9198 CHECK(p->metarray_runtime, ENOMEM);
9200 TAILQ_FOREACH(m, &p->metarrays, node) {
9201 struct metarray_runtime *r = &p->metarray_runtime[m->id];
9204 r->metarray = env_malloc(m->size * sizeof(struct meter),
9205 RTE_CACHE_LINE_SIZE,
9207 CHECK(r->metarray, ENOMEM);
9209 for (i = 0; i < m->size; i++)
9210 meter_init(&r->metarray[i]);
9212 r->size_mask = m->size - 1;
9219 metarray_build_free(struct rte_swx_pipeline *p)
9223 if (!p->metarray_runtime)
9226 for (i = 0; i < p->n_metarrays; i++) {
9227 struct metarray *m = metarray_find_by_id(p, i);
9228 struct metarray_runtime *r = &p->metarray_runtime[i];
9230 env_free(r->metarray, m->size * sizeof(struct meter));
9233 free(p->metarray_runtime);
9234 p->metarray_runtime = NULL;
9238 metarray_free(struct rte_swx_pipeline *p)
9240 metarray_build_free(p);
9244 struct metarray *elem;
9246 elem = TAILQ_FIRST(&p->metarrays);
9250 TAILQ_REMOVE(&p->metarrays, elem, node);
9254 /* Meter profiles. */
9256 struct meter_profile *elem;
9258 elem = TAILQ_FIRST(&p->meter_profiles);
9262 TAILQ_REMOVE(&p->meter_profiles, elem, node);
9271 rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
9273 struct rte_swx_pipeline *pipeline;
9275 /* Check input parameters. */
9278 /* Memory allocation. */
9279 pipeline = calloc(1, sizeof(struct rte_swx_pipeline));
9280 CHECK(pipeline, ENOMEM);
9282 /* Initialization. */
9283 TAILQ_INIT(&pipeline->struct_types);
9284 TAILQ_INIT(&pipeline->port_in_types);
9285 TAILQ_INIT(&pipeline->ports_in);
9286 TAILQ_INIT(&pipeline->port_out_types);
9287 TAILQ_INIT(&pipeline->ports_out);
9288 TAILQ_INIT(&pipeline->extern_types);
9289 TAILQ_INIT(&pipeline->extern_objs);
9290 TAILQ_INIT(&pipeline->extern_funcs);
9291 TAILQ_INIT(&pipeline->headers);
9292 TAILQ_INIT(&pipeline->actions);
9293 TAILQ_INIT(&pipeline->table_types);
9294 TAILQ_INIT(&pipeline->tables);
9295 TAILQ_INIT(&pipeline->regarrays);
9296 TAILQ_INIT(&pipeline->meter_profiles);
9297 TAILQ_INIT(&pipeline->metarrays);
9299 pipeline->n_structs = 1; /* Struct 0 is reserved for action_data. */
9300 pipeline->numa_node = numa_node;
9307 rte_swx_pipeline_free(struct rte_swx_pipeline *p)
9312 free(p->instructions);
9316 table_state_free(p);
9321 extern_func_free(p);
9331 rte_swx_pipeline_instructions_config(struct rte_swx_pipeline *p,
9332 const char **instructions,
9333 uint32_t n_instructions)
9338 err = instruction_config(p, NULL, instructions, n_instructions);
9342 /* Thread instruction pointer reset. */
9343 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9344 struct thread *t = &p->threads[i];
9346 thread_ip_reset(p, t);
9353 rte_swx_pipeline_build(struct rte_swx_pipeline *p)
9358 CHECK(p->build_done == 0, EEXIST);
9360 status = port_in_build(p);
9364 status = port_out_build(p);
9368 status = struct_build(p);
9372 status = extern_obj_build(p);
9376 status = extern_func_build(p);
9380 status = header_build(p);
9384 status = metadata_build(p);
9388 status = action_build(p);
9392 status = table_build(p);
9396 status = table_state_build(p);
9400 status = regarray_build(p);
9404 status = metarray_build(p);
9412 metarray_build_free(p);
9413 regarray_build_free(p);
9414 table_state_build_free(p);
9415 table_build_free(p);
9416 action_build_free(p);
9417 metadata_build_free(p);
9418 header_build_free(p);
9419 extern_func_build_free(p);
9420 extern_obj_build_free(p);
9421 port_out_build_free(p);
9422 port_in_build_free(p);
9423 struct_build_free(p);
9429 rte_swx_pipeline_run(struct rte_swx_pipeline *p, uint32_t n_instructions)
9433 for (i = 0; i < n_instructions; i++)
9438 rte_swx_pipeline_flush(struct rte_swx_pipeline *p)
9442 for (i = 0; i < p->n_ports_out; i++) {
9443 struct port_out_runtime *port = &p->out[i];
9446 port->flush(port->obj);
9454 rte_swx_ctl_pipeline_info_get(struct rte_swx_pipeline *p,
9455 struct rte_swx_ctl_pipeline_info *pipeline)
9457 struct action *action;
9458 struct table *table;
9459 uint32_t n_actions = 0, n_tables = 0;
9461 if (!p || !pipeline)
9464 TAILQ_FOREACH(action, &p->actions, node)
9467 TAILQ_FOREACH(table, &p->tables, node)
9470 pipeline->n_ports_in = p->n_ports_in;
9471 pipeline->n_ports_out = p->n_ports_out;
9472 pipeline->n_actions = n_actions;
9473 pipeline->n_tables = n_tables;
9474 pipeline->n_regarrays = p->n_regarrays;
9475 pipeline->n_metarrays = p->n_metarrays;
9481 rte_swx_ctl_pipeline_numa_node_get(struct rte_swx_pipeline *p, int *numa_node)
9483 if (!p || !numa_node)
9486 *numa_node = p->numa_node;
9491 rte_swx_ctl_action_info_get(struct rte_swx_pipeline *p,
9493 struct rte_swx_ctl_action_info *action)
9495 struct action *a = NULL;
9497 if (!p || (action_id >= p->n_actions) || !action)
9500 a = action_find_by_id(p, action_id);
9504 strcpy(action->name, a->name);
9505 action->n_args = a->st ? a->st->n_fields : 0;
9510 rte_swx_ctl_action_arg_info_get(struct rte_swx_pipeline *p,
9512 uint32_t action_arg_id,
9513 struct rte_swx_ctl_action_arg_info *action_arg)
9515 struct action *a = NULL;
9516 struct field *arg = NULL;
9518 if (!p || (action_id >= p->n_actions) || !action_arg)
9521 a = action_find_by_id(p, action_id);
9522 if (!a || !a->st || (action_arg_id >= a->st->n_fields))
9525 arg = &a->st->fields[action_arg_id];
9526 strcpy(action_arg->name, arg->name);
9527 action_arg->n_bits = arg->n_bits;
9533 rte_swx_ctl_table_info_get(struct rte_swx_pipeline *p,
9535 struct rte_swx_ctl_table_info *table)
9537 struct table *t = NULL;
9542 t = table_find_by_id(p, table_id);
9546 strcpy(table->name, t->name);
9547 strcpy(table->args, t->args);
9548 table->n_match_fields = t->n_fields;
9549 table->n_actions = t->n_actions;
9550 table->default_action_is_const = t->default_action_is_const;
9551 table->size = t->size;
9556 rte_swx_ctl_table_match_field_info_get(struct rte_swx_pipeline *p,
9558 uint32_t match_field_id,
9559 struct rte_swx_ctl_table_match_field_info *match_field)
9562 struct match_field *f;
9564 if (!p || (table_id >= p->n_tables) || !match_field)
9567 t = table_find_by_id(p, table_id);
9568 if (!t || (match_field_id >= t->n_fields))
9571 f = &t->fields[match_field_id];
9572 match_field->match_type = f->match_type;
9573 match_field->is_header = t->header ? 1 : 0;
9574 match_field->n_bits = f->field->n_bits;
9575 match_field->offset = f->field->offset;
9581 rte_swx_ctl_table_action_info_get(struct rte_swx_pipeline *p,
9583 uint32_t table_action_id,
9584 struct rte_swx_ctl_table_action_info *table_action)
9588 if (!p || (table_id >= p->n_tables) || !table_action)
9591 t = table_find_by_id(p, table_id);
9592 if (!t || (table_action_id >= t->n_actions))
9595 table_action->action_id = t->actions[table_action_id]->id;
9601 rte_swx_ctl_table_ops_get(struct rte_swx_pipeline *p,
9603 struct rte_swx_table_ops *table_ops,
9608 if (!p || (table_id >= p->n_tables))
9611 t = table_find_by_id(p, table_id);
9617 memcpy(table_ops, &t->type->ops, sizeof(*table_ops));
9627 rte_swx_pipeline_table_state_get(struct rte_swx_pipeline *p,
9628 struct rte_swx_table_state **table_state)
9630 if (!p || !table_state || !p->build_done)
9633 *table_state = p->table_state;
9638 rte_swx_pipeline_table_state_set(struct rte_swx_pipeline *p,
9639 struct rte_swx_table_state *table_state)
9641 if (!p || !table_state || !p->build_done)
9644 p->table_state = table_state;
9649 rte_swx_ctl_pipeline_port_in_stats_read(struct rte_swx_pipeline *p,
9651 struct rte_swx_port_in_stats *stats)
9653 struct port_in *port;
9658 port = port_in_find(p, port_id);
9662 port->type->ops.stats_read(port->obj, stats);
9667 rte_swx_ctl_pipeline_port_out_stats_read(struct rte_swx_pipeline *p,
9669 struct rte_swx_port_out_stats *stats)
9671 struct port_out *port;
9676 port = port_out_find(p, port_id);
9680 port->type->ops.stats_read(port->obj, stats);
9685 rte_swx_ctl_regarray_info_get(struct rte_swx_pipeline *p,
9686 uint32_t regarray_id,
9687 struct rte_swx_ctl_regarray_info *regarray)
9691 if (!p || !regarray)
9694 r = regarray_find_by_id(p, regarray_id);
9698 strcpy(regarray->name, r->name);
9699 regarray->size = r->size;
9704 rte_swx_ctl_pipeline_regarray_read(struct rte_swx_pipeline *p,
9705 const char *regarray_name,
9706 uint32_t regarray_index,
9709 struct regarray *regarray;
9710 struct regarray_runtime *r;
9712 if (!p || !regarray_name || !value)
9715 regarray = regarray_find(p, regarray_name);
9716 if (!regarray || (regarray_index >= regarray->size))
9719 r = &p->regarray_runtime[regarray->id];
9720 *value = r->regarray[regarray_index];
9725 rte_swx_ctl_pipeline_regarray_write(struct rte_swx_pipeline *p,
9726 const char *regarray_name,
9727 uint32_t regarray_index,
9730 struct regarray *regarray;
9731 struct regarray_runtime *r;
9733 if (!p || !regarray_name)
9736 regarray = regarray_find(p, regarray_name);
9737 if (!regarray || (regarray_index >= regarray->size))
9740 r = &p->regarray_runtime[regarray->id];
9741 r->regarray[regarray_index] = value;
9746 rte_swx_ctl_metarray_info_get(struct rte_swx_pipeline *p,
9747 uint32_t metarray_id,
9748 struct rte_swx_ctl_metarray_info *metarray)
9752 if (!p || !metarray)
9755 m = metarray_find_by_id(p, metarray_id);
9759 strcpy(metarray->name, m->name);
9760 metarray->size = m->size;
9765 rte_swx_ctl_meter_profile_add(struct rte_swx_pipeline *p,
9767 struct rte_meter_trtcm_params *params)
9769 struct meter_profile *mp;
9773 CHECK_NAME(name, EINVAL);
9774 CHECK(params, EINVAL);
9775 CHECK(!meter_profile_find(p, name), EEXIST);
9777 /* Node allocation. */
9778 mp = calloc(1, sizeof(struct meter_profile));
9781 /* Node initialization. */
9782 strcpy(mp->name, name);
9783 memcpy(&mp->params, params, sizeof(struct rte_meter_trtcm_params));
9784 status = rte_meter_trtcm_profile_config(&mp->profile, params);
9790 /* Node add to tailq. */
9791 TAILQ_INSERT_TAIL(&p->meter_profiles, mp, node);
9797 rte_swx_ctl_meter_profile_delete(struct rte_swx_pipeline *p,
9800 struct meter_profile *mp;
9803 CHECK_NAME(name, EINVAL);
9805 mp = meter_profile_find(p, name);
9807 CHECK(!mp->n_users, EBUSY);
9809 /* Remove node from tailq. */
9810 TAILQ_REMOVE(&p->meter_profiles, mp, node);
9817 rte_swx_ctl_meter_reset(struct rte_swx_pipeline *p,
9818 const char *metarray_name,
9819 uint32_t metarray_index)
9821 struct meter_profile *mp_old;
9822 struct metarray *metarray;
9823 struct metarray_runtime *metarray_runtime;
9827 CHECK_NAME(metarray_name, EINVAL);
9829 metarray = metarray_find(p, metarray_name);
9830 CHECK(metarray, EINVAL);
9831 CHECK(metarray_index < metarray->size, EINVAL);
9833 metarray_runtime = &p->metarray_runtime[metarray->id];
9834 m = &metarray_runtime->metarray[metarray_index];
9835 mp_old = m->profile;
9845 rte_swx_ctl_meter_set(struct rte_swx_pipeline *p,
9846 const char *metarray_name,
9847 uint32_t metarray_index,
9848 const char *profile_name)
9850 struct meter_profile *mp, *mp_old;
9851 struct metarray *metarray;
9852 struct metarray_runtime *metarray_runtime;
9856 CHECK_NAME(metarray_name, EINVAL);
9858 metarray = metarray_find(p, metarray_name);
9859 CHECK(metarray, EINVAL);
9860 CHECK(metarray_index < metarray->size, EINVAL);
9862 mp = meter_profile_find(p, profile_name);
9865 metarray_runtime = &p->metarray_runtime[metarray->id];
9866 m = &metarray_runtime->metarray[metarray_index];
9867 mp_old = m->profile;
9869 memset(m, 0, sizeof(struct meter));
9870 rte_meter_trtcm_config(&m->m, &mp->profile);
9872 m->color_mask = RTE_COLORS;
9881 rte_swx_ctl_meter_stats_read(struct rte_swx_pipeline *p,
9882 const char *metarray_name,
9883 uint32_t metarray_index,
9884 struct rte_swx_ctl_meter_stats *stats)
9886 struct metarray *metarray;
9887 struct metarray_runtime *metarray_runtime;
9891 CHECK_NAME(metarray_name, EINVAL);
9893 metarray = metarray_find(p, metarray_name);
9894 CHECK(metarray, EINVAL);
9895 CHECK(metarray_index < metarray->size, EINVAL);
9897 CHECK(stats, EINVAL);
9899 metarray_runtime = &p->metarray_runtime[metarray->id];
9900 m = &metarray_runtime->metarray[metarray_index];
9902 memcpy(stats->n_pkts, m->n_pkts, sizeof(m->n_pkts));
9903 memcpy(stats->n_bytes, m->n_bytes, sizeof(m->n_bytes));