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