sleep in control plane thread
[dpdk.git] / app / test / test_bpf.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018 Intel Corporation
3  */
4
5 #include <stdio.h>
6 #include <string.h>
7 #include <stdint.h>
8 #include <inttypes.h>
9
10 #include <rte_memory.h>
11 #include <rte_debug.h>
12 #include <rte_hexdump.h>
13 #include <rte_random.h>
14 #include <rte_byteorder.h>
15 #include <rte_errno.h>
16 #include <rte_bpf.h>
17 #include <rte_ether.h>
18 #include <rte_ip.h>
19
20 #include "test.h"
21
22 /*
23  * Basic functional tests for librte_bpf.
24  * The main procedure - load eBPF program, execute it and
25  * compare restuls with expected values.
26  */
27
28 struct dummy_offset {
29         uint64_t u64;
30         uint32_t u32;
31         uint16_t u16;
32         uint8_t  u8;
33 };
34
35 struct dummy_vect8 {
36         struct dummy_offset in[8];
37         struct dummy_offset out[8];
38 };
39
40 struct dummy_net {
41         struct rte_ether_hdr eth_hdr;
42         struct rte_vlan_hdr vlan_hdr;
43         struct rte_ipv4_hdr ip_hdr;
44 };
45
46 #define TEST_FILL_1     0xDEADBEEF
47
48 #define TEST_MUL_1      21
49 #define TEST_MUL_2      -100
50
51 #define TEST_SHIFT_1    15
52 #define TEST_SHIFT_2    33
53
54 #define TEST_JCC_1      0
55 #define TEST_JCC_2      -123
56 #define TEST_JCC_3      5678
57 #define TEST_JCC_4      TEST_FILL_1
58
59 #define TEST_IMM_1      UINT64_MAX
60 #define TEST_IMM_2      ((uint64_t)INT64_MIN)
61 #define TEST_IMM_3      ((uint64_t)INT64_MAX + INT32_MAX)
62 #define TEST_IMM_4      ((uint64_t)UINT32_MAX)
63 #define TEST_IMM_5      ((uint64_t)UINT32_MAX + 1)
64
65 #define TEST_MEMFROB    0x2a2a2a2a
66
67 #define STRING_GEEK     0x6B656567
68 #define STRING_WEEK     0x6B656577
69
70 #define TEST_NETMASK 0xffffff00
71 #define TEST_SUBNET  0xaca80200
72
73 uint8_t src_mac[] = { 0x00, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF };
74 uint8_t dst_mac[] = { 0x00, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA };
75
76 uint32_t ip_src_addr = (172U << 24) | (168U << 16) | (2 << 8) | 1;
77 uint32_t ip_dst_addr = (172U << 24) | (168U << 16) | (2 << 8) | 2;
78
79 struct bpf_test {
80         const char *name;
81         size_t arg_sz;
82         struct rte_bpf_prm prm;
83         void (*prepare)(void *);
84         int (*check_result)(uint64_t, const void *);
85         uint32_t allow_fail;
86 };
87
88 /*
89  * Compare return value and result data with expected ones.
90  * Report a failure if they don't match.
91  */
92 static int
93 cmp_res(const char *func, uint64_t exp_rc, uint64_t ret_rc,
94         const void *exp_res, const void *ret_res, size_t res_sz)
95 {
96         int32_t ret;
97
98         ret = 0;
99         if (exp_rc != ret_rc) {
100                 printf("%s@%d: invalid return value, expected: 0x%" PRIx64
101                         ",result: 0x%" PRIx64 "\n",
102                         func, __LINE__, exp_rc, ret_rc);
103                 ret |= -1;
104         }
105
106         if (memcmp(exp_res, ret_res, res_sz) != 0) {
107                 printf("%s: invalid value\n", func);
108                 rte_memdump(stdout, "expected", exp_res, res_sz);
109                 rte_memdump(stdout, "result", ret_res, res_sz);
110                 ret |= -1;
111         }
112
113         return ret;
114 }
115
116 /* store immediate test-cases */
117 static const struct ebpf_insn test_store1_prog[] = {
118         {
119                 .code = (BPF_ST | BPF_MEM | BPF_B),
120                 .dst_reg = EBPF_REG_1,
121                 .off = offsetof(struct dummy_offset, u8),
122                 .imm = TEST_FILL_1,
123         },
124         {
125                 .code = (BPF_ST | BPF_MEM | BPF_H),
126                 .dst_reg = EBPF_REG_1,
127                 .off = offsetof(struct dummy_offset, u16),
128                 .imm = TEST_FILL_1,
129         },
130         {
131                 .code = (BPF_ST | BPF_MEM | BPF_W),
132                 .dst_reg = EBPF_REG_1,
133                 .off = offsetof(struct dummy_offset, u32),
134                 .imm = TEST_FILL_1,
135         },
136         {
137                 .code = (BPF_ST | BPF_MEM | EBPF_DW),
138                 .dst_reg = EBPF_REG_1,
139                 .off = offsetof(struct dummy_offset, u64),
140                 .imm = TEST_FILL_1,
141         },
142         /* return 1 */
143         {
144                 .code = (BPF_ALU | EBPF_MOV | BPF_K),
145                 .dst_reg = EBPF_REG_0,
146                 .imm = 1,
147         },
148         {
149                 .code = (BPF_JMP | EBPF_EXIT),
150         },
151 };
152
153 static void
154 test_store1_prepare(void *arg)
155 {
156         struct dummy_offset *df;
157
158         df = arg;
159         memset(df, 0, sizeof(*df));
160 }
161
162 static int
163 test_store1_check(uint64_t rc, const void *arg)
164 {
165         const struct dummy_offset *dft;
166         struct dummy_offset dfe;
167
168         dft = arg;
169
170         memset(&dfe, 0, sizeof(dfe));
171         dfe.u64 = (int32_t)TEST_FILL_1;
172         dfe.u32 = dfe.u64;
173         dfe.u16 = dfe.u64;
174         dfe.u8 = dfe.u64;
175
176         return cmp_res(__func__, 1, rc, &dfe, dft, sizeof(dfe));
177 }
178
179 /* store register test-cases */
180 static const struct ebpf_insn test_store2_prog[] = {
181
182         {
183                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
184                 .dst_reg = EBPF_REG_2,
185                 .imm = TEST_FILL_1,
186         },
187         {
188                 .code = (BPF_STX | BPF_MEM | BPF_B),
189                 .dst_reg = EBPF_REG_1,
190                 .src_reg = EBPF_REG_2,
191                 .off = offsetof(struct dummy_offset, u8),
192         },
193         {
194                 .code = (BPF_STX | BPF_MEM | BPF_H),
195                 .dst_reg = EBPF_REG_1,
196                 .src_reg = EBPF_REG_2,
197                 .off = offsetof(struct dummy_offset, u16),
198         },
199         {
200                 .code = (BPF_STX | BPF_MEM | BPF_W),
201                 .dst_reg = EBPF_REG_1,
202                 .src_reg = EBPF_REG_2,
203                 .off = offsetof(struct dummy_offset, u32),
204         },
205         {
206                 .code = (BPF_STX | BPF_MEM | EBPF_DW),
207                 .dst_reg = EBPF_REG_1,
208                 .src_reg = EBPF_REG_2,
209                 .off = offsetof(struct dummy_offset, u64),
210         },
211         /* return 1 */
212         {
213                 .code = (BPF_ALU | EBPF_MOV | BPF_K),
214                 .dst_reg = EBPF_REG_0,
215                 .imm = 1,
216         },
217         {
218                 .code = (BPF_JMP | EBPF_EXIT),
219         },
220 };
221
222 /* load test-cases */
223 static const struct ebpf_insn test_load1_prog[] = {
224
225         {
226                 .code = (BPF_LDX | BPF_MEM | BPF_B),
227                 .dst_reg = EBPF_REG_2,
228                 .src_reg = EBPF_REG_1,
229                 .off = offsetof(struct dummy_offset, u8),
230         },
231         {
232                 .code = (BPF_LDX | BPF_MEM | BPF_H),
233                 .dst_reg = EBPF_REG_3,
234                 .src_reg = EBPF_REG_1,
235                 .off = offsetof(struct dummy_offset, u16),
236         },
237         {
238                 .code = (BPF_LDX | BPF_MEM | BPF_W),
239                 .dst_reg = EBPF_REG_4,
240                 .src_reg = EBPF_REG_1,
241                 .off = offsetof(struct dummy_offset, u32),
242         },
243         {
244                 .code = (BPF_LDX | BPF_MEM | EBPF_DW),
245                 .dst_reg = EBPF_REG_0,
246                 .src_reg = EBPF_REG_1,
247                 .off = offsetof(struct dummy_offset, u64),
248         },
249         /* return sum */
250         {
251                 .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
252                 .dst_reg = EBPF_REG_0,
253                 .src_reg = EBPF_REG_4,
254         },
255         {
256                 .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
257                 .dst_reg = EBPF_REG_0,
258                 .src_reg = EBPF_REG_3,
259         },
260         {
261                 .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
262                 .dst_reg = EBPF_REG_0,
263                 .src_reg = EBPF_REG_2,
264         },
265         {
266                 .code = (BPF_JMP | EBPF_EXIT),
267         },
268 };
269
270 static void
271 test_load1_prepare(void *arg)
272 {
273         struct dummy_offset *df;
274
275         df = arg;
276
277         memset(df, 0, sizeof(*df));
278         df->u64 = (int32_t)TEST_FILL_1;
279         df->u32 = df->u64;
280         df->u16 = df->u64;
281         df->u8 = df->u64;
282 }
283
284 static int
285 test_load1_check(uint64_t rc, const void *arg)
286 {
287         uint64_t v;
288         const struct dummy_offset *dft;
289
290         dft = arg;
291         v = dft->u64;
292         v += dft->u32;
293         v += dft->u16;
294         v += dft->u8;
295
296         return cmp_res(__func__, v, rc, dft, dft, sizeof(*dft));
297 }
298
299 /* load immediate test-cases */
300 static const struct ebpf_insn test_ldimm1_prog[] = {
301
302         {
303                 .code = (BPF_LD | BPF_IMM | EBPF_DW),
304                 .dst_reg = EBPF_REG_0,
305                 .imm = (uint32_t)TEST_IMM_1,
306         },
307         {
308                 .imm = TEST_IMM_1 >> 32,
309         },
310         {
311                 .code = (BPF_LD | BPF_IMM | EBPF_DW),
312                 .dst_reg = EBPF_REG_3,
313                 .imm = (uint32_t)TEST_IMM_2,
314         },
315         {
316                 .imm = TEST_IMM_2 >> 32,
317         },
318         {
319                 .code = (BPF_LD | BPF_IMM | EBPF_DW),
320                 .dst_reg = EBPF_REG_5,
321                 .imm = (uint32_t)TEST_IMM_3,
322         },
323         {
324                 .imm = TEST_IMM_3 >> 32,
325         },
326         {
327                 .code = (BPF_LD | BPF_IMM | EBPF_DW),
328                 .dst_reg = EBPF_REG_7,
329                 .imm = (uint32_t)TEST_IMM_4,
330         },
331         {
332                 .imm = TEST_IMM_4 >> 32,
333         },
334         {
335                 .code = (BPF_LD | BPF_IMM | EBPF_DW),
336                 .dst_reg = EBPF_REG_9,
337                 .imm = (uint32_t)TEST_IMM_5,
338         },
339         {
340                 .imm = TEST_IMM_5 >> 32,
341         },
342         /* return sum */
343         {
344                 .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
345                 .dst_reg = EBPF_REG_0,
346                 .src_reg = EBPF_REG_3,
347         },
348         {
349                 .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
350                 .dst_reg = EBPF_REG_0,
351                 .src_reg = EBPF_REG_5,
352         },
353         {
354                 .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
355                 .dst_reg = EBPF_REG_0,
356                 .src_reg = EBPF_REG_7,
357         },
358         {
359                 .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
360                 .dst_reg = EBPF_REG_0,
361                 .src_reg = EBPF_REG_9,
362         },
363         {
364                 .code = (BPF_JMP | EBPF_EXIT),
365         },
366 };
367
368 static int
369 test_ldimm1_check(uint64_t rc, const void *arg)
370 {
371         uint64_t v1, v2;
372
373         v1 = TEST_IMM_1;
374         v2 = TEST_IMM_2;
375         v1 += v2;
376         v2 = TEST_IMM_3;
377         v1 += v2;
378         v2 = TEST_IMM_4;
379         v1 += v2;
380         v2 = TEST_IMM_5;
381         v1 += v2;
382
383         return cmp_res(__func__, v1, rc, arg, arg, 0);
384 }
385
386
387 /* alu mul test-cases */
388 static const struct ebpf_insn test_mul1_prog[] = {
389
390         {
391                 .code = (BPF_LDX | BPF_MEM | BPF_W),
392                 .dst_reg = EBPF_REG_2,
393                 .src_reg = EBPF_REG_1,
394                 .off = offsetof(struct dummy_vect8, in[0].u32),
395         },
396         {
397                 .code = (BPF_LDX | BPF_MEM | EBPF_DW),
398                 .dst_reg = EBPF_REG_3,
399                 .src_reg = EBPF_REG_1,
400                 .off = offsetof(struct dummy_vect8, in[1].u64),
401         },
402         {
403                 .code = (BPF_LDX | BPF_MEM | BPF_W),
404                 .dst_reg = EBPF_REG_4,
405                 .src_reg = EBPF_REG_1,
406                 .off = offsetof(struct dummy_vect8, in[2].u32),
407         },
408         {
409                 .code = (BPF_ALU | BPF_MUL | BPF_K),
410                 .dst_reg = EBPF_REG_2,
411                 .imm = TEST_MUL_1,
412         },
413         {
414                 .code = (EBPF_ALU64 | BPF_MUL | BPF_K),
415                 .dst_reg = EBPF_REG_3,
416                 .imm = TEST_MUL_2,
417         },
418         {
419                 .code = (BPF_ALU | BPF_MUL | BPF_X),
420                 .dst_reg = EBPF_REG_4,
421                 .src_reg = EBPF_REG_2,
422         },
423         {
424                 .code = (EBPF_ALU64 | BPF_MUL | BPF_X),
425                 .dst_reg = EBPF_REG_4,
426                 .src_reg = EBPF_REG_3,
427         },
428         {
429                 .code = (BPF_STX | BPF_MEM | EBPF_DW),
430                 .dst_reg = EBPF_REG_1,
431                 .src_reg = EBPF_REG_2,
432                 .off = offsetof(struct dummy_vect8, out[0].u64),
433         },
434         {
435                 .code = (BPF_STX | BPF_MEM | EBPF_DW),
436                 .dst_reg = EBPF_REG_1,
437                 .src_reg = EBPF_REG_3,
438                 .off = offsetof(struct dummy_vect8, out[1].u64),
439         },
440         {
441                 .code = (BPF_STX | BPF_MEM | EBPF_DW),
442                 .dst_reg = EBPF_REG_1,
443                 .src_reg = EBPF_REG_4,
444                 .off = offsetof(struct dummy_vect8, out[2].u64),
445         },
446         /* return 1 */
447         {
448                 .code = (BPF_ALU | EBPF_MOV | BPF_K),
449                 .dst_reg = EBPF_REG_0,
450                 .imm = 1,
451         },
452         {
453                 .code = (BPF_JMP | EBPF_EXIT),
454         },
455 };
456
457 static void
458 test_mul1_prepare(void *arg)
459 {
460         struct dummy_vect8 *dv;
461         uint64_t v;
462
463         dv = arg;
464
465         v = rte_rand();
466
467         memset(dv, 0, sizeof(*dv));
468         dv->in[0].u32 = v;
469         dv->in[1].u64 = v << 12 | v >> 6;
470         dv->in[2].u32 = -v;
471 }
472
473 static int
474 test_mul1_check(uint64_t rc, const void *arg)
475 {
476         uint64_t r2, r3, r4;
477         const struct dummy_vect8 *dvt;
478         struct dummy_vect8 dve;
479
480         dvt = arg;
481         memset(&dve, 0, sizeof(dve));
482
483         r2 = dvt->in[0].u32;
484         r3 = dvt->in[1].u64;
485         r4 = dvt->in[2].u32;
486
487         r2 = (uint32_t)r2 * TEST_MUL_1;
488         r3 *= TEST_MUL_2;
489         r4 = (uint32_t)(r4 * r2);
490         r4 *= r3;
491
492         dve.out[0].u64 = r2;
493         dve.out[1].u64 = r3;
494         dve.out[2].u64 = r4;
495
496         return cmp_res(__func__, 1, rc, dve.out, dvt->out, sizeof(dve.out));
497 }
498
499 /* alu shift test-cases */
500 static const struct ebpf_insn test_shift1_prog[] = {
501
502         {
503                 .code = (BPF_LDX | BPF_MEM | BPF_W),
504                 .dst_reg = EBPF_REG_2,
505                 .src_reg = EBPF_REG_1,
506                 .off = offsetof(struct dummy_vect8, in[0].u32),
507         },
508         {
509                 .code = (BPF_LDX | BPF_MEM | EBPF_DW),
510                 .dst_reg = EBPF_REG_3,
511                 .src_reg = EBPF_REG_1,
512                 .off = offsetof(struct dummy_vect8, in[1].u64),
513         },
514         {
515                 .code = (BPF_LDX | BPF_MEM | BPF_W),
516                 .dst_reg = EBPF_REG_4,
517                 .src_reg = EBPF_REG_1,
518                 .off = offsetof(struct dummy_vect8, in[2].u32),
519         },
520         {
521                 .code = (BPF_ALU | BPF_LSH | BPF_K),
522                 .dst_reg = EBPF_REG_2,
523                 .imm = TEST_SHIFT_1,
524         },
525         {
526                 .code = (EBPF_ALU64 | EBPF_ARSH | BPF_K),
527                 .dst_reg = EBPF_REG_3,
528                 .imm = TEST_SHIFT_2,
529         },
530         {
531                 .code = (BPF_STX | BPF_MEM | EBPF_DW),
532                 .dst_reg = EBPF_REG_1,
533                 .src_reg = EBPF_REG_2,
534                 .off = offsetof(struct dummy_vect8, out[0].u64),
535         },
536         {
537                 .code = (BPF_STX | BPF_MEM | EBPF_DW),
538                 .dst_reg = EBPF_REG_1,
539                 .src_reg = EBPF_REG_3,
540                 .off = offsetof(struct dummy_vect8, out[1].u64),
541         },
542         {
543                 .code = (BPF_ALU | BPF_RSH | BPF_X),
544                 .dst_reg = EBPF_REG_2,
545                 .src_reg = EBPF_REG_4,
546         },
547         {
548                 .code = (EBPF_ALU64 | BPF_LSH | BPF_X),
549                 .dst_reg = EBPF_REG_3,
550                 .src_reg = EBPF_REG_4,
551         },
552         {
553                 .code = (BPF_STX | BPF_MEM | EBPF_DW),
554                 .dst_reg = EBPF_REG_1,
555                 .src_reg = EBPF_REG_2,
556                 .off = offsetof(struct dummy_vect8, out[2].u64),
557         },
558         {
559                 .code = (BPF_STX | BPF_MEM | EBPF_DW),
560                 .dst_reg = EBPF_REG_1,
561                 .src_reg = EBPF_REG_3,
562                 .off = offsetof(struct dummy_vect8, out[3].u64),
563         },
564         {
565                 .code = (BPF_LDX | BPF_MEM | BPF_W),
566                 .dst_reg = EBPF_REG_2,
567                 .src_reg = EBPF_REG_1,
568                 .off = offsetof(struct dummy_vect8, in[0].u32),
569         },
570         {
571                 .code = (BPF_LDX | BPF_MEM | EBPF_DW),
572                 .dst_reg = EBPF_REG_3,
573                 .src_reg = EBPF_REG_1,
574                 .off = offsetof(struct dummy_vect8, in[1].u64),
575         },
576         {
577                 .code = (BPF_LDX | BPF_MEM | BPF_W),
578                 .dst_reg = EBPF_REG_4,
579                 .src_reg = EBPF_REG_1,
580                 .off = offsetof(struct dummy_vect8, in[2].u32),
581         },
582         {
583                 .code = (BPF_ALU | BPF_AND | BPF_K),
584                 .dst_reg = EBPF_REG_2,
585                 .imm = sizeof(uint64_t) * CHAR_BIT - 1,
586         },
587         {
588                 .code = (EBPF_ALU64 | EBPF_ARSH | BPF_X),
589                 .dst_reg = EBPF_REG_3,
590                 .src_reg = EBPF_REG_2,
591         },
592         {
593                 .code = (BPF_ALU | BPF_AND | BPF_K),
594                 .dst_reg = EBPF_REG_2,
595                 .imm = sizeof(uint32_t) * CHAR_BIT - 1,
596         },
597         {
598                 .code = (BPF_ALU | BPF_LSH | BPF_X),
599                 .dst_reg = EBPF_REG_4,
600                 .src_reg = EBPF_REG_2,
601         },
602         {
603                 .code = (BPF_STX | BPF_MEM | EBPF_DW),
604                 .dst_reg = EBPF_REG_1,
605                 .src_reg = EBPF_REG_4,
606                 .off = offsetof(struct dummy_vect8, out[4].u64),
607         },
608         {
609                 .code = (BPF_STX | BPF_MEM | EBPF_DW),
610                 .dst_reg = EBPF_REG_1,
611                 .src_reg = EBPF_REG_3,
612                 .off = offsetof(struct dummy_vect8, out[5].u64),
613         },
614         /* return 1 */
615         {
616                 .code = (BPF_ALU | EBPF_MOV | BPF_K),
617                 .dst_reg = EBPF_REG_0,
618                 .imm = 1,
619         },
620         {
621                 .code = (BPF_JMP | EBPF_EXIT),
622         },
623 };
624
625 static void
626 test_shift1_prepare(void *arg)
627 {
628         struct dummy_vect8 *dv;
629         uint64_t v;
630
631         dv = arg;
632
633         v = rte_rand();
634
635         memset(dv, 0, sizeof(*dv));
636         dv->in[0].u32 = v;
637         dv->in[1].u64 = v << 12 | v >> 6;
638         dv->in[2].u32 = (-v ^ 5);
639 }
640
641 static int
642 test_shift1_check(uint64_t rc, const void *arg)
643 {
644         uint64_t r2, r3, r4;
645         const struct dummy_vect8 *dvt;
646         struct dummy_vect8 dve;
647
648         dvt = arg;
649         memset(&dve, 0, sizeof(dve));
650
651         r2 = dvt->in[0].u32;
652         r3 = dvt->in[1].u64;
653         r4 = dvt->in[2].u32;
654
655         r2 = (uint32_t)r2 << TEST_SHIFT_1;
656         r3 = (int64_t)r3 >> TEST_SHIFT_2;
657
658         dve.out[0].u64 = r2;
659         dve.out[1].u64 = r3;
660
661         r2 = (uint32_t)r2 >> r4;
662         r3 <<= r4;
663
664         dve.out[2].u64 = r2;
665         dve.out[3].u64 = r3;
666
667         r2 = dvt->in[0].u32;
668         r3 = dvt->in[1].u64;
669         r4 = dvt->in[2].u32;
670
671         r2 &= sizeof(uint64_t) * CHAR_BIT - 1;
672         r3 = (int64_t)r3 >> r2;
673         r2 &= sizeof(uint32_t) * CHAR_BIT - 1;
674         r4 = (uint32_t)r4 << r2;
675
676         dve.out[4].u64 = r4;
677         dve.out[5].u64 = r3;
678
679         return cmp_res(__func__, 1, rc, dve.out, dvt->out, sizeof(dve.out));
680 }
681
682 /* jmp test-cases */
683 static const struct ebpf_insn test_jump1_prog[] = {
684
685         [0] = {
686                 .code = (BPF_ALU | EBPF_MOV | BPF_K),
687                 .dst_reg = EBPF_REG_0,
688                 .imm = 0,
689         },
690         [1] = {
691                 .code = (BPF_LDX | BPF_MEM | BPF_W),
692                 .dst_reg = EBPF_REG_2,
693                 .src_reg = EBPF_REG_1,
694                 .off = offsetof(struct dummy_vect8, in[0].u32),
695         },
696         [2] = {
697                 .code = (BPF_LDX | BPF_MEM | EBPF_DW),
698                 .dst_reg = EBPF_REG_3,
699                 .src_reg = EBPF_REG_1,
700                 .off = offsetof(struct dummy_vect8, in[0].u64),
701         },
702         [3] = {
703                 .code = (BPF_LDX | BPF_MEM | BPF_W),
704                 .dst_reg = EBPF_REG_4,
705                 .src_reg = EBPF_REG_1,
706                 .off = offsetof(struct dummy_vect8, in[1].u32),
707         },
708         [4] = {
709                 .code = (BPF_LDX | BPF_MEM | EBPF_DW),
710                 .dst_reg = EBPF_REG_5,
711                 .src_reg = EBPF_REG_1,
712                 .off = offsetof(struct dummy_vect8, in[1].u64),
713         },
714         [5] = {
715                 .code = (BPF_JMP | BPF_JEQ | BPF_K),
716                 .dst_reg = EBPF_REG_2,
717                 .imm = TEST_JCC_1,
718                 .off = 8,
719         },
720         [6] = {
721                 .code = (BPF_JMP | EBPF_JSLE | BPF_K),
722                 .dst_reg = EBPF_REG_3,
723                 .imm = TEST_JCC_2,
724                 .off = 9,
725         },
726         [7] = {
727                 .code = (BPF_JMP | BPF_JGT | BPF_K),
728                 .dst_reg = EBPF_REG_4,
729                 .imm = TEST_JCC_3,
730                 .off = 10,
731         },
732         [8] = {
733                 .code = (BPF_JMP | BPF_JSET | BPF_K),
734                 .dst_reg = EBPF_REG_5,
735                 .imm = TEST_JCC_4,
736                 .off = 11,
737         },
738         [9] = {
739                 .code = (BPF_JMP | EBPF_JNE | BPF_X),
740                 .dst_reg = EBPF_REG_2,
741                 .src_reg = EBPF_REG_3,
742                 .off = 12,
743         },
744         [10] = {
745                 .code = (BPF_JMP | EBPF_JSGT | BPF_X),
746                 .dst_reg = EBPF_REG_2,
747                 .src_reg = EBPF_REG_4,
748                 .off = 13,
749         },
750         [11] = {
751                 .code = (BPF_JMP | EBPF_JLE | BPF_X),
752                 .dst_reg = EBPF_REG_2,
753                 .src_reg = EBPF_REG_5,
754                 .off = 14,
755         },
756         [12] = {
757                 .code = (BPF_JMP | BPF_JSET | BPF_X),
758                 .dst_reg = EBPF_REG_3,
759                 .src_reg = EBPF_REG_5,
760                 .off = 15,
761         },
762         [13] = {
763                 .code = (BPF_JMP | EBPF_EXIT),
764         },
765         [14] = {
766                 .code = (EBPF_ALU64 | BPF_OR | BPF_K),
767                 .dst_reg = EBPF_REG_0,
768                 .imm = 0x1,
769         },
770         [15] = {
771                 .code = (BPF_JMP | BPF_JA),
772                 .off = -10,
773         },
774         [16] = {
775                 .code = (EBPF_ALU64 | BPF_OR | BPF_K),
776                 .dst_reg = EBPF_REG_0,
777                 .imm = 0x2,
778         },
779         [17] = {
780                 .code = (BPF_JMP | BPF_JA),
781                 .off = -11,
782         },
783         [18] = {
784                 .code = (EBPF_ALU64 | BPF_OR | BPF_K),
785                 .dst_reg = EBPF_REG_0,
786                 .imm = 0x4,
787         },
788         [19] = {
789                 .code = (BPF_JMP | BPF_JA),
790                 .off = -12,
791         },
792         [20] = {
793                 .code = (EBPF_ALU64 | BPF_OR | BPF_K),
794                 .dst_reg = EBPF_REG_0,
795                 .imm = 0x8,
796         },
797         [21] = {
798                 .code = (BPF_JMP | BPF_JA),
799                 .off = -13,
800         },
801         [22] = {
802                 .code = (EBPF_ALU64 | BPF_OR | BPF_K),
803                 .dst_reg = EBPF_REG_0,
804                 .imm = 0x10,
805         },
806         [23] = {
807                 .code = (BPF_JMP | BPF_JA),
808                 .off = -14,
809         },
810         [24] = {
811                 .code = (EBPF_ALU64 | BPF_OR | BPF_K),
812                 .dst_reg = EBPF_REG_0,
813                 .imm = 0x20,
814         },
815         [25] = {
816                 .code = (BPF_JMP | BPF_JA),
817                 .off = -15,
818         },
819         [26] = {
820                 .code = (EBPF_ALU64 | BPF_OR | BPF_K),
821                 .dst_reg = EBPF_REG_0,
822                 .imm = 0x40,
823         },
824         [27] = {
825                 .code = (BPF_JMP | BPF_JA),
826                 .off = -16,
827         },
828         [28] = {
829                 .code = (EBPF_ALU64 | BPF_OR | BPF_K),
830                 .dst_reg = EBPF_REG_0,
831                 .imm = 0x80,
832         },
833         [29] = {
834                 .code = (BPF_JMP | BPF_JA),
835                 .off = -17,
836         },
837 };
838
839 static void
840 test_jump1_prepare(void *arg)
841 {
842         struct dummy_vect8 *dv;
843         uint64_t v1, v2;
844
845         dv = arg;
846
847         v1 = rte_rand();
848         v2 = rte_rand();
849
850         memset(dv, 0, sizeof(*dv));
851         dv->in[0].u64 = v1;
852         dv->in[1].u64 = v2;
853         dv->in[0].u32 = (v1 << 12) + (v2 >> 6);
854         dv->in[1].u32 = (v2 << 12) - (v1 >> 6);
855 }
856
857 static int
858 test_jump1_check(uint64_t rc, const void *arg)
859 {
860         uint64_t r2, r3, r4, r5, rv;
861         const struct dummy_vect8 *dvt;
862
863         dvt = arg;
864
865         rv = 0;
866         r2 = dvt->in[0].u32;
867         r3 = dvt->in[0].u64;
868         r4 = dvt->in[1].u32;
869         r5 = dvt->in[1].u64;
870
871         if (r2 == TEST_JCC_1)
872                 rv |= 0x1;
873         if ((int64_t)r3 <= TEST_JCC_2)
874                 rv |= 0x2;
875         if (r4 > TEST_JCC_3)
876                 rv |= 0x4;
877         if (r5 & TEST_JCC_4)
878                 rv |= 0x8;
879         if (r2 != r3)
880                 rv |= 0x10;
881         if ((int64_t)r2 > (int64_t)r4)
882                 rv |= 0x20;
883         if (r2 <= r5)
884                 rv |= 0x40;
885         if (r3 & r5)
886                 rv |= 0x80;
887
888         return cmp_res(__func__, rv, rc, &rv, &rc, sizeof(rv));
889 }
890
891 /* Jump test case - check ip4_dest in particular subnet */
892 static const struct ebpf_insn test_jump2_prog[] = {
893
894         [0] = {
895                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
896                 .dst_reg = EBPF_REG_2,
897                 .imm = 0xe,
898         },
899         [1] = {
900                 .code = (BPF_LDX | BPF_MEM | BPF_H),
901                 .dst_reg = EBPF_REG_3,
902                 .src_reg = EBPF_REG_1,
903                 .off = 12,
904         },
905         [2] = {
906                 .code = (BPF_JMP | EBPF_JNE | BPF_K),
907                 .dst_reg = EBPF_REG_3,
908                 .off = 2,
909                 .imm = 0x81,
910         },
911         [3] = {
912                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
913                 .dst_reg = EBPF_REG_2,
914                 .imm = 0x12,
915         },
916         [4] = {
917                 .code = (BPF_LDX | BPF_MEM | BPF_H),
918                 .dst_reg = EBPF_REG_3,
919                 .src_reg = EBPF_REG_1,
920                 .off = 16,
921         },
922         [5] = {
923                 .code = (EBPF_ALU64 | BPF_AND | BPF_K),
924                 .dst_reg = EBPF_REG_3,
925                 .imm = 0xffff,
926         },
927         [6] = {
928                 .code = (BPF_JMP | EBPF_JNE | BPF_K),
929                 .dst_reg = EBPF_REG_3,
930                 .off = 9,
931                 .imm = 0x8,
932         },
933         [7] = {
934                 .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
935                 .dst_reg = EBPF_REG_1,
936                 .src_reg = EBPF_REG_2,
937         },
938         [8] = {
939                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
940                 .dst_reg = EBPF_REG_0,
941                 .imm = 0,
942         },
943         [9] = {
944                 .code = (BPF_LDX | BPF_MEM | BPF_W),
945                 .dst_reg = EBPF_REG_1,
946                 .src_reg = EBPF_REG_1,
947                 .off = 16,
948         },
949         [10] = {
950                 .code = (BPF_ALU | EBPF_MOV | BPF_K),
951                 .dst_reg = EBPF_REG_3,
952                 .imm = TEST_NETMASK,
953         },
954         [11] = {
955                 .code = (BPF_ALU | EBPF_END | EBPF_TO_BE),
956                 .dst_reg = EBPF_REG_3,
957                 .imm = sizeof(uint32_t) * CHAR_BIT,
958         },
959         [12] = {
960                 .code = (BPF_ALU | BPF_AND | BPF_X),
961                 .dst_reg = EBPF_REG_1,
962                 .src_reg = EBPF_REG_3,
963         },
964         [13] = {
965                 .code = (BPF_ALU | EBPF_MOV | BPF_K),
966                 .dst_reg = EBPF_REG_3,
967                 .imm = TEST_SUBNET,
968         },
969         [14] = {
970                 .code = (BPF_ALU | EBPF_END | EBPF_TO_BE),
971                 .dst_reg = EBPF_REG_3,
972                 .imm = sizeof(uint32_t) * CHAR_BIT,
973         },
974         [15] = {
975                 .code = (BPF_JMP | BPF_JEQ | BPF_X),
976                 .dst_reg = EBPF_REG_1,
977                 .src_reg = EBPF_REG_3,
978                 .off = 1,
979         },
980         [16] = {
981                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
982                 .dst_reg = EBPF_REG_0,
983                 .imm = -1,
984         },
985         [17] = {
986                 .code = (BPF_JMP | EBPF_EXIT),
987         },
988 };
989
990 /* Preparing a vlan packet */
991 static void
992 test_jump2_prepare(void *arg)
993 {
994         struct dummy_net *dn;
995
996         dn = arg;
997         memset(dn, 0, sizeof(*dn));
998
999         /*
1000          * Initialize ether header.
1001          */
1002         rte_ether_addr_copy((struct rte_ether_addr *)dst_mac,
1003                             &dn->eth_hdr.d_addr);
1004         rte_ether_addr_copy((struct rte_ether_addr *)src_mac,
1005                             &dn->eth_hdr.s_addr);
1006         dn->eth_hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
1007
1008         /*
1009          * Initialize vlan header.
1010          */
1011         dn->vlan_hdr.eth_proto =  rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
1012         dn->vlan_hdr.vlan_tci = 32;
1013
1014         /*
1015          * Initialize IP header.
1016          */
1017         dn->ip_hdr.version_ihl   = 0x45;    /*IP_VERSION | IP_HDRLEN*/
1018         dn->ip_hdr.time_to_live   = 64;   /* IP_DEFTTL */
1019         dn->ip_hdr.next_proto_id = IPPROTO_TCP;
1020         dn->ip_hdr.packet_id = rte_cpu_to_be_16(0x463c);
1021         dn->ip_hdr.total_length   = rte_cpu_to_be_16(60);
1022         dn->ip_hdr.src_addr = rte_cpu_to_be_32(ip_src_addr);
1023         dn->ip_hdr.dst_addr = rte_cpu_to_be_32(ip_dst_addr);
1024 }
1025
1026 static int
1027 test_jump2_check(uint64_t rc, const void *arg)
1028 {
1029         const struct rte_ether_hdr *eth_hdr = arg;
1030         const struct rte_ipv4_hdr *ipv4_hdr;
1031         const void *next = eth_hdr;
1032         uint16_t eth_type;
1033         uint64_t v = -1;
1034
1035         if (eth_hdr->ether_type == htons(0x8100)) {
1036                 const struct rte_vlan_hdr *vlan_hdr =
1037                         (const void *)(eth_hdr + 1);
1038                 eth_type = vlan_hdr->eth_proto;
1039                 next = vlan_hdr + 1;
1040         } else {
1041                 eth_type = eth_hdr->ether_type;
1042                 next = eth_hdr + 1;
1043         }
1044
1045         if (eth_type == htons(0x0800)) {
1046                 ipv4_hdr = next;
1047                 if ((ipv4_hdr->dst_addr & rte_cpu_to_be_32(TEST_NETMASK)) ==
1048                     rte_cpu_to_be_32(TEST_SUBNET)) {
1049                         v = 0;
1050                 }
1051         }
1052
1053         return cmp_res(__func__, v, rc, arg, arg, sizeof(arg));
1054 }
1055
1056 /* alu (add, sub, and, or, xor, neg)  test-cases */
1057 static const struct ebpf_insn test_alu1_prog[] = {
1058
1059         {
1060                 .code = (BPF_LDX | BPF_MEM | BPF_W),
1061                 .dst_reg = EBPF_REG_2,
1062                 .src_reg = EBPF_REG_1,
1063                 .off = offsetof(struct dummy_vect8, in[0].u32),
1064         },
1065         {
1066                 .code = (BPF_LDX | BPF_MEM | EBPF_DW),
1067                 .dst_reg = EBPF_REG_3,
1068                 .src_reg = EBPF_REG_1,
1069                 .off = offsetof(struct dummy_vect8, in[0].u64),
1070         },
1071         {
1072                 .code = (BPF_LDX | BPF_MEM | BPF_W),
1073                 .dst_reg = EBPF_REG_4,
1074                 .src_reg = EBPF_REG_1,
1075                 .off = offsetof(struct dummy_vect8, in[1].u32),
1076         },
1077         {
1078                 .code = (BPF_LDX | BPF_MEM | EBPF_DW),
1079                 .dst_reg = EBPF_REG_5,
1080                 .src_reg = EBPF_REG_1,
1081                 .off = offsetof(struct dummy_vect8, in[1].u64),
1082         },
1083         {
1084                 .code = (BPF_ALU | BPF_AND | BPF_K),
1085                 .dst_reg = EBPF_REG_2,
1086                 .imm = TEST_FILL_1,
1087         },
1088         {
1089                 .code = (EBPF_ALU64 | BPF_OR | BPF_K),
1090                 .dst_reg = EBPF_REG_3,
1091                 .imm = TEST_FILL_1,
1092         },
1093         {
1094                 .code = (BPF_ALU | BPF_XOR | BPF_K),
1095                 .dst_reg = EBPF_REG_4,
1096                 .imm = TEST_FILL_1,
1097         },
1098         {
1099                 .code = (EBPF_ALU64 | BPF_ADD | BPF_K),
1100                 .dst_reg = EBPF_REG_5,
1101                 .imm = TEST_FILL_1,
1102         },
1103         {
1104                 .code = (BPF_STX | BPF_MEM | EBPF_DW),
1105                 .dst_reg = EBPF_REG_1,
1106                 .src_reg = EBPF_REG_2,
1107                 .off = offsetof(struct dummy_vect8, out[0].u64),
1108         },
1109         {
1110                 .code = (BPF_STX | BPF_MEM | EBPF_DW),
1111                 .dst_reg = EBPF_REG_1,
1112                 .src_reg = EBPF_REG_3,
1113                 .off = offsetof(struct dummy_vect8, out[1].u64),
1114         },
1115         {
1116                 .code = (BPF_STX | BPF_MEM | EBPF_DW),
1117                 .dst_reg = EBPF_REG_1,
1118                 .src_reg = EBPF_REG_4,
1119                 .off = offsetof(struct dummy_vect8, out[2].u64),
1120         },
1121         {
1122                 .code = (BPF_STX | BPF_MEM | EBPF_DW),
1123                 .dst_reg = EBPF_REG_1,
1124                 .src_reg = EBPF_REG_5,
1125                 .off = offsetof(struct dummy_vect8, out[3].u64),
1126         },
1127         {
1128                 .code = (BPF_ALU | BPF_OR | BPF_X),
1129                 .dst_reg = EBPF_REG_2,
1130                 .src_reg = EBPF_REG_3,
1131         },
1132         {
1133                 .code = (EBPF_ALU64 | BPF_XOR | BPF_X),
1134                 .dst_reg = EBPF_REG_3,
1135                 .src_reg = EBPF_REG_4,
1136         },
1137         {
1138                 .code = (BPF_ALU | BPF_SUB | BPF_X),
1139                 .dst_reg = EBPF_REG_4,
1140                 .src_reg = EBPF_REG_5,
1141         },
1142         {
1143                 .code = (EBPF_ALU64 | BPF_AND | BPF_X),
1144                 .dst_reg = EBPF_REG_5,
1145                 .src_reg = EBPF_REG_2,
1146         },
1147         {
1148                 .code = (BPF_STX | BPF_MEM | EBPF_DW),
1149                 .dst_reg = EBPF_REG_1,
1150                 .src_reg = EBPF_REG_2,
1151                 .off = offsetof(struct dummy_vect8, out[4].u64),
1152         },
1153         {
1154                 .code = (BPF_STX | BPF_MEM | EBPF_DW),
1155                 .dst_reg = EBPF_REG_1,
1156                 .src_reg = EBPF_REG_3,
1157                 .off = offsetof(struct dummy_vect8, out[5].u64),
1158         },
1159         {
1160                 .code = (BPF_STX | BPF_MEM | EBPF_DW),
1161                 .dst_reg = EBPF_REG_1,
1162                 .src_reg = EBPF_REG_4,
1163                 .off = offsetof(struct dummy_vect8, out[6].u64),
1164         },
1165         {
1166                 .code = (BPF_STX | BPF_MEM | EBPF_DW),
1167                 .dst_reg = EBPF_REG_1,
1168                 .src_reg = EBPF_REG_5,
1169                 .off = offsetof(struct dummy_vect8, out[7].u64),
1170         },
1171         /* return (-r2 + (-r3)) */
1172         {
1173                 .code = (BPF_ALU | BPF_NEG),
1174                 .dst_reg = EBPF_REG_2,
1175         },
1176         {
1177                 .code = (EBPF_ALU64 | BPF_NEG),
1178                 .dst_reg = EBPF_REG_3,
1179         },
1180         {
1181                 .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
1182                 .dst_reg = EBPF_REG_2,
1183                 .src_reg = EBPF_REG_3,
1184         },
1185         {
1186                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
1187                 .dst_reg = EBPF_REG_0,
1188                 .src_reg = EBPF_REG_2,
1189         },
1190         {
1191                 .code = (BPF_JMP | EBPF_EXIT),
1192         },
1193 };
1194
1195 static int
1196 test_alu1_check(uint64_t rc, const void *arg)
1197 {
1198         uint64_t r2, r3, r4, r5, rv;
1199         const struct dummy_vect8 *dvt;
1200         struct dummy_vect8 dve;
1201
1202         dvt = arg;
1203         memset(&dve, 0, sizeof(dve));
1204
1205         r2 = dvt->in[0].u32;
1206         r3 = dvt->in[0].u64;
1207         r4 = dvt->in[1].u32;
1208         r5 = dvt->in[1].u64;
1209
1210         r2 = (uint32_t)r2 & TEST_FILL_1;
1211         r3 |= (int32_t) TEST_FILL_1;
1212         r4 = (uint32_t)r4 ^ TEST_FILL_1;
1213         r5 += (int32_t)TEST_FILL_1;
1214
1215         dve.out[0].u64 = r2;
1216         dve.out[1].u64 = r3;
1217         dve.out[2].u64 = r4;
1218         dve.out[3].u64 = r5;
1219
1220         r2 = (uint32_t)r2 | (uint32_t)r3;
1221         r3 ^= r4;
1222         r4 = (uint32_t)r4 - (uint32_t)r5;
1223         r5 &= r2;
1224
1225         dve.out[4].u64 = r2;
1226         dve.out[5].u64 = r3;
1227         dve.out[6].u64 = r4;
1228         dve.out[7].u64 = r5;
1229
1230         r2 = -(int32_t)r2;
1231         rv = (uint32_t)r2;
1232         r3 = -r3;
1233         rv += r3;
1234
1235         return cmp_res(__func__, rv, rc, dve.out, dvt->out, sizeof(dve.out));
1236 }
1237
1238 /* endianness conversions (BE->LE/LE->BE)  test-cases */
1239 static const struct ebpf_insn test_bele1_prog[] = {
1240
1241         {
1242                 .code = (BPF_LDX | BPF_MEM | BPF_H),
1243                 .dst_reg = EBPF_REG_2,
1244                 .src_reg = EBPF_REG_1,
1245                 .off = offsetof(struct dummy_vect8, in[0].u16),
1246         },
1247         {
1248                 .code = (BPF_LDX | BPF_MEM | BPF_W),
1249                 .dst_reg = EBPF_REG_3,
1250                 .src_reg = EBPF_REG_1,
1251                 .off = offsetof(struct dummy_vect8, in[0].u32),
1252         },
1253         {
1254                 .code = (BPF_LDX | BPF_MEM | EBPF_DW),
1255                 .dst_reg = EBPF_REG_4,
1256                 .src_reg = EBPF_REG_1,
1257                 .off = offsetof(struct dummy_vect8, in[0].u64),
1258         },
1259         {
1260                 .code = (BPF_ALU | EBPF_END | EBPF_TO_BE),
1261                 .dst_reg = EBPF_REG_2,
1262                 .imm = sizeof(uint16_t) * CHAR_BIT,
1263         },
1264         {
1265                 .code = (BPF_ALU | EBPF_END | EBPF_TO_BE),
1266                 .dst_reg = EBPF_REG_3,
1267                 .imm = sizeof(uint32_t) * CHAR_BIT,
1268         },
1269         {
1270                 .code = (BPF_ALU | EBPF_END | EBPF_TO_BE),
1271                 .dst_reg = EBPF_REG_4,
1272                 .imm = sizeof(uint64_t) * CHAR_BIT,
1273         },
1274         {
1275                 .code = (BPF_STX | BPF_MEM | EBPF_DW),
1276                 .dst_reg = EBPF_REG_1,
1277                 .src_reg = EBPF_REG_2,
1278                 .off = offsetof(struct dummy_vect8, out[0].u64),
1279         },
1280         {
1281                 .code = (BPF_STX | BPF_MEM | EBPF_DW),
1282                 .dst_reg = EBPF_REG_1,
1283                 .src_reg = EBPF_REG_3,
1284                 .off = offsetof(struct dummy_vect8, out[1].u64),
1285         },
1286         {
1287                 .code = (BPF_STX | BPF_MEM | EBPF_DW),
1288                 .dst_reg = EBPF_REG_1,
1289                 .src_reg = EBPF_REG_4,
1290                 .off = offsetof(struct dummy_vect8, out[2].u64),
1291         },
1292         {
1293                 .code = (BPF_LDX | BPF_MEM | BPF_H),
1294                 .dst_reg = EBPF_REG_2,
1295                 .src_reg = EBPF_REG_1,
1296                 .off = offsetof(struct dummy_vect8, in[0].u16),
1297         },
1298         {
1299                 .code = (BPF_LDX | BPF_MEM | BPF_W),
1300                 .dst_reg = EBPF_REG_3,
1301                 .src_reg = EBPF_REG_1,
1302                 .off = offsetof(struct dummy_vect8, in[0].u32),
1303         },
1304         {
1305                 .code = (BPF_LDX | BPF_MEM | EBPF_DW),
1306                 .dst_reg = EBPF_REG_4,
1307                 .src_reg = EBPF_REG_1,
1308                 .off = offsetof(struct dummy_vect8, in[0].u64),
1309         },
1310         {
1311                 .code = (BPF_ALU | EBPF_END | EBPF_TO_LE),
1312                 .dst_reg = EBPF_REG_2,
1313                 .imm = sizeof(uint16_t) * CHAR_BIT,
1314         },
1315         {
1316                 .code = (BPF_ALU | EBPF_END | EBPF_TO_LE),
1317                 .dst_reg = EBPF_REG_3,
1318                 .imm = sizeof(uint32_t) * CHAR_BIT,
1319         },
1320         {
1321                 .code = (BPF_ALU | EBPF_END | EBPF_TO_LE),
1322                 .dst_reg = EBPF_REG_4,
1323                 .imm = sizeof(uint64_t) * CHAR_BIT,
1324         },
1325         {
1326                 .code = (BPF_STX | BPF_MEM | EBPF_DW),
1327                 .dst_reg = EBPF_REG_1,
1328                 .src_reg = EBPF_REG_2,
1329                 .off = offsetof(struct dummy_vect8, out[3].u64),
1330         },
1331         {
1332                 .code = (BPF_STX | BPF_MEM | EBPF_DW),
1333                 .dst_reg = EBPF_REG_1,
1334                 .src_reg = EBPF_REG_3,
1335                 .off = offsetof(struct dummy_vect8, out[4].u64),
1336         },
1337         {
1338                 .code = (BPF_STX | BPF_MEM | EBPF_DW),
1339                 .dst_reg = EBPF_REG_1,
1340                 .src_reg = EBPF_REG_4,
1341                 .off = offsetof(struct dummy_vect8, out[5].u64),
1342         },
1343         /* return 1 */
1344         {
1345                 .code = (BPF_ALU | EBPF_MOV | BPF_K),
1346                 .dst_reg = EBPF_REG_0,
1347                 .imm = 1,
1348         },
1349         {
1350                 .code = (BPF_JMP | EBPF_EXIT),
1351         },
1352 };
1353
1354 static void
1355 test_bele1_prepare(void *arg)
1356 {
1357         struct dummy_vect8 *dv;
1358
1359         dv = arg;
1360
1361         memset(dv, 0, sizeof(*dv));
1362         dv->in[0].u64 = rte_rand();
1363         dv->in[0].u32 = dv->in[0].u64;
1364         dv->in[0].u16 = dv->in[0].u64;
1365 }
1366
1367 static int
1368 test_bele1_check(uint64_t rc, const void *arg)
1369 {
1370         uint64_t r2, r3, r4;
1371         const struct dummy_vect8 *dvt;
1372         struct dummy_vect8 dve;
1373
1374         dvt = arg;
1375         memset(&dve, 0, sizeof(dve));
1376
1377         r2 = dvt->in[0].u16;
1378         r3 = dvt->in[0].u32;
1379         r4 = dvt->in[0].u64;
1380
1381         r2 =  rte_cpu_to_be_16(r2);
1382         r3 =  rte_cpu_to_be_32(r3);
1383         r4 =  rte_cpu_to_be_64(r4);
1384
1385         dve.out[0].u64 = r2;
1386         dve.out[1].u64 = r3;
1387         dve.out[2].u64 = r4;
1388
1389         r2 = dvt->in[0].u16;
1390         r3 = dvt->in[0].u32;
1391         r4 = dvt->in[0].u64;
1392
1393         r2 =  rte_cpu_to_le_16(r2);
1394         r3 =  rte_cpu_to_le_32(r3);
1395         r4 =  rte_cpu_to_le_64(r4);
1396
1397         dve.out[3].u64 = r2;
1398         dve.out[4].u64 = r3;
1399         dve.out[5].u64 = r4;
1400
1401         return cmp_res(__func__, 1, rc, dve.out, dvt->out, sizeof(dve.out));
1402 }
1403
1404 /* atomic add test-cases */
1405 static const struct ebpf_insn test_xadd1_prog[] = {
1406
1407         {
1408                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
1409                 .dst_reg = EBPF_REG_2,
1410                 .imm = 1,
1411         },
1412         {
1413                 .code = (BPF_STX | EBPF_XADD | BPF_W),
1414                 .dst_reg = EBPF_REG_1,
1415                 .src_reg = EBPF_REG_2,
1416                 .off = offsetof(struct dummy_offset, u32),
1417         },
1418         {
1419                 .code = (BPF_STX | EBPF_XADD | EBPF_DW),
1420                 .dst_reg = EBPF_REG_1,
1421                 .src_reg = EBPF_REG_2,
1422                 .off = offsetof(struct dummy_offset, u64),
1423         },
1424         {
1425                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
1426                 .dst_reg = EBPF_REG_3,
1427                 .imm = -1,
1428         },
1429         {
1430                 .code = (BPF_STX | EBPF_XADD | BPF_W),
1431                 .dst_reg = EBPF_REG_1,
1432                 .src_reg = EBPF_REG_3,
1433                 .off = offsetof(struct dummy_offset, u32),
1434         },
1435         {
1436                 .code = (BPF_STX | EBPF_XADD | EBPF_DW),
1437                 .dst_reg = EBPF_REG_1,
1438                 .src_reg = EBPF_REG_3,
1439                 .off = offsetof(struct dummy_offset, u64),
1440         },
1441         {
1442                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
1443                 .dst_reg = EBPF_REG_4,
1444                 .imm = TEST_FILL_1,
1445         },
1446         {
1447                 .code = (BPF_STX | EBPF_XADD | BPF_W),
1448                 .dst_reg = EBPF_REG_1,
1449                 .src_reg = EBPF_REG_4,
1450                 .off = offsetof(struct dummy_offset, u32),
1451         },
1452         {
1453                 .code = (BPF_STX | EBPF_XADD | EBPF_DW),
1454                 .dst_reg = EBPF_REG_1,
1455                 .src_reg = EBPF_REG_4,
1456                 .off = offsetof(struct dummy_offset, u64),
1457         },
1458         {
1459                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
1460                 .dst_reg = EBPF_REG_5,
1461                 .imm = TEST_MUL_1,
1462         },
1463         {
1464                 .code = (BPF_STX | EBPF_XADD | BPF_W),
1465                 .dst_reg = EBPF_REG_1,
1466                 .src_reg = EBPF_REG_5,
1467                 .off = offsetof(struct dummy_offset, u32),
1468         },
1469         {
1470                 .code = (BPF_STX | EBPF_XADD | EBPF_DW),
1471                 .dst_reg = EBPF_REG_1,
1472                 .src_reg = EBPF_REG_5,
1473                 .off = offsetof(struct dummy_offset, u64),
1474         },
1475         {
1476                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
1477                 .dst_reg = EBPF_REG_6,
1478                 .imm = TEST_MUL_2,
1479         },
1480         {
1481                 .code = (BPF_STX | EBPF_XADD | BPF_W),
1482                 .dst_reg = EBPF_REG_1,
1483                 .src_reg = EBPF_REG_6,
1484                 .off = offsetof(struct dummy_offset, u32),
1485         },
1486         {
1487                 .code = (BPF_STX | EBPF_XADD | EBPF_DW),
1488                 .dst_reg = EBPF_REG_1,
1489                 .src_reg = EBPF_REG_6,
1490                 .off = offsetof(struct dummy_offset, u64),
1491         },
1492         {
1493                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
1494                 .dst_reg = EBPF_REG_7,
1495                 .imm = TEST_JCC_2,
1496         },
1497         {
1498                 .code = (BPF_STX | EBPF_XADD | BPF_W),
1499                 .dst_reg = EBPF_REG_1,
1500                 .src_reg = EBPF_REG_7,
1501                 .off = offsetof(struct dummy_offset, u32),
1502         },
1503         {
1504                 .code = (BPF_STX | EBPF_XADD | EBPF_DW),
1505                 .dst_reg = EBPF_REG_1,
1506                 .src_reg = EBPF_REG_7,
1507                 .off = offsetof(struct dummy_offset, u64),
1508         },
1509         {
1510                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
1511                 .dst_reg = EBPF_REG_8,
1512                 .imm = TEST_JCC_3,
1513         },
1514         {
1515                 .code = (BPF_STX | EBPF_XADD | BPF_W),
1516                 .dst_reg = EBPF_REG_1,
1517                 .src_reg = EBPF_REG_8,
1518                 .off = offsetof(struct dummy_offset, u32),
1519         },
1520         {
1521                 .code = (BPF_STX | EBPF_XADD | EBPF_DW),
1522                 .dst_reg = EBPF_REG_1,
1523                 .src_reg = EBPF_REG_8,
1524                 .off = offsetof(struct dummy_offset, u64),
1525         },
1526         /* return 1 */
1527         {
1528                 .code = (BPF_ALU | EBPF_MOV | BPF_K),
1529                 .dst_reg = EBPF_REG_0,
1530                 .imm = 1,
1531         },
1532         {
1533                 .code = (BPF_JMP | EBPF_EXIT),
1534         },
1535 };
1536
1537 static int
1538 test_xadd1_check(uint64_t rc, const void *arg)
1539 {
1540         uint64_t rv;
1541         const struct dummy_offset *dft;
1542         struct dummy_offset dfe;
1543
1544         dft = arg;
1545         memset(&dfe, 0, sizeof(dfe));
1546
1547         rv = 1;
1548         rte_atomic32_add((rte_atomic32_t *)&dfe.u32, rv);
1549         rte_atomic64_add((rte_atomic64_t *)&dfe.u64, rv);
1550
1551         rv = -1;
1552         rte_atomic32_add((rte_atomic32_t *)&dfe.u32, rv);
1553         rte_atomic64_add((rte_atomic64_t *)&dfe.u64, rv);
1554
1555         rv = (int32_t)TEST_FILL_1;
1556         rte_atomic32_add((rte_atomic32_t *)&dfe.u32, rv);
1557         rte_atomic64_add((rte_atomic64_t *)&dfe.u64, rv);
1558
1559         rv = TEST_MUL_1;
1560         rte_atomic32_add((rte_atomic32_t *)&dfe.u32, rv);
1561         rte_atomic64_add((rte_atomic64_t *)&dfe.u64, rv);
1562
1563         rv = TEST_MUL_2;
1564         rte_atomic32_add((rte_atomic32_t *)&dfe.u32, rv);
1565         rte_atomic64_add((rte_atomic64_t *)&dfe.u64, rv);
1566
1567         rv = TEST_JCC_2;
1568         rte_atomic32_add((rte_atomic32_t *)&dfe.u32, rv);
1569         rte_atomic64_add((rte_atomic64_t *)&dfe.u64, rv);
1570
1571         rv = TEST_JCC_3;
1572         rte_atomic32_add((rte_atomic32_t *)&dfe.u32, rv);
1573         rte_atomic64_add((rte_atomic64_t *)&dfe.u64, rv);
1574
1575         return cmp_res(__func__, 1, rc, &dfe, dft, sizeof(dfe));
1576 }
1577
1578 /* alu div test-cases */
1579 static const struct ebpf_insn test_div1_prog[] = {
1580
1581         {
1582                 .code = (BPF_LDX | BPF_MEM | BPF_W),
1583                 .dst_reg = EBPF_REG_2,
1584                 .src_reg = EBPF_REG_1,
1585                 .off = offsetof(struct dummy_vect8, in[0].u32),
1586         },
1587         {
1588                 .code = (BPF_LDX | BPF_MEM | EBPF_DW),
1589                 .dst_reg = EBPF_REG_3,
1590                 .src_reg = EBPF_REG_1,
1591                 .off = offsetof(struct dummy_vect8, in[1].u64),
1592         },
1593         {
1594                 .code = (BPF_LDX | BPF_MEM | BPF_W),
1595                 .dst_reg = EBPF_REG_4,
1596                 .src_reg = EBPF_REG_1,
1597                 .off = offsetof(struct dummy_vect8, in[2].u32),
1598         },
1599         {
1600                 .code = (BPF_ALU | BPF_DIV | BPF_K),
1601                 .dst_reg = EBPF_REG_2,
1602                 .imm = TEST_MUL_1,
1603         },
1604         {
1605                 .code = (EBPF_ALU64 | BPF_MOD | BPF_K),
1606                 .dst_reg = EBPF_REG_3,
1607                 .imm = TEST_MUL_2,
1608         },
1609         {
1610                 .code = (EBPF_ALU64 | BPF_OR | BPF_K),
1611                 .dst_reg = EBPF_REG_2,
1612                 .imm = 1,
1613         },
1614         {
1615                 .code = (EBPF_ALU64 | BPF_OR | BPF_K),
1616                 .dst_reg = EBPF_REG_3,
1617                 .imm = 1,
1618         },
1619         {
1620                 .code = (BPF_ALU | BPF_MOD | BPF_X),
1621                 .dst_reg = EBPF_REG_4,
1622                 .src_reg = EBPF_REG_2,
1623         },
1624         {
1625                 .code = (EBPF_ALU64 | BPF_DIV | BPF_X),
1626                 .dst_reg = EBPF_REG_4,
1627                 .src_reg = EBPF_REG_3,
1628         },
1629         {
1630                 .code = (BPF_STX | BPF_MEM | EBPF_DW),
1631                 .dst_reg = EBPF_REG_1,
1632                 .src_reg = EBPF_REG_2,
1633                 .off = offsetof(struct dummy_vect8, out[0].u64),
1634         },
1635         {
1636                 .code = (BPF_STX | BPF_MEM | EBPF_DW),
1637                 .dst_reg = EBPF_REG_1,
1638                 .src_reg = EBPF_REG_3,
1639                 .off = offsetof(struct dummy_vect8, out[1].u64),
1640         },
1641         {
1642                 .code = (BPF_STX | BPF_MEM | EBPF_DW),
1643                 .dst_reg = EBPF_REG_1,
1644                 .src_reg = EBPF_REG_4,
1645                 .off = offsetof(struct dummy_vect8, out[2].u64),
1646         },
1647         /* check that we can handle division by zero gracefully. */
1648         {
1649                 .code = (BPF_LDX | BPF_MEM | BPF_W),
1650                 .dst_reg = EBPF_REG_2,
1651                 .src_reg = EBPF_REG_1,
1652                 .off = offsetof(struct dummy_vect8, in[3].u32),
1653         },
1654         {
1655                 .code = (BPF_ALU | BPF_DIV | BPF_X),
1656                 .dst_reg = EBPF_REG_4,
1657                 .src_reg = EBPF_REG_2,
1658         },
1659         /* return 1 */
1660         {
1661                 .code = (BPF_ALU | EBPF_MOV | BPF_K),
1662                 .dst_reg = EBPF_REG_0,
1663                 .imm = 1,
1664         },
1665         {
1666                 .code = (BPF_JMP | EBPF_EXIT),
1667         },
1668 };
1669
1670 static int
1671 test_div1_check(uint64_t rc, const void *arg)
1672 {
1673         uint64_t r2, r3, r4;
1674         const struct dummy_vect8 *dvt;
1675         struct dummy_vect8 dve;
1676
1677         dvt = arg;
1678         memset(&dve, 0, sizeof(dve));
1679
1680         r2 = dvt->in[0].u32;
1681         r3 = dvt->in[1].u64;
1682         r4 = dvt->in[2].u32;
1683
1684         r2 = (uint32_t)r2 / TEST_MUL_1;
1685         r3 %= TEST_MUL_2;
1686         r2 |= 1;
1687         r3 |= 1;
1688         r4 = (uint32_t)(r4 % r2);
1689         r4 /= r3;
1690
1691         dve.out[0].u64 = r2;
1692         dve.out[1].u64 = r3;
1693         dve.out[2].u64 = r4;
1694
1695         /*
1696          * in the test prog we attempted to divide by zero.
1697          * so return value should return 0.
1698          */
1699         return cmp_res(__func__, 0, rc, dve.out, dvt->out, sizeof(dve.out));
1700 }
1701
1702 /* call test-cases */
1703 static const struct ebpf_insn test_call1_prog[] = {
1704
1705         {
1706                 .code = (BPF_LDX | BPF_MEM | BPF_W),
1707                 .dst_reg = EBPF_REG_2,
1708                 .src_reg = EBPF_REG_1,
1709                 .off = offsetof(struct dummy_offset, u32),
1710         },
1711         {
1712                 .code = (BPF_LDX | BPF_MEM | EBPF_DW),
1713                 .dst_reg = EBPF_REG_3,
1714                 .src_reg = EBPF_REG_1,
1715                 .off = offsetof(struct dummy_offset, u64),
1716         },
1717         {
1718                 .code = (BPF_STX | BPF_MEM | BPF_W),
1719                 .dst_reg = EBPF_REG_10,
1720                 .src_reg = EBPF_REG_2,
1721                 .off = -4,
1722         },
1723         {
1724                 .code = (BPF_STX | BPF_MEM | EBPF_DW),
1725                 .dst_reg = EBPF_REG_10,
1726                 .src_reg = EBPF_REG_3,
1727                 .off = -16,
1728         },
1729         {
1730                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
1731                 .dst_reg = EBPF_REG_2,
1732                 .src_reg = EBPF_REG_10,
1733         },
1734         {
1735                 .code = (EBPF_ALU64 | BPF_SUB | BPF_K),
1736                 .dst_reg = EBPF_REG_2,
1737                 .imm = 4,
1738         },
1739         {
1740                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
1741                 .dst_reg = EBPF_REG_3,
1742                 .src_reg = EBPF_REG_10,
1743         },
1744         {
1745                 .code = (EBPF_ALU64 | BPF_SUB | BPF_K),
1746                 .dst_reg = EBPF_REG_3,
1747                 .imm = 16,
1748         },
1749         {
1750                 .code = (BPF_JMP | EBPF_CALL),
1751                 .imm = 0,
1752         },
1753         {
1754                 .code = (BPF_LDX | BPF_MEM | BPF_W),
1755                 .dst_reg = EBPF_REG_2,
1756                 .src_reg = EBPF_REG_10,
1757                 .off = -4,
1758         },
1759         {
1760                 .code = (BPF_LDX | BPF_MEM | EBPF_DW),
1761                 .dst_reg = EBPF_REG_0,
1762                 .src_reg = EBPF_REG_10,
1763                 .off = -16
1764         },
1765         {
1766                 .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
1767                 .dst_reg = EBPF_REG_0,
1768                 .src_reg = EBPF_REG_2,
1769         },
1770         {
1771                 .code = (BPF_JMP | EBPF_EXIT),
1772         },
1773 };
1774
1775 static void
1776 dummy_func1(const void *p, uint32_t *v32, uint64_t *v64)
1777 {
1778         const struct dummy_offset *dv;
1779
1780         dv = p;
1781
1782         v32[0] += dv->u16;
1783         v64[0] += dv->u8;
1784 }
1785
1786 static int
1787 test_call1_check(uint64_t rc, const void *arg)
1788 {
1789         uint32_t v32;
1790         uint64_t v64;
1791         const struct dummy_offset *dv;
1792
1793         dv = arg;
1794
1795         v32 = dv->u32;
1796         v64 = dv->u64;
1797         dummy_func1(arg, &v32, &v64);
1798         v64 += v32;
1799
1800         if (v64 != rc) {
1801                 printf("%s@%d: invalid return value "
1802                         "expected=0x%" PRIx64 ", actual=0x%" PRIx64 "\n",
1803                         __func__, __LINE__, v64, rc);
1804                 return -1;
1805         }
1806         return 0;
1807         return cmp_res(__func__, v64, rc, dv, dv, sizeof(*dv));
1808 }
1809
1810 static const struct rte_bpf_xsym test_call1_xsym[] = {
1811         {
1812                 .name = RTE_STR(dummy_func1),
1813                 .type = RTE_BPF_XTYPE_FUNC,
1814                 .func = {
1815                         .val = (void *)dummy_func1,
1816                         .nb_args = 3,
1817                         .args = {
1818                                 [0] = {
1819                                         .type = RTE_BPF_ARG_PTR,
1820                                         .size = sizeof(struct dummy_offset),
1821                                 },
1822                                 [1] = {
1823                                         .type = RTE_BPF_ARG_PTR,
1824                                         .size = sizeof(uint32_t),
1825                                 },
1826                                 [2] = {
1827                                         .type = RTE_BPF_ARG_PTR,
1828                                         .size = sizeof(uint64_t),
1829                                 },
1830                         },
1831                 },
1832         },
1833 };
1834
1835 static const struct ebpf_insn test_call2_prog[] = {
1836
1837         {
1838                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
1839                 .dst_reg = EBPF_REG_1,
1840                 .src_reg = EBPF_REG_10,
1841         },
1842         {
1843                 .code = (EBPF_ALU64 | BPF_ADD | BPF_K),
1844                 .dst_reg = EBPF_REG_1,
1845                 .imm = -(int32_t)sizeof(struct dummy_offset),
1846         },
1847         {
1848                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
1849                 .dst_reg = EBPF_REG_2,
1850                 .src_reg = EBPF_REG_10,
1851         },
1852         {
1853                 .code = (EBPF_ALU64 | BPF_ADD | BPF_K),
1854                 .dst_reg = EBPF_REG_2,
1855                 .imm = -2 * (int32_t)sizeof(struct dummy_offset),
1856         },
1857         {
1858                 .code = (BPF_JMP | EBPF_CALL),
1859                 .imm = 0,
1860         },
1861         {
1862                 .code = (BPF_LDX | BPF_MEM | EBPF_DW),
1863                 .dst_reg = EBPF_REG_1,
1864                 .src_reg = EBPF_REG_10,
1865                 .off = -(int32_t)(sizeof(struct dummy_offset) -
1866                         offsetof(struct dummy_offset, u64)),
1867         },
1868         {
1869                 .code = (BPF_LDX | BPF_MEM | BPF_W),
1870                 .dst_reg = EBPF_REG_0,
1871                 .src_reg = EBPF_REG_10,
1872                 .off = -(int32_t)(sizeof(struct dummy_offset) -
1873                         offsetof(struct dummy_offset, u32)),
1874         },
1875         {
1876                 .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
1877                 .dst_reg = EBPF_REG_0,
1878                 .src_reg = EBPF_REG_1,
1879         },
1880         {
1881                 .code = (BPF_LDX | BPF_MEM | BPF_H),
1882                 .dst_reg = EBPF_REG_1,
1883                 .src_reg = EBPF_REG_10,
1884                 .off = -(int32_t)(2 * sizeof(struct dummy_offset) -
1885                         offsetof(struct dummy_offset, u16)),
1886         },
1887         {
1888                 .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
1889                 .dst_reg = EBPF_REG_0,
1890                 .src_reg = EBPF_REG_1,
1891         },
1892         {
1893                 .code = (BPF_LDX | BPF_MEM | BPF_B),
1894                 .dst_reg = EBPF_REG_1,
1895                 .src_reg = EBPF_REG_10,
1896                 .off = -(int32_t)(2 * sizeof(struct dummy_offset) -
1897                         offsetof(struct dummy_offset, u8)),
1898         },
1899         {
1900                 .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
1901                 .dst_reg = EBPF_REG_0,
1902                 .src_reg = EBPF_REG_1,
1903         },
1904         {
1905                 .code = (BPF_JMP | EBPF_EXIT),
1906         },
1907
1908 };
1909
1910 static void
1911 dummy_func2(struct dummy_offset *a, struct dummy_offset *b)
1912 {
1913         uint64_t v;
1914
1915         v = 0;
1916         a->u64 = v++;
1917         a->u32 = v++;
1918         a->u16 = v++;
1919         a->u8 = v++;
1920         b->u64 = v++;
1921         b->u32 = v++;
1922         b->u16 = v++;
1923         b->u8 = v++;
1924 }
1925
1926 static int
1927 test_call2_check(uint64_t rc, const void *arg)
1928 {
1929         uint64_t v;
1930         struct dummy_offset a, b;
1931
1932         RTE_SET_USED(arg);
1933
1934         dummy_func2(&a, &b);
1935         v = a.u64 + a.u32 + b.u16 + b.u8;
1936
1937         if (v != rc) {
1938                 printf("%s@%d: invalid return value "
1939                         "expected=0x%" PRIx64 ", actual=0x%" PRIx64 "\n",
1940                         __func__, __LINE__, v, rc);
1941                 return -1;
1942         }
1943         return 0;
1944 }
1945
1946 static const struct rte_bpf_xsym test_call2_xsym[] = {
1947         {
1948                 .name = RTE_STR(dummy_func2),
1949                 .type = RTE_BPF_XTYPE_FUNC,
1950                 .func = {
1951                         .val = (void *)dummy_func2,
1952                         .nb_args = 2,
1953                         .args = {
1954                                 [0] = {
1955                                         .type = RTE_BPF_ARG_PTR,
1956                                         .size = sizeof(struct dummy_offset),
1957                                 },
1958                                 [1] = {
1959                                         .type = RTE_BPF_ARG_PTR,
1960                                         .size = sizeof(struct dummy_offset),
1961                                 },
1962                         },
1963                 },
1964         },
1965 };
1966
1967 static const struct ebpf_insn test_call3_prog[] = {
1968
1969         {
1970                 .code = (BPF_JMP | EBPF_CALL),
1971                 .imm = 0,
1972         },
1973         {
1974                 .code = (BPF_LDX | BPF_MEM | BPF_B),
1975                 .dst_reg = EBPF_REG_2,
1976                 .src_reg = EBPF_REG_0,
1977                 .off = offsetof(struct dummy_offset, u8),
1978         },
1979         {
1980                 .code = (BPF_LDX | BPF_MEM | BPF_H),
1981                 .dst_reg = EBPF_REG_3,
1982                 .src_reg = EBPF_REG_0,
1983                 .off = offsetof(struct dummy_offset, u16),
1984         },
1985         {
1986                 .code = (BPF_LDX | BPF_MEM | BPF_W),
1987                 .dst_reg = EBPF_REG_4,
1988                 .src_reg = EBPF_REG_0,
1989                 .off = offsetof(struct dummy_offset, u32),
1990         },
1991         {
1992                 .code = (BPF_LDX | BPF_MEM | EBPF_DW),
1993                 .dst_reg = EBPF_REG_0,
1994                 .src_reg = EBPF_REG_0,
1995                 .off = offsetof(struct dummy_offset, u64),
1996         },
1997         /* return sum */
1998         {
1999                 .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
2000                 .dst_reg = EBPF_REG_0,
2001                 .src_reg = EBPF_REG_4,
2002         },
2003         {
2004                 .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
2005                 .dst_reg = EBPF_REG_0,
2006                 .src_reg = EBPF_REG_3,
2007         },
2008         {
2009                 .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
2010                 .dst_reg = EBPF_REG_0,
2011                 .src_reg = EBPF_REG_2,
2012         },
2013         {
2014                 .code = (BPF_JMP | EBPF_EXIT),
2015         },
2016 };
2017
2018 static const struct dummy_offset *
2019 dummy_func3(const struct dummy_vect8 *p)
2020 {
2021         return &p->in[RTE_DIM(p->in) - 1];
2022 }
2023
2024 static void
2025 test_call3_prepare(void *arg)
2026 {
2027         struct dummy_vect8 *pv;
2028         struct dummy_offset *df;
2029
2030         pv = arg;
2031         df = (struct dummy_offset *)(uintptr_t)dummy_func3(pv);
2032
2033         memset(pv, 0, sizeof(*pv));
2034         df->u64 = (int32_t)TEST_FILL_1;
2035         df->u32 = df->u64;
2036         df->u16 = df->u64;
2037         df->u8 = df->u64;
2038 }
2039
2040 static int
2041 test_call3_check(uint64_t rc, const void *arg)
2042 {
2043         uint64_t v;
2044         const struct dummy_vect8 *pv;
2045         const struct dummy_offset *dft;
2046
2047         pv = arg;
2048         dft = dummy_func3(pv);
2049
2050         v = dft->u64;
2051         v += dft->u32;
2052         v += dft->u16;
2053         v += dft->u8;
2054
2055         return cmp_res(__func__, v, rc, pv, pv, sizeof(*pv));
2056 }
2057
2058 static const struct rte_bpf_xsym test_call3_xsym[] = {
2059         {
2060                 .name = RTE_STR(dummy_func3),
2061                 .type = RTE_BPF_XTYPE_FUNC,
2062                 .func = {
2063                         .val = (void *)dummy_func3,
2064                         .nb_args = 1,
2065                         .args = {
2066                                 [0] = {
2067                                         .type = RTE_BPF_ARG_PTR,
2068                                         .size = sizeof(struct dummy_vect8),
2069                                 },
2070                         },
2071                         .ret = {
2072                                 .type = RTE_BPF_ARG_PTR,
2073                                 .size = sizeof(struct dummy_offset),
2074                         },
2075                 },
2076         },
2077 };
2078
2079 /* Test for stack corruption in multiple function calls */
2080 static const struct ebpf_insn test_call4_prog[] = {
2081         {
2082                 .code = (BPF_ST | BPF_MEM | BPF_B),
2083                 .dst_reg = EBPF_REG_10,
2084                 .off = -4,
2085                 .imm = 1,
2086         },
2087         {
2088                 .code = (BPF_ST | BPF_MEM | BPF_B),
2089                 .dst_reg = EBPF_REG_10,
2090                 .off = -3,
2091                 .imm = 2,
2092         },
2093         {
2094                 .code = (BPF_ST | BPF_MEM | BPF_B),
2095                 .dst_reg = EBPF_REG_10,
2096                 .off = -2,
2097                 .imm = 3,
2098         },
2099         {
2100                 .code = (BPF_ST | BPF_MEM | BPF_B),
2101                 .dst_reg = EBPF_REG_10,
2102                 .off = -1,
2103                 .imm = 4,
2104         },
2105         {
2106                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
2107                 .dst_reg = EBPF_REG_1,
2108                 .src_reg = EBPF_REG_10,
2109         },
2110         {
2111                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
2112                 .dst_reg = EBPF_REG_2,
2113                 .imm = 4,
2114         },
2115         {
2116                 .code = (EBPF_ALU64 | BPF_SUB | BPF_X),
2117                 .dst_reg = EBPF_REG_1,
2118                 .src_reg = EBPF_REG_2,
2119         },
2120         {
2121                 .code = (BPF_JMP | EBPF_CALL),
2122                 .imm = 0,
2123         },
2124         {
2125                 .code = (BPF_LDX | BPF_MEM | BPF_B),
2126                 .dst_reg = EBPF_REG_1,
2127                 .src_reg = EBPF_REG_10,
2128                 .off = -4,
2129         },
2130         {
2131                 .code = (BPF_LDX | BPF_MEM | BPF_B),
2132                 .dst_reg = EBPF_REG_2,
2133                 .src_reg = EBPF_REG_10,
2134                 .off = -3,
2135         },
2136         {
2137                 .code = (BPF_LDX | BPF_MEM | BPF_B),
2138                 .dst_reg = EBPF_REG_3,
2139                 .src_reg = EBPF_REG_10,
2140                 .off = -2,
2141         },
2142         {
2143                 .code = (BPF_LDX | BPF_MEM | BPF_B),
2144                 .dst_reg = EBPF_REG_4,
2145                 .src_reg = EBPF_REG_10,
2146                 .off = -1,
2147         },
2148         {
2149                 .code = (BPF_JMP | EBPF_CALL),
2150                 .imm = 1,
2151         },
2152         {
2153                 .code = (EBPF_ALU64 | BPF_XOR | BPF_K),
2154                 .dst_reg = EBPF_REG_0,
2155                 .imm = TEST_MEMFROB,
2156         },
2157         {
2158                 .code = (BPF_JMP | EBPF_EXIT),
2159         },
2160 };
2161
2162 /* Gathering the bytes together */
2163 static uint32_t
2164 dummy_func4_1(uint8_t a, uint8_t b, uint8_t c, uint8_t d)
2165 {
2166         return (a << 24) | (b << 16) | (c << 8) | (d << 0);
2167 }
2168
2169 /* Implementation of memfrob */
2170 static uint32_t
2171 dummy_func4_0(uint32_t *s, uint8_t n)
2172 {
2173         char *p = (char *) s;
2174         while (n-- > 0)
2175                 *p++ ^= 42;
2176         return *s;
2177 }
2178
2179
2180 static int
2181 test_call4_check(uint64_t rc, const void *arg)
2182 {
2183         uint8_t a[4] = {1, 2, 3, 4};
2184         uint32_t s, v = 0;
2185
2186         RTE_SET_USED(arg);
2187
2188         s = dummy_func4_0((uint32_t *)a, 4);
2189
2190         s = dummy_func4_1(a[0], a[1], a[2], a[3]);
2191
2192         v = s ^ TEST_MEMFROB;
2193
2194         return cmp_res(__func__, v, rc, &v, &rc, sizeof(v));
2195 }
2196
2197 static const struct rte_bpf_xsym test_call4_xsym[] = {
2198         [0] = {
2199                 .name = RTE_STR(dummy_func4_0),
2200                 .type = RTE_BPF_XTYPE_FUNC,
2201                 .func = {
2202                         .val = (void *)dummy_func4_0,
2203                         .nb_args = 2,
2204                         .args = {
2205                                 [0] = {
2206                                         .type = RTE_BPF_ARG_PTR,
2207                                         .size = 4 * sizeof(uint8_t),
2208                                 },
2209                                 [1] = {
2210                                         .type = RTE_BPF_ARG_RAW,
2211                                         .size = sizeof(uint8_t),
2212                                 },
2213                         },
2214                         .ret = {
2215                                 .type = RTE_BPF_ARG_RAW,
2216                                 .size = sizeof(uint32_t),
2217                         },
2218                 },
2219         },
2220         [1] = {
2221                 .name = RTE_STR(dummy_func4_1),
2222                 .type = RTE_BPF_XTYPE_FUNC,
2223                 .func = {
2224                         .val = (void *)dummy_func4_1,
2225                         .nb_args = 4,
2226                         .args = {
2227                                 [0] = {
2228                                         .type = RTE_BPF_ARG_RAW,
2229                                         .size = sizeof(uint8_t),
2230                                 },
2231                                 [1] = {
2232                                         .type = RTE_BPF_ARG_RAW,
2233                                         .size = sizeof(uint8_t),
2234                                 },
2235                                 [2] = {
2236                                         .type = RTE_BPF_ARG_RAW,
2237                                         .size = sizeof(uint8_t),
2238                                 },
2239                                 [3] = {
2240                                         .type = RTE_BPF_ARG_RAW,
2241                                         .size = sizeof(uint8_t),
2242                                 },
2243                         },
2244                         .ret = {
2245                                 .type = RTE_BPF_ARG_RAW,
2246                                 .size = sizeof(uint32_t),
2247                         },
2248                 },
2249         },
2250 };
2251
2252 /* string compare test case */
2253 static const struct ebpf_insn test_call5_prog[] = {
2254
2255         [0] = {
2256                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
2257                 .dst_reg = EBPF_REG_1,
2258                 .imm = STRING_GEEK,
2259         },
2260         [1] = {
2261                 .code = (BPF_STX | BPF_MEM | BPF_W),
2262                 .dst_reg = EBPF_REG_10,
2263                 .src_reg = EBPF_REG_1,
2264                 .off = -8,
2265         },
2266         [2] = {
2267                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
2268                 .dst_reg = EBPF_REG_6,
2269                 .imm = 0,
2270         },
2271         [3] = {
2272                 .code = (BPF_STX | BPF_MEM | BPF_B),
2273                 .dst_reg = EBPF_REG_10,
2274                 .src_reg = EBPF_REG_6,
2275                 .off = -4,
2276         },
2277         [4] = {
2278                 .code = (BPF_STX | BPF_MEM | BPF_W),
2279                 .dst_reg = EBPF_REG_10,
2280                 .src_reg = EBPF_REG_6,
2281                 .off = -12,
2282         },
2283         [5] = {
2284                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
2285                 .dst_reg = EBPF_REG_1,
2286                 .imm = STRING_WEEK,
2287         },
2288         [6] = {
2289                 .code = (BPF_STX | BPF_MEM | BPF_W),
2290                 .dst_reg = EBPF_REG_10,
2291                 .src_reg = EBPF_REG_1,
2292                 .off = -16,
2293         },
2294         [7] = {
2295                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
2296                 .dst_reg = EBPF_REG_1,
2297                 .src_reg = EBPF_REG_10,
2298         },
2299         [8] = {
2300                 .code = (EBPF_ALU64 | BPF_ADD | BPF_K),
2301                 .dst_reg = EBPF_REG_1,
2302                 .imm = -8,
2303         },
2304         [9] = {
2305                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
2306                 .dst_reg = EBPF_REG_2,
2307                 .src_reg = EBPF_REG_1,
2308         },
2309         [10] = {
2310                 .code = (BPF_JMP | EBPF_CALL),
2311                 .imm = 0,
2312         },
2313         [11] = {
2314                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
2315                 .dst_reg = EBPF_REG_1,
2316                 .src_reg = EBPF_REG_0,
2317         },
2318         [12] = {
2319                 .code = (BPF_ALU | EBPF_MOV | BPF_K),
2320                 .dst_reg = EBPF_REG_0,
2321                 .imm = -1,
2322         },
2323         [13] = {
2324                 .code = (EBPF_ALU64 | BPF_LSH | BPF_K),
2325                 .dst_reg = EBPF_REG_1,
2326                 .imm = 0x20,
2327         },
2328         [14] = {
2329                 .code = (EBPF_ALU64 | BPF_RSH | BPF_K),
2330                 .dst_reg = EBPF_REG_1,
2331                 .imm = 0x20,
2332         },
2333         [15] = {
2334                 .code = (BPF_JMP | EBPF_JNE | BPF_K),
2335                 .dst_reg = EBPF_REG_1,
2336                 .off = 11,
2337                 .imm = 0,
2338         },
2339         [16] = {
2340                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
2341                 .dst_reg = EBPF_REG_1,
2342                 .src_reg = EBPF_REG_10,
2343         },
2344         [17] = {
2345                 .code = (EBPF_ALU64 | BPF_ADD | BPF_K),
2346                 .dst_reg = EBPF_REG_1,
2347                 .imm = -8,
2348         },
2349         [18] = {
2350                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
2351                 .dst_reg = EBPF_REG_2,
2352                 .src_reg = EBPF_REG_10,
2353         },
2354         [19] = {
2355                 .code = (EBPF_ALU64 | BPF_ADD | BPF_K),
2356                 .dst_reg = EBPF_REG_2,
2357                 .imm = -16,
2358         },
2359         [20] = {
2360                 .code = (BPF_JMP | EBPF_CALL),
2361                 .imm = 0,
2362         },
2363         [21] = {
2364                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
2365                 .dst_reg = EBPF_REG_1,
2366                 .src_reg = EBPF_REG_0,
2367         },
2368         [22] = {
2369                 .code = (EBPF_ALU64 | BPF_LSH | BPF_K),
2370                 .dst_reg = EBPF_REG_1,
2371                 .imm = 0x20,
2372         },
2373         [23] = {
2374                 .code = (EBPF_ALU64 | BPF_RSH | BPF_K),
2375                 .dst_reg = EBPF_REG_1,
2376                 .imm = 0x20,
2377         },
2378         [24] = {
2379                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
2380                 .dst_reg = EBPF_REG_0,
2381                 .src_reg = EBPF_REG_1,
2382         },
2383         [25] = {
2384                 .code = (BPF_JMP | BPF_JEQ | BPF_X),
2385                 .dst_reg = EBPF_REG_1,
2386                 .src_reg = EBPF_REG_6,
2387                 .off = 1,
2388         },
2389         [26] = {
2390                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
2391                 .dst_reg = EBPF_REG_0,
2392                 .imm = 0,
2393         },
2394         [27] = {
2395                 .code = (BPF_JMP | EBPF_EXIT),
2396         },
2397 };
2398
2399 /* String comparision impelementation, return 0 if equal else difference */
2400 static uint32_t
2401 dummy_func5(const char *s1, const char *s2)
2402 {
2403         while (*s1 && (*s1 == *s2)) {
2404                 s1++;
2405                 s2++;
2406         }
2407         return *(const unsigned char *)s1 - *(const unsigned char *)s2;
2408 }
2409
2410 static int
2411 test_call5_check(uint64_t rc, const void *arg)
2412 {
2413         char a[] = "geek";
2414         char b[] = "week";
2415         uint32_t v;
2416
2417         RTE_SET_USED(arg);
2418
2419         v = dummy_func5(a, a);
2420         if (v != 0) {
2421                 v = -1;
2422                 goto fail;
2423         }
2424
2425         v = dummy_func5(a, b);
2426         if (v == 0)
2427                 goto fail;
2428
2429         v = 0;
2430
2431 fail:
2432
2433         return cmp_res(__func__, v, rc, &v, &rc, sizeof(v));
2434 }
2435
2436 static const struct rte_bpf_xsym test_call5_xsym[] = {
2437         [0] = {
2438                 .name = RTE_STR(dummy_func5),
2439                 .type = RTE_BPF_XTYPE_FUNC,
2440                 .func = {
2441                         .val = (void *)dummy_func5,
2442                         .nb_args = 2,
2443                         .args = {
2444                                 [0] = {
2445                                         .type = RTE_BPF_ARG_PTR,
2446                                         .size = sizeof(char),
2447                                 },
2448                                 [1] = {
2449                                         .type = RTE_BPF_ARG_PTR,
2450                                         .size = sizeof(char),
2451                                 },
2452                         },
2453                         .ret = {
2454                                 .type = RTE_BPF_ARG_RAW,
2455                                 .size = sizeof(uint32_t),
2456                         },
2457                 },
2458         },
2459 };
2460
2461 static const struct bpf_test tests[] = {
2462         {
2463                 .name = "test_store1",
2464                 .arg_sz = sizeof(struct dummy_offset),
2465                 .prm = {
2466                         .ins = test_store1_prog,
2467                         .nb_ins = RTE_DIM(test_store1_prog),
2468                         .prog_arg = {
2469                                 .type = RTE_BPF_ARG_PTR,
2470                                 .size = sizeof(struct dummy_offset),
2471                         },
2472                 },
2473                 .prepare = test_store1_prepare,
2474                 .check_result = test_store1_check,
2475         },
2476         {
2477                 .name = "test_store2",
2478                 .arg_sz = sizeof(struct dummy_offset),
2479                 .prm = {
2480                         .ins = test_store2_prog,
2481                         .nb_ins = RTE_DIM(test_store2_prog),
2482                         .prog_arg = {
2483                                 .type = RTE_BPF_ARG_PTR,
2484                                 .size = sizeof(struct dummy_offset),
2485                         },
2486                 },
2487                 .prepare = test_store1_prepare,
2488                 .check_result = test_store1_check,
2489         },
2490         {
2491                 .name = "test_load1",
2492                 .arg_sz = sizeof(struct dummy_offset),
2493                 .prm = {
2494                         .ins = test_load1_prog,
2495                         .nb_ins = RTE_DIM(test_load1_prog),
2496                         .prog_arg = {
2497                                 .type = RTE_BPF_ARG_PTR,
2498                                 .size = sizeof(struct dummy_offset),
2499                         },
2500                 },
2501                 .prepare = test_load1_prepare,
2502                 .check_result = test_load1_check,
2503         },
2504         {
2505                 .name = "test_ldimm1",
2506                 .arg_sz = sizeof(struct dummy_offset),
2507                 .prm = {
2508                         .ins = test_ldimm1_prog,
2509                         .nb_ins = RTE_DIM(test_ldimm1_prog),
2510                         .prog_arg = {
2511                                 .type = RTE_BPF_ARG_PTR,
2512                                 .size = sizeof(struct dummy_offset),
2513                         },
2514                 },
2515                 .prepare = test_store1_prepare,
2516                 .check_result = test_ldimm1_check,
2517         },
2518         {
2519                 .name = "test_mul1",
2520                 .arg_sz = sizeof(struct dummy_vect8),
2521                 .prm = {
2522                         .ins = test_mul1_prog,
2523                         .nb_ins = RTE_DIM(test_mul1_prog),
2524                         .prog_arg = {
2525                                 .type = RTE_BPF_ARG_PTR,
2526                                 .size = sizeof(struct dummy_vect8),
2527                         },
2528                 },
2529                 .prepare = test_mul1_prepare,
2530                 .check_result = test_mul1_check,
2531         },
2532         {
2533                 .name = "test_shift1",
2534                 .arg_sz = sizeof(struct dummy_vect8),
2535                 .prm = {
2536                         .ins = test_shift1_prog,
2537                         .nb_ins = RTE_DIM(test_shift1_prog),
2538                         .prog_arg = {
2539                                 .type = RTE_BPF_ARG_PTR,
2540                                 .size = sizeof(struct dummy_vect8),
2541                         },
2542                 },
2543                 .prepare = test_shift1_prepare,
2544                 .check_result = test_shift1_check,
2545         },
2546         {
2547                 .name = "test_jump1",
2548                 .arg_sz = sizeof(struct dummy_vect8),
2549                 .prm = {
2550                         .ins = test_jump1_prog,
2551                         .nb_ins = RTE_DIM(test_jump1_prog),
2552                         .prog_arg = {
2553                                 .type = RTE_BPF_ARG_PTR,
2554                                 .size = sizeof(struct dummy_vect8),
2555                         },
2556                 },
2557                 .prepare = test_jump1_prepare,
2558                 .check_result = test_jump1_check,
2559         },
2560         {
2561                 .name = "test_jump2",
2562                 .arg_sz = sizeof(struct dummy_net),
2563                 .prm = {
2564                         .ins = test_jump2_prog,
2565                         .nb_ins = RTE_DIM(test_jump2_prog),
2566                         .prog_arg = {
2567                                 .type = RTE_BPF_ARG_PTR,
2568                                 .size = sizeof(struct dummy_net),
2569                         },
2570                 },
2571                 .prepare = test_jump2_prepare,
2572                 .check_result = test_jump2_check,
2573         },
2574         {
2575                 .name = "test_alu1",
2576                 .arg_sz = sizeof(struct dummy_vect8),
2577                 .prm = {
2578                         .ins = test_alu1_prog,
2579                         .nb_ins = RTE_DIM(test_alu1_prog),
2580                         .prog_arg = {
2581                                 .type = RTE_BPF_ARG_PTR,
2582                                 .size = sizeof(struct dummy_vect8),
2583                         },
2584                 },
2585                 .prepare = test_jump1_prepare,
2586                 .check_result = test_alu1_check,
2587         },
2588         {
2589                 .name = "test_bele1",
2590                 .arg_sz = sizeof(struct dummy_vect8),
2591                 .prm = {
2592                         .ins = test_bele1_prog,
2593                         .nb_ins = RTE_DIM(test_bele1_prog),
2594                         .prog_arg = {
2595                                 .type = RTE_BPF_ARG_PTR,
2596                                 .size = sizeof(struct dummy_vect8),
2597                         },
2598                 },
2599                 .prepare = test_bele1_prepare,
2600                 .check_result = test_bele1_check,
2601         },
2602         {
2603                 .name = "test_xadd1",
2604                 .arg_sz = sizeof(struct dummy_offset),
2605                 .prm = {
2606                         .ins = test_xadd1_prog,
2607                         .nb_ins = RTE_DIM(test_xadd1_prog),
2608                         .prog_arg = {
2609                                 .type = RTE_BPF_ARG_PTR,
2610                                 .size = sizeof(struct dummy_offset),
2611                         },
2612                 },
2613                 .prepare = test_store1_prepare,
2614                 .check_result = test_xadd1_check,
2615         },
2616         {
2617                 .name = "test_div1",
2618                 .arg_sz = sizeof(struct dummy_vect8),
2619                 .prm = {
2620                         .ins = test_div1_prog,
2621                         .nb_ins = RTE_DIM(test_div1_prog),
2622                         .prog_arg = {
2623                                 .type = RTE_BPF_ARG_PTR,
2624                                 .size = sizeof(struct dummy_vect8),
2625                         },
2626                 },
2627                 .prepare = test_mul1_prepare,
2628                 .check_result = test_div1_check,
2629         },
2630         {
2631                 .name = "test_call1",
2632                 .arg_sz = sizeof(struct dummy_offset),
2633                 .prm = {
2634                         .ins = test_call1_prog,
2635                         .nb_ins = RTE_DIM(test_call1_prog),
2636                         .prog_arg = {
2637                                 .type = RTE_BPF_ARG_PTR,
2638                                 .size = sizeof(struct dummy_offset),
2639                         },
2640                         .xsym = test_call1_xsym,
2641                         .nb_xsym = RTE_DIM(test_call1_xsym),
2642                 },
2643                 .prepare = test_load1_prepare,
2644                 .check_result = test_call1_check,
2645                 /* for now don't support function calls on 32 bit platform */
2646                 .allow_fail = (sizeof(uint64_t) != sizeof(uintptr_t)),
2647         },
2648         {
2649                 .name = "test_call2",
2650                 .arg_sz = sizeof(struct dummy_offset),
2651                 .prm = {
2652                         .ins = test_call2_prog,
2653                         .nb_ins = RTE_DIM(test_call2_prog),
2654                         .prog_arg = {
2655                                 .type = RTE_BPF_ARG_PTR,
2656                                 .size = sizeof(struct dummy_offset),
2657                         },
2658                         .xsym = test_call2_xsym,
2659                         .nb_xsym = RTE_DIM(test_call2_xsym),
2660                 },
2661                 .prepare = test_store1_prepare,
2662                 .check_result = test_call2_check,
2663                 /* for now don't support function calls on 32 bit platform */
2664                 .allow_fail = (sizeof(uint64_t) != sizeof(uintptr_t)),
2665         },
2666         {
2667                 .name = "test_call3",
2668                 .arg_sz = sizeof(struct dummy_vect8),
2669                 .prm = {
2670                         .ins = test_call3_prog,
2671                         .nb_ins = RTE_DIM(test_call3_prog),
2672                         .prog_arg = {
2673                                 .type = RTE_BPF_ARG_PTR,
2674                                 .size = sizeof(struct dummy_vect8),
2675                         },
2676                         .xsym = test_call3_xsym,
2677                         .nb_xsym = RTE_DIM(test_call3_xsym),
2678                 },
2679                 .prepare = test_call3_prepare,
2680                 .check_result = test_call3_check,
2681                 /* for now don't support function calls on 32 bit platform */
2682                 .allow_fail = (sizeof(uint64_t) != sizeof(uintptr_t)),
2683         },
2684         {
2685                 .name = "test_call4",
2686                 .arg_sz = sizeof(struct dummy_offset),
2687                 .prm = {
2688                         .ins = test_call4_prog,
2689                         .nb_ins = RTE_DIM(test_call4_prog),
2690                         .prog_arg = {
2691                                 .type = RTE_BPF_ARG_PTR,
2692                                 .size = 2 * sizeof(struct dummy_offset),
2693                         },
2694                         .xsym = test_call4_xsym,
2695                         .nb_xsym = RTE_DIM(test_call4_xsym),
2696                 },
2697                 .prepare = test_store1_prepare,
2698                 .check_result = test_call4_check,
2699                 /* for now don't support function calls on 32 bit platform */
2700                 .allow_fail = (sizeof(uint64_t) != sizeof(uintptr_t)),
2701         },
2702         {
2703                 .name = "test_call5",
2704                 .arg_sz = sizeof(struct dummy_offset),
2705                 .prm = {
2706                         .ins = test_call5_prog,
2707                         .nb_ins = RTE_DIM(test_call5_prog),
2708                         .prog_arg = {
2709                                 .type = RTE_BPF_ARG_PTR,
2710                                 .size = sizeof(struct dummy_offset),
2711                         },
2712                         .xsym = test_call5_xsym,
2713                         .nb_xsym = RTE_DIM(test_call5_xsym),
2714                 },
2715                 .prepare = test_store1_prepare,
2716                 .check_result = test_call5_check,
2717                 /* for now don't support function calls on 32 bit platform */
2718                 .allow_fail = (sizeof(uint64_t) != sizeof(uintptr_t)),
2719         },
2720 };
2721
2722 static int
2723 run_test(const struct bpf_test *tst)
2724 {
2725         int32_t ret, rv;
2726         int64_t rc;
2727         struct rte_bpf *bpf;
2728         struct rte_bpf_jit jit;
2729         uint8_t tbuf[tst->arg_sz];
2730
2731         printf("%s(%s) start\n", __func__, tst->name);
2732
2733         bpf = rte_bpf_load(&tst->prm);
2734         if (bpf == NULL) {
2735                 printf("%s@%d: failed to load bpf code, error=%d(%s);\n",
2736                         __func__, __LINE__, rte_errno, strerror(rte_errno));
2737                 return -1;
2738         }
2739
2740         tst->prepare(tbuf);
2741
2742         rc = rte_bpf_exec(bpf, tbuf);
2743         ret = tst->check_result(rc, tbuf);
2744         if (ret != 0) {
2745                 printf("%s@%d: check_result(%s) failed, error: %d(%s);\n",
2746                         __func__, __LINE__, tst->name, ret, strerror(ret));
2747         }
2748
2749         rte_bpf_get_jit(bpf, &jit);
2750         if (jit.func == NULL)
2751                 return 0;
2752
2753         tst->prepare(tbuf);
2754         rc = jit.func(tbuf);
2755         rv = tst->check_result(rc, tbuf);
2756         ret |= rv;
2757         if (rv != 0) {
2758                 printf("%s@%d: check_result(%s) failed, error: %d(%s);\n",
2759                         __func__, __LINE__, tst->name, rv, strerror(ret));
2760         }
2761
2762         rte_bpf_destroy(bpf);
2763         return ret;
2764
2765 }
2766
2767 static int
2768 test_bpf(void)
2769 {
2770         int32_t rc, rv;
2771         uint32_t i;
2772
2773         rc = 0;
2774         for (i = 0; i != RTE_DIM(tests); i++) {
2775                 rv = run_test(tests + i);
2776                 if (tests[i].allow_fail == 0)
2777                         rc |= rv;
2778         }
2779
2780         return rc;
2781 }
2782
2783 REGISTER_TEST_COMMAND(bpf_autotest, test_bpf);