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