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