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