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 INSTR_TX, /* port_out = M */
288 INSTR_TX_I, /* port_out = I */
290 /* extract h.header */
311 /* validate h.header */
314 /* invalidate h.header */
315 INSTR_HDR_INVALIDATE,
319 * dst = HMEF, src = HMEFTI
321 INSTR_MOV, /* dst = MEF, src = MEFT */
322 INSTR_MOV_S, /* (dst, src) = (MEF, H) or (dst, src) = (H, MEFT) */
323 INSTR_MOV_I, /* dst = HMEF, src = I */
325 /* dma h.header t.field
326 * memcpy(h.header, t.field, sizeof(h.header))
339 * dst = HMEF, src = HMEFTI
341 INSTR_ALU_ADD, /* dst = MEF, src = MEF */
342 INSTR_ALU_ADD_MH, /* dst = MEF, src = H */
343 INSTR_ALU_ADD_HM, /* dst = H, src = MEF */
344 INSTR_ALU_ADD_HH, /* dst = H, src = H */
345 INSTR_ALU_ADD_MI, /* dst = MEF, src = I */
346 INSTR_ALU_ADD_HI, /* dst = H, src = I */
350 * dst = HMEF, src = HMEFTI
352 INSTR_ALU_SUB, /* dst = MEF, src = MEF */
353 INSTR_ALU_SUB_MH, /* dst = MEF, src = H */
354 INSTR_ALU_SUB_HM, /* dst = H, src = MEF */
355 INSTR_ALU_SUB_HH, /* dst = H, src = H */
356 INSTR_ALU_SUB_MI, /* dst = MEF, src = I */
357 INSTR_ALU_SUB_HI, /* dst = H, src = I */
360 * dst = dst '+ src[0:1] '+ src[2:3] + ...
361 * dst = H, src = {H, h.header}
363 INSTR_ALU_CKADD_FIELD, /* src = H */
364 INSTR_ALU_CKADD_STRUCT20, /* src = h.header, with sizeof(header) = 20 */
365 INSTR_ALU_CKADD_STRUCT, /* src = h.hdeader, with any sizeof(header) */
371 INSTR_ALU_CKSUB_FIELD,
375 * dst = HMEF, src = HMEFTI
377 INSTR_ALU_AND, /* dst = MEF, src = MEFT */
378 INSTR_ALU_AND_S, /* (dst, src) = (MEF, H) or (dst, src) = (H, MEFT) */
379 INSTR_ALU_AND_I, /* dst = HMEF, src = I */
383 * dst = HMEF, src = HMEFTI
385 INSTR_ALU_OR, /* dst = MEF, src = MEFT */
386 INSTR_ALU_OR_S, /* (dst, src) = (MEF, H) or (dst, src) = (H, MEFT) */
387 INSTR_ALU_OR_I, /* dst = HMEF, src = I */
391 * dst = HMEF, src = HMEFTI
393 INSTR_ALU_XOR, /* dst = MEF, src = MEFT */
394 INSTR_ALU_XOR_S, /* (dst, src) = (MEF, H) or (dst, src) = (H, MEFT) */
395 INSTR_ALU_XOR_I, /* dst = HMEF, src = I */
399 * dst = HMEF, src = HMEFTI
401 INSTR_ALU_SHL, /* dst = MEF, src = MEF */
402 INSTR_ALU_SHL_MH, /* dst = MEF, src = H */
403 INSTR_ALU_SHL_HM, /* dst = H, src = MEF */
404 INSTR_ALU_SHL_HH, /* dst = H, src = H */
405 INSTR_ALU_SHL_MI, /* dst = MEF, src = I */
406 INSTR_ALU_SHL_HI, /* dst = H, src = I */
410 * dst = HMEF, src = HMEFTI
412 INSTR_ALU_SHR, /* dst = MEF, src = MEF */
413 INSTR_ALU_SHR_MH, /* dst = MEF, src = H */
414 INSTR_ALU_SHR_HM, /* dst = H, src = MEF */
415 INSTR_ALU_SHR_HH, /* dst = H, src = H */
416 INSTR_ALU_SHR_MI, /* dst = MEF, src = I */
417 INSTR_ALU_SHR_HI, /* dst = H, src = I */
419 /* regprefetch REGARRAY index
420 * prefetch REGARRAY[index]
423 INSTR_REGPREFETCH_RH, /* index = H */
424 INSTR_REGPREFETCH_RM, /* index = MEFT */
425 INSTR_REGPREFETCH_RI, /* index = I */
427 /* regrd dst REGARRAY index
428 * dst = REGARRAY[index]
429 * dst = HMEF, index = HMEFTI
431 INSTR_REGRD_HRH, /* dst = H, index = H */
432 INSTR_REGRD_HRM, /* dst = H, index = MEFT */
433 INSTR_REGRD_HRI, /* dst = H, index = I */
434 INSTR_REGRD_MRH, /* dst = MEF, index = H */
435 INSTR_REGRD_MRM, /* dst = MEF, index = MEFT */
436 INSTR_REGRD_MRI, /* dst = MEF, index = I */
438 /* regwr REGARRAY index src
439 * REGARRAY[index] = src
440 * index = HMEFTI, src = HMEFTI
442 INSTR_REGWR_RHH, /* index = H, src = H */
443 INSTR_REGWR_RHM, /* index = H, src = MEFT */
444 INSTR_REGWR_RHI, /* index = H, src = I */
445 INSTR_REGWR_RMH, /* index = MEFT, src = H */
446 INSTR_REGWR_RMM, /* index = MEFT, src = MEFT */
447 INSTR_REGWR_RMI, /* index = MEFT, src = I */
448 INSTR_REGWR_RIH, /* index = I, src = H */
449 INSTR_REGWR_RIM, /* index = I, src = MEFT */
450 INSTR_REGWR_RII, /* index = I, src = I */
452 /* regadd REGARRAY index src
453 * REGARRAY[index] += src
454 * index = HMEFTI, src = HMEFTI
456 INSTR_REGADD_RHH, /* index = H, src = H */
457 INSTR_REGADD_RHM, /* index = H, src = MEFT */
458 INSTR_REGADD_RHI, /* index = H, src = I */
459 INSTR_REGADD_RMH, /* index = MEFT, src = H */
460 INSTR_REGADD_RMM, /* index = MEFT, src = MEFT */
461 INSTR_REGADD_RMI, /* index = MEFT, src = I */
462 INSTR_REGADD_RIH, /* index = I, src = H */
463 INSTR_REGADD_RIM, /* index = I, src = MEFT */
464 INSTR_REGADD_RII, /* index = I, src = I */
466 /* metprefetch METARRAY index
467 * prefetch METARRAY[index]
470 INSTR_METPREFETCH_H, /* index = H */
471 INSTR_METPREFETCH_M, /* index = MEFT */
472 INSTR_METPREFETCH_I, /* index = I */
474 /* meter METARRAY index length color_in color_out
475 * color_out = meter(METARRAY[index], length, color_in)
476 * index = HMEFTI, length = HMEFT, color_in = MEFTI, color_out = MEF
478 INSTR_METER_HHM, /* index = H, length = H, color_in = MEFT */
479 INSTR_METER_HHI, /* index = H, length = H, color_in = I */
480 INSTR_METER_HMM, /* index = H, length = MEFT, color_in = MEFT */
481 INSTR_METER_HMI, /* index = H, length = MEFT, color_in = I */
482 INSTR_METER_MHM, /* index = MEFT, length = H, color_in = MEFT */
483 INSTR_METER_MHI, /* index = MEFT, length = H, color_in = I */
484 INSTR_METER_MMM, /* index = MEFT, length = MEFT, color_in = MEFT */
485 INSTR_METER_MMI, /* index = MEFT, length = MEFT, color_in = I */
486 INSTR_METER_IHM, /* index = I, length = H, color_in = MEFT */
487 INSTR_METER_IHI, /* index = I, length = H, color_in = I */
488 INSTR_METER_IMM, /* index = I, length = MEFT, color_in = MEFT */
489 INSTR_METER_IMI, /* index = I, length = MEFT, color_in = I */
494 /* extern e.obj.func */
505 /* jmpv LABEL h.header
506 * Jump if header is valid
510 /* jmpnv LABEL h.header
511 * Jump if header is invalid
516 * Jump if table lookup hit
521 * Jump if table lookup miss
528 INSTR_JMP_ACTION_HIT,
530 /* jmpna LABEL ACTION
531 * Jump if action not run
533 INSTR_JMP_ACTION_MISS,
536 * Jump is a is equal to b
537 * a = HMEFT, b = HMEFTI
539 INSTR_JMP_EQ, /* (a, b) = (MEFT, MEFT) or (a, b) = (H, H) */
540 INSTR_JMP_EQ_S, /* (a, b) = (MEFT, H) or (a, b) = (H, MEFT) */
541 INSTR_JMP_EQ_I, /* (a, b) = (MEFT, I) or (a, b) = (H, I) */
544 * Jump is a is not equal to b
545 * a = HMEFT, b = HMEFTI
547 INSTR_JMP_NEQ, /* (a, b) = (MEFT, MEFT) or (a, b) = (H, H) */
548 INSTR_JMP_NEQ_S, /* (a, b) = (MEFT, H) or (a, b) = (H, MEFT) */
549 INSTR_JMP_NEQ_I, /* (a, b) = (MEFT, I) or (a, b) = (H, I) */
552 * Jump if a is less than b
553 * a = HMEFT, b = HMEFTI
555 INSTR_JMP_LT, /* a = MEF, b = MEF */
556 INSTR_JMP_LT_MH, /* a = MEF, b = H */
557 INSTR_JMP_LT_HM, /* a = H, b = MEF */
558 INSTR_JMP_LT_HH, /* a = H, b = H */
559 INSTR_JMP_LT_MI, /* a = MEF, b = I */
560 INSTR_JMP_LT_HI, /* a = H, b = I */
563 * Jump if a is greater than b
564 * a = HMEFT, b = HMEFTI
566 INSTR_JMP_GT, /* a = MEF, b = MEF */
567 INSTR_JMP_GT_MH, /* a = MEF, b = H */
568 INSTR_JMP_GT_HM, /* a = H, b = MEF */
569 INSTR_JMP_GT_HH, /* a = H, b = H */
570 INSTR_JMP_GT_MI, /* a = MEF, b = I */
571 INSTR_JMP_GT_HI, /* a = H, b = I */
579 struct instr_operand {
600 uint8_t header_id[8];
601 uint8_t struct_id[8];
606 struct instr_hdr_validity {
614 struct instr_extern_obj {
619 struct instr_extern_func {
623 struct instr_dst_src {
624 struct instr_operand dst;
626 struct instr_operand src;
631 struct instr_regarray {
636 struct instr_operand idx;
641 struct instr_operand dstsrc;
651 struct instr_operand idx;
655 struct instr_operand length;
658 struct instr_operand color_in;
659 uint32_t color_in_val;
662 struct instr_operand color_out;
667 uint8_t header_id[8];
668 uint8_t struct_id[8];
679 struct instruction *ip;
682 struct instr_operand a;
688 struct instr_operand b;
694 enum instruction_type type;
697 struct instr_hdr_validity valid;
698 struct instr_dst_src mov;
699 struct instr_regarray regarray;
700 struct instr_meter meter;
701 struct instr_dma dma;
702 struct instr_dst_src alu;
703 struct instr_table table;
704 struct instr_extern_obj ext_obj;
705 struct instr_extern_func ext_func;
706 struct instr_jmp jmp;
710 struct instruction_data {
711 char label[RTE_SWX_NAME_SIZE];
712 char jmp_label[RTE_SWX_NAME_SIZE];
713 uint32_t n_users; /* user = jmp instruction to this instruction. */
721 TAILQ_ENTRY(action) node;
722 char name[RTE_SWX_NAME_SIZE];
723 struct struct_type *st;
724 struct instruction *instructions;
725 uint32_t n_instructions;
729 TAILQ_HEAD(action_tailq, action);
735 TAILQ_ENTRY(table_type) node;
736 char name[RTE_SWX_NAME_SIZE];
737 enum rte_swx_table_match_type match_type;
738 struct rte_swx_table_ops ops;
741 TAILQ_HEAD(table_type_tailq, table_type);
744 enum rte_swx_table_match_type match_type;
749 TAILQ_ENTRY(table) node;
750 char name[RTE_SWX_NAME_SIZE];
751 char args[RTE_SWX_NAME_SIZE];
752 struct table_type *type; /* NULL when n_fields == 0. */
755 struct match_field *fields;
757 struct header *header; /* Only valid when n_fields > 0. */
760 struct action **actions;
761 struct action *default_action;
762 uint8_t *default_action_data;
764 int default_action_is_const;
765 uint32_t action_data_size_max;
771 TAILQ_HEAD(table_tailq, table);
773 struct table_runtime {
774 rte_swx_table_lookup_t func;
783 TAILQ_ENTRY(regarray) node;
784 char name[RTE_SWX_NAME_SIZE];
790 TAILQ_HEAD(regarray_tailq, regarray);
792 struct regarray_runtime {
800 struct meter_profile {
801 TAILQ_ENTRY(meter_profile) node;
802 char name[RTE_SWX_NAME_SIZE];
803 struct rte_meter_trtcm_params params;
804 struct rte_meter_trtcm_profile profile;
808 TAILQ_HEAD(meter_profile_tailq, meter_profile);
811 TAILQ_ENTRY(metarray) node;
812 char name[RTE_SWX_NAME_SIZE];
817 TAILQ_HEAD(metarray_tailq, metarray);
820 struct rte_meter_trtcm m;
821 struct meter_profile *profile;
822 enum rte_color color_mask;
825 uint64_t n_pkts[RTE_COLORS];
826 uint64_t n_bytes[RTE_COLORS];
829 struct metarray_runtime {
830 struct meter *metarray;
839 struct rte_swx_pkt pkt;
845 /* Packet headers. */
846 struct header_runtime *headers; /* Extracted or generated headers. */
847 struct header_out_runtime *headers_out; /* Emitted headers. */
848 uint8_t *header_storage;
849 uint8_t *header_out_storage;
850 uint64_t valid_headers;
851 uint32_t n_headers_out;
853 /* Packet meta-data. */
857 struct table_runtime *tables;
858 struct rte_swx_table_state *table_state;
860 int hit; /* 0 = Miss, 1 = Hit. */
862 /* Extern objects and functions. */
863 struct extern_obj_runtime *extern_objs;
864 struct extern_func_runtime *extern_funcs;
867 struct instruction *ip;
868 struct instruction *ret;
871 #define MASK64_BIT_GET(mask, pos) ((mask) & (1LLU << (pos)))
872 #define MASK64_BIT_SET(mask, pos) ((mask) | (1LLU << (pos)))
873 #define MASK64_BIT_CLR(mask, pos) ((mask) & ~(1LLU << (pos)))
875 #define HEADER_VALID(thread, header_id) \
876 MASK64_BIT_GET((thread)->valid_headers, header_id)
878 #define ALU(thread, ip, operator) \
880 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
881 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
882 uint64_t dst64 = *dst64_ptr; \
883 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
884 uint64_t dst = dst64 & dst64_mask; \
886 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
887 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
888 uint64_t src64 = *src64_ptr; \
889 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->alu.src.n_bits); \
890 uint64_t src = src64 & src64_mask; \
892 uint64_t result = dst operator src; \
894 *dst64_ptr = (dst64 & ~dst64_mask) | (result & dst64_mask); \
897 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
899 #define ALU_S(thread, ip, operator) \
901 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
902 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
903 uint64_t dst64 = *dst64_ptr; \
904 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
905 uint64_t dst = dst64 & dst64_mask; \
907 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
908 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
909 uint64_t src64 = *src64_ptr; \
910 uint64_t src = ntoh64(src64) >> (64 - (ip)->alu.src.n_bits); \
912 uint64_t result = dst operator src; \
914 *dst64_ptr = (dst64 & ~dst64_mask) | (result & dst64_mask); \
919 #define ALU_HM(thread, ip, operator) \
921 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
922 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
923 uint64_t dst64 = *dst64_ptr; \
924 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
925 uint64_t dst = ntoh64(dst64) >> (64 - (ip)->alu.dst.n_bits); \
927 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
928 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
929 uint64_t src64 = *src64_ptr; \
930 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->alu.src.n_bits); \
931 uint64_t src = src64 & src64_mask; \
933 uint64_t result = dst operator src; \
934 result = hton64(result << (64 - (ip)->alu.dst.n_bits)); \
936 *dst64_ptr = (dst64 & ~dst64_mask) | result; \
939 #define ALU_HH(thread, ip, operator) \
941 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
942 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
943 uint64_t dst64 = *dst64_ptr; \
944 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
945 uint64_t dst = ntoh64(dst64) >> (64 - (ip)->alu.dst.n_bits); \
947 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
948 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
949 uint64_t src64 = *src64_ptr; \
950 uint64_t src = ntoh64(src64) >> (64 - (ip)->alu.src.n_bits); \
952 uint64_t result = dst operator src; \
953 result = hton64(result << (64 - (ip)->alu.dst.n_bits)); \
955 *dst64_ptr = (dst64 & ~dst64_mask) | result; \
967 #define ALU_I(thread, ip, operator) \
969 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
970 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
971 uint64_t dst64 = *dst64_ptr; \
972 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
973 uint64_t dst = dst64 & dst64_mask; \
975 uint64_t src = (ip)->alu.src_val; \
977 uint64_t result = dst operator src; \
979 *dst64_ptr = (dst64 & ~dst64_mask) | (result & dst64_mask); \
984 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
986 #define ALU_HI(thread, ip, operator) \
988 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
989 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
990 uint64_t dst64 = *dst64_ptr; \
991 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
992 uint64_t dst = ntoh64(dst64) >> (64 - (ip)->alu.dst.n_bits); \
994 uint64_t src = (ip)->alu.src_val; \
996 uint64_t result = dst operator src; \
997 result = hton64(result << (64 - (ip)->alu.dst.n_bits)); \
999 *dst64_ptr = (dst64 & ~dst64_mask) | result; \
1004 #define ALU_HI ALU_I
1008 #define MOV(thread, ip) \
1010 uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id]; \
1011 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset]; \
1012 uint64_t dst64 = *dst64_ptr; \
1013 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits); \
1015 uint8_t *src_struct = (thread)->structs[(ip)->mov.src.struct_id]; \
1016 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->mov.src.offset]; \
1017 uint64_t src64 = *src64_ptr; \
1018 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->mov.src.n_bits); \
1019 uint64_t src = src64 & src64_mask; \
1021 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask); \
1024 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1026 #define MOV_S(thread, ip) \
1028 uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id]; \
1029 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset]; \
1030 uint64_t dst64 = *dst64_ptr; \
1031 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits); \
1033 uint8_t *src_struct = (thread)->structs[(ip)->mov.src.struct_id]; \
1034 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->mov.src.offset]; \
1035 uint64_t src64 = *src64_ptr; \
1036 uint64_t src = ntoh64(src64) >> (64 - (ip)->mov.src.n_bits); \
1038 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask); \
1047 #define MOV_I(thread, ip) \
1049 uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id]; \
1050 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset]; \
1051 uint64_t dst64 = *dst64_ptr; \
1052 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits); \
1054 uint64_t src = (ip)->mov.src_val; \
1056 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask); \
1059 #define JMP_CMP(thread, ip, operator) \
1061 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1062 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1063 uint64_t a64 = *a64_ptr; \
1064 uint64_t a64_mask = UINT64_MAX >> (64 - (ip)->jmp.a.n_bits); \
1065 uint64_t a = a64 & a64_mask; \
1067 uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id]; \
1068 uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset]; \
1069 uint64_t b64 = *b64_ptr; \
1070 uint64_t b64_mask = UINT64_MAX >> (64 - (ip)->jmp.b.n_bits); \
1071 uint64_t b = b64 & b64_mask; \
1073 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1076 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1078 #define JMP_CMP_S(thread, ip, operator) \
1080 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1081 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1082 uint64_t a64 = *a64_ptr; \
1083 uint64_t a64_mask = UINT64_MAX >> (64 - (ip)->jmp.a.n_bits); \
1084 uint64_t a = a64 & a64_mask; \
1086 uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id]; \
1087 uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset]; \
1088 uint64_t b64 = *b64_ptr; \
1089 uint64_t b = ntoh64(b64) >> (64 - (ip)->jmp.b.n_bits); \
1091 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1094 #define JMP_CMP_MH JMP_CMP_S
1096 #define JMP_CMP_HM(thread, ip, operator) \
1098 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1099 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1100 uint64_t a64 = *a64_ptr; \
1101 uint64_t a = ntoh64(a64) >> (64 - (ip)->jmp.a.n_bits); \
1103 uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id]; \
1104 uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset]; \
1105 uint64_t b64 = *b64_ptr; \
1106 uint64_t b64_mask = UINT64_MAX >> (64 - (ip)->jmp.b.n_bits); \
1107 uint64_t b = b64 & b64_mask; \
1109 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1112 #define JMP_CMP_HH(thread, ip, operator) \
1114 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1115 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1116 uint64_t a64 = *a64_ptr; \
1117 uint64_t a = ntoh64(a64) >> (64 - (ip)->jmp.a.n_bits); \
1119 uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id]; \
1120 uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset]; \
1121 uint64_t b64 = *b64_ptr; \
1122 uint64_t b = ntoh64(b64) >> (64 - (ip)->jmp.b.n_bits); \
1124 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1129 #define JMP_CMP_S JMP_CMP
1130 #define JMP_CMP_MH JMP_CMP
1131 #define JMP_CMP_HM JMP_CMP
1132 #define JMP_CMP_HH JMP_CMP
1136 #define JMP_CMP_I(thread, ip, operator) \
1138 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1139 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1140 uint64_t a64 = *a64_ptr; \
1141 uint64_t a64_mask = UINT64_MAX >> (64 - (ip)->jmp.a.n_bits); \
1142 uint64_t a = a64 & a64_mask; \
1144 uint64_t b = (ip)->jmp.b_val; \
1146 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1149 #define JMP_CMP_MI JMP_CMP_I
1151 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1153 #define JMP_CMP_HI(thread, ip, operator) \
1155 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1156 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1157 uint64_t a64 = *a64_ptr; \
1158 uint64_t a = ntoh64(a64) >> (64 - (ip)->jmp.a.n_bits); \
1160 uint64_t b = (ip)->jmp.b_val; \
1162 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1167 #define JMP_CMP_HI JMP_CMP_I
1171 #define METADATA_READ(thread, offset, n_bits) \
1173 uint64_t *m64_ptr = (uint64_t *)&(thread)->metadata[offset]; \
1174 uint64_t m64 = *m64_ptr; \
1175 uint64_t m64_mask = UINT64_MAX >> (64 - (n_bits)); \
1179 #define METADATA_WRITE(thread, offset, n_bits, value) \
1181 uint64_t *m64_ptr = (uint64_t *)&(thread)->metadata[offset]; \
1182 uint64_t m64 = *m64_ptr; \
1183 uint64_t m64_mask = UINT64_MAX >> (64 - (n_bits)); \
1185 uint64_t m_new = value; \
1187 *m64_ptr = (m64 & ~m64_mask) | (m_new & m64_mask); \
1190 #ifndef RTE_SWX_PIPELINE_THREADS_MAX
1191 #define RTE_SWX_PIPELINE_THREADS_MAX 16
1194 struct rte_swx_pipeline {
1195 struct struct_type_tailq struct_types;
1196 struct port_in_type_tailq port_in_types;
1197 struct port_in_tailq ports_in;
1198 struct port_out_type_tailq port_out_types;
1199 struct port_out_tailq ports_out;
1200 struct extern_type_tailq extern_types;
1201 struct extern_obj_tailq extern_objs;
1202 struct extern_func_tailq extern_funcs;
1203 struct header_tailq headers;
1204 struct struct_type *metadata_st;
1205 uint32_t metadata_struct_id;
1206 struct action_tailq actions;
1207 struct table_type_tailq table_types;
1208 struct table_tailq tables;
1209 struct regarray_tailq regarrays;
1210 struct meter_profile_tailq meter_profiles;
1211 struct metarray_tailq metarrays;
1213 struct port_in_runtime *in;
1214 struct port_out_runtime *out;
1215 struct instruction **action_instructions;
1216 struct rte_swx_table_state *table_state;
1217 struct regarray_runtime *regarray_runtime;
1218 struct metarray_runtime *metarray_runtime;
1219 struct instruction *instructions;
1220 struct thread threads[RTE_SWX_PIPELINE_THREADS_MAX];
1223 uint32_t n_ports_in;
1224 uint32_t n_ports_out;
1225 uint32_t n_extern_objs;
1226 uint32_t n_extern_funcs;
1229 uint32_t n_regarrays;
1230 uint32_t n_metarrays;
1234 uint32_t n_instructions;
1242 static struct struct_type *
1243 struct_type_find(struct rte_swx_pipeline *p, const char *name)
1245 struct struct_type *elem;
1247 TAILQ_FOREACH(elem, &p->struct_types, node)
1248 if (strcmp(elem->name, name) == 0)
1254 static struct field *
1255 struct_type_field_find(struct struct_type *st, const char *name)
1259 for (i = 0; i < st->n_fields; i++) {
1260 struct field *f = &st->fields[i];
1262 if (strcmp(f->name, name) == 0)
1270 rte_swx_pipeline_struct_type_register(struct rte_swx_pipeline *p,
1272 struct rte_swx_field_params *fields,
1275 struct struct_type *st;
1279 CHECK_NAME(name, EINVAL);
1280 CHECK(fields, EINVAL);
1281 CHECK(n_fields, EINVAL);
1283 for (i = 0; i < n_fields; i++) {
1284 struct rte_swx_field_params *f = &fields[i];
1287 CHECK_NAME(f->name, EINVAL);
1288 CHECK(f->n_bits, EINVAL);
1289 CHECK(f->n_bits <= 64, EINVAL);
1290 CHECK((f->n_bits & 7) == 0, EINVAL);
1292 for (j = 0; j < i; j++) {
1293 struct rte_swx_field_params *f_prev = &fields[j];
1295 CHECK(strcmp(f->name, f_prev->name), EINVAL);
1299 CHECK(!struct_type_find(p, name), EEXIST);
1301 /* Node allocation. */
1302 st = calloc(1, sizeof(struct struct_type));
1305 st->fields = calloc(n_fields, sizeof(struct field));
1311 /* Node initialization. */
1312 strcpy(st->name, name);
1313 for (i = 0; i < n_fields; i++) {
1314 struct field *dst = &st->fields[i];
1315 struct rte_swx_field_params *src = &fields[i];
1317 strcpy(dst->name, src->name);
1318 dst->n_bits = src->n_bits;
1319 dst->offset = st->n_bits;
1321 st->n_bits += src->n_bits;
1323 st->n_fields = n_fields;
1325 /* Node add to tailq. */
1326 TAILQ_INSERT_TAIL(&p->struct_types, st, node);
1332 struct_build(struct rte_swx_pipeline *p)
1336 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1337 struct thread *t = &p->threads[i];
1339 t->structs = calloc(p->n_structs, sizeof(uint8_t *));
1340 CHECK(t->structs, ENOMEM);
1347 struct_build_free(struct rte_swx_pipeline *p)
1351 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1352 struct thread *t = &p->threads[i];
1360 struct_free(struct rte_swx_pipeline *p)
1362 struct_build_free(p);
1366 struct struct_type *elem;
1368 elem = TAILQ_FIRST(&p->struct_types);
1372 TAILQ_REMOVE(&p->struct_types, elem, node);
1381 static struct port_in_type *
1382 port_in_type_find(struct rte_swx_pipeline *p, const char *name)
1384 struct port_in_type *elem;
1389 TAILQ_FOREACH(elem, &p->port_in_types, node)
1390 if (strcmp(elem->name, name) == 0)
1397 rte_swx_pipeline_port_in_type_register(struct rte_swx_pipeline *p,
1399 struct rte_swx_port_in_ops *ops)
1401 struct port_in_type *elem;
1404 CHECK_NAME(name, EINVAL);
1406 CHECK(ops->create, EINVAL);
1407 CHECK(ops->free, EINVAL);
1408 CHECK(ops->pkt_rx, EINVAL);
1409 CHECK(ops->stats_read, EINVAL);
1411 CHECK(!port_in_type_find(p, name), EEXIST);
1413 /* Node allocation. */
1414 elem = calloc(1, sizeof(struct port_in_type));
1415 CHECK(elem, ENOMEM);
1417 /* Node initialization. */
1418 strcpy(elem->name, name);
1419 memcpy(&elem->ops, ops, sizeof(*ops));
1421 /* Node add to tailq. */
1422 TAILQ_INSERT_TAIL(&p->port_in_types, elem, node);
1427 static struct port_in *
1428 port_in_find(struct rte_swx_pipeline *p, uint32_t port_id)
1430 struct port_in *port;
1432 TAILQ_FOREACH(port, &p->ports_in, node)
1433 if (port->id == port_id)
1440 rte_swx_pipeline_port_in_config(struct rte_swx_pipeline *p,
1442 const char *port_type_name,
1445 struct port_in_type *type = NULL;
1446 struct port_in *port = NULL;
1451 CHECK(!port_in_find(p, port_id), EINVAL);
1453 CHECK_NAME(port_type_name, EINVAL);
1454 type = port_in_type_find(p, port_type_name);
1455 CHECK(type, EINVAL);
1457 obj = type->ops.create(args);
1460 /* Node allocation. */
1461 port = calloc(1, sizeof(struct port_in));
1462 CHECK(port, ENOMEM);
1464 /* Node initialization. */
1469 /* Node add to tailq. */
1470 TAILQ_INSERT_TAIL(&p->ports_in, port, node);
1471 if (p->n_ports_in < port_id + 1)
1472 p->n_ports_in = port_id + 1;
1478 port_in_build(struct rte_swx_pipeline *p)
1480 struct port_in *port;
1483 CHECK(p->n_ports_in, EINVAL);
1484 CHECK(rte_is_power_of_2(p->n_ports_in), EINVAL);
1486 for (i = 0; i < p->n_ports_in; i++)
1487 CHECK(port_in_find(p, i), EINVAL);
1489 p->in = calloc(p->n_ports_in, sizeof(struct port_in_runtime));
1490 CHECK(p->in, ENOMEM);
1492 TAILQ_FOREACH(port, &p->ports_in, node) {
1493 struct port_in_runtime *in = &p->in[port->id];
1495 in->pkt_rx = port->type->ops.pkt_rx;
1496 in->obj = port->obj;
1503 port_in_build_free(struct rte_swx_pipeline *p)
1510 port_in_free(struct rte_swx_pipeline *p)
1512 port_in_build_free(p);
1516 struct port_in *port;
1518 port = TAILQ_FIRST(&p->ports_in);
1522 TAILQ_REMOVE(&p->ports_in, port, node);
1523 port->type->ops.free(port->obj);
1527 /* Input port types. */
1529 struct port_in_type *elem;
1531 elem = TAILQ_FIRST(&p->port_in_types);
1535 TAILQ_REMOVE(&p->port_in_types, elem, node);
1543 static struct port_out_type *
1544 port_out_type_find(struct rte_swx_pipeline *p, const char *name)
1546 struct port_out_type *elem;
1551 TAILQ_FOREACH(elem, &p->port_out_types, node)
1552 if (!strcmp(elem->name, name))
1559 rte_swx_pipeline_port_out_type_register(struct rte_swx_pipeline *p,
1561 struct rte_swx_port_out_ops *ops)
1563 struct port_out_type *elem;
1566 CHECK_NAME(name, EINVAL);
1568 CHECK(ops->create, EINVAL);
1569 CHECK(ops->free, EINVAL);
1570 CHECK(ops->pkt_tx, EINVAL);
1571 CHECK(ops->stats_read, EINVAL);
1573 CHECK(!port_out_type_find(p, name), EEXIST);
1575 /* Node allocation. */
1576 elem = calloc(1, sizeof(struct port_out_type));
1577 CHECK(elem, ENOMEM);
1579 /* Node initialization. */
1580 strcpy(elem->name, name);
1581 memcpy(&elem->ops, ops, sizeof(*ops));
1583 /* Node add to tailq. */
1584 TAILQ_INSERT_TAIL(&p->port_out_types, elem, node);
1589 static struct port_out *
1590 port_out_find(struct rte_swx_pipeline *p, uint32_t port_id)
1592 struct port_out *port;
1594 TAILQ_FOREACH(port, &p->ports_out, node)
1595 if (port->id == port_id)
1602 rte_swx_pipeline_port_out_config(struct rte_swx_pipeline *p,
1604 const char *port_type_name,
1607 struct port_out_type *type = NULL;
1608 struct port_out *port = NULL;
1613 CHECK(!port_out_find(p, port_id), EINVAL);
1615 CHECK_NAME(port_type_name, EINVAL);
1616 type = port_out_type_find(p, port_type_name);
1617 CHECK(type, EINVAL);
1619 obj = type->ops.create(args);
1622 /* Node allocation. */
1623 port = calloc(1, sizeof(struct port_out));
1624 CHECK(port, ENOMEM);
1626 /* Node initialization. */
1631 /* Node add to tailq. */
1632 TAILQ_INSERT_TAIL(&p->ports_out, port, node);
1633 if (p->n_ports_out < port_id + 1)
1634 p->n_ports_out = port_id + 1;
1640 port_out_build(struct rte_swx_pipeline *p)
1642 struct port_out *port;
1645 CHECK(p->n_ports_out, EINVAL);
1647 for (i = 0; i < p->n_ports_out; i++)
1648 CHECK(port_out_find(p, i), EINVAL);
1650 p->out = calloc(p->n_ports_out, sizeof(struct port_out_runtime));
1651 CHECK(p->out, ENOMEM);
1653 TAILQ_FOREACH(port, &p->ports_out, node) {
1654 struct port_out_runtime *out = &p->out[port->id];
1656 out->pkt_tx = port->type->ops.pkt_tx;
1657 out->flush = port->type->ops.flush;
1658 out->obj = port->obj;
1665 port_out_build_free(struct rte_swx_pipeline *p)
1672 port_out_free(struct rte_swx_pipeline *p)
1674 port_out_build_free(p);
1678 struct port_out *port;
1680 port = TAILQ_FIRST(&p->ports_out);
1684 TAILQ_REMOVE(&p->ports_out, port, node);
1685 port->type->ops.free(port->obj);
1689 /* Output port types. */
1691 struct port_out_type *elem;
1693 elem = TAILQ_FIRST(&p->port_out_types);
1697 TAILQ_REMOVE(&p->port_out_types, elem, node);
1705 static struct extern_type *
1706 extern_type_find(struct rte_swx_pipeline *p, const char *name)
1708 struct extern_type *elem;
1710 TAILQ_FOREACH(elem, &p->extern_types, node)
1711 if (strcmp(elem->name, name) == 0)
1717 static struct extern_type_member_func *
1718 extern_type_member_func_find(struct extern_type *type, const char *name)
1720 struct extern_type_member_func *elem;
1722 TAILQ_FOREACH(elem, &type->funcs, node)
1723 if (strcmp(elem->name, name) == 0)
1729 static struct extern_obj *
1730 extern_obj_find(struct rte_swx_pipeline *p, const char *name)
1732 struct extern_obj *elem;
1734 TAILQ_FOREACH(elem, &p->extern_objs, node)
1735 if (strcmp(elem->name, name) == 0)
1741 static struct extern_type_member_func *
1742 extern_obj_member_func_parse(struct rte_swx_pipeline *p,
1744 struct extern_obj **obj)
1746 struct extern_obj *object;
1747 struct extern_type_member_func *func;
1748 char *object_name, *func_name;
1750 if (name[0] != 'e' || name[1] != '.')
1753 object_name = strdup(&name[2]);
1757 func_name = strchr(object_name, '.');
1766 object = extern_obj_find(p, object_name);
1772 func = extern_type_member_func_find(object->type, func_name);
1785 static struct field *
1786 extern_obj_mailbox_field_parse(struct rte_swx_pipeline *p,
1788 struct extern_obj **object)
1790 struct extern_obj *obj;
1792 char *obj_name, *field_name;
1794 if ((name[0] != 'e') || (name[1] != '.'))
1797 obj_name = strdup(&name[2]);
1801 field_name = strchr(obj_name, '.');
1810 obj = extern_obj_find(p, obj_name);
1816 f = struct_type_field_find(obj->type->mailbox_struct_type, field_name);
1830 rte_swx_pipeline_extern_type_register(struct rte_swx_pipeline *p,
1832 const char *mailbox_struct_type_name,
1833 rte_swx_extern_type_constructor_t constructor,
1834 rte_swx_extern_type_destructor_t destructor)
1836 struct extern_type *elem;
1837 struct struct_type *mailbox_struct_type;
1841 CHECK_NAME(name, EINVAL);
1842 CHECK(!extern_type_find(p, name), EEXIST);
1844 CHECK_NAME(mailbox_struct_type_name, EINVAL);
1845 mailbox_struct_type = struct_type_find(p, mailbox_struct_type_name);
1846 CHECK(mailbox_struct_type, EINVAL);
1848 CHECK(constructor, EINVAL);
1849 CHECK(destructor, EINVAL);
1851 /* Node allocation. */
1852 elem = calloc(1, sizeof(struct extern_type));
1853 CHECK(elem, ENOMEM);
1855 /* Node initialization. */
1856 strcpy(elem->name, name);
1857 elem->mailbox_struct_type = mailbox_struct_type;
1858 elem->constructor = constructor;
1859 elem->destructor = destructor;
1860 TAILQ_INIT(&elem->funcs);
1862 /* Node add to tailq. */
1863 TAILQ_INSERT_TAIL(&p->extern_types, elem, node);
1869 rte_swx_pipeline_extern_type_member_func_register(struct rte_swx_pipeline *p,
1870 const char *extern_type_name,
1872 rte_swx_extern_type_member_func_t member_func)
1874 struct extern_type *type;
1875 struct extern_type_member_func *type_member;
1879 CHECK_NAME(extern_type_name, EINVAL);
1880 type = extern_type_find(p, extern_type_name);
1881 CHECK(type, EINVAL);
1882 CHECK(type->n_funcs < RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX, ENOSPC);
1884 CHECK_NAME(name, EINVAL);
1885 CHECK(!extern_type_member_func_find(type, name), EEXIST);
1887 CHECK(member_func, EINVAL);
1889 /* Node allocation. */
1890 type_member = calloc(1, sizeof(struct extern_type_member_func));
1891 CHECK(type_member, ENOMEM);
1893 /* Node initialization. */
1894 strcpy(type_member->name, name);
1895 type_member->func = member_func;
1896 type_member->id = type->n_funcs;
1898 /* Node add to tailq. */
1899 TAILQ_INSERT_TAIL(&type->funcs, type_member, node);
1906 rte_swx_pipeline_extern_object_config(struct rte_swx_pipeline *p,
1907 const char *extern_type_name,
1911 struct extern_type *type;
1912 struct extern_obj *obj;
1917 CHECK_NAME(extern_type_name, EINVAL);
1918 type = extern_type_find(p, extern_type_name);
1919 CHECK(type, EINVAL);
1921 CHECK_NAME(name, EINVAL);
1922 CHECK(!extern_obj_find(p, name), EEXIST);
1924 /* Node allocation. */
1925 obj = calloc(1, sizeof(struct extern_obj));
1928 /* Object construction. */
1929 obj_handle = type->constructor(args);
1935 /* Node initialization. */
1936 strcpy(obj->name, name);
1938 obj->obj = obj_handle;
1939 obj->struct_id = p->n_structs;
1940 obj->id = p->n_extern_objs;
1942 /* Node add to tailq. */
1943 TAILQ_INSERT_TAIL(&p->extern_objs, obj, node);
1951 extern_obj_build(struct rte_swx_pipeline *p)
1955 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1956 struct thread *t = &p->threads[i];
1957 struct extern_obj *obj;
1959 t->extern_objs = calloc(p->n_extern_objs,
1960 sizeof(struct extern_obj_runtime));
1961 CHECK(t->extern_objs, ENOMEM);
1963 TAILQ_FOREACH(obj, &p->extern_objs, node) {
1964 struct extern_obj_runtime *r =
1965 &t->extern_objs[obj->id];
1966 struct extern_type_member_func *func;
1967 uint32_t mailbox_size =
1968 obj->type->mailbox_struct_type->n_bits / 8;
1972 r->mailbox = calloc(1, mailbox_size);
1973 CHECK(r->mailbox, ENOMEM);
1975 TAILQ_FOREACH(func, &obj->type->funcs, node)
1976 r->funcs[func->id] = func->func;
1978 t->structs[obj->struct_id] = r->mailbox;
1986 extern_obj_build_free(struct rte_swx_pipeline *p)
1990 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1991 struct thread *t = &p->threads[i];
1994 if (!t->extern_objs)
1997 for (j = 0; j < p->n_extern_objs; j++) {
1998 struct extern_obj_runtime *r = &t->extern_objs[j];
2003 free(t->extern_objs);
2004 t->extern_objs = NULL;
2009 extern_obj_free(struct rte_swx_pipeline *p)
2011 extern_obj_build_free(p);
2013 /* Extern objects. */
2015 struct extern_obj *elem;
2017 elem = TAILQ_FIRST(&p->extern_objs);
2021 TAILQ_REMOVE(&p->extern_objs, elem, node);
2023 elem->type->destructor(elem->obj);
2029 struct extern_type *elem;
2031 elem = TAILQ_FIRST(&p->extern_types);
2035 TAILQ_REMOVE(&p->extern_types, elem, node);
2038 struct extern_type_member_func *func;
2040 func = TAILQ_FIRST(&elem->funcs);
2044 TAILQ_REMOVE(&elem->funcs, func, node);
2055 static struct extern_func *
2056 extern_func_find(struct rte_swx_pipeline *p, const char *name)
2058 struct extern_func *elem;
2060 TAILQ_FOREACH(elem, &p->extern_funcs, node)
2061 if (strcmp(elem->name, name) == 0)
2067 static struct extern_func *
2068 extern_func_parse(struct rte_swx_pipeline *p,
2071 if (name[0] != 'f' || name[1] != '.')
2074 return extern_func_find(p, &name[2]);
2077 static struct field *
2078 extern_func_mailbox_field_parse(struct rte_swx_pipeline *p,
2080 struct extern_func **function)
2082 struct extern_func *func;
2084 char *func_name, *field_name;
2086 if ((name[0] != 'f') || (name[1] != '.'))
2089 func_name = strdup(&name[2]);
2093 field_name = strchr(func_name, '.');
2102 func = extern_func_find(p, func_name);
2108 f = struct_type_field_find(func->mailbox_struct_type, field_name);
2122 rte_swx_pipeline_extern_func_register(struct rte_swx_pipeline *p,
2124 const char *mailbox_struct_type_name,
2125 rte_swx_extern_func_t func)
2127 struct extern_func *f;
2128 struct struct_type *mailbox_struct_type;
2132 CHECK_NAME(name, EINVAL);
2133 CHECK(!extern_func_find(p, name), EEXIST);
2135 CHECK_NAME(mailbox_struct_type_name, EINVAL);
2136 mailbox_struct_type = struct_type_find(p, mailbox_struct_type_name);
2137 CHECK(mailbox_struct_type, EINVAL);
2139 CHECK(func, EINVAL);
2141 /* Node allocation. */
2142 f = calloc(1, sizeof(struct extern_func));
2143 CHECK(func, ENOMEM);
2145 /* Node initialization. */
2146 strcpy(f->name, name);
2147 f->mailbox_struct_type = mailbox_struct_type;
2149 f->struct_id = p->n_structs;
2150 f->id = p->n_extern_funcs;
2152 /* Node add to tailq. */
2153 TAILQ_INSERT_TAIL(&p->extern_funcs, f, node);
2154 p->n_extern_funcs++;
2161 extern_func_build(struct rte_swx_pipeline *p)
2165 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
2166 struct thread *t = &p->threads[i];
2167 struct extern_func *func;
2169 /* Memory allocation. */
2170 t->extern_funcs = calloc(p->n_extern_funcs,
2171 sizeof(struct extern_func_runtime));
2172 CHECK(t->extern_funcs, ENOMEM);
2174 /* Extern function. */
2175 TAILQ_FOREACH(func, &p->extern_funcs, node) {
2176 struct extern_func_runtime *r =
2177 &t->extern_funcs[func->id];
2178 uint32_t mailbox_size =
2179 func->mailbox_struct_type->n_bits / 8;
2181 r->func = func->func;
2183 r->mailbox = calloc(1, mailbox_size);
2184 CHECK(r->mailbox, ENOMEM);
2186 t->structs[func->struct_id] = r->mailbox;
2194 extern_func_build_free(struct rte_swx_pipeline *p)
2198 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
2199 struct thread *t = &p->threads[i];
2202 if (!t->extern_funcs)
2205 for (j = 0; j < p->n_extern_funcs; j++) {
2206 struct extern_func_runtime *r = &t->extern_funcs[j];
2211 free(t->extern_funcs);
2212 t->extern_funcs = NULL;
2217 extern_func_free(struct rte_swx_pipeline *p)
2219 extern_func_build_free(p);
2222 struct extern_func *elem;
2224 elem = TAILQ_FIRST(&p->extern_funcs);
2228 TAILQ_REMOVE(&p->extern_funcs, elem, node);
2236 static struct header *
2237 header_find(struct rte_swx_pipeline *p, const char *name)
2239 struct header *elem;
2241 TAILQ_FOREACH(elem, &p->headers, node)
2242 if (strcmp(elem->name, name) == 0)
2248 static struct header *
2249 header_parse(struct rte_swx_pipeline *p,
2252 if (name[0] != 'h' || name[1] != '.')
2255 return header_find(p, &name[2]);
2258 static struct field *
2259 header_field_parse(struct rte_swx_pipeline *p,
2261 struct header **header)
2265 char *header_name, *field_name;
2267 if ((name[0] != 'h') || (name[1] != '.'))
2270 header_name = strdup(&name[2]);
2274 field_name = strchr(header_name, '.');
2283 h = header_find(p, header_name);
2289 f = struct_type_field_find(h->st, field_name);
2303 rte_swx_pipeline_packet_header_register(struct rte_swx_pipeline *p,
2305 const char *struct_type_name)
2307 struct struct_type *st;
2309 size_t n_headers_max;
2312 CHECK_NAME(name, EINVAL);
2313 CHECK_NAME(struct_type_name, EINVAL);
2315 CHECK(!header_find(p, name), EEXIST);
2317 st = struct_type_find(p, struct_type_name);
2320 n_headers_max = RTE_SIZEOF_FIELD(struct thread, valid_headers) * 8;
2321 CHECK(p->n_headers < n_headers_max, ENOSPC);
2323 /* Node allocation. */
2324 h = calloc(1, sizeof(struct header));
2327 /* Node initialization. */
2328 strcpy(h->name, name);
2330 h->struct_id = p->n_structs;
2331 h->id = p->n_headers;
2333 /* Node add to tailq. */
2334 TAILQ_INSERT_TAIL(&p->headers, h, node);
2342 header_build(struct rte_swx_pipeline *p)
2345 uint32_t n_bytes = 0, i;
2347 TAILQ_FOREACH(h, &p->headers, node) {
2348 n_bytes += h->st->n_bits / 8;
2351 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
2352 struct thread *t = &p->threads[i];
2353 uint32_t offset = 0;
2355 t->headers = calloc(p->n_headers,
2356 sizeof(struct header_runtime));
2357 CHECK(t->headers, ENOMEM);
2359 t->headers_out = calloc(p->n_headers,
2360 sizeof(struct header_out_runtime));
2361 CHECK(t->headers_out, ENOMEM);
2363 t->header_storage = calloc(1, n_bytes);
2364 CHECK(t->header_storage, ENOMEM);
2366 t->header_out_storage = calloc(1, n_bytes);
2367 CHECK(t->header_out_storage, ENOMEM);
2369 TAILQ_FOREACH(h, &p->headers, node) {
2370 uint8_t *header_storage;
2372 header_storage = &t->header_storage[offset];
2373 offset += h->st->n_bits / 8;
2375 t->headers[h->id].ptr0 = header_storage;
2376 t->structs[h->struct_id] = header_storage;
2384 header_build_free(struct rte_swx_pipeline *p)
2388 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
2389 struct thread *t = &p->threads[i];
2391 free(t->headers_out);
2392 t->headers_out = NULL;
2397 free(t->header_out_storage);
2398 t->header_out_storage = NULL;
2400 free(t->header_storage);
2401 t->header_storage = NULL;
2406 header_free(struct rte_swx_pipeline *p)
2408 header_build_free(p);
2411 struct header *elem;
2413 elem = TAILQ_FIRST(&p->headers);
2417 TAILQ_REMOVE(&p->headers, elem, node);
2425 static struct field *
2426 metadata_field_parse(struct rte_swx_pipeline *p, const char *name)
2428 if (!p->metadata_st)
2431 if (name[0] != 'm' || name[1] != '.')
2434 return struct_type_field_find(p->metadata_st, &name[2]);
2438 rte_swx_pipeline_packet_metadata_register(struct rte_swx_pipeline *p,
2439 const char *struct_type_name)
2441 struct struct_type *st = NULL;
2445 CHECK_NAME(struct_type_name, EINVAL);
2446 st = struct_type_find(p, struct_type_name);
2448 CHECK(!p->metadata_st, EINVAL);
2450 p->metadata_st = st;
2451 p->metadata_struct_id = p->n_structs;
2459 metadata_build(struct rte_swx_pipeline *p)
2461 uint32_t n_bytes = p->metadata_st->n_bits / 8;
2464 /* Thread-level initialization. */
2465 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
2466 struct thread *t = &p->threads[i];
2469 metadata = calloc(1, n_bytes);
2470 CHECK(metadata, ENOMEM);
2472 t->metadata = metadata;
2473 t->structs[p->metadata_struct_id] = metadata;
2480 metadata_build_free(struct rte_swx_pipeline *p)
2484 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
2485 struct thread *t = &p->threads[i];
2493 metadata_free(struct rte_swx_pipeline *p)
2495 metadata_build_free(p);
2502 instruction_is_tx(enum instruction_type type)
2515 instruction_is_jmp(struct instruction *instr)
2517 switch (instr->type) {
2519 case INSTR_JMP_VALID:
2520 case INSTR_JMP_INVALID:
2522 case INSTR_JMP_MISS:
2523 case INSTR_JMP_ACTION_HIT:
2524 case INSTR_JMP_ACTION_MISS:
2526 case INSTR_JMP_EQ_S:
2527 case INSTR_JMP_EQ_I:
2529 case INSTR_JMP_NEQ_S:
2530 case INSTR_JMP_NEQ_I:
2532 case INSTR_JMP_LT_MH:
2533 case INSTR_JMP_LT_HM:
2534 case INSTR_JMP_LT_HH:
2535 case INSTR_JMP_LT_MI:
2536 case INSTR_JMP_LT_HI:
2538 case INSTR_JMP_GT_MH:
2539 case INSTR_JMP_GT_HM:
2540 case INSTR_JMP_GT_HH:
2541 case INSTR_JMP_GT_MI:
2542 case INSTR_JMP_GT_HI:
2550 static struct field *
2551 action_field_parse(struct action *action, const char *name);
2553 static struct field *
2554 struct_field_parse(struct rte_swx_pipeline *p,
2555 struct action *action,
2557 uint32_t *struct_id)
2564 struct header *header;
2566 f = header_field_parse(p, name, &header);
2570 *struct_id = header->struct_id;
2576 f = metadata_field_parse(p, name);
2580 *struct_id = p->metadata_struct_id;
2589 f = action_field_parse(action, name);
2599 struct extern_obj *obj;
2601 f = extern_obj_mailbox_field_parse(p, name, &obj);
2605 *struct_id = obj->struct_id;
2611 struct extern_func *func;
2613 f = extern_func_mailbox_field_parse(p, name, &func);
2617 *struct_id = func->struct_id;
2627 pipeline_port_inc(struct rte_swx_pipeline *p)
2629 p->port_id = (p->port_id + 1) & (p->n_ports_in - 1);
2633 thread_ip_reset(struct rte_swx_pipeline *p, struct thread *t)
2635 t->ip = p->instructions;
2639 thread_ip_set(struct thread *t, struct instruction *ip)
2645 thread_ip_action_call(struct rte_swx_pipeline *p,
2650 t->ip = p->action_instructions[action_id];
2654 thread_ip_inc(struct rte_swx_pipeline *p);
2657 thread_ip_inc(struct rte_swx_pipeline *p)
2659 struct thread *t = &p->threads[p->thread_id];
2665 thread_ip_inc_cond(struct thread *t, int cond)
2671 thread_yield(struct rte_swx_pipeline *p)
2673 p->thread_id = (p->thread_id + 1) & (RTE_SWX_PIPELINE_THREADS_MAX - 1);
2677 thread_yield_cond(struct rte_swx_pipeline *p, int cond)
2679 p->thread_id = (p->thread_id + cond) & (RTE_SWX_PIPELINE_THREADS_MAX - 1);
2686 instr_rx_translate(struct rte_swx_pipeline *p,
2687 struct action *action,
2690 struct instruction *instr,
2691 struct instruction_data *data __rte_unused)
2695 CHECK(!action, EINVAL);
2696 CHECK(n_tokens == 2, EINVAL);
2698 f = metadata_field_parse(p, tokens[1]);
2701 instr->type = INSTR_RX;
2702 instr->io.io.offset = f->offset / 8;
2703 instr->io.io.n_bits = f->n_bits;
2708 instr_rx_exec(struct rte_swx_pipeline *p);
2711 instr_rx_exec(struct rte_swx_pipeline *p)
2713 struct thread *t = &p->threads[p->thread_id];
2714 struct instruction *ip = t->ip;
2715 struct port_in_runtime *port = &p->in[p->port_id];
2716 struct rte_swx_pkt *pkt = &t->pkt;
2720 pkt_received = port->pkt_rx(port->obj, pkt);
2721 t->ptr = &pkt->pkt[pkt->offset];
2722 rte_prefetch0(t->ptr);
2724 TRACE("[Thread %2u] rx %s from port %u\n",
2726 pkt_received ? "1 pkt" : "0 pkts",
2730 t->valid_headers = 0;
2731 t->n_headers_out = 0;
2734 METADATA_WRITE(t, ip->io.io.offset, ip->io.io.n_bits, p->port_id);
2737 t->table_state = p->table_state;
2740 pipeline_port_inc(p);
2741 thread_ip_inc_cond(t, pkt_received);
2749 instr_tx_translate(struct rte_swx_pipeline *p,
2750 struct action *action __rte_unused,
2753 struct instruction *instr,
2754 struct instruction_data *data __rte_unused)
2756 char *port = tokens[1];
2760 CHECK(n_tokens == 2, EINVAL);
2762 f = metadata_field_parse(p, port);
2764 instr->type = INSTR_TX;
2765 instr->io.io.offset = f->offset / 8;
2766 instr->io.io.n_bits = f->n_bits;
2771 port_val = strtoul(port, &port, 0);
2772 CHECK(!port[0], EINVAL);
2774 instr->type = INSTR_TX_I;
2775 instr->io.io.val = port_val;
2780 instr_drop_translate(struct rte_swx_pipeline *p,
2781 struct action *action __rte_unused,
2782 char **tokens __rte_unused,
2784 struct instruction *instr,
2785 struct instruction_data *data __rte_unused)
2787 CHECK(n_tokens == 1, EINVAL);
2790 instr->type = INSTR_TX_I;
2791 instr->io.io.val = p->n_ports_out - 1;
2796 emit_handler(struct thread *t)
2798 struct header_out_runtime *h0 = &t->headers_out[0];
2799 struct header_out_runtime *h1 = &t->headers_out[1];
2800 uint32_t offset = 0, i;
2802 /* No header change or header decapsulation. */
2803 if ((t->n_headers_out == 1) &&
2804 (h0->ptr + h0->n_bytes == t->ptr)) {
2805 TRACE("Emit handler: no header change or header decap.\n");
2807 t->pkt.offset -= h0->n_bytes;
2808 t->pkt.length += h0->n_bytes;
2813 /* Header encapsulation (optionally, with prior header decasulation). */
2814 if ((t->n_headers_out == 2) &&
2815 (h1->ptr + h1->n_bytes == t->ptr) &&
2816 (h0->ptr == h0->ptr0)) {
2819 TRACE("Emit handler: header encapsulation.\n");
2821 offset = h0->n_bytes + h1->n_bytes;
2822 memcpy(t->ptr - offset, h0->ptr, h0->n_bytes);
2823 t->pkt.offset -= offset;
2824 t->pkt.length += offset;
2829 /* Header insertion. */
2832 /* Header extraction. */
2835 /* For any other case. */
2836 TRACE("Emit handler: complex case.\n");
2838 for (i = 0; i < t->n_headers_out; i++) {
2839 struct header_out_runtime *h = &t->headers_out[i];
2841 memcpy(&t->header_out_storage[offset], h->ptr, h->n_bytes);
2842 offset += h->n_bytes;
2846 memcpy(t->ptr - offset, t->header_out_storage, offset);
2847 t->pkt.offset -= offset;
2848 t->pkt.length += offset;
2853 instr_tx_exec(struct rte_swx_pipeline *p);
2856 instr_tx_exec(struct rte_swx_pipeline *p)
2858 struct thread *t = &p->threads[p->thread_id];
2859 struct instruction *ip = t->ip;
2860 uint64_t port_id = METADATA_READ(t, ip->io.io.offset, ip->io.io.n_bits);
2861 struct port_out_runtime *port = &p->out[port_id];
2862 struct rte_swx_pkt *pkt = &t->pkt;
2864 TRACE("[Thread %2u]: tx 1 pkt to port %u\n",
2872 port->pkt_tx(port->obj, pkt);
2875 thread_ip_reset(p, t);
2880 instr_tx_i_exec(struct rte_swx_pipeline *p)
2882 struct thread *t = &p->threads[p->thread_id];
2883 struct instruction *ip = t->ip;
2884 uint64_t port_id = ip->io.io.val;
2885 struct port_out_runtime *port = &p->out[port_id];
2886 struct rte_swx_pkt *pkt = &t->pkt;
2888 TRACE("[Thread %2u]: tx (i) 1 pkt to port %u\n",
2896 port->pkt_tx(port->obj, pkt);
2899 thread_ip_reset(p, t);
2907 instr_hdr_extract_translate(struct rte_swx_pipeline *p,
2908 struct action *action,
2911 struct instruction *instr,
2912 struct instruction_data *data __rte_unused)
2916 CHECK(!action, EINVAL);
2917 CHECK(n_tokens == 2, EINVAL);
2919 h = header_parse(p, tokens[1]);
2922 instr->type = INSTR_HDR_EXTRACT;
2923 instr->io.hdr.header_id[0] = h->id;
2924 instr->io.hdr.struct_id[0] = h->struct_id;
2925 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
2930 __instr_hdr_extract_exec(struct rte_swx_pipeline *p, uint32_t n_extract);
2933 __instr_hdr_extract_exec(struct rte_swx_pipeline *p, uint32_t n_extract)
2935 struct thread *t = &p->threads[p->thread_id];
2936 struct instruction *ip = t->ip;
2937 uint64_t valid_headers = t->valid_headers;
2938 uint8_t *ptr = t->ptr;
2939 uint32_t offset = t->pkt.offset;
2940 uint32_t length = t->pkt.length;
2943 for (i = 0; i < n_extract; i++) {
2944 uint32_t header_id = ip->io.hdr.header_id[i];
2945 uint32_t struct_id = ip->io.hdr.struct_id[i];
2946 uint32_t n_bytes = ip->io.hdr.n_bytes[i];
2948 TRACE("[Thread %2u]: extract header %u (%u bytes)\n",
2954 t->structs[struct_id] = ptr;
2955 valid_headers = MASK64_BIT_SET(valid_headers, header_id);
2964 t->valid_headers = valid_headers;
2967 t->pkt.offset = offset;
2968 t->pkt.length = length;
2973 instr_hdr_extract_exec(struct rte_swx_pipeline *p)
2975 __instr_hdr_extract_exec(p, 1);
2982 instr_hdr_extract2_exec(struct rte_swx_pipeline *p)
2984 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n",
2987 __instr_hdr_extract_exec(p, 2);
2994 instr_hdr_extract3_exec(struct rte_swx_pipeline *p)
2996 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n",
2999 __instr_hdr_extract_exec(p, 3);
3006 instr_hdr_extract4_exec(struct rte_swx_pipeline *p)
3008 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n",
3011 __instr_hdr_extract_exec(p, 4);
3018 instr_hdr_extract5_exec(struct rte_swx_pipeline *p)
3020 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n",
3023 __instr_hdr_extract_exec(p, 5);
3030 instr_hdr_extract6_exec(struct rte_swx_pipeline *p)
3032 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n",
3035 __instr_hdr_extract_exec(p, 6);
3042 instr_hdr_extract7_exec(struct rte_swx_pipeline *p)
3044 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n",
3047 __instr_hdr_extract_exec(p, 7);
3054 instr_hdr_extract8_exec(struct rte_swx_pipeline *p)
3056 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n",
3059 __instr_hdr_extract_exec(p, 8);
3069 instr_hdr_emit_translate(struct rte_swx_pipeline *p,
3070 struct action *action __rte_unused,
3073 struct instruction *instr,
3074 struct instruction_data *data __rte_unused)
3078 CHECK(n_tokens == 2, EINVAL);
3080 h = header_parse(p, tokens[1]);
3083 instr->type = INSTR_HDR_EMIT;
3084 instr->io.hdr.header_id[0] = h->id;
3085 instr->io.hdr.struct_id[0] = h->struct_id;
3086 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
3091 __instr_hdr_emit_exec(struct rte_swx_pipeline *p, uint32_t n_emit);
3094 __instr_hdr_emit_exec(struct rte_swx_pipeline *p, uint32_t n_emit)
3096 struct thread *t = &p->threads[p->thread_id];
3097 struct instruction *ip = t->ip;
3098 uint32_t n_headers_out = t->n_headers_out;
3099 struct header_out_runtime *ho = &t->headers_out[n_headers_out - 1];
3100 uint8_t *ho_ptr = NULL;
3101 uint32_t ho_nbytes = 0, i;
3103 for (i = 0; i < n_emit; i++) {
3104 uint32_t header_id = ip->io.hdr.header_id[i];
3105 uint32_t struct_id = ip->io.hdr.struct_id[i];
3106 uint32_t n_bytes = ip->io.hdr.n_bytes[i];
3108 struct header_runtime *hi = &t->headers[header_id];
3109 uint8_t *hi_ptr = t->structs[struct_id];
3111 TRACE("[Thread %2u]: emit header %u\n",
3117 if (!t->n_headers_out) {
3118 ho = &t->headers_out[0];
3120 ho->ptr0 = hi->ptr0;
3124 ho_nbytes = n_bytes;
3131 ho_nbytes = ho->n_bytes;
3135 if (ho_ptr + ho_nbytes == hi_ptr) {
3136 ho_nbytes += n_bytes;
3138 ho->n_bytes = ho_nbytes;
3141 ho->ptr0 = hi->ptr0;
3145 ho_nbytes = n_bytes;
3151 ho->n_bytes = ho_nbytes;
3152 t->n_headers_out = n_headers_out;
3156 instr_hdr_emit_exec(struct rte_swx_pipeline *p)
3158 __instr_hdr_emit_exec(p, 1);
3165 instr_hdr_emit_tx_exec(struct rte_swx_pipeline *p)
3167 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n",
3170 __instr_hdr_emit_exec(p, 1);
3175 instr_hdr_emit2_tx_exec(struct rte_swx_pipeline *p)
3177 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n",
3180 __instr_hdr_emit_exec(p, 2);
3185 instr_hdr_emit3_tx_exec(struct rte_swx_pipeline *p)
3187 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n",
3190 __instr_hdr_emit_exec(p, 3);
3195 instr_hdr_emit4_tx_exec(struct rte_swx_pipeline *p)
3197 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n",
3200 __instr_hdr_emit_exec(p, 4);
3205 instr_hdr_emit5_tx_exec(struct rte_swx_pipeline *p)
3207 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n",
3210 __instr_hdr_emit_exec(p, 5);
3215 instr_hdr_emit6_tx_exec(struct rte_swx_pipeline *p)
3217 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n",
3220 __instr_hdr_emit_exec(p, 6);
3225 instr_hdr_emit7_tx_exec(struct rte_swx_pipeline *p)
3227 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n",
3230 __instr_hdr_emit_exec(p, 7);
3235 instr_hdr_emit8_tx_exec(struct rte_swx_pipeline *p)
3237 TRACE("[Thread %2u] *** The next 9 instructions are fused. ***\n",
3240 __instr_hdr_emit_exec(p, 8);
3248 instr_hdr_validate_translate(struct rte_swx_pipeline *p,
3249 struct action *action __rte_unused,
3252 struct instruction *instr,
3253 struct instruction_data *data __rte_unused)
3257 CHECK(n_tokens == 2, EINVAL);
3259 h = header_parse(p, tokens[1]);
3262 instr->type = INSTR_HDR_VALIDATE;
3263 instr->valid.header_id = h->id;
3268 instr_hdr_validate_exec(struct rte_swx_pipeline *p)
3270 struct thread *t = &p->threads[p->thread_id];
3271 struct instruction *ip = t->ip;
3272 uint32_t header_id = ip->valid.header_id;
3274 TRACE("[Thread %2u] validate header %u\n", p->thread_id, header_id);
3277 t->valid_headers = MASK64_BIT_SET(t->valid_headers, header_id);
3287 instr_hdr_invalidate_translate(struct rte_swx_pipeline *p,
3288 struct action *action __rte_unused,
3291 struct instruction *instr,
3292 struct instruction_data *data __rte_unused)
3296 CHECK(n_tokens == 2, EINVAL);
3298 h = header_parse(p, tokens[1]);
3301 instr->type = INSTR_HDR_INVALIDATE;
3302 instr->valid.header_id = h->id;
3307 instr_hdr_invalidate_exec(struct rte_swx_pipeline *p)
3309 struct thread *t = &p->threads[p->thread_id];
3310 struct instruction *ip = t->ip;
3311 uint32_t header_id = ip->valid.header_id;
3313 TRACE("[Thread %2u] invalidate header %u\n", p->thread_id, header_id);
3316 t->valid_headers = MASK64_BIT_CLR(t->valid_headers, header_id);
3325 static struct table *
3326 table_find(struct rte_swx_pipeline *p, const char *name);
3329 instr_table_translate(struct rte_swx_pipeline *p,
3330 struct action *action,
3333 struct instruction *instr,
3334 struct instruction_data *data __rte_unused)
3338 CHECK(!action, EINVAL);
3339 CHECK(n_tokens == 2, EINVAL);
3341 t = table_find(p, tokens[1]);
3344 instr->type = INSTR_TABLE;
3345 instr->table.table_id = t->id;
3350 instr_table_exec(struct rte_swx_pipeline *p)
3352 struct thread *t = &p->threads[p->thread_id];
3353 struct instruction *ip = t->ip;
3354 uint32_t table_id = ip->table.table_id;
3355 struct rte_swx_table_state *ts = &t->table_state[table_id];
3356 struct table_runtime *table = &t->tables[table_id];
3358 uint8_t *action_data;
3362 done = table->func(ts->obj,
3370 TRACE("[Thread %2u] table %u (not finalized)\n",
3378 action_id = hit ? action_id : ts->default_action_id;
3379 action_data = hit ? action_data : ts->default_action_data;
3381 TRACE("[Thread %2u] table %u (%s, action %u)\n",
3384 hit ? "hit" : "miss",
3385 (uint32_t)action_id);
3387 t->action_id = action_id;
3388 t->structs[0] = action_data;
3392 thread_ip_action_call(p, t, action_id);
3399 instr_extern_translate(struct rte_swx_pipeline *p,
3400 struct action *action __rte_unused,
3403 struct instruction *instr,
3404 struct instruction_data *data __rte_unused)
3406 char *token = tokens[1];
3408 CHECK(n_tokens == 2, EINVAL);
3410 if (token[0] == 'e') {
3411 struct extern_obj *obj;
3412 struct extern_type_member_func *func;
3414 func = extern_obj_member_func_parse(p, token, &obj);
3415 CHECK(func, EINVAL);
3417 instr->type = INSTR_EXTERN_OBJ;
3418 instr->ext_obj.ext_obj_id = obj->id;
3419 instr->ext_obj.func_id = func->id;
3424 if (token[0] == 'f') {
3425 struct extern_func *func;
3427 func = extern_func_parse(p, token);
3428 CHECK(func, EINVAL);
3430 instr->type = INSTR_EXTERN_FUNC;
3431 instr->ext_func.ext_func_id = func->id;
3440 instr_extern_obj_exec(struct rte_swx_pipeline *p)
3442 struct thread *t = &p->threads[p->thread_id];
3443 struct instruction *ip = t->ip;
3444 uint32_t obj_id = ip->ext_obj.ext_obj_id;
3445 uint32_t func_id = ip->ext_obj.func_id;
3446 struct extern_obj_runtime *obj = &t->extern_objs[obj_id];
3447 rte_swx_extern_type_member_func_t func = obj->funcs[func_id];
3449 TRACE("[Thread %2u] extern obj %u member func %u\n",
3454 /* Extern object member function execute. */
3455 uint32_t done = func(obj->obj, obj->mailbox);
3458 thread_ip_inc_cond(t, done);
3459 thread_yield_cond(p, done ^ 1);
3463 instr_extern_func_exec(struct rte_swx_pipeline *p)
3465 struct thread *t = &p->threads[p->thread_id];
3466 struct instruction *ip = t->ip;
3467 uint32_t ext_func_id = ip->ext_func.ext_func_id;
3468 struct extern_func_runtime *ext_func = &t->extern_funcs[ext_func_id];
3469 rte_swx_extern_func_t func = ext_func->func;
3471 TRACE("[Thread %2u] extern func %u\n",
3475 /* Extern function execute. */
3476 uint32_t done = func(ext_func->mailbox);
3479 thread_ip_inc_cond(t, done);
3480 thread_yield_cond(p, done ^ 1);
3487 instr_mov_translate(struct rte_swx_pipeline *p,
3488 struct action *action,
3491 struct instruction *instr,
3492 struct instruction_data *data __rte_unused)
3494 char *dst = tokens[1], *src = tokens[2];
3495 struct field *fdst, *fsrc;
3497 uint32_t dst_struct_id, src_struct_id;
3499 CHECK(n_tokens == 3, EINVAL);
3501 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3502 CHECK(fdst, EINVAL);
3505 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3507 instr->type = INSTR_MOV;
3508 if ((dst[0] == 'h' && src[0] != 'h') ||
3509 (dst[0] != 'h' && src[0] == 'h'))
3510 instr->type = INSTR_MOV_S;
3512 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
3513 instr->mov.dst.n_bits = fdst->n_bits;
3514 instr->mov.dst.offset = fdst->offset / 8;
3515 instr->mov.src.struct_id = (uint8_t)src_struct_id;
3516 instr->mov.src.n_bits = fsrc->n_bits;
3517 instr->mov.src.offset = fsrc->offset / 8;
3522 src_val = strtoull(src, &src, 0);
3523 CHECK(!src[0], EINVAL);
3526 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3528 instr->type = INSTR_MOV_I;
3529 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
3530 instr->mov.dst.n_bits = fdst->n_bits;
3531 instr->mov.dst.offset = fdst->offset / 8;
3532 instr->mov.src_val = src_val;
3537 instr_mov_exec(struct rte_swx_pipeline *p)
3539 struct thread *t = &p->threads[p->thread_id];
3540 struct instruction *ip = t->ip;
3542 TRACE("[Thread %2u] mov\n",
3552 instr_mov_s_exec(struct rte_swx_pipeline *p)
3554 struct thread *t = &p->threads[p->thread_id];
3555 struct instruction *ip = t->ip;
3557 TRACE("[Thread %2u] mov (s)\n",
3567 instr_mov_i_exec(struct rte_swx_pipeline *p)
3569 struct thread *t = &p->threads[p->thread_id];
3570 struct instruction *ip = t->ip;
3572 TRACE("[Thread %2u] mov m.f %" PRIx64 "\n",
3586 instr_dma_translate(struct rte_swx_pipeline *p,
3587 struct action *action,
3590 struct instruction *instr,
3591 struct instruction_data *data __rte_unused)
3593 char *dst = tokens[1];
3594 char *src = tokens[2];
3598 CHECK(action, EINVAL);
3599 CHECK(n_tokens == 3, EINVAL);
3601 h = header_parse(p, dst);
3604 tf = action_field_parse(action, src);
3607 instr->type = INSTR_DMA_HT;
3608 instr->dma.dst.header_id[0] = h->id;
3609 instr->dma.dst.struct_id[0] = h->struct_id;
3610 instr->dma.n_bytes[0] = h->st->n_bits / 8;
3611 instr->dma.src.offset[0] = tf->offset / 8;
3617 __instr_dma_ht_exec(struct rte_swx_pipeline *p, uint32_t n_dma);
3620 __instr_dma_ht_exec(struct rte_swx_pipeline *p, uint32_t n_dma)
3622 struct thread *t = &p->threads[p->thread_id];
3623 struct instruction *ip = t->ip;
3624 uint8_t *action_data = t->structs[0];
3625 uint64_t valid_headers = t->valid_headers;
3628 for (i = 0; i < n_dma; i++) {
3629 uint32_t header_id = ip->dma.dst.header_id[i];
3630 uint32_t struct_id = ip->dma.dst.struct_id[i];
3631 uint32_t offset = ip->dma.src.offset[i];
3632 uint32_t n_bytes = ip->dma.n_bytes[i];
3634 struct header_runtime *h = &t->headers[header_id];
3635 uint8_t *h_ptr0 = h->ptr0;
3636 uint8_t *h_ptr = t->structs[struct_id];
3638 void *dst = MASK64_BIT_GET(valid_headers, header_id) ?
3640 void *src = &action_data[offset];
3642 TRACE("[Thread %2u] dma h.s t.f\n", p->thread_id);
3645 memcpy(dst, src, n_bytes);
3646 t->structs[struct_id] = dst;
3647 valid_headers = MASK64_BIT_SET(valid_headers, header_id);
3650 t->valid_headers = valid_headers;
3654 instr_dma_ht_exec(struct rte_swx_pipeline *p)
3656 __instr_dma_ht_exec(p, 1);
3663 instr_dma_ht2_exec(struct rte_swx_pipeline *p)
3665 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n",
3668 __instr_dma_ht_exec(p, 2);
3675 instr_dma_ht3_exec(struct rte_swx_pipeline *p)
3677 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n",
3680 __instr_dma_ht_exec(p, 3);
3687 instr_dma_ht4_exec(struct rte_swx_pipeline *p)
3689 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n",
3692 __instr_dma_ht_exec(p, 4);
3699 instr_dma_ht5_exec(struct rte_swx_pipeline *p)
3701 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n",
3704 __instr_dma_ht_exec(p, 5);
3711 instr_dma_ht6_exec(struct rte_swx_pipeline *p)
3713 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n",
3716 __instr_dma_ht_exec(p, 6);
3723 instr_dma_ht7_exec(struct rte_swx_pipeline *p)
3725 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n",
3728 __instr_dma_ht_exec(p, 7);
3735 instr_dma_ht8_exec(struct rte_swx_pipeline *p)
3737 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n",
3740 __instr_dma_ht_exec(p, 8);
3750 instr_alu_add_translate(struct rte_swx_pipeline *p,
3751 struct action *action,
3754 struct instruction *instr,
3755 struct instruction_data *data __rte_unused)
3757 char *dst = tokens[1], *src = tokens[2];
3758 struct field *fdst, *fsrc;
3760 uint32_t dst_struct_id, src_struct_id;
3762 CHECK(n_tokens == 3, EINVAL);
3764 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3765 CHECK(fdst, EINVAL);
3767 /* ADD, ADD_HM, ADD_MH, ADD_HH. */
3768 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3770 instr->type = INSTR_ALU_ADD;
3771 if (dst[0] == 'h' && src[0] != 'h')
3772 instr->type = INSTR_ALU_ADD_HM;
3773 if (dst[0] != 'h' && src[0] == 'h')
3774 instr->type = INSTR_ALU_ADD_MH;
3775 if (dst[0] == 'h' && src[0] == 'h')
3776 instr->type = INSTR_ALU_ADD_HH;
3778 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3779 instr->alu.dst.n_bits = fdst->n_bits;
3780 instr->alu.dst.offset = fdst->offset / 8;
3781 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3782 instr->alu.src.n_bits = fsrc->n_bits;
3783 instr->alu.src.offset = fsrc->offset / 8;
3787 /* ADD_MI, ADD_HI. */
3788 src_val = strtoull(src, &src, 0);
3789 CHECK(!src[0], EINVAL);
3791 instr->type = INSTR_ALU_ADD_MI;
3793 instr->type = INSTR_ALU_ADD_HI;
3795 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3796 instr->alu.dst.n_bits = fdst->n_bits;
3797 instr->alu.dst.offset = fdst->offset / 8;
3798 instr->alu.src_val = src_val;
3803 instr_alu_sub_translate(struct rte_swx_pipeline *p,
3804 struct action *action,
3807 struct instruction *instr,
3808 struct instruction_data *data __rte_unused)
3810 char *dst = tokens[1], *src = tokens[2];
3811 struct field *fdst, *fsrc;
3813 uint32_t dst_struct_id, src_struct_id;
3815 CHECK(n_tokens == 3, EINVAL);
3817 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3818 CHECK(fdst, EINVAL);
3820 /* SUB, SUB_HM, SUB_MH, SUB_HH. */
3821 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3823 instr->type = INSTR_ALU_SUB;
3824 if (dst[0] == 'h' && src[0] != 'h')
3825 instr->type = INSTR_ALU_SUB_HM;
3826 if (dst[0] != 'h' && src[0] == 'h')
3827 instr->type = INSTR_ALU_SUB_MH;
3828 if (dst[0] == 'h' && src[0] == 'h')
3829 instr->type = INSTR_ALU_SUB_HH;
3831 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3832 instr->alu.dst.n_bits = fdst->n_bits;
3833 instr->alu.dst.offset = fdst->offset / 8;
3834 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3835 instr->alu.src.n_bits = fsrc->n_bits;
3836 instr->alu.src.offset = fsrc->offset / 8;
3840 /* SUB_MI, SUB_HI. */
3841 src_val = strtoull(src, &src, 0);
3842 CHECK(!src[0], EINVAL);
3844 instr->type = INSTR_ALU_SUB_MI;
3846 instr->type = INSTR_ALU_SUB_HI;
3848 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3849 instr->alu.dst.n_bits = fdst->n_bits;
3850 instr->alu.dst.offset = fdst->offset / 8;
3851 instr->alu.src_val = src_val;
3856 instr_alu_ckadd_translate(struct rte_swx_pipeline *p,
3857 struct action *action __rte_unused,
3860 struct instruction *instr,
3861 struct instruction_data *data __rte_unused)
3863 char *dst = tokens[1], *src = tokens[2];
3864 struct header *hdst, *hsrc;
3865 struct field *fdst, *fsrc;
3867 CHECK(n_tokens == 3, EINVAL);
3869 fdst = header_field_parse(p, dst, &hdst);
3870 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
3873 fsrc = header_field_parse(p, src, &hsrc);
3875 instr->type = INSTR_ALU_CKADD_FIELD;
3876 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
3877 instr->alu.dst.n_bits = fdst->n_bits;
3878 instr->alu.dst.offset = fdst->offset / 8;
3879 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
3880 instr->alu.src.n_bits = fsrc->n_bits;
3881 instr->alu.src.offset = fsrc->offset / 8;
3885 /* CKADD_STRUCT, CKADD_STRUCT20. */
3886 hsrc = header_parse(p, src);
3887 CHECK(hsrc, EINVAL);
3889 instr->type = INSTR_ALU_CKADD_STRUCT;
3890 if ((hsrc->st->n_bits / 8) == 20)
3891 instr->type = INSTR_ALU_CKADD_STRUCT20;
3893 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
3894 instr->alu.dst.n_bits = fdst->n_bits;
3895 instr->alu.dst.offset = fdst->offset / 8;
3896 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
3897 instr->alu.src.n_bits = hsrc->st->n_bits;
3898 instr->alu.src.offset = 0; /* Unused. */
3903 instr_alu_cksub_translate(struct rte_swx_pipeline *p,
3904 struct action *action __rte_unused,
3907 struct instruction *instr,
3908 struct instruction_data *data __rte_unused)
3910 char *dst = tokens[1], *src = tokens[2];
3911 struct header *hdst, *hsrc;
3912 struct field *fdst, *fsrc;
3914 CHECK(n_tokens == 3, EINVAL);
3916 fdst = header_field_parse(p, dst, &hdst);
3917 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
3919 fsrc = header_field_parse(p, src, &hsrc);
3920 CHECK(fsrc, EINVAL);
3922 instr->type = INSTR_ALU_CKSUB_FIELD;
3923 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
3924 instr->alu.dst.n_bits = fdst->n_bits;
3925 instr->alu.dst.offset = fdst->offset / 8;
3926 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
3927 instr->alu.src.n_bits = fsrc->n_bits;
3928 instr->alu.src.offset = fsrc->offset / 8;
3933 instr_alu_shl_translate(struct rte_swx_pipeline *p,
3934 struct action *action,
3937 struct instruction *instr,
3938 struct instruction_data *data __rte_unused)
3940 char *dst = tokens[1], *src = tokens[2];
3941 struct field *fdst, *fsrc;
3943 uint32_t dst_struct_id, src_struct_id;
3945 CHECK(n_tokens == 3, EINVAL);
3947 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3948 CHECK(fdst, EINVAL);
3950 /* SHL, SHL_HM, SHL_MH, SHL_HH. */
3951 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3953 instr->type = INSTR_ALU_SHL;
3954 if (dst[0] == 'h' && src[0] != 'h')
3955 instr->type = INSTR_ALU_SHL_HM;
3956 if (dst[0] != 'h' && src[0] == 'h')
3957 instr->type = INSTR_ALU_SHL_MH;
3958 if (dst[0] == 'h' && src[0] == 'h')
3959 instr->type = INSTR_ALU_SHL_HH;
3961 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3962 instr->alu.dst.n_bits = fdst->n_bits;
3963 instr->alu.dst.offset = fdst->offset / 8;
3964 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3965 instr->alu.src.n_bits = fsrc->n_bits;
3966 instr->alu.src.offset = fsrc->offset / 8;
3970 /* SHL_MI, SHL_HI. */
3971 src_val = strtoull(src, &src, 0);
3972 CHECK(!src[0], EINVAL);
3974 instr->type = INSTR_ALU_SHL_MI;
3976 instr->type = INSTR_ALU_SHL_HI;
3978 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3979 instr->alu.dst.n_bits = fdst->n_bits;
3980 instr->alu.dst.offset = fdst->offset / 8;
3981 instr->alu.src_val = src_val;
3986 instr_alu_shr_translate(struct rte_swx_pipeline *p,
3987 struct action *action,
3990 struct instruction *instr,
3991 struct instruction_data *data __rte_unused)
3993 char *dst = tokens[1], *src = tokens[2];
3994 struct field *fdst, *fsrc;
3996 uint32_t dst_struct_id, src_struct_id;
3998 CHECK(n_tokens == 3, EINVAL);
4000 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4001 CHECK(fdst, EINVAL);
4003 /* SHR, SHR_HM, SHR_MH, SHR_HH. */
4004 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4006 instr->type = INSTR_ALU_SHR;
4007 if (dst[0] == 'h' && src[0] != 'h')
4008 instr->type = INSTR_ALU_SHR_HM;
4009 if (dst[0] != 'h' && src[0] == 'h')
4010 instr->type = INSTR_ALU_SHR_MH;
4011 if (dst[0] == 'h' && src[0] == 'h')
4012 instr->type = INSTR_ALU_SHR_HH;
4014 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4015 instr->alu.dst.n_bits = fdst->n_bits;
4016 instr->alu.dst.offset = fdst->offset / 8;
4017 instr->alu.src.struct_id = (uint8_t)src_struct_id;
4018 instr->alu.src.n_bits = fsrc->n_bits;
4019 instr->alu.src.offset = fsrc->offset / 8;
4023 /* SHR_MI, SHR_HI. */
4024 src_val = strtoull(src, &src, 0);
4025 CHECK(!src[0], EINVAL);
4027 instr->type = INSTR_ALU_SHR_MI;
4029 instr->type = INSTR_ALU_SHR_HI;
4031 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4032 instr->alu.dst.n_bits = fdst->n_bits;
4033 instr->alu.dst.offset = fdst->offset / 8;
4034 instr->alu.src_val = src_val;
4039 instr_alu_and_translate(struct rte_swx_pipeline *p,
4040 struct action *action,
4043 struct instruction *instr,
4044 struct instruction_data *data __rte_unused)
4046 char *dst = tokens[1], *src = tokens[2];
4047 struct field *fdst, *fsrc;
4049 uint32_t dst_struct_id, src_struct_id;
4051 CHECK(n_tokens == 3, EINVAL);
4053 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4054 CHECK(fdst, EINVAL);
4057 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4059 instr->type = INSTR_ALU_AND;
4060 if ((dst[0] == 'h' && src[0] != 'h') ||
4061 (dst[0] != 'h' && src[0] == 'h'))
4062 instr->type = INSTR_ALU_AND_S;
4064 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4065 instr->alu.dst.n_bits = fdst->n_bits;
4066 instr->alu.dst.offset = fdst->offset / 8;
4067 instr->alu.src.struct_id = (uint8_t)src_struct_id;
4068 instr->alu.src.n_bits = fsrc->n_bits;
4069 instr->alu.src.offset = fsrc->offset / 8;
4074 src_val = strtoull(src, &src, 0);
4075 CHECK(!src[0], EINVAL);
4078 src_val = hton64(src_val) >> (64 - fdst->n_bits);
4080 instr->type = INSTR_ALU_AND_I;
4081 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4082 instr->alu.dst.n_bits = fdst->n_bits;
4083 instr->alu.dst.offset = fdst->offset / 8;
4084 instr->alu.src_val = src_val;
4089 instr_alu_or_translate(struct rte_swx_pipeline *p,
4090 struct action *action,
4093 struct instruction *instr,
4094 struct instruction_data *data __rte_unused)
4096 char *dst = tokens[1], *src = tokens[2];
4097 struct field *fdst, *fsrc;
4099 uint32_t dst_struct_id, src_struct_id;
4101 CHECK(n_tokens == 3, EINVAL);
4103 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4104 CHECK(fdst, EINVAL);
4107 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4109 instr->type = INSTR_ALU_OR;
4110 if ((dst[0] == 'h' && src[0] != 'h') ||
4111 (dst[0] != 'h' && src[0] == 'h'))
4112 instr->type = INSTR_ALU_OR_S;
4114 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4115 instr->alu.dst.n_bits = fdst->n_bits;
4116 instr->alu.dst.offset = fdst->offset / 8;
4117 instr->alu.src.struct_id = (uint8_t)src_struct_id;
4118 instr->alu.src.n_bits = fsrc->n_bits;
4119 instr->alu.src.offset = fsrc->offset / 8;
4124 src_val = strtoull(src, &src, 0);
4125 CHECK(!src[0], EINVAL);
4128 src_val = hton64(src_val) >> (64 - fdst->n_bits);
4130 instr->type = INSTR_ALU_OR_I;
4131 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4132 instr->alu.dst.n_bits = fdst->n_bits;
4133 instr->alu.dst.offset = fdst->offset / 8;
4134 instr->alu.src_val = src_val;
4139 instr_alu_xor_translate(struct rte_swx_pipeline *p,
4140 struct action *action,
4143 struct instruction *instr,
4144 struct instruction_data *data __rte_unused)
4146 char *dst = tokens[1], *src = tokens[2];
4147 struct field *fdst, *fsrc;
4149 uint32_t dst_struct_id, src_struct_id;
4151 CHECK(n_tokens == 3, EINVAL);
4153 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4154 CHECK(fdst, EINVAL);
4157 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4159 instr->type = INSTR_ALU_XOR;
4160 if ((dst[0] == 'h' && src[0] != 'h') ||
4161 (dst[0] != 'h' && src[0] == 'h'))
4162 instr->type = INSTR_ALU_XOR_S;
4164 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4165 instr->alu.dst.n_bits = fdst->n_bits;
4166 instr->alu.dst.offset = fdst->offset / 8;
4167 instr->alu.src.struct_id = (uint8_t)src_struct_id;
4168 instr->alu.src.n_bits = fsrc->n_bits;
4169 instr->alu.src.offset = fsrc->offset / 8;
4174 src_val = strtoull(src, &src, 0);
4175 CHECK(!src[0], EINVAL);
4178 src_val = hton64(src_val) >> (64 - fdst->n_bits);
4180 instr->type = INSTR_ALU_XOR_I;
4181 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4182 instr->alu.dst.n_bits = fdst->n_bits;
4183 instr->alu.dst.offset = fdst->offset / 8;
4184 instr->alu.src_val = src_val;
4189 instr_alu_add_exec(struct rte_swx_pipeline *p)
4191 struct thread *t = &p->threads[p->thread_id];
4192 struct instruction *ip = t->ip;
4194 TRACE("[Thread %2u] add\n", p->thread_id);
4204 instr_alu_add_mh_exec(struct rte_swx_pipeline *p)
4206 struct thread *t = &p->threads[p->thread_id];
4207 struct instruction *ip = t->ip;
4209 TRACE("[Thread %2u] add (mh)\n", p->thread_id);
4219 instr_alu_add_hm_exec(struct rte_swx_pipeline *p)
4221 struct thread *t = &p->threads[p->thread_id];
4222 struct instruction *ip = t->ip;
4224 TRACE("[Thread %2u] add (hm)\n", p->thread_id);
4234 instr_alu_add_hh_exec(struct rte_swx_pipeline *p)
4236 struct thread *t = &p->threads[p->thread_id];
4237 struct instruction *ip = t->ip;
4239 TRACE("[Thread %2u] add (hh)\n", p->thread_id);
4249 instr_alu_add_mi_exec(struct rte_swx_pipeline *p)
4251 struct thread *t = &p->threads[p->thread_id];
4252 struct instruction *ip = t->ip;
4254 TRACE("[Thread %2u] add (mi)\n", p->thread_id);
4264 instr_alu_add_hi_exec(struct rte_swx_pipeline *p)
4266 struct thread *t = &p->threads[p->thread_id];
4267 struct instruction *ip = t->ip;
4269 TRACE("[Thread %2u] add (hi)\n", p->thread_id);
4279 instr_alu_sub_exec(struct rte_swx_pipeline *p)
4281 struct thread *t = &p->threads[p->thread_id];
4282 struct instruction *ip = t->ip;
4284 TRACE("[Thread %2u] sub\n", p->thread_id);
4294 instr_alu_sub_mh_exec(struct rte_swx_pipeline *p)
4296 struct thread *t = &p->threads[p->thread_id];
4297 struct instruction *ip = t->ip;
4299 TRACE("[Thread %2u] sub (mh)\n", p->thread_id);
4309 instr_alu_sub_hm_exec(struct rte_swx_pipeline *p)
4311 struct thread *t = &p->threads[p->thread_id];
4312 struct instruction *ip = t->ip;
4314 TRACE("[Thread %2u] sub (hm)\n", p->thread_id);
4324 instr_alu_sub_hh_exec(struct rte_swx_pipeline *p)
4326 struct thread *t = &p->threads[p->thread_id];
4327 struct instruction *ip = t->ip;
4329 TRACE("[Thread %2u] sub (hh)\n", p->thread_id);
4339 instr_alu_sub_mi_exec(struct rte_swx_pipeline *p)
4341 struct thread *t = &p->threads[p->thread_id];
4342 struct instruction *ip = t->ip;
4344 TRACE("[Thread %2u] sub (mi)\n", p->thread_id);
4354 instr_alu_sub_hi_exec(struct rte_swx_pipeline *p)
4356 struct thread *t = &p->threads[p->thread_id];
4357 struct instruction *ip = t->ip;
4359 TRACE("[Thread %2u] sub (hi)\n", p->thread_id);
4369 instr_alu_shl_exec(struct rte_swx_pipeline *p)
4371 struct thread *t = &p->threads[p->thread_id];
4372 struct instruction *ip = t->ip;
4374 TRACE("[Thread %2u] shl\n", p->thread_id);
4384 instr_alu_shl_mh_exec(struct rte_swx_pipeline *p)
4386 struct thread *t = &p->threads[p->thread_id];
4387 struct instruction *ip = t->ip;
4389 TRACE("[Thread %2u] shl (mh)\n", p->thread_id);
4399 instr_alu_shl_hm_exec(struct rte_swx_pipeline *p)
4401 struct thread *t = &p->threads[p->thread_id];
4402 struct instruction *ip = t->ip;
4404 TRACE("[Thread %2u] shl (hm)\n", p->thread_id);
4414 instr_alu_shl_hh_exec(struct rte_swx_pipeline *p)
4416 struct thread *t = &p->threads[p->thread_id];
4417 struct instruction *ip = t->ip;
4419 TRACE("[Thread %2u] shl (hh)\n", p->thread_id);
4429 instr_alu_shl_mi_exec(struct rte_swx_pipeline *p)
4431 struct thread *t = &p->threads[p->thread_id];
4432 struct instruction *ip = t->ip;
4434 TRACE("[Thread %2u] shl (mi)\n", p->thread_id);
4444 instr_alu_shl_hi_exec(struct rte_swx_pipeline *p)
4446 struct thread *t = &p->threads[p->thread_id];
4447 struct instruction *ip = t->ip;
4449 TRACE("[Thread %2u] shl (hi)\n", p->thread_id);
4459 instr_alu_shr_exec(struct rte_swx_pipeline *p)
4461 struct thread *t = &p->threads[p->thread_id];
4462 struct instruction *ip = t->ip;
4464 TRACE("[Thread %2u] shr\n", p->thread_id);
4474 instr_alu_shr_mh_exec(struct rte_swx_pipeline *p)
4476 struct thread *t = &p->threads[p->thread_id];
4477 struct instruction *ip = t->ip;
4479 TRACE("[Thread %2u] shr (mh)\n", p->thread_id);
4489 instr_alu_shr_hm_exec(struct rte_swx_pipeline *p)
4491 struct thread *t = &p->threads[p->thread_id];
4492 struct instruction *ip = t->ip;
4494 TRACE("[Thread %2u] shr (hm)\n", p->thread_id);
4504 instr_alu_shr_hh_exec(struct rte_swx_pipeline *p)
4506 struct thread *t = &p->threads[p->thread_id];
4507 struct instruction *ip = t->ip;
4509 TRACE("[Thread %2u] shr (hh)\n", p->thread_id);
4519 instr_alu_shr_mi_exec(struct rte_swx_pipeline *p)
4521 struct thread *t = &p->threads[p->thread_id];
4522 struct instruction *ip = t->ip;
4524 TRACE("[Thread %2u] shr (mi)\n", p->thread_id);
4534 instr_alu_shr_hi_exec(struct rte_swx_pipeline *p)
4536 struct thread *t = &p->threads[p->thread_id];
4537 struct instruction *ip = t->ip;
4539 TRACE("[Thread %2u] shr (hi)\n", p->thread_id);
4549 instr_alu_and_exec(struct rte_swx_pipeline *p)
4551 struct thread *t = &p->threads[p->thread_id];
4552 struct instruction *ip = t->ip;
4554 TRACE("[Thread %2u] and\n", p->thread_id);
4564 instr_alu_and_s_exec(struct rte_swx_pipeline *p)
4566 struct thread *t = &p->threads[p->thread_id];
4567 struct instruction *ip = t->ip;
4569 TRACE("[Thread %2u] and (s)\n", p->thread_id);
4579 instr_alu_and_i_exec(struct rte_swx_pipeline *p)
4581 struct thread *t = &p->threads[p->thread_id];
4582 struct instruction *ip = t->ip;
4584 TRACE("[Thread %2u] and (i)\n", p->thread_id);
4594 instr_alu_or_exec(struct rte_swx_pipeline *p)
4596 struct thread *t = &p->threads[p->thread_id];
4597 struct instruction *ip = t->ip;
4599 TRACE("[Thread %2u] or\n", p->thread_id);
4609 instr_alu_or_s_exec(struct rte_swx_pipeline *p)
4611 struct thread *t = &p->threads[p->thread_id];
4612 struct instruction *ip = t->ip;
4614 TRACE("[Thread %2u] or (s)\n", p->thread_id);
4624 instr_alu_or_i_exec(struct rte_swx_pipeline *p)
4626 struct thread *t = &p->threads[p->thread_id];
4627 struct instruction *ip = t->ip;
4629 TRACE("[Thread %2u] or (i)\n", p->thread_id);
4639 instr_alu_xor_exec(struct rte_swx_pipeline *p)
4641 struct thread *t = &p->threads[p->thread_id];
4642 struct instruction *ip = t->ip;
4644 TRACE("[Thread %2u] xor\n", p->thread_id);
4654 instr_alu_xor_s_exec(struct rte_swx_pipeline *p)
4656 struct thread *t = &p->threads[p->thread_id];
4657 struct instruction *ip = t->ip;
4659 TRACE("[Thread %2u] xor (s)\n", p->thread_id);
4669 instr_alu_xor_i_exec(struct rte_swx_pipeline *p)
4671 struct thread *t = &p->threads[p->thread_id];
4672 struct instruction *ip = t->ip;
4674 TRACE("[Thread %2u] xor (i)\n", p->thread_id);
4684 instr_alu_ckadd_field_exec(struct rte_swx_pipeline *p)
4686 struct thread *t = &p->threads[p->thread_id];
4687 struct instruction *ip = t->ip;
4688 uint8_t *dst_struct, *src_struct;
4689 uint16_t *dst16_ptr, dst;
4690 uint64_t *src64_ptr, src64, src64_mask, src;
4693 TRACE("[Thread %2u] ckadd (field)\n", p->thread_id);
4696 dst_struct = t->structs[ip->alu.dst.struct_id];
4697 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
4700 src_struct = t->structs[ip->alu.src.struct_id];
4701 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
4703 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
4704 src = src64 & src64_mask;
4709 /* The first input (r) is a 16-bit number. The second and the third
4710 * inputs are 32-bit numbers. In the worst case scenario, the sum of the
4711 * three numbers (output r) is a 34-bit number.
4713 r += (src >> 32) + (src & 0xFFFFFFFF);
4715 /* The first input is a 16-bit number. The second input is an 18-bit
4716 * number. In the worst case scenario, the sum of the two numbers is a
4719 r = (r & 0xFFFF) + (r >> 16);
4721 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
4722 * a 3-bit number (0 .. 7). Their sum is a 17-bit number (0 .. 0x10006).
4724 r = (r & 0xFFFF) + (r >> 16);
4726 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
4727 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
4728 * 0x10006), the output r is (0 .. 7). So no carry bit can be generated,
4729 * therefore the output r is always a 16-bit number.
4731 r = (r & 0xFFFF) + (r >> 16);
4736 *dst16_ptr = (uint16_t)r;
4743 instr_alu_cksub_field_exec(struct rte_swx_pipeline *p)
4745 struct thread *t = &p->threads[p->thread_id];
4746 struct instruction *ip = t->ip;
4747 uint8_t *dst_struct, *src_struct;
4748 uint16_t *dst16_ptr, dst;
4749 uint64_t *src64_ptr, src64, src64_mask, src;
4752 TRACE("[Thread %2u] cksub (field)\n", p->thread_id);
4755 dst_struct = t->structs[ip->alu.dst.struct_id];
4756 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
4759 src_struct = t->structs[ip->alu.src.struct_id];
4760 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
4762 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
4763 src = src64 & src64_mask;
4768 /* Subtraction in 1's complement arithmetic (i.e. a '- b) is the same as
4769 * the following sequence of operations in 2's complement arithmetic:
4770 * a '- b = (a - b) % 0xFFFF.
4772 * In order to prevent an underflow for the below subtraction, in which
4773 * a 33-bit number (the subtrahend) is taken out of a 16-bit number (the
4774 * minuend), we first add a multiple of the 0xFFFF modulus to the
4775 * minuend. The number we add to the minuend needs to be a 34-bit number
4776 * or higher, so for readability reasons we picked the 36-bit multiple.
4777 * We are effectively turning the 16-bit minuend into a 36-bit number:
4778 * (a - b) % 0xFFFF = (a + 0xFFFF00000 - b) % 0xFFFF.
4780 r += 0xFFFF00000ULL; /* The output r is a 36-bit number. */
4782 /* A 33-bit number is subtracted from a 36-bit number (the input r). The
4783 * result (the output r) is a 36-bit number.
4785 r -= (src >> 32) + (src & 0xFFFFFFFF);
4787 /* The first input is a 16-bit number. The second input is a 20-bit
4788 * number. Their sum is a 21-bit number.
4790 r = (r & 0xFFFF) + (r >> 16);
4792 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
4793 * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1001E).
4795 r = (r & 0xFFFF) + (r >> 16);
4797 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
4798 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
4799 * 0x1001E), the output r is (0 .. 31). So no carry bit can be
4800 * generated, therefore the output r is always a 16-bit number.
4802 r = (r & 0xFFFF) + (r >> 16);
4807 *dst16_ptr = (uint16_t)r;
4814 instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline *p)
4816 struct thread *t = &p->threads[p->thread_id];
4817 struct instruction *ip = t->ip;
4818 uint8_t *dst_struct, *src_struct;
4819 uint16_t *dst16_ptr;
4820 uint32_t *src32_ptr;
4823 TRACE("[Thread %2u] ckadd (struct of 20 bytes)\n", p->thread_id);
4826 dst_struct = t->structs[ip->alu.dst.struct_id];
4827 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
4829 src_struct = t->structs[ip->alu.src.struct_id];
4830 src32_ptr = (uint32_t *)&src_struct[0];
4832 r0 = src32_ptr[0]; /* r0 is a 32-bit number. */
4833 r1 = src32_ptr[1]; /* r1 is a 32-bit number. */
4834 r0 += src32_ptr[2]; /* The output r0 is a 33-bit number. */
4835 r1 += src32_ptr[3]; /* The output r1 is a 33-bit number. */
4836 r0 += r1 + src32_ptr[4]; /* The output r0 is a 35-bit number. */
4838 /* The first input is a 16-bit number. The second input is a 19-bit
4839 * number. Their sum is a 20-bit number.
4841 r0 = (r0 & 0xFFFF) + (r0 >> 16);
4843 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
4844 * a 4-bit number (0 .. 15). The sum is a 17-bit number (0 .. 0x1000E).
4846 r0 = (r0 & 0xFFFF) + (r0 >> 16);
4848 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
4849 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
4850 * 0x1000E), the output r is (0 .. 15). So no carry bit can be
4851 * generated, therefore the output r is always a 16-bit number.
4853 r0 = (r0 & 0xFFFF) + (r0 >> 16);
4856 r0 = r0 ? r0 : 0xFFFF;
4858 *dst16_ptr = (uint16_t)r0;
4865 instr_alu_ckadd_struct_exec(struct rte_swx_pipeline *p)
4867 struct thread *t = &p->threads[p->thread_id];
4868 struct instruction *ip = t->ip;
4869 uint8_t *dst_struct, *src_struct;
4870 uint16_t *dst16_ptr;
4871 uint32_t *src32_ptr;
4875 TRACE("[Thread %2u] ckadd (struct)\n", p->thread_id);
4878 dst_struct = t->structs[ip->alu.dst.struct_id];
4879 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
4881 src_struct = t->structs[ip->alu.src.struct_id];
4882 src32_ptr = (uint32_t *)&src_struct[0];
4884 /* The max number of 32-bit words in a 256-byte header is 8 = 2^3.
4885 * Therefore, in the worst case scenario, a 35-bit number is added to a
4886 * 16-bit number (the input r), so the output r is 36-bit number.
4888 for (i = 0; i < ip->alu.src.n_bits / 32; i++, src32_ptr++)
4891 /* The first input is a 16-bit number. The second input is a 20-bit
4892 * number. Their sum is a 21-bit number.
4894 r = (r & 0xFFFF) + (r >> 16);
4896 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
4897 * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1000E).
4899 r = (r & 0xFFFF) + (r >> 16);
4901 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
4902 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
4903 * 0x1001E), the output r is (0 .. 31). So no carry bit can be
4904 * generated, therefore the output r is always a 16-bit number.
4906 r = (r & 0xFFFF) + (r >> 16);
4911 *dst16_ptr = (uint16_t)r;
4920 static struct regarray *
4921 regarray_find(struct rte_swx_pipeline *p, const char *name);
4924 instr_regprefetch_translate(struct rte_swx_pipeline *p,
4925 struct action *action,
4928 struct instruction *instr,
4929 struct instruction_data *data __rte_unused)
4931 char *regarray = tokens[1], *idx = tokens[2];
4934 uint32_t idx_struct_id, idx_val;
4936 CHECK(n_tokens == 3, EINVAL);
4938 r = regarray_find(p, regarray);
4941 /* REGPREFETCH_RH, REGPREFETCH_RM. */
4942 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4944 instr->type = INSTR_REGPREFETCH_RM;
4946 instr->type = INSTR_REGPREFETCH_RH;
4948 instr->regarray.regarray_id = r->id;
4949 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4950 instr->regarray.idx.n_bits = fidx->n_bits;
4951 instr->regarray.idx.offset = fidx->offset / 8;
4952 instr->regarray.dstsrc_val = 0; /* Unused. */
4956 /* REGPREFETCH_RI. */
4957 idx_val = strtoul(idx, &idx, 0);
4958 CHECK(!idx[0], EINVAL);
4960 instr->type = INSTR_REGPREFETCH_RI;
4961 instr->regarray.regarray_id = r->id;
4962 instr->regarray.idx_val = idx_val;
4963 instr->regarray.dstsrc_val = 0; /* Unused. */
4968 instr_regrd_translate(struct rte_swx_pipeline *p,
4969 struct action *action,
4972 struct instruction *instr,
4973 struct instruction_data *data __rte_unused)
4975 char *dst = tokens[1], *regarray = tokens[2], *idx = tokens[3];
4977 struct field *fdst, *fidx;
4978 uint32_t dst_struct_id, idx_struct_id, idx_val;
4980 CHECK(n_tokens == 4, EINVAL);
4982 r = regarray_find(p, regarray);
4985 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4986 CHECK(fdst, EINVAL);
4988 /* REGRD_HRH, REGRD_HRM, REGRD_MRH, REGRD_MRM. */
4989 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4991 instr->type = INSTR_REGRD_MRM;
4992 if (dst[0] == 'h' && idx[0] != 'h')
4993 instr->type = INSTR_REGRD_HRM;
4994 if (dst[0] != 'h' && idx[0] == 'h')
4995 instr->type = INSTR_REGRD_MRH;
4996 if (dst[0] == 'h' && idx[0] == 'h')
4997 instr->type = INSTR_REGRD_HRH;
4999 instr->regarray.regarray_id = r->id;
5000 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
5001 instr->regarray.idx.n_bits = fidx->n_bits;
5002 instr->regarray.idx.offset = fidx->offset / 8;
5003 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
5004 instr->regarray.dstsrc.n_bits = fdst->n_bits;
5005 instr->regarray.dstsrc.offset = fdst->offset / 8;
5009 /* REGRD_MRI, REGRD_HRI. */
5010 idx_val = strtoul(idx, &idx, 0);
5011 CHECK(!idx[0], EINVAL);
5013 instr->type = INSTR_REGRD_MRI;
5015 instr->type = INSTR_REGRD_HRI;
5017 instr->regarray.regarray_id = r->id;
5018 instr->regarray.idx_val = idx_val;
5019 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
5020 instr->regarray.dstsrc.n_bits = fdst->n_bits;
5021 instr->regarray.dstsrc.offset = fdst->offset / 8;
5026 instr_regwr_translate(struct rte_swx_pipeline *p,
5027 struct action *action,
5030 struct instruction *instr,
5031 struct instruction_data *data __rte_unused)
5033 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
5035 struct field *fidx, *fsrc;
5037 uint32_t idx_struct_id, idx_val, src_struct_id;
5039 CHECK(n_tokens == 4, EINVAL);
5041 r = regarray_find(p, regarray);
5044 /* REGWR_RHH, REGWR_RHM, REGWR_RMH, REGWR_RMM. */
5045 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
5046 fsrc = struct_field_parse(p, action, src, &src_struct_id);
5048 instr->type = INSTR_REGWR_RMM;
5049 if (idx[0] == 'h' && src[0] != 'h')
5050 instr->type = INSTR_REGWR_RHM;
5051 if (idx[0] != 'h' && src[0] == 'h')
5052 instr->type = INSTR_REGWR_RMH;
5053 if (idx[0] == 'h' && src[0] == 'h')
5054 instr->type = INSTR_REGWR_RHH;
5056 instr->regarray.regarray_id = r->id;
5057 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
5058 instr->regarray.idx.n_bits = fidx->n_bits;
5059 instr->regarray.idx.offset = fidx->offset / 8;
5060 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
5061 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
5062 instr->regarray.dstsrc.offset = fsrc->offset / 8;
5066 /* REGWR_RHI, REGWR_RMI. */
5067 if (fidx && !fsrc) {
5068 src_val = strtoull(src, &src, 0);
5069 CHECK(!src[0], EINVAL);
5071 instr->type = INSTR_REGWR_RMI;
5073 instr->type = INSTR_REGWR_RHI;
5075 instr->regarray.regarray_id = r->id;
5076 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
5077 instr->regarray.idx.n_bits = fidx->n_bits;
5078 instr->regarray.idx.offset = fidx->offset / 8;
5079 instr->regarray.dstsrc_val = src_val;
5083 /* REGWR_RIH, REGWR_RIM. */
5084 if (!fidx && fsrc) {
5085 idx_val = strtoul(idx, &idx, 0);
5086 CHECK(!idx[0], EINVAL);
5088 instr->type = INSTR_REGWR_RIM;
5090 instr->type = INSTR_REGWR_RIH;
5092 instr->regarray.regarray_id = r->id;
5093 instr->regarray.idx_val = idx_val;
5094 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
5095 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
5096 instr->regarray.dstsrc.offset = fsrc->offset / 8;
5101 src_val = strtoull(src, &src, 0);
5102 CHECK(!src[0], EINVAL);
5104 idx_val = strtoul(idx, &idx, 0);
5105 CHECK(!idx[0], EINVAL);
5107 instr->type = INSTR_REGWR_RII;
5108 instr->regarray.idx_val = idx_val;
5109 instr->regarray.dstsrc_val = src_val;
5115 instr_regadd_translate(struct rte_swx_pipeline *p,
5116 struct action *action,
5119 struct instruction *instr,
5120 struct instruction_data *data __rte_unused)
5122 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
5124 struct field *fidx, *fsrc;
5126 uint32_t idx_struct_id, idx_val, src_struct_id;
5128 CHECK(n_tokens == 4, EINVAL);
5130 r = regarray_find(p, regarray);
5133 /* REGADD_RHH, REGADD_RHM, REGADD_RMH, REGADD_RMM. */
5134 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
5135 fsrc = struct_field_parse(p, action, src, &src_struct_id);
5137 instr->type = INSTR_REGADD_RMM;
5138 if (idx[0] == 'h' && src[0] != 'h')
5139 instr->type = INSTR_REGADD_RHM;
5140 if (idx[0] != 'h' && src[0] == 'h')
5141 instr->type = INSTR_REGADD_RMH;
5142 if (idx[0] == 'h' && src[0] == 'h')
5143 instr->type = INSTR_REGADD_RHH;
5145 instr->regarray.regarray_id = r->id;
5146 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
5147 instr->regarray.idx.n_bits = fidx->n_bits;
5148 instr->regarray.idx.offset = fidx->offset / 8;
5149 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
5150 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
5151 instr->regarray.dstsrc.offset = fsrc->offset / 8;
5155 /* REGADD_RHI, REGADD_RMI. */
5156 if (fidx && !fsrc) {
5157 src_val = strtoull(src, &src, 0);
5158 CHECK(!src[0], EINVAL);
5160 instr->type = INSTR_REGADD_RMI;
5162 instr->type = INSTR_REGADD_RHI;
5164 instr->regarray.regarray_id = r->id;
5165 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
5166 instr->regarray.idx.n_bits = fidx->n_bits;
5167 instr->regarray.idx.offset = fidx->offset / 8;
5168 instr->regarray.dstsrc_val = src_val;
5172 /* REGADD_RIH, REGADD_RIM. */
5173 if (!fidx && fsrc) {
5174 idx_val = strtoul(idx, &idx, 0);
5175 CHECK(!idx[0], EINVAL);
5177 instr->type = INSTR_REGADD_RIM;
5179 instr->type = INSTR_REGADD_RIH;
5181 instr->regarray.regarray_id = r->id;
5182 instr->regarray.idx_val = idx_val;
5183 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
5184 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
5185 instr->regarray.dstsrc.offset = fsrc->offset / 8;
5190 src_val = strtoull(src, &src, 0);
5191 CHECK(!src[0], EINVAL);
5193 idx_val = strtoul(idx, &idx, 0);
5194 CHECK(!idx[0], EINVAL);
5196 instr->type = INSTR_REGADD_RII;
5197 instr->regarray.idx_val = idx_val;
5198 instr->regarray.dstsrc_val = src_val;
5202 static inline uint64_t *
5203 instr_regarray_regarray(struct rte_swx_pipeline *p, struct instruction *ip)
5205 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
5209 static inline uint64_t
5210 instr_regarray_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
5212 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
5214 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
5215 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
5216 uint64_t idx64 = *idx64_ptr;
5217 uint64_t idx64_mask = UINT64_MAX >> (64 - ip->regarray.idx.n_bits);
5218 uint64_t idx = idx64 & idx64_mask & r->size_mask;
5223 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5225 static inline uint64_t
5226 instr_regarray_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
5228 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
5230 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
5231 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
5232 uint64_t idx64 = *idx64_ptr;
5233 uint64_t idx = (ntoh64(idx64) >> (64 - ip->regarray.idx.n_bits)) & r->size_mask;
5240 #define instr_regarray_idx_nbo instr_regarray_idx_hbo
5244 static inline uint64_t
5245 instr_regarray_idx_imm(struct rte_swx_pipeline *p, struct instruction *ip)
5247 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
5249 uint64_t idx = ip->regarray.idx_val & r->size_mask;
5254 static inline uint64_t
5255 instr_regarray_src_hbo(struct thread *t, struct instruction *ip)
5257 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
5258 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
5259 uint64_t src64 = *src64_ptr;
5260 uint64_t src64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
5261 uint64_t src = src64 & src64_mask;
5266 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5268 static inline uint64_t
5269 instr_regarray_src_nbo(struct thread *t, struct instruction *ip)
5271 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
5272 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
5273 uint64_t src64 = *src64_ptr;
5274 uint64_t src = ntoh64(src64) >> (64 - ip->regarray.dstsrc.n_bits);
5281 #define instr_regarray_src_nbo instr_regarray_src_hbo
5286 instr_regarray_dst_hbo_src_hbo_set(struct thread *t, struct instruction *ip, uint64_t src)
5288 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
5289 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
5290 uint64_t dst64 = *dst64_ptr;
5291 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
5293 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
5297 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5300 instr_regarray_dst_nbo_src_hbo_set(struct thread *t, struct instruction *ip, uint64_t src)
5302 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
5303 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
5304 uint64_t dst64 = *dst64_ptr;
5305 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
5307 src = hton64(src) >> (64 - ip->regarray.dstsrc.n_bits);
5308 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
5313 #define instr_regarray_dst_nbo_src_hbo_set instr_regarray_dst_hbo_src_hbo_set
5318 instr_regprefetch_rh_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] regprefetch (r[h])\n", p->thread_id);
5327 regarray = instr_regarray_regarray(p, ip);
5328 idx = instr_regarray_idx_nbo(p, t, ip);
5329 rte_prefetch0(®array[idx]);
5336 instr_regprefetch_rm_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] regprefetch (r[m])\n", p->thread_id);
5345 regarray = instr_regarray_regarray(p, ip);
5346 idx = instr_regarray_idx_hbo(p, t, ip);
5347 rte_prefetch0(®array[idx]);
5354 instr_regprefetch_ri_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;
5360 TRACE("[Thread %2u] regprefetch (r[i])\n", p->thread_id);
5363 regarray = instr_regarray_regarray(p, ip);
5364 idx = instr_regarray_idx_imm(p, ip);
5365 rte_prefetch0(®array[idx]);
5372 instr_regrd_hrh_exec(struct rte_swx_pipeline *p)
5374 struct thread *t = &p->threads[p->thread_id];
5375 struct instruction *ip = t->ip;
5376 uint64_t *regarray, idx;
5378 TRACE("[Thread %2u] regrd (h = r[h])\n", p->thread_id);
5381 regarray = instr_regarray_regarray(p, ip);
5382 idx = instr_regarray_idx_nbo(p, t, ip);
5383 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
5390 instr_regrd_hrm_exec(struct rte_swx_pipeline *p)
5392 struct thread *t = &p->threads[p->thread_id];
5393 struct instruction *ip = t->ip;
5394 uint64_t *regarray, idx;
5396 TRACE("[Thread %2u] regrd (h = r[m])\n", p->thread_id);
5399 regarray = instr_regarray_regarray(p, ip);
5400 idx = instr_regarray_idx_hbo(p, t, ip);
5401 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
5408 instr_regrd_mrh_exec(struct rte_swx_pipeline *p)
5410 struct thread *t = &p->threads[p->thread_id];
5411 struct instruction *ip = t->ip;
5412 uint64_t *regarray, idx;
5414 TRACE("[Thread %2u] regrd (m = r[h])\n", p->thread_id);
5417 regarray = instr_regarray_regarray(p, ip);
5418 idx = instr_regarray_idx_nbo(p, t, ip);
5419 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
5426 instr_regrd_mrm_exec(struct rte_swx_pipeline *p)
5428 struct thread *t = &p->threads[p->thread_id];
5429 struct instruction *ip = t->ip;
5430 uint64_t *regarray, idx;
5433 regarray = instr_regarray_regarray(p, ip);
5434 idx = instr_regarray_idx_hbo(p, t, ip);
5435 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
5442 instr_regrd_hri_exec(struct rte_swx_pipeline *p)
5444 struct thread *t = &p->threads[p->thread_id];
5445 struct instruction *ip = t->ip;
5446 uint64_t *regarray, idx;
5448 TRACE("[Thread %2u] regrd (h = r[i])\n", p->thread_id);
5451 regarray = instr_regarray_regarray(p, ip);
5452 idx = instr_regarray_idx_imm(p, ip);
5453 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
5460 instr_regrd_mri_exec(struct rte_swx_pipeline *p)
5462 struct thread *t = &p->threads[p->thread_id];
5463 struct instruction *ip = t->ip;
5464 uint64_t *regarray, idx;
5466 TRACE("[Thread %2u] regrd (m = r[i])\n", p->thread_id);
5469 regarray = instr_regarray_regarray(p, ip);
5470 idx = instr_regarray_idx_imm(p, ip);
5471 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
5478 instr_regwr_rhh_exec(struct rte_swx_pipeline *p)
5480 struct thread *t = &p->threads[p->thread_id];
5481 struct instruction *ip = t->ip;
5482 uint64_t *regarray, idx, src;
5484 TRACE("[Thread %2u] regwr (r[h] = h)\n", p->thread_id);
5487 regarray = instr_regarray_regarray(p, ip);
5488 idx = instr_regarray_idx_nbo(p, t, ip);
5489 src = instr_regarray_src_nbo(t, ip);
5490 regarray[idx] = src;
5497 instr_regwr_rhm_exec(struct rte_swx_pipeline *p)
5499 struct thread *t = &p->threads[p->thread_id];
5500 struct instruction *ip = t->ip;
5501 uint64_t *regarray, idx, src;
5503 TRACE("[Thread %2u] regwr (r[h] = m)\n", p->thread_id);
5506 regarray = instr_regarray_regarray(p, ip);
5507 idx = instr_regarray_idx_nbo(p, t, ip);
5508 src = instr_regarray_src_hbo(t, ip);
5509 regarray[idx] = src;
5516 instr_regwr_rmh_exec(struct rte_swx_pipeline *p)
5518 struct thread *t = &p->threads[p->thread_id];
5519 struct instruction *ip = t->ip;
5520 uint64_t *regarray, idx, src;
5522 TRACE("[Thread %2u] regwr (r[m] = h)\n", p->thread_id);
5525 regarray = instr_regarray_regarray(p, ip);
5526 idx = instr_regarray_idx_hbo(p, t, ip);
5527 src = instr_regarray_src_nbo(t, ip);
5528 regarray[idx] = src;
5535 instr_regwr_rmm_exec(struct rte_swx_pipeline *p)
5537 struct thread *t = &p->threads[p->thread_id];
5538 struct instruction *ip = t->ip;
5539 uint64_t *regarray, idx, src;
5541 TRACE("[Thread %2u] regwr (r[m] = m)\n", p->thread_id);
5544 regarray = instr_regarray_regarray(p, ip);
5545 idx = instr_regarray_idx_hbo(p, t, ip);
5546 src = instr_regarray_src_hbo(t, ip);
5547 regarray[idx] = src;
5554 instr_regwr_rhi_exec(struct rte_swx_pipeline *p)
5556 struct thread *t = &p->threads[p->thread_id];
5557 struct instruction *ip = t->ip;
5558 uint64_t *regarray, idx, src;
5560 TRACE("[Thread %2u] regwr (r[h] = i)\n", p->thread_id);
5563 regarray = instr_regarray_regarray(p, ip);
5564 idx = instr_regarray_idx_nbo(p, t, ip);
5565 src = ip->regarray.dstsrc_val;
5566 regarray[idx] = src;
5573 instr_regwr_rmi_exec(struct rte_swx_pipeline *p)
5575 struct thread *t = &p->threads[p->thread_id];
5576 struct instruction *ip = t->ip;
5577 uint64_t *regarray, idx, src;
5579 TRACE("[Thread %2u] regwr (r[m] = i)\n", p->thread_id);
5582 regarray = instr_regarray_regarray(p, ip);
5583 idx = instr_regarray_idx_hbo(p, t, ip);
5584 src = ip->regarray.dstsrc_val;
5585 regarray[idx] = src;
5592 instr_regwr_rih_exec(struct rte_swx_pipeline *p)
5594 struct thread *t = &p->threads[p->thread_id];
5595 struct instruction *ip = t->ip;
5596 uint64_t *regarray, idx, src;
5598 TRACE("[Thread %2u] regwr (r[i] = h)\n", p->thread_id);
5601 regarray = instr_regarray_regarray(p, ip);
5602 idx = instr_regarray_idx_imm(p, ip);
5603 src = instr_regarray_src_nbo(t, ip);
5604 regarray[idx] = src;
5611 instr_regwr_rim_exec(struct rte_swx_pipeline *p)
5613 struct thread *t = &p->threads[p->thread_id];
5614 struct instruction *ip = t->ip;
5615 uint64_t *regarray, idx, src;
5617 TRACE("[Thread %2u] regwr (r[i] = m)\n", p->thread_id);
5620 regarray = instr_regarray_regarray(p, ip);
5621 idx = instr_regarray_idx_imm(p, ip);
5622 src = instr_regarray_src_hbo(t, ip);
5623 regarray[idx] = src;
5630 instr_regwr_rii_exec(struct rte_swx_pipeline *p)
5632 struct thread *t = &p->threads[p->thread_id];
5633 struct instruction *ip = t->ip;
5634 uint64_t *regarray, idx, src;
5636 TRACE("[Thread %2u] regwr (r[i] = i)\n", p->thread_id);
5639 regarray = instr_regarray_regarray(p, ip);
5640 idx = instr_regarray_idx_imm(p, ip);
5641 src = ip->regarray.dstsrc_val;
5642 regarray[idx] = src;
5649 instr_regadd_rhh_exec(struct rte_swx_pipeline *p)
5651 struct thread *t = &p->threads[p->thread_id];
5652 struct instruction *ip = t->ip;
5653 uint64_t *regarray, idx, src;
5655 TRACE("[Thread %2u] regadd (r[h] += h)\n", p->thread_id);
5658 regarray = instr_regarray_regarray(p, ip);
5659 idx = instr_regarray_idx_nbo(p, t, ip);
5660 src = instr_regarray_src_nbo(t, ip);
5661 regarray[idx] += src;
5668 instr_regadd_rhm_exec(struct rte_swx_pipeline *p)
5670 struct thread *t = &p->threads[p->thread_id];
5671 struct instruction *ip = t->ip;
5672 uint64_t *regarray, idx, src;
5674 TRACE("[Thread %2u] regadd (r[h] += m)\n", p->thread_id);
5677 regarray = instr_regarray_regarray(p, ip);
5678 idx = instr_regarray_idx_nbo(p, t, ip);
5679 src = instr_regarray_src_hbo(t, ip);
5680 regarray[idx] += src;
5687 instr_regadd_rmh_exec(struct rte_swx_pipeline *p)
5689 struct thread *t = &p->threads[p->thread_id];
5690 struct instruction *ip = t->ip;
5691 uint64_t *regarray, idx, src;
5693 TRACE("[Thread %2u] regadd (r[m] += h)\n", p->thread_id);
5696 regarray = instr_regarray_regarray(p, ip);
5697 idx = instr_regarray_idx_hbo(p, t, ip);
5698 src = instr_regarray_src_nbo(t, ip);
5699 regarray[idx] += src;
5706 instr_regadd_rmm_exec(struct rte_swx_pipeline *p)
5708 struct thread *t = &p->threads[p->thread_id];
5709 struct instruction *ip = t->ip;
5710 uint64_t *regarray, idx, src;
5712 TRACE("[Thread %2u] regadd (r[m] += m)\n", p->thread_id);
5715 regarray = instr_regarray_regarray(p, ip);
5716 idx = instr_regarray_idx_hbo(p, t, ip);
5717 src = instr_regarray_src_hbo(t, ip);
5718 regarray[idx] += src;
5725 instr_regadd_rhi_exec(struct rte_swx_pipeline *p)
5727 struct thread *t = &p->threads[p->thread_id];
5728 struct instruction *ip = t->ip;
5729 uint64_t *regarray, idx, src;
5731 TRACE("[Thread %2u] regadd (r[h] += i)\n", p->thread_id);
5734 regarray = instr_regarray_regarray(p, ip);
5735 idx = instr_regarray_idx_nbo(p, t, ip);
5736 src = ip->regarray.dstsrc_val;
5737 regarray[idx] += src;
5744 instr_regadd_rmi_exec(struct rte_swx_pipeline *p)
5746 struct thread *t = &p->threads[p->thread_id];
5747 struct instruction *ip = t->ip;
5748 uint64_t *regarray, idx, src;
5750 TRACE("[Thread %2u] regadd (r[m] += i)\n", p->thread_id);
5753 regarray = instr_regarray_regarray(p, ip);
5754 idx = instr_regarray_idx_hbo(p, t, ip);
5755 src = ip->regarray.dstsrc_val;
5756 regarray[idx] += src;
5763 instr_regadd_rih_exec(struct rte_swx_pipeline *p)
5765 struct thread *t = &p->threads[p->thread_id];
5766 struct instruction *ip = t->ip;
5767 uint64_t *regarray, idx, src;
5769 TRACE("[Thread %2u] regadd (r[i] += h)\n", p->thread_id);
5772 regarray = instr_regarray_regarray(p, ip);
5773 idx = instr_regarray_idx_imm(p, ip);
5774 src = instr_regarray_src_nbo(t, ip);
5775 regarray[idx] += src;
5782 instr_regadd_rim_exec(struct rte_swx_pipeline *p)
5784 struct thread *t = &p->threads[p->thread_id];
5785 struct instruction *ip = t->ip;
5786 uint64_t *regarray, idx, src;
5788 TRACE("[Thread %2u] regadd (r[i] += m)\n", p->thread_id);
5791 regarray = instr_regarray_regarray(p, ip);
5792 idx = instr_regarray_idx_imm(p, ip);
5793 src = instr_regarray_src_hbo(t, ip);
5794 regarray[idx] += src;
5801 instr_regadd_rii_exec(struct rte_swx_pipeline *p)
5803 struct thread *t = &p->threads[p->thread_id];
5804 struct instruction *ip = t->ip;
5805 uint64_t *regarray, idx, src;
5807 TRACE("[Thread %2u] regadd (r[i] += i)\n", p->thread_id);
5810 regarray = instr_regarray_regarray(p, ip);
5811 idx = instr_regarray_idx_imm(p, ip);
5812 src = ip->regarray.dstsrc_val;
5813 regarray[idx] += src;
5822 static struct metarray *
5823 metarray_find(struct rte_swx_pipeline *p, const char *name);
5826 instr_metprefetch_translate(struct rte_swx_pipeline *p,
5827 struct action *action,
5830 struct instruction *instr,
5831 struct instruction_data *data __rte_unused)
5833 char *metarray = tokens[1], *idx = tokens[2];
5836 uint32_t idx_struct_id, idx_val;
5838 CHECK(n_tokens == 3, EINVAL);
5840 m = metarray_find(p, metarray);
5843 /* METPREFETCH_H, METPREFETCH_M. */
5844 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
5846 instr->type = INSTR_METPREFETCH_M;
5848 instr->type = INSTR_METPREFETCH_H;
5850 instr->meter.metarray_id = m->id;
5851 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
5852 instr->meter.idx.n_bits = fidx->n_bits;
5853 instr->meter.idx.offset = fidx->offset / 8;
5857 /* METPREFETCH_I. */
5858 idx_val = strtoul(idx, &idx, 0);
5859 CHECK(!idx[0], EINVAL);
5861 instr->type = INSTR_METPREFETCH_I;
5862 instr->meter.metarray_id = m->id;
5863 instr->meter.idx_val = idx_val;
5868 instr_meter_translate(struct rte_swx_pipeline *p,
5869 struct action *action,
5872 struct instruction *instr,
5873 struct instruction_data *data __rte_unused)
5875 char *metarray = tokens[1], *idx = tokens[2], *length = tokens[3];
5876 char *color_in = tokens[4], *color_out = tokens[5];
5878 struct field *fidx, *flength, *fcin, *fcout;
5879 uint32_t idx_struct_id, length_struct_id;
5880 uint32_t color_in_struct_id, color_out_struct_id;
5882 CHECK(n_tokens == 6, EINVAL);
5884 m = metarray_find(p, metarray);
5887 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
5889 flength = struct_field_parse(p, action, length, &length_struct_id);
5890 CHECK(flength, EINVAL);
5892 fcin = struct_field_parse(p, action, color_in, &color_in_struct_id);
5894 fcout = struct_field_parse(p, NULL, color_out, &color_out_struct_id);
5895 CHECK(fcout, EINVAL);
5897 /* index = HMEFT, length = HMEFT, color_in = MEFT, color_out = MEF. */
5899 instr->type = INSTR_METER_MMM;
5900 if (idx[0] == 'h' && length[0] == 'h')
5901 instr->type = INSTR_METER_HHM;
5902 if (idx[0] == 'h' && length[0] != 'h')
5903 instr->type = INSTR_METER_HMM;
5904 if (idx[0] != 'h' && length[0] == 'h')
5905 instr->type = INSTR_METER_MHM;
5907 instr->meter.metarray_id = m->id;
5909 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
5910 instr->meter.idx.n_bits = fidx->n_bits;
5911 instr->meter.idx.offset = fidx->offset / 8;
5913 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5914 instr->meter.length.n_bits = flength->n_bits;
5915 instr->meter.length.offset = flength->offset / 8;
5917 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
5918 instr->meter.color_in.n_bits = fcin->n_bits;
5919 instr->meter.color_in.offset = fcin->offset / 8;
5921 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5922 instr->meter.color_out.n_bits = fcout->n_bits;
5923 instr->meter.color_out.offset = fcout->offset / 8;
5928 /* index = HMEFT, length = HMEFT, color_in = I, color_out = MEF. */
5929 if (fidx && !fcin) {
5930 uint32_t color_in_val = strtoul(color_in, &color_in, 0);
5931 CHECK(!color_in[0], EINVAL);
5933 instr->type = INSTR_METER_MMI;
5934 if (idx[0] == 'h' && length[0] == 'h')
5935 instr->type = INSTR_METER_HHI;
5936 if (idx[0] == 'h' && length[0] != 'h')
5937 instr->type = INSTR_METER_HMI;
5938 if (idx[0] != 'h' && length[0] == 'h')
5939 instr->type = INSTR_METER_MHI;
5941 instr->meter.metarray_id = m->id;
5943 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
5944 instr->meter.idx.n_bits = fidx->n_bits;
5945 instr->meter.idx.offset = fidx->offset / 8;
5947 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5948 instr->meter.length.n_bits = flength->n_bits;
5949 instr->meter.length.offset = flength->offset / 8;
5951 instr->meter.color_in_val = color_in_val;
5953 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5954 instr->meter.color_out.n_bits = fcout->n_bits;
5955 instr->meter.color_out.offset = fcout->offset / 8;
5960 /* index = I, length = HMEFT, color_in = MEFT, color_out = MEF. */
5961 if (!fidx && fcin) {
5964 idx_val = strtoul(idx, &idx, 0);
5965 CHECK(!idx[0], EINVAL);
5967 instr->type = INSTR_METER_IMM;
5968 if (length[0] == 'h')
5969 instr->type = INSTR_METER_IHM;
5971 instr->meter.metarray_id = m->id;
5973 instr->meter.idx_val = idx_val;
5975 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5976 instr->meter.length.n_bits = flength->n_bits;
5977 instr->meter.length.offset = flength->offset / 8;
5979 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
5980 instr->meter.color_in.n_bits = fcin->n_bits;
5981 instr->meter.color_in.offset = fcin->offset / 8;
5983 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5984 instr->meter.color_out.n_bits = fcout->n_bits;
5985 instr->meter.color_out.offset = fcout->offset / 8;
5990 /* index = I, length = HMEFT, color_in = I, color_out = MEF. */
5991 if (!fidx && !fcin) {
5992 uint32_t idx_val, color_in_val;
5994 idx_val = strtoul(idx, &idx, 0);
5995 CHECK(!idx[0], EINVAL);
5997 color_in_val = strtoul(color_in, &color_in, 0);
5998 CHECK(!color_in[0], EINVAL);
6000 instr->type = INSTR_METER_IMI;
6001 if (length[0] == 'h')
6002 instr->type = INSTR_METER_IHI;
6004 instr->meter.metarray_id = m->id;
6006 instr->meter.idx_val = idx_val;
6008 instr->meter.length.struct_id = (uint8_t)length_struct_id;
6009 instr->meter.length.n_bits = flength->n_bits;
6010 instr->meter.length.offset = flength->offset / 8;
6012 instr->meter.color_in_val = color_in_val;
6014 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
6015 instr->meter.color_out.n_bits = fcout->n_bits;
6016 instr->meter.color_out.offset = fcout->offset / 8;
6024 static inline struct meter *
6025 instr_meter_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
6027 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
6029 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
6030 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
6031 uint64_t idx64 = *idx64_ptr;
6032 uint64_t idx64_mask = UINT64_MAX >> (64 - (ip)->meter.idx.n_bits);
6033 uint64_t idx = idx64 & idx64_mask & r->size_mask;
6035 return &r->metarray[idx];
6038 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
6040 static inline struct meter *
6041 instr_meter_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
6043 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
6045 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
6046 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
6047 uint64_t idx64 = *idx64_ptr;
6048 uint64_t idx = (ntoh64(idx64) >> (64 - ip->meter.idx.n_bits)) & r->size_mask;
6050 return &r->metarray[idx];
6055 #define instr_meter_idx_nbo instr_meter_idx_hbo
6059 static inline struct meter *
6060 instr_meter_idx_imm(struct rte_swx_pipeline *p, struct instruction *ip)
6062 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
6064 uint64_t idx = ip->meter.idx_val & r->size_mask;
6066 return &r->metarray[idx];
6069 static inline uint32_t
6070 instr_meter_length_hbo(struct thread *t, struct instruction *ip)
6072 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
6073 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
6074 uint64_t src64 = *src64_ptr;
6075 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->meter.length.n_bits);
6076 uint64_t src = src64 & src64_mask;
6078 return (uint32_t)src;
6081 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
6083 static inline uint32_t
6084 instr_meter_length_nbo(struct thread *t, struct instruction *ip)
6086 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
6087 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
6088 uint64_t src64 = *src64_ptr;
6089 uint64_t src = ntoh64(src64) >> (64 - ip->meter.length.n_bits);
6091 return (uint32_t)src;
6096 #define instr_meter_length_nbo instr_meter_length_hbo
6100 static inline enum rte_color
6101 instr_meter_color_in_hbo(struct thread *t, struct instruction *ip)
6103 uint8_t *src_struct = t->structs[ip->meter.color_in.struct_id];
6104 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.color_in.offset];
6105 uint64_t src64 = *src64_ptr;
6106 uint64_t src64_mask = UINT64_MAX >> (64 - ip->meter.color_in.n_bits);
6107 uint64_t src = src64 & src64_mask;
6109 return (enum rte_color)src;
6113 instr_meter_color_out_hbo_set(struct thread *t, struct instruction *ip, enum rte_color color_out)
6115 uint8_t *dst_struct = t->structs[ip->meter.color_out.struct_id];
6116 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->meter.color_out.offset];
6117 uint64_t dst64 = *dst64_ptr;
6118 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->meter.color_out.n_bits);
6120 uint64_t src = (uint64_t)color_out;
6122 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
6126 instr_metprefetch_h_exec(struct rte_swx_pipeline *p)
6128 struct thread *t = &p->threads[p->thread_id];
6129 struct instruction *ip = t->ip;
6132 TRACE("[Thread %2u] metprefetch (h)\n", p->thread_id);
6135 m = instr_meter_idx_nbo(p, t, ip);
6143 instr_metprefetch_m_exec(struct rte_swx_pipeline *p)
6145 struct thread *t = &p->threads[p->thread_id];
6146 struct instruction *ip = t->ip;
6149 TRACE("[Thread %2u] metprefetch (m)\n", p->thread_id);
6152 m = instr_meter_idx_hbo(p, t, ip);
6160 instr_metprefetch_i_exec(struct rte_swx_pipeline *p)
6162 struct thread *t = &p->threads[p->thread_id];
6163 struct instruction *ip = t->ip;
6166 TRACE("[Thread %2u] metprefetch (i)\n", p->thread_id);
6169 m = instr_meter_idx_imm(p, ip);
6177 instr_meter_hhm_exec(struct rte_swx_pipeline *p)
6179 struct thread *t = &p->threads[p->thread_id];
6180 struct instruction *ip = t->ip;
6182 uint64_t time, n_pkts, n_bytes;
6184 enum rte_color color_in, color_out;
6186 TRACE("[Thread %2u] meter (hhm)\n", p->thread_id);
6189 m = instr_meter_idx_nbo(p, t, ip);
6190 rte_prefetch0(m->n_pkts);
6191 time = rte_get_tsc_cycles();
6192 length = instr_meter_length_nbo(t, ip);
6193 color_in = instr_meter_color_in_hbo(t, ip);
6195 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6196 &m->profile->profile,
6201 color_out &= m->color_mask;
6203 n_pkts = m->n_pkts[color_out];
6204 n_bytes = m->n_bytes[color_out];
6206 instr_meter_color_out_hbo_set(t, ip, color_out);
6208 m->n_pkts[color_out] = n_pkts + 1;
6209 m->n_bytes[color_out] = n_bytes + length;
6216 instr_meter_hhi_exec(struct rte_swx_pipeline *p)
6218 struct thread *t = &p->threads[p->thread_id];
6219 struct instruction *ip = t->ip;
6221 uint64_t time, n_pkts, n_bytes;
6223 enum rte_color color_in, color_out;
6225 TRACE("[Thread %2u] meter (hhi)\n", p->thread_id);
6228 m = instr_meter_idx_nbo(p, t, ip);
6229 rte_prefetch0(m->n_pkts);
6230 time = rte_get_tsc_cycles();
6231 length = instr_meter_length_nbo(t, ip);
6232 color_in = (enum rte_color)ip->meter.color_in_val;
6234 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6235 &m->profile->profile,
6240 color_out &= m->color_mask;
6242 n_pkts = m->n_pkts[color_out];
6243 n_bytes = m->n_bytes[color_out];
6245 instr_meter_color_out_hbo_set(t, ip, color_out);
6247 m->n_pkts[color_out] = n_pkts + 1;
6248 m->n_bytes[color_out] = n_bytes + length;
6255 instr_meter_hmm_exec(struct rte_swx_pipeline *p)
6257 struct thread *t = &p->threads[p->thread_id];
6258 struct instruction *ip = t->ip;
6260 uint64_t time, n_pkts, n_bytes;
6262 enum rte_color color_in, color_out;
6264 TRACE("[Thread %2u] meter (hmm)\n", p->thread_id);
6267 m = instr_meter_idx_nbo(p, t, ip);
6268 rte_prefetch0(m->n_pkts);
6269 time = rte_get_tsc_cycles();
6270 length = instr_meter_length_hbo(t, ip);
6271 color_in = instr_meter_color_in_hbo(t, ip);
6273 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6274 &m->profile->profile,
6279 color_out &= m->color_mask;
6281 n_pkts = m->n_pkts[color_out];
6282 n_bytes = m->n_bytes[color_out];
6284 instr_meter_color_out_hbo_set(t, ip, color_out);
6286 m->n_pkts[color_out] = n_pkts + 1;
6287 m->n_bytes[color_out] = n_bytes + length;
6293 instr_meter_hmi_exec(struct rte_swx_pipeline *p)
6295 struct thread *t = &p->threads[p->thread_id];
6296 struct instruction *ip = t->ip;
6298 uint64_t time, n_pkts, n_bytes;
6300 enum rte_color color_in, color_out;
6302 TRACE("[Thread %2u] meter (hmi)\n", p->thread_id);
6305 m = instr_meter_idx_nbo(p, t, ip);
6306 rte_prefetch0(m->n_pkts);
6307 time = rte_get_tsc_cycles();
6308 length = instr_meter_length_hbo(t, ip);
6309 color_in = (enum rte_color)ip->meter.color_in_val;
6311 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6312 &m->profile->profile,
6317 color_out &= m->color_mask;
6319 n_pkts = m->n_pkts[color_out];
6320 n_bytes = m->n_bytes[color_out];
6322 instr_meter_color_out_hbo_set(t, ip, color_out);
6324 m->n_pkts[color_out] = n_pkts + 1;
6325 m->n_bytes[color_out] = n_bytes + length;
6332 instr_meter_mhm_exec(struct rte_swx_pipeline *p)
6334 struct thread *t = &p->threads[p->thread_id];
6335 struct instruction *ip = t->ip;
6337 uint64_t time, n_pkts, n_bytes;
6339 enum rte_color color_in, color_out;
6341 TRACE("[Thread %2u] meter (mhm)\n", p->thread_id);
6344 m = instr_meter_idx_hbo(p, t, ip);
6345 rte_prefetch0(m->n_pkts);
6346 time = rte_get_tsc_cycles();
6347 length = instr_meter_length_nbo(t, ip);
6348 color_in = instr_meter_color_in_hbo(t, ip);
6350 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6351 &m->profile->profile,
6356 color_out &= m->color_mask;
6358 n_pkts = m->n_pkts[color_out];
6359 n_bytes = m->n_bytes[color_out];
6361 instr_meter_color_out_hbo_set(t, ip, color_out);
6363 m->n_pkts[color_out] = n_pkts + 1;
6364 m->n_bytes[color_out] = n_bytes + length;
6371 instr_meter_mhi_exec(struct rte_swx_pipeline *p)
6373 struct thread *t = &p->threads[p->thread_id];
6374 struct instruction *ip = t->ip;
6376 uint64_t time, n_pkts, n_bytes;
6378 enum rte_color color_in, color_out;
6380 TRACE("[Thread %2u] meter (mhi)\n", p->thread_id);
6383 m = instr_meter_idx_hbo(p, t, ip);
6384 rte_prefetch0(m->n_pkts);
6385 time = rte_get_tsc_cycles();
6386 length = instr_meter_length_nbo(t, ip);
6387 color_in = (enum rte_color)ip->meter.color_in_val;
6389 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6390 &m->profile->profile,
6395 color_out &= m->color_mask;
6397 n_pkts = m->n_pkts[color_out];
6398 n_bytes = m->n_bytes[color_out];
6400 instr_meter_color_out_hbo_set(t, ip, color_out);
6402 m->n_pkts[color_out] = n_pkts + 1;
6403 m->n_bytes[color_out] = n_bytes + length;
6410 instr_meter_mmm_exec(struct rte_swx_pipeline *p)
6412 struct thread *t = &p->threads[p->thread_id];
6413 struct instruction *ip = t->ip;
6415 uint64_t time, n_pkts, n_bytes;
6417 enum rte_color color_in, color_out;
6419 TRACE("[Thread %2u] meter (mmm)\n", p->thread_id);
6422 m = instr_meter_idx_hbo(p, t, ip);
6423 rte_prefetch0(m->n_pkts);
6424 time = rte_get_tsc_cycles();
6425 length = instr_meter_length_hbo(t, ip);
6426 color_in = instr_meter_color_in_hbo(t, ip);
6428 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6429 &m->profile->profile,
6434 color_out &= m->color_mask;
6436 n_pkts = m->n_pkts[color_out];
6437 n_bytes = m->n_bytes[color_out];
6439 instr_meter_color_out_hbo_set(t, ip, color_out);
6441 m->n_pkts[color_out] = n_pkts + 1;
6442 m->n_bytes[color_out] = n_bytes + length;
6449 instr_meter_mmi_exec(struct rte_swx_pipeline *p)
6451 struct thread *t = &p->threads[p->thread_id];
6452 struct instruction *ip = t->ip;
6454 uint64_t time, n_pkts, n_bytes;
6456 enum rte_color color_in, color_out;
6458 TRACE("[Thread %2u] meter (mmi)\n", p->thread_id);
6461 m = instr_meter_idx_hbo(p, t, ip);
6462 rte_prefetch0(m->n_pkts);
6463 time = rte_get_tsc_cycles();
6464 length = instr_meter_length_hbo(t, ip);
6465 color_in = (enum rte_color)ip->meter.color_in_val;
6467 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6468 &m->profile->profile,
6473 color_out &= m->color_mask;
6475 n_pkts = m->n_pkts[color_out];
6476 n_bytes = m->n_bytes[color_out];
6478 instr_meter_color_out_hbo_set(t, ip, color_out);
6480 m->n_pkts[color_out] = n_pkts + 1;
6481 m->n_bytes[color_out] = n_bytes + length;
6488 instr_meter_ihm_exec(struct rte_swx_pipeline *p)
6490 struct thread *t = &p->threads[p->thread_id];
6491 struct instruction *ip = t->ip;
6493 uint64_t time, n_pkts, n_bytes;
6495 enum rte_color color_in, color_out;
6497 TRACE("[Thread %2u] meter (ihm)\n", p->thread_id);
6500 m = instr_meter_idx_imm(p, ip);
6501 rte_prefetch0(m->n_pkts);
6502 time = rte_get_tsc_cycles();
6503 length = instr_meter_length_nbo(t, ip);
6504 color_in = instr_meter_color_in_hbo(t, ip);
6506 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6507 &m->profile->profile,
6512 color_out &= m->color_mask;
6514 n_pkts = m->n_pkts[color_out];
6515 n_bytes = m->n_bytes[color_out];
6517 instr_meter_color_out_hbo_set(t, ip, color_out);
6519 m->n_pkts[color_out] = n_pkts + 1;
6520 m->n_bytes[color_out] = n_bytes + length;
6527 instr_meter_ihi_exec(struct rte_swx_pipeline *p)
6529 struct thread *t = &p->threads[p->thread_id];
6530 struct instruction *ip = t->ip;
6532 uint64_t time, n_pkts, n_bytes;
6534 enum rte_color color_in, color_out;
6536 TRACE("[Thread %2u] meter (ihi)\n", p->thread_id);
6539 m = instr_meter_idx_imm(p, ip);
6540 rte_prefetch0(m->n_pkts);
6541 time = rte_get_tsc_cycles();
6542 length = instr_meter_length_nbo(t, ip);
6543 color_in = (enum rte_color)ip->meter.color_in_val;
6545 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6546 &m->profile->profile,
6551 color_out &= m->color_mask;
6553 n_pkts = m->n_pkts[color_out];
6554 n_bytes = m->n_bytes[color_out];
6556 instr_meter_color_out_hbo_set(t, ip, color_out);
6558 m->n_pkts[color_out] = n_pkts + 1;
6559 m->n_bytes[color_out] = n_bytes + length;
6566 instr_meter_imm_exec(struct rte_swx_pipeline *p)
6568 struct thread *t = &p->threads[p->thread_id];
6569 struct instruction *ip = t->ip;
6571 uint64_t time, n_pkts, n_bytes;
6573 enum rte_color color_in, color_out;
6575 TRACE("[Thread %2u] meter (imm)\n", p->thread_id);
6578 m = instr_meter_idx_imm(p, ip);
6579 rte_prefetch0(m->n_pkts);
6580 time = rte_get_tsc_cycles();
6581 length = instr_meter_length_hbo(t, ip);
6582 color_in = instr_meter_color_in_hbo(t, ip);
6584 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6585 &m->profile->profile,
6590 color_out &= m->color_mask;
6592 n_pkts = m->n_pkts[color_out];
6593 n_bytes = m->n_bytes[color_out];
6595 instr_meter_color_out_hbo_set(t, ip, color_out);
6597 m->n_pkts[color_out] = n_pkts + 1;
6598 m->n_bytes[color_out] = n_bytes + length;
6604 instr_meter_imi_exec(struct rte_swx_pipeline *p)
6606 struct thread *t = &p->threads[p->thread_id];
6607 struct instruction *ip = t->ip;
6609 uint64_t time, n_pkts, n_bytes;
6611 enum rte_color color_in, color_out;
6613 TRACE("[Thread %2u] meter (imi)\n", p->thread_id);
6616 m = instr_meter_idx_imm(p, ip);
6617 rte_prefetch0(m->n_pkts);
6618 time = rte_get_tsc_cycles();
6619 length = instr_meter_length_hbo(t, ip);
6620 color_in = (enum rte_color)ip->meter.color_in_val;
6622 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6623 &m->profile->profile,
6628 color_out &= m->color_mask;
6630 n_pkts = m->n_pkts[color_out];
6631 n_bytes = m->n_bytes[color_out];
6633 instr_meter_color_out_hbo_set(t, ip, color_out);
6635 m->n_pkts[color_out] = n_pkts + 1;
6636 m->n_bytes[color_out] = n_bytes + length;
6645 static struct action *
6646 action_find(struct rte_swx_pipeline *p, const char *name);
6649 instr_jmp_translate(struct rte_swx_pipeline *p __rte_unused,
6650 struct action *action __rte_unused,
6653 struct instruction *instr,
6654 struct instruction_data *data)
6656 CHECK(n_tokens == 2, EINVAL);
6658 strcpy(data->jmp_label, tokens[1]);
6660 instr->type = INSTR_JMP;
6661 instr->jmp.ip = NULL; /* Resolved later. */
6666 instr_jmp_valid_translate(struct rte_swx_pipeline *p,
6667 struct action *action __rte_unused,
6670 struct instruction *instr,
6671 struct instruction_data *data)
6675 CHECK(n_tokens == 3, EINVAL);
6677 strcpy(data->jmp_label, tokens[1]);
6679 h = header_parse(p, tokens[2]);
6682 instr->type = INSTR_JMP_VALID;
6683 instr->jmp.ip = NULL; /* Resolved later. */
6684 instr->jmp.header_id = h->id;
6689 instr_jmp_invalid_translate(struct rte_swx_pipeline *p,
6690 struct action *action __rte_unused,
6693 struct instruction *instr,
6694 struct instruction_data *data)
6698 CHECK(n_tokens == 3, EINVAL);
6700 strcpy(data->jmp_label, tokens[1]);
6702 h = header_parse(p, tokens[2]);
6705 instr->type = INSTR_JMP_INVALID;
6706 instr->jmp.ip = NULL; /* Resolved later. */
6707 instr->jmp.header_id = h->id;
6712 instr_jmp_hit_translate(struct rte_swx_pipeline *p __rte_unused,
6713 struct action *action,
6716 struct instruction *instr,
6717 struct instruction_data *data)
6719 CHECK(!action, EINVAL);
6720 CHECK(n_tokens == 2, EINVAL);
6722 strcpy(data->jmp_label, tokens[1]);
6724 instr->type = INSTR_JMP_HIT;
6725 instr->jmp.ip = NULL; /* Resolved later. */
6730 instr_jmp_miss_translate(struct rte_swx_pipeline *p __rte_unused,
6731 struct action *action,
6734 struct instruction *instr,
6735 struct instruction_data *data)
6737 CHECK(!action, EINVAL);
6738 CHECK(n_tokens == 2, EINVAL);
6740 strcpy(data->jmp_label, tokens[1]);
6742 instr->type = INSTR_JMP_MISS;
6743 instr->jmp.ip = NULL; /* Resolved later. */
6748 instr_jmp_action_hit_translate(struct rte_swx_pipeline *p,
6749 struct action *action,
6752 struct instruction *instr,
6753 struct instruction_data *data)
6757 CHECK(!action, EINVAL);
6758 CHECK(n_tokens == 3, EINVAL);
6760 strcpy(data->jmp_label, tokens[1]);
6762 a = action_find(p, tokens[2]);
6765 instr->type = INSTR_JMP_ACTION_HIT;
6766 instr->jmp.ip = NULL; /* Resolved later. */
6767 instr->jmp.action_id = a->id;
6772 instr_jmp_action_miss_translate(struct rte_swx_pipeline *p,
6773 struct action *action,
6776 struct instruction *instr,
6777 struct instruction_data *data)
6781 CHECK(!action, EINVAL);
6782 CHECK(n_tokens == 3, EINVAL);
6784 strcpy(data->jmp_label, tokens[1]);
6786 a = action_find(p, tokens[2]);
6789 instr->type = INSTR_JMP_ACTION_MISS;
6790 instr->jmp.ip = NULL; /* Resolved later. */
6791 instr->jmp.action_id = a->id;
6796 instr_jmp_eq_translate(struct rte_swx_pipeline *p,
6797 struct action *action,
6800 struct instruction *instr,
6801 struct instruction_data *data)
6803 char *a = tokens[2], *b = tokens[3];
6804 struct field *fa, *fb;
6806 uint32_t a_struct_id, b_struct_id;
6808 CHECK(n_tokens == 4, EINVAL);
6810 strcpy(data->jmp_label, tokens[1]);
6812 fa = struct_field_parse(p, action, a, &a_struct_id);
6815 /* JMP_EQ or JMP_EQ_S. */
6816 fb = struct_field_parse(p, action, b, &b_struct_id);
6818 instr->type = INSTR_JMP_EQ;
6819 if ((a[0] == 'h' && b[0] != 'h') ||
6820 (a[0] != 'h' && b[0] == 'h'))
6821 instr->type = INSTR_JMP_EQ_S;
6822 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.struct_id = (uint8_t)b_struct_id;
6828 instr->jmp.b.n_bits = fb->n_bits;
6829 instr->jmp.b.offset = fb->offset / 8;
6834 b_val = strtoull(b, &b, 0);
6835 CHECK(!b[0], EINVAL);
6838 b_val = hton64(b_val) >> (64 - fa->n_bits);
6840 instr->type = INSTR_JMP_EQ_I;
6841 instr->jmp.ip = NULL; /* Resolved later. */
6842 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6843 instr->jmp.a.n_bits = fa->n_bits;
6844 instr->jmp.a.offset = fa->offset / 8;
6845 instr->jmp.b_val = b_val;
6850 instr_jmp_neq_translate(struct rte_swx_pipeline *p,
6851 struct action *action,
6854 struct instruction *instr,
6855 struct instruction_data *data)
6857 char *a = tokens[2], *b = tokens[3];
6858 struct field *fa, *fb;
6860 uint32_t a_struct_id, b_struct_id;
6862 CHECK(n_tokens == 4, EINVAL);
6864 strcpy(data->jmp_label, tokens[1]);
6866 fa = struct_field_parse(p, action, a, &a_struct_id);
6869 /* JMP_NEQ or JMP_NEQ_S. */
6870 fb = struct_field_parse(p, action, b, &b_struct_id);
6872 instr->type = INSTR_JMP_NEQ;
6873 if ((a[0] == 'h' && b[0] != 'h') ||
6874 (a[0] != 'h' && b[0] == 'h'))
6875 instr->type = INSTR_JMP_NEQ_S;
6876 instr->jmp.ip = NULL; /* Resolved later. */
6878 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6879 instr->jmp.a.n_bits = fa->n_bits;
6880 instr->jmp.a.offset = fa->offset / 8;
6881 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6882 instr->jmp.b.n_bits = fb->n_bits;
6883 instr->jmp.b.offset = fb->offset / 8;
6888 b_val = strtoull(b, &b, 0);
6889 CHECK(!b[0], EINVAL);
6892 b_val = hton64(b_val) >> (64 - fa->n_bits);
6894 instr->type = INSTR_JMP_NEQ_I;
6895 instr->jmp.ip = NULL; /* Resolved later. */
6896 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6897 instr->jmp.a.n_bits = fa->n_bits;
6898 instr->jmp.a.offset = fa->offset / 8;
6899 instr->jmp.b_val = b_val;
6904 instr_jmp_lt_translate(struct rte_swx_pipeline *p,
6905 struct action *action,
6908 struct instruction *instr,
6909 struct instruction_data *data)
6911 char *a = tokens[2], *b = tokens[3];
6912 struct field *fa, *fb;
6914 uint32_t a_struct_id, b_struct_id;
6916 CHECK(n_tokens == 4, EINVAL);
6918 strcpy(data->jmp_label, tokens[1]);
6920 fa = struct_field_parse(p, action, a, &a_struct_id);
6923 /* JMP_LT, JMP_LT_MH, JMP_LT_HM, JMP_LT_HH. */
6924 fb = struct_field_parse(p, action, b, &b_struct_id);
6926 instr->type = INSTR_JMP_LT;
6927 if (a[0] == 'h' && b[0] != 'h')
6928 instr->type = INSTR_JMP_LT_HM;
6929 if (a[0] != 'h' && b[0] == 'h')
6930 instr->type = INSTR_JMP_LT_MH;
6931 if (a[0] == 'h' && b[0] == 'h')
6932 instr->type = INSTR_JMP_LT_HH;
6933 instr->jmp.ip = NULL; /* Resolved later. */
6935 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6936 instr->jmp.a.n_bits = fa->n_bits;
6937 instr->jmp.a.offset = fa->offset / 8;
6938 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6939 instr->jmp.b.n_bits = fb->n_bits;
6940 instr->jmp.b.offset = fb->offset / 8;
6944 /* JMP_LT_MI, JMP_LT_HI. */
6945 b_val = strtoull(b, &b, 0);
6946 CHECK(!b[0], EINVAL);
6948 instr->type = INSTR_JMP_LT_MI;
6950 instr->type = INSTR_JMP_LT_HI;
6951 instr->jmp.ip = NULL; /* Resolved later. */
6953 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6954 instr->jmp.a.n_bits = fa->n_bits;
6955 instr->jmp.a.offset = fa->offset / 8;
6956 instr->jmp.b_val = b_val;
6961 instr_jmp_gt_translate(struct rte_swx_pipeline *p,
6962 struct action *action,
6965 struct instruction *instr,
6966 struct instruction_data *data)
6968 char *a = tokens[2], *b = tokens[3];
6969 struct field *fa, *fb;
6971 uint32_t a_struct_id, b_struct_id;
6973 CHECK(n_tokens == 4, EINVAL);
6975 strcpy(data->jmp_label, tokens[1]);
6977 fa = struct_field_parse(p, action, a, &a_struct_id);
6980 /* JMP_GT, JMP_GT_MH, JMP_GT_HM, JMP_GT_HH. */
6981 fb = struct_field_parse(p, action, b, &b_struct_id);
6983 instr->type = INSTR_JMP_GT;
6984 if (a[0] == 'h' && b[0] != 'h')
6985 instr->type = INSTR_JMP_GT_HM;
6986 if (a[0] != 'h' && b[0] == 'h')
6987 instr->type = INSTR_JMP_GT_MH;
6988 if (a[0] == 'h' && b[0] == 'h')
6989 instr->type = INSTR_JMP_GT_HH;
6990 instr->jmp.ip = NULL; /* Resolved later. */
6992 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6993 instr->jmp.a.n_bits = fa->n_bits;
6994 instr->jmp.a.offset = fa->offset / 8;
6995 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6996 instr->jmp.b.n_bits = fb->n_bits;
6997 instr->jmp.b.offset = fb->offset / 8;
7001 /* JMP_GT_MI, JMP_GT_HI. */
7002 b_val = strtoull(b, &b, 0);
7003 CHECK(!b[0], EINVAL);
7005 instr->type = INSTR_JMP_GT_MI;
7007 instr->type = INSTR_JMP_GT_HI;
7008 instr->jmp.ip = NULL; /* Resolved later. */
7010 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
7011 instr->jmp.a.n_bits = fa->n_bits;
7012 instr->jmp.a.offset = fa->offset / 8;
7013 instr->jmp.b_val = b_val;
7018 instr_jmp_exec(struct rte_swx_pipeline *p)
7020 struct thread *t = &p->threads[p->thread_id];
7021 struct instruction *ip = t->ip;
7023 TRACE("[Thread %2u] jmp\n", p->thread_id);
7025 thread_ip_set(t, ip->jmp.ip);
7029 instr_jmp_valid_exec(struct rte_swx_pipeline *p)
7031 struct thread *t = &p->threads[p->thread_id];
7032 struct instruction *ip = t->ip;
7033 uint32_t header_id = ip->jmp.header_id;
7035 TRACE("[Thread %2u] jmpv\n", p->thread_id);
7037 t->ip = HEADER_VALID(t, header_id) ? ip->jmp.ip : (t->ip + 1);
7041 instr_jmp_invalid_exec(struct rte_swx_pipeline *p)
7043 struct thread *t = &p->threads[p->thread_id];
7044 struct instruction *ip = t->ip;
7045 uint32_t header_id = ip->jmp.header_id;
7047 TRACE("[Thread %2u] jmpnv\n", p->thread_id);
7049 t->ip = HEADER_VALID(t, header_id) ? (t->ip + 1) : ip->jmp.ip;
7053 instr_jmp_hit_exec(struct rte_swx_pipeline *p)
7055 struct thread *t = &p->threads[p->thread_id];
7056 struct instruction *ip = t->ip;
7057 struct instruction *ip_next[] = {t->ip + 1, ip->jmp.ip};
7059 TRACE("[Thread %2u] jmph\n", p->thread_id);
7061 t->ip = ip_next[t->hit];
7065 instr_jmp_miss_exec(struct rte_swx_pipeline *p)
7067 struct thread *t = &p->threads[p->thread_id];
7068 struct instruction *ip = t->ip;
7069 struct instruction *ip_next[] = {ip->jmp.ip, t->ip + 1};
7071 TRACE("[Thread %2u] jmpnh\n", p->thread_id);
7073 t->ip = ip_next[t->hit];
7077 instr_jmp_action_hit_exec(struct rte_swx_pipeline *p)
7079 struct thread *t = &p->threads[p->thread_id];
7080 struct instruction *ip = t->ip;
7082 TRACE("[Thread %2u] jmpa\n", p->thread_id);
7084 t->ip = (ip->jmp.action_id == t->action_id) ? ip->jmp.ip : (t->ip + 1);
7088 instr_jmp_action_miss_exec(struct rte_swx_pipeline *p)
7090 struct thread *t = &p->threads[p->thread_id];
7091 struct instruction *ip = t->ip;
7093 TRACE("[Thread %2u] jmpna\n", p->thread_id);
7095 t->ip = (ip->jmp.action_id == t->action_id) ? (t->ip + 1) : ip->jmp.ip;
7099 instr_jmp_eq_exec(struct rte_swx_pipeline *p)
7101 struct thread *t = &p->threads[p->thread_id];
7102 struct instruction *ip = t->ip;
7104 TRACE("[Thread %2u] jmpeq\n", p->thread_id);
7110 instr_jmp_eq_s_exec(struct rte_swx_pipeline *p)
7112 struct thread *t = &p->threads[p->thread_id];
7113 struct instruction *ip = t->ip;
7115 TRACE("[Thread %2u] jmpeq (s)\n", p->thread_id);
7117 JMP_CMP_S(t, ip, ==);
7121 instr_jmp_eq_i_exec(struct rte_swx_pipeline *p)
7123 struct thread *t = &p->threads[p->thread_id];
7124 struct instruction *ip = t->ip;
7126 TRACE("[Thread %2u] jmpeq (i)\n", p->thread_id);
7128 JMP_CMP_I(t, ip, ==);
7132 instr_jmp_neq_exec(struct rte_swx_pipeline *p)
7134 struct thread *t = &p->threads[p->thread_id];
7135 struct instruction *ip = t->ip;
7137 TRACE("[Thread %2u] jmpneq\n", p->thread_id);
7143 instr_jmp_neq_s_exec(struct rte_swx_pipeline *p)
7145 struct thread *t = &p->threads[p->thread_id];
7146 struct instruction *ip = t->ip;
7148 TRACE("[Thread %2u] jmpneq (s)\n", p->thread_id);
7150 JMP_CMP_S(t, ip, !=);
7154 instr_jmp_neq_i_exec(struct rte_swx_pipeline *p)
7156 struct thread *t = &p->threads[p->thread_id];
7157 struct instruction *ip = t->ip;
7159 TRACE("[Thread %2u] jmpneq (i)\n", p->thread_id);
7161 JMP_CMP_I(t, ip, !=);
7165 instr_jmp_lt_exec(struct rte_swx_pipeline *p)
7167 struct thread *t = &p->threads[p->thread_id];
7168 struct instruction *ip = t->ip;
7170 TRACE("[Thread %2u] jmplt\n", p->thread_id);
7176 instr_jmp_lt_mh_exec(struct rte_swx_pipeline *p)
7178 struct thread *t = &p->threads[p->thread_id];
7179 struct instruction *ip = t->ip;
7181 TRACE("[Thread %2u] jmplt (mh)\n", p->thread_id);
7183 JMP_CMP_MH(t, ip, <);
7187 instr_jmp_lt_hm_exec(struct rte_swx_pipeline *p)
7189 struct thread *t = &p->threads[p->thread_id];
7190 struct instruction *ip = t->ip;
7192 TRACE("[Thread %2u] jmplt (hm)\n", p->thread_id);
7194 JMP_CMP_HM(t, ip, <);
7198 instr_jmp_lt_hh_exec(struct rte_swx_pipeline *p)
7200 struct thread *t = &p->threads[p->thread_id];
7201 struct instruction *ip = t->ip;
7203 TRACE("[Thread %2u] jmplt (hh)\n", p->thread_id);
7205 JMP_CMP_HH(t, ip, <);
7209 instr_jmp_lt_mi_exec(struct rte_swx_pipeline *p)
7211 struct thread *t = &p->threads[p->thread_id];
7212 struct instruction *ip = t->ip;
7214 TRACE("[Thread %2u] jmplt (mi)\n", p->thread_id);
7216 JMP_CMP_MI(t, ip, <);
7220 instr_jmp_lt_hi_exec(struct rte_swx_pipeline *p)
7222 struct thread *t = &p->threads[p->thread_id];
7223 struct instruction *ip = t->ip;
7225 TRACE("[Thread %2u] jmplt (hi)\n", p->thread_id);
7227 JMP_CMP_HI(t, ip, <);
7231 instr_jmp_gt_exec(struct rte_swx_pipeline *p)
7233 struct thread *t = &p->threads[p->thread_id];
7234 struct instruction *ip = t->ip;
7236 TRACE("[Thread %2u] jmpgt\n", p->thread_id);
7242 instr_jmp_gt_mh_exec(struct rte_swx_pipeline *p)
7244 struct thread *t = &p->threads[p->thread_id];
7245 struct instruction *ip = t->ip;
7247 TRACE("[Thread %2u] jmpgt (mh)\n", p->thread_id);
7249 JMP_CMP_MH(t, ip, >);
7253 instr_jmp_gt_hm_exec(struct rte_swx_pipeline *p)
7255 struct thread *t = &p->threads[p->thread_id];
7256 struct instruction *ip = t->ip;
7258 TRACE("[Thread %2u] jmpgt (hm)\n", p->thread_id);
7260 JMP_CMP_HM(t, ip, >);
7264 instr_jmp_gt_hh_exec(struct rte_swx_pipeline *p)
7266 struct thread *t = &p->threads[p->thread_id];
7267 struct instruction *ip = t->ip;
7269 TRACE("[Thread %2u] jmpgt (hh)\n", p->thread_id);
7271 JMP_CMP_HH(t, ip, >);
7275 instr_jmp_gt_mi_exec(struct rte_swx_pipeline *p)
7277 struct thread *t = &p->threads[p->thread_id];
7278 struct instruction *ip = t->ip;
7280 TRACE("[Thread %2u] jmpgt (mi)\n", p->thread_id);
7282 JMP_CMP_MI(t, ip, >);
7286 instr_jmp_gt_hi_exec(struct rte_swx_pipeline *p)
7288 struct thread *t = &p->threads[p->thread_id];
7289 struct instruction *ip = t->ip;
7291 TRACE("[Thread %2u] jmpgt (hi)\n", p->thread_id);
7293 JMP_CMP_HI(t, ip, >);
7300 instr_return_translate(struct rte_swx_pipeline *p __rte_unused,
7301 struct action *action,
7302 char **tokens __rte_unused,
7304 struct instruction *instr,
7305 struct instruction_data *data __rte_unused)
7307 CHECK(action, EINVAL);
7308 CHECK(n_tokens == 1, EINVAL);
7310 instr->type = INSTR_RETURN;
7315 instr_return_exec(struct rte_swx_pipeline *p)
7317 struct thread *t = &p->threads[p->thread_id];
7319 TRACE("[Thread %2u] return\n", p->thread_id);
7325 instr_translate(struct rte_swx_pipeline *p,
7326 struct action *action,
7328 struct instruction *instr,
7329 struct instruction_data *data)
7331 char *tokens[RTE_SWX_INSTRUCTION_TOKENS_MAX];
7332 int n_tokens = 0, tpos = 0;
7334 /* Parse the instruction string into tokens. */
7338 token = strtok_r(string, " \t\v", &string);
7342 CHECK(n_tokens < RTE_SWX_INSTRUCTION_TOKENS_MAX, EINVAL);
7343 CHECK_NAME(token, EINVAL);
7345 tokens[n_tokens] = token;
7349 CHECK(n_tokens, EINVAL);
7351 /* Handle the optional instruction label. */
7352 if ((n_tokens >= 2) && !strcmp(tokens[1], ":")) {
7353 strcpy(data->label, tokens[0]);
7356 CHECK(n_tokens - tpos, EINVAL);
7359 /* Identify the instruction type. */
7360 if (!strcmp(tokens[tpos], "rx"))
7361 return instr_rx_translate(p,
7368 if (!strcmp(tokens[tpos], "tx"))
7369 return instr_tx_translate(p,
7376 if (!strcmp(tokens[tpos], "drop"))
7377 return instr_drop_translate(p,
7384 if (!strcmp(tokens[tpos], "extract"))
7385 return instr_hdr_extract_translate(p,
7392 if (!strcmp(tokens[tpos], "emit"))
7393 return instr_hdr_emit_translate(p,
7400 if (!strcmp(tokens[tpos], "validate"))
7401 return instr_hdr_validate_translate(p,
7408 if (!strcmp(tokens[tpos], "invalidate"))
7409 return instr_hdr_invalidate_translate(p,
7416 if (!strcmp(tokens[tpos], "mov"))
7417 return instr_mov_translate(p,
7424 if (!strcmp(tokens[tpos], "dma"))
7425 return instr_dma_translate(p,
7432 if (!strcmp(tokens[tpos], "add"))
7433 return instr_alu_add_translate(p,
7440 if (!strcmp(tokens[tpos], "sub"))
7441 return instr_alu_sub_translate(p,
7448 if (!strcmp(tokens[tpos], "ckadd"))
7449 return instr_alu_ckadd_translate(p,
7456 if (!strcmp(tokens[tpos], "cksub"))
7457 return instr_alu_cksub_translate(p,
7464 if (!strcmp(tokens[tpos], "and"))
7465 return instr_alu_and_translate(p,
7472 if (!strcmp(tokens[tpos], "or"))
7473 return instr_alu_or_translate(p,
7480 if (!strcmp(tokens[tpos], "xor"))
7481 return instr_alu_xor_translate(p,
7488 if (!strcmp(tokens[tpos], "shl"))
7489 return instr_alu_shl_translate(p,
7496 if (!strcmp(tokens[tpos], "shr"))
7497 return instr_alu_shr_translate(p,
7504 if (!strcmp(tokens[tpos], "regprefetch"))
7505 return instr_regprefetch_translate(p,
7512 if (!strcmp(tokens[tpos], "regrd"))
7513 return instr_regrd_translate(p,
7520 if (!strcmp(tokens[tpos], "regwr"))
7521 return instr_regwr_translate(p,
7528 if (!strcmp(tokens[tpos], "regadd"))
7529 return instr_regadd_translate(p,
7536 if (!strcmp(tokens[tpos], "metprefetch"))
7537 return instr_metprefetch_translate(p,
7544 if (!strcmp(tokens[tpos], "meter"))
7545 return instr_meter_translate(p,
7552 if (!strcmp(tokens[tpos], "table"))
7553 return instr_table_translate(p,
7560 if (!strcmp(tokens[tpos], "extern"))
7561 return instr_extern_translate(p,
7568 if (!strcmp(tokens[tpos], "jmp"))
7569 return instr_jmp_translate(p,
7576 if (!strcmp(tokens[tpos], "jmpv"))
7577 return instr_jmp_valid_translate(p,
7584 if (!strcmp(tokens[tpos], "jmpnv"))
7585 return instr_jmp_invalid_translate(p,
7592 if (!strcmp(tokens[tpos], "jmph"))
7593 return instr_jmp_hit_translate(p,
7600 if (!strcmp(tokens[tpos], "jmpnh"))
7601 return instr_jmp_miss_translate(p,
7608 if (!strcmp(tokens[tpos], "jmpa"))
7609 return instr_jmp_action_hit_translate(p,
7616 if (!strcmp(tokens[tpos], "jmpna"))
7617 return instr_jmp_action_miss_translate(p,
7624 if (!strcmp(tokens[tpos], "jmpeq"))
7625 return instr_jmp_eq_translate(p,
7632 if (!strcmp(tokens[tpos], "jmpneq"))
7633 return instr_jmp_neq_translate(p,
7640 if (!strcmp(tokens[tpos], "jmplt"))
7641 return instr_jmp_lt_translate(p,
7648 if (!strcmp(tokens[tpos], "jmpgt"))
7649 return instr_jmp_gt_translate(p,
7656 if (!strcmp(tokens[tpos], "return"))
7657 return instr_return_translate(p,
7667 static struct instruction_data *
7668 label_find(struct instruction_data *data, uint32_t n, const char *label)
7672 for (i = 0; i < n; i++)
7673 if (!strcmp(label, data[i].label))
7680 label_is_used(struct instruction_data *data, uint32_t n, const char *label)
7682 uint32_t count = 0, i;
7687 for (i = 0; i < n; i++)
7688 if (!strcmp(label, data[i].jmp_label))
7695 instr_label_check(struct instruction_data *instruction_data,
7696 uint32_t n_instructions)
7700 /* Check that all instruction labels are unique. */
7701 for (i = 0; i < n_instructions; i++) {
7702 struct instruction_data *data = &instruction_data[i];
7703 char *label = data->label;
7709 for (j = i + 1; j < n_instructions; j++)
7710 CHECK(strcmp(label, data[j].label), EINVAL);
7713 /* Get users for each instruction label. */
7714 for (i = 0; i < n_instructions; i++) {
7715 struct instruction_data *data = &instruction_data[i];
7716 char *label = data->label;
7718 data->n_users = label_is_used(instruction_data,
7727 instr_jmp_resolve(struct instruction *instructions,
7728 struct instruction_data *instruction_data,
7729 uint32_t n_instructions)
7733 for (i = 0; i < n_instructions; i++) {
7734 struct instruction *instr = &instructions[i];
7735 struct instruction_data *data = &instruction_data[i];
7736 struct instruction_data *found;
7738 if (!instruction_is_jmp(instr))
7741 found = label_find(instruction_data,
7744 CHECK(found, EINVAL);
7746 instr->jmp.ip = &instructions[found - instruction_data];
7753 instr_verify(struct rte_swx_pipeline *p __rte_unused,
7755 struct instruction *instr,
7756 struct instruction_data *data __rte_unused,
7757 uint32_t n_instructions)
7760 enum instruction_type type;
7763 /* Check that the first instruction is rx. */
7764 CHECK(instr[0].type == INSTR_RX, EINVAL);
7766 /* Check that there is at least one tx instruction. */
7767 for (i = 0; i < n_instructions; i++) {
7768 type = instr[i].type;
7770 if (instruction_is_tx(type))
7773 CHECK(i < n_instructions, EINVAL);
7775 /* Check that the last instruction is either tx or unconditional
7778 type = instr[n_instructions - 1].type;
7779 CHECK(instruction_is_tx(type) || (type == INSTR_JMP), EINVAL);
7783 enum instruction_type type;
7786 /* Check that there is at least one return or tx instruction. */
7787 for (i = 0; i < n_instructions; i++) {
7788 type = instr[i].type;
7790 if ((type == INSTR_RETURN) || instruction_is_tx(type))
7793 CHECK(i < n_instructions, EINVAL);
7800 instr_pattern_extract_many_detect(struct instruction *instr,
7801 struct instruction_data *data,
7803 uint32_t *n_pattern_instr)
7807 for (i = 0; i < n_instr; i++) {
7808 if (data[i].invalid)
7811 if (instr[i].type != INSTR_HDR_EXTRACT)
7814 if (i == RTE_DIM(instr->io.hdr.header_id))
7817 if (i && data[i].n_users)
7824 *n_pattern_instr = i;
7829 instr_pattern_extract_many_optimize(struct instruction *instr,
7830 struct instruction_data *data,
7835 for (i = 1; i < n_instr; i++) {
7837 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
7838 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
7839 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
7841 data[i].invalid = 1;
7846 instr_pattern_emit_many_tx_detect(struct instruction *instr,
7847 struct instruction_data *data,
7849 uint32_t *n_pattern_instr)
7853 for (i = 0; i < n_instr; i++) {
7854 if (data[i].invalid)
7857 if (instr[i].type != INSTR_HDR_EMIT)
7860 if (i == RTE_DIM(instr->io.hdr.header_id))
7863 if (i && data[i].n_users)
7870 if (!instruction_is_tx(instr[i].type))
7873 if (data[i].n_users)
7878 *n_pattern_instr = i;
7883 instr_pattern_emit_many_tx_optimize(struct instruction *instr,
7884 struct instruction_data *data,
7889 /* Any emit instruction in addition to the first one. */
7890 for (i = 1; i < n_instr - 1; i++) {
7892 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
7893 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
7894 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
7896 data[i].invalid = 1;
7899 /* The TX instruction is the last one in the pattern. */
7901 instr[0].io.io.offset = instr[i].io.io.offset;
7902 instr[0].io.io.n_bits = instr[i].io.io.n_bits;
7903 data[i].invalid = 1;
7907 instr_pattern_dma_many_detect(struct instruction *instr,
7908 struct instruction_data *data,
7910 uint32_t *n_pattern_instr)
7914 for (i = 0; i < n_instr; i++) {
7915 if (data[i].invalid)
7918 if (instr[i].type != INSTR_DMA_HT)
7921 if (i == RTE_DIM(instr->dma.dst.header_id))
7924 if (i && data[i].n_users)
7931 *n_pattern_instr = i;
7936 instr_pattern_dma_many_optimize(struct instruction *instr,
7937 struct instruction_data *data,
7942 for (i = 1; i < n_instr; i++) {
7944 instr[0].dma.dst.header_id[i] = instr[i].dma.dst.header_id[0];
7945 instr[0].dma.dst.struct_id[i] = instr[i].dma.dst.struct_id[0];
7946 instr[0].dma.src.offset[i] = instr[i].dma.src.offset[0];
7947 instr[0].dma.n_bytes[i] = instr[i].dma.n_bytes[0];
7949 data[i].invalid = 1;
7954 instr_optimize(struct instruction *instructions,
7955 struct instruction_data *instruction_data,
7956 uint32_t n_instructions)
7958 uint32_t i, pos = 0;
7960 for (i = 0; i < n_instructions; ) {
7961 struct instruction *instr = &instructions[i];
7962 struct instruction_data *data = &instruction_data[i];
7963 uint32_t n_instr = 0;
7967 detected = instr_pattern_extract_many_detect(instr,
7972 instr_pattern_extract_many_optimize(instr,
7979 /* Emit many + TX. */
7980 detected = instr_pattern_emit_many_tx_detect(instr,
7985 instr_pattern_emit_many_tx_optimize(instr,
7993 detected = instr_pattern_dma_many_detect(instr,
7998 instr_pattern_dma_many_optimize(instr, data, n_instr);
8003 /* No pattern starting at the current instruction. */
8007 /* Eliminate the invalid instructions that have been optimized out. */
8008 for (i = 0; i < n_instructions; i++) {
8009 struct instruction *instr = &instructions[i];
8010 struct instruction_data *data = &instruction_data[i];
8016 memcpy(&instructions[pos], instr, sizeof(*instr));
8017 memcpy(&instruction_data[pos], data, sizeof(*data));
8027 instruction_config(struct rte_swx_pipeline *p,
8029 const char **instructions,
8030 uint32_t n_instructions)
8032 struct instruction *instr = NULL;
8033 struct instruction_data *data = NULL;
8037 CHECK(n_instructions, EINVAL);
8038 CHECK(instructions, EINVAL);
8039 for (i = 0; i < n_instructions; i++)
8040 CHECK_INSTRUCTION(instructions[i], EINVAL);
8042 /* Memory allocation. */
8043 instr = calloc(n_instructions, sizeof(struct instruction));
8049 data = calloc(n_instructions, sizeof(struct instruction_data));
8055 for (i = 0; i < n_instructions; i++) {
8056 char *string = strdup(instructions[i]);
8062 err = instr_translate(p, a, string, &instr[i], &data[i]);
8071 err = instr_label_check(data, n_instructions);
8075 err = instr_verify(p, a, instr, data, n_instructions);
8079 n_instructions = instr_optimize(instr, data, n_instructions);
8081 err = instr_jmp_resolve(instr, data, n_instructions);
8086 a->instructions = instr;
8087 a->n_instructions = n_instructions;
8089 p->instructions = instr;
8090 p->n_instructions = n_instructions;
8102 typedef void (*instr_exec_t)(struct rte_swx_pipeline *);
8104 static instr_exec_t instruction_table[] = {
8105 [INSTR_RX] = instr_rx_exec,
8106 [INSTR_TX] = instr_tx_exec,
8107 [INSTR_TX_I] = instr_tx_i_exec,
8109 [INSTR_HDR_EXTRACT] = instr_hdr_extract_exec,
8110 [INSTR_HDR_EXTRACT2] = instr_hdr_extract2_exec,
8111 [INSTR_HDR_EXTRACT3] = instr_hdr_extract3_exec,
8112 [INSTR_HDR_EXTRACT4] = instr_hdr_extract4_exec,
8113 [INSTR_HDR_EXTRACT5] = instr_hdr_extract5_exec,
8114 [INSTR_HDR_EXTRACT6] = instr_hdr_extract6_exec,
8115 [INSTR_HDR_EXTRACT7] = instr_hdr_extract7_exec,
8116 [INSTR_HDR_EXTRACT8] = instr_hdr_extract8_exec,
8118 [INSTR_HDR_EMIT] = instr_hdr_emit_exec,
8119 [INSTR_HDR_EMIT_TX] = instr_hdr_emit_tx_exec,
8120 [INSTR_HDR_EMIT2_TX] = instr_hdr_emit2_tx_exec,
8121 [INSTR_HDR_EMIT3_TX] = instr_hdr_emit3_tx_exec,
8122 [INSTR_HDR_EMIT4_TX] = instr_hdr_emit4_tx_exec,
8123 [INSTR_HDR_EMIT5_TX] = instr_hdr_emit5_tx_exec,
8124 [INSTR_HDR_EMIT6_TX] = instr_hdr_emit6_tx_exec,
8125 [INSTR_HDR_EMIT7_TX] = instr_hdr_emit7_tx_exec,
8126 [INSTR_HDR_EMIT8_TX] = instr_hdr_emit8_tx_exec,
8128 [INSTR_HDR_VALIDATE] = instr_hdr_validate_exec,
8129 [INSTR_HDR_INVALIDATE] = instr_hdr_invalidate_exec,
8131 [INSTR_MOV] = instr_mov_exec,
8132 [INSTR_MOV_S] = instr_mov_s_exec,
8133 [INSTR_MOV_I] = instr_mov_i_exec,
8135 [INSTR_DMA_HT] = instr_dma_ht_exec,
8136 [INSTR_DMA_HT2] = instr_dma_ht2_exec,
8137 [INSTR_DMA_HT3] = instr_dma_ht3_exec,
8138 [INSTR_DMA_HT4] = instr_dma_ht4_exec,
8139 [INSTR_DMA_HT5] = instr_dma_ht5_exec,
8140 [INSTR_DMA_HT6] = instr_dma_ht6_exec,
8141 [INSTR_DMA_HT7] = instr_dma_ht7_exec,
8142 [INSTR_DMA_HT8] = instr_dma_ht8_exec,
8144 [INSTR_ALU_ADD] = instr_alu_add_exec,
8145 [INSTR_ALU_ADD_MH] = instr_alu_add_mh_exec,
8146 [INSTR_ALU_ADD_HM] = instr_alu_add_hm_exec,
8147 [INSTR_ALU_ADD_HH] = instr_alu_add_hh_exec,
8148 [INSTR_ALU_ADD_MI] = instr_alu_add_mi_exec,
8149 [INSTR_ALU_ADD_HI] = instr_alu_add_hi_exec,
8151 [INSTR_ALU_SUB] = instr_alu_sub_exec,
8152 [INSTR_ALU_SUB_MH] = instr_alu_sub_mh_exec,
8153 [INSTR_ALU_SUB_HM] = instr_alu_sub_hm_exec,
8154 [INSTR_ALU_SUB_HH] = instr_alu_sub_hh_exec,
8155 [INSTR_ALU_SUB_MI] = instr_alu_sub_mi_exec,
8156 [INSTR_ALU_SUB_HI] = instr_alu_sub_hi_exec,
8158 [INSTR_ALU_CKADD_FIELD] = instr_alu_ckadd_field_exec,
8159 [INSTR_ALU_CKADD_STRUCT] = instr_alu_ckadd_struct_exec,
8160 [INSTR_ALU_CKADD_STRUCT20] = instr_alu_ckadd_struct20_exec,
8161 [INSTR_ALU_CKSUB_FIELD] = instr_alu_cksub_field_exec,
8163 [INSTR_ALU_AND] = instr_alu_and_exec,
8164 [INSTR_ALU_AND_S] = instr_alu_and_s_exec,
8165 [INSTR_ALU_AND_I] = instr_alu_and_i_exec,
8167 [INSTR_ALU_OR] = instr_alu_or_exec,
8168 [INSTR_ALU_OR_S] = instr_alu_or_s_exec,
8169 [INSTR_ALU_OR_I] = instr_alu_or_i_exec,
8171 [INSTR_ALU_XOR] = instr_alu_xor_exec,
8172 [INSTR_ALU_XOR_S] = instr_alu_xor_s_exec,
8173 [INSTR_ALU_XOR_I] = instr_alu_xor_i_exec,
8175 [INSTR_ALU_SHL] = instr_alu_shl_exec,
8176 [INSTR_ALU_SHL_MH] = instr_alu_shl_mh_exec,
8177 [INSTR_ALU_SHL_HM] = instr_alu_shl_hm_exec,
8178 [INSTR_ALU_SHL_HH] = instr_alu_shl_hh_exec,
8179 [INSTR_ALU_SHL_MI] = instr_alu_shl_mi_exec,
8180 [INSTR_ALU_SHL_HI] = instr_alu_shl_hi_exec,
8182 [INSTR_ALU_SHR] = instr_alu_shr_exec,
8183 [INSTR_ALU_SHR_MH] = instr_alu_shr_mh_exec,
8184 [INSTR_ALU_SHR_HM] = instr_alu_shr_hm_exec,
8185 [INSTR_ALU_SHR_HH] = instr_alu_shr_hh_exec,
8186 [INSTR_ALU_SHR_MI] = instr_alu_shr_mi_exec,
8187 [INSTR_ALU_SHR_HI] = instr_alu_shr_hi_exec,
8189 [INSTR_REGPREFETCH_RH] = instr_regprefetch_rh_exec,
8190 [INSTR_REGPREFETCH_RM] = instr_regprefetch_rm_exec,
8191 [INSTR_REGPREFETCH_RI] = instr_regprefetch_ri_exec,
8193 [INSTR_REGRD_HRH] = instr_regrd_hrh_exec,
8194 [INSTR_REGRD_HRM] = instr_regrd_hrm_exec,
8195 [INSTR_REGRD_MRH] = instr_regrd_mrh_exec,
8196 [INSTR_REGRD_MRM] = instr_regrd_mrm_exec,
8197 [INSTR_REGRD_HRI] = instr_regrd_hri_exec,
8198 [INSTR_REGRD_MRI] = instr_regrd_mri_exec,
8200 [INSTR_REGWR_RHH] = instr_regwr_rhh_exec,
8201 [INSTR_REGWR_RHM] = instr_regwr_rhm_exec,
8202 [INSTR_REGWR_RMH] = instr_regwr_rmh_exec,
8203 [INSTR_REGWR_RMM] = instr_regwr_rmm_exec,
8204 [INSTR_REGWR_RHI] = instr_regwr_rhi_exec,
8205 [INSTR_REGWR_RMI] = instr_regwr_rmi_exec,
8206 [INSTR_REGWR_RIH] = instr_regwr_rih_exec,
8207 [INSTR_REGWR_RIM] = instr_regwr_rim_exec,
8208 [INSTR_REGWR_RII] = instr_regwr_rii_exec,
8210 [INSTR_REGADD_RHH] = instr_regadd_rhh_exec,
8211 [INSTR_REGADD_RHM] = instr_regadd_rhm_exec,
8212 [INSTR_REGADD_RMH] = instr_regadd_rmh_exec,
8213 [INSTR_REGADD_RMM] = instr_regadd_rmm_exec,
8214 [INSTR_REGADD_RHI] = instr_regadd_rhi_exec,
8215 [INSTR_REGADD_RMI] = instr_regadd_rmi_exec,
8216 [INSTR_REGADD_RIH] = instr_regadd_rih_exec,
8217 [INSTR_REGADD_RIM] = instr_regadd_rim_exec,
8218 [INSTR_REGADD_RII] = instr_regadd_rii_exec,
8220 [INSTR_METPREFETCH_H] = instr_metprefetch_h_exec,
8221 [INSTR_METPREFETCH_M] = instr_metprefetch_m_exec,
8222 [INSTR_METPREFETCH_I] = instr_metprefetch_i_exec,
8224 [INSTR_METER_HHM] = instr_meter_hhm_exec,
8225 [INSTR_METER_HHI] = instr_meter_hhi_exec,
8226 [INSTR_METER_HMM] = instr_meter_hmm_exec,
8227 [INSTR_METER_HMI] = instr_meter_hmi_exec,
8228 [INSTR_METER_MHM] = instr_meter_mhm_exec,
8229 [INSTR_METER_MHI] = instr_meter_mhi_exec,
8230 [INSTR_METER_MMM] = instr_meter_mmm_exec,
8231 [INSTR_METER_MMI] = instr_meter_mmi_exec,
8232 [INSTR_METER_IHM] = instr_meter_ihm_exec,
8233 [INSTR_METER_IHI] = instr_meter_ihi_exec,
8234 [INSTR_METER_IMM] = instr_meter_imm_exec,
8235 [INSTR_METER_IMI] = instr_meter_imi_exec,
8237 [INSTR_TABLE] = instr_table_exec,
8238 [INSTR_EXTERN_OBJ] = instr_extern_obj_exec,
8239 [INSTR_EXTERN_FUNC] = instr_extern_func_exec,
8241 [INSTR_JMP] = instr_jmp_exec,
8242 [INSTR_JMP_VALID] = instr_jmp_valid_exec,
8243 [INSTR_JMP_INVALID] = instr_jmp_invalid_exec,
8244 [INSTR_JMP_HIT] = instr_jmp_hit_exec,
8245 [INSTR_JMP_MISS] = instr_jmp_miss_exec,
8246 [INSTR_JMP_ACTION_HIT] = instr_jmp_action_hit_exec,
8247 [INSTR_JMP_ACTION_MISS] = instr_jmp_action_miss_exec,
8249 [INSTR_JMP_EQ] = instr_jmp_eq_exec,
8250 [INSTR_JMP_EQ_S] = instr_jmp_eq_s_exec,
8251 [INSTR_JMP_EQ_I] = instr_jmp_eq_i_exec,
8253 [INSTR_JMP_NEQ] = instr_jmp_neq_exec,
8254 [INSTR_JMP_NEQ_S] = instr_jmp_neq_s_exec,
8255 [INSTR_JMP_NEQ_I] = instr_jmp_neq_i_exec,
8257 [INSTR_JMP_LT] = instr_jmp_lt_exec,
8258 [INSTR_JMP_LT_MH] = instr_jmp_lt_mh_exec,
8259 [INSTR_JMP_LT_HM] = instr_jmp_lt_hm_exec,
8260 [INSTR_JMP_LT_HH] = instr_jmp_lt_hh_exec,
8261 [INSTR_JMP_LT_MI] = instr_jmp_lt_mi_exec,
8262 [INSTR_JMP_LT_HI] = instr_jmp_lt_hi_exec,
8264 [INSTR_JMP_GT] = instr_jmp_gt_exec,
8265 [INSTR_JMP_GT_MH] = instr_jmp_gt_mh_exec,
8266 [INSTR_JMP_GT_HM] = instr_jmp_gt_hm_exec,
8267 [INSTR_JMP_GT_HH] = instr_jmp_gt_hh_exec,
8268 [INSTR_JMP_GT_MI] = instr_jmp_gt_mi_exec,
8269 [INSTR_JMP_GT_HI] = instr_jmp_gt_hi_exec,
8271 [INSTR_RETURN] = instr_return_exec,
8275 instr_exec(struct rte_swx_pipeline *p)
8277 struct thread *t = &p->threads[p->thread_id];
8278 struct instruction *ip = t->ip;
8279 instr_exec_t instr = instruction_table[ip->type];
8287 static struct action *
8288 action_find(struct rte_swx_pipeline *p, const char *name)
8290 struct action *elem;
8295 TAILQ_FOREACH(elem, &p->actions, node)
8296 if (strcmp(elem->name, name) == 0)
8302 static struct action *
8303 action_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8305 struct action *action = NULL;
8307 TAILQ_FOREACH(action, &p->actions, node)
8308 if (action->id == id)
8314 static struct field *
8315 action_field_find(struct action *a, const char *name)
8317 return a->st ? struct_type_field_find(a->st, name) : NULL;
8320 static struct field *
8321 action_field_parse(struct action *action, const char *name)
8323 if (name[0] != 't' || name[1] != '.')
8326 return action_field_find(action, &name[2]);
8330 rte_swx_pipeline_action_config(struct rte_swx_pipeline *p,
8332 const char *args_struct_type_name,
8333 const char **instructions,
8334 uint32_t n_instructions)
8336 struct struct_type *args_struct_type;
8342 CHECK_NAME(name, EINVAL);
8343 CHECK(!action_find(p, name), EEXIST);
8345 if (args_struct_type_name) {
8346 CHECK_NAME(args_struct_type_name, EINVAL);
8347 args_struct_type = struct_type_find(p, args_struct_type_name);
8348 CHECK(args_struct_type, EINVAL);
8350 args_struct_type = NULL;
8353 /* Node allocation. */
8354 a = calloc(1, sizeof(struct action));
8357 /* Node initialization. */
8358 strcpy(a->name, name);
8359 a->st = args_struct_type;
8360 a->id = p->n_actions;
8362 /* Instruction translation. */
8363 err = instruction_config(p, a, instructions, n_instructions);
8369 /* Node add to tailq. */
8370 TAILQ_INSERT_TAIL(&p->actions, a, node);
8377 action_build(struct rte_swx_pipeline *p)
8379 struct action *action;
8381 p->action_instructions = calloc(p->n_actions,
8382 sizeof(struct instruction *));
8383 CHECK(p->action_instructions, ENOMEM);
8385 TAILQ_FOREACH(action, &p->actions, node)
8386 p->action_instructions[action->id] = action->instructions;
8392 action_build_free(struct rte_swx_pipeline *p)
8394 free(p->action_instructions);
8395 p->action_instructions = NULL;
8399 action_free(struct rte_swx_pipeline *p)
8401 action_build_free(p);
8404 struct action *action;
8406 action = TAILQ_FIRST(&p->actions);
8410 TAILQ_REMOVE(&p->actions, action, node);
8411 free(action->instructions);
8419 static struct table_type *
8420 table_type_find(struct rte_swx_pipeline *p, const char *name)
8422 struct table_type *elem;
8424 TAILQ_FOREACH(elem, &p->table_types, node)
8425 if (strcmp(elem->name, name) == 0)
8431 static struct table_type *
8432 table_type_resolve(struct rte_swx_pipeline *p,
8433 const char *recommended_type_name,
8434 enum rte_swx_table_match_type match_type)
8436 struct table_type *elem;
8438 /* Only consider the recommended type if the match type is correct. */
8439 if (recommended_type_name)
8440 TAILQ_FOREACH(elem, &p->table_types, node)
8441 if (!strcmp(elem->name, recommended_type_name) &&
8442 (elem->match_type == match_type))
8445 /* Ignore the recommended type and get the first element with this match
8448 TAILQ_FOREACH(elem, &p->table_types, node)
8449 if (elem->match_type == match_type)
8455 static struct table *
8456 table_find(struct rte_swx_pipeline *p, const char *name)
8460 TAILQ_FOREACH(elem, &p->tables, node)
8461 if (strcmp(elem->name, name) == 0)
8467 static struct table *
8468 table_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8470 struct table *table = NULL;
8472 TAILQ_FOREACH(table, &p->tables, node)
8473 if (table->id == id)
8480 rte_swx_pipeline_table_type_register(struct rte_swx_pipeline *p,
8482 enum rte_swx_table_match_type match_type,
8483 struct rte_swx_table_ops *ops)
8485 struct table_type *elem;
8489 CHECK_NAME(name, EINVAL);
8490 CHECK(!table_type_find(p, name), EEXIST);
8493 CHECK(ops->create, EINVAL);
8494 CHECK(ops->lkp, EINVAL);
8495 CHECK(ops->free, EINVAL);
8497 /* Node allocation. */
8498 elem = calloc(1, sizeof(struct table_type));
8499 CHECK(elem, ENOMEM);
8501 /* Node initialization. */
8502 strcpy(elem->name, name);
8503 elem->match_type = match_type;
8504 memcpy(&elem->ops, ops, sizeof(*ops));
8506 /* Node add to tailq. */
8507 TAILQ_INSERT_TAIL(&p->table_types, elem, node);
8512 static enum rte_swx_table_match_type
8513 table_match_type_resolve(struct rte_swx_match_field_params *fields,
8515 uint32_t max_offset_field_id)
8517 uint32_t n_fields_em = 0, i;
8519 for (i = 0; i < n_fields; i++)
8520 if (fields[i].match_type == RTE_SWX_TABLE_MATCH_EXACT)
8523 if (n_fields_em == n_fields)
8524 return RTE_SWX_TABLE_MATCH_EXACT;
8526 if ((n_fields_em == n_fields - 1) &&
8527 (fields[max_offset_field_id].match_type == RTE_SWX_TABLE_MATCH_LPM))
8528 return RTE_SWX_TABLE_MATCH_LPM;
8530 return RTE_SWX_TABLE_MATCH_WILDCARD;
8534 table_match_fields_check(struct rte_swx_pipeline *p,
8535 struct rte_swx_pipeline_table_params *params,
8536 struct header **header,
8537 uint32_t *min_offset_field_id,
8538 uint32_t *max_offset_field_id)
8540 struct header *h0 = NULL;
8541 struct field *hf, *mf;
8542 uint32_t *offset = NULL, min_offset, max_offset, min_offset_pos, max_offset_pos, i;
8545 /* Return if no match fields. */
8546 if (!params->n_fields) {
8547 if (params->fields) {
8555 /* Memory allocation. */
8556 offset = calloc(params->n_fields, sizeof(uint32_t));
8562 /* Check that all the match fields belong to either the same header or
8565 hf = header_field_parse(p, params->fields[0].name, &h0);
8566 mf = metadata_field_parse(p, params->fields[0].name);
8572 offset[0] = h0 ? hf->offset : mf->offset;
8574 for (i = 1; i < params->n_fields; i++)
8578 hf = header_field_parse(p, params->fields[i].name, &h);
8579 if (!hf || (h->id != h0->id)) {
8584 offset[i] = hf->offset;
8586 mf = metadata_field_parse(p, params->fields[i].name);
8592 offset[i] = mf->offset;
8595 /* Check that there are no duplicated match fields. */
8596 for (i = 0; i < params->n_fields; i++) {
8599 for (j = 0; j < i; j++)
8600 if (offset[j] == offset[i]) {
8606 /* Find the min and max offset fields. */
8607 min_offset = offset[0];
8608 max_offset = offset[0];
8612 for (i = 1; i < params->n_fields; i++) {
8613 if (offset[i] < min_offset) {
8614 min_offset = offset[i];
8618 if (offset[i] > max_offset) {
8619 max_offset = offset[i];
8628 if (min_offset_field_id)
8629 *min_offset_field_id = min_offset_pos;
8631 if (max_offset_field_id)
8632 *max_offset_field_id = max_offset_pos;
8640 rte_swx_pipeline_table_config(struct rte_swx_pipeline *p,
8642 struct rte_swx_pipeline_table_params *params,
8643 const char *recommended_table_type_name,
8647 struct table_type *type;
8649 struct action *default_action;
8650 struct header *header = NULL;
8651 uint32_t action_data_size_max = 0, min_offset_field_id = 0, max_offset_field_id = 0, i;
8656 CHECK_NAME(name, EINVAL);
8657 CHECK(!table_find(p, name), EEXIST);
8659 CHECK(params, EINVAL);
8662 status = table_match_fields_check(p,
8665 &min_offset_field_id,
8666 &max_offset_field_id);
8670 /* Action checks. */
8671 CHECK(params->n_actions, EINVAL);
8672 CHECK(params->action_names, EINVAL);
8673 for (i = 0; i < params->n_actions; i++) {
8674 const char *action_name = params->action_names[i];
8676 uint32_t action_data_size;
8678 CHECK_NAME(action_name, EINVAL);
8680 a = action_find(p, action_name);
8683 action_data_size = a->st ? a->st->n_bits / 8 : 0;
8684 if (action_data_size > action_data_size_max)
8685 action_data_size_max = action_data_size;
8688 CHECK_NAME(params->default_action_name, EINVAL);
8689 for (i = 0; i < p->n_actions; i++)
8690 if (!strcmp(params->action_names[i],
8691 params->default_action_name))
8693 CHECK(i < params->n_actions, EINVAL);
8694 default_action = action_find(p, params->default_action_name);
8695 CHECK((default_action->st && params->default_action_data) ||
8696 !params->default_action_data, EINVAL);
8698 /* Table type checks. */
8699 if (recommended_table_type_name)
8700 CHECK_NAME(recommended_table_type_name, EINVAL);
8702 if (params->n_fields) {
8703 enum rte_swx_table_match_type match_type;
8705 match_type = table_match_type_resolve(params->fields,
8707 max_offset_field_id);
8708 type = table_type_resolve(p,
8709 recommended_table_type_name,
8711 CHECK(type, EINVAL);
8716 /* Memory allocation. */
8717 t = calloc(1, sizeof(struct table));
8720 t->fields = calloc(params->n_fields, sizeof(struct match_field));
8726 t->actions = calloc(params->n_actions, sizeof(struct action *));
8733 if (action_data_size_max) {
8734 t->default_action_data = calloc(1, action_data_size_max);
8735 if (!t->default_action_data) {
8743 /* Node initialization. */
8744 strcpy(t->name, name);
8745 if (args && args[0])
8746 strcpy(t->args, args);
8749 for (i = 0; i < params->n_fields; i++) {
8750 struct rte_swx_match_field_params *field = ¶ms->fields[i];
8751 struct match_field *f = &t->fields[i];
8753 f->match_type = field->match_type;
8755 header_field_parse(p, field->name, NULL) :
8756 metadata_field_parse(p, field->name);
8758 t->n_fields = params->n_fields;
8761 for (i = 0; i < params->n_actions; i++)
8762 t->actions[i] = action_find(p, params->action_names[i]);
8763 t->default_action = default_action;
8764 if (default_action->st)
8765 memcpy(t->default_action_data,
8766 params->default_action_data,
8767 default_action->st->n_bits / 8);
8768 t->n_actions = params->n_actions;
8769 t->default_action_is_const = params->default_action_is_const;
8770 t->action_data_size_max = action_data_size_max;
8773 t->id = p->n_tables;
8775 /* Node add to tailq. */
8776 TAILQ_INSERT_TAIL(&p->tables, t, node);
8782 static struct rte_swx_table_params *
8783 table_params_get(struct table *table)
8785 struct rte_swx_table_params *params;
8786 struct field *first, *last;
8788 uint32_t key_size, key_offset, action_data_size, i;
8790 /* Memory allocation. */
8791 params = calloc(1, sizeof(struct rte_swx_table_params));
8795 /* Find first (smallest offset) and last (biggest offset) match fields. */
8796 first = table->fields[0].field;
8797 last = table->fields[0].field;
8799 for (i = 0; i < table->n_fields; i++) {
8800 struct field *f = table->fields[i].field;
8802 if (f->offset < first->offset)
8805 if (f->offset > last->offset)
8809 /* Key offset and size. */
8810 key_offset = first->offset / 8;
8811 key_size = (last->offset + last->n_bits - first->offset) / 8;
8813 /* Memory allocation. */
8814 key_mask = calloc(1, key_size);
8821 for (i = 0; i < table->n_fields; i++) {
8822 struct field *f = table->fields[i].field;
8823 uint32_t start = (f->offset - first->offset) / 8;
8824 size_t size = f->n_bits / 8;
8826 memset(&key_mask[start], 0xFF, size);
8829 /* Action data size. */
8830 action_data_size = 0;
8831 for (i = 0; i < table->n_actions; i++) {
8832 struct action *action = table->actions[i];
8833 uint32_t ads = action->st ? action->st->n_bits / 8 : 0;
8835 if (ads > action_data_size)
8836 action_data_size = ads;
8840 params->match_type = table->type->match_type;
8841 params->key_size = key_size;
8842 params->key_offset = key_offset;
8843 params->key_mask0 = key_mask;
8844 params->action_data_size = action_data_size;
8845 params->n_keys_max = table->size;
8851 table_params_free(struct rte_swx_table_params *params)
8856 free(params->key_mask0);
8861 table_state_build(struct rte_swx_pipeline *p)
8863 struct table *table;
8865 p->table_state = calloc(p->n_tables,
8866 sizeof(struct rte_swx_table_state));
8867 CHECK(p->table_state, ENOMEM);
8869 TAILQ_FOREACH(table, &p->tables, node) {
8870 struct rte_swx_table_state *ts = &p->table_state[table->id];
8873 struct rte_swx_table_params *params;
8876 params = table_params_get(table);
8877 CHECK(params, ENOMEM);
8879 ts->obj = table->type->ops.create(params,
8884 table_params_free(params);
8885 CHECK(ts->obj, ENODEV);
8888 /* ts->default_action_data. */
8889 if (table->action_data_size_max) {
8890 ts->default_action_data =
8891 malloc(table->action_data_size_max);
8892 CHECK(ts->default_action_data, ENOMEM);
8894 memcpy(ts->default_action_data,
8895 table->default_action_data,
8896 table->action_data_size_max);
8899 /* ts->default_action_id. */
8900 ts->default_action_id = table->default_action->id;
8907 table_state_build_free(struct rte_swx_pipeline *p)
8911 if (!p->table_state)
8914 for (i = 0; i < p->n_tables; i++) {
8915 struct rte_swx_table_state *ts = &p->table_state[i];
8916 struct table *table = table_find_by_id(p, i);
8919 if (table->type && ts->obj)
8920 table->type->ops.free(ts->obj);
8922 /* ts->default_action_data. */
8923 free(ts->default_action_data);
8926 free(p->table_state);
8927 p->table_state = NULL;
8931 table_state_free(struct rte_swx_pipeline *p)
8933 table_state_build_free(p);
8937 table_stub_lkp(void *table __rte_unused,
8938 void *mailbox __rte_unused,
8939 uint8_t **key __rte_unused,
8940 uint64_t *action_id __rte_unused,
8941 uint8_t **action_data __rte_unused,
8945 return 1; /* DONE. */
8949 table_build(struct rte_swx_pipeline *p)
8953 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8954 struct thread *t = &p->threads[i];
8955 struct table *table;
8957 t->tables = calloc(p->n_tables, sizeof(struct table_runtime));
8958 CHECK(t->tables, ENOMEM);
8960 TAILQ_FOREACH(table, &p->tables, node) {
8961 struct table_runtime *r = &t->tables[table->id];
8966 size = table->type->ops.mailbox_size_get();
8969 r->func = table->type->ops.lkp;
8973 r->mailbox = calloc(1, size);
8974 CHECK(r->mailbox, ENOMEM);
8978 r->key = table->header ?
8979 &t->structs[table->header->struct_id] :
8980 &t->structs[p->metadata_struct_id];
8982 r->func = table_stub_lkp;
8991 table_build_free(struct rte_swx_pipeline *p)
8995 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8996 struct thread *t = &p->threads[i];
9002 for (j = 0; j < p->n_tables; j++) {
9003 struct table_runtime *r = &t->tables[j];
9014 table_free(struct rte_swx_pipeline *p)
9016 table_build_free(p);
9022 elem = TAILQ_FIRST(&p->tables);
9026 TAILQ_REMOVE(&p->tables, elem, node);
9028 free(elem->actions);
9029 free(elem->default_action_data);
9035 struct table_type *elem;
9037 elem = TAILQ_FIRST(&p->table_types);
9041 TAILQ_REMOVE(&p->table_types, elem, node);
9049 static struct regarray *
9050 regarray_find(struct rte_swx_pipeline *p, const char *name)
9052 struct regarray *elem;
9054 TAILQ_FOREACH(elem, &p->regarrays, node)
9055 if (!strcmp(elem->name, name))
9061 static struct regarray *
9062 regarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9064 struct regarray *elem = NULL;
9066 TAILQ_FOREACH(elem, &p->regarrays, node)
9074 rte_swx_pipeline_regarray_config(struct rte_swx_pipeline *p,
9083 CHECK_NAME(name, EINVAL);
9084 CHECK(!regarray_find(p, name), EEXIST);
9086 CHECK(size, EINVAL);
9087 size = rte_align32pow2(size);
9089 /* Memory allocation. */
9090 r = calloc(1, sizeof(struct regarray));
9093 /* Node initialization. */
9094 strcpy(r->name, name);
9095 r->init_val = init_val;
9097 r->id = p->n_regarrays;
9099 /* Node add to tailq. */
9100 TAILQ_INSERT_TAIL(&p->regarrays, r, node);
9107 regarray_build(struct rte_swx_pipeline *p)
9109 struct regarray *regarray;
9111 if (!p->n_regarrays)
9114 p->regarray_runtime = calloc(p->n_regarrays, sizeof(struct regarray_runtime));
9115 CHECK(p->regarray_runtime, ENOMEM);
9117 TAILQ_FOREACH(regarray, &p->regarrays, node) {
9118 struct regarray_runtime *r = &p->regarray_runtime[regarray->id];
9121 r->regarray = env_malloc(regarray->size * sizeof(uint64_t),
9122 RTE_CACHE_LINE_SIZE,
9124 CHECK(r->regarray, ENOMEM);
9126 if (regarray->init_val)
9127 for (i = 0; i < regarray->size; i++)
9128 r->regarray[i] = regarray->init_val;
9130 r->size_mask = regarray->size - 1;
9137 regarray_build_free(struct rte_swx_pipeline *p)
9141 if (!p->regarray_runtime)
9144 for (i = 0; i < p->n_regarrays; i++) {
9145 struct regarray *regarray = regarray_find_by_id(p, i);
9146 struct regarray_runtime *r = &p->regarray_runtime[i];
9148 env_free(r->regarray, regarray->size * sizeof(uint64_t));
9151 free(p->regarray_runtime);
9152 p->regarray_runtime = NULL;
9156 regarray_free(struct rte_swx_pipeline *p)
9158 regarray_build_free(p);
9161 struct regarray *elem;
9163 elem = TAILQ_FIRST(&p->regarrays);
9167 TAILQ_REMOVE(&p->regarrays, elem, node);
9175 static struct meter_profile *
9176 meter_profile_find(struct rte_swx_pipeline *p, const char *name)
9178 struct meter_profile *elem;
9180 TAILQ_FOREACH(elem, &p->meter_profiles, node)
9181 if (!strcmp(elem->name, name))
9187 static struct metarray *
9188 metarray_find(struct rte_swx_pipeline *p, const char *name)
9190 struct metarray *elem;
9192 TAILQ_FOREACH(elem, &p->metarrays, node)
9193 if (!strcmp(elem->name, name))
9199 static struct metarray *
9200 metarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9202 struct metarray *elem = NULL;
9204 TAILQ_FOREACH(elem, &p->metarrays, node)
9212 rte_swx_pipeline_metarray_config(struct rte_swx_pipeline *p,
9220 CHECK_NAME(name, EINVAL);
9221 CHECK(!metarray_find(p, name), EEXIST);
9223 CHECK(size, EINVAL);
9224 size = rte_align32pow2(size);
9226 /* Memory allocation. */
9227 m = calloc(1, sizeof(struct metarray));
9230 /* Node initialization. */
9231 strcpy(m->name, name);
9233 m->id = p->n_metarrays;
9235 /* Node add to tailq. */
9236 TAILQ_INSERT_TAIL(&p->metarrays, m, node);
9242 struct meter_profile meter_profile_default = {
9251 .cir_bytes_per_period = 1,
9253 .pir_bytes_per_period = 1,
9260 meter_init(struct meter *m)
9262 memset(m, 0, sizeof(struct meter));
9263 rte_meter_trtcm_config(&m->m, &meter_profile_default.profile);
9264 m->profile = &meter_profile_default;
9265 m->color_mask = RTE_COLOR_GREEN;
9267 meter_profile_default.n_users++;
9271 metarray_build(struct rte_swx_pipeline *p)
9275 if (!p->n_metarrays)
9278 p->metarray_runtime = calloc(p->n_metarrays, sizeof(struct metarray_runtime));
9279 CHECK(p->metarray_runtime, ENOMEM);
9281 TAILQ_FOREACH(m, &p->metarrays, node) {
9282 struct metarray_runtime *r = &p->metarray_runtime[m->id];
9285 r->metarray = env_malloc(m->size * sizeof(struct meter),
9286 RTE_CACHE_LINE_SIZE,
9288 CHECK(r->metarray, ENOMEM);
9290 for (i = 0; i < m->size; i++)
9291 meter_init(&r->metarray[i]);
9293 r->size_mask = m->size - 1;
9300 metarray_build_free(struct rte_swx_pipeline *p)
9304 if (!p->metarray_runtime)
9307 for (i = 0; i < p->n_metarrays; i++) {
9308 struct metarray *m = metarray_find_by_id(p, i);
9309 struct metarray_runtime *r = &p->metarray_runtime[i];
9311 env_free(r->metarray, m->size * sizeof(struct meter));
9314 free(p->metarray_runtime);
9315 p->metarray_runtime = NULL;
9319 metarray_free(struct rte_swx_pipeline *p)
9321 metarray_build_free(p);
9325 struct metarray *elem;
9327 elem = TAILQ_FIRST(&p->metarrays);
9331 TAILQ_REMOVE(&p->metarrays, elem, node);
9335 /* Meter profiles. */
9337 struct meter_profile *elem;
9339 elem = TAILQ_FIRST(&p->meter_profiles);
9343 TAILQ_REMOVE(&p->meter_profiles, elem, node);
9352 rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
9354 struct rte_swx_pipeline *pipeline;
9356 /* Check input parameters. */
9359 /* Memory allocation. */
9360 pipeline = calloc(1, sizeof(struct rte_swx_pipeline));
9361 CHECK(pipeline, ENOMEM);
9363 /* Initialization. */
9364 TAILQ_INIT(&pipeline->struct_types);
9365 TAILQ_INIT(&pipeline->port_in_types);
9366 TAILQ_INIT(&pipeline->ports_in);
9367 TAILQ_INIT(&pipeline->port_out_types);
9368 TAILQ_INIT(&pipeline->ports_out);
9369 TAILQ_INIT(&pipeline->extern_types);
9370 TAILQ_INIT(&pipeline->extern_objs);
9371 TAILQ_INIT(&pipeline->extern_funcs);
9372 TAILQ_INIT(&pipeline->headers);
9373 TAILQ_INIT(&pipeline->actions);
9374 TAILQ_INIT(&pipeline->table_types);
9375 TAILQ_INIT(&pipeline->tables);
9376 TAILQ_INIT(&pipeline->regarrays);
9377 TAILQ_INIT(&pipeline->meter_profiles);
9378 TAILQ_INIT(&pipeline->metarrays);
9380 pipeline->n_structs = 1; /* Struct 0 is reserved for action_data. */
9381 pipeline->numa_node = numa_node;
9388 rte_swx_pipeline_free(struct rte_swx_pipeline *p)
9393 free(p->instructions);
9397 table_state_free(p);
9402 extern_func_free(p);
9412 rte_swx_pipeline_instructions_config(struct rte_swx_pipeline *p,
9413 const char **instructions,
9414 uint32_t n_instructions)
9419 err = instruction_config(p, NULL, instructions, n_instructions);
9423 /* Thread instruction pointer reset. */
9424 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9425 struct thread *t = &p->threads[i];
9427 thread_ip_reset(p, t);
9434 rte_swx_pipeline_build(struct rte_swx_pipeline *p)
9439 CHECK(p->build_done == 0, EEXIST);
9441 status = port_in_build(p);
9445 status = port_out_build(p);
9449 status = struct_build(p);
9453 status = extern_obj_build(p);
9457 status = extern_func_build(p);
9461 status = header_build(p);
9465 status = metadata_build(p);
9469 status = action_build(p);
9473 status = table_build(p);
9477 status = table_state_build(p);
9481 status = regarray_build(p);
9485 status = metarray_build(p);
9493 metarray_build_free(p);
9494 regarray_build_free(p);
9495 table_state_build_free(p);
9496 table_build_free(p);
9497 action_build_free(p);
9498 metadata_build_free(p);
9499 header_build_free(p);
9500 extern_func_build_free(p);
9501 extern_obj_build_free(p);
9502 port_out_build_free(p);
9503 port_in_build_free(p);
9504 struct_build_free(p);
9510 rte_swx_pipeline_run(struct rte_swx_pipeline *p, uint32_t n_instructions)
9514 for (i = 0; i < n_instructions; i++)
9519 rte_swx_pipeline_flush(struct rte_swx_pipeline *p)
9523 for (i = 0; i < p->n_ports_out; i++) {
9524 struct port_out_runtime *port = &p->out[i];
9527 port->flush(port->obj);
9535 rte_swx_ctl_pipeline_info_get(struct rte_swx_pipeline *p,
9536 struct rte_swx_ctl_pipeline_info *pipeline)
9538 struct action *action;
9539 struct table *table;
9540 uint32_t n_actions = 0, n_tables = 0;
9542 if (!p || !pipeline)
9545 TAILQ_FOREACH(action, &p->actions, node)
9548 TAILQ_FOREACH(table, &p->tables, node)
9551 pipeline->n_ports_in = p->n_ports_in;
9552 pipeline->n_ports_out = p->n_ports_out;
9553 pipeline->n_actions = n_actions;
9554 pipeline->n_tables = n_tables;
9555 pipeline->n_regarrays = p->n_regarrays;
9556 pipeline->n_metarrays = p->n_metarrays;
9562 rte_swx_ctl_pipeline_numa_node_get(struct rte_swx_pipeline *p, int *numa_node)
9564 if (!p || !numa_node)
9567 *numa_node = p->numa_node;
9572 rte_swx_ctl_action_info_get(struct rte_swx_pipeline *p,
9574 struct rte_swx_ctl_action_info *action)
9576 struct action *a = NULL;
9578 if (!p || (action_id >= p->n_actions) || !action)
9581 a = action_find_by_id(p, action_id);
9585 strcpy(action->name, a->name);
9586 action->n_args = a->st ? a->st->n_fields : 0;
9591 rte_swx_ctl_action_arg_info_get(struct rte_swx_pipeline *p,
9593 uint32_t action_arg_id,
9594 struct rte_swx_ctl_action_arg_info *action_arg)
9596 struct action *a = NULL;
9597 struct field *arg = NULL;
9599 if (!p || (action_id >= p->n_actions) || !action_arg)
9602 a = action_find_by_id(p, action_id);
9603 if (!a || !a->st || (action_arg_id >= a->st->n_fields))
9606 arg = &a->st->fields[action_arg_id];
9607 strcpy(action_arg->name, arg->name);
9608 action_arg->n_bits = arg->n_bits;
9614 rte_swx_ctl_table_info_get(struct rte_swx_pipeline *p,
9616 struct rte_swx_ctl_table_info *table)
9618 struct table *t = NULL;
9623 t = table_find_by_id(p, table_id);
9627 strcpy(table->name, t->name);
9628 strcpy(table->args, t->args);
9629 table->n_match_fields = t->n_fields;
9630 table->n_actions = t->n_actions;
9631 table->default_action_is_const = t->default_action_is_const;
9632 table->size = t->size;
9637 rte_swx_ctl_table_match_field_info_get(struct rte_swx_pipeline *p,
9639 uint32_t match_field_id,
9640 struct rte_swx_ctl_table_match_field_info *match_field)
9643 struct match_field *f;
9645 if (!p || (table_id >= p->n_tables) || !match_field)
9648 t = table_find_by_id(p, table_id);
9649 if (!t || (match_field_id >= t->n_fields))
9652 f = &t->fields[match_field_id];
9653 match_field->match_type = f->match_type;
9654 match_field->is_header = t->header ? 1 : 0;
9655 match_field->n_bits = f->field->n_bits;
9656 match_field->offset = f->field->offset;
9662 rte_swx_ctl_table_action_info_get(struct rte_swx_pipeline *p,
9664 uint32_t table_action_id,
9665 struct rte_swx_ctl_table_action_info *table_action)
9669 if (!p || (table_id >= p->n_tables) || !table_action)
9672 t = table_find_by_id(p, table_id);
9673 if (!t || (table_action_id >= t->n_actions))
9676 table_action->action_id = t->actions[table_action_id]->id;
9682 rte_swx_ctl_table_ops_get(struct rte_swx_pipeline *p,
9684 struct rte_swx_table_ops *table_ops,
9689 if (!p || (table_id >= p->n_tables))
9692 t = table_find_by_id(p, table_id);
9698 memcpy(table_ops, &t->type->ops, sizeof(*table_ops));
9708 rte_swx_pipeline_table_state_get(struct rte_swx_pipeline *p,
9709 struct rte_swx_table_state **table_state)
9711 if (!p || !table_state || !p->build_done)
9714 *table_state = p->table_state;
9719 rte_swx_pipeline_table_state_set(struct rte_swx_pipeline *p,
9720 struct rte_swx_table_state *table_state)
9722 if (!p || !table_state || !p->build_done)
9725 p->table_state = table_state;
9730 rte_swx_ctl_pipeline_port_in_stats_read(struct rte_swx_pipeline *p,
9732 struct rte_swx_port_in_stats *stats)
9734 struct port_in *port;
9739 port = port_in_find(p, port_id);
9743 port->type->ops.stats_read(port->obj, stats);
9748 rte_swx_ctl_pipeline_port_out_stats_read(struct rte_swx_pipeline *p,
9750 struct rte_swx_port_out_stats *stats)
9752 struct port_out *port;
9757 port = port_out_find(p, port_id);
9761 port->type->ops.stats_read(port->obj, stats);
9766 rte_swx_ctl_regarray_info_get(struct rte_swx_pipeline *p,
9767 uint32_t regarray_id,
9768 struct rte_swx_ctl_regarray_info *regarray)
9772 if (!p || !regarray)
9775 r = regarray_find_by_id(p, regarray_id);
9779 strcpy(regarray->name, r->name);
9780 regarray->size = r->size;
9785 rte_swx_ctl_pipeline_regarray_read(struct rte_swx_pipeline *p,
9786 const char *regarray_name,
9787 uint32_t regarray_index,
9790 struct regarray *regarray;
9791 struct regarray_runtime *r;
9793 if (!p || !regarray_name || !value)
9796 regarray = regarray_find(p, regarray_name);
9797 if (!regarray || (regarray_index >= regarray->size))
9800 r = &p->regarray_runtime[regarray->id];
9801 *value = r->regarray[regarray_index];
9806 rte_swx_ctl_pipeline_regarray_write(struct rte_swx_pipeline *p,
9807 const char *regarray_name,
9808 uint32_t regarray_index,
9811 struct regarray *regarray;
9812 struct regarray_runtime *r;
9814 if (!p || !regarray_name)
9817 regarray = regarray_find(p, regarray_name);
9818 if (!regarray || (regarray_index >= regarray->size))
9821 r = &p->regarray_runtime[regarray->id];
9822 r->regarray[regarray_index] = value;
9827 rte_swx_ctl_metarray_info_get(struct rte_swx_pipeline *p,
9828 uint32_t metarray_id,
9829 struct rte_swx_ctl_metarray_info *metarray)
9833 if (!p || !metarray)
9836 m = metarray_find_by_id(p, metarray_id);
9840 strcpy(metarray->name, m->name);
9841 metarray->size = m->size;
9846 rte_swx_ctl_meter_profile_add(struct rte_swx_pipeline *p,
9848 struct rte_meter_trtcm_params *params)
9850 struct meter_profile *mp;
9854 CHECK_NAME(name, EINVAL);
9855 CHECK(params, EINVAL);
9856 CHECK(!meter_profile_find(p, name), EEXIST);
9858 /* Node allocation. */
9859 mp = calloc(1, sizeof(struct meter_profile));
9862 /* Node initialization. */
9863 strcpy(mp->name, name);
9864 memcpy(&mp->params, params, sizeof(struct rte_meter_trtcm_params));
9865 status = rte_meter_trtcm_profile_config(&mp->profile, params);
9871 /* Node add to tailq. */
9872 TAILQ_INSERT_TAIL(&p->meter_profiles, mp, node);
9878 rte_swx_ctl_meter_profile_delete(struct rte_swx_pipeline *p,
9881 struct meter_profile *mp;
9884 CHECK_NAME(name, EINVAL);
9886 mp = meter_profile_find(p, name);
9888 CHECK(!mp->n_users, EBUSY);
9890 /* Remove node from tailq. */
9891 TAILQ_REMOVE(&p->meter_profiles, mp, node);
9898 rte_swx_ctl_meter_reset(struct rte_swx_pipeline *p,
9899 const char *metarray_name,
9900 uint32_t metarray_index)
9902 struct meter_profile *mp_old;
9903 struct metarray *metarray;
9904 struct metarray_runtime *metarray_runtime;
9908 CHECK_NAME(metarray_name, EINVAL);
9910 metarray = metarray_find(p, metarray_name);
9911 CHECK(metarray, EINVAL);
9912 CHECK(metarray_index < metarray->size, EINVAL);
9914 metarray_runtime = &p->metarray_runtime[metarray->id];
9915 m = &metarray_runtime->metarray[metarray_index];
9916 mp_old = m->profile;
9926 rte_swx_ctl_meter_set(struct rte_swx_pipeline *p,
9927 const char *metarray_name,
9928 uint32_t metarray_index,
9929 const char *profile_name)
9931 struct meter_profile *mp, *mp_old;
9932 struct metarray *metarray;
9933 struct metarray_runtime *metarray_runtime;
9937 CHECK_NAME(metarray_name, EINVAL);
9939 metarray = metarray_find(p, metarray_name);
9940 CHECK(metarray, EINVAL);
9941 CHECK(metarray_index < metarray->size, EINVAL);
9943 mp = meter_profile_find(p, profile_name);
9946 metarray_runtime = &p->metarray_runtime[metarray->id];
9947 m = &metarray_runtime->metarray[metarray_index];
9948 mp_old = m->profile;
9950 memset(m, 0, sizeof(struct meter));
9951 rte_meter_trtcm_config(&m->m, &mp->profile);
9953 m->color_mask = RTE_COLORS;
9962 rte_swx_ctl_meter_stats_read(struct rte_swx_pipeline *p,
9963 const char *metarray_name,
9964 uint32_t metarray_index,
9965 struct rte_swx_ctl_meter_stats *stats)
9967 struct metarray *metarray;
9968 struct metarray_runtime *metarray_runtime;
9972 CHECK_NAME(metarray_name, EINVAL);
9974 metarray = metarray_find(p, metarray_name);
9975 CHECK(metarray, EINVAL);
9976 CHECK(metarray_index < metarray->size, EINVAL);
9978 CHECK(stats, EINVAL);
9980 metarray_runtime = &p->metarray_runtime[metarray->id];
9981 m = &metarray_runtime->metarray[metarray_index];
9983 memcpy(stats->n_pkts, m->n_pkts, sizeof(m->n_pkts));
9984 memcpy(stats->n_bytes, m->n_bytes, sizeof(m->n_bytes));