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