table: improve learner table timers
[dpdk.git] / lib / pipeline / rte_swx_pipeline_internal.h
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2021 Intel Corporation
3  */
4 #ifndef __INCLUDE_RTE_SWX_PIPELINE_INTERNAL_H__
5 #define __INCLUDE_RTE_SWX_PIPELINE_INTERNAL_H__
6
7 #include <inttypes.h>
8 #include <string.h>
9 #include <sys/queue.h>
10
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>
16
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>
21
22 #ifndef TRACE_LEVEL
23 #define TRACE_LEVEL 0
24 #endif
25
26 #if TRACE_LEVEL
27 #define TRACE(...) printf(__VA_ARGS__)
28 #else
29 #define TRACE(...)
30 #endif
31
32 /*
33  * Environment.
34  */
35 #define ntoh64(x) rte_be_to_cpu_64(x)
36 #define hton64(x) rte_cpu_to_be_64(x)
37
38 /*
39  * Struct.
40  */
41 struct field {
42         char name[RTE_SWX_NAME_SIZE];
43         uint32_t n_bits;
44         uint32_t offset;
45         int var_size;
46 };
47
48 struct struct_type {
49         TAILQ_ENTRY(struct_type) node;
50         char name[RTE_SWX_NAME_SIZE];
51         struct field *fields;
52         uint32_t n_fields;
53         uint32_t n_bits;
54         uint32_t n_bits_min;
55         int var_size;
56 };
57
58 TAILQ_HEAD(struct_type_tailq, struct_type);
59
60 /*
61  * Input port.
62  */
63 struct port_in_type {
64         TAILQ_ENTRY(port_in_type) node;
65         char name[RTE_SWX_NAME_SIZE];
66         struct rte_swx_port_in_ops ops;
67 };
68
69 TAILQ_HEAD(port_in_type_tailq, port_in_type);
70
71 struct port_in {
72         TAILQ_ENTRY(port_in) node;
73         struct port_in_type *type;
74         void *obj;
75         uint32_t id;
76 };
77
78 TAILQ_HEAD(port_in_tailq, port_in);
79
80 struct port_in_runtime {
81         rte_swx_port_in_pkt_rx_t pkt_rx;
82         void *obj;
83 };
84
85 /*
86  * Output port.
87  */
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;
92 };
93
94 TAILQ_HEAD(port_out_type_tailq, port_out_type);
95
96 struct port_out {
97         TAILQ_ENTRY(port_out) node;
98         struct port_out_type *type;
99         void *obj;
100         uint32_t id;
101 };
102
103 TAILQ_HEAD(port_out_tailq, port_out);
104
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;
110         void *obj;
111 };
112
113 /*
114  * Packet mirroring.
115  */
116 struct mirroring_session {
117         uint32_t port_id;
118         int fast_clone;
119         uint32_t truncation_length;
120 };
121
122 /*
123  * Extern object.
124  */
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;
129         uint32_t id;
130 };
131
132 TAILQ_HEAD(extern_type_member_func_tailq, extern_type_member_func);
133
134 struct extern_type {
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;
141         uint32_t n_funcs;
142 };
143
144 TAILQ_HEAD(extern_type_tailq, extern_type);
145
146 struct extern_obj {
147         TAILQ_ENTRY(extern_obj) node;
148         char name[RTE_SWX_NAME_SIZE];
149         struct extern_type *type;
150         void *obj;
151         uint32_t struct_id;
152         uint32_t id;
153 };
154
155 TAILQ_HEAD(extern_obj_tailq, extern_obj);
156
157 #ifndef RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX
158 #define RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX 8
159 #endif
160
161 struct extern_obj_runtime {
162         void *obj;
163         uint8_t *mailbox;
164         rte_swx_extern_type_member_func_t funcs[RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX];
165 };
166
167 /*
168  * Extern function.
169  */
170 struct extern_func {
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;
175         uint32_t struct_id;
176         uint32_t id;
177 };
178
179 TAILQ_HEAD(extern_func_tailq, extern_func);
180
181 struct extern_func_runtime {
182         uint8_t *mailbox;
183         rte_swx_extern_func_t func;
184 };
185
186 /*
187  * Header.
188  */
189 struct header {
190         TAILQ_ENTRY(header) node;
191         char name[RTE_SWX_NAME_SIZE];
192         struct struct_type *st;
193         uint32_t struct_id;
194         uint32_t id;
195 };
196
197 TAILQ_HEAD(header_tailq, header);
198
199 struct header_runtime {
200         uint8_t *ptr0;
201         uint32_t n_bytes;
202 };
203
204 struct header_out_runtime {
205         uint8_t *ptr0;
206         uint8_t *ptr;
207         uint32_t n_bytes;
208 };
209
210 /*
211  * Instruction.
212  */
213
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
218  * headers.
219  */
220
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)
228  */
229
230 enum instruction_type {
231         /* rx m.port_in */
232         INSTR_RX,
233
234         /* tx port_out
235          * port_out = MI
236          */
237         INSTR_TX,   /* port_out = M */
238         INSTR_TX_I, /* port_out = I */
239         INSTR_DROP,
240
241         /*
242          * mirror slot_id session_id
243          * slot_id = MEFT
244          * session_id = MEFT
245          */
246         INSTR_MIRROR,
247
248         /* recirculate
249          */
250         INSTR_RECIRCULATE,
251
252         /* recircid m.recirc_pass_id
253          * Read the internal recirculation pass ID into the specified meta-data field.
254          */
255         INSTR_RECIRCID,
256
257         /* extract h.header */
258         INSTR_HDR_EXTRACT,
259         INSTR_HDR_EXTRACT2,
260         INSTR_HDR_EXTRACT3,
261         INSTR_HDR_EXTRACT4,
262         INSTR_HDR_EXTRACT5,
263         INSTR_HDR_EXTRACT6,
264         INSTR_HDR_EXTRACT7,
265         INSTR_HDR_EXTRACT8,
266
267         /* extract h.header m.last_field_size */
268         INSTR_HDR_EXTRACT_M,
269
270         /* lookahead h.header */
271         INSTR_HDR_LOOKAHEAD,
272
273         /* emit h.header */
274         INSTR_HDR_EMIT,
275         INSTR_HDR_EMIT_TX,
276         INSTR_HDR_EMIT2_TX,
277         INSTR_HDR_EMIT3_TX,
278         INSTR_HDR_EMIT4_TX,
279         INSTR_HDR_EMIT5_TX,
280         INSTR_HDR_EMIT6_TX,
281         INSTR_HDR_EMIT7_TX,
282         INSTR_HDR_EMIT8_TX,
283
284         /* validate h.header */
285         INSTR_HDR_VALIDATE,
286
287         /* invalidate h.header */
288         INSTR_HDR_INVALIDATE,
289
290         /* mov dst src
291          * dst = src
292          * dst = HMEF, src = HMEFTI
293          */
294         INSTR_MOV,    /* dst = MEF, src = MEFT */
295         INSTR_MOV_MH, /* dst = MEF, src = H */
296         INSTR_MOV_HM, /* dst = H, src = MEFT */
297         INSTR_MOV_HH, /* dst = H, src = H */
298         INSTR_MOV_I,  /* dst = HMEF, src = I */
299
300         /* dma h.header t.field
301          * memcpy(h.header, t.field, sizeof(h.header))
302          */
303         INSTR_DMA_HT,
304         INSTR_DMA_HT2,
305         INSTR_DMA_HT3,
306         INSTR_DMA_HT4,
307         INSTR_DMA_HT5,
308         INSTR_DMA_HT6,
309         INSTR_DMA_HT7,
310         INSTR_DMA_HT8,
311
312         /* add dst src
313          * dst += src
314          * dst = HMEF, src = HMEFTI
315          */
316         INSTR_ALU_ADD,    /* dst = MEF, src = MEF */
317         INSTR_ALU_ADD_MH, /* dst = MEF, src = H */
318         INSTR_ALU_ADD_HM, /* dst = H, src = MEF */
319         INSTR_ALU_ADD_HH, /* dst = H, src = H */
320         INSTR_ALU_ADD_MI, /* dst = MEF, src = I */
321         INSTR_ALU_ADD_HI, /* dst = H, src = I */
322
323         /* sub dst src
324          * dst -= src
325          * dst = HMEF, src = HMEFTI
326          */
327         INSTR_ALU_SUB,    /* dst = MEF, src = MEF */
328         INSTR_ALU_SUB_MH, /* dst = MEF, src = H */
329         INSTR_ALU_SUB_HM, /* dst = H, src = MEF */
330         INSTR_ALU_SUB_HH, /* dst = H, src = H */
331         INSTR_ALU_SUB_MI, /* dst = MEF, src = I */
332         INSTR_ALU_SUB_HI, /* dst = H, src = I */
333
334         /* ckadd dst src
335          * dst = dst '+ src[0:1] '+ src[2:3] '+ ...
336          * dst = H, src = {H, h.header}, '+ = 1's complement addition operator
337          */
338         INSTR_ALU_CKADD_FIELD,    /* src = H */
339         INSTR_ALU_CKADD_STRUCT20, /* src = h.header, with sizeof(header) = 20 bytes. */
340         INSTR_ALU_CKADD_STRUCT,   /* src = h.header, with sizeof(header) any 4-byte multiple. */
341
342         /* cksub dst src
343          * dst = dst '- src
344          * dst = H, src = H, '- = 1's complement subtraction operator
345          */
346         INSTR_ALU_CKSUB_FIELD,
347
348         /* and dst src
349          * dst &= src
350          * dst = HMEF, src = HMEFTI
351          */
352         INSTR_ALU_AND,    /* dst = MEF, src = MEFT */
353         INSTR_ALU_AND_MH, /* dst = MEF, src = H */
354         INSTR_ALU_AND_HM, /* dst = H, src = MEFT */
355         INSTR_ALU_AND_HH, /* dst = H, src = H */
356         INSTR_ALU_AND_I,  /* dst = HMEF, src = I */
357
358         /* or dst src
359          * dst |= src
360          * dst = HMEF, src = HMEFTI
361          */
362         INSTR_ALU_OR,    /* dst = MEF, src = MEFT */
363         INSTR_ALU_OR_MH, /* dst = MEF, src = H */
364         INSTR_ALU_OR_HM, /* dst = H, src = MEFT */
365         INSTR_ALU_OR_HH, /* dst = H, src = H */
366         INSTR_ALU_OR_I,  /* dst = HMEF, src = I */
367
368         /* xor dst src
369          * dst ^= src
370          * dst = HMEF, src = HMEFTI
371          */
372         INSTR_ALU_XOR,    /* dst = MEF, src = MEFT */
373         INSTR_ALU_XOR_MH, /* dst = MEF, src = H */
374         INSTR_ALU_XOR_HM, /* dst = H, src = MEFT */
375         INSTR_ALU_XOR_HH, /* dst = H, src = H */
376         INSTR_ALU_XOR_I,  /* dst = HMEF, src = I */
377
378         /* shl dst src
379          * dst <<= src
380          * dst = HMEF, src = HMEFTI
381          */
382         INSTR_ALU_SHL,    /* dst = MEF, src = MEF */
383         INSTR_ALU_SHL_MH, /* dst = MEF, src = H */
384         INSTR_ALU_SHL_HM, /* dst = H, src = MEF */
385         INSTR_ALU_SHL_HH, /* dst = H, src = H */
386         INSTR_ALU_SHL_MI, /* dst = MEF, src = I */
387         INSTR_ALU_SHL_HI, /* dst = H, src = I */
388
389         /* shr dst src
390          * dst >>= src
391          * dst = HMEF, src = HMEFTI
392          */
393         INSTR_ALU_SHR,    /* dst = MEF, src = MEF */
394         INSTR_ALU_SHR_MH, /* dst = MEF, src = H */
395         INSTR_ALU_SHR_HM, /* dst = H, src = MEF */
396         INSTR_ALU_SHR_HH, /* dst = H, src = H */
397         INSTR_ALU_SHR_MI, /* dst = MEF, src = I */
398         INSTR_ALU_SHR_HI, /* dst = H, src = I */
399
400         /* regprefetch REGARRAY index
401          * prefetch REGARRAY[index]
402          * index = HMEFTI
403          */
404         INSTR_REGPREFETCH_RH, /* index = H */
405         INSTR_REGPREFETCH_RM, /* index = MEFT */
406         INSTR_REGPREFETCH_RI, /* index = I */
407
408         /* regrd dst REGARRAY index
409          * dst = REGARRAY[index]
410          * dst = HMEF, index = HMEFTI
411          */
412         INSTR_REGRD_HRH, /* dst = H, index = H */
413         INSTR_REGRD_HRM, /* dst = H, index = MEFT */
414         INSTR_REGRD_HRI, /* dst = H, index = I */
415         INSTR_REGRD_MRH, /* dst = MEF, index = H */
416         INSTR_REGRD_MRM, /* dst = MEF, index = MEFT */
417         INSTR_REGRD_MRI, /* dst = MEF, index = I */
418
419         /* regwr REGARRAY index src
420          * REGARRAY[index] = src
421          * index = HMEFTI, src = HMEFTI
422          */
423         INSTR_REGWR_RHH, /* index = H, src = H */
424         INSTR_REGWR_RHM, /* index = H, src = MEFT */
425         INSTR_REGWR_RHI, /* index = H, src = I */
426         INSTR_REGWR_RMH, /* index = MEFT, src = H */
427         INSTR_REGWR_RMM, /* index = MEFT, src = MEFT */
428         INSTR_REGWR_RMI, /* index = MEFT, src = I */
429         INSTR_REGWR_RIH, /* index = I, src = H */
430         INSTR_REGWR_RIM, /* index = I, src = MEFT */
431         INSTR_REGWR_RII, /* index = I, src = I */
432
433         /* regadd REGARRAY index src
434          * REGARRAY[index] += src
435          * index = HMEFTI, src = HMEFTI
436          */
437         INSTR_REGADD_RHH, /* index = H, src = H */
438         INSTR_REGADD_RHM, /* index = H, src = MEFT */
439         INSTR_REGADD_RHI, /* index = H, src = I */
440         INSTR_REGADD_RMH, /* index = MEFT, src = H */
441         INSTR_REGADD_RMM, /* index = MEFT, src = MEFT */
442         INSTR_REGADD_RMI, /* index = MEFT, src = I */
443         INSTR_REGADD_RIH, /* index = I, src = H */
444         INSTR_REGADD_RIM, /* index = I, src = MEFT */
445         INSTR_REGADD_RII, /* index = I, src = I */
446
447         /* metprefetch METARRAY index
448          * prefetch METARRAY[index]
449          * index = HMEFTI
450          */
451         INSTR_METPREFETCH_H, /* index = H */
452         INSTR_METPREFETCH_M, /* index = MEFT */
453         INSTR_METPREFETCH_I, /* index = I */
454
455         /* meter METARRAY index length color_in color_out
456          * color_out = meter(METARRAY[index], length, color_in)
457          * index = HMEFTI, length = HMEFT, color_in = MEFTI, color_out = MEF
458          */
459         INSTR_METER_HHM, /* index = H, length = H, color_in = MEFT */
460         INSTR_METER_HHI, /* index = H, length = H, color_in = I */
461         INSTR_METER_HMM, /* index = H, length = MEFT, color_in = MEFT */
462         INSTR_METER_HMI, /* index = H, length = MEFT, color_in = I */
463         INSTR_METER_MHM, /* index = MEFT, length = H, color_in = MEFT */
464         INSTR_METER_MHI, /* index = MEFT, length = H, color_in = I */
465         INSTR_METER_MMM, /* index = MEFT, length = MEFT, color_in = MEFT */
466         INSTR_METER_MMI, /* index = MEFT, length = MEFT, color_in = I */
467         INSTR_METER_IHM, /* index = I, length = H, color_in = MEFT */
468         INSTR_METER_IHI, /* index = I, length = H, color_in = I */
469         INSTR_METER_IMM, /* index = I, length = MEFT, color_in = MEFT */
470         INSTR_METER_IMI, /* index = I, length = MEFT, color_in = I */
471
472         /* table TABLE */
473         INSTR_TABLE,
474         INSTR_TABLE_AF,
475         INSTR_SELECTOR,
476         INSTR_LEARNER,
477         INSTR_LEARNER_AF,
478
479         /* learn LEARNER ACTION_NAME [ m.action_first_arg ] */
480         INSTR_LEARNER_LEARN,
481
482         /* forget */
483         INSTR_LEARNER_FORGET,
484
485         /* extern e.obj.func */
486         INSTR_EXTERN_OBJ,
487
488         /* extern f.func */
489         INSTR_EXTERN_FUNC,
490
491         /* jmp LABEL
492          * Unconditional jump
493          */
494         INSTR_JMP,
495
496         /* jmpv LABEL h.header
497          * Jump if header is valid
498          */
499         INSTR_JMP_VALID,
500
501         /* jmpnv LABEL h.header
502          * Jump if header is invalid
503          */
504         INSTR_JMP_INVALID,
505
506         /* jmph LABEL
507          * Jump if table lookup hit
508          */
509         INSTR_JMP_HIT,
510
511         /* jmpnh LABEL
512          * Jump if table lookup miss
513          */
514         INSTR_JMP_MISS,
515
516         /* jmpa LABEL ACTION
517          * Jump if action run
518          */
519         INSTR_JMP_ACTION_HIT,
520
521         /* jmpna LABEL ACTION
522          * Jump if action not run
523          */
524         INSTR_JMP_ACTION_MISS,
525
526         /* jmpeq LABEL a b
527          * Jump if a is equal to b
528          * a = HMEFT, b = HMEFTI
529          */
530         INSTR_JMP_EQ,    /* a = MEFT, b = MEFT */
531         INSTR_JMP_EQ_MH, /* a = MEFT, b = H */
532         INSTR_JMP_EQ_HM, /* a = H, b = MEFT */
533         INSTR_JMP_EQ_HH, /* a = H, b = H */
534         INSTR_JMP_EQ_I,  /* (a, b) = (MEFT, I) or (a, b) = (H, I) */
535
536         /* jmpneq LABEL a b
537          * Jump if a is not equal to b
538          * a = HMEFT, b = HMEFTI
539          */
540         INSTR_JMP_NEQ,    /* a = MEFT, b = MEFT */
541         INSTR_JMP_NEQ_MH, /* a = MEFT, b = H */
542         INSTR_JMP_NEQ_HM, /* a = H, b = MEFT */
543         INSTR_JMP_NEQ_HH, /* a = H, b = H */
544         INSTR_JMP_NEQ_I,  /* (a, b) = (MEFT, I) or (a, b) = (H, I) */
545
546         /* jmplt LABEL a b
547          * Jump if a is less than b
548          * a = HMEFT, b = HMEFTI
549          */
550         INSTR_JMP_LT,    /* a = MEFT, b = MEFT */
551         INSTR_JMP_LT_MH, /* a = MEFT, b = H */
552         INSTR_JMP_LT_HM, /* a = H, b = MEFT */
553         INSTR_JMP_LT_HH, /* a = H, b = H */
554         INSTR_JMP_LT_MI, /* a = MEFT, b = I */
555         INSTR_JMP_LT_HI, /* a = H, b = I */
556
557         /* jmpgt LABEL a b
558          * Jump if a is greater than b
559          * a = HMEFT, b = HMEFTI
560          */
561         INSTR_JMP_GT,    /* a = MEFT, b = MEFT */
562         INSTR_JMP_GT_MH, /* a = MEFT, b = H */
563         INSTR_JMP_GT_HM, /* a = H, b = MEFT */
564         INSTR_JMP_GT_HH, /* a = H, b = H */
565         INSTR_JMP_GT_MI, /* a = MEFT, b = I */
566         INSTR_JMP_GT_HI, /* a = H, b = I */
567
568         /* return
569          * Return from action
570          */
571         INSTR_RETURN,
572
573         /* Start of custom instructions. */
574         INSTR_CUSTOM_0,
575 };
576
577 struct instr_operand {
578         uint8_t struct_id;
579         uint8_t n_bits;
580         uint8_t offset;
581         uint8_t pad;
582 };
583
584 struct instr_io {
585         struct {
586                 union {
587                         struct {
588                                 uint8_t offset;
589                                 uint8_t n_bits;
590                                 uint8_t pad[2];
591                         };
592
593                         uint32_t val;
594                 };
595         } io;
596
597         struct {
598                 uint8_t header_id[8];
599                 uint8_t struct_id[8];
600                 uint8_t n_bytes[8];
601         } hdr;
602 };
603
604 struct instr_hdr_validity {
605         uint8_t header_id;
606 };
607
608 struct instr_table {
609         uint8_t table_id;
610 };
611
612 struct instr_learn {
613         uint8_t action_id;
614         uint8_t mf_offset;
615 };
616
617 struct instr_extern_obj {
618         uint8_t ext_obj_id;
619         uint8_t func_id;
620 };
621
622 struct instr_extern_func {
623         uint8_t ext_func_id;
624 };
625
626 struct instr_dst_src {
627         struct instr_operand dst;
628         union {
629                 struct instr_operand src;
630                 uint64_t src_val;
631         };
632 };
633
634 struct instr_regarray {
635         uint8_t regarray_id;
636         uint8_t pad[3];
637
638         union {
639                 struct instr_operand idx;
640                 uint32_t idx_val;
641         };
642
643         union {
644                 struct instr_operand dstsrc;
645                 uint64_t dstsrc_val;
646         };
647 };
648
649 struct instr_meter {
650         uint8_t metarray_id;
651         uint8_t pad[3];
652
653         union {
654                 struct instr_operand idx;
655                 uint32_t idx_val;
656         };
657
658         struct instr_operand length;
659
660         union {
661                 struct instr_operand color_in;
662                 uint32_t color_in_val;
663         };
664
665         struct instr_operand color_out;
666 };
667
668 struct instr_dma {
669         struct {
670                 uint8_t header_id[8];
671                 uint8_t struct_id[8];
672         } dst;
673
674         struct {
675                 uint8_t offset[8];
676         } src;
677
678         uint16_t n_bytes[8];
679 };
680
681 struct instr_jmp {
682         struct instruction *ip;
683
684         union {
685                 struct instr_operand a;
686                 uint8_t header_id;
687                 uint8_t action_id;
688         };
689
690         union {
691                 struct instr_operand b;
692                 uint64_t b_val;
693         };
694 };
695
696 struct instruction {
697         enum instruction_type type;
698         union {
699                 struct instr_io io;
700                 struct instr_dst_src mirror;
701                 struct instr_hdr_validity valid;
702                 struct instr_dst_src mov;
703                 struct instr_regarray regarray;
704                 struct instr_meter meter;
705                 struct instr_dma dma;
706                 struct instr_dst_src alu;
707                 struct instr_table table;
708                 struct instr_learn learn;
709                 struct instr_extern_obj ext_obj;
710                 struct instr_extern_func ext_func;
711                 struct instr_jmp jmp;
712         };
713 };
714
715 struct instruction_data {
716         char label[RTE_SWX_NAME_SIZE];
717         char jmp_label[RTE_SWX_NAME_SIZE];
718         uint32_t n_users; /* user = jmp instruction to this instruction. */
719         int invalid;
720 };
721
722 typedef void (*instr_exec_t)(struct rte_swx_pipeline *);
723
724 /*
725  * Action.
726  */
727 typedef void
728 (*action_func_t)(struct rte_swx_pipeline *p);
729
730 struct action {
731         TAILQ_ENTRY(action) node;
732         char name[RTE_SWX_NAME_SIZE];
733         struct struct_type *st;
734         int *args_endianness; /* 0 = Host Byte Order (HBO); 1 = Network Byte Order (NBO). */
735         struct instruction *instructions;
736         struct instruction_data *instruction_data;
737         uint32_t n_instructions;
738         uint32_t id;
739 };
740
741 TAILQ_HEAD(action_tailq, action);
742
743 /*
744  * Table.
745  */
746 struct table_type {
747         TAILQ_ENTRY(table_type) node;
748         char name[RTE_SWX_NAME_SIZE];
749         enum rte_swx_table_match_type match_type;
750         struct rte_swx_table_ops ops;
751 };
752
753 TAILQ_HEAD(table_type_tailq, table_type);
754
755 struct match_field {
756         enum rte_swx_table_match_type match_type;
757         struct field *field;
758 };
759
760 struct table {
761         TAILQ_ENTRY(table) node;
762         char name[RTE_SWX_NAME_SIZE];
763         char args[RTE_SWX_NAME_SIZE];
764         struct table_type *type; /* NULL when n_fields == 0. */
765
766         /* Match. */
767         struct match_field *fields;
768         uint32_t n_fields;
769         struct header *header; /* Only valid when n_fields > 0. */
770
771         /* Action. */
772         struct action **actions;
773         struct action *default_action;
774         uint8_t *default_action_data;
775         uint32_t n_actions;
776         int default_action_is_const;
777         uint32_t action_data_size_max;
778         int *action_is_for_table_entries;
779         int *action_is_for_default_entry;
780
781         uint32_t size;
782         uint32_t id;
783 };
784
785 TAILQ_HEAD(table_tailq, table);
786
787 struct table_runtime {
788         rte_swx_table_lookup_t func;
789         void *mailbox;
790         uint8_t **key;
791 };
792
793 struct table_statistics {
794         uint64_t n_pkts_hit[2]; /* 0 = Miss, 1 = Hit. */
795         uint64_t *n_pkts_action;
796 };
797
798 /*
799  * Selector.
800  */
801 struct selector {
802         TAILQ_ENTRY(selector) node;
803         char name[RTE_SWX_NAME_SIZE];
804
805         struct field *group_id_field;
806         struct field **selector_fields;
807         uint32_t n_selector_fields;
808         struct header *selector_header;
809         struct field *member_id_field;
810
811         uint32_t n_groups_max;
812         uint32_t n_members_per_group_max;
813
814         uint32_t id;
815 };
816
817 TAILQ_HEAD(selector_tailq, selector);
818
819 struct selector_runtime {
820         void *mailbox;
821         uint8_t **group_id_buffer;
822         uint8_t **selector_buffer;
823         uint8_t **member_id_buffer;
824 };
825
826 struct selector_statistics {
827         uint64_t n_pkts;
828 };
829
830 /*
831  * Learner table.
832  */
833 struct learner {
834         TAILQ_ENTRY(learner) node;
835         char name[RTE_SWX_NAME_SIZE];
836
837         /* Match. */
838         struct field **fields;
839         uint32_t n_fields;
840         struct header *header;
841
842         /* Action. */
843         struct action **actions;
844         struct action *default_action;
845         uint8_t *default_action_data;
846         uint32_t n_actions;
847         int default_action_is_const;
848         uint32_t action_data_size_max;
849         int *action_is_for_table_entries;
850         int *action_is_for_default_entry;
851
852         uint32_t size;
853         uint32_t timeout;
854         uint32_t id;
855 };
856
857 TAILQ_HEAD(learner_tailq, learner);
858
859 struct learner_runtime {
860         void *mailbox;
861         uint8_t **key;
862 };
863
864 struct learner_statistics {
865         uint64_t n_pkts_hit[2]; /* 0 = Miss, 1 = Hit. */
866         uint64_t n_pkts_learn[2]; /* 0 = Learn OK, 1 = Learn error. */
867         uint64_t n_pkts_forget;
868         uint64_t *n_pkts_action;
869 };
870
871 /*
872  * Register array.
873  */
874 struct regarray {
875         TAILQ_ENTRY(regarray) node;
876         char name[RTE_SWX_NAME_SIZE];
877         uint64_t init_val;
878         uint32_t size;
879         uint32_t id;
880 };
881
882 TAILQ_HEAD(regarray_tailq, regarray);
883
884 struct regarray_runtime {
885         uint64_t *regarray;
886         uint32_t size_mask;
887 };
888
889 /*
890  * Meter array.
891  */
892 struct meter_profile {
893         TAILQ_ENTRY(meter_profile) node;
894         char name[RTE_SWX_NAME_SIZE];
895         struct rte_meter_trtcm_params params;
896         struct rte_meter_trtcm_profile profile;
897         uint32_t n_users;
898 };
899
900 TAILQ_HEAD(meter_profile_tailq, meter_profile);
901
902 struct metarray {
903         TAILQ_ENTRY(metarray) node;
904         char name[RTE_SWX_NAME_SIZE];
905         uint32_t size;
906         uint32_t id;
907 };
908
909 TAILQ_HEAD(metarray_tailq, metarray);
910
911 struct meter {
912         struct rte_meter_trtcm m;
913         struct meter_profile *profile;
914         enum rte_color color_mask;
915         uint8_t pad[20];
916
917         uint64_t n_pkts[RTE_COLORS];
918         uint64_t n_bytes[RTE_COLORS];
919 };
920
921 struct metarray_runtime {
922         struct meter *metarray;
923         uint32_t size_mask;
924 };
925
926 /*
927  * Pipeline.
928  */
929 struct thread {
930         /* Packet. */
931         struct rte_swx_pkt pkt;
932         uint8_t *ptr;
933         uint32_t *mirroring_slots;
934         uint64_t mirroring_slots_mask;
935         int recirculate;
936         uint32_t recirc_pass_id;
937
938         /* Structures. */
939         uint8_t **structs;
940
941         /* Packet headers. */
942         struct header_runtime *headers; /* Extracted or generated headers. */
943         struct header_out_runtime *headers_out; /* Emitted headers. */
944         uint8_t *header_storage;
945         uint8_t *header_out_storage;
946         uint64_t valid_headers;
947         uint32_t n_headers_out;
948
949         /* Packet meta-data. */
950         uint8_t *metadata;
951
952         /* Tables. */
953         struct table_runtime *tables;
954         struct selector_runtime *selectors;
955         struct learner_runtime *learners;
956         struct rte_swx_table_state *table_state;
957         uint64_t action_id;
958         int hit; /* 0 = Miss, 1 = Hit. */
959         uint32_t learner_id;
960         uint64_t time;
961
962         /* Extern objects and functions. */
963         struct extern_obj_runtime *extern_objs;
964         struct extern_func_runtime *extern_funcs;
965
966         /* Instructions. */
967         struct instruction *ip;
968         struct instruction *ret;
969 };
970
971 #define MASK64_BIT_GET(mask, pos) ((mask) & (1LLU << (pos)))
972 #define MASK64_BIT_SET(mask, pos) ((mask) | (1LLU << (pos)))
973 #define MASK64_BIT_CLR(mask, pos) ((mask) & ~(1LLU << (pos)))
974
975 #define HEADER_VALID(thread, header_id) \
976         MASK64_BIT_GET((thread)->valid_headers, header_id)
977
978 static inline uint64_t
979 instr_operand_hbo(struct thread *t, const struct instr_operand *x)
980 {
981         uint8_t *x_struct = t->structs[x->struct_id];
982         uint64_t *x64_ptr = (uint64_t *)&x_struct[x->offset];
983         uint64_t x64 = *x64_ptr;
984         uint64_t x64_mask = UINT64_MAX >> (64 - x->n_bits);
985
986         return x64 & x64_mask;
987 }
988
989 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
990
991 static inline uint64_t
992 instr_operand_nbo(struct thread *t, const struct instr_operand *x)
993 {
994         uint8_t *x_struct = t->structs[x->struct_id];
995         uint64_t *x64_ptr = (uint64_t *)&x_struct[x->offset];
996         uint64_t x64 = *x64_ptr;
997
998         return ntoh64(x64) >> (64 - x->n_bits);
999 }
1000
1001 #else
1002
1003 #define instr_operand_nbo instr_operand_hbo
1004
1005 #endif
1006
1007 #define ALU(thread, ip, operator)  \
1008 {                                                                              \
1009         uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id];      \
1010         uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset];   \
1011         uint64_t dst64 = *dst64_ptr;                                           \
1012         uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits);       \
1013         uint64_t dst = dst64 & dst64_mask;                                     \
1014                                                                                \
1015         uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id];      \
1016         uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset];   \
1017         uint64_t src64 = *src64_ptr;                                           \
1018         uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->alu.src.n_bits);       \
1019         uint64_t src = src64 & src64_mask;                                     \
1020                                                                                \
1021         uint64_t result = dst operator src;                                    \
1022                                                                                \
1023         *dst64_ptr = (dst64 & ~dst64_mask) | (result & dst64_mask);            \
1024 }
1025
1026 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1027
1028 #define ALU_MH(thread, ip, operator)  \
1029 {                                                                              \
1030         uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id];      \
1031         uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset];   \
1032         uint64_t dst64 = *dst64_ptr;                                           \
1033         uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits);       \
1034         uint64_t dst = dst64 & dst64_mask;                                     \
1035                                                                                \
1036         uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id];      \
1037         uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset];   \
1038         uint64_t src64 = *src64_ptr;                                           \
1039         uint64_t src = ntoh64(src64) >> (64 - (ip)->alu.src.n_bits);           \
1040                                                                                \
1041         uint64_t result = dst operator src;                                    \
1042                                                                                \
1043         *dst64_ptr = (dst64 & ~dst64_mask) | (result & dst64_mask);            \
1044 }
1045
1046 #define ALU_HM(thread, ip, operator)  \
1047 {                                                                              \
1048         uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id];      \
1049         uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset];   \
1050         uint64_t dst64 = *dst64_ptr;                                           \
1051         uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits);       \
1052         uint64_t dst = ntoh64(dst64) >> (64 - (ip)->alu.dst.n_bits);           \
1053                                                                                \
1054         uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id];      \
1055         uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset];   \
1056         uint64_t src64 = *src64_ptr;                                           \
1057         uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->alu.src.n_bits);       \
1058         uint64_t src = src64 & src64_mask;                                     \
1059                                                                                \
1060         uint64_t result = dst operator src;                                    \
1061         result = hton64(result << (64 - (ip)->alu.dst.n_bits));                \
1062                                                                                \
1063         *dst64_ptr = (dst64 & ~dst64_mask) | result;                           \
1064 }
1065
1066 #define ALU_HM_FAST(thread, ip, operator)  \
1067 {                                                                                 \
1068         uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id];         \
1069         uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset];      \
1070         uint64_t dst64 = *dst64_ptr;                                              \
1071         uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits);          \
1072         uint64_t dst = dst64 & dst64_mask;                                        \
1073                                                                                   \
1074         uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id];         \
1075         uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset];      \
1076         uint64_t src64 = *src64_ptr;                                              \
1077         uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->alu.src.n_bits);          \
1078         uint64_t src = hton64(src64 & src64_mask) >> (64 - (ip)->alu.dst.n_bits); \
1079                                                                                   \
1080         uint64_t result = dst operator src;                                       \
1081                                                                                   \
1082         *dst64_ptr = (dst64 & ~dst64_mask) | result;                              \
1083 }
1084
1085 #define ALU_HH(thread, ip, operator)  \
1086 {                                                                              \
1087         uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id];      \
1088         uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset];   \
1089         uint64_t dst64 = *dst64_ptr;                                           \
1090         uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits);       \
1091         uint64_t dst = ntoh64(dst64) >> (64 - (ip)->alu.dst.n_bits);           \
1092                                                                                \
1093         uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id];      \
1094         uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset];   \
1095         uint64_t src64 = *src64_ptr;                                           \
1096         uint64_t src = ntoh64(src64) >> (64 - (ip)->alu.src.n_bits);           \
1097                                                                                \
1098         uint64_t result = dst operator src;                                    \
1099         result = hton64(result << (64 - (ip)->alu.dst.n_bits));                \
1100                                                                                \
1101         *dst64_ptr = (dst64 & ~dst64_mask) | result;                           \
1102 }
1103
1104 #define ALU_HH_FAST(thread, ip, operator)  \
1105 {                                                                                             \
1106         uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id];                     \
1107         uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset];                  \
1108         uint64_t dst64 = *dst64_ptr;                                                          \
1109         uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits);                      \
1110         uint64_t dst = dst64 & dst64_mask;                                                    \
1111                                                                                               \
1112         uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id];                     \
1113         uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset];                  \
1114         uint64_t src64 = *src64_ptr;                                                          \
1115         uint64_t src = (src64 << (64 - (ip)->alu.src.n_bits)) >> (64 - (ip)->alu.dst.n_bits); \
1116                                                                                               \
1117         uint64_t result = dst operator src;                                                   \
1118                                                                                               \
1119         *dst64_ptr = (dst64 & ~dst64_mask) | result;                                          \
1120 }
1121
1122 #else
1123
1124 #define ALU_MH ALU
1125 #define ALU_HM ALU
1126 #define ALU_HM_FAST ALU
1127 #define ALU_HH ALU
1128 #define ALU_HH_FAST ALU
1129
1130 #endif
1131
1132 #define ALU_I(thread, ip, operator)  \
1133 {                                                                              \
1134         uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id];      \
1135         uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset];   \
1136         uint64_t dst64 = *dst64_ptr;                                           \
1137         uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits);       \
1138         uint64_t dst = dst64 & dst64_mask;                                     \
1139                                                                                \
1140         uint64_t src = (ip)->alu.src_val;                                      \
1141                                                                                \
1142         uint64_t result = dst operator src;                                    \
1143                                                                                \
1144         *dst64_ptr = (dst64 & ~dst64_mask) | (result & dst64_mask);            \
1145 }
1146
1147 #define ALU_MI ALU_I
1148
1149 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1150
1151 #define ALU_HI(thread, ip, operator)  \
1152 {                                                                              \
1153         uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id];      \
1154         uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset];   \
1155         uint64_t dst64 = *dst64_ptr;                                           \
1156         uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits);       \
1157         uint64_t dst = ntoh64(dst64) >> (64 - (ip)->alu.dst.n_bits);           \
1158                                                                                \
1159         uint64_t src = (ip)->alu.src_val;                                      \
1160                                                                                \
1161         uint64_t result = dst operator src;                                    \
1162         result = hton64(result << (64 - (ip)->alu.dst.n_bits));                \
1163                                                                                \
1164         *dst64_ptr = (dst64 & ~dst64_mask) | result;                           \
1165 }
1166
1167 #else
1168
1169 #define ALU_HI ALU_I
1170
1171 #endif
1172
1173 #define MOV(thread, ip)  \
1174 {                                                                              \
1175         uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id];      \
1176         uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset];   \
1177         uint64_t dst64 = *dst64_ptr;                                           \
1178         uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits);       \
1179                                                                                \
1180         uint8_t *src_struct = (thread)->structs[(ip)->mov.src.struct_id];      \
1181         uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->mov.src.offset];   \
1182         uint64_t src64 = *src64_ptr;                                           \
1183         uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->mov.src.n_bits);       \
1184         uint64_t src = src64 & src64_mask;                                     \
1185                                                                                \
1186         *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);               \
1187 }
1188
1189 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1190
1191 #define MOV_MH(thread, ip)  \
1192 {                                                                              \
1193         uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id];      \
1194         uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset];   \
1195         uint64_t dst64 = *dst64_ptr;                                           \
1196         uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits);       \
1197                                                                                \
1198         uint8_t *src_struct = (thread)->structs[(ip)->mov.src.struct_id];      \
1199         uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->mov.src.offset];   \
1200         uint64_t src64 = *src64_ptr;                                           \
1201         uint64_t src = ntoh64(src64) >> (64 - (ip)->mov.src.n_bits);           \
1202                                                                                \
1203         *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);               \
1204 }
1205
1206 #define MOV_HM(thread, ip)  \
1207 {                                                                              \
1208         uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id];      \
1209         uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset];   \
1210         uint64_t dst64 = *dst64_ptr;                                           \
1211         uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits);       \
1212                                                                                \
1213         uint8_t *src_struct = (thread)->structs[(ip)->mov.src.struct_id];      \
1214         uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->mov.src.offset];   \
1215         uint64_t src64 = *src64_ptr;                                           \
1216         uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->mov.src.n_bits);       \
1217         uint64_t src = src64 & src64_mask;                                     \
1218                                                                                \
1219         src = hton64(src) >> (64 - (ip)->mov.dst.n_bits);                      \
1220         *dst64_ptr = (dst64 & ~dst64_mask) | src;                              \
1221 }
1222
1223 #define MOV_HH(thread, ip)  \
1224 {                                                                              \
1225         uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id];      \
1226         uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset];   \
1227         uint64_t dst64 = *dst64_ptr;                                           \
1228         uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits);       \
1229                                                                                \
1230         uint8_t *src_struct = (thread)->structs[(ip)->mov.src.struct_id];      \
1231         uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->mov.src.offset];   \
1232         uint64_t src64 = *src64_ptr;                                           \
1233                                                                                \
1234         uint64_t src = src64 << (64 - (ip)->mov.src.n_bits);                   \
1235         src = src >> (64 - (ip)->mov.dst.n_bits);                              \
1236         *dst64_ptr = (dst64 & ~dst64_mask) | src;                              \
1237 }
1238
1239 #else
1240
1241 #define MOV_MH MOV
1242 #define MOV_HM MOV
1243 #define MOV_HH MOV
1244
1245 #endif
1246
1247 #define MOV_I(thread, ip)  \
1248 {                                                                              \
1249         uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id];      \
1250         uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset];   \
1251         uint64_t dst64 = *dst64_ptr;                                           \
1252         uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits);       \
1253                                                                                \
1254         uint64_t src = (ip)->mov.src_val;                                      \
1255                                                                                \
1256         *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);               \
1257 }
1258
1259 #define JMP_CMP(thread, ip, operator)  \
1260 {                                                                              \
1261         uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id];          \
1262         uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset];         \
1263         uint64_t a64 = *a64_ptr;                                               \
1264         uint64_t a64_mask = UINT64_MAX >> (64 - (ip)->jmp.a.n_bits);           \
1265         uint64_t a = a64 & a64_mask;                                           \
1266                                                                                \
1267         uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id];          \
1268         uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset];         \
1269         uint64_t b64 = *b64_ptr;                                               \
1270         uint64_t b64_mask = UINT64_MAX >> (64 - (ip)->jmp.b.n_bits);           \
1271         uint64_t b = b64 & b64_mask;                                           \
1272                                                                                \
1273         (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1);     \
1274 }
1275
1276 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1277
1278 #define JMP_CMP_MH(thread, ip, operator)  \
1279 {                                                                              \
1280         uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id];          \
1281         uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset];         \
1282         uint64_t a64 = *a64_ptr;                                               \
1283         uint64_t a64_mask = UINT64_MAX >> (64 - (ip)->jmp.a.n_bits);           \
1284         uint64_t a = a64 & a64_mask;                                           \
1285                                                                                \
1286         uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id];          \
1287         uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset];         \
1288         uint64_t b64 = *b64_ptr;                                               \
1289         uint64_t b = ntoh64(b64) >> (64 - (ip)->jmp.b.n_bits);                 \
1290                                                                                \
1291         (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1);     \
1292 }
1293
1294 #define JMP_CMP_HM(thread, ip, operator)  \
1295 {                                                                              \
1296         uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id];          \
1297         uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset];         \
1298         uint64_t a64 = *a64_ptr;                                               \
1299         uint64_t a = ntoh64(a64) >> (64 - (ip)->jmp.a.n_bits);                 \
1300                                                                                \
1301         uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id];          \
1302         uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset];         \
1303         uint64_t b64 = *b64_ptr;                                               \
1304         uint64_t b64_mask = UINT64_MAX >> (64 - (ip)->jmp.b.n_bits);           \
1305         uint64_t b = b64 & b64_mask;                                           \
1306                                                                                \
1307         (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1);     \
1308 }
1309
1310 #define JMP_CMP_HH(thread, ip, operator)  \
1311 {                                                                              \
1312         uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id];          \
1313         uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset];         \
1314         uint64_t a64 = *a64_ptr;                                               \
1315         uint64_t a = ntoh64(a64) >> (64 - (ip)->jmp.a.n_bits);                 \
1316                                                                                \
1317         uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id];          \
1318         uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset];         \
1319         uint64_t b64 = *b64_ptr;                                               \
1320         uint64_t b = ntoh64(b64) >> (64 - (ip)->jmp.b.n_bits);                 \
1321                                                                                \
1322         (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1);     \
1323 }
1324
1325 #define JMP_CMP_HH_FAST(thread, ip, operator)  \
1326 {                                                                              \
1327         uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id];          \
1328         uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset];         \
1329         uint64_t a64 = *a64_ptr;                                               \
1330         uint64_t a = a64 << (64 - (ip)->jmp.a.n_bits);                         \
1331                                                                                \
1332         uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id];          \
1333         uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset];         \
1334         uint64_t b64 = *b64_ptr;                                               \
1335         uint64_t b = b64 << (64 - (ip)->jmp.b.n_bits);                         \
1336                                                                                \
1337         (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1);     \
1338 }
1339
1340 #else
1341
1342 #define JMP_CMP_MH JMP_CMP
1343 #define JMP_CMP_HM JMP_CMP
1344 #define JMP_CMP_HH JMP_CMP
1345 #define JMP_CMP_HH_FAST JMP_CMP
1346
1347 #endif
1348
1349 #define JMP_CMP_I(thread, ip, operator)  \
1350 {                                                                              \
1351         uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id];          \
1352         uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset];         \
1353         uint64_t a64 = *a64_ptr;                                               \
1354         uint64_t a64_mask = UINT64_MAX >> (64 - (ip)->jmp.a.n_bits);           \
1355         uint64_t a = a64 & a64_mask;                                           \
1356                                                                                \
1357         uint64_t b = (ip)->jmp.b_val;                                          \
1358                                                                                \
1359         (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1);     \
1360 }
1361
1362 #define JMP_CMP_MI JMP_CMP_I
1363
1364 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1365
1366 #define JMP_CMP_HI(thread, ip, operator)  \
1367 {                                                                              \
1368         uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id];          \
1369         uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset];         \
1370         uint64_t a64 = *a64_ptr;                                               \
1371         uint64_t a = ntoh64(a64) >> (64 - (ip)->jmp.a.n_bits);                 \
1372                                                                                \
1373         uint64_t b = (ip)->jmp.b_val;                                          \
1374                                                                                \
1375         (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1);     \
1376 }
1377
1378 #else
1379
1380 #define JMP_CMP_HI JMP_CMP_I
1381
1382 #endif
1383
1384 #define METADATA_READ(thread, offset, n_bits)                                  \
1385 ({                                                                             \
1386         uint64_t *m64_ptr = (uint64_t *)&(thread)->metadata[offset];           \
1387         uint64_t m64 = *m64_ptr;                                               \
1388         uint64_t m64_mask = UINT64_MAX >> (64 - (n_bits));                     \
1389         (m64 & m64_mask);                                                      \
1390 })
1391
1392 #define METADATA_WRITE(thread, offset, n_bits, value)                          \
1393 {                                                                              \
1394         uint64_t *m64_ptr = (uint64_t *)&(thread)->metadata[offset];           \
1395         uint64_t m64 = *m64_ptr;                                               \
1396         uint64_t m64_mask = UINT64_MAX >> (64 - (n_bits));                     \
1397                                                                                \
1398         uint64_t m_new = value;                                                \
1399                                                                                \
1400         *m64_ptr = (m64 & ~m64_mask) | (m_new & m64_mask);                     \
1401 }
1402
1403 #ifndef RTE_SWX_PIPELINE_THREADS_MAX
1404 #define RTE_SWX_PIPELINE_THREADS_MAX 16
1405 #endif
1406
1407 #ifndef RTE_SWX_PIPELINE_INSTRUCTION_TABLE_SIZE_MAX
1408 #define RTE_SWX_PIPELINE_INSTRUCTION_TABLE_SIZE_MAX 256
1409 #endif
1410
1411 struct rte_swx_pipeline {
1412         struct struct_type_tailq struct_types;
1413         struct port_in_type_tailq port_in_types;
1414         struct port_in_tailq ports_in;
1415         struct port_out_type_tailq port_out_types;
1416         struct port_out_tailq ports_out;
1417         struct extern_type_tailq extern_types;
1418         struct extern_obj_tailq extern_objs;
1419         struct extern_func_tailq extern_funcs;
1420         struct header_tailq headers;
1421         struct struct_type *metadata_st;
1422         uint32_t metadata_struct_id;
1423         struct action_tailq actions;
1424         struct table_type_tailq table_types;
1425         struct table_tailq tables;
1426         struct selector_tailq selectors;
1427         struct learner_tailq learners;
1428         struct regarray_tailq regarrays;
1429         struct meter_profile_tailq meter_profiles;
1430         struct metarray_tailq metarrays;
1431
1432         struct port_in_runtime *in;
1433         struct port_out_runtime *out;
1434         struct mirroring_session *mirroring_sessions;
1435         struct instruction **action_instructions;
1436         action_func_t *action_funcs;
1437         struct rte_swx_table_state *table_state;
1438         struct table_statistics *table_stats;
1439         struct selector_statistics *selector_stats;
1440         struct learner_statistics *learner_stats;
1441         struct regarray_runtime *regarray_runtime;
1442         struct metarray_runtime *metarray_runtime;
1443         struct instruction *instructions;
1444         struct instruction_data *instruction_data;
1445         instr_exec_t *instruction_table;
1446         struct thread threads[RTE_SWX_PIPELINE_THREADS_MAX];
1447         void *lib;
1448
1449         uint32_t n_structs;
1450         uint32_t n_ports_in;
1451         uint32_t n_ports_out;
1452         uint32_t n_mirroring_slots;
1453         uint32_t n_mirroring_sessions;
1454         uint32_t n_extern_objs;
1455         uint32_t n_extern_funcs;
1456         uint32_t n_actions;
1457         uint32_t n_tables;
1458         uint32_t n_selectors;
1459         uint32_t n_learners;
1460         uint32_t n_regarrays;
1461         uint32_t n_metarrays;
1462         uint32_t n_headers;
1463         uint32_t thread_id;
1464         uint32_t port_id;
1465         uint32_t n_instructions;
1466         int build_done;
1467         int numa_node;
1468 };
1469
1470 /*
1471  * Instruction.
1472  */
1473 static inline void
1474 pipeline_port_inc(struct rte_swx_pipeline *p)
1475 {
1476         p->port_id = (p->port_id + 1) & (p->n_ports_in - 1);
1477 }
1478
1479 static inline void
1480 thread_ip_reset(struct rte_swx_pipeline *p, struct thread *t)
1481 {
1482         t->ip = p->instructions;
1483 }
1484
1485 static inline void
1486 thread_ip_set(struct thread *t, struct instruction *ip)
1487 {
1488         t->ip = ip;
1489 }
1490
1491 static inline void
1492 thread_ip_action_call(struct rte_swx_pipeline *p,
1493                       struct thread *t,
1494                       uint32_t action_id)
1495 {
1496         t->ret = t->ip + 1;
1497         t->ip = p->action_instructions[action_id];
1498 }
1499
1500 static inline void
1501 thread_ip_inc(struct rte_swx_pipeline *p);
1502
1503 static inline void
1504 thread_ip_inc(struct rte_swx_pipeline *p)
1505 {
1506         struct thread *t = &p->threads[p->thread_id];
1507
1508         t->ip++;
1509 }
1510
1511 static inline void
1512 thread_ip_inc_cond(struct thread *t, int cond)
1513 {
1514         t->ip += cond;
1515 }
1516
1517 static inline void
1518 thread_yield(struct rte_swx_pipeline *p)
1519 {
1520         p->thread_id = (p->thread_id + 1) & (RTE_SWX_PIPELINE_THREADS_MAX - 1);
1521 }
1522
1523 static inline void
1524 thread_yield_cond(struct rte_swx_pipeline *p, int cond)
1525 {
1526         p->thread_id = (p->thread_id + cond) & (RTE_SWX_PIPELINE_THREADS_MAX - 1);
1527 }
1528
1529 /*
1530  * rx.
1531  */
1532 static inline int
1533 __instr_rx_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
1534 {
1535         struct port_in_runtime *port = &p->in[p->port_id];
1536         struct rte_swx_pkt *pkt = &t->pkt;
1537         int pkt_received;
1538
1539         /* Recirculation: keep the current packet. */
1540         if (t->recirculate) {
1541                 TRACE("[Thread %2u] rx - recirculate (pass %u)\n",
1542                       p->thread_id,
1543                       t->recirc_pass_id + 1);
1544
1545                 /* Packet. */
1546                 t->ptr = &pkt->pkt[pkt->offset];
1547                 t->mirroring_slots_mask = 0;
1548                 t->recirculate = 0;
1549                 t->recirc_pass_id++;
1550
1551                 /* Headers. */
1552                 t->valid_headers = 0;
1553                 t->n_headers_out = 0;
1554
1555                 /* Tables. */
1556                 t->table_state = p->table_state;
1557
1558                 return 1;
1559         }
1560
1561         /* Packet. */
1562         pkt_received = port->pkt_rx(port->obj, pkt);
1563         t->ptr = &pkt->pkt[pkt->offset];
1564         rte_prefetch0(t->ptr);
1565
1566         TRACE("[Thread %2u] rx %s from port %u\n",
1567               p->thread_id,
1568               pkt_received ? "1 pkt" : "0 pkts",
1569               p->port_id);
1570
1571         t->mirroring_slots_mask = 0;
1572         t->recirc_pass_id = 0;
1573
1574         /* Headers. */
1575         t->valid_headers = 0;
1576         t->n_headers_out = 0;
1577
1578         /* Meta-data. */
1579         METADATA_WRITE(t, ip->io.io.offset, ip->io.io.n_bits, p->port_id);
1580
1581         /* Tables. */
1582         t->table_state = p->table_state;
1583
1584         /* Thread. */
1585         pipeline_port_inc(p);
1586
1587         return pkt_received;
1588 }
1589
1590 static inline void
1591 instr_rx_exec(struct rte_swx_pipeline *p)
1592 {
1593         struct thread *t = &p->threads[p->thread_id];
1594         struct instruction *ip = t->ip;
1595         int pkt_received;
1596
1597         /* Packet. */
1598         pkt_received = __instr_rx_exec(p, t, ip);
1599
1600         /* Thread. */
1601         thread_ip_inc_cond(t, pkt_received);
1602         thread_yield(p);
1603 }
1604
1605 /*
1606  * tx.
1607  */
1608 static inline void
1609 emit_handler(struct thread *t)
1610 {
1611         struct header_out_runtime *h0 = &t->headers_out[0];
1612         struct header_out_runtime *h1 = &t->headers_out[1];
1613         uint32_t offset = 0, i;
1614
1615         /* No header change or header decapsulation. */
1616         if ((t->n_headers_out == 1) &&
1617             (h0->ptr + h0->n_bytes == t->ptr)) {
1618                 TRACE("Emit handler: no header change or header decap.\n");
1619
1620                 t->pkt.offset -= h0->n_bytes;
1621                 t->pkt.length += h0->n_bytes;
1622
1623                 return;
1624         }
1625
1626         /* Header encapsulation (optionally, with prior header decapsulation). */
1627         if ((t->n_headers_out == 2) &&
1628             (h1->ptr + h1->n_bytes == t->ptr) &&
1629             (h0->ptr == h0->ptr0)) {
1630                 uint32_t offset;
1631
1632                 TRACE("Emit handler: header encapsulation.\n");
1633
1634                 offset = h0->n_bytes + h1->n_bytes;
1635                 memcpy(t->ptr - offset, h0->ptr, h0->n_bytes);
1636                 t->pkt.offset -= offset;
1637                 t->pkt.length += offset;
1638
1639                 return;
1640         }
1641
1642         /* For any other case. */
1643         TRACE("Emit handler: complex case.\n");
1644
1645         for (i = 0; i < t->n_headers_out; i++) {
1646                 struct header_out_runtime *h = &t->headers_out[i];
1647
1648                 memcpy(&t->header_out_storage[offset], h->ptr, h->n_bytes);
1649                 offset += h->n_bytes;
1650         }
1651
1652         if (offset) {
1653                 memcpy(t->ptr - offset, t->header_out_storage, offset);
1654                 t->pkt.offset -= offset;
1655                 t->pkt.length += offset;
1656         }
1657 }
1658
1659 static inline void
1660 mirroring_handler(struct rte_swx_pipeline *p, struct thread *t, struct rte_swx_pkt *pkt)
1661 {
1662         uint64_t slots_mask = t->mirroring_slots_mask, slot_mask;
1663         uint32_t slot_id;
1664
1665         for (slot_id = 0, slot_mask = 1LLU ; slots_mask; slot_id++, slot_mask <<= 1)
1666                 if (slot_mask & slots_mask) {
1667                         struct port_out_runtime *port;
1668                         struct mirroring_session *session;
1669                         uint32_t port_id, session_id;
1670
1671                         session_id = t->mirroring_slots[slot_id];
1672                         session = &p->mirroring_sessions[session_id];
1673
1674                         port_id = session->port_id;
1675                         port = &p->out[port_id];
1676
1677                         if (session->fast_clone)
1678                                 port->pkt_fast_clone_tx(port->obj, pkt);
1679                         else
1680                                 port->pkt_clone_tx(port->obj, pkt, session->truncation_length);
1681
1682                         slots_mask &= ~slot_mask;
1683                 }
1684 }
1685
1686 static inline void
1687 __instr_tx_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
1688 {
1689         uint64_t port_id = METADATA_READ(t, ip->io.io.offset, ip->io.io.n_bits);
1690         struct port_out_runtime *port = &p->out[port_id];
1691         struct rte_swx_pkt *pkt = &t->pkt;
1692
1693         /* Recirculation: keep the current packet. */
1694         if (t->recirculate) {
1695                 TRACE("[Thread %2u]: tx 1 pkt - recirculate\n",
1696                       p->thread_id);
1697
1698                 /* Headers. */
1699                 emit_handler(t);
1700
1701                 /* Packet. */
1702                 mirroring_handler(p, t, pkt);
1703
1704                 return;
1705         }
1706
1707         TRACE("[Thread %2u]: tx 1 pkt to port %u\n",
1708               p->thread_id,
1709               (uint32_t)port_id);
1710
1711         /* Headers. */
1712         emit_handler(t);
1713
1714         /* Packet. */
1715         mirroring_handler(p, t, pkt);
1716         port->pkt_tx(port->obj, pkt);
1717 }
1718
1719 static inline void
1720 __instr_tx_i_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
1721 {
1722         uint64_t port_id = ip->io.io.val;
1723         struct port_out_runtime *port = &p->out[port_id];
1724         struct rte_swx_pkt *pkt = &t->pkt;
1725
1726         /* Recirculation: keep the current packet. */
1727         if (t->recirculate) {
1728                 TRACE("[Thread %2u]: tx (i) 1 pkt - recirculate\n",
1729                       p->thread_id);
1730
1731                 /* Headers. */
1732                 emit_handler(t);
1733
1734                 /* Packet. */
1735                 mirroring_handler(p, t, pkt);
1736
1737                 return;
1738         }
1739
1740         TRACE("[Thread %2u]: tx (i) 1 pkt to port %u\n",
1741               p->thread_id,
1742               (uint32_t)port_id);
1743
1744         /* Headers. */
1745         emit_handler(t);
1746
1747         /* Packet. */
1748         mirroring_handler(p, t, pkt);
1749         port->pkt_tx(port->obj, pkt);
1750 }
1751
1752 static inline void
1753 __instr_drop_exec(struct rte_swx_pipeline *p,
1754                   struct thread *t,
1755                   const struct instruction *ip __rte_unused)
1756 {
1757         uint64_t port_id = p->n_ports_out - 1;
1758         struct port_out_runtime *port = &p->out[port_id];
1759         struct rte_swx_pkt *pkt = &t->pkt;
1760
1761         TRACE("[Thread %2u]: drop 1 pkt\n",
1762               p->thread_id);
1763
1764         /* Headers. */
1765         emit_handler(t);
1766
1767         /* Packet. */
1768         mirroring_handler(p, t, pkt);
1769         port->pkt_tx(port->obj, pkt);
1770 }
1771
1772 static inline void
1773 __instr_mirror_exec(struct rte_swx_pipeline *p,
1774                     struct thread *t,
1775                     const struct instruction *ip)
1776 {
1777         uint64_t slot_id = instr_operand_hbo(t, &ip->mirror.dst);
1778         uint64_t session_id = instr_operand_hbo(t, &ip->mirror.src);
1779
1780         slot_id &= p->n_mirroring_slots - 1;
1781         session_id &= p->n_mirroring_sessions - 1;
1782
1783         TRACE("[Thread %2u]: mirror pkt (slot = %u, session = %u)\n",
1784               p->thread_id,
1785               (uint32_t)slot_id,
1786               (uint32_t)session_id);
1787
1788         t->mirroring_slots[slot_id] = session_id;
1789         t->mirroring_slots_mask |= 1LLU << slot_id;
1790 }
1791
1792 static inline void
1793 __instr_recirculate_exec(struct rte_swx_pipeline *p __rte_unused,
1794                          struct thread *t,
1795                          const struct instruction *ip __rte_unused)
1796 {
1797         TRACE("[Thread %2u]: recirculate\n",
1798               p->thread_id);
1799
1800         t->recirculate = 1;
1801 }
1802
1803 static inline void
1804 __instr_recircid_exec(struct rte_swx_pipeline *p __rte_unused,
1805                       struct thread *t,
1806                       const struct instruction *ip)
1807 {
1808         TRACE("[Thread %2u]: recircid (pass %u)\n",
1809               p->thread_id,
1810               t->recirc_pass_id);
1811
1812         /* Meta-data. */
1813         METADATA_WRITE(t, ip->io.io.offset, ip->io.io.n_bits, t->recirc_pass_id);
1814 }
1815
1816 /*
1817  * extract.
1818  */
1819 static inline void
1820 __instr_hdr_extract_many_exec(struct rte_swx_pipeline *p __rte_unused,
1821                               struct thread *t,
1822                               const struct instruction *ip,
1823                               uint32_t n_extract)
1824 {
1825         uint64_t valid_headers = t->valid_headers;
1826         uint8_t *ptr = t->ptr;
1827         uint32_t offset = t->pkt.offset;
1828         uint32_t length = t->pkt.length;
1829         uint32_t i;
1830
1831         for (i = 0; i < n_extract; i++) {
1832                 uint32_t header_id = ip->io.hdr.header_id[i];
1833                 uint32_t struct_id = ip->io.hdr.struct_id[i];
1834                 uint32_t n_bytes = ip->io.hdr.n_bytes[i];
1835
1836                 TRACE("[Thread %2u]: extract header %u (%u bytes)\n",
1837                       p->thread_id,
1838                       header_id,
1839                       n_bytes);
1840
1841                 /* Headers. */
1842                 t->structs[struct_id] = ptr;
1843                 valid_headers = MASK64_BIT_SET(valid_headers, header_id);
1844
1845                 /* Packet. */
1846                 offset += n_bytes;
1847                 length -= n_bytes;
1848                 ptr += n_bytes;
1849         }
1850
1851         /* Headers. */
1852         t->valid_headers = valid_headers;
1853
1854         /* Packet. */
1855         t->pkt.offset = offset;
1856         t->pkt.length = length;
1857         t->ptr = ptr;
1858 }
1859
1860 static inline void
1861 __instr_hdr_extract_exec(struct rte_swx_pipeline *p,
1862                          struct thread *t,
1863                          const struct instruction *ip)
1864 {
1865         __instr_hdr_extract_many_exec(p, t, ip, 1);
1866 }
1867
1868 static inline void
1869 __instr_hdr_extract2_exec(struct rte_swx_pipeline *p,
1870                           struct thread *t,
1871                           const struct instruction *ip)
1872 {
1873         TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n", p->thread_id);
1874
1875         __instr_hdr_extract_many_exec(p, t, ip, 2);
1876 }
1877
1878 static inline void
1879 __instr_hdr_extract3_exec(struct rte_swx_pipeline *p,
1880                           struct thread *t,
1881                           const struct instruction *ip)
1882 {
1883         TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n", p->thread_id);
1884
1885         __instr_hdr_extract_many_exec(p, t, ip, 3);
1886 }
1887
1888 static inline void
1889 __instr_hdr_extract4_exec(struct rte_swx_pipeline *p,
1890                           struct thread *t,
1891                           const struct instruction *ip)
1892 {
1893         TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n", p->thread_id);
1894
1895         __instr_hdr_extract_many_exec(p, t, ip, 4);
1896 }
1897
1898 static inline void
1899 __instr_hdr_extract5_exec(struct rte_swx_pipeline *p,
1900                           struct thread *t,
1901                           const struct instruction *ip)
1902 {
1903         TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n", p->thread_id);
1904
1905         __instr_hdr_extract_many_exec(p, t, ip, 5);
1906 }
1907
1908 static inline void
1909 __instr_hdr_extract6_exec(struct rte_swx_pipeline *p,
1910                           struct thread *t,
1911                           const struct instruction *ip)
1912 {
1913         TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n", p->thread_id);
1914
1915         __instr_hdr_extract_many_exec(p, t, ip, 6);
1916 }
1917
1918 static inline void
1919 __instr_hdr_extract7_exec(struct rte_swx_pipeline *p,
1920                           struct thread *t,
1921                           const struct instruction *ip)
1922 {
1923         TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n", p->thread_id);
1924
1925         __instr_hdr_extract_many_exec(p, t, ip, 7);
1926 }
1927
1928 static inline void
1929 __instr_hdr_extract8_exec(struct rte_swx_pipeline *p,
1930                           struct thread *t,
1931                           const struct instruction *ip)
1932 {
1933         TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n", p->thread_id);
1934
1935         __instr_hdr_extract_many_exec(p, t, ip, 8);
1936 }
1937
1938 static inline void
1939 __instr_hdr_extract_m_exec(struct rte_swx_pipeline *p __rte_unused,
1940                            struct thread *t,
1941                            const struct instruction *ip)
1942 {
1943         uint64_t valid_headers = t->valid_headers;
1944         uint8_t *ptr = t->ptr;
1945         uint32_t offset = t->pkt.offset;
1946         uint32_t length = t->pkt.length;
1947
1948         uint32_t n_bytes_last = METADATA_READ(t, ip->io.io.offset, ip->io.io.n_bits);
1949         uint32_t header_id = ip->io.hdr.header_id[0];
1950         uint32_t struct_id = ip->io.hdr.struct_id[0];
1951         uint32_t n_bytes = ip->io.hdr.n_bytes[0];
1952
1953         struct header_runtime *h = &t->headers[header_id];
1954
1955         TRACE("[Thread %2u]: extract header %u (%u + %u bytes)\n",
1956               p->thread_id,
1957               header_id,
1958               n_bytes,
1959               n_bytes_last);
1960
1961         n_bytes += n_bytes_last;
1962
1963         /* Headers. */
1964         t->structs[struct_id] = ptr;
1965         t->valid_headers = MASK64_BIT_SET(valid_headers, header_id);
1966         h->n_bytes = n_bytes;
1967
1968         /* Packet. */
1969         t->pkt.offset = offset + n_bytes;
1970         t->pkt.length = length - n_bytes;
1971         t->ptr = ptr + n_bytes;
1972 }
1973
1974 static inline void
1975 __instr_hdr_lookahead_exec(struct rte_swx_pipeline *p __rte_unused,
1976                            struct thread *t,
1977                            const struct instruction *ip)
1978 {
1979         uint64_t valid_headers = t->valid_headers;
1980         uint8_t *ptr = t->ptr;
1981
1982         uint32_t header_id = ip->io.hdr.header_id[0];
1983         uint32_t struct_id = ip->io.hdr.struct_id[0];
1984
1985         TRACE("[Thread %2u]: lookahead header %u\n",
1986               p->thread_id,
1987               header_id);
1988
1989         /* Headers. */
1990         t->structs[struct_id] = ptr;
1991         t->valid_headers = MASK64_BIT_SET(valid_headers, header_id);
1992 }
1993
1994 /*
1995  * emit.
1996  */
1997 static inline void
1998 __instr_hdr_emit_many_exec(struct rte_swx_pipeline *p __rte_unused,
1999                            struct thread *t,
2000                            const struct instruction *ip,
2001                            uint32_t n_emit)
2002 {
2003         uint64_t valid_headers = t->valid_headers;
2004         uint32_t n_headers_out = t->n_headers_out;
2005         struct header_out_runtime *ho = NULL;
2006         uint8_t *ho_ptr = NULL;
2007         uint32_t ho_nbytes = 0, i;
2008
2009         for (i = 0; i < n_emit; i++) {
2010                 uint32_t header_id = ip->io.hdr.header_id[i];
2011                 uint32_t struct_id = ip->io.hdr.struct_id[i];
2012
2013                 struct header_runtime *hi = &t->headers[header_id];
2014                 uint8_t *hi_ptr0 = hi->ptr0;
2015                 uint32_t n_bytes = hi->n_bytes;
2016
2017                 uint8_t *hi_ptr = t->structs[struct_id];
2018
2019                 if (!MASK64_BIT_GET(valid_headers, header_id)) {
2020                         TRACE("[Thread %2u]: emit header %u (invalid)\n",
2021                               p->thread_id,
2022                               header_id);
2023
2024                         continue;
2025                 }
2026
2027                 TRACE("[Thread %2u]: emit header %u (valid)\n",
2028                       p->thread_id,
2029                       header_id);
2030
2031                 /* Headers. */
2032                 if (!ho) {
2033                         if (!n_headers_out) {
2034                                 ho = &t->headers_out[0];
2035
2036                                 ho->ptr0 = hi_ptr0;
2037                                 ho->ptr = hi_ptr;
2038
2039                                 ho_ptr = hi_ptr;
2040                                 ho_nbytes = n_bytes;
2041
2042                                 n_headers_out = 1;
2043
2044                                 continue;
2045                         } else {
2046                                 ho = &t->headers_out[n_headers_out - 1];
2047
2048                                 ho_ptr = ho->ptr;
2049                                 ho_nbytes = ho->n_bytes;
2050                         }
2051                 }
2052
2053                 if (ho_ptr + ho_nbytes == hi_ptr) {
2054                         ho_nbytes += n_bytes;
2055                 } else {
2056                         ho->n_bytes = ho_nbytes;
2057
2058                         ho++;
2059                         ho->ptr0 = hi_ptr0;
2060                         ho->ptr = hi_ptr;
2061
2062                         ho_ptr = hi_ptr;
2063                         ho_nbytes = n_bytes;
2064
2065                         n_headers_out++;
2066                 }
2067         }
2068
2069         if (ho)
2070                 ho->n_bytes = ho_nbytes;
2071         t->n_headers_out = n_headers_out;
2072 }
2073
2074 static inline void
2075 __instr_hdr_emit_exec(struct rte_swx_pipeline *p,
2076                       struct thread *t,
2077                       const struct instruction *ip)
2078 {
2079         __instr_hdr_emit_many_exec(p, t, ip, 1);
2080 }
2081
2082 static inline void
2083 __instr_hdr_emit_tx_exec(struct rte_swx_pipeline *p,
2084                          struct thread *t,
2085                          const struct instruction *ip)
2086 {
2087         TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n", p->thread_id);
2088
2089         __instr_hdr_emit_many_exec(p, t, ip, 1);
2090         __instr_tx_exec(p, t, ip);
2091 }
2092
2093 static inline void
2094 __instr_hdr_emit2_tx_exec(struct rte_swx_pipeline *p,
2095                           struct thread *t,
2096                           const struct instruction *ip)
2097 {
2098         TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n", p->thread_id);
2099
2100         __instr_hdr_emit_many_exec(p, t, ip, 2);
2101         __instr_tx_exec(p, t, ip);
2102 }
2103
2104 static inline void
2105 __instr_hdr_emit3_tx_exec(struct rte_swx_pipeline *p,
2106                           struct thread *t,
2107                           const struct instruction *ip)
2108 {
2109         TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n", p->thread_id);
2110
2111         __instr_hdr_emit_many_exec(p, t, ip, 3);
2112         __instr_tx_exec(p, t, ip);
2113 }
2114
2115 static inline void
2116 __instr_hdr_emit4_tx_exec(struct rte_swx_pipeline *p,
2117                           struct thread *t,
2118                           const struct instruction *ip)
2119 {
2120         TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n", p->thread_id);
2121
2122         __instr_hdr_emit_many_exec(p, t, ip, 4);
2123         __instr_tx_exec(p, t, ip);
2124 }
2125
2126 static inline void
2127 __instr_hdr_emit5_tx_exec(struct rte_swx_pipeline *p,
2128                           struct thread *t,
2129                           const struct instruction *ip)
2130 {
2131         TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n", p->thread_id);
2132
2133         __instr_hdr_emit_many_exec(p, t, ip, 5);
2134         __instr_tx_exec(p, t, ip);
2135 }
2136
2137 static inline void
2138 __instr_hdr_emit6_tx_exec(struct rte_swx_pipeline *p,
2139                           struct thread *t,
2140                           const struct instruction *ip)
2141 {
2142         TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n", p->thread_id);
2143
2144         __instr_hdr_emit_many_exec(p, t, ip, 6);
2145         __instr_tx_exec(p, t, ip);
2146 }
2147
2148 static inline void
2149 __instr_hdr_emit7_tx_exec(struct rte_swx_pipeline *p,
2150                           struct thread *t,
2151                           const struct instruction *ip)
2152 {
2153         TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n", p->thread_id);
2154
2155         __instr_hdr_emit_many_exec(p, t, ip, 7);
2156         __instr_tx_exec(p, t, ip);
2157 }
2158
2159 static inline void
2160 __instr_hdr_emit8_tx_exec(struct rte_swx_pipeline *p,
2161                           struct thread *t,
2162                           const struct instruction *ip)
2163 {
2164         TRACE("[Thread %2u] *** The next 9 instructions are fused. ***\n", p->thread_id);
2165
2166         __instr_hdr_emit_many_exec(p, t, ip, 8);
2167         __instr_tx_exec(p, t, ip);
2168 }
2169
2170 /*
2171  * validate.
2172  */
2173 static inline void
2174 __instr_hdr_validate_exec(struct rte_swx_pipeline *p __rte_unused,
2175                           struct thread *t,
2176                           const struct instruction *ip)
2177 {
2178         uint32_t header_id = ip->valid.header_id;
2179
2180         TRACE("[Thread %2u] validate header %u\n", p->thread_id, header_id);
2181
2182         /* Headers. */
2183         t->valid_headers = MASK64_BIT_SET(t->valid_headers, header_id);
2184 }
2185
2186 /*
2187  * invalidate.
2188  */
2189 static inline void
2190 __instr_hdr_invalidate_exec(struct rte_swx_pipeline *p __rte_unused,
2191                             struct thread *t,
2192                             const struct instruction *ip)
2193 {
2194         uint32_t header_id = ip->valid.header_id;
2195
2196         TRACE("[Thread %2u] invalidate header %u\n", p->thread_id, header_id);
2197
2198         /* Headers. */
2199         t->valid_headers = MASK64_BIT_CLR(t->valid_headers, header_id);
2200 }
2201
2202 /*
2203  * learn.
2204  */
2205 static inline void
2206 __instr_learn_exec(struct rte_swx_pipeline *p,
2207                    struct thread *t,
2208                    const struct instruction *ip)
2209 {
2210         uint64_t action_id = ip->learn.action_id;
2211         uint32_t mf_offset = ip->learn.mf_offset;
2212         uint32_t learner_id = t->learner_id;
2213         struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2214                 p->n_selectors + learner_id];
2215         struct learner_runtime *l = &t->learners[learner_id];
2216         struct learner_statistics *stats = &p->learner_stats[learner_id];
2217         uint32_t status;
2218
2219         /* Table. */
2220         status = rte_swx_table_learner_add(ts->obj,
2221                                            l->mailbox,
2222                                            t->time,
2223                                            action_id,
2224                                            &t->metadata[mf_offset],
2225                                            0);
2226
2227         TRACE("[Thread %2u] learner %u learn %s\n",
2228               p->thread_id,
2229               learner_id,
2230               status ? "ok" : "error");
2231
2232         stats->n_pkts_learn[status] += 1;
2233 }
2234
2235 /*
2236  * forget.
2237  */
2238 static inline void
2239 __instr_forget_exec(struct rte_swx_pipeline *p,
2240                     struct thread *t,
2241                     const struct instruction *ip __rte_unused)
2242 {
2243         uint32_t learner_id = t->learner_id;
2244         struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2245                 p->n_selectors + learner_id];
2246         struct learner_runtime *l = &t->learners[learner_id];
2247         struct learner_statistics *stats = &p->learner_stats[learner_id];
2248
2249         /* Table. */
2250         rte_swx_table_learner_delete(ts->obj, l->mailbox);
2251
2252         TRACE("[Thread %2u] learner %u forget\n",
2253               p->thread_id,
2254               learner_id);
2255
2256         stats->n_pkts_forget += 1;
2257 }
2258
2259 /*
2260  * extern.
2261  */
2262 static inline uint32_t
2263 __instr_extern_obj_exec(struct rte_swx_pipeline *p __rte_unused,
2264                         struct thread *t,
2265                         const struct instruction *ip)
2266 {
2267         uint32_t obj_id = ip->ext_obj.ext_obj_id;
2268         uint32_t func_id = ip->ext_obj.func_id;
2269         struct extern_obj_runtime *obj = &t->extern_objs[obj_id];
2270         rte_swx_extern_type_member_func_t func = obj->funcs[func_id];
2271         uint32_t done;
2272
2273         TRACE("[Thread %2u] extern obj %u member func %u\n",
2274               p->thread_id,
2275               obj_id,
2276               func_id);
2277
2278         done = func(obj->obj, obj->mailbox);
2279
2280         return done;
2281 }
2282
2283 static inline uint32_t
2284 __instr_extern_func_exec(struct rte_swx_pipeline *p __rte_unused,
2285                          struct thread *t,
2286                          const struct instruction *ip)
2287 {
2288         uint32_t ext_func_id = ip->ext_func.ext_func_id;
2289         struct extern_func_runtime *ext_func = &t->extern_funcs[ext_func_id];
2290         rte_swx_extern_func_t func = ext_func->func;
2291         uint32_t done;
2292
2293         TRACE("[Thread %2u] extern func %u\n",
2294               p->thread_id,
2295               ext_func_id);
2296
2297         done = func(ext_func->mailbox);
2298
2299         return done;
2300 }
2301
2302 /*
2303  * mov.
2304  */
2305 static inline void
2306 __instr_mov_exec(struct rte_swx_pipeline *p __rte_unused,
2307                  struct thread *t,
2308                  const struct instruction *ip)
2309 {
2310         TRACE("[Thread %2u] mov\n", p->thread_id);
2311
2312         MOV(t, ip);
2313 }
2314
2315 static inline void
2316 __instr_mov_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2317                     struct thread *t,
2318                     const struct instruction *ip)
2319 {
2320         TRACE("[Thread %2u] mov (mh)\n", p->thread_id);
2321
2322         MOV_MH(t, ip);
2323 }
2324
2325 static inline void
2326 __instr_mov_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2327                     struct thread *t,
2328                     const struct instruction *ip)
2329 {
2330         TRACE("[Thread %2u] mov (hm)\n", p->thread_id);
2331
2332         MOV_HM(t, ip);
2333 }
2334
2335 static inline void
2336 __instr_mov_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2337                     struct thread *t,
2338                     const struct instruction *ip)
2339 {
2340         TRACE("[Thread %2u] mov (hh)\n", p->thread_id);
2341
2342         MOV_HH(t, ip);
2343 }
2344
2345 static inline void
2346 __instr_mov_i_exec(struct rte_swx_pipeline *p __rte_unused,
2347                    struct thread *t,
2348                    const struct instruction *ip)
2349 {
2350         TRACE("[Thread %2u] mov m.f %" PRIx64 "\n", p->thread_id, ip->mov.src_val);
2351
2352         MOV_I(t, ip);
2353 }
2354
2355 /*
2356  * dma.
2357  */
2358 static inline void
2359 __instr_dma_ht_many_exec(struct rte_swx_pipeline *p __rte_unused,
2360                          struct thread *t,
2361                          const struct instruction *ip,
2362                          uint32_t n_dma)
2363 {
2364         uint8_t *action_data = t->structs[0];
2365         uint64_t valid_headers = t->valid_headers;
2366         uint32_t i;
2367
2368         for (i = 0; i < n_dma; i++) {
2369                 uint32_t header_id = ip->dma.dst.header_id[i];
2370                 uint32_t struct_id = ip->dma.dst.struct_id[i];
2371                 uint32_t offset = ip->dma.src.offset[i];
2372                 uint32_t n_bytes = ip->dma.n_bytes[i];
2373
2374                 struct header_runtime *h = &t->headers[header_id];
2375                 uint8_t *h_ptr0 = h->ptr0;
2376                 uint8_t *h_ptr = t->structs[struct_id];
2377
2378                 void *dst = MASK64_BIT_GET(valid_headers, header_id) ?
2379                         h_ptr : h_ptr0;
2380                 void *src = &action_data[offset];
2381
2382                 TRACE("[Thread %2u] dma h.s t.f\n", p->thread_id);
2383
2384                 /* Headers. */
2385                 memcpy(dst, src, n_bytes);
2386                 t->structs[struct_id] = dst;
2387                 valid_headers = MASK64_BIT_SET(valid_headers, header_id);
2388         }
2389
2390         t->valid_headers = valid_headers;
2391 }
2392
2393 static inline void
2394 __instr_dma_ht_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2395 {
2396         __instr_dma_ht_many_exec(p, t, ip, 1);
2397 }
2398
2399 static inline void
2400 __instr_dma_ht2_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2401 {
2402         TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n", p->thread_id);
2403
2404         __instr_dma_ht_many_exec(p, t, ip, 2);
2405 }
2406
2407 static inline void
2408 __instr_dma_ht3_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2409 {
2410         TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n", p->thread_id);
2411
2412         __instr_dma_ht_many_exec(p, t, ip, 3);
2413 }
2414
2415 static inline void
2416 __instr_dma_ht4_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2417 {
2418         TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n", p->thread_id);
2419
2420         __instr_dma_ht_many_exec(p, t, ip, 4);
2421 }
2422
2423 static inline void
2424 __instr_dma_ht5_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2425 {
2426         TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n", p->thread_id);
2427
2428         __instr_dma_ht_many_exec(p, t, ip, 5);
2429 }
2430
2431 static inline void
2432 __instr_dma_ht6_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2433 {
2434         TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n", p->thread_id);
2435
2436         __instr_dma_ht_many_exec(p, t, ip, 6);
2437 }
2438
2439 static inline void
2440 __instr_dma_ht7_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2441 {
2442         TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n", p->thread_id);
2443
2444         __instr_dma_ht_many_exec(p, t, ip, 7);
2445 }
2446
2447 static inline void
2448 __instr_dma_ht8_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2449 {
2450         TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n", p->thread_id);
2451
2452         __instr_dma_ht_many_exec(p, t, ip, 8);
2453 }
2454
2455 /*
2456  * alu.
2457  */
2458 static inline void
2459 __instr_alu_add_exec(struct rte_swx_pipeline *p __rte_unused,
2460                      struct thread *t,
2461                      const struct instruction *ip)
2462 {
2463         TRACE("[Thread %2u] add\n", p->thread_id);
2464
2465         ALU(t, ip, +);
2466 }
2467
2468 static inline void
2469 __instr_alu_add_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2470                         struct thread *t,
2471                         const struct instruction *ip)
2472 {
2473         TRACE("[Thread %2u] add (mh)\n", p->thread_id);
2474
2475         ALU_MH(t, ip, +);
2476 }
2477
2478 static inline void
2479 __instr_alu_add_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2480                         struct thread *t,
2481                         const struct instruction *ip)
2482 {
2483         TRACE("[Thread %2u] add (hm)\n", p->thread_id);
2484
2485         ALU_HM(t, ip, +);
2486 }
2487
2488 static inline void
2489 __instr_alu_add_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2490                         struct thread *t,
2491                         const struct instruction *ip)
2492 {
2493         TRACE("[Thread %2u] add (hh)\n", p->thread_id);
2494
2495         ALU_HH(t, ip, +);
2496 }
2497
2498 static inline void
2499 __instr_alu_add_mi_exec(struct rte_swx_pipeline *p __rte_unused,
2500                         struct thread *t,
2501                         const struct instruction *ip)
2502 {
2503         TRACE("[Thread %2u] add (mi)\n", p->thread_id);
2504
2505         ALU_MI(t, ip, +);
2506 }
2507
2508 static inline void
2509 __instr_alu_add_hi_exec(struct rte_swx_pipeline *p __rte_unused,
2510                         struct thread *t,
2511                         const struct instruction *ip)
2512 {
2513         TRACE("[Thread %2u] add (hi)\n", p->thread_id);
2514
2515         ALU_HI(t, ip, +);
2516 }
2517
2518 static inline void
2519 __instr_alu_sub_exec(struct rte_swx_pipeline *p __rte_unused,
2520                      struct thread *t,
2521                      const struct instruction *ip)
2522 {
2523         TRACE("[Thread %2u] sub\n", p->thread_id);
2524
2525         ALU(t, ip, -);
2526 }
2527
2528 static inline void
2529 __instr_alu_sub_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2530                         struct thread *t,
2531                         const struct instruction *ip)
2532 {
2533         TRACE("[Thread %2u] sub (mh)\n", p->thread_id);
2534
2535         ALU_MH(t, ip, -);
2536 }
2537
2538 static inline void
2539 __instr_alu_sub_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2540                         struct thread *t,
2541                         const struct instruction *ip)
2542 {
2543         TRACE("[Thread %2u] sub (hm)\n", p->thread_id);
2544
2545         ALU_HM(t, ip, -);
2546 }
2547
2548 static inline void
2549 __instr_alu_sub_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2550                         struct thread *t,
2551                         const struct instruction *ip)
2552 {
2553         TRACE("[Thread %2u] sub (hh)\n", p->thread_id);
2554
2555         ALU_HH(t, ip, -);
2556 }
2557
2558 static inline void
2559 __instr_alu_sub_mi_exec(struct rte_swx_pipeline *p __rte_unused,
2560                         struct thread *t,
2561                         const struct instruction *ip)
2562 {
2563         TRACE("[Thread %2u] sub (mi)\n", p->thread_id);
2564
2565         ALU_MI(t, ip, -);
2566 }
2567
2568 static inline void
2569 __instr_alu_sub_hi_exec(struct rte_swx_pipeline *p __rte_unused,
2570                         struct thread *t,
2571                         const struct instruction *ip)
2572 {
2573         TRACE("[Thread %2u] sub (hi)\n", p->thread_id);
2574
2575         ALU_HI(t, ip, -);
2576 }
2577
2578 static inline void
2579 __instr_alu_shl_exec(struct rte_swx_pipeline *p __rte_unused,
2580                      struct thread *t,
2581                      const struct instruction *ip)
2582 {
2583         TRACE("[Thread %2u] shl\n", p->thread_id);
2584
2585         ALU(t, ip, <<);
2586 }
2587
2588 static inline void
2589 __instr_alu_shl_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2590                         struct thread *t,
2591                         const struct instruction *ip)
2592 {
2593         TRACE("[Thread %2u] shl (mh)\n", p->thread_id);
2594
2595         ALU_MH(t, ip, <<);
2596 }
2597
2598 static inline void
2599 __instr_alu_shl_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2600                         struct thread *t,
2601                         const struct instruction *ip)
2602 {
2603         TRACE("[Thread %2u] shl (hm)\n", p->thread_id);
2604
2605         ALU_HM(t, ip, <<);
2606 }
2607
2608 static inline void
2609 __instr_alu_shl_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2610                         struct thread *t,
2611                         const struct instruction *ip)
2612 {
2613         TRACE("[Thread %2u] shl (hh)\n", p->thread_id);
2614
2615         ALU_HH(t, ip, <<);
2616 }
2617
2618 static inline void
2619 __instr_alu_shl_mi_exec(struct rte_swx_pipeline *p __rte_unused,
2620                         struct thread *t,
2621                         const struct instruction *ip)
2622 {
2623         TRACE("[Thread %2u] shl (mi)\n", p->thread_id);
2624
2625         ALU_MI(t, ip, <<);
2626 }
2627
2628 static inline void
2629 __instr_alu_shl_hi_exec(struct rte_swx_pipeline *p __rte_unused,
2630                         struct thread *t,
2631                         const struct instruction *ip)
2632 {
2633         TRACE("[Thread %2u] shl (hi)\n", p->thread_id);
2634
2635         ALU_HI(t, ip, <<);
2636 }
2637
2638 static inline void
2639 __instr_alu_shr_exec(struct rte_swx_pipeline *p __rte_unused,
2640                      struct thread *t,
2641                      const struct instruction *ip)
2642 {
2643         TRACE("[Thread %2u] shr\n", p->thread_id);
2644
2645         ALU(t, ip, >>);
2646 }
2647
2648 static inline void
2649 __instr_alu_shr_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2650                         struct thread *t,
2651                         const struct instruction *ip)
2652 {
2653         TRACE("[Thread %2u] shr (mh)\n", p->thread_id);
2654
2655         ALU_MH(t, ip, >>);
2656 }
2657
2658 static inline void
2659 __instr_alu_shr_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2660                         struct thread *t,
2661                         const struct instruction *ip)
2662 {
2663         TRACE("[Thread %2u] shr (hm)\n", p->thread_id);
2664
2665         ALU_HM(t, ip, >>);
2666 }
2667
2668 static inline void
2669 __instr_alu_shr_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2670                         struct thread *t,
2671                         const struct instruction *ip)
2672 {
2673         TRACE("[Thread %2u] shr (hh)\n", p->thread_id);
2674
2675         ALU_HH(t, ip, >>);
2676 }
2677
2678 static inline void
2679 __instr_alu_shr_mi_exec(struct rte_swx_pipeline *p __rte_unused,
2680                         struct thread *t,
2681                         const struct instruction *ip)
2682 {
2683         TRACE("[Thread %2u] shr (mi)\n", p->thread_id);
2684
2685         /* Structs. */
2686         ALU_MI(t, ip, >>);
2687 }
2688
2689 static inline void
2690 __instr_alu_shr_hi_exec(struct rte_swx_pipeline *p __rte_unused,
2691                         struct thread *t,
2692                         const struct instruction *ip)
2693 {
2694         TRACE("[Thread %2u] shr (hi)\n", p->thread_id);
2695
2696         ALU_HI(t, ip, >>);
2697 }
2698
2699 static inline void
2700 __instr_alu_and_exec(struct rte_swx_pipeline *p __rte_unused,
2701                      struct thread *t,
2702                      const struct instruction *ip)
2703 {
2704         TRACE("[Thread %2u] and\n", p->thread_id);
2705
2706         ALU(t, ip, &);
2707 }
2708
2709 static inline void
2710 __instr_alu_and_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2711                         struct thread *t,
2712                         const struct instruction *ip)
2713 {
2714         TRACE("[Thread %2u] and (mh)\n", p->thread_id);
2715
2716         ALU_MH(t, ip, &);
2717 }
2718
2719 static inline void
2720 __instr_alu_and_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2721                         struct thread *t,
2722                         const struct instruction *ip)
2723 {
2724         TRACE("[Thread %2u] and (hm)\n", p->thread_id);
2725
2726         ALU_HM_FAST(t, ip, &);
2727 }
2728
2729 static inline void
2730 __instr_alu_and_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2731                         struct thread *t,
2732                         const struct instruction *ip)
2733 {
2734         TRACE("[Thread %2u] and (hh)\n", p->thread_id);
2735
2736         ALU_HH_FAST(t, ip, &);
2737 }
2738
2739 static inline void
2740 __instr_alu_and_i_exec(struct rte_swx_pipeline *p __rte_unused,
2741                        struct thread *t,
2742                        const struct instruction *ip)
2743 {
2744         TRACE("[Thread %2u] and (i)\n", p->thread_id);
2745
2746         ALU_I(t, ip, &);
2747 }
2748
2749 static inline void
2750 __instr_alu_or_exec(struct rte_swx_pipeline *p __rte_unused,
2751                     struct thread *t,
2752                     const struct instruction *ip)
2753 {
2754         TRACE("[Thread %2u] or\n", p->thread_id);
2755
2756         ALU(t, ip, |);
2757 }
2758
2759 static inline void
2760 __instr_alu_or_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2761                        struct thread *t,
2762                        const struct instruction *ip)
2763 {
2764         TRACE("[Thread %2u] or (mh)\n", p->thread_id);
2765
2766         ALU_MH(t, ip, |);
2767 }
2768
2769 static inline void
2770 __instr_alu_or_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2771                        struct thread *t,
2772                        const struct instruction *ip)
2773 {
2774         TRACE("[Thread %2u] or (hm)\n", p->thread_id);
2775
2776         ALU_HM_FAST(t, ip, |);
2777 }
2778
2779 static inline void
2780 __instr_alu_or_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2781                        struct thread *t,
2782                        const struct instruction *ip)
2783 {
2784         TRACE("[Thread %2u] or (hh)\n", p->thread_id);
2785
2786         ALU_HH_FAST(t, ip, |);
2787 }
2788
2789 static inline void
2790 __instr_alu_or_i_exec(struct rte_swx_pipeline *p __rte_unused,
2791                       struct thread *t,
2792                       const struct instruction *ip)
2793 {
2794         TRACE("[Thread %2u] or (i)\n", p->thread_id);
2795
2796         ALU_I(t, ip, |);
2797 }
2798
2799 static inline void
2800 __instr_alu_xor_exec(struct rte_swx_pipeline *p __rte_unused,
2801                      struct thread *t,
2802                      const struct instruction *ip)
2803 {
2804         TRACE("[Thread %2u] xor\n", p->thread_id);
2805
2806         ALU(t, ip, ^);
2807 }
2808
2809 static inline void
2810 __instr_alu_xor_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2811                         struct thread *t,
2812                         const struct instruction *ip)
2813 {
2814         TRACE("[Thread %2u] xor (mh)\n", p->thread_id);
2815
2816         ALU_MH(t, ip, ^);
2817 }
2818
2819 static inline void
2820 __instr_alu_xor_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2821                         struct thread *t,
2822                         const struct instruction *ip)
2823 {
2824         TRACE("[Thread %2u] xor (hm)\n", p->thread_id);
2825
2826         ALU_HM_FAST(t, ip, ^);
2827 }
2828
2829 static inline void
2830 __instr_alu_xor_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2831                         struct thread *t,
2832                         const struct instruction *ip)
2833 {
2834         TRACE("[Thread %2u] xor (hh)\n", p->thread_id);
2835
2836         ALU_HH_FAST(t, ip, ^);
2837 }
2838
2839 static inline void
2840 __instr_alu_xor_i_exec(struct rte_swx_pipeline *p __rte_unused,
2841                        struct thread *t,
2842                        const struct instruction *ip)
2843 {
2844         TRACE("[Thread %2u] xor (i)\n", p->thread_id);
2845
2846         ALU_I(t, ip, ^);
2847 }
2848
2849 static inline void
2850 __instr_alu_ckadd_field_exec(struct rte_swx_pipeline *p __rte_unused,
2851                              struct thread *t,
2852                              const struct instruction *ip)
2853 {
2854         uint8_t *dst_struct, *src_struct;
2855         uint16_t *dst16_ptr, dst;
2856         uint64_t *src64_ptr, src64, src64_mask, src;
2857         uint64_t r;
2858
2859         TRACE("[Thread %2u] ckadd (field)\n", p->thread_id);
2860
2861         /* Structs. */
2862         dst_struct = t->structs[ip->alu.dst.struct_id];
2863         dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
2864         dst = *dst16_ptr;
2865
2866         src_struct = t->structs[ip->alu.src.struct_id];
2867         src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
2868         src64 = *src64_ptr;
2869         src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
2870         src = src64 & src64_mask;
2871
2872         /* Initialize the result with destination 1's complement. */
2873         r = dst;
2874         r = ~r & 0xFFFF;
2875
2876         /* The first input (r) is a 16-bit number. The second and the third
2877          * inputs are 32-bit numbers. In the worst case scenario, the sum of the
2878          * three numbers (output r) is a 34-bit number.
2879          */
2880         r += (src >> 32) + (src & 0xFFFFFFFF);
2881
2882         /* The first input is a 16-bit number. The second input is an 18-bit
2883          * number. In the worst case scenario, the sum of the two numbers is a
2884          * 19-bit number.
2885          */
2886         r = (r & 0xFFFF) + (r >> 16);
2887
2888         /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
2889          * a 3-bit number (0 .. 7). Their sum is a 17-bit number (0 .. 0x10006).
2890          */
2891         r = (r & 0xFFFF) + (r >> 16);
2892
2893         /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
2894          * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
2895          * 0x10006), the output r is (0 .. 7). So no carry bit can be generated,
2896          * therefore the output r is always a 16-bit number.
2897          */
2898         r = (r & 0xFFFF) + (r >> 16);
2899
2900         /* Apply 1's complement to the result. */
2901         r = ~r & 0xFFFF;
2902         r = r ? r : 0xFFFF;
2903
2904         *dst16_ptr = (uint16_t)r;
2905 }
2906
2907 static inline void
2908 __instr_alu_cksub_field_exec(struct rte_swx_pipeline *p __rte_unused,
2909                              struct thread *t,
2910                              const struct instruction *ip)
2911 {
2912         uint8_t *dst_struct, *src_struct;
2913         uint16_t *dst16_ptr, dst;
2914         uint64_t *src64_ptr, src64, src64_mask, src;
2915         uint64_t r;
2916
2917         TRACE("[Thread %2u] cksub (field)\n", p->thread_id);
2918
2919         /* Structs. */
2920         dst_struct = t->structs[ip->alu.dst.struct_id];
2921         dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
2922         dst = *dst16_ptr;
2923
2924         src_struct = t->structs[ip->alu.src.struct_id];
2925         src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
2926         src64 = *src64_ptr;
2927         src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
2928         src = src64 & src64_mask;
2929
2930         /* Initialize the result with destination 1's complement. */
2931         r = dst;
2932         r = ~r & 0xFFFF;
2933
2934         /* Subtraction in 1's complement arithmetic (i.e. a '- b) is the same as
2935          * the following sequence of operations in 2's complement arithmetic:
2936          *    a '- b = (a - b) % 0xFFFF.
2937          *
2938          * In order to prevent an underflow for the below subtraction, in which
2939          * a 33-bit number (the subtrahend) is taken out of a 16-bit number (the
2940          * minuend), we first add a multiple of the 0xFFFF modulus to the
2941          * minuend. The number we add to the minuend needs to be a 34-bit number
2942          * or higher, so for readability reasons we picked the 36-bit multiple.
2943          * We are effectively turning the 16-bit minuend into a 36-bit number:
2944          *    (a - b) % 0xFFFF = (a + 0xFFFF00000 - b) % 0xFFFF.
2945          */
2946         r += 0xFFFF00000ULL; /* The output r is a 36-bit number. */
2947
2948         /* A 33-bit number is subtracted from a 36-bit number (the input r). The
2949          * result (the output r) is a 36-bit number.
2950          */
2951         r -= (src >> 32) + (src & 0xFFFFFFFF);
2952
2953         /* The first input is a 16-bit number. The second input is a 20-bit
2954          * number. Their sum is a 21-bit number.
2955          */
2956         r = (r & 0xFFFF) + (r >> 16);
2957
2958         /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
2959          * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1001E).
2960          */
2961         r = (r & 0xFFFF) + (r >> 16);
2962
2963         /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
2964          * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
2965          * 0x1001E), the output r is (0 .. 31). So no carry bit can be
2966          * generated, therefore the output r is always a 16-bit number.
2967          */
2968         r = (r & 0xFFFF) + (r >> 16);
2969
2970         /* Apply 1's complement to the result. */
2971         r = ~r & 0xFFFF;
2972         r = r ? r : 0xFFFF;
2973
2974         *dst16_ptr = (uint16_t)r;
2975 }
2976
2977 static inline void
2978 __instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline *p __rte_unused,
2979                                 struct thread *t,
2980                                 const struct instruction *ip)
2981 {
2982         uint8_t *dst_struct, *src_struct;
2983         uint16_t *dst16_ptr, dst;
2984         uint32_t *src32_ptr;
2985         uint64_t r0, r1;
2986
2987         TRACE("[Thread %2u] ckadd (struct of 20 bytes)\n", p->thread_id);
2988
2989         /* Structs. */
2990         dst_struct = t->structs[ip->alu.dst.struct_id];
2991         dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
2992         dst = *dst16_ptr;
2993
2994         src_struct = t->structs[ip->alu.src.struct_id];
2995         src32_ptr = (uint32_t *)&src_struct[0];
2996
2997         /* Initialize the result with destination 1's complement. */
2998         r0 = dst;
2999         r0 = ~r0 & 0xFFFF;
3000
3001         r0 += src32_ptr[0]; /* The output r0 is a 33-bit number. */
3002         r1 = src32_ptr[1]; /* r1 is a 32-bit number. */
3003         r0 += src32_ptr[2]; /* The output r0 is a 34-bit number. */
3004         r1 += src32_ptr[3]; /* The output r1 is a 33-bit number. */
3005         r0 += r1 + src32_ptr[4]; /* The output r0 is a 35-bit number. */
3006
3007         /* The first input is a 16-bit number. The second input is a 19-bit
3008          * number. Their sum is a 20-bit number.
3009          */
3010         r0 = (r0 & 0xFFFF) + (r0 >> 16);
3011
3012         /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
3013          * a 4-bit number (0 .. 15). The sum is a 17-bit number (0 .. 0x1000E).
3014          */
3015         r0 = (r0 & 0xFFFF) + (r0 >> 16);
3016
3017         /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
3018          * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
3019          * 0x1000E), the output r is (0 .. 15). So no carry bit can be
3020          * generated, therefore the output r is always a 16-bit number.
3021          */
3022         r0 = (r0 & 0xFFFF) + (r0 >> 16);
3023
3024         /* Apply 1's complement to the result. */
3025         r0 = ~r0 & 0xFFFF;
3026         r0 = r0 ? r0 : 0xFFFF;
3027
3028         *dst16_ptr = (uint16_t)r0;
3029 }
3030
3031 static inline void
3032 __instr_alu_ckadd_struct_exec(struct rte_swx_pipeline *p __rte_unused,
3033                               struct thread *t,
3034                               const struct instruction *ip)
3035 {
3036         uint32_t src_header_id = ip->alu.src.n_bits; /* The src header ID is stored here. */
3037         uint32_t n_src_header_bytes = t->headers[src_header_id].n_bytes;
3038         uint8_t *dst_struct, *src_struct;
3039         uint16_t *dst16_ptr, dst;
3040         uint32_t *src32_ptr;
3041         uint64_t r;
3042         uint32_t i;
3043
3044         if (n_src_header_bytes == 20) {
3045                 __instr_alu_ckadd_struct20_exec(p, t, ip);
3046                 return;
3047         }
3048
3049         TRACE("[Thread %2u] ckadd (struct)\n", p->thread_id);
3050
3051         /* Structs. */
3052         dst_struct = t->structs[ip->alu.dst.struct_id];
3053         dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
3054         dst = *dst16_ptr;
3055
3056         src_struct = t->structs[ip->alu.src.struct_id];
3057         src32_ptr = (uint32_t *)&src_struct[0];
3058
3059         /* Initialize the result with destination 1's complement. */
3060         r = dst;
3061         r = ~r & 0xFFFF;
3062
3063         /* The max number of 32-bit words in a 32K-byte header is 2^13.
3064          * Therefore, in the worst case scenario, a 45-bit number is added to a
3065          * 16-bit number (the input r), so the output r is 46-bit number.
3066          */
3067         for (i = 0; i < n_src_header_bytes / 4; i++, src32_ptr++)
3068                 r += *src32_ptr;
3069
3070         /* The first input is a 16-bit number. The second input is a 30-bit
3071          * number. Their sum is a 31-bit number.
3072          */
3073         r = (r & 0xFFFF) + (r >> 16);
3074
3075         /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
3076          * a 15-bit number (0 .. 0x7FFF). The sum is a 17-bit number (0 .. 0x17FFE).
3077          */
3078         r = (r & 0xFFFF) + (r >> 16);
3079
3080         /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
3081          * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
3082          * 0x17FFE), the output r is (0 .. 0x7FFF). So no carry bit can be
3083          * generated, therefore the output r is always a 16-bit number.
3084          */
3085         r = (r & 0xFFFF) + (r >> 16);
3086
3087         /* Apply 1's complement to the result. */
3088         r = ~r & 0xFFFF;
3089         r = r ? r : 0xFFFF;
3090
3091         *dst16_ptr = (uint16_t)r;
3092 }
3093
3094 /*
3095  * Register array.
3096  */
3097 static inline uint64_t *
3098 instr_regarray_regarray(struct rte_swx_pipeline *p, const struct instruction *ip)
3099 {
3100         struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
3101         return r->regarray;
3102 }
3103
3104 static inline uint64_t
3105 instr_regarray_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3106 {
3107         struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
3108
3109         uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
3110         uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
3111         uint64_t idx64 = *idx64_ptr;
3112         uint64_t idx64_mask = UINT64_MAX >> (64 - ip->regarray.idx.n_bits);
3113         uint64_t idx = idx64 & idx64_mask & r->size_mask;
3114
3115         return idx;
3116 }
3117
3118 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
3119
3120 static inline uint64_t
3121 instr_regarray_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3122 {
3123         struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
3124
3125         uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
3126         uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
3127         uint64_t idx64 = *idx64_ptr;
3128         uint64_t idx = (ntoh64(idx64) >> (64 - ip->regarray.idx.n_bits)) & r->size_mask;
3129
3130         return idx;
3131 }
3132
3133 #else
3134
3135 #define instr_regarray_idx_nbo instr_regarray_idx_hbo
3136
3137 #endif
3138
3139 static inline uint64_t
3140 instr_regarray_idx_imm(struct rte_swx_pipeline *p, const struct instruction *ip)
3141 {
3142         struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
3143
3144         uint64_t idx = ip->regarray.idx_val & r->size_mask;
3145
3146         return idx;
3147 }
3148
3149 static inline uint64_t
3150 instr_regarray_src_hbo(struct thread *t, const struct instruction *ip)
3151 {
3152         uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
3153         uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
3154         uint64_t src64 = *src64_ptr;
3155         uint64_t src64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
3156         uint64_t src = src64 & src64_mask;
3157
3158         return src;
3159 }
3160
3161 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
3162
3163 static inline uint64_t
3164 instr_regarray_src_nbo(struct thread *t, const struct instruction *ip)
3165 {
3166         uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
3167         uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
3168         uint64_t src64 = *src64_ptr;
3169         uint64_t src = ntoh64(src64) >> (64 - ip->regarray.dstsrc.n_bits);
3170
3171         return src;
3172 }
3173
3174 #else
3175
3176 #define instr_regarray_src_nbo instr_regarray_src_hbo
3177
3178 #endif
3179
3180 static inline void
3181 instr_regarray_dst_hbo_src_hbo_set(struct thread *t, const struct instruction *ip, uint64_t src)
3182 {
3183         uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
3184         uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
3185         uint64_t dst64 = *dst64_ptr;
3186         uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
3187
3188         *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
3189
3190 }
3191
3192 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
3193
3194 static inline void
3195 instr_regarray_dst_nbo_src_hbo_set(struct thread *t, const struct instruction *ip, uint64_t src)
3196 {
3197         uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
3198         uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
3199         uint64_t dst64 = *dst64_ptr;
3200         uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
3201
3202         src = hton64(src) >> (64 - ip->regarray.dstsrc.n_bits);
3203         *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
3204 }
3205
3206 #else
3207
3208 #define instr_regarray_dst_nbo_src_hbo_set instr_regarray_dst_hbo_src_hbo_set
3209
3210 #endif
3211
3212 static inline void
3213 __instr_regprefetch_rh_exec(struct rte_swx_pipeline *p,
3214                             struct thread *t,
3215                             const struct instruction *ip)
3216 {
3217         uint64_t *regarray, idx;
3218
3219         TRACE("[Thread %2u] regprefetch (r[h])\n", p->thread_id);
3220
3221         regarray = instr_regarray_regarray(p, ip);
3222         idx = instr_regarray_idx_nbo(p, t, ip);
3223         rte_prefetch0(&regarray[idx]);
3224 }
3225
3226 static inline void
3227 __instr_regprefetch_rm_exec(struct rte_swx_pipeline *p,
3228                             struct thread *t,
3229                             const struct instruction *ip)
3230 {
3231         uint64_t *regarray, idx;
3232
3233         TRACE("[Thread %2u] regprefetch (r[m])\n", p->thread_id);
3234
3235         regarray = instr_regarray_regarray(p, ip);
3236         idx = instr_regarray_idx_hbo(p, t, ip);
3237         rte_prefetch0(&regarray[idx]);
3238 }
3239
3240 static inline void
3241 __instr_regprefetch_ri_exec(struct rte_swx_pipeline *p,
3242                             struct thread *t __rte_unused,
3243                             const struct instruction *ip)
3244 {
3245         uint64_t *regarray, idx;
3246
3247         TRACE("[Thread %2u] regprefetch (r[i])\n", p->thread_id);
3248
3249         regarray = instr_regarray_regarray(p, ip);
3250         idx = instr_regarray_idx_imm(p, ip);
3251         rte_prefetch0(&regarray[idx]);
3252 }
3253
3254 static inline void
3255 __instr_regrd_hrh_exec(struct rte_swx_pipeline *p,
3256                        struct thread *t,
3257                        const struct instruction *ip)
3258 {
3259         uint64_t *regarray, idx;
3260
3261         TRACE("[Thread %2u] regrd (h = r[h])\n", p->thread_id);
3262
3263         regarray = instr_regarray_regarray(p, ip);
3264         idx = instr_regarray_idx_nbo(p, t, ip);
3265         instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
3266 }
3267
3268 static inline void
3269 __instr_regrd_hrm_exec(struct rte_swx_pipeline *p,
3270                        struct thread *t,
3271                        const struct instruction *ip)
3272 {
3273         uint64_t *regarray, idx;
3274
3275         TRACE("[Thread %2u] regrd (h = r[m])\n", p->thread_id);
3276
3277         /* Structs. */
3278         regarray = instr_regarray_regarray(p, ip);
3279         idx = instr_regarray_idx_hbo(p, t, ip);
3280         instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
3281 }
3282
3283 static inline void
3284 __instr_regrd_mrh_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3285 {
3286         uint64_t *regarray, idx;
3287
3288         TRACE("[Thread %2u] regrd (m = r[h])\n", p->thread_id);
3289
3290         regarray = instr_regarray_regarray(p, ip);
3291         idx = instr_regarray_idx_nbo(p, t, ip);
3292         instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
3293 }
3294
3295 static inline void
3296 __instr_regrd_mrm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3297 {
3298         uint64_t *regarray, idx;
3299
3300         TRACE("[Thread %2u] regrd (m = r[m])\n", p->thread_id);
3301
3302         regarray = instr_regarray_regarray(p, ip);
3303         idx = instr_regarray_idx_hbo(p, t, ip);
3304         instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
3305 }
3306
3307 static inline void
3308 __instr_regrd_hri_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3309 {
3310         uint64_t *regarray, idx;
3311
3312         TRACE("[Thread %2u] regrd (h = r[i])\n", p->thread_id);
3313
3314         regarray = instr_regarray_regarray(p, ip);
3315         idx = instr_regarray_idx_imm(p, ip);
3316         instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
3317 }
3318
3319 static inline void
3320 __instr_regrd_mri_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3321 {
3322         uint64_t *regarray, idx;
3323
3324         TRACE("[Thread %2u] regrd (m = r[i])\n", p->thread_id);
3325
3326         regarray = instr_regarray_regarray(p, ip);
3327         idx = instr_regarray_idx_imm(p, ip);
3328         instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
3329 }
3330
3331 static inline void
3332 __instr_regwr_rhh_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3333 {
3334         uint64_t *regarray, idx, src;
3335
3336         TRACE("[Thread %2u] regwr (r[h] = h)\n", p->thread_id);
3337
3338         regarray = instr_regarray_regarray(p, ip);
3339         idx = instr_regarray_idx_nbo(p, t, ip);
3340         src = instr_regarray_src_nbo(t, ip);
3341         regarray[idx] = src;
3342 }
3343
3344 static inline void
3345 __instr_regwr_rhm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3346 {
3347         uint64_t *regarray, idx, src;
3348
3349         TRACE("[Thread %2u] regwr (r[h] = m)\n", p->thread_id);
3350
3351         regarray = instr_regarray_regarray(p, ip);
3352         idx = instr_regarray_idx_nbo(p, t, ip);
3353         src = instr_regarray_src_hbo(t, ip);
3354         regarray[idx] = src;
3355 }
3356
3357 static inline void
3358 __instr_regwr_rmh_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3359 {
3360         uint64_t *regarray, idx, src;
3361
3362         TRACE("[Thread %2u] regwr (r[m] = h)\n", p->thread_id);
3363
3364         regarray = instr_regarray_regarray(p, ip);
3365         idx = instr_regarray_idx_hbo(p, t, ip);
3366         src = instr_regarray_src_nbo(t, ip);
3367         regarray[idx] = src;
3368 }
3369
3370 static inline void
3371 __instr_regwr_rmm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3372 {
3373         uint64_t *regarray, idx, src;
3374
3375         TRACE("[Thread %2u] regwr (r[m] = m)\n", p->thread_id);
3376
3377         regarray = instr_regarray_regarray(p, ip);
3378         idx = instr_regarray_idx_hbo(p, t, ip);
3379         src = instr_regarray_src_hbo(t, ip);
3380         regarray[idx] = src;
3381 }
3382
3383 static inline void
3384 __instr_regwr_rhi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3385 {
3386         uint64_t *regarray, idx, src;
3387
3388         TRACE("[Thread %2u] regwr (r[h] = i)\n", p->thread_id);
3389
3390         regarray = instr_regarray_regarray(p, ip);
3391         idx = instr_regarray_idx_nbo(p, t, ip);
3392         src = ip->regarray.dstsrc_val;
3393         regarray[idx] = src;
3394 }
3395
3396 static inline void
3397 __instr_regwr_rmi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3398 {
3399         uint64_t *regarray, idx, src;
3400
3401         TRACE("[Thread %2u] regwr (r[m] = i)\n", p->thread_id);
3402
3403         regarray = instr_regarray_regarray(p, ip);
3404         idx = instr_regarray_idx_hbo(p, t, ip);
3405         src = ip->regarray.dstsrc_val;
3406         regarray[idx] = src;
3407 }
3408
3409 static inline void
3410 __instr_regwr_rih_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3411 {
3412         uint64_t *regarray, idx, src;
3413
3414         TRACE("[Thread %2u] regwr (r[i] = h)\n", p->thread_id);
3415
3416         regarray = instr_regarray_regarray(p, ip);
3417         idx = instr_regarray_idx_imm(p, ip);
3418         src = instr_regarray_src_nbo(t, ip);
3419         regarray[idx] = src;
3420 }
3421
3422 static inline void
3423 __instr_regwr_rim_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3424 {
3425         uint64_t *regarray, idx, src;
3426
3427         TRACE("[Thread %2u] regwr (r[i] = m)\n", p->thread_id);
3428
3429         regarray = instr_regarray_regarray(p, ip);
3430         idx = instr_regarray_idx_imm(p, ip);
3431         src = instr_regarray_src_hbo(t, ip);
3432         regarray[idx] = src;
3433 }
3434
3435 static inline void
3436 __instr_regwr_rii_exec(struct rte_swx_pipeline *p,
3437                        struct thread *t __rte_unused,
3438                        const struct instruction *ip)
3439 {
3440         uint64_t *regarray, idx, src;
3441
3442         TRACE("[Thread %2u] regwr (r[i] = i)\n", p->thread_id);
3443
3444         regarray = instr_regarray_regarray(p, ip);
3445         idx = instr_regarray_idx_imm(p, ip);
3446         src = ip->regarray.dstsrc_val;
3447         regarray[idx] = src;
3448 }
3449
3450 static inline void
3451 __instr_regadd_rhh_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3452 {
3453         uint64_t *regarray, idx, src;
3454
3455         TRACE("[Thread %2u] regadd (r[h] += h)\n", p->thread_id);
3456
3457         regarray = instr_regarray_regarray(p, ip);
3458         idx = instr_regarray_idx_nbo(p, t, ip);
3459         src = instr_regarray_src_nbo(t, ip);
3460         regarray[idx] += src;
3461 }
3462
3463 static inline void
3464 __instr_regadd_rhm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3465 {
3466         uint64_t *regarray, idx, src;
3467
3468         TRACE("[Thread %2u] regadd (r[h] += m)\n", p->thread_id);
3469
3470         regarray = instr_regarray_regarray(p, ip);
3471         idx = instr_regarray_idx_nbo(p, t, ip);
3472         src = instr_regarray_src_hbo(t, ip);
3473         regarray[idx] += src;
3474 }
3475
3476 static inline void
3477 __instr_regadd_rmh_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3478 {
3479         uint64_t *regarray, idx, src;
3480
3481         TRACE("[Thread %2u] regadd (r[m] += h)\n", p->thread_id);
3482
3483         regarray = instr_regarray_regarray(p, ip);
3484         idx = instr_regarray_idx_hbo(p, t, ip);
3485         src = instr_regarray_src_nbo(t, ip);
3486         regarray[idx] += src;
3487 }
3488
3489 static inline void
3490 __instr_regadd_rmm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3491 {
3492         uint64_t *regarray, idx, src;
3493
3494         TRACE("[Thread %2u] regadd (r[m] += m)\n", p->thread_id);
3495
3496         regarray = instr_regarray_regarray(p, ip);
3497         idx = instr_regarray_idx_hbo(p, t, ip);
3498         src = instr_regarray_src_hbo(t, ip);
3499         regarray[idx] += src;
3500 }
3501
3502 static inline void
3503 __instr_regadd_rhi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3504 {
3505         uint64_t *regarray, idx, src;
3506
3507         TRACE("[Thread %2u] regadd (r[h] += i)\n", p->thread_id);
3508
3509         regarray = instr_regarray_regarray(p, ip);
3510         idx = instr_regarray_idx_nbo(p, t, ip);
3511         src = ip->regarray.dstsrc_val;
3512         regarray[idx] += src;
3513 }
3514
3515 static inline void
3516 __instr_regadd_rmi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3517 {
3518         uint64_t *regarray, idx, src;
3519
3520         TRACE("[Thread %2u] regadd (r[m] += i)\n", p->thread_id);
3521
3522         regarray = instr_regarray_regarray(p, ip);
3523         idx = instr_regarray_idx_hbo(p, t, ip);
3524         src = ip->regarray.dstsrc_val;
3525         regarray[idx] += src;
3526 }
3527
3528 static inline void
3529 __instr_regadd_rih_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3530 {
3531         uint64_t *regarray, idx, src;
3532
3533         TRACE("[Thread %2u] regadd (r[i] += h)\n", p->thread_id);
3534
3535         regarray = instr_regarray_regarray(p, ip);
3536         idx = instr_regarray_idx_imm(p, ip);
3537         src = instr_regarray_src_nbo(t, ip);
3538         regarray[idx] += src;
3539 }
3540
3541 static inline void
3542 __instr_regadd_rim_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3543 {
3544         uint64_t *regarray, idx, src;
3545
3546         TRACE("[Thread %2u] regadd (r[i] += m)\n", p->thread_id);
3547
3548         regarray = instr_regarray_regarray(p, ip);
3549         idx = instr_regarray_idx_imm(p, ip);
3550         src = instr_regarray_src_hbo(t, ip);
3551         regarray[idx] += src;
3552 }
3553
3554 static inline void
3555 __instr_regadd_rii_exec(struct rte_swx_pipeline *p,
3556                         struct thread *t __rte_unused,
3557                         const struct instruction *ip)
3558 {
3559         uint64_t *regarray, idx, src;
3560
3561         TRACE("[Thread %2u] regadd (r[i] += i)\n", p->thread_id);
3562
3563         regarray = instr_regarray_regarray(p, ip);
3564         idx = instr_regarray_idx_imm(p, ip);
3565         src = ip->regarray.dstsrc_val;
3566         regarray[idx] += src;
3567 }
3568
3569 /*
3570  * metarray.
3571  */
3572 static inline struct meter *
3573 instr_meter_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3574 {
3575         struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
3576
3577         uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
3578         uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
3579         uint64_t idx64 = *idx64_ptr;
3580         uint64_t idx64_mask = UINT64_MAX >> (64 - (ip)->meter.idx.n_bits);
3581         uint64_t idx = idx64 & idx64_mask & r->size_mask;
3582
3583         return &r->metarray[idx];
3584 }
3585
3586 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
3587
3588 static inline struct meter *
3589 instr_meter_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3590 {
3591         struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
3592
3593         uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
3594         uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
3595         uint64_t idx64 = *idx64_ptr;
3596         uint64_t idx = (ntoh64(idx64) >> (64 - ip->meter.idx.n_bits)) & r->size_mask;
3597
3598         return &r->metarray[idx];
3599 }
3600
3601 #else
3602
3603 #define instr_meter_idx_nbo instr_meter_idx_hbo
3604
3605 #endif
3606
3607 static inline struct meter *
3608 instr_meter_idx_imm(struct rte_swx_pipeline *p, const struct instruction *ip)
3609 {
3610         struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
3611
3612         uint64_t idx =  ip->meter.idx_val & r->size_mask;
3613
3614         return &r->metarray[idx];
3615 }
3616
3617 static inline uint32_t
3618 instr_meter_length_hbo(struct thread *t, const struct instruction *ip)
3619 {
3620         uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
3621         uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
3622         uint64_t src64 = *src64_ptr;
3623         uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->meter.length.n_bits);
3624         uint64_t src = src64 & src64_mask;
3625
3626         return (uint32_t)src;
3627 }
3628
3629 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
3630
3631 static inline uint32_t
3632 instr_meter_length_nbo(struct thread *t, const struct instruction *ip)
3633 {
3634         uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
3635         uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
3636         uint64_t src64 = *src64_ptr;
3637         uint64_t src = ntoh64(src64) >> (64 - ip->meter.length.n_bits);
3638
3639         return (uint32_t)src;
3640 }
3641
3642 #else
3643
3644 #define instr_meter_length_nbo instr_meter_length_hbo
3645
3646 #endif
3647
3648 static inline enum rte_color
3649 instr_meter_color_in_hbo(struct thread *t, const struct instruction *ip)
3650 {
3651         uint8_t *src_struct = t->structs[ip->meter.color_in.struct_id];
3652         uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.color_in.offset];
3653         uint64_t src64 = *src64_ptr;
3654         uint64_t src64_mask = UINT64_MAX >> (64 - ip->meter.color_in.n_bits);
3655         uint64_t src = src64 & src64_mask;
3656
3657         return (enum rte_color)src;
3658 }
3659
3660 static inline void
3661 instr_meter_color_out_hbo_set(struct thread *t,
3662                               const struct instruction *ip,
3663                               enum rte_color color_out)
3664 {
3665         uint8_t *dst_struct = t->structs[ip->meter.color_out.struct_id];
3666         uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->meter.color_out.offset];
3667         uint64_t dst64 = *dst64_ptr;
3668         uint64_t dst64_mask = UINT64_MAX >> (64 - ip->meter.color_out.n_bits);
3669
3670         uint64_t src = (uint64_t)color_out;
3671
3672         *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
3673 }
3674
3675 static inline void
3676 __instr_metprefetch_h_exec(struct rte_swx_pipeline *p,
3677                            struct thread *t,
3678                            const struct instruction *ip)
3679 {
3680         struct meter *m;
3681
3682         TRACE("[Thread %2u] metprefetch (h)\n", p->thread_id);
3683
3684         m = instr_meter_idx_nbo(p, t, ip);
3685         rte_prefetch0(m);
3686 }
3687
3688 static inline void
3689 __instr_metprefetch_m_exec(struct rte_swx_pipeline *p,
3690                            struct thread *t,
3691                            const struct instruction *ip)
3692 {
3693         struct meter *m;
3694
3695         TRACE("[Thread %2u] metprefetch (m)\n", p->thread_id);
3696
3697         m = instr_meter_idx_hbo(p, t, ip);
3698         rte_prefetch0(m);
3699 }
3700
3701 static inline void
3702 __instr_metprefetch_i_exec(struct rte_swx_pipeline *p,
3703                            struct thread *t __rte_unused,
3704                            const struct instruction *ip)
3705 {
3706         struct meter *m;
3707
3708         TRACE("[Thread %2u] metprefetch (i)\n", p->thread_id);
3709
3710         m = instr_meter_idx_imm(p, ip);
3711         rte_prefetch0(m);
3712 }
3713
3714 static inline void
3715 __instr_meter_hhm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3716 {
3717         struct meter *m;
3718         uint64_t time, n_pkts, n_bytes;
3719         uint32_t length;
3720         enum rte_color color_in, color_out;
3721
3722         TRACE("[Thread %2u] meter (hhm)\n", p->thread_id);
3723
3724         m = instr_meter_idx_nbo(p, t, ip);
3725         rte_prefetch0(m->n_pkts);
3726         time = rte_get_tsc_cycles();
3727         length = instr_meter_length_nbo(t, ip);
3728         color_in = instr_meter_color_in_hbo(t, ip);
3729
3730         color_out = rte_meter_trtcm_color_aware_check(&m->m,
3731                 &m->profile->profile,
3732                 time,
3733                 length,
3734                 color_in);
3735
3736         color_out &= m->color_mask;
3737
3738         n_pkts = m->n_pkts[color_out];
3739         n_bytes = m->n_bytes[color_out];
3740
3741         instr_meter_color_out_hbo_set(t, ip, color_out);
3742
3743         m->n_pkts[color_out] = n_pkts + 1;
3744         m->n_bytes[color_out] = n_bytes + length;
3745 }
3746
3747 static inline void
3748 __instr_meter_hhi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3749 {
3750         struct meter *m;
3751         uint64_t time, n_pkts, n_bytes;
3752         uint32_t length;
3753         enum rte_color color_in, color_out;
3754
3755         TRACE("[Thread %2u] meter (hhi)\n", p->thread_id);
3756
3757         m = instr_meter_idx_nbo(p, t, ip);
3758         rte_prefetch0(m->n_pkts);
3759         time = rte_get_tsc_cycles();
3760         length = instr_meter_length_nbo(t, ip);
3761         color_in = (enum rte_color)ip->meter.color_in_val;
3762
3763         color_out = rte_meter_trtcm_color_aware_check(&m->m,
3764                 &m->profile->profile,
3765                 time,
3766                 length,
3767                 color_in);
3768
3769         color_out &= m->color_mask;
3770
3771         n_pkts = m->n_pkts[color_out];
3772         n_bytes = m->n_bytes[color_out];
3773
3774         instr_meter_color_out_hbo_set(t, ip, color_out);
3775
3776         m->n_pkts[color_out] = n_pkts + 1;
3777         m->n_bytes[color_out] = n_bytes + length;
3778 }
3779
3780 static inline void
3781 __instr_meter_hmm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3782 {
3783         struct meter *m;
3784         uint64_t time, n_pkts, n_bytes;
3785         uint32_t length;
3786         enum rte_color color_in, color_out;
3787
3788         TRACE("[Thread %2u] meter (hmm)\n", p->thread_id);
3789
3790         m = instr_meter_idx_nbo(p, t, ip);
3791         rte_prefetch0(m->n_pkts);
3792         time = rte_get_tsc_cycles();
3793         length = instr_meter_length_hbo(t, ip);
3794         color_in = instr_meter_color_in_hbo(t, ip);
3795
3796         color_out = rte_meter_trtcm_color_aware_check(&m->m,
3797                 &m->profile->profile,
3798                 time,
3799                 length,
3800                 color_in);
3801
3802         color_out &= m->color_mask;
3803
3804         n_pkts = m->n_pkts[color_out];
3805         n_bytes = m->n_bytes[color_out];
3806
3807         instr_meter_color_out_hbo_set(t, ip, color_out);
3808
3809         m->n_pkts[color_out] = n_pkts + 1;
3810         m->n_bytes[color_out] = n_bytes + length;
3811 }
3812
3813 static inline void
3814 __instr_meter_hmi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3815 {
3816         struct meter *m;
3817         uint64_t time, n_pkts, n_bytes;
3818         uint32_t length;
3819         enum rte_color color_in, color_out;
3820
3821         TRACE("[Thread %2u] meter (hmi)\n", p->thread_id);
3822
3823         m = instr_meter_idx_nbo(p, t, ip);
3824         rte_prefetch0(m->n_pkts);
3825         time = rte_get_tsc_cycles();
3826         length = instr_meter_length_hbo(t, ip);
3827         color_in = (enum rte_color)ip->meter.color_in_val;
3828
3829         color_out = rte_meter_trtcm_color_aware_check(&m->m,
3830                 &m->profile->profile,
3831                 time,
3832                 length,
3833                 color_in);
3834
3835         color_out &= m->color_mask;
3836
3837         n_pkts = m->n_pkts[color_out];
3838         n_bytes = m->n_bytes[color_out];
3839
3840         instr_meter_color_out_hbo_set(t, ip, color_out);
3841
3842         m->n_pkts[color_out] = n_pkts + 1;
3843         m->n_bytes[color_out] = n_bytes + length;
3844 }
3845
3846 static inline void
3847 __instr_meter_mhm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3848 {
3849         struct meter *m;
3850         uint64_t time, n_pkts, n_bytes;
3851         uint32_t length;
3852         enum rte_color color_in, color_out;
3853
3854         TRACE("[Thread %2u] meter (mhm)\n", p->thread_id);
3855
3856         m = instr_meter_idx_hbo(p, t, ip);
3857         rte_prefetch0(m->n_pkts);
3858         time = rte_get_tsc_cycles();
3859         length = instr_meter_length_nbo(t, ip);
3860         color_in = instr_meter_color_in_hbo(t, ip);
3861
3862         color_out = rte_meter_trtcm_color_aware_check(&m->m,
3863                 &m->profile->profile,
3864                 time,
3865                 length,
3866                 color_in);
3867
3868         color_out &= m->color_mask;
3869
3870         n_pkts = m->n_pkts[color_out];
3871         n_bytes = m->n_bytes[color_out];
3872
3873         instr_meter_color_out_hbo_set(t, ip, color_out);
3874
3875         m->n_pkts[color_out] = n_pkts + 1;
3876         m->n_bytes[color_out] = n_bytes + length;
3877 }
3878
3879 static inline void
3880 __instr_meter_mhi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3881 {
3882         struct meter *m;
3883         uint64_t time, n_pkts, n_bytes;
3884         uint32_t length;
3885         enum rte_color color_in, color_out;
3886
3887         TRACE("[Thread %2u] meter (mhi)\n", p->thread_id);
3888
3889         m = instr_meter_idx_hbo(p, t, ip);
3890         rte_prefetch0(m->n_pkts);
3891         time = rte_get_tsc_cycles();
3892         length = instr_meter_length_nbo(t, ip);
3893         color_in = (enum rte_color)ip->meter.color_in_val;
3894
3895         color_out = rte_meter_trtcm_color_aware_check(&m->m,
3896                 &m->profile->profile,
3897                 time,
3898                 length,
3899                 color_in);
3900
3901         color_out &= m->color_mask;
3902
3903         n_pkts = m->n_pkts[color_out];
3904         n_bytes = m->n_bytes[color_out];
3905
3906         instr_meter_color_out_hbo_set(t, ip, color_out);
3907
3908         m->n_pkts[color_out] = n_pkts + 1;
3909         m->n_bytes[color_out] = n_bytes + length;
3910 }
3911
3912 static inline void
3913 __instr_meter_mmm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3914 {
3915         struct meter *m;
3916         uint64_t time, n_pkts, n_bytes;
3917         uint32_t length;
3918         enum rte_color color_in, color_out;
3919
3920         TRACE("[Thread %2u] meter (mmm)\n", p->thread_id);
3921
3922         m = instr_meter_idx_hbo(p, t, ip);
3923         rte_prefetch0(m->n_pkts);
3924         time = rte_get_tsc_cycles();
3925         length = instr_meter_length_hbo(t, ip);
3926         color_in = instr_meter_color_in_hbo(t, ip);
3927
3928         color_out = rte_meter_trtcm_color_aware_check(&m->m,
3929                 &m->profile->profile,
3930                 time,
3931                 length,
3932                 color_in);
3933
3934         color_out &= m->color_mask;
3935
3936         n_pkts = m->n_pkts[color_out];
3937         n_bytes = m->n_bytes[color_out];
3938
3939         instr_meter_color_out_hbo_set(t, ip, color_out);
3940
3941         m->n_pkts[color_out] = n_pkts + 1;
3942         m->n_bytes[color_out] = n_bytes + length;
3943 }
3944
3945 static inline void
3946 __instr_meter_mmi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3947 {
3948         struct meter *m;
3949         uint64_t time, n_pkts, n_bytes;
3950         uint32_t length;
3951         enum rte_color color_in, color_out;
3952
3953         TRACE("[Thread %2u] meter (mmi)\n", p->thread_id);
3954
3955         m = instr_meter_idx_hbo(p, t, ip);
3956         rte_prefetch0(m->n_pkts);
3957         time = rte_get_tsc_cycles();
3958         length = instr_meter_length_hbo(t, ip);
3959         color_in = (enum rte_color)ip->meter.color_in_val;
3960
3961         color_out = rte_meter_trtcm_color_aware_check(&m->m,
3962                 &m->profile->profile,
3963                 time,
3964                 length,
3965                 color_in);
3966
3967         color_out &= m->color_mask;
3968
3969         n_pkts = m->n_pkts[color_out];
3970         n_bytes = m->n_bytes[color_out];
3971
3972         instr_meter_color_out_hbo_set(t, ip, color_out);
3973
3974         m->n_pkts[color_out] = n_pkts + 1;
3975         m->n_bytes[color_out] = n_bytes + length;
3976 }
3977
3978 static inline void
3979 __instr_meter_ihm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3980 {
3981         struct meter *m;
3982         uint64_t time, n_pkts, n_bytes;
3983         uint32_t length;
3984         enum rte_color color_in, color_out;
3985
3986         TRACE("[Thread %2u] meter (ihm)\n", p->thread_id);
3987
3988         m = instr_meter_idx_imm(p, ip);
3989         rte_prefetch0(m->n_pkts);
3990         time = rte_get_tsc_cycles();
3991         length = instr_meter_length_nbo(t, ip);
3992         color_in = instr_meter_color_in_hbo(t, ip);
3993
3994         color_out = rte_meter_trtcm_color_aware_check(&m->m,
3995                 &m->profile->profile,
3996                 time,
3997                 length,
3998                 color_in);
3999
4000         color_out &= m->color_mask;
4001
4002         n_pkts = m->n_pkts[color_out];
4003         n_bytes = m->n_bytes[color_out];
4004
4005         instr_meter_color_out_hbo_set(t, ip, color_out);
4006
4007         m->n_pkts[color_out] = n_pkts + 1;
4008         m->n_bytes[color_out] = n_bytes + length;
4009 }
4010
4011 static inline void
4012 __instr_meter_ihi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
4013 {
4014         struct meter *m;
4015         uint64_t time, n_pkts, n_bytes;
4016         uint32_t length;
4017         enum rte_color color_in, color_out;
4018
4019         TRACE("[Thread %2u] meter (ihi)\n", p->thread_id);
4020
4021         m = instr_meter_idx_imm(p, ip);
4022         rte_prefetch0(m->n_pkts);
4023         time = rte_get_tsc_cycles();
4024         length = instr_meter_length_nbo(t, ip);
4025         color_in = (enum rte_color)ip->meter.color_in_val;
4026
4027         color_out = rte_meter_trtcm_color_aware_check(&m->m,
4028                 &m->profile->profile,
4029                 time,
4030                 length,
4031                 color_in);
4032
4033         color_out &= m->color_mask;
4034
4035         n_pkts = m->n_pkts[color_out];
4036         n_bytes = m->n_bytes[color_out];
4037
4038         instr_meter_color_out_hbo_set(t, ip, color_out);
4039
4040         m->n_pkts[color_out] = n_pkts + 1;
4041         m->n_bytes[color_out] = n_bytes + length;
4042 }
4043
4044 static inline void
4045 __instr_meter_imm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
4046 {
4047         struct meter *m;
4048         uint64_t time, n_pkts, n_bytes;
4049         uint32_t length;
4050         enum rte_color color_in, color_out;
4051
4052         TRACE("[Thread %2u] meter (imm)\n", p->thread_id);
4053
4054         m = instr_meter_idx_imm(p, ip);
4055         rte_prefetch0(m->n_pkts);
4056         time = rte_get_tsc_cycles();
4057         length = instr_meter_length_hbo(t, ip);
4058         color_in = instr_meter_color_in_hbo(t, ip);
4059
4060         color_out = rte_meter_trtcm_color_aware_check(&m->m,
4061                 &m->profile->profile,
4062                 time,
4063                 length,
4064                 color_in);
4065
4066         color_out &= m->color_mask;
4067
4068         n_pkts = m->n_pkts[color_out];
4069         n_bytes = m->n_bytes[color_out];
4070
4071         instr_meter_color_out_hbo_set(t, ip, color_out);
4072
4073         m->n_pkts[color_out] = n_pkts + 1;
4074         m->n_bytes[color_out] = n_bytes + length;
4075 }
4076
4077 static inline void
4078 __instr_meter_imi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
4079 {
4080         struct meter *m;
4081         uint64_t time, n_pkts, n_bytes;
4082         uint32_t length;
4083         enum rte_color color_in, color_out;
4084
4085         TRACE("[Thread %2u] meter (imi)\n", p->thread_id);
4086
4087         m = instr_meter_idx_imm(p, ip);
4088         rte_prefetch0(m->n_pkts);
4089         time = rte_get_tsc_cycles();
4090         length = instr_meter_length_hbo(t, ip);
4091         color_in = (enum rte_color)ip->meter.color_in_val;
4092
4093         color_out = rte_meter_trtcm_color_aware_check(&m->m,
4094                 &m->profile->profile,
4095                 time,
4096                 length,
4097                 color_in);
4098
4099         color_out &= m->color_mask;
4100
4101         n_pkts = m->n_pkts[color_out];
4102         n_bytes = m->n_bytes[color_out];
4103
4104         instr_meter_color_out_hbo_set(t, ip, color_out);
4105
4106         m->n_pkts[color_out] = n_pkts + 1;
4107         m->n_bytes[color_out] = n_bytes + length;
4108 }
4109
4110 #endif