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;
779 struct table_statistics {
780 uint64_t n_pkts_hit[2]; /* 0 = Miss, 1 = Hit. */
781 uint64_t *n_pkts_action;
788 TAILQ_ENTRY(regarray) node;
789 char name[RTE_SWX_NAME_SIZE];
795 TAILQ_HEAD(regarray_tailq, regarray);
797 struct regarray_runtime {
805 struct meter_profile {
806 TAILQ_ENTRY(meter_profile) node;
807 char name[RTE_SWX_NAME_SIZE];
808 struct rte_meter_trtcm_params params;
809 struct rte_meter_trtcm_profile profile;
813 TAILQ_HEAD(meter_profile_tailq, meter_profile);
816 TAILQ_ENTRY(metarray) node;
817 char name[RTE_SWX_NAME_SIZE];
822 TAILQ_HEAD(metarray_tailq, metarray);
825 struct rte_meter_trtcm m;
826 struct meter_profile *profile;
827 enum rte_color color_mask;
830 uint64_t n_pkts[RTE_COLORS];
831 uint64_t n_bytes[RTE_COLORS];
834 struct metarray_runtime {
835 struct meter *metarray;
844 struct rte_swx_pkt pkt;
850 /* Packet headers. */
851 struct header_runtime *headers; /* Extracted or generated headers. */
852 struct header_out_runtime *headers_out; /* Emitted headers. */
853 uint8_t *header_storage;
854 uint8_t *header_out_storage;
855 uint64_t valid_headers;
856 uint32_t n_headers_out;
858 /* Packet meta-data. */
862 struct table_runtime *tables;
863 struct rte_swx_table_state *table_state;
865 int hit; /* 0 = Miss, 1 = Hit. */
867 /* Extern objects and functions. */
868 struct extern_obj_runtime *extern_objs;
869 struct extern_func_runtime *extern_funcs;
872 struct instruction *ip;
873 struct instruction *ret;
876 #define MASK64_BIT_GET(mask, pos) ((mask) & (1LLU << (pos)))
877 #define MASK64_BIT_SET(mask, pos) ((mask) | (1LLU << (pos)))
878 #define MASK64_BIT_CLR(mask, pos) ((mask) & ~(1LLU << (pos)))
880 #define HEADER_VALID(thread, header_id) \
881 MASK64_BIT_GET((thread)->valid_headers, header_id)
883 #define ALU(thread, ip, operator) \
885 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
886 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
887 uint64_t dst64 = *dst64_ptr; \
888 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
889 uint64_t dst = dst64 & dst64_mask; \
891 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
892 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
893 uint64_t src64 = *src64_ptr; \
894 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->alu.src.n_bits); \
895 uint64_t src = src64 & src64_mask; \
897 uint64_t result = dst operator src; \
899 *dst64_ptr = (dst64 & ~dst64_mask) | (result & dst64_mask); \
902 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
904 #define ALU_S(thread, ip, operator) \
906 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
907 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
908 uint64_t dst64 = *dst64_ptr; \
909 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
910 uint64_t dst = dst64 & dst64_mask; \
912 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
913 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
914 uint64_t src64 = *src64_ptr; \
915 uint64_t src = ntoh64(src64) >> (64 - (ip)->alu.src.n_bits); \
917 uint64_t result = dst operator src; \
919 *dst64_ptr = (dst64 & ~dst64_mask) | (result & dst64_mask); \
924 #define ALU_HM(thread, ip, operator) \
926 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
927 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
928 uint64_t dst64 = *dst64_ptr; \
929 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
930 uint64_t dst = ntoh64(dst64) >> (64 - (ip)->alu.dst.n_bits); \
932 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
933 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
934 uint64_t src64 = *src64_ptr; \
935 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->alu.src.n_bits); \
936 uint64_t src = src64 & src64_mask; \
938 uint64_t result = dst operator src; \
939 result = hton64(result << (64 - (ip)->alu.dst.n_bits)); \
941 *dst64_ptr = (dst64 & ~dst64_mask) | result; \
944 #define ALU_HH(thread, ip, operator) \
946 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
947 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
948 uint64_t dst64 = *dst64_ptr; \
949 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
950 uint64_t dst = ntoh64(dst64) >> (64 - (ip)->alu.dst.n_bits); \
952 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
953 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
954 uint64_t src64 = *src64_ptr; \
955 uint64_t src = ntoh64(src64) >> (64 - (ip)->alu.src.n_bits); \
957 uint64_t result = dst operator src; \
958 result = hton64(result << (64 - (ip)->alu.dst.n_bits)); \
960 *dst64_ptr = (dst64 & ~dst64_mask) | result; \
972 #define ALU_I(thread, ip, operator) \
974 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
975 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
976 uint64_t dst64 = *dst64_ptr; \
977 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
978 uint64_t dst = dst64 & dst64_mask; \
980 uint64_t src = (ip)->alu.src_val; \
982 uint64_t result = dst operator src; \
984 *dst64_ptr = (dst64 & ~dst64_mask) | (result & dst64_mask); \
989 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
991 #define ALU_HI(thread, ip, operator) \
993 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
994 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
995 uint64_t dst64 = *dst64_ptr; \
996 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
997 uint64_t dst = ntoh64(dst64) >> (64 - (ip)->alu.dst.n_bits); \
999 uint64_t src = (ip)->alu.src_val; \
1001 uint64_t result = dst operator src; \
1002 result = hton64(result << (64 - (ip)->alu.dst.n_bits)); \
1004 *dst64_ptr = (dst64 & ~dst64_mask) | result; \
1009 #define ALU_HI ALU_I
1013 #define MOV(thread, ip) \
1015 uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id]; \
1016 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset]; \
1017 uint64_t dst64 = *dst64_ptr; \
1018 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits); \
1020 uint8_t *src_struct = (thread)->structs[(ip)->mov.src.struct_id]; \
1021 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->mov.src.offset]; \
1022 uint64_t src64 = *src64_ptr; \
1023 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->mov.src.n_bits); \
1024 uint64_t src = src64 & src64_mask; \
1026 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask); \
1029 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1031 #define MOV_S(thread, ip) \
1033 uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id]; \
1034 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset]; \
1035 uint64_t dst64 = *dst64_ptr; \
1036 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits); \
1038 uint8_t *src_struct = (thread)->structs[(ip)->mov.src.struct_id]; \
1039 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->mov.src.offset]; \
1040 uint64_t src64 = *src64_ptr; \
1041 uint64_t src = ntoh64(src64) >> (64 - (ip)->mov.src.n_bits); \
1043 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask); \
1052 #define MOV_I(thread, ip) \
1054 uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id]; \
1055 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset]; \
1056 uint64_t dst64 = *dst64_ptr; \
1057 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits); \
1059 uint64_t src = (ip)->mov.src_val; \
1061 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask); \
1064 #define JMP_CMP(thread, ip, operator) \
1066 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1067 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1068 uint64_t a64 = *a64_ptr; \
1069 uint64_t a64_mask = UINT64_MAX >> (64 - (ip)->jmp.a.n_bits); \
1070 uint64_t a = a64 & a64_mask; \
1072 uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id]; \
1073 uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset]; \
1074 uint64_t b64 = *b64_ptr; \
1075 uint64_t b64_mask = UINT64_MAX >> (64 - (ip)->jmp.b.n_bits); \
1076 uint64_t b = b64 & b64_mask; \
1078 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1081 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1083 #define JMP_CMP_S(thread, ip, operator) \
1085 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1086 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1087 uint64_t a64 = *a64_ptr; \
1088 uint64_t a64_mask = UINT64_MAX >> (64 - (ip)->jmp.a.n_bits); \
1089 uint64_t a = a64 & a64_mask; \
1091 uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id]; \
1092 uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset]; \
1093 uint64_t b64 = *b64_ptr; \
1094 uint64_t b = ntoh64(b64) >> (64 - (ip)->jmp.b.n_bits); \
1096 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1099 #define JMP_CMP_MH JMP_CMP_S
1101 #define JMP_CMP_HM(thread, ip, operator) \
1103 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1104 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1105 uint64_t a64 = *a64_ptr; \
1106 uint64_t a = ntoh64(a64) >> (64 - (ip)->jmp.a.n_bits); \
1108 uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id]; \
1109 uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset]; \
1110 uint64_t b64 = *b64_ptr; \
1111 uint64_t b64_mask = UINT64_MAX >> (64 - (ip)->jmp.b.n_bits); \
1112 uint64_t b = b64 & b64_mask; \
1114 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1117 #define JMP_CMP_HH(thread, ip, operator) \
1119 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1120 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1121 uint64_t a64 = *a64_ptr; \
1122 uint64_t a = ntoh64(a64) >> (64 - (ip)->jmp.a.n_bits); \
1124 uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id]; \
1125 uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset]; \
1126 uint64_t b64 = *b64_ptr; \
1127 uint64_t b = ntoh64(b64) >> (64 - (ip)->jmp.b.n_bits); \
1129 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1134 #define JMP_CMP_S JMP_CMP
1135 #define JMP_CMP_MH JMP_CMP
1136 #define JMP_CMP_HM JMP_CMP
1137 #define JMP_CMP_HH JMP_CMP
1141 #define JMP_CMP_I(thread, ip, operator) \
1143 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1144 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1145 uint64_t a64 = *a64_ptr; \
1146 uint64_t a64_mask = UINT64_MAX >> (64 - (ip)->jmp.a.n_bits); \
1147 uint64_t a = a64 & a64_mask; \
1149 uint64_t b = (ip)->jmp.b_val; \
1151 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1154 #define JMP_CMP_MI JMP_CMP_I
1156 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1158 #define JMP_CMP_HI(thread, ip, operator) \
1160 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1161 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1162 uint64_t a64 = *a64_ptr; \
1163 uint64_t a = ntoh64(a64) >> (64 - (ip)->jmp.a.n_bits); \
1165 uint64_t b = (ip)->jmp.b_val; \
1167 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1172 #define JMP_CMP_HI JMP_CMP_I
1176 #define METADATA_READ(thread, offset, n_bits) \
1178 uint64_t *m64_ptr = (uint64_t *)&(thread)->metadata[offset]; \
1179 uint64_t m64 = *m64_ptr; \
1180 uint64_t m64_mask = UINT64_MAX >> (64 - (n_bits)); \
1184 #define METADATA_WRITE(thread, offset, n_bits, value) \
1186 uint64_t *m64_ptr = (uint64_t *)&(thread)->metadata[offset]; \
1187 uint64_t m64 = *m64_ptr; \
1188 uint64_t m64_mask = UINT64_MAX >> (64 - (n_bits)); \
1190 uint64_t m_new = value; \
1192 *m64_ptr = (m64 & ~m64_mask) | (m_new & m64_mask); \
1195 #ifndef RTE_SWX_PIPELINE_THREADS_MAX
1196 #define RTE_SWX_PIPELINE_THREADS_MAX 16
1199 struct rte_swx_pipeline {
1200 struct struct_type_tailq struct_types;
1201 struct port_in_type_tailq port_in_types;
1202 struct port_in_tailq ports_in;
1203 struct port_out_type_tailq port_out_types;
1204 struct port_out_tailq ports_out;
1205 struct extern_type_tailq extern_types;
1206 struct extern_obj_tailq extern_objs;
1207 struct extern_func_tailq extern_funcs;
1208 struct header_tailq headers;
1209 struct struct_type *metadata_st;
1210 uint32_t metadata_struct_id;
1211 struct action_tailq actions;
1212 struct table_type_tailq table_types;
1213 struct table_tailq tables;
1214 struct regarray_tailq regarrays;
1215 struct meter_profile_tailq meter_profiles;
1216 struct metarray_tailq metarrays;
1218 struct port_in_runtime *in;
1219 struct port_out_runtime *out;
1220 struct instruction **action_instructions;
1221 struct rte_swx_table_state *table_state;
1222 struct table_statistics *table_stats;
1223 struct regarray_runtime *regarray_runtime;
1224 struct metarray_runtime *metarray_runtime;
1225 struct instruction *instructions;
1226 struct thread threads[RTE_SWX_PIPELINE_THREADS_MAX];
1229 uint32_t n_ports_in;
1230 uint32_t n_ports_out;
1231 uint32_t n_extern_objs;
1232 uint32_t n_extern_funcs;
1235 uint32_t n_regarrays;
1236 uint32_t n_metarrays;
1240 uint32_t n_instructions;
1248 static struct struct_type *
1249 struct_type_find(struct rte_swx_pipeline *p, const char *name)
1251 struct struct_type *elem;
1253 TAILQ_FOREACH(elem, &p->struct_types, node)
1254 if (strcmp(elem->name, name) == 0)
1260 static struct field *
1261 struct_type_field_find(struct struct_type *st, const char *name)
1265 for (i = 0; i < st->n_fields; i++) {
1266 struct field *f = &st->fields[i];
1268 if (strcmp(f->name, name) == 0)
1276 rte_swx_pipeline_struct_type_register(struct rte_swx_pipeline *p,
1278 struct rte_swx_field_params *fields,
1281 struct struct_type *st;
1285 CHECK_NAME(name, EINVAL);
1286 CHECK(fields, EINVAL);
1287 CHECK(n_fields, EINVAL);
1289 for (i = 0; i < n_fields; i++) {
1290 struct rte_swx_field_params *f = &fields[i];
1293 CHECK_NAME(f->name, EINVAL);
1294 CHECK(f->n_bits, EINVAL);
1295 CHECK(f->n_bits <= 64, EINVAL);
1296 CHECK((f->n_bits & 7) == 0, EINVAL);
1298 for (j = 0; j < i; j++) {
1299 struct rte_swx_field_params *f_prev = &fields[j];
1301 CHECK(strcmp(f->name, f_prev->name), EINVAL);
1305 CHECK(!struct_type_find(p, name), EEXIST);
1307 /* Node allocation. */
1308 st = calloc(1, sizeof(struct struct_type));
1311 st->fields = calloc(n_fields, sizeof(struct field));
1317 /* Node initialization. */
1318 strcpy(st->name, name);
1319 for (i = 0; i < n_fields; i++) {
1320 struct field *dst = &st->fields[i];
1321 struct rte_swx_field_params *src = &fields[i];
1323 strcpy(dst->name, src->name);
1324 dst->n_bits = src->n_bits;
1325 dst->offset = st->n_bits;
1327 st->n_bits += src->n_bits;
1329 st->n_fields = n_fields;
1331 /* Node add to tailq. */
1332 TAILQ_INSERT_TAIL(&p->struct_types, st, node);
1338 struct_build(struct rte_swx_pipeline *p)
1342 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1343 struct thread *t = &p->threads[i];
1345 t->structs = calloc(p->n_structs, sizeof(uint8_t *));
1346 CHECK(t->structs, ENOMEM);
1353 struct_build_free(struct rte_swx_pipeline *p)
1357 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1358 struct thread *t = &p->threads[i];
1366 struct_free(struct rte_swx_pipeline *p)
1368 struct_build_free(p);
1372 struct struct_type *elem;
1374 elem = TAILQ_FIRST(&p->struct_types);
1378 TAILQ_REMOVE(&p->struct_types, elem, node);
1387 static struct port_in_type *
1388 port_in_type_find(struct rte_swx_pipeline *p, const char *name)
1390 struct port_in_type *elem;
1395 TAILQ_FOREACH(elem, &p->port_in_types, node)
1396 if (strcmp(elem->name, name) == 0)
1403 rte_swx_pipeline_port_in_type_register(struct rte_swx_pipeline *p,
1405 struct rte_swx_port_in_ops *ops)
1407 struct port_in_type *elem;
1410 CHECK_NAME(name, EINVAL);
1412 CHECK(ops->create, EINVAL);
1413 CHECK(ops->free, EINVAL);
1414 CHECK(ops->pkt_rx, EINVAL);
1415 CHECK(ops->stats_read, EINVAL);
1417 CHECK(!port_in_type_find(p, name), EEXIST);
1419 /* Node allocation. */
1420 elem = calloc(1, sizeof(struct port_in_type));
1421 CHECK(elem, ENOMEM);
1423 /* Node initialization. */
1424 strcpy(elem->name, name);
1425 memcpy(&elem->ops, ops, sizeof(*ops));
1427 /* Node add to tailq. */
1428 TAILQ_INSERT_TAIL(&p->port_in_types, elem, node);
1433 static struct port_in *
1434 port_in_find(struct rte_swx_pipeline *p, uint32_t port_id)
1436 struct port_in *port;
1438 TAILQ_FOREACH(port, &p->ports_in, node)
1439 if (port->id == port_id)
1446 rte_swx_pipeline_port_in_config(struct rte_swx_pipeline *p,
1448 const char *port_type_name,
1451 struct port_in_type *type = NULL;
1452 struct port_in *port = NULL;
1457 CHECK(!port_in_find(p, port_id), EINVAL);
1459 CHECK_NAME(port_type_name, EINVAL);
1460 type = port_in_type_find(p, port_type_name);
1461 CHECK(type, EINVAL);
1463 obj = type->ops.create(args);
1466 /* Node allocation. */
1467 port = calloc(1, sizeof(struct port_in));
1468 CHECK(port, ENOMEM);
1470 /* Node initialization. */
1475 /* Node add to tailq. */
1476 TAILQ_INSERT_TAIL(&p->ports_in, port, node);
1477 if (p->n_ports_in < port_id + 1)
1478 p->n_ports_in = port_id + 1;
1484 port_in_build(struct rte_swx_pipeline *p)
1486 struct port_in *port;
1489 CHECK(p->n_ports_in, EINVAL);
1490 CHECK(rte_is_power_of_2(p->n_ports_in), EINVAL);
1492 for (i = 0; i < p->n_ports_in; i++)
1493 CHECK(port_in_find(p, i), EINVAL);
1495 p->in = calloc(p->n_ports_in, sizeof(struct port_in_runtime));
1496 CHECK(p->in, ENOMEM);
1498 TAILQ_FOREACH(port, &p->ports_in, node) {
1499 struct port_in_runtime *in = &p->in[port->id];
1501 in->pkt_rx = port->type->ops.pkt_rx;
1502 in->obj = port->obj;
1509 port_in_build_free(struct rte_swx_pipeline *p)
1516 port_in_free(struct rte_swx_pipeline *p)
1518 port_in_build_free(p);
1522 struct port_in *port;
1524 port = TAILQ_FIRST(&p->ports_in);
1528 TAILQ_REMOVE(&p->ports_in, port, node);
1529 port->type->ops.free(port->obj);
1533 /* Input port types. */
1535 struct port_in_type *elem;
1537 elem = TAILQ_FIRST(&p->port_in_types);
1541 TAILQ_REMOVE(&p->port_in_types, elem, node);
1549 static struct port_out_type *
1550 port_out_type_find(struct rte_swx_pipeline *p, const char *name)
1552 struct port_out_type *elem;
1557 TAILQ_FOREACH(elem, &p->port_out_types, node)
1558 if (!strcmp(elem->name, name))
1565 rte_swx_pipeline_port_out_type_register(struct rte_swx_pipeline *p,
1567 struct rte_swx_port_out_ops *ops)
1569 struct port_out_type *elem;
1572 CHECK_NAME(name, EINVAL);
1574 CHECK(ops->create, EINVAL);
1575 CHECK(ops->free, EINVAL);
1576 CHECK(ops->pkt_tx, EINVAL);
1577 CHECK(ops->stats_read, EINVAL);
1579 CHECK(!port_out_type_find(p, name), EEXIST);
1581 /* Node allocation. */
1582 elem = calloc(1, sizeof(struct port_out_type));
1583 CHECK(elem, ENOMEM);
1585 /* Node initialization. */
1586 strcpy(elem->name, name);
1587 memcpy(&elem->ops, ops, sizeof(*ops));
1589 /* Node add to tailq. */
1590 TAILQ_INSERT_TAIL(&p->port_out_types, elem, node);
1595 static struct port_out *
1596 port_out_find(struct rte_swx_pipeline *p, uint32_t port_id)
1598 struct port_out *port;
1600 TAILQ_FOREACH(port, &p->ports_out, node)
1601 if (port->id == port_id)
1608 rte_swx_pipeline_port_out_config(struct rte_swx_pipeline *p,
1610 const char *port_type_name,
1613 struct port_out_type *type = NULL;
1614 struct port_out *port = NULL;
1619 CHECK(!port_out_find(p, port_id), EINVAL);
1621 CHECK_NAME(port_type_name, EINVAL);
1622 type = port_out_type_find(p, port_type_name);
1623 CHECK(type, EINVAL);
1625 obj = type->ops.create(args);
1628 /* Node allocation. */
1629 port = calloc(1, sizeof(struct port_out));
1630 CHECK(port, ENOMEM);
1632 /* Node initialization. */
1637 /* Node add to tailq. */
1638 TAILQ_INSERT_TAIL(&p->ports_out, port, node);
1639 if (p->n_ports_out < port_id + 1)
1640 p->n_ports_out = port_id + 1;
1646 port_out_build(struct rte_swx_pipeline *p)
1648 struct port_out *port;
1651 CHECK(p->n_ports_out, EINVAL);
1653 for (i = 0; i < p->n_ports_out; i++)
1654 CHECK(port_out_find(p, i), EINVAL);
1656 p->out = calloc(p->n_ports_out, sizeof(struct port_out_runtime));
1657 CHECK(p->out, ENOMEM);
1659 TAILQ_FOREACH(port, &p->ports_out, node) {
1660 struct port_out_runtime *out = &p->out[port->id];
1662 out->pkt_tx = port->type->ops.pkt_tx;
1663 out->flush = port->type->ops.flush;
1664 out->obj = port->obj;
1671 port_out_build_free(struct rte_swx_pipeline *p)
1678 port_out_free(struct rte_swx_pipeline *p)
1680 port_out_build_free(p);
1684 struct port_out *port;
1686 port = TAILQ_FIRST(&p->ports_out);
1690 TAILQ_REMOVE(&p->ports_out, port, node);
1691 port->type->ops.free(port->obj);
1695 /* Output port types. */
1697 struct port_out_type *elem;
1699 elem = TAILQ_FIRST(&p->port_out_types);
1703 TAILQ_REMOVE(&p->port_out_types, elem, node);
1711 static struct extern_type *
1712 extern_type_find(struct rte_swx_pipeline *p, const char *name)
1714 struct extern_type *elem;
1716 TAILQ_FOREACH(elem, &p->extern_types, node)
1717 if (strcmp(elem->name, name) == 0)
1723 static struct extern_type_member_func *
1724 extern_type_member_func_find(struct extern_type *type, const char *name)
1726 struct extern_type_member_func *elem;
1728 TAILQ_FOREACH(elem, &type->funcs, node)
1729 if (strcmp(elem->name, name) == 0)
1735 static struct extern_obj *
1736 extern_obj_find(struct rte_swx_pipeline *p, const char *name)
1738 struct extern_obj *elem;
1740 TAILQ_FOREACH(elem, &p->extern_objs, node)
1741 if (strcmp(elem->name, name) == 0)
1747 static struct extern_type_member_func *
1748 extern_obj_member_func_parse(struct rte_swx_pipeline *p,
1750 struct extern_obj **obj)
1752 struct extern_obj *object;
1753 struct extern_type_member_func *func;
1754 char *object_name, *func_name;
1756 if (name[0] != 'e' || name[1] != '.')
1759 object_name = strdup(&name[2]);
1763 func_name = strchr(object_name, '.');
1772 object = extern_obj_find(p, object_name);
1778 func = extern_type_member_func_find(object->type, func_name);
1791 static struct field *
1792 extern_obj_mailbox_field_parse(struct rte_swx_pipeline *p,
1794 struct extern_obj **object)
1796 struct extern_obj *obj;
1798 char *obj_name, *field_name;
1800 if ((name[0] != 'e') || (name[1] != '.'))
1803 obj_name = strdup(&name[2]);
1807 field_name = strchr(obj_name, '.');
1816 obj = extern_obj_find(p, obj_name);
1822 f = struct_type_field_find(obj->type->mailbox_struct_type, field_name);
1836 rte_swx_pipeline_extern_type_register(struct rte_swx_pipeline *p,
1838 const char *mailbox_struct_type_name,
1839 rte_swx_extern_type_constructor_t constructor,
1840 rte_swx_extern_type_destructor_t destructor)
1842 struct extern_type *elem;
1843 struct struct_type *mailbox_struct_type;
1847 CHECK_NAME(name, EINVAL);
1848 CHECK(!extern_type_find(p, name), EEXIST);
1850 CHECK_NAME(mailbox_struct_type_name, EINVAL);
1851 mailbox_struct_type = struct_type_find(p, mailbox_struct_type_name);
1852 CHECK(mailbox_struct_type, EINVAL);
1854 CHECK(constructor, EINVAL);
1855 CHECK(destructor, EINVAL);
1857 /* Node allocation. */
1858 elem = calloc(1, sizeof(struct extern_type));
1859 CHECK(elem, ENOMEM);
1861 /* Node initialization. */
1862 strcpy(elem->name, name);
1863 elem->mailbox_struct_type = mailbox_struct_type;
1864 elem->constructor = constructor;
1865 elem->destructor = destructor;
1866 TAILQ_INIT(&elem->funcs);
1868 /* Node add to tailq. */
1869 TAILQ_INSERT_TAIL(&p->extern_types, elem, node);
1875 rte_swx_pipeline_extern_type_member_func_register(struct rte_swx_pipeline *p,
1876 const char *extern_type_name,
1878 rte_swx_extern_type_member_func_t member_func)
1880 struct extern_type *type;
1881 struct extern_type_member_func *type_member;
1885 CHECK_NAME(extern_type_name, EINVAL);
1886 type = extern_type_find(p, extern_type_name);
1887 CHECK(type, EINVAL);
1888 CHECK(type->n_funcs < RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX, ENOSPC);
1890 CHECK_NAME(name, EINVAL);
1891 CHECK(!extern_type_member_func_find(type, name), EEXIST);
1893 CHECK(member_func, EINVAL);
1895 /* Node allocation. */
1896 type_member = calloc(1, sizeof(struct extern_type_member_func));
1897 CHECK(type_member, ENOMEM);
1899 /* Node initialization. */
1900 strcpy(type_member->name, name);
1901 type_member->func = member_func;
1902 type_member->id = type->n_funcs;
1904 /* Node add to tailq. */
1905 TAILQ_INSERT_TAIL(&type->funcs, type_member, node);
1912 rte_swx_pipeline_extern_object_config(struct rte_swx_pipeline *p,
1913 const char *extern_type_name,
1917 struct extern_type *type;
1918 struct extern_obj *obj;
1923 CHECK_NAME(extern_type_name, EINVAL);
1924 type = extern_type_find(p, extern_type_name);
1925 CHECK(type, EINVAL);
1927 CHECK_NAME(name, EINVAL);
1928 CHECK(!extern_obj_find(p, name), EEXIST);
1930 /* Node allocation. */
1931 obj = calloc(1, sizeof(struct extern_obj));
1934 /* Object construction. */
1935 obj_handle = type->constructor(args);
1941 /* Node initialization. */
1942 strcpy(obj->name, name);
1944 obj->obj = obj_handle;
1945 obj->struct_id = p->n_structs;
1946 obj->id = p->n_extern_objs;
1948 /* Node add to tailq. */
1949 TAILQ_INSERT_TAIL(&p->extern_objs, obj, node);
1957 extern_obj_build(struct rte_swx_pipeline *p)
1961 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1962 struct thread *t = &p->threads[i];
1963 struct extern_obj *obj;
1965 t->extern_objs = calloc(p->n_extern_objs,
1966 sizeof(struct extern_obj_runtime));
1967 CHECK(t->extern_objs, ENOMEM);
1969 TAILQ_FOREACH(obj, &p->extern_objs, node) {
1970 struct extern_obj_runtime *r =
1971 &t->extern_objs[obj->id];
1972 struct extern_type_member_func *func;
1973 uint32_t mailbox_size =
1974 obj->type->mailbox_struct_type->n_bits / 8;
1978 r->mailbox = calloc(1, mailbox_size);
1979 CHECK(r->mailbox, ENOMEM);
1981 TAILQ_FOREACH(func, &obj->type->funcs, node)
1982 r->funcs[func->id] = func->func;
1984 t->structs[obj->struct_id] = r->mailbox;
1992 extern_obj_build_free(struct rte_swx_pipeline *p)
1996 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
1997 struct thread *t = &p->threads[i];
2000 if (!t->extern_objs)
2003 for (j = 0; j < p->n_extern_objs; j++) {
2004 struct extern_obj_runtime *r = &t->extern_objs[j];
2009 free(t->extern_objs);
2010 t->extern_objs = NULL;
2015 extern_obj_free(struct rte_swx_pipeline *p)
2017 extern_obj_build_free(p);
2019 /* Extern objects. */
2021 struct extern_obj *elem;
2023 elem = TAILQ_FIRST(&p->extern_objs);
2027 TAILQ_REMOVE(&p->extern_objs, elem, node);
2029 elem->type->destructor(elem->obj);
2035 struct extern_type *elem;
2037 elem = TAILQ_FIRST(&p->extern_types);
2041 TAILQ_REMOVE(&p->extern_types, elem, node);
2044 struct extern_type_member_func *func;
2046 func = TAILQ_FIRST(&elem->funcs);
2050 TAILQ_REMOVE(&elem->funcs, func, node);
2061 static struct extern_func *
2062 extern_func_find(struct rte_swx_pipeline *p, const char *name)
2064 struct extern_func *elem;
2066 TAILQ_FOREACH(elem, &p->extern_funcs, node)
2067 if (strcmp(elem->name, name) == 0)
2073 static struct extern_func *
2074 extern_func_parse(struct rte_swx_pipeline *p,
2077 if (name[0] != 'f' || name[1] != '.')
2080 return extern_func_find(p, &name[2]);
2083 static struct field *
2084 extern_func_mailbox_field_parse(struct rte_swx_pipeline *p,
2086 struct extern_func **function)
2088 struct extern_func *func;
2090 char *func_name, *field_name;
2092 if ((name[0] != 'f') || (name[1] != '.'))
2095 func_name = strdup(&name[2]);
2099 field_name = strchr(func_name, '.');
2108 func = extern_func_find(p, func_name);
2114 f = struct_type_field_find(func->mailbox_struct_type, field_name);
2128 rte_swx_pipeline_extern_func_register(struct rte_swx_pipeline *p,
2130 const char *mailbox_struct_type_name,
2131 rte_swx_extern_func_t func)
2133 struct extern_func *f;
2134 struct struct_type *mailbox_struct_type;
2138 CHECK_NAME(name, EINVAL);
2139 CHECK(!extern_func_find(p, name), EEXIST);
2141 CHECK_NAME(mailbox_struct_type_name, EINVAL);
2142 mailbox_struct_type = struct_type_find(p, mailbox_struct_type_name);
2143 CHECK(mailbox_struct_type, EINVAL);
2145 CHECK(func, EINVAL);
2147 /* Node allocation. */
2148 f = calloc(1, sizeof(struct extern_func));
2149 CHECK(func, ENOMEM);
2151 /* Node initialization. */
2152 strcpy(f->name, name);
2153 f->mailbox_struct_type = mailbox_struct_type;
2155 f->struct_id = p->n_structs;
2156 f->id = p->n_extern_funcs;
2158 /* Node add to tailq. */
2159 TAILQ_INSERT_TAIL(&p->extern_funcs, f, node);
2160 p->n_extern_funcs++;
2167 extern_func_build(struct rte_swx_pipeline *p)
2171 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
2172 struct thread *t = &p->threads[i];
2173 struct extern_func *func;
2175 /* Memory allocation. */
2176 t->extern_funcs = calloc(p->n_extern_funcs,
2177 sizeof(struct extern_func_runtime));
2178 CHECK(t->extern_funcs, ENOMEM);
2180 /* Extern function. */
2181 TAILQ_FOREACH(func, &p->extern_funcs, node) {
2182 struct extern_func_runtime *r =
2183 &t->extern_funcs[func->id];
2184 uint32_t mailbox_size =
2185 func->mailbox_struct_type->n_bits / 8;
2187 r->func = func->func;
2189 r->mailbox = calloc(1, mailbox_size);
2190 CHECK(r->mailbox, ENOMEM);
2192 t->structs[func->struct_id] = r->mailbox;
2200 extern_func_build_free(struct rte_swx_pipeline *p)
2204 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
2205 struct thread *t = &p->threads[i];
2208 if (!t->extern_funcs)
2211 for (j = 0; j < p->n_extern_funcs; j++) {
2212 struct extern_func_runtime *r = &t->extern_funcs[j];
2217 free(t->extern_funcs);
2218 t->extern_funcs = NULL;
2223 extern_func_free(struct rte_swx_pipeline *p)
2225 extern_func_build_free(p);
2228 struct extern_func *elem;
2230 elem = TAILQ_FIRST(&p->extern_funcs);
2234 TAILQ_REMOVE(&p->extern_funcs, elem, node);
2242 static struct header *
2243 header_find(struct rte_swx_pipeline *p, const char *name)
2245 struct header *elem;
2247 TAILQ_FOREACH(elem, &p->headers, node)
2248 if (strcmp(elem->name, name) == 0)
2254 static struct header *
2255 header_parse(struct rte_swx_pipeline *p,
2258 if (name[0] != 'h' || name[1] != '.')
2261 return header_find(p, &name[2]);
2264 static struct field *
2265 header_field_parse(struct rte_swx_pipeline *p,
2267 struct header **header)
2271 char *header_name, *field_name;
2273 if ((name[0] != 'h') || (name[1] != '.'))
2276 header_name = strdup(&name[2]);
2280 field_name = strchr(header_name, '.');
2289 h = header_find(p, header_name);
2295 f = struct_type_field_find(h->st, field_name);
2309 rte_swx_pipeline_packet_header_register(struct rte_swx_pipeline *p,
2311 const char *struct_type_name)
2313 struct struct_type *st;
2315 size_t n_headers_max;
2318 CHECK_NAME(name, EINVAL);
2319 CHECK_NAME(struct_type_name, EINVAL);
2321 CHECK(!header_find(p, name), EEXIST);
2323 st = struct_type_find(p, struct_type_name);
2326 n_headers_max = RTE_SIZEOF_FIELD(struct thread, valid_headers) * 8;
2327 CHECK(p->n_headers < n_headers_max, ENOSPC);
2329 /* Node allocation. */
2330 h = calloc(1, sizeof(struct header));
2333 /* Node initialization. */
2334 strcpy(h->name, name);
2336 h->struct_id = p->n_structs;
2337 h->id = p->n_headers;
2339 /* Node add to tailq. */
2340 TAILQ_INSERT_TAIL(&p->headers, h, node);
2348 header_build(struct rte_swx_pipeline *p)
2351 uint32_t n_bytes = 0, i;
2353 TAILQ_FOREACH(h, &p->headers, node) {
2354 n_bytes += h->st->n_bits / 8;
2357 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
2358 struct thread *t = &p->threads[i];
2359 uint32_t offset = 0;
2361 t->headers = calloc(p->n_headers,
2362 sizeof(struct header_runtime));
2363 CHECK(t->headers, ENOMEM);
2365 t->headers_out = calloc(p->n_headers,
2366 sizeof(struct header_out_runtime));
2367 CHECK(t->headers_out, ENOMEM);
2369 t->header_storage = calloc(1, n_bytes);
2370 CHECK(t->header_storage, ENOMEM);
2372 t->header_out_storage = calloc(1, n_bytes);
2373 CHECK(t->header_out_storage, ENOMEM);
2375 TAILQ_FOREACH(h, &p->headers, node) {
2376 uint8_t *header_storage;
2378 header_storage = &t->header_storage[offset];
2379 offset += h->st->n_bits / 8;
2381 t->headers[h->id].ptr0 = header_storage;
2382 t->structs[h->struct_id] = header_storage;
2390 header_build_free(struct rte_swx_pipeline *p)
2394 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
2395 struct thread *t = &p->threads[i];
2397 free(t->headers_out);
2398 t->headers_out = NULL;
2403 free(t->header_out_storage);
2404 t->header_out_storage = NULL;
2406 free(t->header_storage);
2407 t->header_storage = NULL;
2412 header_free(struct rte_swx_pipeline *p)
2414 header_build_free(p);
2417 struct header *elem;
2419 elem = TAILQ_FIRST(&p->headers);
2423 TAILQ_REMOVE(&p->headers, elem, node);
2431 static struct field *
2432 metadata_field_parse(struct rte_swx_pipeline *p, const char *name)
2434 if (!p->metadata_st)
2437 if (name[0] != 'm' || name[1] != '.')
2440 return struct_type_field_find(p->metadata_st, &name[2]);
2444 rte_swx_pipeline_packet_metadata_register(struct rte_swx_pipeline *p,
2445 const char *struct_type_name)
2447 struct struct_type *st = NULL;
2451 CHECK_NAME(struct_type_name, EINVAL);
2452 st = struct_type_find(p, struct_type_name);
2454 CHECK(!p->metadata_st, EINVAL);
2456 p->metadata_st = st;
2457 p->metadata_struct_id = p->n_structs;
2465 metadata_build(struct rte_swx_pipeline *p)
2467 uint32_t n_bytes = p->metadata_st->n_bits / 8;
2470 /* Thread-level initialization. */
2471 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
2472 struct thread *t = &p->threads[i];
2475 metadata = calloc(1, n_bytes);
2476 CHECK(metadata, ENOMEM);
2478 t->metadata = metadata;
2479 t->structs[p->metadata_struct_id] = metadata;
2486 metadata_build_free(struct rte_swx_pipeline *p)
2490 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
2491 struct thread *t = &p->threads[i];
2499 metadata_free(struct rte_swx_pipeline *p)
2501 metadata_build_free(p);
2508 instruction_is_tx(enum instruction_type type)
2521 instruction_is_jmp(struct instruction *instr)
2523 switch (instr->type) {
2525 case INSTR_JMP_VALID:
2526 case INSTR_JMP_INVALID:
2528 case INSTR_JMP_MISS:
2529 case INSTR_JMP_ACTION_HIT:
2530 case INSTR_JMP_ACTION_MISS:
2532 case INSTR_JMP_EQ_S:
2533 case INSTR_JMP_EQ_I:
2535 case INSTR_JMP_NEQ_S:
2536 case INSTR_JMP_NEQ_I:
2538 case INSTR_JMP_LT_MH:
2539 case INSTR_JMP_LT_HM:
2540 case INSTR_JMP_LT_HH:
2541 case INSTR_JMP_LT_MI:
2542 case INSTR_JMP_LT_HI:
2544 case INSTR_JMP_GT_MH:
2545 case INSTR_JMP_GT_HM:
2546 case INSTR_JMP_GT_HH:
2547 case INSTR_JMP_GT_MI:
2548 case INSTR_JMP_GT_HI:
2556 static struct field *
2557 action_field_parse(struct action *action, const char *name);
2559 static struct field *
2560 struct_field_parse(struct rte_swx_pipeline *p,
2561 struct action *action,
2563 uint32_t *struct_id)
2570 struct header *header;
2572 f = header_field_parse(p, name, &header);
2576 *struct_id = header->struct_id;
2582 f = metadata_field_parse(p, name);
2586 *struct_id = p->metadata_struct_id;
2595 f = action_field_parse(action, name);
2605 struct extern_obj *obj;
2607 f = extern_obj_mailbox_field_parse(p, name, &obj);
2611 *struct_id = obj->struct_id;
2617 struct extern_func *func;
2619 f = extern_func_mailbox_field_parse(p, name, &func);
2623 *struct_id = func->struct_id;
2633 pipeline_port_inc(struct rte_swx_pipeline *p)
2635 p->port_id = (p->port_id + 1) & (p->n_ports_in - 1);
2639 thread_ip_reset(struct rte_swx_pipeline *p, struct thread *t)
2641 t->ip = p->instructions;
2645 thread_ip_set(struct thread *t, struct instruction *ip)
2651 thread_ip_action_call(struct rte_swx_pipeline *p,
2656 t->ip = p->action_instructions[action_id];
2660 thread_ip_inc(struct rte_swx_pipeline *p);
2663 thread_ip_inc(struct rte_swx_pipeline *p)
2665 struct thread *t = &p->threads[p->thread_id];
2671 thread_ip_inc_cond(struct thread *t, int cond)
2677 thread_yield(struct rte_swx_pipeline *p)
2679 p->thread_id = (p->thread_id + 1) & (RTE_SWX_PIPELINE_THREADS_MAX - 1);
2683 thread_yield_cond(struct rte_swx_pipeline *p, int cond)
2685 p->thread_id = (p->thread_id + cond) & (RTE_SWX_PIPELINE_THREADS_MAX - 1);
2692 instr_rx_translate(struct rte_swx_pipeline *p,
2693 struct action *action,
2696 struct instruction *instr,
2697 struct instruction_data *data __rte_unused)
2701 CHECK(!action, EINVAL);
2702 CHECK(n_tokens == 2, EINVAL);
2704 f = metadata_field_parse(p, tokens[1]);
2707 instr->type = INSTR_RX;
2708 instr->io.io.offset = f->offset / 8;
2709 instr->io.io.n_bits = f->n_bits;
2714 instr_rx_exec(struct rte_swx_pipeline *p);
2717 instr_rx_exec(struct rte_swx_pipeline *p)
2719 struct thread *t = &p->threads[p->thread_id];
2720 struct instruction *ip = t->ip;
2721 struct port_in_runtime *port = &p->in[p->port_id];
2722 struct rte_swx_pkt *pkt = &t->pkt;
2726 pkt_received = port->pkt_rx(port->obj, pkt);
2727 t->ptr = &pkt->pkt[pkt->offset];
2728 rte_prefetch0(t->ptr);
2730 TRACE("[Thread %2u] rx %s from port %u\n",
2732 pkt_received ? "1 pkt" : "0 pkts",
2736 t->valid_headers = 0;
2737 t->n_headers_out = 0;
2740 METADATA_WRITE(t, ip->io.io.offset, ip->io.io.n_bits, p->port_id);
2743 t->table_state = p->table_state;
2746 pipeline_port_inc(p);
2747 thread_ip_inc_cond(t, pkt_received);
2755 instr_tx_translate(struct rte_swx_pipeline *p,
2756 struct action *action __rte_unused,
2759 struct instruction *instr,
2760 struct instruction_data *data __rte_unused)
2762 char *port = tokens[1];
2766 CHECK(n_tokens == 2, EINVAL);
2768 f = metadata_field_parse(p, port);
2770 instr->type = INSTR_TX;
2771 instr->io.io.offset = f->offset / 8;
2772 instr->io.io.n_bits = f->n_bits;
2777 port_val = strtoul(port, &port, 0);
2778 CHECK(!port[0], EINVAL);
2780 instr->type = INSTR_TX_I;
2781 instr->io.io.val = port_val;
2786 instr_drop_translate(struct rte_swx_pipeline *p,
2787 struct action *action __rte_unused,
2788 char **tokens __rte_unused,
2790 struct instruction *instr,
2791 struct instruction_data *data __rte_unused)
2793 CHECK(n_tokens == 1, EINVAL);
2796 instr->type = INSTR_TX_I;
2797 instr->io.io.val = p->n_ports_out - 1;
2802 emit_handler(struct thread *t)
2804 struct header_out_runtime *h0 = &t->headers_out[0];
2805 struct header_out_runtime *h1 = &t->headers_out[1];
2806 uint32_t offset = 0, i;
2808 /* No header change or header decapsulation. */
2809 if ((t->n_headers_out == 1) &&
2810 (h0->ptr + h0->n_bytes == t->ptr)) {
2811 TRACE("Emit handler: no header change or header decap.\n");
2813 t->pkt.offset -= h0->n_bytes;
2814 t->pkt.length += h0->n_bytes;
2819 /* Header encapsulation (optionally, with prior header decasulation). */
2820 if ((t->n_headers_out == 2) &&
2821 (h1->ptr + h1->n_bytes == t->ptr) &&
2822 (h0->ptr == h0->ptr0)) {
2825 TRACE("Emit handler: header encapsulation.\n");
2827 offset = h0->n_bytes + h1->n_bytes;
2828 memcpy(t->ptr - offset, h0->ptr, h0->n_bytes);
2829 t->pkt.offset -= offset;
2830 t->pkt.length += offset;
2835 /* Header insertion. */
2838 /* Header extraction. */
2841 /* For any other case. */
2842 TRACE("Emit handler: complex case.\n");
2844 for (i = 0; i < t->n_headers_out; i++) {
2845 struct header_out_runtime *h = &t->headers_out[i];
2847 memcpy(&t->header_out_storage[offset], h->ptr, h->n_bytes);
2848 offset += h->n_bytes;
2852 memcpy(t->ptr - offset, t->header_out_storage, offset);
2853 t->pkt.offset -= offset;
2854 t->pkt.length += offset;
2859 instr_tx_exec(struct rte_swx_pipeline *p);
2862 instr_tx_exec(struct rte_swx_pipeline *p)
2864 struct thread *t = &p->threads[p->thread_id];
2865 struct instruction *ip = t->ip;
2866 uint64_t port_id = METADATA_READ(t, ip->io.io.offset, ip->io.io.n_bits);
2867 struct port_out_runtime *port = &p->out[port_id];
2868 struct rte_swx_pkt *pkt = &t->pkt;
2870 TRACE("[Thread %2u]: tx 1 pkt to port %u\n",
2878 port->pkt_tx(port->obj, pkt);
2881 thread_ip_reset(p, t);
2886 instr_tx_i_exec(struct rte_swx_pipeline *p)
2888 struct thread *t = &p->threads[p->thread_id];
2889 struct instruction *ip = t->ip;
2890 uint64_t port_id = ip->io.io.val;
2891 struct port_out_runtime *port = &p->out[port_id];
2892 struct rte_swx_pkt *pkt = &t->pkt;
2894 TRACE("[Thread %2u]: tx (i) 1 pkt to port %u\n",
2902 port->pkt_tx(port->obj, pkt);
2905 thread_ip_reset(p, t);
2913 instr_hdr_extract_translate(struct rte_swx_pipeline *p,
2914 struct action *action,
2917 struct instruction *instr,
2918 struct instruction_data *data __rte_unused)
2922 CHECK(!action, EINVAL);
2923 CHECK(n_tokens == 2, EINVAL);
2925 h = header_parse(p, tokens[1]);
2928 instr->type = INSTR_HDR_EXTRACT;
2929 instr->io.hdr.header_id[0] = h->id;
2930 instr->io.hdr.struct_id[0] = h->struct_id;
2931 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
2936 __instr_hdr_extract_exec(struct rte_swx_pipeline *p, uint32_t n_extract);
2939 __instr_hdr_extract_exec(struct rte_swx_pipeline *p, uint32_t n_extract)
2941 struct thread *t = &p->threads[p->thread_id];
2942 struct instruction *ip = t->ip;
2943 uint64_t valid_headers = t->valid_headers;
2944 uint8_t *ptr = t->ptr;
2945 uint32_t offset = t->pkt.offset;
2946 uint32_t length = t->pkt.length;
2949 for (i = 0; i < n_extract; i++) {
2950 uint32_t header_id = ip->io.hdr.header_id[i];
2951 uint32_t struct_id = ip->io.hdr.struct_id[i];
2952 uint32_t n_bytes = ip->io.hdr.n_bytes[i];
2954 TRACE("[Thread %2u]: extract header %u (%u bytes)\n",
2960 t->structs[struct_id] = ptr;
2961 valid_headers = MASK64_BIT_SET(valid_headers, header_id);
2970 t->valid_headers = valid_headers;
2973 t->pkt.offset = offset;
2974 t->pkt.length = length;
2979 instr_hdr_extract_exec(struct rte_swx_pipeline *p)
2981 __instr_hdr_extract_exec(p, 1);
2988 instr_hdr_extract2_exec(struct rte_swx_pipeline *p)
2990 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n",
2993 __instr_hdr_extract_exec(p, 2);
3000 instr_hdr_extract3_exec(struct rte_swx_pipeline *p)
3002 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n",
3005 __instr_hdr_extract_exec(p, 3);
3012 instr_hdr_extract4_exec(struct rte_swx_pipeline *p)
3014 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n",
3017 __instr_hdr_extract_exec(p, 4);
3024 instr_hdr_extract5_exec(struct rte_swx_pipeline *p)
3026 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n",
3029 __instr_hdr_extract_exec(p, 5);
3036 instr_hdr_extract6_exec(struct rte_swx_pipeline *p)
3038 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n",
3041 __instr_hdr_extract_exec(p, 6);
3048 instr_hdr_extract7_exec(struct rte_swx_pipeline *p)
3050 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n",
3053 __instr_hdr_extract_exec(p, 7);
3060 instr_hdr_extract8_exec(struct rte_swx_pipeline *p)
3062 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n",
3065 __instr_hdr_extract_exec(p, 8);
3075 instr_hdr_emit_translate(struct rte_swx_pipeline *p,
3076 struct action *action __rte_unused,
3079 struct instruction *instr,
3080 struct instruction_data *data __rte_unused)
3084 CHECK(n_tokens == 2, EINVAL);
3086 h = header_parse(p, tokens[1]);
3089 instr->type = INSTR_HDR_EMIT;
3090 instr->io.hdr.header_id[0] = h->id;
3091 instr->io.hdr.struct_id[0] = h->struct_id;
3092 instr->io.hdr.n_bytes[0] = h->st->n_bits / 8;
3097 __instr_hdr_emit_exec(struct rte_swx_pipeline *p, uint32_t n_emit);
3100 __instr_hdr_emit_exec(struct rte_swx_pipeline *p, uint32_t n_emit)
3102 struct thread *t = &p->threads[p->thread_id];
3103 struct instruction *ip = t->ip;
3104 uint32_t n_headers_out = t->n_headers_out;
3105 struct header_out_runtime *ho = &t->headers_out[n_headers_out - 1];
3106 uint8_t *ho_ptr = NULL;
3107 uint32_t ho_nbytes = 0, i;
3109 for (i = 0; i < n_emit; i++) {
3110 uint32_t header_id = ip->io.hdr.header_id[i];
3111 uint32_t struct_id = ip->io.hdr.struct_id[i];
3112 uint32_t n_bytes = ip->io.hdr.n_bytes[i];
3114 struct header_runtime *hi = &t->headers[header_id];
3115 uint8_t *hi_ptr = t->structs[struct_id];
3117 TRACE("[Thread %2u]: emit header %u\n",
3123 if (!t->n_headers_out) {
3124 ho = &t->headers_out[0];
3126 ho->ptr0 = hi->ptr0;
3130 ho_nbytes = n_bytes;
3137 ho_nbytes = ho->n_bytes;
3141 if (ho_ptr + ho_nbytes == hi_ptr) {
3142 ho_nbytes += n_bytes;
3144 ho->n_bytes = ho_nbytes;
3147 ho->ptr0 = hi->ptr0;
3151 ho_nbytes = n_bytes;
3157 ho->n_bytes = ho_nbytes;
3158 t->n_headers_out = n_headers_out;
3162 instr_hdr_emit_exec(struct rte_swx_pipeline *p)
3164 __instr_hdr_emit_exec(p, 1);
3171 instr_hdr_emit_tx_exec(struct rte_swx_pipeline *p)
3173 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n",
3176 __instr_hdr_emit_exec(p, 1);
3181 instr_hdr_emit2_tx_exec(struct rte_swx_pipeline *p)
3183 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n",
3186 __instr_hdr_emit_exec(p, 2);
3191 instr_hdr_emit3_tx_exec(struct rte_swx_pipeline *p)
3193 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n",
3196 __instr_hdr_emit_exec(p, 3);
3201 instr_hdr_emit4_tx_exec(struct rte_swx_pipeline *p)
3203 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n",
3206 __instr_hdr_emit_exec(p, 4);
3211 instr_hdr_emit5_tx_exec(struct rte_swx_pipeline *p)
3213 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n",
3216 __instr_hdr_emit_exec(p, 5);
3221 instr_hdr_emit6_tx_exec(struct rte_swx_pipeline *p)
3223 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n",
3226 __instr_hdr_emit_exec(p, 6);
3231 instr_hdr_emit7_tx_exec(struct rte_swx_pipeline *p)
3233 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n",
3236 __instr_hdr_emit_exec(p, 7);
3241 instr_hdr_emit8_tx_exec(struct rte_swx_pipeline *p)
3243 TRACE("[Thread %2u] *** The next 9 instructions are fused. ***\n",
3246 __instr_hdr_emit_exec(p, 8);
3254 instr_hdr_validate_translate(struct rte_swx_pipeline *p,
3255 struct action *action __rte_unused,
3258 struct instruction *instr,
3259 struct instruction_data *data __rte_unused)
3263 CHECK(n_tokens == 2, EINVAL);
3265 h = header_parse(p, tokens[1]);
3268 instr->type = INSTR_HDR_VALIDATE;
3269 instr->valid.header_id = h->id;
3274 instr_hdr_validate_exec(struct rte_swx_pipeline *p)
3276 struct thread *t = &p->threads[p->thread_id];
3277 struct instruction *ip = t->ip;
3278 uint32_t header_id = ip->valid.header_id;
3280 TRACE("[Thread %2u] validate header %u\n", p->thread_id, header_id);
3283 t->valid_headers = MASK64_BIT_SET(t->valid_headers, header_id);
3293 instr_hdr_invalidate_translate(struct rte_swx_pipeline *p,
3294 struct action *action __rte_unused,
3297 struct instruction *instr,
3298 struct instruction_data *data __rte_unused)
3302 CHECK(n_tokens == 2, EINVAL);
3304 h = header_parse(p, tokens[1]);
3307 instr->type = INSTR_HDR_INVALIDATE;
3308 instr->valid.header_id = h->id;
3313 instr_hdr_invalidate_exec(struct rte_swx_pipeline *p)
3315 struct thread *t = &p->threads[p->thread_id];
3316 struct instruction *ip = t->ip;
3317 uint32_t header_id = ip->valid.header_id;
3319 TRACE("[Thread %2u] invalidate header %u\n", p->thread_id, header_id);
3322 t->valid_headers = MASK64_BIT_CLR(t->valid_headers, header_id);
3331 static struct table *
3332 table_find(struct rte_swx_pipeline *p, const char *name);
3335 instr_table_translate(struct rte_swx_pipeline *p,
3336 struct action *action,
3339 struct instruction *instr,
3340 struct instruction_data *data __rte_unused)
3344 CHECK(!action, EINVAL);
3345 CHECK(n_tokens == 2, EINVAL);
3347 t = table_find(p, tokens[1]);
3350 instr->type = INSTR_TABLE;
3351 instr->table.table_id = t->id;
3356 instr_table_exec(struct rte_swx_pipeline *p)
3358 struct thread *t = &p->threads[p->thread_id];
3359 struct instruction *ip = t->ip;
3360 uint32_t table_id = ip->table.table_id;
3361 struct rte_swx_table_state *ts = &t->table_state[table_id];
3362 struct table_runtime *table = &t->tables[table_id];
3363 struct table_statistics *stats = &p->table_stats[table_id];
3364 uint64_t action_id, n_pkts_hit, n_pkts_action;
3365 uint8_t *action_data;
3369 done = table->func(ts->obj,
3377 TRACE("[Thread %2u] table %u (not finalized)\n",
3385 action_id = hit ? action_id : ts->default_action_id;
3386 action_data = hit ? action_data : ts->default_action_data;
3387 n_pkts_hit = stats->n_pkts_hit[hit];
3388 n_pkts_action = stats->n_pkts_action[action_id];
3390 TRACE("[Thread %2u] table %u (%s, action %u)\n",
3393 hit ? "hit" : "miss",
3394 (uint32_t)action_id);
3396 t->action_id = action_id;
3397 t->structs[0] = action_data;
3399 stats->n_pkts_hit[hit] = n_pkts_hit + 1;
3400 stats->n_pkts_action[action_id] = n_pkts_action + 1;
3403 thread_ip_action_call(p, t, action_id);
3410 instr_extern_translate(struct rte_swx_pipeline *p,
3411 struct action *action __rte_unused,
3414 struct instruction *instr,
3415 struct instruction_data *data __rte_unused)
3417 char *token = tokens[1];
3419 CHECK(n_tokens == 2, EINVAL);
3421 if (token[0] == 'e') {
3422 struct extern_obj *obj;
3423 struct extern_type_member_func *func;
3425 func = extern_obj_member_func_parse(p, token, &obj);
3426 CHECK(func, EINVAL);
3428 instr->type = INSTR_EXTERN_OBJ;
3429 instr->ext_obj.ext_obj_id = obj->id;
3430 instr->ext_obj.func_id = func->id;
3435 if (token[0] == 'f') {
3436 struct extern_func *func;
3438 func = extern_func_parse(p, token);
3439 CHECK(func, EINVAL);
3441 instr->type = INSTR_EXTERN_FUNC;
3442 instr->ext_func.ext_func_id = func->id;
3451 instr_extern_obj_exec(struct rte_swx_pipeline *p)
3453 struct thread *t = &p->threads[p->thread_id];
3454 struct instruction *ip = t->ip;
3455 uint32_t obj_id = ip->ext_obj.ext_obj_id;
3456 uint32_t func_id = ip->ext_obj.func_id;
3457 struct extern_obj_runtime *obj = &t->extern_objs[obj_id];
3458 rte_swx_extern_type_member_func_t func = obj->funcs[func_id];
3460 TRACE("[Thread %2u] extern obj %u member func %u\n",
3465 /* Extern object member function execute. */
3466 uint32_t done = func(obj->obj, obj->mailbox);
3469 thread_ip_inc_cond(t, done);
3470 thread_yield_cond(p, done ^ 1);
3474 instr_extern_func_exec(struct rte_swx_pipeline *p)
3476 struct thread *t = &p->threads[p->thread_id];
3477 struct instruction *ip = t->ip;
3478 uint32_t ext_func_id = ip->ext_func.ext_func_id;
3479 struct extern_func_runtime *ext_func = &t->extern_funcs[ext_func_id];
3480 rte_swx_extern_func_t func = ext_func->func;
3482 TRACE("[Thread %2u] extern func %u\n",
3486 /* Extern function execute. */
3487 uint32_t done = func(ext_func->mailbox);
3490 thread_ip_inc_cond(t, done);
3491 thread_yield_cond(p, done ^ 1);
3498 instr_mov_translate(struct rte_swx_pipeline *p,
3499 struct action *action,
3502 struct instruction *instr,
3503 struct instruction_data *data __rte_unused)
3505 char *dst = tokens[1], *src = tokens[2];
3506 struct field *fdst, *fsrc;
3508 uint32_t dst_struct_id, src_struct_id;
3510 CHECK(n_tokens == 3, EINVAL);
3512 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3513 CHECK(fdst, EINVAL);
3516 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3518 instr->type = INSTR_MOV;
3519 if ((dst[0] == 'h' && src[0] != 'h') ||
3520 (dst[0] != 'h' && src[0] == 'h'))
3521 instr->type = INSTR_MOV_S;
3523 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
3524 instr->mov.dst.n_bits = fdst->n_bits;
3525 instr->mov.dst.offset = fdst->offset / 8;
3526 instr->mov.src.struct_id = (uint8_t)src_struct_id;
3527 instr->mov.src.n_bits = fsrc->n_bits;
3528 instr->mov.src.offset = fsrc->offset / 8;
3533 src_val = strtoull(src, &src, 0);
3534 CHECK(!src[0], EINVAL);
3537 src_val = hton64(src_val) >> (64 - fdst->n_bits);
3539 instr->type = INSTR_MOV_I;
3540 instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
3541 instr->mov.dst.n_bits = fdst->n_bits;
3542 instr->mov.dst.offset = fdst->offset / 8;
3543 instr->mov.src_val = src_val;
3548 instr_mov_exec(struct rte_swx_pipeline *p)
3550 struct thread *t = &p->threads[p->thread_id];
3551 struct instruction *ip = t->ip;
3553 TRACE("[Thread %2u] mov\n",
3563 instr_mov_s_exec(struct rte_swx_pipeline *p)
3565 struct thread *t = &p->threads[p->thread_id];
3566 struct instruction *ip = t->ip;
3568 TRACE("[Thread %2u] mov (s)\n",
3578 instr_mov_i_exec(struct rte_swx_pipeline *p)
3580 struct thread *t = &p->threads[p->thread_id];
3581 struct instruction *ip = t->ip;
3583 TRACE("[Thread %2u] mov m.f %" PRIx64 "\n",
3597 instr_dma_translate(struct rte_swx_pipeline *p,
3598 struct action *action,
3601 struct instruction *instr,
3602 struct instruction_data *data __rte_unused)
3604 char *dst = tokens[1];
3605 char *src = tokens[2];
3609 CHECK(action, EINVAL);
3610 CHECK(n_tokens == 3, EINVAL);
3612 h = header_parse(p, dst);
3615 tf = action_field_parse(action, src);
3618 instr->type = INSTR_DMA_HT;
3619 instr->dma.dst.header_id[0] = h->id;
3620 instr->dma.dst.struct_id[0] = h->struct_id;
3621 instr->dma.n_bytes[0] = h->st->n_bits / 8;
3622 instr->dma.src.offset[0] = tf->offset / 8;
3628 __instr_dma_ht_exec(struct rte_swx_pipeline *p, uint32_t n_dma);
3631 __instr_dma_ht_exec(struct rte_swx_pipeline *p, uint32_t n_dma)
3633 struct thread *t = &p->threads[p->thread_id];
3634 struct instruction *ip = t->ip;
3635 uint8_t *action_data = t->structs[0];
3636 uint64_t valid_headers = t->valid_headers;
3639 for (i = 0; i < n_dma; i++) {
3640 uint32_t header_id = ip->dma.dst.header_id[i];
3641 uint32_t struct_id = ip->dma.dst.struct_id[i];
3642 uint32_t offset = ip->dma.src.offset[i];
3643 uint32_t n_bytes = ip->dma.n_bytes[i];
3645 struct header_runtime *h = &t->headers[header_id];
3646 uint8_t *h_ptr0 = h->ptr0;
3647 uint8_t *h_ptr = t->structs[struct_id];
3649 void *dst = MASK64_BIT_GET(valid_headers, header_id) ?
3651 void *src = &action_data[offset];
3653 TRACE("[Thread %2u] dma h.s t.f\n", p->thread_id);
3656 memcpy(dst, src, n_bytes);
3657 t->structs[struct_id] = dst;
3658 valid_headers = MASK64_BIT_SET(valid_headers, header_id);
3661 t->valid_headers = valid_headers;
3665 instr_dma_ht_exec(struct rte_swx_pipeline *p)
3667 __instr_dma_ht_exec(p, 1);
3674 instr_dma_ht2_exec(struct rte_swx_pipeline *p)
3676 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n",
3679 __instr_dma_ht_exec(p, 2);
3686 instr_dma_ht3_exec(struct rte_swx_pipeline *p)
3688 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n",
3691 __instr_dma_ht_exec(p, 3);
3698 instr_dma_ht4_exec(struct rte_swx_pipeline *p)
3700 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n",
3703 __instr_dma_ht_exec(p, 4);
3710 instr_dma_ht5_exec(struct rte_swx_pipeline *p)
3712 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n",
3715 __instr_dma_ht_exec(p, 5);
3722 instr_dma_ht6_exec(struct rte_swx_pipeline *p)
3724 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n",
3727 __instr_dma_ht_exec(p, 6);
3734 instr_dma_ht7_exec(struct rte_swx_pipeline *p)
3736 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n",
3739 __instr_dma_ht_exec(p, 7);
3746 instr_dma_ht8_exec(struct rte_swx_pipeline *p)
3748 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n",
3751 __instr_dma_ht_exec(p, 8);
3761 instr_alu_add_translate(struct rte_swx_pipeline *p,
3762 struct action *action,
3765 struct instruction *instr,
3766 struct instruction_data *data __rte_unused)
3768 char *dst = tokens[1], *src = tokens[2];
3769 struct field *fdst, *fsrc;
3771 uint32_t dst_struct_id, src_struct_id;
3773 CHECK(n_tokens == 3, EINVAL);
3775 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3776 CHECK(fdst, EINVAL);
3778 /* ADD, ADD_HM, ADD_MH, ADD_HH. */
3779 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3781 instr->type = INSTR_ALU_ADD;
3782 if (dst[0] == 'h' && src[0] != 'h')
3783 instr->type = INSTR_ALU_ADD_HM;
3784 if (dst[0] != 'h' && src[0] == 'h')
3785 instr->type = INSTR_ALU_ADD_MH;
3786 if (dst[0] == 'h' && src[0] == 'h')
3787 instr->type = INSTR_ALU_ADD_HH;
3789 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3790 instr->alu.dst.n_bits = fdst->n_bits;
3791 instr->alu.dst.offset = fdst->offset / 8;
3792 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3793 instr->alu.src.n_bits = fsrc->n_bits;
3794 instr->alu.src.offset = fsrc->offset / 8;
3798 /* ADD_MI, ADD_HI. */
3799 src_val = strtoull(src, &src, 0);
3800 CHECK(!src[0], EINVAL);
3802 instr->type = INSTR_ALU_ADD_MI;
3804 instr->type = INSTR_ALU_ADD_HI;
3806 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3807 instr->alu.dst.n_bits = fdst->n_bits;
3808 instr->alu.dst.offset = fdst->offset / 8;
3809 instr->alu.src_val = src_val;
3814 instr_alu_sub_translate(struct rte_swx_pipeline *p,
3815 struct action *action,
3818 struct instruction *instr,
3819 struct instruction_data *data __rte_unused)
3821 char *dst = tokens[1], *src = tokens[2];
3822 struct field *fdst, *fsrc;
3824 uint32_t dst_struct_id, src_struct_id;
3826 CHECK(n_tokens == 3, EINVAL);
3828 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3829 CHECK(fdst, EINVAL);
3831 /* SUB, SUB_HM, SUB_MH, SUB_HH. */
3832 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3834 instr->type = INSTR_ALU_SUB;
3835 if (dst[0] == 'h' && src[0] != 'h')
3836 instr->type = INSTR_ALU_SUB_HM;
3837 if (dst[0] != 'h' && src[0] == 'h')
3838 instr->type = INSTR_ALU_SUB_MH;
3839 if (dst[0] == 'h' && src[0] == 'h')
3840 instr->type = INSTR_ALU_SUB_HH;
3842 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3843 instr->alu.dst.n_bits = fdst->n_bits;
3844 instr->alu.dst.offset = fdst->offset / 8;
3845 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3846 instr->alu.src.n_bits = fsrc->n_bits;
3847 instr->alu.src.offset = fsrc->offset / 8;
3851 /* SUB_MI, SUB_HI. */
3852 src_val = strtoull(src, &src, 0);
3853 CHECK(!src[0], EINVAL);
3855 instr->type = INSTR_ALU_SUB_MI;
3857 instr->type = INSTR_ALU_SUB_HI;
3859 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3860 instr->alu.dst.n_bits = fdst->n_bits;
3861 instr->alu.dst.offset = fdst->offset / 8;
3862 instr->alu.src_val = src_val;
3867 instr_alu_ckadd_translate(struct rte_swx_pipeline *p,
3868 struct action *action __rte_unused,
3871 struct instruction *instr,
3872 struct instruction_data *data __rte_unused)
3874 char *dst = tokens[1], *src = tokens[2];
3875 struct header *hdst, *hsrc;
3876 struct field *fdst, *fsrc;
3878 CHECK(n_tokens == 3, EINVAL);
3880 fdst = header_field_parse(p, dst, &hdst);
3881 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
3884 fsrc = header_field_parse(p, src, &hsrc);
3886 instr->type = INSTR_ALU_CKADD_FIELD;
3887 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
3888 instr->alu.dst.n_bits = fdst->n_bits;
3889 instr->alu.dst.offset = fdst->offset / 8;
3890 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
3891 instr->alu.src.n_bits = fsrc->n_bits;
3892 instr->alu.src.offset = fsrc->offset / 8;
3896 /* CKADD_STRUCT, CKADD_STRUCT20. */
3897 hsrc = header_parse(p, src);
3898 CHECK(hsrc, EINVAL);
3900 instr->type = INSTR_ALU_CKADD_STRUCT;
3901 if ((hsrc->st->n_bits / 8) == 20)
3902 instr->type = INSTR_ALU_CKADD_STRUCT20;
3904 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
3905 instr->alu.dst.n_bits = fdst->n_bits;
3906 instr->alu.dst.offset = fdst->offset / 8;
3907 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
3908 instr->alu.src.n_bits = hsrc->st->n_bits;
3909 instr->alu.src.offset = 0; /* Unused. */
3914 instr_alu_cksub_translate(struct rte_swx_pipeline *p,
3915 struct action *action __rte_unused,
3918 struct instruction *instr,
3919 struct instruction_data *data __rte_unused)
3921 char *dst = tokens[1], *src = tokens[2];
3922 struct header *hdst, *hsrc;
3923 struct field *fdst, *fsrc;
3925 CHECK(n_tokens == 3, EINVAL);
3927 fdst = header_field_parse(p, dst, &hdst);
3928 CHECK(fdst && (fdst->n_bits == 16), EINVAL);
3930 fsrc = header_field_parse(p, src, &hsrc);
3931 CHECK(fsrc, EINVAL);
3933 instr->type = INSTR_ALU_CKSUB_FIELD;
3934 instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
3935 instr->alu.dst.n_bits = fdst->n_bits;
3936 instr->alu.dst.offset = fdst->offset / 8;
3937 instr->alu.src.struct_id = (uint8_t)hsrc->struct_id;
3938 instr->alu.src.n_bits = fsrc->n_bits;
3939 instr->alu.src.offset = fsrc->offset / 8;
3944 instr_alu_shl_translate(struct rte_swx_pipeline *p,
3945 struct action *action,
3948 struct instruction *instr,
3949 struct instruction_data *data __rte_unused)
3951 char *dst = tokens[1], *src = tokens[2];
3952 struct field *fdst, *fsrc;
3954 uint32_t dst_struct_id, src_struct_id;
3956 CHECK(n_tokens == 3, EINVAL);
3958 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
3959 CHECK(fdst, EINVAL);
3961 /* SHL, SHL_HM, SHL_MH, SHL_HH. */
3962 fsrc = struct_field_parse(p, action, src, &src_struct_id);
3964 instr->type = INSTR_ALU_SHL;
3965 if (dst[0] == 'h' && src[0] != 'h')
3966 instr->type = INSTR_ALU_SHL_HM;
3967 if (dst[0] != 'h' && src[0] == 'h')
3968 instr->type = INSTR_ALU_SHL_MH;
3969 if (dst[0] == 'h' && src[0] == 'h')
3970 instr->type = INSTR_ALU_SHL_HH;
3972 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3973 instr->alu.dst.n_bits = fdst->n_bits;
3974 instr->alu.dst.offset = fdst->offset / 8;
3975 instr->alu.src.struct_id = (uint8_t)src_struct_id;
3976 instr->alu.src.n_bits = fsrc->n_bits;
3977 instr->alu.src.offset = fsrc->offset / 8;
3981 /* SHL_MI, SHL_HI. */
3982 src_val = strtoull(src, &src, 0);
3983 CHECK(!src[0], EINVAL);
3985 instr->type = INSTR_ALU_SHL_MI;
3987 instr->type = INSTR_ALU_SHL_HI;
3989 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
3990 instr->alu.dst.n_bits = fdst->n_bits;
3991 instr->alu.dst.offset = fdst->offset / 8;
3992 instr->alu.src_val = src_val;
3997 instr_alu_shr_translate(struct rte_swx_pipeline *p,
3998 struct action *action,
4001 struct instruction *instr,
4002 struct instruction_data *data __rte_unused)
4004 char *dst = tokens[1], *src = tokens[2];
4005 struct field *fdst, *fsrc;
4007 uint32_t dst_struct_id, src_struct_id;
4009 CHECK(n_tokens == 3, EINVAL);
4011 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4012 CHECK(fdst, EINVAL);
4014 /* SHR, SHR_HM, SHR_MH, SHR_HH. */
4015 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4017 instr->type = INSTR_ALU_SHR;
4018 if (dst[0] == 'h' && src[0] != 'h')
4019 instr->type = INSTR_ALU_SHR_HM;
4020 if (dst[0] != 'h' && src[0] == 'h')
4021 instr->type = INSTR_ALU_SHR_MH;
4022 if (dst[0] == 'h' && src[0] == 'h')
4023 instr->type = INSTR_ALU_SHR_HH;
4025 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4026 instr->alu.dst.n_bits = fdst->n_bits;
4027 instr->alu.dst.offset = fdst->offset / 8;
4028 instr->alu.src.struct_id = (uint8_t)src_struct_id;
4029 instr->alu.src.n_bits = fsrc->n_bits;
4030 instr->alu.src.offset = fsrc->offset / 8;
4034 /* SHR_MI, SHR_HI. */
4035 src_val = strtoull(src, &src, 0);
4036 CHECK(!src[0], EINVAL);
4038 instr->type = INSTR_ALU_SHR_MI;
4040 instr->type = INSTR_ALU_SHR_HI;
4042 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4043 instr->alu.dst.n_bits = fdst->n_bits;
4044 instr->alu.dst.offset = fdst->offset / 8;
4045 instr->alu.src_val = src_val;
4050 instr_alu_and_translate(struct rte_swx_pipeline *p,
4051 struct action *action,
4054 struct instruction *instr,
4055 struct instruction_data *data __rte_unused)
4057 char *dst = tokens[1], *src = tokens[2];
4058 struct field *fdst, *fsrc;
4060 uint32_t dst_struct_id, src_struct_id;
4062 CHECK(n_tokens == 3, EINVAL);
4064 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4065 CHECK(fdst, EINVAL);
4068 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4070 instr->type = INSTR_ALU_AND;
4071 if ((dst[0] == 'h' && src[0] != 'h') ||
4072 (dst[0] != 'h' && src[0] == 'h'))
4073 instr->type = INSTR_ALU_AND_S;
4075 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4076 instr->alu.dst.n_bits = fdst->n_bits;
4077 instr->alu.dst.offset = fdst->offset / 8;
4078 instr->alu.src.struct_id = (uint8_t)src_struct_id;
4079 instr->alu.src.n_bits = fsrc->n_bits;
4080 instr->alu.src.offset = fsrc->offset / 8;
4085 src_val = strtoull(src, &src, 0);
4086 CHECK(!src[0], EINVAL);
4089 src_val = hton64(src_val) >> (64 - fdst->n_bits);
4091 instr->type = INSTR_ALU_AND_I;
4092 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4093 instr->alu.dst.n_bits = fdst->n_bits;
4094 instr->alu.dst.offset = fdst->offset / 8;
4095 instr->alu.src_val = src_val;
4100 instr_alu_or_translate(struct rte_swx_pipeline *p,
4101 struct action *action,
4104 struct instruction *instr,
4105 struct instruction_data *data __rte_unused)
4107 char *dst = tokens[1], *src = tokens[2];
4108 struct field *fdst, *fsrc;
4110 uint32_t dst_struct_id, src_struct_id;
4112 CHECK(n_tokens == 3, EINVAL);
4114 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4115 CHECK(fdst, EINVAL);
4118 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4120 instr->type = INSTR_ALU_OR;
4121 if ((dst[0] == 'h' && src[0] != 'h') ||
4122 (dst[0] != 'h' && src[0] == 'h'))
4123 instr->type = INSTR_ALU_OR_S;
4125 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4126 instr->alu.dst.n_bits = fdst->n_bits;
4127 instr->alu.dst.offset = fdst->offset / 8;
4128 instr->alu.src.struct_id = (uint8_t)src_struct_id;
4129 instr->alu.src.n_bits = fsrc->n_bits;
4130 instr->alu.src.offset = fsrc->offset / 8;
4135 src_val = strtoull(src, &src, 0);
4136 CHECK(!src[0], EINVAL);
4139 src_val = hton64(src_val) >> (64 - fdst->n_bits);
4141 instr->type = INSTR_ALU_OR_I;
4142 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4143 instr->alu.dst.n_bits = fdst->n_bits;
4144 instr->alu.dst.offset = fdst->offset / 8;
4145 instr->alu.src_val = src_val;
4150 instr_alu_xor_translate(struct rte_swx_pipeline *p,
4151 struct action *action,
4154 struct instruction *instr,
4155 struct instruction_data *data __rte_unused)
4157 char *dst = tokens[1], *src = tokens[2];
4158 struct field *fdst, *fsrc;
4160 uint32_t dst_struct_id, src_struct_id;
4162 CHECK(n_tokens == 3, EINVAL);
4164 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4165 CHECK(fdst, EINVAL);
4168 fsrc = struct_field_parse(p, action, src, &src_struct_id);
4170 instr->type = INSTR_ALU_XOR;
4171 if ((dst[0] == 'h' && src[0] != 'h') ||
4172 (dst[0] != 'h' && src[0] == 'h'))
4173 instr->type = INSTR_ALU_XOR_S;
4175 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4176 instr->alu.dst.n_bits = fdst->n_bits;
4177 instr->alu.dst.offset = fdst->offset / 8;
4178 instr->alu.src.struct_id = (uint8_t)src_struct_id;
4179 instr->alu.src.n_bits = fsrc->n_bits;
4180 instr->alu.src.offset = fsrc->offset / 8;
4185 src_val = strtoull(src, &src, 0);
4186 CHECK(!src[0], EINVAL);
4189 src_val = hton64(src_val) >> (64 - fdst->n_bits);
4191 instr->type = INSTR_ALU_XOR_I;
4192 instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
4193 instr->alu.dst.n_bits = fdst->n_bits;
4194 instr->alu.dst.offset = fdst->offset / 8;
4195 instr->alu.src_val = src_val;
4200 instr_alu_add_exec(struct rte_swx_pipeline *p)
4202 struct thread *t = &p->threads[p->thread_id];
4203 struct instruction *ip = t->ip;
4205 TRACE("[Thread %2u] add\n", p->thread_id);
4215 instr_alu_add_mh_exec(struct rte_swx_pipeline *p)
4217 struct thread *t = &p->threads[p->thread_id];
4218 struct instruction *ip = t->ip;
4220 TRACE("[Thread %2u] add (mh)\n", p->thread_id);
4230 instr_alu_add_hm_exec(struct rte_swx_pipeline *p)
4232 struct thread *t = &p->threads[p->thread_id];
4233 struct instruction *ip = t->ip;
4235 TRACE("[Thread %2u] add (hm)\n", p->thread_id);
4245 instr_alu_add_hh_exec(struct rte_swx_pipeline *p)
4247 struct thread *t = &p->threads[p->thread_id];
4248 struct instruction *ip = t->ip;
4250 TRACE("[Thread %2u] add (hh)\n", p->thread_id);
4260 instr_alu_add_mi_exec(struct rte_swx_pipeline *p)
4262 struct thread *t = &p->threads[p->thread_id];
4263 struct instruction *ip = t->ip;
4265 TRACE("[Thread %2u] add (mi)\n", p->thread_id);
4275 instr_alu_add_hi_exec(struct rte_swx_pipeline *p)
4277 struct thread *t = &p->threads[p->thread_id];
4278 struct instruction *ip = t->ip;
4280 TRACE("[Thread %2u] add (hi)\n", p->thread_id);
4290 instr_alu_sub_exec(struct rte_swx_pipeline *p)
4292 struct thread *t = &p->threads[p->thread_id];
4293 struct instruction *ip = t->ip;
4295 TRACE("[Thread %2u] sub\n", p->thread_id);
4305 instr_alu_sub_mh_exec(struct rte_swx_pipeline *p)
4307 struct thread *t = &p->threads[p->thread_id];
4308 struct instruction *ip = t->ip;
4310 TRACE("[Thread %2u] sub (mh)\n", p->thread_id);
4320 instr_alu_sub_hm_exec(struct rte_swx_pipeline *p)
4322 struct thread *t = &p->threads[p->thread_id];
4323 struct instruction *ip = t->ip;
4325 TRACE("[Thread %2u] sub (hm)\n", p->thread_id);
4335 instr_alu_sub_hh_exec(struct rte_swx_pipeline *p)
4337 struct thread *t = &p->threads[p->thread_id];
4338 struct instruction *ip = t->ip;
4340 TRACE("[Thread %2u] sub (hh)\n", p->thread_id);
4350 instr_alu_sub_mi_exec(struct rte_swx_pipeline *p)
4352 struct thread *t = &p->threads[p->thread_id];
4353 struct instruction *ip = t->ip;
4355 TRACE("[Thread %2u] sub (mi)\n", p->thread_id);
4365 instr_alu_sub_hi_exec(struct rte_swx_pipeline *p)
4367 struct thread *t = &p->threads[p->thread_id];
4368 struct instruction *ip = t->ip;
4370 TRACE("[Thread %2u] sub (hi)\n", p->thread_id);
4380 instr_alu_shl_exec(struct rte_swx_pipeline *p)
4382 struct thread *t = &p->threads[p->thread_id];
4383 struct instruction *ip = t->ip;
4385 TRACE("[Thread %2u] shl\n", p->thread_id);
4395 instr_alu_shl_mh_exec(struct rte_swx_pipeline *p)
4397 struct thread *t = &p->threads[p->thread_id];
4398 struct instruction *ip = t->ip;
4400 TRACE("[Thread %2u] shl (mh)\n", p->thread_id);
4410 instr_alu_shl_hm_exec(struct rte_swx_pipeline *p)
4412 struct thread *t = &p->threads[p->thread_id];
4413 struct instruction *ip = t->ip;
4415 TRACE("[Thread %2u] shl (hm)\n", p->thread_id);
4425 instr_alu_shl_hh_exec(struct rte_swx_pipeline *p)
4427 struct thread *t = &p->threads[p->thread_id];
4428 struct instruction *ip = t->ip;
4430 TRACE("[Thread %2u] shl (hh)\n", p->thread_id);
4440 instr_alu_shl_mi_exec(struct rte_swx_pipeline *p)
4442 struct thread *t = &p->threads[p->thread_id];
4443 struct instruction *ip = t->ip;
4445 TRACE("[Thread %2u] shl (mi)\n", p->thread_id);
4455 instr_alu_shl_hi_exec(struct rte_swx_pipeline *p)
4457 struct thread *t = &p->threads[p->thread_id];
4458 struct instruction *ip = t->ip;
4460 TRACE("[Thread %2u] shl (hi)\n", p->thread_id);
4470 instr_alu_shr_exec(struct rte_swx_pipeline *p)
4472 struct thread *t = &p->threads[p->thread_id];
4473 struct instruction *ip = t->ip;
4475 TRACE("[Thread %2u] shr\n", p->thread_id);
4485 instr_alu_shr_mh_exec(struct rte_swx_pipeline *p)
4487 struct thread *t = &p->threads[p->thread_id];
4488 struct instruction *ip = t->ip;
4490 TRACE("[Thread %2u] shr (mh)\n", p->thread_id);
4500 instr_alu_shr_hm_exec(struct rte_swx_pipeline *p)
4502 struct thread *t = &p->threads[p->thread_id];
4503 struct instruction *ip = t->ip;
4505 TRACE("[Thread %2u] shr (hm)\n", p->thread_id);
4515 instr_alu_shr_hh_exec(struct rte_swx_pipeline *p)
4517 struct thread *t = &p->threads[p->thread_id];
4518 struct instruction *ip = t->ip;
4520 TRACE("[Thread %2u] shr (hh)\n", p->thread_id);
4530 instr_alu_shr_mi_exec(struct rte_swx_pipeline *p)
4532 struct thread *t = &p->threads[p->thread_id];
4533 struct instruction *ip = t->ip;
4535 TRACE("[Thread %2u] shr (mi)\n", p->thread_id);
4545 instr_alu_shr_hi_exec(struct rte_swx_pipeline *p)
4547 struct thread *t = &p->threads[p->thread_id];
4548 struct instruction *ip = t->ip;
4550 TRACE("[Thread %2u] shr (hi)\n", p->thread_id);
4560 instr_alu_and_exec(struct rte_swx_pipeline *p)
4562 struct thread *t = &p->threads[p->thread_id];
4563 struct instruction *ip = t->ip;
4565 TRACE("[Thread %2u] and\n", p->thread_id);
4575 instr_alu_and_s_exec(struct rte_swx_pipeline *p)
4577 struct thread *t = &p->threads[p->thread_id];
4578 struct instruction *ip = t->ip;
4580 TRACE("[Thread %2u] and (s)\n", p->thread_id);
4590 instr_alu_and_i_exec(struct rte_swx_pipeline *p)
4592 struct thread *t = &p->threads[p->thread_id];
4593 struct instruction *ip = t->ip;
4595 TRACE("[Thread %2u] and (i)\n", p->thread_id);
4605 instr_alu_or_exec(struct rte_swx_pipeline *p)
4607 struct thread *t = &p->threads[p->thread_id];
4608 struct instruction *ip = t->ip;
4610 TRACE("[Thread %2u] or\n", p->thread_id);
4620 instr_alu_or_s_exec(struct rte_swx_pipeline *p)
4622 struct thread *t = &p->threads[p->thread_id];
4623 struct instruction *ip = t->ip;
4625 TRACE("[Thread %2u] or (s)\n", p->thread_id);
4635 instr_alu_or_i_exec(struct rte_swx_pipeline *p)
4637 struct thread *t = &p->threads[p->thread_id];
4638 struct instruction *ip = t->ip;
4640 TRACE("[Thread %2u] or (i)\n", p->thread_id);
4650 instr_alu_xor_exec(struct rte_swx_pipeline *p)
4652 struct thread *t = &p->threads[p->thread_id];
4653 struct instruction *ip = t->ip;
4655 TRACE("[Thread %2u] xor\n", p->thread_id);
4665 instr_alu_xor_s_exec(struct rte_swx_pipeline *p)
4667 struct thread *t = &p->threads[p->thread_id];
4668 struct instruction *ip = t->ip;
4670 TRACE("[Thread %2u] xor (s)\n", p->thread_id);
4680 instr_alu_xor_i_exec(struct rte_swx_pipeline *p)
4682 struct thread *t = &p->threads[p->thread_id];
4683 struct instruction *ip = t->ip;
4685 TRACE("[Thread %2u] xor (i)\n", p->thread_id);
4695 instr_alu_ckadd_field_exec(struct rte_swx_pipeline *p)
4697 struct thread *t = &p->threads[p->thread_id];
4698 struct instruction *ip = t->ip;
4699 uint8_t *dst_struct, *src_struct;
4700 uint16_t *dst16_ptr, dst;
4701 uint64_t *src64_ptr, src64, src64_mask, src;
4704 TRACE("[Thread %2u] ckadd (field)\n", p->thread_id);
4707 dst_struct = t->structs[ip->alu.dst.struct_id];
4708 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
4711 src_struct = t->structs[ip->alu.src.struct_id];
4712 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
4714 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
4715 src = src64 & src64_mask;
4720 /* The first input (r) is a 16-bit number. The second and the third
4721 * inputs are 32-bit numbers. In the worst case scenario, the sum of the
4722 * three numbers (output r) is a 34-bit number.
4724 r += (src >> 32) + (src & 0xFFFFFFFF);
4726 /* The first input is a 16-bit number. The second input is an 18-bit
4727 * number. In the worst case scenario, the sum of the two numbers is a
4730 r = (r & 0xFFFF) + (r >> 16);
4732 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
4733 * a 3-bit number (0 .. 7). Their sum is a 17-bit number (0 .. 0x10006).
4735 r = (r & 0xFFFF) + (r >> 16);
4737 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
4738 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
4739 * 0x10006), the output r is (0 .. 7). So no carry bit can be generated,
4740 * therefore the output r is always a 16-bit number.
4742 r = (r & 0xFFFF) + (r >> 16);
4747 *dst16_ptr = (uint16_t)r;
4754 instr_alu_cksub_field_exec(struct rte_swx_pipeline *p)
4756 struct thread *t = &p->threads[p->thread_id];
4757 struct instruction *ip = t->ip;
4758 uint8_t *dst_struct, *src_struct;
4759 uint16_t *dst16_ptr, dst;
4760 uint64_t *src64_ptr, src64, src64_mask, src;
4763 TRACE("[Thread %2u] cksub (field)\n", p->thread_id);
4766 dst_struct = t->structs[ip->alu.dst.struct_id];
4767 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
4770 src_struct = t->structs[ip->alu.src.struct_id];
4771 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
4773 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
4774 src = src64 & src64_mask;
4779 /* Subtraction in 1's complement arithmetic (i.e. a '- b) is the same as
4780 * the following sequence of operations in 2's complement arithmetic:
4781 * a '- b = (a - b) % 0xFFFF.
4783 * In order to prevent an underflow for the below subtraction, in which
4784 * a 33-bit number (the subtrahend) is taken out of a 16-bit number (the
4785 * minuend), we first add a multiple of the 0xFFFF modulus to the
4786 * minuend. The number we add to the minuend needs to be a 34-bit number
4787 * or higher, so for readability reasons we picked the 36-bit multiple.
4788 * We are effectively turning the 16-bit minuend into a 36-bit number:
4789 * (a - b) % 0xFFFF = (a + 0xFFFF00000 - b) % 0xFFFF.
4791 r += 0xFFFF00000ULL; /* The output r is a 36-bit number. */
4793 /* A 33-bit number is subtracted from a 36-bit number (the input r). The
4794 * result (the output r) is a 36-bit number.
4796 r -= (src >> 32) + (src & 0xFFFFFFFF);
4798 /* The first input is a 16-bit number. The second input is a 20-bit
4799 * number. Their sum is a 21-bit number.
4801 r = (r & 0xFFFF) + (r >> 16);
4803 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
4804 * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1001E).
4806 r = (r & 0xFFFF) + (r >> 16);
4808 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
4809 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
4810 * 0x1001E), the output r is (0 .. 31). So no carry bit can be
4811 * generated, therefore the output r is always a 16-bit number.
4813 r = (r & 0xFFFF) + (r >> 16);
4818 *dst16_ptr = (uint16_t)r;
4825 instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline *p)
4827 struct thread *t = &p->threads[p->thread_id];
4828 struct instruction *ip = t->ip;
4829 uint8_t *dst_struct, *src_struct;
4830 uint16_t *dst16_ptr;
4831 uint32_t *src32_ptr;
4834 TRACE("[Thread %2u] ckadd (struct of 20 bytes)\n", p->thread_id);
4837 dst_struct = t->structs[ip->alu.dst.struct_id];
4838 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
4840 src_struct = t->structs[ip->alu.src.struct_id];
4841 src32_ptr = (uint32_t *)&src_struct[0];
4843 r0 = src32_ptr[0]; /* r0 is a 32-bit number. */
4844 r1 = src32_ptr[1]; /* r1 is a 32-bit number. */
4845 r0 += src32_ptr[2]; /* The output r0 is a 33-bit number. */
4846 r1 += src32_ptr[3]; /* The output r1 is a 33-bit number. */
4847 r0 += r1 + src32_ptr[4]; /* The output r0 is a 35-bit number. */
4849 /* The first input is a 16-bit number. The second input is a 19-bit
4850 * number. Their sum is a 20-bit number.
4852 r0 = (r0 & 0xFFFF) + (r0 >> 16);
4854 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
4855 * a 4-bit number (0 .. 15). The sum is a 17-bit number (0 .. 0x1000E).
4857 r0 = (r0 & 0xFFFF) + (r0 >> 16);
4859 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
4860 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
4861 * 0x1000E), the output r is (0 .. 15). So no carry bit can be
4862 * generated, therefore the output r is always a 16-bit number.
4864 r0 = (r0 & 0xFFFF) + (r0 >> 16);
4867 r0 = r0 ? r0 : 0xFFFF;
4869 *dst16_ptr = (uint16_t)r0;
4876 instr_alu_ckadd_struct_exec(struct rte_swx_pipeline *p)
4878 struct thread *t = &p->threads[p->thread_id];
4879 struct instruction *ip = t->ip;
4880 uint8_t *dst_struct, *src_struct;
4881 uint16_t *dst16_ptr;
4882 uint32_t *src32_ptr;
4886 TRACE("[Thread %2u] ckadd (struct)\n", p->thread_id);
4889 dst_struct = t->structs[ip->alu.dst.struct_id];
4890 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
4892 src_struct = t->structs[ip->alu.src.struct_id];
4893 src32_ptr = (uint32_t *)&src_struct[0];
4895 /* The max number of 32-bit words in a 256-byte header is 8 = 2^3.
4896 * Therefore, in the worst case scenario, a 35-bit number is added to a
4897 * 16-bit number (the input r), so the output r is 36-bit number.
4899 for (i = 0; i < ip->alu.src.n_bits / 32; i++, src32_ptr++)
4902 /* The first input is a 16-bit number. The second input is a 20-bit
4903 * number. Their sum is a 21-bit number.
4905 r = (r & 0xFFFF) + (r >> 16);
4907 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
4908 * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1000E).
4910 r = (r & 0xFFFF) + (r >> 16);
4912 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
4913 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
4914 * 0x1001E), the output r is (0 .. 31). So no carry bit can be
4915 * generated, therefore the output r is always a 16-bit number.
4917 r = (r & 0xFFFF) + (r >> 16);
4922 *dst16_ptr = (uint16_t)r;
4931 static struct regarray *
4932 regarray_find(struct rte_swx_pipeline *p, const char *name);
4935 instr_regprefetch_translate(struct rte_swx_pipeline *p,
4936 struct action *action,
4939 struct instruction *instr,
4940 struct instruction_data *data __rte_unused)
4942 char *regarray = tokens[1], *idx = tokens[2];
4945 uint32_t idx_struct_id, idx_val;
4947 CHECK(n_tokens == 3, EINVAL);
4949 r = regarray_find(p, regarray);
4952 /* REGPREFETCH_RH, REGPREFETCH_RM. */
4953 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
4955 instr->type = INSTR_REGPREFETCH_RM;
4957 instr->type = INSTR_REGPREFETCH_RH;
4959 instr->regarray.regarray_id = r->id;
4960 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
4961 instr->regarray.idx.n_bits = fidx->n_bits;
4962 instr->regarray.idx.offset = fidx->offset / 8;
4963 instr->regarray.dstsrc_val = 0; /* Unused. */
4967 /* REGPREFETCH_RI. */
4968 idx_val = strtoul(idx, &idx, 0);
4969 CHECK(!idx[0], EINVAL);
4971 instr->type = INSTR_REGPREFETCH_RI;
4972 instr->regarray.regarray_id = r->id;
4973 instr->regarray.idx_val = idx_val;
4974 instr->regarray.dstsrc_val = 0; /* Unused. */
4979 instr_regrd_translate(struct rte_swx_pipeline *p,
4980 struct action *action,
4983 struct instruction *instr,
4984 struct instruction_data *data __rte_unused)
4986 char *dst = tokens[1], *regarray = tokens[2], *idx = tokens[3];
4988 struct field *fdst, *fidx;
4989 uint32_t dst_struct_id, idx_struct_id, idx_val;
4991 CHECK(n_tokens == 4, EINVAL);
4993 r = regarray_find(p, regarray);
4996 fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
4997 CHECK(fdst, EINVAL);
4999 /* REGRD_HRH, REGRD_HRM, REGRD_MRH, REGRD_MRM. */
5000 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
5002 instr->type = INSTR_REGRD_MRM;
5003 if (dst[0] == 'h' && idx[0] != 'h')
5004 instr->type = INSTR_REGRD_HRM;
5005 if (dst[0] != 'h' && idx[0] == 'h')
5006 instr->type = INSTR_REGRD_MRH;
5007 if (dst[0] == 'h' && idx[0] == 'h')
5008 instr->type = INSTR_REGRD_HRH;
5010 instr->regarray.regarray_id = r->id;
5011 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
5012 instr->regarray.idx.n_bits = fidx->n_bits;
5013 instr->regarray.idx.offset = fidx->offset / 8;
5014 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
5015 instr->regarray.dstsrc.n_bits = fdst->n_bits;
5016 instr->regarray.dstsrc.offset = fdst->offset / 8;
5020 /* REGRD_MRI, REGRD_HRI. */
5021 idx_val = strtoul(idx, &idx, 0);
5022 CHECK(!idx[0], EINVAL);
5024 instr->type = INSTR_REGRD_MRI;
5026 instr->type = INSTR_REGRD_HRI;
5028 instr->regarray.regarray_id = r->id;
5029 instr->regarray.idx_val = idx_val;
5030 instr->regarray.dstsrc.struct_id = (uint8_t)dst_struct_id;
5031 instr->regarray.dstsrc.n_bits = fdst->n_bits;
5032 instr->regarray.dstsrc.offset = fdst->offset / 8;
5037 instr_regwr_translate(struct rte_swx_pipeline *p,
5038 struct action *action,
5041 struct instruction *instr,
5042 struct instruction_data *data __rte_unused)
5044 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
5046 struct field *fidx, *fsrc;
5048 uint32_t idx_struct_id, idx_val, src_struct_id;
5050 CHECK(n_tokens == 4, EINVAL);
5052 r = regarray_find(p, regarray);
5055 /* REGWR_RHH, REGWR_RHM, REGWR_RMH, REGWR_RMM. */
5056 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
5057 fsrc = struct_field_parse(p, action, src, &src_struct_id);
5059 instr->type = INSTR_REGWR_RMM;
5060 if (idx[0] == 'h' && src[0] != 'h')
5061 instr->type = INSTR_REGWR_RHM;
5062 if (idx[0] != 'h' && src[0] == 'h')
5063 instr->type = INSTR_REGWR_RMH;
5064 if (idx[0] == 'h' && src[0] == 'h')
5065 instr->type = INSTR_REGWR_RHH;
5067 instr->regarray.regarray_id = r->id;
5068 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
5069 instr->regarray.idx.n_bits = fidx->n_bits;
5070 instr->regarray.idx.offset = fidx->offset / 8;
5071 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
5072 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
5073 instr->regarray.dstsrc.offset = fsrc->offset / 8;
5077 /* REGWR_RHI, REGWR_RMI. */
5078 if (fidx && !fsrc) {
5079 src_val = strtoull(src, &src, 0);
5080 CHECK(!src[0], EINVAL);
5082 instr->type = INSTR_REGWR_RMI;
5084 instr->type = INSTR_REGWR_RHI;
5086 instr->regarray.regarray_id = r->id;
5087 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
5088 instr->regarray.idx.n_bits = fidx->n_bits;
5089 instr->regarray.idx.offset = fidx->offset / 8;
5090 instr->regarray.dstsrc_val = src_val;
5094 /* REGWR_RIH, REGWR_RIM. */
5095 if (!fidx && fsrc) {
5096 idx_val = strtoul(idx, &idx, 0);
5097 CHECK(!idx[0], EINVAL);
5099 instr->type = INSTR_REGWR_RIM;
5101 instr->type = INSTR_REGWR_RIH;
5103 instr->regarray.regarray_id = r->id;
5104 instr->regarray.idx_val = idx_val;
5105 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
5106 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
5107 instr->regarray.dstsrc.offset = fsrc->offset / 8;
5112 src_val = strtoull(src, &src, 0);
5113 CHECK(!src[0], EINVAL);
5115 idx_val = strtoul(idx, &idx, 0);
5116 CHECK(!idx[0], EINVAL);
5118 instr->type = INSTR_REGWR_RII;
5119 instr->regarray.idx_val = idx_val;
5120 instr->regarray.dstsrc_val = src_val;
5126 instr_regadd_translate(struct rte_swx_pipeline *p,
5127 struct action *action,
5130 struct instruction *instr,
5131 struct instruction_data *data __rte_unused)
5133 char *regarray = tokens[1], *idx = tokens[2], *src = tokens[3];
5135 struct field *fidx, *fsrc;
5137 uint32_t idx_struct_id, idx_val, src_struct_id;
5139 CHECK(n_tokens == 4, EINVAL);
5141 r = regarray_find(p, regarray);
5144 /* REGADD_RHH, REGADD_RHM, REGADD_RMH, REGADD_RMM. */
5145 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
5146 fsrc = struct_field_parse(p, action, src, &src_struct_id);
5148 instr->type = INSTR_REGADD_RMM;
5149 if (idx[0] == 'h' && src[0] != 'h')
5150 instr->type = INSTR_REGADD_RHM;
5151 if (idx[0] != 'h' && src[0] == 'h')
5152 instr->type = INSTR_REGADD_RMH;
5153 if (idx[0] == 'h' && src[0] == 'h')
5154 instr->type = INSTR_REGADD_RHH;
5156 instr->regarray.regarray_id = r->id;
5157 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
5158 instr->regarray.idx.n_bits = fidx->n_bits;
5159 instr->regarray.idx.offset = fidx->offset / 8;
5160 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
5161 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
5162 instr->regarray.dstsrc.offset = fsrc->offset / 8;
5166 /* REGADD_RHI, REGADD_RMI. */
5167 if (fidx && !fsrc) {
5168 src_val = strtoull(src, &src, 0);
5169 CHECK(!src[0], EINVAL);
5171 instr->type = INSTR_REGADD_RMI;
5173 instr->type = INSTR_REGADD_RHI;
5175 instr->regarray.regarray_id = r->id;
5176 instr->regarray.idx.struct_id = (uint8_t)idx_struct_id;
5177 instr->regarray.idx.n_bits = fidx->n_bits;
5178 instr->regarray.idx.offset = fidx->offset / 8;
5179 instr->regarray.dstsrc_val = src_val;
5183 /* REGADD_RIH, REGADD_RIM. */
5184 if (!fidx && fsrc) {
5185 idx_val = strtoul(idx, &idx, 0);
5186 CHECK(!idx[0], EINVAL);
5188 instr->type = INSTR_REGADD_RIM;
5190 instr->type = INSTR_REGADD_RIH;
5192 instr->regarray.regarray_id = r->id;
5193 instr->regarray.idx_val = idx_val;
5194 instr->regarray.dstsrc.struct_id = (uint8_t)src_struct_id;
5195 instr->regarray.dstsrc.n_bits = fsrc->n_bits;
5196 instr->regarray.dstsrc.offset = fsrc->offset / 8;
5201 src_val = strtoull(src, &src, 0);
5202 CHECK(!src[0], EINVAL);
5204 idx_val = strtoul(idx, &idx, 0);
5205 CHECK(!idx[0], EINVAL);
5207 instr->type = INSTR_REGADD_RII;
5208 instr->regarray.idx_val = idx_val;
5209 instr->regarray.dstsrc_val = src_val;
5213 static inline uint64_t *
5214 instr_regarray_regarray(struct rte_swx_pipeline *p, struct instruction *ip)
5216 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
5220 static inline uint64_t
5221 instr_regarray_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
5223 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
5225 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
5226 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
5227 uint64_t idx64 = *idx64_ptr;
5228 uint64_t idx64_mask = UINT64_MAX >> (64 - ip->regarray.idx.n_bits);
5229 uint64_t idx = idx64 & idx64_mask & r->size_mask;
5234 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5236 static inline uint64_t
5237 instr_regarray_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
5239 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
5241 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
5242 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
5243 uint64_t idx64 = *idx64_ptr;
5244 uint64_t idx = (ntoh64(idx64) >> (64 - ip->regarray.idx.n_bits)) & r->size_mask;
5251 #define instr_regarray_idx_nbo instr_regarray_idx_hbo
5255 static inline uint64_t
5256 instr_regarray_idx_imm(struct rte_swx_pipeline *p, struct instruction *ip)
5258 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
5260 uint64_t idx = ip->regarray.idx_val & r->size_mask;
5265 static inline uint64_t
5266 instr_regarray_src_hbo(struct thread *t, struct instruction *ip)
5268 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
5269 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
5270 uint64_t src64 = *src64_ptr;
5271 uint64_t src64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
5272 uint64_t src = src64 & src64_mask;
5277 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5279 static inline uint64_t
5280 instr_regarray_src_nbo(struct thread *t, struct instruction *ip)
5282 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
5283 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
5284 uint64_t src64 = *src64_ptr;
5285 uint64_t src = ntoh64(src64) >> (64 - ip->regarray.dstsrc.n_bits);
5292 #define instr_regarray_src_nbo instr_regarray_src_hbo
5297 instr_regarray_dst_hbo_src_hbo_set(struct thread *t, struct instruction *ip, uint64_t src)
5299 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
5300 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
5301 uint64_t dst64 = *dst64_ptr;
5302 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
5304 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
5308 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5311 instr_regarray_dst_nbo_src_hbo_set(struct thread *t, struct instruction *ip, uint64_t src)
5313 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
5314 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
5315 uint64_t dst64 = *dst64_ptr;
5316 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
5318 src = hton64(src) >> (64 - ip->regarray.dstsrc.n_bits);
5319 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
5324 #define instr_regarray_dst_nbo_src_hbo_set instr_regarray_dst_hbo_src_hbo_set
5329 instr_regprefetch_rh_exec(struct rte_swx_pipeline *p)
5331 struct thread *t = &p->threads[p->thread_id];
5332 struct instruction *ip = t->ip;
5333 uint64_t *regarray, idx;
5335 TRACE("[Thread %2u] regprefetch (r[h])\n", p->thread_id);
5338 regarray = instr_regarray_regarray(p, ip);
5339 idx = instr_regarray_idx_nbo(p, t, ip);
5340 rte_prefetch0(®array[idx]);
5347 instr_regprefetch_rm_exec(struct rte_swx_pipeline *p)
5349 struct thread *t = &p->threads[p->thread_id];
5350 struct instruction *ip = t->ip;
5351 uint64_t *regarray, idx;
5353 TRACE("[Thread %2u] regprefetch (r[m])\n", p->thread_id);
5356 regarray = instr_regarray_regarray(p, ip);
5357 idx = instr_regarray_idx_hbo(p, t, ip);
5358 rte_prefetch0(®array[idx]);
5365 instr_regprefetch_ri_exec(struct rte_swx_pipeline *p)
5367 struct thread *t = &p->threads[p->thread_id];
5368 struct instruction *ip = t->ip;
5369 uint64_t *regarray, idx;
5371 TRACE("[Thread %2u] regprefetch (r[i])\n", p->thread_id);
5374 regarray = instr_regarray_regarray(p, ip);
5375 idx = instr_regarray_idx_imm(p, ip);
5376 rte_prefetch0(®array[idx]);
5383 instr_regrd_hrh_exec(struct rte_swx_pipeline *p)
5385 struct thread *t = &p->threads[p->thread_id];
5386 struct instruction *ip = t->ip;
5387 uint64_t *regarray, idx;
5389 TRACE("[Thread %2u] regrd (h = r[h])\n", p->thread_id);
5392 regarray = instr_regarray_regarray(p, ip);
5393 idx = instr_regarray_idx_nbo(p, t, ip);
5394 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
5401 instr_regrd_hrm_exec(struct rte_swx_pipeline *p)
5403 struct thread *t = &p->threads[p->thread_id];
5404 struct instruction *ip = t->ip;
5405 uint64_t *regarray, idx;
5407 TRACE("[Thread %2u] regrd (h = r[m])\n", p->thread_id);
5410 regarray = instr_regarray_regarray(p, ip);
5411 idx = instr_regarray_idx_hbo(p, t, ip);
5412 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
5419 instr_regrd_mrh_exec(struct rte_swx_pipeline *p)
5421 struct thread *t = &p->threads[p->thread_id];
5422 struct instruction *ip = t->ip;
5423 uint64_t *regarray, idx;
5425 TRACE("[Thread %2u] regrd (m = r[h])\n", p->thread_id);
5428 regarray = instr_regarray_regarray(p, ip);
5429 idx = instr_regarray_idx_nbo(p, t, ip);
5430 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
5437 instr_regrd_mrm_exec(struct rte_swx_pipeline *p)
5439 struct thread *t = &p->threads[p->thread_id];
5440 struct instruction *ip = t->ip;
5441 uint64_t *regarray, idx;
5444 regarray = instr_regarray_regarray(p, ip);
5445 idx = instr_regarray_idx_hbo(p, t, ip);
5446 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
5453 instr_regrd_hri_exec(struct rte_swx_pipeline *p)
5455 struct thread *t = &p->threads[p->thread_id];
5456 struct instruction *ip = t->ip;
5457 uint64_t *regarray, idx;
5459 TRACE("[Thread %2u] regrd (h = r[i])\n", p->thread_id);
5462 regarray = instr_regarray_regarray(p, ip);
5463 idx = instr_regarray_idx_imm(p, ip);
5464 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
5471 instr_regrd_mri_exec(struct rte_swx_pipeline *p)
5473 struct thread *t = &p->threads[p->thread_id];
5474 struct instruction *ip = t->ip;
5475 uint64_t *regarray, idx;
5477 TRACE("[Thread %2u] regrd (m = r[i])\n", p->thread_id);
5480 regarray = instr_regarray_regarray(p, ip);
5481 idx = instr_regarray_idx_imm(p, ip);
5482 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
5489 instr_regwr_rhh_exec(struct rte_swx_pipeline *p)
5491 struct thread *t = &p->threads[p->thread_id];
5492 struct instruction *ip = t->ip;
5493 uint64_t *regarray, idx, src;
5495 TRACE("[Thread %2u] regwr (r[h] = h)\n", p->thread_id);
5498 regarray = instr_regarray_regarray(p, ip);
5499 idx = instr_regarray_idx_nbo(p, t, ip);
5500 src = instr_regarray_src_nbo(t, ip);
5501 regarray[idx] = src;
5508 instr_regwr_rhm_exec(struct rte_swx_pipeline *p)
5510 struct thread *t = &p->threads[p->thread_id];
5511 struct instruction *ip = t->ip;
5512 uint64_t *regarray, idx, src;
5514 TRACE("[Thread %2u] regwr (r[h] = m)\n", p->thread_id);
5517 regarray = instr_regarray_regarray(p, ip);
5518 idx = instr_regarray_idx_nbo(p, t, ip);
5519 src = instr_regarray_src_hbo(t, ip);
5520 regarray[idx] = src;
5527 instr_regwr_rmh_exec(struct rte_swx_pipeline *p)
5529 struct thread *t = &p->threads[p->thread_id];
5530 struct instruction *ip = t->ip;
5531 uint64_t *regarray, idx, src;
5533 TRACE("[Thread %2u] regwr (r[m] = h)\n", p->thread_id);
5536 regarray = instr_regarray_regarray(p, ip);
5537 idx = instr_regarray_idx_hbo(p, t, ip);
5538 src = instr_regarray_src_nbo(t, ip);
5539 regarray[idx] = src;
5546 instr_regwr_rmm_exec(struct rte_swx_pipeline *p)
5548 struct thread *t = &p->threads[p->thread_id];
5549 struct instruction *ip = t->ip;
5550 uint64_t *regarray, idx, src;
5552 TRACE("[Thread %2u] regwr (r[m] = m)\n", p->thread_id);
5555 regarray = instr_regarray_regarray(p, ip);
5556 idx = instr_regarray_idx_hbo(p, t, ip);
5557 src = instr_regarray_src_hbo(t, ip);
5558 regarray[idx] = src;
5565 instr_regwr_rhi_exec(struct rte_swx_pipeline *p)
5567 struct thread *t = &p->threads[p->thread_id];
5568 struct instruction *ip = t->ip;
5569 uint64_t *regarray, idx, src;
5571 TRACE("[Thread %2u] regwr (r[h] = i)\n", p->thread_id);
5574 regarray = instr_regarray_regarray(p, ip);
5575 idx = instr_regarray_idx_nbo(p, t, ip);
5576 src = ip->regarray.dstsrc_val;
5577 regarray[idx] = src;
5584 instr_regwr_rmi_exec(struct rte_swx_pipeline *p)
5586 struct thread *t = &p->threads[p->thread_id];
5587 struct instruction *ip = t->ip;
5588 uint64_t *regarray, idx, src;
5590 TRACE("[Thread %2u] regwr (r[m] = i)\n", p->thread_id);
5593 regarray = instr_regarray_regarray(p, ip);
5594 idx = instr_regarray_idx_hbo(p, t, ip);
5595 src = ip->regarray.dstsrc_val;
5596 regarray[idx] = src;
5603 instr_regwr_rih_exec(struct rte_swx_pipeline *p)
5605 struct thread *t = &p->threads[p->thread_id];
5606 struct instruction *ip = t->ip;
5607 uint64_t *regarray, idx, src;
5609 TRACE("[Thread %2u] regwr (r[i] = h)\n", p->thread_id);
5612 regarray = instr_regarray_regarray(p, ip);
5613 idx = instr_regarray_idx_imm(p, ip);
5614 src = instr_regarray_src_nbo(t, ip);
5615 regarray[idx] = src;
5622 instr_regwr_rim_exec(struct rte_swx_pipeline *p)
5624 struct thread *t = &p->threads[p->thread_id];
5625 struct instruction *ip = t->ip;
5626 uint64_t *regarray, idx, src;
5628 TRACE("[Thread %2u] regwr (r[i] = m)\n", p->thread_id);
5631 regarray = instr_regarray_regarray(p, ip);
5632 idx = instr_regarray_idx_imm(p, ip);
5633 src = instr_regarray_src_hbo(t, ip);
5634 regarray[idx] = src;
5641 instr_regwr_rii_exec(struct rte_swx_pipeline *p)
5643 struct thread *t = &p->threads[p->thread_id];
5644 struct instruction *ip = t->ip;
5645 uint64_t *regarray, idx, src;
5647 TRACE("[Thread %2u] regwr (r[i] = i)\n", p->thread_id);
5650 regarray = instr_regarray_regarray(p, ip);
5651 idx = instr_regarray_idx_imm(p, ip);
5652 src = ip->regarray.dstsrc_val;
5653 regarray[idx] = src;
5660 instr_regadd_rhh_exec(struct rte_swx_pipeline *p)
5662 struct thread *t = &p->threads[p->thread_id];
5663 struct instruction *ip = t->ip;
5664 uint64_t *regarray, idx, src;
5666 TRACE("[Thread %2u] regadd (r[h] += h)\n", p->thread_id);
5669 regarray = instr_regarray_regarray(p, ip);
5670 idx = instr_regarray_idx_nbo(p, t, ip);
5671 src = instr_regarray_src_nbo(t, ip);
5672 regarray[idx] += src;
5679 instr_regadd_rhm_exec(struct rte_swx_pipeline *p)
5681 struct thread *t = &p->threads[p->thread_id];
5682 struct instruction *ip = t->ip;
5683 uint64_t *regarray, idx, src;
5685 TRACE("[Thread %2u] regadd (r[h] += m)\n", p->thread_id);
5688 regarray = instr_regarray_regarray(p, ip);
5689 idx = instr_regarray_idx_nbo(p, t, ip);
5690 src = instr_regarray_src_hbo(t, ip);
5691 regarray[idx] += src;
5698 instr_regadd_rmh_exec(struct rte_swx_pipeline *p)
5700 struct thread *t = &p->threads[p->thread_id];
5701 struct instruction *ip = t->ip;
5702 uint64_t *regarray, idx, src;
5704 TRACE("[Thread %2u] regadd (r[m] += h)\n", p->thread_id);
5707 regarray = instr_regarray_regarray(p, ip);
5708 idx = instr_regarray_idx_hbo(p, t, ip);
5709 src = instr_regarray_src_nbo(t, ip);
5710 regarray[idx] += src;
5717 instr_regadd_rmm_exec(struct rte_swx_pipeline *p)
5719 struct thread *t = &p->threads[p->thread_id];
5720 struct instruction *ip = t->ip;
5721 uint64_t *regarray, idx, src;
5723 TRACE("[Thread %2u] regadd (r[m] += m)\n", p->thread_id);
5726 regarray = instr_regarray_regarray(p, ip);
5727 idx = instr_regarray_idx_hbo(p, t, ip);
5728 src = instr_regarray_src_hbo(t, ip);
5729 regarray[idx] += src;
5736 instr_regadd_rhi_exec(struct rte_swx_pipeline *p)
5738 struct thread *t = &p->threads[p->thread_id];
5739 struct instruction *ip = t->ip;
5740 uint64_t *regarray, idx, src;
5742 TRACE("[Thread %2u] regadd (r[h] += i)\n", p->thread_id);
5745 regarray = instr_regarray_regarray(p, ip);
5746 idx = instr_regarray_idx_nbo(p, t, ip);
5747 src = ip->regarray.dstsrc_val;
5748 regarray[idx] += src;
5755 instr_regadd_rmi_exec(struct rte_swx_pipeline *p)
5757 struct thread *t = &p->threads[p->thread_id];
5758 struct instruction *ip = t->ip;
5759 uint64_t *regarray, idx, src;
5761 TRACE("[Thread %2u] regadd (r[m] += i)\n", p->thread_id);
5764 regarray = instr_regarray_regarray(p, ip);
5765 idx = instr_regarray_idx_hbo(p, t, ip);
5766 src = ip->regarray.dstsrc_val;
5767 regarray[idx] += src;
5774 instr_regadd_rih_exec(struct rte_swx_pipeline *p)
5776 struct thread *t = &p->threads[p->thread_id];
5777 struct instruction *ip = t->ip;
5778 uint64_t *regarray, idx, src;
5780 TRACE("[Thread %2u] regadd (r[i] += h)\n", p->thread_id);
5783 regarray = instr_regarray_regarray(p, ip);
5784 idx = instr_regarray_idx_imm(p, ip);
5785 src = instr_regarray_src_nbo(t, ip);
5786 regarray[idx] += src;
5793 instr_regadd_rim_exec(struct rte_swx_pipeline *p)
5795 struct thread *t = &p->threads[p->thread_id];
5796 struct instruction *ip = t->ip;
5797 uint64_t *regarray, idx, src;
5799 TRACE("[Thread %2u] regadd (r[i] += m)\n", p->thread_id);
5802 regarray = instr_regarray_regarray(p, ip);
5803 idx = instr_regarray_idx_imm(p, ip);
5804 src = instr_regarray_src_hbo(t, ip);
5805 regarray[idx] += src;
5812 instr_regadd_rii_exec(struct rte_swx_pipeline *p)
5814 struct thread *t = &p->threads[p->thread_id];
5815 struct instruction *ip = t->ip;
5816 uint64_t *regarray, idx, src;
5818 TRACE("[Thread %2u] regadd (r[i] += i)\n", p->thread_id);
5821 regarray = instr_regarray_regarray(p, ip);
5822 idx = instr_regarray_idx_imm(p, ip);
5823 src = ip->regarray.dstsrc_val;
5824 regarray[idx] += src;
5833 static struct metarray *
5834 metarray_find(struct rte_swx_pipeline *p, const char *name);
5837 instr_metprefetch_translate(struct rte_swx_pipeline *p,
5838 struct action *action,
5841 struct instruction *instr,
5842 struct instruction_data *data __rte_unused)
5844 char *metarray = tokens[1], *idx = tokens[2];
5847 uint32_t idx_struct_id, idx_val;
5849 CHECK(n_tokens == 3, EINVAL);
5851 m = metarray_find(p, metarray);
5854 /* METPREFETCH_H, METPREFETCH_M. */
5855 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
5857 instr->type = INSTR_METPREFETCH_M;
5859 instr->type = INSTR_METPREFETCH_H;
5861 instr->meter.metarray_id = m->id;
5862 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
5863 instr->meter.idx.n_bits = fidx->n_bits;
5864 instr->meter.idx.offset = fidx->offset / 8;
5868 /* METPREFETCH_I. */
5869 idx_val = strtoul(idx, &idx, 0);
5870 CHECK(!idx[0], EINVAL);
5872 instr->type = INSTR_METPREFETCH_I;
5873 instr->meter.metarray_id = m->id;
5874 instr->meter.idx_val = idx_val;
5879 instr_meter_translate(struct rte_swx_pipeline *p,
5880 struct action *action,
5883 struct instruction *instr,
5884 struct instruction_data *data __rte_unused)
5886 char *metarray = tokens[1], *idx = tokens[2], *length = tokens[3];
5887 char *color_in = tokens[4], *color_out = tokens[5];
5889 struct field *fidx, *flength, *fcin, *fcout;
5890 uint32_t idx_struct_id, length_struct_id;
5891 uint32_t color_in_struct_id, color_out_struct_id;
5893 CHECK(n_tokens == 6, EINVAL);
5895 m = metarray_find(p, metarray);
5898 fidx = struct_field_parse(p, action, idx, &idx_struct_id);
5900 flength = struct_field_parse(p, action, length, &length_struct_id);
5901 CHECK(flength, EINVAL);
5903 fcin = struct_field_parse(p, action, color_in, &color_in_struct_id);
5905 fcout = struct_field_parse(p, NULL, color_out, &color_out_struct_id);
5906 CHECK(fcout, EINVAL);
5908 /* index = HMEFT, length = HMEFT, color_in = MEFT, color_out = MEF. */
5910 instr->type = INSTR_METER_MMM;
5911 if (idx[0] == 'h' && length[0] == 'h')
5912 instr->type = INSTR_METER_HHM;
5913 if (idx[0] == 'h' && length[0] != 'h')
5914 instr->type = INSTR_METER_HMM;
5915 if (idx[0] != 'h' && length[0] == 'h')
5916 instr->type = INSTR_METER_MHM;
5918 instr->meter.metarray_id = m->id;
5920 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
5921 instr->meter.idx.n_bits = fidx->n_bits;
5922 instr->meter.idx.offset = fidx->offset / 8;
5924 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5925 instr->meter.length.n_bits = flength->n_bits;
5926 instr->meter.length.offset = flength->offset / 8;
5928 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
5929 instr->meter.color_in.n_bits = fcin->n_bits;
5930 instr->meter.color_in.offset = fcin->offset / 8;
5932 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5933 instr->meter.color_out.n_bits = fcout->n_bits;
5934 instr->meter.color_out.offset = fcout->offset / 8;
5939 /* index = HMEFT, length = HMEFT, color_in = I, color_out = MEF. */
5940 if (fidx && !fcin) {
5941 uint32_t color_in_val = strtoul(color_in, &color_in, 0);
5942 CHECK(!color_in[0], EINVAL);
5944 instr->type = INSTR_METER_MMI;
5945 if (idx[0] == 'h' && length[0] == 'h')
5946 instr->type = INSTR_METER_HHI;
5947 if (idx[0] == 'h' && length[0] != 'h')
5948 instr->type = INSTR_METER_HMI;
5949 if (idx[0] != 'h' && length[0] == 'h')
5950 instr->type = INSTR_METER_MHI;
5952 instr->meter.metarray_id = m->id;
5954 instr->meter.idx.struct_id = (uint8_t)idx_struct_id;
5955 instr->meter.idx.n_bits = fidx->n_bits;
5956 instr->meter.idx.offset = fidx->offset / 8;
5958 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5959 instr->meter.length.n_bits = flength->n_bits;
5960 instr->meter.length.offset = flength->offset / 8;
5962 instr->meter.color_in_val = color_in_val;
5964 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5965 instr->meter.color_out.n_bits = fcout->n_bits;
5966 instr->meter.color_out.offset = fcout->offset / 8;
5971 /* index = I, length = HMEFT, color_in = MEFT, color_out = MEF. */
5972 if (!fidx && fcin) {
5975 idx_val = strtoul(idx, &idx, 0);
5976 CHECK(!idx[0], EINVAL);
5978 instr->type = INSTR_METER_IMM;
5979 if (length[0] == 'h')
5980 instr->type = INSTR_METER_IHM;
5982 instr->meter.metarray_id = m->id;
5984 instr->meter.idx_val = idx_val;
5986 instr->meter.length.struct_id = (uint8_t)length_struct_id;
5987 instr->meter.length.n_bits = flength->n_bits;
5988 instr->meter.length.offset = flength->offset / 8;
5990 instr->meter.color_in.struct_id = (uint8_t)color_in_struct_id;
5991 instr->meter.color_in.n_bits = fcin->n_bits;
5992 instr->meter.color_in.offset = fcin->offset / 8;
5994 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
5995 instr->meter.color_out.n_bits = fcout->n_bits;
5996 instr->meter.color_out.offset = fcout->offset / 8;
6001 /* index = I, length = HMEFT, color_in = I, color_out = MEF. */
6002 if (!fidx && !fcin) {
6003 uint32_t idx_val, color_in_val;
6005 idx_val = strtoul(idx, &idx, 0);
6006 CHECK(!idx[0], EINVAL);
6008 color_in_val = strtoul(color_in, &color_in, 0);
6009 CHECK(!color_in[0], EINVAL);
6011 instr->type = INSTR_METER_IMI;
6012 if (length[0] == 'h')
6013 instr->type = INSTR_METER_IHI;
6015 instr->meter.metarray_id = m->id;
6017 instr->meter.idx_val = idx_val;
6019 instr->meter.length.struct_id = (uint8_t)length_struct_id;
6020 instr->meter.length.n_bits = flength->n_bits;
6021 instr->meter.length.offset = flength->offset / 8;
6023 instr->meter.color_in_val = color_in_val;
6025 instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id;
6026 instr->meter.color_out.n_bits = fcout->n_bits;
6027 instr->meter.color_out.offset = fcout->offset / 8;
6035 static inline struct meter *
6036 instr_meter_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
6038 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
6040 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
6041 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
6042 uint64_t idx64 = *idx64_ptr;
6043 uint64_t idx64_mask = UINT64_MAX >> (64 - (ip)->meter.idx.n_bits);
6044 uint64_t idx = idx64 & idx64_mask & r->size_mask;
6046 return &r->metarray[idx];
6049 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
6051 static inline struct meter *
6052 instr_meter_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, struct instruction *ip)
6054 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
6056 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
6057 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
6058 uint64_t idx64 = *idx64_ptr;
6059 uint64_t idx = (ntoh64(idx64) >> (64 - ip->meter.idx.n_bits)) & r->size_mask;
6061 return &r->metarray[idx];
6066 #define instr_meter_idx_nbo instr_meter_idx_hbo
6070 static inline struct meter *
6071 instr_meter_idx_imm(struct rte_swx_pipeline *p, struct instruction *ip)
6073 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
6075 uint64_t idx = ip->meter.idx_val & r->size_mask;
6077 return &r->metarray[idx];
6080 static inline uint32_t
6081 instr_meter_length_hbo(struct thread *t, struct instruction *ip)
6083 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
6084 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
6085 uint64_t src64 = *src64_ptr;
6086 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->meter.length.n_bits);
6087 uint64_t src = src64 & src64_mask;
6089 return (uint32_t)src;
6092 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
6094 static inline uint32_t
6095 instr_meter_length_nbo(struct thread *t, struct instruction *ip)
6097 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
6098 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
6099 uint64_t src64 = *src64_ptr;
6100 uint64_t src = ntoh64(src64) >> (64 - ip->meter.length.n_bits);
6102 return (uint32_t)src;
6107 #define instr_meter_length_nbo instr_meter_length_hbo
6111 static inline enum rte_color
6112 instr_meter_color_in_hbo(struct thread *t, struct instruction *ip)
6114 uint8_t *src_struct = t->structs[ip->meter.color_in.struct_id];
6115 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.color_in.offset];
6116 uint64_t src64 = *src64_ptr;
6117 uint64_t src64_mask = UINT64_MAX >> (64 - ip->meter.color_in.n_bits);
6118 uint64_t src = src64 & src64_mask;
6120 return (enum rte_color)src;
6124 instr_meter_color_out_hbo_set(struct thread *t, struct instruction *ip, enum rte_color color_out)
6126 uint8_t *dst_struct = t->structs[ip->meter.color_out.struct_id];
6127 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->meter.color_out.offset];
6128 uint64_t dst64 = *dst64_ptr;
6129 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->meter.color_out.n_bits);
6131 uint64_t src = (uint64_t)color_out;
6133 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
6137 instr_metprefetch_h_exec(struct rte_swx_pipeline *p)
6139 struct thread *t = &p->threads[p->thread_id];
6140 struct instruction *ip = t->ip;
6143 TRACE("[Thread %2u] metprefetch (h)\n", p->thread_id);
6146 m = instr_meter_idx_nbo(p, t, ip);
6154 instr_metprefetch_m_exec(struct rte_swx_pipeline *p)
6156 struct thread *t = &p->threads[p->thread_id];
6157 struct instruction *ip = t->ip;
6160 TRACE("[Thread %2u] metprefetch (m)\n", p->thread_id);
6163 m = instr_meter_idx_hbo(p, t, ip);
6171 instr_metprefetch_i_exec(struct rte_swx_pipeline *p)
6173 struct thread *t = &p->threads[p->thread_id];
6174 struct instruction *ip = t->ip;
6177 TRACE("[Thread %2u] metprefetch (i)\n", p->thread_id);
6180 m = instr_meter_idx_imm(p, ip);
6188 instr_meter_hhm_exec(struct rte_swx_pipeline *p)
6190 struct thread *t = &p->threads[p->thread_id];
6191 struct instruction *ip = t->ip;
6193 uint64_t time, n_pkts, n_bytes;
6195 enum rte_color color_in, color_out;
6197 TRACE("[Thread %2u] meter (hhm)\n", p->thread_id);
6200 m = instr_meter_idx_nbo(p, t, ip);
6201 rte_prefetch0(m->n_pkts);
6202 time = rte_get_tsc_cycles();
6203 length = instr_meter_length_nbo(t, ip);
6204 color_in = instr_meter_color_in_hbo(t, ip);
6206 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6207 &m->profile->profile,
6212 color_out &= m->color_mask;
6214 n_pkts = m->n_pkts[color_out];
6215 n_bytes = m->n_bytes[color_out];
6217 instr_meter_color_out_hbo_set(t, ip, color_out);
6219 m->n_pkts[color_out] = n_pkts + 1;
6220 m->n_bytes[color_out] = n_bytes + length;
6227 instr_meter_hhi_exec(struct rte_swx_pipeline *p)
6229 struct thread *t = &p->threads[p->thread_id];
6230 struct instruction *ip = t->ip;
6232 uint64_t time, n_pkts, n_bytes;
6234 enum rte_color color_in, color_out;
6236 TRACE("[Thread %2u] meter (hhi)\n", p->thread_id);
6239 m = instr_meter_idx_nbo(p, t, ip);
6240 rte_prefetch0(m->n_pkts);
6241 time = rte_get_tsc_cycles();
6242 length = instr_meter_length_nbo(t, ip);
6243 color_in = (enum rte_color)ip->meter.color_in_val;
6245 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6246 &m->profile->profile,
6251 color_out &= m->color_mask;
6253 n_pkts = m->n_pkts[color_out];
6254 n_bytes = m->n_bytes[color_out];
6256 instr_meter_color_out_hbo_set(t, ip, color_out);
6258 m->n_pkts[color_out] = n_pkts + 1;
6259 m->n_bytes[color_out] = n_bytes + length;
6266 instr_meter_hmm_exec(struct rte_swx_pipeline *p)
6268 struct thread *t = &p->threads[p->thread_id];
6269 struct instruction *ip = t->ip;
6271 uint64_t time, n_pkts, n_bytes;
6273 enum rte_color color_in, color_out;
6275 TRACE("[Thread %2u] meter (hmm)\n", p->thread_id);
6278 m = instr_meter_idx_nbo(p, t, ip);
6279 rte_prefetch0(m->n_pkts);
6280 time = rte_get_tsc_cycles();
6281 length = instr_meter_length_hbo(t, ip);
6282 color_in = instr_meter_color_in_hbo(t, ip);
6284 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6285 &m->profile->profile,
6290 color_out &= m->color_mask;
6292 n_pkts = m->n_pkts[color_out];
6293 n_bytes = m->n_bytes[color_out];
6295 instr_meter_color_out_hbo_set(t, ip, color_out);
6297 m->n_pkts[color_out] = n_pkts + 1;
6298 m->n_bytes[color_out] = n_bytes + length;
6304 instr_meter_hmi_exec(struct rte_swx_pipeline *p)
6306 struct thread *t = &p->threads[p->thread_id];
6307 struct instruction *ip = t->ip;
6309 uint64_t time, n_pkts, n_bytes;
6311 enum rte_color color_in, color_out;
6313 TRACE("[Thread %2u] meter (hmi)\n", p->thread_id);
6316 m = instr_meter_idx_nbo(p, t, ip);
6317 rte_prefetch0(m->n_pkts);
6318 time = rte_get_tsc_cycles();
6319 length = instr_meter_length_hbo(t, ip);
6320 color_in = (enum rte_color)ip->meter.color_in_val;
6322 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6323 &m->profile->profile,
6328 color_out &= m->color_mask;
6330 n_pkts = m->n_pkts[color_out];
6331 n_bytes = m->n_bytes[color_out];
6333 instr_meter_color_out_hbo_set(t, ip, color_out);
6335 m->n_pkts[color_out] = n_pkts + 1;
6336 m->n_bytes[color_out] = n_bytes + length;
6343 instr_meter_mhm_exec(struct rte_swx_pipeline *p)
6345 struct thread *t = &p->threads[p->thread_id];
6346 struct instruction *ip = t->ip;
6348 uint64_t time, n_pkts, n_bytes;
6350 enum rte_color color_in, color_out;
6352 TRACE("[Thread %2u] meter (mhm)\n", p->thread_id);
6355 m = instr_meter_idx_hbo(p, t, ip);
6356 rte_prefetch0(m->n_pkts);
6357 time = rte_get_tsc_cycles();
6358 length = instr_meter_length_nbo(t, ip);
6359 color_in = instr_meter_color_in_hbo(t, ip);
6361 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6362 &m->profile->profile,
6367 color_out &= m->color_mask;
6369 n_pkts = m->n_pkts[color_out];
6370 n_bytes = m->n_bytes[color_out];
6372 instr_meter_color_out_hbo_set(t, ip, color_out);
6374 m->n_pkts[color_out] = n_pkts + 1;
6375 m->n_bytes[color_out] = n_bytes + length;
6382 instr_meter_mhi_exec(struct rte_swx_pipeline *p)
6384 struct thread *t = &p->threads[p->thread_id];
6385 struct instruction *ip = t->ip;
6387 uint64_t time, n_pkts, n_bytes;
6389 enum rte_color color_in, color_out;
6391 TRACE("[Thread %2u] meter (mhi)\n", p->thread_id);
6394 m = instr_meter_idx_hbo(p, t, ip);
6395 rte_prefetch0(m->n_pkts);
6396 time = rte_get_tsc_cycles();
6397 length = instr_meter_length_nbo(t, ip);
6398 color_in = (enum rte_color)ip->meter.color_in_val;
6400 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6401 &m->profile->profile,
6406 color_out &= m->color_mask;
6408 n_pkts = m->n_pkts[color_out];
6409 n_bytes = m->n_bytes[color_out];
6411 instr_meter_color_out_hbo_set(t, ip, color_out);
6413 m->n_pkts[color_out] = n_pkts + 1;
6414 m->n_bytes[color_out] = n_bytes + length;
6421 instr_meter_mmm_exec(struct rte_swx_pipeline *p)
6423 struct thread *t = &p->threads[p->thread_id];
6424 struct instruction *ip = t->ip;
6426 uint64_t time, n_pkts, n_bytes;
6428 enum rte_color color_in, color_out;
6430 TRACE("[Thread %2u] meter (mmm)\n", p->thread_id);
6433 m = instr_meter_idx_hbo(p, t, ip);
6434 rte_prefetch0(m->n_pkts);
6435 time = rte_get_tsc_cycles();
6436 length = instr_meter_length_hbo(t, ip);
6437 color_in = instr_meter_color_in_hbo(t, ip);
6439 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6440 &m->profile->profile,
6445 color_out &= m->color_mask;
6447 n_pkts = m->n_pkts[color_out];
6448 n_bytes = m->n_bytes[color_out];
6450 instr_meter_color_out_hbo_set(t, ip, color_out);
6452 m->n_pkts[color_out] = n_pkts + 1;
6453 m->n_bytes[color_out] = n_bytes + length;
6460 instr_meter_mmi_exec(struct rte_swx_pipeline *p)
6462 struct thread *t = &p->threads[p->thread_id];
6463 struct instruction *ip = t->ip;
6465 uint64_t time, n_pkts, n_bytes;
6467 enum rte_color color_in, color_out;
6469 TRACE("[Thread %2u] meter (mmi)\n", p->thread_id);
6472 m = instr_meter_idx_hbo(p, t, ip);
6473 rte_prefetch0(m->n_pkts);
6474 time = rte_get_tsc_cycles();
6475 length = instr_meter_length_hbo(t, ip);
6476 color_in = (enum rte_color)ip->meter.color_in_val;
6478 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6479 &m->profile->profile,
6484 color_out &= m->color_mask;
6486 n_pkts = m->n_pkts[color_out];
6487 n_bytes = m->n_bytes[color_out];
6489 instr_meter_color_out_hbo_set(t, ip, color_out);
6491 m->n_pkts[color_out] = n_pkts + 1;
6492 m->n_bytes[color_out] = n_bytes + length;
6499 instr_meter_ihm_exec(struct rte_swx_pipeline *p)
6501 struct thread *t = &p->threads[p->thread_id];
6502 struct instruction *ip = t->ip;
6504 uint64_t time, n_pkts, n_bytes;
6506 enum rte_color color_in, color_out;
6508 TRACE("[Thread %2u] meter (ihm)\n", p->thread_id);
6511 m = instr_meter_idx_imm(p, ip);
6512 rte_prefetch0(m->n_pkts);
6513 time = rte_get_tsc_cycles();
6514 length = instr_meter_length_nbo(t, ip);
6515 color_in = instr_meter_color_in_hbo(t, ip);
6517 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6518 &m->profile->profile,
6523 color_out &= m->color_mask;
6525 n_pkts = m->n_pkts[color_out];
6526 n_bytes = m->n_bytes[color_out];
6528 instr_meter_color_out_hbo_set(t, ip, color_out);
6530 m->n_pkts[color_out] = n_pkts + 1;
6531 m->n_bytes[color_out] = n_bytes + length;
6538 instr_meter_ihi_exec(struct rte_swx_pipeline *p)
6540 struct thread *t = &p->threads[p->thread_id];
6541 struct instruction *ip = t->ip;
6543 uint64_t time, n_pkts, n_bytes;
6545 enum rte_color color_in, color_out;
6547 TRACE("[Thread %2u] meter (ihi)\n", p->thread_id);
6550 m = instr_meter_idx_imm(p, ip);
6551 rte_prefetch0(m->n_pkts);
6552 time = rte_get_tsc_cycles();
6553 length = instr_meter_length_nbo(t, ip);
6554 color_in = (enum rte_color)ip->meter.color_in_val;
6556 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6557 &m->profile->profile,
6562 color_out &= m->color_mask;
6564 n_pkts = m->n_pkts[color_out];
6565 n_bytes = m->n_bytes[color_out];
6567 instr_meter_color_out_hbo_set(t, ip, color_out);
6569 m->n_pkts[color_out] = n_pkts + 1;
6570 m->n_bytes[color_out] = n_bytes + length;
6577 instr_meter_imm_exec(struct rte_swx_pipeline *p)
6579 struct thread *t = &p->threads[p->thread_id];
6580 struct instruction *ip = t->ip;
6582 uint64_t time, n_pkts, n_bytes;
6584 enum rte_color color_in, color_out;
6586 TRACE("[Thread %2u] meter (imm)\n", p->thread_id);
6589 m = instr_meter_idx_imm(p, ip);
6590 rte_prefetch0(m->n_pkts);
6591 time = rte_get_tsc_cycles();
6592 length = instr_meter_length_hbo(t, ip);
6593 color_in = instr_meter_color_in_hbo(t, ip);
6595 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6596 &m->profile->profile,
6601 color_out &= m->color_mask;
6603 n_pkts = m->n_pkts[color_out];
6604 n_bytes = m->n_bytes[color_out];
6606 instr_meter_color_out_hbo_set(t, ip, color_out);
6608 m->n_pkts[color_out] = n_pkts + 1;
6609 m->n_bytes[color_out] = n_bytes + length;
6615 instr_meter_imi_exec(struct rte_swx_pipeline *p)
6617 struct thread *t = &p->threads[p->thread_id];
6618 struct instruction *ip = t->ip;
6620 uint64_t time, n_pkts, n_bytes;
6622 enum rte_color color_in, color_out;
6624 TRACE("[Thread %2u] meter (imi)\n", p->thread_id);
6627 m = instr_meter_idx_imm(p, ip);
6628 rte_prefetch0(m->n_pkts);
6629 time = rte_get_tsc_cycles();
6630 length = instr_meter_length_hbo(t, ip);
6631 color_in = (enum rte_color)ip->meter.color_in_val;
6633 color_out = rte_meter_trtcm_color_aware_check(&m->m,
6634 &m->profile->profile,
6639 color_out &= m->color_mask;
6641 n_pkts = m->n_pkts[color_out];
6642 n_bytes = m->n_bytes[color_out];
6644 instr_meter_color_out_hbo_set(t, ip, color_out);
6646 m->n_pkts[color_out] = n_pkts + 1;
6647 m->n_bytes[color_out] = n_bytes + length;
6656 static struct action *
6657 action_find(struct rte_swx_pipeline *p, const char *name);
6660 instr_jmp_translate(struct rte_swx_pipeline *p __rte_unused,
6661 struct action *action __rte_unused,
6664 struct instruction *instr,
6665 struct instruction_data *data)
6667 CHECK(n_tokens == 2, EINVAL);
6669 strcpy(data->jmp_label, tokens[1]);
6671 instr->type = INSTR_JMP;
6672 instr->jmp.ip = NULL; /* Resolved later. */
6677 instr_jmp_valid_translate(struct rte_swx_pipeline *p,
6678 struct action *action __rte_unused,
6681 struct instruction *instr,
6682 struct instruction_data *data)
6686 CHECK(n_tokens == 3, EINVAL);
6688 strcpy(data->jmp_label, tokens[1]);
6690 h = header_parse(p, tokens[2]);
6693 instr->type = INSTR_JMP_VALID;
6694 instr->jmp.ip = NULL; /* Resolved later. */
6695 instr->jmp.header_id = h->id;
6700 instr_jmp_invalid_translate(struct rte_swx_pipeline *p,
6701 struct action *action __rte_unused,
6704 struct instruction *instr,
6705 struct instruction_data *data)
6709 CHECK(n_tokens == 3, EINVAL);
6711 strcpy(data->jmp_label, tokens[1]);
6713 h = header_parse(p, tokens[2]);
6716 instr->type = INSTR_JMP_INVALID;
6717 instr->jmp.ip = NULL; /* Resolved later. */
6718 instr->jmp.header_id = h->id;
6723 instr_jmp_hit_translate(struct rte_swx_pipeline *p __rte_unused,
6724 struct action *action,
6727 struct instruction *instr,
6728 struct instruction_data *data)
6730 CHECK(!action, EINVAL);
6731 CHECK(n_tokens == 2, EINVAL);
6733 strcpy(data->jmp_label, tokens[1]);
6735 instr->type = INSTR_JMP_HIT;
6736 instr->jmp.ip = NULL; /* Resolved later. */
6741 instr_jmp_miss_translate(struct rte_swx_pipeline *p __rte_unused,
6742 struct action *action,
6745 struct instruction *instr,
6746 struct instruction_data *data)
6748 CHECK(!action, EINVAL);
6749 CHECK(n_tokens == 2, EINVAL);
6751 strcpy(data->jmp_label, tokens[1]);
6753 instr->type = INSTR_JMP_MISS;
6754 instr->jmp.ip = NULL; /* Resolved later. */
6759 instr_jmp_action_hit_translate(struct rte_swx_pipeline *p,
6760 struct action *action,
6763 struct instruction *instr,
6764 struct instruction_data *data)
6768 CHECK(!action, EINVAL);
6769 CHECK(n_tokens == 3, EINVAL);
6771 strcpy(data->jmp_label, tokens[1]);
6773 a = action_find(p, tokens[2]);
6776 instr->type = INSTR_JMP_ACTION_HIT;
6777 instr->jmp.ip = NULL; /* Resolved later. */
6778 instr->jmp.action_id = a->id;
6783 instr_jmp_action_miss_translate(struct rte_swx_pipeline *p,
6784 struct action *action,
6787 struct instruction *instr,
6788 struct instruction_data *data)
6792 CHECK(!action, EINVAL);
6793 CHECK(n_tokens == 3, EINVAL);
6795 strcpy(data->jmp_label, tokens[1]);
6797 a = action_find(p, tokens[2]);
6800 instr->type = INSTR_JMP_ACTION_MISS;
6801 instr->jmp.ip = NULL; /* Resolved later. */
6802 instr->jmp.action_id = a->id;
6807 instr_jmp_eq_translate(struct rte_swx_pipeline *p,
6808 struct action *action,
6811 struct instruction *instr,
6812 struct instruction_data *data)
6814 char *a = tokens[2], *b = tokens[3];
6815 struct field *fa, *fb;
6817 uint32_t a_struct_id, b_struct_id;
6819 CHECK(n_tokens == 4, EINVAL);
6821 strcpy(data->jmp_label, tokens[1]);
6823 fa = struct_field_parse(p, action, a, &a_struct_id);
6826 /* JMP_EQ or JMP_EQ_S. */
6827 fb = struct_field_parse(p, action, b, &b_struct_id);
6829 instr->type = INSTR_JMP_EQ;
6830 if ((a[0] == 'h' && b[0] != 'h') ||
6831 (a[0] != 'h' && b[0] == 'h'))
6832 instr->type = INSTR_JMP_EQ_S;
6833 instr->jmp.ip = NULL; /* Resolved later. */
6835 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6836 instr->jmp.a.n_bits = fa->n_bits;
6837 instr->jmp.a.offset = fa->offset / 8;
6838 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6839 instr->jmp.b.n_bits = fb->n_bits;
6840 instr->jmp.b.offset = fb->offset / 8;
6845 b_val = strtoull(b, &b, 0);
6846 CHECK(!b[0], EINVAL);
6849 b_val = hton64(b_val) >> (64 - fa->n_bits);
6851 instr->type = INSTR_JMP_EQ_I;
6852 instr->jmp.ip = NULL; /* Resolved later. */
6853 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6854 instr->jmp.a.n_bits = fa->n_bits;
6855 instr->jmp.a.offset = fa->offset / 8;
6856 instr->jmp.b_val = b_val;
6861 instr_jmp_neq_translate(struct rte_swx_pipeline *p,
6862 struct action *action,
6865 struct instruction *instr,
6866 struct instruction_data *data)
6868 char *a = tokens[2], *b = tokens[3];
6869 struct field *fa, *fb;
6871 uint32_t a_struct_id, b_struct_id;
6873 CHECK(n_tokens == 4, EINVAL);
6875 strcpy(data->jmp_label, tokens[1]);
6877 fa = struct_field_parse(p, action, a, &a_struct_id);
6880 /* JMP_NEQ or JMP_NEQ_S. */
6881 fb = struct_field_parse(p, action, b, &b_struct_id);
6883 instr->type = INSTR_JMP_NEQ;
6884 if ((a[0] == 'h' && b[0] != 'h') ||
6885 (a[0] != 'h' && b[0] == 'h'))
6886 instr->type = INSTR_JMP_NEQ_S;
6887 instr->jmp.ip = NULL; /* Resolved later. */
6889 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6890 instr->jmp.a.n_bits = fa->n_bits;
6891 instr->jmp.a.offset = fa->offset / 8;
6892 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6893 instr->jmp.b.n_bits = fb->n_bits;
6894 instr->jmp.b.offset = fb->offset / 8;
6899 b_val = strtoull(b, &b, 0);
6900 CHECK(!b[0], EINVAL);
6903 b_val = hton64(b_val) >> (64 - fa->n_bits);
6905 instr->type = INSTR_JMP_NEQ_I;
6906 instr->jmp.ip = NULL; /* Resolved later. */
6907 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6908 instr->jmp.a.n_bits = fa->n_bits;
6909 instr->jmp.a.offset = fa->offset / 8;
6910 instr->jmp.b_val = b_val;
6915 instr_jmp_lt_translate(struct rte_swx_pipeline *p,
6916 struct action *action,
6919 struct instruction *instr,
6920 struct instruction_data *data)
6922 char *a = tokens[2], *b = tokens[3];
6923 struct field *fa, *fb;
6925 uint32_t a_struct_id, b_struct_id;
6927 CHECK(n_tokens == 4, EINVAL);
6929 strcpy(data->jmp_label, tokens[1]);
6931 fa = struct_field_parse(p, action, a, &a_struct_id);
6934 /* JMP_LT, JMP_LT_MH, JMP_LT_HM, JMP_LT_HH. */
6935 fb = struct_field_parse(p, action, b, &b_struct_id);
6937 instr->type = INSTR_JMP_LT;
6938 if (a[0] == 'h' && b[0] != 'h')
6939 instr->type = INSTR_JMP_LT_HM;
6940 if (a[0] != 'h' && b[0] == 'h')
6941 instr->type = INSTR_JMP_LT_MH;
6942 if (a[0] == 'h' && b[0] == 'h')
6943 instr->type = INSTR_JMP_LT_HH;
6944 instr->jmp.ip = NULL; /* Resolved later. */
6946 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6947 instr->jmp.a.n_bits = fa->n_bits;
6948 instr->jmp.a.offset = fa->offset / 8;
6949 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
6950 instr->jmp.b.n_bits = fb->n_bits;
6951 instr->jmp.b.offset = fb->offset / 8;
6955 /* JMP_LT_MI, JMP_LT_HI. */
6956 b_val = strtoull(b, &b, 0);
6957 CHECK(!b[0], EINVAL);
6959 instr->type = INSTR_JMP_LT_MI;
6961 instr->type = INSTR_JMP_LT_HI;
6962 instr->jmp.ip = NULL; /* Resolved later. */
6964 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
6965 instr->jmp.a.n_bits = fa->n_bits;
6966 instr->jmp.a.offset = fa->offset / 8;
6967 instr->jmp.b_val = b_val;
6972 instr_jmp_gt_translate(struct rte_swx_pipeline *p,
6973 struct action *action,
6976 struct instruction *instr,
6977 struct instruction_data *data)
6979 char *a = tokens[2], *b = tokens[3];
6980 struct field *fa, *fb;
6982 uint32_t a_struct_id, b_struct_id;
6984 CHECK(n_tokens == 4, EINVAL);
6986 strcpy(data->jmp_label, tokens[1]);
6988 fa = struct_field_parse(p, action, a, &a_struct_id);
6991 /* JMP_GT, JMP_GT_MH, JMP_GT_HM, JMP_GT_HH. */
6992 fb = struct_field_parse(p, action, b, &b_struct_id);
6994 instr->type = INSTR_JMP_GT;
6995 if (a[0] == 'h' && b[0] != 'h')
6996 instr->type = INSTR_JMP_GT_HM;
6997 if (a[0] != 'h' && b[0] == 'h')
6998 instr->type = INSTR_JMP_GT_MH;
6999 if (a[0] == 'h' && b[0] == 'h')
7000 instr->type = INSTR_JMP_GT_HH;
7001 instr->jmp.ip = NULL; /* Resolved later. */
7003 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
7004 instr->jmp.a.n_bits = fa->n_bits;
7005 instr->jmp.a.offset = fa->offset / 8;
7006 instr->jmp.b.struct_id = (uint8_t)b_struct_id;
7007 instr->jmp.b.n_bits = fb->n_bits;
7008 instr->jmp.b.offset = fb->offset / 8;
7012 /* JMP_GT_MI, JMP_GT_HI. */
7013 b_val = strtoull(b, &b, 0);
7014 CHECK(!b[0], EINVAL);
7016 instr->type = INSTR_JMP_GT_MI;
7018 instr->type = INSTR_JMP_GT_HI;
7019 instr->jmp.ip = NULL; /* Resolved later. */
7021 instr->jmp.a.struct_id = (uint8_t)a_struct_id;
7022 instr->jmp.a.n_bits = fa->n_bits;
7023 instr->jmp.a.offset = fa->offset / 8;
7024 instr->jmp.b_val = b_val;
7029 instr_jmp_exec(struct rte_swx_pipeline *p)
7031 struct thread *t = &p->threads[p->thread_id];
7032 struct instruction *ip = t->ip;
7034 TRACE("[Thread %2u] jmp\n", p->thread_id);
7036 thread_ip_set(t, ip->jmp.ip);
7040 instr_jmp_valid_exec(struct rte_swx_pipeline *p)
7042 struct thread *t = &p->threads[p->thread_id];
7043 struct instruction *ip = t->ip;
7044 uint32_t header_id = ip->jmp.header_id;
7046 TRACE("[Thread %2u] jmpv\n", p->thread_id);
7048 t->ip = HEADER_VALID(t, header_id) ? ip->jmp.ip : (t->ip + 1);
7052 instr_jmp_invalid_exec(struct rte_swx_pipeline *p)
7054 struct thread *t = &p->threads[p->thread_id];
7055 struct instruction *ip = t->ip;
7056 uint32_t header_id = ip->jmp.header_id;
7058 TRACE("[Thread %2u] jmpnv\n", p->thread_id);
7060 t->ip = HEADER_VALID(t, header_id) ? (t->ip + 1) : ip->jmp.ip;
7064 instr_jmp_hit_exec(struct rte_swx_pipeline *p)
7066 struct thread *t = &p->threads[p->thread_id];
7067 struct instruction *ip = t->ip;
7068 struct instruction *ip_next[] = {t->ip + 1, ip->jmp.ip};
7070 TRACE("[Thread %2u] jmph\n", p->thread_id);
7072 t->ip = ip_next[t->hit];
7076 instr_jmp_miss_exec(struct rte_swx_pipeline *p)
7078 struct thread *t = &p->threads[p->thread_id];
7079 struct instruction *ip = t->ip;
7080 struct instruction *ip_next[] = {ip->jmp.ip, t->ip + 1};
7082 TRACE("[Thread %2u] jmpnh\n", p->thread_id);
7084 t->ip = ip_next[t->hit];
7088 instr_jmp_action_hit_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] jmpa\n", p->thread_id);
7095 t->ip = (ip->jmp.action_id == t->action_id) ? ip->jmp.ip : (t->ip + 1);
7099 instr_jmp_action_miss_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] jmpna\n", p->thread_id);
7106 t->ip = (ip->jmp.action_id == t->action_id) ? (t->ip + 1) : ip->jmp.ip;
7110 instr_jmp_eq_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\n", p->thread_id);
7121 instr_jmp_eq_s_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 (s)\n", p->thread_id);
7128 JMP_CMP_S(t, ip, ==);
7132 instr_jmp_eq_i_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] jmpeq (i)\n", p->thread_id);
7139 JMP_CMP_I(t, ip, ==);
7143 instr_jmp_neq_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\n", p->thread_id);
7154 instr_jmp_neq_s_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 (s)\n", p->thread_id);
7161 JMP_CMP_S(t, ip, !=);
7165 instr_jmp_neq_i_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] jmpneq (i)\n", p->thread_id);
7172 JMP_CMP_I(t, ip, !=);
7176 instr_jmp_lt_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\n", p->thread_id);
7187 instr_jmp_lt_mh_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 (mh)\n", p->thread_id);
7194 JMP_CMP_MH(t, ip, <);
7198 instr_jmp_lt_hm_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 (hm)\n", p->thread_id);
7205 JMP_CMP_HM(t, ip, <);
7209 instr_jmp_lt_hh_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 (hh)\n", p->thread_id);
7216 JMP_CMP_HH(t, ip, <);
7220 instr_jmp_lt_mi_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 (mi)\n", p->thread_id);
7227 JMP_CMP_MI(t, ip, <);
7231 instr_jmp_lt_hi_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] jmplt (hi)\n", p->thread_id);
7238 JMP_CMP_HI(t, ip, <);
7242 instr_jmp_gt_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\n", p->thread_id);
7253 instr_jmp_gt_mh_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 (mh)\n", p->thread_id);
7260 JMP_CMP_MH(t, ip, >);
7264 instr_jmp_gt_hm_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 (hm)\n", p->thread_id);
7271 JMP_CMP_HM(t, ip, >);
7275 instr_jmp_gt_hh_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 (hh)\n", p->thread_id);
7282 JMP_CMP_HH(t, ip, >);
7286 instr_jmp_gt_mi_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 (mi)\n", p->thread_id);
7293 JMP_CMP_MI(t, ip, >);
7297 instr_jmp_gt_hi_exec(struct rte_swx_pipeline *p)
7299 struct thread *t = &p->threads[p->thread_id];
7300 struct instruction *ip = t->ip;
7302 TRACE("[Thread %2u] jmpgt (hi)\n", p->thread_id);
7304 JMP_CMP_HI(t, ip, >);
7311 instr_return_translate(struct rte_swx_pipeline *p __rte_unused,
7312 struct action *action,
7313 char **tokens __rte_unused,
7315 struct instruction *instr,
7316 struct instruction_data *data __rte_unused)
7318 CHECK(action, EINVAL);
7319 CHECK(n_tokens == 1, EINVAL);
7321 instr->type = INSTR_RETURN;
7326 instr_return_exec(struct rte_swx_pipeline *p)
7328 struct thread *t = &p->threads[p->thread_id];
7330 TRACE("[Thread %2u] return\n", p->thread_id);
7336 instr_translate(struct rte_swx_pipeline *p,
7337 struct action *action,
7339 struct instruction *instr,
7340 struct instruction_data *data)
7342 char *tokens[RTE_SWX_INSTRUCTION_TOKENS_MAX];
7343 int n_tokens = 0, tpos = 0;
7345 /* Parse the instruction string into tokens. */
7349 token = strtok_r(string, " \t\v", &string);
7353 CHECK(n_tokens < RTE_SWX_INSTRUCTION_TOKENS_MAX, EINVAL);
7354 CHECK_NAME(token, EINVAL);
7356 tokens[n_tokens] = token;
7360 CHECK(n_tokens, EINVAL);
7362 /* Handle the optional instruction label. */
7363 if ((n_tokens >= 2) && !strcmp(tokens[1], ":")) {
7364 strcpy(data->label, tokens[0]);
7367 CHECK(n_tokens - tpos, EINVAL);
7370 /* Identify the instruction type. */
7371 if (!strcmp(tokens[tpos], "rx"))
7372 return instr_rx_translate(p,
7379 if (!strcmp(tokens[tpos], "tx"))
7380 return instr_tx_translate(p,
7387 if (!strcmp(tokens[tpos], "drop"))
7388 return instr_drop_translate(p,
7395 if (!strcmp(tokens[tpos], "extract"))
7396 return instr_hdr_extract_translate(p,
7403 if (!strcmp(tokens[tpos], "emit"))
7404 return instr_hdr_emit_translate(p,
7411 if (!strcmp(tokens[tpos], "validate"))
7412 return instr_hdr_validate_translate(p,
7419 if (!strcmp(tokens[tpos], "invalidate"))
7420 return instr_hdr_invalidate_translate(p,
7427 if (!strcmp(tokens[tpos], "mov"))
7428 return instr_mov_translate(p,
7435 if (!strcmp(tokens[tpos], "dma"))
7436 return instr_dma_translate(p,
7443 if (!strcmp(tokens[tpos], "add"))
7444 return instr_alu_add_translate(p,
7451 if (!strcmp(tokens[tpos], "sub"))
7452 return instr_alu_sub_translate(p,
7459 if (!strcmp(tokens[tpos], "ckadd"))
7460 return instr_alu_ckadd_translate(p,
7467 if (!strcmp(tokens[tpos], "cksub"))
7468 return instr_alu_cksub_translate(p,
7475 if (!strcmp(tokens[tpos], "and"))
7476 return instr_alu_and_translate(p,
7483 if (!strcmp(tokens[tpos], "or"))
7484 return instr_alu_or_translate(p,
7491 if (!strcmp(tokens[tpos], "xor"))
7492 return instr_alu_xor_translate(p,
7499 if (!strcmp(tokens[tpos], "shl"))
7500 return instr_alu_shl_translate(p,
7507 if (!strcmp(tokens[tpos], "shr"))
7508 return instr_alu_shr_translate(p,
7515 if (!strcmp(tokens[tpos], "regprefetch"))
7516 return instr_regprefetch_translate(p,
7523 if (!strcmp(tokens[tpos], "regrd"))
7524 return instr_regrd_translate(p,
7531 if (!strcmp(tokens[tpos], "regwr"))
7532 return instr_regwr_translate(p,
7539 if (!strcmp(tokens[tpos], "regadd"))
7540 return instr_regadd_translate(p,
7547 if (!strcmp(tokens[tpos], "metprefetch"))
7548 return instr_metprefetch_translate(p,
7555 if (!strcmp(tokens[tpos], "meter"))
7556 return instr_meter_translate(p,
7563 if (!strcmp(tokens[tpos], "table"))
7564 return instr_table_translate(p,
7571 if (!strcmp(tokens[tpos], "extern"))
7572 return instr_extern_translate(p,
7579 if (!strcmp(tokens[tpos], "jmp"))
7580 return instr_jmp_translate(p,
7587 if (!strcmp(tokens[tpos], "jmpv"))
7588 return instr_jmp_valid_translate(p,
7595 if (!strcmp(tokens[tpos], "jmpnv"))
7596 return instr_jmp_invalid_translate(p,
7603 if (!strcmp(tokens[tpos], "jmph"))
7604 return instr_jmp_hit_translate(p,
7611 if (!strcmp(tokens[tpos], "jmpnh"))
7612 return instr_jmp_miss_translate(p,
7619 if (!strcmp(tokens[tpos], "jmpa"))
7620 return instr_jmp_action_hit_translate(p,
7627 if (!strcmp(tokens[tpos], "jmpna"))
7628 return instr_jmp_action_miss_translate(p,
7635 if (!strcmp(tokens[tpos], "jmpeq"))
7636 return instr_jmp_eq_translate(p,
7643 if (!strcmp(tokens[tpos], "jmpneq"))
7644 return instr_jmp_neq_translate(p,
7651 if (!strcmp(tokens[tpos], "jmplt"))
7652 return instr_jmp_lt_translate(p,
7659 if (!strcmp(tokens[tpos], "jmpgt"))
7660 return instr_jmp_gt_translate(p,
7667 if (!strcmp(tokens[tpos], "return"))
7668 return instr_return_translate(p,
7678 static struct instruction_data *
7679 label_find(struct instruction_data *data, uint32_t n, const char *label)
7683 for (i = 0; i < n; i++)
7684 if (!strcmp(label, data[i].label))
7691 label_is_used(struct instruction_data *data, uint32_t n, const char *label)
7693 uint32_t count = 0, i;
7698 for (i = 0; i < n; i++)
7699 if (!strcmp(label, data[i].jmp_label))
7706 instr_label_check(struct instruction_data *instruction_data,
7707 uint32_t n_instructions)
7711 /* Check that all instruction labels are unique. */
7712 for (i = 0; i < n_instructions; i++) {
7713 struct instruction_data *data = &instruction_data[i];
7714 char *label = data->label;
7720 for (j = i + 1; j < n_instructions; j++)
7721 CHECK(strcmp(label, data[j].label), EINVAL);
7724 /* Get users for each instruction label. */
7725 for (i = 0; i < n_instructions; i++) {
7726 struct instruction_data *data = &instruction_data[i];
7727 char *label = data->label;
7729 data->n_users = label_is_used(instruction_data,
7738 instr_jmp_resolve(struct instruction *instructions,
7739 struct instruction_data *instruction_data,
7740 uint32_t n_instructions)
7744 for (i = 0; i < n_instructions; i++) {
7745 struct instruction *instr = &instructions[i];
7746 struct instruction_data *data = &instruction_data[i];
7747 struct instruction_data *found;
7749 if (!instruction_is_jmp(instr))
7752 found = label_find(instruction_data,
7755 CHECK(found, EINVAL);
7757 instr->jmp.ip = &instructions[found - instruction_data];
7764 instr_verify(struct rte_swx_pipeline *p __rte_unused,
7766 struct instruction *instr,
7767 struct instruction_data *data __rte_unused,
7768 uint32_t n_instructions)
7771 enum instruction_type type;
7774 /* Check that the first instruction is rx. */
7775 CHECK(instr[0].type == INSTR_RX, EINVAL);
7777 /* Check that there is at least one tx instruction. */
7778 for (i = 0; i < n_instructions; i++) {
7779 type = instr[i].type;
7781 if (instruction_is_tx(type))
7784 CHECK(i < n_instructions, EINVAL);
7786 /* Check that the last instruction is either tx or unconditional
7789 type = instr[n_instructions - 1].type;
7790 CHECK(instruction_is_tx(type) || (type == INSTR_JMP), EINVAL);
7794 enum instruction_type type;
7797 /* Check that there is at least one return or tx instruction. */
7798 for (i = 0; i < n_instructions; i++) {
7799 type = instr[i].type;
7801 if ((type == INSTR_RETURN) || instruction_is_tx(type))
7804 CHECK(i < n_instructions, EINVAL);
7811 instr_pattern_extract_many_detect(struct instruction *instr,
7812 struct instruction_data *data,
7814 uint32_t *n_pattern_instr)
7818 for (i = 0; i < n_instr; i++) {
7819 if (data[i].invalid)
7822 if (instr[i].type != INSTR_HDR_EXTRACT)
7825 if (i == RTE_DIM(instr->io.hdr.header_id))
7828 if (i && data[i].n_users)
7835 *n_pattern_instr = i;
7840 instr_pattern_extract_many_optimize(struct instruction *instr,
7841 struct instruction_data *data,
7846 for (i = 1; i < n_instr; i++) {
7848 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
7849 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
7850 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
7852 data[i].invalid = 1;
7857 instr_pattern_emit_many_tx_detect(struct instruction *instr,
7858 struct instruction_data *data,
7860 uint32_t *n_pattern_instr)
7864 for (i = 0; i < n_instr; i++) {
7865 if (data[i].invalid)
7868 if (instr[i].type != INSTR_HDR_EMIT)
7871 if (i == RTE_DIM(instr->io.hdr.header_id))
7874 if (i && data[i].n_users)
7881 if (!instruction_is_tx(instr[i].type))
7884 if (data[i].n_users)
7889 *n_pattern_instr = i;
7894 instr_pattern_emit_many_tx_optimize(struct instruction *instr,
7895 struct instruction_data *data,
7900 /* Any emit instruction in addition to the first one. */
7901 for (i = 1; i < n_instr - 1; i++) {
7903 instr[0].io.hdr.header_id[i] = instr[i].io.hdr.header_id[0];
7904 instr[0].io.hdr.struct_id[i] = instr[i].io.hdr.struct_id[0];
7905 instr[0].io.hdr.n_bytes[i] = instr[i].io.hdr.n_bytes[0];
7907 data[i].invalid = 1;
7910 /* The TX instruction is the last one in the pattern. */
7912 instr[0].io.io.offset = instr[i].io.io.offset;
7913 instr[0].io.io.n_bits = instr[i].io.io.n_bits;
7914 data[i].invalid = 1;
7918 instr_pattern_dma_many_detect(struct instruction *instr,
7919 struct instruction_data *data,
7921 uint32_t *n_pattern_instr)
7925 for (i = 0; i < n_instr; i++) {
7926 if (data[i].invalid)
7929 if (instr[i].type != INSTR_DMA_HT)
7932 if (i == RTE_DIM(instr->dma.dst.header_id))
7935 if (i && data[i].n_users)
7942 *n_pattern_instr = i;
7947 instr_pattern_dma_many_optimize(struct instruction *instr,
7948 struct instruction_data *data,
7953 for (i = 1; i < n_instr; i++) {
7955 instr[0].dma.dst.header_id[i] = instr[i].dma.dst.header_id[0];
7956 instr[0].dma.dst.struct_id[i] = instr[i].dma.dst.struct_id[0];
7957 instr[0].dma.src.offset[i] = instr[i].dma.src.offset[0];
7958 instr[0].dma.n_bytes[i] = instr[i].dma.n_bytes[0];
7960 data[i].invalid = 1;
7965 instr_optimize(struct instruction *instructions,
7966 struct instruction_data *instruction_data,
7967 uint32_t n_instructions)
7969 uint32_t i, pos = 0;
7971 for (i = 0; i < n_instructions; ) {
7972 struct instruction *instr = &instructions[i];
7973 struct instruction_data *data = &instruction_data[i];
7974 uint32_t n_instr = 0;
7978 detected = instr_pattern_extract_many_detect(instr,
7983 instr_pattern_extract_many_optimize(instr,
7990 /* Emit many + TX. */
7991 detected = instr_pattern_emit_many_tx_detect(instr,
7996 instr_pattern_emit_many_tx_optimize(instr,
8004 detected = instr_pattern_dma_many_detect(instr,
8009 instr_pattern_dma_many_optimize(instr, data, n_instr);
8014 /* No pattern starting at the current instruction. */
8018 /* Eliminate the invalid instructions that have been optimized out. */
8019 for (i = 0; i < n_instructions; i++) {
8020 struct instruction *instr = &instructions[i];
8021 struct instruction_data *data = &instruction_data[i];
8027 memcpy(&instructions[pos], instr, sizeof(*instr));
8028 memcpy(&instruction_data[pos], data, sizeof(*data));
8038 instruction_config(struct rte_swx_pipeline *p,
8040 const char **instructions,
8041 uint32_t n_instructions)
8043 struct instruction *instr = NULL;
8044 struct instruction_data *data = NULL;
8048 CHECK(n_instructions, EINVAL);
8049 CHECK(instructions, EINVAL);
8050 for (i = 0; i < n_instructions; i++)
8051 CHECK_INSTRUCTION(instructions[i], EINVAL);
8053 /* Memory allocation. */
8054 instr = calloc(n_instructions, sizeof(struct instruction));
8060 data = calloc(n_instructions, sizeof(struct instruction_data));
8066 for (i = 0; i < n_instructions; i++) {
8067 char *string = strdup(instructions[i]);
8073 err = instr_translate(p, a, string, &instr[i], &data[i]);
8082 err = instr_label_check(data, n_instructions);
8086 err = instr_verify(p, a, instr, data, n_instructions);
8090 n_instructions = instr_optimize(instr, data, n_instructions);
8092 err = instr_jmp_resolve(instr, data, n_instructions);
8097 a->instructions = instr;
8098 a->n_instructions = n_instructions;
8100 p->instructions = instr;
8101 p->n_instructions = n_instructions;
8113 typedef void (*instr_exec_t)(struct rte_swx_pipeline *);
8115 static instr_exec_t instruction_table[] = {
8116 [INSTR_RX] = instr_rx_exec,
8117 [INSTR_TX] = instr_tx_exec,
8118 [INSTR_TX_I] = instr_tx_i_exec,
8120 [INSTR_HDR_EXTRACT] = instr_hdr_extract_exec,
8121 [INSTR_HDR_EXTRACT2] = instr_hdr_extract2_exec,
8122 [INSTR_HDR_EXTRACT3] = instr_hdr_extract3_exec,
8123 [INSTR_HDR_EXTRACT4] = instr_hdr_extract4_exec,
8124 [INSTR_HDR_EXTRACT5] = instr_hdr_extract5_exec,
8125 [INSTR_HDR_EXTRACT6] = instr_hdr_extract6_exec,
8126 [INSTR_HDR_EXTRACT7] = instr_hdr_extract7_exec,
8127 [INSTR_HDR_EXTRACT8] = instr_hdr_extract8_exec,
8129 [INSTR_HDR_EMIT] = instr_hdr_emit_exec,
8130 [INSTR_HDR_EMIT_TX] = instr_hdr_emit_tx_exec,
8131 [INSTR_HDR_EMIT2_TX] = instr_hdr_emit2_tx_exec,
8132 [INSTR_HDR_EMIT3_TX] = instr_hdr_emit3_tx_exec,
8133 [INSTR_HDR_EMIT4_TX] = instr_hdr_emit4_tx_exec,
8134 [INSTR_HDR_EMIT5_TX] = instr_hdr_emit5_tx_exec,
8135 [INSTR_HDR_EMIT6_TX] = instr_hdr_emit6_tx_exec,
8136 [INSTR_HDR_EMIT7_TX] = instr_hdr_emit7_tx_exec,
8137 [INSTR_HDR_EMIT8_TX] = instr_hdr_emit8_tx_exec,
8139 [INSTR_HDR_VALIDATE] = instr_hdr_validate_exec,
8140 [INSTR_HDR_INVALIDATE] = instr_hdr_invalidate_exec,
8142 [INSTR_MOV] = instr_mov_exec,
8143 [INSTR_MOV_S] = instr_mov_s_exec,
8144 [INSTR_MOV_I] = instr_mov_i_exec,
8146 [INSTR_DMA_HT] = instr_dma_ht_exec,
8147 [INSTR_DMA_HT2] = instr_dma_ht2_exec,
8148 [INSTR_DMA_HT3] = instr_dma_ht3_exec,
8149 [INSTR_DMA_HT4] = instr_dma_ht4_exec,
8150 [INSTR_DMA_HT5] = instr_dma_ht5_exec,
8151 [INSTR_DMA_HT6] = instr_dma_ht6_exec,
8152 [INSTR_DMA_HT7] = instr_dma_ht7_exec,
8153 [INSTR_DMA_HT8] = instr_dma_ht8_exec,
8155 [INSTR_ALU_ADD] = instr_alu_add_exec,
8156 [INSTR_ALU_ADD_MH] = instr_alu_add_mh_exec,
8157 [INSTR_ALU_ADD_HM] = instr_alu_add_hm_exec,
8158 [INSTR_ALU_ADD_HH] = instr_alu_add_hh_exec,
8159 [INSTR_ALU_ADD_MI] = instr_alu_add_mi_exec,
8160 [INSTR_ALU_ADD_HI] = instr_alu_add_hi_exec,
8162 [INSTR_ALU_SUB] = instr_alu_sub_exec,
8163 [INSTR_ALU_SUB_MH] = instr_alu_sub_mh_exec,
8164 [INSTR_ALU_SUB_HM] = instr_alu_sub_hm_exec,
8165 [INSTR_ALU_SUB_HH] = instr_alu_sub_hh_exec,
8166 [INSTR_ALU_SUB_MI] = instr_alu_sub_mi_exec,
8167 [INSTR_ALU_SUB_HI] = instr_alu_sub_hi_exec,
8169 [INSTR_ALU_CKADD_FIELD] = instr_alu_ckadd_field_exec,
8170 [INSTR_ALU_CKADD_STRUCT] = instr_alu_ckadd_struct_exec,
8171 [INSTR_ALU_CKADD_STRUCT20] = instr_alu_ckadd_struct20_exec,
8172 [INSTR_ALU_CKSUB_FIELD] = instr_alu_cksub_field_exec,
8174 [INSTR_ALU_AND] = instr_alu_and_exec,
8175 [INSTR_ALU_AND_S] = instr_alu_and_s_exec,
8176 [INSTR_ALU_AND_I] = instr_alu_and_i_exec,
8178 [INSTR_ALU_OR] = instr_alu_or_exec,
8179 [INSTR_ALU_OR_S] = instr_alu_or_s_exec,
8180 [INSTR_ALU_OR_I] = instr_alu_or_i_exec,
8182 [INSTR_ALU_XOR] = instr_alu_xor_exec,
8183 [INSTR_ALU_XOR_S] = instr_alu_xor_s_exec,
8184 [INSTR_ALU_XOR_I] = instr_alu_xor_i_exec,
8186 [INSTR_ALU_SHL] = instr_alu_shl_exec,
8187 [INSTR_ALU_SHL_MH] = instr_alu_shl_mh_exec,
8188 [INSTR_ALU_SHL_HM] = instr_alu_shl_hm_exec,
8189 [INSTR_ALU_SHL_HH] = instr_alu_shl_hh_exec,
8190 [INSTR_ALU_SHL_MI] = instr_alu_shl_mi_exec,
8191 [INSTR_ALU_SHL_HI] = instr_alu_shl_hi_exec,
8193 [INSTR_ALU_SHR] = instr_alu_shr_exec,
8194 [INSTR_ALU_SHR_MH] = instr_alu_shr_mh_exec,
8195 [INSTR_ALU_SHR_HM] = instr_alu_shr_hm_exec,
8196 [INSTR_ALU_SHR_HH] = instr_alu_shr_hh_exec,
8197 [INSTR_ALU_SHR_MI] = instr_alu_shr_mi_exec,
8198 [INSTR_ALU_SHR_HI] = instr_alu_shr_hi_exec,
8200 [INSTR_REGPREFETCH_RH] = instr_regprefetch_rh_exec,
8201 [INSTR_REGPREFETCH_RM] = instr_regprefetch_rm_exec,
8202 [INSTR_REGPREFETCH_RI] = instr_regprefetch_ri_exec,
8204 [INSTR_REGRD_HRH] = instr_regrd_hrh_exec,
8205 [INSTR_REGRD_HRM] = instr_regrd_hrm_exec,
8206 [INSTR_REGRD_MRH] = instr_regrd_mrh_exec,
8207 [INSTR_REGRD_MRM] = instr_regrd_mrm_exec,
8208 [INSTR_REGRD_HRI] = instr_regrd_hri_exec,
8209 [INSTR_REGRD_MRI] = instr_regrd_mri_exec,
8211 [INSTR_REGWR_RHH] = instr_regwr_rhh_exec,
8212 [INSTR_REGWR_RHM] = instr_regwr_rhm_exec,
8213 [INSTR_REGWR_RMH] = instr_regwr_rmh_exec,
8214 [INSTR_REGWR_RMM] = instr_regwr_rmm_exec,
8215 [INSTR_REGWR_RHI] = instr_regwr_rhi_exec,
8216 [INSTR_REGWR_RMI] = instr_regwr_rmi_exec,
8217 [INSTR_REGWR_RIH] = instr_regwr_rih_exec,
8218 [INSTR_REGWR_RIM] = instr_regwr_rim_exec,
8219 [INSTR_REGWR_RII] = instr_regwr_rii_exec,
8221 [INSTR_REGADD_RHH] = instr_regadd_rhh_exec,
8222 [INSTR_REGADD_RHM] = instr_regadd_rhm_exec,
8223 [INSTR_REGADD_RMH] = instr_regadd_rmh_exec,
8224 [INSTR_REGADD_RMM] = instr_regadd_rmm_exec,
8225 [INSTR_REGADD_RHI] = instr_regadd_rhi_exec,
8226 [INSTR_REGADD_RMI] = instr_regadd_rmi_exec,
8227 [INSTR_REGADD_RIH] = instr_regadd_rih_exec,
8228 [INSTR_REGADD_RIM] = instr_regadd_rim_exec,
8229 [INSTR_REGADD_RII] = instr_regadd_rii_exec,
8231 [INSTR_METPREFETCH_H] = instr_metprefetch_h_exec,
8232 [INSTR_METPREFETCH_M] = instr_metprefetch_m_exec,
8233 [INSTR_METPREFETCH_I] = instr_metprefetch_i_exec,
8235 [INSTR_METER_HHM] = instr_meter_hhm_exec,
8236 [INSTR_METER_HHI] = instr_meter_hhi_exec,
8237 [INSTR_METER_HMM] = instr_meter_hmm_exec,
8238 [INSTR_METER_HMI] = instr_meter_hmi_exec,
8239 [INSTR_METER_MHM] = instr_meter_mhm_exec,
8240 [INSTR_METER_MHI] = instr_meter_mhi_exec,
8241 [INSTR_METER_MMM] = instr_meter_mmm_exec,
8242 [INSTR_METER_MMI] = instr_meter_mmi_exec,
8243 [INSTR_METER_IHM] = instr_meter_ihm_exec,
8244 [INSTR_METER_IHI] = instr_meter_ihi_exec,
8245 [INSTR_METER_IMM] = instr_meter_imm_exec,
8246 [INSTR_METER_IMI] = instr_meter_imi_exec,
8248 [INSTR_TABLE] = instr_table_exec,
8249 [INSTR_EXTERN_OBJ] = instr_extern_obj_exec,
8250 [INSTR_EXTERN_FUNC] = instr_extern_func_exec,
8252 [INSTR_JMP] = instr_jmp_exec,
8253 [INSTR_JMP_VALID] = instr_jmp_valid_exec,
8254 [INSTR_JMP_INVALID] = instr_jmp_invalid_exec,
8255 [INSTR_JMP_HIT] = instr_jmp_hit_exec,
8256 [INSTR_JMP_MISS] = instr_jmp_miss_exec,
8257 [INSTR_JMP_ACTION_HIT] = instr_jmp_action_hit_exec,
8258 [INSTR_JMP_ACTION_MISS] = instr_jmp_action_miss_exec,
8260 [INSTR_JMP_EQ] = instr_jmp_eq_exec,
8261 [INSTR_JMP_EQ_S] = instr_jmp_eq_s_exec,
8262 [INSTR_JMP_EQ_I] = instr_jmp_eq_i_exec,
8264 [INSTR_JMP_NEQ] = instr_jmp_neq_exec,
8265 [INSTR_JMP_NEQ_S] = instr_jmp_neq_s_exec,
8266 [INSTR_JMP_NEQ_I] = instr_jmp_neq_i_exec,
8268 [INSTR_JMP_LT] = instr_jmp_lt_exec,
8269 [INSTR_JMP_LT_MH] = instr_jmp_lt_mh_exec,
8270 [INSTR_JMP_LT_HM] = instr_jmp_lt_hm_exec,
8271 [INSTR_JMP_LT_HH] = instr_jmp_lt_hh_exec,
8272 [INSTR_JMP_LT_MI] = instr_jmp_lt_mi_exec,
8273 [INSTR_JMP_LT_HI] = instr_jmp_lt_hi_exec,
8275 [INSTR_JMP_GT] = instr_jmp_gt_exec,
8276 [INSTR_JMP_GT_MH] = instr_jmp_gt_mh_exec,
8277 [INSTR_JMP_GT_HM] = instr_jmp_gt_hm_exec,
8278 [INSTR_JMP_GT_HH] = instr_jmp_gt_hh_exec,
8279 [INSTR_JMP_GT_MI] = instr_jmp_gt_mi_exec,
8280 [INSTR_JMP_GT_HI] = instr_jmp_gt_hi_exec,
8282 [INSTR_RETURN] = instr_return_exec,
8286 instr_exec(struct rte_swx_pipeline *p)
8288 struct thread *t = &p->threads[p->thread_id];
8289 struct instruction *ip = t->ip;
8290 instr_exec_t instr = instruction_table[ip->type];
8298 static struct action *
8299 action_find(struct rte_swx_pipeline *p, const char *name)
8301 struct action *elem;
8306 TAILQ_FOREACH(elem, &p->actions, node)
8307 if (strcmp(elem->name, name) == 0)
8313 static struct action *
8314 action_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8316 struct action *action = NULL;
8318 TAILQ_FOREACH(action, &p->actions, node)
8319 if (action->id == id)
8325 static struct field *
8326 action_field_find(struct action *a, const char *name)
8328 return a->st ? struct_type_field_find(a->st, name) : NULL;
8331 static struct field *
8332 action_field_parse(struct action *action, const char *name)
8334 if (name[0] != 't' || name[1] != '.')
8337 return action_field_find(action, &name[2]);
8341 rte_swx_pipeline_action_config(struct rte_swx_pipeline *p,
8343 const char *args_struct_type_name,
8344 const char **instructions,
8345 uint32_t n_instructions)
8347 struct struct_type *args_struct_type;
8353 CHECK_NAME(name, EINVAL);
8354 CHECK(!action_find(p, name), EEXIST);
8356 if (args_struct_type_name) {
8357 CHECK_NAME(args_struct_type_name, EINVAL);
8358 args_struct_type = struct_type_find(p, args_struct_type_name);
8359 CHECK(args_struct_type, EINVAL);
8361 args_struct_type = NULL;
8364 /* Node allocation. */
8365 a = calloc(1, sizeof(struct action));
8368 /* Node initialization. */
8369 strcpy(a->name, name);
8370 a->st = args_struct_type;
8371 a->id = p->n_actions;
8373 /* Instruction translation. */
8374 err = instruction_config(p, a, instructions, n_instructions);
8380 /* Node add to tailq. */
8381 TAILQ_INSERT_TAIL(&p->actions, a, node);
8388 action_build(struct rte_swx_pipeline *p)
8390 struct action *action;
8392 p->action_instructions = calloc(p->n_actions,
8393 sizeof(struct instruction *));
8394 CHECK(p->action_instructions, ENOMEM);
8396 TAILQ_FOREACH(action, &p->actions, node)
8397 p->action_instructions[action->id] = action->instructions;
8403 action_build_free(struct rte_swx_pipeline *p)
8405 free(p->action_instructions);
8406 p->action_instructions = NULL;
8410 action_free(struct rte_swx_pipeline *p)
8412 action_build_free(p);
8415 struct action *action;
8417 action = TAILQ_FIRST(&p->actions);
8421 TAILQ_REMOVE(&p->actions, action, node);
8422 free(action->instructions);
8430 static struct table_type *
8431 table_type_find(struct rte_swx_pipeline *p, const char *name)
8433 struct table_type *elem;
8435 TAILQ_FOREACH(elem, &p->table_types, node)
8436 if (strcmp(elem->name, name) == 0)
8442 static struct table_type *
8443 table_type_resolve(struct rte_swx_pipeline *p,
8444 const char *recommended_type_name,
8445 enum rte_swx_table_match_type match_type)
8447 struct table_type *elem;
8449 /* Only consider the recommended type if the match type is correct. */
8450 if (recommended_type_name)
8451 TAILQ_FOREACH(elem, &p->table_types, node)
8452 if (!strcmp(elem->name, recommended_type_name) &&
8453 (elem->match_type == match_type))
8456 /* Ignore the recommended type and get the first element with this match
8459 TAILQ_FOREACH(elem, &p->table_types, node)
8460 if (elem->match_type == match_type)
8466 static struct table *
8467 table_find(struct rte_swx_pipeline *p, const char *name)
8471 TAILQ_FOREACH(elem, &p->tables, node)
8472 if (strcmp(elem->name, name) == 0)
8478 static struct table *
8479 table_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
8481 struct table *table = NULL;
8483 TAILQ_FOREACH(table, &p->tables, node)
8484 if (table->id == id)
8491 rte_swx_pipeline_table_type_register(struct rte_swx_pipeline *p,
8493 enum rte_swx_table_match_type match_type,
8494 struct rte_swx_table_ops *ops)
8496 struct table_type *elem;
8500 CHECK_NAME(name, EINVAL);
8501 CHECK(!table_type_find(p, name), EEXIST);
8504 CHECK(ops->create, EINVAL);
8505 CHECK(ops->lkp, EINVAL);
8506 CHECK(ops->free, EINVAL);
8508 /* Node allocation. */
8509 elem = calloc(1, sizeof(struct table_type));
8510 CHECK(elem, ENOMEM);
8512 /* Node initialization. */
8513 strcpy(elem->name, name);
8514 elem->match_type = match_type;
8515 memcpy(&elem->ops, ops, sizeof(*ops));
8517 /* Node add to tailq. */
8518 TAILQ_INSERT_TAIL(&p->table_types, elem, node);
8523 static enum rte_swx_table_match_type
8524 table_match_type_resolve(struct rte_swx_match_field_params *fields,
8526 uint32_t max_offset_field_id)
8528 uint32_t n_fields_em = 0, i;
8530 for (i = 0; i < n_fields; i++)
8531 if (fields[i].match_type == RTE_SWX_TABLE_MATCH_EXACT)
8534 if (n_fields_em == n_fields)
8535 return RTE_SWX_TABLE_MATCH_EXACT;
8537 if ((n_fields_em == n_fields - 1) &&
8538 (fields[max_offset_field_id].match_type == RTE_SWX_TABLE_MATCH_LPM))
8539 return RTE_SWX_TABLE_MATCH_LPM;
8541 return RTE_SWX_TABLE_MATCH_WILDCARD;
8545 table_match_fields_check(struct rte_swx_pipeline *p,
8546 struct rte_swx_pipeline_table_params *params,
8547 struct header **header,
8548 uint32_t *min_offset_field_id,
8549 uint32_t *max_offset_field_id)
8551 struct header *h0 = NULL;
8552 struct field *hf, *mf;
8553 uint32_t *offset = NULL, min_offset, max_offset, min_offset_pos, max_offset_pos, i;
8556 /* Return if no match fields. */
8557 if (!params->n_fields) {
8558 if (params->fields) {
8566 /* Memory allocation. */
8567 offset = calloc(params->n_fields, sizeof(uint32_t));
8573 /* Check that all the match fields belong to either the same header or
8576 hf = header_field_parse(p, params->fields[0].name, &h0);
8577 mf = metadata_field_parse(p, params->fields[0].name);
8583 offset[0] = h0 ? hf->offset : mf->offset;
8585 for (i = 1; i < params->n_fields; i++)
8589 hf = header_field_parse(p, params->fields[i].name, &h);
8590 if (!hf || (h->id != h0->id)) {
8595 offset[i] = hf->offset;
8597 mf = metadata_field_parse(p, params->fields[i].name);
8603 offset[i] = mf->offset;
8606 /* Check that there are no duplicated match fields. */
8607 for (i = 0; i < params->n_fields; i++) {
8610 for (j = 0; j < i; j++)
8611 if (offset[j] == offset[i]) {
8617 /* Find the min and max offset fields. */
8618 min_offset = offset[0];
8619 max_offset = offset[0];
8623 for (i = 1; i < params->n_fields; i++) {
8624 if (offset[i] < min_offset) {
8625 min_offset = offset[i];
8629 if (offset[i] > max_offset) {
8630 max_offset = offset[i];
8639 if (min_offset_field_id)
8640 *min_offset_field_id = min_offset_pos;
8642 if (max_offset_field_id)
8643 *max_offset_field_id = max_offset_pos;
8651 rte_swx_pipeline_table_config(struct rte_swx_pipeline *p,
8653 struct rte_swx_pipeline_table_params *params,
8654 const char *recommended_table_type_name,
8658 struct table_type *type;
8660 struct action *default_action;
8661 struct header *header = NULL;
8662 uint32_t action_data_size_max = 0, min_offset_field_id = 0, max_offset_field_id = 0, i;
8667 CHECK_NAME(name, EINVAL);
8668 CHECK(!table_find(p, name), EEXIST);
8670 CHECK(params, EINVAL);
8673 status = table_match_fields_check(p,
8676 &min_offset_field_id,
8677 &max_offset_field_id);
8681 /* Action checks. */
8682 CHECK(params->n_actions, EINVAL);
8683 CHECK(params->action_names, EINVAL);
8684 for (i = 0; i < params->n_actions; i++) {
8685 const char *action_name = params->action_names[i];
8687 uint32_t action_data_size;
8689 CHECK_NAME(action_name, EINVAL);
8691 a = action_find(p, action_name);
8694 action_data_size = a->st ? a->st->n_bits / 8 : 0;
8695 if (action_data_size > action_data_size_max)
8696 action_data_size_max = action_data_size;
8699 CHECK_NAME(params->default_action_name, EINVAL);
8700 for (i = 0; i < p->n_actions; i++)
8701 if (!strcmp(params->action_names[i],
8702 params->default_action_name))
8704 CHECK(i < params->n_actions, EINVAL);
8705 default_action = action_find(p, params->default_action_name);
8706 CHECK((default_action->st && params->default_action_data) ||
8707 !params->default_action_data, EINVAL);
8709 /* Table type checks. */
8710 if (recommended_table_type_name)
8711 CHECK_NAME(recommended_table_type_name, EINVAL);
8713 if (params->n_fields) {
8714 enum rte_swx_table_match_type match_type;
8716 match_type = table_match_type_resolve(params->fields,
8718 max_offset_field_id);
8719 type = table_type_resolve(p,
8720 recommended_table_type_name,
8722 CHECK(type, EINVAL);
8727 /* Memory allocation. */
8728 t = calloc(1, sizeof(struct table));
8731 t->fields = calloc(params->n_fields, sizeof(struct match_field));
8737 t->actions = calloc(params->n_actions, sizeof(struct action *));
8744 if (action_data_size_max) {
8745 t->default_action_data = calloc(1, action_data_size_max);
8746 if (!t->default_action_data) {
8754 /* Node initialization. */
8755 strcpy(t->name, name);
8756 if (args && args[0])
8757 strcpy(t->args, args);
8760 for (i = 0; i < params->n_fields; i++) {
8761 struct rte_swx_match_field_params *field = ¶ms->fields[i];
8762 struct match_field *f = &t->fields[i];
8764 f->match_type = field->match_type;
8766 header_field_parse(p, field->name, NULL) :
8767 metadata_field_parse(p, field->name);
8769 t->n_fields = params->n_fields;
8772 for (i = 0; i < params->n_actions; i++)
8773 t->actions[i] = action_find(p, params->action_names[i]);
8774 t->default_action = default_action;
8775 if (default_action->st)
8776 memcpy(t->default_action_data,
8777 params->default_action_data,
8778 default_action->st->n_bits / 8);
8779 t->n_actions = params->n_actions;
8780 t->default_action_is_const = params->default_action_is_const;
8781 t->action_data_size_max = action_data_size_max;
8784 t->id = p->n_tables;
8786 /* Node add to tailq. */
8787 TAILQ_INSERT_TAIL(&p->tables, t, node);
8793 static struct rte_swx_table_params *
8794 table_params_get(struct table *table)
8796 struct rte_swx_table_params *params;
8797 struct field *first, *last;
8799 uint32_t key_size, key_offset, action_data_size, i;
8801 /* Memory allocation. */
8802 params = calloc(1, sizeof(struct rte_swx_table_params));
8806 /* Find first (smallest offset) and last (biggest offset) match fields. */
8807 first = table->fields[0].field;
8808 last = table->fields[0].field;
8810 for (i = 0; i < table->n_fields; i++) {
8811 struct field *f = table->fields[i].field;
8813 if (f->offset < first->offset)
8816 if (f->offset > last->offset)
8820 /* Key offset and size. */
8821 key_offset = first->offset / 8;
8822 key_size = (last->offset + last->n_bits - first->offset) / 8;
8824 /* Memory allocation. */
8825 key_mask = calloc(1, key_size);
8832 for (i = 0; i < table->n_fields; i++) {
8833 struct field *f = table->fields[i].field;
8834 uint32_t start = (f->offset - first->offset) / 8;
8835 size_t size = f->n_bits / 8;
8837 memset(&key_mask[start], 0xFF, size);
8840 /* Action data size. */
8841 action_data_size = 0;
8842 for (i = 0; i < table->n_actions; i++) {
8843 struct action *action = table->actions[i];
8844 uint32_t ads = action->st ? action->st->n_bits / 8 : 0;
8846 if (ads > action_data_size)
8847 action_data_size = ads;
8851 params->match_type = table->type->match_type;
8852 params->key_size = key_size;
8853 params->key_offset = key_offset;
8854 params->key_mask0 = key_mask;
8855 params->action_data_size = action_data_size;
8856 params->n_keys_max = table->size;
8862 table_params_free(struct rte_swx_table_params *params)
8867 free(params->key_mask0);
8872 table_state_build(struct rte_swx_pipeline *p)
8874 struct table *table;
8876 p->table_state = calloc(p->n_tables,
8877 sizeof(struct rte_swx_table_state));
8878 CHECK(p->table_state, ENOMEM);
8880 TAILQ_FOREACH(table, &p->tables, node) {
8881 struct rte_swx_table_state *ts = &p->table_state[table->id];
8884 struct rte_swx_table_params *params;
8887 params = table_params_get(table);
8888 CHECK(params, ENOMEM);
8890 ts->obj = table->type->ops.create(params,
8895 table_params_free(params);
8896 CHECK(ts->obj, ENODEV);
8899 /* ts->default_action_data. */
8900 if (table->action_data_size_max) {
8901 ts->default_action_data =
8902 malloc(table->action_data_size_max);
8903 CHECK(ts->default_action_data, ENOMEM);
8905 memcpy(ts->default_action_data,
8906 table->default_action_data,
8907 table->action_data_size_max);
8910 /* ts->default_action_id. */
8911 ts->default_action_id = table->default_action->id;
8918 table_state_build_free(struct rte_swx_pipeline *p)
8922 if (!p->table_state)
8925 for (i = 0; i < p->n_tables; i++) {
8926 struct rte_swx_table_state *ts = &p->table_state[i];
8927 struct table *table = table_find_by_id(p, i);
8930 if (table->type && ts->obj)
8931 table->type->ops.free(ts->obj);
8933 /* ts->default_action_data. */
8934 free(ts->default_action_data);
8937 free(p->table_state);
8938 p->table_state = NULL;
8942 table_state_free(struct rte_swx_pipeline *p)
8944 table_state_build_free(p);
8948 table_stub_lkp(void *table __rte_unused,
8949 void *mailbox __rte_unused,
8950 uint8_t **key __rte_unused,
8951 uint64_t *action_id __rte_unused,
8952 uint8_t **action_data __rte_unused,
8956 return 1; /* DONE. */
8960 table_build(struct rte_swx_pipeline *p)
8964 /* Per pipeline: table statistics. */
8965 p->table_stats = calloc(p->n_tables, sizeof(struct table_statistics));
8966 CHECK(p->table_stats, ENOMEM);
8968 for (i = 0; i < p->n_tables; i++) {
8969 p->table_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
8970 CHECK(p->table_stats[i].n_pkts_action, ENOMEM);
8973 /* Per thread: table runt-time. */
8974 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
8975 struct thread *t = &p->threads[i];
8976 struct table *table;
8978 t->tables = calloc(p->n_tables, sizeof(struct table_runtime));
8979 CHECK(t->tables, ENOMEM);
8981 TAILQ_FOREACH(table, &p->tables, node) {
8982 struct table_runtime *r = &t->tables[table->id];
8987 size = table->type->ops.mailbox_size_get();
8990 r->func = table->type->ops.lkp;
8994 r->mailbox = calloc(1, size);
8995 CHECK(r->mailbox, ENOMEM);
8999 r->key = table->header ?
9000 &t->structs[table->header->struct_id] :
9001 &t->structs[p->metadata_struct_id];
9003 r->func = table_stub_lkp;
9012 table_build_free(struct rte_swx_pipeline *p)
9016 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9017 struct thread *t = &p->threads[i];
9023 for (j = 0; j < p->n_tables; j++) {
9024 struct table_runtime *r = &t->tables[j];
9033 if (p->table_stats) {
9034 for (i = 0; i < p->n_tables; i++)
9035 free(p->table_stats[i].n_pkts_action);
9037 free(p->table_stats);
9042 table_free(struct rte_swx_pipeline *p)
9044 table_build_free(p);
9050 elem = TAILQ_FIRST(&p->tables);
9054 TAILQ_REMOVE(&p->tables, elem, node);
9056 free(elem->actions);
9057 free(elem->default_action_data);
9063 struct table_type *elem;
9065 elem = TAILQ_FIRST(&p->table_types);
9069 TAILQ_REMOVE(&p->table_types, elem, node);
9077 static struct regarray *
9078 regarray_find(struct rte_swx_pipeline *p, const char *name)
9080 struct regarray *elem;
9082 TAILQ_FOREACH(elem, &p->regarrays, node)
9083 if (!strcmp(elem->name, name))
9089 static struct regarray *
9090 regarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9092 struct regarray *elem = NULL;
9094 TAILQ_FOREACH(elem, &p->regarrays, node)
9102 rte_swx_pipeline_regarray_config(struct rte_swx_pipeline *p,
9111 CHECK_NAME(name, EINVAL);
9112 CHECK(!regarray_find(p, name), EEXIST);
9114 CHECK(size, EINVAL);
9115 size = rte_align32pow2(size);
9117 /* Memory allocation. */
9118 r = calloc(1, sizeof(struct regarray));
9121 /* Node initialization. */
9122 strcpy(r->name, name);
9123 r->init_val = init_val;
9125 r->id = p->n_regarrays;
9127 /* Node add to tailq. */
9128 TAILQ_INSERT_TAIL(&p->regarrays, r, node);
9135 regarray_build(struct rte_swx_pipeline *p)
9137 struct regarray *regarray;
9139 if (!p->n_regarrays)
9142 p->regarray_runtime = calloc(p->n_regarrays, sizeof(struct regarray_runtime));
9143 CHECK(p->regarray_runtime, ENOMEM);
9145 TAILQ_FOREACH(regarray, &p->regarrays, node) {
9146 struct regarray_runtime *r = &p->regarray_runtime[regarray->id];
9149 r->regarray = env_malloc(regarray->size * sizeof(uint64_t),
9150 RTE_CACHE_LINE_SIZE,
9152 CHECK(r->regarray, ENOMEM);
9154 if (regarray->init_val)
9155 for (i = 0; i < regarray->size; i++)
9156 r->regarray[i] = regarray->init_val;
9158 r->size_mask = regarray->size - 1;
9165 regarray_build_free(struct rte_swx_pipeline *p)
9169 if (!p->regarray_runtime)
9172 for (i = 0; i < p->n_regarrays; i++) {
9173 struct regarray *regarray = regarray_find_by_id(p, i);
9174 struct regarray_runtime *r = &p->regarray_runtime[i];
9176 env_free(r->regarray, regarray->size * sizeof(uint64_t));
9179 free(p->regarray_runtime);
9180 p->regarray_runtime = NULL;
9184 regarray_free(struct rte_swx_pipeline *p)
9186 regarray_build_free(p);
9189 struct regarray *elem;
9191 elem = TAILQ_FIRST(&p->regarrays);
9195 TAILQ_REMOVE(&p->regarrays, elem, node);
9203 static struct meter_profile *
9204 meter_profile_find(struct rte_swx_pipeline *p, const char *name)
9206 struct meter_profile *elem;
9208 TAILQ_FOREACH(elem, &p->meter_profiles, node)
9209 if (!strcmp(elem->name, name))
9215 static struct metarray *
9216 metarray_find(struct rte_swx_pipeline *p, const char *name)
9218 struct metarray *elem;
9220 TAILQ_FOREACH(elem, &p->metarrays, node)
9221 if (!strcmp(elem->name, name))
9227 static struct metarray *
9228 metarray_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
9230 struct metarray *elem = NULL;
9232 TAILQ_FOREACH(elem, &p->metarrays, node)
9240 rte_swx_pipeline_metarray_config(struct rte_swx_pipeline *p,
9248 CHECK_NAME(name, EINVAL);
9249 CHECK(!metarray_find(p, name), EEXIST);
9251 CHECK(size, EINVAL);
9252 size = rte_align32pow2(size);
9254 /* Memory allocation. */
9255 m = calloc(1, sizeof(struct metarray));
9258 /* Node initialization. */
9259 strcpy(m->name, name);
9261 m->id = p->n_metarrays;
9263 /* Node add to tailq. */
9264 TAILQ_INSERT_TAIL(&p->metarrays, m, node);
9270 struct meter_profile meter_profile_default = {
9279 .cir_bytes_per_period = 1,
9281 .pir_bytes_per_period = 1,
9288 meter_init(struct meter *m)
9290 memset(m, 0, sizeof(struct meter));
9291 rte_meter_trtcm_config(&m->m, &meter_profile_default.profile);
9292 m->profile = &meter_profile_default;
9293 m->color_mask = RTE_COLOR_GREEN;
9295 meter_profile_default.n_users++;
9299 metarray_build(struct rte_swx_pipeline *p)
9303 if (!p->n_metarrays)
9306 p->metarray_runtime = calloc(p->n_metarrays, sizeof(struct metarray_runtime));
9307 CHECK(p->metarray_runtime, ENOMEM);
9309 TAILQ_FOREACH(m, &p->metarrays, node) {
9310 struct metarray_runtime *r = &p->metarray_runtime[m->id];
9313 r->metarray = env_malloc(m->size * sizeof(struct meter),
9314 RTE_CACHE_LINE_SIZE,
9316 CHECK(r->metarray, ENOMEM);
9318 for (i = 0; i < m->size; i++)
9319 meter_init(&r->metarray[i]);
9321 r->size_mask = m->size - 1;
9328 metarray_build_free(struct rte_swx_pipeline *p)
9332 if (!p->metarray_runtime)
9335 for (i = 0; i < p->n_metarrays; i++) {
9336 struct metarray *m = metarray_find_by_id(p, i);
9337 struct metarray_runtime *r = &p->metarray_runtime[i];
9339 env_free(r->metarray, m->size * sizeof(struct meter));
9342 free(p->metarray_runtime);
9343 p->metarray_runtime = NULL;
9347 metarray_free(struct rte_swx_pipeline *p)
9349 metarray_build_free(p);
9353 struct metarray *elem;
9355 elem = TAILQ_FIRST(&p->metarrays);
9359 TAILQ_REMOVE(&p->metarrays, elem, node);
9363 /* Meter profiles. */
9365 struct meter_profile *elem;
9367 elem = TAILQ_FIRST(&p->meter_profiles);
9371 TAILQ_REMOVE(&p->meter_profiles, elem, node);
9380 rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
9382 struct rte_swx_pipeline *pipeline;
9384 /* Check input parameters. */
9387 /* Memory allocation. */
9388 pipeline = calloc(1, sizeof(struct rte_swx_pipeline));
9389 CHECK(pipeline, ENOMEM);
9391 /* Initialization. */
9392 TAILQ_INIT(&pipeline->struct_types);
9393 TAILQ_INIT(&pipeline->port_in_types);
9394 TAILQ_INIT(&pipeline->ports_in);
9395 TAILQ_INIT(&pipeline->port_out_types);
9396 TAILQ_INIT(&pipeline->ports_out);
9397 TAILQ_INIT(&pipeline->extern_types);
9398 TAILQ_INIT(&pipeline->extern_objs);
9399 TAILQ_INIT(&pipeline->extern_funcs);
9400 TAILQ_INIT(&pipeline->headers);
9401 TAILQ_INIT(&pipeline->actions);
9402 TAILQ_INIT(&pipeline->table_types);
9403 TAILQ_INIT(&pipeline->tables);
9404 TAILQ_INIT(&pipeline->regarrays);
9405 TAILQ_INIT(&pipeline->meter_profiles);
9406 TAILQ_INIT(&pipeline->metarrays);
9408 pipeline->n_structs = 1; /* Struct 0 is reserved for action_data. */
9409 pipeline->numa_node = numa_node;
9416 rte_swx_pipeline_free(struct rte_swx_pipeline *p)
9421 free(p->instructions);
9425 table_state_free(p);
9430 extern_func_free(p);
9440 rte_swx_pipeline_instructions_config(struct rte_swx_pipeline *p,
9441 const char **instructions,
9442 uint32_t n_instructions)
9447 err = instruction_config(p, NULL, instructions, n_instructions);
9451 /* Thread instruction pointer reset. */
9452 for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
9453 struct thread *t = &p->threads[i];
9455 thread_ip_reset(p, t);
9462 rte_swx_pipeline_build(struct rte_swx_pipeline *p)
9467 CHECK(p->build_done == 0, EEXIST);
9469 status = port_in_build(p);
9473 status = port_out_build(p);
9477 status = struct_build(p);
9481 status = extern_obj_build(p);
9485 status = extern_func_build(p);
9489 status = header_build(p);
9493 status = metadata_build(p);
9497 status = action_build(p);
9501 status = table_build(p);
9505 status = table_state_build(p);
9509 status = regarray_build(p);
9513 status = metarray_build(p);
9521 metarray_build_free(p);
9522 regarray_build_free(p);
9523 table_state_build_free(p);
9524 table_build_free(p);
9525 action_build_free(p);
9526 metadata_build_free(p);
9527 header_build_free(p);
9528 extern_func_build_free(p);
9529 extern_obj_build_free(p);
9530 port_out_build_free(p);
9531 port_in_build_free(p);
9532 struct_build_free(p);
9538 rte_swx_pipeline_run(struct rte_swx_pipeline *p, uint32_t n_instructions)
9542 for (i = 0; i < n_instructions; i++)
9547 rte_swx_pipeline_flush(struct rte_swx_pipeline *p)
9551 for (i = 0; i < p->n_ports_out; i++) {
9552 struct port_out_runtime *port = &p->out[i];
9555 port->flush(port->obj);
9563 rte_swx_ctl_pipeline_info_get(struct rte_swx_pipeline *p,
9564 struct rte_swx_ctl_pipeline_info *pipeline)
9566 struct action *action;
9567 struct table *table;
9568 uint32_t n_actions = 0, n_tables = 0;
9570 if (!p || !pipeline)
9573 TAILQ_FOREACH(action, &p->actions, node)
9576 TAILQ_FOREACH(table, &p->tables, node)
9579 pipeline->n_ports_in = p->n_ports_in;
9580 pipeline->n_ports_out = p->n_ports_out;
9581 pipeline->n_actions = n_actions;
9582 pipeline->n_tables = n_tables;
9583 pipeline->n_regarrays = p->n_regarrays;
9584 pipeline->n_metarrays = p->n_metarrays;
9590 rte_swx_ctl_pipeline_numa_node_get(struct rte_swx_pipeline *p, int *numa_node)
9592 if (!p || !numa_node)
9595 *numa_node = p->numa_node;
9600 rte_swx_ctl_action_info_get(struct rte_swx_pipeline *p,
9602 struct rte_swx_ctl_action_info *action)
9604 struct action *a = NULL;
9606 if (!p || (action_id >= p->n_actions) || !action)
9609 a = action_find_by_id(p, action_id);
9613 strcpy(action->name, a->name);
9614 action->n_args = a->st ? a->st->n_fields : 0;
9619 rte_swx_ctl_action_arg_info_get(struct rte_swx_pipeline *p,
9621 uint32_t action_arg_id,
9622 struct rte_swx_ctl_action_arg_info *action_arg)
9624 struct action *a = NULL;
9625 struct field *arg = NULL;
9627 if (!p || (action_id >= p->n_actions) || !action_arg)
9630 a = action_find_by_id(p, action_id);
9631 if (!a || !a->st || (action_arg_id >= a->st->n_fields))
9634 arg = &a->st->fields[action_arg_id];
9635 strcpy(action_arg->name, arg->name);
9636 action_arg->n_bits = arg->n_bits;
9642 rte_swx_ctl_table_info_get(struct rte_swx_pipeline *p,
9644 struct rte_swx_ctl_table_info *table)
9646 struct table *t = NULL;
9651 t = table_find_by_id(p, table_id);
9655 strcpy(table->name, t->name);
9656 strcpy(table->args, t->args);
9657 table->n_match_fields = t->n_fields;
9658 table->n_actions = t->n_actions;
9659 table->default_action_is_const = t->default_action_is_const;
9660 table->size = t->size;
9665 rte_swx_ctl_table_match_field_info_get(struct rte_swx_pipeline *p,
9667 uint32_t match_field_id,
9668 struct rte_swx_ctl_table_match_field_info *match_field)
9671 struct match_field *f;
9673 if (!p || (table_id >= p->n_tables) || !match_field)
9676 t = table_find_by_id(p, table_id);
9677 if (!t || (match_field_id >= t->n_fields))
9680 f = &t->fields[match_field_id];
9681 match_field->match_type = f->match_type;
9682 match_field->is_header = t->header ? 1 : 0;
9683 match_field->n_bits = f->field->n_bits;
9684 match_field->offset = f->field->offset;
9690 rte_swx_ctl_table_action_info_get(struct rte_swx_pipeline *p,
9692 uint32_t table_action_id,
9693 struct rte_swx_ctl_table_action_info *table_action)
9697 if (!p || (table_id >= p->n_tables) || !table_action)
9700 t = table_find_by_id(p, table_id);
9701 if (!t || (table_action_id >= t->n_actions))
9704 table_action->action_id = t->actions[table_action_id]->id;
9710 rte_swx_ctl_table_ops_get(struct rte_swx_pipeline *p,
9712 struct rte_swx_table_ops *table_ops,
9717 if (!p || (table_id >= p->n_tables))
9720 t = table_find_by_id(p, table_id);
9726 memcpy(table_ops, &t->type->ops, sizeof(*table_ops));
9736 rte_swx_pipeline_table_state_get(struct rte_swx_pipeline *p,
9737 struct rte_swx_table_state **table_state)
9739 if (!p || !table_state || !p->build_done)
9742 *table_state = p->table_state;
9747 rte_swx_pipeline_table_state_set(struct rte_swx_pipeline *p,
9748 struct rte_swx_table_state *table_state)
9750 if (!p || !table_state || !p->build_done)
9753 p->table_state = table_state;
9758 rte_swx_ctl_pipeline_port_in_stats_read(struct rte_swx_pipeline *p,
9760 struct rte_swx_port_in_stats *stats)
9762 struct port_in *port;
9767 port = port_in_find(p, port_id);
9771 port->type->ops.stats_read(port->obj, stats);
9776 rte_swx_ctl_pipeline_port_out_stats_read(struct rte_swx_pipeline *p,
9778 struct rte_swx_port_out_stats *stats)
9780 struct port_out *port;
9785 port = port_out_find(p, port_id);
9789 port->type->ops.stats_read(port->obj, stats);
9794 rte_swx_ctl_pipeline_table_stats_read(struct rte_swx_pipeline *p,
9795 const char *table_name,
9796 struct rte_swx_table_stats *stats)
9798 struct table *table;
9799 struct table_statistics *table_stats;
9801 if (!p || !table_name || !table_name[0] || !stats || !stats->n_pkts_action)
9804 table = table_find(p, table_name);
9808 table_stats = &p->table_stats[table->id];
9810 memcpy(&stats->n_pkts_action,
9811 &table_stats->n_pkts_action,
9812 p->n_actions * sizeof(uint64_t));
9814 stats->n_pkts_hit = table_stats->n_pkts_hit[1];
9815 stats->n_pkts_miss = table_stats->n_pkts_hit[0];
9821 rte_swx_ctl_regarray_info_get(struct rte_swx_pipeline *p,
9822 uint32_t regarray_id,
9823 struct rte_swx_ctl_regarray_info *regarray)
9827 if (!p || !regarray)
9830 r = regarray_find_by_id(p, regarray_id);
9834 strcpy(regarray->name, r->name);
9835 regarray->size = r->size;
9840 rte_swx_ctl_pipeline_regarray_read(struct rte_swx_pipeline *p,
9841 const char *regarray_name,
9842 uint32_t regarray_index,
9845 struct regarray *regarray;
9846 struct regarray_runtime *r;
9848 if (!p || !regarray_name || !value)
9851 regarray = regarray_find(p, regarray_name);
9852 if (!regarray || (regarray_index >= regarray->size))
9855 r = &p->regarray_runtime[regarray->id];
9856 *value = r->regarray[regarray_index];
9861 rte_swx_ctl_pipeline_regarray_write(struct rte_swx_pipeline *p,
9862 const char *regarray_name,
9863 uint32_t regarray_index,
9866 struct regarray *regarray;
9867 struct regarray_runtime *r;
9869 if (!p || !regarray_name)
9872 regarray = regarray_find(p, regarray_name);
9873 if (!regarray || (regarray_index >= regarray->size))
9876 r = &p->regarray_runtime[regarray->id];
9877 r->regarray[regarray_index] = value;
9882 rte_swx_ctl_metarray_info_get(struct rte_swx_pipeline *p,
9883 uint32_t metarray_id,
9884 struct rte_swx_ctl_metarray_info *metarray)
9888 if (!p || !metarray)
9891 m = metarray_find_by_id(p, metarray_id);
9895 strcpy(metarray->name, m->name);
9896 metarray->size = m->size;
9901 rte_swx_ctl_meter_profile_add(struct rte_swx_pipeline *p,
9903 struct rte_meter_trtcm_params *params)
9905 struct meter_profile *mp;
9909 CHECK_NAME(name, EINVAL);
9910 CHECK(params, EINVAL);
9911 CHECK(!meter_profile_find(p, name), EEXIST);
9913 /* Node allocation. */
9914 mp = calloc(1, sizeof(struct meter_profile));
9917 /* Node initialization. */
9918 strcpy(mp->name, name);
9919 memcpy(&mp->params, params, sizeof(struct rte_meter_trtcm_params));
9920 status = rte_meter_trtcm_profile_config(&mp->profile, params);
9926 /* Node add to tailq. */
9927 TAILQ_INSERT_TAIL(&p->meter_profiles, mp, node);
9933 rte_swx_ctl_meter_profile_delete(struct rte_swx_pipeline *p,
9936 struct meter_profile *mp;
9939 CHECK_NAME(name, EINVAL);
9941 mp = meter_profile_find(p, name);
9943 CHECK(!mp->n_users, EBUSY);
9945 /* Remove node from tailq. */
9946 TAILQ_REMOVE(&p->meter_profiles, mp, node);
9953 rte_swx_ctl_meter_reset(struct rte_swx_pipeline *p,
9954 const char *metarray_name,
9955 uint32_t metarray_index)
9957 struct meter_profile *mp_old;
9958 struct metarray *metarray;
9959 struct metarray_runtime *metarray_runtime;
9963 CHECK_NAME(metarray_name, EINVAL);
9965 metarray = metarray_find(p, metarray_name);
9966 CHECK(metarray, EINVAL);
9967 CHECK(metarray_index < metarray->size, EINVAL);
9969 metarray_runtime = &p->metarray_runtime[metarray->id];
9970 m = &metarray_runtime->metarray[metarray_index];
9971 mp_old = m->profile;
9981 rte_swx_ctl_meter_set(struct rte_swx_pipeline *p,
9982 const char *metarray_name,
9983 uint32_t metarray_index,
9984 const char *profile_name)
9986 struct meter_profile *mp, *mp_old;
9987 struct metarray *metarray;
9988 struct metarray_runtime *metarray_runtime;
9992 CHECK_NAME(metarray_name, EINVAL);
9994 metarray = metarray_find(p, metarray_name);
9995 CHECK(metarray, EINVAL);
9996 CHECK(metarray_index < metarray->size, EINVAL);
9998 mp = meter_profile_find(p, profile_name);
10001 metarray_runtime = &p->metarray_runtime[metarray->id];
10002 m = &metarray_runtime->metarray[metarray_index];
10003 mp_old = m->profile;
10005 memset(m, 0, sizeof(struct meter));
10006 rte_meter_trtcm_config(&m->m, &mp->profile);
10008 m->color_mask = RTE_COLORS;
10017 rte_swx_ctl_meter_stats_read(struct rte_swx_pipeline *p,
10018 const char *metarray_name,
10019 uint32_t metarray_index,
10020 struct rte_swx_ctl_meter_stats *stats)
10022 struct metarray *metarray;
10023 struct metarray_runtime *metarray_runtime;
10027 CHECK_NAME(metarray_name, EINVAL);
10029 metarray = metarray_find(p, metarray_name);
10030 CHECK(metarray, EINVAL);
10031 CHECK(metarray_index < metarray->size, EINVAL);
10033 CHECK(stats, EINVAL);
10035 metarray_runtime = &p->metarray_runtime[metarray->id];
10036 m = &metarray_runtime->metarray[metarray_index];
10038 memcpy(stats->n_pkts, m->n_pkts, sizeof(m->n_pkts));
10039 memcpy(stats->n_bytes, m->n_bytes, sizeof(m->n_bytes));