1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2021 Intel Corporation
4 #ifndef __INCLUDE_RTE_SWX_PIPELINE_INTERNAL_H__
5 #define __INCLUDE_RTE_SWX_PIPELINE_INTERNAL_H__
11 #include <rte_byteorder.h>
12 #include <rte_common.h>
13 #include <rte_cycles.h>
14 #include <rte_prefetch.h>
15 #include <rte_meter.h>
17 #include <rte_swx_table_selector.h>
18 #include <rte_swx_table_learner.h>
19 #include <rte_swx_pipeline.h>
20 #include <rte_swx_ctl.h>
27 #define TRACE(...) printf(__VA_ARGS__)
35 #define ntoh64(x) rte_be_to_cpu_64(x)
36 #define hton64(x) rte_cpu_to_be_64(x)
42 char name[RTE_SWX_NAME_SIZE];
49 TAILQ_ENTRY(struct_type) node;
50 char name[RTE_SWX_NAME_SIZE];
58 TAILQ_HEAD(struct_type_tailq, struct_type);
64 TAILQ_ENTRY(port_in_type) node;
65 char name[RTE_SWX_NAME_SIZE];
66 struct rte_swx_port_in_ops ops;
69 TAILQ_HEAD(port_in_type_tailq, port_in_type);
72 TAILQ_ENTRY(port_in) node;
73 struct port_in_type *type;
78 TAILQ_HEAD(port_in_tailq, port_in);
80 struct port_in_runtime {
81 rte_swx_port_in_pkt_rx_t pkt_rx;
88 struct port_out_type {
89 TAILQ_ENTRY(port_out_type) node;
90 char name[RTE_SWX_NAME_SIZE];
91 struct rte_swx_port_out_ops ops;
94 TAILQ_HEAD(port_out_type_tailq, port_out_type);
97 TAILQ_ENTRY(port_out) node;
98 struct port_out_type *type;
103 TAILQ_HEAD(port_out_tailq, port_out);
105 struct port_out_runtime {
106 rte_swx_port_out_pkt_tx_t pkt_tx;
107 rte_swx_port_out_pkt_fast_clone_tx_t pkt_fast_clone_tx;
108 rte_swx_port_out_pkt_clone_tx_t pkt_clone_tx;
109 rte_swx_port_out_flush_t flush;
116 struct mirroring_session {
119 uint32_t truncation_length;
125 struct extern_type_member_func {
126 TAILQ_ENTRY(extern_type_member_func) node;
127 char name[RTE_SWX_NAME_SIZE];
128 rte_swx_extern_type_member_func_t func;
132 TAILQ_HEAD(extern_type_member_func_tailq, extern_type_member_func);
135 TAILQ_ENTRY(extern_type) node;
136 char name[RTE_SWX_NAME_SIZE];
137 struct struct_type *mailbox_struct_type;
138 rte_swx_extern_type_constructor_t constructor;
139 rte_swx_extern_type_destructor_t destructor;
140 struct extern_type_member_func_tailq funcs;
144 TAILQ_HEAD(extern_type_tailq, extern_type);
147 TAILQ_ENTRY(extern_obj) node;
148 char name[RTE_SWX_NAME_SIZE];
149 struct extern_type *type;
155 TAILQ_HEAD(extern_obj_tailq, extern_obj);
157 #ifndef RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX
158 #define RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX 8
161 struct extern_obj_runtime {
164 rte_swx_extern_type_member_func_t funcs[RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX];
171 TAILQ_ENTRY(extern_func) node;
172 char name[RTE_SWX_NAME_SIZE];
173 struct struct_type *mailbox_struct_type;
174 rte_swx_extern_func_t func;
179 TAILQ_HEAD(extern_func_tailq, extern_func);
181 struct extern_func_runtime {
183 rte_swx_extern_func_t func;
190 TAILQ_ENTRY(header) node;
191 char name[RTE_SWX_NAME_SIZE];
192 struct struct_type *st;
197 TAILQ_HEAD(header_tailq, header);
199 struct header_runtime {
204 struct header_out_runtime {
214 /* Packet headers are always in Network Byte Order (NBO), i.e. big endian.
215 * Packet meta-data fields are always assumed to be in Host Byte Order (HBO).
216 * Table entry fields can be in either NBO or HBO; they are assumed to be in HBO
217 * when transferred to packet meta-data and in NBO when transferred to packet
221 /* Notation conventions:
222 * -Header field: H = h.header.field (dst/src)
223 * -Meta-data field: M = m.field (dst/src)
224 * -Extern object mailbox field: E = e.field (dst/src)
225 * -Extern function mailbox field: F = f.field (dst/src)
226 * -Table action data field: T = t.field (src only)
227 * -Immediate value: I = 32-bit unsigned value (src only)
230 enum instruction_type {
237 INSTR_TX, /* port_out = M */
238 INSTR_TX_I, /* port_out = I */
242 * mirror slot_id session_id
248 /* extract h.header */
258 /* extract h.header m.last_field_size */
261 /* lookahead h.header */
275 /* validate h.header */
278 /* invalidate h.header */
279 INSTR_HDR_INVALIDATE,
283 * dst = HMEF, src = HMEFTI
285 INSTR_MOV, /* dst = MEF, src = MEFT */
286 INSTR_MOV_MH, /* dst = MEF, src = H */
287 INSTR_MOV_HM, /* dst = H, src = MEFT */
288 INSTR_MOV_HH, /* dst = H, src = H */
289 INSTR_MOV_I, /* dst = HMEF, src = I */
291 /* dma h.header t.field
292 * memcpy(h.header, t.field, sizeof(h.header))
305 * dst = HMEF, src = HMEFTI
307 INSTR_ALU_ADD, /* dst = MEF, src = MEF */
308 INSTR_ALU_ADD_MH, /* dst = MEF, src = H */
309 INSTR_ALU_ADD_HM, /* dst = H, src = MEF */
310 INSTR_ALU_ADD_HH, /* dst = H, src = H */
311 INSTR_ALU_ADD_MI, /* dst = MEF, src = I */
312 INSTR_ALU_ADD_HI, /* dst = H, src = I */
316 * dst = HMEF, src = HMEFTI
318 INSTR_ALU_SUB, /* dst = MEF, src = MEF */
319 INSTR_ALU_SUB_MH, /* dst = MEF, src = H */
320 INSTR_ALU_SUB_HM, /* dst = H, src = MEF */
321 INSTR_ALU_SUB_HH, /* dst = H, src = H */
322 INSTR_ALU_SUB_MI, /* dst = MEF, src = I */
323 INSTR_ALU_SUB_HI, /* dst = H, src = I */
326 * dst = dst '+ src[0:1] '+ src[2:3] '+ ...
327 * dst = H, src = {H, h.header}, '+ = 1's complement addition operator
329 INSTR_ALU_CKADD_FIELD, /* src = H */
330 INSTR_ALU_CKADD_STRUCT20, /* src = h.header, with sizeof(header) = 20 bytes. */
331 INSTR_ALU_CKADD_STRUCT, /* src = h.header, with sizeof(header) any 4-byte multiple. */
335 * dst = H, src = H, '- = 1's complement subtraction operator
337 INSTR_ALU_CKSUB_FIELD,
341 * dst = HMEF, src = HMEFTI
343 INSTR_ALU_AND, /* dst = MEF, src = MEFT */
344 INSTR_ALU_AND_MH, /* dst = MEF, src = H */
345 INSTR_ALU_AND_HM, /* dst = H, src = MEFT */
346 INSTR_ALU_AND_HH, /* dst = H, src = H */
347 INSTR_ALU_AND_I, /* dst = HMEF, src = I */
351 * dst = HMEF, src = HMEFTI
353 INSTR_ALU_OR, /* dst = MEF, src = MEFT */
354 INSTR_ALU_OR_MH, /* dst = MEF, src = H */
355 INSTR_ALU_OR_HM, /* dst = H, src = MEFT */
356 INSTR_ALU_OR_HH, /* dst = H, src = H */
357 INSTR_ALU_OR_I, /* dst = HMEF, src = I */
361 * dst = HMEF, src = HMEFTI
363 INSTR_ALU_XOR, /* dst = MEF, src = MEFT */
364 INSTR_ALU_XOR_MH, /* dst = MEF, src = H */
365 INSTR_ALU_XOR_HM, /* dst = H, src = MEFT */
366 INSTR_ALU_XOR_HH, /* dst = H, src = H */
367 INSTR_ALU_XOR_I, /* dst = HMEF, src = I */
371 * dst = HMEF, src = HMEFTI
373 INSTR_ALU_SHL, /* dst = MEF, src = MEF */
374 INSTR_ALU_SHL_MH, /* dst = MEF, src = H */
375 INSTR_ALU_SHL_HM, /* dst = H, src = MEF */
376 INSTR_ALU_SHL_HH, /* dst = H, src = H */
377 INSTR_ALU_SHL_MI, /* dst = MEF, src = I */
378 INSTR_ALU_SHL_HI, /* dst = H, src = I */
382 * dst = HMEF, src = HMEFTI
384 INSTR_ALU_SHR, /* dst = MEF, src = MEF */
385 INSTR_ALU_SHR_MH, /* dst = MEF, src = H */
386 INSTR_ALU_SHR_HM, /* dst = H, src = MEF */
387 INSTR_ALU_SHR_HH, /* dst = H, src = H */
388 INSTR_ALU_SHR_MI, /* dst = MEF, src = I */
389 INSTR_ALU_SHR_HI, /* dst = H, src = I */
391 /* regprefetch REGARRAY index
392 * prefetch REGARRAY[index]
395 INSTR_REGPREFETCH_RH, /* index = H */
396 INSTR_REGPREFETCH_RM, /* index = MEFT */
397 INSTR_REGPREFETCH_RI, /* index = I */
399 /* regrd dst REGARRAY index
400 * dst = REGARRAY[index]
401 * dst = HMEF, index = HMEFTI
403 INSTR_REGRD_HRH, /* dst = H, index = H */
404 INSTR_REGRD_HRM, /* dst = H, index = MEFT */
405 INSTR_REGRD_HRI, /* dst = H, index = I */
406 INSTR_REGRD_MRH, /* dst = MEF, index = H */
407 INSTR_REGRD_MRM, /* dst = MEF, index = MEFT */
408 INSTR_REGRD_MRI, /* dst = MEF, index = I */
410 /* regwr REGARRAY index src
411 * REGARRAY[index] = src
412 * index = HMEFTI, src = HMEFTI
414 INSTR_REGWR_RHH, /* index = H, src = H */
415 INSTR_REGWR_RHM, /* index = H, src = MEFT */
416 INSTR_REGWR_RHI, /* index = H, src = I */
417 INSTR_REGWR_RMH, /* index = MEFT, src = H */
418 INSTR_REGWR_RMM, /* index = MEFT, src = MEFT */
419 INSTR_REGWR_RMI, /* index = MEFT, src = I */
420 INSTR_REGWR_RIH, /* index = I, src = H */
421 INSTR_REGWR_RIM, /* index = I, src = MEFT */
422 INSTR_REGWR_RII, /* index = I, src = I */
424 /* regadd REGARRAY index src
425 * REGARRAY[index] += src
426 * index = HMEFTI, src = HMEFTI
428 INSTR_REGADD_RHH, /* index = H, src = H */
429 INSTR_REGADD_RHM, /* index = H, src = MEFT */
430 INSTR_REGADD_RHI, /* index = H, src = I */
431 INSTR_REGADD_RMH, /* index = MEFT, src = H */
432 INSTR_REGADD_RMM, /* index = MEFT, src = MEFT */
433 INSTR_REGADD_RMI, /* index = MEFT, src = I */
434 INSTR_REGADD_RIH, /* index = I, src = H */
435 INSTR_REGADD_RIM, /* index = I, src = MEFT */
436 INSTR_REGADD_RII, /* index = I, src = I */
438 /* metprefetch METARRAY index
439 * prefetch METARRAY[index]
442 INSTR_METPREFETCH_H, /* index = H */
443 INSTR_METPREFETCH_M, /* index = MEFT */
444 INSTR_METPREFETCH_I, /* index = I */
446 /* meter METARRAY index length color_in color_out
447 * color_out = meter(METARRAY[index], length, color_in)
448 * index = HMEFTI, length = HMEFT, color_in = MEFTI, color_out = MEF
450 INSTR_METER_HHM, /* index = H, length = H, color_in = MEFT */
451 INSTR_METER_HHI, /* index = H, length = H, color_in = I */
452 INSTR_METER_HMM, /* index = H, length = MEFT, color_in = MEFT */
453 INSTR_METER_HMI, /* index = H, length = MEFT, color_in = I */
454 INSTR_METER_MHM, /* index = MEFT, length = H, color_in = MEFT */
455 INSTR_METER_MHI, /* index = MEFT, length = H, color_in = I */
456 INSTR_METER_MMM, /* index = MEFT, length = MEFT, color_in = MEFT */
457 INSTR_METER_MMI, /* index = MEFT, length = MEFT, color_in = I */
458 INSTR_METER_IHM, /* index = I, length = H, color_in = MEFT */
459 INSTR_METER_IHI, /* index = I, length = H, color_in = I */
460 INSTR_METER_IMM, /* index = I, length = MEFT, color_in = MEFT */
461 INSTR_METER_IMI, /* index = I, length = MEFT, color_in = I */
470 /* learn LEARNER ACTION_NAME [ m.action_first_arg ] */
474 INSTR_LEARNER_FORGET,
476 /* extern e.obj.func */
487 /* jmpv LABEL h.header
488 * Jump if header is valid
492 /* jmpnv LABEL h.header
493 * Jump if header is invalid
498 * Jump if table lookup hit
503 * Jump if table lookup miss
510 INSTR_JMP_ACTION_HIT,
512 /* jmpna LABEL ACTION
513 * Jump if action not run
515 INSTR_JMP_ACTION_MISS,
518 * Jump if a is equal to b
519 * a = HMEFT, b = HMEFTI
521 INSTR_JMP_EQ, /* a = MEFT, b = MEFT */
522 INSTR_JMP_EQ_MH, /* a = MEFT, b = H */
523 INSTR_JMP_EQ_HM, /* a = H, b = MEFT */
524 INSTR_JMP_EQ_HH, /* a = H, b = H */
525 INSTR_JMP_EQ_I, /* (a, b) = (MEFT, I) or (a, b) = (H, I) */
528 * Jump if a is not equal to b
529 * a = HMEFT, b = HMEFTI
531 INSTR_JMP_NEQ, /* a = MEFT, b = MEFT */
532 INSTR_JMP_NEQ_MH, /* a = MEFT, b = H */
533 INSTR_JMP_NEQ_HM, /* a = H, b = MEFT */
534 INSTR_JMP_NEQ_HH, /* a = H, b = H */
535 INSTR_JMP_NEQ_I, /* (a, b) = (MEFT, I) or (a, b) = (H, I) */
538 * Jump if a is less than b
539 * a = HMEFT, b = HMEFTI
541 INSTR_JMP_LT, /* a = MEFT, b = MEFT */
542 INSTR_JMP_LT_MH, /* a = MEFT, b = H */
543 INSTR_JMP_LT_HM, /* a = H, b = MEFT */
544 INSTR_JMP_LT_HH, /* a = H, b = H */
545 INSTR_JMP_LT_MI, /* a = MEFT, b = I */
546 INSTR_JMP_LT_HI, /* a = H, b = I */
549 * Jump if a is greater than b
550 * a = HMEFT, b = HMEFTI
552 INSTR_JMP_GT, /* a = MEFT, b = MEFT */
553 INSTR_JMP_GT_MH, /* a = MEFT, b = H */
554 INSTR_JMP_GT_HM, /* a = H, b = MEFT */
555 INSTR_JMP_GT_HH, /* a = H, b = H */
556 INSTR_JMP_GT_MI, /* a = MEFT, b = I */
557 INSTR_JMP_GT_HI, /* a = H, b = I */
564 /* Start of custom instructions. */
568 struct instr_operand {
589 uint8_t header_id[8];
590 uint8_t struct_id[8];
595 struct instr_hdr_validity {
608 struct instr_extern_obj {
613 struct instr_extern_func {
617 struct instr_dst_src {
618 struct instr_operand dst;
620 struct instr_operand src;
625 struct instr_regarray {
630 struct instr_operand idx;
635 struct instr_operand dstsrc;
645 struct instr_operand idx;
649 struct instr_operand length;
652 struct instr_operand color_in;
653 uint32_t color_in_val;
656 struct instr_operand color_out;
661 uint8_t header_id[8];
662 uint8_t struct_id[8];
673 struct instruction *ip;
676 struct instr_operand a;
682 struct instr_operand b;
688 enum instruction_type type;
691 struct instr_dst_src mirror;
692 struct instr_hdr_validity valid;
693 struct instr_dst_src mov;
694 struct instr_regarray regarray;
695 struct instr_meter meter;
696 struct instr_dma dma;
697 struct instr_dst_src alu;
698 struct instr_table table;
699 struct instr_learn learn;
700 struct instr_extern_obj ext_obj;
701 struct instr_extern_func ext_func;
702 struct instr_jmp jmp;
706 struct instruction_data {
707 char label[RTE_SWX_NAME_SIZE];
708 char jmp_label[RTE_SWX_NAME_SIZE];
709 uint32_t n_users; /* user = jmp instruction to this instruction. */
713 typedef void (*instr_exec_t)(struct rte_swx_pipeline *);
719 (*action_func_t)(struct rte_swx_pipeline *p);
722 TAILQ_ENTRY(action) node;
723 char name[RTE_SWX_NAME_SIZE];
724 struct struct_type *st;
725 int *args_endianness; /* 0 = Host Byte Order (HBO); 1 = Network Byte Order (NBO). */
726 struct instruction *instructions;
727 struct instruction_data *instruction_data;
728 uint32_t n_instructions;
732 TAILQ_HEAD(action_tailq, action);
738 TAILQ_ENTRY(table_type) node;
739 char name[RTE_SWX_NAME_SIZE];
740 enum rte_swx_table_match_type match_type;
741 struct rte_swx_table_ops ops;
744 TAILQ_HEAD(table_type_tailq, table_type);
747 enum rte_swx_table_match_type match_type;
752 TAILQ_ENTRY(table) node;
753 char name[RTE_SWX_NAME_SIZE];
754 char args[RTE_SWX_NAME_SIZE];
755 struct table_type *type; /* NULL when n_fields == 0. */
758 struct match_field *fields;
760 struct header *header; /* Only valid when n_fields > 0. */
763 struct action **actions;
764 struct action *default_action;
765 uint8_t *default_action_data;
767 int default_action_is_const;
768 uint32_t action_data_size_max;
769 int *action_is_for_table_entries;
770 int *action_is_for_default_entry;
776 TAILQ_HEAD(table_tailq, table);
778 struct table_runtime {
779 rte_swx_table_lookup_t func;
784 struct table_statistics {
785 uint64_t n_pkts_hit[2]; /* 0 = Miss, 1 = Hit. */
786 uint64_t *n_pkts_action;
793 TAILQ_ENTRY(selector) node;
794 char name[RTE_SWX_NAME_SIZE];
796 struct field *group_id_field;
797 struct field **selector_fields;
798 uint32_t n_selector_fields;
799 struct header *selector_header;
800 struct field *member_id_field;
802 uint32_t n_groups_max;
803 uint32_t n_members_per_group_max;
808 TAILQ_HEAD(selector_tailq, selector);
810 struct selector_runtime {
812 uint8_t **group_id_buffer;
813 uint8_t **selector_buffer;
814 uint8_t **member_id_buffer;
817 struct selector_statistics {
825 TAILQ_ENTRY(learner) node;
826 char name[RTE_SWX_NAME_SIZE];
829 struct field **fields;
831 struct header *header;
834 struct action **actions;
835 struct action *default_action;
836 uint8_t *default_action_data;
838 int default_action_is_const;
839 uint32_t action_data_size_max;
840 int *action_is_for_table_entries;
841 int *action_is_for_default_entry;
848 TAILQ_HEAD(learner_tailq, learner);
850 struct learner_runtime {
855 struct learner_statistics {
856 uint64_t n_pkts_hit[2]; /* 0 = Miss, 1 = Hit. */
857 uint64_t n_pkts_learn[2]; /* 0 = Learn OK, 1 = Learn error. */
858 uint64_t n_pkts_forget;
859 uint64_t *n_pkts_action;
866 TAILQ_ENTRY(regarray) node;
867 char name[RTE_SWX_NAME_SIZE];
873 TAILQ_HEAD(regarray_tailq, regarray);
875 struct regarray_runtime {
883 struct meter_profile {
884 TAILQ_ENTRY(meter_profile) node;
885 char name[RTE_SWX_NAME_SIZE];
886 struct rte_meter_trtcm_params params;
887 struct rte_meter_trtcm_profile profile;
891 TAILQ_HEAD(meter_profile_tailq, meter_profile);
894 TAILQ_ENTRY(metarray) node;
895 char name[RTE_SWX_NAME_SIZE];
900 TAILQ_HEAD(metarray_tailq, metarray);
903 struct rte_meter_trtcm m;
904 struct meter_profile *profile;
905 enum rte_color color_mask;
908 uint64_t n_pkts[RTE_COLORS];
909 uint64_t n_bytes[RTE_COLORS];
912 struct metarray_runtime {
913 struct meter *metarray;
922 struct rte_swx_pkt pkt;
924 uint32_t *mirroring_slots;
925 uint64_t mirroring_slots_mask;
930 /* Packet headers. */
931 struct header_runtime *headers; /* Extracted or generated headers. */
932 struct header_out_runtime *headers_out; /* Emitted headers. */
933 uint8_t *header_storage;
934 uint8_t *header_out_storage;
935 uint64_t valid_headers;
936 uint32_t n_headers_out;
938 /* Packet meta-data. */
942 struct table_runtime *tables;
943 struct selector_runtime *selectors;
944 struct learner_runtime *learners;
945 struct rte_swx_table_state *table_state;
947 int hit; /* 0 = Miss, 1 = Hit. */
951 /* Extern objects and functions. */
952 struct extern_obj_runtime *extern_objs;
953 struct extern_func_runtime *extern_funcs;
956 struct instruction *ip;
957 struct instruction *ret;
960 #define MASK64_BIT_GET(mask, pos) ((mask) & (1LLU << (pos)))
961 #define MASK64_BIT_SET(mask, pos) ((mask) | (1LLU << (pos)))
962 #define MASK64_BIT_CLR(mask, pos) ((mask) & ~(1LLU << (pos)))
964 #define HEADER_VALID(thread, header_id) \
965 MASK64_BIT_GET((thread)->valid_headers, header_id)
967 static inline uint64_t
968 instr_operand_hbo(struct thread *t, const struct instr_operand *x)
970 uint8_t *x_struct = t->structs[x->struct_id];
971 uint64_t *x64_ptr = (uint64_t *)&x_struct[x->offset];
972 uint64_t x64 = *x64_ptr;
973 uint64_t x64_mask = UINT64_MAX >> (64 - x->n_bits);
975 return x64 & x64_mask;
978 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
980 static inline uint64_t
981 instr_operand_nbo(struct thread *t, const struct instr_operand *x)
983 uint8_t *x_struct = t->structs[x->struct_id];
984 uint64_t *x64_ptr = (uint64_t *)&x_struct[x->offset];
985 uint64_t x64 = *x64_ptr;
987 return ntoh64(x64) >> (64 - x->n_bits);
992 #define instr_operand_nbo instr_operand_hbo
996 #define ALU(thread, ip, operator) \
998 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
999 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
1000 uint64_t dst64 = *dst64_ptr; \
1001 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
1002 uint64_t dst = dst64 & dst64_mask; \
1004 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
1005 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
1006 uint64_t src64 = *src64_ptr; \
1007 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->alu.src.n_bits); \
1008 uint64_t src = src64 & src64_mask; \
1010 uint64_t result = dst operator src; \
1012 *dst64_ptr = (dst64 & ~dst64_mask) | (result & dst64_mask); \
1015 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1017 #define ALU_MH(thread, ip, operator) \
1019 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
1020 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
1021 uint64_t dst64 = *dst64_ptr; \
1022 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
1023 uint64_t dst = dst64 & dst64_mask; \
1025 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
1026 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
1027 uint64_t src64 = *src64_ptr; \
1028 uint64_t src = ntoh64(src64) >> (64 - (ip)->alu.src.n_bits); \
1030 uint64_t result = dst operator src; \
1032 *dst64_ptr = (dst64 & ~dst64_mask) | (result & dst64_mask); \
1035 #define ALU_HM(thread, ip, operator) \
1037 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
1038 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
1039 uint64_t dst64 = *dst64_ptr; \
1040 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
1041 uint64_t dst = ntoh64(dst64) >> (64 - (ip)->alu.dst.n_bits); \
1043 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
1044 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
1045 uint64_t src64 = *src64_ptr; \
1046 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->alu.src.n_bits); \
1047 uint64_t src = src64 & src64_mask; \
1049 uint64_t result = dst operator src; \
1050 result = hton64(result << (64 - (ip)->alu.dst.n_bits)); \
1052 *dst64_ptr = (dst64 & ~dst64_mask) | result; \
1055 #define ALU_HM_FAST(thread, ip, operator) \
1057 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
1058 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
1059 uint64_t dst64 = *dst64_ptr; \
1060 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
1061 uint64_t dst = dst64 & dst64_mask; \
1063 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
1064 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
1065 uint64_t src64 = *src64_ptr; \
1066 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->alu.src.n_bits); \
1067 uint64_t src = hton64(src64 & src64_mask) >> (64 - (ip)->alu.dst.n_bits); \
1069 uint64_t result = dst operator src; \
1071 *dst64_ptr = (dst64 & ~dst64_mask) | result; \
1074 #define ALU_HH(thread, ip, operator) \
1076 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
1077 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
1078 uint64_t dst64 = *dst64_ptr; \
1079 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
1080 uint64_t dst = ntoh64(dst64) >> (64 - (ip)->alu.dst.n_bits); \
1082 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
1083 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
1084 uint64_t src64 = *src64_ptr; \
1085 uint64_t src = ntoh64(src64) >> (64 - (ip)->alu.src.n_bits); \
1087 uint64_t result = dst operator src; \
1088 result = hton64(result << (64 - (ip)->alu.dst.n_bits)); \
1090 *dst64_ptr = (dst64 & ~dst64_mask) | result; \
1093 #define ALU_HH_FAST(thread, ip, operator) \
1095 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
1096 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
1097 uint64_t dst64 = *dst64_ptr; \
1098 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
1099 uint64_t dst = dst64 & dst64_mask; \
1101 uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id]; \
1102 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset]; \
1103 uint64_t src64 = *src64_ptr; \
1104 uint64_t src = (src64 << (64 - (ip)->alu.src.n_bits)) >> (64 - (ip)->alu.dst.n_bits); \
1106 uint64_t result = dst operator src; \
1108 *dst64_ptr = (dst64 & ~dst64_mask) | result; \
1115 #define ALU_HM_FAST ALU
1117 #define ALU_HH_FAST ALU
1121 #define ALU_I(thread, ip, operator) \
1123 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
1124 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
1125 uint64_t dst64 = *dst64_ptr; \
1126 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
1127 uint64_t dst = dst64 & dst64_mask; \
1129 uint64_t src = (ip)->alu.src_val; \
1131 uint64_t result = dst operator src; \
1133 *dst64_ptr = (dst64 & ~dst64_mask) | (result & dst64_mask); \
1136 #define ALU_MI ALU_I
1138 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1140 #define ALU_HI(thread, ip, operator) \
1142 uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id]; \
1143 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset]; \
1144 uint64_t dst64 = *dst64_ptr; \
1145 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits); \
1146 uint64_t dst = ntoh64(dst64) >> (64 - (ip)->alu.dst.n_bits); \
1148 uint64_t src = (ip)->alu.src_val; \
1150 uint64_t result = dst operator src; \
1151 result = hton64(result << (64 - (ip)->alu.dst.n_bits)); \
1153 *dst64_ptr = (dst64 & ~dst64_mask) | result; \
1158 #define ALU_HI ALU_I
1162 #define MOV(thread, ip) \
1164 uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id]; \
1165 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset]; \
1166 uint64_t dst64 = *dst64_ptr; \
1167 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits); \
1169 uint8_t *src_struct = (thread)->structs[(ip)->mov.src.struct_id]; \
1170 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->mov.src.offset]; \
1171 uint64_t src64 = *src64_ptr; \
1172 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->mov.src.n_bits); \
1173 uint64_t src = src64 & src64_mask; \
1175 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask); \
1178 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1180 #define MOV_MH(thread, ip) \
1182 uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id]; \
1183 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset]; \
1184 uint64_t dst64 = *dst64_ptr; \
1185 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits); \
1187 uint8_t *src_struct = (thread)->structs[(ip)->mov.src.struct_id]; \
1188 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->mov.src.offset]; \
1189 uint64_t src64 = *src64_ptr; \
1190 uint64_t src = ntoh64(src64) >> (64 - (ip)->mov.src.n_bits); \
1192 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask); \
1195 #define MOV_HM(thread, ip) \
1197 uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id]; \
1198 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset]; \
1199 uint64_t dst64 = *dst64_ptr; \
1200 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits); \
1202 uint8_t *src_struct = (thread)->structs[(ip)->mov.src.struct_id]; \
1203 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->mov.src.offset]; \
1204 uint64_t src64 = *src64_ptr; \
1205 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->mov.src.n_bits); \
1206 uint64_t src = src64 & src64_mask; \
1208 src = hton64(src) >> (64 - (ip)->mov.dst.n_bits); \
1209 *dst64_ptr = (dst64 & ~dst64_mask) | src; \
1212 #define MOV_HH(thread, ip) \
1214 uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id]; \
1215 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset]; \
1216 uint64_t dst64 = *dst64_ptr; \
1217 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits); \
1219 uint8_t *src_struct = (thread)->structs[(ip)->mov.src.struct_id]; \
1220 uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->mov.src.offset]; \
1221 uint64_t src64 = *src64_ptr; \
1223 uint64_t src = src64 << (64 - (ip)->mov.src.n_bits); \
1224 src = src >> (64 - (ip)->mov.dst.n_bits); \
1225 *dst64_ptr = (dst64 & ~dst64_mask) | src; \
1236 #define MOV_I(thread, ip) \
1238 uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id]; \
1239 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset]; \
1240 uint64_t dst64 = *dst64_ptr; \
1241 uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits); \
1243 uint64_t src = (ip)->mov.src_val; \
1245 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask); \
1248 #define JMP_CMP(thread, ip, operator) \
1250 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1251 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1252 uint64_t a64 = *a64_ptr; \
1253 uint64_t a64_mask = UINT64_MAX >> (64 - (ip)->jmp.a.n_bits); \
1254 uint64_t a = a64 & a64_mask; \
1256 uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id]; \
1257 uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset]; \
1258 uint64_t b64 = *b64_ptr; \
1259 uint64_t b64_mask = UINT64_MAX >> (64 - (ip)->jmp.b.n_bits); \
1260 uint64_t b = b64 & b64_mask; \
1262 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1265 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1267 #define JMP_CMP_MH(thread, ip, operator) \
1269 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1270 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1271 uint64_t a64 = *a64_ptr; \
1272 uint64_t a64_mask = UINT64_MAX >> (64 - (ip)->jmp.a.n_bits); \
1273 uint64_t a = a64 & a64_mask; \
1275 uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id]; \
1276 uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset]; \
1277 uint64_t b64 = *b64_ptr; \
1278 uint64_t b = ntoh64(b64) >> (64 - (ip)->jmp.b.n_bits); \
1280 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1283 #define JMP_CMP_HM(thread, ip, operator) \
1285 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1286 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1287 uint64_t a64 = *a64_ptr; \
1288 uint64_t a = ntoh64(a64) >> (64 - (ip)->jmp.a.n_bits); \
1290 uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id]; \
1291 uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset]; \
1292 uint64_t b64 = *b64_ptr; \
1293 uint64_t b64_mask = UINT64_MAX >> (64 - (ip)->jmp.b.n_bits); \
1294 uint64_t b = b64 & b64_mask; \
1296 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1299 #define JMP_CMP_HH(thread, ip, operator) \
1301 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1302 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1303 uint64_t a64 = *a64_ptr; \
1304 uint64_t a = ntoh64(a64) >> (64 - (ip)->jmp.a.n_bits); \
1306 uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id]; \
1307 uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset]; \
1308 uint64_t b64 = *b64_ptr; \
1309 uint64_t b = ntoh64(b64) >> (64 - (ip)->jmp.b.n_bits); \
1311 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1314 #define JMP_CMP_HH_FAST(thread, ip, operator) \
1316 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1317 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1318 uint64_t a64 = *a64_ptr; \
1319 uint64_t a = a64 << (64 - (ip)->jmp.a.n_bits); \
1321 uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id]; \
1322 uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset]; \
1323 uint64_t b64 = *b64_ptr; \
1324 uint64_t b = b64 << (64 - (ip)->jmp.b.n_bits); \
1326 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1331 #define JMP_CMP_MH JMP_CMP
1332 #define JMP_CMP_HM JMP_CMP
1333 #define JMP_CMP_HH JMP_CMP
1334 #define JMP_CMP_HH_FAST JMP_CMP
1338 #define JMP_CMP_I(thread, ip, operator) \
1340 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1341 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1342 uint64_t a64 = *a64_ptr; \
1343 uint64_t a64_mask = UINT64_MAX >> (64 - (ip)->jmp.a.n_bits); \
1344 uint64_t a = a64 & a64_mask; \
1346 uint64_t b = (ip)->jmp.b_val; \
1348 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1351 #define JMP_CMP_MI JMP_CMP_I
1353 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1355 #define JMP_CMP_HI(thread, ip, operator) \
1357 uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id]; \
1358 uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset]; \
1359 uint64_t a64 = *a64_ptr; \
1360 uint64_t a = ntoh64(a64) >> (64 - (ip)->jmp.a.n_bits); \
1362 uint64_t b = (ip)->jmp.b_val; \
1364 (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1); \
1369 #define JMP_CMP_HI JMP_CMP_I
1373 #define METADATA_READ(thread, offset, n_bits) \
1375 uint64_t *m64_ptr = (uint64_t *)&(thread)->metadata[offset]; \
1376 uint64_t m64 = *m64_ptr; \
1377 uint64_t m64_mask = UINT64_MAX >> (64 - (n_bits)); \
1381 #define METADATA_WRITE(thread, offset, n_bits, value) \
1383 uint64_t *m64_ptr = (uint64_t *)&(thread)->metadata[offset]; \
1384 uint64_t m64 = *m64_ptr; \
1385 uint64_t m64_mask = UINT64_MAX >> (64 - (n_bits)); \
1387 uint64_t m_new = value; \
1389 *m64_ptr = (m64 & ~m64_mask) | (m_new & m64_mask); \
1392 #ifndef RTE_SWX_PIPELINE_THREADS_MAX
1393 #define RTE_SWX_PIPELINE_THREADS_MAX 16
1396 #ifndef RTE_SWX_PIPELINE_INSTRUCTION_TABLE_SIZE_MAX
1397 #define RTE_SWX_PIPELINE_INSTRUCTION_TABLE_SIZE_MAX 256
1400 struct rte_swx_pipeline {
1401 struct struct_type_tailq struct_types;
1402 struct port_in_type_tailq port_in_types;
1403 struct port_in_tailq ports_in;
1404 struct port_out_type_tailq port_out_types;
1405 struct port_out_tailq ports_out;
1406 struct extern_type_tailq extern_types;
1407 struct extern_obj_tailq extern_objs;
1408 struct extern_func_tailq extern_funcs;
1409 struct header_tailq headers;
1410 struct struct_type *metadata_st;
1411 uint32_t metadata_struct_id;
1412 struct action_tailq actions;
1413 struct table_type_tailq table_types;
1414 struct table_tailq tables;
1415 struct selector_tailq selectors;
1416 struct learner_tailq learners;
1417 struct regarray_tailq regarrays;
1418 struct meter_profile_tailq meter_profiles;
1419 struct metarray_tailq metarrays;
1421 struct port_in_runtime *in;
1422 struct port_out_runtime *out;
1423 struct mirroring_session *mirroring_sessions;
1424 struct instruction **action_instructions;
1425 action_func_t *action_funcs;
1426 struct rte_swx_table_state *table_state;
1427 struct table_statistics *table_stats;
1428 struct selector_statistics *selector_stats;
1429 struct learner_statistics *learner_stats;
1430 struct regarray_runtime *regarray_runtime;
1431 struct metarray_runtime *metarray_runtime;
1432 struct instruction *instructions;
1433 struct instruction_data *instruction_data;
1434 instr_exec_t *instruction_table;
1435 struct thread threads[RTE_SWX_PIPELINE_THREADS_MAX];
1439 uint32_t n_ports_in;
1440 uint32_t n_ports_out;
1441 uint32_t n_mirroring_slots;
1442 uint32_t n_mirroring_sessions;
1443 uint32_t n_extern_objs;
1444 uint32_t n_extern_funcs;
1447 uint32_t n_selectors;
1448 uint32_t n_learners;
1449 uint32_t n_regarrays;
1450 uint32_t n_metarrays;
1454 uint32_t n_instructions;
1463 pipeline_port_inc(struct rte_swx_pipeline *p)
1465 p->port_id = (p->port_id + 1) & (p->n_ports_in - 1);
1469 thread_ip_reset(struct rte_swx_pipeline *p, struct thread *t)
1471 t->ip = p->instructions;
1475 thread_ip_set(struct thread *t, struct instruction *ip)
1481 thread_ip_action_call(struct rte_swx_pipeline *p,
1486 t->ip = p->action_instructions[action_id];
1490 thread_ip_inc(struct rte_swx_pipeline *p);
1493 thread_ip_inc(struct rte_swx_pipeline *p)
1495 struct thread *t = &p->threads[p->thread_id];
1501 thread_ip_inc_cond(struct thread *t, int cond)
1507 thread_yield(struct rte_swx_pipeline *p)
1509 p->thread_id = (p->thread_id + 1) & (RTE_SWX_PIPELINE_THREADS_MAX - 1);
1513 thread_yield_cond(struct rte_swx_pipeline *p, int cond)
1515 p->thread_id = (p->thread_id + cond) & (RTE_SWX_PIPELINE_THREADS_MAX - 1);
1522 __instr_rx_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
1524 struct port_in_runtime *port = &p->in[p->port_id];
1525 struct rte_swx_pkt *pkt = &t->pkt;
1529 pkt_received = port->pkt_rx(port->obj, pkt);
1530 t->ptr = &pkt->pkt[pkt->offset];
1531 rte_prefetch0(t->ptr);
1533 TRACE("[Thread %2u] rx %s from port %u\n",
1535 pkt_received ? "1 pkt" : "0 pkts",
1538 t->mirroring_slots_mask = 0;
1541 t->valid_headers = 0;
1542 t->n_headers_out = 0;
1545 METADATA_WRITE(t, ip->io.io.offset, ip->io.io.n_bits, p->port_id);
1548 t->table_state = p->table_state;
1551 pipeline_port_inc(p);
1553 return pkt_received;
1557 instr_rx_exec(struct rte_swx_pipeline *p)
1559 struct thread *t = &p->threads[p->thread_id];
1560 struct instruction *ip = t->ip;
1564 pkt_received = __instr_rx_exec(p, t, ip);
1567 thread_ip_inc_cond(t, pkt_received);
1575 emit_handler(struct thread *t)
1577 struct header_out_runtime *h0 = &t->headers_out[0];
1578 struct header_out_runtime *h1 = &t->headers_out[1];
1579 uint32_t offset = 0, i;
1581 /* No header change or header decapsulation. */
1582 if ((t->n_headers_out == 1) &&
1583 (h0->ptr + h0->n_bytes == t->ptr)) {
1584 TRACE("Emit handler: no header change or header decap.\n");
1586 t->pkt.offset -= h0->n_bytes;
1587 t->pkt.length += h0->n_bytes;
1592 /* Header encapsulation (optionally, with prior header decapsulation). */
1593 if ((t->n_headers_out == 2) &&
1594 (h1->ptr + h1->n_bytes == t->ptr) &&
1595 (h0->ptr == h0->ptr0)) {
1598 TRACE("Emit handler: header encapsulation.\n");
1600 offset = h0->n_bytes + h1->n_bytes;
1601 memcpy(t->ptr - offset, h0->ptr, h0->n_bytes);
1602 t->pkt.offset -= offset;
1603 t->pkt.length += offset;
1608 /* For any other case. */
1609 TRACE("Emit handler: complex case.\n");
1611 for (i = 0; i < t->n_headers_out; i++) {
1612 struct header_out_runtime *h = &t->headers_out[i];
1614 memcpy(&t->header_out_storage[offset], h->ptr, h->n_bytes);
1615 offset += h->n_bytes;
1619 memcpy(t->ptr - offset, t->header_out_storage, offset);
1620 t->pkt.offset -= offset;
1621 t->pkt.length += offset;
1626 mirroring_handler(struct rte_swx_pipeline *p, struct thread *t, struct rte_swx_pkt *pkt)
1628 uint64_t slots_mask = t->mirroring_slots_mask, slot_mask;
1631 for (slot_id = 0, slot_mask = 1LLU ; slots_mask; slot_id++, slot_mask <<= 1)
1632 if (slot_mask & slots_mask) {
1633 struct port_out_runtime *port;
1634 struct mirroring_session *session;
1635 uint32_t port_id, session_id;
1637 session_id = t->mirroring_slots[slot_id];
1638 session = &p->mirroring_sessions[session_id];
1640 port_id = session->port_id;
1641 port = &p->out[port_id];
1643 if (session->fast_clone)
1644 port->pkt_fast_clone_tx(port->obj, pkt);
1646 port->pkt_clone_tx(port->obj, pkt, session->truncation_length);
1648 slots_mask &= ~slot_mask;
1653 __instr_tx_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
1655 uint64_t port_id = METADATA_READ(t, ip->io.io.offset, ip->io.io.n_bits);
1656 struct port_out_runtime *port = &p->out[port_id];
1657 struct rte_swx_pkt *pkt = &t->pkt;
1659 TRACE("[Thread %2u]: tx 1 pkt to port %u\n",
1667 mirroring_handler(p, t, pkt);
1668 port->pkt_tx(port->obj, pkt);
1672 __instr_tx_i_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
1674 uint64_t port_id = ip->io.io.val;
1675 struct port_out_runtime *port = &p->out[port_id];
1676 struct rte_swx_pkt *pkt = &t->pkt;
1678 TRACE("[Thread %2u]: tx (i) 1 pkt to port %u\n",
1686 mirroring_handler(p, t, pkt);
1687 port->pkt_tx(port->obj, pkt);
1691 __instr_drop_exec(struct rte_swx_pipeline *p,
1693 const struct instruction *ip __rte_unused)
1695 uint64_t port_id = p->n_ports_out - 1;
1696 struct port_out_runtime *port = &p->out[port_id];
1697 struct rte_swx_pkt *pkt = &t->pkt;
1699 TRACE("[Thread %2u]: drop 1 pkt\n",
1706 mirroring_handler(p, t, pkt);
1707 port->pkt_tx(port->obj, pkt);
1711 __instr_mirror_exec(struct rte_swx_pipeline *p,
1713 const struct instruction *ip)
1715 uint64_t slot_id = instr_operand_hbo(t, &ip->mirror.dst);
1716 uint64_t session_id = instr_operand_hbo(t, &ip->mirror.src);
1718 slot_id &= p->n_mirroring_slots - 1;
1719 session_id &= p->n_mirroring_sessions - 1;
1721 TRACE("[Thread %2u]: mirror pkt (slot = %u, session = %u)\n",
1724 (uint32_t)session_id);
1726 t->mirroring_slots[slot_id] = session_id;
1727 t->mirroring_slots_mask |= 1LLU << slot_id;
1734 __instr_hdr_extract_many_exec(struct rte_swx_pipeline *p __rte_unused,
1736 const struct instruction *ip,
1739 uint64_t valid_headers = t->valid_headers;
1740 uint8_t *ptr = t->ptr;
1741 uint32_t offset = t->pkt.offset;
1742 uint32_t length = t->pkt.length;
1745 for (i = 0; i < n_extract; i++) {
1746 uint32_t header_id = ip->io.hdr.header_id[i];
1747 uint32_t struct_id = ip->io.hdr.struct_id[i];
1748 uint32_t n_bytes = ip->io.hdr.n_bytes[i];
1750 TRACE("[Thread %2u]: extract header %u (%u bytes)\n",
1756 t->structs[struct_id] = ptr;
1757 valid_headers = MASK64_BIT_SET(valid_headers, header_id);
1766 t->valid_headers = valid_headers;
1769 t->pkt.offset = offset;
1770 t->pkt.length = length;
1775 __instr_hdr_extract_exec(struct rte_swx_pipeline *p,
1777 const struct instruction *ip)
1779 __instr_hdr_extract_many_exec(p, t, ip, 1);
1783 __instr_hdr_extract2_exec(struct rte_swx_pipeline *p,
1785 const struct instruction *ip)
1787 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n", p->thread_id);
1789 __instr_hdr_extract_many_exec(p, t, ip, 2);
1793 __instr_hdr_extract3_exec(struct rte_swx_pipeline *p,
1795 const struct instruction *ip)
1797 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n", p->thread_id);
1799 __instr_hdr_extract_many_exec(p, t, ip, 3);
1803 __instr_hdr_extract4_exec(struct rte_swx_pipeline *p,
1805 const struct instruction *ip)
1807 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n", p->thread_id);
1809 __instr_hdr_extract_many_exec(p, t, ip, 4);
1813 __instr_hdr_extract5_exec(struct rte_swx_pipeline *p,
1815 const struct instruction *ip)
1817 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n", p->thread_id);
1819 __instr_hdr_extract_many_exec(p, t, ip, 5);
1823 __instr_hdr_extract6_exec(struct rte_swx_pipeline *p,
1825 const struct instruction *ip)
1827 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n", p->thread_id);
1829 __instr_hdr_extract_many_exec(p, t, ip, 6);
1833 __instr_hdr_extract7_exec(struct rte_swx_pipeline *p,
1835 const struct instruction *ip)
1837 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n", p->thread_id);
1839 __instr_hdr_extract_many_exec(p, t, ip, 7);
1843 __instr_hdr_extract8_exec(struct rte_swx_pipeline *p,
1845 const struct instruction *ip)
1847 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n", p->thread_id);
1849 __instr_hdr_extract_many_exec(p, t, ip, 8);
1853 __instr_hdr_extract_m_exec(struct rte_swx_pipeline *p __rte_unused,
1855 const struct instruction *ip)
1857 uint64_t valid_headers = t->valid_headers;
1858 uint8_t *ptr = t->ptr;
1859 uint32_t offset = t->pkt.offset;
1860 uint32_t length = t->pkt.length;
1862 uint32_t n_bytes_last = METADATA_READ(t, ip->io.io.offset, ip->io.io.n_bits);
1863 uint32_t header_id = ip->io.hdr.header_id[0];
1864 uint32_t struct_id = ip->io.hdr.struct_id[0];
1865 uint32_t n_bytes = ip->io.hdr.n_bytes[0];
1867 struct header_runtime *h = &t->headers[header_id];
1869 TRACE("[Thread %2u]: extract header %u (%u + %u bytes)\n",
1875 n_bytes += n_bytes_last;
1878 t->structs[struct_id] = ptr;
1879 t->valid_headers = MASK64_BIT_SET(valid_headers, header_id);
1880 h->n_bytes = n_bytes;
1883 t->pkt.offset = offset + n_bytes;
1884 t->pkt.length = length - n_bytes;
1885 t->ptr = ptr + n_bytes;
1889 __instr_hdr_lookahead_exec(struct rte_swx_pipeline *p __rte_unused,
1891 const struct instruction *ip)
1893 uint64_t valid_headers = t->valid_headers;
1894 uint8_t *ptr = t->ptr;
1896 uint32_t header_id = ip->io.hdr.header_id[0];
1897 uint32_t struct_id = ip->io.hdr.struct_id[0];
1899 TRACE("[Thread %2u]: lookahead header %u\n",
1904 t->structs[struct_id] = ptr;
1905 t->valid_headers = MASK64_BIT_SET(valid_headers, header_id);
1912 __instr_hdr_emit_many_exec(struct rte_swx_pipeline *p __rte_unused,
1914 const struct instruction *ip,
1917 uint64_t valid_headers = t->valid_headers;
1918 uint32_t n_headers_out = t->n_headers_out;
1919 struct header_out_runtime *ho = NULL;
1920 uint8_t *ho_ptr = NULL;
1921 uint32_t ho_nbytes = 0, i;
1923 for (i = 0; i < n_emit; i++) {
1924 uint32_t header_id = ip->io.hdr.header_id[i];
1925 uint32_t struct_id = ip->io.hdr.struct_id[i];
1927 struct header_runtime *hi = &t->headers[header_id];
1928 uint8_t *hi_ptr0 = hi->ptr0;
1929 uint32_t n_bytes = hi->n_bytes;
1931 uint8_t *hi_ptr = t->structs[struct_id];
1933 if (!MASK64_BIT_GET(valid_headers, header_id)) {
1934 TRACE("[Thread %2u]: emit header %u (invalid)\n",
1941 TRACE("[Thread %2u]: emit header %u (valid)\n",
1947 if (!n_headers_out) {
1948 ho = &t->headers_out[0];
1954 ho_nbytes = n_bytes;
1960 ho = &t->headers_out[n_headers_out - 1];
1963 ho_nbytes = ho->n_bytes;
1967 if (ho_ptr + ho_nbytes == hi_ptr) {
1968 ho_nbytes += n_bytes;
1970 ho->n_bytes = ho_nbytes;
1977 ho_nbytes = n_bytes;
1984 ho->n_bytes = ho_nbytes;
1985 t->n_headers_out = n_headers_out;
1989 __instr_hdr_emit_exec(struct rte_swx_pipeline *p,
1991 const struct instruction *ip)
1993 __instr_hdr_emit_many_exec(p, t, ip, 1);
1997 __instr_hdr_emit_tx_exec(struct rte_swx_pipeline *p,
1999 const struct instruction *ip)
2001 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n", p->thread_id);
2003 __instr_hdr_emit_many_exec(p, t, ip, 1);
2004 __instr_tx_exec(p, t, ip);
2008 __instr_hdr_emit2_tx_exec(struct rte_swx_pipeline *p,
2010 const struct instruction *ip)
2012 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n", p->thread_id);
2014 __instr_hdr_emit_many_exec(p, t, ip, 2);
2015 __instr_tx_exec(p, t, ip);
2019 __instr_hdr_emit3_tx_exec(struct rte_swx_pipeline *p,
2021 const struct instruction *ip)
2023 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n", p->thread_id);
2025 __instr_hdr_emit_many_exec(p, t, ip, 3);
2026 __instr_tx_exec(p, t, ip);
2030 __instr_hdr_emit4_tx_exec(struct rte_swx_pipeline *p,
2032 const struct instruction *ip)
2034 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n", p->thread_id);
2036 __instr_hdr_emit_many_exec(p, t, ip, 4);
2037 __instr_tx_exec(p, t, ip);
2041 __instr_hdr_emit5_tx_exec(struct rte_swx_pipeline *p,
2043 const struct instruction *ip)
2045 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n", p->thread_id);
2047 __instr_hdr_emit_many_exec(p, t, ip, 5);
2048 __instr_tx_exec(p, t, ip);
2052 __instr_hdr_emit6_tx_exec(struct rte_swx_pipeline *p,
2054 const struct instruction *ip)
2056 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n", p->thread_id);
2058 __instr_hdr_emit_many_exec(p, t, ip, 6);
2059 __instr_tx_exec(p, t, ip);
2063 __instr_hdr_emit7_tx_exec(struct rte_swx_pipeline *p,
2065 const struct instruction *ip)
2067 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n", p->thread_id);
2069 __instr_hdr_emit_many_exec(p, t, ip, 7);
2070 __instr_tx_exec(p, t, ip);
2074 __instr_hdr_emit8_tx_exec(struct rte_swx_pipeline *p,
2076 const struct instruction *ip)
2078 TRACE("[Thread %2u] *** The next 9 instructions are fused. ***\n", p->thread_id);
2080 __instr_hdr_emit_many_exec(p, t, ip, 8);
2081 __instr_tx_exec(p, t, ip);
2088 __instr_hdr_validate_exec(struct rte_swx_pipeline *p __rte_unused,
2090 const struct instruction *ip)
2092 uint32_t header_id = ip->valid.header_id;
2094 TRACE("[Thread %2u] validate header %u\n", p->thread_id, header_id);
2097 t->valid_headers = MASK64_BIT_SET(t->valid_headers, header_id);
2104 __instr_hdr_invalidate_exec(struct rte_swx_pipeline *p __rte_unused,
2106 const struct instruction *ip)
2108 uint32_t header_id = ip->valid.header_id;
2110 TRACE("[Thread %2u] invalidate header %u\n", p->thread_id, header_id);
2113 t->valid_headers = MASK64_BIT_CLR(t->valid_headers, header_id);
2120 __instr_learn_exec(struct rte_swx_pipeline *p,
2122 const struct instruction *ip)
2124 uint64_t action_id = ip->learn.action_id;
2125 uint32_t mf_offset = ip->learn.mf_offset;
2126 uint32_t learner_id = t->learner_id;
2127 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2128 p->n_selectors + learner_id];
2129 struct learner_runtime *l = &t->learners[learner_id];
2130 struct learner_statistics *stats = &p->learner_stats[learner_id];
2134 status = rte_swx_table_learner_add(ts->obj,
2138 &t->metadata[mf_offset]);
2140 TRACE("[Thread %2u] learner %u learn %s\n",
2143 status ? "ok" : "error");
2145 stats->n_pkts_learn[status] += 1;
2152 __instr_forget_exec(struct rte_swx_pipeline *p,
2154 const struct instruction *ip __rte_unused)
2156 uint32_t learner_id = t->learner_id;
2157 struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2158 p->n_selectors + learner_id];
2159 struct learner_runtime *l = &t->learners[learner_id];
2160 struct learner_statistics *stats = &p->learner_stats[learner_id];
2163 rte_swx_table_learner_delete(ts->obj, l->mailbox);
2165 TRACE("[Thread %2u] learner %u forget\n",
2169 stats->n_pkts_forget += 1;
2175 static inline uint32_t
2176 __instr_extern_obj_exec(struct rte_swx_pipeline *p __rte_unused,
2178 const struct instruction *ip)
2180 uint32_t obj_id = ip->ext_obj.ext_obj_id;
2181 uint32_t func_id = ip->ext_obj.func_id;
2182 struct extern_obj_runtime *obj = &t->extern_objs[obj_id];
2183 rte_swx_extern_type_member_func_t func = obj->funcs[func_id];
2186 TRACE("[Thread %2u] extern obj %u member func %u\n",
2191 done = func(obj->obj, obj->mailbox);
2196 static inline uint32_t
2197 __instr_extern_func_exec(struct rte_swx_pipeline *p __rte_unused,
2199 const struct instruction *ip)
2201 uint32_t ext_func_id = ip->ext_func.ext_func_id;
2202 struct extern_func_runtime *ext_func = &t->extern_funcs[ext_func_id];
2203 rte_swx_extern_func_t func = ext_func->func;
2206 TRACE("[Thread %2u] extern func %u\n",
2210 done = func(ext_func->mailbox);
2219 __instr_mov_exec(struct rte_swx_pipeline *p __rte_unused,
2221 const struct instruction *ip)
2223 TRACE("[Thread %2u] mov\n", p->thread_id);
2229 __instr_mov_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2231 const struct instruction *ip)
2233 TRACE("[Thread %2u] mov (mh)\n", p->thread_id);
2239 __instr_mov_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2241 const struct instruction *ip)
2243 TRACE("[Thread %2u] mov (hm)\n", p->thread_id);
2249 __instr_mov_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2251 const struct instruction *ip)
2253 TRACE("[Thread %2u] mov (hh)\n", p->thread_id);
2259 __instr_mov_i_exec(struct rte_swx_pipeline *p __rte_unused,
2261 const struct instruction *ip)
2263 TRACE("[Thread %2u] mov m.f %" PRIx64 "\n", p->thread_id, ip->mov.src_val);
2272 __instr_dma_ht_many_exec(struct rte_swx_pipeline *p __rte_unused,
2274 const struct instruction *ip,
2277 uint8_t *action_data = t->structs[0];
2278 uint64_t valid_headers = t->valid_headers;
2281 for (i = 0; i < n_dma; i++) {
2282 uint32_t header_id = ip->dma.dst.header_id[i];
2283 uint32_t struct_id = ip->dma.dst.struct_id[i];
2284 uint32_t offset = ip->dma.src.offset[i];
2285 uint32_t n_bytes = ip->dma.n_bytes[i];
2287 struct header_runtime *h = &t->headers[header_id];
2288 uint8_t *h_ptr0 = h->ptr0;
2289 uint8_t *h_ptr = t->structs[struct_id];
2291 void *dst = MASK64_BIT_GET(valid_headers, header_id) ?
2293 void *src = &action_data[offset];
2295 TRACE("[Thread %2u] dma h.s t.f\n", p->thread_id);
2298 memcpy(dst, src, n_bytes);
2299 t->structs[struct_id] = dst;
2300 valid_headers = MASK64_BIT_SET(valid_headers, header_id);
2303 t->valid_headers = valid_headers;
2307 __instr_dma_ht_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2309 __instr_dma_ht_many_exec(p, t, ip, 1);
2313 __instr_dma_ht2_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2315 TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n", p->thread_id);
2317 __instr_dma_ht_many_exec(p, t, ip, 2);
2321 __instr_dma_ht3_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2323 TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n", p->thread_id);
2325 __instr_dma_ht_many_exec(p, t, ip, 3);
2329 __instr_dma_ht4_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2331 TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n", p->thread_id);
2333 __instr_dma_ht_many_exec(p, t, ip, 4);
2337 __instr_dma_ht5_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2339 TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n", p->thread_id);
2341 __instr_dma_ht_many_exec(p, t, ip, 5);
2345 __instr_dma_ht6_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2347 TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n", p->thread_id);
2349 __instr_dma_ht_many_exec(p, t, ip, 6);
2353 __instr_dma_ht7_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2355 TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n", p->thread_id);
2357 __instr_dma_ht_many_exec(p, t, ip, 7);
2361 __instr_dma_ht8_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2363 TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n", p->thread_id);
2365 __instr_dma_ht_many_exec(p, t, ip, 8);
2372 __instr_alu_add_exec(struct rte_swx_pipeline *p __rte_unused,
2374 const struct instruction *ip)
2376 TRACE("[Thread %2u] add\n", p->thread_id);
2382 __instr_alu_add_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2384 const struct instruction *ip)
2386 TRACE("[Thread %2u] add (mh)\n", p->thread_id);
2392 __instr_alu_add_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2394 const struct instruction *ip)
2396 TRACE("[Thread %2u] add (hm)\n", p->thread_id);
2402 __instr_alu_add_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2404 const struct instruction *ip)
2406 TRACE("[Thread %2u] add (hh)\n", p->thread_id);
2412 __instr_alu_add_mi_exec(struct rte_swx_pipeline *p __rte_unused,
2414 const struct instruction *ip)
2416 TRACE("[Thread %2u] add (mi)\n", p->thread_id);
2422 __instr_alu_add_hi_exec(struct rte_swx_pipeline *p __rte_unused,
2424 const struct instruction *ip)
2426 TRACE("[Thread %2u] add (hi)\n", p->thread_id);
2432 __instr_alu_sub_exec(struct rte_swx_pipeline *p __rte_unused,
2434 const struct instruction *ip)
2436 TRACE("[Thread %2u] sub\n", p->thread_id);
2442 __instr_alu_sub_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2444 const struct instruction *ip)
2446 TRACE("[Thread %2u] sub (mh)\n", p->thread_id);
2452 __instr_alu_sub_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2454 const struct instruction *ip)
2456 TRACE("[Thread %2u] sub (hm)\n", p->thread_id);
2462 __instr_alu_sub_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2464 const struct instruction *ip)
2466 TRACE("[Thread %2u] sub (hh)\n", p->thread_id);
2472 __instr_alu_sub_mi_exec(struct rte_swx_pipeline *p __rte_unused,
2474 const struct instruction *ip)
2476 TRACE("[Thread %2u] sub (mi)\n", p->thread_id);
2482 __instr_alu_sub_hi_exec(struct rte_swx_pipeline *p __rte_unused,
2484 const struct instruction *ip)
2486 TRACE("[Thread %2u] sub (hi)\n", p->thread_id);
2492 __instr_alu_shl_exec(struct rte_swx_pipeline *p __rte_unused,
2494 const struct instruction *ip)
2496 TRACE("[Thread %2u] shl\n", p->thread_id);
2502 __instr_alu_shl_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2504 const struct instruction *ip)
2506 TRACE("[Thread %2u] shl (mh)\n", p->thread_id);
2512 __instr_alu_shl_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2514 const struct instruction *ip)
2516 TRACE("[Thread %2u] shl (hm)\n", p->thread_id);
2522 __instr_alu_shl_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2524 const struct instruction *ip)
2526 TRACE("[Thread %2u] shl (hh)\n", p->thread_id);
2532 __instr_alu_shl_mi_exec(struct rte_swx_pipeline *p __rte_unused,
2534 const struct instruction *ip)
2536 TRACE("[Thread %2u] shl (mi)\n", p->thread_id);
2542 __instr_alu_shl_hi_exec(struct rte_swx_pipeline *p __rte_unused,
2544 const struct instruction *ip)
2546 TRACE("[Thread %2u] shl (hi)\n", p->thread_id);
2552 __instr_alu_shr_exec(struct rte_swx_pipeline *p __rte_unused,
2554 const struct instruction *ip)
2556 TRACE("[Thread %2u] shr\n", p->thread_id);
2562 __instr_alu_shr_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2564 const struct instruction *ip)
2566 TRACE("[Thread %2u] shr (mh)\n", p->thread_id);
2572 __instr_alu_shr_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2574 const struct instruction *ip)
2576 TRACE("[Thread %2u] shr (hm)\n", p->thread_id);
2582 __instr_alu_shr_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2584 const struct instruction *ip)
2586 TRACE("[Thread %2u] shr (hh)\n", p->thread_id);
2592 __instr_alu_shr_mi_exec(struct rte_swx_pipeline *p __rte_unused,
2594 const struct instruction *ip)
2596 TRACE("[Thread %2u] shr (mi)\n", p->thread_id);
2603 __instr_alu_shr_hi_exec(struct rte_swx_pipeline *p __rte_unused,
2605 const struct instruction *ip)
2607 TRACE("[Thread %2u] shr (hi)\n", p->thread_id);
2613 __instr_alu_and_exec(struct rte_swx_pipeline *p __rte_unused,
2615 const struct instruction *ip)
2617 TRACE("[Thread %2u] and\n", p->thread_id);
2623 __instr_alu_and_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2625 const struct instruction *ip)
2627 TRACE("[Thread %2u] and (mh)\n", p->thread_id);
2633 __instr_alu_and_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2635 const struct instruction *ip)
2637 TRACE("[Thread %2u] and (hm)\n", p->thread_id);
2639 ALU_HM_FAST(t, ip, &);
2643 __instr_alu_and_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2645 const struct instruction *ip)
2647 TRACE("[Thread %2u] and (hh)\n", p->thread_id);
2649 ALU_HH_FAST(t, ip, &);
2653 __instr_alu_and_i_exec(struct rte_swx_pipeline *p __rte_unused,
2655 const struct instruction *ip)
2657 TRACE("[Thread %2u] and (i)\n", p->thread_id);
2663 __instr_alu_or_exec(struct rte_swx_pipeline *p __rte_unused,
2665 const struct instruction *ip)
2667 TRACE("[Thread %2u] or\n", p->thread_id);
2673 __instr_alu_or_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2675 const struct instruction *ip)
2677 TRACE("[Thread %2u] or (mh)\n", p->thread_id);
2683 __instr_alu_or_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2685 const struct instruction *ip)
2687 TRACE("[Thread %2u] or (hm)\n", p->thread_id);
2689 ALU_HM_FAST(t, ip, |);
2693 __instr_alu_or_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2695 const struct instruction *ip)
2697 TRACE("[Thread %2u] or (hh)\n", p->thread_id);
2699 ALU_HH_FAST(t, ip, |);
2703 __instr_alu_or_i_exec(struct rte_swx_pipeline *p __rte_unused,
2705 const struct instruction *ip)
2707 TRACE("[Thread %2u] or (i)\n", p->thread_id);
2713 __instr_alu_xor_exec(struct rte_swx_pipeline *p __rte_unused,
2715 const struct instruction *ip)
2717 TRACE("[Thread %2u] xor\n", p->thread_id);
2723 __instr_alu_xor_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2725 const struct instruction *ip)
2727 TRACE("[Thread %2u] xor (mh)\n", p->thread_id);
2733 __instr_alu_xor_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2735 const struct instruction *ip)
2737 TRACE("[Thread %2u] xor (hm)\n", p->thread_id);
2739 ALU_HM_FAST(t, ip, ^);
2743 __instr_alu_xor_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2745 const struct instruction *ip)
2747 TRACE("[Thread %2u] xor (hh)\n", p->thread_id);
2749 ALU_HH_FAST(t, ip, ^);
2753 __instr_alu_xor_i_exec(struct rte_swx_pipeline *p __rte_unused,
2755 const struct instruction *ip)
2757 TRACE("[Thread %2u] xor (i)\n", p->thread_id);
2763 __instr_alu_ckadd_field_exec(struct rte_swx_pipeline *p __rte_unused,
2765 const struct instruction *ip)
2767 uint8_t *dst_struct, *src_struct;
2768 uint16_t *dst16_ptr, dst;
2769 uint64_t *src64_ptr, src64, src64_mask, src;
2772 TRACE("[Thread %2u] ckadd (field)\n", p->thread_id);
2775 dst_struct = t->structs[ip->alu.dst.struct_id];
2776 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
2779 src_struct = t->structs[ip->alu.src.struct_id];
2780 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
2782 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
2783 src = src64 & src64_mask;
2785 /* Initialize the result with destination 1's complement. */
2789 /* The first input (r) is a 16-bit number. The second and the third
2790 * inputs are 32-bit numbers. In the worst case scenario, the sum of the
2791 * three numbers (output r) is a 34-bit number.
2793 r += (src >> 32) + (src & 0xFFFFFFFF);
2795 /* The first input is a 16-bit number. The second input is an 18-bit
2796 * number. In the worst case scenario, the sum of the two numbers is a
2799 r = (r & 0xFFFF) + (r >> 16);
2801 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
2802 * a 3-bit number (0 .. 7). Their sum is a 17-bit number (0 .. 0x10006).
2804 r = (r & 0xFFFF) + (r >> 16);
2806 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
2807 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
2808 * 0x10006), the output r is (0 .. 7). So no carry bit can be generated,
2809 * therefore the output r is always a 16-bit number.
2811 r = (r & 0xFFFF) + (r >> 16);
2813 /* Apply 1's complement to the result. */
2817 *dst16_ptr = (uint16_t)r;
2821 __instr_alu_cksub_field_exec(struct rte_swx_pipeline *p __rte_unused,
2823 const struct instruction *ip)
2825 uint8_t *dst_struct, *src_struct;
2826 uint16_t *dst16_ptr, dst;
2827 uint64_t *src64_ptr, src64, src64_mask, src;
2830 TRACE("[Thread %2u] cksub (field)\n", p->thread_id);
2833 dst_struct = t->structs[ip->alu.dst.struct_id];
2834 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
2837 src_struct = t->structs[ip->alu.src.struct_id];
2838 src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
2840 src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
2841 src = src64 & src64_mask;
2843 /* Initialize the result with destination 1's complement. */
2847 /* Subtraction in 1's complement arithmetic (i.e. a '- b) is the same as
2848 * the following sequence of operations in 2's complement arithmetic:
2849 * a '- b = (a - b) % 0xFFFF.
2851 * In order to prevent an underflow for the below subtraction, in which
2852 * a 33-bit number (the subtrahend) is taken out of a 16-bit number (the
2853 * minuend), we first add a multiple of the 0xFFFF modulus to the
2854 * minuend. The number we add to the minuend needs to be a 34-bit number
2855 * or higher, so for readability reasons we picked the 36-bit multiple.
2856 * We are effectively turning the 16-bit minuend into a 36-bit number:
2857 * (a - b) % 0xFFFF = (a + 0xFFFF00000 - b) % 0xFFFF.
2859 r += 0xFFFF00000ULL; /* The output r is a 36-bit number. */
2861 /* A 33-bit number is subtracted from a 36-bit number (the input r). The
2862 * result (the output r) is a 36-bit number.
2864 r -= (src >> 32) + (src & 0xFFFFFFFF);
2866 /* The first input is a 16-bit number. The second input is a 20-bit
2867 * number. Their sum is a 21-bit number.
2869 r = (r & 0xFFFF) + (r >> 16);
2871 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
2872 * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1001E).
2874 r = (r & 0xFFFF) + (r >> 16);
2876 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
2877 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
2878 * 0x1001E), the output r is (0 .. 31). So no carry bit can be
2879 * generated, therefore the output r is always a 16-bit number.
2881 r = (r & 0xFFFF) + (r >> 16);
2883 /* Apply 1's complement to the result. */
2887 *dst16_ptr = (uint16_t)r;
2891 __instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline *p __rte_unused,
2893 const struct instruction *ip)
2895 uint8_t *dst_struct, *src_struct;
2896 uint16_t *dst16_ptr, dst;
2897 uint32_t *src32_ptr;
2900 TRACE("[Thread %2u] ckadd (struct of 20 bytes)\n", p->thread_id);
2903 dst_struct = t->structs[ip->alu.dst.struct_id];
2904 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
2907 src_struct = t->structs[ip->alu.src.struct_id];
2908 src32_ptr = (uint32_t *)&src_struct[0];
2910 /* Initialize the result with destination 1's complement. */
2914 r0 += src32_ptr[0]; /* The output r0 is a 33-bit number. */
2915 r1 = src32_ptr[1]; /* r1 is a 32-bit number. */
2916 r0 += src32_ptr[2]; /* The output r0 is a 34-bit number. */
2917 r1 += src32_ptr[3]; /* The output r1 is a 33-bit number. */
2918 r0 += r1 + src32_ptr[4]; /* The output r0 is a 35-bit number. */
2920 /* The first input is a 16-bit number. The second input is a 19-bit
2921 * number. Their sum is a 20-bit number.
2923 r0 = (r0 & 0xFFFF) + (r0 >> 16);
2925 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
2926 * a 4-bit number (0 .. 15). The sum is a 17-bit number (0 .. 0x1000E).
2928 r0 = (r0 & 0xFFFF) + (r0 >> 16);
2930 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
2931 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
2932 * 0x1000E), the output r is (0 .. 15). So no carry bit can be
2933 * generated, therefore the output r is always a 16-bit number.
2935 r0 = (r0 & 0xFFFF) + (r0 >> 16);
2937 /* Apply 1's complement to the result. */
2939 r0 = r0 ? r0 : 0xFFFF;
2941 *dst16_ptr = (uint16_t)r0;
2945 __instr_alu_ckadd_struct_exec(struct rte_swx_pipeline *p __rte_unused,
2947 const struct instruction *ip)
2949 uint32_t src_header_id = ip->alu.src.n_bits; /* The src header ID is stored here. */
2950 uint32_t n_src_header_bytes = t->headers[src_header_id].n_bytes;
2951 uint8_t *dst_struct, *src_struct;
2952 uint16_t *dst16_ptr, dst;
2953 uint32_t *src32_ptr;
2957 if (n_src_header_bytes == 20) {
2958 __instr_alu_ckadd_struct20_exec(p, t, ip);
2962 TRACE("[Thread %2u] ckadd (struct)\n", p->thread_id);
2965 dst_struct = t->structs[ip->alu.dst.struct_id];
2966 dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
2969 src_struct = t->structs[ip->alu.src.struct_id];
2970 src32_ptr = (uint32_t *)&src_struct[0];
2972 /* Initialize the result with destination 1's complement. */
2976 /* The max number of 32-bit words in a 32K-byte header is 2^13.
2977 * Therefore, in the worst case scenario, a 45-bit number is added to a
2978 * 16-bit number (the input r), so the output r is 46-bit number.
2980 for (i = 0; i < n_src_header_bytes / 4; i++, src32_ptr++)
2983 /* The first input is a 16-bit number. The second input is a 30-bit
2984 * number. Their sum is a 31-bit number.
2986 r = (r & 0xFFFF) + (r >> 16);
2988 /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
2989 * a 15-bit number (0 .. 0x7FFF). The sum is a 17-bit number (0 .. 0x17FFE).
2991 r = (r & 0xFFFF) + (r >> 16);
2993 /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
2994 * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
2995 * 0x17FFE), the output r is (0 .. 0x7FFF). So no carry bit can be
2996 * generated, therefore the output r is always a 16-bit number.
2998 r = (r & 0xFFFF) + (r >> 16);
3000 /* Apply 1's complement to the result. */
3004 *dst16_ptr = (uint16_t)r;
3010 static inline uint64_t *
3011 instr_regarray_regarray(struct rte_swx_pipeline *p, const struct instruction *ip)
3013 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
3017 static inline uint64_t
3018 instr_regarray_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3020 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
3022 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
3023 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
3024 uint64_t idx64 = *idx64_ptr;
3025 uint64_t idx64_mask = UINT64_MAX >> (64 - ip->regarray.idx.n_bits);
3026 uint64_t idx = idx64 & idx64_mask & r->size_mask;
3031 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
3033 static inline uint64_t
3034 instr_regarray_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3036 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
3038 uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
3039 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
3040 uint64_t idx64 = *idx64_ptr;
3041 uint64_t idx = (ntoh64(idx64) >> (64 - ip->regarray.idx.n_bits)) & r->size_mask;
3048 #define instr_regarray_idx_nbo instr_regarray_idx_hbo
3052 static inline uint64_t
3053 instr_regarray_idx_imm(struct rte_swx_pipeline *p, const struct instruction *ip)
3055 struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
3057 uint64_t idx = ip->regarray.idx_val & r->size_mask;
3062 static inline uint64_t
3063 instr_regarray_src_hbo(struct thread *t, const struct instruction *ip)
3065 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
3066 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
3067 uint64_t src64 = *src64_ptr;
3068 uint64_t src64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
3069 uint64_t src = src64 & src64_mask;
3074 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
3076 static inline uint64_t
3077 instr_regarray_src_nbo(struct thread *t, const struct instruction *ip)
3079 uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
3080 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
3081 uint64_t src64 = *src64_ptr;
3082 uint64_t src = ntoh64(src64) >> (64 - ip->regarray.dstsrc.n_bits);
3089 #define instr_regarray_src_nbo instr_regarray_src_hbo
3094 instr_regarray_dst_hbo_src_hbo_set(struct thread *t, const struct instruction *ip, uint64_t src)
3096 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
3097 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
3098 uint64_t dst64 = *dst64_ptr;
3099 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
3101 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
3105 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
3108 instr_regarray_dst_nbo_src_hbo_set(struct thread *t, const struct instruction *ip, uint64_t src)
3110 uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
3111 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
3112 uint64_t dst64 = *dst64_ptr;
3113 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
3115 src = hton64(src) >> (64 - ip->regarray.dstsrc.n_bits);
3116 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
3121 #define instr_regarray_dst_nbo_src_hbo_set instr_regarray_dst_hbo_src_hbo_set
3126 __instr_regprefetch_rh_exec(struct rte_swx_pipeline *p,
3128 const struct instruction *ip)
3130 uint64_t *regarray, idx;
3132 TRACE("[Thread %2u] regprefetch (r[h])\n", p->thread_id);
3134 regarray = instr_regarray_regarray(p, ip);
3135 idx = instr_regarray_idx_nbo(p, t, ip);
3136 rte_prefetch0(®array[idx]);
3140 __instr_regprefetch_rm_exec(struct rte_swx_pipeline *p,
3142 const struct instruction *ip)
3144 uint64_t *regarray, idx;
3146 TRACE("[Thread %2u] regprefetch (r[m])\n", p->thread_id);
3148 regarray = instr_regarray_regarray(p, ip);
3149 idx = instr_regarray_idx_hbo(p, t, ip);
3150 rte_prefetch0(®array[idx]);
3154 __instr_regprefetch_ri_exec(struct rte_swx_pipeline *p,
3155 struct thread *t __rte_unused,
3156 const struct instruction *ip)
3158 uint64_t *regarray, idx;
3160 TRACE("[Thread %2u] regprefetch (r[i])\n", p->thread_id);
3162 regarray = instr_regarray_regarray(p, ip);
3163 idx = instr_regarray_idx_imm(p, ip);
3164 rte_prefetch0(®array[idx]);
3168 __instr_regrd_hrh_exec(struct rte_swx_pipeline *p,
3170 const struct instruction *ip)
3172 uint64_t *regarray, idx;
3174 TRACE("[Thread %2u] regrd (h = r[h])\n", p->thread_id);
3176 regarray = instr_regarray_regarray(p, ip);
3177 idx = instr_regarray_idx_nbo(p, t, ip);
3178 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
3182 __instr_regrd_hrm_exec(struct rte_swx_pipeline *p,
3184 const struct instruction *ip)
3186 uint64_t *regarray, idx;
3188 TRACE("[Thread %2u] regrd (h = r[m])\n", p->thread_id);
3191 regarray = instr_regarray_regarray(p, ip);
3192 idx = instr_regarray_idx_hbo(p, t, ip);
3193 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
3197 __instr_regrd_mrh_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3199 uint64_t *regarray, idx;
3201 TRACE("[Thread %2u] regrd (m = r[h])\n", p->thread_id);
3203 regarray = instr_regarray_regarray(p, ip);
3204 idx = instr_regarray_idx_nbo(p, t, ip);
3205 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
3209 __instr_regrd_mrm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3211 uint64_t *regarray, idx;
3213 TRACE("[Thread %2u] regrd (m = r[m])\n", p->thread_id);
3215 regarray = instr_regarray_regarray(p, ip);
3216 idx = instr_regarray_idx_hbo(p, t, ip);
3217 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
3221 __instr_regrd_hri_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3223 uint64_t *regarray, idx;
3225 TRACE("[Thread %2u] regrd (h = r[i])\n", p->thread_id);
3227 regarray = instr_regarray_regarray(p, ip);
3228 idx = instr_regarray_idx_imm(p, ip);
3229 instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
3233 __instr_regrd_mri_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3235 uint64_t *regarray, idx;
3237 TRACE("[Thread %2u] regrd (m = r[i])\n", p->thread_id);
3239 regarray = instr_regarray_regarray(p, ip);
3240 idx = instr_regarray_idx_imm(p, ip);
3241 instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
3245 __instr_regwr_rhh_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3247 uint64_t *regarray, idx, src;
3249 TRACE("[Thread %2u] regwr (r[h] = h)\n", p->thread_id);
3251 regarray = instr_regarray_regarray(p, ip);
3252 idx = instr_regarray_idx_nbo(p, t, ip);
3253 src = instr_regarray_src_nbo(t, ip);
3254 regarray[idx] = src;
3258 __instr_regwr_rhm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3260 uint64_t *regarray, idx, src;
3262 TRACE("[Thread %2u] regwr (r[h] = m)\n", p->thread_id);
3264 regarray = instr_regarray_regarray(p, ip);
3265 idx = instr_regarray_idx_nbo(p, t, ip);
3266 src = instr_regarray_src_hbo(t, ip);
3267 regarray[idx] = src;
3271 __instr_regwr_rmh_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3273 uint64_t *regarray, idx, src;
3275 TRACE("[Thread %2u] regwr (r[m] = h)\n", p->thread_id);
3277 regarray = instr_regarray_regarray(p, ip);
3278 idx = instr_regarray_idx_hbo(p, t, ip);
3279 src = instr_regarray_src_nbo(t, ip);
3280 regarray[idx] = src;
3284 __instr_regwr_rmm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3286 uint64_t *regarray, idx, src;
3288 TRACE("[Thread %2u] regwr (r[m] = m)\n", p->thread_id);
3290 regarray = instr_regarray_regarray(p, ip);
3291 idx = instr_regarray_idx_hbo(p, t, ip);
3292 src = instr_regarray_src_hbo(t, ip);
3293 regarray[idx] = src;
3297 __instr_regwr_rhi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3299 uint64_t *regarray, idx, src;
3301 TRACE("[Thread %2u] regwr (r[h] = i)\n", p->thread_id);
3303 regarray = instr_regarray_regarray(p, ip);
3304 idx = instr_regarray_idx_nbo(p, t, ip);
3305 src = ip->regarray.dstsrc_val;
3306 regarray[idx] = src;
3310 __instr_regwr_rmi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3312 uint64_t *regarray, idx, src;
3314 TRACE("[Thread %2u] regwr (r[m] = i)\n", p->thread_id);
3316 regarray = instr_regarray_regarray(p, ip);
3317 idx = instr_regarray_idx_hbo(p, t, ip);
3318 src = ip->regarray.dstsrc_val;
3319 regarray[idx] = src;
3323 __instr_regwr_rih_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3325 uint64_t *regarray, idx, src;
3327 TRACE("[Thread %2u] regwr (r[i] = h)\n", p->thread_id);
3329 regarray = instr_regarray_regarray(p, ip);
3330 idx = instr_regarray_idx_imm(p, ip);
3331 src = instr_regarray_src_nbo(t, ip);
3332 regarray[idx] = src;
3336 __instr_regwr_rim_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3338 uint64_t *regarray, idx, src;
3340 TRACE("[Thread %2u] regwr (r[i] = m)\n", p->thread_id);
3342 regarray = instr_regarray_regarray(p, ip);
3343 idx = instr_regarray_idx_imm(p, ip);
3344 src = instr_regarray_src_hbo(t, ip);
3345 regarray[idx] = src;
3349 __instr_regwr_rii_exec(struct rte_swx_pipeline *p,
3350 struct thread *t __rte_unused,
3351 const struct instruction *ip)
3353 uint64_t *regarray, idx, src;
3355 TRACE("[Thread %2u] regwr (r[i] = i)\n", p->thread_id);
3357 regarray = instr_regarray_regarray(p, ip);
3358 idx = instr_regarray_idx_imm(p, ip);
3359 src = ip->regarray.dstsrc_val;
3360 regarray[idx] = src;
3364 __instr_regadd_rhh_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3366 uint64_t *regarray, idx, src;
3368 TRACE("[Thread %2u] regadd (r[h] += h)\n", p->thread_id);
3370 regarray = instr_regarray_regarray(p, ip);
3371 idx = instr_regarray_idx_nbo(p, t, ip);
3372 src = instr_regarray_src_nbo(t, ip);
3373 regarray[idx] += src;
3377 __instr_regadd_rhm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3379 uint64_t *regarray, idx, src;
3381 TRACE("[Thread %2u] regadd (r[h] += m)\n", p->thread_id);
3383 regarray = instr_regarray_regarray(p, ip);
3384 idx = instr_regarray_idx_nbo(p, t, ip);
3385 src = instr_regarray_src_hbo(t, ip);
3386 regarray[idx] += src;
3390 __instr_regadd_rmh_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3392 uint64_t *regarray, idx, src;
3394 TRACE("[Thread %2u] regadd (r[m] += h)\n", p->thread_id);
3396 regarray = instr_regarray_regarray(p, ip);
3397 idx = instr_regarray_idx_hbo(p, t, ip);
3398 src = instr_regarray_src_nbo(t, ip);
3399 regarray[idx] += src;
3403 __instr_regadd_rmm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3405 uint64_t *regarray, idx, src;
3407 TRACE("[Thread %2u] regadd (r[m] += m)\n", p->thread_id);
3409 regarray = instr_regarray_regarray(p, ip);
3410 idx = instr_regarray_idx_hbo(p, t, ip);
3411 src = instr_regarray_src_hbo(t, ip);
3412 regarray[idx] += src;
3416 __instr_regadd_rhi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3418 uint64_t *regarray, idx, src;
3420 TRACE("[Thread %2u] regadd (r[h] += i)\n", p->thread_id);
3422 regarray = instr_regarray_regarray(p, ip);
3423 idx = instr_regarray_idx_nbo(p, t, ip);
3424 src = ip->regarray.dstsrc_val;
3425 regarray[idx] += src;
3429 __instr_regadd_rmi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3431 uint64_t *regarray, idx, src;
3433 TRACE("[Thread %2u] regadd (r[m] += i)\n", p->thread_id);
3435 regarray = instr_regarray_regarray(p, ip);
3436 idx = instr_regarray_idx_hbo(p, t, ip);
3437 src = ip->regarray.dstsrc_val;
3438 regarray[idx] += src;
3442 __instr_regadd_rih_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3444 uint64_t *regarray, idx, src;
3446 TRACE("[Thread %2u] regadd (r[i] += h)\n", p->thread_id);
3448 regarray = instr_regarray_regarray(p, ip);
3449 idx = instr_regarray_idx_imm(p, ip);
3450 src = instr_regarray_src_nbo(t, ip);
3451 regarray[idx] += src;
3455 __instr_regadd_rim_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3457 uint64_t *regarray, idx, src;
3459 TRACE("[Thread %2u] regadd (r[i] += m)\n", p->thread_id);
3461 regarray = instr_regarray_regarray(p, ip);
3462 idx = instr_regarray_idx_imm(p, ip);
3463 src = instr_regarray_src_hbo(t, ip);
3464 regarray[idx] += src;
3468 __instr_regadd_rii_exec(struct rte_swx_pipeline *p,
3469 struct thread *t __rte_unused,
3470 const struct instruction *ip)
3472 uint64_t *regarray, idx, src;
3474 TRACE("[Thread %2u] regadd (r[i] += i)\n", p->thread_id);
3476 regarray = instr_regarray_regarray(p, ip);
3477 idx = instr_regarray_idx_imm(p, ip);
3478 src = ip->regarray.dstsrc_val;
3479 regarray[idx] += src;
3485 static inline struct meter *
3486 instr_meter_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3488 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
3490 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
3491 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
3492 uint64_t idx64 = *idx64_ptr;
3493 uint64_t idx64_mask = UINT64_MAX >> (64 - (ip)->meter.idx.n_bits);
3494 uint64_t idx = idx64 & idx64_mask & r->size_mask;
3496 return &r->metarray[idx];
3499 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
3501 static inline struct meter *
3502 instr_meter_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3504 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
3506 uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
3507 uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
3508 uint64_t idx64 = *idx64_ptr;
3509 uint64_t idx = (ntoh64(idx64) >> (64 - ip->meter.idx.n_bits)) & r->size_mask;
3511 return &r->metarray[idx];
3516 #define instr_meter_idx_nbo instr_meter_idx_hbo
3520 static inline struct meter *
3521 instr_meter_idx_imm(struct rte_swx_pipeline *p, const struct instruction *ip)
3523 struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
3525 uint64_t idx = ip->meter.idx_val & r->size_mask;
3527 return &r->metarray[idx];
3530 static inline uint32_t
3531 instr_meter_length_hbo(struct thread *t, const struct instruction *ip)
3533 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
3534 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
3535 uint64_t src64 = *src64_ptr;
3536 uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->meter.length.n_bits);
3537 uint64_t src = src64 & src64_mask;
3539 return (uint32_t)src;
3542 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
3544 static inline uint32_t
3545 instr_meter_length_nbo(struct thread *t, const struct instruction *ip)
3547 uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
3548 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
3549 uint64_t src64 = *src64_ptr;
3550 uint64_t src = ntoh64(src64) >> (64 - ip->meter.length.n_bits);
3552 return (uint32_t)src;
3557 #define instr_meter_length_nbo instr_meter_length_hbo
3561 static inline enum rte_color
3562 instr_meter_color_in_hbo(struct thread *t, const struct instruction *ip)
3564 uint8_t *src_struct = t->structs[ip->meter.color_in.struct_id];
3565 uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.color_in.offset];
3566 uint64_t src64 = *src64_ptr;
3567 uint64_t src64_mask = UINT64_MAX >> (64 - ip->meter.color_in.n_bits);
3568 uint64_t src = src64 & src64_mask;
3570 return (enum rte_color)src;
3574 instr_meter_color_out_hbo_set(struct thread *t,
3575 const struct instruction *ip,
3576 enum rte_color color_out)
3578 uint8_t *dst_struct = t->structs[ip->meter.color_out.struct_id];
3579 uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->meter.color_out.offset];
3580 uint64_t dst64 = *dst64_ptr;
3581 uint64_t dst64_mask = UINT64_MAX >> (64 - ip->meter.color_out.n_bits);
3583 uint64_t src = (uint64_t)color_out;
3585 *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
3589 __instr_metprefetch_h_exec(struct rte_swx_pipeline *p,
3591 const struct instruction *ip)
3595 TRACE("[Thread %2u] metprefetch (h)\n", p->thread_id);
3597 m = instr_meter_idx_nbo(p, t, ip);
3602 __instr_metprefetch_m_exec(struct rte_swx_pipeline *p,
3604 const struct instruction *ip)
3608 TRACE("[Thread %2u] metprefetch (m)\n", p->thread_id);
3610 m = instr_meter_idx_hbo(p, t, ip);
3615 __instr_metprefetch_i_exec(struct rte_swx_pipeline *p,
3616 struct thread *t __rte_unused,
3617 const struct instruction *ip)
3621 TRACE("[Thread %2u] metprefetch (i)\n", p->thread_id);
3623 m = instr_meter_idx_imm(p, ip);
3628 __instr_meter_hhm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3631 uint64_t time, n_pkts, n_bytes;
3633 enum rte_color color_in, color_out;
3635 TRACE("[Thread %2u] meter (hhm)\n", p->thread_id);
3637 m = instr_meter_idx_nbo(p, t, ip);
3638 rte_prefetch0(m->n_pkts);
3639 time = rte_get_tsc_cycles();
3640 length = instr_meter_length_nbo(t, ip);
3641 color_in = instr_meter_color_in_hbo(t, ip);
3643 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3644 &m->profile->profile,
3649 color_out &= m->color_mask;
3651 n_pkts = m->n_pkts[color_out];
3652 n_bytes = m->n_bytes[color_out];
3654 instr_meter_color_out_hbo_set(t, ip, color_out);
3656 m->n_pkts[color_out] = n_pkts + 1;
3657 m->n_bytes[color_out] = n_bytes + length;
3661 __instr_meter_hhi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3664 uint64_t time, n_pkts, n_bytes;
3666 enum rte_color color_in, color_out;
3668 TRACE("[Thread %2u] meter (hhi)\n", p->thread_id);
3670 m = instr_meter_idx_nbo(p, t, ip);
3671 rte_prefetch0(m->n_pkts);
3672 time = rte_get_tsc_cycles();
3673 length = instr_meter_length_nbo(t, ip);
3674 color_in = (enum rte_color)ip->meter.color_in_val;
3676 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3677 &m->profile->profile,
3682 color_out &= m->color_mask;
3684 n_pkts = m->n_pkts[color_out];
3685 n_bytes = m->n_bytes[color_out];
3687 instr_meter_color_out_hbo_set(t, ip, color_out);
3689 m->n_pkts[color_out] = n_pkts + 1;
3690 m->n_bytes[color_out] = n_bytes + length;
3694 __instr_meter_hmm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3697 uint64_t time, n_pkts, n_bytes;
3699 enum rte_color color_in, color_out;
3701 TRACE("[Thread %2u] meter (hmm)\n", p->thread_id);
3703 m = instr_meter_idx_nbo(p, t, ip);
3704 rte_prefetch0(m->n_pkts);
3705 time = rte_get_tsc_cycles();
3706 length = instr_meter_length_hbo(t, ip);
3707 color_in = instr_meter_color_in_hbo(t, ip);
3709 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3710 &m->profile->profile,
3715 color_out &= m->color_mask;
3717 n_pkts = m->n_pkts[color_out];
3718 n_bytes = m->n_bytes[color_out];
3720 instr_meter_color_out_hbo_set(t, ip, color_out);
3722 m->n_pkts[color_out] = n_pkts + 1;
3723 m->n_bytes[color_out] = n_bytes + length;
3727 __instr_meter_hmi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3730 uint64_t time, n_pkts, n_bytes;
3732 enum rte_color color_in, color_out;
3734 TRACE("[Thread %2u] meter (hmi)\n", p->thread_id);
3736 m = instr_meter_idx_nbo(p, t, ip);
3737 rte_prefetch0(m->n_pkts);
3738 time = rte_get_tsc_cycles();
3739 length = instr_meter_length_hbo(t, ip);
3740 color_in = (enum rte_color)ip->meter.color_in_val;
3742 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3743 &m->profile->profile,
3748 color_out &= m->color_mask;
3750 n_pkts = m->n_pkts[color_out];
3751 n_bytes = m->n_bytes[color_out];
3753 instr_meter_color_out_hbo_set(t, ip, color_out);
3755 m->n_pkts[color_out] = n_pkts + 1;
3756 m->n_bytes[color_out] = n_bytes + length;
3760 __instr_meter_mhm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3763 uint64_t time, n_pkts, n_bytes;
3765 enum rte_color color_in, color_out;
3767 TRACE("[Thread %2u] meter (mhm)\n", p->thread_id);
3769 m = instr_meter_idx_hbo(p, t, ip);
3770 rte_prefetch0(m->n_pkts);
3771 time = rte_get_tsc_cycles();
3772 length = instr_meter_length_nbo(t, ip);
3773 color_in = instr_meter_color_in_hbo(t, ip);
3775 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3776 &m->profile->profile,
3781 color_out &= m->color_mask;
3783 n_pkts = m->n_pkts[color_out];
3784 n_bytes = m->n_bytes[color_out];
3786 instr_meter_color_out_hbo_set(t, ip, color_out);
3788 m->n_pkts[color_out] = n_pkts + 1;
3789 m->n_bytes[color_out] = n_bytes + length;
3793 __instr_meter_mhi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3796 uint64_t time, n_pkts, n_bytes;
3798 enum rte_color color_in, color_out;
3800 TRACE("[Thread %2u] meter (mhi)\n", p->thread_id);
3802 m = instr_meter_idx_hbo(p, t, ip);
3803 rte_prefetch0(m->n_pkts);
3804 time = rte_get_tsc_cycles();
3805 length = instr_meter_length_nbo(t, ip);
3806 color_in = (enum rte_color)ip->meter.color_in_val;
3808 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3809 &m->profile->profile,
3814 color_out &= m->color_mask;
3816 n_pkts = m->n_pkts[color_out];
3817 n_bytes = m->n_bytes[color_out];
3819 instr_meter_color_out_hbo_set(t, ip, color_out);
3821 m->n_pkts[color_out] = n_pkts + 1;
3822 m->n_bytes[color_out] = n_bytes + length;
3826 __instr_meter_mmm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3829 uint64_t time, n_pkts, n_bytes;
3831 enum rte_color color_in, color_out;
3833 TRACE("[Thread %2u] meter (mmm)\n", p->thread_id);
3835 m = instr_meter_idx_hbo(p, t, ip);
3836 rte_prefetch0(m->n_pkts);
3837 time = rte_get_tsc_cycles();
3838 length = instr_meter_length_hbo(t, ip);
3839 color_in = instr_meter_color_in_hbo(t, ip);
3841 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3842 &m->profile->profile,
3847 color_out &= m->color_mask;
3849 n_pkts = m->n_pkts[color_out];
3850 n_bytes = m->n_bytes[color_out];
3852 instr_meter_color_out_hbo_set(t, ip, color_out);
3854 m->n_pkts[color_out] = n_pkts + 1;
3855 m->n_bytes[color_out] = n_bytes + length;
3859 __instr_meter_mmi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3862 uint64_t time, n_pkts, n_bytes;
3864 enum rte_color color_in, color_out;
3866 TRACE("[Thread %2u] meter (mmi)\n", p->thread_id);
3868 m = instr_meter_idx_hbo(p, t, ip);
3869 rte_prefetch0(m->n_pkts);
3870 time = rte_get_tsc_cycles();
3871 length = instr_meter_length_hbo(t, ip);
3872 color_in = (enum rte_color)ip->meter.color_in_val;
3874 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3875 &m->profile->profile,
3880 color_out &= m->color_mask;
3882 n_pkts = m->n_pkts[color_out];
3883 n_bytes = m->n_bytes[color_out];
3885 instr_meter_color_out_hbo_set(t, ip, color_out);
3887 m->n_pkts[color_out] = n_pkts + 1;
3888 m->n_bytes[color_out] = n_bytes + length;
3892 __instr_meter_ihm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3895 uint64_t time, n_pkts, n_bytes;
3897 enum rte_color color_in, color_out;
3899 TRACE("[Thread %2u] meter (ihm)\n", p->thread_id);
3901 m = instr_meter_idx_imm(p, ip);
3902 rte_prefetch0(m->n_pkts);
3903 time = rte_get_tsc_cycles();
3904 length = instr_meter_length_nbo(t, ip);
3905 color_in = instr_meter_color_in_hbo(t, ip);
3907 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3908 &m->profile->profile,
3913 color_out &= m->color_mask;
3915 n_pkts = m->n_pkts[color_out];
3916 n_bytes = m->n_bytes[color_out];
3918 instr_meter_color_out_hbo_set(t, ip, color_out);
3920 m->n_pkts[color_out] = n_pkts + 1;
3921 m->n_bytes[color_out] = n_bytes + length;
3925 __instr_meter_ihi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3928 uint64_t time, n_pkts, n_bytes;
3930 enum rte_color color_in, color_out;
3932 TRACE("[Thread %2u] meter (ihi)\n", p->thread_id);
3934 m = instr_meter_idx_imm(p, ip);
3935 rte_prefetch0(m->n_pkts);
3936 time = rte_get_tsc_cycles();
3937 length = instr_meter_length_nbo(t, ip);
3938 color_in = (enum rte_color)ip->meter.color_in_val;
3940 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3941 &m->profile->profile,
3946 color_out &= m->color_mask;
3948 n_pkts = m->n_pkts[color_out];
3949 n_bytes = m->n_bytes[color_out];
3951 instr_meter_color_out_hbo_set(t, ip, color_out);
3953 m->n_pkts[color_out] = n_pkts + 1;
3954 m->n_bytes[color_out] = n_bytes + length;
3958 __instr_meter_imm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3961 uint64_t time, n_pkts, n_bytes;
3963 enum rte_color color_in, color_out;
3965 TRACE("[Thread %2u] meter (imm)\n", p->thread_id);
3967 m = instr_meter_idx_imm(p, ip);
3968 rte_prefetch0(m->n_pkts);
3969 time = rte_get_tsc_cycles();
3970 length = instr_meter_length_hbo(t, ip);
3971 color_in = instr_meter_color_in_hbo(t, ip);
3973 color_out = rte_meter_trtcm_color_aware_check(&m->m,
3974 &m->profile->profile,
3979 color_out &= m->color_mask;
3981 n_pkts = m->n_pkts[color_out];
3982 n_bytes = m->n_bytes[color_out];
3984 instr_meter_color_out_hbo_set(t, ip, color_out);
3986 m->n_pkts[color_out] = n_pkts + 1;
3987 m->n_bytes[color_out] = n_bytes + length;
3991 __instr_meter_imi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3994 uint64_t time, n_pkts, n_bytes;
3996 enum rte_color color_in, color_out;
3998 TRACE("[Thread %2u] meter (imi)\n", p->thread_id);
4000 m = instr_meter_idx_imm(p, ip);
4001 rte_prefetch0(m->n_pkts);
4002 time = rte_get_tsc_cycles();
4003 length = instr_meter_length_hbo(t, ip);
4004 color_in = (enum rte_color)ip->meter.color_in_val;
4006 color_out = rte_meter_trtcm_color_aware_check(&m->m,
4007 &m->profile->profile,
4012 color_out &= m->color_mask;
4014 n_pkts = m->n_pkts[color_out];
4015 n_bytes = m->n_bytes[color_out];
4017 instr_meter_color_out_hbo_set(t, ip, color_out);
4019 m->n_pkts[color_out] = n_pkts + 1;
4020 m->n_bytes[color_out] = n_bytes + length;