test/bpf: fix few small issues
[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         return cmp_res(__func__, v64, rc, dv, dv, sizeof(*dv));
1801 }
1802
1803 static const struct rte_bpf_xsym test_call1_xsym[] = {
1804         {
1805                 .name = RTE_STR(dummy_func1),
1806                 .type = RTE_BPF_XTYPE_FUNC,
1807                 .func = {
1808                         .val = (void *)dummy_func1,
1809                         .nb_args = 3,
1810                         .args = {
1811                                 [0] = {
1812                                         .type = RTE_BPF_ARG_PTR,
1813                                         .size = sizeof(struct dummy_offset),
1814                                 },
1815                                 [1] = {
1816                                         .type = RTE_BPF_ARG_PTR,
1817                                         .size = sizeof(uint32_t),
1818                                 },
1819                                 [2] = {
1820                                         .type = RTE_BPF_ARG_PTR,
1821                                         .size = sizeof(uint64_t),
1822                                 },
1823                         },
1824                 },
1825         },
1826 };
1827
1828 static const struct ebpf_insn test_call2_prog[] = {
1829
1830         {
1831                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
1832                 .dst_reg = EBPF_REG_1,
1833                 .src_reg = EBPF_REG_10,
1834         },
1835         {
1836                 .code = (EBPF_ALU64 | BPF_ADD | BPF_K),
1837                 .dst_reg = EBPF_REG_1,
1838                 .imm = -(int32_t)sizeof(struct dummy_offset),
1839         },
1840         {
1841                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
1842                 .dst_reg = EBPF_REG_2,
1843                 .src_reg = EBPF_REG_10,
1844         },
1845         {
1846                 .code = (EBPF_ALU64 | BPF_ADD | BPF_K),
1847                 .dst_reg = EBPF_REG_2,
1848                 .imm = -2 * (int32_t)sizeof(struct dummy_offset),
1849         },
1850         {
1851                 .code = (BPF_JMP | EBPF_CALL),
1852                 .imm = 0,
1853         },
1854         {
1855                 .code = (BPF_LDX | BPF_MEM | EBPF_DW),
1856                 .dst_reg = EBPF_REG_1,
1857                 .src_reg = EBPF_REG_10,
1858                 .off = -(int32_t)(sizeof(struct dummy_offset) -
1859                         offsetof(struct dummy_offset, u64)),
1860         },
1861         {
1862                 .code = (BPF_LDX | BPF_MEM | BPF_W),
1863                 .dst_reg = EBPF_REG_0,
1864                 .src_reg = EBPF_REG_10,
1865                 .off = -(int32_t)(sizeof(struct dummy_offset) -
1866                         offsetof(struct dummy_offset, u32)),
1867         },
1868         {
1869                 .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
1870                 .dst_reg = EBPF_REG_0,
1871                 .src_reg = EBPF_REG_1,
1872         },
1873         {
1874                 .code = (BPF_LDX | BPF_MEM | BPF_H),
1875                 .dst_reg = EBPF_REG_1,
1876                 .src_reg = EBPF_REG_10,
1877                 .off = -(int32_t)(2 * sizeof(struct dummy_offset) -
1878                         offsetof(struct dummy_offset, u16)),
1879         },
1880         {
1881                 .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
1882                 .dst_reg = EBPF_REG_0,
1883                 .src_reg = EBPF_REG_1,
1884         },
1885         {
1886                 .code = (BPF_LDX | BPF_MEM | BPF_B),
1887                 .dst_reg = EBPF_REG_1,
1888                 .src_reg = EBPF_REG_10,
1889                 .off = -(int32_t)(2 * sizeof(struct dummy_offset) -
1890                         offsetof(struct dummy_offset, u8)),
1891         },
1892         {
1893                 .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
1894                 .dst_reg = EBPF_REG_0,
1895                 .src_reg = EBPF_REG_1,
1896         },
1897         {
1898                 .code = (BPF_JMP | EBPF_EXIT),
1899         },
1900
1901 };
1902
1903 static void
1904 dummy_func2(struct dummy_offset *a, struct dummy_offset *b)
1905 {
1906         uint64_t v;
1907
1908         v = 0;
1909         a->u64 = v++;
1910         a->u32 = v++;
1911         a->u16 = v++;
1912         a->u8 = v++;
1913         b->u64 = v++;
1914         b->u32 = v++;
1915         b->u16 = v++;
1916         b->u8 = v++;
1917 }
1918
1919 static int
1920 test_call2_check(uint64_t rc, const void *arg)
1921 {
1922         uint64_t v;
1923         struct dummy_offset a, b;
1924
1925         RTE_SET_USED(arg);
1926
1927         dummy_func2(&a, &b);
1928         v = a.u64 + a.u32 + b.u16 + b.u8;
1929
1930         return cmp_res(__func__, v, rc, arg, arg, 0);
1931 }
1932
1933 static const struct rte_bpf_xsym test_call2_xsym[] = {
1934         {
1935                 .name = RTE_STR(dummy_func2),
1936                 .type = RTE_BPF_XTYPE_FUNC,
1937                 .func = {
1938                         .val = (void *)dummy_func2,
1939                         .nb_args = 2,
1940                         .args = {
1941                                 [0] = {
1942                                         .type = RTE_BPF_ARG_PTR,
1943                                         .size = sizeof(struct dummy_offset),
1944                                 },
1945                                 [1] = {
1946                                         .type = RTE_BPF_ARG_PTR,
1947                                         .size = sizeof(struct dummy_offset),
1948                                 },
1949                         },
1950                 },
1951         },
1952 };
1953
1954 static const struct ebpf_insn test_call3_prog[] = {
1955
1956         {
1957                 .code = (BPF_JMP | EBPF_CALL),
1958                 .imm = 0,
1959         },
1960         {
1961                 .code = (BPF_LDX | BPF_MEM | BPF_B),
1962                 .dst_reg = EBPF_REG_2,
1963                 .src_reg = EBPF_REG_0,
1964                 .off = offsetof(struct dummy_offset, u8),
1965         },
1966         {
1967                 .code = (BPF_LDX | BPF_MEM | BPF_H),
1968                 .dst_reg = EBPF_REG_3,
1969                 .src_reg = EBPF_REG_0,
1970                 .off = offsetof(struct dummy_offset, u16),
1971         },
1972         {
1973                 .code = (BPF_LDX | BPF_MEM | BPF_W),
1974                 .dst_reg = EBPF_REG_4,
1975                 .src_reg = EBPF_REG_0,
1976                 .off = offsetof(struct dummy_offset, u32),
1977         },
1978         {
1979                 .code = (BPF_LDX | BPF_MEM | EBPF_DW),
1980                 .dst_reg = EBPF_REG_0,
1981                 .src_reg = EBPF_REG_0,
1982                 .off = offsetof(struct dummy_offset, u64),
1983         },
1984         /* return sum */
1985         {
1986                 .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
1987                 .dst_reg = EBPF_REG_0,
1988                 .src_reg = EBPF_REG_4,
1989         },
1990         {
1991                 .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
1992                 .dst_reg = EBPF_REG_0,
1993                 .src_reg = EBPF_REG_3,
1994         },
1995         {
1996                 .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
1997                 .dst_reg = EBPF_REG_0,
1998                 .src_reg = EBPF_REG_2,
1999         },
2000         {
2001                 .code = (BPF_JMP | EBPF_EXIT),
2002         },
2003 };
2004
2005 static const struct dummy_offset *
2006 dummy_func3(const struct dummy_vect8 *p)
2007 {
2008         return &p->in[RTE_DIM(p->in) - 1];
2009 }
2010
2011 static void
2012 test_call3_prepare(void *arg)
2013 {
2014         struct dummy_vect8 *pv;
2015         struct dummy_offset *df;
2016
2017         pv = arg;
2018         df = (struct dummy_offset *)(uintptr_t)dummy_func3(pv);
2019
2020         memset(pv, 0, sizeof(*pv));
2021         df->u64 = (int32_t)TEST_FILL_1;
2022         df->u32 = df->u64;
2023         df->u16 = df->u64;
2024         df->u8 = df->u64;
2025 }
2026
2027 static int
2028 test_call3_check(uint64_t rc, const void *arg)
2029 {
2030         uint64_t v;
2031         const struct dummy_vect8 *pv;
2032         const struct dummy_offset *dft;
2033
2034         pv = arg;
2035         dft = dummy_func3(pv);
2036
2037         v = dft->u64;
2038         v += dft->u32;
2039         v += dft->u16;
2040         v += dft->u8;
2041
2042         return cmp_res(__func__, v, rc, pv, pv, sizeof(*pv));
2043 }
2044
2045 static const struct rte_bpf_xsym test_call3_xsym[] = {
2046         {
2047                 .name = RTE_STR(dummy_func3),
2048                 .type = RTE_BPF_XTYPE_FUNC,
2049                 .func = {
2050                         .val = (void *)dummy_func3,
2051                         .nb_args = 1,
2052                         .args = {
2053                                 [0] = {
2054                                         .type = RTE_BPF_ARG_PTR,
2055                                         .size = sizeof(struct dummy_vect8),
2056                                 },
2057                         },
2058                         .ret = {
2059                                 .type = RTE_BPF_ARG_PTR,
2060                                 .size = sizeof(struct dummy_offset),
2061                         },
2062                 },
2063         },
2064 };
2065
2066 /* Test for stack corruption in multiple function calls */
2067 static const struct ebpf_insn test_call4_prog[] = {
2068         {
2069                 .code = (BPF_ST | BPF_MEM | BPF_B),
2070                 .dst_reg = EBPF_REG_10,
2071                 .off = -4,
2072                 .imm = 1,
2073         },
2074         {
2075                 .code = (BPF_ST | BPF_MEM | BPF_B),
2076                 .dst_reg = EBPF_REG_10,
2077                 .off = -3,
2078                 .imm = 2,
2079         },
2080         {
2081                 .code = (BPF_ST | BPF_MEM | BPF_B),
2082                 .dst_reg = EBPF_REG_10,
2083                 .off = -2,
2084                 .imm = 3,
2085         },
2086         {
2087                 .code = (BPF_ST | BPF_MEM | BPF_B),
2088                 .dst_reg = EBPF_REG_10,
2089                 .off = -1,
2090                 .imm = 4,
2091         },
2092         {
2093                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
2094                 .dst_reg = EBPF_REG_1,
2095                 .src_reg = EBPF_REG_10,
2096         },
2097         {
2098                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
2099                 .dst_reg = EBPF_REG_2,
2100                 .imm = 4,
2101         },
2102         {
2103                 .code = (EBPF_ALU64 | BPF_SUB | BPF_X),
2104                 .dst_reg = EBPF_REG_1,
2105                 .src_reg = EBPF_REG_2,
2106         },
2107         {
2108                 .code = (BPF_JMP | EBPF_CALL),
2109                 .imm = 0,
2110         },
2111         {
2112                 .code = (BPF_LDX | BPF_MEM | BPF_B),
2113                 .dst_reg = EBPF_REG_1,
2114                 .src_reg = EBPF_REG_10,
2115                 .off = -4,
2116         },
2117         {
2118                 .code = (BPF_LDX | BPF_MEM | BPF_B),
2119                 .dst_reg = EBPF_REG_2,
2120                 .src_reg = EBPF_REG_10,
2121                 .off = -3,
2122         },
2123         {
2124                 .code = (BPF_LDX | BPF_MEM | BPF_B),
2125                 .dst_reg = EBPF_REG_3,
2126                 .src_reg = EBPF_REG_10,
2127                 .off = -2,
2128         },
2129         {
2130                 .code = (BPF_LDX | BPF_MEM | BPF_B),
2131                 .dst_reg = EBPF_REG_4,
2132                 .src_reg = EBPF_REG_10,
2133                 .off = -1,
2134         },
2135         {
2136                 .code = (BPF_JMP | EBPF_CALL),
2137                 .imm = 1,
2138         },
2139         {
2140                 .code = (EBPF_ALU64 | BPF_XOR | BPF_K),
2141                 .dst_reg = EBPF_REG_0,
2142                 .imm = TEST_MEMFROB,
2143         },
2144         {
2145                 .code = (BPF_JMP | EBPF_EXIT),
2146         },
2147 };
2148
2149 /* Gathering the bytes together */
2150 static uint32_t
2151 dummy_func4_1(uint8_t a, uint8_t b, uint8_t c, uint8_t d)
2152 {
2153         return (a << 24) | (b << 16) | (c << 8) | (d << 0);
2154 }
2155
2156 /* Implementation of memfrob */
2157 static uint32_t
2158 dummy_func4_0(uint32_t *s, uint8_t n)
2159 {
2160         char *p = (char *) s;
2161         while (n-- > 0)
2162                 *p++ ^= 42;
2163         return *s;
2164 }
2165
2166
2167 static int
2168 test_call4_check(uint64_t rc, const void *arg)
2169 {
2170         uint8_t a[4] = {1, 2, 3, 4};
2171         uint32_t s, v = 0;
2172
2173         RTE_SET_USED(arg);
2174
2175         s = dummy_func4_0((uint32_t *)a, 4);
2176
2177         s = dummy_func4_1(a[0], a[1], a[2], a[3]);
2178
2179         v = s ^ TEST_MEMFROB;
2180
2181         return cmp_res(__func__, v, rc, &v, &rc, sizeof(v));
2182 }
2183
2184 static const struct rte_bpf_xsym test_call4_xsym[] = {
2185         [0] = {
2186                 .name = RTE_STR(dummy_func4_0),
2187                 .type = RTE_BPF_XTYPE_FUNC,
2188                 .func = {
2189                         .val = (void *)dummy_func4_0,
2190                         .nb_args = 2,
2191                         .args = {
2192                                 [0] = {
2193                                         .type = RTE_BPF_ARG_PTR,
2194                                         .size = 4 * sizeof(uint8_t),
2195                                 },
2196                                 [1] = {
2197                                         .type = RTE_BPF_ARG_RAW,
2198                                         .size = sizeof(uint8_t),
2199                                 },
2200                         },
2201                         .ret = {
2202                                 .type = RTE_BPF_ARG_RAW,
2203                                 .size = sizeof(uint32_t),
2204                         },
2205                 },
2206         },
2207         [1] = {
2208                 .name = RTE_STR(dummy_func4_1),
2209                 .type = RTE_BPF_XTYPE_FUNC,
2210                 .func = {
2211                         .val = (void *)dummy_func4_1,
2212                         .nb_args = 4,
2213                         .args = {
2214                                 [0] = {
2215                                         .type = RTE_BPF_ARG_RAW,
2216                                         .size = sizeof(uint8_t),
2217                                 },
2218                                 [1] = {
2219                                         .type = RTE_BPF_ARG_RAW,
2220                                         .size = sizeof(uint8_t),
2221                                 },
2222                                 [2] = {
2223                                         .type = RTE_BPF_ARG_RAW,
2224                                         .size = sizeof(uint8_t),
2225                                 },
2226                                 [3] = {
2227                                         .type = RTE_BPF_ARG_RAW,
2228                                         .size = sizeof(uint8_t),
2229                                 },
2230                         },
2231                         .ret = {
2232                                 .type = RTE_BPF_ARG_RAW,
2233                                 .size = sizeof(uint32_t),
2234                         },
2235                 },
2236         },
2237 };
2238
2239 /* string compare test case */
2240 static const struct ebpf_insn test_call5_prog[] = {
2241
2242         [0] = {
2243                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
2244                 .dst_reg = EBPF_REG_1,
2245                 .imm = STRING_GEEK,
2246         },
2247         [1] = {
2248                 .code = (BPF_STX | BPF_MEM | BPF_W),
2249                 .dst_reg = EBPF_REG_10,
2250                 .src_reg = EBPF_REG_1,
2251                 .off = -8,
2252         },
2253         [2] = {
2254                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
2255                 .dst_reg = EBPF_REG_6,
2256                 .imm = 0,
2257         },
2258         [3] = {
2259                 .code = (BPF_STX | BPF_MEM | BPF_B),
2260                 .dst_reg = EBPF_REG_10,
2261                 .src_reg = EBPF_REG_6,
2262                 .off = -4,
2263         },
2264         [4] = {
2265                 .code = (BPF_STX | BPF_MEM | BPF_W),
2266                 .dst_reg = EBPF_REG_10,
2267                 .src_reg = EBPF_REG_6,
2268                 .off = -12,
2269         },
2270         [5] = {
2271                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
2272                 .dst_reg = EBPF_REG_1,
2273                 .imm = STRING_WEEK,
2274         },
2275         [6] = {
2276                 .code = (BPF_STX | BPF_MEM | BPF_W),
2277                 .dst_reg = EBPF_REG_10,
2278                 .src_reg = EBPF_REG_1,
2279                 .off = -16,
2280         },
2281         [7] = {
2282                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
2283                 .dst_reg = EBPF_REG_1,
2284                 .src_reg = EBPF_REG_10,
2285         },
2286         [8] = {
2287                 .code = (EBPF_ALU64 | BPF_ADD | BPF_K),
2288                 .dst_reg = EBPF_REG_1,
2289                 .imm = -8,
2290         },
2291         [9] = {
2292                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
2293                 .dst_reg = EBPF_REG_2,
2294                 .src_reg = EBPF_REG_1,
2295         },
2296         [10] = {
2297                 .code = (BPF_JMP | EBPF_CALL),
2298                 .imm = 0,
2299         },
2300         [11] = {
2301                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
2302                 .dst_reg = EBPF_REG_1,
2303                 .src_reg = EBPF_REG_0,
2304         },
2305         [12] = {
2306                 .code = (BPF_ALU | EBPF_MOV | BPF_K),
2307                 .dst_reg = EBPF_REG_0,
2308                 .imm = -1,
2309         },
2310         [13] = {
2311                 .code = (EBPF_ALU64 | BPF_LSH | BPF_K),
2312                 .dst_reg = EBPF_REG_1,
2313                 .imm = 0x20,
2314         },
2315         [14] = {
2316                 .code = (EBPF_ALU64 | BPF_RSH | BPF_K),
2317                 .dst_reg = EBPF_REG_1,
2318                 .imm = 0x20,
2319         },
2320         [15] = {
2321                 .code = (BPF_JMP | EBPF_JNE | BPF_K),
2322                 .dst_reg = EBPF_REG_1,
2323                 .off = 11,
2324                 .imm = 0,
2325         },
2326         [16] = {
2327                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
2328                 .dst_reg = EBPF_REG_1,
2329                 .src_reg = EBPF_REG_10,
2330         },
2331         [17] = {
2332                 .code = (EBPF_ALU64 | BPF_ADD | BPF_K),
2333                 .dst_reg = EBPF_REG_1,
2334                 .imm = -8,
2335         },
2336         [18] = {
2337                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
2338                 .dst_reg = EBPF_REG_2,
2339                 .src_reg = EBPF_REG_10,
2340         },
2341         [19] = {
2342                 .code = (EBPF_ALU64 | BPF_ADD | BPF_K),
2343                 .dst_reg = EBPF_REG_2,
2344                 .imm = -16,
2345         },
2346         [20] = {
2347                 .code = (BPF_JMP | EBPF_CALL),
2348                 .imm = 0,
2349         },
2350         [21] = {
2351                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
2352                 .dst_reg = EBPF_REG_1,
2353                 .src_reg = EBPF_REG_0,
2354         },
2355         [22] = {
2356                 .code = (EBPF_ALU64 | BPF_LSH | BPF_K),
2357                 .dst_reg = EBPF_REG_1,
2358                 .imm = 0x20,
2359         },
2360         [23] = {
2361                 .code = (EBPF_ALU64 | BPF_RSH | BPF_K),
2362                 .dst_reg = EBPF_REG_1,
2363                 .imm = 0x20,
2364         },
2365         [24] = {
2366                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
2367                 .dst_reg = EBPF_REG_0,
2368                 .src_reg = EBPF_REG_1,
2369         },
2370         [25] = {
2371                 .code = (BPF_JMP | BPF_JEQ | BPF_X),
2372                 .dst_reg = EBPF_REG_1,
2373                 .src_reg = EBPF_REG_6,
2374                 .off = 1,
2375         },
2376         [26] = {
2377                 .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
2378                 .dst_reg = EBPF_REG_0,
2379                 .imm = 0,
2380         },
2381         [27] = {
2382                 .code = (BPF_JMP | EBPF_EXIT),
2383         },
2384 };
2385
2386 /* String comparision impelementation, return 0 if equal else difference */
2387 static uint32_t
2388 dummy_func5(const char *s1, const char *s2)
2389 {
2390         while (*s1 && (*s1 == *s2)) {
2391                 s1++;
2392                 s2++;
2393         }
2394         return *(const unsigned char *)s1 - *(const unsigned char *)s2;
2395 }
2396
2397 static int
2398 test_call5_check(uint64_t rc, const void *arg)
2399 {
2400         char a[] = "geek";
2401         char b[] = "week";
2402         uint32_t v;
2403
2404         RTE_SET_USED(arg);
2405
2406         v = dummy_func5(a, a);
2407         if (v != 0) {
2408                 v = -1;
2409                 goto fail;
2410         }
2411
2412         v = dummy_func5(a, b);
2413         if (v == 0)
2414                 goto fail;
2415
2416         v = 0;
2417
2418 fail:
2419         return cmp_res(__func__, v, rc, &v, &rc, sizeof(v));
2420 }
2421
2422 static const struct rte_bpf_xsym test_call5_xsym[] = {
2423         [0] = {
2424                 .name = RTE_STR(dummy_func5),
2425                 .type = RTE_BPF_XTYPE_FUNC,
2426                 .func = {
2427                         .val = (void *)dummy_func5,
2428                         .nb_args = 2,
2429                         .args = {
2430                                 [0] = {
2431                                         .type = RTE_BPF_ARG_PTR,
2432                                         .size = sizeof(char),
2433                                 },
2434                                 [1] = {
2435                                         .type = RTE_BPF_ARG_PTR,
2436                                         .size = sizeof(char),
2437                                 },
2438                         },
2439                         .ret = {
2440                                 .type = RTE_BPF_ARG_RAW,
2441                                 .size = sizeof(uint32_t),
2442                         },
2443                 },
2444         },
2445 };
2446
2447 /* all bpf test cases */
2448 static const struct bpf_test tests[] = {
2449         {
2450                 .name = "test_store1",
2451                 .arg_sz = sizeof(struct dummy_offset),
2452                 .prm = {
2453                         .ins = test_store1_prog,
2454                         .nb_ins = RTE_DIM(test_store1_prog),
2455                         .prog_arg = {
2456                                 .type = RTE_BPF_ARG_PTR,
2457                                 .size = sizeof(struct dummy_offset),
2458                         },
2459                 },
2460                 .prepare = test_store1_prepare,
2461                 .check_result = test_store1_check,
2462         },
2463         {
2464                 .name = "test_store2",
2465                 .arg_sz = sizeof(struct dummy_offset),
2466                 .prm = {
2467                         .ins = test_store2_prog,
2468                         .nb_ins = RTE_DIM(test_store2_prog),
2469                         .prog_arg = {
2470                                 .type = RTE_BPF_ARG_PTR,
2471                                 .size = sizeof(struct dummy_offset),
2472                         },
2473                 },
2474                 .prepare = test_store1_prepare,
2475                 .check_result = test_store1_check,
2476         },
2477         {
2478                 .name = "test_load1",
2479                 .arg_sz = sizeof(struct dummy_offset),
2480                 .prm = {
2481                         .ins = test_load1_prog,
2482                         .nb_ins = RTE_DIM(test_load1_prog),
2483                         .prog_arg = {
2484                                 .type = RTE_BPF_ARG_PTR,
2485                                 .size = sizeof(struct dummy_offset),
2486                         },
2487                 },
2488                 .prepare = test_load1_prepare,
2489                 .check_result = test_load1_check,
2490         },
2491         {
2492                 .name = "test_ldimm1",
2493                 .arg_sz = sizeof(struct dummy_offset),
2494                 .prm = {
2495                         .ins = test_ldimm1_prog,
2496                         .nb_ins = RTE_DIM(test_ldimm1_prog),
2497                         .prog_arg = {
2498                                 .type = RTE_BPF_ARG_PTR,
2499                                 .size = sizeof(struct dummy_offset),
2500                         },
2501                 },
2502                 .prepare = test_store1_prepare,
2503                 .check_result = test_ldimm1_check,
2504         },
2505         {
2506                 .name = "test_mul1",
2507                 .arg_sz = sizeof(struct dummy_vect8),
2508                 .prm = {
2509                         .ins = test_mul1_prog,
2510                         .nb_ins = RTE_DIM(test_mul1_prog),
2511                         .prog_arg = {
2512                                 .type = RTE_BPF_ARG_PTR,
2513                                 .size = sizeof(struct dummy_vect8),
2514                         },
2515                 },
2516                 .prepare = test_mul1_prepare,
2517                 .check_result = test_mul1_check,
2518         },
2519         {
2520                 .name = "test_shift1",
2521                 .arg_sz = sizeof(struct dummy_vect8),
2522                 .prm = {
2523                         .ins = test_shift1_prog,
2524                         .nb_ins = RTE_DIM(test_shift1_prog),
2525                         .prog_arg = {
2526                                 .type = RTE_BPF_ARG_PTR,
2527                                 .size = sizeof(struct dummy_vect8),
2528                         },
2529                 },
2530                 .prepare = test_shift1_prepare,
2531                 .check_result = test_shift1_check,
2532         },
2533         {
2534                 .name = "test_jump1",
2535                 .arg_sz = sizeof(struct dummy_vect8),
2536                 .prm = {
2537                         .ins = test_jump1_prog,
2538                         .nb_ins = RTE_DIM(test_jump1_prog),
2539                         .prog_arg = {
2540                                 .type = RTE_BPF_ARG_PTR,
2541                                 .size = sizeof(struct dummy_vect8),
2542                         },
2543                 },
2544                 .prepare = test_jump1_prepare,
2545                 .check_result = test_jump1_check,
2546         },
2547         {
2548                 .name = "test_jump2",
2549                 .arg_sz = sizeof(struct dummy_net),
2550                 .prm = {
2551                         .ins = test_jump2_prog,
2552                         .nb_ins = RTE_DIM(test_jump2_prog),
2553                         .prog_arg = {
2554                                 .type = RTE_BPF_ARG_PTR,
2555                                 .size = sizeof(struct dummy_net),
2556                         },
2557                 },
2558                 .prepare = test_jump2_prepare,
2559                 .check_result = test_jump2_check,
2560         },
2561         {
2562                 .name = "test_alu1",
2563                 .arg_sz = sizeof(struct dummy_vect8),
2564                 .prm = {
2565                         .ins = test_alu1_prog,
2566                         .nb_ins = RTE_DIM(test_alu1_prog),
2567                         .prog_arg = {
2568                                 .type = RTE_BPF_ARG_PTR,
2569                                 .size = sizeof(struct dummy_vect8),
2570                         },
2571                 },
2572                 .prepare = test_jump1_prepare,
2573                 .check_result = test_alu1_check,
2574         },
2575         {
2576                 .name = "test_bele1",
2577                 .arg_sz = sizeof(struct dummy_vect8),
2578                 .prm = {
2579                         .ins = test_bele1_prog,
2580                         .nb_ins = RTE_DIM(test_bele1_prog),
2581                         .prog_arg = {
2582                                 .type = RTE_BPF_ARG_PTR,
2583                                 .size = sizeof(struct dummy_vect8),
2584                         },
2585                 },
2586                 .prepare = test_bele1_prepare,
2587                 .check_result = test_bele1_check,
2588         },
2589         {
2590                 .name = "test_xadd1",
2591                 .arg_sz = sizeof(struct dummy_offset),
2592                 .prm = {
2593                         .ins = test_xadd1_prog,
2594                         .nb_ins = RTE_DIM(test_xadd1_prog),
2595                         .prog_arg = {
2596                                 .type = RTE_BPF_ARG_PTR,
2597                                 .size = sizeof(struct dummy_offset),
2598                         },
2599                 },
2600                 .prepare = test_store1_prepare,
2601                 .check_result = test_xadd1_check,
2602         },
2603         {
2604                 .name = "test_div1",
2605                 .arg_sz = sizeof(struct dummy_vect8),
2606                 .prm = {
2607                         .ins = test_div1_prog,
2608                         .nb_ins = RTE_DIM(test_div1_prog),
2609                         .prog_arg = {
2610                                 .type = RTE_BPF_ARG_PTR,
2611                                 .size = sizeof(struct dummy_vect8),
2612                         },
2613                 },
2614                 .prepare = test_mul1_prepare,
2615                 .check_result = test_div1_check,
2616         },
2617         {
2618                 .name = "test_call1",
2619                 .arg_sz = sizeof(struct dummy_offset),
2620                 .prm = {
2621                         .ins = test_call1_prog,
2622                         .nb_ins = RTE_DIM(test_call1_prog),
2623                         .prog_arg = {
2624                                 .type = RTE_BPF_ARG_PTR,
2625                                 .size = sizeof(struct dummy_offset),
2626                         },
2627                         .xsym = test_call1_xsym,
2628                         .nb_xsym = RTE_DIM(test_call1_xsym),
2629                 },
2630                 .prepare = test_load1_prepare,
2631                 .check_result = test_call1_check,
2632                 /* for now don't support function calls on 32 bit platform */
2633                 .allow_fail = (sizeof(uint64_t) != sizeof(uintptr_t)),
2634         },
2635         {
2636                 .name = "test_call2",
2637                 .arg_sz = sizeof(struct dummy_offset),
2638                 .prm = {
2639                         .ins = test_call2_prog,
2640                         .nb_ins = RTE_DIM(test_call2_prog),
2641                         .prog_arg = {
2642                                 .type = RTE_BPF_ARG_PTR,
2643                                 .size = sizeof(struct dummy_offset),
2644                         },
2645                         .xsym = test_call2_xsym,
2646                         .nb_xsym = RTE_DIM(test_call2_xsym),
2647                 },
2648                 .prepare = test_store1_prepare,
2649                 .check_result = test_call2_check,
2650                 /* for now don't support function calls on 32 bit platform */
2651                 .allow_fail = (sizeof(uint64_t) != sizeof(uintptr_t)),
2652         },
2653         {
2654                 .name = "test_call3",
2655                 .arg_sz = sizeof(struct dummy_vect8),
2656                 .prm = {
2657                         .ins = test_call3_prog,
2658                         .nb_ins = RTE_DIM(test_call3_prog),
2659                         .prog_arg = {
2660                                 .type = RTE_BPF_ARG_PTR,
2661                                 .size = sizeof(struct dummy_vect8),
2662                         },
2663                         .xsym = test_call3_xsym,
2664                         .nb_xsym = RTE_DIM(test_call3_xsym),
2665                 },
2666                 .prepare = test_call3_prepare,
2667                 .check_result = test_call3_check,
2668                 /* for now don't support function calls on 32 bit platform */
2669                 .allow_fail = (sizeof(uint64_t) != sizeof(uintptr_t)),
2670         },
2671         {
2672                 .name = "test_call4",
2673                 .arg_sz = sizeof(struct dummy_offset),
2674                 .prm = {
2675                         .ins = test_call4_prog,
2676                         .nb_ins = RTE_DIM(test_call4_prog),
2677                         .prog_arg = {
2678                                 .type = RTE_BPF_ARG_PTR,
2679                                 .size = 2 * sizeof(struct dummy_offset),
2680                         },
2681                         .xsym = test_call4_xsym,
2682                         .nb_xsym = RTE_DIM(test_call4_xsym),
2683                 },
2684                 .prepare = test_store1_prepare,
2685                 .check_result = test_call4_check,
2686                 /* for now don't support function calls on 32 bit platform */
2687                 .allow_fail = (sizeof(uint64_t) != sizeof(uintptr_t)),
2688         },
2689         {
2690                 .name = "test_call5",
2691                 .arg_sz = sizeof(struct dummy_offset),
2692                 .prm = {
2693                         .ins = test_call5_prog,
2694                         .nb_ins = RTE_DIM(test_call5_prog),
2695                         .prog_arg = {
2696                                 .type = RTE_BPF_ARG_PTR,
2697                                 .size = sizeof(struct dummy_offset),
2698                         },
2699                         .xsym = test_call5_xsym,
2700                         .nb_xsym = RTE_DIM(test_call5_xsym),
2701                 },
2702                 .prepare = test_store1_prepare,
2703                 .check_result = test_call5_check,
2704                 /* for now don't support function calls on 32 bit platform */
2705                 .allow_fail = (sizeof(uint64_t) != sizeof(uintptr_t)),
2706         },
2707 };
2708
2709 static int
2710 run_test(const struct bpf_test *tst)
2711 {
2712         int32_t ret, rv;
2713         int64_t rc;
2714         struct rte_bpf *bpf;
2715         struct rte_bpf_jit jit;
2716         uint8_t tbuf[tst->arg_sz];
2717
2718         printf("%s(%s) start\n", __func__, tst->name);
2719
2720         bpf = rte_bpf_load(&tst->prm);
2721         if (bpf == NULL) {
2722                 printf("%s@%d: failed to load bpf code, error=%d(%s);\n",
2723                         __func__, __LINE__, rte_errno, strerror(rte_errno));
2724                 return -1;
2725         }
2726
2727         tst->prepare(tbuf);
2728         rc = rte_bpf_exec(bpf, tbuf);
2729         ret = tst->check_result(rc, tbuf);
2730         if (ret != 0) {
2731                 printf("%s@%d: check_result(%s) failed, error: %d(%s);\n",
2732                         __func__, __LINE__, tst->name, ret, strerror(ret));
2733         }
2734
2735         /* repeat the same test with jit, when possible */
2736         rte_bpf_get_jit(bpf, &jit);
2737         if (jit.func != NULL) {
2738
2739                 tst->prepare(tbuf);
2740                 rc = jit.func(tbuf);
2741                 rv = tst->check_result(rc, tbuf);
2742                 ret |= rv;
2743                 if (rv != 0) {
2744                         printf("%s@%d: check_result(%s) failed, "
2745                                 "error: %d(%s);\n",
2746                                 __func__, __LINE__, tst->name,
2747                                 rv, strerror(ret));
2748                 }
2749         }
2750
2751         rte_bpf_destroy(bpf);
2752         return ret;
2753
2754 }
2755
2756 static int
2757 test_bpf(void)
2758 {
2759         int32_t rc, rv;
2760         uint32_t i;
2761
2762         rc = 0;
2763         for (i = 0; i != RTE_DIM(tests); i++) {
2764                 rv = run_test(tests + i);
2765                 if (tests[i].allow_fail == 0)
2766                         rc |= rv;
2767         }
2768
2769         return rc;
2770 }
2771
2772 REGISTER_TEST_COMMAND(bpf_autotest, test_bpf);