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