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